Merge branch 'master' into var-subset
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 9eeb154..e81f187 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -34,7 +34,7 @@
 
   distcheck:
     docker:
-      - image: ubuntu:17.10
+      - image: ubuntu:19.04
     steps:
       - checkout
       - run: apt update && apt install -y ninja-build binutils libtool autoconf automake make cmake gcc g++ pkg-config ragel gtk-doc-tools libfontconfig1-dev libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
@@ -192,18 +192,27 @@
       - run: make -j32
       - run: make check || .ci/fail.sh | asan_symbolize | c++filt
 
-  fedora-O0-debug-outoftreebuild:
+  fedora-O0-debug-outoftreebuild-mingw:
     docker:
       - image: fedora
     steps:
       - checkout
-      - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python || true
+      - run: dnf install -y pkg-config ragel gcc gcc-c++ automake autoconf libtool make which glib2-devel freetype-devel cairo-devel libicu-devel gobject-introspection-devel graphite2-devel redhat-rpm-config python wine mingw32-gcc-c++ mingw64-gcc-c++ mingw32-glib2 mingw32-cairo mingw32-freetype mingw64-glib2 mingw64-cairo mingw64-freetype glibc-devel.i686 || true
       - run: CFLAGS="-O0" CXXFLAGS="-O0" CPPFLAGS="-DHB_DEBUG" NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2
-      - run: mkdir build && cd build && ../configure && make && (make check || ../.ci/fail.sh)
+      - run: mkdir build && cd build && ../configure && make -j32 && (make check || ../.ci/fail.sh)
+      - run: pip install pefile
+      - run: mkdir winbuild32 && cd winbuild32 && ../mingw32.sh && make -j32 && make dist-win && cp harfbuzz-*-win32.zip harfbuzz-win32.zip
+      - run: mkdir winbuild64 && cd winbuild64 && ../mingw64.sh && make -j32 && make dist-win && cp harfbuzz-*-win64.zip harfbuzz-win64.zip
+      - store_artifacts:
+          path: winbuild32/harfbuzz-win32.zip
+          destination: harfbuzz-win32.zip
+      - store_artifacts:
+          path: winbuild64/harfbuzz-win64.zip
+          destination: harfbuzz-win64.zip
 
   cmake-gcc:
     docker:
-      - image: ubuntu:17.10
+      - image: ubuntu:19.04
     steps:
       - checkout
       - run: apt update && apt install -y ninja-build binutils cmake gcc g++ pkg-config ragel gtk-doc-tools libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
@@ -213,17 +222,17 @@
       - run: CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test
       - run: ninja -Cbuild install
 
-  cmake-oracledeveloperstudio:
-    docker:
-      - image: fedora
-    steps:
-      - checkout
-      - run: dnf install -y gcc ragel cmake make which glib2-devel freetype-devel cairo-devel libicu-devel graphite2-devel wget tar bzip2 python libnsl || true
-      - run: wget http://$ODSUSER:$ODSPASS@behdad.org/harfbuzz-private/OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 && tar xf OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 --owner root --group root --no-same-owner
-      - run: CC=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/suncc CXX=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/sunCC cmake -DHB_HAVE_GRAPHITE2=ON -DHB_BUILTIN_UCDN=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H.
-      - run: make -Cbuild -j32
-      - run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test
-      - run: make -Cbuild install
+  #cmake-oracledeveloperstudio:
+  #  docker:
+  #    - image: fedora
+  #  steps:
+  #    - checkout
+  #    - run: dnf install -y gcc ragel cmake make which glib2-devel freetype-devel cairo-devel libicu-devel graphite2-devel wget tar bzip2 python libnsl || true
+  #    - run: wget http://$ODSUSER:$ODSPASS@behdad.org/harfbuzz-private/OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 && tar xf OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 --owner root --group root --no-same-owner
+  #    - run: CC=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/suncc CXX=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/sunCC cmake -DHB_HAVE_GRAPHITE2=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H.
+  #    - run: make -Cbuild -j32
+  #    - run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test
+  #    - run: make -Cbuild install
 
   crosscompile-notest-djgpp:
     docker:
@@ -253,12 +262,12 @@
       - run: cmake -Bbuild -H. -GNinja
       - run: ninja -Cbuild
 
-  crosscompile-cmake-notest-browser-asmjs:
+  crosscompile-cmake-notest-browser-asmjs-hb_tiny:
     docker:
       - image: dockcross/browser-asmjs
     steps:
       - checkout
-      - run: cmake -Bbuild -H. -GNinja
+      - run: cmake -Bbuild -H. -GNinja -DCMAKE_CXX_FLAGS="-DHB_TINY"
       - run: ninja -Cbuild
 
   crosscompile-cmake-notest-linux-arm64:
@@ -308,7 +317,7 @@
       - clang-msan
       - clang-tsan
       - clang-ubsan
-      - fedora-O0-debug-outoftreebuild
+      - fedora-O0-debug-outoftreebuild-mingw
 
       # cmake based builds
       - cmake-gcc
@@ -322,7 +331,7 @@
 
       ## cmake
       - crosscompile-cmake-notest-android-arm
-      - crosscompile-cmake-notest-browser-asmjs
+      - crosscompile-cmake-notest-browser-asmjs-hb_tiny
       - crosscompile-cmake-notest-linux-arm64
       - crosscompile-cmake-notest-linux-mips
       #- crosscompile-cmake-notest-windows-x64
diff --git a/.travis.yml b/.travis.yml
index 703fac2..d788263 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
 # Build Configuration for Travis
-dist: trusty
+dist: xenial
 
 language: cpp
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a8d12c1..4ffabad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,7 +35,6 @@
 ## HarfBuzz build configurations
 option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF)
 option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF)
-option(HB_BUILTIN_UCDN "Use HarfBuzz provided UCDN" ON)
 option(HB_HAVE_GLIB "Enable glib unicode functions" OFF)
 option(HB_HAVE_ICU "Enable icu unicode functions" OFF)
 if (APPLE)
@@ -70,7 +69,6 @@
 if (HB_CHECK)
   set (BUILD_SHARED_LIBS ON)
   set (HB_BUILD_UTILS ON)
-  set (HB_BUILTIN_UCDN ON)
   set (HB_HAVE_ICU)
   set (HB_HAVE_GLIB ON)
   #set (HB_HAVE_GOBJECT ON)
@@ -160,7 +158,6 @@
 
 file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES)
 file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES)
-file(READ ${PROJECT_SOURCE_DIR}/src/hb-ucdn/Makefile.sources UCDNSOURCES)
 
 extract_make_variable(HB_BASE_sources ${SRCSOURCES})
 add_prefix_to_list(HB_BASE_sources "${PROJECT_SOURCE_DIR}/src/")
@@ -191,9 +188,6 @@
 extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES})
 add_prefix_to_list(HB_OT_SHAPE_CLOSURE_sources "${PROJECT_SOURCE_DIR}/util/")
 
-extract_make_variable(LIBHB_UCDN_sources ${UCDNSOURCES})
-add_prefix_to_list(LIBHB_UCDN_sources "${PROJECT_SOURCE_DIR}/src/hb-ucdn/")
-
 
 file(READ configure.ac CONFIGUREAC)
 string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC})
@@ -295,14 +289,6 @@
   mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY)
 endif ()
 
-if (HB_BUILTIN_UCDN)
-  include_directories(src/hb-ucdn)
-  add_definitions(-DHAVE_UCDN)
-
-  list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ucdn.cc)
-  list(APPEND project_extra_sources ${LIBHB_UCDN_sources})
-endif ()
-
 if (HB_HAVE_GLIB)
   add_definitions(-DHAVE_GLIB)
 
diff --git a/Makefile.am b/Makefile.am
index f9f6e36..26ebdc6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,12 +9,18 @@
 EXTRA_DIST = \
 	autogen.sh \
 	harfbuzz.doap \
+	README.md \
+	README.mingw.md \
 	README.python.md \
-	README.wine.md \
 	BUILD.md \
 	RELEASING.md \
+	TESTING.md \
 	CMakeLists.txt \
 	replace-enum-strings.cmake \
+	mingw-configure.sh \
+	mingw-ldd.py \
+	mingw32.sh \
+	mingw64.sh \
 	$(NULL)
 
 MAINTAINERCLEANFILES = \
@@ -60,8 +66,6 @@
 	--enable-introspection \
 	$(NULL)
 
-# TODO: Copy infrastructure from cairo
-
 # TAR_OPTIONS is not set as env var for 'make dist'.  How to fix that?
 TAR_OPTIONS = --owner=0 --group=0
 
@@ -70,8 +74,7 @@
 dist-clear-sticky-bits:
 	chmod -R a-s $(distdir)
 
-
-tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.bz2
+tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.xz
 sha256_file = $(tar_file).sha256
 gpg_file = $(sha256_file).asc
 $(sha256_file): $(tar_file)
@@ -82,5 +85,18 @@
 
 release-files: $(tar_file) $(sha256_file) $(gpg_file)
 
+dist-win:
+	@case $(host_triplet) in *-w64-mingw32) ;; *) echo "Error: Requires mingw build. See README.mingw.md.">&2; exit 1 ;; esac
+	@DIR=$(PACKAGE_TARNAME)-$(VERSION)-win`case $(host_triplet) in i686-*) echo 32 ;; x86_64-*) echo 64 ;; esac`; \
+	$(RM) -r $$DIR; $(MKDIR_P) $$DIR || exit 1; \
+	cp util/.libs/hb-{shape,view,subset}.exe $$DIR && \
+	$(top_srcdir)/mingw-ldd.py $$DIR/hb-view.exe | grep -v 'not found' | cut -d '>' -f 2 | xargs cp -t $$DIR && \
+	cp src/.libs/libharfbuzz{,-subset}-0.dll $$DIR && \
+	chmod a+x $$DIR/*.{exe,dll} && \
+	$(STRIP) $$DIR/*.{exe,dll} && \
+	zip -r $$DIR.zip $$DIR && \
+	$(RM) -r $$DIR && \
+	echo "$$DIR.zip is ready."
+
 
 -include $(top_srcdir)/git.mk
diff --git a/NEWS b/NEWS
index f3e424f..5192973 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,28 @@
+Overview of changes leading to 2.5.1
+Friday, May 31, 2019
+====================================
+- Fix build with various versions of Visual Studio.
+- Improved documentation, thanks to Nathan Willis.
+- Bugfix in subsetting glyf table.
+- Improved scripts for cross-compiling for Windows using mingw.
+- Rename HB_MATH_GLYPH_PART_FLAG_EXTENDER to HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER.
+  A deprecated macro is added for backwards-compatibility.
+
+
+Overview of changes leading to 2.5.0
+Friday, May 24, 2019
+====================================
+- This release does not include much functional changes, but includes major internal
+  code-base changes.  We now require C++11.  Support for gcc 4.8 and earlier has been
+  dropped.
+- New hb-config.hh facility for compiling smaller library for embedded and web usecases.
+- New Unicode Character Databse implementation that is half the size of previously-used
+  UCDN.
+- Subsetter improvements.
+- Improved documentation, thanks to Nathan Willis.
+- Misc shaping fixes.
+
+
 Overview of changes leading to 2.4.0
 Monday, March 25, 2019
 ====================================
diff --git a/README.md b/README.md
index fd93be8..ce0a04d 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,10 @@
 
   http://harfbuzz.org/
 
-For license information, see the file COPYING.
+For license information, see [COPYING](COPYING).
+
+For build information, see [BUILD.md](BUILD.md).
+
+For test execution, see [TESTING.md](TESTING.md).
 
 Documentation: https://harfbuzz.github.io
diff --git a/README.mingw.md b/README.mingw.md
new file mode 100644
index 0000000..76d1a87
--- /dev/null
+++ b/README.mingw.md
@@ -0,0 +1,48 @@
+For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe,
+as a widely used and tested shaper is used as more-or-less OpenType reference
+implementation and that specially is important where OpenType specification
+is or wasn't that clear. For having access to Uniscribe on Linux/macOS these
+steps are recommended:
+
+1. Install Wine from your favorite package manager.  On Fedora that's `dnf install wine`.
+
+2. And `mingw-w64` compiler.
+   With `brew` on macOS, you can have it like `brew install mingw-w64`.
+   On Fedora, with `dnf install mingw32-gcc-c++`, or `dnf install mingw64-gcc-c++` for the
+   64-bit Windows.
+
+3. Install cross-compiled dependency packages.  Alternatively see [^1] below.
+   On Fedora that would be `dnf install mingw32-glib2 mingw32-cairo mingw32-freetype`
+   for 32-bit, or `dnf install mingw64-glib2 mingw64-cairo mingw64-freetype` for 64-bit.
+
+5. `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild`
+
+6. Run `../mingw32.sh` for 32-bit build, or `../mingw64.sh` for 64-bit.  This configures
+   HarfBuzz for cross-compiling.  It enables Uniscribe backend as well.
+
+7. `make`
+
+Now you can use hb-shape using `wine util/hb-shape.exe` but if you like to shape with
+the Microsoft Uniscribe,
+
+8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your
+   Windows installation (assuming you have a 64-bit installation, otherwise
+   `C:\Windows\System32\usp10.dll`) that it is not a DirectWrite proxy
+   ([for more info](https://en.wikipedia.org/wiki/Uniscribe)).
+   Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise
+   it is designed to work with DirectWrite which Wine can't work with its original one.
+   You want a Uniscribe from Windows 7 or older.
+
+   Put the DLL in the folder you are going to run the next command,
+
+9. `WINEDLLOVERRIDES="usp10=n" wine util/hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe`
+
+(`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need)
+
+
+[^1] Download and put [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ)
+     in your `~/.local/i686-w64-mingw32`.  Then replace all the instances of
+     `/home/behdad/.local/i586-mingw32msvc` and `/home/behdad/.local/i686-w64-mingw32`
+     with `<$HOME>/.local/i686-w64-mingw32` on that folder.
+     (`<$HOME>` replace it with `/home/XXX` or `/Users/XXX` on macOS)
+     You shouldn't replace the instances of those inside binary files.
diff --git a/README.wine.md b/README.wine.md
deleted file mode 100644
index 799eb63..0000000
--- a/README.wine.md
+++ /dev/null
@@ -1,40 +0,0 @@
-For the development of HarfBuzz, the Microsoft shaping technology, Uniscribe,
-as a widely used and tested shaper is used as more-or-less OpenType reference
-implementation and that specially is important where OpenType specification
-is or wasn't that clear. For having access to Uniscribe on Linux/macOS these
-steps are recommended:
-
-1. Install Wine from your favorite package manager.
-
-2. And `mingw-w64` compiler.
-   With `brew` on macOS, you can have it like `brew install mingw-w64`
-
-3. Download and put [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ)
-   on your `~/.local/i686-w64-mingw32`.
-
-4. Replace all the instances of `/home/behdad/.local/i586-mingw32msvc`
-   and `/home/behdad/.local/i686-w64-mingw32` with `<$HOME>/.local/i686-w64-mingw32`
-   on that folder. (`<$HOME>` replace it with `/home/XXX` or `/Users/XXX` on macOS)
-
-   Probably you shouldn't replace the ones are inside binaries.
-
-5. `NOCONFIGURE=1 ./autogen.sh && mkdir winbuild && cd winbuild`
-
-6. `../mingw32.sh --with-uniscribe && cd ..`
-
-7. `make -Cwinbuild`
-
-Now you can use hb-shape using `wine winbuild/util/hb-shape.exe` but if you like to
-to use the original Uniscribe,
-
-8. Bring a 32bit version of `usp10.dll` for yourself from `C:\Windows\SysWOW64\usp10.dll` of your
-   Windows installation (assuming you have a 64-bit installation, otherwise `C:\Windows\System32\usp10.dll`)
-   that it is not a DirectWrite proxy ([for more info](https://en.wikipedia.org/wiki/Uniscribe)).
-   Rule of thumb, your `usp10.dll` should have a size more than 500kb, otherwise
-   it is designed to work with DirectWrite which Wine can't work with its original one.
-
-   Put the dll on the folder you are going to run the next command,
-
-9. `WINEDLLOVERRIDES="usp10=n" wine winbuild/util/hb-shape.exe fontname.ttf -u 0061,0062,0063 --shaper=uniscribe`
-
-(`0061,0062,0063` means `abc`, use test/shaping/hb-unicode-decode to generate ones you need)
diff --git a/RELEASING.md b/RELEASING.md
index 5dcce58..360aea7 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -46,27 +46,21 @@
 
 10. Build win32 bundle.
 
-   a. Put contents of [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) on your `~/.local/i686-w64-mingw32`,
+   a. Build Win32 binaries.  See [README.mingw.md](README.mingw.md).
 
-   b. Run `../mingw32.sh --with-uniscribe` script to configure harfbuzz with mingw
-   in a subdirector (eg. winbuild/),
-
-   c. make
-
-   d. Back in the parent directory, run `./UPDATE.sh`(available below) to build win32
-      bundle.
+   b. Run "make dist-win" to build Win32 bundle.
 
 11. Copy all artefacts to users.freedesktop.org and move them into
     `/srv/www.freedesktop.org/www/software/harfbuzz/release` There should be four
     files.  Eg.:
  ```
--rw-r--r--  1 behdad eng 1592693 Jul 18 11:25 harfbuzz-1.4.7.tar.bz2
--rw-r--r--  1 behdad eng      89 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256
--rw-r--r--  1 behdad eng     339 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256.asc
+-rw-r--r--  1 behdad eng 1592693 Jul 18 11:25 harfbuzz-1.4.7.tar.xz
+-rw-r--r--  1 behdad eng      89 Jul 18 11:34 harfbuzz-1.4.7.tar.xz.sha256
+-rw-r--r--  1 behdad eng     339 Jul 18 11:34 harfbuzz-1.4.7.tar.xz.sha256.asc
 -rw-r--r--  1 behdad eng 2895619 Jul 18 11:34 harfbuzz-1.4.7-win32.zip
 ```
 
-12. While doing that, quickly double-check the size of the .tar.bz2 and .zip
+12. While doing that, quickly double-check the size of the .tar.xz and .zip
     files against their previous releases to make sure nothing bad happened.
     They should be in the ballpark, perhaps slightly larger.  Sometimes they
     do shrink, that's not by itself a stopper.
@@ -76,39 +70,3 @@
 
 14. Go to GitHub release page [here](https://github.com/harfbuzz/harfbuzz/releases),
     edit the tag, upload artefacts and NEWS entry and save.
-
-
-## UPDATE.sh
-```bash
-#!/bin/bash
-
-v=$1
-
-if test "x$v" = x; then
-	echo "usage: UPDATE.sh micro-version"
-	exit 1
-fi
-
-dir_prefix=harfbuzz-1.4.
-dir_suffix=-win32
-dir=$dir_prefix$v$dir_suffix
-dir_old=$dir_prefix$((v-1))$dir_suffix
-if test -d "$dir"; then
-	echo "New dir $dir exists; not overwriting"
-	exit 1
-fi
-if ! test -d "$dir_old"; then
-	echo "Old dir $dir_old does NOT exist; aborting"
-	exit 1
-fi
-set -ex
-cp -a "$dir_old" "$dir.tmp"
-rm -f "$dir.tmp"/GDX32.dll
-rm -f "$dir.tmp"/usp10.dll
-cp ../winbuild/src/.libs/libharfbuzz-0.dll{,.def} $dir.tmp/
-cp ../winbuild/util/.libs/hb-{shape,view}.exe $dir.tmp/
-i686-w64-mingw32-strip $dir.tmp/{hb-shape.exe,hb-view.exe,libharfbuzz-0.dll}
-mv $dir.tmp $dir
-zip -r $dir.zip $dir
-echo Bundle $dir.zip ready
-```
diff --git a/TESTING.md b/TESTING.md
new file mode 100644
index 0000000..4efc64c
--- /dev/null
+++ b/TESTING.md
@@ -0,0 +1,75 @@
+## Build & Run
+
+Depending on what area you are working in change or add `HB_DEBUG_<whatever>`.
+Values defined in `hb-debug.hh`.
+
+```shell
+# quick sanity check
+time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \
+  && (make -j4 -C test/api check || cat test/api/test-suite.log))
+
+# slower sanity check
+time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \
+   && make -j4 -C src check \
+   && make -j4 -C test/api check \
+   && make -j4 -C test/subset check)
+
+# confirm you didn't break anything else
+time (make -j4 CPPFLAGS='-DHB_DEBUG_SUBSET=100' \
+  && make -j4 check)
+
+# often catches files you didn't add, e.g. test fonts to EXTRA_DIST
+make distcheck
+```
+
+### Run tests with asan
+
+**NOTE**: this sometimes yields harder to read results than the full fuzzer
+
+```shell
+# For nice symbols tell asan how to symoblize. Note that it doesn't like versioned copies like llvm-symbolizer-3.8
+# export ASAN_SYMBOLIZER_PATH=path to version-less llvm-symbolizer
+# ex
+export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.8/bin/llvm-symbolizer
+
+./configure CC=clang CXX=clang++ CPPFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address
+# make/run tests as usual
+```
+
+### Debug with GDB
+
+```
+cd ./util
+../libtool --mode=execute gdb --args ./hb-subset ...
+```
+
+### Enable Debug Logging
+
+```shell
+# make clean if you previously build w/o debug logging
+make CPPFLAGS=-DHB_DEBUG_SUBSET=100
+```
+
+## Build and Test via CMake
+
+Note: You'll need to first install ninja-build via apt-get.
+
+```shell
+cd harfbuzz
+mkdir buid
+cmake -DHB_CHECK=ON -Bbuild -H. -GNinja && ninja -Cbuild && CTEST_OUTPUT_ON_FAILURE=1 ninja -Cbuild test
+```
+## Test with the Fuzzer
+
+```shell
+# push your changs to a branch on googlefonts/harfbuzz
+# In a local copy of oss-fuzz, edit projects/harfbuzz/Dockerfile
+# Change the git clone to pull your branch
+
+# Do this periodically
+sudo python infra/helper.py build_image harfbuzz
+
+# Do these to update/run
+sudo python infra/helper.py build_fuzzers --sanitizer address harfbuzz
+sudo python infra/helper.py run_fuzzer harfbuzz hb-subset-fuzzer
+```
diff --git a/appveyor.yml b/appveyor.yml
index 21d4ea7..236bb1b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -2,11 +2,13 @@
 
 environment:
   matrix:
+
     - compiler: msvc
       generator: Visual Studio 14
       platform: Win32
       configuration: Debug
       triplet: x86-windows
+
     - compiler: msvc
       generator: Visual Studio 14 Win64
       platform: x64
@@ -19,10 +21,35 @@
       configuration: Debug
 
 
+    # Build only
+
+    #- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
+    #  compiler: msvc2
+    #  generator: Visual Studio 12
+    #  platform: Win32
+    #  configuration: Release
+    #  triplet: x86-windows
+
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+      compiler: msvc2
+      generator: Visual Studio 15
+      platform: Win32
+      configuration: Release
+      triplet: x86-windows
+
+    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+      compiler: msvc2
+      generator: Visual Studio 16
+      platform: Win32
+      configuration: Release
+      triplet: x86-windows
+
+
     - compiler: msys2
       MINGW_PREFIX: /mingw64
       MINGW_CHOST: x86_64-w64-mingw32
       MSYS2_ARCH: x86_64
+
     - compiler: msys2
       MINGW_PREFIX: /mingw32
       MINGW_CHOST: i686-w64-mingw32
@@ -30,30 +57,26 @@
 
 
 install:
-# - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -Sy && pacman --noconfirm --force -S pacman-mirrors && pacman --force -Syu --noconfirm"'
-  - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{gcc,freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"'
-  - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel"
-  - set PATH=%PATH%;C:\msys64\mingw64\bin # msys2 is added just for having "ragel" on PATH
-  - 'if "%compiler%"=="cygwin" %CYGWIN_PREFIX%\setup-%CYGWIN_ARCH%.exe -g -q -P cygwin-devel,libfreetype-devel,libcairo-devel,libicu-devel,gcc,gcc-g++,gobject-introspection,libglib2.0-devel,libgraphite2-devel,pkg-config,python2'
+  - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm --force -S --needed mingw-w64-$MSYS2_ARCH-{gcc,freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2,ragel}"'
   - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" vcpkg install glib:%triplet% freetype:%triplet% cairo:%triplet%'
 
 build_script:
-  - 'if "%compiler%"=="msvc" md build'
-  - 'if "%compiler%"=="msvc" cd build'
+  - 'if "%compiler%"=="msvc" if "%platform%"=="ARM" cmake -Bbuild -H. -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%"'
+  - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" cmake -Bbuild -H. -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake'
+
   - 'if "%compiler%"=="msvc" set PATH=%PATH%;C:\Program Files (x86)\MSBuild\14.0\Bin'
-
-  - 'if "%compiler%"=="msvc" if "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%" ../'
-  - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -DHB_BUILD_UTILS=ON -G "%generator%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake ../'
-
+  - 'if "%compiler%"=="msvc" cd build'
   - 'if "%compiler%"=="msvc" msbuild harfbuzz.sln /p:Configuration=%configuration% /p:Platform=%platform%'
   - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" ctest --output-on-failure -C %configuration%'
 
+  - 'if "%compiler%"=="msvc2" cmake -G "%generator%" -Bbuild -H.'
+  - 'if "%compiler%"=="msvc2" cmake --build build --config %configuration%'
+
   - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://raw.githubusercontent.com/mirror/mingw-w64/023eb04c396d4e8d8fcf604cfababc53dae13398/mingw-w64-headers/include/dwrite_1.h > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"'
   - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make -j3 check || .ci/fail.sh"'
 
 cache:
   - c:\tools\vcpkg\installed\
-  - '%CYGWIN_PREFIX%\var\cache\setup'
 
 notifications:
   - provider: Email
diff --git a/configure.ac b/configure.ac
index 98e9c32..6a68df7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [2.4.0],
+        [2.5.1],
         [https://github.com/harfbuzz/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
@@ -9,7 +9,7 @@
 AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
-AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
+AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-xz no-dist-gzip -Wall no-define color-tests -Wno-portability])
 AM_SILENT_RULES([yes])
 AX_CODE_COVERAGE
 
@@ -134,9 +134,7 @@
 AM_CONDITIONAL(OS_WIN32, test "$hb_os_win32" = "yes")
 
 have_pthread=false
-if test "$hb_os_win32" = no; then
-	AX_PTHREAD([have_pthread=true])
-fi
+AX_PTHREAD([have_pthread=true])
 if $have_pthread; then
 	AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
 fi
@@ -300,21 +298,6 @@
 
 dnl ===========================================================================
 
-AC_ARG_WITH(ucdn,
-	[AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@],
-			[Use builtin UCDN library @<:@default=yes@:>@])],,
-	[with_ucdn=yes])
-have_ucdn=false
-if test "x$with_ucdn" = "xyes"; then
-	have_ucdn=true
-fi
-if $have_ucdn; then
-	AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
-fi
-AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
-
-dnl ==========================================================================
-
 AC_ARG_WITH(graphite2,
 	[AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@],
 			[Use the graphite2 library @<:@default=no@:>@])],,
@@ -497,7 +480,6 @@
 Makefile
 src/Makefile
 src/harfbuzz-config.cmake
-src/hb-ucdn/Makefile
 util/Makefile
 test/Makefile
 test/api/Makefile
@@ -525,7 +507,7 @@
 Build configuration:
 
 Unicode callbacks (you want at least one):
-	Builtin (UCDN):		${have_ucdn}
+	Builtin			true
 	Glib:			${have_glib}
 	ICU:			${have_icu}
 
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 9b54b40..f4bf2fd 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -33,7 +33,7 @@
 
 # Header files or dirs to ignore when scanning. Use base file/dir names
 # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
-IGNORE_HFILES=`cd $(top_srcdir)/src; find . -path './hb-*/*.h' | sed 's@^.*/@@'`
+IGNORE_HFILES=`cd $(top_srcdir)/src; find . -path './*/*.h' | sed 's@^.*/@@'`
 if HAVE_GOBJECT
 else
 IGNORE_HFILES+=hb-gobject.h hb-gobject-enums.h hb-gobject-structs.h
@@ -75,12 +75,14 @@
 	usermanual-what-is-harfbuzz.xml \
 	usermanual-install-harfbuzz.xml \
 	usermanual-getting-started.xml \
+	usermanual-glyph-information.xml \
 	usermanual-shaping-concepts.xml \
+	usermanual-object-model.xml \
 	usermanual-buffers-language-script-and-direction.xml \
 	usermanual-fonts-and-faces.xml \
-	usermanual-clusters.xml \
 	usermanual-opentype-features.xml \
-	usermanual-glyph-information.xml \
+	usermanual-clusters.xml \
+	usermanual-utilities.xml \
 	version.xml
 
 # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index e48d175..2e4b35c 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -33,11 +33,12 @@
       <xi:include href="usermanual-install-harfbuzz.xml"/>
       <xi:include href="usermanual-getting-started.xml"/>
       <xi:include href="usermanual-shaping-concepts.xml"/>
+      <xi:include href="usermanual-object-model.xml"/>
       <xi:include href="usermanual-buffers-language-script-and-direction.xml"/>
       <xi:include href="usermanual-fonts-and-faces.xml"/>
-      <xi:include href="usermanual-clusters.xml"/>
       <xi:include href="usermanual-opentype-features.xml"/>
-      <xi:include href="usermanual-glyph-information.xml"/>
+      <xi:include href="usermanual-clusters.xml"/>
+      <xi:include href="usermanual-utilities.xml"/>
   </part>
 
   <part>
diff --git a/docs/usermanual-buffers-language-script-and-direction.xml b/docs/usermanual-buffers-language-script-and-direction.xml
index 1c6b5da..2865426 100644
--- a/docs/usermanual-buffers-language-script-and-direction.xml
+++ b/docs/usermanual-buffers-language-script-and-direction.xml
@@ -7,30 +7,38 @@
 <chapter id="buffers-language-script-and-direction">
   <title>Buffers, language, script and direction</title>
   <para>
-    The input to HarfBuzz is a series of Unicode characters, stored in a
+    The input to the HarfBuzz shaper is a series of Unicode characters, stored in a
     buffer. In this chapter, we'll look at how to set up a buffer with
-    the text that we want and then customize the properties of the
-    buffer.
+    the text that we want and how to customize the properties of the
+    buffer. We'll also look at a piece of lower-level machinery that
+    you will need to understand before proceeding: the functions that
+    HarfBuzz uses to retrieve Unicode information.
+  </para>
+  <para>
+    After shaping is complete, HarfBuzz puts its output back
+    into the buffer. But getting that output requires setting up a
+    face and a font first, so we will look at that in the next chapter
+    instead of here.
   </para>
   <section id="creating-and-destroying-buffers">
     <title>Creating and destroying buffers</title>
     <para>
       As we saw in our <emphasis>Getting Started</emphasis> example, a
       buffer is created and 
-      initialized with <literal>hb_buffer_create()</literal>. This
+      initialized with <function>hb_buffer_create()</function>. This
       produces a new, empty buffer object, instantiated with some
       default values and ready to accept your Unicode strings.
     </para>
     <para>
       HarfBuzz manages the memory of objects (such as buffers) that it
       creates, so you don't have to. When you have finished working on 
-      a buffer, you can call <literal>hb_buffer_destroy()</literal>:
+      a buffer, you can call <function>hb_buffer_destroy()</function>:
     </para>
     <programlisting language="C">
-  hb_buffer_t *buffer = hb_buffer_create();
-  ...
-  hb_buffer_destroy(buffer);
-</programlisting>
+      hb_buffer_t *buf = hb_buffer_create();
+      ...
+      hb_buffer_destroy(buf);
+    </programlisting>
     <para>
       This will destroy the object and free its associated memory -
       unless some other part of the program holds a reference to this
@@ -39,46 +47,364 @@
       else destroying it, you should increase its reference count:
     </para>
     <programlisting language="C">
-void somefunc(hb_buffer_t *buffer) {
-  buffer = hb_buffer_reference(buffer);
-  ...
-</programlisting>
+      void somefunc(hb_buffer_t *buf) {
+      buf = hb_buffer_reference(buf);
+      ...
+    </programlisting>
     <para>
       And then decrease it once you're done with it:
     </para>
     <programlisting language="C">
-  hb_buffer_destroy(buffer);
-}
-</programlisting>
+      hb_buffer_destroy(buf);
+      }
+    </programlisting>
+    <para>
+      While we are on the subject of reference-counting buffers, it is
+      worth noting that an individual buffer can only meaningfully be
+      used by one thread at a time.
+    </para>
     <para>
       To throw away all the data in your buffer and start from scratch,
-      call <literal>hb_buffer_reset(buffer)</literal>. If you want to
+      call <function>hb_buffer_reset(buf)</function>. If you want to
       throw away the string in the buffer but keep the options, you can
-      instead call <literal>hb_buffer_clear_contents(buffer)</literal>.
+      instead call <function>hb_buffer_clear_contents(buf)</function>.
     </para>
   </section>
+  
   <section id="adding-text-to-the-buffer">
     <title>Adding text to the buffer</title>
     <para>
       Now we have a brand new HarfBuzz buffer. Let's start filling it
       with text! From HarfBuzz's perspective, a buffer is just a stream
-      of Unicode codepoints, but your input string is probably in one of
-      the standard Unicode character encodings (UTF-8, UTF-16, UTF-32)
+      of Unicode code points, but your input string is probably in one of
+      the standard Unicode character encodings (UTF-8, UTF-16, or
+      UTF-32). HarfBuzz provides convenience functions that accept
+      each of these encodings:
+      <function>hb_buffer_add_utf8()</function>,
+      <function>hb_buffer_add_utf16()</function>, and
+      <function>hb_buffer_add_utf32()</function>. Other than the
+      character encoding they accept, they function identically.
     </para>
+    <para>
+      You can add UTF-8 text to a buffer by passing in the text array,
+      the array's length, an offset into the array for the first
+      character to add, and the length of the segment to add:
+    </para>
+    <programlisting language="C">
+    hb_buffer_add_utf8 (hb_buffer_t *buf,
+                    const char *text,
+                    int text_length,
+                    unsigned int item_offset,
+                    int item_length)
+    </programlisting>
+    <para>
+      So, in practice, you can say:
+    </para>
+    <programlisting language="C">
+      hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));
+    </programlisting>
+    <para>
+      This will append your new characters to
+      <parameter>buf</parameter>, not replace its existing
+      contents. Also, note that you can use <literal>-1</literal> in
+      place of the first instance of <function>strlen(text)</function>
+      if your text array is NULL-terminated. Similarly, you can also use
+      <literal>-1</literal> as the final argument want to add its full
+      contents.
+    </para>
+    <para>
+      Whatever start <parameter>item_offset</parameter> and
+      <parameter>item_length</parameter> you provide, HarfBuzz will also
+      attempt to grab the five characters <emphasis>before</emphasis>
+      the offset point and the five characters
+      <emphasis>after</emphasis> the designated end. These are the
+      before and after "context" segments, which are used internally
+      for HarfBuzz to make shaping decisions. They will not be part of
+      the final output, but they ensure that HarfBuzz's
+      script-specific shaping operations are correct. If there are
+      fewer than five characters available for the before or after
+      contexts, HarfBuzz will just grab what is there.
+    </para>
+    <para>
+      For longer text runs, such as full paragraphs, it might be
+      tempting to only add smaller sub-segments to a buffer and
+      shape them in piecemeal fashion. Generally, this is not a good
+      idea, however, because a lot of shaping decisions are
+      dependent on this context information. For example, in Arabic
+      and other connected scripts, HarfBuzz needs to know the code
+      points before and after each character in order to correctly
+      determine which glyph to return.
+    </para>
+    <para>
+      The safest approach is to add all of the text available, then
+      use <parameter>item_offset</parameter> and
+      <parameter>item_length</parameter> to indicate which characters you
+      want shaped, so that HarfBuzz has access to any context.
+    </para>
+    <para>
+      You can also add Unicode code points directly with
+      <function>hb_buffer_add_codepoints()</function>. The arguments
+      to this function are the same as those for the UTF
+      encodings. But it is particularly important to note that
+      HarfBuzz does not do validity checking on the text that is added
+      to a buffer. Invalid code points will be replaced, but it is up
+      to you to do any deep-sanity checking necessary.
+    </para>
+    
   </section>
+  
   <section id="setting-buffer-properties">
     <title>Setting buffer properties</title>
     <para>
+      Buffers containing input characters still need several
+      properties set before HarfBuzz can shape their text correctly.
     </para>
-  </section>
-  <section id="what-about-the-other-scripts">
-    <title>What about the other scripts?</title>
     <para>
+      Initially, all buffers are set to the
+      <literal>HB_BUFFER_CONTENT_TYPE_INVALID</literal> content
+      type. After adding text, the buffer should be set to
+      <literal>HB_BUFFER_CONTENT_TYPE_UNICODE</literal> instead, which
+      indicates that it contains un-shaped input
+      characters. After shaping, the buffer will have the
+      <literal>HB_BUFFER_CONTENT_TYPE_GLYPHS</literal> content type.
+    </para>
+    <para>
+      <function>hb_buffer_add_utf8()</function> and the
+      other UTF functions set the content type of their buffer
+      automatically. But if you are reusing a buffer you may want to
+      check its state with
+      <function>hb_buffer_get_content_type(buffer)</function>. If
+      necessary you can set the content type with
+    </para>
+    <programlisting language="C">
+      hb_buffer_set_content_type(buf, HB_BUFFER_CONTENT_TYPE_UNICODE);
+    </programlisting>
+    <para>
+      to prepare for shaping.
+    </para>
+    <para>
+      Buffers also need to carry information about the script,
+      language, and text direction of their contents. You can set
+      these properties individually:
+    </para>
+    <programlisting language="C">
+      hb_buffer_set_direction(buf, HB_DIRECTION_LTR);
+      hb_buffer_set_script(buf, HB_SCRIPT_LATIN);
+      hb_buffer_set_language(buf, hb_language_from_string("en", -1));
+    </programlisting>
+    <para>
+      However, since these properties are often the repeated for
+      multiple text runs, you can also save them in a
+      <literal>hb_segment_properties_t</literal> for reuse:
+    </para>
+    <programlisting language="C">
+      hb_segment_properties_t *savedprops;
+      hb_buffer_get_segment_properties (buf, savedprops);
+      ...
+      hb_buffer_set_segment_properties (buf2, savedprops);
+    </programlisting>
+    <para>
+      HarfBuzz also provides getter functions to retrieve a buffer's
+      direction, script, and language properties individually.
+    </para>
+    <para>
+      HarfBuzz recognizes four text directions in
+      <type>hb_direction_t</type>: left-to-right
+      (<literal>HB_DIRECTION_LTR</literal>), right-to-left (<literal>HB_DIRECTION_RTL</literal>),
+      top-to-bottom (<literal>HB_DIRECTION_TTB</literal>), and
+      bottom-to-top (<literal>HB_DIRECTION_BTT</literal>).  For the
+      script property, HarfBuzz uses identifiers based on the
+      <ulink
+      url="https://unicode.org/iso15924/">ISO 15924
+      standard</ulink>. For languages, HarfBuzz uses tags based on the
+      <ulink url="https://tools.ietf.org/html/bcp47">IETF BCP 47</ulink> standard.
+    </para>
+    <para>
+      Helper functions are provided to convert character strings into
+      the necessary script and language tag types.
+    </para>
+    <para>
+      Two additional buffer properties to be aware of are the
+      "invisible glyph" and the replacement code point. The
+      replacement code point is inserted into buffer output in place of
+      any invalid code points encountered in the input. By default, it
+      is the Unicode <literal>REPLACEMENT CHARACTER</literal> code
+      point, <literal>U+FFFD</literal> "&#xFFFD;". You can change this with
+    </para>
+    <programlisting language="C">
+      hb_buffer_set_replacement_codepoint(buf, replacement);
+    </programlisting>
+    <para>
+      passing in the replacement Unicode code point as the
+      <parameter>replacement</parameter> parameter.
+    </para>
+    <para>
+      The invisible glyph is used to replace all output glyphs that
+      are invisible. By default, the standard space character
+      <literal>U+0020</literal> is used; you can replace this (for
+      example, when using a font that provides script-specific
+      spaces) with 
+    </para>
+    <programlisting language="C">
+      hb_buffer_set_invisible_glyph(buf, replacement_glyph);
+    </programlisting>
+    <para>
+      Do note that in the <parameter>replacement_glyph</parameter>
+      parameter, you must provide the glyph ID of the replacement you
+      wish to use, not the Unicode code point.
+    </para>
+    <para>
+      HarfBuzz supports a few additional flags you might want to set
+      on your buffer under certain circumstances. The
+      <literal>HB_BUFFER_FLAG_BOT</literal> and
+      <literal>HB_BUFFER_FLAG_EOT</literal> flags tell HarfBuzz
+      that the buffer represents the beginning or end (respectively)
+      of a text element (such as a paragraph or other block). Knowing
+      this allows HarfBuzz to apply certain contextual font features
+      when shaping, such as initial or final variants in connected
+      scripts.
+    </para>
+    <para>
+      <literal>HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES</literal>
+      tells HarfBuzz not to hide glyphs with the
+      <literal>Default_Ignorable</literal> property in Unicode. This 
+      property designates control characters and other non-printing
+      code points, such as joiners and variation selectors. Normally
+      HarfBuzz replaces them in the output buffer with zero-width
+      space glyphs (using the "invisible glyph" property discussed
+      above); setting this flag causes them to be printed, which can
+      be helpful for troubleshooting.
+    </para>
+    <para>
+      Conversely, setting the
+      <literal>HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES</literal> flag
+      tells HarfBuzz to remove <literal>Default_Ignorable</literal>
+      glyphs from the output buffer entirely. Finally, setting the
+      <literal>HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE</literal>
+      flag tells HarfBuzz not to insert the dotted-circle glyph
+      (<literal>U+25CC</literal>, "&#x25CC;"), which is normally
+      inserted into buffer output when broken character sequences are
+      encountered (such as combining marks that are not attached to a
+      base character).
     </para>
   </section>
+  
   <section id="customizing-unicode-functions">
     <title>Customizing Unicode functions</title>
     <para>
+      HarfBuzz requires some simple functions for accessing
+      information from the Unicode Character Database (such as the
+      <literal>General_Category</literal> (gc) and
+      <literal>Script</literal> (sc) properties) that is useful
+      for shaping, as well as some useful operations like composing and
+      decomposing code points.
+    </para>
+    <para>
+      HarfBuzz includes its own internal, lightweight set of Unicode
+      functions. At build time, it is also possible to compile support
+      for some other options, such as the Unicode functions provided
+      by GLib or the International Components for Unicode (ICU)
+      library. Generally, this option is only of interest for client
+      programs that have specific integration requirements or that do
+      a significant amount of customization.
+    </para>
+    <para>
+      If your program has access to other Unicode functions, however,
+      such as through a system library or application framework, you
+      might prefer to use those instead of the built-in
+      options. HarfBuzz supports this by implementing its Unicode
+      functions as a set of virtual methods that you can replace —
+      without otherwise affecting HarfBuzz's functionality.
+    </para>
+    <para>
+      The Unicode functions are specified in a structure called
+      <literal>unicode_funcs</literal> which is attached to each
+      buffer. But even though <literal>unicode_funcs</literal> is
+      associated with a <type>hb_buffer_t</type>, the functions
+      themselves are called by other HarfBuzz APIs that access
+      buffers, so it would be unwise for you to hook different
+      functions into different buffers.
+    </para>
+    <para>
+      In addition, you can mark your <literal>unicode_funcs</literal>
+      as immutable by calling
+      <function>hb_unicode_funcs_make_immutable (ufuncs)</function>.
+      This is especially useful if your code is a
+      library or framework that will have its own client programs. By
+      marking your Unicode function choices as immutable, you prevent
+      your own client programs from changing the
+      <literal>unicode_funcs</literal> configuration and introducing
+      inconsistencies and errors downstream.
+    </para>
+    <para>
+      You can retrieve the Unicode-functions configuration for
+      your buffer by calling <function>hb_buffer_get_unicode_funcs()</function>:
+    </para>
+    <programlisting language="C">
+      hb_unicode_funcs_t *ufunctions;
+      ufunctions = hb_buffer_get_unicode_funcs(buf);
+    </programlisting>
+    <para>
+      The current version of <literal>unicode_funcs</literal> uses six functions:
+    </para>
+    <itemizedlist>
+      <listitem>
+	<para>
+	  <function>hb_unicode_combining_class_func_t</function>:
+	  returns the Canonical Combining Class of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_general_category_func_t</function>:
+	  returns the General Category (gc) of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_mirroring_func_t</function>: returns
+	  the Mirroring Glyph code point (for bi-directional
+	  replacement) of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_script_func_t</function>: returns the
+	  Script (sc) property of a code point.
+      	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_compose_func_t</function>: returns the
+	  canonical composition of a sequence of two code points.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <function>hb_unicode_decompose_func_t</function>: returns
+	  the canonical decomposition of a code point.
+	</para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      Note, however, that future HarfBuzz releases may alter this set.
+    </para>
+    <para>
+      Each Unicode function has a corresponding setter, with which you
+      can assign a callback to your replacement function. For example,
+      to replace
+      <function>hb_unicode_general_category_func_t</function>, you can call
+    </para>
+    <programlisting language="C">
+      hb_unicode_funcs_set_general_category_func (*ufuncs, func, *user_data, destroy)	    
+    </programlisting>
+    <para>
+      Virtualizing this set of Unicode functions is primarily intended
+      to improve portability. There is no need for every client
+      program to make the effort to replace the default options, so if
+      you are unsure, do not feel any pressure to customize
+      <literal>unicode_funcs</literal>. 
     </para>
   </section>
+  
 </chapter>
diff --git a/docs/usermanual-clusters.xml b/docs/usermanual-clusters.xml
index b8d9191..a7b1658 100644
--- a/docs/usermanual-clusters.xml
+++ b/docs/usermanual-clusters.xml
@@ -158,7 +158,7 @@
     <para>
       For left-to-right scripts (LTR) and top-to-bottom scripts (TTB),
       HarfBuzz will preserve the monotonic property: client programs
-      are guaranteed that monotonically increasing initial clulster
+      are guaranteed that monotonically increasing initial cluster
       values will be returned as monotonically increasing final
       cluster values.
     </para>
@@ -167,7 +167,7 @@
       the directionality of the buffer itself is reversed for final
       output as a matter of design. Therefore, HarfBuzz inverts the
       monotonic property: client programs are guaranteed that
-      monotonically increasing initial clulster values will be
+      monotonically increasing initial cluster values will be
       returned as monotonically <emphasis>decreasing</emphasis> final
       cluster values.
     </para>
diff --git a/docs/usermanual-fonts-and-faces.xml b/docs/usermanual-fonts-and-faces.xml
index 5536004..b87f0e5 100644
--- a/docs/usermanual-fonts-and-faces.xml
+++ b/docs/usermanual-fonts-and-faces.xml
@@ -5,20 +5,449 @@
   <!ENTITY version SYSTEM "version.xml">
 ]>
 <chapter id="fonts-and-faces">
-  <title>Fonts and faces</title>
-  <section id="using-freetype">
+  <title>Fonts, faces, and output</title>
+    <para>
+      In the previous chapter, we saw how to set up a buffer and fill
+      it with text as Unicode code points. In order to shape this
+      buffer text with HarfBuzz, you will need also need a font
+      object.
+    </para>
+    <para>
+      HarfBuzz provides abstractions to help you cache and reuse the
+      heavier parts of working with binary fonts, so we will look at
+      how to do that. We will also look at how to work with the
+      FreeType font-rendering library and at how you can customize
+      HarfBuzz to work with other libraries.
+    </para>
+    <para>
+      Finally, we will look at how to work with OpenType variable
+      fonts, the latest update to the OpenType font format, and at
+      some other recent additions to OpenType.
+    </para>
+
+  <section id="fonts-and-faces-objects">
+    <title>Font and face objects</title>
+    <para>
+      The outcome of shaping a run of text depends on the contents of
+      a specific font file (such as the substitutions and positioning
+      moves in the 'GSUB' and 'GPOS' tables), so HarfBuzz makes
+      accessing those internals fast.
+    </para>
+    <para>
+      An <type>hb_face_t</type> represents a <emphasis>face</emphasis>
+      in HarfBuzz. This data type is a wrapper around an
+      <type>hb_blob_t</type> blob that holds the contents of a binary
+      font file. Since HarfBuzz supports TrueType Collections and
+      OpenType Collections (each of which can include multiple
+      typefaces), a HarfBuzz face also requires an index number
+      specifying which typeface in the file you want to use. Most of
+      the font files you will encounter in the wild include just a
+      single face, however, so most of the time you would pass in
+      <literal>0</literal> as the index when you create a face:
+    </para>
+    <programlisting language="C">
+      hb_blob_t* blob = hb_blob_create_from_file(file);
+      ...
+      hb_face_t* face = hb_face_create(blob, 0);
+    </programlisting>
+    <para>
+      On its own, a face object is not quite ready to use for
+      shaping. The typeface must be set to a specific point size in
+      order for some details (such as hinting) to work. In addition,
+      if the font file in question is an OpenType Variable Font, then
+      you may need to specify one or variation-axis settings (or a
+      named instance) in order to get the output you need.
+    </para>
+    <para>
+      In HarfBuzz, you do this by creating a <emphasis>font</emphasis>
+      object from your face.
+    </para>
+    <para>
+      Font objects also have the advantage of being considerably
+      lighter-weight than face objects (remember that a face contains
+      the contents of a binary font file mapped into memory). As a
+      result, you can cache and reuse a font object, but you could
+      also create a new one for each additional size you needed.
+      Creating new fonts incurs some additional overhead, of course,
+      but whether or not it is excessive is your call in the end. In
+      contrast, face objects are substantially larger, and you really
+      should cache them and reuse them whenever possible.
+    </para>
+    <para>
+      You can create a font object from a face object:
+    </para>
+    <programlisting language="C">
+      hb_font_t* hb_font = hb_font_create(hb_face);
+    </programlisting>
+    <para>
+      After creating a font, there are a few properties you should
+      set. Many fonts enable and disable hints based on the size it
+      is used at, so setting this is important for font
+      objects. <function>hb_font_set_ppem(font, x_ppem,
+      y_ppem)</function> sets the pixels-per-EM value of the font. You
+      can also set the point size of the font with
+      <function>hb_font_set_ppem(font, ptem)</function>. HarfBuzz uses the
+      industry standard 72 points per inch.
+    </para>
+    <para>
+      HarfBuzz lets you specify the degree subpixel precision you want
+      through a scaling factor. You can set horizontal and
+      vertical scaling factors on the
+      font by calling <function>hb_font_set_scale(font, x_scale,
+      y_scale)</function>. 
+    </para>
+    <para>
+      There may be times when you are handed a font object and need to
+      access the face object that it comes from. For that, you can call
+    </para>
+    <programlisting language="C">
+      hb_face = hb_font_get_face(hb_font);
+    </programlisting>
+    <para>
+      You can also create a font object from an existing font object
+      using the <function>hb_font_create_sub_font()</function>
+      function. This creates a child font object that is initiated
+      with the same attributes as its parent; it can be used to
+      quickly set up a new font for the purpose of overriding a specific
+      font-functions method.
+    </para>
+    <para>
+      All face objects and font objects are lifecycle-managed by
+      HarfBuzz. After creating a face, you increase its reference
+      count with <function>hb_face_reference(face)</function> and
+      decrease it with
+      <function>hb_face_destroy(face)</function>. Likewise, you
+      increase the reference count on a font with
+      <function>hb_font_reference(font)</function> and decrease it
+      with <function>hb_font_destroy(font)</function>.
+    </para>
+    <para>
+      You can also attach user data to face objects and font objects.
+    </para>
+  </section>
+
+ <section id="fonts-and-faces-custom-functions">
+    <title>Customizing font functions</title>
+    <para>
+      During shaping, HarfBuzz frequently needs to query font objects
+      to get at the contents and parameters of the glyphs in a font
+      file. It includes a built-in set of functions that is tailored
+      to working with OpenType fonts. However, as was the case with
+      Unicode functions in the buffers chapter, HarfBuzz also wants to
+      make it easy for you to assign a substitute set of font
+      functions if you are developing a program to work with a library
+      or platform that provides its own font functions. 
+    </para>
+    <para>
+      Therefore, the HarfBuzz API defines a set of virtual
+      methods for accessing font-object properties, and you can
+      replace the defaults with your own selections without
+      interfering with the shaping process. Each font object in
+      HarfBuzz includes a structure called
+      <literal>font_funcs</literal> that serves as a vtable for the
+      font object. The virtual methods in
+      <literal>font_funcs</literal> are:
+    </para>
+    <itemizedlist>
+      <listitem>
+    <para>
+      <function>hb_font_get_font_h_extents_func_t</function>: returns
+      the extents of the font for horizontal text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_font_v_extents_func_t</function>: returns
+      the extents of the font for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_nominal_glyph_func_t</function>: returns
+      the font's nominal glyph for a given code point.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_variation_glyph_func_t</function>: returns
+      the font's glyph for a given code point when it is followed by a
+      given Variation Selector.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_nominal_glyphs_func_t</function>: returns
+      the font's nominal glyphs for a series of code points.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_advance_func_t</function>: returns
+      the advance for a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_h_advance_func_t</function>: returns
+      the advance for a glyph for horizontal text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_v_advance_func_t</function>:returns
+      the advance for a glyph for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_advances_func_t</function>: returns
+      the advances for a series of glyphs.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_h_advances_func_t</function>: returns
+      the advances for a series of glyphs for horizontal text .
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_v_advances_func_t</function>: returns
+      the advances for a series of glyphs for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_origin_func_t</function>: returns
+      the origin coordinates of a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_h_origin_func_t</function>: returns
+      the origin coordinates of a glyph for horizontal text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_v_origin_func_t</function>: returns
+      the origin coordinates of a glyph for vertical text.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_extents_func_t</function>: returns
+      the extents for a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_contour_point_func_t</function>:
+      returns the coordinates of a specific contour point from a glyph.
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_name_func_t</function>: returns the
+      name of a glyph (from its glyph index).
+    </para>
+      </listitem>
+      <listitem>
+    <para>
+      <function>hb_font_get_glyph_from_name_func_t</function>: returns
+      the glyph index that corresponds to a given glyph name.
+    </para>
+      </listitem>
+    </itemizedlist>
+    <para>
+      You can fetch the font-functions configuration for a font object
+      by calling <function>hb_font_get_font_funcs()</function>:
+    </para>
+    <programlisting language="C">
+      hb_font_funcs_t *ffunctions;
+      ffunctions = hb_font_get_font_funcs (font);
+    </programlisting>
+    <para>
+      The individual methods can each be replaced with their own setter
+      function, such as
+      <function>hb_font_funcs_set_nominal_glyph_func(*ffunctions,
+      func, *user_data, destroy)</function>. 
+    </para>
+    <para>
+      Font-functions structures can be reused for multiple font
+      objects, and can be reference counted with
+      <function>hb_font_funcs_reference()</function> and
+      <function>hb_font_funcs_destroy()</function>. Just like other
+      objects in HarfBuzz, you can set user-data for each
+      font-functions structure and assign a destroy callback for
+      it.
+    </para>
+    <para>
+      You can also mark a font-functions structure as immutable,
+      with <function>hb_font_funcs_make_immutable()</function>. This
+      is especially useful if your code is a library or framework that
+      will have its own client programs. By marking your
+      font-functions structures as immutable, you prevent your client
+      programs from changing the configuration and introducing
+      inconsistencies and errors downstream.
+    </para>
+  </section>
+
+  <section id="fonts-and-faces-native-opentype">
+    <title>Font objects and HarfBuzz's native OpenType implementation</title>
+    <para>
+      By default, whenever HarfBuzz creates a font object, it will
+      configure the font to use a built-in set of font functions that
+      supports contemporary OpenType font internals. If you want to
+      work with OpenType or TrueType fonts, you should be able to use
+      these functions without difficulty.
+    </para>
+    <para>
+      Many of the methods in the font-functions structure deal with
+      the fundamental properties of glyphs that are required for
+      shaping text: extents (the maximums and minimums on each axis),
+      origins (the <literal>(0,0)</literal> coordinate point which
+      glyphs are drawn in reference to), and advances (the amount that
+      the cursor needs to be moved after drawing each glyph, including
+      any empty space for the glyph's side bearings).
+    </para>
+    <para>
+      As you can see in the list of functions, there are separate "horizontal"
+      and "vertical" variants depending on whether the text is set in
+      the horizontal or vertical direction. For some scripts, fonts
+      that are designed to support text set horizontally or vertically (for
+      example, in Japanese) may include metrics for both text
+      directions. When fonts don't include this information, HarfBuzz
+      does its best to transform what the font provides.
+    </para>
+    <para>
+      In addition to the direction-specific functions, HarfBuzz
+      provides some higher-level functions for fetching information
+      like extents and advances for a glyph. If you call
+    </para>
+    <programlisting language="C">
+      hb_font_get_glyph_advance_for_direction(font, direction, extents);
+    </programlisting>
+    <para>
+      then you can provide any <type>hb_direction_t</type> as the
+      <parameter>direction</parameter> parameter, and HarfBuzz will
+      use the correct function variant for the text direction. There
+      are similar higher-level versions of the functions for fetching
+      extents, origin coordinates, and contour-point
+      coordinates. There are also addition and subtraction functions
+      for moving points with respect to the origin.
+    </para>
+    <para>
+      There are also methods for fetching the glyph ID that
+      corresponds to a Unicode code point (possibly when followed by a
+      variation-selector code point), fetching the glyph name from the
+      font, and fetching the glyph ID that corresponds to a glyph name
+      you already have.
+    </para>
+    <para>
+      HarfBuzz also provides functions for converting between glyph
+      names and string
+      variables. <function>hb_font_glyph_to_string(font, glyph, s,
+      size)</function> retrieves the name for the glyph ID
+      <parameter>glyph</parameter> from the font object. It generates a
+      generic name of the form <literal>gidDDD</literal> (where DDD is
+      the glyph index) if there is no name for the glyph in the
+      font. The <function>hb_font_glyph_from_string(font, s, len,
+      glyph)</function> takes an input string <parameter>s</parameter>
+      and looks for a glyph with that name in the font, returning its
+      glyph ID in the <parameter>glyph</parameter>
+      output parameter. It automatically parses
+      <literal>gidDDD</literal> and <literal>uniUUUU</literal> strings.
+    </para>
+  </section>
+
+
+  <!-- Commenting out FreeType integration section-holder for now. May move
+       to the full-blown Integration Chapter. -->
+  
+  <!--   <section id="fonts-and-faces-freetype">
     <title>Using FreeType</title>
     <para>
+
     </para>
-  </section>
-  <section id="using-harfbuzzs-native-opentype-implementation">
-    <title>Using HarfBuzz's native OpenType implementation</title>
     <para>
+      
     </para>
-  </section>
-  <section id="using-your-own-font-functions">
-    <title>Using your own font functions</title>
+  </section> -->
+
+  <section id="fonts-and-faces-variable">
+    <title>Working with OpenType Variable Fonts</title>
     <para>
+      If you are working with OpenType Variable Fonts, there are a few
+      additional functions you should use to specify the
+      variation-axis settings of your font object. Without doing so,
+      your variable font's font object can still be used, but only at
+      the default setting for every axis (which, of course, is
+      sometimes what you want, but does not cover general usage).
+    </para>
+    <para>
+      HarfBuzz manages variation settings in the
+      <type>hb_variation_t</type> data type, which holds a <property>tag</property> for the
+      variation-axis identifier tag and a <property>value</property> for its
+      setting. You can retrieve the list of variation axes in a font
+      binary from the face object (not from a font object, notably) by
+      calling <function>hb_ot_var_get_axis_count(face)</function> to
+      find the number of axes, then using
+      <function>hb_ot_var_get_axis_infos()</function> to collect the 
+      axis structures:
+    </para>
+    <programlisting language="C">
+      axes = hb_ot_var_get_axis_count(face);
+      ...
+      hb_ot_var_get_axis_infos(face, 0, axes, axes_array);
+    </programlisting>
+    <para>
+      For each axis returned in the array, you can can access the
+      identifier in its <property>tag</property>. HarfBuzz also has
+      tag definitions predefined for the five standard axes specified
+      in OpenType (<literal>ital</literal> for italic,
+      <literal>opsz</literal> for optical size,
+      <literal>slnt</literal> for slant, <literal>wdth</literal> for
+      width, and <literal>wght</literal> for weight). Each axis also
+      has a <property>min_value</property>, a
+      <property>default_value</property>, and a <property>max_value</property>.
+    </para>
+    <para>
+      To set your font object's variation settings, you call the
+      <function>hb_font_set_variations()</function> function with an
+      array of <type>hb_variation_t</type> variation settings. Let's
+      say our font has weight and width axes. We need to specify each
+      of the axes by tag and assign a value on the axis:
+    </para>
+    <programlisting language="C">
+      unsigned int variation_count = 2;
+      hb_variation_t variation_data[variation_count];
+      variation_data[0].tag = HB_OT_TAG_VAR_AXIS_WIDTH;
+      variation_data[1].tag = HB_OT_TAG_VAR_AXIS_WEIGHT;
+      variation_data[0].value = 80;
+      variation_data[1].value = 750;
+      ...
+      hb_font_set_variations(font, variation_data, variation_count);
+    </programlisting>
+    <para>
+      That should give us a slightly condensed font ("normal" on the
+      <literal>wdth</literal> axis is 100) at a noticeably bolder
+      weight ("regular" is 400 on the <literal>wght</literal> axis).
+    </para>
+    <para>
+      In practice, though, you should always check that the value you
+      want to set on the axis is within the
+      [<property>min_value</property>,<property>max_value</property>]
+      range actually implemented in the font's variation axis. After
+      all, a font might only provide lighter-than-regular weights, and
+      setting a heavier value on the <literal>wght</literal> axis will
+      not change that. 
+    </para>
+    <para>
+      Once your variation settings are specified on your font object,
+      however, shaping with a variable font is just like shaping a
+      static font.
     </para>
   </section>
-</chapter>
+
+ </chapter>
diff --git a/docs/usermanual-install-harfbuzz.xml b/docs/usermanual-install-harfbuzz.xml
index a1e7ab0..2b61ce8 100644
--- a/docs/usermanual-install-harfbuzz.xml
+++ b/docs/usermanual-install-harfbuzz.xml
@@ -246,7 +246,7 @@
 	  <listitem>
 	    <para>
 	     Use <ulink url="https://developer.gnome.org/glib/">GLib</ulink>. <emphasis>(Default = auto)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the GLib
 	      library.  The default setting is to check for the
@@ -297,7 +297,7 @@
 	  <listitem>
 	    <para>
 	      Use <ulink url="https://www.freedesktop.org/wiki/Software/fontconfig/">Fontconfig</ulink>. <emphasis>(Default = auto)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the Fontconfig
 	      library, which provides font-matching functions and
@@ -317,7 +317,7 @@
 	  <listitem>
 	    <para>
 	      Use the <ulink url="http://site.icu-project.org/home">ICU</ulink> library. <emphasis>(Default = auto)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the
 	      <emphasis>International Components for
@@ -331,29 +331,11 @@
 	</varlistentry>
 	
 	<varlistentry>
-	  <term><command>--with-ucdn</command></term>
-	  <listitem>
-	    <para>
-	      Use HarfBuzz's <ulink url="https://github.com/harfbuzz/harfbuzz/tree/master/src/hb-ucdn">built-in UCDN library</ulink>. <emphasis>(Default = auto)</emphasis>
-	    </para>	    
-	    <para>
-	      The HarfBuzz source tree includes a <emphasis>Unicode
-	      Database and Normalization</emphasis> (UCDN) library
-	      that provides access to basic character properties in
-	      the Unicode Character Database (UCD) as well as low-level
-	      normalization functions. HarfBuzz can be built without
-	      this UCDN support if the usage of a different UCDN
-	      library is desired.
-	    </para>
-	  </listitem>
-	</varlistentry>
-	
-	<varlistentry>
 	  <term><command>--with-graphite2</command></term>
 	  <listitem>
 	    <para>
 	      Use the <ulink url="http://graphite.sil.org/">Graphite2</ulink> library. <emphasis>(Default = no)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the Graphite2
 	      library, which provides support for the Graphite shaping
@@ -367,7 +349,7 @@
 	  <listitem>
 	    <para>
 	      Use the <ulink url="https://www.freetype.org/">FreeType</ulink> library. <emphasis>(Default = auto)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the FreeType
 	      font-rendering library. The default setting is to check for the
@@ -384,7 +366,7 @@
 	      Use the <ulink
 	      url="https://docs.microsoft.com/en-us/windows/desktop/intl/uniscribe">Uniscribe</ulink>
 	      library (experimental). <emphasis>(Default = no)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the Uniscribe
 	      font-rendering library. Uniscribe is available on
@@ -400,7 +382,7 @@
 	  <listitem>
 	    <para>
 	      Use the <ulink url="https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal">DirectWrite</ulink> library (experimental). <emphasis>(Default = no)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the DirectWrite
 	      font-rendering library. DirectWrite is available on
@@ -416,7 +398,7 @@
 	  <listitem>
 	    <para>
 	      Use the <ulink url="https://developer.apple.com/documentation/coretext">CoreText</ulink> library. <emphasis>(Default = no)</emphasis>
-	    </para>	    
+	    </para>
 	    <para>
 	      This option enables or disables usage of the CoreText
 	      library. CoreText is available on macOS and iOS systems.
diff --git a/docs/usermanual-object-model.xml b/docs/usermanual-object-model.xml
new file mode 100644
index 0000000..f571c47
--- /dev/null
+++ b/docs/usermanual-object-model.xml
@@ -0,0 +1,258 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="object-model">
+  <title>The HarfBuzz object model</title>
+  <section id="object-model-intro">
+    <title>An overview of data types in HarfBuzz</title>
+    <para>
+      HarfBuzz features two kinds of data types: non-opaque,
+      pass-by-value types and opaque, heap-allocated types.  This kind
+      of separation is common in C libraries that have to provide
+      API/ABI compatibility (almost) indefinitely. 
+    </para>
+    <para>
+      <emphasis>Value types:</emphasis> The non-opaque, pass-by-value
+      types include integer types, enums, and small structs.  Exposing
+      a struct in the public API makes it impossible to expand the
+      struct in the future. As such, exposing structs is reserved for
+      cases where it’s extremely inefficient to do otherwise.
+    </para>
+    <para>
+      In HarfBuzz, several structs, like <literal>hb_glyph_info_t</literal> and
+      <literal>hb_glyph_position_t</literal>, fall into that efficiency-sensitive
+      category and are non-opaque.
+    </para>
+    <para>
+      For all non-opaque structs where future extensibility may be
+      necessary, reserved members are included to hold space for
+      possible future members.  As such, it’s important to provide
+      <function>equal()</function>, and <function>hash()</function>
+      methods for such structs, allowing users of the API do
+      effectively deal with the type without having to 
+      adapt their code to future changes. 
+    </para>
+    <para>
+      Important value types provided by HarfBuzz include the structs
+      for working with Unicode code points, glyphs, and tags for font
+      tables and features, as well as the enums for many Unicode and
+      OpenType properties.
+    </para>
+  </section>
+  
+  <section id="object-model-object-types">
+    <title>Objects in HarfBuzz</title>
+    <para>
+      <emphasis>Object types:</emphasis> Opaque struct types are used
+      for what HarfBuzz loosely calls "objects."  This doesn’t have
+      much to do with the terminology from object-oriented programming
+      (OOP), although some of the concepts are similar.
+    </para>
+    <para>
+      In HarfBuzz, all object types provide certain
+      lifecycle-management APIs.  Objects are reference-counted, and
+      constructed with various <function>create()</function> methods, referenced via
+      <function>reference()</function> and dereferenced using
+      <function>destroy()</function>.
+    </para>
+    <para>
+      For example,
+      the <literal>hb_buffer_t</literal> object has
+      <function>hb_buffer_create()</function> as its constructor,
+      <function>hb_buffer_reference()</function> to reference, and
+      <function>hb_buffer_destroy()</function> to dereference. 
+    </para>
+    <para>
+      After construction, each object's properties are accessible only
+      through the setter and getter functions described in the API
+      Reference manual.
+    </para>
+    <para>
+      Key object types provided by HarfBuzz include:
+    </para>
+    <itemizedlist spacing="compact">
+      <listitem>
+	<para>
+	  <emphasis>blobs</emphasis>, which act as low-level wrappers around binary
+	  data. Blobs are typically used to hold the contents of a
+	  binary font file.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>faces</emphasis>, which represent typefaces from a
+	  font file, but without specific parameters (such as size) set.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>fonts</emphasis>, which represent instances of a
+	  face with all of their parameters specified.
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>buffers</emphasis>, which hold Unicode code points
+	  for characters (before shaping) and the shaped glyph output
+	  (after shaping).
+	</para>
+      </listitem>
+      <listitem>
+	<para>
+	  <emphasis>shape plans</emphasis>, which store the settings
+	  that HarfBuzz will use when shaping a particular text
+	  segment. Shape plans are not generally used by client
+	  programs directly, but as we will see in a later chapter,
+	  they are still valuable to understand.
+	</para>
+      </listitem>
+    </itemizedlist>
+	
+  </section>
+
+  
+  
+  <section id="object-model-lifecycle">
+    <title>Object lifecycle management</title>
+    <para>
+      Each object type in HarfBuzz provides a
+      <function>create()</function> method. Some object types provide
+      additional variants of <function>create()</function> to handle
+      special cases or to speed up common tasks; those variants are
+      documented in the API reference. For example,
+      <function>hb_blob_create_from_file()</function> constructs a new
+      blob directly from the contents of a file.
+    </para>
+    <para>
+      All objects are created with an initial reference count of
+      <literal>1</literal>. Client programs can increase the reference
+      count on an object by calling its
+      <function>reference()</function> method. Whenever a client
+      program is finished with an object, it should call its 
+      corresponding <function>destroy()</function> method. The destroy
+      method will decrease the reference count on the object and,
+      whenever the reference count reaches zero, it will also destroy
+      the object and free all of the associated memory.
+    </para>
+    <para>
+      All of HarfBuzz's object-lifecycle-management APIs are
+      thread-safe (unless you compiled HarfBuzz from source with the
+      <literal>HB_NO_MT</literal> configuration flag), even when the
+      object as a whole is not thread-safe. 
+      It is also permissible to <function>reference()</function> or to 
+      <function>destroy()</function> the <literal>NULL</literal>
+      value.
+    </para>
+    <para>
+      Some objects are thread-safe after they have been constructed
+      and set up. The general pattern is to
+      <function>create()</function> the object, make a few
+      <function>set_*()</function> calls to set up the
+      object, and then use it without further modification.
+    </para>
+    <para>
+      To ensure that such an object is not modified, client programs
+      can explicitly mark an object as immutable. HarfBuzz provides
+      <function>make_immutable()</function> methods to mark an object
+      as immutable and <function>is_immutable()</function> methods to
+      test whether or not an object is immutable. Attempts to use
+      setter functions on immutable objects will fail silently; see the API
+      Reference manual for specifics. 
+    </para>
+    <para>
+      Note also that there are no "make mutable" methods. If client
+      programs need to alter an object previously marked as immutable,
+      they will need to make a duplicate of the original.
+    </para>
+    <para>
+      Finally, object constructors (and, indeed, as much of the
+      shaping API as possible) will never return
+      <literal>NULL</literal>.  Instead, if there is an allocation
+      error, each constructor will return an “empty” object
+      singleton.
+    </para>
+    <para>
+      These empty-object singletons are inert and safe (although
+      typically useless) to pass around.  This design choice avoids
+      having to check for <literal>NULL</literal> pointers all
+      throughout the code.
+    </para>
+    <para>
+      In addition, this “empty” object singleton can also be accessed
+      using the <function>get_empty()</function> method of the object
+      type in question.
+    </para>
+  </section>
+
+  
+  <section id="object-model-user-data">
+    <title>User data</title>
+    <para>
+      To better integrate with client programs, HarfBuzz's objects
+      offer a "user data" mechanism that can be used to attach
+      arbitrary data to the object.  User-data attachment can be
+      useful for tying the lifecycles of various pieces of data
+      together, or for creating language bindings. 
+    </para>
+    <para>
+      Each object type has a <function>set_user_data()</function>
+      method and a <function>get_user_data()</function> method. The
+      <function>set_user_data()</function> methods take a client-provided
+      <literal>key</literal> and a pointer,
+      <literal>user_data</literal>, pointing to the data itself. Once
+      the key-data pair has been attached to the object, the
+      <function>get_user_data()</function> method can be called with
+      the key, returning the <function>user_data</function> pointer.
+    </para>
+    <para>
+      The <function>set_user_data()</function> methods also support an
+      optional <function>destroy</function> callback. Client programs
+      can set the <function>destroy</function> callback and receive
+      notification from HarfBuzz whenever the object is destructed.
+    </para>
+    <para>
+      Finally, each <function>set_user_data()</function> method allows
+      the client program to set a <literal>replace</literal> Boolean
+      indicating whether or not the function call should replace any
+      existing <literal>user_data</literal>
+      associated with the specified key.
+    </para>
+  </section>  
+
+  
+  
+  <section id="object-model-blobs">
+    <title>Blobs</title>
+    <para>
+      While most of HarfBuzz's object types are specific to the
+      shaping process, <emphasis>blobs</emphasis> are somewhat
+      different.
+    </para>
+    <para>
+      Blobs are an abstraction desgined to negotiate lifecycle and
+      permissions for raw pieces of data.  For example, when you load
+      the raw font data into memory and want to pass it to HarfBuzz,
+      you do so in a <literal>hb_blob_t</literal> wrapper.
+    </para>
+    <para>
+      This allows you to take advantage of HarffBuzz's
+      reference-counting and <function>destroy</function>
+      callbacks. If you allocated the memory for the data using 
+      <function>malloc()</function>, you would create the blob using
+    </para>
+    <programlisting language="C">
+      hb_blob_create (data, length, HB_MEMORY_MODE_WRITABLE, NULL, free)
+    </programlisting>
+    <para>
+      That way, HarfBuzz will call <function>free()</function> on the
+      allocated memory whenever the blob drops its last reference and
+      is deconstructed.  Consequently, the user code can stop worrying
+      about freeing memory and let the reference-counting machinery
+      take care of that. 
+    </para>
+  </section>
+  
+</chapter>
diff --git a/docs/usermanual-opentype-features.xml b/docs/usermanual-opentype-features.xml
index 51ff55a..3eedab3 100644
--- a/docs/usermanual-opentype-features.xml
+++ b/docs/usermanual-opentype-features.xml
@@ -6,14 +6,299 @@
 ]>
 <chapter id="shaping-and-shape-plans">
   <title>Shaping and shape plans</title>
-  <section id="opentype-features">
+  <para>
+    Once you have your face and font objects configured as desired and
+    your input buffer is filled with the characters you need to shape,
+    all you need to do is call <function>hb_shape()</function>.
+  </para>
+  <para>
+    HarfBuzz will return the shaped version of the text in the same
+    buffer that you provided, but it will be in output mode. At that
+    point, you can iterate through the glyphs in the buffer, drawing
+    each one at the specified position or handing them off to the
+    appropriate graphics library.
+  </para>
+  <para>
+    For the most part, HarfBuzz's shaping step is straightforward from
+    the outside. But that doesn't mean there will never be cases where
+    you want to look under the hood and see what is happening on the
+    inside. HarfBuzz provides facilities for doing that, too.
+  </para>
+  
+  <section id="shaping-buffer-output">
+    <title>Shaping and buffer output</title>
+    <para>
+      The <function>hb_shape()</function> function call takes four arguments: the font
+      object to use, the buffer of characters to shape, an array of
+      user-specified features to apply, and the length of that feature
+      array. The feature array can be NULL, so for the sake of
+      simplicity we will start with that case.
+    </para>
+    <para>
+      Internally, HarfBuzz looks  at the tables of the font file to
+      determine where glyph classes, substitutions, and positioning
+      are defined, using that information to decide which
+      <emphasis>shaper</emphasis> to use (<literal>ot</literal> for
+      OpenType fonts, <literal>aat</literal> for Apple Advanced
+      Typography fonts, and so on). It also looks at the direction,
+      script, and language properties of the segment to figure out
+      which script-specific shaping model is needed (at least, in
+      shapers that support multiple options).      
+    </para>
+    <para>
+      If a font has a GDEF table, then that is used for
+      glyph classes; if not, HarfBuzz will fall back to Unicode
+      categorization by code point. If a font has an AAT "morx" table,
+      then it is used for substitutions; if not, but there is a GSUB
+      table, then the GSUB table is used. If the font has an AAT
+      "kerx" table, then it is used for positioning; if not, but
+      there is a GPOS table, then the GPOS table is used. If neither
+      table is found, but there is a "kern" table, then HarfBuzz will
+      use the "kern" table. If there is no "kerx", no GPOS, and no
+      "kern", HarfBuzz will fall back to positioning marks itself.
+    </para>
+    <para>
+      With a well-behaved OpenType font, you expect GDEF, GSUB, and
+      GPOS tables to all be applied. HarfBuzz implements the
+      script-specific shaping models in internal functions, rather
+      than in the public API.
+    </para>
+    <para>
+      The algorithms
+      used for complex scripts can be quite involved; HarfBuzz tries
+      to be compatible with the OpenType Layout specification
+      and, wherever there is any ambiguity, HarfBuzz attempts to replicate the
+      output of Microsoft's Uniscribe engine. See the <ulink
+      url="https://docs.microsoft.com/en-us/typography/script-development/standard">Microsoft
+      Typography pages</ulink> for more detail.
+    </para>
+    <para>
+      In general, though, all that you need to know is that
+      <function>hb_shape()</function> returns the results of shaping
+      in the same buffer that you provided. The buffer's content type
+      will now be set to
+      <literal>HB_BUFFER_CONTENT_TYPE_GLYPHS</literal>, indicating
+      that it contains shaped output, rather than input text. You can
+      now extract the glyph information and positioning arrays:
+    </para>
+    <programlisting language="C">
+      hb_glyph_info_t *glyph_info    = hb_buffer_get_glyph_infos(buf, &amp;glyph_count);
+      hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &amp;glyph_count);
+    </programlisting>
+    <para>
+      The glyph information array holds a <type>hb_glyph_info_t</type>
+      for each output glyph, which has two fields:
+      <parameter>codepoint</parameter> and
+      <parameter>cluster</parameter>. Whereas, in the input buffer,
+      the <parameter>codepoint</parameter> field contained the Unicode
+      code point, it now contains the glyph ID of the corresponding
+      glyph in the font. The <parameter>cluster</parameter> field is
+      an integer that you can use to help identify when shaping has
+      reordered, split, or combined code points; we will say more
+      about that in the next chapter.
+    </para>
+    <para>
+      The glyph positions array holds a corresponding
+      <type>hb_glyph_position_t</type> for each output glyph,
+      containing four fields: <parameter>x_advance</parameter>,
+      <parameter>y_advance</parameter>,
+      <parameter>x_offset</parameter>, and
+      <parameter>y_offset</parameter>. The advances tell you how far
+      you need to move the drawing point after drawing this glyph,
+      depending on whether you are setting horizontal text (in which
+      case you will have x advances) or vertical text (for which you
+      will have y advances). The x and y offsets tell you where to
+      move to start drawing the glyph; usually you will have both and
+      x and a y offset, regardless of the text direction.
+    </para>
+    <para>
+      Most of the time, you will rely on a font-rendering library or
+      other graphics library to do the actual drawing of glyphs, so
+      you will need to iterate through the glyphs in the buffer and
+      pass the corresponding values off.
+    </para>
+  </section>
+  
+  <section id="shaping-opentype-features">
     <title>OpenType features</title>
     <para>
+      OpenType features enable fonts to include smart behavior,
+      implemented as "lookup" rules stored in the GSUB and GPOS
+      tables. The OpenType specification defines a long list of
+      standard features that fonts can use for these behaviors; each
+      feature has a four-character reserved name and a well-defined
+      semantic meaning.
+    </para>
+    <para>
+      Some OpenType features are defined for the purpose of supporting
+      complex-script shaping, and are automatically activated, but
+      only when a buffer's script property is set to a script that the
+      feature supports.
+    </para>
+    <para>
+      Other features are more generic and can apply to several (or
+      any) script, and shaping engines are expected to implement
+      them. By default, HarfBuzz activates several of these features
+      on every text run. They include <literal>ccmp</literal>,
+      <literal>locl</literal>, <literal>mark</literal>,
+      <literal>mkmk</literal>, and <literal>rlig</literal>.
+    </para>
+    <para>
+      In addition, if the text direction is horizontal, HarfBuzz
+      also applies the <literal>calt</literal>,
+      <literal>clig</literal>, <literal>curs</literal>,
+      <literal>kern</literal>, <literal>liga</literal>,
+      <literal>rclt</literal>, and <literal>frac</literal> features.
+    </para>
+    <para>
+      If the text direction is vertical, HarfBuzz applies
+      the <literal>vert</literal> feature by default.
+    </para>
+    <para>
+      Still other features are designed to be purely optional and left
+      up to the application or the end user to enable or disable as desired.
+    </para>
+    <para>
+      You can adjust the set of features that HarfBuzz applies to a
+      buffer by supplying an array of <type>hb_feature_t</type>
+      features as the third argument to
+      <function>hb_shape()</function>. For a simple case, let's just
+      enable the <literal>dlig</literal> feature, which turns on any
+      "discretionary" ligatures in the font:
+    </para>
+    <programlisting language="C">
+      hb_feature_t userfeatures[1];
+      userfeatures[0].tag = HB_TAG('d','l','i','g');
+      userfeatures[0].value = 1;
+      userfeatures[0].start = HB_FEATURE_GLOBAL_START;
+      userfeatures[0].end = HB_FEATURE_GLOBAL_END;
+    </programlisting>
+    <para>
+      <literal>HB_FEATURE_GLOBAL_END</literal> and
+      <literal>HB_FEATURE_GLOBAL_END</literal> are macros we can use
+      to indicate that the features will be applied to the entire
+      buffer. We could also have used a literal <literal>0</literal>
+      for the start and a <literal>-1</literal> to indicate the end of
+      the buffer (or have selected other start and end positions, if needed).
+    </para>
+    <para>
+      When we pass the <varname>userfeatures</varname> array to
+      <function>hb_shape()</function>, any discretionary ligature
+      substitutions from our font that match the text in our buffer
+      will get performed:
+    </para>
+    <programlisting language="C">
+      hb_shape(font, buf, userfeatures, num_features);
+    </programlisting>
+    <para>
+      Just like we enabled the <literal>dlig</literal> feature by
+      setting its <parameter>value</parameter> to
+      <literal>1</literal>, you would disable a feature by setting its
+      <parameter>value</parameter> to <literal>0</literal>. Some
+      features can take other <parameter>value</parameter> settings;
+      be sure you read the full specification of each feature tag to
+      understand what it does and how to control it.
     </para>
   </section>
-  <section id="plans-and-caching">
+
+  <section id="shaping-shaper-selection">
+    <title>Shaper selection</title>
+    <para>
+      The basic version of <function>hb_shape()</function> determines
+      its shaping strategy based on examining the capabilities of the
+      font file. OpenType font tables cause HarfBuzz to try the
+      <literal>ot</literal> shaper, while AAT font tables cause HarfBuzz to try the
+      <literal>aat</literal> shaper. 
+    </para>
+    <para>
+      In the real world, however, a font might include some unusual
+      mix of tables, or one of the tables might simply be broken for
+      the script you need to shape. So, sometimes, you might not
+      want to rely on HarfBuzz's process for deciding what to do, and
+      just tell <function>hb_shape()</function> what you want it to try.
+    </para>
+    <para>
+      <function>hb_shape_full()</function> is an alternate shaping
+      function that lets you supply a list of shapers for HarfBuzz to
+      try, in order, when shaping your buffer. For example, if you
+      have determined that HarfBuzz's attempts to work around broken
+      tables gives you better results than the AAT shaper itself does,
+      you might move the AAT shaper to the end of your list of
+      preferences and call <function>hb_shape_full()</function>
+    </para>
+    <programlisting language="C">
+      char *shaperprefs[3] = {"ot", "default", "aat"};
+      ...
+      hb_shape_full(font, buf, userfeatures, num_features, shaperprefs);
+    </programlisting>
+    <para>
+      to get results you are happier with.
+    </para>
+    <para>
+      You may also want to call
+      <function>hb_shape_list_shapers()</function> to get a list of
+      the shapers that were built at compile time in your copy of HarfBuzz.
+    </para>
+  </section>
+  
+  <section id="shaping-plans-and-caching">
     <title>Plans and caching</title>
     <para>
+      Internally, HarfBuzz uses a structure called a shape plan to
+      track its decisions about how to shape the contents of a
+      buffer. The <function>hb_shape()</function> function builds up the shape plan by
+      examining segment properties and by inspecting the contents of
+      the font.
+    </para>
+    <para>
+      This process can involve some decision-making and
+      trade-offs — for example, HarfBuzz inspects the GSUB and GPOS
+      lookups for the script and language tags set on the segment
+      properties, but it falls back on the lookups under the
+      <literal>DFLT</literal> tag (and sometimes other common tags)
+      if there are actually no lookups for the tag requested.
+    </para>
+    <para>
+      HarfBuzz also includes some work-arounds for
+      handling well-known older font conventions that do not follow
+      OpenType or Unicode specifications, for buggy system fonts, and for
+      peculiarities of Microsoft Uniscribe. All of that means that a
+      shape plan, while not something that you should edit directly in
+      client code, still might be an object that you want to
+      inspect. Furthermore, if resources are tight, you might want to
+      cache the shape plan that HarfBuzz builds for your buffer and
+      font, so that you do not have to rebuild it for every shaping call.
+    </para>
+    <para>
+      You can create a cacheable shape plan with
+      <function>hb_shape_plan_create_cached(face, props,
+      user_features, num_user_features, shaper_list)</function>, where
+      <parameter>face</parameter> is a face object (not a font object,
+      notably), <parameter>props</parameter> is an
+      <type>hb_segment_properties_t</type>,
+      <parameter>user_features</parameter> is an array of
+      <type>hb_feature_t</type>s (with length
+      <parameter>num_user_features</parameter>), and
+      <parameter>shaper_list</parameter> is a list of shapers to try.
+    </para>
+    <para>
+      Shape plans are objects in HarfBuzz, so there are
+      reference-counting functions and user-data attachment functions
+      you can
+      use. <function>hb_shape_plan_reference(shape_plan)</function>
+      increases the reference count on a shape plan, while
+      <function>hb_shape_plan_destroy(shape_plan)</function> decreases
+      the reference count, destroying the shape plan when the last
+      reference is dropped.
+    </para>
+    <para>
+      You can attach user data to a shaper (with a key) using the
+      <function>hb_shape_plan_set_user_data(shape_plan,key,data,destroy,replace)</function>
+      function, optionally supplying a <function>destroy</function>
+      callback to use. You can then fetch the user data attached to a
+      shape plan with
+      <function>hb_shape_plan_get_user_data(shape_plan, key)</function>.
     </para>
   </section>
+  
 </chapter>
diff --git a/docs/usermanual-utilities.xml b/docs/usermanual-utilities.xml
new file mode 100644
index 0000000..1c5370c
--- /dev/null
+++ b/docs/usermanual-utilities.xml
@@ -0,0 +1,244 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+]>
+<chapter id="utilities">
+  <title>Utilities</title>
+  <para>
+    HarfBuzz includes several auxiliary components in addition to the
+    main APIs. These include a set of command-line tools, a set of
+    lower-level APIs for common data types that may be of interest to
+    client programs, and an embedded library for working with
+    Unicode Character Database (UCD) data.
+  </para>
+  
+  <section id="utilities-command-line-tools">
+    <title>Command-line tools</title>
+    <para>
+      HarfBuzz include three command-line tools:
+      <program>hb-shape</program>, <program>hb-view</program>, and
+      <program>hb-subset</program>. They can be used to examine
+      HarfBuzz's functionality, debug font binaries, or explore the
+      various shaping models and features from a terminal.
+    </para>
+    
+    <section id="utilities-command-line-hbshape">
+      <title>hb-shape</title>
+      <para>
+	<emphasis><program>hb-shape</program></emphasis> allows you to run HarfBuzz's
+	<function>hb_shape()</function> function on an input string and
+	to examine the outcome, in human-readable form, as terminal
+	output. <program>hb-shape</program> does
+	<emphasis>not</emphasis> render the results of the shaping call
+	into rendered text (you can use <program>hb-view</program>, below, for
+	that). Instead, it prints out the final glyph indices and
+	positions, taking all shaping operations into account, as if the
+	input string were a HarfBuzz input buffer.
+      </para>
+      <para>
+	You can specify the font to be used for shaping and, with
+	command-line options, you can add various aspects of the
+	internal state to the output that is sent to the terminal. The
+	general format is
+      </para>
+      <programlisting>
+	<command>hb-shape</command> <optional>[OPTIONS]</optional>
+      <parameter>path/to/font/file.ttf</parameter>
+      <parameter>yourinputtext</parameter>
+      </programlisting>
+      <para>
+	The default output format is plain text (although JSON output
+	can be selected instead by specifying the option
+	<optional>--output-format=json</optional>). The default output
+	syntax reports each glyph name (or glyph index if there is no
+	name) followed by its cluster value, its horizontal and vertical
+	position displacement, and its horizontal and vertical advances.
+      </para>
+      <para>
+	Output options exist to skip any of these elements in the
+	output, and to include additional data, such as Unicode
+	code-point values, glyph extents, glyph flags, or interim
+	shaping results.
+      </para>
+      <para>
+	Output can also be redirected to a file, or input read from a
+	file. Additional options enable you to enable or disable
+	specific font features, to set variation-font axis values, to
+	alter the language, script, direction, and clustering settings
+	used, to enable sanity checks, or to change which shaping engine is used.
+      </para>
+      <para>
+	For a complete explanation of the options available, run
+      </para>
+      <programlisting>
+	<command>hb-shape</command> <parameter>--help</parameter>
+      </programlisting>  
+    </section>
+    
+    <section id="utilities-command-line-hbview">
+      <title>hb-view</title>
+      <para>
+	<emphasis><program>hb-view</program></emphasis> allows you to
+	see the shaped output of an input string in rendered
+	form. Like <program>hb-shape</program>,
+	<program>hb-view</program> takes a font file and a text string
+	as its arguments:
+      </para>
+      <programlisting>
+	<command>hb-view</command> <optional>[OPTIONS]</optional>
+	<parameter>path/to/font/file.ttf</parameter>
+	<parameter>yourinputtext</parameter>
+      </programlisting>
+      <para>
+	By default, <program>hb-view</program> renders the shaped
+	text in ASCII block-character images as terminal output. By
+	appending the
+	<command>--output-file=<optional>filename</optional></command>
+	switch, you can write the output to a PNG, SVG, or PDF file
+	(among other formats).
+      </para>
+      <para>
+	As with <program>hb-shape</program>, a lengthy set of options
+	is available, with which you can  enable or disable
+	specific font features, set variation-font axis values,
+	alter the language, script, direction, and clustering settings
+	used, enable sanity checks, or change which shaping engine is
+	used.
+      </para>
+      <para>
+	You can also set the foreground and background colors used for
+	the output, independently control the width of all four
+	margins, alter the line spacing, and annotate the output image
+	with 
+      </para>
+      <para>
+	In general, <program>hb-view</program> is a quick way to
+	verify that the output of HarfBuzz's shaping operation looks
+	correct for a given text-and-font combination, but you may
+	want to use <program>hb-shape</program> to figure out exactly
+	why something does not appear as expected.
+      </para>
+    </section>
+    
+    <section id="utilities-command-line-hbsubset">
+      <title>hb-subset</title>
+      <para>
+	<emphasis><program>hb-subset</program></emphasis> allows you
+	to generate a subset of a given font, with a limited set of
+	supported characters, features, and variation settings.
+      </para>
+      <para>
+	By default, you provide an input font and an input text string
+	as the arguments to <program>hb-subset</program>, and it will
+	generate a font that covers the input text exactly like the
+	input font does, but includes no other characters or features.
+      </para>
+      <programlisting>
+	<command>hb-subset</command> <optional>[OPTIONS]</optional>
+	<parameter>path/to/font/file.ttf</parameter>
+	<parameter>yourinputtext</parameter>
+      </programlisting>
+      <para>
+	For example, to create a subset of Noto Serif that just includes the
+	numerals and the lowercase Latin alphabet, you could run
+      </para>
+      <programlisting>
+	<command>hb-subset</command> <optional>[OPTIONS]</optional>
+	<parameter>NotoSerif-Regular.ttf</parameter>
+	<parameter>0123456789abcdefghijklmnopqrstuvwxyz</parameter>
+      </programlisting>
+      <para>
+	There are options available to remove hinting from the
+	subsetted font and to specify a list of variation-axis settings.
+      </para>
+    </section>
+    
+  </section>
+  
+  <section id="utilities-common-types-apis">
+    <title>Common data types and APIs</title>
+    <para>
+      HarfBuzz includes several APIs for working with general-purpose
+      data that you may find convenient to leverage in your own
+      software. They include set operations and integer-to-integer
+      mapping operations.
+    </para>
+    <para>
+      HarfBuzz uses set operations for internal bookkeeping, such as
+      when it collects all of the glyph IDs covered by a particular
+      font feature. You can also use the set API to build sets, add
+      and remove elements, test whether or not sets contain particular
+      elements, or compute the unions, intersections, or differences
+      between sets.
+    </para>
+    <para>
+      All set elements are integers (specifically,
+      <type>hb_codepoint_t</type> 32-bit unsigned ints), and there are
+      functions for fetching the minimum and maximum element from a
+      set. The set API also includes some functions that might not 
+      be part of a generic set facility, such as the ability to add a
+      contiguous range of integer elements to a set in bulk, and the
+      ability to fetch the next-smallest or next-largest element.
+    </para>
+    <para>
+      The HarfBuzz set API includes some conveniences as well. All
+      sets are lifecycle-managed, just like other HarfBuzz
+      objects. You increase the reference count on a set with
+      <function>hb_set_reference()</function> and decrease it with
+      <function>hb_set_destroy()</function>. You can also attach
+      user data to a set, just like you can to blobs, buffers, faces,
+      fonts, and other objects, and set destroy callbacks.
+    </para>
+    <para>
+      HarfBuzz also provides an API for keeping track of
+      integer-to-integer mappings. As with the set API, each integer is
+      stored as an unsigned 32-bit <type>hb_codepoint_t</type>
+      element. Maps, like other objects, are reference counted with
+      reference and destroy functions, and you can attach user data to
+      them. The mapping operations include adding and deleting
+      integer-to-integer key:value pairs to the map, testing for the
+      presence of a key, fetching the population of the map, and so on.
+    </para>
+    <para>
+      There are several other internal HarfBuzz facilities that are
+      exposed publicly and which you may want to take advantage of
+      while processing text. HarfBuzz uses a common
+      <type>hb_tag_t</type> for a variety of OpenType tag identifiers (for
+      scripts, languages, font features, table names, variation-axis
+      names, and more), and provides functions for converting strings
+      to tags and vice-versa. 
+    </para>
+    <para>
+      Finally, HarfBuzz also includes data type for Booleans, bit
+      masks, and other simple types.
+    </para>
+  </section>
+
+  <section id="utilities-ucdn">
+    <title>UCDN</title>
+    <para>
+      HarfBuzz includes a copy of the <ulink
+      url="https://github.com/grigorig/ucdn">UCDN</ulink> (Unicode
+      Database and Normalization) library, which provides functions
+      for accessing basic Unicode character properties, performing
+      canonical composition, and performing both canonical and
+      compatibility decomposition.
+    </para>
+    <para>
+      Currently, UCDN supports direct queries for several more character
+      properties than HarfBuzz's built-in set of Unicode functions
+      does, such as the BiDirectional Class, East Asian Width, Paired
+      Bracket and Resolved Linebreak properties. If you need to access
+      more properties than HarfBuzz's internal implementation
+      provides, using the built-in UCDN functions may be a useful solution.
+    </para>
+    <para>
+      The built-in UCDN functions are compiled by default when
+      building HarfBuzz from source, but this can be disabled with a
+      compile-time switch.
+    </para>
+  </section>
+
+</chapter>
diff --git a/mingw-configure.sh b/mingw-configure.sh
new file mode 100755
index 0000000..3281ce3
--- /dev/null
+++ b/mingw-configure.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+case $1 in
+	i686 | x86_64) ;;
+	*) echo "Usage: $0 i686|x86_64" >&2; exit 1 ;;
+esac
+
+target=$1-w64-mingw32
+shift
+
+exec "$(dirname "$0")"/configure \
+	--build=`../config.guess` \
+	--host=$target \
+	--prefix=$HOME/.local/$target \
+	CC= \
+	CXX= \
+	CPP= \
+	LD= \
+	CFLAGS="-static-libgcc" \
+	CXXFLAGS="-static-libgcc -static-libstdc++" \
+	CPPFLAGS="-I$HOME/.local/$target/include" \
+	LDFLAGS=-L$HOME/.local/$target/lib \
+	PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig:/usr/$target/sys-root/mingw/lib/pkgconfig/ \
+	PKG_CONFIG_PATH=$HOME/.local/$target/share/pkgconfig:/usr/$target/sys-root/mingw/share/pkgconfig/ \
+	PATH=$HOME/.local/$target/bin:/usr/$target/sys-root/mingw/bin:/usr/$target/bin:$PATH \
+	--without-icu \
+	--with-uniscribe \
+	"$@"
diff --git a/mingw-ldd.py b/mingw-ldd.py
new file mode 100755
index 0000000..1d659ef
--- /dev/null
+++ b/mingw-ldd.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+# Copied from https://github.com/xantares/mingw-ldd/blob/master/mingw-ldd.py
+# Modified to point to right prefix location on Fedora.
+
+# WTFPL - Do What the Fuck You Want to Public License
+from __future__ import print_function
+import pefile
+import os
+import sys
+
+
+def get_dependency(filename):
+    deps = []
+    pe = pefile.PE(filename)
+    for imp in pe.DIRECTORY_ENTRY_IMPORT:
+        deps.append(imp.dll.decode())
+    return deps
+
+
+def dep_tree(root, prefix=None):
+    if not prefix:
+        arch = get_arch(root)
+        #print('Arch =', arch)
+        prefix = '/usr/'+arch+'-w64-mingw32/sys-root/mingw/bin'
+        #print('Using default prefix', prefix)
+    dep_dlls = dict()
+
+    def dep_tree_impl(root, prefix):
+        for dll in get_dependency(root):
+            if dll in dep_dlls:
+                continue
+            full_path = os.path.join(prefix, dll)
+            if os.path.exists(full_path):
+                dep_dlls[dll] = full_path
+                dep_tree_impl(full_path, prefix=prefix)
+            else:
+                dep_dlls[dll] = 'not found'
+
+    dep_tree_impl(root, prefix)
+    return (dep_dlls)
+
+
+def get_arch(filename):
+    type2arch= {pefile.OPTIONAL_HEADER_MAGIC_PE: 'i686',
+                pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS: 'x86_64'}
+    pe = pefile.PE(filename)
+    try:
+        return type2arch[pe.PE_TYPE]
+    except KeyError:
+        sys.stderr.write('Error: unknown architecture')
+        sys.exit(1)
+
+if __name__ == '__main__':
+    filename = sys.argv[1]
+    for dll, full_path in dep_tree(filename).items():
+        print(' ' * 7, dll, '=>', full_path)
+
diff --git a/mingw32.sh b/mingw32.sh
index 6774405..77edffa 100755
--- a/mingw32.sh
+++ b/mingw32.sh
@@ -1,22 +1,2 @@
-#!/bin/bash
-
-target=i686-w64-mingw32
-
-unset CC
-unset CXX
-unset CPP
-unset LD
-unset LDFLAGS
-unset CFLAGS
-unset CXXFLAGS
-unset PKG_CONFIG_PATH
-
-# Removed -static from the following
-export CFLAGS="-static-libgcc"
-export CXXFLAGS="-static-libgcc -static-libstdc++"
-export CPPFLAGS="-I$HOME/.local/$target/include -O2"
-export LDFLAGS=-L$HOME/.local/$target/lib
-export PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig
-export PATH=$HOME/.local/$target/bin:$PATH
-
-../configure --build=`../config.guess` --host=$target --prefix=$HOME/.local/$target "$@"
+#!/bin/sh
+exec "$(dirname "$0")"/mingw-configure.sh i686 "$@"
diff --git a/mingw64.sh b/mingw64.sh
index 49a1431..28724a4 100755
--- a/mingw64.sh
+++ b/mingw64.sh
@@ -1,22 +1,2 @@
-#!/bin/bash
-
-target=x86_64-w64-mingw32
-
-unset CC
-unset CXX
-unset CPP
-unset LD
-unset LDFLAGS
-unset CFLAGS
-unset CXXFLAGS
-unset PKG_CONFIG_PATH
-
-# Removed -static from the following
-export CFLAGS="-static-libgcc"
-export CXXFLAGS="-static-libgcc -static-libstdc++"
-export CPPFLAGS="-I$HOME/.local/$target/include -O2"
-export LDFLAGS=-L$HOME/.local/$target/lib
-export PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig
-export PATH=$HOME/.local/$target/bin:$PATH
-
-../configure --build=`../config.guess` --host=$target --prefix=$HOME/.local/$target "$@"
+#!/bin/sh
+exec "$(dirname "$0")"/mingw-configure.sh x86_64 "$@"
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b5512f..d126c40 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -87,17 +87,6 @@
 HBHEADERS += $(HB_CORETEXT_headers)
 endif
 
-if HAVE_UCDN
-SUBDIRS += hb-ucdn
-HBCFLAGS += -I$(srcdir)/hb-ucdn
-HBLIBS   += hb-ucdn/libhb-ucdn.la
-HBSOURCES += $(HB_UCDN_sources)
-hb-ucdn/libhb-ucdn.la: ucdn
-ucdn:
-	@$(MAKE) $(AM_MAKEFLAGS) -C hb-ucdn
-endif
-DIST_SUBDIRS += hb-ucdn
-
 
 BUILT_SOURCES += \
 	hb-version.h
@@ -258,6 +247,7 @@
 	gen-indic-table.py \
 	gen-os2-unicode-ranges.py \
 	gen-tag-table.py \
+	gen-ucd-table.py \
 	gen-use-table.py \
 	gen-vowel-constraints.py \
 	$(NULL)
@@ -384,7 +374,7 @@
 dump_use_data_CPPFLAGS = $(HBCFLAGS)
 dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
 
-COMPILED_TESTS = test-algs test-iter test-ot-tag test-unicode-ranges
+COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges
 COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
 COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
 check_PROGRAMS += $(COMPILED_TESTS)
@@ -398,6 +388,10 @@
 test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_iter_LDADD = $(COMPILED_TESTS_LDADD)
 
+test_meta_SOURCES = test-meta.cc hb-static.cc
+test_meta_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
+test_meta_LDADD = $(COMPILED_TESTS_LDADD)
+
 test_ot_tag_SOURCES = hb-ot-tag.cc
 test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
 test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 289e126..477bf5a 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -31,6 +31,7 @@
 	hb-cff1-interp-cs.hh \
 	hb-cff2-interp-cs.hh \
 	hb-common.cc \
+	hb-config.hh \
 	hb-debug.hh \
 	hb-dispatch.hh \
 	hb-face.cc \
@@ -147,6 +148,8 @@
 	hb-shaper.hh \
 	hb-static.cc \
 	hb-string-array.hh \
+	hb-ucd-table.hh \
+	hb-ucd.cc \
 	hb-unicode-emoji-table.hh \
 	hb-unicode.cc \
 	hb-unicode.hh \
@@ -226,9 +229,6 @@
 HB_UNISCRIBE_sources = hb-uniscribe.cc
 HB_UNISCRIBE_headers = hb-uniscribe.h
 
-# Additional supplemental sources
-HB_UCDN_sources  = hb-ucdn.cc
-
 # Sources for libharfbuzz-gobject and libharfbuzz-icu
 HB_ICU_sources = hb-icu.cc
 HB_ICU_headers = hb-icu.h
@@ -244,9 +244,6 @@
 	hb-subset-cff1.hh \
 	hb-subset-cff2.cc \
 	hb-subset-cff2.hh \
-	hb-subset-glyf.cc \
-	hb-subset-glyf.hh \
-	hb-subset-glyf.hh \
 	hb-subset-input.cc \
 	hb-subset-input.hh \
 	hb-subset-plan.cc \
diff --git a/src/check-symbols.sh b/src/check-symbols.sh
index 423d186..f181b63 100755
--- a/src/check-symbols.sh
+++ b/src/check-symbols.sh
@@ -7,7 +7,7 @@
 test -z "$libs" && libs=.libs
 stat=0
 
-IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_flush\|llvm_.*'
+IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*'
 
 if which nm 2>/dev/null >/dev/null; then
 	:
diff --git a/src/gen-os2-unicode-ranges.py b/src/gen-os2-unicode-ranges.py
old mode 100644
new mode 100755
index 8cf5985..515f4ca
--- a/src/gen-os2-unicode-ranges.py
+++ b/src/gen-os2-unicode-ranges.py
@@ -1,8 +1,10 @@
+#!/usr/bin/python
+
 # -*- coding: utf-8 -*-
 
 # Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh
 # Input is a tab seperated list of unicode ranges from the otspec
-# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1).
+# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur).
 
 from __future__ import print_function, division, absolute_import
 
diff --git a/src/gen-ucd-table.py b/src/gen-ucd-table.py
new file mode 100755
index 0000000..3f82180
--- /dev/null
+++ b/src/gen-ucd-table.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+
+from __future__ import print_function, division, absolute_import
+
+import io, os.path, sys, re
+
+if len (sys.argv) != 2:
+	print("usage: ./gen-ucd-table ucd.nonunihan.grouped.xml", file=sys.stderr)
+	sys.exit(1)
+
+
+# https://github.com/harfbuzz/packtab
+import packTab
+import packTab.ucdxml
+
+ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1])
+ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml)
+
+
+gc = [u['gc'] for u in ucd]
+ccc = [int(u['ccc']) for u in ucd]
+bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
+#gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
+#gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
+
+sc = [u['sc'] for u in ucd]
+
+dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
+      if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
+ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
+
+assert not any(v for v in dm.values() if len(v) not in (1,2))
+dm1 = sorted(set(v for v in dm.values() if len(v) == 1))
+dm1_array = ['0x%04Xu' % v for v in dm1]
+dm1_order = {v:i+1 for i,v in enumerate(dm1)}
+dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2)
+dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" %
+        (v+(i if i not in ce and not ccc[i] else 0,)), v)
+       for v,i in dm2]
+dm2_array = [s for s,v in dm2]
+l = 1 + len(dm1_array)
+dm2_order = {v[1]:i+l for i,v in enumerate(dm2)}
+dm_order = {None: 0}
+dm_order.update(dm1_order)
+dm_order.update(dm2_order)
+
+gc_order = packTab.AutoMapping()
+for _ in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
+          'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
+          'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',):
+    gc_order[_]
+
+sc_order = packTab.AutoMapping()
+sc_array = []
+sc_re = re.compile(" (HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
+for line in open('hb-common.h'):
+    m = sc_re.search (line)
+    if not m: continue
+    name = m.group(1)
+    tag = ''.join(m.group(i) for i in range(2, 6))
+    i = sc_order[tag]
+    assert i == len(sc_array)
+    sc_array.append(name)
+
+# TODO Currently if gc_order or sc_order do not capture all values, we get in
+# trouble because they silently add new values.  We should be able to "freeze"
+# them, or just do the mapping ourselves.
+
+DEFAULT = 1
+COMPACT = 3
+
+
+print("/* == Start of generated table == */")
+print("/*")
+print(" * The following table is generated by running:")
+print(" *")
+print(" *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml")
+print(" *")
+print(" * on file with this description:", ucdxml.description)
+print(" */")
+print()
+print("#ifndef HB_UCD_TABLE_HH")
+print("#define HB_UCD_TABLE_HH")
+print()
+
+print()
+print('#include "hb.hh"')
+print()
+
+code = packTab.Code('_hb_ucd')
+sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
+dm1_array, _ = code.addArray('hb_codepoint_t', 'dm1_map', dm1_array)
+dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array)
+code.print_c(linkage='static inline')
+
+for compression in (DEFAULT, COMPACT):
+    print()
+    if compression == DEFAULT:
+        print('#ifndef HB_OPTIMIZE_SIZE')
+    else:
+        print('#else')
+    print()
+
+    code = packTab.Code('_hb_ucd')
+
+    packTab.pack_table(gc, 'Cn', mapping=gc_order, compression=compression).genCode(code, 'gc')
+    packTab.pack_table(ccc, 0, compression=compression).genCode(code, 'ccc')
+    packTab.pack_table(bmg, 0, compression=compression).genCode(code, 'bmg')
+    packTab.pack_table(sc, 'Zzzz', mapping=sc_order, compression=compression).genCode(code, 'sc')
+    packTab.pack_table(dm, None, mapping=dm_order, compression=compression).genCode(code, 'dm')
+
+    code.print_c(linkage='static inline')
+
+
+    if compression != DEFAULT:
+        print()
+        print('#endif')
+    print()
+
+print()
+print("#endif /* HB_UCD_TABLE_HH */")
+print()
+print("/* == End of generated table == */")
diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index 1a33b8a..820838c 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -47,6 +47,14 @@
 
 # TODO Characters that are not in Unicode Indic files, but used in USE
 data[0][0x034F] = defaults[0]
+data[0][0x1B61] = defaults[0]
+data[0][0x1B63] = defaults[0]
+data[0][0x1B64] = defaults[0]
+data[0][0x1B65] = defaults[0]
+data[0][0x1B66] = defaults[0]
+data[0][0x1B67] = defaults[0]
+data[0][0x1B69] = defaults[0]
+data[0][0x1B6A] = defaults[0]
 data[0][0x2060] = defaults[0]
 # TODO https://github.com/harfbuzz/harfbuzz/pull/1685
 data[0][0x1B5B] = 'Consonant_Placeholder'
@@ -54,7 +62,7 @@
 data[0][0x1B5F] = 'Consonant_Placeholder'
 data[0][0x1B62] = 'Consonant_Placeholder'
 data[0][0x1B68] = 'Consonant_Placeholder'
-# TODO https://github.com/roozbehp/unicode-data/issues/9
+# TODO https://github.com/harfbuzz/harfbuzz/issues/1035
 data[0][0x11C44] = 'Consonant_Placeholder'
 data[0][0x11C45] = 'Consonant_Placeholder'
 # TODO https://github.com/harfbuzz/harfbuzz/pull/1399
@@ -189,15 +197,15 @@
 def is_CGJ(U, UISC, UGC):
 	return U == 0x034F
 def is_CONS_FINAL(U, UISC, UGC):
-	# Consonant_Initial_Postfixed is new in Unicode 11; not in the spec.
 	return ((UISC == Consonant_Final and UGC != Lo) or
-		UISC == Consonant_Initial_Postfixed or
 		UISC == Consonant_Succeeding_Repha)
 def is_CONS_FINAL_MOD(U, UISC, UGC):
 	#SPEC-DRAFT return  UISC in [Consonant_Final_Modifier, Syllable_Modifier]
 	return  UISC == Syllable_Modifier
 def is_CONS_MED(U, UISC, UGC):
-	return UISC == Consonant_Medial and UGC != Lo
+	# Consonant_Initial_Postfixed is new in Unicode 11; not in the spec.
+	return (UISC == Consonant_Medial and UGC != Lo or
+		UISC == Consonant_Initial_Postfixed)
 def is_CONS_MOD(U, UISC, UGC):
 	return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
 def is_CONS_SUB(U, UISC, UGC):
@@ -206,7 +214,9 @@
 def is_CONS_WITH_STACKER(U, UISC, UGC):
 	return UISC == Consonant_With_Stacker
 def is_HALANT(U, UISC, UGC):
-	return UISC in [Virama, Invisible_Stacker] and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC)
+	return (UISC in [Virama, Invisible_Stacker]
+		and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC)
+		and not is_SAKOT(U, UISC, UGC))
 def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC):
 	# https://github.com/harfbuzz/harfbuzz/issues/1102
 	# https://github.com/harfbuzz/harfbuzz/issues/1379
@@ -222,6 +232,7 @@
 def is_OTHER(U, UISC, UGC):
 	#SPEC-OUTDATED return UGC == Zs # or any other SCRIPT_COMMON characters
 	return (UISC == Other
+		and not is_SYM(U, UISC, UGC)
 		and not is_SYM_MOD(U, UISC, UGC)
 		and not is_CGJ(U, UISC, UGC)
 		and not is_Word_Joiner(U, UISC, UGC)
@@ -231,6 +242,8 @@
 	return UGC == 'Cn'
 def is_REPHA(U, UISC, UGC):
 	return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
+def is_SAKOT(U, UISC, UGC):
+	return U == 0x1A60
 def is_SYM(U, UISC, UGC):
 	if U == 0x25CC: return False #SPEC-DRAFT
 	#SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter
@@ -240,11 +253,11 @@
 def is_VARIATION_SELECTOR(U, UISC, UGC):
 	return 0xFE00 <= U <= 0xFE0F
 def is_VOWEL(U, UISC, UGC):
-	# https://github.com/roozbehp/unicode-data/issues/6
+	# https://github.com/harfbuzz/harfbuzz/issues/376
 	return (UISC == Pure_Killer or
 		(UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29]))
 def is_VOWEL_MOD(U, UISC, UGC):
-	# https://github.com/roozbehp/unicode-data/issues/6
+	# https://github.com/harfbuzz/harfbuzz/issues/376
 	return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
 		(UGC != Lo and (UISC == Bindu or U in [0xAA29])))
 
@@ -270,6 +283,7 @@
 	'Rsv':	is_Reserved,
 	'R':	is_REPHA,
 	'S':	is_SYM,
+	'Sk':	is_SAKOT,
 	'SM':	is_SYM_MOD,
 	'VS':	is_VARIATION_SELECTOR,
 	'V':	is_VOWEL,
@@ -311,7 +325,11 @@
 	'H': None,
 	'HVM': None,
 	'B': None,
-	'FM': None,
+	'FM': {
+		'Abv': [Top],
+		'Blw': [Bottom],
+		'Pst': [Not_Applicable],
+	},
 	'SUB': None,
 }
 
@@ -350,15 +368,9 @@
 		# the nasalization marks, maybe only for U+1CE9..U+1CF1.
 		if U == 0x1CED: UISC = Tone_Mark
 
-		# TODO: https://github.com/harfbuzz/harfbuzz/issues/525
-		if U == 0x1A7F: UISC = Consonant_Final
-
 		# TODO: https://github.com/harfbuzz/harfbuzz/issues/1105
 		if U == 0x11134: UISC = Gemination_Mark
 
-		# TODO: https://github.com/harfbuzz/harfbuzz/pull/1399
-		if U == 0x111C9: UISC = Consonant_Final
-
 		values = [k for k,v in items if v(U,UISC,UGC)]
 		assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
 		USE = values[0]
diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py
index afb21d9..1340d97 100755
--- a/src/gen-vowel-constraints.py
+++ b/src/gen-vowel-constraints.py
@@ -180,6 +180,9 @@
 print ('\t\t\t\t       hb_buffer_t              *buffer,')
 print ('\t\t\t\t       hb_font_t                *font HB_UNUSED)')
 print ('{')
+print ('#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS)')
+print ('  return;')
+print ('#endif')
 print ('  if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)')
 print ('    return;')
 print ()
diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh
index 4087b8c..ef98884 100644
--- a/src/hb-aat-layout-ankr-table.hh
+++ b/src/hb-aat-layout-ankr-table.hh
@@ -83,7 +83,7 @@
   protected:
   HBUINT16	version; 	/* Version number (set to zero) */
   HBUINT16	flags;		/* Flags (currently unused; set to zero) */
-  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors> > >
+  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
 		lookupTable;	/* Offset to the table's lookup table */
   LNNOffsetTo<HBUINT8>
 		anchorData;	/* Offset to the glyph data table */
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
index 7c74d79..a8c4b76 100644
--- a/src/hb-aat-layout-common.hh
+++ b/src/hb-aat-layout-common.hh
@@ -125,7 +125,7 @@
 
   protected:
   HBUINT16	format;		/* Format identifier--format = 2 */
-  VarSizedBinSearchArrayOf<LookupSegmentSingle<T> >
+  VarSizedBinSearchArrayOf<LookupSegmentSingle<T>>
 		segments;	/* The actual segments. These must already be sorted,
 				 * according to the first word in each one (the last
 				 * glyph in each segment). */
@@ -154,7 +154,7 @@
 		  valuesZ.sanitize (c, base, last - first + 1));
   }
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -164,7 +164,7 @@
 
   GlyphID	last;		/* Last GlyphID in this segment */
   GlyphID	first;		/* First GlyphID in this segment */
-  NNOffsetTo<UnsizedArrayOf<T> >
+  NNOffsetTo<UnsizedArrayOf<T>>
 		valuesZ;	/* A 16-bit offset from the start of
 				 * the table to the data. */
   public:
@@ -196,7 +196,7 @@
 
   protected:
   HBUINT16	format;		/* Format identifier--format = 4 */
-  VarSizedBinSearchArrayOf<LookupSegmentArray<T> >
+  VarSizedBinSearchArrayOf<LookupSegmentArray<T>>
 		segments;	/* The actual segments. These must already be sorted,
 				 * according to the first word in each one (the last
 				 * glyph in each segment). */
@@ -253,7 +253,7 @@
 
   protected:
   HBUINT16	format;		/* Format identifier--format = 6 */
-  VarSizedBinSearchArrayOf<LookupSingle<T> >
+  VarSizedBinSearchArrayOf<LookupSingle<T>>
 		entries;	/* The actual entries, sorted by glyph index. */
   public:
   DEFINE_SIZE_ARRAY (8, entries);
@@ -419,7 +419,7 @@
 /* Ugly hand-coded null objects for template Lookup<> :(. */
 extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
 template <typename T>
-struct Null<AAT::Lookup<T> > {
+struct Null<AAT::Lookup<T>> {
   static AAT::Lookup<T> const & get_null ()
   { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
 };
@@ -510,7 +510,7 @@
   const Entry<Extra> &get_entry (int state, unsigned int klass) const
   {
     if (unlikely (klass >= nClasses))
-      klass = StateTable<Types, Entry<Extra> >::CLASS_OUT_OF_BOUNDS;
+      klass = StateTable<Types, Entry<Extra>>::CLASS_OUT_OF_BOUNDS;
 
     const HBUSHORT *states = (this+stateArrayTable).arrayZ;
     const Entry<Extra> *entries = (this+entryTable).arrayZ;
@@ -576,7 +576,7 @@
 	  if (unlikely (stop > states))
 	    return_trace (false);
 	  for (const HBUSHORT *p = states; stop < p; p--)
-	    num_entries = MAX<unsigned int> (num_entries, *(p - 1) + 1);
+	    num_entries = hb_max (num_entries, *(p - 1) + 1);
 	  state_neg = min_state;
 	}
       }
@@ -597,7 +597,7 @@
 	  if (unlikely (stop < states))
 	    return_trace (false);
 	  for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
-	    num_entries = MAX<unsigned int> (num_entries, *p + 1);
+	    num_entries = hb_max (num_entries, *p + 1);
 	  state_pos = max_state + 1;
 	}
       }
@@ -611,8 +611,8 @@
 	for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
 	{
 	  int newState = new_state (p->newState);
-	  min_state = MIN (min_state, newState);
-	  max_state = MAX (max_state, newState);
+	  min_state = hb_min (min_state, newState);
+	  max_state = hb_max (max_state, newState);
 	}
 	entry = num_entries;
       }
@@ -631,7 +631,7 @@
 		classTable;	/* Offset to the class table. */
   NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
 		stateArrayTable;/* Offset to the state array. */
-  NNOffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT>
+  NNOffsetTo<UnsizedArrayOf<Entry<Extra>>, HBUINT>
 		entryTable;	/* Offset to the entry array. */
 
   public:
diff --git a/src/hb-aat-layout-feat-table.hh b/src/hb-aat-layout-feat-table.hh
index ab23ee0..a20ef86 100644
--- a/src/hb-aat-layout-feat-table.hh
+++ b/src/hb-aat-layout-feat-table.hh
@@ -165,7 +165,7 @@
     unsigned int feature_count = featureNameCount;
     if (count && *count)
     {
-      unsigned int len = MIN (feature_count - start_offset, *count);
+      unsigned int len = hb_min (feature_count - start_offset, *count);
       for (unsigned int i = 0; i < len; i++)
 	features[i] = namesZ[i + start_offset].get_feature_type ();
       *count = len;
diff --git a/src/hb-aat-layout-just-table.hh b/src/hb-aat-layout-just-table.hh
index d53f8f1..e15c946 100644
--- a/src/hb-aat-layout-just-table.hh
+++ b/src/hb-aat-layout-just-table.hh
@@ -309,7 +309,7 @@
   public:
   DEFINE_SIZE_STATIC (24);
 };
-  
+
 typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
 
 struct JustificationCategory
@@ -371,7 +371,7 @@
 				 * of postcompensation subtable (set to zero if none).
 				 *
 				 * The postcompensation subtable, if present in the font. */
-  Lookup<OffsetTo<WidthDeltaCluster> >
+  Lookup<OffsetTo<WidthDeltaCluster>>
   		lookupTable;	/* Lookup table associating glyphs with width delta
 				 * clusters. See the description of Width Delta Clusters
 				 * table for details on how to interpret the lookup values. */
diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index a64c807..cec63ac 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -251,7 +251,7 @@
 
       if (Format1EntryT::performAction (entry) && depth)
       {
-	unsigned int tuple_count = MAX (1u, table->header.tuple_count ());
+	unsigned int tuple_count = hb_max (1u, table->header.tuple_count ());
 
 	unsigned int kern_idx = Format1EntryT::kernActionIndex (entry);
 	kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
@@ -712,18 +712,18 @@
   {
     struct Long
     {
-      LNNOffsetTo<Lookup<HBUINT32> >		rowIndexTable;
-      LNNOffsetTo<Lookup<HBUINT32> >		columnIndexTable;
-      LNNOffsetTo<UnsizedArrayOf<FWORD32> >	array;
+      LNNOffsetTo<Lookup<HBUINT32>>		rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT32>>		columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD32>>	array;
     } l;
     struct Short
     {
-      LNNOffsetTo<Lookup<HBUINT16> >		rowIndexTable;
-      LNNOffsetTo<Lookup<HBUINT16> >		columnIndexTable;
-      LNNOffsetTo<UnsizedArrayOf<FWORD> >	array;
+      LNNOffsetTo<Lookup<HBUINT16>>		rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT16>>		columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD>>	array;
     } s;
   } u;
-  LNNOffsetTo<UnsizedArrayOf<FWORD> >	vector;
+  LNNOffsetTo<UnsizedArrayOf<FWORD>>	vector;
   public:
   DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
 };
@@ -771,17 +771,17 @@
   unsigned int get_size () const { return u.header.length; }
   unsigned int get_type () const { return u.header.coverage & u.header.SubtableType; }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     unsigned int subtable_type = get_type ();
     TRACE_DISPATCH (this, subtable_type);
     switch (subtable_type) {
-    case 0:	return_trace (c->dispatch (u.format0));
-    case 1:	return_trace (c->dispatch (u.format1));
-    case 2:	return_trace (c->dispatch (u.format2));
-    case 4:	return_trace (c->dispatch (u.format4));
-    case 6:	return_trace (c->dispatch (u.format6));
+    case 0:	return_trace (c->dispatch (u.format0, hb_forward<Ts> (ds)...));
+    case 1:	return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+    case 2:	return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
+    case 4:	return_trace (c->dispatch (u.format4, hb_forward<Ts> (ds)...));
+    case 6:	return_trace (c->dispatch (u.format6, hb_forward<Ts> (ds)...));
     default:	return_trace (c->default_return_value ());
     }
   }
diff --git a/src/hb-aat-layout-lcar-table.hh b/src/hb-aat-layout-lcar-table.hh
index 4be799f..cd96d03 100644
--- a/src/hb-aat-layout-lcar-table.hh
+++ b/src/hb-aat-layout-lcar-table.hh
@@ -81,7 +81,7 @@
   protected:
   FixedVersion<>version;	/* Version number of the ligature caret table */
   HBUINT16	format;		/* Format of the ligature caret table. */
-  Lookup<OffsetTo<LigCaretClassEntry> >
+  Lookup<OffsetTo<LigCaretClassEntry>>
 		lookup;		/* data Lookup table associating glyphs */
 
   public:
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 4a1d959..81d7897 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -88,7 +88,7 @@
 	start = buffer->idx;
 
       if (flags & MarkLast)
-	end = MIN (buffer->idx + 1, buffer->len);
+	end = hb_min (buffer->idx + 1, buffer->len);
 
       if ((flags & Verb) && start < end)
       {
@@ -117,14 +117,14 @@
 	};
 
 	unsigned int m = map[flags & Verb];
-	unsigned int l = MIN<unsigned int> (2, m >> 4);
-	unsigned int r = MIN<unsigned int> (2, m & 0x0F);
+	unsigned int l = hb_min (2u, m >> 4);
+	unsigned int r = hb_min (2u, m & 0x0F);
 	bool reverse_l = 3 == (m >> 4);
 	bool reverse_r = 3 == (m & 0x0F);
 
 	if (end - start >= l + r)
 	{
-	  buffer->merge_clusters (start, MIN (buffer->idx + 1, buffer->len));
+	  buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len));
 	  buffer->merge_clusters (start, end);
 
 	  hb_glyph_info_t *info = buffer->info;
@@ -261,13 +261,13 @@
       }
       if (replacement)
       {
-	buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
+	buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
 	buffer->info[mark].codepoint = *replacement;
 	ret = true;
       }
 
       replacement = nullptr;
-      unsigned int idx = MIN (buffer->idx, buffer->len - 1);
+      unsigned int idx = hb_min (buffer->idx, buffer->len - 1);
       if (Types::extended)
       {
 	if (entry.data.currentIndex != 0xFFFF)
@@ -337,9 +337,9 @@
       const EntryData &data = entries[i].data;
 
       if (data.markIndex != 0xFFFF)
-	num_lookups = MAX<unsigned int> (num_lookups, 1 + data.markIndex);
+	num_lookups = hb_max (num_lookups, 1 + data.markIndex);
       if (data.currentIndex != 0xFFFF)
-	num_lookups = MAX<unsigned int> (num_lookups, 1 + data.currentIndex);
+	num_lookups = hb_max (num_lookups, 1 + data.currentIndex);
     }
 
     return_trace (substitutionTables.sanitize (c, this, num_lookups));
@@ -744,7 +744,7 @@
 
 	buffer->move_to (end + count);
 
-	buffer->unsafe_to_break_from_outbuffer (mark, MIN (buffer->idx + 1, buffer->len));
+	buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len));
       }
 
       if (flags & SetMark)
@@ -883,17 +883,17 @@
     Insertion		= 5
   };
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     unsigned int subtable_type = get_type ();
     TRACE_DISPATCH (this, subtable_type);
     switch (subtable_type) {
-    case Rearrangement:		return_trace (c->dispatch (u.rearrangement));
-    case Contextual:		return_trace (c->dispatch (u.contextual));
-    case Ligature:		return_trace (c->dispatch (u.ligature));
-    case Noncontextual:		return_trace (c->dispatch (u.noncontextual));
-    case Insertion:		return_trace (c->dispatch (u.insertion));
+    case Rearrangement:		return_trace (c->dispatch (u.rearrangement, hb_forward<Ts> (ds)...));
+    case Contextual:		return_trace (c->dispatch (u.contextual, hb_forward<Ts> (ds)...));
+    case Ligature:		return_trace (c->dispatch (u.ligature, hb_forward<Ts> (ds)...));
+    case Noncontextual:		return_trace (c->dispatch (u.noncontextual, hb_forward<Ts> (ds)...));
+    case Insertion:		return_trace (c->dispatch (u.insertion, hb_forward<Ts> (ds)...));
     default:			return_trace (c->default_return_value ());
     }
   }
@@ -969,7 +969,7 @@
   void apply (hb_aat_apply_context_t *c,
 		     hb_mask_t flags) const
   {
-    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
@@ -1031,7 +1031,7 @@
       if (unlikely (!c->buffer->successful)) return;
 
     skip:
-      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
+      subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
       c->set_lookup_index (c->lookup_index + 1);
     }
   }
@@ -1049,13 +1049,13 @@
     if (!c->check_array (featureZ.arrayZ, featureCount))
       return_trace (false);
 
-    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
       if (!subtable->sanitize (c))
 	return_trace (false);
-      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
+      subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
     }
 
     return_trace (true);
@@ -1095,7 +1095,7 @@
     for (unsigned int i = 0; i < count; i++)
     {
       map->chain_flags.push (chain->compile_flags (mapper));
-      chain = &StructAfter<Chain<Types> > (*chain);
+      chain = &StructAfter<Chain<Types>> (*chain);
     }
   }
 
@@ -1109,7 +1109,7 @@
     {
       chain->apply (c, c->plan->aat_map.chain_flags[i]);
       if (unlikely (!c->buffer->successful)) return;
-      chain = &StructAfter<Chain<Types> > (*chain);
+      chain = &StructAfter<Chain<Types>> (*chain);
     }
   }
 
@@ -1125,7 +1125,7 @@
     {
       if (!chain->sanitize (c, version))
 	return_trace (false);
-      chain = &StructAfter<Chain<Types> > (*chain);
+      chain = &StructAfter<Chain<Types>> (*chain);
     }
 
     return_trace (true);
diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index 0c8e455..2eace2a 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -66,7 +66,7 @@
   NameID	trackNameID;	/* The 'name' table index for this track.
 				 * (a short word or phrase like "loose"
 				 * or "very tight") */
-  NNOffsetTo<UnsizedArrayOf<FWORD> >
+  NNOffsetTo<UnsizedArrayOf<FWORD>>
 		valuesZ;	/* Offset from start of tracking table to
 				 * per-size tracking values for this track. */
 
@@ -133,8 +133,8 @@
       if (size_table[size_index].to_float () >= csspx)
         break;
 
-    return round (interpolate_at (size_index ? size_index - 1 : 0, csspx,
-				  *trackTableEntry, base));
+    return roundf (interpolate_at (size_index ? size_index - 1 : 0, csspx,
+				   *trackTableEntry, base));
   }
 
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 1966ded..35ba611 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -135,11 +135,15 @@
 const hb_aat_feature_mapping_t *
 hb_aat_layout_find_feature_mapping (hb_tag_t tag)
 {
-  return (const hb_aat_feature_mapping_t *) bsearch (&tag,
-						     feature_mappings,
-						     ARRAY_LENGTH (feature_mappings),
-						     sizeof (feature_mappings[0]),
-						     hb_aat_feature_mapping_t::cmp);
+#ifdef HB_NO_SHAPE_AAT
+  return nullptr;
+#endif
+
+  return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag,
+							feature_mappings,
+							ARRAY_LENGTH (feature_mappings),
+							sizeof (feature_mappings[0]),
+							hb_aat_feature_mapping_t::cmp);
 }
 
 
@@ -147,6 +151,8 @@
  * hb_aat_apply_context_t
  */
 
+/* Note: This context is used for kerning, even without AAT. */
+
 AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
 						     hb_font_t *font_,
 						     hb_buffer_t *buffer_,
@@ -183,6 +189,10 @@
 hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
 			   hb_aat_map_t *map)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   const AAT::morx& morx = *mapper->face->table.morx;
   if (morx.has_data ())
   {
@@ -209,6 +219,10 @@
 hb_bool_t
 hb_aat_layout_has_substitution (hb_face_t *face)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return false;
+#endif
+
   return face->table.morx->has_data () ||
 	 face->table.mort->has_data ();
 }
@@ -218,6 +232,10 @@
 			  hb_font_t *font,
 			  hb_buffer_t *buffer)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
   const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
   if (morx.has_data ())
@@ -240,6 +258,10 @@
 void
 hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   hb_glyph_position_t *pos = buffer->pos;
@@ -257,6 +279,10 @@
 void
 hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
 }
 
@@ -270,6 +296,10 @@
 hb_bool_t
 hb_aat_layout_has_positioning (hb_face_t *face)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return false;
+#endif
+
   return face->table.kerx->has_data ();
 }
 
@@ -278,6 +308,10 @@
 			hb_font_t *font,
 			hb_buffer_t *buffer)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
   const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
 
@@ -297,6 +331,10 @@
 hb_bool_t
 hb_aat_layout_has_tracking (hb_face_t *face)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return false;
+#endif
+
   return face->table.trak->has_data ();
 }
 
@@ -305,6 +343,10 @@
 		     hb_font_t *font,
 		     hb_buffer_t *buffer)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   const AAT::trak& trak = *font->face->table.trak;
 
   AAT::hb_aat_apply_context_t c (plan, font, buffer);
@@ -328,6 +370,12 @@
 				 unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
 				 hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */)
 {
+#ifdef HB_NO_SHAPE_AAT
+  if (feature_count)
+    *feature_count = 0;
+  return 0;
+#endif
+
   return face->table.feat->get_feature_types (start_offset, feature_count, features);
 }
 
@@ -344,6 +392,10 @@
 hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
 					hb_aat_layout_feature_type_t  feature_type)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return HB_OT_NAME_ID_INVALID;
+#endif
+
   return face->table.feat->get_feature_name_id (feature_type);
 }
 
@@ -372,5 +424,11 @@
 					       hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
 					       unsigned int                          *default_index   /* OUT.     May be NULL. */)
 {
+#ifdef HB_NO_SHAPE_AAT
+  if (selector_count)
+    *selector_count = 0;
+  return 0;
+#endif
+
   return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
 }
diff --git a/src/hb-aat-ltag-table.hh b/src/hb-aat-ltag-table.hh
index 6f34a00..711f9aa 100644
--- a/src/hb-aat-ltag-table.hh
+++ b/src/hb-aat-ltag-table.hh
@@ -50,7 +50,7 @@
   }
 
   protected:
-  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
+  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
 		tag;		/* Offset from the start of the table to
 				 * the beginning of the string */
   HBUINT16	length;		/* String length (in bytes) */
diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc
index 98c5d7f..d57ee84 100644
--- a/src/hb-aat-map.cc
+++ b/src/hb-aat-map.cc
@@ -34,6 +34,10 @@
 void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
 					unsigned int value)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   if (tag == HB_TAG ('a','a','l','t'))
   {
     feature_info_t *info = features.push();
@@ -53,6 +57,10 @@
 void
 hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
 {
+#ifdef HB_NO_SHAPE_AAT
+  return;
+#endif
+
   /* Sort features and merge duplicates */
   if (features.length)
   {
diff --git a/src/hb-algs.hh b/src/hb-algs.hh
index c346780..0b34f71 100644
--- a/src/hb-algs.hh
+++ b/src/hb-algs.hh
@@ -34,26 +34,54 @@
 #include "hb-null.hh"
 
 
+/* Encodes three unsigned integers in one 64-bit number.  If the inputs have more than 21 bits,
+ * values will be truncated / overlap, and might not decode exactly. */
+#define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
+#define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
+#define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
+#define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
+
+
 struct
 {
-  template <typename T> T
-  operator () (const T& v) const { return v; }
-} HB_FUNCOBJ (hb_identity);
+  /* Note.  This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
+  template <typename T> auto
+  operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
+}
+HB_FUNCOBJ (hb_identity);
+struct
+{
+  /* Like identity(), but only retains lvalue-references.  Rvalues are returned as rvalues. */
+  template <typename T> T&
+  operator () (T& v) const { return v; }
+
+  template <typename T> hb_remove_reference<T>
+  operator () (T&& v) const { return v; }
+}
+HB_FUNCOBJ (hb_lidentity);
+struct
+{
+  /* Like identity(), but always returns rvalue. */
+  template <typename T> hb_remove_reference<T>
+  operator () (T&& v) const { return v; }
+}
+HB_FUNCOBJ (hb_ridentity);
 
 struct
 {
   template <typename T> bool
-  operator () (const T& v) const { return bool (v); }
-} HB_FUNCOBJ (hb_bool);
+  operator () (T&& v) const { return bool (hb_forward<T> (v)); }
+}
+HB_FUNCOBJ (hb_bool);
 
 struct
 {
   private:
   template <typename T> auto
-  impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref_pointer (v).hash ())
+  impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
 
   template <typename T,
-	    hb_enable_if (hb_is_integer (T))> auto
+	    hb_enable_if (hb_is_integral (T))> auto
   impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
   (
     /* Knuth's multiplicative method: */
@@ -64,40 +92,97 @@
 
   template <typename T> auto
   operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
-} HB_FUNCOBJ (hb_hash);
+}
+HB_FUNCOBJ (hb_hash);
+
 
 struct
 {
   private:
 
   /* Pointer-to-member-function. */
-  template <typename Appl, typename Val1, typename ...Vals> auto
-  impl (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN
-  ((hb_deref_pointer (hb_forward<Val1> (v1)).*hb_forward<Appl> (a)) (hb_forward<Vals> (vs)...))
+  template <typename Appl, typename T, typename ...Ts> auto
+  impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
+  ((hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
 
   /* Pointer-to-member. */
-  template <typename Appl, typename Val> auto
-  impl (Appl&& a, hb_priority<1>, Val &&v) const HB_AUTO_RETURN
-  ((hb_deref_pointer (hb_forward<Val> (v))).*hb_forward<Appl> (a))
+  template <typename Appl, typename T> auto
+  impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
+  ((hb_deref (hb_forward<T> (v))).*hb_forward<Appl> (a))
 
   /* Operator(). */
-  template <typename Appl, typename ...Vals> auto
-  impl (Appl&& a, hb_priority<0>, Vals &&...vs) const HB_AUTO_RETURN
-  (hb_deref_pointer (hb_forward<Appl> (a)) (hb_forward<Vals> (vs)...))
+  template <typename Appl, typename ...Ts> auto
+  impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
+  (hb_deref (hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
 
   public:
-  template <typename Appl, typename Val1, typename ...Vals> auto
-  impl2 (Appl&& a, hb_priority<2>, Val1 &&v1, Vals &&...vs) const HB_AUTO_RETURN
-  (hb_deref_pointer (hb_forward<Val1> (v1)).*hb_forward<Appl> (a) (hb_forward<Vals> (vs)...))
 
-  template <typename Appl, typename ...Vals> auto
-  operator () (Appl&& a, Vals &&...vs) const HB_AUTO_RETURN
+  template <typename Appl, typename ...Ts> auto
+  operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
   (
     impl (hb_forward<Appl> (a),
 	  hb_prioritize,
-	  hb_forward<Vals> (vs)...)
+	  hb_forward<Ts> (ds)...)
   )
-} HB_FUNCOBJ (hb_invoke);
+}
+HB_FUNCOBJ (hb_invoke);
+
+template <unsigned Pos, typename Appl, typename V>
+struct hb_partial_t
+{
+  hb_partial_t (Appl a, V v) : a (a), v (v) {}
+
+  static_assert (Pos > 0, "");
+
+  template <typename ...Ts,
+	    unsigned P = Pos,
+	    hb_enable_if (P == 1)> auto
+  operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
+						   hb_declval (V),
+						   hb_declval (Ts)...))
+  {
+    return hb_invoke (hb_forward<Appl> (a),
+		      hb_forward<V> (v),
+		      hb_forward<Ts> (ds)...);
+  }
+  template <typename T0, typename ...Ts,
+	    unsigned P = Pos,
+	    hb_enable_if (P == 2)> auto
+  operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
+							    hb_declval (T0),
+							    hb_declval (V),
+							    hb_declval (Ts)...))
+  {
+    return hb_invoke (hb_forward<Appl> (a),
+		      hb_forward<T0> (d0),
+		      hb_forward<V> (v),
+		      hb_forward<Ts> (ds)...);
+  }
+
+  private:
+  hb_reference_wrapper<Appl> a;
+  V v;
+};
+template <unsigned Pos=1, typename Appl, typename V>
+auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
+(( hb_partial_t<Pos, Appl, V> (a, v) ))
+
+/* The following hacky replacement version is to make Visual Stuiod build:. */ \
+/* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
+#ifdef _MSC_VER
+#define HB_PARTIALIZE(Pos) \
+  template <typename _T> \
+  decltype(auto) operator () (_T&& _v) const \
+  { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
+  static_assert (true, "")
+#else
+#define HB_PARTIALIZE(Pos) \
+  template <typename _T> \
+  auto operator () (_T&& _v) const HB_AUTO_RETURN \
+  (hb_partial<Pos> (this, hb_forward<_T> (_v))) \
+  static_assert (true, "")
+#endif
+
 
 struct
 {
@@ -105,7 +190,7 @@
 
   template <typename Pred, typename Val> auto
   impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
-  (hb_deref_pointer (hb_forward<Pred> (p)).has (v))
+  (hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v)))
 
   template <typename Pred, typename Val> auto
   impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
@@ -122,21 +207,56 @@
 	  hb_forward<Val> (v),
 	  hb_prioritize)
   )
-} HB_FUNCOBJ (hb_has);
+}
+HB_FUNCOBJ (hb_has);
+
+struct
+{
+  private:
+
+  template <typename Pred, typename Val> auto
+  impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
+  (
+    hb_has (hb_forward<Pred> (p),
+	    hb_forward<Val> (v))
+  )
+
+  template <typename Pred, typename Val> auto
+  impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
+  (
+    hb_forward<Pred> (p) == hb_forward<Val> (v)
+  )
+
+  public:
+
+  template <typename Pred, typename Val> auto
+  operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
+    impl (hb_forward<Pred> (p),
+	  hb_forward<Val> (v),
+	  hb_prioritize)
+  )
+}
+HB_FUNCOBJ (hb_match);
 
 struct
 {
   private:
 
   template <typename Proj, typename Val> auto
+  impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
+  (hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v)))
+
+  template <typename Proj, typename Val> auto
   impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
-  (hb_deref_pointer (hb_forward<Proj> (f)).get (hb_forward<Val> (v)))
+  (
+    hb_invoke (hb_forward<Proj> (f),
+	       hb_forward<Val> (v))
+  )
 
   template <typename Proj, typename Val> auto
   impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
   (
-    hb_invoke (hb_forward<Proj> (f),
-	       hb_forward<Val> (v))
+    hb_forward<Proj> (f)[hb_forward<Val> (v)]
   )
 
   public:
@@ -148,7 +268,8 @@
 	  hb_forward<Val> (v),
 	  hb_prioritize)
   )
-} HB_FUNCOBJ (hb_get);
+}
+HB_FUNCOBJ (hb_get);
 
 
 template <typename T1, typename T2>
@@ -159,38 +280,61 @@
   typedef hb_pair_t<T1, T2> pair_t;
 
   hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
-  hb_pair_t (const pair_t& o) : first (o.first), second (o.second) {}
+
+  template <typename Q1, typename Q2,
+	    hb_enable_if (hb_is_convertible (T1, Q1) &&
+			  hb_is_convertible (T2, T2))>
+  operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
+
+  hb_pair_t<T1, T2> reverse () const
+  { return hb_pair_t<T1, T2> (second, first); }
 
   bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
+  bool operator != (const pair_t& o) const { return !(*this == o); }
+  bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
+  bool operator >= (const pair_t& o) const { return !(*this < o); }
+  bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
+  bool operator <= (const pair_t& o) const { return !(*this > o); }
 
   T1 first;
   T2 second;
 };
+#define hb_pair_t(T1,T2) hb_pair_t<T1, T2>
 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
 
 struct
 {
-  template <typename Pair> auto
-  operator () (const Pair& pair) const HB_AUTO_RETURN (pair.first)
-} HB_FUNCOBJ (hb_first);
+  template <typename Pair> typename Pair::first_t
+  operator () (const Pair& pair) const { return pair.first; }
+}
+HB_FUNCOBJ (hb_first);
 
 struct
 {
-  template <typename Pair> auto
-  operator () (const Pair& pair) const HB_AUTO_RETURN (pair.second)
-} HB_FUNCOBJ (hb_second);
+  template <typename Pair> typename Pair::second_t
+  operator () (const Pair& pair) const { return pair.second; }
+}
+HB_FUNCOBJ (hb_second);
 
+/* Note.  In min/max impl, we can use hb_type_identity<T> for second argument.
+ * However, that would silently convert between different-signedness integers.
+ * Instead we accept two different types, such that compiler can err if
+ * comparing integers of different signedness. */
 struct
 {
   template <typename T, typename T2> auto
-  operator () (const T& a, const T2& b) const HB_AUTO_RETURN (a <= b ? a : b)
-} HB_FUNCOBJ (hb_min);
+  operator () (T&& a, T2&& b) const HB_AUTO_RETURN
+  (hb_forward<T> (a) <= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
+}
+HB_FUNCOBJ (hb_min);
 struct
 {
   template <typename T, typename T2> auto
-  operator () (const T& a, const T2& b) const HB_AUTO_RETURN (a >= b ? a : b)
-} HB_FUNCOBJ (hb_max);
+  operator () (T&& a, T2&& b) const HB_AUTO_RETURN
+  (hb_forward<T> (a) >= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
+}
+HB_FUNCOBJ (hb_max);
 
 
 /*
@@ -402,14 +546,6 @@
 static inline unsigned char TOLOWER (unsigned char c)
 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
 
-#undef MIN
-template <typename Type>
-static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
-
-#undef MAX
-template <typename Type>
-static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
-
 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
 { return (a + (b - 1)) / b; }
 
@@ -467,40 +603,19 @@
 /*
  * Sort and search.
  */
-
+template <typename ...Ts>
 static inline void *
 hb_bsearch (const void *key, const void *base,
 	    size_t nmemb, size_t size,
-	    int (*compar)(const void *_key, const void *_item))
-{
-  int min = 0, max = (int) nmemb - 1;
-  while (min <= max)
-  {
-    int mid = (min + max) / 2;
-    const void *p = (const void *) (((const char *) base) + (mid * size));
-    int c = compar (key, p);
-    if (c < 0)
-      max = mid - 1;
-    else if (c > 0)
-      min = mid + 1;
-    else
-      return (void *) p;
-  }
-  return nullptr;
-}
-
-static inline void *
-hb_bsearch_r (const void *key, const void *base,
-	      size_t nmemb, size_t size,
-	      int (*compar)(const void *_key, const void *_item, void *_arg),
-	      void *arg)
+	    int (*compar)(const void *_key, const void *_item, Ts... _ds),
+	    Ts... ds)
 {
   int min = 0, max = (int) nmemb - 1;
   while (min <= max)
   {
     int mid = ((unsigned int) min + (unsigned int) max) / 2;
     const void *p = (const void *) (((const char *) base) + (mid * size));
-    int c = compar (key, p, arg);
+    int c = compar (key, p, ds...);
     if (c < 0)
       max = mid - 1;
     else if (c > 0)
@@ -661,7 +776,7 @@
 {
   /* Pain because we don't know whether s is nul-terminated. */
   char buf[64];
-  len = MIN (ARRAY_LENGTH (buf) - 1, len);
+  len = hb_min (ARRAY_LENGTH (buf) - 1, len);
   strncpy (buf, s, len);
   buf[len] = '\0';
 
@@ -675,30 +790,83 @@
 }
 
 
-struct HbOpOr
-{
-  static constexpr bool passthru_left = true;
-  static constexpr bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
-};
-struct HbOpAnd
-{
+/* Operators. */
+
+struct hb_bitwise_and
+{ HB_PARTIALIZE(2);
   static constexpr bool passthru_left = false;
   static constexpr bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
-};
-struct HbOpMinus
-{
-  static constexpr bool passthru_left = true;
-  static constexpr bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
-};
-struct HbOpXor
-{
+  template <typename T> auto
+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
+}
+HB_FUNCOBJ (hb_bitwise_and);
+struct hb_bitwise_or
+{ HB_PARTIALIZE(2);
   static constexpr bool passthru_left = true;
   static constexpr bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
-};
+  template <typename T> auto
+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
+}
+HB_FUNCOBJ (hb_bitwise_or);
+struct hb_bitwise_xor
+{ HB_PARTIALIZE(2);
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = true;
+  template <typename T> auto
+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
+}
+HB_FUNCOBJ (hb_bitwise_xor);
+struct hb_bitwise_sub
+{ HB_PARTIALIZE(2);
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = false;
+  template <typename T> auto
+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
+}
+HB_FUNCOBJ (hb_bitwise_sub);
+
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T, typename T2> auto
+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
+}
+HB_FUNCOBJ (hb_add);
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T, typename T2> auto
+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
+}
+HB_FUNCOBJ (hb_sub);
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T, typename T2> auto
+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
+}
+HB_FUNCOBJ (hb_mul);
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T, typename T2> auto
+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
+}
+HB_FUNCOBJ (hb_div);
+struct
+{ HB_PARTIALIZE(2);
+  template <typename T, typename T2> auto
+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
+}
+HB_FUNCOBJ (hb_mod);
+struct
+{
+  template <typename T> auto
+  operator () (const T &a) const HB_AUTO_RETURN (+a)
+}
+HB_FUNCOBJ (hb_pos);
+struct
+{
+  template <typename T> auto
+  operator () (const T &a) const HB_AUTO_RETURN (-a)
+}
+HB_FUNCOBJ (hb_neg);
 
 
 /* Compiler-assisted vectorization. */
@@ -714,26 +882,26 @@
 
   void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
 
-  template <class Op>
-  hb_vector_size_t process (const hb_vector_size_t &o) const
+  template <typename Op>
+  hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
   {
     hb_vector_size_t r;
 #if HB_VECTOR_SIZE
     if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
       for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-	Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
+	r.u.vec[i] = op (u.vec[i], o.u.vec[i]);
     else
 #endif
       for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-	Op::process (r.u.v[i], u.v[i], o.u.v[i]);
+	r.u.v[i] = op (u.v[i], o.u.v[i]);
     return r;
   }
   hb_vector_size_t operator | (const hb_vector_size_t &o) const
-  { return process<HbOpOr> (o); }
+  { return process (hb_bitwise_or, o); }
   hb_vector_size_t operator & (const hb_vector_size_t &o) const
-  { return process<HbOpAnd> (o); }
+  { return process (hb_bitwise_and, o); }
   hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-  { return process<HbOpXor> (o); }
+  { return process (hb_bitwise_xor, o); }
   hb_vector_size_t operator ~ () const
   {
     hb_vector_size_t r;
diff --git a/src/hb-array.hh b/src/hb-array.hh
index b4619ee..587000c 100644
--- a/src/hb-array.hh
+++ b/src/hb-array.hh
@@ -42,19 +42,20 @@
   /*
    * Constructors.
    */
-  hb_array_t () : arrayZ (nullptr), length (0) {}
-  hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
-  template <unsigned int length_> hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
+  hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {}
+  hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {}
+  template <unsigned int length_>
+  hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {}
 
   template <typename U,
-	    hb_enable_if (hb_is_cr_convertible_to(U, Type))>
+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
   hb_array_t (const hb_array_t<U> &o) :
     hb_iter_with_fallback_t<hb_array_t<Type>, Type&> (),
-    arrayZ (o.arrayZ), length (o.length) {}
+    arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
   template <typename U,
-	    hb_enable_if (hb_is_cr_convertible_to(U, Type))>
+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
   hb_array_t& operator = (const hb_array_t<U> &o)
-  { arrayZ = o.arrayZ; length = o.length; return *this; }
+  { arrayZ = o.arrayZ; length = o.length; backwards_length = o.backwards_length; return *this; }
 
   /*
    * Iterator implementation.
@@ -71,15 +72,25 @@
     if (unlikely (n > length))
       n = length;
     length -= n;
+    backwards_length += n;
     arrayZ += n;
   }
   void __rewind__ (unsigned n)
   {
-    if (unlikely (n > length))
-      n = length;
-    length -= n;
+    if (unlikely (n > backwards_length))
+      n = backwards_length;
+    length += n;
+    backwards_length -= n;
+    arrayZ -= n;
   }
   unsigned __len__ () const { return length; }
+  /* Ouch. The operator== compares the contents of the array.  For range-based for loops,
+   * it's best if we can just compare arrayZ, though comparing contents is still fast,
+   * but also would require that Type has operator==.  As such, we optimize this operator
+   * for range-based for loop and just compare arrayZ.  No need to compare length, as we
+   * assume we're only compared to .end(). */
+  bool operator != (const hb_array_t& o) const
+  { return arrayZ != o.arrayZ; }
 
   /* Extra operators.
    */
@@ -141,7 +152,7 @@
   }
   void qsort (unsigned int start, unsigned int end)
   {
-    end = MIN (end, length);
+    end = hb_min (end, length);
     assert (start <= end);
     if (likely (start < end))
       ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
@@ -164,7 +175,7 @@
     else
       count -= start_offset;
     if (seg_count)
-      count = *seg_count = MIN (count, *seg_count);
+      count = *seg_count = hb_min (count, *seg_count);
     return hb_array_t<Type> (arrayZ + start_offset, count);
   }
   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
@@ -174,6 +185,17 @@
   void free ()
   { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
 
+  template <typename hb_serialize_context_t>
+  hb_array_t copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    auto* out = c->start_embed (arrayZ);
+    if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
+    for (unsigned i = 0; i < length; i++)
+      out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
+    return_trace (hb_array_t (out, length));
+  }
+
   template <typename hb_sanitize_context_t>
   bool sanitize (hb_sanitize_context_t *c) const
   { return c->check_array (arrayZ, length); }
@@ -185,6 +207,7 @@
   public:
   Type *arrayZ;
   unsigned int length;
+  unsigned int backwards_length;
 };
 template <typename T> inline hb_array_t<T>
 hb_array (T *array, unsigned int length)
@@ -212,18 +235,23 @@
 
   hb_sorted_array_t () : hb_array_t<Type> () {}
   hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
-  template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
+  template <unsigned int length_>
+  hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
 
   template <typename U,
-	    hb_enable_if (hb_is_cr_convertible_to(U, Type))>
+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
   hb_sorted_array_t (const hb_array_t<U> &o) :
     hb_iter_t<hb_sorted_array_t<Type>, Type&> (),
     hb_array_t<Type> (o) {}
   template <typename U,
-	    hb_enable_if (hb_is_cr_convertible_to(U, Type))>
+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
   hb_sorted_array_t& operator = (const hb_array_t<U> &o)
   { hb_array_t<Type> (*this) = o; return *this; }
 
+  /* Iterator implementation. */
+  bool operator != (const hb_sorted_array_t& o) const
+  { return this->arrayZ != o.arrayZ || this->length != o.length; }
+
   hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
   { return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
   hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
@@ -296,7 +324,7 @@
 {
   return length == o.length &&
   + hb_zip (*this, o)
-  | hb_map ([] (hb_pair_t<T&, T&> &&_) -> bool { return _.first == _.second; })
+  | hb_map ([] (hb_pair_t<T&, T&> &&_) { return _.first == _.second; })
   | hb_all
   ;
 }
@@ -306,7 +334,7 @@
   return
   + hb_iter (*this)
   | hb_map (hb_hash)
-  | hb_reduce ([] (uint32_t a, uint32_t b) -> uint32_t { return a * 31 + b; }, 0)
+  | hb_reduce ([] (uint32_t a, uint32_t b) { return a * 31 + b; }, 0)
   ;
 }
 
diff --git a/src/hb-atomic.hh b/src/hb-atomic.hh
index 8307a54..45413d5 100644
--- a/src/hb-atomic.hh
+++ b/src/hb-atomic.hh
@@ -107,7 +107,7 @@
 
 static inline void _hb_memory_barrier ()
 {
-#if !defined(MemoryBarrier)
+#ifndef MemoryBarrier
   /* MinGW has a convoluted history of supporting MemoryBarrier. */
   LONG dummy = 0;
   InterlockedExchange (&dummy, 1);
@@ -216,7 +216,7 @@
 
 #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
 
-#define _hb_memory_barrier()
+#define _hb_memory_barrier()			do {} while (0)
 
 #define hb_atomic_int_impl_add(AI, V)		((*(AI) += (V)) - (V))
 
@@ -227,7 +227,7 @@
 
 #define hb_atomic_int_impl_add(AI, V)		((*(AI) += (V)) - (V))
 
-#define _hb_memory_barrier()
+#define _hb_memory_barrier()			do {} while (0)
 
 #define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
 
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 54637c7..5783fb2 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -30,7 +30,7 @@
  * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
  * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
  */
-#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER)
+#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) && !defined(__NetBSD__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-macros"
 #define _POSIX_C_SOURCE 200809L
@@ -155,7 +155,7 @@
   hb_blob_make_immutable (parent);
 
   blob = hb_blob_create (parent->data + offset,
-			 MIN (length, parent->length - offset),
+			 hb_min (length, parent->length - offset),
 			 HB_MEMORY_MODE_READONLY,
 			 hb_blob_reference (parent),
 			 _hb_blob_destroy);
diff --git a/src/hb-blob.h b/src/hb-blob.h
index d1d9134..f80e9af 100644
--- a/src/hb-blob.h
+++ b/src/hb-blob.h
@@ -71,6 +71,9 @@
 		void              *user_data,
 		hb_destroy_func_t  destroy);
 
+HB_EXTERN hb_blob_t *
+hb_blob_create_from_file (const char *file_name);
+
 /* Always creates with MEMORY_MODE_READONLY.
  * Even if the parent blob is writable, we don't
  * want the user of the sub-blob to be able to
@@ -123,9 +126,6 @@
 HB_EXTERN char *
 hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
 
-HB_EXTERN hb_blob_t *
-hb_blob_create_from_file (const char *file_name);
-
 HB_END_DECLS
 
 #endif /* HB_BLOB_H */
diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc
index 6e265e8..d3732fd 100644
--- a/src/hb-buffer-serialize.cc
+++ b/src/hb-buffer-serialize.cc
@@ -28,8 +28,10 @@
 
 
 static const char *serialize_formats[] = {
+#ifndef HB_NO_BUFFER_SERIALIZE
   "text",
   "json",
+#endif
   nullptr
 };
 
@@ -85,10 +87,12 @@
 const char *
 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
 {
-  switch (format)
+  switch ((unsigned) format)
   {
+#ifndef HB_NO_BUFFER_SERIALIZE
     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
     case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
+#endif
     default:
     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:	return nullptr;
   }
@@ -138,34 +142,34 @@
       *p++ = '"';
     }
     else
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
 
     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
     }
 
     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
     {
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
 			     x+pos[i].x_offset, y+pos[i].y_offset));
       if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
 			       pos[i].x_advance, pos[i].y_advance));
     }
 
     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
     {
       if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
     }
 
     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
     {
       hb_glyph_extents_t extents;
       hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
 		extents.x_bearing, extents.y_bearing));
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
 		extents.width, extents.height));
     }
 
@@ -224,37 +228,37 @@
       p += strlen (p);
     }
     else
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
 
     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
     }
 
     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
     {
       if (x+pos[i].x_offset || y+pos[i].y_offset)
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
 
       if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
       {
 	*p++ = '+';
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
 	if (pos[i].y_advance)
-	  p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
+	  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
       }
     }
 
     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
     {
       if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
-	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
     }
 
     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
     {
       hb_glyph_extents_t extents;
       hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
-      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
     }
 
     unsigned int l = p - b;
@@ -344,6 +348,10 @@
   if (buf_size)
     *buf = '\0';
 
+#ifdef HB_NO_BUFFER_SERIALIZE
+  return 0;
+#endif
+
   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
 
@@ -380,7 +388,7 @@
 parse_uint (const char *pp, const char *end, uint32_t *pv)
 {
   char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
   strncpy (buf, pp, len);
   buf[len] = '\0';
 
@@ -401,7 +409,7 @@
 parse_int (const char *pp, const char *end, int32_t *pv)
 {
   char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
   strncpy (buf, pp, len);
   buf[len] = '\0';
 
@@ -449,6 +457,10 @@
     end_ptr = &end;
   *end_ptr = buf;
 
+#ifdef HB_NO_BUFFER_SERIALIZE
+  return false;
+#endif
+
   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
 
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 2dc02e9..bbbbd22 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -524,7 +524,7 @@
   unsigned int cluster = info[start].cluster;
 
   for (unsigned int i = start + 1; i < end; i++)
-    cluster = MIN<unsigned int> (cluster, info[i].cluster);
+    cluster = hb_min (cluster, info[i].cluster);
 
   /* Extend end */
   while (end < len && info[end - 1].cluster == info[end].cluster)
@@ -555,7 +555,7 @@
   unsigned int cluster = out_info[start].cluster;
 
   for (unsigned int i = start + 1; i < end; i++)
-    cluster = MIN<unsigned int> (cluster, out_info[i].cluster);
+    cluster = hb_min (cluster, out_info[i].cluster);
 
   /* Extend start */
   while (start && out_info[start - 1].cluster == out_info[start].cluster)
@@ -2026,7 +2026,10 @@
 bool
 hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
 {
+#ifdef HB_NO_BUFFER_MESSAGE
+  return false;
+#endif
   char buf[100];
-  vsnprintf (buf, sizeof (buf),  fmt, ap);
+  vsnprintf (buf, sizeof (buf), fmt, ap);
   return (bool) this->message_func (this, font, buf, this->message_data);
 }
diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh
index 330f88b..b2b190a 100644
--- a/src/hb-buffer.hh
+++ b/src/hb-buffer.hh
@@ -379,7 +379,7 @@
 				     unsigned int cluster) const
   {
     for (unsigned int i = start; i < end; i++)
-      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
+      cluster = hb_min (cluster, infos[i].cluster);
     return cluster;
   }
   void
diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh
index 283bdf1..61bdba5 100644
--- a/src/hb-cff-interp-cs-common.hh
+++ b/src/hb-cff-interp-cs-common.hh
@@ -147,8 +147,9 @@
     return callStack.in_error () || SUPER::in_error ();
   }
 
-  bool popSubrNum (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
+  bool pop_subr_num (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
   {
+    subr_num = 0;
     int n = SUPER::argStack.pop_int ();
     n += biasedSubrs.get_bias ();
     if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ())))
@@ -158,11 +159,11 @@
     return true;
   }
 
-  void callSubr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
+  void call_subr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
   {
-    unsigned int subr_num;
+    unsigned int subr_num = 0;
 
-    if (unlikely (!popSubrNum (biasedSubrs, subr_num)
+    if (unlikely (!pop_subr_num (biasedSubrs, subr_num)
 		 || callStack.get_count () >= kMaxCallLimit))
     {
       SUPER::set_error ();
@@ -175,7 +176,7 @@
     SUPER::str_ref = context.str_ref;
   }
 
-  void returnFromSubr ()
+  void return_from_subr ()
   {
     if (unlikely (SUPER::str_ref.in_error ()))
       SUPER::set_error ();
@@ -246,7 +247,7 @@
   static void flex1 (ENV &env, PARAM& param) {}
 };
 
-template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM> >
+template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM>>
 struct cs_opset_t : opset_t<ARG>
 {
   static void process_op (op_code_t op, ENV &env, PARAM& param)
@@ -254,7 +255,7 @@
     switch (op) {
 
       case OpCode_return:
-	env.returnFromSubr ();
+	env.return_from_subr ();
 	break;
       case OpCode_endchar:
 	OPSET::check_width (op, env, param);
@@ -267,11 +268,11 @@
 	break;
 
       case OpCode_callsubr:
-	env.callSubr (env.localSubrs, CSType_LocalSubr);
+	env.call_subr (env.localSubrs, CSType_LocalSubr);
 	break;
 
       case OpCode_callgsubr:
-	env.callSubr (env.globalSubrs, CSType_GlobalSubr);
+	env.call_subr (env.globalSubrs, CSType_GlobalSubr);
 	break;
 
       case OpCode_hstem:
diff --git a/src/hb-cff1-interp-cs.hh b/src/hb-cff1-interp-cs.hh
index c7209ed..cc52856 100644
--- a/src/hb-cff1-interp-cs.hh
+++ b/src/hb-cff1-interp-cs.hh
@@ -81,7 +81,7 @@
   typedef cs_interp_env_t<number_t, CFF1Subrs> SUPER;
 };
 
-template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM> >
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM>>
 struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>
 {
   /* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh
index 49e5ee7..1faf208 100644
--- a/src/hb-cff2-interp-cs.hh
+++ b/src/hb-cff2-interp-cs.hh
@@ -193,7 +193,7 @@
 
   typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
 };
-template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM> >
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM>>
 struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
 {
   static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
diff --git a/src/hb-common.cc b/src/hb-common.cc
index c453443..71791db 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -67,7 +67,7 @@
         p = c + strlen (c);
 
 #define OPTION(name, symbol) \
-	if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true;
+	if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) do { u.opts.symbol = true; } while (0)
 
       OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
       OPTION ("aat", aat);
@@ -356,7 +356,7 @@
   {
     /* NUL-terminate it. */
     char strbuf[64];
-    len = MIN (len, (int) sizeof (strbuf) - 1);
+    len = hb_min (len, (int) sizeof (strbuf) - 1);
     memcpy (strbuf, str, len);
     strbuf[len] = '\0';
     item = lang_find_or_insert (strbuf);
@@ -720,7 +720,7 @@
 parse_uint (const char **pp, const char *end, unsigned int *pv)
 {
   char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
   strncpy (buf, *pp, len);
   buf[len] = '\0';
 
@@ -744,7 +744,7 @@
 parse_uint32 (const char **pp, const char *end, uint32_t *pv)
 {
   char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
   strncpy (buf, *pp, len);
   buf[len] = '\0';
 
@@ -825,7 +825,7 @@
 parse_float (const char **pp, const char *end, float *pv)
 {
   char buf[32];
-  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
   strncpy (buf, *pp, len);
   buf[len] = '\0';
 
@@ -1071,21 +1071,21 @@
   {
     s[len++] = '[';
     if (feature->start)
-      len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
+      len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
     if (feature->end != feature->start + 1) {
       s[len++] = ':';
       if (feature->end != (unsigned int) -1)
-	len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
+	len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
     }
     s[len++] = ']';
   }
   if (feature->value > 1)
   {
     s[len++] = '=';
-    len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
+    len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
   }
   assert (len < ARRAY_LENGTH (s));
-  len = MIN (len, size - 1);
+  len = hb_min (len, size - 1);
   memcpy (buf, s, len);
   buf[len] = '\0';
 }
@@ -1152,20 +1152,21 @@
   while (len && s[len - 1] == ' ')
     len--;
   s[len++] = '=';
-  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
+  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
 
   assert (len < ARRAY_LENGTH (s));
-  len = MIN (len, size - 1);
+  len = hb_min (len, size - 1);
   memcpy (buf, s, len);
   buf[len] = '\0';
 }
 
 /**
  * hb_color_get_alpha:
+ * color: a #hb_color_t we are interested in its channels.
  *
+ * Return value: Alpha channel value of the given color
  *
- *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
 uint8_t
 (hb_color_get_alpha) (hb_color_t color)
@@ -1175,10 +1176,11 @@
 
 /**
  * hb_color_get_red:
+ * color: a #hb_color_t we are interested in its channels.
  *
+ * Return value: Red channel value of the given color
  *
- *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
 uint8_t
 (hb_color_get_red) (hb_color_t color)
@@ -1188,10 +1190,11 @@
 
 /**
  * hb_color_get_green:
+ * color: a #hb_color_t we are interested in its channels.
  *
+ * Return value: Green channel value of the given color
  *
- *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
 uint8_t
 (hb_color_get_green) (hb_color_t color)
@@ -1201,10 +1204,11 @@
 
 /**
  * hb_color_get_blue:
+ * color: a #hb_color_t we are interested in its channels.
  *
+ * Return value: Blue channel value of the given color
  *
- *
- * Since: REPLACEME
+ * Since: 2.1.0
  */
 uint8_t
 (hb_color_get_blue) (hb_color_t color)
diff --git a/src/hb-config.hh b/src/hb-config.hh
new file mode 100644
index 0000000..8bdce35
--- /dev/null
+++ b/src/hb-config.hh
@@ -0,0 +1,131 @@
+/*
+ * Copyright © 2019  Facebook, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Facebook Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_CONFIG_HH
+#define HB_CONFIG_HH
+
+#if 0 /* Make test happy. */
+#include "hb.hh"
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HB_TINY
+#define HB_LEAN
+#define HB_MINI
+#define HB_NO_MT
+#ifndef NDEBUG
+#define NDEBUG
+#endif
+#ifndef __OPTIMIZE_SIZE__
+#define __OPTIMIZE_SIZE__
+#endif
+#endif
+
+#ifdef HB_LEAN
+#define HB_DISABLE_DEPRECATED
+#define HB_NDEBUG
+#define HB_NO_ATEXIT
+#define HB_NO_BUFFER_MESSAGE
+#define HB_NO_BUFFER_SERIALIZE
+#define HB_NO_BITMAP
+#define HB_NO_CFF
+#define HB_NO_COLOR
+#define HB_NO_GETENV
+#define HB_NO_LAYOUT_UNUSED
+#define HB_NO_MATH
+#define HB_NO_NAME
+#define HB_NO_SUBSET_LAYOUT
+#endif
+
+#ifdef HB_MINI
+#define HB_NO_AAT
+#define HB_NO_LEGACY
+#endif
+
+/* Closure. */
+
+#ifdef HB_DISABLE_DEPRECATED
+#define HB_IF_NOT_DEPRECATED(x)
+#else
+#define HB_IF_NOT_DEPRECATED(x) x
+#endif
+
+#ifdef HB_NO_AAT
+#define HB_NO_OT_NAME_LANGUAGE_AAT
+#define HB_NO_SHAPE_AAT
+#endif
+
+#ifdef HB_NO_BITMAP
+#define HB_NO_OT_FONT_BITMAP
+#endif
+
+#ifdef HB_NO_CFF
+#define HB_NO_OT_FONT_CFF
+#define HB_NO_SUBSET_CFF
+#endif
+
+#ifdef HB_NO_GETENV
+#define HB_NO_UNISCRIBE_BUG_COMPATIBLE
+#endif
+
+#ifdef HB_NO_LEGACY
+#define HB_NO_OT_LAYOUT_BLACKLIST
+#define HB_NO_OT_SHAPE_FALLBACK
+#endif
+
+#ifdef HB_NO_NAME
+#define HB_NO_OT_NAME_LANGUAGE
+#endif
+
+#ifdef HB_NO_OT_SHAPE_FALLBACK
+#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
+#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
+#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
+#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
+#endif
+
+#ifdef NDEBUG
+#ifndef HB_NDEBUG
+#define HB_NDEBUG
+#endif
+#endif
+
+#ifdef __OPTIMIZE_SIZE__
+#ifndef HB_OPTIMIZE_SIZE
+#define HB_OPTIMIZE_SIZE
+#endif
+#endif
+
+#ifdef HAVE_CONFIG_OVERRIDE_H
+#include "config-override.h"
+#endif
+
+
+#endif /* HB_CONFIG_HH */
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 66f0fce..85993d1 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -55,13 +55,13 @@
    * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
    */
   ptem *= 96.f / 72.f;
-  return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem;
+  return (CGFloat) (ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem);
 }
 static float
 coretext_font_size_to_ptem (CGFloat size)
 {
-  size *= 72.f / 96.f;
-  return size <= 0.f ? 0 : size;
+  size *= 72. / 96.;
+  return size <= 0 ? 0 : size;
 }
 
 static void
@@ -598,7 +598,7 @@
       } else {
         active_feature_t *feature = active_features.find (&event->feature);
 	if (feature)
-	  active_features.remove (feature - active_features.arrayZ ());
+	  active_features.remove (feature - active_features.arrayZ);
       }
     }
   }
@@ -608,7 +608,7 @@
 
 #define ALLOCATE_ARRAY(Type, name, len, on_no_room) \
   Type *name = (Type *) scratch; \
-  { \
+  do { \
     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
     if (unlikely (_consumed > scratch_size)) \
     { \
@@ -617,7 +617,7 @@
     } \
     scratch += _consumed; \
     scratch_size -= _consumed; \
-  }
+  } while (0)
 
   ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/);
   unsigned int chars_len = 0;
@@ -771,7 +771,7 @@
 	      feature.start < chars_len && feature.start < feature.end)
 	  {
 	    CFRange feature_range = CFRangeMake (feature.start,
-	                                         MIN (feature.end, chars_len) - feature.start);
+	                                         hb_min (feature.end, chars_len) - feature.start);
 	    if (feature.value)
 	      CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName);
 	    else
@@ -1116,7 +1116,7 @@
 	unsigned int cluster = info[count - 1].cluster;
 	for (unsigned int i = count - 1; i > 0; i--)
 	{
-	  cluster = MIN (cluster, info[i - 1].cluster);
+	  cluster = hb_min (cluster, info[i - 1].cluster);
 	  info[i - 1].cluster = cluster;
 	}
       }
@@ -1125,7 +1125,7 @@
 	unsigned int cluster = info[0].cluster;
 	for (unsigned int i = 1; i < count; i++)
 	{
-	  cluster = MIN (cluster, info[i].cluster);
+	  cluster = hb_min (cluster, info[i].cluster);
 	  info[i].cluster = cluster;
 	}
       }
diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index 52d5942..e6d06e3 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -63,7 +63,7 @@
 static inline hb_options_t
 hb_options ()
 {
-#if defined(HB_NO_OPTIONS)
+#ifdef HB_NO_GETENV
   return hb_options_t ();
 #endif
   /* Make a local copy, so we can access bitfield threadsafely. */
@@ -161,7 +161,7 @@
       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
     fprintf (stderr, "%2u %s" VRBAR "%s",
 	     level,
-	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
+	     bars + sizeof (bars) - 1 - hb_min ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
 	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
   } else
     fprintf (stderr, "   " VRBAR LBAR);
@@ -249,8 +249,8 @@
 };
 
 template <>
-struct hb_printer_t<hb_void_t> {
-  const char *print (hb_void_t) { return ""; }
+struct hb_printer_t<hb_empty_t> {
+  const char *print (hb_empty_t) { return ""; }
 };
 
 
@@ -266,7 +266,7 @@
   }
 }
 template <>
-/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
+/*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED)
 {}
 
 template <int max_level, typename ret_t>
@@ -330,18 +330,20 @@
 				   const char *message,
 				   ...) HB_PRINTF_FUNC(6, 7) {}
 
-  ret_t ret (ret_t v,
-	     const char *func HB_UNUSED = nullptr,
-	     unsigned int line HB_UNUSED = 0) { return v; }
+  template <typename T>
+  T ret (T&& v,
+	 const char *func HB_UNUSED = nullptr,
+	 unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
 };
 
 /* For disabled tracing; optimize out everything.
  * https://github.com/harfbuzz/harfbuzz/pull/605 */
 template <typename ret_t>
 struct hb_no_trace_t {
-  ret_t ret (ret_t v,
-	     const char *func HB_UNUSED = "",
-	     unsigned int line HB_UNUSED = 0) { return v; }
+  template <typename T>
+  T ret (T&& v,
+	 const char *func HB_UNUSED = nullptr,
+	 unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
 };
 
 #define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h
index 4a5e702..026a62c 100644
--- a/src/hb-deprecated.h
+++ b/src/hb-deprecated.h
@@ -63,7 +63,7 @@
 					       hb_codepoint_t *glyph,
 					       void *user_data);
 
-HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void
+HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func and hb_font_funcs_set_variation_glyph_func) void
 hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
 			      hb_font_get_glyph_func_t func,
 			      void *user_data, hb_destroy_func_t destroy);
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index d8076c9..b135c49 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -530,12 +530,12 @@
   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
 #define ALLOCATE_ARRAY(Type, name, len) \
   Type *name = (Type *) scratch; \
-  { \
+  do { \
     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
     assert (_consumed <= scratch_size); \
     scratch += _consumed; \
     scratch_size -= _consumed; \
-  }
+  } while (0)
 
 #define utf16_index() var1.u32
 
@@ -778,7 +778,7 @@
   {
     uint32_t *p =
       &vis_clusters[log_clusters[buffer->info[i].utf16_index ()]];
-    *p = MIN (*p, buffer->info[i].cluster);
+    *p = hb_min (*p, buffer->info[i].cluster);
   }
   for (unsigned int i = 1; i < glyphCount; i++)
     if (vis_clusters[i] == (uint32_t) -1)
@@ -930,7 +930,9 @@
 
 /**
  * hb_directwrite_face_create:
- * @font_face:
+ * @font_face: a DirectWrite IDWriteFontFace object.
+ *
+ * Return value: #hb_face_t object corresponding to the given input
  *
  * Since: 2.4.0
  **/
@@ -945,9 +947,11 @@
 
 /**
 * hb_directwrite_face_get_font_face:
-* @face:
+* @face: a #hb_face_t object
 *
-* Since: REPLACEME
+* Return value: DirectWrite IDWriteFontFace object corresponding to the given input
+*
+* Since: 2.5.0
 **/
 IDWriteFontFace *
 hb_directwrite_face_get_font_face (hb_face_t *face)
diff --git a/src/hb-dispatch.hh b/src/hb-dispatch.hh
index c4347a6..be4a90f 100644
--- a/src/hb-dispatch.hh
+++ b/src/hb-dispatch.hh
@@ -38,10 +38,18 @@
 template <typename Context, typename Return, unsigned int MaxDebugDepth>
 struct hb_dispatch_context_t
 {
+  private:
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const Context* thiz () const { return static_cast<const Context *> (this); }
+        Context* thiz ()       { return static_cast<      Context *> (this); }
+  public:
   static constexpr unsigned max_debug_depth = MaxDebugDepth;
   typedef Return return_t;
   template <typename T, typename F>
   bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
+  template <typename T, typename ...Ts>
+  return_t dispatch (const T &obj, Ts&&... ds)
+  { return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); }
   static return_t no_dispatch_return_value () { return Context::default_return_value (); }
   static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
 };
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 20daefd..19ee353 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -336,6 +336,7 @@
   return ret;
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 static hb_position_t
 hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
@@ -373,6 +374,7 @@
 {
   return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
 }
+#endif
 
 static hb_bool_t
 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
@@ -925,6 +927,7 @@
   return font->get_glyph_v_origin (glyph, x, y);
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_font_get_glyph_h_kerning:
  * @font: a font.
@@ -964,6 +967,7 @@
 {
   return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
 }
+#endif
 
 /**
  * hb_font_get_glyph_extents:
@@ -1173,6 +1177,7 @@
   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_font_get_glyph_kerning_for_direction:
  * @font: a font.
@@ -1195,6 +1200,7 @@
 {
   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
 }
+#endif
 
 /**
  * hb_font_get_glyph_extents_for_origin:
@@ -1347,7 +1353,7 @@
 {
   hb_font_t *font = _hb_font_create (face);
 
-#if !defined(HB_NO_OT_FONT)
+#ifndef HB_NO_OT_FONT
   /* Install our in-house, very lightweight, funcs. */
   hb_ot_font_set_funcs (font);
 #endif
@@ -1916,6 +1922,7 @@
 }
 
 
+#ifndef HB_DISABLE_DEPRECATED
 /*
  * Deprecated get_glyph_func():
  */
@@ -2038,3 +2045,4 @@
 					  trampoline,
 					  trampoline_destroy);
 }
+#endif
diff --git a/src/hb-font.hh b/src/hb-font.hh
index aaa0fd9..95551bf 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -51,8 +51,8 @@
   HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
+  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning)) \
+  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \
   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
@@ -304,17 +304,25 @@
   hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
 				     hb_codepoint_t right_glyph)
   {
+#ifdef HB_DISABLE_DEPRECATED
+    return 0;
+#else
     return klass->get.f.glyph_h_kerning (this, user_data,
 					 left_glyph, right_glyph,
 					 klass->user_data.glyph_h_kerning);
+#endif
   }
 
   hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
 				     hb_codepoint_t bottom_glyph)
   {
+#ifdef HB_DISABLE_DEPRECATED
+    return 0;
+#else
     return klass->get.f.glyph_v_kerning (this, user_data,
 					 top_glyph, bottom_glyph,
 					 klass->user_data.glyph_v_kerning);
+#endif
   }
 
   hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
@@ -607,7 +615,7 @@
     return (hb_position_t) (scaled / upem);
   }
   hb_position_t em_scalef (float v, int scale)
-  { return (hb_position_t) round (v * scale / face->get_upem ()); }
+  { return (hb_position_t) roundf (v * scale / face->get_upem ()); }
   float em_fscale (int16_t v, int scale)
   { return (float) v * scale / face->get_upem (); }
 };
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index f8dab8b..d70c38a 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -439,7 +439,7 @@
   else {
     /* Make a nul-terminated version. */
     char buf[128];
-    len = MIN (len, (int) sizeof (buf) - 1);
+    len = hb_min (len, (int) sizeof (buf) - 1);
     strncpy (buf, name, len);
     buf[len] = '\0';
     *glyph = FT_Get_Name_Index (ft_face, buf);
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index fdb5453..f799f8b 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -202,6 +202,7 @@
 {
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_graphite2_font_get_gr_font:
  *
@@ -213,6 +214,7 @@
 {
   return nullptr;
 }
+#endif
 
 
 /*
@@ -308,12 +310,12 @@
 
 #define ALLOCATE_ARRAY(Type, name, len) \
   Type *name = (Type *) scratch; \
-  { \
+  do { \
     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
     assert (_consumed <= scratch_size); \
     scratch += _consumed; \
     scratch_size -= _consumed; \
-  }
+  } while (0)
 
   ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
   ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
diff --git a/src/hb-icu.cc b/src/hb-icu.cc
index c26c91d..399829a 100644
--- a/src/hb-icu.cc
+++ b/src/hb-icu.cc
@@ -49,6 +49,9 @@
  * Functions for using HarfBuzz with the ICU library to provide Unicode data.
  **/
 
+/* ICU doesn't do-while(0) around their statements.  Ugh!
+ * https://unicode-org.atlassian.net/browse/CLDR-13027 */
+#define HB_ICU_STMT(S) do { S } while (0)
 
 hb_script_t
 hb_icu_script_to_script (UScriptCode script)
@@ -183,9 +186,9 @@
 
   len = 0;
   err = false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err);
+  HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err));
   if (err) return false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err);
+  HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err));
   if (err) return false;
 
   icu_err = U_ZERO_ERROR;
@@ -193,7 +196,7 @@
   if (U_FAILURE (icu_err))
     return false;
   if (u_countChar32 (normalized, len) == 1) {
-    U16_GET_UNSAFE (normalized, 0, *ab);
+    HB_ICU_STMT (U16_GET_UNSAFE (normalized, 0, *ab));
     ret = true;
   } else {
     ret = false;
@@ -221,13 +224,13 @@
 
     len = u_countChar32 (decomposed, len);
     if (len == 1) {
-      U16_GET_UNSAFE (decomposed, 0, *a);
+      HB_ICU_STMT (U16_GET_UNSAFE (decomposed, 0, *a));
       *b = 0;
       return *a != ab;
     } else if (len == 2) {
       len =0;
-      U16_NEXT_UNSAFE (decomposed, len, *a);
-      U16_NEXT_UNSAFE (decomposed, len, *b);
+      HB_ICU_STMT (U16_NEXT_UNSAFE (decomposed, len, *a));
+      HB_ICU_STMT (U16_NEXT_UNSAFE (decomposed, len, *b));
     }
     return true;
   }
@@ -236,7 +239,7 @@
   /* We don't ifdef-out the fallback code such that compiler always
    * sees it and makes sure it's compilable. */
 
-  UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
+  UChar utf16[2], normalized[2 * 19/*HB_UNICODE_MAX_DECOMPOSITION_LEN*/ + 1];
   unsigned int len;
   hb_bool_t ret, err;
   UErrorCode icu_err;
@@ -247,7 +250,7 @@
 
   len = 0;
   err = false;
-  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err);
+  HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err));
   if (err) return false;
 
   icu_err = U_ZERO_ERROR;
@@ -258,13 +261,13 @@
   len = u_countChar32 (normalized, len);
 
   if (len == 1) {
-    U16_GET_UNSAFE (normalized, 0, *a);
+    HB_ICU_STMT (U16_GET_UNSAFE (normalized, 0, *a));
     *b = 0;
     ret = *a != ab;
   } else if (len == 2) {
     len =0;
-    U16_NEXT_UNSAFE (normalized, len, *a);
-    U16_NEXT_UNSAFE (normalized, len, *b);
+    HB_ICU_STMT (U16_NEXT_UNSAFE (normalized, len, *a));
+    HB_ICU_STMT (U16_NEXT_UNSAFE (normalized, len, *b));
 
     /* Here's the ugly part: if ab decomposes to a single character and
      * that character decomposes again, we have to detect that and undo
@@ -275,7 +278,7 @@
     if (U_FAILURE (icu_err))
       return false;
     hb_codepoint_t c;
-    U16_GET_UNSAFE (recomposed, 0, c);
+    HB_ICU_STMT (U16_GET_UNSAFE (recomposed, 0, c));
     if (c != *a && c != ab) {
       *a = c;
       *b = 0;
@@ -284,7 +287,7 @@
   } else {
     /* If decomposed to more than two characters, take the last one,
      * and recompose the rest to get the first component. */
-    U16_PREV_UNSAFE (normalized, len, *b); /* Changes len in-place. */
+    HB_ICU_STMT (U16_PREV_UNSAFE (normalized, len, *b)); /* Changes len in-place. */
     UChar recomposed[18 * 2];
     icu_err = U_ZERO_ERROR;
     len = unorm2_normalize (unorm2_getNFCInstance (&icu_err), normalized, len, recomposed, ARRAY_LENGTH (recomposed), &icu_err);
@@ -293,7 +296,7 @@
     /* We expect that recomposed has exactly one character now. */
     if (unlikely (u_countChar32 (recomposed, len) != 1))
       return false;
-    U16_GET_UNSAFE (recomposed, 0, *a);
+    HB_ICU_STMT (U16_GET_UNSAFE (recomposed, 0, *a));
     ret = true;
   }
 
diff --git a/src/hb-iter.hh b/src/hb-iter.hh
index f094728..5df4333 100644
--- a/src/hb-iter.hh
+++ b/src/hb-iter.hh
@@ -42,9 +42,19 @@
  * copied by value.  If the collection / object being iterated on
  * is writable, then the iterator returns lvalues, otherwise it
  * returns rvalues.
+ *
+ * TODO Document more.
+ *
+ * If iterator implementation implements operator!=, then can be
+ * used in range-based for loop.  That comes free if the iterator
+ * is random-access.  Otherwise, the range-based for loop incurs
+ * one traversal to find end(), which can be avoided if written
+ * as a while-style for loop, or if iterator implements a faster
+ * __end__() method.
+ * TODO When opting in for C++17, address this by changing return
+ * type of .end()?
  */
 
-
 /*
  * Base classes for iterators.
  */
@@ -72,10 +82,13 @@
   /* Operators. */
   iter_t iter () const { return *thiz(); }
   iter_t operator + () const { return *thiz(); }
+  iter_t begin () const { return *thiz(); }
+  iter_t end () const { return thiz()->__end__ (); }
   explicit operator bool () const { return thiz()->__more__ (); }
   unsigned len () const { return thiz()->__len__ (); }
   /* The following can only be enabled if item_t is reference type.  Otherwise
-   * it will be returning pointer to temporary rvalue. */
+   * it will be returning pointer to temporary rvalue.
+   * TODO Use a wrapper return type to fix for non-reference type. */
   template <typename T = item_t,
 	    hb_enable_if (hb_is_reference (T))>
   hb_remove_reference<item_t>* operator -> () const { return hb_addressof (**thiz()); }
@@ -83,30 +96,40 @@
   item_t operator * () { return thiz()->__item__ (); }
   item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
   item_t operator [] (unsigned i) { return thiz()->__item_at__ (i); }
-  iter_t& operator += (unsigned count) { thiz()->__forward__ (count); return *thiz(); }
-  iter_t& operator ++ () { thiz()->__next__ (); return *thiz(); }
-  iter_t& operator -= (unsigned count) { thiz()->__rewind__ (count); return *thiz(); }
-  iter_t& operator -- () { thiz()->__prev__ (); return *thiz(); }
+  iter_t& operator += (unsigned count) &  { thiz()->__forward__ (count); return *thiz(); }
+  iter_t  operator += (unsigned count) && { thiz()->__forward__ (count); return *thiz(); }
+  iter_t& operator ++ () &  { thiz()->__next__ (); return *thiz(); }
+  iter_t  operator ++ () && { thiz()->__next__ (); return *thiz(); }
+  iter_t& operator -= (unsigned count) &  { thiz()->__rewind__ (count); return *thiz(); }
+  iter_t  operator -= (unsigned count) && { thiz()->__rewind__ (count); return *thiz(); }
+  iter_t& operator -- () &  { thiz()->__prev__ (); return *thiz(); }
+  iter_t  operator -- () && { thiz()->__prev__ (); return *thiz(); }
   iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; }
   friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; }
   iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
   iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; }
   iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
   template <typename T>
-  iter_t& operator >> (T &v) { v = **thiz(); ++*thiz(); return *thiz(); }
+  iter_t& operator >> (T &v) &  { v = **thiz(); ++*thiz(); return *thiz(); }
   template <typename T>
-  iter_t& operator >> (T &v) const { v = **thiz(); ++*thiz(); return *thiz(); }
+  iter_t  operator >> (T &v) && { v = **thiz(); ++*thiz(); return *thiz(); }
   template <typename T>
-  iter_t& operator << (const T v) { **thiz() = v; ++*thiz(); return *thiz(); }
+  iter_t& operator << (const T v) &  { **thiz() = v; ++*thiz(); return *thiz(); }
+  template <typename T>
+  iter_t  operator << (const T v) && { **thiz() = v; ++*thiz(); return *thiz(); }
 
   protected:
-  hb_iter_t () {}
-  hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
-  void operator = (const hb_iter_t &o HB_UNUSED) {}
+  hb_iter_t () = default;
+  hb_iter_t (const hb_iter_t &o HB_UNUSED) = default;
+  hb_iter_t (hb_iter_t &&o HB_UNUSED) = default;
+  hb_iter_t& operator = (const hb_iter_t &o HB_UNUSED) = default;
+  hb_iter_t& operator = (hb_iter_t &&o HB_UNUSED) = default;
 };
 
 #define HB_ITER_USING(Name) \
   using item_t = typename Name::item_t; \
+  using Name::begin; \
+  using Name::end; \
   using Name::item_size; \
   using Name::is_iterator; \
   using Name::iter; \
@@ -125,18 +148,20 @@
   using Name::operator <<; \
   static_assert (true, "")
 
-/* Returns iterator type of a type. */
-#define hb_iter_t(Iterable) decltype (hb_declval (Iterable).iter ())
+/* Returns iterator / item type of a type. */
+template <typename Iterable>
+using hb_iter_type = decltype (hb_deref (hb_declval (Iterable)).iter ());
+template <typename Iterable>
+using hb_item_type = decltype (*hb_deref (hb_declval (Iterable)).iter ());
 
 
 template <typename> struct hb_array_t;
 
 struct
 {
-  template <typename T>
-  hb_iter_t (T)
+  template <typename T> hb_iter_type<T>
   operator () (T&& c) const
-  { return c.iter (); }
+  { return hb_deref (hb_forward<T> (c)).iter (); }
 
   /* Specialization for C arrays. */
 
@@ -148,8 +173,8 @@
   operator () (Type (&array)[length]) const
   { return hb_array_t<Type> (array, length); }
 
-} HB_FUNCOBJ (hb_iter);
-
+}
+HB_FUNCOBJ (hb_iter);
 
 /* Mixin to fill in what the subclass doesn't provide. */
 template <typename iter_t, typename item_t = typename iter_t::__item_t__>
@@ -166,22 +191,36 @@
   item_t __item_at__ (unsigned i) const { return *(*thiz() + i); }
 
   /* Termination: Implement __more__(), or __len__() if random-access. */
-  bool __more__ () const { return thiz()->len (); }
+  bool __more__ () const { return bool (thiz()->len ()); }
   unsigned __len__ () const
-  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
+  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; } return l; }
 
   /* Advancing: Implement __next__(), or __forward__() if random-access. */
   void __next__ () { *thiz() += 1; }
-  void __forward__ (unsigned n) { while (n--) ++*thiz(); }
+  void __forward__ (unsigned n) { while (*thiz() && n--) ++*thiz(); }
 
   /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
   void __prev__ () { *thiz() -= 1; }
-  void __rewind__ (unsigned n) { while (n--) --*thiz(); }
+  void __rewind__ (unsigned n) { while (*thiz() && n--) --*thiz(); }
+
+  /* Range-based for: Implement __end__() if can be done faster,
+   * and operator!=. */
+  iter_t __end__ () const
+  {
+    if (thiz()->is_random_access_iterator)
+      return *thiz() + thiz()->len ();
+    /* Above expression loops twice. Following loops once. */
+    auto it = *thiz();
+    while (it) ++it;
+    return it;
+  }
 
   protected:
-  hb_iter_fallback_mixin_t () {}
-  hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
-  void operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
+  hb_iter_fallback_mixin_t () = default;
+  hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default;
+  hb_iter_fallback_mixin_t (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default;
+  hb_iter_fallback_mixin_t& operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default;
+  hb_iter_fallback_mixin_t& operator = (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default;
 };
 
 template <typename iter_t, typename item_t = typename iter_t::__item_t__>
@@ -190,17 +229,32 @@
   hb_iter_fallback_mixin_t<iter_t, item_t>
 {
   protected:
-  hb_iter_with_fallback_t () {}
-  hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) :
-    hb_iter_t<iter_t, item_t> (o),
-    hb_iter_fallback_mixin_t<iter_t, item_t> (o) {}
-  void operator = (const hb_iter_with_fallback_t &o HB_UNUSED) {}
+  hb_iter_with_fallback_t () = default;
+  hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) = default;
+  hb_iter_with_fallback_t (hb_iter_with_fallback_t &&o HB_UNUSED) = default;
+  hb_iter_with_fallback_t& operator = (const hb_iter_with_fallback_t &o HB_UNUSED) = default;
+  hb_iter_with_fallback_t& operator = (hb_iter_with_fallback_t &&o HB_UNUSED) = default;
 };
 
 /*
  * Meta-programming predicates.
  */
 
+/* hb_is_iterator() / hb_is_iterator_of() */
+
+template<typename Iter, typename Item>
+struct hb_is_iterator_of
+{
+  template <typename Item2 = Item>
+  static hb_true_type impl (hb_priority<2>, hb_iter_t<Iter, hb_type_identity<Item2>> *);
+  static hb_false_type impl (hb_priority<0>, const void *);
+
+  public:
+  static constexpr bool value = decltype (impl (hb_prioritize, hb_declval (Iter*)))::value;
+};
+#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
+#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
+
 /* hb_is_iterable() */
 
 template <typename T>
@@ -209,45 +263,78 @@
   private:
 
   template <typename U>
-  static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_t ());
+  static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_type ());
 
   template <typename>
-  static hb_false_t impl (hb_priority<0>);
+  static hb_false_type impl (hb_priority<0>);
 
   public:
-
-  enum { value = decltype (impl<T> (hb_prioritize))::value };
+  static constexpr bool value = decltype (impl<T> (hb_prioritize))::value;
 };
 #define hb_is_iterable(Iterable) hb_is_iterable<Iterable>::value
 
-/* TODO Add hb_is_iterable_of().
- * TODO Add random_access / sorted variants. */
-
-/* hb_is_iterator() / hb_is_random_access_iterator() / hb_is_sorted_iterator() */
-
-template <typename Iter, typename Item>
-static inline char _hb_is_iterator_of (hb_priority<0>, const void *) { return 0; }
-template <typename Iter,
-	  typename Item,
-	  typename Item2 = typename Iter::item_t,
-	  hb_enable_if (hb_is_cr_convertible_to (Item2, Item))>
-static inline int _hb_is_iterator_of (hb_priority<2>, hb_iter_t<Iter, Item2> *) { return 0; }
+/* hb_is_source_of() / hb_is_sink_of() */
 
 template<typename Iter, typename Item>
-struct hb_is_iterator_of { enum {
-  value = sizeof (int) == sizeof (_hb_is_iterator_of<Iter, Item> (hb_prioritize, hb_declval (Iter*))) }; };
-#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
-#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
+struct hb_is_source_of
+{
+  private:
+  template <typename Iter2 = Iter,
+	    hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<hb_add_const<Item>>))>
+  static hb_true_type impl (hb_priority<2>);
+  template <typename Iter2 = Iter>
+  static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ());
+  static hb_false_type impl (hb_priority<0>);
 
-#define hb_is_random_access_iterator_of(Iter, Item) \
-  hb_is_iterator_of (Iter, Item) && Iter::is_random_access_iterator
-#define hb_is_random_access_iterator(Iter) \
-  hb_is_random_access_iterator_of (Iter, typename Iter::item_t)
+  public:
+  static constexpr bool value = decltype (impl (hb_prioritize))::value;
+};
+#define hb_is_source_of(Iter, Item) hb_is_source_of<Iter, Item>::value
 
-#define hb_is_sorted_iterator_of(Iter, Item) \
-  hb_is_iterator_of (Iter, Item) && Iter::is_sorted_iterator
-#define hb_is_sorted_iterator(Iter) \
-  hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
+template<typename Iter, typename Item>
+struct hb_is_sink_of
+{
+  private:
+  template <typename Iter2 = Iter,
+	    hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<Item>))>
+  static hb_true_type impl (hb_priority<2>);
+  template <typename Iter2 = Iter>
+  static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) << hb_declval (Item), hb_true_type ());
+  static hb_false_type impl (hb_priority<0>);
+
+  public:
+  static constexpr bool value = decltype (impl (hb_prioritize))::value;
+};
+#define hb_is_sink_of(Iter, Item) hb_is_sink_of<Iter, Item>::value
+
+/* This is commonly used, so define: */
+#define hb_is_sorted_source_of(Iter, Item) \
+	(hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator)
+
+
+/* Range-based 'for' for iterables. */
+
+template <typename Iterable,
+	  hb_requires (hb_is_iterable (Iterable))>
+static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())
+
+template <typename Iterable,
+	  hb_requires (hb_is_iterable (Iterable))>
+static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())
+
+/* begin()/end() are NOT looked up non-ADL.  So each namespace must declare them.
+ * Do it for namespace OT. */
+namespace OT {
+
+template <typename Iterable,
+	  hb_requires (hb_is_iterable (Iterable))>
+static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())
+
+template <typename Iterable,
+	  hb_requires (hb_is_iterable (Iterable))>
+static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())
+
+}
 
 
 /*
@@ -255,46 +342,59 @@
  */
 
 template <typename Lhs, typename Rhs,
-	  hb_enable_if (hb_is_iterator (Lhs))>
+	  hb_requires (hb_is_iterator (Lhs))>
 static inline auto
-operator | (Lhs lhs, const Rhs &rhs) HB_AUTO_RETURN (rhs (lhs))
+operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward<Rhs> (rhs) (hb_forward<Lhs> (lhs)))
 
 /* hb_map(), hb_filter(), hb_reduce() */
 
-template <typename Iter, typename Proj,
-	 hb_enable_if (hb_is_iterator (Iter))>
-struct hb_map_iter_t :
-  hb_iter_t<hb_map_iter_t<Iter, Proj>,
-	    decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t)))>
-{
-  hb_map_iter_t (const Iter& it, Proj f) : it (it), f (f) {}
+enum  class hb_function_sortedness_t {
+  NOT_SORTED,
+  RETAINS_SORTING,
+  SORTED,
+};
 
-  typedef decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t))) __item_t__;
+template <typename Iter, typename Proj, hb_function_sortedness_t Sorted,
+	 hb_requires (hb_is_iterator (Iter))>
+struct hb_map_iter_t :
+  hb_iter_t<hb_map_iter_t<Iter, Proj, Sorted>,
+	    decltype (hb_get (hb_declval (Proj), *hb_declval (Iter)))>
+{
+  hb_map_iter_t (const Iter& it, Proj f_) : it (it), f (f_) {}
+
+  typedef decltype (hb_get (hb_declval (Proj), *hb_declval (Iter))) __item_t__;
   static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
-  __item_t__ __item__ () const { return hb_get (f, *it); }
-  __item_t__ __item_at__ (unsigned i) const { return hb_get (f, it[i]); }
+  static constexpr bool is_sorted_iterator =
+    Sorted == hb_function_sortedness_t::SORTED ? true :
+    Sorted == hb_function_sortedness_t::RETAINS_SORTING ? Iter::is_sorted_iterator :
+    false;
+  __item_t__ __item__ () const { return hb_get (f.get (), *it); }
+  __item_t__ __item_at__ (unsigned i) const { return hb_get (f.get (), it[i]); }
   bool __more__ () const { return bool (it); }
   unsigned __len__ () const { return it.len (); }
   void __next__ () { ++it; }
   void __forward__ (unsigned n) { it += n; }
   void __prev__ () { --it; }
   void __rewind__ (unsigned n) { it -= n; }
+  hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); }
+  bool operator != (const hb_map_iter_t& o) const
+  { return it != o.it; }
 
   private:
   Iter it;
-  Proj f;
+  hb_reference_wrapper<Proj> f;
 };
 
-template <typename Proj>
+template <typename Proj, hb_function_sortedness_t Sorted>
 struct hb_map_iter_factory_t
 {
   hb_map_iter_factory_t (Proj f) : f (f) {}
 
   template <typename Iter,
-	    hb_enable_if (hb_is_iterator (Iter))>
-  hb_map_iter_t<Iter, Proj>
-  operator () (Iter it) const
-  { return hb_map_iter_t<Iter, Proj> (it, f); }
+	    hb_requires (hb_is_iterator (Iter))>
+  hb_map_iter_t<Iter, Proj, Sorted>
+  operator () (Iter it)
+  { return hb_map_iter_t<Iter, Proj, Sorted> (it, f); }
 
   private:
   Proj f;
@@ -302,31 +402,51 @@
 struct
 {
   template <typename Proj>
-  hb_map_iter_factory_t<Proj>
+  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED>
   operator () (Proj&& f) const
-  { return hb_map_iter_factory_t<Proj> (f); }
-} HB_FUNCOBJ (hb_map);
+  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED> (f); }
+}
+HB_FUNCOBJ (hb_map);
+struct
+{
+  template <typename Proj>
+  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING>
+  operator () (Proj&& f) const
+  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING> (f); }
+}
+HB_FUNCOBJ (hb_map_retains_sorting);
+struct
+{
+  template <typename Proj>
+  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED>
+  operator () (Proj&& f) const
+  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED> (f); }
+}
+HB_FUNCOBJ (hb_map_sorted);
 
 template <typename Iter, typename Pred, typename Proj,
-	 hb_enable_if (hb_is_iterator (Iter))>
+	 hb_requires (hb_is_iterator (Iter))>
 struct hb_filter_iter_t :
   hb_iter_with_fallback_t<hb_filter_iter_t<Iter, Pred, Proj>,
 			  typename Iter::item_t>
 {
-  hb_filter_iter_t (const Iter& it_, Pred p, Proj f) : it (it_), p (p), f (f)
-  { while (it && !hb_has (p, hb_get (f, *it))) ++it; }
+  hb_filter_iter_t (const Iter& it_, Pred p_, Proj f_) : it (it_), p (p_), f (f_)
+  { while (it && !hb_has (p.get (), hb_get (f.get (), *it))) ++it; }
 
   typedef typename Iter::item_t __item_t__;
   static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
   __item_t__ __item__ () const { return *it; }
   bool __more__ () const { return bool (it); }
-  void __next__ () { do ++it; while (it && !p (f (*it))); }
-  void __prev__ () { --it; }
+  void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
+  void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
+  hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); }
+  bool operator != (const hb_filter_iter_t& o) const
+  { return it != o.it; }
 
   private:
   Iter it;
-  Pred p;
-  Proj f;
+  hb_reference_wrapper<Pred> p;
+  hb_reference_wrapper<Proj> f;
 };
 template <typename Pred, typename Proj>
 struct hb_filter_iter_factory_t
@@ -334,9 +454,9 @@
   hb_filter_iter_factory_t (Pred p, Proj f) : p (p), f (f) {}
 
   template <typename Iter,
-	    hb_enable_if (hb_is_iterator (Iter))>
+	    hb_requires (hb_is_iterator (Iter))>
   hb_filter_iter_t<Iter, Pred, Proj>
-  operator () (Iter it) const
+  operator () (Iter it)
   { return hb_filter_iter_t<Iter, Pred, Proj> (it, p, f); }
 
   private:
@@ -345,12 +465,13 @@
 };
 struct
 {
-  template <typename Pred = decltype ((hb_bool)),
+  template <typename Pred = decltype ((hb_identity)),
 	    typename Proj = decltype ((hb_identity))>
   hb_filter_iter_factory_t<Pred, Proj>
-  operator () (Pred&& p = hb_bool, Proj&& f = hb_identity) const
+  operator () (Pred&& p = hb_identity, Proj&& f = hb_identity) const
   { return hb_filter_iter_factory_t<Pred, Proj> (p, f); }
-} HB_FUNCOBJ (hb_filter);
+}
+HB_FUNCOBJ (hb_filter);
 
 template <typename Redu, typename InitT>
 struct hb_reduce_t
@@ -358,10 +479,10 @@
   hb_reduce_t (Redu r, InitT init_value) : r (r), init_value (init_value) {}
 
   template <typename Iter,
-	    hb_enable_if (hb_is_iterator (Iter)),
+	    hb_requires (hb_is_iterator (Iter)),
 	    typename AccuT = decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>
   AccuT
-  operator () (Iter it) const
+  operator () (Iter it)
   {
     AccuT value = init_value;
     for (; it; ++it)
@@ -379,7 +500,8 @@
   hb_reduce_t<Redu, InitT>
   operator () (Redu&& r, InitT init_value) const
   { return hb_reduce_t<Redu, InitT> (r, init_value); }
-} HB_FUNCOBJ (hb_reduce);
+}
+HB_FUNCOBJ (hb_reduce);
 
 
 /* hb_zip() */
@@ -387,7 +509,7 @@
 template <typename A, typename B>
 struct hb_zip_iter_t :
   hb_iter_t<hb_zip_iter_t<A, B>,
-	    hb_pair_t<typename A::item_t, typename B::item_t> >
+	    hb_pair_t<typename A::item_t, typename B::item_t>>
 {
   hb_zip_iter_t () {}
   hb_zip_iter_t (const A& a, const B& b) : a (a), b (b) {}
@@ -396,17 +518,45 @@
   static constexpr bool is_random_access_iterator =
     A::is_random_access_iterator &&
     B::is_random_access_iterator;
-  static constexpr bool is_sorted_iterator =
-    A::is_sorted_iterator &&
-    B::is_sorted_iterator;
+  /* Note.  The following categorization is only valid if A is strictly sorted,
+   * ie. does NOT have duplicates.  Previously I tried to categorize sortedness
+   * more granularly, see commits:
+   *
+   *   513762849a683914fc266a17ddf38f133cccf072
+   *   4d3cf2adb669c345cc43832d11689271995e160a
+   *
+   * However, that was not enough, since hb_sorted_array_t, hb_sorted_vector_t,
+   * SortedArrayOf, etc all needed to be updated to add more variants.  At that
+   * point I saw it not worth the effort, and instead we now deem all sorted
+   * collections as essentially strictly-sorted for the purposes of zip.
+   *
+   * The above assumption is not as bad as it sounds.  Our "sorted" comes with
+   * no guarantees.  It's just a contract, put in place to help you remember,
+   * and think about, whether an iterator you receive is expected to be
+   * sorted or not.  As such, it's not perfect by definition, and should not
+   * be treated so.  The inaccuracy here just errs in the direction of being
+   * more permissive, so your code compiles instead of erring on the side of
+   * marking your zipped iterator unsorted in which case your code won't
+   * compile.
+   *
+   * This semantical limitation does NOT affect logic in any other place I
+   * know of as of this writing.
+   */
+  static constexpr bool is_sorted_iterator = A::is_sorted_iterator;
+
   __item_t__ __item__ () const { return __item_t__ (*a, *b); }
   __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); }
-  bool __more__ () const { return a && b; }
-  unsigned __len__ () const { return MIN (a.len (), b.len ()); }
+  bool __more__ () const { return bool (a) && bool (b); }
+  unsigned __len__ () const { return hb_min (a.len (), b.len ()); }
   void __next__ () { ++a; ++b; }
   void __forward__ (unsigned n) { a += n; b += n; }
   void __prev__ () { --a; --b; }
   void __rewind__ (unsigned n) { a -= n; b -= n; }
+  hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); }
+  /* Note, we should stop if ANY of the iters reaches end.  As such two compare
+   * unequal if both items are unequal, NOT if either is unequal. */
+  bool operator != (const hb_zip_iter_t& o) const
+  { return a != o.a && b != o.b; }
 
   private:
   A a;
@@ -415,46 +565,12 @@
 struct
 {
   template <typename A, typename B,
-	    hb_enable_if (hb_is_iterable (A) && hb_is_iterable (B))>
-  hb_zip_iter_t<hb_iter_t (A), hb_iter_t (B)>
-  operator () (A& a, B &b) const
-  { return hb_zip_iter_t<hb_iter_t (A), hb_iter_t (B)> (hb_iter (a), hb_iter (b)); }
-} HB_FUNCOBJ (hb_zip);
-
-/* hb_enumerate */
-
-template <typename Iter,
-	 hb_enable_if (hb_is_iterator (Iter))>
-struct hb_enumerate_iter_t :
-  hb_iter_t<hb_enumerate_iter_t<Iter>,
-	    hb_pair_t<unsigned, typename Iter::item_t> >
-{
-  hb_enumerate_iter_t (const Iter& it) : i (0), it (it) {}
-
-  typedef hb_pair_t<unsigned, typename Iter::item_t> __item_t__;
-  static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
-  static constexpr bool is_sorted_iterator = true;
-  __item_t__ __item__ () const { return __item_t__ (+i, *it); }
-  __item_t__ __item_at__ (unsigned j) const { return __item_t__ (i + j, it[j]); }
-  bool __more__ () const { return bool (it); }
-  unsigned __len__ () const { return it.len (); }
-  void __next__ () { ++i; ++it; }
-  void __forward__ (unsigned n) { i += n; it += n; }
-  void __prev__ () { --i; --it; }
-  void __rewind__ (unsigned n) { i -= n; it -= n; }
-
-  private:
-  unsigned i;
-  Iter it;
-};
-struct
-{
-  template <typename Iterable,
-	    hb_enable_if (hb_is_iterable (Iterable))>
-  hb_enumerate_iter_t<hb_iter_t (Iterable)>
-  operator () (Iterable& it) const
-  { return hb_enumerate_iter_t<hb_iter_t (Iterable)> (hb_iter (it)); }
-} HB_FUNCOBJ (hb_enumerate);
+	    hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
+  hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>>
+  operator () (A&& a, B&& b) const
+  { return hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
+}
+HB_FUNCOBJ (hb_zip);
 
 /* hb_apply() */
 
@@ -464,9 +580,8 @@
   hb_apply_t (Appl a) : a (a) {}
 
   template <typename Iter,
-	    hb_enable_if (hb_is_iterator (Iter))>
-  void
-  operator () (Iter it) const
+	    hb_requires (hb_is_iterator (Iter))>
+  void operator () (Iter it)
   {
     for (; it; ++it)
       (void) hb_invoke (a, *it);
@@ -484,19 +599,91 @@
   template <typename Appl> hb_apply_t<Appl&>
   operator () (Appl *a) const
   { return hb_apply_t<Appl&> (*a); }
-} HB_FUNCOBJ (hb_apply);
+}
+HB_FUNCOBJ (hb_apply);
+
+/* hb_iota()/hb_range() */
+
+template <typename T, typename S>
+struct hb_counter_iter_t :
+  hb_iter_t<hb_counter_iter_t<T, S>, T>
+{
+  hb_counter_iter_t (T start, T end_, S step) : v (start), end_ (end_for (start, end_, step)), step (step) {}
+
+  typedef T __item_t__;
+  static constexpr bool is_random_access_iterator = true;
+  static constexpr bool is_sorted_iterator = true;
+  __item_t__ __item__ () const { return +v; }
+  __item_t__ __item_at__ (unsigned j) const { return v + j * step; }
+  bool __more__ () const { return v != end_; }
+  unsigned __len__ () const { return !step ? UINT_MAX : (end_ - v) / step; }
+  void __next__ () { v += step; }
+  void __forward__ (unsigned n) { v += n * step; }
+  void __prev__ () { v -= step; }
+  void __rewind__ (unsigned n) { v -= n * step; }
+  hb_counter_iter_t __end__ () const { return hb_counter_iter_t (end_, end_, step); }
+  bool operator != (const hb_counter_iter_t& o) const
+  { return v != o.v; }
+
+  private:
+  static inline T end_for (T start, T end_, S step)
+  {
+    if (!step)
+      return end_;
+    auto res = (end_ - start) % step;
+    if (!res)
+      return end_;
+    end_ += step - res;
+    return end_;
+  }
+
+  private:
+  T v;
+  T end_;
+  S step;
+};
+struct
+{
+  template <typename T = unsigned, typename S = unsigned> hb_counter_iter_t<T, S>
+  operator () (T start = 0u, S&& step = 1u) const
+  { return hb_counter_iter_t<T, S> (start, step >= 0 ? hb_int_max (T) : hb_int_min (T), step); }
+}
+HB_FUNCOBJ (hb_iota);
+struct
+{
+  template <typename T = unsigned> hb_counter_iter_t<T, unsigned>
+  operator () (T end = (unsigned) -1) const
+  { return hb_counter_iter_t<T, unsigned> (0, end, 1u); }
+
+  template <typename T, typename S = unsigned> hb_counter_iter_t<T, S>
+  operator () (T start, T end, S&& step = 1u) const
+  { return hb_counter_iter_t<T, S> (start, end, step); }
+}
+HB_FUNCOBJ (hb_range);
+
+/* hb_enumerate */
+
+struct
+{
+  template <typename Iterable,
+	    typename Index = unsigned,
+	    hb_requires (hb_is_iterable (Iterable))>
+  auto operator () (Iterable&& it, Index start = 0u) const HB_AUTO_RETURN
+  ( hb_zip (hb_iota (start), it) )
+}
+HB_FUNCOBJ (hb_enumerate);
+
 
 /* hb_sink() */
 
 template <typename Sink>
 struct hb_sink_t
 {
-  hb_sink_t (Sink&& s) : s (s) {}
+  hb_sink_t (Sink s) : s (s) {}
 
   template <typename Iter,
-	    hb_enable_if (hb_is_iterator (Iter))>
-  void
-  operator () (Iter it) const
+	    hb_requires (hb_is_iterator (Iter))>
+  void operator () (Iter it)
   {
     for (; it; ++it)
       s << *it;
@@ -514,33 +701,33 @@
   template <typename Sink> hb_sink_t<Sink&>
   operator () (Sink *s) const
   { return hb_sink_t<Sink&> (*s); }
-} HB_FUNCOBJ (hb_sink);
+}
+HB_FUNCOBJ (hb_sink);
 
 /* hb-drain: hb_sink to void / blackhole / /dev/null. */
 
 struct
 {
   template <typename Iter,
-	    hb_enable_if (hb_is_iterator (Iter))>
-  void
-  operator () (Iter it) const
+	    hb_requires (hb_is_iterator (Iter))>
+  void operator () (Iter it) const
   {
     for (; it; ++it)
       (void) *it;
   }
-} HB_FUNCOBJ (hb_drain);
+}
+HB_FUNCOBJ (hb_drain);
 
 /* hb_unzip(): unzip and sink to two sinks. */
 
 template <typename Sink1, typename Sink2>
 struct hb_unzip_t
 {
-  hb_unzip_t (Sink1&& s1, Sink2&& s2) : s1 (s1), s2 (s2) {}
+  hb_unzip_t (Sink1 s1, Sink2 s2) : s1 (s1), s2 (s2) {}
 
   template <typename Iter,
-	    hb_enable_if (hb_is_iterator (Iter))>
-  void
-  operator () (Iter it) const
+	    hb_requires (hb_is_iterator (Iter))>
+  void operator () (Iter it)
   {
     for (; it; ++it)
     {
@@ -563,7 +750,8 @@
   template <typename Sink1, typename Sink2> hb_unzip_t<Sink1&, Sink2&>
   operator () (Sink1 *s1, Sink2 *s2) const
   { return hb_unzip_t<Sink1&, Sink2&> (*s1, *s2); }
-} HB_FUNCOBJ (hb_unzip);
+}
+HB_FUNCOBJ (hb_unzip);
 
 
 /* hb-all, hb-any, hb-none. */
@@ -571,49 +759,61 @@
 struct
 {
   template <typename Iterable,
-	    hb_enable_if (hb_is_iterable (Iterable))>
-  bool
-  operator () (Iterable&& c) const
+	    typename Pred = decltype ((hb_identity)),
+	    typename Proj = decltype ((hb_identity)),
+	    hb_requires (hb_is_iterable (Iterable))>
+  bool operator () (Iterable&& c,
+		    Pred&& p = hb_identity,
+		    Proj&& f = hb_identity) const
   {
     for (auto it = hb_iter (c); it; ++it)
-      if (!*it)
+      if (!hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
 	return false;
     return true;
   }
-} HB_FUNCOBJ (hb_all);
+}
+HB_FUNCOBJ (hb_all);
 struct
 {
   template <typename Iterable,
-	    hb_enable_if (hb_is_iterable (Iterable))>
-  bool
-  operator () (Iterable&& c) const
+	    typename Pred = decltype ((hb_identity)),
+	    typename Proj = decltype ((hb_identity)),
+	    hb_requires (hb_is_iterable (Iterable))>
+  bool operator () (Iterable&& c,
+		    Pred&& p = hb_identity,
+		    Proj&& f = hb_identity) const
   {
     for (auto it = hb_iter (c); it; ++it)
-      if (*it)
+      if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
 	return true;
     return false;
   }
-} HB_FUNCOBJ (hb_any);
+}
+HB_FUNCOBJ (hb_any);
 struct
 {
   template <typename Iterable,
-	    hb_enable_if (hb_is_iterable (Iterable))>
-  bool
-  operator () (Iterable&& c) const
+	    typename Pred = decltype ((hb_identity)),
+	    typename Proj = decltype ((hb_identity)),
+	    hb_requires (hb_is_iterable (Iterable))>
+  bool operator () (Iterable&& c,
+		    Pred&& p = hb_identity,
+		    Proj&& f = hb_identity) const
   {
     for (auto it = hb_iter (c); it; ++it)
-      if (*it)
+      if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
 	return false;
     return true;
   }
-} HB_FUNCOBJ (hb_none);
+}
+HB_FUNCOBJ (hb_none);
 
 /*
  * Algorithms operating on iterators.
  */
 
 template <typename C, typename V,
-	  hb_enable_if (hb_is_iterable (C))>
+	  hb_requires (hb_is_iterable (C))>
 inline void
 hb_fill (C& c, const V &v)
 {
diff --git a/src/hb-map.hh b/src/hb-map.hh
index bbb1bef..26e4930 100644
--- a/src/hb-map.hh
+++ b/src/hb-map.hh
@@ -43,8 +43,8 @@
   hb_hashmap_t ()  { init (); }
   ~hb_hashmap_t () { fini (); }
 
-  static_assert (hb_is_integer (K) || hb_is_pointer (K), "");
-  static_assert (hb_is_integer (V) || hb_is_pointer (V), "");
+  static_assert (hb_is_integral (K) || hb_is_pointer (K), "");
+  static_assert (hb_is_integral (V) || hb_is_pointer (V), "");
 
   /* TODO If key type is a pointer, keep hash in item_t and use to:
    * 1. avoid rehashing when resizing table, and
@@ -57,11 +57,12 @@
 
     void clear () { key = kINVALID; value = vINVALID; }
 
-    bool operator == (K o) { return hb_deref_pointer (key) == hb_deref_pointer (o); }
+    bool operator == (K o) { return hb_deref (key) == hb_deref (o); }
     bool operator == (const item_t &o) { return *this == o.key; }
     bool is_unused () const    { return key == kINVALID; }
     bool is_tombstone () const { return key != kINVALID && value == vINVALID; }
     bool is_real () const { return key != kINVALID && value != vINVALID; }
+    hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
   };
 
   hb_object_header_t header;
@@ -181,7 +182,12 @@
   static constexpr V SENTINEL = vINVALID;
   typedef V value_t;
   value_t operator [] (K k) const { return get (k); }
-  bool has (K k) const { return (*this)[k] != SENTINEL; }
+  bool has (K k, V *vp = nullptr) const
+  {
+    V v = (*this)[k];
+    if (vp) *vp = v;
+    return v != SENTINEL;
+  }
   /* Projection. */
   V operator () (K k) const { return get (k); }
 
@@ -201,6 +207,34 @@
 
   unsigned int get_population () const { return population; }
 
+  /*
+   * Iterator
+   */
+  auto iter () const HB_AUTO_RETURN
+  (
+    + hb_array (items, mask ? mask + 1 : 0)
+    | hb_filter (&item_t::is_real)
+    | hb_map (&item_t::get_pair)
+  )
+  auto keys () const HB_AUTO_RETURN
+  (
+    + hb_array (items, mask ? mask + 1 : 0)
+    | hb_filter (&item_t::is_real)
+    | hb_map (&item_t::key)
+    | hb_map (hb_ridentity)
+  )
+  auto values () const HB_AUTO_RETURN
+  (
+    + hb_array (items, mask ? mask + 1 : 0)
+    | hb_filter (&item_t::is_real)
+    | hb_map (&item_t::value)
+    | hb_map (hb_ridentity)
+  )
+
+  /* Sink interface. */
+  hb_hashmap_t<K, V, kINVALID, vINVALID>& operator << (const hb_pair_t<K, V>& v)
+  { set (v.first, v.second); return *this; }
+
   protected:
 
   unsigned int bucket_for (K key) const
@@ -211,9 +245,9 @@
     while (!items[i].is_unused ())
     {
       if (items[i] == key)
-        return i;
+	return i;
       if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
-        tombstone = i;
+	tombstone = i;
       i = (i + ++step) & mask;
     }
     return tombstone == (unsigned) -1 ? i : tombstone;
diff --git a/src/hb-meta.hh b/src/hb-meta.hh
index b80358c..df8ebd1 100644
--- a/src/hb-meta.hh
+++ b/src/hb-meta.hh
@@ -35,28 +35,38 @@
  */
 
 /* Void!  For when we need a expression-type of void. */
-struct hb_void_t { typedef void value; };
+struct hb_empty_t {};
 
-/* Void meta-function ala std::void_t
- * https://en.cppreference.com/w/cpp/types/void_t */
-template<typename... Ts> struct _hb_void_tt { typedef void type; };
-template<typename... Ts> using hb_void_tt = typename _hb_void_tt<Ts...>::type;
+/* https://en.cppreference.com/w/cpp/types/void_t */
+template<typename... Ts> struct _hb_void_t { typedef void type; };
+template<typename... Ts> using hb_void_t = typename _hb_void_t<Ts...>::type;
 
-template<typename Head, typename... Ts> struct _hb_head_tt { typedef Head type; };
-template<typename... Ts> using hb_head_tt = typename _hb_head_tt<Ts...>::type;
+template<typename Head, typename... Ts> struct _hb_head_t { typedef Head type; };
+template<typename... Ts> using hb_head_t = typename _hb_head_t<Ts...>::type;
 
-/* Bool!  For when we need to evaluate type-dependent expressions
- * in a template argument. */
-template <bool b> struct hb_bool_tt { enum { value = b }; };
-typedef hb_bool_tt<true> hb_true_t;
-typedef hb_bool_tt<false> hb_false_t;
+template <typename T, T v> struct hb_integral_constant { static constexpr T value = v; };
+template <bool b> using hb_bool_constant = hb_integral_constant<bool, b>;
+using hb_true_type = hb_bool_constant<true>;
+using hb_false_type = hb_bool_constant<false>;
 
 
+/* Basic type SFINAE. */
+
+template <bool B, typename T = void> struct hb_enable_if {};
+template <typename T>                struct hb_enable_if<true, T> { typedef T type; };
+#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr
+/* Concepts/Requires alias: */
+#define hb_requires(Cond) hb_enable_if((Cond))
+
+template <typename T, typename T2> struct hb_is_same : hb_false_type {};
+template <typename T>              struct hb_is_same<T, T> : hb_true_type {};
+#define hb_is_same(T, T2) hb_is_same<T, T2>::value
+
 /* Function overloading SFINAE and priority. */
 
-#define HB_RETURN(Ret, E) -> hb_head_tt<Ret, decltype ((E))> { return (E); }
+#define HB_RETURN(Ret, E) -> hb_head_t<Ret, decltype ((E))> { return (E); }
 #define HB_AUTO_RETURN(E) -> decltype ((E)) { return (E); }
-#define HB_VOID_RETURN(E) -> hb_void_tt<decltype ((E))> { (E); }
+#define HB_VOID_RETURN(E) -> hb_void_t<decltype ((E))> { (E); }
 
 template <unsigned Pri> struct hb_priority : hb_priority<Pri - 1> {};
 template <>             struct hb_priority<0> {};
@@ -65,13 +75,13 @@
 #define HB_FUNCOBJ(x) static_const x HB_UNUSED
 
 
-template <typename T> struct hb_match_identity { typedef T type; };
-template <typename T> using hb_type_identity = typename hb_match_identity<T>::type;
+template <typename T> struct hb_type_identity_t { typedef T type; };
+template <typename T> using hb_type_identity = typename hb_type_identity_t<T>::type;
 
 struct
 {
   template <typename T>
-  T* operator () (const T& arg) const
+  T* operator () (T& arg) const
   {
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-align"
@@ -81,32 +91,82 @@
 		reinterpret_cast<const volatile char&> (arg)));
 #pragma GCC diagnostic pop
   }
-} HB_FUNCOBJ (hb_addressof);
+}
+HB_FUNCOBJ (hb_addressof);
 
 template <typename T> static inline T hb_declval ();
 #define hb_declval(T) (hb_declval<T> ())
 
-template <typename T> struct hb_match_const { typedef T type; enum { value = false }; };
-template <typename T> struct hb_match_const<const T> { typedef T type; enum { value = true }; };
+template <typename T> struct hb_match_const		: hb_type_identity_t<T>, hb_bool_constant<false>{};
+template <typename T> struct hb_match_const<const T>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
 template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
+template <typename T> using hb_add_const = const T;
 #define hb_is_const(T) hb_match_const<T>::value
-template <typename T> struct hb_match_reference { typedef T type; enum { value = false }; };
-template <typename T> struct hb_match_reference<T &> { typedef T type; enum { value = true }; };
+template <typename T> struct hb_match_reference		: hb_type_identity_t<T>, hb_bool_constant<false>{};
+template <typename T> struct hb_match_reference<T &>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
+template <typename T> struct hb_match_reference<T &&>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
 template <typename T> using hb_remove_reference = typename hb_match_reference<T>::type;
+template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity<T&>;
+template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
+template <typename T> using hb_add_lvalue_reference = decltype (_hb_try_add_lvalue_reference<T> (hb_prioritize));
+template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_type_identity<T&&>;
+template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
+template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
 #define hb_is_reference(T) hb_match_reference<T>::value
-template <typename T> struct hb_match_pointer { typedef T type; enum { value = false }; };
-template <typename T> struct hb_match_pointer<T *> { typedef T type; enum { value = true }; };
+template <typename T> struct hb_match_pointer		: hb_type_identity_t<T>, hb_bool_constant<false>{};
+template <typename T> struct hb_match_pointer<T *>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
 template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
+template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
+template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
+template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize));
 #define hb_is_pointer(T) hb_match_pointer<T>::value
 
+
 /* TODO Add feature-parity to std::decay. */
 template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
 
-#define hb_is_cr_convertible_to(A, B) ( \
-	hb_is_same (hb_decay<A>, hb_decay<B>) && \
-	hb_is_const (A) <= hb_is_const (B) && \
-	hb_is_reference (A) >= hb_is_reference (B))
 
+template<bool B, class T, class F>
+struct _hb_conditional { typedef T type; };
+template<class T, class F>
+struct _hb_conditional<false, T, F> { typedef F type; };
+template<bool B, class T, class F>
+using hb_conditional = typename _hb_conditional<B, T, F>::type;
+
+
+template <typename From, typename To>
+struct hb_is_convertible
+{
+  private:
+  static constexpr bool   from_void = hb_is_same (void, hb_decay<From>);
+  static constexpr bool     to_void = hb_is_same (void, hb_decay<To>  );
+  static constexpr bool either_void = from_void || to_void;
+  static constexpr bool   both_void = from_void && to_void;
+
+  static hb_true_type impl2 (hb_conditional<to_void, int, To>);
+
+  template <typename T>
+  static auto impl (hb_priority<1>) -> decltype (impl2 (hb_declval (T)));
+  template <typename T>
+  static hb_false_type impl (hb_priority<0>);
+  public:
+  static constexpr bool value = both_void ||
+		       (!either_void &&
+			decltype (impl<hb_conditional<from_void, int, From>> (hb_prioritize))::value);
+};
+#define hb_is_convertible(From,To) hb_is_convertible<From, To>::value
+
+template <typename Base, typename Derived>
+using hb_is_base_of = hb_is_convertible<hb_decay<Derived> *, hb_decay<Base> *>;
+#define hb_is_base_of(Base,Derived) hb_is_base_of<Base, Derived>::value
+
+template <typename From, typename To>
+using hb_is_cr_convertible = hb_bool_constant<
+  hb_is_same (hb_decay<From>, hb_decay<To>) &&
+  (!hb_is_const (From) || hb_is_const (To)) &&
+  (!hb_is_reference (To) || hb_is_const (To) || hb_is_reference (To))
+>;
+#define hb_is_cr_convertible(From,To) hb_is_cr_convertible<From, To>::value
 
 /* std::move and std::forward */
 
@@ -125,56 +185,216 @@
 
   template <typename T> auto
   operator () (T *v) const HB_AUTO_RETURN (*v)
+}
+HB_FUNCOBJ (hb_deref);
 
-} HB_FUNCOBJ (hb_deref_pointer);
+struct
+{
+  template <typename T> auto
+  operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
+
+  template <typename T> auto
+  operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
+}
+HB_FUNCOBJ (hb_ref);
+
+template <typename T>
+struct hb_reference_wrapper
+{
+  hb_reference_wrapper (T v) : v (v) {}
+  bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
+  bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
+  operator T () const { return v; }
+  T get () const { return v; }
+  T v;
+};
+template <typename T>
+struct hb_reference_wrapper<T&>
+{
+  hb_reference_wrapper (T& v) : v (hb_addressof (v)) {}
+  bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
+  bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
+  operator T& () const { return *v; }
+  T& get () const { return *v; }
+  T* v;
+};
 
 
-template<bool B, typename T = void> struct hb_enable_if {};
-template<typename T>                struct hb_enable_if<true, T> { typedef T type; };
-#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr
+template <typename T>
+using hb_is_integral = hb_bool_constant<
+  hb_is_same (hb_decay<T>, char) ||
+  hb_is_same (hb_decay<T>, signed char) ||
+  hb_is_same (hb_decay<T>, unsigned char) ||
+  hb_is_same (hb_decay<T>, signed int) ||
+  hb_is_same (hb_decay<T>, unsigned int) ||
+  hb_is_same (hb_decay<T>, signed short) ||
+  hb_is_same (hb_decay<T>, unsigned short) ||
+  hb_is_same (hb_decay<T>, signed long) ||
+  hb_is_same (hb_decay<T>, unsigned long) ||
+  hb_is_same (hb_decay<T>, signed long long) ||
+  hb_is_same (hb_decay<T>, unsigned long long) ||
+  false
+>;
+#define hb_is_integral(T) hb_is_integral<T>::value
+template <typename T>
+using hb_is_floating_point = hb_bool_constant<
+  hb_is_same (hb_decay<T>, float) ||
+  hb_is_same (hb_decay<T>, double) ||
+  hb_is_same (hb_decay<T>, long double) ||
+  false
+>;
+#define hb_is_floating_point(T) hb_is_floating_point<T>::value
+template <typename T>
+using hb_is_arithmetic = hb_bool_constant<
+  hb_is_integral (T) ||
+  hb_is_floating_point (T) ||
+  false
+>;
+#define hb_is_arithmetic(T) hb_is_arithmetic<T>::value
 
-template <typename T, typename T2> struct hb_is_same : hb_false_t {};
-template <typename T>              struct hb_is_same<T, T> : hb_true_t {};
-#define hb_is_same(T, T2) hb_is_same<T, T2>::value
 
-template <typename T> struct hb_is_signed;
-template <> struct hb_is_signed<char> { enum { value = CHAR_MIN < 0 }; };
-template <> struct hb_is_signed<signed char> { enum { value = true }; };
-template <> struct hb_is_signed<unsigned char> { enum { value = false }; };
-template <> struct hb_is_signed<signed short> { enum { value = true }; };
-template <> struct hb_is_signed<unsigned short> { enum { value = false }; };
-template <> struct hb_is_signed<signed int> { enum { value = true }; };
-template <> struct hb_is_signed<unsigned int> { enum { value = false }; };
-template <> struct hb_is_signed<signed long> { enum { value = true }; };
-template <> struct hb_is_signed<unsigned long> { enum { value = false }; };
-template <> struct hb_is_signed<signed long long> { enum { value = true }; };
-template <> struct hb_is_signed<unsigned long long> { enum { value = false }; };
+template <typename T>
+using hb_is_signed = hb_conditional<hb_is_arithmetic (T),
+				    hb_bool_constant<(T) -1 < (T) 0>,
+				    hb_false_type>;
 #define hb_is_signed(T) hb_is_signed<T>::value
+template <typename T>
+using hb_is_unsigned = hb_conditional<hb_is_arithmetic (T),
+				      hb_bool_constant<(T) 0 < (T) -1>,
+				      hb_false_type>;
+#define hb_is_unsigned(T) hb_is_unsigned<T>::value
 
-template <typename T> struct hb_int_min { static constexpr T value = 0; };
-template <> struct hb_int_min<char> { static constexpr char value = CHAR_MIN; };
-template <> struct hb_int_min<int>  { static constexpr int  value = INT_MIN;  };
-template <> struct hb_int_min<long> { static constexpr long value = LONG_MIN; };
+template <typename T> struct hb_int_min;
+template <> struct hb_int_min<char>			: hb_integral_constant<char,			CHAR_MIN>	{};
+template <> struct hb_int_min<signed char>		: hb_integral_constant<signed char,		SCHAR_MIN>	{};
+template <> struct hb_int_min<unsigned char>		: hb_integral_constant<unsigned char,		0>		{};
+template <> struct hb_int_min<signed short>		: hb_integral_constant<signed short,		SHRT_MIN>	{};
+template <> struct hb_int_min<unsigned short>		: hb_integral_constant<unsigned short,		0>		{};
+template <> struct hb_int_min<signed int>		: hb_integral_constant<signed int,		INT_MIN>	{};
+template <> struct hb_int_min<unsigned int>		: hb_integral_constant<unsigned int,		0>		{};
+template <> struct hb_int_min<signed long>		: hb_integral_constant<signed long,		LONG_MIN>	{};
+template <> struct hb_int_min<unsigned long>		: hb_integral_constant<unsigned long,		0>		{};
+template <> struct hb_int_min<signed long long>		: hb_integral_constant<signed long long,	LLONG_MIN>	{};
+template <> struct hb_int_min<unsigned long long>	: hb_integral_constant<unsigned long long,	0>		{};
 #define hb_int_min(T) hb_int_min<T>::value
+template <typename T> struct hb_int_max;
+template <> struct hb_int_max<char>			: hb_integral_constant<char,			CHAR_MAX>	{};
+template <> struct hb_int_max<signed char>		: hb_integral_constant<signed char,		SCHAR_MAX>	{};
+template <> struct hb_int_max<unsigned char>		: hb_integral_constant<unsigned char,		UCHAR_MAX>	{};
+template <> struct hb_int_max<signed short>		: hb_integral_constant<signed short,		SHRT_MAX>	{};
+template <> struct hb_int_max<unsigned short>		: hb_integral_constant<unsigned short,		USHRT_MAX>	{};
+template <> struct hb_int_max<signed int>		: hb_integral_constant<signed int,		INT_MAX>	{};
+template <> struct hb_int_max<unsigned int>		: hb_integral_constant<unsigned int,		UINT_MAX>	{};
+template <> struct hb_int_max<signed long>		: hb_integral_constant<signed long,		LONG_MAX>	{};
+template <> struct hb_int_max<unsigned long>		: hb_integral_constant<unsigned long,		ULONG_MAX>	{};
+template <> struct hb_int_max<signed long long>		: hb_integral_constant<signed long long,	LLONG_MAX>	{};
+template <> struct hb_int_max<unsigned long long>	: hb_integral_constant<unsigned long long,	ULLONG_MAX>	{};
+#define hb_int_max(T) hb_int_max<T>::value
 
-template <bool is_signed> struct hb_signedness_int;
-template <> struct hb_signedness_int<false> { typedef unsigned int value; };
-template <> struct hb_signedness_int<true>  { typedef   signed int value; };
-#define hb_signedness_int(T) hb_signedness_int<T>::value
 
-template <typename T> struct hb_is_integer { enum { value = false }; };
-template <> struct hb_is_integer<char> { enum { value = true }; };
-template <> struct hb_is_integer<signed char> { enum { value = true }; };
-template <> struct hb_is_integer<unsigned char> { enum { value = true }; };
-template <> struct hb_is_integer<signed short> { enum { value = true }; };
-template <> struct hb_is_integer<unsigned short> { enum { value = true }; };
-template <> struct hb_is_integer<signed int> { enum { value = true }; };
-template <> struct hb_is_integer<unsigned int> { enum { value = true }; };
-template <> struct hb_is_integer<signed long> { enum { value = true }; };
-template <> struct hb_is_integer<unsigned long> { enum { value = true }; };
-template <> struct hb_is_integer<signed long long> { enum { value = true }; };
-template <> struct hb_is_integer<unsigned long long> { enum { value = true }; };
-#define hb_is_integer(T) hb_is_integer<T>::value
+
+template <typename T, typename>
+struct _hb_is_destructible : hb_false_type {};
+template <typename T>
+struct _hb_is_destructible<T, hb_void_t<decltype (hb_declval (T).~T ())>> : hb_true_type {};
+template <typename T>
+using hb_is_destructible = _hb_is_destructible<T, void>;
+#define hb_is_destructible(T) hb_is_destructible<T>::value
+
+template <typename T, typename, typename ...Ts>
+struct _hb_is_constructible : hb_false_type {};
+template <typename T, typename ...Ts>
+struct _hb_is_constructible<T, hb_void_t<decltype (T (hb_declval (Ts)...))>, Ts...> : hb_true_type {};
+template <typename T, typename ...Ts>
+using hb_is_constructible = _hb_is_constructible<T, void, Ts...>;
+#define hb_is_constructible(...) hb_is_constructible<__VA_ARGS__>::value
+
+template <typename T>
+using hb_is_default_constructible = hb_is_constructible<T>;
+#define hb_is_default_constructible(T) hb_is_default_constructible<T>::value
+
+template <typename T>
+using hb_is_copy_constructible = hb_is_constructible<T, hb_add_lvalue_reference<hb_add_const<T>>>;
+#define hb_is_copy_constructible(T) hb_is_copy_constructible<T>::value
+
+template <typename T>
+using hb_is_move_constructible = hb_is_constructible<T, hb_add_rvalue_reference<hb_add_const<T>>>;
+#define hb_is_move_constructible(T) hb_is_move_constructible<T>::value
+
+template <typename T, typename U, typename>
+struct _hb_is_assignable : hb_false_type {};
+template <typename T, typename U>
+struct _hb_is_assignable<T, U, hb_void_t<decltype (hb_declval (T) = hb_declval (U))>> : hb_true_type {};
+template <typename T, typename U>
+using hb_is_assignable = _hb_is_assignable<T, U, void>;
+#define hb_is_assignable(T,U) hb_is_assignable<T, U>::value
+
+template <typename T>
+using hb_is_copy_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
+					       hb_add_lvalue_reference<hb_add_const<T>>>;
+#define hb_is_copy_assignable(T) hb_is_copy_assignable<T>::value
+
+template <typename T>
+using hb_is_move_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
+					       hb_add_rvalue_reference<T>>;
+#define hb_is_move_assignable(T) hb_is_move_assignable<T>::value
+
+/* Trivial versions. */
+
+template <typename T> union hb_trivial { T value; };
+
+/* Don't know how to do the following. */
+template <typename T>
+using hb_is_trivially_destructible= hb_is_destructible<hb_trivial<T>>;
+#define hb_is_trivially_destructible(T) hb_is_trivially_destructible<T>::value
+
+/* Don't know how to do the following. */
+//template <typename T, typename ...Ts>
+//using hb_is_trivially_constructible= hb_is_constructible<hb_trivial<T>, hb_trivial<Ts>...>;
+//#define hb_is_trivially_constructible(...) hb_is_trivially_constructible<__VA_ARGS__>::value
+
+template <typename T>
+using hb_is_trivially_default_constructible= hb_is_default_constructible<hb_trivial<T>>;
+#define hb_is_trivially_default_constructible(T) hb_is_trivially_default_constructible<T>::value
+
+template <typename T>
+using hb_is_trivially_copy_constructible= hb_is_copy_constructible<hb_trivial<T>>;
+#define hb_is_trivially_copy_constructible(T) hb_is_trivially_copy_constructible<T>::value
+
+template <typename T>
+using hb_is_trivially_move_constructible= hb_is_move_constructible<hb_trivial<T>>;
+#define hb_is_trivially_move_constructible(T) hb_is_trivially_move_constructible<T>::value
+
+/* Don't know how to do the following. */
+//template <typename T, typename U>
+//using hb_is_trivially_assignable= hb_is_assignable<hb_trivial<T>, hb_trivial<U>>;
+//#define hb_is_trivially_assignable(T,U) hb_is_trivially_assignable<T, U>::value
+
+template <typename T>
+using hb_is_trivially_copy_assignable= hb_is_copy_assignable<hb_trivial<T>>;
+#define hb_is_trivially_copy_assignable(T) hb_is_trivially_copy_assignable<T>::value
+
+template <typename T>
+using hb_is_trivially_move_assignable= hb_is_move_assignable<hb_trivial<T>>;
+#define hb_is_trivially_move_assignable(T) hb_is_trivially_move_assignable<T>::value
+
+template <typename T>
+using hb_is_trivially_copyable= hb_bool_constant<
+  hb_is_trivially_destructible (T) &&
+  (!hb_is_move_assignable (T) || hb_is_trivially_move_assignable (T)) &&
+  (!hb_is_move_constructible (T) || hb_is_trivially_move_constructible (T)) &&
+  (!hb_is_copy_assignable (T) || hb_is_trivially_copy_assignable (T)) &&
+  (!hb_is_copy_constructible (T) || hb_is_trivially_copy_constructible (T)) &&
+  true
+>;
+#define hb_is_trivially_copyable(T) hb_is_trivially_copyable<T>::value
+
+template <typename T>
+using hb_is_trivial= hb_bool_constant<
+  hb_is_trivially_copyable (T) &&
+  hb_is_trivially_default_constructible (T)
+>;
+#define hb_is_trivial(T) hb_is_trivial<T>::value
 
 
 #endif /* HB_META_HH */
diff --git a/src/hb-mutex.hh b/src/hb-mutex.hh
index a760e73..cbbfa26 100644
--- a/src/hb-mutex.hh
+++ b/src/hb-mutex.hh
@@ -48,6 +48,17 @@
 /* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
 
 
+#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
+
+#include <pthread.h>
+typedef pthread_mutex_t hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT	PTHREAD_MUTEX_INITIALIZER
+#define hb_mutex_impl_init(M)	pthread_mutex_init (M, nullptr)
+#define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
+#define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
+#define hb_mutex_impl_finish(M)	pthread_mutex_destroy (M)
+
+
 #elif !defined(HB_NO_MT) && defined(_WIN32)
 
 #include <windows.h>
@@ -63,17 +74,6 @@
 #define hb_mutex_impl_finish(M)	DeleteCriticalSection (M)
 
 
-#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
-
-#include <pthread.h>
-typedef pthread_mutex_t hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT	PTHREAD_MUTEX_INITIALIZER
-#define hb_mutex_impl_init(M)	pthread_mutex_init (M, nullptr)
-#define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
-#define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
-#define hb_mutex_impl_finish(M)	pthread_mutex_destroy (M)
-
-
 #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
 
 #if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
diff --git a/src/hb-null.hh b/src/hb-null.hh
index 1e20a47..674b4df 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -46,16 +46,13 @@
  * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
  */
 
-template <typename T, typename B>
-struct _hb_null_size
-{ enum { value = sizeof (T) }; };
+template <typename T, typename>
+struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
 template <typename T>
-struct _hb_null_size<T, hb_bool_tt<true || sizeof (T::min_size)> >
-{ enum { value = T::null_size }; };
+struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::null_size> {};
 
 template <typename T>
-struct hb_null_size
-{ enum { value = _hb_null_size<T, hb_true_t>::value }; };
+using hb_null_size = _hb_null_size<T, void>;
 #define hb_null_size(T) hb_null_size<T>::value
 
 /* These doesn't belong here, but since is copy/paste from above, put it here. */
@@ -63,16 +60,12 @@
 /* hb_static_size (T)
  * Returns T::static_size if T::min_size is defined, or sizeof (T) otherwise. */
 
-template <typename T, typename B>
-struct _hb_static_size
-{ enum { value = sizeof (T) }; };
+template <typename T, typename>
+struct _hb_static_size : hb_integral_constant<unsigned, sizeof (T)> {};
 template <typename T>
-struct _hb_static_size<T, hb_bool_tt<true || sizeof (T::min_size)> >
-{ enum { value = T::static_size }; };
-
+struct _hb_static_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::static_size> {};
 template <typename T>
-struct hb_static_size
-{ enum { value = _hb_static_size<T, hb_true_t>::value }; };
+using hb_static_size = _hb_static_size<T, void>;
 #define hb_static_size(T) hb_static_size<T>::value
 
 
@@ -95,7 +88,7 @@
 template <typename QType>
 struct NullHelper
 {
-  typedef hb_remove_const<hb_remove_reference<QType> > Type;
+  typedef hb_remove_const<hb_remove_reference<QType>> Type;
   static const Type & get_null () { return Null<Type>::get_null (); }
 };
 #define Null(Type) NullHelper<Type>::get_null ()
@@ -148,7 +141,7 @@
 template <typename QType>
 struct CrapHelper
 {
-  typedef hb_remove_const<hb_remove_reference<QType> > Type;
+  typedef hb_remove_const<hb_remove_reference<QType>> Type;
   static Type & get_crap () { return Crap<Type> (); }
 };
 #define Crap(Type) CrapHelper<Type>::get_crap ()
diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh
index 7e916ae..5318c7f 100644
--- a/src/hb-open-file.hh
+++ b/src/hb-open-file.hh
@@ -94,7 +94,7 @@
       if (start_offset >= tables.len)
         *table_count = 0;
       else
-        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
+        *table_count = hb_min (*table_count, tables.len - start_offset);
 
       const TableRecord *sub_tables = tables.arrayZ + start_offset;
       unsigned int count = *table_count;
@@ -222,7 +222,7 @@
   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
   FixedVersion<>version;	/* Version of the TTC Header (1.0),
 				 * 0x00010000u */
-  LArrayOf<LOffsetTo<OffsetTable> >
+  LArrayOf<LOffsetTo<OffsetTable>>
 		table;		/* Array of offsets to the OffsetTable for each font
 				 * from the beginning of the file */
   public:
@@ -334,7 +334,7 @@
   protected:
   Tag		tag;		/* Resource type. */
   HBUINT16	resCountM1;	/* Number of resources minus 1. */
-  NNOffsetTo<UnsizedArrayOf<ResourceRecord> >
+  NNOffsetTo<UnsizedArrayOf<ResourceRecord>>
 		resourcesZ;	/* Offset from beginning of resource type list
 				 * to reference item list for this type. */
   public:
@@ -390,7 +390,7 @@
   HBUINT32	reserved1;	/* Reserved for handle to next resource map */
   HBUINT16	resreved2;	/* Reserved for file reference number */
   HBUINT16	attrs;		/* Resource fork attribute */
-  NNOffsetTo<ArrayOfM1<ResourceTypeRecord> >
+  NNOffsetTo<ArrayOfM1<ResourceTypeRecord>>
 		typeList;	/* Offset from beginning of map to
 				 * resource type list */
   Offset16	nameList;	/* Offset from beginning of map to
@@ -422,7 +422,7 @@
   }
 
   protected:
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
 		data;		/* Offset from beginning of resource fork
 				 * to resource data */
   LNNOffsetTo<ResourceMap >
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 041b984..de2d256 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -57,7 +57,7 @@
 struct IntType
 {
   typedef Type type;
-  typedef typename hb_signedness_int (hb_is_signed (Type)) wide_type;
+  typedef hb_conditional<hb_is_signed (Type), signed, unsigned> wide_type;
 
   IntType<Type, Size>& operator = (wide_type i) { v = i; return *this; }
   operator wide_type () const { return v; }
@@ -110,7 +110,7 @@
   F2DOT14& operator = (uint16_t i ) { HBINT16::operator= (i); return *this; }
   // 16384 means 1<<14
   float to_float () const  { return ((int32_t) v) / 16384.f; }
-  void set_float (float f) { v = round (f * 16384.f); }
+  void set_float (float f) { v = roundf (f * 16384.f); }
   public:
   DEFINE_SIZE_STATIC (2);
 };
@@ -121,7 +121,7 @@
   Fixed& operator = (uint32_t i) { HBINT32::operator= (i); return *this; }
   // 65536 means 1<<16
   float to_float () const  { return ((int32_t) v) / 65536.f; }
-  void set_float (float f) { v = round (f * 65536.f); }
+  void set_float (float f) { v = roundf (f * 65536.f); }
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -279,32 +279,70 @@
     return StructAtOffset<Type> (base, *this);
   }
 
+  template <typename Base,
+	    hb_enable_if (hb_is_convertible (const Base, const void *))>
+  friend const Type& operator + (const Base &base, const OffsetTo &offset) { return offset ((const void *) base); }
+  template <typename Base,
+	    hb_enable_if (hb_is_convertible (const Base, const void *))>
+  friend const Type& operator + (const OffsetTo &offset, const Base &base) { return offset ((const void *) base); }
+  template <typename Base,
+	    hb_enable_if (hb_is_convertible (Base, void *))>
+  friend Type& operator + (Base &&base, OffsetTo &offset) { return offset ((void *) base); }
+  template <typename Base,
+	    hb_enable_if (hb_is_convertible (Base, void *))>
+  friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); }
+
   Type& serialize (hb_serialize_context_t *c, const void *base)
   {
     return * (Type *) Offset<OffsetType>::serialize (c, base);
   }
 
-  template <typename T, typename ...Ts>
-  bool serialize_subset (hb_subset_context_t *c, const T &src, const void *base, Ts &&...ds)
+  template <typename ...Ts>
+  bool serialize_subset (hb_subset_context_t *c,
+			 const OffsetTo& src,
+			 const void *src_base,
+			 const void *dst_base,
+			 Ts&&... ds)
   {
     *this = 0;
-    if (has_null && &src == &Null (T))
+    if (src.is_null ())
       return false;
 
     auto *s = c->serializer;
 
     s->push ();
 
-    bool ret = src.subset (c, hb_forward<Ts> (ds)...);
+    bool ret = c->dispatch (src_base+src, hb_forward<Ts> (ds)...);
 
     if (ret || !has_null)
-      s->add_link (*this, s->pop_pack (), base);
+      s->add_link (*this, s->pop_pack (), dst_base);
     else
       s->pop_discard ();
 
     return ret;
   }
 
+  /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
+  template <typename ...Ts>
+  bool serialize_copy (hb_serialize_context_t *c,
+		       const OffsetTo& src,
+		       const void *src_base,
+		       const void *dst_base,
+		       Ts&&... ds)
+  {
+    *this = 0;
+    if (src.is_null ())
+      return false;
+
+    c->push ();
+
+    bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
+
+    c->add_link (*this, c->pop_pack (), dst_base);
+
+    return ret;
+  }
+
   bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
@@ -315,12 +353,12 @@
   }
 
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     return_trace (sanitize_shallow (c, base) &&
 		  (this->is_null () ||
-		   StructAtOffset<Type> (base, *this).sanitize (c, hb_forward<Ts> (ds)...) ||
+		   c->dispatch (StructAtOffset<Type> (base, *this), hb_forward<Ts> (ds)...) ||
 		   neuter (c)));
   }
 
@@ -340,11 +378,6 @@
 template <typename Type>
 using LNNOffsetTo = LOffsetTo<Type, false>;
 
-template <typename Base, typename OffsetType, bool has_null, typename Type>
-static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
-template <typename Base, typename OffsetType, bool has_null, typename Type>
-static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
-
 
 /*
  * Array Types
@@ -395,35 +428,42 @@
   void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
   { as_array (len).qsort (start, end); }
 
-  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
   {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize() as well as an
-     * assignment opreator.  This ensures that they do not
-     * reference other structs via offsets.
-     */
-    if (false)
-    {
-      arrayZ[0].sanitize (c);
-      Type v;
-      v = arrayZ[0];
-    }
-
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend (*this, items_len))) return_trace (false);
     return_trace (true);
   }
+  template <typename Iterator,
+	    hb_requires (hb_is_source_of (Iterator, Type))>
+  bool serialize (hb_serialize_context_t *c, Iterator items)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned count = items.len ();
+    if (unlikely (!serialize (c, count))) return_trace (false);
+    /* TODO Umm. Just exhaust the iterator instead?  Being extra
+     * cautious right now.. */
+    for (unsigned i = 0; i < count; i++, ++items)
+      arrayZ[i] = *items;
+    return_trace (true);
+  }
+
+  UnsizedArrayOf* copy (hb_serialize_context_t *c, unsigned count) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (this);
+    if (unlikely (!as_array (count).copy (c))) return_trace (nullptr);
+    return_trace (out);
+  }
+
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
     for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, hb_forward<Ts> (ds)...)))
+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
 	return_trace (false);
     return_trace (true);
   }
@@ -442,7 +482,7 @@
 
 /* Unsized array of offset's */
 template <typename Type, typename OffsetType, bool has_null=true>
-using UnsizedOffsetArrayOf = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null> >;
+using UnsizedOffsetArrayOf = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
 
 /* Unsized array of offsets relative to the beginning of the array itself. */
 template <typename Type, typename OffsetType, bool has_null=true>
@@ -464,7 +504,7 @@
   }
 
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>
@@ -553,7 +593,7 @@
     return_trace (true);
   }
   template <typename Iterator,
-	    hb_enable_if (hb_is_iterator_of (Iterator, const Type))>
+	    hb_requires (hb_is_source_of (Iterator, Type))>
   bool serialize (hb_serialize_context_t *c, Iterator items)
   {
     TRACE_SERIALIZE (this);
@@ -561,41 +601,30 @@
     if (unlikely (!serialize (c, count))) return_trace (false);
     /* TODO Umm. Just exhaust the iterator instead?  Being extra
      * cautious right now.. */
-    for (unsigned i = 0; i < count; i++, items++)
+    for (unsigned i = 0; i < count; i++, ++items)
       arrayZ[i] = *items;
     return_trace (true);
   }
 
-  bool sanitize (hb_sanitize_context_t *c) const
+  ArrayOf* copy (hb_serialize_context_t *c) const
   {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize() as well as an
-     * assignment opreator.  This ensures that they do not
-     * reference other structs via offsets.
-     */
-    if (false)
-    {
-      arrayZ[0].sanitize (c);
-      Type v;
-      v = arrayZ[0];
-    }
-
-    return_trace (true);
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (this);
+    if (unlikely (!c->extend_min (out))) return_trace (nullptr);
+    c->check_assign (out->len, len);
+    if (unlikely (!as_array ().copy (c))) return_trace (nullptr);
+    return_trace (out);
   }
+
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, hb_forward<Ts> (ds)...)))
+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
 	return_trace (false);
     return_trace (true);
   }
@@ -628,9 +657,9 @@
 
 /* Array of Offset's */
 template <typename Type>
-using OffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT16> >;
+using OffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT16>>;
 template <typename Type>
-using LOffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT32> >;
+using LOffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>>;
 template <typename Type>
 using LOffsetLArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
 
@@ -658,12 +687,12 @@
     if (unlikely (!out)) return_trace (false);
     unsigned int count = this->len;
     for (unsigned int i = 0; i < count; i++)
-      out->arrayZ[i].serialize_subset (c, (*this)[i], out);
+      out->arrayZ[i].serialize_subset (c, this->arrayZ[i], this, out);
     return_trace (true);
   }
 
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     return_trace (OffsetArrayOf<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
@@ -705,26 +734,16 @@
     return_trace (true);
   }
 
-  bool sanitize (hb_sanitize_context_t *c) const
+  template <typename ...Ts>
+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize() as well as an
-     * assignment opreator.  This ensures that they do not
-     * reference other structs via offsets.
-     */
-    if (false)
-    {
-      arrayZ[0].sanitize (c);
-      Type v;
-      v = arrayZ[0];
-    }
-
+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
+    unsigned int count = lenP1 ? lenP1 - 1 : 0;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
+	return_trace (false);
     return_trace (true);
   }
 
@@ -765,13 +784,13 @@
   { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
 
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
     unsigned int count = lenM1 + 1;
     for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, hb_forward<Ts> (ds)...)))
+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
 	return_trace (false);
     return_trace (true);
   }
@@ -822,7 +841,7 @@
     return_trace (ret);
   }
   template <typename Iterator,
-	    hb_enable_if (hb_is_sorted_iterator_of (Iterator, const Type))>
+	    hb_requires (hb_is_sorted_source_of (Iterator, Type))>
   bool serialize (hb_serialize_context_t *c, Iterator items)
   {
     TRACE_SERIALIZE (this);
@@ -830,7 +849,6 @@
     return_trace (ret);
   }
 
-
   template <typename T>
   Type &bsearch (const T &x, Type &not_found = Crap (Type))
   { return *as_array ().bsearch (x, &not_found); }
@@ -863,7 +881,7 @@
   {
     len = v;
     assert (len == v);
-    entrySelector = MAX (1u, hb_bit_storage (v)) - 1;
+    entrySelector = hb_max (1u, hb_bit_storage (v)) - 1;
     searchRange = 16 * (1u << entrySelector);
     rangeShift = v * 16 > searchRange
 		 ? 16 * v - searchRange
@@ -882,7 +900,7 @@
 };
 
 template <typename Type, typename LenType=HBUINT16>
-using BinSearchArrayOf = SortedArrayOf<Type, BinSearchHeader<LenType> >;
+using BinSearchArrayOf = SortedArrayOf<Type, BinSearchHeader<LenType>>;
 
 
 struct VarSizedBinSearchHeader
@@ -947,33 +965,12 @@
   unsigned int get_size () const
   { return header.static_size + header.nUnits * header.unitSize; }
 
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize() as well as an
-     * assignment opreator.  This ensures that they do not
-     * reference other structs via offsets.
-     */
-    if (false)
-    {
-      (*this)[0].sanitize (c);
-      Type v;
-      v = (*this)[0];
-    }
-
-    return_trace (true);
-  }
   template <typename ...Ts>
-  bool sanitize (hb_sanitize_context_t *c, Ts &&...ds) const
+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
     unsigned int count = get_length ();
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(*this)[i].sanitize (c, hb_forward<Ts> (ds)...)))
diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh
index e843195..555ade5 100644
--- a/src/hb-ot-cff-common.hh
+++ b/src/hb-ot-cff-common.hh
@@ -97,12 +97,12 @@
   unsigned int offset_array_size () const
   { return calculate_offset_array_size (offSize, count); }
 
-  static unsigned int calculate_serialized_size (unsigned int offSize, unsigned int count, unsigned int dataSize)
+  static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize)
   {
     if (count == 0)
       return COUNT::static_size;
     else
-      return min_size + calculate_offset_array_size (offSize, count) + dataSize;
+      return min_size + calculate_offset_array_size (offSize_, count) + dataSize;
   }
 
   bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
@@ -132,7 +132,7 @@
       if (unlikely (!c->extend_min (*this))) return_trace (false);
       this->count = byteArray.length;
       this->offSize = offSize_;
-      if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
+      if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
 	return_trace (false);
 
       /* serialize indices */
@@ -167,7 +167,7 @@
     byteArray.resize (buffArray.length);
     for (unsigned int i = 0; i < byteArray.length; i++)
     {
-      byteArray[i] = byte_str_t (buffArray[i].arrayZ (), buffArray[i].length);
+      byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length);
     }
     bool result = this->serialize (c, offSize_, byteArray);
     byteArray.fini ();
@@ -277,7 +277,7 @@
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     this->count = dataArrayLen;
     this->offSize = offSize_;
-    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
+    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
       return_trace (false);
 
     /* serialize indices */
@@ -428,7 +428,7 @@
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     this->count = fontDicts.length;
     this->offSize = offSize_;
-    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
+    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
       return_trace (false);
 
     /* serialize font dict offsets */
@@ -465,7 +465,7 @@
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     this->count = fdCount;
     this->offSize = offSize_;
-    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
+    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
       return_trace (false);
 
     /* serialize font dict offsets */
@@ -604,9 +604,9 @@
     TRACE_SANITIZE (this);
 
     return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
-			  (format == 0)?
+			  ((format == 0)?
 			  u.format0.sanitize (c, fdcount):
-			  u.format3.sanitize (c, fdcount)));
+			  u.format3.sanitize (c, fdcount))));
   }
 
   bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
diff --git a/src/hb-ot-cff1-table.cc b/src/hb-ot-cff1-table.cc
index 1d97e54..e6dd6a7 100644
--- a/src/hb-ot-cff1-table.cc
+++ b/src/hb-ot-cff1-table.cc
@@ -27,6 +27,8 @@
 #include "hb-ot-cff1-table.hh"
 #include "hb-cff1-interp-cs.hh"
 
+#ifndef HB_NO_CFF
+
 using namespace CFF;
 
 /* SID to code */
@@ -305,6 +307,11 @@
 
 bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
 {
+#ifdef HB_NO_OT_FONT_CFF
+  /* XXX Remove check when this code moves to .hh file. */
+  return true;
+#endif
+
   bounds_t  bounds;
 
   if (!_get_bounds (this, glyph, bounds))
@@ -383,3 +390,5 @@
   }
   return false;
 }
+
+#endif
diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh
index 3957d5d..b1298b7 100644
--- a/src/hb-ot-cff1-table.hh
+++ b/src/hb-ot-cff1-table.hh
@@ -576,7 +576,7 @@
     TRACE_SERIALIZE (this);
     if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
     {
-      if (!unlikely (c->extend_min (this->count)))
+      if (unlikely (!c->extend_min (this->count)))
 	return_trace (false);
       count = 0;
       return_trace (true);
@@ -599,9 +599,9 @@
   }
 
   /* in parallel to above */
-  unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const hb_bimap_t &sidmap) const
+  unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_bimap_t &sidmap) const
   {
-    offSize = 0;
+    offSize_ = 0;
     if ((count == 0) || (sidmap.get_count () == 0))
       return count.static_size;
 
@@ -610,8 +610,8 @@
       if (sidmap[i] != HB_MAP_VALUE_INVALID)
 	dataSize += length_at (i);
 
-    offSize = calcOffSize(dataSize);
-    return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
+    offSize_ = calcOffSize(dataSize);
+    return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_count (), dataSize);
   }
 };
 
diff --git a/src/hb-ot-cff2-table.cc b/src/hb-ot-cff2-table.cc
index d2463d7..f1fa6ec 100644
--- a/src/hb-ot-cff2-table.cc
+++ b/src/hb-ot-cff2-table.cc
@@ -27,6 +27,8 @@
 #include "hb-ot-cff2-table.hh"
 #include "hb-cff2-interp-cs.hh"
 
+#ifndef HB_NO_OT_FONT_CFF
+
 using namespace CFF;
 
 struct extents_param_t
@@ -99,6 +101,11 @@
 					   hb_codepoint_t glyph,
 					   hb_glyph_extents_t *extents) const
 {
+#ifdef HB_NO_OT_FONT_CFF
+  /* XXX Remove check when this code moves to .hh file. */
+  return true;
+#endif
+
   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
 
   unsigned int num_coords;
@@ -134,3 +141,5 @@
 
   return true;
 }
+
+#endif
diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh
index a7b0ba9..74acc77 100644
--- a/src/hb-ot-cff2-table.hh
+++ b/src/hb-ot-cff2-table.hh
@@ -56,11 +56,11 @@
     TRACE_SANITIZE (this);
 
     return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
-			  (format == 0)?
+			  ((format == 0)?
 			  u.format0.sanitize (c, fdcount):
 			    ((format == 3)?
 			    u.format3.sanitize (c, fdcount):
-			    u.format4.sanitize (c, fdcount))));
+			    u.format4.sanitize (c, fdcount)))));
   }
 
   bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 0a7d1ef..9e9679f 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -93,7 +93,7 @@
     this->length = get_sub_table_size (segments);
 
     this->segCountX2 = segments.length * 2;
-    this->entrySelector = MAX (1u, hb_bit_storage (segments.length)) - 1;
+    this->entrySelector = hb_max (1u, hb_bit_storage (segments.length)) - 1;
     this->searchRange = 2 * (1u << this->entrySelector);
     this->rangeShift = segments.length * 2 > this->searchRange
 		       ? 2 * segments.length - this->searchRange
@@ -142,7 +142,7 @@
 	for (unsigned int j = 0; j < num_codepoints; j++)
 	{
 	  hb_codepoint_t cp = segments[i].start_code + j;
-	  hb_codepoint_t new_gid;
+	  hb_codepoint_t new_gid = 0;
 	  if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
 	    return_trace (false);
 	  glyph_id_array[j] = new_gid;
@@ -183,7 +183,7 @@
 
     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
     while (plan->unicodes->next (&cp)) {
-      hb_codepoint_t new_gid;
+      hb_codepoint_t new_gid = 0;
       if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
       {
 	DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
@@ -348,7 +348,7 @@
       /* Some broken fonts have too long of a "length" value.
        * If that is the case, just change the value to truncate
        * the subtable at the end of the blob. */
-      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
+      uint16_t new_length = (uint16_t) hb_min ((uintptr_t) 65535,
 					    (uintptr_t) (c->end -
 							 (char *) this));
       if (!c->try_set (&length, new_length))
@@ -478,7 +478,7 @@
   {
     for (unsigned int i = 0; i < this->groups.len; i++) {
       out->add_range (this->groups[i].startCharCode,
-		      MIN ((hb_codepoint_t) this->groups[i].endCharCode,
+		      hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
 			   (hb_codepoint_t) HB_UNICODE_MAX));
     }
   }
@@ -518,31 +518,31 @@
 
 
   bool serialize (hb_serialize_context_t *c,
-		  const hb_sorted_vector_t<CmapSubtableLongGroup> &groups)
+		  const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
     this->format = 12;
     this->reserved = 0;
-    this->length = get_sub_table_size (groups);
+    this->length = get_sub_table_size (groups_data);
 
-    return_trace (CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups));
+    return_trace (CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups_data));
   }
 
-  static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups)
+  static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
   {
-    return 16 + 12 * groups.length;
+    return 16 + 12 * groups_data.length;
   }
 
   static bool create_sub_table_plan (const hb_subset_plan_t *plan,
-				     hb_sorted_vector_t<CmapSubtableLongGroup> *groups)
+				     hb_sorted_vector_t<CmapSubtableLongGroup> *groups_out)
   {
     CmapSubtableLongGroup *group = nullptr;
 
     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
     while (plan->unicodes->next (&cp)) {
-      hb_codepoint_t new_gid;
+      hb_codepoint_t new_gid = 0;
       if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
       {
 	DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
@@ -551,7 +551,7 @@
 
       if (!group || !_is_gid_consecutive (group, cp, new_gid))
       {
-	group = groups->push ();
+	group = groups_out->push ();
 	group->startCharCode = cp;
 	group->endCharCode = cp;
 	group->glyphID = new_gid;
@@ -560,8 +560,8 @@
     }
 
     DEBUG_MSG(SUBSET, nullptr, "cmap");
-    for (unsigned int i = 0; i < groups->length; i++) {
-      CmapSubtableLongGroup& group = (*groups)[i];
+    for (unsigned int i = 0; i < groups_out->length; i++) {
+      CmapSubtableLongGroup& group = (*groups_out)[i];
       DEBUG_MSG(SUBSET, nullptr, "  %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
     }
 
@@ -623,7 +623,7 @@
     for (unsigned int i = 0; i < count; i++)
     {
       hb_codepoint_t first = arrayZ[i].startUnicodeValue;
-      hb_codepoint_t last = MIN ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
+      hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
 				 (hb_codepoint_t) HB_UNICODE_MAX);
       out->add_range (first, last);
     }
@@ -863,6 +863,7 @@
     if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
       return false;
 
+    if (!find_subtable (12)) return true;
     return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
   }
 
@@ -881,8 +882,7 @@
 
     table->version = 0;
 
-    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3)))
-      return false;
+    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ cmap_subset_plan.format12_groups ? 3 : 2))) return false;
 
     // TODO(grieger): Convert the below to a for loop
 
@@ -897,9 +897,12 @@
     format4_plat3_rec.encodingID = 1; // Unicode BMP
 
     // Format 12 Encoding Record
-    EncodingRecord &format12_rec = table->encodingRecord[2];
-    format12_rec.platformID = 3; // Windows
-    format12_rec.encodingID = 10; // Unicode UCS-4
+    if (cmap_subset_plan.format12_groups)
+    {
+      EncodingRecord &format12_rec = table->encodingRecord[2];
+      format12_rec.platformID = 3; // Windows
+      format12_rec.encodingID = 10; // Unicode UCS-4
+    }
 
     // Write out format 4 sub table
     {
@@ -913,7 +916,9 @@
     }
 
     // Write out format 12 sub table.
+    if (cmap_subset_plan.format12_groups)
     {
+      EncodingRecord &format12_rec = table->encodingRecord[2];
       CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
       subtable.u.format = 12;
 
@@ -1154,6 +1159,18 @@
     return &(this+result.subtable);
   }
 
+  bool find_subtable (unsigned format) const
+  {
+    auto it =
+    + hb_iter (encodingRecord)
+    | hb_map (&EncodingRecord::subtable)
+    | hb_map (hb_add (this))
+    | hb_filter ([&] (const CmapSubtable& _) { return _.u.format == format; })
+    ;
+
+    return it.len ();
+  }
+
   public:
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh
index 333ceaa..7955cf6 100644
--- a/src/hb-ot-color-cbdt-table.hh
+++ b/src/hb-ot-color-cbdt-table.hh
@@ -144,7 +144,7 @@
   }
 
   IndexSubtableHeader	header;
-  UnsizedArrayOf<Offset<OffsetType> >
+  UnsizedArrayOf<Offset<OffsetType>>
  			offsetArrayZ;
   public:
   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
@@ -349,15 +349,15 @@
     if (unlikely (!count))
       return Null(BitmapSizeTable);
 
-    unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+    unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
     if (!requested_ppem)
       requested_ppem = 1<<30; /* Choose largest strike. */
     unsigned int best_i = 0;
-    unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY);
+    unsigned int best_ppem = hb_max (sizeTables[0].ppemX, sizeTables[0].ppemY);
 
     for (unsigned int i = 1; i < count; i++)
     {
-      unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY);
+      unsigned int ppem = hb_max (sizeTables[i].ppemX, sizeTables[i].ppemY);
       if ((requested_ppem <= ppem && ppem < best_ppem) ||
 	  (requested_ppem > best_ppem && ppem > best_ppem))
       {
@@ -442,12 +442,12 @@
       }
 
       /* Convert to font units. */
-      double x_scale = upem / (double) strike.ppemX;
-      double y_scale = upem / (double) strike.ppemY;
-      extents->x_bearing = round (extents->x_bearing * x_scale);
-      extents->y_bearing = round (extents->y_bearing * y_scale);
-      extents->width = round (extents->width * x_scale);
-      extents->height = round (extents->height * y_scale);
+      float x_scale = upem / (float) strike.ppemX;
+      float y_scale = upem / (float) strike.ppemY;
+      extents->x_bearing = roundf (extents->x_bearing * x_scale);
+      extents->y_bearing = roundf (extents->y_bearing * y_scale);
+      extents->width = roundf (extents->width * x_scale);
+      extents->height = roundf (extents->height * y_scale);
 
       return true;
     }
diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh
index a57911a..90f89d5 100644
--- a/src/hb-ot-color-colr-table.hh
+++ b/src/hb-ot-color-colr-table.hh
@@ -125,9 +125,9 @@
   protected:
   HBUINT16	version;	/* Table version number (starts at 0). */
   HBUINT16	numBaseGlyphs;	/* Number of Base Glyph Records. */
-  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord> >
+  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>>
 		baseGlyphsZ;	/* Offset to Base Glyph records. */
-  LNNOffsetTo<UnsizedArrayOf<LayerRecord> >
+  LNNOffsetTo<UnsizedArrayOf<LayerRecord>>
 		layersZ;	/* Offset to Layer Records. */
   HBUINT16	numLayers;	/* Number of Layer Records. */
   public:
diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh
index 4070493..9ec2957 100644
--- a/src/hb-ot-color-cpal-table.hh
+++ b/src/hb-ot-color-cpal-table.hh
@@ -87,15 +87,15 @@
   }
 
   protected:
-  LNNOffsetTo<UnsizedArrayOf<HBUINT32> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT32>>
 		paletteFlagsZ;		/* Offset from the beginning of CPAL table to
 					 * the Palette Type Array. Set to 0 if no array
 					 * is provided. */
-  LNNOffsetTo<UnsizedArrayOf<NameID> >
+  LNNOffsetTo<UnsizedArrayOf<NameID>>
 		paletteLabelsZ;		/* Offset from the beginning of CPAL table to
 					 * the palette labels array. Set to 0 if no
 					 * array is provided. */
-  LNNOffsetTo<UnsizedArrayOf<NameID> >
+  LNNOffsetTo<UnsizedArrayOf<NameID>>
 		colorLabelsZ;		/* Offset from the beginning of CPAL table to
 					 * the color labels array. Set to 0
 					 * if no array is provided. */
@@ -144,7 +144,7 @@
     {
       hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count);
       /* Always return numColors colors per palette even if it has out-of-bounds start index. */
-      unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count);
+      unsigned int count = hb_min ((unsigned) hb_max ((int) (numColors - start_offset), 0), *color_count);
       *color_count = count;
       for (unsigned int i = 0; i < count; i++)
         colors[i] = segment_colors[i]; /* Bound-checked read. */
@@ -176,7 +176,7 @@
   HBUINT16	numPalettes;		/* Number of palettes in the table. */
   HBUINT16	numColorRecords;	/* Total number of color records, combined for
 					 * all palettes. */
-  LNNOffsetTo<UnsizedArrayOf<BGRAColor> >
+  LNNOffsetTo<UnsizedArrayOf<BGRAColor>>
 		colorRecordsZ;		/* Offset from the beginning of CPAL table to
 					 * the first ColorRecord. */
   UnsizedArrayOf<HBUINT16>
diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh
index f6bdbb3..9b725c4 100644
--- a/src/hb-ot-color-sbix-table.hh
+++ b/src/hb-ot-color-sbix-table.hh
@@ -121,7 +121,7 @@
   HBUINT16	resolution;	/* The device pixel density (in PPI) for which this
 				 * strike was designed. (E.g., 96 PPI, 192 PPI.) */
   protected:
-  UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
+  UnsizedArrayOf<LOffsetTo<SBIXGlyph>>
 		imageOffsetsZ;	/* Offset from the beginning of the strike data header
 				 * to bitmap data for an individual glyph ID. */
   public:
@@ -175,7 +175,7 @@
       if (unlikely (!count))
         return Null(SBIXStrike);
 
-      unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+      unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
       if (!requested_ppem)
         requested_ppem = 1<<30; /* Choose largest strike. */
       /* TODO Add DPI sensitivity as well? */
@@ -242,11 +242,11 @@
       /* Convert to font units. */
       if (strike_ppem)
       {
-	double scale = font->face->get_upem () / (double) strike_ppem;
-	extents->x_bearing = round (extents->x_bearing * scale);
-	extents->y_bearing = round (extents->y_bearing * scale);
-	extents->width = round (extents->width * scale);
-	extents->height = round (extents->height * scale);
+	float scale = font->face->get_upem () / (float) strike_ppem;
+	extents->x_bearing = roundf (extents->x_bearing * scale);
+	extents->y_bearing = roundf (extents->y_bearing * scale);
+	extents->width = roundf (extents->width * scale);
+	extents->height = roundf (extents->height * scale);
       }
 
       hb_blob_destroy (blob);
diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh
index 6e8eddf..926d61e 100644
--- a/src/hb-ot-color-svg-table.hh
+++ b/src/hb-ot-color-svg-table.hh
@@ -62,7 +62,7 @@
 				 * this index entry. */
   HBUINT16	endGlyphID;	/* The last glyph ID in the range described by
 				 * this index entry. Must be >= startGlyphID. */
-  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
 		svgDoc;		/* Offset from the beginning of the SVG Document Index
 				 * to an SVG document. Must be non-zero. */
   HBUINT32	svgDocLength;	/* Length of the SVG document.
@@ -107,7 +107,7 @@
 
   protected:
   HBUINT16	version;	/* Table version (starting at 0). */
-  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry> >
+  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry>>
 		svgDocEntries;	/* Offset (relative to the start of the SVG table) to the
 				 * SVG Documents Index. Must be non-zero. */
 				/* Array of SVG Document Index Entries. */
diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc
index 791135b..20c602c 100644
--- a/src/hb-ot-color.cc
+++ b/src/hb-ot-color.cc
@@ -47,6 +47,8 @@
  * @include: hb-ot.h
  *
  * Functions for fetching color-font information from OpenType font faces.
+ *
+ * HarfBuzz supports `COLR`/`CPAL`, `sbix`, `CBDT`, and `SVG` color fonts.
  **/
 
 
@@ -57,42 +59,54 @@
 
 /**
  * hb_ot_color_has_palettes:
- * @face: a font face.
+ * @face: #hb_face_t to work upon
  *
- * Returns: whether CPAL table is available.
+ * Tests whether a face includes a `CPAL` color-palette table.
+ *
+ * Return value: true if data found, false otherwise
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_palettes (hb_face_t *face)
 {
+#ifdef HB_NO_COLOR
+  return false;
+#endif
   return face->table.CPAL->has_data ();
 }
 
 /**
  * hb_ot_color_palette_get_count:
- * @face: a font face.
+ * @face: #hb_face_t to work upon
  *
- * Returns: the number of color palettes in @face, or zero if @face has
- * no colors.
+ * Fetches the number of color palettes in a face.
+ *
+ * Return value: the number of palettes found
  *
  * Since: 2.1.0
  */
 unsigned int
 hb_ot_color_palette_get_count (hb_face_t *face)
 {
+#ifdef HB_NO_COLOR
+  return 0;
+#endif
   return face->table.CPAL->get_palette_count ();
 }
 
 /**
  * hb_ot_color_palette_get_name_id:
- * @face:    a font face.
- * @palette_index: the index of the color palette whose name is being requested.
+ * @face: #hb_face_t to work upon
+ * @palette_index: The index of the color palette 
  *
- * Retrieves the name id of a color palette. For example, a color font can
- * have themed palettes like "Spring", "Summer", "Fall", and "Winter".
+ * Fetches the `name` table Name ID that provides display names for
+ * a `CPAL` color palette. 
  *
- * Returns: an identifier within @face's `name` table.
+ * Palette display names can be generic (e.g., "Default") or provide
+ * specific, themed names (e.g., "Spring", "Summer", "Fall", and "Winter").
+ *
+ * Return value: the Named ID found for the palette. 
  * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
  *
  * Since: 2.1.0
@@ -101,15 +115,24 @@
 hb_ot_color_palette_get_name_id (hb_face_t *face,
 				 unsigned int palette_index)
 {
+#ifdef HB_NO_COLOR
+  return HB_OT_NAME_ID_INVALID;
+#endif
   return face->table.CPAL->get_palette_name_id (palette_index);
 }
 
 /**
  * hb_ot_color_palette_color_get_name_id:
- * @face:        a font face.
- * @color_index: palette entry index.
+ * @face: #hb_face_t to work upon
+ * @color_index: The index of the color
  *
- * Returns: Name ID associated with a palette entry, e.g. eye color
+ * Fetches the `name` table Name ID that provides display names for
+ * the specificed color in a face's `CPAL` color palette. 
+ *
+ * Display names can be generic (e.g., "Background") or specific
+ * (e.g., "Eye color").
+ *
+ * Return value: the Name ID found for the color.
  *
  * Since: 2.1.0
  */
@@ -117,15 +140,20 @@
 hb_ot_color_palette_color_get_name_id (hb_face_t *face,
 				       unsigned int color_index)
 {
+#ifdef HB_NO_COLOR
+  return HB_OT_NAME_ID_INVALID;
+#endif
   return face->table.CPAL->get_color_name_id (color_index);
 }
 
 /**
  * hb_ot_color_palette_get_flags:
- * @face:          a font face
- * @palette_index: the index of the color palette whose flags are being requested
+ * @face: #hb_face_t to work upon
+ * @palette_index: The index of the color palette
  *
- * Returns: the flags for the requested color palette.
+ * Fetches the flags defined for a color palette.
+ *
+ * Return value: the #hb_ot_color_palette_flags_t of the requested color palette
  *
  * Since: 2.1.0
  */
@@ -133,30 +161,30 @@
 hb_ot_color_palette_get_flags (hb_face_t *face,
 			       unsigned int palette_index)
 {
+#ifdef HB_NO_COLOR
+  return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
+#endif
   return face->table.CPAL->get_palette_flags (palette_index);
 }
 
 /**
  * hb_ot_color_palette_get_colors:
- * @face:         a font face.
- * @palette_index:the index of the color palette whose colors
- *                are being requested.
- * @start_offset: the index of the first color being requested.
- * @color_count:  (inout) (optional): on input, how many colors
- *                can be maximally stored into the @colors array;
- *                on output, how many colors were actually stored.
- * @colors: (array length=color_count) (out) (optional):
- *                an array of #hb_color_t records. After calling
- *                this function, @colors will be filled with
- *                the palette colors. If @colors is NULL, the function
- *                will just return the number of total colors
- *                without storing any actual colors; this can be used
- *                for allocating a buffer of suitable size before calling
- *                hb_ot_color_palette_get_colors() a second time.
+ * @face: #hb_face_t to work upon
+ * @palette_index: the index of the color palette to query
+ * @start_offset: offset of the first color to retrieve
+ * @color_count: (inout) (optional): Input = the maximum number of colors to return;
+ *               Output = the actual number of colors returned (may be zero)
+ * @colors: (out) (array length=color_count) (nullable): The array of #hb_color_t records found
  *
- * Retrieves the colors in a color palette.
+ * Fetches a list of the colors in a color palette.
  *
- * Returns: the total number of colors in the palette.
+ * After calling this function, @colors will be filled with the palette
+ * colors. If @colors is NULL, the function will just return the number
+ * of total colors without storing any actual colors; this can be used
+ * for allocating a buffer of suitable size before calling
+ * hb_ot_color_palette_get_colors() a second time.
+ *
+ * Return value: the total number of colors in the palette
  *
  * Since: 2.1.0
  */
@@ -167,6 +195,11 @@
 				unsigned int  *colors_count  /* IN/OUT.  May be NULL. */,
 				hb_color_t    *colors        /* OUT.     May be NULL. */)
 {
+#ifdef HB_NO_COLOR
+  if (colors_count)
+    *colors_count = 0;
+  return 0;
+#endif
   return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors);
 }
 
@@ -177,28 +210,36 @@
 
 /**
  * hb_ot_color_has_layers:
- * @face: a font face.
+ * @face: #hb_face_t to work upon
  *
- * Returns: whether COLR table is available.
+ * Tests whether a face includes any `COLR` color layers.
+ *
+ * Return value: true if data found, false otherwise
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_layers (hb_face_t *face)
 {
+#ifdef HB_NO_COLOR
+  return false;
+#endif
   return face->table.COLR->has_data ();
 }
 
 /**
  * hb_ot_color_glyph_get_layers:
- * @face:         a font face.
- * @glyph:        a layered color glyph id.
- * @start_offset: starting offset of layers.
- * @count:  (inout) (optional): gets number of layers available to be written on buffer
- * 				and returns number of written layers.
- * @layers: (array length=count) (out) (optional): layers buffer to buffer.
+ * @face: #hb_face_t to work upon
+ * @glyph: The glyph index to query
+ * @start_offset: offset of the first layer to retrieve
+ * @layer_count: (inout) (optional): Input = the maximum number of layers to return;
+ *         Output = the actual number of layers returned (may be zero)
+ * @layers: (out) (array length=layer_count) (nullable): The array of layers found
  *
- * Returns: Total number of layers a layered color glyph have.
+ * Fetches a list of all color layers for the specified glyph index in the specified
+ * face. The list returned will begin at the offset provided.
+ *
+ * Return value: Total number of layers available for the glyph index queried
  *
  * Since: 2.1.0
  */
@@ -206,10 +247,15 @@
 hb_ot_color_glyph_get_layers (hb_face_t           *face,
 			      hb_codepoint_t       glyph,
 			      unsigned int         start_offset,
-			      unsigned int        *count, /* IN/OUT.  May be NULL. */
+			      unsigned int        *layer_count, /* IN/OUT.  May be NULL. */
 			      hb_ot_color_layer_t *layers /* OUT.     May be NULL. */)
 {
-  return face->table.COLR->get_glyph_layers (glyph, start_offset, count, layers);
+#ifdef HB_NO_COLOR
+  if (layer_count)
+    *layer_count = 0;
+  return 0;
+#endif
+  return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers);
 }
 
 
@@ -219,34 +265,40 @@
 
 /**
  * hb_ot_color_has_svg:
- * @face: a font face.
+ * @face: #hb_face_t to work upon.
  *
- * Check whether @face has SVG glyph images.
+ * Tests whether a face includes any `SVG` glyph images.
  *
- * Returns true if available, false otherwise.
+ * Return value: true if data found, false otherwise.
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_svg (hb_face_t *face)
 {
+#ifdef HB_NO_COLOR
+  return false;
+#endif
   return face->table.SVG->has_data ();
 }
 
 /**
  * hb_ot_color_glyph_reference_svg:
- * @face:  a font face.
- * @glyph: a svg glyph index.
+ * @face: #hb_face_t to work upon
+ * @glyph: a svg glyph index
  *
- * Get SVG document for a glyph. The blob may be either plain text or gzip-encoded.
+ * Fetches the SVG document for a glyph. The blob may be either plain text or gzip-encoded.
  *
- * Returns: (transfer full): respective svg blob of the glyph, if available.
+ * Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available
  *
  * Since: 2.1.0
  */
 hb_blob_t *
 hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
 {
+#ifdef HB_NO_COLOR
+  return hb_blob_get_empty ();
+#endif
   return face->table.SVG->reference_blob_for_glyph (glyph);
 }
 
@@ -257,36 +309,43 @@
 
 /**
  * hb_ot_color_has_png:
- * @face: a font face.
+ * @face: #hb_face_t to work upon
  *
- * Check whether @face has PNG glyph images (either CBDT or sbix tables).
+ * Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables).
  *
- * Returns true if available, false otherwise.
+ * Return value: true if data found, false otherwise
  *
  * Since: 2.1.0
  */
 hb_bool_t
 hb_ot_color_has_png (hb_face_t *face)
 {
+#ifdef HB_NO_COLOR
+  return false;
+#endif
   return face->table.CBDT->has_data () || face->table.sbix->has_data ();
 }
 
 /**
  * hb_ot_color_glyph_reference_png:
- * @font:  a font object, not face. upem should be set on
- * 	   that font object if one wants to get optimal png blob, otherwise
- * 	   return the biggest one
- * @glyph: a glyph index.
+ * @font: #hb_font_t to work upon
+ * @glyph: a glyph index
  *
- * Get PNG image for a glyph.
+ * Fetches the PNG image for a glyph. This function takes a font object, not a face object,
+ * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
+ * object. If UPEM is unset, the blob returned will be the largest PNG available.
  *
- * Returns: (transfer full): respective PNG blob of the glyph, if available.
+ * Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available
  *
  * Since: 2.1.0
  */
 hb_blob_t *
 hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t  glyph)
 {
+#ifdef HB_NO_COLOR
+  return hb_blob_get_empty ();
+#endif
+
   hb_blob_t *blob = hb_blob_get_empty ();
 
   if (font->face->table.sbix->has_data ())
diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h
index 49646bf..63ef20a 100644
--- a/src/hb-ot-color.h
+++ b/src/hb-ot-color.h
@@ -59,11 +59,11 @@
 
 /**
  * hb_ot_color_palette_flags_t:
- * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special
+ * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: Default indicating that there is nothing special
  *   to note about a color palette.
- * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: Flag indicating that the color
  *   palette is appropriate to use when displaying the font on a light background such as white.
- * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: Flag indicating that the color
  *   palette is appropriate to use when displaying the font on a dark background such as black.
  *
  * Since: 2.1.0
@@ -110,7 +110,7 @@
 hb_ot_color_glyph_get_layers (hb_face_t           *face,
 			      hb_codepoint_t       glyph,
 			      unsigned int         start_offset,
-			      unsigned int        *count, /* IN/OUT.  May be NULL. */
+			      unsigned int        *layer_count, /* IN/OUT.  May be NULL. */
 			      hb_ot_color_layer_t *layers /* OUT.     May be NULL. */);
 
 /*
diff --git a/src/hb-ot-deprecated.h b/src/hb-ot-deprecated.h
index bce51b7..bc72f8a 100644
--- a/src/hb-ot-deprecated.h
+++ b/src/hb-ot-deprecated.h
@@ -40,6 +40,10 @@
 #ifndef HB_DISABLE_DEPRECATED
 
 
+/* https://github.com/harfbuzz/harfbuzz/issues/1734 */
+#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER
+
+
 /* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
 HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
 hb_ot_layout_table_choose_script (hb_face_t      *face,
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 01d4563..21ca3c0 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -181,19 +181,20 @@
 			 void *user_data HB_UNUSED)
 {
   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
-  bool ret = ot_face->sbix->get_extents (font, glyph, extents);
-  if (!ret)
-    ret = ot_face->glyf->get_extents (font, glyph, extents);
-#if !defined(HB_NO_OT_FONT_CFF)
-  if (!ret)
-    ret = ot_face->cff1->get_extents (glyph, extents);
-  if (!ret)
-    ret = ot_face->cff2->get_extents (font, glyph, extents);
+  bool ret = false;
+
+#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
+  if (!ret) ret = ot_face->sbix->get_extents (font, glyph, extents);
 #endif
-#if !defined(HB_NO_OT_FONT_BITMAP)
-  if (!ret)
-    ret = ot_face->CBDT->get_extents (font, glyph, extents);
+  if (!ret) ret = ot_face->glyf->get_extents (glyph, extents);
+#ifndef HB_NO_OT_FONT_CFF
+  if (!ret) ret = ot_face->cff1->get_extents (glyph, extents);
+  if (!ret) ret = ot_face->cff2->get_extents (font, glyph, extents);
 #endif
+#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
+  if (!ret) ret = ot_face->CBDT->get_extents (font, glyph, extents);
+#endif
+
   // TODO Hook up side-bearings variations.
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index b65fddd..90addc4 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -21,7 +21,7 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
- * Google Author(s): Behdad Esfahbod
+* Google Author(s): Behdad Esfahbod, Garret Rieger, Roderick Sheeter
  * Adobe Author(s): Michiharu Ariza
  */
 
@@ -32,7 +32,6 @@
 #include "hb-ot-head-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-var-gvar-table.hh"
-#include "hb-subset-glyf.hh"
 
 #include <float.h>
 
@@ -63,7 +62,7 @@
   public:
   DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
 			* check the size externally, allow Null() object of it by
-			* defining it MIN() instead. */
+			* defining it _MIN instead. */
 };
 
 
@@ -86,26 +85,172 @@
     return_trace (true);
   }
 
-  bool subset (hb_subset_plan_t *plan) const
+  template<typename Iterator,
+	   hb_requires (hb_is_source_of (Iterator, unsigned int))>
+  static bool
+  _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets)
   {
-    hb_blob_t *glyf_prime = nullptr;
-    hb_blob_t *loca_prime = nullptr;
+    unsigned max_offset = + padded_offsets | hb_reduce(hb_add, 0);
+    unsigned num_offsets = padded_offsets.len () + 1;
+    bool use_short_loca = max_offset < 0x1FFFF;
+    unsigned entry_size = use_short_loca ? 2 : 4;
+    char *loca_prime_data = (char *) calloc (entry_size, num_offsets);
 
-    bool success = true;
-    bool use_short_loca = false;
-    if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
-      success = success && plan->add_table (HB_OT_TAG_glyf, glyf_prime);
-      success = success && plan->add_table (HB_OT_TAG_loca, loca_prime);
-      success = success && _add_head_and_set_loca_version (plan, use_short_loca);
-    } else {
-      success = false;
-    }
-    hb_blob_destroy (loca_prime);
-    hb_blob_destroy (glyf_prime);
+    if (unlikely (!loca_prime_data)) return false;
 
-    return success;
+    DEBUG_MSG(SUBSET, nullptr, "loca entry_size %d num_offsets %d max_offset %d size %d", entry_size, num_offsets, max_offset, entry_size * num_offsets);
+
+    if (use_short_loca)
+      _write_loca (padded_offsets, 1, hb_array ((HBUINT16*) loca_prime_data, num_offsets));
+    else
+      _write_loca (padded_offsets, 0, hb_array ((HBUINT32*) loca_prime_data, num_offsets));
+
+    hb_blob_t * loca_blob = hb_blob_create (loca_prime_data,
+					    entry_size * num_offsets,
+					    HB_MEMORY_MODE_WRITABLE,
+					    loca_prime_data,
+					    free);
+
+    bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
+		  && _add_head_and_set_loca_version(plan, use_short_loca);
+
+    hb_blob_destroy (loca_blob);
+    return result;
   }
 
+  template<typename IteratorIn, typename IteratorOut,
+	   hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
+	   hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
+  static void
+  _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest)
+  {
+    unsigned int offset = 0;
+    dest << 0;
+    + it
+    | hb_map ([=, &offset] (unsigned int padded_size) {
+      offset += padded_size;
+      DEBUG_MSG(SUBSET, nullptr, "loca entry offset %d", offset);
+      return offset >> right_shift;
+    })
+    | hb_sink (dest)
+    ;
+  }
+
+  // requires source of SubsetGlyph complains the identifier isn't declared
+  template <typename Iterator>
+  bool serialize(hb_serialize_context_t *c,
+		 Iterator it,
+		 const hb_subset_plan_t *plan)
+  {
+    TRACE_SERIALIZE (this);
+
+    + it
+    | hb_apply ([=] (const SubsetGlyph& _) { _.serialize (c, plan); })
+    ;
+
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+
+    glyf *glyf_prime = c->serializer->start_embed <glyf> ();
+    if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
+
+    // Byte region(s) per glyph to output
+    // unpadded, hints removed if so requested
+    // If we fail to process a glyph we produce an empty (0-length) glyph
+    hb_vector_t<SubsetGlyph> glyphs;
+    _populate_subset_glyphs (c->plan, &glyphs);
+
+    glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan);
+
+    auto padded_offsets =
+    + hb_iter (glyphs)
+    | hb_map (&SubsetGlyph::padded_size)
+    ;
+
+    if (c->serializer->in_error ()) return_trace (false);
+    return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, padded_offsets)));
+  }
+
+  template <typename SubsetGlyph>
+  void
+  _populate_subset_glyphs (const hb_subset_plan_t * plan,
+			   hb_vector_t<SubsetGlyph> * glyphs /* OUT */) const
+  {
+    OT::glyf::accelerator_t glyf;
+    glyf.init (plan->source);
+
+    + hb_range (plan->num_output_glyphs ())
+    | hb_map ([&] (hb_codepoint_t new_gid) {
+      SubsetGlyph subset_glyph;
+      subset_glyph.new_gid = new_gid;
+
+      // should never fail: all old gids should be mapped
+      if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph;
+
+      subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this, subset_glyph.old_gid);
+      if (plan->drop_hints) subset_glyph.drop_hints (glyf);
+      else subset_glyph.dest_start = subset_glyph.source_glyph;
+
+      return subset_glyph;
+    })
+    | hb_sink (glyphs)
+    ;
+
+    glyf.fini();
+  }
+
+  static void
+  _fix_component_gids (const hb_subset_plan_t *plan,
+		       hb_bytes_t glyph)
+  {
+    OT::glyf::CompositeGlyphHeader::Iterator iterator;
+    if (OT::glyf::CompositeGlyphHeader::get_iterator (&glyph,
+						      glyph.length,
+						      &iterator))
+    {
+      do
+      {
+	hb_codepoint_t new_gid;
+	if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
+					&new_gid))
+	  continue;
+	((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex = new_gid;
+      } while (iterator.move_to_next ());
+    }
+  }
+
+  static void
+  _zero_instruction_length (hb_bytes_t glyph)
+  {
+    const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (&glyph, 0);
+    int16_t num_contours = (int16_t) glyph_header.numberOfContours;
+    if (num_contours <= 0) return;  // only for simple glyphs
+
+    const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (&glyph, GlyphHeader::static_size + 2 * num_contours);
+    (HBUINT16 &) instruction_length = 0;
+  }
+
+  static bool _remove_composite_instruction_flag (hb_bytes_t glyph)
+  {
+    const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (&glyph, 0);
+    if (glyph_header.numberOfContours >= 0) return true;  // only for composites
+
+    /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
+    OT::glyf::CompositeGlyphHeader::Iterator composite_it;
+    if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false;
+    const OT::glyf::CompositeGlyphHeader *composite_header;
+    do {
+      composite_header = composite_it.current;
+      OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&composite_header->flags);
+      *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS;
+    } while (composite_it.move_to_next ());
+    return true;
+}
+
   static bool
   _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
   {
@@ -261,6 +406,7 @@
     }
 
     public:
+    // TODO rewrite using new iterator framework if possible
     struct Iterator
     {
       const char *glyph_start;
@@ -330,7 +476,7 @@
       loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
       glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
 
-      num_glyphs = MAX (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+      num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
 
       gvar_accel.init (face);
       hmtx_accel.init (face);
@@ -690,7 +836,7 @@
     public:
     /* based on FontTools _g_l_y_f.py::trim */
     bool remove_padding (unsigned int start_offset,
-				unsigned int *end_offset) const
+			 unsigned int *end_offset) const
     {
       if (*end_offset - start_offset < GlyphHeader::static_size) return true;
 
@@ -788,61 +934,55 @@
       return true;
     }
 
-    bool get_instruction_offsets (unsigned int start_offset,
-				  unsigned int end_offset,
-				  unsigned int *instruction_start /* OUT */,
-				  unsigned int *instruction_end /* OUT */) const
+    bool get_instruction_length (hb_bytes_t glyph,
+				 unsigned int * length /* OUT */) const
     {
-      if (end_offset - start_offset < GlyphHeader::static_size)
+      /* Empty glyph; no instructions. */
+      if (glyph.length < GlyphHeader::static_size)
       {
-	*instruction_start = 0;
-	*instruction_end = 0;
-	return true; /* Empty glyph; no instructions. */
+	*length = 0;
+	// only 0 byte glyphs are healthy when missing GlyphHeader
+	return glyph.length == 0;
       }
-      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
+      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (&glyph, 0);
       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
       if (num_contours < 0)
       {
+	unsigned int start = glyph.length;
+	unsigned int end = glyph.length;
+	unsigned int glyph_offset = &glyph - glyf_table;
 	CompositeGlyphHeader::Iterator composite_it;
-	if (unlikely (!CompositeGlyphHeader::get_iterator (
-	    (const char*) this->glyf_table + start_offset,
-	     end_offset - start_offset, &composite_it))) return false;
+	if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false;
 	const CompositeGlyphHeader *last;
 	do {
 	  last = composite_it.current;
 	} while (composite_it.move_to_next ());
 
 	if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
-	  *instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size ();
-	else
-	  *instruction_start = end_offset;
-	*instruction_end = end_offset;
-	if (unlikely (*instruction_start > *instruction_end))
+	  start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size () - glyph_offset;
+	if (unlikely (start > end))
 	{
-	  DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
+	  DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside %d byte buffer", start, glyph.length);
 	  return false;
 	}
+	*length = end - start;
       }
       else
       {
-	unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
-	if (unlikely (instruction_length_offset + 2 > end_offset))
+	unsigned int instruction_length_offset = GlyphHeader::static_size + 2 * num_contours;
+	if (unlikely (instruction_length_offset + 2 > glyph.length))
 	{
 	  DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength.");
 	  return false;
 	}
 
-	const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
-	unsigned int start = instruction_length_offset + 2;
-	unsigned int end = start + (uint16_t) instruction_length;
-	if (unlikely (end > end_offset)) // Out of bounds of the current glyph
+	const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (&glyph, instruction_length_offset);
+	if (unlikely (instruction_length_offset + instruction_length > glyph.length)) // Out of bounds of the current glyph
 	{
 	  DEBUG_MSG(SUBSET, nullptr, "The instructions array overruns the glyph's boundaries.");
 	  return false;
 	}
-
-	*instruction_start = start;
-	*instruction_end = end;
+	*length = (uint16_t) instruction_length;
       }
       return true;
     }
@@ -896,15 +1036,34 @@
       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
 
       /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
-      /* extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); */
+      /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
       extents->x_bearing = hmtx_accel.get_side_bearing (glyph);
-      extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
-      extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - MIN (glyph_header.xMin, glyph_header.xMax);
-      extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
+      extents->y_bearing = hb_max (glyph_header.yMin, glyph_header.yMax);
+      extents->width     = hb_max (glyph_header.xMin, glyph_header.xMax) - hb_min (glyph_header.xMin, glyph_header.xMax);
+      extents->height    = hb_min (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
 
       return true;
     }
 
+  hb_bytes_t bytes_for_glyph (const char * glyf, hb_codepoint_t gid)
+  {
+    unsigned int start_offset, end_offset;
+    if (unlikely (!(get_offsets (gid, &start_offset, &end_offset) &&
+      remove_padding (start_offset, &end_offset))))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Unable to get offset or remove padding for %d", gid);
+      return hb_bytes_t ();
+    }
+    hb_bytes_t glyph = hb_bytes_t (glyf + start_offset, end_offset - start_offset);
+    if (glyph.length == 0) return glyph;
+    if (unlikely (glyph.length < GlyphHeader::static_size))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Glyph size smaller than minimum header %d", gid);
+      return hb_bytes_t ();
+    }
+    return glyph;
+  }
+
     private:
     bool short_offset;
     unsigned int num_glyphs;
@@ -917,12 +1076,99 @@
     vmtx::accelerator_t		vmtx_accel;
   };
 
+
+  struct SubsetGlyph
+  {
+    hb_codepoint_t new_gid;
+    hb_codepoint_t old_gid;
+    hb_bytes_t source_glyph;
+    hb_bytes_t dest_start;  // region of source_glyph to copy first
+    hb_bytes_t dest_end;    // region of source_glyph to copy second
+
+
+  bool serialize (hb_serialize_context_t *c,
+		  const hb_subset_plan_t *plan) const
+  {
+    TRACE_SERIALIZE (this);
+
+    hb_bytes_t dest_glyph = dest_start.copy(c);
+    dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy(c).length);
+    unsigned int pad_length = padding ();
+    DEBUG_MSG(SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length  + pad_length, pad_length);
+
+    HBUINT8 pad;
+    pad = 0;
+    while (pad_length > 0)
+    {
+      c->embed(pad);
+      pad_length--;
+    }
+
+    if (dest_glyph.length)
+    {
+      _fix_component_gids (plan, dest_glyph);
+      if (plan->drop_hints)
+      {
+	_zero_instruction_length (dest_glyph);
+	c->check_success (_remove_composite_instruction_flag (dest_glyph));
+      }
+    }
+
+    return_trace (true);
+  }
+
+    void drop_hints (const OT::glyf::accelerator_t& glyf)
+    {
+      if (source_glyph.length == 0) return;
+
+      unsigned int instruction_length = 0;
+      if (!glyf.get_instruction_length (source_glyph, &instruction_length))
+      {
+	 DEBUG_MSG(SUBSET, nullptr, "Unable to read instruction length for new_gid %d", new_gid);
+	return ;
+      }
+
+      const GlyphHeader& header = StructAtOffset<GlyphHeader> (&source_glyph, 0);
+      int16_t num_contours = (int16_t) header.numberOfContours;
+      DEBUG_MSG(SUBSET, nullptr, "new_gid %d (%d contours) drop %d instruction bytes from %d byte source glyph", new_gid, num_contours, instruction_length, source_glyph.length);
+      if (num_contours < 0)
+      {
+	// composite, just chop instructions off the end
+	dest_start = hb_bytes_t (&source_glyph, source_glyph.length - instruction_length);
+      }
+      else
+      {
+	// simple glyph
+	dest_start = hb_bytes_t (&source_glyph, GlyphHeader::static_size + 2 * header.numberOfContours + 2);
+	dest_end = hb_bytes_t (&source_glyph + dest_start.length + instruction_length,
+			       source_glyph.length - dest_start.length - instruction_length);
+DEBUG_MSG(SUBSET, nullptr, "source_len %d start len %d instruction_len %d end len %d", source_glyph.length, dest_start.length, instruction_length, dest_end.length);
+      }
+    }
+
+    unsigned int length () const
+    {
+      return dest_start.length + dest_end.length;
+    }
+
+    // pad to 2 to ensure 2-byte loca will be ok
+    unsigned int padding () const
+    {
+      return length () % 2;
+    }
+
+    unsigned int padded_size () const
+    {
+      return length () + padding ();
+    }
+  };
+
   protected:
   UnsizedArrayOf<HBUINT8>	dataZ;		/* Glyphs data. */
   public:
   DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
 			* check the size externally, allow Null() object of it by
-			* defining it MIN() instead. */
+			* defining it _MIN instead. */
 };
 
 struct glyf_accelerator_t : glyf::accelerator_t {};
diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh
index 847b326..96c1d1f 100644
--- a/src/hb-ot-hdmx-table.hh
+++ b/src/hb-ot-hdmx-table.hh
@@ -41,71 +41,31 @@
 
 struct DeviceRecord
 {
-  struct SubsetView
-  {
-    const DeviceRecord *source_device_record;
-    unsigned int sizeDeviceRecord;
-    hb_subset_plan_t *subset_plan;
-
-    void init (const DeviceRecord *source_device_record,
-	       unsigned int sizeDeviceRecord,
-	       hb_subset_plan_t   *subset_plan)
-    {
-      this->source_device_record = source_device_record;
-      this->sizeDeviceRecord = sizeDeviceRecord;
-      this->subset_plan = subset_plan;
-    }
-
-    unsigned int len () const
-    { return this->subset_plan->num_output_glyphs (); }
-
-    const HBUINT8* operator [] (unsigned int new_gid) const
-    {
-      if (unlikely (new_gid >= len ())) return nullptr;
-
-      hb_codepoint_t old_gid;
-      if (!this->subset_plan->old_gid_for_new_gid (new_gid, &old_gid))
-        return &Null(HBUINT8);
-
-      if (old_gid >= sizeDeviceRecord - DeviceRecord::min_size)
-        return nullptr;
-      return &(this->source_device_record->widthsZ[old_gid]);
-    }
-  };
-
-  static unsigned int get_size (unsigned int count)
+  static unsigned int get_size (unsigned count)
   { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
 
-  bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it)
   {
     TRACE_SERIALIZE (this);
 
-    unsigned int size = get_size (subset_view.len ());
-    if (unlikely (!c->allocate_size<DeviceRecord> (size)))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.",
-		 size);
-      return_trace (false);
-    }
+    unsigned length = it.len ();
 
-    this->pixelSize = subset_view.source_device_record->pixelSize;
-    this->maxWidth = subset_view.source_device_record->maxWidth;
+    if (unlikely (!c->extend (*this, length)))  return_trace (false);
 
-    for (unsigned int i = 0; i < subset_view.len (); i++)
-    {
-      const HBUINT8 *width = subset_view[i];
-      if (!width)
-      {
-	DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
-	return_trace (false);
-      }
-      widthsZ[i] = *width;
-    }
+    this->pixelSize = pixelSize;
+    this->maxWidth =
+    + it
+    | hb_reduce (hb_max, 0u);
+
+    + it
+    | hb_sink (widthsZ.as_array (length));
 
     return_trace (true);
   }
 
-  bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned sizeDeviceRecord) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
@@ -135,62 +95,63 @@
     return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
   }
 
-  bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  template<typename Iterator,
+	   hb_requires (hb_is_iterator (Iterator))>
+  bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
   {
     TRACE_SERIALIZE (this);
 
     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
 
-    this->version = source_hdmx->version;
-    this->numRecords = source_hdmx->numRecords;
-    this->sizeDeviceRecord = DeviceRecord::get_size (plan->num_output_glyphs ());
+    this->version = version;
+    this->numRecords = it.len ();
+    this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0);
 
-    for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
-    {
-      DeviceRecord::SubsetView subset_view;
-      subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
+    + it
+    | hb_apply ([c] (const hb_item_type<Iterator>& _) {
+		  c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
+		})
+    ;
 
-      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
-	return_trace (false);
-    }
+    return_trace (c->successful);
+  }
 
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+
+    hdmx *hdmx_prime = c->serializer->start_embed <hdmx> ();
+    if (unlikely (!hdmx_prime)) return_trace (false);
+
+    auto it =
+    + hb_range ((unsigned) numRecords)
+    | hb_map ([c, this] (unsigned _)
+	{
+	  const DeviceRecord *device_record =
+	    &StructAtOffset<DeviceRecord> (&firstDeviceRecord,
+					   _ * sizeDeviceRecord);
+	  auto row =
+	    + hb_range (c->plan->num_output_glyphs ())
+	    | hb_map (c->plan->reverse_glyph_map)
+	    | hb_map ([=] (hb_codepoint_t _)
+		      {
+			if (c->plan->is_empty_glyph (_))
+			  return Null(HBUINT8);
+			return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
+		      })
+	    ;
+	  return hb_pair ((unsigned) device_record->pixelSize, +row);
+	})
+    ;
+
+    hdmx_prime->serialize (c->serializer, version, it);
     return_trace (true);
   }
 
-  static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  unsigned get_num_glyphs () const
   {
-    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->num_output_glyphs ());
-  }
-
-  bool subset (hb_subset_plan_t *plan) const
-  {
-    size_t dest_size = get_subsetted_size (this, plan);
-    hdmx *dest = (hdmx *) malloc (dest_size);
-    if (unlikely (!dest))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size);
-      return false;
-    }
-
-    hb_serialize_context_t c (dest, dest_size);
-    hdmx *hdmx_prime = c.start_serialize<hdmx> ();
-    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan))
-    {
-      free (dest);
-      DEBUG_MSG(SUBSET, nullptr, "Failed to serialize write new hdmx.");
-      return false;
-    }
-    c.end_serialize ();
-
-    hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest,
-						 dest_size,
-						 HB_MEMORY_MODE_READONLY,
-						 dest,
-						 free);
-    bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
-    hb_blob_destroy (hdmx_prime_blob);
-
-    return result;
+    return sizeDeviceRecord - DeviceRecord::min_size;
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 9a2b842..1b09d8d 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -92,74 +92,71 @@
     return result;
   }
 
-  bool subset (hb_subset_plan_t *plan) const
+  template<typename Iterator,
+           hb_requires (hb_is_iterator (Iterator))>
+  void serialize (hb_serialize_context_t *c,
+                  Iterator it,
+                  unsigned num_advances)
   {
-    typename T::accelerator_t _mtx;
-    _mtx.init (plan->source);
+    unsigned idx = 0;
+    + it
+    | hb_apply ([c, &idx, num_advances] (const hb_item_type<Iterator>& _)
+                {
+                  if (idx < num_advances)
+                  {
+                    LongMetric lm;
+                    lm.advance = _.first;
+                    lm.sb = _.second;
+                    if (unlikely (!c->embed<LongMetric> (&lm))) return;
+                  }
+                  else
+                  {
+                    FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
+                    if (unlikely (!sb)) return;
+                    *sb = _.second;
+                  }
+                  idx++;
+                })
+    ;
+  }
 
-    /* All the trailing glyphs with the same advance can use one LongMetric
-     * and just keep LSB */
-    unsigned int num_output_glyphs = plan->num_output_glyphs ();
-    unsigned int num_advances = _mtx.num_advances_for_subset (plan);
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
 
-    /* alloc the new table */
-    size_t dest_sz = num_advances * 4
-		  + (num_output_glyphs - num_advances) * 2;
-    void *dest = (void *) malloc (dest_sz);
-    if (unlikely (!dest))
-    {
-      return false;
-    }
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes",
-              HB_UNTAG(T::tableTag), num_advances, num_output_glyphs - num_advances, (unsigned int) dest_sz);
+    T *table_prime = c->serializer->start_embed <T> ();
+    if (unlikely (!table_prime)) return_trace (false);
 
-    // Copy everything over
-    char * dest_pos = (char *) dest;
+    accelerator_t _mtx;
+    _mtx.init (c->plan->source);
+    unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
 
-    bool failed = false;
-    for (unsigned int i = 0; i < num_output_glyphs; i++)
-    {
-      int side_bearing = 0;
-      unsigned int advance = 0;
-      hb_codepoint_t old_gid;
-      if (plan->old_gid_for_new_gid (i, &old_gid))
-      {
-        // Glyph is not an empty glyph so copy advance and side bearing
-        // from the input font.
-        side_bearing = _mtx.get_side_bearing (old_gid);
-        advance = _mtx.get_advance (old_gid);
-      }
+    auto it =
+    + hb_range (c->plan->num_output_glyphs ())
+    | hb_map ([c, &_mtx] (unsigned _)
+	{
+	  hb_codepoint_t old_gid;
+	  if (c->plan->old_gid_for_new_gid (_, &old_gid))
+            return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+          else
+	    return hb_pair (0u, 0u);
+	})
+    ;
 
-      bool has_advance = i < num_advances;
-      if (has_advance)
-      {
-        ((LongMetric *) dest_pos)->advance = advance;
-        ((LongMetric *) dest_pos)->sb = side_bearing;
-      }
-      else
-      {
-        *((FWORD *) dest_pos) = side_bearing;
-      }
-      dest_pos += (has_advance ? 4 : 2);
-    }
+    table_prime->serialize (c->serializer, it, num_advances);
+
     _mtx.fini ();
 
+    if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ()))
+      return_trace (false);
+
     // Amend header num hmetrics
-    if (failed || unlikely (!subset_update_header (plan, num_advances)))
+    if (unlikely (!subset_update_header (c->plan, num_advances)))
     {
-      free (dest);
-      return false;
+      return_trace (false);
     }
 
-    hb_blob_t *result = hb_blob_create ((const char *)dest,
-                                        dest_sz,
-                                        HB_MEMORY_MODE_READONLY,
-                                        dest,
-                                        free);
-    bool success = plan->add_table (T::tableTag, result);
-    hb_blob_destroy (result);
-    return success;
+    return_trace (true);
   }
 
   struct accelerator_t : hmtxvmtx_accelerator_base_t
@@ -264,7 +261,7 @@
 	  return default_advance;
       }
 
-      return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
+      return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance;
     }
 
     unsigned int get_advance (hb_codepoint_t  glyph,
diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh
index ec6a3c8..ae2bcc9 100644
--- a/src/hb-ot-kern-table.hh
+++ b/src/hb-ot-kern-table.hh
@@ -47,9 +47,9 @@
   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
     hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
-    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount);
-    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount);
-    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount);
+    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
+    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
+    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
 
     unsigned int leftC = leftClass[left];
     unsigned int rightC = rightClass[right];
@@ -121,16 +121,20 @@
     }
   }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     unsigned int subtable_type = get_type ();
     TRACE_DISPATCH (this, subtable_type);
     switch (subtable_type) {
     case 0:	return_trace (c->dispatch (u.format0));
-    case 1:	return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ());
+#ifndef HB_NO_SHAPE_AAT
+    case 1:	return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward<Ts> (ds)...) : c->default_return_value ());
+#endif
     case 2:	return_trace (c->dispatch (u.format2));
-    case 3:	return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ());
+#ifndef HB_NO_SHAPE_AAT
+    case 3:	return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward<Ts> (ds)...) : c->default_return_value ());
+#endif
     default:	return_trace (c->default_return_value ());
     }
   }
@@ -278,7 +282,9 @@
   {
     switch (get_type ()) {
     case 0: return u.ot.has_state_machine ();
+#ifndef HB_NO_SHAPE_AAT
     case 1: return u.aat.has_state_machine ();
+#endif
     default:return false;
     }
   }
@@ -287,7 +293,9 @@
   {
     switch (get_type ()) {
     case 0: return u.ot.has_cross_stream ();
+#ifndef HB_NO_SHAPE_AAT
     case 1: return u.aat.has_cross_stream ();
+#endif
     default:return false;
     }
   }
@@ -296,7 +304,9 @@
   {
     switch (get_type ()) {
     case 0: return u.ot.get_h_kerning (left, right);
+#ifndef HB_NO_SHAPE_AAT
     case 1: return u.aat.get_h_kerning (left, right);
+#endif
     default:return 0;
     }
   }
@@ -304,14 +314,16 @@
   bool apply (AAT::hb_aat_apply_context_t *c) const
   { return dispatch (c); }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     unsigned int subtable_type = get_type ();
     TRACE_DISPATCH (this, subtable_type);
     switch (subtable_type) {
-    case 0:	return_trace (c->dispatch (u.ot));
-    case 1:	return_trace (c->dispatch (u.aat));
+    case 0:	return_trace (c->dispatch (u.ot, hb_forward<Ts> (ds)...));
+#ifndef HB_NO_SHAPE_AAT
+    case 1:	return_trace (c->dispatch (u.aat, hb_forward<Ts> (ds)...));
+#endif
     default:	return_trace (c->default_return_value ());
     }
   }
@@ -328,7 +340,9 @@
   HBUINT32		version32;
   HBUINT16		major;
   KernOT		ot;
+#ifndef HB_NO_SHAPE_AAT
   KernAAT		aat;
+#endif
   } u;
   public:
   DEFINE_SIZE_UNION (4, version32);
diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 7ef573e..0912362 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -447,7 +447,7 @@
   }
 
   protected:
-  OffsetTo<SortedArrayOf<Tag> >
+  OffsetTo<SortedArrayOf<Tag>>
 		baseTagList;	/* Offset to BaseTagList table, from beginning
 				 * of Axis table (may be NULL)
 				 * Array of 4-byte baseline identification tags — must
diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh
index ea01c5a..a6d9185 100644
--- a/src/hb-ot-layout-common.hh
+++ b/src/hb-ot-layout-common.hh
@@ -104,7 +104,7 @@
 };
 
 template <typename Type>
-struct RecordArrayOf : SortedArrayOf<Record<Type> >
+struct RecordArrayOf : SortedArrayOf<Record<Type>>
 {
   const OffsetTo<Type>& get_offset (unsigned int i) const
   { return (*this)[i].offset; }
@@ -139,11 +139,11 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    struct RecordListOf<Type> *out = c->serializer->embed (*this);
+    auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
     unsigned int count = this->len;
     for (unsigned int i = 0; i < count; i++)
-      out->get_offset (i).serialize_subset (c, (*this)[i], out);
+      out->get_offset (i).serialize_subset (c, this->get_offset (i), this, out);
     return_trace (true);
   }
 
@@ -227,13 +227,13 @@
   {
     if (reqFeatureIndex == 0xFFFFu)
       return Index::NOT_FOUND_INDEX;
-   return reqFeatureIndex;;
+   return reqFeatureIndex;
   }
 
-  bool subset (hb_subset_context_t *c) const
+  LangSys* copy (hb_serialize_context_t *c) const
   {
-    TRACE_SUBSET (this);
-    return_trace (c->serializer->embed (*this));
+    TRACE_SERIALIZE (this);
+    return_trace (c->embed (*this));
   }
 
   bool sanitize (hb_sanitize_context_t *c,
@@ -278,12 +278,12 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    struct Script *out = c->serializer->embed (*this);
+    auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
-    out->defaultLangSys.serialize_subset (c, this+defaultLangSys, out);
+    out->defaultLangSys.serialize_copy (c->serializer, defaultLangSys, this, out);
     unsigned int count = langSys.len;
     for (unsigned int i = 0; i < count; i++)
-      out->langSys.arrayZ[i].offset.serialize_subset (c, this+langSys[i].offset, out);
+      out->langSys.arrayZ[i].offset.serialize_copy (c->serializer, langSys[i].offset, this, out);
     return_trace (true);
   }
 
@@ -560,7 +560,7 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    struct Feature *out = c->serializer->embed (*this);
+    auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
     out->featureParams = 0; /* TODO(subset) FeatureParams. */
     return_trace (true);
@@ -649,15 +649,18 @@
   unsigned int get_subtable_count () const { return subTable.len; }
 
   template <typename TSubTable>
-  const TSubTable& get_subtable (unsigned int i) const
-  { return this+CastR<OffsetArrayOf<TSubTable> > (subTable)[i]; }
-
-  template <typename TSubTable>
   const OffsetArrayOf<TSubTable>& get_subtables () const
-  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+  { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
   template <typename TSubTable>
   OffsetArrayOf<TSubTable>& get_subtables ()
-  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+  { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
+
+  template <typename TSubTable>
+  const TSubTable& get_subtable (unsigned int i) const
+  { return this+get_subtables<TSubTable> ()[i]; }
+  template <typename TSubTable>
+  TSubTable& get_subtable (unsigned int i)
+  { return this+get_subtables<TSubTable> ()[i]; }
 
   unsigned int get_size () const
   {
@@ -683,14 +686,14 @@
     return flag;
   }
 
-  template <typename TSubTable, typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename TSubTable, typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     unsigned int lookup_type = get_type ();
     TRACE_DISPATCH (this, lookup_type);
     unsigned int count = get_subtable_count ();
     for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type);
+      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, hb_forward<Ts> (ds)...);
       if (c->stop_sublookup_iteration (r))
 	return_trace (r);
     }
@@ -716,28 +719,11 @@
     return_trace (true);
   }
 
-  /* Older compilers need this to NOT be locally defined in a function. */
-  template <typename TSubTable>
-  struct SubTableSubsetWrapper
-  {
-    SubTableSubsetWrapper (const TSubTable &subtable_,
-			   unsigned int lookup_type_) :
-			     subtable (subtable_),
-			     lookup_type (lookup_type_) {}
-
-    bool subset (hb_subset_context_t *c) const
-    { return subtable.dispatch (c, lookup_type); }
-
-    private:
-    const TSubTable &subtable;
-    unsigned int lookup_type;
-  };
-
   template <typename TSubTable>
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    struct Lookup *out = c->serializer->embed (*this);
+    auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
 
     /* Subset the actual subtables. */
@@ -747,23 +733,11 @@
     OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
     unsigned int count = subTable.len;
     for (unsigned int i = 0; i < count; i++)
-    {
-      SubTableSubsetWrapper<TSubTable> wrapper (this+subtables[i], get_type ());
-
-      out_subtables[i].serialize_subset (c, wrapper, out);
-    }
+      out_subtables[i].serialize_subset (c, subtables[i], this, out, get_type ());
 
     return_trace (true);
   }
 
-  /* Older compilers need this to NOT be locally defined in a function. */
-  template <typename TSubTable>
-  struct SubTableSanitizeWrapper : TSubTable
-  {
-    bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const
-    { return this->dispatch (c, lookup_type); }
-  };
-
   template <typename TSubTable>
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -775,16 +749,21 @@
       if (!markFilteringSet.sanitize (c)) return_trace (false);
     }
 
-    if (unlikely (!CastR<OffsetArrayOf<SubTableSanitizeWrapper<TSubTable> > > (subTable)
-		   .sanitize (c, this, get_type ())))
+    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
       return_trace (false);
 
-    if (unlikely (get_type () == TSubTable::Extension))
+    if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
     {
       /* The spec says all subtables of an Extension lookup should
        * have the same type, which shall not be the Extension type
        * itself (but we already checked for that).
-       * This is specially important if one has a reverse type! */
+       * This is specially important if one has a reverse type!
+       *
+       * We only do this if sanitizer edit_count is zero.  Otherwise,
+       * some of the subtables might have become insane after they
+       * were sanity-checked by the edits of subsequent subtables.
+       * https://bugs.chromium.org/p/chromium/issues/detail?id=960331
+       */
       unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
       unsigned int count = get_subtable_count ();
       for (unsigned int i = 1; i < count; i++)
@@ -792,7 +771,6 @@
 	  return_trace (false);
     }
     return_trace (true);
-    return_trace (true);
   }
 
   private:
@@ -827,7 +805,7 @@
   }
 
   template <typename Iterator,
-	    hb_enable_if (hb_is_sorted_iterator_of (Iterator, const GlyphID))>
+      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
   {
     TRACE_SERIALIZE (this);
@@ -865,6 +843,8 @@
     bool more () const { return i < c->glyphArray.len; }
     void next () { i++; }
     hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
+    bool operator != (const iter_t& o) const
+    { return i != o.i || c != o.c; }
 
     private:
     const struct CoverageFormat1 *c;
@@ -894,7 +874,7 @@
   }
 
   template <typename Iterator,
-	    hb_enable_if (hb_is_sorted_iterator_of (Iterator, const GlyphID))>
+      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
   {
     TRACE_SERIALIZE (this);
@@ -905,30 +885,36 @@
       rangeRecord.len = 0;
       return_trace (true);
     }
-    /* TODO(iter) Port to non-random-access iterator interface. */
-    unsigned int count = glyphs.len ();
 
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < count; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-	num_ranges++;
-    rangeRecord.len = num_ranges;
-    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+    /* TODO(iter) Write more efficiently? */
 
-    unsigned int range = 0;
-    rangeRecord[range].start = glyphs[0];
-    rangeRecord[range].value = 0;
-    for (unsigned int i = 1; i < count; i++)
+    unsigned num_ranges = 0;
+    hb_codepoint_t last = (hb_codepoint_t) -2;
+    for (auto g: glyphs)
     {
-      if (glyphs[i - 1] + 1 != glyphs[i])
-      {
-	rangeRecord[range].end = glyphs[i - 1];
-	range++;
-	rangeRecord[range].start = glyphs[i];
-	rangeRecord[range].value = i;
-      }
+      if (last + 1 != g)
+        num_ranges++;
+      last = g;
     }
-    rangeRecord[range].end = glyphs[count - 1];
+
+    if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
+
+    unsigned count = 0;
+    unsigned range = (unsigned) -1;
+    last = (hb_codepoint_t) -2;
+    for (auto g: glyphs)
+    {
+      if (last + 1 != g)
+      {
+        range++;
+	rangeRecord[range].start = g;
+	rangeRecord[range].value = count;
+      }
+      rangeRecord[range].end = g;
+      last = g;
+      count++;
+    }
+
     return_trace (true);
   }
 
@@ -1017,6 +1003,8 @@
       j++;
     }
     hb_codepoint_t get_glyph () const { return j; }
+    bool operator != (const iter_t& o) const
+    { return i != o.i || j != o.j || c != o.c; }
 
     private:
     const struct CoverageFormat2 *c;
@@ -1056,18 +1044,22 @@
   }
 
   template <typename Iterator,
-	    hb_enable_if (hb_is_sorted_iterator_of (Iterator, const GlyphID))>
+      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    /* TODO(iter) Port to non-random-access iterator interface. */
-    unsigned int count = glyphs.len ();
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < count; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-	num_ranges++;
+    unsigned count = 0;
+    unsigned num_ranges = 0;
+    hb_codepoint_t last = (hb_codepoint_t) -2;
+    for (auto g: glyphs)
+    {
+      if (last + 1 != g)
+        num_ranges++;
+      last = g;
+      count++;
+    }
     u.format = count * 2 < num_ranges * 3 ? 1 : 2;
 
     switch (u.format)
@@ -1166,6 +1158,16 @@
       default:return 0;
       }
     }
+    bool operator != (const iter_t& o) const
+    {
+      if (format != o.format) return true;
+      switch (format)
+      {
+      case 1: return u.format1 != o.u.format1;
+      case 2: return u.format2 != o.u.format2;
+      default:return false;
+      }
+    }
 
     private:
     unsigned int format;
@@ -1223,7 +1225,7 @@
     hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u);
 
     startGlyph = glyph_min;
-    classValue.len = glyph_max - glyph_min + 1;
+    c->check_assign (classValue.len, glyph_max - glyph_min + 1);
     if (unlikely (!c->extend (classValue))) return_trace (false);
 
     for (unsigned int i = 0; i < glyphs.length; i++)
@@ -2163,10 +2165,10 @@
     return (this+record.substitutions).find_substitute (feature_index);
   }
 
-  bool subset (hb_subset_context_t *c) const
+  FeatureVariations* copy (hb_serialize_context_t *c) const
   {
-    TRACE_SUBSET (this);
-    return_trace (c->serializer->embed (*this));
+    TRACE_SERIALIZE (this);
+    return_trace (c->embed (*this));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index dc8b9b8..0fca994 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -220,7 +220,7 @@
   {
     if (caret_count)
     {
-      hb_array_t <const OffsetTo<CaretValue> > array = carets.sub_array (start_offset, caret_count);
+      hb_array_t <const OffsetTo<CaretValue>> array = carets.sub_array (start_offset, caret_count);
       unsigned int count = array.length;
       for (unsigned int i = 0; i < count; i++)
 	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
@@ -296,7 +296,7 @@
 
   protected:
   HBUINT16	format;			/* Format identifier--format = 1 */
-  ArrayOf<LOffsetTo<Coverage> >
+  ArrayOf<LOffsetTo<Coverage>>
 		coverage;		/* Array of long offsets to mark set
 					 * coverage tables */
   public:
@@ -439,19 +439,19 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    struct GDEF *out = c->serializer->embed (*this);
+    auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
 
-    out->glyphClassDef.serialize_subset (c, this+glyphClassDef, out);
-    out->attachList = 0;//TODO(subset) serialize_subset (c, this+attachList, out);
-    out->ligCaretList = 0;//TODO(subset) serialize_subset (c, this+ligCaretList, out);
-    out->markAttachClassDef.serialize_subset (c, this+markAttachClassDef, out);
+    out->glyphClassDef.serialize_subset (c, glyphClassDef, this, out);
+    out->attachList = 0;//TODO(subset) serialize_subset (c, attachList, this, out);
+    out->ligCaretList = 0;//TODO(subset) serialize_subset (c, ligCaretList, this, out);
+    out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, out);
 
     if (version.to_int () >= 0x00010002u)
-      out->markGlyphSetsDef = 0;// TODO(subset) serialize_subset (c, this+markGlyphSetsDef, out);
+      out->markGlyphSetsDef = 0;// TODO(subset) serialize_subset (c, markGlyphSetsDef, this, out);
 
     if (version.to_int () >= 0x00010003u)
-      out->varStore = 0;// TODO(subset) serialize_subset (c, this+varStore, out);
+      out->varStore = 0;// TODO(subset) serialize_subset (c, varStore, this, out);
 
     return_trace (true);
   }
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index a7257df..86c45be 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -174,11 +174,11 @@
   }
 
   HB_INTERNAL static OffsetTo<Device>& get_device (Value* value)
-  { return *CastP<OffsetTo<Device> > (value); }
+  { return *CastP<OffsetTo<Device>> (value); }
   HB_INTERNAL static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
   {
     if (worked) *worked |= bool (*value);
-    return *CastP<OffsetTo<Device> > (value);
+    return *CastP<OffsetTo<Device>> (value);
   }
 
   HB_INTERNAL static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
@@ -393,7 +393,7 @@
 
   HBUINT16	rows;			/* Number of rows */
   protected:
-  UnsizedArrayOf<OffsetTo<Anchor> >
+  UnsizedArrayOf<OffsetTo<Anchor>>
 		matrixZ;		/* Matrix of offsets to Anchor tables--
 					 * from beginning of AnchorMatrix table */
   public:
@@ -446,8 +446,8 @@
     glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
 
     hb_glyph_position_t &o = buffer->cur_pos();
-    o.x_offset = round (base_x - mark_x);
-    o.y_offset = round (base_y - mark_y);
+    o.x_offset = roundf (base_x - mark_x);
+    o.y_offset = roundf (base_y - mark_y);
     o.attach_type() = ATTACH_TYPE_MARK;
     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
@@ -576,14 +576,14 @@
 
 struct SinglePos
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -726,7 +726,7 @@
     + hb_zip (this+coverage, pairSet)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_map ([&] (const OffsetTo<PairSet> &_) -> bool
+    | hb_map ([=] (const OffsetTo<PairSet> &_)
 	      { return (this+_).intersects (glyphs, valueFormat); })
     | hb_any
     ;
@@ -907,14 +907,14 @@
 
 struct PairPos
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -993,32 +993,32 @@
     /* Main-direction adjustment */
     switch (c->direction) {
       case HB_DIRECTION_LTR:
-	pos[i].x_advance  = round (exit_x) + pos[i].x_offset;
+	pos[i].x_advance  = roundf (exit_x) + pos[i].x_offset;
 
-	d = round (entry_x) + pos[j].x_offset;
+	d = roundf (entry_x) + pos[j].x_offset;
 	pos[j].x_advance -= d;
 	pos[j].x_offset  -= d;
 	break;
       case HB_DIRECTION_RTL:
-	d = round (exit_x) + pos[i].x_offset;
+	d = roundf (exit_x) + pos[i].x_offset;
 	pos[i].x_advance -= d;
 	pos[i].x_offset  -= d;
 
-	pos[j].x_advance  = round (entry_x) + pos[j].x_offset;
+	pos[j].x_advance  = roundf (entry_x) + pos[j].x_offset;
 	break;
       case HB_DIRECTION_TTB:
-	pos[i].y_advance  = round (exit_y) + pos[i].y_offset;
+	pos[i].y_advance  = roundf (exit_y) + pos[i].y_offset;
 
-	d = round (entry_y) + pos[j].y_offset;
+	d = roundf (entry_y) + pos[j].y_offset;
 	pos[j].y_advance -= d;
 	pos[j].y_offset  -= d;
 	break;
       case HB_DIRECTION_BTT:
-	d = round (exit_y) + pos[i].y_offset;
+	d = roundf (exit_y) + pos[i].y_offset;
 	pos[i].y_advance -= d;
 	pos[i].y_offset  -= d;
 
-	pos[j].y_advance  = round (entry_y);
+	pos[j].y_advance  = roundf (entry_y);
 	break;
       case HB_DIRECTION_INVALID:
       default:
@@ -1092,13 +1092,13 @@
 
 struct CursivePos
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -1208,13 +1208,13 @@
 
 struct MarkBasePos
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -1287,7 +1287,7 @@
     unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
     unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
     if (lig_id && lig_id == mark_id && mark_comp > 0)
-      comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
+      comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
     else
       comp_index = comp_count - 1;
 
@@ -1333,13 +1333,13 @@
 
 struct MarkLigPos
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -1455,13 +1455,13 @@
 
 struct MarkMarkPos
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -1507,20 +1507,20 @@
     Extension		= 9
   };
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, lookup_type);
     switch (lookup_type) {
-    case Single:		return_trace (u.single.dispatch (c));
-    case Pair:			return_trace (u.pair.dispatch (c));
-    case Cursive:		return_trace (u.cursive.dispatch (c));
-    case MarkBase:		return_trace (u.markBase.dispatch (c));
-    case MarkLig:		return_trace (u.markLig.dispatch (c));
-    case MarkMark:		return_trace (u.markMark.dispatch (c));
-    case Context:		return_trace (u.context.dispatch (c));
-    case ChainContext:		return_trace (u.chainContext.dispatch (c));
-    case Extension:		return_trace (u.extension.dispatch (c));
+    case Single:		return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
+    case Pair:			return_trace (u.pair.dispatch (c, hb_forward<Ts> (ds)...));
+    case Cursive:		return_trace (u.cursive.dispatch (c, hb_forward<Ts> (ds)...));
+    case MarkBase:		return_trace (u.markBase.dispatch (c, hb_forward<Ts> (ds)...));
+    case MarkLig:		return_trace (u.markLig.dispatch (c, hb_forward<Ts> (ds)...));
+    case MarkMark:		return_trace (u.markMark.dispatch (c, hb_forward<Ts> (ds)...));
+    case Context:		return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
+    case ChainContext:		return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
+    case Extension:		return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
     default:			return_trace (c->default_return_value ());
     }
   }
@@ -1581,9 +1581,9 @@
   template <typename context_t>
   static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<SubTable> (c); }
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+  { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
 
   bool subset (hb_subset_context_t *c) const
   { return Lookup::subset<SubTable> (c); }
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 10c35e3..f532f9d 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -34,10 +34,12 @@
 
 namespace OT {
 
+typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
 
+template<typename Iterator>
 static inline void SingleSubst_serialize (hb_serialize_context_t *c,
-					  hb_sorted_array_t<const GlyphID> glyphs,
-					  hb_array_t<const GlyphID> substitutes);
+					  Iterator it);
+
 
 struct SingleSubstFormat1
 {
@@ -46,9 +48,10 @@
 
   void closure (hb_closure_context_t *c) const
   {
+    unsigned d = deltaGlyphID;
     + hb_iter (this+coverage)
     | hb_filter (*c->glyphs)
-    | hb_map ([&] (hb_codepoint_t g) -> hb_codepoint_t { return (g + deltaGlyphID) & 0xFFFFu; })
+    | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
     | hb_sink (c->output)
     ;
   }
@@ -56,9 +59,9 @@
   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-
+    unsigned d = deltaGlyphID;
     + hb_iter (this+coverage)
-    | hb_map ([&] (hb_codepoint_t g) -> hb_codepoint_t { return (g + deltaGlyphID) & 0xFFFFu; })
+    | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
     | hb_sink (c->output)
     ;
   }
@@ -83,8 +86,10 @@
     return_trace (true);
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c,
-		  hb_sorted_array_t<const GlyphID> glyphs,
+		  Iterator glyphs,
 		  unsigned delta)
   {
     TRACE_SERIALIZE (this);
@@ -97,23 +102,22 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
     const hb_map_t &glyph_map = *c->plan->glyph_map;
 
-    hb_sorted_vector_t<GlyphID> from;
-    hb_vector_t<GlyphID> to;
     hb_codepoint_t delta = deltaGlyphID;
 
+    auto it =
     + hb_iter (this+coverage)
     | hb_filter (glyphset)
-    | hb_map ([&] (hb_codepoint_t g) -> hb_pair_t<hb_codepoint_t, hb_codepoint_t>
-	      { return hb_pair<hb_codepoint_t, hb_codepoint_t> (glyph_map[g],
-								glyph_map[(g + delta) & 0xFFFF]); })
-    | hb_unzip (from, to);
+    | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
+				return hb_codepoint_pair_t (glyph_map[g],
+							    glyph_map[(g + delta) & 0xFFFF]); })
+    ;
 
-    c->serializer->propagate_error (from, to);
-    SingleSubst_serialize (c->serializer, from, to);
-    return_trace (from.length);
+    bool ret = bool (it);
+    SingleSubst_serialize (c->serializer, it);
+    return_trace (ret);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -174,11 +178,21 @@
     return_trace (true);
   }
 
+  template<typename Iterator,
+	   hb_requires (hb_is_sorted_source_of (Iterator,
+						hb_codepoint_pair_t))>
   bool serialize (hb_serialize_context_t *c,
-		  hb_sorted_array_t<const GlyphID> glyphs,
-		  hb_array_t<const GlyphID> substitutes)
+		  Iterator it)
   {
     TRACE_SERIALIZE (this);
+    auto substitutes =
+      + it
+      | hb_map (hb_second)
+      ;
+    auto glyphs =
+      + it
+      | hb_map_retains_sorting (hb_first)
+      ;
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
@@ -188,21 +202,19 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
     const hb_map_t &glyph_map = *c->plan->glyph_map;
 
-    hb_sorted_vector_t<GlyphID> from;
-    hb_vector_t<GlyphID> to;
-
+    auto it =
     + hb_zip (this+coverage, substitute)
     | hb_filter (glyphset, hb_first)
-    | hb_map ([&] (hb_pair_t<hb_codepoint_t, const GlyphID &> p) -> hb_pair_t<hb_codepoint_t, hb_codepoint_t>
-	      { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
-    | hb_unzip (from, to);
+    | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const GlyphID &> p) -> hb_codepoint_pair_t
+			      { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+    ;
 
-    c->serializer->propagate_error (from, to);
-    SingleSubst_serialize (c->serializer, from, to);
-    return_trace (from.length);
+    bool ret = bool (it);
+    SingleSubst_serialize (c->serializer, it);
+    return_trace (ret);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -225,40 +237,45 @@
 
 struct SingleSubst
 {
+
+  template<typename Iterator,
+	   hb_requires (hb_is_sorted_source_of (Iterator,
+						const hb_codepoint_pair_t))>
   bool serialize (hb_serialize_context_t *c,
-		  hb_sorted_array_t<const GlyphID> glyphs,
-		  hb_array_t<const GlyphID> substitutes)
+		  Iterator glyphs)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned format = 2;
     unsigned delta = 0;
-    if (glyphs.length)
+    if (glyphs.len ())
     {
       format = 1;
-      delta = (unsigned) (substitutes[0] - glyphs[0]) & 0xFFFF;
-      for (unsigned int i = 1; i < glyphs.length; i++)
-	if (delta != ((unsigned) (substitutes[i] - glyphs[i]) & 0xFFFF)) {
-	  format = 2;
-	  break;
-	}
+      auto get_delta = [=] (hb_codepoint_pair_t _) {
+			 return (unsigned) (_.second - _.first) & 0xFFFF;
+		       };
+      delta = get_delta (*glyphs);
+      if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
     }
     u.format = format;
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, delta));
-    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes));
+    case 1: return_trace (u.format1.serialize (c,
+					       + glyphs
+					       | hb_map_retains_sorting (hb_first),
+					       delta));
+    case 2: return_trace (u.format2.serialize (c, glyphs));
     default:return_trace (false);
     }
   }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -271,11 +288,11 @@
   } u;
 };
 
+template<typename Iterator>
 static inline void
 SingleSubst_serialize (hb_serialize_context_t *c,
-		       hb_sorted_array_t<const GlyphID> glyphs,
-		       hb_array_t<const GlyphID> substitutes)
-{ c->start_embed<SingleSubst> ()->serialize (c, glyphs, substitutes); }
+		       Iterator it)
+{ c->start_embed<SingleSubst> ()->serialize (c, it); }
 
 struct Sequence
 {
@@ -321,8 +338,10 @@
     return_trace (true);
   }
 
+  template <typename Iterator,
+	    hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c,
-		  hb_array_t<const GlyphID> subst)
+		  Iterator subst)
   {
     TRACE_SERIALIZE (this);
     return_trace (substitute.serialize (c, subst));
@@ -351,7 +370,8 @@
     + hb_zip (this+coverage, sequence)
     | hb_filter (*c->glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<Sequence> &_) { (this+_).closure (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const Sequence &_) { _.closure (c); })
     ;
   }
 
@@ -360,7 +380,8 @@
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     + hb_zip (this+coverage, sequence)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<Sequence> &_) { (this+_).collect_glyphs (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
     ;
   }
 
@@ -440,13 +461,13 @@
     }
   }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -484,7 +505,7 @@
     unsigned int shift = hb_ctz (lookup_mask);
     unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
 
-    /* If alt_index is MAX, randomize feature if it is the rand feature. */
+    /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
     if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
       alt_index = c->random_number () % count + 1;
 
@@ -495,8 +516,10 @@
     return_trace (true);
   }
 
+  template <typename Iterator,
+	    hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c,
-		  hb_array_t<const GlyphID> alts)
+		  Iterator alts)
   {
     TRACE_SERIALIZE (this);
     return_trace (alternates.serialize (c, alts));
@@ -525,7 +548,8 @@
   {
     + hb_zip (this+coverage, alternateSet)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<AlternateSet> &_) { (this+_).closure (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
     ;
   }
 
@@ -534,7 +558,8 @@
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     + hb_zip (this+coverage, alternateSet)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<AlternateSet> &_) { (this+_).collect_glyphs (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
     ;
   }
 
@@ -614,13 +639,13 @@
     }
   }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -640,7 +665,7 @@
     unsigned int count = component.lenP1;
     for (unsigned int i = 1; i < count; i++)
       if (!glyphs->has (component[i]))
-        return false;
+	return false;
     return true;
   }
 
@@ -707,9 +732,11 @@
     return_trace (true);
   }
 
+  template <typename Iterator,
+	    hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
   bool serialize (hb_serialize_context_t *c,
 		  GlyphID ligature,
-		  hb_array_t<const GlyphID> components /* Starting from second */)
+		  Iterator components /* Starting from second */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
@@ -741,7 +768,8 @@
   {
     return
     + hb_iter (ligature)
-    | hb_map ([&] (const OffsetTo<Ligature> &_) -> bool { return (this+_).intersects (glyphs); })
+    | hb_map (hb_add (this))
+    | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
     | hb_any
     ;
   }
@@ -749,14 +777,16 @@
   void closure (hb_closure_context_t *c) const
   {
     + hb_iter (ligature)
-    | hb_apply ([&] (const OffsetTo<Ligature> &_) { (this+_).closure (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const Ligature &_) { _.closure (c); })
     ;
   }
 
   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     + hb_iter (ligature)
-    | hb_apply ([&] (const OffsetTo<Ligature> &_) { (this+_).collect_glyphs (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
     ;
   }
 
@@ -764,7 +794,8 @@
   {
     return
     + hb_iter (ligature)
-    | hb_map ([&] (const OffsetTo<Ligature> &_) -> bool { return (this+_).would_apply (c); })
+    | hb_map (hb_add (this))
+    | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
     | hb_any
     ;
   }
@@ -792,7 +823,7 @@
     if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
     for (unsigned int i = 0; i < ligatures.length; i++)
     {
-      unsigned int component_count = MAX<int> (component_count_list[i] - 1, 0);
+      unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
       if (unlikely (!ligature[i].serialize (c, this)
 				.serialize (c,
 					    ligatures[i],
@@ -825,7 +856,7 @@
     + hb_zip (this+coverage, ligatureSet)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_map ([&] (const OffsetTo<LigatureSet> &_) -> bool
+    | hb_map ([this, glyphs] (const OffsetTo<LigatureSet> &_)
 	      { return (this+_).intersects (glyphs); })
     | hb_any
     ;
@@ -836,7 +867,8 @@
     + hb_zip (this+coverage, ligatureSet)
     | hb_filter (*c->glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<LigatureSet> &_) { (this+_).closure (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
     ;
   }
 
@@ -846,7 +878,8 @@
 
     + hb_zip (this+coverage, ligatureSet)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<LigatureSet> &_) { (this+_).collect_glyphs (c); })
+    | hb_map (hb_add (this))
+    | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
     ;
   }
 
@@ -945,13 +978,13 @@
     }
   }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -983,19 +1016,19 @@
     if (!(this+coverage).intersects (glyphs))
       return false;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
 
     unsigned int count;
 
     count = backtrack.len;
     for (unsigned int i = 0; i < count; i++)
       if (!(this+backtrack[i]).intersects (glyphs))
-        return false;
+	return false;
 
     count = lookahead.len;
     for (unsigned int i = 0; i < count; i++)
       if (!(this+lookahead[i]).intersects (glyphs))
-        return false;
+	return false;
 
     return true;
   }
@@ -1004,8 +1037,8 @@
   {
     if (!intersects (c->glyphs)) return;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
 
     + hb_zip (this+coverage, substitute)
     | hb_filter (*c->glyphs, hb_first)
@@ -1024,12 +1057,12 @@
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(this+backtrack[i]).add_coverage (c->before))) return;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
     count = lookahead.len;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(this+lookahead[i]).add_coverage (c->after))) return;
 
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
     count = substitute.len;
     c->output->add_array (substitute.arrayZ, substitute.len);
   }
@@ -1048,15 +1081,15 @@
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
 
   unsigned int start_index = 0, end_index = 0;
     if (match_backtrack (c,
 			 backtrack.len, (HBUINT16 *) backtrack.arrayZ,
 			 match_coverage, this,
 			 &start_index) &&
-        match_lookahead (c,
+	match_lookahead (c,
 			 lookahead.len, (HBUINT16 *) lookahead.arrayZ,
 			 match_coverage, this,
 			 1, &end_index))
@@ -1084,10 +1117,10 @@
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
       return_trace (false);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
     if (!lookahead.sanitize (c, this))
       return_trace (false);
-    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
     return_trace (substitute.sanitize (c));
   }
 
@@ -1113,13 +1146,13 @@
 
 struct ReverseChainSingleSubst
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -1153,19 +1186,19 @@
     ReverseChainSingle	= 8
   };
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, lookup_type);
     switch (lookup_type) {
-    case Single:		return_trace (u.single.dispatch (c));
-    case Multiple:		return_trace (u.multiple.dispatch (c));
-    case Alternate:		return_trace (u.alternate.dispatch (c));
-    case Ligature:		return_trace (u.ligature.dispatch (c));
-    case Context:		return_trace (u.context.dispatch (c));
-    case ChainContext:		return_trace (u.chainContext.dispatch (c));
-    case Extension:		return_trace (u.extension.dispatch (c));
-    case ReverseChainSingle:	return_trace (u.reverseChainContextSingle.dispatch (c));
+    case Single:		return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
+    case Multiple:		return_trace (u.multiple.dispatch (c, hb_forward<Ts> (ds)...));
+    case Alternate:		return_trace (u.alternate.dispatch (c, hb_forward<Ts> (ds)...));
+    case Ligature:		return_trace (u.ligature.dispatch (c, hb_forward<Ts> (ds)...));
+    case Context:		return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
+    case ChainContext:		return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
+    case Extension:		return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
+    case ReverseChainSingle:	return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward<Ts> (ds)...));
     default:			return_trace (c->default_return_value ());
     }
   }
@@ -1254,17 +1287,18 @@
   HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
   SubTable& serialize_subtable (hb_serialize_context_t *c,
-				       unsigned int i)
+				unsigned int i)
   { return get_subtables<SubTable> ()[i].serialize (c, this); }
 
   bool serialize_single (hb_serialize_context_t *c,
 			 uint32_t lookup_props,
-		         hb_sorted_array_t<const GlyphID> glyphs,
-		         hb_array_t<const GlyphID> substitutes)
+			 hb_sorted_array_t<const GlyphID> glyphs,
+			 hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes));
+    return_trace (serialize_subtable (c, 0).u.single.
+		  serialize (c, hb_zip (glyphs, substitutes)));
   }
 
   bool serialize_multiple (hb_serialize_context_t *c,
@@ -1275,10 +1309,11 @@
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
-								  glyphs,
-								  substitute_len_list,
-								  substitute_glyphs_list));
+    return_trace (serialize_subtable (c, 0).u.multiple.
+		  serialize (c,
+			     glyphs,
+			     substitute_len_list,
+			     substitute_glyphs_list));
   }
 
   bool serialize_alternate (hb_serialize_context_t *c,
@@ -1289,10 +1324,11 @@
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
-								   glyphs,
-								   alternate_len_list,
-								   alternate_glyphs_list));
+    return_trace (serialize_subtable (c, 0).u.alternate.
+		  serialize (c,
+			     glyphs,
+			     alternate_len_list,
+			     alternate_glyphs_list));
   }
 
   bool serialize_ligature (hb_serialize_context_t *c,
@@ -1305,12 +1341,13 @@
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
-								  first_glyphs,
-								  ligature_per_first_glyph_count_list,
-								  ligatures_list,
-								  component_count_list,
-								  component_list));
+    return_trace (serialize_subtable (c, 0).u.ligature.
+		  serialize (c,
+			     first_glyphs,
+			     ligature_per_first_glyph_count_list,
+			     ligatures_list,
+			     component_count_list,
+			     component_list));
   }
 
   template <typename context_t>
@@ -1319,7 +1356,7 @@
   HB_INTERNAL static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
   {
     if (!c->should_visit_lookup (lookup_index))
-      return hb_void_t ();
+      return hb_empty_t ();
 
     hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
 
@@ -1331,9 +1368,9 @@
     return ret;
   }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<SubTable> (c); }
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+  { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
 
   bool subset (hb_subset_context_t *c) const
   { return Lookup::subset<SubTable> (c); }
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 840c142..4bc3d7e 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -59,13 +59,13 @@
 };
 
 struct hb_closure_context_t :
-       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, 0>
+       hb_dispatch_context_t<hb_closure_context_t, hb_empty_t, 0>
 {
   const char *get_name () { return "CLOSURE"; }
   typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
   template <typename T>
-  return_t dispatch (const T &obj) { obj.closure (this); return hb_void_t (); }
-  static return_t default_return_value () { return hb_void_t (); }
+  return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); }
+  static return_t default_return_value () { return hb_empty_t (); }
   void recurse (unsigned int lookup_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
@@ -151,13 +151,13 @@
 
 
 struct hb_collect_glyphs_context_t :
-       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, 0>
+       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_empty_t, 0>
 {
   const char *get_name () { return "COLLECT_GLYPHS"; }
   typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
   template <typename T>
-  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return hb_void_t (); }
-  static return_t default_return_value () { return hb_void_t (); }
+  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return hb_empty_t (); }
+  static return_t default_return_value () { return hb_empty_t (); }
   void recurse (unsigned int lookup_index)
   {
     if (unlikely (nesting_level_left == 0 || !recurse_func))
@@ -610,7 +610,7 @@
 
 
 struct hb_get_subtables_context_t :
-       hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
+       hb_dispatch_context_t<hb_get_subtables_context_t, hb_empty_t, HB_DEBUG_APPLY>
 {
   template <typename Type>
   HB_INTERNAL static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
@@ -652,9 +652,9 @@
   {
     hb_applicable_t *entry = array.push();
     entry->init (obj, apply_to<T>);
-    return hb_void_t ();
+    return hb_empty_t ();
   }
-  static return_t default_return_value () { return hb_void_t (); }
+  static return_t default_return_value () { return hb_empty_t (); }
 
   hb_get_subtables_context_t (array_t &array_) :
 			      array (array_),
@@ -708,7 +708,7 @@
 {
   return
   + hb_iter (values, count)
-  | hb_map ([&] (const HBUINT16 &_) -> bool { return intersects_func (glyphs, _, intersects_data); })
+  | hb_map ([&] (const HBUINT16 &_) { return intersects_func (glyphs, _, intersects_data); })
   | hb_any
   ;
 }
@@ -849,7 +849,7 @@
 	if (ligbase == LIGBASE_NOT_CHECKED)
 	{
 	  bool found = false;
-	  const hb_glyph_info_t *out = buffer->out_info;
+	  const auto *out = buffer->out_info;
 	  unsigned int j = buffer->out_len;
 	  while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
 	  {
@@ -973,7 +973,7 @@
 	if (this_comp == 0)
 	  this_comp = last_num_components;
 	unsigned int new_lig_comp = components_so_far - last_num_components +
-				    MIN (this_comp, last_num_components);
+				    hb_min (this_comp, last_num_components);
 	  _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
       }
       buffer->next_glyph ();
@@ -995,7 +995,7 @@
 	if (!this_comp)
 	  break;
 	unsigned int new_lig_comp = components_so_far - last_num_components +
-				    MIN (this_comp, last_num_components);
+				    hb_min (this_comp, last_num_components);
 	_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
       } else
 	break;
@@ -1173,7 +1173,7 @@
     else
     {
       /* NOTE: delta is negative. */
-      delta = MAX (delta, (int) next - (int) count);
+      delta = hb_max (delta, (int) next - (int) count);
       next -= delta;
     }
 
@@ -1299,7 +1299,7 @@
 
   void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
   {
-    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
 						       (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
     context_closure_lookup (c,
 			    inputCount, inputZ.arrayZ,
@@ -1310,7 +1310,7 @@
   void collect_glyphs (hb_collect_glyphs_context_t *c,
 		       ContextCollectGlyphsLookupContext &lookup_context) const
   {
-    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
     context_collect_glyphs_lookup (c,
 				   inputCount, inputZ.arrayZ,
@@ -1321,7 +1321,7 @@
   bool would_apply (hb_would_apply_context_t *c,
 		    ContextApplyLookupContext &lookup_context) const
   {
-    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
     return context_would_apply_lookup (c,
 				       inputCount, inputZ.arrayZ,
@@ -1333,7 +1333,7 @@
 	      ContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
-    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
     return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
   }
@@ -1371,7 +1371,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_map ([&] (const OffsetTo<Rule> &_) -> bool { return (this+_).intersects (glyphs, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const Rule &_) { return _.intersects (glyphs, lookup_context); })
     | hb_any
     ;
   }
@@ -1381,7 +1382,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_apply ([&] (const OffsetTo<Rule> &_) { (this+_).closure (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const Rule &_) { _.closure (c, lookup_context); })
     ;
   }
 
@@ -1390,7 +1392,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_apply ([&] (const OffsetTo<Rule> &_) { (this+_).collect_glyphs (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const Rule &_) { _.collect_glyphs (c, lookup_context); })
     ;
   }
 
@@ -1399,7 +1402,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_map ([&] (const OffsetTo<Rule> &_) -> bool { return (this+_).would_apply (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const Rule &_) { return _.would_apply (c, lookup_context); })
     | hb_any
     ;
   }
@@ -1410,7 +1414,8 @@
     TRACE_APPLY (this);
     return_trace (
     + hb_iter (rule)
-    | hb_map ([&] (const OffsetTo<Rule> &_) -> bool { return (this+_).apply (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
     | hb_any
     )
     ;
@@ -1444,7 +1449,8 @@
     + hb_zip (this+coverage, ruleSet)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_map ([&] (const OffsetTo<RuleSet> &_) -> bool { return (this+_).intersects (glyphs, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const RuleSet &_) { return _.intersects (glyphs, lookup_context); })
     | hb_any
     ;
   }
@@ -1459,7 +1465,8 @@
     + hb_zip (this+coverage, ruleSet)
     | hb_filter (*c->glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<RuleSet> &_) { (this+_).closure (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); })
     ;
   }
 
@@ -1473,7 +1480,8 @@
     };
 
     + hb_iter (ruleSet)
-    | hb_apply ([&] (const OffsetTo<RuleSet> &_) { (this+_).collect_glyphs (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
     ;
   }
 
@@ -1546,7 +1554,7 @@
 
     return
     + hb_enumerate (ruleSet)
-    | hb_map ([&] (const hb_pair_t<unsigned, const OffsetTo<RuleSet> &> p) -> bool
+    | hb_map ([&] (const hb_pair_t<unsigned, const OffsetTo<RuleSet> &> p)
 	      { return class_def.intersects_class (glyphs, p.first) &&
 		       (this+p.second).intersects (glyphs, lookup_context); })
     | hb_any
@@ -1567,11 +1575,12 @@
 
     return
     + hb_enumerate (ruleSet)
-    | hb_filter ([&] (unsigned _) -> bool
+    | hb_filter ([&] (unsigned _)
 		 { return class_def.intersects_class (c->glyphs, _); },
 		 hb_first)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<RuleSet> &_) { (this+_).closure (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); })
     ;
   }
 
@@ -1586,7 +1595,8 @@
     };
 
     + hb_iter (ruleSet)
-    | hb_apply ([&] (const OffsetTo<RuleSet> &_) { (this+_).collect_glyphs (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
     ;
   }
 
@@ -1751,7 +1761,7 @@
   HBUINT16	glyphCount;		/* Number of glyphs in the input glyph
 					 * sequence */
   HBUINT16	lookupCount;		/* Number of LookupRecords */
-  UnsizedArrayOf<OffsetTo<Coverage> >
+  UnsizedArrayOf<OffsetTo<Coverage>>
 		coverageZ;		/* Array of offsets to Coverage
 					 * table in glyph sequence order */
 /*UnsizedArrayOf<LookupRecord>
@@ -1763,15 +1773,15 @@
 
 struct Context
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
+    case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -1923,8 +1933,8 @@
 {
   bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
   {
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
     return chain_context_intersects (glyphs,
 				     backtrack.len, backtrack.arrayZ,
 				     input.lenP1, input.arrayZ,
@@ -1935,9 +1945,9 @@
   void closure (hb_closure_context_t *c,
 		ChainContextClosureLookupContext &lookup_context) const
   {
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     chain_context_closure_lookup (c,
 				  backtrack.len, backtrack.arrayZ,
 				  input.lenP1, input.arrayZ,
@@ -1949,9 +1959,9 @@
   void collect_glyphs (hb_collect_glyphs_context_t *c,
 		       ChainContextCollectGlyphsLookupContext &lookup_context) const
   {
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     chain_context_collect_glyphs_lookup (c,
 					 backtrack.len, backtrack.arrayZ,
 					 input.lenP1, input.arrayZ,
@@ -1963,9 +1973,9 @@
   bool would_apply (hb_would_apply_context_t *c,
 		    ChainContextApplyLookupContext &lookup_context) const
   {
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     return chain_context_would_apply_lookup (c,
 					     backtrack.len, backtrack.arrayZ,
 					     input.lenP1, input.arrayZ,
@@ -1976,9 +1986,9 @@
   bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   {
     TRACE_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     return_trace (chain_context_apply_lookup (c,
 					      backtrack.len, backtrack.arrayZ,
 					      input.lenP1, input.arrayZ,
@@ -1990,11 +2000,11 @@
   {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c)) return_trace (false);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
     if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
     if (!lookahead.sanitize (c)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     return_trace (lookup.sanitize (c));
   }
 
@@ -2022,7 +2032,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_map ([&] (const OffsetTo<ChainRule> &_) -> bool { return (this+_).intersects (glyphs, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const ChainRule &_) { return _.intersects (glyphs, lookup_context); })
     | hb_any
     ;
   }
@@ -2030,7 +2041,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_apply ([&] (const OffsetTo<ChainRule> &_) { (this+_).closure (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const ChainRule &_) { _.closure (c, lookup_context); })
     ;
   }
 
@@ -2038,7 +2050,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_apply ([&] (const OffsetTo<ChainRule> &_) { (this+_).collect_glyphs (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const ChainRule &_) { _.collect_glyphs (c, lookup_context); })
     ;
   }
 
@@ -2046,7 +2059,8 @@
   {
     return
     + hb_iter (rule)
-    | hb_map ([&] (const OffsetTo<ChainRule> &_) -> bool { return (this+_).would_apply (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const ChainRule &_) { return _.would_apply (c, lookup_context); })
     | hb_any
     ;
   }
@@ -2056,7 +2070,8 @@
     TRACE_APPLY (this);
     return_trace (
     + hb_iter (rule)
-    | hb_map ([&] (const OffsetTo<ChainRule> &_) -> bool { return (this+_).apply (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
     | hb_any
     )
     ;
@@ -2089,7 +2104,8 @@
     + hb_zip (this+coverage, ruleSet)
     | hb_filter (*glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_map ([&] (const OffsetTo<ChainRuleSet> &_) -> bool { return (this+_).intersects (glyphs, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_map ([&] (const ChainRuleSet &_) { return _.intersects (glyphs, lookup_context); })
     | hb_any
     ;
   }
@@ -2104,7 +2120,8 @@
     + hb_zip (this+coverage, ruleSet)
     | hb_filter (*c->glyphs, hb_first)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<ChainRuleSet> &_) { (this+_).closure (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); })
     ;
   }
 
@@ -2118,7 +2135,8 @@
     };
 
     + hb_iter (ruleSet)
-    | hb_apply ([&] (const OffsetTo<ChainRuleSet> &_) { (this+_).collect_glyphs (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
     ;
   }
 
@@ -2193,9 +2211,9 @@
 
     return
     + hb_enumerate (ruleSet)
-    | hb_map ([&] (const hb_pair_t<unsigned, const OffsetTo<ChainRuleSet> &> p) -> bool
-		   { return input_class_def.intersects_class (glyphs, p.first) &&
-			    (this+p.second).intersects (glyphs, lookup_context); })
+    | hb_map ([&] (const hb_pair_t<unsigned, const OffsetTo<ChainRuleSet> &> p)
+	      { return input_class_def.intersects_class (glyphs, p.first) &&
+		       (this+p.second).intersects (glyphs, lookup_context); })
     | hb_any
     ;
   }
@@ -2217,11 +2235,12 @@
 
     return
     + hb_enumerate (ruleSet)
-    | hb_filter ([&] (unsigned _) -> bool
+    | hb_filter ([&] (unsigned _)
 		 { return input_class_def.intersects_class (c->glyphs, _); },
 		 hb_first)
     | hb_map (hb_second)
-    | hb_apply ([&] (const OffsetTo<ChainRuleSet> &_) { (this+_).closure (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); })
     ;
   }
 
@@ -2241,7 +2260,8 @@
     };
 
     + hb_iter (ruleSet)
-    | hb_apply ([&] (const OffsetTo<ChainRuleSet> &_) { (this+_).collect_glyphs (c, lookup_context); })
+    | hb_map (hb_add (this))
+    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
     ;
   }
 
@@ -2330,12 +2350,12 @@
 {
   bool intersects (const hb_set_t *glyphs) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
 
     if (!(this+input[0]).intersects (glyphs))
       return false;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
     struct ChainContextClosureLookupContext lookup_context = {
       {intersects_coverage},
       {this, this, this}
@@ -2349,13 +2369,13 @@
 
   void closure (hb_closure_context_t *c) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
 
     if (!(this+input[0]).intersects (c->glyphs))
       return;
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     struct ChainContextClosureLookupContext lookup_context = {
       {intersects_coverage},
       {this, this, this}
@@ -2370,12 +2390,12 @@
 
   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
 
     (this+input[0]).add_coverage (c->input);
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     struct ChainContextCollectGlyphsLookupContext lookup_context = {
       {collect_coverage},
       {this, this, this}
@@ -2390,9 +2410,9 @@
 
   bool would_apply (hb_would_apply_context_t *c) const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
@@ -2406,20 +2426,20 @@
 
   const Coverage &get_coverage () const
   {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
     return this+input[0];
   }
 
   bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
 
     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     struct ChainContextApplyLookupContext lookup_context = {
       {match_coverage},
       {this, this, this}
@@ -2442,12 +2462,12 @@
   {
     TRACE_SANITIZE (this);
     if (!backtrack.sanitize (c, this)) return_trace (false);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
     if (!input.sanitize (c, this)) return_trace (false);
     if (!input.len) return_trace (false); /* To be consistent with Context. */
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
     if (!lookahead.sanitize (c, this)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
     return_trace (lookup.sanitize (c));
   }
 
@@ -2474,15 +2494,15 @@
 
 struct ChainContext
 {
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
+    case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -2504,18 +2524,14 @@
 
   template <typename X>
   const X& get_subtable () const
-  {
-    unsigned int offset = extensionOffset;
-    if (unlikely (!offset)) return Null(typename T::SubTable);
-    return StructAtOffset<typename T::SubTable> (this, offset);
-  }
+  { return this + CastR<LOffsetTo<typename T::SubTable>> (extensionOffset); }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, format);
     if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
-    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type ()));
+    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), hb_forward<Ts> (ds)...));
   }
 
   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
@@ -2523,7 +2539,6 @@
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-		  extensionOffset != 0 &&
 		  extensionLookupType != T::SubTable::Extension);
   }
 
@@ -2532,7 +2547,7 @@
   HBUINT16	extensionLookupType;	/* Lookup type of subtable referenced
 					 * by ExtensionOffset (i.e. the
 					 * extension subtable). */
-  HBUINT32	extensionOffset;	/* Offset to the extension subtable,
+  Offset32	extensionOffset;	/* Offset to the extension subtable,
 					 * of lookup type subtable. */
   public:
   DEFINE_SIZE_STATIC (8);
@@ -2557,13 +2572,13 @@
     }
   }
 
-  template <typename context_t>
-  typename context_t::return_t dispatch (context_t *c) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
     switch (u.format) {
-    case 1: return_trace (u.format1.dispatch (c));
+    case 1: return_trace (u.format1.dispatch (c, hb_forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -2666,21 +2681,22 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    struct GSUBGPOS *out = c->serializer->embed (*this);
+    auto *out = c->serializer->embed (*this);
     if (unlikely (!out)) return_trace (false);
 
-    out->scriptList.serialize_subset (c, this+scriptList, out);
-    out->featureList.serialize_subset (c, this+featureList, out);
+    out->scriptList.serialize_subset (c, scriptList, this, out);
+    out->featureList.serialize_subset (c, featureList, this, out);
 
     typedef OffsetListOf<TLookup> TLookupList;
     /* TODO Use intersects() to count how many subtables survive? */
-    CastR<OffsetTo<TLookupList> > (out->lookupList)
+    CastR<OffsetTo<TLookupList>> (out->lookupList)
       .serialize_subset (c,
-			 this+CastR<const OffsetTo<TLookupList> > (lookupList),
+			 CastR<OffsetTo<TLookupList>> (lookupList),
+			 this,
 			 out);
 
     if (version.to_int () >= 0x00010001u)
-     out->featureVars.serialize_subset (c, this+featureVars, out);
+     out->featureVars.serialize_copy (c->serializer, featureVars, this, out);
 
     return_trace (true);
   }
@@ -2700,7 +2716,7 @@
 		  likely (version.major == 1) &&
 		  scriptList.sanitize (c, this) &&
 		  featureList.sanitize (c, this) &&
-		  CastR<OffsetTo<TLookupList> > (lookupList).sanitize (c, this) &&
+		  CastR<OffsetTo<TLookupList>> (lookupList).sanitize (c, this) &&
 		  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
   }
 
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 1e2d159..1945df4 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -138,7 +138,7 @@
 OT::GDEF::is_blacklisted (hb_blob_t *blob,
 			  hb_face_t *face) const
 {
-#if defined(HB_NO_OT_LAYOUT_BLACKLIST)
+#ifdef HB_NO_OT_LAYOUT_BLACKLIST
   return false;
 #endif
   /* The ugly business of blacklisting individual fonts' tables happen here!
@@ -158,84 +158,82 @@
    *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
    *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
    */
-#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z))
-  switch ENCODE(blob->length,
-		face->table.GSUB->table.get_length (),
-		face->table.GPOS->table.get_length ())
+  switch HB_CODEPOINT_ENCODE3(blob->length,
+			      face->table.GSUB->table.get_length (),
+			      face->table.GPOS->table.get_length ())
   {
     /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
-    case ENCODE (442, 2874, 42038):
+    case HB_CODEPOINT_ENCODE3 (442, 2874, 42038):
     /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
-    case ENCODE (430, 2874, 40662):
+    case HB_CODEPOINT_ENCODE3 (430, 2874, 40662):
     /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
-    case ENCODE (442, 2874, 39116):
+    case HB_CODEPOINT_ENCODE3 (442, 2874, 39116):
     /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
-    case ENCODE (430, 2874, 39374):
+    case HB_CODEPOINT_ENCODE3 (430, 2874, 39374):
     /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
-    case ENCODE (490, 3046, 41638):
+    case HB_CODEPOINT_ENCODE3 (490, 3046, 41638):
     /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
-    case ENCODE (478, 3046, 41902):
+    case HB_CODEPOINT_ENCODE3 (478, 3046, 41902):
     /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
-    case ENCODE (898, 12554, 46470):
+    case HB_CODEPOINT_ENCODE3 (898, 12554, 46470):
     /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
-    case ENCODE (910, 12566, 47732):
+    case HB_CODEPOINT_ENCODE3 (910, 12566, 47732):
     /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
-    case ENCODE (928, 23298, 59332):
+    case HB_CODEPOINT_ENCODE3 (928, 23298, 59332):
     /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
-    case ENCODE (940, 23310, 60732):
+    case HB_CODEPOINT_ENCODE3 (940, 23310, 60732):
     /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-    case ENCODE (964, 23836, 60072):
+    case HB_CODEPOINT_ENCODE3 (964, 23836, 60072):
     /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-    case ENCODE (976, 23832, 61456):
+    case HB_CODEPOINT_ENCODE3 (976, 23832, 61456):
     /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
-    case ENCODE (994, 24474, 60336):
+    case HB_CODEPOINT_ENCODE3 (994, 24474, 60336):
     /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
-    case ENCODE (1006, 24470, 61740):
+    case HB_CODEPOINT_ENCODE3 (1006, 24470, 61740):
     /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-    case ENCODE (1006, 24576, 61346):
+    case HB_CODEPOINT_ENCODE3 (1006, 24576, 61346):
     /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-    case ENCODE (1018, 24572, 62828):
+    case HB_CODEPOINT_ENCODE3 (1018, 24572, 62828):
     /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
-    case ENCODE (1006, 24576, 61352):
+    case HB_CODEPOINT_ENCODE3 (1006, 24576, 61352):
     /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
-    case ENCODE (1018, 24572, 62834):
+    case HB_CODEPOINT_ENCODE3 (1018, 24572, 62834):
     /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
-    case ENCODE (832, 7324, 47162):
+    case HB_CODEPOINT_ENCODE3 (832, 7324, 47162):
     /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
-    case ENCODE (844, 7302, 45474):
+    case HB_CODEPOINT_ENCODE3 (844, 7302, 45474):
     /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
-    case ENCODE (180, 13054, 7254):
+    case HB_CODEPOINT_ENCODE3 (180, 13054, 7254):
     /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
-    case ENCODE (192, 12638, 7254):
+    case HB_CODEPOINT_ENCODE3 (192, 12638, 7254):
     /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
-    case ENCODE (192, 12690, 7254):
+    case HB_CODEPOINT_ENCODE3 (192, 12690, 7254):
     /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
     /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
-    case ENCODE (188, 248, 3852):
+    case HB_CODEPOINT_ENCODE3 (188, 248, 3852):
     /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
     /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
-    case ENCODE (188, 264, 3426):
+    case HB_CODEPOINT_ENCODE3 (188, 264, 3426):
     /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
-    case ENCODE (1058, 47032, 11818):
+    case HB_CODEPOINT_ENCODE3 (1058, 47032, 11818):
     /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
-    case ENCODE (1046, 47030, 12600):
+    case HB_CODEPOINT_ENCODE3 (1046, 47030, 12600):
     /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
-    case ENCODE (1058, 71796, 16770):
+    case HB_CODEPOINT_ENCODE3 (1058, 71796, 16770):
     /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
-    case ENCODE (1046, 71790, 17862):
+    case HB_CODEPOINT_ENCODE3 (1046, 71790, 17862):
     /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
-    case ENCODE (1046, 71788, 17112):
+    case HB_CODEPOINT_ENCODE3 (1046, 71788, 17112):
     /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
-    case ENCODE (1058, 71794, 17514):
+    case HB_CODEPOINT_ENCODE3 (1058, 71794, 17514):
     /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
-    case ENCODE (1330, 109904, 57938):
+    case HB_CODEPOINT_ENCODE3 (1330, 109904, 57938):
     /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
-    case ENCODE (1330, 109904, 58972):
+    case HB_CODEPOINT_ENCODE3 (1330, 109904, 58972):
     /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
      *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
-    case ENCODE (1004, 59092, 14836):
+    case HB_CODEPOINT_ENCODE3 (1004, 59092, 14836):
       return true;
-#undef ENCODE
   }
   return false;
 }
@@ -335,6 +333,12 @@
 				unsigned int   *point_count /* IN/OUT */,
 				unsigned int   *point_array /* OUT */)
 {
+#ifdef HB_NO_LAYOUT_UNUSED
+  if (point_count)
+    *point_count = 0;
+  return 0;
+#endif
+
   return face->table.GDEF->table->get_attach_points (glyph,
 						     start_offset,
 						     point_count,
@@ -364,6 +368,12 @@
 				  unsigned int   *caret_count /* IN/OUT */,
 				  hb_position_t  *caret_array /* OUT */)
 {
+#ifdef HB_NO_LAYOUT_UNUSED
+  if (caret_count)
+    *caret_count = 0;
+  return 0;
+#endif
+
   unsigned int result_caret_count = 0;
   unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
   if (result)
@@ -384,7 +394,7 @@
 OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
 			  hb_face_t *face) const
 {
-#if defined(HB_NO_OT_LAYOUT_BLACKLIST)
+#ifdef HB_NO_OT_LAYOUT_BLACKLIST
   return false;
 #endif
   /* Mac OS X prefers morx over GSUB.  It also ships with various Indic fonts,
@@ -412,7 +422,7 @@
 OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
 			  hb_face_t *face HB_UNUSED) const
 {
-#if defined(HB_NO_OT_LAYOUT_BLACKLIST)
+#ifdef HB_NO_OT_LAYOUT_BLACKLIST
   return false;
 #endif
   return false;
@@ -500,6 +510,7 @@
   return false;
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_ot_layout_table_choose_script:
  * @face: #hb_face_t to work upon
@@ -521,6 +532,7 @@
   for (t = script_tags; *t; t++);
   return hb_ot_layout_table_select_script (face, table_tag, t - script_tags, script_tags, script_index, chosen_script);
 }
+#endif
 
 /**
  * hb_ot_layout_table_select_script:
@@ -672,6 +684,7 @@
 }
 
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_ot_layout_script_find_language:
  * @face: #hb_face_t to work upon
@@ -685,6 +698,8 @@
  *
  * Return value: true if the language tag is found, false otherwise
  *
+ * Since: ??
+ * Deprecated: ??
  **/
 hb_bool_t
 hb_ot_layout_script_find_language (hb_face_t    *face,
@@ -700,6 +715,7 @@
 					      &language_tag,
 					      language_index);
 }
+#endif
 
 
 /**
@@ -716,7 +732,6 @@
  *
  * Return value: true if the language tag is found, false otherwise
  *
- *
  * Since: 2.0.0
  **/
 hb_bool_t
@@ -1735,7 +1750,7 @@
   unsigned int len = 0;
   if (char_count && characters && start_offset < cv_params.characters.len)
   {
-    len = MIN (cv_params.characters.len - start_offset, *char_count);
+    len = hb_min (cv_params.characters.len - start_offset, *char_count);
     for (unsigned int i = 0; i < len; ++i)
       characters[i] = cv_params.characters[start_offset + i];
   }
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 359ee1b..3b9a78e 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -94,7 +94,7 @@
 hb_ot_layout_has_glyph_classes (hb_face_t *face);
 
 /**
- * hb_ot_layout_get_glyph_class:
+ * hb_ot_layout_glyph_class_t:
  * @HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: Glyphs not matching the other classifications
  * @HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: Spacing, single characters, capable of accepting marks
  * @HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: Glyphs that represent ligation of multiple characters
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 846414c..92d70bb 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -188,12 +188,12 @@
 	  feature_infos[j].default_value = feature_infos[i].default_value;
 	} else {
 	  feature_infos[j].flags &= ~F_GLOBAL;
-	  feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value);
+	  feature_infos[j].max_value = hb_max (feature_infos[j].max_value, feature_infos[i].max_value);
 	  /* Inherit default_value from j */
 	}
 	feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK);
-	feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]);
-	feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]);
+	feature_infos[j].stage[0] = hb_min (feature_infos[j].stage[0], feature_infos[i].stage[0]);
+	feature_infos[j].stage[1] = hb_min (feature_infos[j].stage[1], feature_infos[i].stage[1]);
       }
     feature_infos.shrink (j + 1);
   }
@@ -213,7 +213,7 @@
       bits_needed = 0;
     else
       /* Limit bits per feature. */
-      bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
+      bits_needed = hb_min (HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
 
     if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
       continue; /* Feature disabled, or not enough bits. */
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
index 62bf072..0b16e0b 100644
--- a/src/hb-ot-math-table.hh
+++ b/src/hb-ot-math-table.hh
@@ -462,7 +462,7 @@
     out.end_connector_length	= font->em_scale (endConnectorLength, scale);
     out.full_advance		= font->em_scale (fullAdvance, scale);
 
-    static_assert ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
+    static_assert ((unsigned int) HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER ==
 		   (unsigned int) PartFlags::Extender, "");
 
     out.flags = (hb_ot_math_glyph_part_flags_t)
@@ -664,7 +664,7 @@
   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
      the MathVariants table, for shapes growing in vertical/horizontal
      direction. */
-  UnsizedArrayOf<OffsetTo<MathGlyphConstruction> >
+  UnsizedArrayOf<OffsetTo<MathGlyphConstruction>>
  			glyphConstruction;
 
   public:
diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc
index bd31bf5..7f27923 100644
--- a/src/hb-ot-math.cc
+++ b/src/hb-ot-math.cc
@@ -37,6 +37,11 @@
  * @include: hb-ot.h
  *
  * Functions for fetching mathematics layout data from OpenType fonts.
+ *
+ * HarfBuzz itself does not implement a math layout solution. The
+ * functions and types provided can be used by client programs to access
+ * the font data necessary for typesetting OpenType Math layout.
+ *
  **/
 
 
@@ -48,31 +53,36 @@
  * hb_ot_math_has_data:
  * @face: #hb_face_t to test
  *
- * This function allows to verify the presence of an OpenType MATH table on the
- * face.
+ * Tests whether a face has a `MATH` table.
  *
- * Return value: true if face has a MATH table, false otherwise
+ * Return value: true if the table is found, false otherwise
  *
  * Since: 1.3.3
  **/
 hb_bool_t
 hb_ot_math_has_data (hb_face_t *face)
 {
+#ifdef HB_NO_MATH
+  return false;
+#endif
+
   return face->table.MATH->has_data ();
 }
 
 /**
  * hb_ot_math_get_constant:
- * @font: #hb_font_t from which to retrieve the value
+ * @font: #hb_font_t to work upon
  * @constant: #hb_ot_math_constant_t the constant to retrieve
  *
- * This function returns the requested math constants as a #hb_position_t.
- * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
- * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
- * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
- * actually an integer between 0 and 100 representing that percentage.
+ * Fetches the specified math constant. For most constants, the value returned
+ * is an #hb_position_t.
  *
- * Return value: the requested constant or 0
+ * However, if the requested constant is #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
+ * #HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
+ * #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, then the return value is
+ * an integer between 0 and 100 representing that percentage.
+ *
+ * Return value: the requested constant or zero
  *
  * Since: 1.3.3
  **/
@@ -80,15 +90,22 @@
 hb_ot_math_get_constant (hb_font_t *font,
 			 hb_ot_math_constant_t constant)
 {
+#ifdef HB_NO_MATH
+  return 0;
+#endif
+
   return font->face->table.MATH->get_constant(constant, font);
 }
 
 /**
  * hb_ot_math_get_glyph_italics_correction:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph index from which to retrieve the value
  *
- * Return value: the italics correction of the glyph or 0
+ * Fetches an italics-correction value (if one exists) for the specified
+ * glyph index.
+ *
+  * Return value: the italics correction of the glyph or zero
  *
  * Since: 1.3.3
  **/
@@ -96,15 +113,29 @@
 hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
 					 hb_codepoint_t glyph)
 {
+#ifdef HB_NO_MATH
+  return 0;
+#endif
+
   return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font);
 }
 
 /**
  * hb_ot_math_get_glyph_top_accent_attachment:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph index from which to retrieve the value
  *
- * Return value: the top accent attachment of the glyph or 0
+ * Fetches a top-accent-attachment value (if one exists) for the specified
+ * glyph index.
+ *
+ * For any glyph that does not have a top-accent-attachment value - that is,
+ * a glyph not covered by the `MathTopAccentAttachment` table (or, when
+ * @font has no `MathTopAccentAttachment` table or no `MATH` table, any
+ * glyph) - the function synthesizes a value, returning the position at
+ * one-half the glyph's advance width.
+ *
+ * Return value: the top accent attachment of the glyph or 0.5 * the advance
+ *               width of @glyph
  *
  * Since: 1.3.3
  **/
@@ -112,13 +143,19 @@
 hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
 					    hb_codepoint_t glyph)
 {
+#ifdef HB_NO_MATH
+  return 0;
+#endif
+
   return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font);
 }
 
 /**
  * hb_ot_math_is_glyph_extended_shape:
- * @face: a #hb_face_t to test
- * @glyph: a glyph index to test
+ * @face: #hb_face_t to work upon
+ * @glyph: The glyph index to test
+ *
+ * Tests whether the given glyph index is an extended shape in the face.
  *
  * Return value: true if the glyph is an extended shape, false otherwise
  *
@@ -128,23 +165,29 @@
 hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
 				    hb_codepoint_t glyph)
 {
+#ifdef HB_NO_MATH
+  return false;
+#endif
+
   return face->table.MATH->get_glyph_info().is_extended_shape (glyph);
 }
 
 /**
  * hb_ot_math_get_glyph_kerning:
- * @font: #hb_font_t from which to retrieve the value
- * @glyph: glyph index from which to retrieve the value
- * @kern: the #hb_ot_math_kern_t from which to retrieve the value
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph index from which to retrieve the value
+ * @kern: The #hb_ot_math_kern_t from which to retrieve the value
  * @correction_height: the correction height to use to determine the kerning.
  *
- * This function tries to retrieve the MathKern table for the specified font,
- * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
- * MathKern table to find one value that is greater or equal to specified
- * correction_height. If one is found the corresponding value from the list of
- * kerns is returned and otherwise the last kern value is returned.
+ * Fetches the math kerning (cut-ins) value for the specified font, glyph index, and
+ * @kern. 
  *
- * Return value: requested kerning or 0
+ * If the MathKern table is found, the function examines it to find a height
+ * value that is greater or equal to @correction_height. If such a height
+ * value is found, corresponding kerning value from the table is returned. If
+ * no such height value is found, the last kerning value is returned.
+ *
+ * Return value: requested kerning value or zero
  *
  * Since: 1.3.3
  **/
@@ -154,6 +197,10 @@
 			      hb_ot_math_kern_t kern,
 			      hb_position_t correction_height)
 {
+#ifdef HB_NO_MATH
+  return 0;
+#endif
+
   return font->face->table.MATH->get_glyph_info().get_kerning (glyph,
 							       kern,
 							       correction_height,
@@ -162,20 +209,24 @@
 
 /**
  * hb_ot_math_get_glyph_variants:
- * @font: #hb_font_t from which to retrieve the values
- * @glyph: index of the glyph to stretch
- * @direction: direction of the stretching
+ * @font: #hb_font_t to work upon
+ * @glyph: The index of the glyph to stretch
+ * @direction: The direction of the stretching (horizontal or vertical)
  * @start_offset: offset of the first variant to retrieve
- * @variants_count: maximum number of variants to retrieve after start_offset
- * (IN) and actual number of variants retrieved (OUT)
- * @variants: array of size at least @variants_count to store the result
+ * @variants_count: (inout): Input = the maximum number of variants to return;
+ *                           Output = the actual number of variants returned
+ * @variants: (out) (array length=variants_count): array of variants returned
  *
- * This function tries to retrieve the MathGlyphConstruction for the specified
- * font, glyph and direction. Note that only the value of
- * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
- * of size variants as an array of hb_ot_math_glyph_variant_t structs.
+ * Fetches the MathGlyphConstruction for the specified font, glyph index, and
+ * direction. The corresponding list of size variants is returned as a list of
+ * #hb_ot_math_glyph_variant_t structs.
  *
- * Return value: the total number of size variants available or 0
+ * <note>The @direction parameter is only used to select between horizontal
+ * or vertical directions for the construction. Even though all #hb_direction_t
+ * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is
+ * considered.</note> 
+ *
+ * Return value: the total number of size variants available or zero
  *
  * Since: 1.3.3
  **/
@@ -187,6 +238,12 @@
 			       unsigned int *variants_count, /* IN/OUT */
 			       hb_ot_math_glyph_variant_t *variants /* OUT */)
 {
+#ifdef HB_NO_MATH
+  if (variants_count)
+    *variants_count = 0;
+  return 0;
+#endif
+
   return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font,
 								    start_offset,
 								    variants_count,
@@ -195,15 +252,19 @@
 
 /**
  * hb_ot_math_get_min_connector_overlap:
- * @font: #hb_font_t from which to retrieve the value
- * @direction: direction of the stretching
+ * @font: #hb_font_t to work upon
+ * @direction: direction of the stretching (horizontal or vertical)
  *
- * This function tries to retrieve the MathVariants table for the specified
- * font and returns the minimum overlap of connecting glyphs to draw a glyph
- * assembly in the specified direction. Note that only the value of
- * #HB_DIRECTION_IS_HORIZONTAL is considered.
+ * Fetches the MathVariants table for the specified font and returns the
+ * minimum overlap of connecting glyphs that are required to draw a glyph
+ * assembly in the specified direction.
  *
- * Return value: requested min connector overlap or 0
+ * <note>The @direction parameter is only used to select between horizontal
+ * or vertical directions for the construction. Even though all #hb_direction_t
+ * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is
+ * considered.</note> 
+ *
+ * Return value: requested minimum connector overlap or zero
  *
  * Since: 1.3.3
  **/
@@ -211,24 +272,33 @@
 hb_ot_math_get_min_connector_overlap (hb_font_t *font,
 				      hb_direction_t direction)
 {
+#ifdef HB_NO_MATH
+  return 0;
+#endif
+
   return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font);
 }
 
 /**
  * hb_ot_math_get_glyph_assembly:
- * @font: #hb_font_t from which to retrieve the values
- * @glyph: index of the glyph to stretch
- * @direction: direction of the stretching
+ * @font: #hb_font_t to work upon
+ * @glyph: The index of the glyph to stretch
+ * @direction: direction of the stretching (horizontal or vertical)
  * @start_offset: offset of the first glyph part to retrieve
- * @parts_count: maximum number of glyph parts to retrieve after start_offset
- * (IN) and actual number of parts retrieved (OUT)
- * @parts: array of size at least @parts_count to store the result
- * @italics_correction: italic correction of the glyph assembly
+ * @parts_count: (inout): Input = maximum number of glyph parts to return;
+ *               Output = actual number of parts returned
+ * @parts: (out) (array length=parts_count): the glyph parts returned
+ * @italics_correction: (out): italics correction of the glyph assembly
  *
- * This function tries to retrieve the GlyphAssembly for the specified font,
- * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
- * is considered. It provides the information necessary to draw the glyph
- * assembly as an array of #hb_ot_math_glyph_part_t.
+ * Fetches the GlyphAssembly for the specified font, glyph index, and direction.
+ * Returned are a list of #hb_ot_math_glyph_part_t glyph parts that can be
+ * used to draw the glyph and an italics-correction value (if one is defined
+ * in the font).
+ *
+ * <note>The @direction parameter is only used to select between horizontal
+ * or vertical directions for the construction. Even though all #hb_direction_t
+ * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is
+ * considered.</note> 
  *
  * Return value: the total number of parts in the glyph assembly
  *
@@ -243,6 +313,12 @@
 			       hb_ot_math_glyph_part_t *parts, /* OUT */
 			       hb_position_t *italics_correction /* OUT */)
 {
+#ifdef HB_NO_MATH
+  if (parts_count)
+    *parts_count = 0;
+  return 0;
+#endif
+
   return font->face->table.MATH->get_variants().get_glyph_parts (glyph,
 								 direction,
 								 font,
diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h
index 521a5ca..7b2befb 100644
--- a/src/hb-ot-math.h
+++ b/src/hb-ot-math.h
@@ -50,6 +50,9 @@
 /**
  * hb_ot_math_constant_t:
  *
+ * The 'MATH' table constants specified at
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/math
+ *
  * Since: 1.3.3
  */
 typedef enum {
@@ -114,6 +117,9 @@
 /**
  * hb_ot_math_kern_t:
  *
+ * The math kerning-table types defined for the four corners
+ * of a glyph.
+ *
  * Since: 1.3.3
  */
 typedef enum {
@@ -125,6 +131,10 @@
 
 /**
  * hb_ot_math_glyph_variant_t:
+ * @glyph: The glyph index of the variant
+ * @advance: The advance width of the variant
+ *
+ * Data type to hold math-variant information for a glyph.
  *
  * Since: 1.3.3
  */
@@ -136,14 +146,25 @@
 /**
  * hb_ot_math_glyph_part_flags_t:
  *
+ * Flags for math glyph parts.
+ *
  * Since: 1.3.3
  */
 typedef enum { /*< flags >*/
-  HB_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
+  HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
 } hb_ot_math_glyph_part_flags_t;
 
 /**
  * hb_ot_math_glyph_part_t:
+ * @glyph: The glyph index of the variant part
+ * @start_connector_length: The length of the connector on the starting side of the variant part
+ * @end_connection_length: The length of the connector on the ending side of the variant part
+ * @full_advance: The total advance of the part
+ * @flags: #hb_ot_math_glyph_part_flags_t flags for the part
+ * 
+ * Data type to hold information for a "part" component of a math-variant glyph.
+ * Large variants for stretchable math glyphs (such as parentheses) can be constructed
+ * on the fly from parts.
  *
  * Since: 1.3.3
  */
diff --git a/src/hb-ot-name-language-static.hh b/src/hb-ot-name-language-static.hh
index fac3178..580e763 100644
--- a/src/hb-ot-name-language-static.hh
+++ b/src/hb-ot-name-language-static.hh
@@ -430,6 +430,9 @@
 			  const hb_ot_language_map_t *array,
 			  unsigned int len)
 {
+#ifdef HB_NO_OT_NAME_LANGUAGE
+  return HB_LANGUAGE_INVALID;
+#endif
   const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *)
 				      hb_bsearch (&code,
 						  array,
diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh
index 72deb10..68d7b3a 100644
--- a/src/hb-ot-name-table.hh
+++ b/src/hb-ot-name-table.hh
@@ -51,6 +51,7 @@
 {
   hb_language_t language (hb_face_t *face) const
   {
+#ifndef HB_NO_OT_NAME_LANGUAGE
     unsigned int p = platformID;
     unsigned int l = languageID;
 
@@ -60,11 +61,12 @@
     if (p == 1)
       return _hb_ot_name_language_for_mac_code (l);
 
-#if !defined(HB_NO_NAME_TABLE_AAT)
+#ifndef HB_NO_OT_NAME_LANGUAGE_AAT
     if (p == 0)
       return _hb_aat_language_get (face, l);
 #endif
 
+#endif
     return HB_LANGUAGE_INVALID;
   }
 
@@ -95,11 +97,21 @@
     return UNSUPPORTED;
   }
 
+  NameRecord* copy (hb_serialize_context_t *c,
+		    const void *src_base,
+		    const void *dst_base) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->embed (this);
+    if (unlikely (!out)) return_trace (nullptr);
+    out->offset.serialize_copy (c, offset, src_base, dst_base, length);
+    return_trace (out);
+  }
+
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    /* We can check from base all the way up to the end of string... */
-    return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
+    return_trace (c->check_struct (this) && offset.sanitize (c, base, length));
   }
 
   HBUINT16	platformID;	/* Platform ID. */
@@ -107,7 +119,8 @@
   HBUINT16	languageID;	/* Language ID. */
   HBUINT16	nameID;		/* Name ID. */
   HBUINT16	length;		/* String length (in bytes). */
-  HBUINT16	offset;		/* String offset from start of storage area (in bytes). */
+  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
+		offset;		/* String offset from start of storage area (in bytes). */
   public:
   DEFINE_SIZE_STATIC (12);
 };
@@ -158,159 +171,58 @@
   unsigned int get_size () const
   { return min_size + count * nameRecordZ.item_size; }
 
-  void get_subsetted_ids (const name *source_name,
-                             const hb_subset_plan_t *plan,
-                             hb_vector_t<unsigned int>& name_record_idx_to_retain) const
-  {
-    for(unsigned int i = 0; i < count; i++)
-    {
-      if (format == 0 && (unsigned int) source_name->nameRecordZ[i].nameID > 25)
-        continue;
-      if (!hb_set_is_empty (plan->name_ids) &&
-          !hb_set_has (plan->name_ids, source_name->nameRecordZ[i].nameID))
-        continue;
-      name_record_idx_to_retain.push (i);
-    }
-  }
-
-  bool serialize_name_record (hb_serialize_context_t *c,
-                              const name *source_name,
-                              const hb_vector_t<unsigned int>& name_record_idx_to_retain)
-  {
-    for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++)
-    {
-      unsigned int idx = name_record_idx_to_retain[i];
-      if (unlikely (idx >= source_name->count))
-      {
-        DEBUG_MSG (SUBSET, nullptr, "Invalid index: %d.", idx);
-        return false;
-      }
-
-      c->push<NameRecord> ();
-
-      NameRecord *p = c->embed<NameRecord> (source_name->nameRecordZ[idx]);
-      if (!p)
-        return false;
-      p->offset = 0;
-    }
-
-    return true;
-  }
-
-  bool serialize_strings (hb_serialize_context_t *c,
-                          const name *source_name,
-                          const hb_subset_plan_t *plan,
-                          const hb_vector_t<unsigned int>& name_record_idx_to_retain)
-  {
-    hb_face_t *face = plan->source;
-    accelerator_t acc;
-    acc.init (face);
-
-    for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++)
-    {
-      unsigned int idx = name_record_idx_to_retain[i];
-      unsigned int size = acc.get_name (idx).get_size ();
-
-      c->push<char> ();
-      char *new_pos = c->allocate_size<char> (size);
-      
-      if (unlikely (new_pos == nullptr))
-      {
-        acc.fini ();
-        DEBUG_MSG (SUBSET, nullptr, "Couldn't allocate enough space for Name string: %u.",
-                   size);
-        return false;
-      }
-
-      const HBUINT8* source_string_pool = (source_name + source_name->stringOffset).arrayZ;
-      unsigned int name_record_offset = source_name->nameRecordZ[idx].offset;
-
-      memcpy (new_pos, source_string_pool + name_record_offset, size);
-    }
-
-    acc.fini ();
-    return true;
-  }
-
-  bool pack_record_and_strings (name *dest_name_unpacked,
-                                hb_serialize_context_t *c, 
-                                unsigned length)
-  {
-    hb_hashmap_t<unsigned, unsigned> id_str_idx_map;
-    for (int i = length-1; i >= 0; i--)
-    {
-      unsigned objidx = c->pop_pack ();
-      id_str_idx_map.set ((unsigned)i, objidx);
-    }
-
-    const void *base = & (dest_name_unpacked->nameRecordZ[length]); 
-    for (int i = length-1; i >= 0; i--)
-    {
-      unsigned str_idx = id_str_idx_map.get ((unsigned)i);
-      NameRecord& namerecord = dest_name_unpacked->nameRecordZ[i];
-      c->add_link<HBUINT16> (namerecord.offset, str_idx, base);
-      c->pop_pack ();
-    }
-
-    if (c->in_error ())
-      return false;
-
-    return true;
-  }
-
+  template <typename Iterator,
+	    hb_requires (hb_is_source_of (Iterator, const NameRecord &))>
   bool serialize (hb_serialize_context_t *c,
-                  const name *source_name,
-                  const hb_subset_plan_t *plan,
-                  const hb_vector_t<unsigned int>& name_record_idx_to_retain)
+		  Iterator it,
+		  const void *src_string_pool)
   {
     TRACE_SERIALIZE (this);
 
     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
 
-    this->format = source_name->format;
-    this->count = name_record_idx_to_retain.length;
-    this->stringOffset = min_size + name_record_idx_to_retain.length * NameRecord::static_size;
+    this->format = 0;
+    this->count = it.len ();
 
+    auto snap = c->snapshot ();
+    this->nameRecordZ.serialize (c, this->count);
+    if (unlikely (!c->check_assign (this->stringOffset, c->length ()))) return_trace (false);
+    c->revert (snap);
 
-    if (!serialize_name_record (c, source_name, name_record_idx_to_retain))
-      return_trace (false);
+    const void *dst_string_pool = &(this + this->stringOffset);
 
-    if (!serialize_strings (c, source_name, plan, name_record_idx_to_retain))
-      return_trace (false);
+    + it
+    | hb_apply ([=] (const NameRecord& _) { c->copy (_, src_string_pool, dst_string_pool); })
+    ;
 
-    if (!pack_record_and_strings (this, c, name_record_idx_to_retain.length))
-      return_trace (false);
+    if (unlikely (c->ran_out_of_room)) return_trace (false);
+
+    assert (this->stringOffset == c->length ());
 
     return_trace (true);
   }
 
   bool subset (hb_subset_context_t *c) const
   {
-    hb_subset_plan_t *plan = c->plan;
-    hb_vector_t<unsigned int> name_record_idx_to_retain;
+    TRACE_SUBSET (this);
 
-    get_subsetted_ids (this, plan, name_record_idx_to_retain);
+    name *name_prime = c->serializer->start_embed<name> ();
+    if (unlikely (!name_prime)) return_trace (false);
 
-    hb_serialize_context_t *serializer = c->serializer;
-    name *name_prime = serializer->start_embed<name> ();
-    if (!name_prime || !name_prime->serialize (serializer, this, plan, name_record_idx_to_retain))
-    {
-      DEBUG_MSG (SUBSET, nullptr, "Failed to serialize write new name.");
-      return false;
-    }
-    
-    return true;
+    auto it =
+    + nameRecordZ.as_array (count)
+    | hb_filter (c->plan->name_ids, &NameRecord::nameID)
+    ;
+
+    name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
+    return_trace (name_prime->count);
   }
 
   bool sanitize_records (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     const void *string_pool = (this+stringOffset).arrayZ;
-    unsigned int _count = count;
-    /* Move to run-time?! */
-    for (unsigned int i = 0; i < _count; i++)
-      if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false);
-    return_trace (true);
+    return_trace (nameRecordZ.sanitize (c, count, string_pool));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -319,7 +231,8 @@
     return_trace (c->check_struct (this) &&
 		  likely (format == 0 || format == 1) &&
 		  c->check_array (nameRecordZ.arrayZ, count) &&
-		  c->check_range (this, stringOffset));
+		  c->check_range (this, stringOffset) &&
+		  sanitize_records (c));
   }
 
   struct accelerator_t
@@ -409,7 +322,7 @@
   /* We only implement format 0 for now. */
   HBUINT16	format;			/* Format selector (=0/1). */
   HBUINT16	count;			/* Number of name records. */
-  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
+  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
 		stringOffset;		/* Offset to start of string storage (from start of table). */
   UnsizedArrayOf<NameRecord>
 		nameRecordZ;		/* The name records where count is the number of records. */
diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc
index 907ae6a..5cd1cc1 100644
--- a/src/hb-ot-name.cc
+++ b/src/hb-ot-name.cc
@@ -58,6 +58,11 @@
 hb_ot_name_list_names (hb_face_t    *face,
 		       unsigned int *num_entries /* OUT */)
 {
+#ifdef HB_NO_NAME
+  if (num_entries)
+    *num_entries = 0;
+  return 0;
+#endif
   const OT::name_accelerator_t &name = *face->table.name;
   if (num_entries) *num_entries = name.names.length;
   return (const hb_ot_name_entry_t *) name.names;
@@ -93,7 +98,7 @@
 
       dst = dst_next;
       src = src_next;
-    };
+    }
 
     *text_size = dst - text;
     *dst = 0; /* NUL-terminate. */
@@ -105,7 +110,7 @@
   {
     src = in_utf_t::next (src, src_end, &unicode, replacement);
     dst_len += out_utf_t::encode_len (unicode);
-  };
+  }
   return dst_len;
 }
 
@@ -167,6 +172,11 @@
 		     unsigned int    *text_size /* IN/OUT */,
 		     char            *text      /* OUT */)
 {
+#ifdef HB_NO_NAME
+  if (text_size)
+    *text_size = 0;
+  return 0;
+#endif
   return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size,
 					(hb_utf8_t::codepoint_t *) text);
 }
@@ -194,6 +204,11 @@
 		      unsigned int    *text_size /* IN/OUT */,
 		      uint16_t        *text      /* OUT */)
 {
+#ifdef HB_NO_NAME
+  if (text_size)
+    *text_size = 0;
+  return 0;
+#endif
   return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text);
 }
 
@@ -220,5 +235,10 @@
 		      unsigned int    *text_size /* IN/OUT */,
 		      uint32_t        *text      /* OUT */)
 {
+#ifdef HB_NO_NAME
+  if (text_size)
+    *text_size = 0;
+  return 0;
+#endif
   return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
 }
diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh
index 21aa94d..970bbe6 100644
--- a/src/hb-ot-post-table.hh
+++ b/src/hb-ot-post-table.hh
@@ -131,7 +131,7 @@
       hb_bytes_t s = find_glyph_name (glyph);
       if (!s.length) return false;
       if (!buf_len) return true;
-      unsigned int len = MIN (buf_len - 1, s.length);
+      unsigned int len = hb_min (buf_len - 1, s.length);
       strncpy (buf, s.arrayZ, len);
       buf[len] = '\0';
       return true;
@@ -168,8 +168,8 @@
       }
 
       hb_bytes_t st (name, len);
-      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count,
-							     sizeof (gids[0]), cmp_key, (void *) this);
+      const uint16_t *gid = (const uint16_t *) hb_bsearch (hb_addressof (st), gids, count,
+							   sizeof (gids[0]), cmp_key, (void *) this);
       if (gid)
       {
 	*glyph = *gid;
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index 4daf2a6..3212e0c 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -383,7 +383,7 @@
 		       hb_font_t *font,
 		       hb_buffer_t *buffer)
 {
-#if defined(HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK)
+#ifdef HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
   return;
 #endif
 
diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc
index db88018..1498973 100644
--- a/src/hb-ot-shape-complex-hebrew.cc
+++ b/src/hb-ot-shape-complex-hebrew.cc
@@ -70,7 +70,7 @@
 
   bool found = (bool) c->unicode->compose (a, b, ab);
 
-#if defined(HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK)
+#ifdef HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
   return found;
 #endif
 
diff --git a/src/hb-ot-shape-complex-indic-machine.hh b/src/hb-ot-shape-complex-indic-machine.hh
index 08b90e9..ca26ecb 100644
--- a/src/hb-ot-shape-complex-indic-machine.hh
+++ b/src/hb-ot-shape-complex-indic-machine.hh
@@ -34,788 +34,284 @@
 
 #line 36 "hb-ot-shape-complex-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
-	8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
-	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
-	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-	16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
-	4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
-	7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 
-	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
-	4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
-	4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 
-	5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
-	7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
-	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 
-	4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u, 
-	7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
-	5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
-	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 
-	4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 
-	5u, 8u, 8u, 8u, 1u, 19u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 
-	5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 
-	4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-	3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
-	1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
-	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
-	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 
-	10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-	3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
-	4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 
-	1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, 
-	4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
-	4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
-	4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 
-	3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
-	3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 
-	1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
-	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
-	1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 
-	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
-	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
-	5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 
-	5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 
-	4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 
-	1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
-	3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 
-	1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 
-	10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 
-	10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0
+	8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
+	4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 
+	4u, 8u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 
+	6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 
+	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 5u, 8u, 8u, 8u, 1u, 19u, 
+	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 
+	1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 
+	3u, 10u, 5u, 10u, 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
+	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 
+	1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 
+	5u, 10u, 3u, 17u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
+	3u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 
+	4u, 10u, 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 
+	3u, 17u, 4u, 13u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
+	1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 
+	5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 1u, 17u, 
+	3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 
+	5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
-	1, 5, 3, 1, 4, 3, 1, 4, 
-	3, 1, 4, 3, 1, 5, 1, 1, 
-	5, 1, 1, 5, 1, 1, 5, 1, 
-	1, 10, 5, 10, 5, 10, 5, 10, 
-	5, 10, 1, 5, 3, 1, 4, 3, 
-	1, 4, 3, 1, 4, 3, 1, 5, 
-	1, 1, 5, 1, 1, 5, 1, 1, 
-	5, 1, 1, 10, 5, 10, 5, 10, 
-	5, 10, 5, 10, 1, 5, 3, 1, 
-	4, 3, 1, 4, 3, 1, 4, 3, 
-	1, 5, 1, 1, 5, 1, 1, 5, 
-	1, 1, 5, 1, 1, 10, 5, 10, 
-	5, 10, 5, 10, 5, 1, 5, 3, 
-	1, 4, 3, 1, 4, 3, 1, 4, 
-	3, 1, 5, 1, 1, 5, 1, 1, 
-	5, 1, 1, 5, 1, 1, 10, 5, 
-	10, 5, 10, 5, 10, 5, 10, 10, 
-	4, 1, 19, 15, 15, 14, 16, 15, 
-	15, 14, 16, 15, 15, 14, 16, 15, 
-	15, 14, 16, 15, 15, 14, 6, 6, 
-	6, 1, 1, 1, 6, 8, 6, 8, 
-	7, 6, 8, 7, 6, 8, 7, 6, 
-	8, 7, 7, 15, 15, 16, 16, 16, 
-	15, 15, 16, 16, 16, 15, 15, 16, 
-	16, 16, 15, 15, 16, 16, 16, 15, 
-	15, 15, 15, 14, 16, 15, 15, 14, 
-	16, 15, 15, 14, 16, 15, 15, 14, 
-	16, 15, 15, 14, 6, 6, 6, 1, 
-	1, 1, 6, 8, 6, 8, 7, 6, 
-	8, 7, 6, 8, 7, 6, 8, 7, 
-	7, 15, 15, 16, 16, 16, 15, 15, 
-	16, 16, 16, 15, 15, 16, 16, 16, 
-	15, 15, 16, 16, 16, 5, 15, 15, 
-	14, 16, 15, 15, 14, 16, 15, 15, 
-	14, 16, 15, 15, 14, 16, 15, 15, 
-	14, 6, 6, 6, 1, 1, 1, 6, 
-	8, 6, 8, 7, 6, 8, 7, 6, 
-	8, 7, 6, 8, 7, 7, 15, 15, 
-	16, 16, 16, 15, 15, 16, 16, 16, 
-	15, 15, 16, 16, 16, 15, 15, 16, 
-	16, 16, 10, 15, 5, 15, 15, 14, 
-	16, 15, 15, 14, 16, 15, 15, 14, 
-	16, 15, 15, 14, 16, 15, 15, 14, 
-	6, 6, 6, 1, 1, 1, 6, 8, 
-	6, 8, 7, 6, 8, 7, 6, 8, 
-	7, 6, 8, 7, 7, 15, 15, 16, 
-	16, 16, 15, 15, 16, 16, 16, 15, 
-	15, 16, 16, 16, 15, 15, 16, 16, 
-	16, 15, 17, 15, 17, 10, 6, 1, 
-	1, 1, 6, 16, 8, 6, 6, 1, 
-	1, 1, 6, 16
+	1, 5, 3, 4, 5, 1, 1, 5, 
+	10, 5, 1, 3, 4, 5, 1, 1, 
+	5, 10, 10, 10, 1, 3, 4, 5, 
+	1, 1, 5, 5, 10, 1, 3, 4, 
+	5, 1, 1, 5, 5, 4, 1, 19, 
+	15, 15, 14, 16, 6, 6, 1, 6, 
+	16, 16, 16, 8, 7, 6, 7, 6, 
+	8, 6, 15, 15, 15, 15, 14, 16, 
+	15, 15, 14, 16, 6, 1, 6, 16, 
+	16, 8, 7, 6, 7, 6, 6, 8, 
+	6, 15, 15, 5, 15, 15, 14, 16, 
+	15, 16, 6, 1, 6, 16, 16, 8, 
+	7, 6, 15, 7, 6, 6, 8, 6, 
+	15, 10, 5, 15, 15, 14, 16, 15, 
+	16, 6, 1, 6, 16, 16, 8, 7, 
+	6, 15, 7, 6, 6, 8, 6, 17, 
+	15, 17, 10, 6, 1, 6, 16, 8, 
+	6, 6, 1, 6, 16
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
-	0, 2, 8, 12, 14, 19, 23, 25, 
-	30, 34, 36, 41, 45, 47, 53, 55, 
-	57, 63, 65, 67, 73, 75, 77, 83, 
-	85, 87, 98, 104, 115, 121, 132, 138, 
-	149, 155, 166, 168, 174, 178, 180, 185, 
-	189, 191, 196, 200, 202, 207, 211, 213, 
-	219, 221, 223, 229, 231, 233, 239, 241, 
-	243, 249, 251, 253, 264, 270, 281, 287, 
-	298, 304, 315, 321, 332, 334, 340, 344, 
-	346, 351, 355, 357, 362, 366, 368, 373, 
-	377, 379, 385, 387, 389, 395, 397, 399, 
-	405, 407, 409, 415, 417, 419, 430, 436, 
-	447, 453, 464, 470, 481, 487, 489, 495, 
-	499, 501, 506, 510, 512, 517, 521, 523, 
-	528, 532, 534, 540, 542, 544, 550, 552, 
-	554, 560, 562, 564, 570, 572, 574, 585, 
-	591, 602, 608, 619, 625, 636, 642, 653, 
-	664, 669, 671, 691, 707, 723, 738, 755, 
-	771, 787, 802, 819, 835, 851, 866, 883, 
-	899, 915, 930, 947, 963, 979, 994, 1001, 
-	1008, 1015, 1017, 1019, 1021, 1028, 1037, 1044, 
-	1053, 1061, 1068, 1077, 1085, 1092, 1101, 1109, 
-	1116, 1125, 1133, 1141, 1157, 1173, 1190, 1207, 
-	1224, 1240, 1256, 1273, 1290, 1307, 1323, 1339, 
-	1356, 1373, 1390, 1406, 1422, 1439, 1456, 1473, 
-	1489, 1505, 1521, 1537, 1552, 1569, 1585, 1601, 
-	1616, 1633, 1649, 1665, 1680, 1697, 1713, 1729, 
-	1744, 1761, 1777, 1793, 1808, 1815, 1822, 1829, 
-	1831, 1833, 1835, 1842, 1851, 1858, 1867, 1875, 
-	1882, 1891, 1899, 1906, 1915, 1923, 1930, 1939, 
-	1947, 1955, 1971, 1987, 2004, 2021, 2038, 2054, 
-	2070, 2087, 2104, 2121, 2137, 2153, 2170, 2187, 
-	2204, 2220, 2236, 2253, 2270, 2287, 2293, 2309, 
-	2325, 2340, 2357, 2373, 2389, 2404, 2421, 2437, 
-	2453, 2468, 2485, 2501, 2517, 2532, 2549, 2565, 
-	2581, 2596, 2603, 2610, 2617, 2619, 2621, 2623, 
-	2630, 2639, 2646, 2655, 2663, 2670, 2679, 2687, 
-	2694, 2703, 2711, 2718, 2727, 2735, 2743, 2759, 
-	2775, 2792, 2809, 2826, 2842, 2858, 2875, 2892, 
-	2909, 2925, 2941, 2958, 2975, 2992, 3008, 3024, 
-	3041, 3058, 3075, 3086, 3102, 3108, 3124, 3140, 
-	3155, 3172, 3188, 3204, 3219, 3236, 3252, 3268, 
-	3283, 3300, 3316, 3332, 3347, 3364, 3380, 3396, 
-	3411, 3418, 3425, 3432, 3434, 3436, 3438, 3445, 
-	3454, 3461, 3470, 3478, 3485, 3494, 3502, 3509, 
-	3518, 3526, 3533, 3542, 3550, 3558, 3574, 3590, 
-	3607, 3624, 3641, 3657, 3673, 3690, 3707, 3724, 
-	3740, 3756, 3773, 3790, 3807, 3823, 3839, 3856, 
-	3873, 3890, 3906, 3924, 3940, 3958, 3969, 3976, 
-	3978, 3980, 3982, 3989, 4006, 4015, 4022, 4029, 
-	4031, 4033, 4035, 4042
+	0, 2, 8, 12, 17, 23, 25, 27, 
+	33, 44, 50, 52, 56, 61, 67, 69, 
+	71, 77, 88, 99, 110, 112, 116, 121, 
+	127, 129, 131, 137, 143, 154, 156, 160, 
+	165, 171, 173, 175, 181, 187, 192, 194, 
+	214, 230, 246, 261, 278, 285, 292, 294, 
+	301, 318, 335, 352, 361, 369, 376, 384, 
+	391, 400, 407, 423, 439, 455, 471, 486, 
+	503, 519, 535, 550, 567, 574, 576, 583, 
+	600, 617, 626, 634, 641, 649, 656, 663, 
+	672, 679, 695, 711, 717, 733, 749, 764, 
+	781, 797, 814, 821, 823, 830, 847, 864, 
+	873, 881, 888, 904, 912, 919, 926, 935, 
+	942, 958, 969, 975, 991, 1007, 1022, 1039, 
+	1055, 1072, 1079, 1081, 1088, 1105, 1122, 1131, 
+	1139, 1146, 1162, 1170, 1177, 1184, 1193, 1200, 
+	1218, 1234, 1252, 1263, 1270, 1272, 1279, 1296, 
+	1305, 1312, 1319, 1321, 1328
 };
 
-static const short _indic_syllable_machine_indicies[] = {
+static const unsigned char _indic_syllable_machine_indicies[] = {
 	1, 0, 2, 3, 3, 4, 1, 0, 
-	5, 5, 4, 0, 4, 0, 6, 6, 
-	7, 1, 0, 8, 8, 7, 0, 7, 
-	0, 9, 9, 10, 1, 0, 11, 11, 
-	10, 0, 10, 0, 12, 12, 13, 1, 
-	0, 14, 14, 13, 0, 13, 0, 15, 
-	0, 0, 0, 1, 0, 16, 0, 17, 
-	0, 18, 12, 12, 13, 1, 0, 19, 
-	0, 20, 0, 21, 9, 9, 10, 1, 
-	0, 22, 0, 23, 0, 24, 6, 6, 
-	7, 1, 0, 25, 0, 26, 0, 2, 
-	3, 3, 4, 1, 0, 0, 0, 0, 
-	27, 0, 28, 3, 3, 4, 1, 0, 
-	28, 3, 3, 4, 1, 0, 0, 0, 
-	0, 29, 0, 30, 3, 3, 4, 1, 
-	0, 30, 3, 3, 4, 1, 0, 0, 
-	0, 0, 31, 0, 32, 3, 3, 4, 
-	1, 0, 32, 3, 3, 4, 1, 0, 
-	0, 0, 0, 33, 0, 34, 3, 3, 
-	4, 1, 0, 34, 3, 3, 4, 1, 
-	0, 0, 0, 0, 35, 0, 37, 36, 
-	38, 39, 39, 40, 37, 36, 41, 41, 
-	40, 36, 40, 36, 42, 42, 43, 37, 
-	36, 44, 44, 43, 36, 43, 36, 45, 
-	45, 46, 37, 36, 47, 47, 46, 36, 
-	46, 36, 48, 48, 49, 37, 36, 50, 
-	50, 49, 36, 49, 36, 51, 36, 36, 
-	36, 37, 36, 52, 36, 53, 36, 54, 
-	48, 48, 49, 37, 36, 55, 36, 56, 
-	36, 57, 45, 45, 46, 37, 36, 58, 
-	36, 59, 36, 60, 42, 42, 43, 37, 
-	36, 61, 36, 62, 36, 38, 39, 39, 
-	40, 37, 36, 36, 36, 36, 63, 36, 
-	64, 39, 39, 40, 37, 36, 64, 39, 
-	39, 40, 37, 36, 36, 36, 36, 65, 
-	36, 66, 39, 39, 40, 37, 36, 66, 
-	39, 39, 40, 37, 36, 36, 36, 36, 
-	67, 36, 68, 39, 39, 40, 37, 36, 
-	68, 39, 39, 40, 37, 36, 36, 36, 
-	36, 69, 36, 70, 39, 39, 40, 37, 
-	36, 70, 39, 39, 40, 37, 36, 36, 
-	36, 36, 71, 36, 73, 72, 74, 75, 
-	75, 76, 73, 72, 78, 78, 76, 77, 
-	76, 77, 79, 79, 80, 73, 72, 81, 
-	81, 80, 72, 80, 72, 82, 82, 83, 
-	73, 72, 84, 84, 83, 72, 83, 72, 
-	85, 85, 86, 73, 72, 87, 87, 86, 
-	72, 86, 72, 88, 72, 72, 72, 73, 
-	72, 89, 72, 90, 72, 91, 85, 85, 
-	86, 73, 72, 92, 72, 93, 72, 94, 
-	82, 82, 83, 73, 72, 95, 72, 96, 
-	72, 97, 79, 79, 80, 73, 72, 98, 
-	72, 99, 72, 74, 75, 75, 76, 73, 
-	72, 72, 72, 72, 100, 72, 101, 75, 
-	75, 76, 73, 72, 101, 75, 75, 76, 
-	73, 72, 72, 72, 72, 102, 72, 103, 
-	75, 75, 76, 73, 72, 103, 75, 75, 
-	76, 73, 72, 72, 72, 72, 104, 72, 
-	105, 75, 75, 76, 73, 72, 105, 75, 
-	75, 76, 73, 72, 72, 72, 72, 106, 
-	72, 107, 75, 75, 76, 73, 72, 109, 
-	108, 110, 111, 111, 112, 109, 108, 113, 
-	113, 112, 108, 112, 108, 114, 114, 115, 
-	109, 108, 116, 116, 115, 108, 115, 108, 
-	117, 117, 118, 109, 108, 119, 119, 118, 
-	108, 118, 108, 120, 120, 121, 109, 108, 
-	122, 122, 121, 108, 121, 108, 123, 108, 
-	108, 108, 109, 108, 124, 108, 125, 108, 
-	126, 120, 120, 121, 109, 108, 127, 108, 
-	128, 108, 129, 117, 117, 118, 109, 108, 
-	130, 108, 131, 108, 132, 114, 114, 115, 
-	109, 108, 133, 108, 134, 108, 110, 111, 
-	111, 112, 109, 108, 108, 108, 108, 135, 
-	108, 136, 111, 111, 112, 109, 108, 136, 
-	111, 111, 112, 109, 108, 108, 108, 108, 
-	137, 108, 138, 111, 111, 112, 109, 108, 
-	138, 111, 111, 112, 109, 108, 108, 108, 
-	108, 139, 108, 140, 111, 111, 112, 109, 
-	108, 140, 111, 111, 112, 109, 108, 108, 
-	108, 108, 141, 108, 142, 111, 111, 112, 
-	109, 108, 142, 111, 111, 112, 109, 108, 
-	108, 108, 108, 143, 108, 107, 75, 75, 
-	76, 73, 72, 72, 72, 72, 144, 72, 
-	78, 78, 76, 1, 0, 146, 145, 148, 
-	149, 150, 151, 152, 153, 76, 73, 147, 
-	154, 155, 155, 144, 147, 156, 157, 158, 
-	159, 160, 147, 162, 163, 164, 165, 4, 
-	1, 161, 166, 161, 161, 35, 161, 161, 
-	161, 167, 161, 168, 163, 169, 169, 4, 
-	1, 161, 166, 161, 161, 161, 161, 161, 
-	161, 167, 161, 163, 169, 169, 4, 1, 
-	161, 166, 161, 161, 161, 161, 161, 161, 
-	167, 161, 170, 161, 161, 161, 17, 171, 
-	161, 1, 161, 166, 161, 161, 161, 161, 
-	161, 170, 161, 172, 173, 174, 175, 4, 
-	1, 161, 166, 161, 161, 33, 161, 161, 
-	161, 167, 161, 176, 173, 177, 177, 4, 
-	1, 161, 166, 161, 161, 161, 161, 161, 
-	161, 167, 161, 173, 177, 177, 4, 1, 
-	161, 166, 161, 161, 161, 161, 161, 161, 
-	167, 161, 178, 161, 161, 161, 17, 179, 
-	161, 1, 161, 166, 161, 161, 161, 161, 
-	161, 178, 161, 180, 181, 182, 183, 4, 
-	1, 161, 166, 161, 161, 31, 161, 161, 
-	161, 167, 161, 184, 181, 185, 185, 4, 
-	1, 161, 166, 161, 161, 161, 161, 161, 
-	161, 167, 161, 181, 185, 185, 4, 1, 
-	161, 166, 161, 161, 161, 161, 161, 161, 
-	167, 161, 186, 161, 161, 161, 17, 187, 
-	161, 1, 161, 166, 161, 161, 161, 161, 
-	161, 186, 161, 188, 189, 190, 191, 4, 
-	1, 161, 166, 161, 161, 29, 161, 161, 
-	161, 167, 161, 192, 189, 193, 193, 4, 
-	1, 161, 166, 161, 161, 161, 161, 161, 
-	161, 167, 161, 189, 193, 193, 4, 1, 
-	161, 166, 161, 161, 161, 161, 161, 161, 
-	167, 161, 194, 161, 161, 161, 17, 195, 
-	161, 1, 161, 166, 161, 161, 161, 161, 
-	161, 194, 161, 196, 197, 198, 199, 4, 
-	1, 161, 166, 161, 161, 27, 161, 161, 
-	161, 167, 161, 200, 197, 201, 201, 4, 
-	1, 161, 166, 161, 161, 161, 161, 161, 
-	161, 167, 161, 197, 201, 201, 4, 1, 
-	161, 166, 161, 161, 161, 161, 161, 161, 
-	167, 161, 17, 202, 161, 1, 161, 166, 
-	161, 203, 203, 161, 1, 161, 166, 161, 
-	204, 161, 161, 205, 161, 166, 161, 166, 
-	161, 206, 161, 207, 161, 204, 161, 161, 
-	161, 161, 166, 161, 17, 161, 203, 203, 
-	161, 1, 161, 166, 161, 203, 202, 161, 
-	1, 161, 166, 161, 208, 26, 209, 210, 
-	7, 1, 161, 166, 161, 26, 209, 210, 
-	7, 1, 161, 166, 161, 209, 209, 7, 
-	1, 161, 166, 161, 211, 23, 212, 213, 
-	10, 1, 161, 166, 161, 23, 212, 213, 
-	10, 1, 161, 166, 161, 212, 212, 10, 
-	1, 161, 166, 161, 214, 20, 215, 216, 
-	13, 1, 161, 166, 161, 20, 215, 216, 
-	13, 1, 161, 166, 161, 215, 215, 13, 
-	1, 161, 166, 161, 217, 17, 203, 218, 
-	161, 1, 161, 166, 161, 17, 203, 218, 
-	161, 1, 161, 166, 161, 197, 201, 201, 
-	4, 1, 161, 166, 161, 196, 197, 201, 
-	201, 4, 1, 161, 166, 161, 161, 161, 
-	161, 161, 161, 167, 161, 196, 197, 198, 
-	201, 4, 1, 161, 166, 161, 161, 27, 
-	161, 161, 161, 167, 161, 194, 161, 219, 
-	161, 203, 203, 161, 1, 161, 166, 161, 
-	161, 161, 161, 161, 194, 161, 194, 161, 
-	161, 161, 203, 203, 161, 1, 161, 166, 
-	161, 161, 161, 161, 161, 194, 161, 194, 
-	161, 161, 161, 203, 195, 161, 1, 161, 
-	166, 161, 161, 161, 161, 161, 194, 161, 
-	188, 189, 193, 193, 4, 1, 161, 166, 
-	161, 161, 161, 161, 161, 161, 167, 161, 
-	188, 189, 190, 193, 4, 1, 161, 166, 
-	161, 161, 29, 161, 161, 161, 167, 161, 
-	186, 161, 220, 161, 203, 203, 161, 1, 
-	161, 166, 161, 161, 161, 161, 161, 186, 
-	161, 186, 161, 161, 161, 203, 203, 161, 
-	1, 161, 166, 161, 161, 161, 161, 161, 
-	186, 161, 186, 161, 161, 161, 203, 187, 
-	161, 1, 161, 166, 161, 161, 161, 161, 
-	161, 186, 161, 180, 181, 185, 185, 4, 
-	1, 161, 166, 161, 161, 161, 161, 161, 
-	161, 167, 161, 180, 181, 182, 185, 4, 
-	1, 161, 166, 161, 161, 31, 161, 161, 
-	161, 167, 161, 178, 161, 221, 161, 203, 
-	203, 161, 1, 161, 166, 161, 161, 161, 
-	161, 161, 178, 161, 178, 161, 161, 161, 
-	203, 203, 161, 1, 161, 166, 161, 161, 
-	161, 161, 161, 178, 161, 178, 161, 161, 
-	161, 203, 179, 161, 1, 161, 166, 161, 
-	161, 161, 161, 161, 178, 161, 172, 173, 
-	177, 177, 4, 1, 161, 166, 161, 161, 
-	161, 161, 161, 161, 167, 161, 172, 173, 
-	174, 177, 4, 1, 161, 166, 161, 161, 
-	33, 161, 161, 161, 167, 161, 170, 161, 
-	222, 161, 203, 203, 161, 1, 161, 166, 
-	161, 161, 161, 161, 161, 170, 161, 170, 
-	161, 161, 161, 203, 203, 161, 1, 161, 
-	166, 161, 161, 161, 161, 161, 170, 161, 
-	170, 161, 161, 161, 203, 171, 161, 1, 
-	161, 166, 161, 161, 161, 161, 161, 170, 
-	161, 162, 163, 169, 169, 4, 1, 161, 
-	166, 161, 161, 161, 161, 161, 161, 167, 
-	161, 162, 163, 164, 169, 4, 1, 161, 
-	166, 161, 161, 35, 161, 161, 161, 167, 
-	161, 224, 225, 226, 227, 40, 37, 223, 
-	228, 223, 223, 71, 223, 223, 223, 229, 
-	223, 230, 225, 231, 227, 40, 37, 223, 
-	228, 223, 223, 223, 223, 223, 223, 229, 
-	223, 225, 231, 227, 40, 37, 223, 228, 
-	223, 223, 223, 223, 223, 223, 229, 223, 
-	232, 223, 223, 223, 53, 233, 223, 37, 
-	223, 228, 223, 223, 223, 223, 223, 232, 
-	223, 234, 235, 236, 237, 40, 37, 223, 
-	228, 223, 223, 69, 223, 223, 223, 229, 
-	223, 238, 235, 239, 239, 40, 37, 223, 
-	228, 223, 223, 223, 223, 223, 223, 229, 
-	223, 235, 239, 239, 40, 37, 223, 228, 
-	223, 223, 223, 223, 223, 223, 229, 223, 
-	240, 223, 223, 223, 53, 241, 223, 37, 
-	223, 228, 223, 223, 223, 223, 223, 240, 
-	223, 242, 243, 244, 245, 40, 37, 223, 
-	228, 223, 223, 67, 223, 223, 223, 229, 
-	223, 246, 243, 247, 247, 40, 37, 223, 
-	228, 223, 223, 223, 223, 223, 223, 229, 
-	223, 243, 247, 247, 40, 37, 223, 228, 
-	223, 223, 223, 223, 223, 223, 229, 223, 
-	248, 223, 223, 223, 53, 249, 223, 37, 
-	223, 228, 223, 223, 223, 223, 223, 248, 
-	223, 250, 251, 252, 253, 40, 37, 223, 
-	228, 223, 223, 65, 223, 223, 223, 229, 
-	223, 254, 251, 255, 255, 40, 37, 223, 
-	228, 223, 223, 223, 223, 223, 223, 229, 
-	223, 251, 255, 255, 40, 37, 223, 228, 
-	223, 223, 223, 223, 223, 223, 229, 223, 
-	256, 223, 223, 223, 53, 257, 223, 37, 
-	223, 228, 223, 223, 223, 223, 223, 256, 
-	223, 258, 259, 260, 261, 40, 37, 223, 
-	228, 223, 223, 63, 223, 223, 223, 229, 
-	223, 262, 259, 263, 263, 40, 37, 223, 
-	228, 223, 223, 223, 223, 223, 223, 229, 
-	223, 259, 263, 263, 40, 37, 223, 228, 
-	223, 223, 223, 223, 223, 223, 229, 223, 
-	53, 264, 223, 37, 223, 228, 223, 265, 
-	265, 223, 37, 223, 228, 223, 266, 223, 
-	223, 267, 223, 228, 223, 228, 223, 268, 
-	223, 269, 223, 266, 223, 223, 223, 223, 
-	228, 223, 53, 223, 265, 265, 223, 37, 
-	223, 228, 223, 265, 264, 223, 37, 223, 
-	228, 223, 270, 62, 271, 272, 43, 37, 
-	223, 228, 223, 62, 271, 272, 43, 37, 
-	223, 228, 223, 271, 271, 43, 37, 223, 
-	228, 223, 273, 59, 274, 275, 46, 37, 
-	223, 228, 223, 59, 274, 275, 46, 37, 
-	223, 228, 223, 274, 274, 46, 37, 223, 
-	228, 223, 276, 56, 277, 278, 49, 37, 
-	223, 228, 223, 56, 277, 278, 49, 37, 
-	223, 228, 223, 277, 277, 49, 37, 223, 
-	228, 223, 279, 53, 265, 280, 223, 37, 
-	223, 228, 223, 53, 265, 280, 223, 37, 
-	223, 228, 223, 259, 263, 263, 40, 37, 
-	223, 228, 223, 258, 259, 263, 263, 40, 
-	37, 223, 228, 223, 223, 223, 223, 223, 
-	223, 229, 223, 258, 259, 260, 263, 40, 
-	37, 223, 228, 223, 223, 63, 223, 223, 
-	223, 229, 223, 256, 223, 281, 223, 265, 
-	265, 223, 37, 223, 228, 223, 223, 223, 
-	223, 223, 256, 223, 256, 223, 223, 223, 
-	265, 265, 223, 37, 223, 228, 223, 223, 
-	223, 223, 223, 256, 223, 256, 223, 223, 
-	223, 265, 257, 223, 37, 223, 228, 223, 
-	223, 223, 223, 223, 256, 223, 250, 251, 
-	255, 255, 40, 37, 223, 228, 223, 223, 
-	223, 223, 223, 223, 229, 223, 250, 251, 
-	252, 255, 40, 37, 223, 228, 223, 223, 
-	65, 223, 223, 223, 229, 223, 248, 223, 
-	282, 223, 265, 265, 223, 37, 223, 228, 
-	223, 223, 223, 223, 223, 248, 223, 248, 
-	223, 223, 223, 265, 265, 223, 37, 223, 
-	228, 223, 223, 223, 223, 223, 248, 223, 
-	248, 223, 223, 223, 265, 249, 223, 37, 
-	223, 228, 223, 223, 223, 223, 223, 248, 
-	223, 242, 243, 247, 247, 40, 37, 223, 
-	228, 223, 223, 223, 223, 223, 223, 229, 
-	223, 242, 243, 244, 247, 40, 37, 223, 
-	228, 223, 223, 67, 223, 223, 223, 229, 
-	223, 240, 223, 283, 223, 265, 265, 223, 
-	37, 223, 228, 223, 223, 223, 223, 223, 
-	240, 223, 240, 223, 223, 223, 265, 265, 
-	223, 37, 223, 228, 223, 223, 223, 223, 
-	223, 240, 223, 240, 223, 223, 223, 265, 
-	241, 223, 37, 223, 228, 223, 223, 223, 
-	223, 223, 240, 223, 234, 235, 239, 239, 
-	40, 37, 223, 228, 223, 223, 223, 223, 
-	223, 223, 229, 223, 234, 235, 236, 239, 
-	40, 37, 223, 228, 223, 223, 69, 223, 
-	223, 223, 229, 223, 232, 223, 284, 223, 
-	265, 265, 223, 37, 223, 228, 223, 223, 
-	223, 223, 223, 232, 223, 232, 223, 223, 
-	223, 265, 265, 223, 37, 223, 228, 223, 
-	223, 223, 223, 223, 232, 223, 232, 223, 
-	223, 223, 265, 233, 223, 37, 223, 228, 
-	223, 223, 223, 223, 223, 232, 223, 70, 
-	39, 39, 40, 37, 223, 224, 225, 231, 
-	227, 40, 37, 223, 228, 223, 223, 223, 
-	223, 223, 223, 229, 223, 286, 151, 287, 
-	287, 76, 73, 285, 154, 285, 285, 285, 
-	285, 285, 285, 158, 285, 151, 287, 287, 
-	76, 73, 285, 154, 285, 285, 285, 285, 
-	285, 285, 158, 285, 288, 285, 285, 285, 
-	90, 289, 285, 73, 285, 154, 285, 285, 
-	285, 285, 285, 288, 285, 290, 291, 292, 
-	293, 76, 73, 285, 154, 285, 285, 106, 
-	285, 285, 285, 158, 285, 294, 291, 295, 
-	295, 76, 73, 285, 154, 285, 285, 285, 
-	285, 285, 285, 158, 285, 291, 295, 295, 
-	76, 73, 285, 154, 285, 285, 285, 285, 
-	285, 285, 158, 285, 296, 285, 285, 285, 
-	90, 297, 285, 73, 285, 154, 285, 285, 
-	285, 285, 285, 296, 285, 298, 299, 300, 
-	301, 76, 73, 285, 154, 285, 285, 104, 
-	285, 285, 285, 158, 285, 302, 299, 303, 
-	303, 76, 73, 285, 154, 285, 285, 285, 
-	285, 285, 285, 158, 285, 299, 303, 303, 
-	76, 73, 285, 154, 285, 285, 285, 285, 
-	285, 285, 158, 285, 304, 285, 285, 285, 
-	90, 305, 285, 73, 285, 154, 285, 285, 
-	285, 285, 285, 304, 285, 306, 307, 308, 
-	309, 76, 73, 285, 154, 285, 285, 102, 
-	285, 285, 285, 158, 285, 310, 307, 311, 
-	311, 76, 73, 285, 154, 285, 285, 285, 
-	285, 285, 285, 158, 285, 307, 311, 311, 
-	76, 73, 285, 154, 285, 285, 285, 285, 
-	285, 285, 158, 285, 312, 285, 285, 285, 
-	90, 313, 285, 73, 285, 154, 285, 285, 
-	285, 285, 285, 312, 285, 314, 315, 316, 
-	317, 76, 73, 285, 154, 285, 285, 100, 
-	285, 285, 285, 158, 285, 318, 315, 319, 
-	319, 76, 73, 285, 154, 285, 285, 285, 
-	285, 285, 285, 158, 285, 315, 319, 319, 
-	76, 73, 285, 154, 285, 285, 285, 285, 
-	285, 285, 158, 285, 90, 320, 285, 73, 
-	285, 154, 285, 321, 321, 285, 73, 285, 
-	154, 285, 322, 285, 285, 323, 285, 154, 
-	285, 154, 285, 324, 285, 325, 285, 322, 
-	285, 285, 285, 285, 154, 285, 90, 285, 
-	321, 321, 285, 73, 285, 154, 285, 321, 
-	320, 285, 73, 285, 154, 285, 326, 99, 
-	327, 328, 80, 73, 285, 154, 285, 99, 
-	327, 328, 80, 73, 285, 154, 285, 327, 
-	327, 80, 73, 285, 154, 285, 329, 96, 
-	330, 331, 83, 73, 285, 154, 285, 96, 
-	330, 331, 83, 73, 285, 154, 285, 330, 
-	330, 83, 73, 285, 154, 285, 332, 93, 
-	333, 334, 86, 73, 285, 154, 285, 93, 
-	333, 334, 86, 73, 285, 154, 285, 333, 
-	333, 86, 73, 285, 154, 285, 335, 90, 
-	321, 336, 285, 73, 285, 154, 285, 90, 
-	321, 336, 285, 73, 285, 154, 285, 315, 
-	319, 319, 76, 73, 285, 154, 285, 314, 
-	315, 319, 319, 76, 73, 285, 154, 285, 
-	285, 285, 285, 285, 285, 158, 285, 314, 
-	315, 316, 319, 76, 73, 285, 154, 285, 
-	285, 100, 285, 285, 285, 158, 285, 312, 
-	285, 337, 285, 321, 321, 285, 73, 285, 
-	154, 285, 285, 285, 285, 285, 312, 285, 
-	312, 285, 285, 285, 321, 321, 285, 73, 
-	285, 154, 285, 285, 285, 285, 285, 312, 
-	285, 312, 285, 285, 285, 321, 313, 285, 
-	73, 285, 154, 285, 285, 285, 285, 285, 
-	312, 285, 306, 307, 311, 311, 76, 73, 
-	285, 154, 285, 285, 285, 285, 285, 285, 
-	158, 285, 306, 307, 308, 311, 76, 73, 
-	285, 154, 285, 285, 102, 285, 285, 285, 
-	158, 285, 304, 285, 338, 285, 321, 321, 
-	285, 73, 285, 154, 285, 285, 285, 285, 
-	285, 304, 285, 304, 285, 285, 285, 321, 
-	321, 285, 73, 285, 154, 285, 285, 285, 
-	285, 285, 304, 285, 304, 285, 285, 285, 
-	321, 305, 285, 73, 285, 154, 285, 285, 
-	285, 285, 285, 304, 285, 298, 299, 303, 
-	303, 76, 73, 285, 154, 285, 285, 285, 
-	285, 285, 285, 158, 285, 298, 299, 300, 
-	303, 76, 73, 285, 154, 285, 285, 104, 
-	285, 285, 285, 158, 285, 296, 285, 339, 
-	285, 321, 321, 285, 73, 285, 154, 285, 
-	285, 285, 285, 285, 296, 285, 296, 285, 
-	285, 285, 321, 321, 285, 73, 285, 154, 
-	285, 285, 285, 285, 285, 296, 285, 296, 
-	285, 285, 285, 321, 297, 285, 73, 285, 
-	154, 285, 285, 285, 285, 285, 296, 285, 
-	290, 291, 295, 295, 76, 73, 285, 154, 
-	285, 285, 285, 285, 285, 285, 158, 285, 
-	290, 291, 292, 295, 76, 73, 285, 154, 
-	285, 285, 106, 285, 285, 285, 158, 285, 
-	288, 285, 340, 285, 321, 321, 285, 73, 
-	285, 154, 285, 285, 285, 285, 285, 288, 
-	285, 288, 285, 285, 285, 321, 321, 285, 
-	73, 285, 154, 285, 285, 285, 285, 285, 
-	288, 285, 288, 285, 285, 285, 321, 289, 
-	285, 73, 285, 154, 285, 285, 285, 285, 
-	285, 288, 285, 107, 75, 75, 76, 73, 
-	341, 341, 341, 341, 144, 341, 150, 151, 
-	287, 287, 76, 73, 285, 154, 285, 285, 
-	285, 285, 285, 285, 158, 285, 107, 75, 
-	75, 76, 73, 341, 343, 344, 345, 346, 
-	112, 109, 342, 347, 342, 342, 143, 342, 
-	342, 342, 348, 342, 349, 344, 346, 346, 
-	112, 109, 342, 347, 342, 342, 342, 342, 
-	342, 342, 348, 342, 344, 346, 346, 112, 
-	109, 342, 347, 342, 342, 342, 342, 342, 
-	342, 348, 342, 350, 342, 342, 342, 125, 
-	351, 342, 109, 342, 347, 342, 342, 342, 
-	342, 342, 350, 342, 352, 353, 354, 355, 
-	112, 109, 342, 347, 342, 342, 141, 342, 
-	342, 342, 348, 342, 356, 353, 357, 357, 
-	112, 109, 342, 347, 342, 342, 342, 342, 
-	342, 342, 348, 342, 353, 357, 357, 112, 
-	109, 342, 347, 342, 342, 342, 342, 342, 
-	342, 348, 342, 358, 342, 342, 342, 125, 
-	359, 342, 109, 342, 347, 342, 342, 342, 
-	342, 342, 358, 342, 360, 361, 362, 363, 
-	112, 109, 342, 347, 342, 342, 139, 342, 
-	342, 342, 348, 342, 364, 361, 365, 365, 
-	112, 109, 342, 347, 342, 342, 342, 342, 
-	342, 342, 348, 342, 361, 365, 365, 112, 
-	109, 342, 347, 342, 342, 342, 342, 342, 
-	342, 348, 342, 366, 342, 342, 342, 125, 
-	367, 342, 109, 342, 347, 342, 342, 342, 
-	342, 342, 366, 342, 368, 369, 370, 371, 
-	112, 109, 342, 347, 342, 342, 137, 342, 
-	342, 342, 348, 342, 372, 369, 373, 373, 
-	112, 109, 342, 347, 342, 342, 342, 342, 
-	342, 342, 348, 342, 369, 373, 373, 112, 
-	109, 342, 347, 342, 342, 342, 342, 342, 
-	342, 348, 342, 374, 342, 342, 342, 125, 
-	375, 342, 109, 342, 347, 342, 342, 342, 
-	342, 342, 374, 342, 376, 377, 378, 379, 
-	112, 109, 342, 347, 342, 342, 135, 342, 
-	342, 342, 348, 342, 380, 377, 381, 381, 
-	112, 109, 342, 347, 342, 342, 342, 342, 
-	342, 342, 348, 342, 377, 381, 381, 112, 
-	109, 342, 347, 342, 342, 342, 342, 342, 
-	342, 348, 342, 125, 382, 342, 109, 342, 
-	347, 342, 383, 383, 342, 109, 342, 347, 
-	342, 384, 342, 342, 385, 342, 347, 342, 
-	347, 342, 386, 342, 387, 342, 384, 342, 
-	342, 342, 342, 347, 342, 125, 342, 383, 
-	383, 342, 109, 342, 347, 342, 383, 382, 
-	342, 109, 342, 347, 342, 388, 134, 389, 
-	390, 115, 109, 342, 347, 342, 134, 389, 
-	390, 115, 109, 342, 347, 342, 389, 389, 
-	115, 109, 342, 347, 342, 391, 131, 392, 
-	393, 118, 109, 342, 347, 342, 131, 392, 
-	393, 118, 109, 342, 347, 342, 392, 392, 
-	118, 109, 342, 347, 342, 394, 128, 395, 
-	396, 121, 109, 342, 347, 342, 128, 395, 
-	396, 121, 109, 342, 347, 342, 395, 395, 
-	121, 109, 342, 347, 342, 397, 125, 383, 
-	398, 342, 109, 342, 347, 342, 125, 383, 
-	398, 342, 109, 342, 347, 342, 377, 381, 
-	381, 112, 109, 342, 347, 342, 376, 377, 
-	381, 381, 112, 109, 342, 347, 342, 342, 
-	342, 342, 342, 342, 348, 342, 376, 377, 
-	378, 381, 112, 109, 342, 347, 342, 342, 
-	135, 342, 342, 342, 348, 342, 374, 342, 
-	399, 342, 383, 383, 342, 109, 342, 347, 
-	342, 342, 342, 342, 342, 374, 342, 374, 
-	342, 342, 342, 383, 383, 342, 109, 342, 
-	347, 342, 342, 342, 342, 342, 374, 342, 
-	374, 342, 342, 342, 383, 375, 342, 109, 
-	342, 347, 342, 342, 342, 342, 342, 374, 
-	342, 368, 369, 373, 373, 112, 109, 342, 
-	347, 342, 342, 342, 342, 342, 342, 348, 
-	342, 368, 369, 370, 373, 112, 109, 342, 
-	347, 342, 342, 137, 342, 342, 342, 348, 
-	342, 366, 342, 400, 342, 383, 383, 342, 
-	109, 342, 347, 342, 342, 342, 342, 342, 
-	366, 342, 366, 342, 342, 342, 383, 383, 
-	342, 109, 342, 347, 342, 342, 342, 342, 
-	342, 366, 342, 366, 342, 342, 342, 383, 
-	367, 342, 109, 342, 347, 342, 342, 342, 
-	342, 342, 366, 342, 360, 361, 365, 365, 
-	112, 109, 342, 347, 342, 342, 342, 342, 
-	342, 342, 348, 342, 360, 361, 362, 365, 
-	112, 109, 342, 347, 342, 342, 139, 342, 
-	342, 342, 348, 342, 358, 342, 401, 342, 
-	383, 383, 342, 109, 342, 347, 342, 342, 
-	342, 342, 342, 358, 342, 358, 342, 342, 
-	342, 383, 383, 342, 109, 342, 347, 342, 
-	342, 342, 342, 342, 358, 342, 358, 342, 
-	342, 342, 383, 359, 342, 109, 342, 347, 
-	342, 342, 342, 342, 342, 358, 342, 352, 
-	353, 357, 357, 112, 109, 342, 347, 342, 
-	342, 342, 342, 342, 342, 348, 342, 352, 
-	353, 354, 357, 112, 109, 342, 347, 342, 
-	342, 141, 342, 342, 342, 348, 342, 350, 
-	342, 402, 342, 383, 383, 342, 109, 342, 
-	347, 342, 342, 342, 342, 342, 350, 342, 
-	350, 342, 342, 342, 383, 383, 342, 109, 
-	342, 347, 342, 342, 342, 342, 342, 350, 
-	342, 350, 342, 342, 342, 383, 351, 342, 
-	109, 342, 347, 342, 342, 342, 342, 342, 
-	350, 342, 343, 344, 346, 346, 112, 109, 
-	342, 347, 342, 342, 342, 342, 342, 342, 
-	348, 342, 148, 149, 150, 151, 403, 287, 
-	76, 73, 285, 154, 155, 155, 144, 285, 
-	285, 148, 158, 285, 162, 404, 164, 165, 
-	4, 1, 161, 166, 161, 161, 35, 161, 
-	161, 161, 167, 161, 170, 149, 150, 151, 
-	405, 406, 76, 407, 161, 408, 161, 155, 
-	144, 161, 161, 170, 158, 161, 107, 409, 
-	409, 76, 407, 161, 166, 161, 161, 144, 
-	161, 410, 161, 161, 411, 161, 408, 161, 
-	408, 161, 412, 161, 207, 161, 410, 161, 
-	161, 161, 161, 408, 161, 170, 161, 222, 
-	107, 409, 409, 76, 407, 161, 166, 161, 
-	161, 161, 161, 161, 170, 161, 414, 413, 
-	415, 415, 413, 146, 413, 416, 413, 415, 
-	415, 413, 146, 413, 416, 413, 417, 413, 
-	413, 418, 413, 416, 413, 416, 413, 419, 
-	413, 420, 413, 417, 413, 413, 413, 413, 
-	416, 413, 148, 341, 341, 341, 341, 341, 
-	341, 341, 341, 341, 155, 341, 341, 341, 
-	341, 148, 341, 0
+	3, 3, 4, 0, 3, 3, 4, 1, 
+	0, 5, 3, 3, 4, 1, 0, 6, 
+	0, 7, 0, 8, 3, 3, 4, 1, 
+	0, 2, 3, 3, 4, 1, 0, 0, 
+	0, 0, 9, 0, 11, 12, 12, 13, 
+	14, 10, 14, 10, 12, 12, 13, 10, 
+	12, 12, 13, 14, 10, 15, 12, 12, 
+	13, 14, 10, 16, 10, 17, 10, 18, 
+	12, 12, 13, 14, 10, 11, 12, 12, 
+	13, 14, 10, 10, 10, 10, 19, 10, 
+	11, 12, 12, 13, 14, 10, 10, 10, 
+	10, 20, 10, 22, 23, 23, 24, 25, 
+	21, 21, 21, 21, 26, 21, 25, 21, 
+	23, 23, 24, 27, 23, 23, 24, 25, 
+	21, 28, 23, 23, 24, 25, 21, 29, 
+	21, 30, 21, 22, 23, 23, 24, 25, 
+	21, 31, 23, 23, 24, 25, 21, 33, 
+	34, 34, 35, 36, 32, 32, 32, 32, 
+	37, 32, 36, 32, 34, 34, 35, 32, 
+	34, 34, 35, 36, 32, 38, 34, 34, 
+	35, 36, 32, 39, 32, 40, 32, 33, 
+	34, 34, 35, 36, 32, 41, 34, 34, 
+	35, 36, 32, 23, 23, 24, 1, 0, 
+	43, 42, 45, 46, 47, 48, 49, 50, 
+	24, 25, 44, 51, 52, 52, 26, 44, 
+	53, 54, 55, 56, 57, 44, 59, 60, 
+	61, 62, 4, 1, 58, 63, 58, 58, 
+	9, 58, 58, 58, 64, 58, 65, 60, 
+	66, 66, 4, 1, 58, 63, 58, 58, 
+	58, 58, 58, 58, 64, 58, 60, 66, 
+	66, 4, 1, 58, 63, 58, 58, 58, 
+	58, 58, 58, 64, 58, 45, 58, 58, 
+	58, 67, 68, 58, 1, 58, 63, 58, 
+	58, 58, 58, 58, 45, 58, 69, 69, 
+	58, 1, 58, 63, 58, 63, 58, 58, 
+	70, 58, 63, 58, 63, 58, 63, 58, 
+	58, 58, 58, 63, 58, 45, 58, 71, 
+	58, 69, 69, 58, 1, 58, 63, 58, 
+	58, 58, 58, 58, 45, 58, 45, 58, 
+	58, 58, 69, 69, 58, 1, 58, 63, 
+	58, 58, 58, 58, 58, 45, 58, 45, 
+	58, 58, 58, 69, 68, 58, 1, 58, 
+	63, 58, 58, 58, 58, 58, 45, 58, 
+	72, 7, 73, 74, 4, 1, 58, 63, 
+	58, 7, 73, 74, 4, 1, 58, 63, 
+	58, 73, 73, 4, 1, 58, 63, 58, 
+	75, 76, 76, 4, 1, 58, 63, 58, 
+	67, 77, 58, 1, 58, 63, 58, 67, 
+	58, 69, 69, 58, 1, 58, 63, 58, 
+	69, 77, 58, 1, 58, 63, 58, 59, 
+	60, 66, 66, 4, 1, 58, 63, 58, 
+	58, 58, 58, 58, 58, 64, 58, 59, 
+	60, 61, 66, 4, 1, 58, 63, 58, 
+	58, 9, 58, 58, 58, 64, 58, 79, 
+	80, 81, 82, 13, 14, 78, 83, 78, 
+	78, 20, 78, 78, 78, 84, 78, 85, 
+	80, 86, 82, 13, 14, 78, 83, 78, 
+	78, 78, 78, 78, 78, 84, 78, 80, 
+	86, 82, 13, 14, 78, 83, 78, 78, 
+	78, 78, 78, 78, 84, 78, 87, 78, 
+	78, 78, 88, 89, 78, 14, 78, 83, 
+	78, 78, 78, 78, 78, 87, 78, 90, 
+	80, 91, 92, 13, 14, 78, 83, 78, 
+	78, 19, 78, 78, 78, 84, 78, 93, 
+	80, 86, 86, 13, 14, 78, 83, 78, 
+	78, 78, 78, 78, 78, 84, 78, 80, 
+	86, 86, 13, 14, 78, 83, 78, 78, 
+	78, 78, 78, 78, 84, 78, 87, 78, 
+	78, 78, 94, 89, 78, 14, 78, 83, 
+	78, 78, 78, 78, 78, 87, 78, 83, 
+	78, 78, 95, 78, 83, 78, 83, 78, 
+	83, 78, 78, 78, 78, 83, 78, 87, 
+	78, 96, 78, 94, 94, 78, 14, 78, 
+	83, 78, 78, 78, 78, 78, 87, 78, 
+	87, 78, 78, 78, 94, 94, 78, 14, 
+	78, 83, 78, 78, 78, 78, 78, 87, 
+	78, 97, 17, 98, 99, 13, 14, 78, 
+	83, 78, 17, 98, 99, 13, 14, 78, 
+	83, 78, 98, 98, 13, 14, 78, 83, 
+	78, 100, 101, 101, 13, 14, 78, 83, 
+	78, 88, 102, 78, 14, 78, 83, 78, 
+	94, 94, 78, 14, 78, 83, 78, 88, 
+	78, 94, 94, 78, 14, 78, 83, 78, 
+	94, 102, 78, 14, 78, 83, 78, 90, 
+	80, 86, 86, 13, 14, 78, 83, 78, 
+	78, 78, 78, 78, 78, 84, 78, 90, 
+	80, 91, 86, 13, 14, 78, 83, 78, 
+	78, 19, 78, 78, 78, 84, 78, 11, 
+	12, 12, 13, 14, 78, 79, 80, 86, 
+	82, 13, 14, 78, 83, 78, 78, 78, 
+	78, 78, 78, 84, 78, 104, 48, 105, 
+	105, 24, 25, 103, 51, 103, 103, 103, 
+	103, 103, 103, 55, 103, 48, 105, 105, 
+	24, 25, 103, 51, 103, 103, 103, 103, 
+	103, 103, 55, 103, 106, 103, 103, 103, 
+	107, 108, 103, 25, 103, 51, 103, 103, 
+	103, 103, 103, 106, 103, 47, 48, 109, 
+	110, 24, 25, 103, 51, 103, 103, 26, 
+	103, 103, 103, 55, 103, 106, 103, 103, 
+	103, 111, 108, 103, 25, 103, 51, 103, 
+	103, 103, 103, 103, 106, 103, 51, 103, 
+	103, 112, 103, 51, 103, 51, 103, 51, 
+	103, 103, 103, 103, 51, 103, 106, 103, 
+	113, 103, 111, 111, 103, 25, 103, 51, 
+	103, 103, 103, 103, 103, 106, 103, 106, 
+	103, 103, 103, 111, 111, 103, 25, 103, 
+	51, 103, 103, 103, 103, 103, 106, 103, 
+	114, 30, 115, 116, 24, 25, 103, 51, 
+	103, 30, 115, 116, 24, 25, 103, 51, 
+	103, 115, 115, 24, 25, 103, 51, 103, 
+	47, 48, 105, 105, 24, 25, 103, 51, 
+	103, 103, 103, 103, 103, 103, 55, 103, 
+	117, 118, 118, 24, 25, 103, 51, 103, 
+	107, 119, 103, 25, 103, 51, 103, 111, 
+	111, 103, 25, 103, 51, 103, 107, 103, 
+	111, 111, 103, 25, 103, 51, 103, 111, 
+	119, 103, 25, 103, 51, 103, 47, 48, 
+	109, 105, 24, 25, 103, 51, 103, 103, 
+	26, 103, 103, 103, 55, 103, 22, 23, 
+	23, 24, 25, 120, 120, 120, 120, 26, 
+	120, 22, 23, 23, 24, 25, 120, 122, 
+	123, 124, 125, 35, 36, 121, 126, 121, 
+	121, 37, 121, 121, 121, 127, 121, 128, 
+	123, 125, 125, 35, 36, 121, 126, 121, 
+	121, 121, 121, 121, 121, 127, 121, 123, 
+	125, 125, 35, 36, 121, 126, 121, 121, 
+	121, 121, 121, 121, 127, 121, 129, 121, 
+	121, 121, 130, 131, 121, 36, 121, 126, 
+	121, 121, 121, 121, 121, 129, 121, 122, 
+	123, 124, 52, 35, 36, 121, 126, 121, 
+	121, 37, 121, 121, 121, 127, 121, 129, 
+	121, 121, 121, 132, 131, 121, 36, 121, 
+	126, 121, 121, 121, 121, 121, 129, 121, 
+	126, 121, 121, 133, 121, 126, 121, 126, 
+	121, 126, 121, 121, 121, 121, 126, 121, 
+	129, 121, 134, 121, 132, 132, 121, 36, 
+	121, 126, 121, 121, 121, 121, 121, 129, 
+	121, 129, 121, 121, 121, 132, 132, 121, 
+	36, 121, 126, 121, 121, 121, 121, 121, 
+	129, 121, 135, 40, 136, 137, 35, 36, 
+	121, 126, 121, 40, 136, 137, 35, 36, 
+	121, 126, 121, 136, 136, 35, 36, 121, 
+	126, 121, 122, 123, 125, 125, 35, 36, 
+	121, 126, 121, 121, 121, 121, 121, 121, 
+	127, 121, 138, 139, 139, 35, 36, 121, 
+	126, 121, 130, 140, 121, 36, 121, 126, 
+	121, 132, 132, 121, 36, 121, 126, 121, 
+	130, 121, 132, 132, 121, 36, 121, 126, 
+	121, 132, 140, 121, 36, 121, 126, 121, 
+	45, 46, 47, 48, 109, 105, 24, 25, 
+	103, 51, 52, 52, 26, 103, 103, 45, 
+	55, 103, 59, 141, 61, 62, 4, 1, 
+	58, 63, 58, 58, 9, 58, 58, 58, 
+	64, 58, 45, 46, 47, 48, 142, 143, 
+	24, 144, 58, 145, 58, 52, 26, 58, 
+	58, 45, 55, 58, 22, 146, 146, 24, 
+	144, 58, 63, 58, 58, 26, 58, 145, 
+	58, 58, 147, 58, 145, 58, 145, 58, 
+	145, 58, 58, 58, 58, 145, 58, 45, 
+	58, 71, 22, 146, 146, 24, 144, 58, 
+	63, 58, 58, 58, 58, 58, 45, 58, 
+	149, 148, 150, 150, 148, 43, 148, 151, 
+	148, 150, 150, 148, 43, 148, 151, 148, 
+	151, 148, 148, 152, 148, 151, 148, 151, 
+	148, 151, 148, 148, 148, 148, 151, 148, 
+	45, 120, 120, 120, 120, 120, 120, 120, 
+	120, 120, 52, 120, 120, 120, 120, 45, 
+	120, 0
 };
 
-static const short _indic_syllable_machine_trans_targs[] = {
-	138, 160, 166, 2, 167, 3, 5, 170, 
-	6, 8, 173, 9, 11, 176, 12, 14, 
-	15, 159, 17, 18, 175, 20, 21, 172, 
-	23, 24, 169, 179, 183, 184, 188, 189, 
-	193, 194, 198, 199, 138, 222, 228, 36, 
-	229, 37, 39, 232, 40, 42, 235, 43, 
-	45, 238, 46, 48, 49, 221, 51, 52, 
-	237, 54, 55, 234, 57, 58, 231, 241, 
-	245, 246, 250, 251, 255, 256, 260, 262, 
-	138, 283, 289, 70, 290, 138, 71, 73, 
-	293, 74, 76, 296, 77, 79, 299, 80, 
-	82, 83, 282, 85, 86, 298, 88, 89, 
-	295, 91, 92, 292, 302, 306, 307, 311, 
-	312, 316, 317, 321, 138, 346, 352, 103, 
-	353, 104, 106, 356, 107, 109, 359, 110, 
-	112, 362, 113, 115, 116, 345, 118, 119, 
-	361, 121, 122, 358, 124, 125, 355, 365, 
-	369, 370, 374, 375, 379, 380, 384, 385, 
-	323, 138, 398, 138, 139, 201, 263, 265, 
-	322, 324, 285, 325, 386, 387, 301, 396, 
-	403, 138, 140, 142, 33, 200, 162, 178, 
-	141, 32, 143, 196, 144, 146, 31, 195, 
-	145, 30, 147, 191, 148, 150, 29, 190, 
-	149, 28, 151, 186, 152, 154, 27, 185, 
-	153, 26, 155, 181, 156, 158, 25, 180, 
-	157, 1, 165, 0, 161, 164, 163, 138, 
-	168, 4, 22, 171, 7, 19, 174, 10, 
-	16, 177, 13, 182, 187, 192, 197, 138, 
-	202, 204, 67, 261, 224, 240, 203, 66, 
-	205, 258, 206, 208, 65, 257, 207, 64, 
-	209, 253, 210, 212, 63, 252, 211, 62, 
-	213, 248, 214, 216, 61, 247, 215, 60, 
-	217, 243, 218, 220, 59, 242, 219, 35, 
-	227, 34, 223, 226, 225, 138, 230, 38, 
-	56, 233, 41, 53, 236, 44, 50, 239, 
-	47, 244, 249, 254, 259, 138, 264, 100, 
-	266, 319, 267, 269, 99, 318, 268, 98, 
-	270, 314, 271, 273, 97, 313, 272, 96, 
-	274, 309, 275, 277, 95, 308, 276, 94, 
-	278, 304, 279, 281, 93, 303, 280, 69, 
-	288, 68, 284, 287, 286, 138, 291, 72, 
-	90, 294, 75, 87, 297, 78, 84, 300, 
-	81, 305, 310, 315, 320, 138, 138, 326, 
-	328, 134, 133, 348, 364, 327, 329, 382, 
-	330, 332, 132, 381, 331, 131, 333, 377, 
-	334, 336, 130, 376, 335, 129, 337, 372, 
-	338, 340, 128, 371, 339, 127, 341, 367, 
-	342, 344, 126, 366, 343, 102, 351, 101, 
-	347, 350, 349, 138, 354, 105, 123, 357, 
-	108, 120, 360, 111, 117, 363, 114, 368, 
-	373, 378, 383, 135, 388, 389, 395, 390, 
-	392, 136, 391, 394, 393, 138, 397, 137, 
-	400, 399, 402, 401, 138
+static const unsigned char _indic_syllable_machine_trans_targs[] = {
+	39, 45, 50, 2, 51, 5, 6, 53, 
+	57, 58, 39, 67, 11, 73, 68, 14, 
+	15, 75, 80, 81, 84, 39, 89, 21, 
+	95, 90, 98, 39, 24, 25, 97, 103, 
+	39, 112, 30, 118, 113, 121, 33, 34, 
+	120, 126, 39, 137, 39, 40, 60, 85, 
+	87, 105, 106, 91, 107, 127, 128, 99, 
+	135, 140, 39, 41, 43, 8, 59, 46, 
+	54, 42, 1, 44, 48, 0, 47, 49, 
+	52, 3, 4, 55, 7, 56, 39, 61, 
+	63, 18, 83, 69, 76, 62, 9, 64, 
+	78, 71, 65, 17, 82, 66, 10, 70, 
+	72, 74, 12, 13, 77, 16, 79, 39, 
+	86, 26, 88, 101, 93, 19, 104, 20, 
+	92, 94, 96, 22, 23, 100, 27, 102, 
+	39, 39, 108, 110, 28, 35, 114, 122, 
+	109, 111, 124, 116, 29, 115, 117, 119, 
+	31, 32, 123, 36, 125, 129, 130, 134, 
+	131, 132, 37, 133, 39, 136, 38, 138, 
+	139
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
 	1, 0, 2, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 0, 2, 2, 2, 2, 2, 2, 
-	2, 2, 2, 2, 3, 0, 2, 0, 
-	2, 0, 0, 2, 0, 0, 2, 0, 
-	0, 2, 0, 0, 0, 2, 0, 0, 
-	2, 0, 0, 2, 0, 0, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	4, 0, 2, 0, 2, 5, 0, 0, 
-	2, 0, 0, 2, 0, 0, 2, 0, 
-	0, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 0, 2, 6, 2, 6, 2, 
-	6, 2, 6, 2, 7, 0, 2, 0, 
-	2, 0, 0, 2, 0, 0, 2, 0, 
-	0, 2, 0, 0, 0, 2, 0, 0, 
-	2, 0, 0, 2, 0, 0, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	6, 8, 0, 11, 2, 2, 6, 0, 
-	12, 12, 0, 2, 6, 2, 6, 2, 
-	0, 13, 2, 0, 0, 2, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 2, 2, 0, 0, 2, 
-	2, 0, 2, 0, 0, 0, 0, 14, 
-	2, 0, 0, 2, 0, 0, 2, 0, 
-	0, 2, 0, 2, 2, 2, 2, 15, 
-	2, 0, 0, 2, 0, 2, 2, 0, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 2, 2, 0, 0, 2, 2, 0, 
-	2, 0, 0, 0, 0, 16, 2, 0, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 2, 2, 2, 2, 17, 6, 0, 
-	6, 2, 6, 0, 0, 6, 6, 0, 
-	6, 2, 6, 0, 0, 6, 6, 0, 
-	6, 2, 6, 0, 0, 6, 6, 0, 
-	6, 2, 6, 0, 0, 6, 6, 0, 
-	2, 0, 0, 0, 0, 18, 2, 0, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 2, 2, 2, 2, 19, 20, 2, 
-	0, 0, 0, 0, 2, 2, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 2, 
-	2, 0, 0, 2, 2, 0, 2, 0, 
-	0, 0, 0, 21, 2, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 2, 
-	2, 2, 2, 0, 0, 22, 22, 0, 
-	0, 0, 0, 0, 0, 23, 2, 0, 
-	0, 0, 0, 0, 24
+	2, 2, 3, 2, 0, 2, 0, 0, 
+	0, 2, 2, 2, 2, 4, 2, 0, 
+	5, 0, 5, 6, 0, 0, 5, 2, 
+	7, 2, 0, 2, 0, 2, 0, 0, 
+	2, 2, 8, 0, 11, 2, 2, 5, 
+	0, 12, 12, 0, 2, 5, 2, 5, 
+	2, 0, 13, 2, 0, 0, 2, 0, 
+	2, 2, 0, 2, 2, 0, 0, 2, 
+	2, 0, 0, 0, 0, 2, 14, 2, 
+	0, 0, 2, 0, 2, 2, 0, 2, 
+	2, 2, 2, 0, 2, 2, 0, 0, 
+	2, 2, 0, 0, 0, 0, 2, 15, 
+	5, 0, 5, 2, 2, 0, 5, 0, 
+	0, 2, 5, 0, 0, 0, 0, 2, 
+	16, 17, 2, 0, 0, 0, 0, 2, 
+	2, 2, 2, 2, 0, 0, 2, 2, 
+	0, 0, 0, 0, 2, 0, 18, 18, 
+	0, 0, 0, 0, 19, 2, 0, 0, 
+	0
 };
 
 static const char _indic_syllable_machine_to_state_actions[] = {
@@ -823,6 +319,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 9, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -835,41 +332,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 9, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0
+	0, 0, 0, 0, 0
 };
 
 static const char _indic_syllable_machine_from_state_actions[] = {
@@ -877,6 +340,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 10, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -889,102 +353,35 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 10, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0
+	0, 0, 0, 0, 0
 };
 
 static const short _indic_syllable_machine_eof_trans[] = {
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 1, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 37, 37, 37, 37, 
-	37, 37, 37, 37, 73, 73, 78, 78, 
-	73, 73, 73, 73, 73, 73, 73, 73, 
-	73, 73, 73, 73, 73, 73, 73, 73, 
-	73, 73, 73, 73, 73, 73, 73, 73, 
-	73, 73, 73, 73, 73, 109, 109, 109, 
-	109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 109, 109, 109, 109, 109, 
-	109, 109, 109, 109, 109, 109, 109, 73, 
-	1, 146, 0, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 162, 162, 162, 162, 
-	162, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 224, 
-	224, 224, 224, 224, 224, 224, 224, 286, 
-	286, 286, 286, 286, 286, 286, 286, 286, 
-	286, 286, 286, 286, 286, 286, 286, 286, 
-	286, 286, 286, 286, 286, 286, 286, 286, 
-	286, 286, 286, 286, 286, 286, 286, 286, 
-	286, 286, 286, 286, 286, 286, 286, 286, 
-	286, 286, 286, 286, 286, 286, 286, 286, 
-	286, 286, 286, 286, 286, 286, 286, 286, 
-	286, 286, 342, 286, 342, 343, 343, 343, 
-	343, 343, 343, 343, 343, 343, 343, 343, 
-	343, 343, 343, 343, 343, 343, 343, 343, 
-	343, 343, 343, 343, 343, 343, 343, 343, 
-	343, 343, 343, 343, 343, 343, 343, 343, 
-	343, 343, 343, 343, 343, 343, 343, 343, 
-	343, 343, 343, 343, 343, 343, 343, 343, 
-	343, 343, 343, 343, 343, 343, 343, 343, 
-	343, 343, 286, 162, 162, 162, 162, 162, 
-	162, 162, 162, 162, 414, 414, 414, 414, 
-	414, 414, 414, 342
+	1, 11, 11, 11, 11, 11, 11, 11, 
+	11, 11, 11, 22, 22, 28, 22, 22, 
+	22, 22, 22, 22, 33, 33, 33, 33, 
+	33, 33, 33, 33, 33, 1, 43, 0, 
+	59, 59, 59, 59, 59, 59, 59, 59, 
+	59, 59, 59, 59, 59, 59, 59, 59, 
+	59, 59, 59, 59, 79, 79, 79, 79, 
+	79, 79, 79, 79, 79, 79, 79, 79, 
+	79, 79, 79, 79, 79, 79, 79, 79, 
+	79, 79, 79, 79, 79, 104, 104, 104, 
+	104, 104, 104, 104, 104, 104, 104, 104, 
+	104, 104, 104, 104, 104, 104, 104, 104, 
+	104, 121, 121, 122, 122, 122, 122, 122, 
+	122, 122, 122, 122, 122, 122, 122, 122, 
+	122, 122, 122, 122, 122, 122, 122, 104, 
+	59, 59, 59, 59, 59, 59, 59, 149, 
+	149, 149, 149, 149, 121
 };
 
-static const int indic_syllable_machine_start = 138;
-static const int indic_syllable_machine_first_final = 138;
+static const int indic_syllable_machine_start = 39;
+static const int indic_syllable_machine_first_final = 39;
 static const int indic_syllable_machine_error = -1;
 
-static const int indic_syllable_machine_en_main = 138;
+static const int indic_syllable_machine_en_main = 39;
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.rl"
@@ -1010,7 +407,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 1014 "hb-ot-shape-complex-indic-machine.hh"
+#line 411 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	cs = indic_syllable_machine_start;
 	ts = 0;
@@ -1026,12 +423,12 @@
 
   unsigned int syllable_serial = 1;
   
-#line 1030 "hb-ot-shape-complex-indic-machine.hh"
+#line 427 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
-	const short *_inds;
+	const unsigned char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
@@ -1040,7 +437,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 1044 "hb-ot-shape-complex-indic-machine.hh"
+#line 441 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -1062,26 +459,6 @@
 #line 1 "NONE"
 	{te = p+1;}
 	break;
-	case 14:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (consonant_syllable); }}
-	break;
-	case 16:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (vowel_syllable); }}
-	break;
-	case 21:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (standalone_cluster); }}
-	break;
-	case 24:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (symbol_cluster); }}
-	break;
-	case 18:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
-	{te = p+1;{ found_syllable (broken_cluster); }}
-	break;
 	case 11:
 #line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (non_indic_cluster); }}
@@ -1090,23 +467,23 @@
 #line 84 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
-	case 15:
+	case 14:
 #line 85 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (vowel_syllable); }}
 	break;
-	case 20:
+	case 17:
 #line 86 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (standalone_cluster); }}
 	break;
-	case 23:
+	case 19:
 #line 87 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (symbol_cluster); }}
 	break;
-	case 17:
+	case 15:
 #line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
-	case 19:
+	case 16:
 #line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (non_indic_cluster); }}
 	break;
@@ -1130,7 +507,7 @@
 #line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
-	case 5:
+	case 6:
 #line 1 "NONE"
 	{	switch( act ) {
 	case 1:
@@ -1145,13 +522,13 @@
 	}
 	}
 	break;
-	case 22:
+	case 18:
 #line 1 "NONE"
 	{te = p+1;}
 #line 84 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 1;}
 	break;
-	case 6:
+	case 5:
 #line 1 "NONE"
 	{te = p+1;}
 #line 88 "hb-ot-shape-complex-indic-machine.rl"
@@ -1163,7 +540,7 @@
 #line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 6;}
 	break;
-#line 1167 "hb-ot-shape-complex-indic-machine.hh"
+#line 544 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 _again:
@@ -1172,7 +549,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 1176 "hb-ot-shape-complex-indic-machine.hh"
+#line 553 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	if ( ++p != pe )
diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl
index f7e022b..a2a88af 100644
--- a/src/hb-ot-shape-complex-indic-machine.rl
+++ b/src/hb-ot-shape-complex-indic-machine.rl
@@ -64,14 +64,14 @@
 cn = c.ZWJ?.n?;
 forced_rakar = ZWJ H ZWJ Ra;
 symbol = Symbol.N?;
-matra_group = z{0,3}.M.N?.(H | forced_rakar)?;
-syllable_tail = (z?.SM.SM?.ZWNJ?)? A{0,3}?;
+matra_group = z*.M.N?.(H | forced_rakar)?;
+syllable_tail = (z?.SM.SM?.ZWNJ?)? A*;
 halant_group = (z?.H.(ZWJ.N?)?);
 final_halant_group = halant_group | H.ZWNJ;
 medial_group = CM?;
-halant_or_matra_group = (final_halant_group | matra_group{0,4});
+halant_or_matra_group = (final_halant_group | matra_group*);
 
-complex_syllable_tail = (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail;
+complex_syllable_tail = (halant_group.cn)* medial_group halant_or_matra_group syllable_tail;
 
 consonant_syllable =	(Repha|CS)? cn complex_syllable_tail;
 vowel_syllable =	reph? V.n? (ZWJ | complex_syllable_tail);
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index 6d46fe3..f8cb574 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -274,7 +274,11 @@
   const indic_config_t *config;
 
   bool is_old_spec;
+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
   bool uniscribe_bug_compatible;
+#else
+  static constexpr bool uniscribe_bug_compatible = false;
+#endif
   mutable hb_atomic_int_t virama_glyph;
 
   would_substitute_feature_t rphf;
@@ -300,7 +304,9 @@
     }
 
   indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
   indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
+#endif
   indic_plan->virama_glyph.set_relaxed (-1);
 
   /* Use zero-context would_substitute() matching for new-spec of the main
@@ -645,7 +651,7 @@
   /* Reorder characters */
 
   for (unsigned int i = start; i < base; i++)
-    info[i].indic_position() = MIN (POS_PRE_C, (indic_position_t) info[i].indic_position());
+    info[i].indic_position() = hb_min (POS_PRE_C, (indic_position_t) info[i].indic_position());
 
   if (base < end)
     info[base].indic_position() = POS_BASE_C;
@@ -801,7 +807,7 @@
 	  unsigned int j = start + info[i].syllable();
 	  while (j != i)
 	  {
-	    max = MAX (max, j);
+	    max = hb_max (max, j);
 	    unsigned int next = start + info[j].syllable();
 	    info[j].syllable() = 255; /* So we don't process j later again. */
 	    j = next;
@@ -918,11 +924,10 @@
 				       hb_buffer_t *buffer,
 				       unsigned int start, unsigned int end)
 {
-  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
-
   /* We treat placeholder/dotted-circle as if they are consonants, so we
    * should just chain.  Only if not in compatibility mode that is... */
 
+  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
   if (indic_plan->uniscribe_bug_compatible)
   {
     /* For dotted-circle, this is what Uniscribe does:
@@ -1231,14 +1236,14 @@
 
 	  /* Note: this merge_clusters() is intentionally *after* the reordering.
 	   * Indic matra reordering is special and tricky... */
-	  buffer->merge_clusters (new_pos, MIN (end, base + 1));
+	  buffer->merge_clusters (new_pos, hb_min (end, base + 1));
 
 	  new_pos--;
 	}
     } else {
       for (unsigned int i = start; i < base; i++)
 	if (info[i].indic_position () == POS_PRE_M) {
-	  buffer->merge_clusters (i, MIN (end, base + 1));
+	  buffer->merge_clusters (i, hb_min (end, base + 1));
 	  break;
 	}
     }
@@ -1371,13 +1376,15 @@
        * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
        */
       if (!indic_plan->uniscribe_bug_compatible &&
-	  unlikely (is_halant (info[new_reph_pos]))) {
+	  unlikely (is_halant (info[new_reph_pos])))
+      {
 	for (unsigned int i = base + 1; i < new_reph_pos; i++)
 	  if (info[i].indic_category() == OT_M) {
 	    /* Ok, got it. */
 	    new_reph_pos--;
 	  }
       }
+
       goto reph_move;
     }
 
@@ -1590,11 +1597,10 @@
      *   https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping
      */
 
+
     const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
-
     hb_codepoint_t glyph;
-
-    if (hb_options ().uniscribe_bug_compatible ||
+    if (indic_plan->uniscribe_bug_compatible ||
 	(c->font->get_nominal_glyph (ab, &glyph) &&
 	 indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
     {
diff --git a/src/hb-ot-shape-complex-indic.hh b/src/hb-ot-shape-complex-indic.hh
index 13ab516..dc8f8c7 100644
--- a/src/hb-ot-shape-complex-indic.hh
+++ b/src/hb-ot-shape-complex-indic.hh
@@ -278,7 +278,7 @@
     case POS_POST_C:	return MATRA_POS_RIGHT (u);
     case POS_ABOVE_C:	return MATRA_POS_TOP (u);
     case POS_BELOW_C:	return MATRA_POS_BOTTOM (u);
-  };
+  }
   return side;
 }
 
diff --git a/src/hb-ot-shape-complex-khmer.hh b/src/hb-ot-shape-complex-khmer.hh
index 6222945..21015c7 100644
--- a/src/hb-ot-shape-complex-khmer.hh
+++ b/src/hb-ot-shape-complex-khmer.hh
@@ -105,7 +105,7 @@
       case POS_ABOVE_C:	cat = OT_VAbv; break;
       case POS_POST_C:	cat = OT_VPst; break;
       default: assert (0);
-    };
+    }
 
   info.khmer_category() = cat;
 }
diff --git a/src/hb-ot-shape-complex-myanmar-machine.hh b/src/hb-ot-shape-complex-myanmar-machine.hh
index 0c19e4f..b7b04cb 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -36,29 +36,31 @@
 static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
 	1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 
-	5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 30u, 3u, 29u, 1u, 32u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 32u, 8u, 8u, 
-	0
+	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
+	5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 
+	3u, 29u, 3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
+	3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 
+	3u, 29u, 1u, 32u, 1u, 32u, 8u, 8u, 0
 };
 
 static const char _myanmar_syllable_machine_key_spans[] = {
 	32, 28, 25, 4, 25, 23, 21, 21, 
 	27, 27, 27, 27, 16, 27, 27, 27, 
-	27, 27, 28, 27, 27, 27, 27, 25, 
-	4, 25, 23, 21, 21, 27, 27, 27, 
-	27, 28, 27, 32, 27, 27, 27, 27, 
-	27, 28, 27, 27, 27, 27, 32, 1
+	27, 27, 28, 27, 27, 27, 27, 27, 
+	25, 4, 25, 23, 21, 21, 27, 27, 
+	27, 27, 16, 28, 27, 27, 27, 27, 
+	27, 28, 27, 27, 27, 27, 27, 28, 
+	27, 32, 32, 1
 };
 
 static const short _myanmar_syllable_machine_index_offsets[] = {
 	0, 33, 62, 88, 93, 119, 143, 165, 
 	187, 215, 243, 271, 299, 316, 344, 372, 
 	400, 428, 456, 485, 513, 541, 569, 597, 
-	623, 628, 654, 678, 700, 722, 750, 778, 
-	806, 834, 863, 891, 924, 952, 980, 1008, 
-	1036, 1064, 1093, 1121, 1149, 1177, 1205, 1238
+	625, 651, 656, 682, 706, 728, 750, 778, 
+	806, 834, 862, 879, 908, 936, 964, 992, 
+	1020, 1048, 1077, 1105, 1133, 1161, 1189, 1217, 
+	1246, 1274, 1307, 1340
 };
 
 static const char _myanmar_syllable_machine_indicies[] = {
@@ -124,120 +126,134 @@
 	21, 21, 21, 21, 21, 21, 32, 33, 
 	34, 35, 36, 43, 21, 22, 21, 24, 
 	24, 21, 25, 21, 26, 21, 21, 21, 
-	21, 21, 21, 21, 43, 21, 21, 28, 
+	21, 21, 21, 21, 21, 21, 21, 28, 
 	21, 30, 21, 32, 33, 34, 35, 36, 
 	21, 22, 21, 24, 24, 21, 25, 21, 
 	26, 21, 21, 21, 21, 21, 21, 21, 
 	43, 21, 21, 28, 21, 21, 21, 32, 
 	33, 34, 35, 36, 21, 22, 21, 24, 
 	24, 21, 25, 21, 26, 21, 21, 21, 
-	21, 21, 21, 21, 43, 21, 21, 28, 
+	21, 21, 21, 21, 44, 21, 21, 28, 
 	29, 30, 21, 32, 33, 34, 35, 36, 
-	21, 22, 23, 24, 24, 21, 25, 21, 
+	21, 22, 21, 24, 24, 21, 25, 21, 
 	26, 21, 21, 21, 21, 21, 21, 21, 
-	27, 21, 21, 28, 29, 30, 31, 32, 
-	33, 34, 35, 36, 21, 3, 3, 44, 
-	5, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 45, 44, 44, 44, 44, 44, 
-	44, 14, 44, 44, 44, 18, 44, 3, 
-	3, 44, 5, 44, 3, 3, 44, 5, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	14, 44, 44, 44, 18, 44, 46, 44, 
-	3, 3, 44, 5, 44, 14, 44, 44, 
-	44, 44, 44, 44, 44, 47, 44, 44, 
-	44, 44, 44, 44, 14, 44, 3, 3, 
-	44, 5, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 47, 44, 44, 44, 44, 
-	44, 44, 14, 44, 3, 3, 44, 5, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	14, 44, 2, 44, 3, 3, 44, 5, 
-	44, 6, 44, 44, 44, 44, 44, 44, 
-	44, 48, 44, 44, 48, 44, 44, 44, 
-	14, 49, 44, 44, 18, 44, 2, 44, 
-	3, 3, 44, 5, 44, 6, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 14, 44, 44, 44, 
-	18, 44, 2, 44, 3, 3, 44, 5, 
-	44, 6, 44, 44, 44, 44, 44, 44, 
-	44, 48, 44, 44, 44, 44, 44, 44, 
-	14, 49, 44, 44, 18, 44, 2, 44, 
-	3, 3, 44, 5, 44, 6, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 14, 49, 44, 44, 
-	18, 44, 22, 23, 24, 24, 21, 25, 
-	21, 26, 21, 21, 21, 21, 21, 21, 
-	21, 50, 21, 21, 28, 29, 30, 31, 
-	32, 33, 34, 35, 36, 37, 21, 22, 
-	51, 24, 24, 21, 25, 21, 26, 21, 
-	21, 21, 21, 21, 21, 21, 27, 21, 
-	21, 28, 29, 30, 31, 32, 33, 34, 
-	35, 36, 21, 1, 1, 2, 3, 3, 
-	3, 44, 5, 44, 6, 1, 44, 44, 
-	44, 44, 1, 44, 8, 44, 44, 10, 
+	21, 21, 21, 28, 29, 30, 21, 32, 
+	33, 34, 35, 36, 21, 22, 23, 24, 
+	24, 21, 25, 21, 26, 21, 21, 21, 
+	21, 21, 21, 21, 27, 21, 21, 28, 
+	29, 30, 31, 32, 33, 34, 35, 36, 
+	21, 46, 46, 45, 5, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 47, 45, 
+	45, 45, 45, 45, 45, 14, 45, 45, 
+	45, 18, 45, 46, 46, 45, 5, 45, 
+	46, 46, 45, 5, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 14, 45, 45, 45, 
+	18, 45, 48, 45, 46, 46, 45, 5, 
+	45, 14, 45, 45, 45, 45, 45, 45, 
+	45, 49, 45, 45, 45, 45, 45, 45, 
+	14, 45, 46, 46, 45, 5, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 49, 
+	45, 45, 45, 45, 45, 45, 14, 45, 
+	46, 46, 45, 5, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 14, 45, 2, 45, 
+	46, 46, 45, 5, 45, 6, 45, 45, 
+	45, 45, 45, 45, 45, 50, 45, 45, 
+	50, 45, 45, 45, 14, 51, 45, 45, 
+	18, 45, 2, 45, 46, 46, 45, 5, 
+	45, 6, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	14, 45, 45, 45, 18, 45, 2, 45, 
+	46, 46, 45, 5, 45, 6, 45, 45, 
+	45, 45, 45, 45, 45, 50, 45, 45, 
+	45, 45, 45, 45, 14, 51, 45, 45, 
+	18, 45, 2, 45, 46, 46, 45, 5, 
+	45, 6, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	14, 51, 45, 45, 18, 45, 52, 52, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 52, 45, 2, 
+	3, 46, 46, 45, 5, 45, 6, 45, 
+	45, 45, 45, 45, 45, 45, 8, 45, 
+	45, 10, 11, 12, 13, 14, 15, 16, 
+	17, 18, 19, 45, 2, 45, 46, 46, 
+	45, 5, 45, 6, 45, 45, 45, 45, 
+	45, 45, 45, 8, 45, 45, 10, 11, 
+	12, 13, 14, 15, 16, 17, 18, 45, 
+	2, 45, 46, 46, 45, 5, 45, 6, 
+	45, 45, 45, 45, 45, 45, 45, 53, 
+	45, 45, 45, 45, 45, 45, 14, 15, 
+	16, 17, 18, 45, 2, 45, 46, 46, 
+	45, 5, 45, 6, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 14, 15, 16, 17, 18, 45, 
+	2, 45, 46, 46, 45, 5, 45, 6, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 14, 15, 
+	16, 45, 18, 45, 2, 45, 46, 46, 
+	45, 5, 45, 6, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 14, 45, 16, 45, 18, 45, 
+	2, 45, 46, 46, 45, 5, 45, 6, 
+	45, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 14, 15, 
+	16, 17, 18, 53, 45, 2, 45, 46, 
+	46, 45, 5, 45, 6, 45, 45, 45, 
+	45, 45, 45, 45, 45, 45, 45, 10, 
+	45, 12, 45, 14, 15, 16, 17, 18, 
+	45, 2, 45, 46, 46, 45, 5, 45, 
+	6, 45, 45, 45, 45, 45, 45, 45, 
+	53, 45, 45, 10, 45, 45, 45, 14, 
+	15, 16, 17, 18, 45, 2, 45, 46, 
+	46, 45, 5, 45, 6, 45, 45, 45, 
+	45, 45, 45, 45, 54, 45, 45, 10, 
+	11, 12, 45, 14, 15, 16, 17, 18, 
+	45, 2, 45, 46, 46, 45, 5, 45, 
+	6, 45, 45, 45, 45, 45, 45, 45, 
+	45, 45, 45, 10, 11, 12, 45, 14, 
+	15, 16, 17, 18, 45, 2, 3, 46, 
+	46, 45, 5, 45, 6, 45, 45, 45, 
+	45, 45, 45, 45, 8, 45, 45, 10, 
 	11, 12, 13, 14, 15, 16, 17, 18, 
-	19, 44, 1, 44, 2, 44, 3, 3, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 8, 44, 44, 10, 11, 
-	12, 13, 14, 15, 16, 17, 18, 44, 
-	2, 44, 3, 3, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 52, 
-	44, 44, 44, 44, 44, 44, 14, 15, 
-	16, 17, 18, 44, 2, 44, 3, 3, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 14, 15, 16, 17, 18, 44, 
-	2, 44, 3, 3, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 14, 15, 
-	16, 44, 18, 44, 2, 44, 3, 3, 
-	44, 5, 44, 6, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 14, 44, 16, 44, 18, 44, 
-	2, 44, 3, 3, 44, 5, 44, 6, 
-	44, 44, 44, 44, 44, 44, 44, 44, 
-	44, 44, 44, 44, 44, 44, 14, 15, 
-	16, 17, 18, 52, 44, 2, 44, 3, 
-	3, 44, 5, 44, 6, 44, 44, 44, 
-	44, 44, 44, 44, 52, 44, 44, 10, 
-	44, 12, 44, 14, 15, 16, 17, 18, 
-	44, 2, 44, 3, 3, 44, 5, 44, 
-	6, 44, 44, 44, 44, 44, 44, 44, 
-	52, 44, 44, 10, 44, 44, 44, 14, 
-	15, 16, 17, 18, 44, 2, 44, 3, 
-	3, 44, 5, 44, 6, 44, 44, 44, 
-	44, 44, 44, 44, 52, 44, 44, 10, 
-	11, 12, 44, 14, 15, 16, 17, 18, 
-	44, 2, 3, 3, 3, 44, 5, 44, 
-	6, 44, 44, 44, 44, 44, 44, 44, 
-	8, 44, 44, 10, 11, 12, 13, 14, 
-	15, 16, 17, 18, 44, 1, 1, 53, 
-	53, 53, 53, 53, 53, 53, 53, 1, 
-	53, 53, 53, 53, 1, 53, 53, 53, 
-	53, 53, 53, 53, 53, 53, 53, 53, 
-	53, 53, 53, 53, 1, 53, 54, 53, 
-	0
+	45, 22, 23, 24, 24, 21, 25, 21, 
+	26, 21, 21, 21, 21, 21, 21, 21, 
+	55, 21, 21, 28, 29, 30, 31, 32, 
+	33, 34, 35, 36, 37, 21, 22, 56, 
+	24, 24, 21, 25, 21, 26, 21, 21, 
+	21, 21, 21, 21, 21, 27, 21, 21, 
+	28, 29, 30, 31, 32, 33, 34, 35, 
+	36, 21, 1, 1, 2, 3, 46, 46, 
+	45, 5, 45, 6, 1, 45, 45, 45, 
+	45, 1, 45, 8, 45, 45, 10, 11, 
+	12, 13, 14, 15, 16, 17, 18, 19, 
+	45, 1, 45, 1, 1, 57, 57, 57, 
+	57, 57, 57, 57, 57, 1, 57, 57, 
+	57, 57, 1, 57, 57, 57, 57, 57, 
+	57, 57, 57, 57, 57, 57, 57, 57, 
+	57, 57, 1, 57, 58, 57, 0
 };
 
 static const char _myanmar_syllable_machine_trans_targs[] = {
-	0, 1, 23, 0, 0, 24, 30, 33, 
-	36, 46, 37, 42, 43, 44, 26, 39, 
-	40, 41, 29, 45, 47, 0, 2, 12, 
+	0, 1, 24, 34, 0, 25, 31, 47, 
+	36, 50, 37, 42, 43, 44, 27, 39, 
+	40, 41, 30, 46, 51, 0, 2, 12, 
 	0, 3, 9, 13, 14, 19, 20, 21, 
-	5, 16, 17, 18, 8, 22, 4, 6, 
-	7, 10, 11, 15, 0, 25, 27, 28, 
-	31, 32, 34, 35, 38, 0, 0
+	5, 16, 17, 18, 8, 23, 4, 6, 
+	7, 10, 11, 15, 22, 0, 0, 26, 
+	28, 29, 32, 33, 35, 38, 45, 48, 
+	49, 0, 0
 };
 
 static const char _myanmar_syllable_machine_trans_actions[] = {
-	3, 0, 0, 4, 5, 0, 0, 0, 
+	3, 0, 0, 0, 4, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 6, 0, 0, 
-	7, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 5, 0, 0, 
+	6, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 8, 0, 0, 0, 
-	0, 0, 0, 0, 0, 9, 10
+	0, 0, 0, 0, 0, 7, 8, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 9, 10
 };
 
 static const char _myanmar_syllable_machine_to_state_actions[] = {
@@ -246,7 +262,8 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0
 };
 
 static const char _myanmar_syllable_machine_from_state_actions[] = {
@@ -255,16 +272,18 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0
 };
 
 static const short _myanmar_syllable_machine_eof_trans[] = {
 	0, 22, 22, 22, 22, 22, 22, 22, 
 	22, 22, 22, 22, 22, 22, 22, 22, 
-	22, 22, 22, 22, 22, 22, 22, 45, 
-	45, 45, 45, 45, 45, 45, 45, 45, 
-	45, 22, 22, 45, 45, 45, 45, 45, 
-	45, 45, 45, 45, 45, 45, 54, 54
+	22, 22, 22, 22, 22, 22, 22, 22, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 46, 
+	46, 46, 46, 46, 46, 46, 46, 22, 
+	22, 46, 58, 58
 };
 
 static const int myanmar_syllable_machine_start = 0;
@@ -297,7 +316,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 301 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 320 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	cs = myanmar_syllable_machine_start;
 	ts = 0;
@@ -313,7 +332,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 317 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 336 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -327,7 +346,7 @@
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 331 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 350 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -345,11 +364,11 @@
 		goto _again;
 
 	switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
-	case 7:
+	case 6:
 #line 86 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (consonant_syllable); }}
 	break;
-	case 5:
+	case 4:
 #line 87 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
 	break;
@@ -357,7 +376,7 @@
 #line 88 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (punctuation_cluster); }}
 	break;
-	case 4:
+	case 8:
 #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
@@ -365,11 +384,11 @@
 #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
 	break;
-	case 6:
+	case 5:
 #line 86 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
-	case 8:
+	case 7:
 #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
@@ -377,7 +396,7 @@
 #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
 	break;
-#line 381 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 400 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 _again:
@@ -386,7 +405,7 @@
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 390 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 409 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	if ( ++p != pe )
diff --git a/src/hb-ot-shape-complex-myanmar-machine.rl b/src/hb-ot-shape-complex-myanmar-machine.rl
index 7845a86..6659989 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.rl
+++ b/src/hb-ot-shape-complex-myanmar-machine.rl
@@ -69,15 +69,15 @@
 
 c = C|Ra;			# is_consonant
 
-medial_group = MY? MR? MW? MH? As?;
+medial_group = MY? As? MR? ((MW MH? | MH) As?)?;
 main_vowel_group = (VPre.VS?)* VAbv* VBlw* A* (DB As?)?;
 post_vowel_group = VPst MH? As* VAbv* A* (DB As?)?;
 pwo_tone_group = PT A* DB? As?;
 
 complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?;
-syllable_tail = (H | complex_syllable_tail);
+syllable_tail = (H (c|IV).VS?)* (H | complex_syllable_tail);
 
-consonant_syllable =	(k|CS)? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail;
+consonant_syllable =	(k|CS)? (c|IV|D|GB).VS? syllable_tail;
 punctuation_cluster = 	P V;
 broken_cluster =	k? VS? syllable_tail;
 other =			any;
diff --git a/src/hb-ot-shape-complex-myanmar.hh b/src/hb-ot-shape-complex-myanmar.hh
index 3e9537a..9ec78ef 100644
--- a/src/hb-ot-shape-complex-myanmar.hh
+++ b/src/hb-ot-shape-complex-myanmar.hh
@@ -146,7 +146,7 @@
       break;
 
     case 0xAA74u: case 0xAA75u: case 0xAA76u:
-      /* https://github.com/roozbehp/unicode-data/issues/3 */
+      /* https://github.com/harfbuzz/harfbuzz/issues/218 */
       cat = OT_C;
       break;
   }
diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc
index 130ea1c..22d4aa3 100644
--- a/src/hb-ot-shape-complex-thai.cc
+++ b/src/hb-ot-shape-complex-thai.cc
@@ -218,7 +218,7 @@
 		     hb_buffer_t              *buffer,
 		     hb_font_t                *font)
 {
-#if defined(HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK)
+#ifdef HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
   return;
 #endif
 
diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh
index c9410e4..01fe3d7 100644
--- a/src/hb-ot-shape-complex-use-machine.hh
+++ b/src/hb-ot-shape-complex-use-machine.hh
@@ -36,326 +36,344 @@
 
 #line 38 "hb-ot-shape-complex-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
-	12u, 44u, 1u, 15u, 1u, 1u, 12u, 44u, 0u, 44u, 21u, 21u, 8u, 44u, 8u, 44u,
-	1u, 15u, 1u, 1u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u,
-	8u, 39u, 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
-	8u, 44u, 8u, 44u, 8u, 44u, 1u, 39u, 8u, 44u, 13u, 21u, 4u, 4u, 13u, 13u,
-	8u, 44u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u,
-	8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
-	8u, 44u, 8u, 44u, 1u, 39u, 1u, 15u, 12u, 44u, 1u, 44u, 8u, 44u, 21u, 42u,
-	41u, 42u, 42u, 42u, 1u, 5u, 0
+	12u, 48u, 1u, 15u, 1u, 1u, 12u, 48u, 1u, 1u, 0u, 48u, 21u, 21u, 11u, 48u, 
+	11u, 48u, 1u, 15u, 1u, 1u, 11u, 48u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 
+	26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 
+	23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 11u, 48u, 
+	1u, 48u, 11u, 48u, 13u, 21u, 4u, 4u, 13u, 13u, 11u, 48u, 11u, 48u, 41u, 42u, 
+	42u, 42u, 11u, 48u, 11u, 48u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 
+	45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, 
+	23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 11u, 48u, 1u, 48u, 1u, 15u, 
+	4u, 4u, 13u, 21u, 13u, 13u, 12u, 48u, 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, 
+	21u, 42u, 1u, 5u, 0
 };
 
 static const char _use_syllable_machine_key_spans[] = {
-	33, 15, 1, 33, 45, 1, 37, 37,
-	15, 1, 37, 37, 32, 19, 19, 19,
-	32, 32, 32, 37, 37, 37, 37, 37,
-	37, 37, 37, 39, 37, 9, 1, 1,
-	37, 37, 37, 32, 19, 19, 19, 32,
-	32, 32, 37, 37, 37, 37, 37, 37,
-	37, 37, 39, 15, 33, 44, 37, 22,
-	2, 1, 5
+	37, 15, 1, 37, 1, 49, 1, 38, 
+	38, 15, 1, 38, 27, 26, 24, 23, 
+	22, 2, 1, 25, 25, 25, 1, 25, 
+	26, 26, 26, 27, 27, 27, 27, 38, 
+	48, 38, 9, 1, 1, 38, 38, 2, 
+	1, 38, 38, 27, 26, 24, 23, 22, 
+	2, 1, 25, 25, 25, 25, 26, 26, 
+	26, 27, 27, 27, 27, 38, 48, 15, 
+	1, 9, 1, 37, 48, 38, 2, 1, 
+	22, 5
 };
 
 static const short _use_syllable_machine_index_offsets[] = {
-	0, 34, 50, 52, 86, 132, 134, 172,
-	210, 226, 228, 266, 304, 337, 357, 377,
-	397, 430, 463, 496, 534, 572, 610, 648,
-	686, 724, 762, 800, 840, 878, 888, 890,
-	892, 930, 968, 1006, 1039, 1059, 1079, 1099,
-	1132, 1165, 1198, 1236, 1274, 1312, 1350, 1388,
-	1426, 1464, 1502, 1542, 1558, 1592, 1637, 1675,
-	1698, 1701, 1703
+	0, 38, 54, 56, 94, 96, 146, 148, 
+	187, 226, 242, 244, 283, 311, 338, 363, 
+	387, 410, 413, 415, 441, 467, 493, 495, 
+	521, 548, 575, 602, 630, 658, 686, 714, 
+	753, 802, 841, 851, 853, 855, 894, 933, 
+	936, 938, 977, 1016, 1044, 1071, 1096, 1120, 
+	1143, 1146, 1148, 1174, 1200, 1226, 1252, 1279, 
+	1306, 1333, 1361, 1389, 1417, 1445, 1484, 1533, 
+	1549, 1551, 1561, 1563, 1601, 1650, 1689, 1692, 
+	1694, 1717
 };
 
 static const char _use_syllable_machine_indicies[] = {
-	1, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	1, 0, 3, 2, 2, 2, 2, 2, 
+	1, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	1, 0, 0, 0, 1, 0, 3, 2, 
 	2, 2, 2, 2, 2, 2, 2, 2, 
-	4, 2, 3, 2, 6, 5, 5, 5,
-	5, 5, 5, 5, 5, 5, 5, 5,
-	5, 5, 5, 5, 5, 5, 5, 5,
-	5, 5, 5, 5, 5, 5, 5, 5,
-	5, 5, 5, 5, 6, 5, 7, 8,
-	9, 7, 10, 8, 9, 9, 11, 9, 
-	9, 3, 12, 9, 9, 13, 7, 7, 
-	14, 15, 9, 9, 16, 17, 18, 19, 
-	20, 21, 22, 16, 23, 24, 25, 26, 
-	27, 28, 9, 29, 30, 31, 9, 9, 
-	9, 32, 33, 9, 35, 34, 37, 36,
-	36, 38, 1, 36, 36, 39, 36, 36,
-	36, 36, 36, 40, 41, 42, 43, 44,
-	45, 46, 47, 41, 48, 40, 49, 50,
-	51, 52, 36, 53, 54, 55, 36, 36,
-	36, 36, 56, 36, 37, 36, 36, 38,
-	1, 36, 36, 39, 36, 36, 36, 36,
-	36, 57, 41, 42, 43, 44, 45, 46,
-	47, 41, 48, 49, 49, 50, 51, 52,
-	36, 53, 54, 55, 36, 36, 36, 36,
-	56, 36, 38, 58, 58, 58, 58, 58,
-	58, 58, 58, 58, 58, 58, 58, 58,
-	59, 58, 38, 58, 37, 36, 36, 38,
-	1, 36, 36, 39, 36, 36, 36, 36,
-	36, 36, 41, 42, 43, 44, 45, 46,
-	47, 41, 48, 49, 49, 50, 51, 52,
-	36, 53, 54, 55, 36, 36, 36, 36,
-	56, 36, 37, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	41, 42, 43, 44, 45, 36, 36, 36,
-	36, 36, 36, 50, 51, 52, 36, 53,
-	54, 55, 36, 36, 36, 36, 42, 36,
-	37, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 42,
-	43, 44, 45, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 53, 54, 55,
-	36, 37, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 43, 44, 45, 36, 37, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 44, 45,
-	36, 37, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 45, 36, 37, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 43, 44, 45,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 53, 54, 55, 36, 37, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 43, 44,
-	45, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 54, 55, 36, 37,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 43,
-	44, 45, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 55, 36,
-	37, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 42,
-	43, 44, 45, 36, 36, 36, 36, 36,
-	36, 50, 51, 52, 36, 53, 54, 55,
-	36, 36, 36, 36, 42, 36, 37, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 42, 43, 44,
-	45, 36, 36, 36, 36, 36, 36, 36,
-	51, 52, 36, 53, 54, 55, 36, 36,
-	36, 36, 42, 36, 37, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 42, 43, 44, 45, 36,
-	36, 36, 36, 36, 36, 36, 36, 52,
-	36, 53, 54, 55, 36, 36, 36, 36,
-	42, 36, 37, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	41, 42, 43, 44, 45, 36, 47, 41,
-	36, 36, 36, 50, 51, 52, 36, 53,
-	54, 55, 36, 36, 36, 36, 42, 36,
-	37, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 41, 42,
-	43, 44, 45, 36, 60, 41, 36, 36,
-	36, 50, 51, 52, 36, 53, 54, 55,
-	36, 36, 36, 36, 42, 36, 37, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 36, 36, 41, 42, 43, 44,
-	45, 36, 36, 41, 36, 36, 36, 50,
-	51, 52, 36, 53, 54, 55, 36, 36,
-	36, 36, 42, 36, 37, 36, 36, 36,
-	36, 36, 36, 36, 36, 36, 36, 36,
-	36, 36, 41, 42, 43, 44, 45, 46,
-	47, 41, 36, 36, 36, 50, 51, 52,
-	36, 53, 54, 55, 36, 36, 36, 36,
-	42, 36, 37, 36, 36, 38, 1, 36,
-	36, 39, 36, 36, 36, 36, 36, 36,
-	41, 42, 43, 44, 45, 46, 47, 41,
-	48, 36, 49, 50, 51, 52, 36, 53,
-	54, 55, 36, 36, 36, 36, 56, 36,
-	38, 58, 58, 58, 58, 58, 58, 37,
-	58, 58, 58, 58, 58, 58, 59, 58,
-	58, 58, 58, 58, 58, 58, 42, 43,
-	44, 45, 58, 58, 58, 58, 58, 58,
-	58, 58, 58, 58, 53, 54, 55, 58,
-	37, 36, 36, 38, 1, 36, 36, 39,
-	36, 36, 36, 36, 36, 36, 41, 42,
-	43, 44, 45, 46, 47, 41, 48, 40,
-	49, 50, 51, 52, 36, 53, 54, 55,
-	36, 36, 36, 36, 56, 36, 62, 61,
-	61, 61, 61, 61, 61, 61, 63, 61,
-	10, 64, 62, 61, 11, 65, 65, 3,
-	6, 65, 65, 66, 65, 65, 65, 65,
-	65, 67, 16, 17, 18, 19, 20, 21,
-	22, 16, 23, 25, 25, 26, 27, 28,
-	65, 29, 30, 31, 65, 65, 65, 65,
-	33, 65, 11, 65, 65, 3, 6, 65,
-	65, 66, 65, 65, 65, 65, 65, 65,
-	16, 17, 18, 19, 20, 21, 22, 16, 
-	23, 25, 25, 26, 27, 28, 65, 29,
-	30, 31, 65, 65, 65, 65, 33, 65,
-	11, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 16, 17,
-	18, 19, 20, 65, 65, 65, 65, 65,
-	65, 26, 27, 28, 65, 29, 30, 31,
-	65, 65, 65, 65, 17, 65, 11, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 17, 18, 19,
-	20, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 29, 30, 31, 65, 11,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 18,
-	19, 20, 65, 11, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 19, 20, 65, 11,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 20, 65, 11, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 18, 19, 20, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	29, 30, 31, 65, 11, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 18, 19, 20, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 30, 31, 65, 11, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 18, 19, 20,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 31, 65, 11, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 17, 18, 19,
-	20, 65, 65, 65, 65, 65, 65, 26,
-	27, 28, 65, 29, 30, 31, 65, 65,
-	65, 65, 17, 65, 11, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 17, 18, 19, 20, 65,
-	65, 65, 65, 65, 65, 65, 27, 28,
-	65, 29, 30, 31, 65, 65, 65, 65,
-	17, 65, 11, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 17, 18, 19, 20, 65, 65, 65,
-	65, 65, 65, 65, 65, 28, 65, 29,
-	30, 31, 65, 65, 65, 65, 17, 65,
-	11, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 16, 17,
-	18, 19, 20, 65, 22, 16, 65, 65,
-	65, 26, 27, 28, 65, 29, 30, 31,
-	65, 65, 65, 65, 17, 65, 11, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 16, 17, 18, 19,
-	20, 65, 68, 16, 65, 65, 65, 26,
-	27, 28, 65, 29, 30, 31, 65, 65,
-	65, 65, 17, 65, 11, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 16, 17, 18, 19, 20, 65,
-	65, 16, 65, 65, 65, 26, 27, 28,
-	65, 29, 30, 31, 65, 65, 65, 65,
-	17, 65, 11, 65, 65, 65, 65, 65,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	16, 17, 18, 19, 20, 21, 22, 16,
-	65, 65, 65, 26, 27, 28, 65, 29,
-	30, 31, 65, 65, 65, 65, 17, 65,
-	11, 65, 65, 3, 6, 65, 65, 66,
-	65, 65, 65, 65, 65, 65, 16, 17,
-	18, 19, 20, 21, 22, 16, 23, 65,
-	25, 26, 27, 28, 65, 29, 30, 31,
-	65, 65, 65, 65, 33, 65, 3, 65,
-	65, 65, 65, 65, 65, 11, 65, 65,
-	65, 65, 65, 65, 4, 65, 65, 65,
-	65, 65, 65, 65, 17, 18, 19, 20,
-	65, 65, 65, 65, 65, 65, 65, 65,
-	65, 65, 29, 30, 31, 65, 3, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 4, 69, 6, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 69, 69, 69, 69,
-	69, 69, 69, 69, 69, 69, 6, 69,
-	8, 65, 65, 65, 8, 65, 65, 11,
-	65, 65, 3, 6, 65, 65, 66, 65,
-	65, 65, 65, 65, 65, 16, 17, 18,
-	19, 20, 21, 22, 16, 23, 24, 25, 
-	26, 27, 28, 65, 29, 30, 31, 65,
-	65, 65, 65, 33, 65, 11, 65, 65,
-	3, 6, 65, 65, 66, 65, 65, 65,
-	65, 65, 65, 16, 17, 18, 19, 20,
-	21, 22, 16, 23, 24, 25, 26, 27,
-	28, 65, 29, 30, 31, 65, 65, 65,
-	65, 33, 65, 71, 70, 70, 70, 70,
-	70, 70, 70, 70, 70, 70, 70, 70,
-	70, 70, 70, 70, 70, 70, 70, 71,
-	72, 70, 71, 72, 70, 72, 70, 8,
-	69, 69, 69, 8, 69, 0
+	2, 2, 2, 2, 4, 2, 3, 2, 
+	6, 5, 5, 5, 5, 5, 5, 5, 
+	5, 5, 5, 5, 5, 5, 5, 5, 
+	5, 5, 5, 5, 5, 5, 5, 5, 
+	5, 5, 5, 5, 5, 5, 5, 5, 
+	6, 5, 5, 5, 6, 5, 7, 5, 
+	8, 9, 10, 8, 11, 12, 10, 10, 
+	10, 10, 10, 3, 13, 14, 10, 15, 
+	8, 8, 16, 17, 10, 10, 18, 19, 
+	20, 21, 22, 23, 24, 18, 25, 26, 
+	27, 28, 29, 30, 10, 31, 32, 33, 
+	10, 34, 35, 36, 37, 38, 39, 40, 
+	13, 10, 42, 41, 44, 1, 43, 43, 
+	45, 43, 43, 43, 43, 43, 46, 47, 
+	48, 49, 50, 51, 52, 53, 47, 54, 
+	46, 55, 56, 57, 58, 43, 59, 60, 
+	61, 43, 43, 43, 43, 62, 63, 64, 
+	65, 1, 43, 44, 1, 43, 43, 45, 
+	43, 43, 43, 43, 43, 66, 47, 48, 
+	49, 50, 51, 52, 53, 47, 54, 55, 
+	55, 56, 57, 58, 43, 59, 60, 61, 
+	43, 43, 43, 43, 62, 63, 64, 65, 
+	1, 43, 44, 67, 67, 67, 67, 67, 
+	67, 67, 67, 67, 67, 67, 67, 67, 
+	68, 67, 44, 67, 44, 1, 43, 43, 
+	45, 43, 43, 43, 43, 43, 43, 47, 
+	48, 49, 50, 51, 52, 53, 47, 54, 
+	55, 55, 56, 57, 58, 43, 59, 60, 
+	61, 43, 43, 43, 43, 62, 63, 64, 
+	65, 1, 43, 47, 48, 49, 50, 51, 
+	43, 43, 43, 43, 43, 43, 56, 57, 
+	58, 43, 59, 60, 61, 43, 43, 43, 
+	43, 48, 63, 64, 65, 69, 43, 48, 
+	49, 50, 51, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 59, 60, 61, 
+	43, 43, 43, 43, 43, 63, 64, 65, 
+	69, 43, 49, 50, 51, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 63, 
+	64, 65, 43, 50, 51, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 63, 
+	64, 65, 43, 51, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 63, 64, 
+	65, 43, 63, 64, 43, 64, 43, 49, 
+	50, 51, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 59, 60, 61, 43, 
+	43, 43, 43, 43, 63, 64, 65, 69, 
+	43, 49, 50, 51, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 60, 
+	61, 43, 43, 43, 43, 43, 63, 64, 
+	65, 69, 43, 49, 50, 51, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 61, 43, 43, 43, 43, 43, 
+	63, 64, 65, 69, 43, 71, 70, 49, 
+	50, 51, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 63, 64, 65, 69, 
+	43, 48, 49, 50, 51, 43, 43, 43, 
+	43, 43, 43, 56, 57, 58, 43, 59, 
+	60, 61, 43, 43, 43, 43, 48, 63, 
+	64, 65, 69, 43, 48, 49, 50, 51, 
+	43, 43, 43, 43, 43, 43, 43, 57, 
+	58, 43, 59, 60, 61, 43, 43, 43, 
+	43, 48, 63, 64, 65, 69, 43, 48, 
+	49, 50, 51, 43, 43, 43, 43, 43, 
+	43, 43, 43, 58, 43, 59, 60, 61, 
+	43, 43, 43, 43, 48, 63, 64, 65, 
+	69, 43, 47, 48, 49, 50, 51, 43, 
+	53, 47, 43, 43, 43, 56, 57, 58, 
+	43, 59, 60, 61, 43, 43, 43, 43, 
+	48, 63, 64, 65, 69, 43, 47, 48, 
+	49, 50, 51, 43, 72, 47, 43, 43, 
+	43, 56, 57, 58, 43, 59, 60, 61, 
+	43, 43, 43, 43, 48, 63, 64, 65, 
+	69, 43, 47, 48, 49, 50, 51, 43, 
+	43, 47, 43, 43, 43, 56, 57, 58, 
+	43, 59, 60, 61, 43, 43, 43, 43, 
+	48, 63, 64, 65, 69, 43, 47, 48, 
+	49, 50, 51, 52, 53, 47, 43, 43, 
+	43, 56, 57, 58, 43, 59, 60, 61, 
+	43, 43, 43, 43, 48, 63, 64, 65, 
+	69, 43, 44, 1, 43, 43, 45, 43, 
+	43, 43, 43, 43, 43, 47, 48, 49, 
+	50, 51, 52, 53, 47, 54, 43, 55, 
+	56, 57, 58, 43, 59, 60, 61, 43, 
+	43, 43, 43, 62, 63, 64, 65, 1, 
+	43, 44, 67, 67, 67, 67, 67, 67, 
+	67, 67, 67, 67, 67, 67, 67, 68, 
+	67, 67, 67, 67, 67, 67, 67, 48, 
+	49, 50, 51, 67, 67, 67, 67, 67, 
+	67, 67, 67, 67, 67, 59, 60, 61, 
+	67, 67, 67, 67, 67, 63, 64, 65, 
+	69, 67, 44, 1, 43, 43, 45, 43, 
+	43, 43, 43, 43, 43, 47, 48, 49, 
+	50, 51, 52, 53, 47, 54, 46, 55, 
+	56, 57, 58, 43, 59, 60, 61, 43, 
+	43, 43, 43, 62, 63, 64, 65, 1, 
+	43, 74, 73, 73, 73, 73, 73, 73, 
+	73, 75, 73, 11, 76, 74, 73, 44, 
+	1, 43, 43, 45, 43, 43, 43, 43, 
+	43, 77, 47, 48, 49, 50, 51, 52, 
+	53, 47, 54, 46, 55, 56, 57, 58, 
+	43, 59, 60, 61, 43, 78, 79, 43, 
+	62, 63, 64, 65, 1, 43, 44, 1, 
+	43, 43, 45, 43, 43, 43, 43, 43, 
+	43, 47, 48, 49, 50, 51, 52, 53, 
+	47, 54, 46, 55, 56, 57, 58, 43, 
+	59, 60, 61, 43, 78, 79, 43, 62, 
+	63, 64, 65, 1, 43, 78, 79, 80, 
+	79, 80, 3, 6, 81, 81, 82, 81, 
+	81, 81, 81, 81, 83, 18, 19, 20, 
+	21, 22, 23, 24, 18, 25, 27, 27, 
+	28, 29, 30, 81, 31, 32, 33, 81, 
+	81, 81, 81, 37, 38, 39, 40, 6, 
+	81, 3, 6, 81, 81, 82, 81, 81, 
+	81, 81, 81, 81, 18, 19, 20, 21, 
+	22, 23, 24, 18, 25, 27, 27, 28, 
+	29, 30, 81, 31, 32, 33, 81, 81, 
+	81, 81, 37, 38, 39, 40, 6, 81, 
+	18, 19, 20, 21, 22, 81, 81, 81, 
+	81, 81, 81, 28, 29, 30, 81, 31, 
+	32, 33, 81, 81, 81, 81, 19, 38, 
+	39, 40, 84, 81, 19, 20, 21, 22, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 31, 32, 33, 81, 81, 81, 
+	81, 81, 38, 39, 40, 84, 81, 20, 
+	21, 22, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 38, 39, 40, 81, 
+	21, 22, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 38, 39, 40, 81, 
+	22, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 38, 39, 40, 81, 38, 
+	39, 81, 39, 81, 20, 21, 22, 81, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	81, 31, 32, 33, 81, 81, 81, 81, 
+	81, 38, 39, 40, 84, 81, 20, 21, 
+	22, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 32, 33, 81, 81, 
+	81, 81, 81, 38, 39, 40, 84, 81, 
+	20, 21, 22, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 33, 
+	81, 81, 81, 81, 81, 38, 39, 40, 
+	84, 81, 20, 21, 22, 81, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 38, 
+	39, 40, 84, 81, 19, 20, 21, 22, 
+	81, 81, 81, 81, 81, 81, 28, 29, 
+	30, 81, 31, 32, 33, 81, 81, 81, 
+	81, 19, 38, 39, 40, 84, 81, 19, 
+	20, 21, 22, 81, 81, 81, 81, 81, 
+	81, 81, 29, 30, 81, 31, 32, 33, 
+	81, 81, 81, 81, 19, 38, 39, 40, 
+	84, 81, 19, 20, 21, 22, 81, 81, 
+	81, 81, 81, 81, 81, 81, 30, 81, 
+	31, 32, 33, 81, 81, 81, 81, 19, 
+	38, 39, 40, 84, 81, 18, 19, 20, 
+	21, 22, 81, 24, 18, 81, 81, 81, 
+	28, 29, 30, 81, 31, 32, 33, 81, 
+	81, 81, 81, 19, 38, 39, 40, 84, 
+	81, 18, 19, 20, 21, 22, 81, 85, 
+	18, 81, 81, 81, 28, 29, 30, 81, 
+	31, 32, 33, 81, 81, 81, 81, 19, 
+	38, 39, 40, 84, 81, 18, 19, 20, 
+	21, 22, 81, 81, 18, 81, 81, 81, 
+	28, 29, 30, 81, 31, 32, 33, 81, 
+	81, 81, 81, 19, 38, 39, 40, 84, 
+	81, 18, 19, 20, 21, 22, 23, 24, 
+	18, 81, 81, 81, 28, 29, 30, 81, 
+	31, 32, 33, 81, 81, 81, 81, 19, 
+	38, 39, 40, 84, 81, 3, 6, 81, 
+	81, 82, 81, 81, 81, 81, 81, 81, 
+	18, 19, 20, 21, 22, 23, 24, 18, 
+	25, 81, 27, 28, 29, 30, 81, 31, 
+	32, 33, 81, 81, 81, 81, 37, 38, 
+	39, 40, 6, 81, 3, 81, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	81, 81, 4, 81, 81, 81, 81, 81, 
+	81, 81, 19, 20, 21, 22, 81, 81, 
+	81, 81, 81, 81, 81, 81, 81, 81, 
+	31, 32, 33, 81, 81, 81, 81, 81, 
+	38, 39, 40, 84, 81, 3, 86, 86, 
+	86, 86, 86, 86, 86, 86, 86, 86, 
+	86, 86, 86, 4, 86, 87, 81, 14, 
+	81, 81, 81, 81, 81, 81, 81, 88, 
+	81, 14, 81, 6, 86, 86, 86, 86, 
+	86, 86, 86, 86, 86, 86, 86, 86, 
+	86, 86, 86, 86, 86, 86, 86, 86, 
+	86, 86, 86, 86, 86, 86, 86, 86, 
+	86, 86, 86, 6, 86, 86, 86, 6, 
+	86, 9, 81, 81, 81, 9, 81, 81, 
+	81, 81, 81, 3, 6, 14, 81, 82, 
+	81, 81, 81, 81, 81, 81, 18, 19, 
+	20, 21, 22, 23, 24, 18, 25, 26, 
+	27, 28, 29, 30, 81, 31, 32, 33, 
+	81, 34, 35, 81, 37, 38, 39, 40, 
+	6, 81, 3, 6, 81, 81, 82, 81, 
+	81, 81, 81, 81, 81, 18, 19, 20, 
+	21, 22, 23, 24, 18, 25, 26, 27, 
+	28, 29, 30, 81, 31, 32, 33, 81, 
+	81, 81, 81, 37, 38, 39, 40, 6, 
+	81, 34, 35, 81, 35, 81, 78, 80, 
+	80, 80, 80, 80, 80, 80, 80, 80, 
+	80, 80, 80, 80, 80, 80, 80, 80, 
+	80, 80, 78, 79, 80, 9, 86, 86, 
+	86, 9, 86, 0
 };
 
 static const char _use_syllable_machine_trans_targs[] = {
-	4, 8, 4, 32, 2, 4, 1, 5,
-	6, 4, 29, 4, 51, 52, 53, 55,
-	34, 35, 36, 37, 38, 45, 46, 48,
-	54, 49, 42, 43, 44, 39, 40, 41,
-	58, 50, 4, 4, 4, 4, 7, 0,
-	28, 11, 12, 13, 14, 15, 22, 23,
-	25, 26, 19, 20, 21, 16, 17, 18,
-	27, 10, 4, 9, 24, 4, 30, 31,
-	4, 4, 3, 33, 47, 4, 4, 56,
-	57
+	5, 9, 5, 41, 2, 5, 1, 53, 
+	6, 7, 5, 34, 37, 63, 64, 67, 
+	68, 72, 43, 44, 45, 46, 47, 57, 
+	58, 60, 69, 61, 54, 55, 56, 50, 
+	51, 52, 70, 71, 73, 62, 48, 49, 
+	5, 5, 5, 5, 8, 0, 33, 12, 
+	13, 14, 15, 16, 27, 28, 30, 31, 
+	24, 25, 26, 19, 20, 21, 32, 17, 
+	18, 5, 11, 5, 10, 22, 5, 23, 
+	29, 5, 35, 36, 5, 38, 39, 40, 
+	5, 5, 3, 42, 4, 59, 5, 65, 
+	66
 };
 
 static const char _use_syllable_machine_trans_actions[] = {
-	1, 0, 2, 3, 0, 4, 0, 0, 
-	7, 8, 0, 9, 10, 10, 3, 0, 
+	1, 0, 2, 3, 0, 4, 0, 5, 
+	0, 5, 8, 0, 5, 9, 0, 9, 
+	3, 0, 5, 5, 0, 0, 0, 5, 
+	5, 5, 3, 3, 5, 5, 5, 5, 
+	5, 5, 0, 0, 0, 3, 0, 0, 
+	10, 11, 12, 13, 5, 0, 5, 0, 
+	0, 0, 0, 0, 0, 0, 0, 5, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	3, 3, 0, 0, 0, 0, 0, 0, 
-	0, 3, 11, 12, 13, 14, 7, 0,
-	7, 0, 0, 0, 0, 0, 0, 0,
-	0, 7, 0, 0, 0, 0, 0, 0,
-	0, 7, 15, 0, 0, 16, 0, 0,
-	17, 18, 0, 3, 0, 19, 20, 0,
+	0, 14, 5, 15, 0, 0, 16, 0, 
+	0, 17, 0, 0, 18, 5, 0, 0, 
+	19, 20, 0, 3, 0, 5, 21, 0, 
 	0
 };
 
 static const char _use_syllable_machine_to_state_actions[] = {
-	0, 0, 0, 0, 5, 0, 0, 0, 
+	0, 0, 0, 0, 0, 6, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0
 };
 
 static const char _use_syllable_machine_from_state_actions[] = {
-	0, 0, 0, 0, 6, 0, 0, 0, 
+	0, 0, 0, 0, 0, 7, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0
 };
 
 static const short _use_syllable_machine_eof_trans[] = {
-	1, 3, 3, 6, 0, 35, 37, 37,
-	59, 59, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 59, 37, 62, 65, 62,
-	66, 66, 66, 66, 66, 66, 66, 66,
-	66, 66, 66, 66, 66, 66, 66, 66,
-	66, 66, 66, 70, 70, 66, 66, 71,
-	71, 71, 70
+	1, 3, 3, 6, 6, 0, 42, 44, 
+	44, 68, 68, 44, 44, 44, 44, 44, 
+	44, 44, 44, 44, 44, 44, 71, 44, 
+	44, 44, 44, 44, 44, 44, 44, 44, 
+	68, 44, 74, 77, 74, 44, 44, 81, 
+	81, 82, 82, 82, 82, 82, 82, 82, 
+	82, 82, 82, 82, 82, 82, 82, 82, 
+	82, 82, 82, 82, 82, 82, 82, 87, 
+	82, 82, 82, 87, 82, 82, 82, 82, 
+	81, 87
 };
 
-static const int use_syllable_machine_start = 4;
-static const int use_syllable_machine_first_final = 4;
+static const int use_syllable_machine_start = 5;
+static const int use_syllable_machine_first_final = 5;
 static const int use_syllable_machine_error = -1;
 
-static const int use_syllable_machine_en_main = 4;
+static const int use_syllable_machine_en_main = 5;
 
 
 #line 38 "hb-ot-shape-complex-use-machine.rl"
 
 
 
-#line 143 "hb-ot-shape-complex-use-machine.rl"
+#line 162 "hb-ot-shape-complex-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -374,7 +392,7 @@
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 378 "hb-ot-shape-complex-use-machine.hh"
+#line 396 "hb-ot-shape-complex-use-machine.hh"
 	{
 	cs = use_syllable_machine_start;
 	ts = 0;
@@ -382,7 +400,7 @@
 	act = 0;
 	}
 
-#line 163 "hb-ot-shape-complex-use-machine.rl"
+#line 182 "hb-ot-shape-complex-use-machine.rl"
 
 
   p = 0;
@@ -390,7 +408,7 @@
 
   unsigned int syllable_serial = 1;
   
-#line 394 "hb-ot-shape-complex-use-machine.hh"
+#line 412 "hb-ot-shape-complex-use-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -400,11 +418,11 @@
 		goto _test_eof;
 _resume:
 	switch ( _use_syllable_machine_from_state_actions[cs] ) {
-	case 6:
+	case 7:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 408 "hb-ot-shape-complex-use-machine.hh"
+#line 426 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -422,73 +440,77 @@
 		goto _again;
 
 	switch ( _use_syllable_machine_trans_actions[_trans] ) {
-	case 7:
+	case 5:
 #line 1 "NONE"
 	{te = p+1;}
 	break;
 	case 12:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 150 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (independent_cluster); }}
 	break;
 	case 14:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 153 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (standard_cluster); }}
 	break;
-	case 9:
-#line 138 "hb-ot-shape-complex-use-machine.rl"
+	case 10:
+#line 157 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
 	case 8:
-#line 139 "hb-ot-shape-complex-use-machine.rl"
+#line 158 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (non_cluster); }}
 	break;
 	case 11:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 150 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (independent_cluster); }}
 	break;
 	case 15:
-#line 133 "hb-ot-shape-complex-use-machine.rl"
+#line 151 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
 	break;
+	case 16:
+#line 152 "hb-ot-shape-complex-use-machine.rl"
+	{te = p;p--;{ found_syllable (sakot_terminated_cluster); }}
+	break;
 	case 13:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 153 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (standard_cluster); }}
 	break;
-	case 17:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
+	case 18:
+#line 154 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
 	break;
-	case 16:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+	case 17:
+#line 155 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (numeral_cluster); }}
 	break;
-	case 20:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+	case 19:
+#line 156 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (symbol_cluster); }}
 	break;
-	case 18:
-#line 138 "hb-ot-shape-complex-use-machine.rl"
+	case 20:
+#line 157 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
-	case 19:
-#line 139 "hb-ot-shape-complex-use-machine.rl"
+	case 21:
+#line 158 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (non_cluster); }}
 	break;
 	case 1:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 153 "hb-ot-shape-complex-use-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (standard_cluster); }}
 	break;
 	case 4:
-#line 138 "hb-ot-shape-complex-use-machine.rl"
+#line 157 "hb-ot-shape-complex-use-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
 	case 2:
 #line 1 "NONE"
 	{	switch( act ) {
-	case 7:
+	case 8:
 	{{p = ((te))-1;} found_syllable (broken_cluster); }
 	break;
-	case 8:
+	case 9:
 	{{p = ((te))-1;} found_syllable (non_cluster); }
 	break;
 	}
@@ -497,25 +519,25 @@
 	case 3:
 #line 1 "NONE"
 	{te = p+1;}
-#line 138 "hb-ot-shape-complex-use-machine.rl"
-	{act = 7;}
-	break;
-	case 10:
-#line 1 "NONE"
-	{te = p+1;}
-#line 139 "hb-ot-shape-complex-use-machine.rl"
+#line 157 "hb-ot-shape-complex-use-machine.rl"
 	{act = 8;}
 	break;
-#line 510 "hb-ot-shape-complex-use-machine.hh"
+	case 9:
+#line 1 "NONE"
+	{te = p+1;}
+#line 158 "hb-ot-shape-complex-use-machine.rl"
+	{act = 9;}
+	break;
+#line 532 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 _again:
 	switch ( _use_syllable_machine_to_state_actions[cs] ) {
-	case 5:
+	case 6:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 519 "hb-ot-shape-complex-use-machine.hh"
+#line 541 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	if ( ++p != pe )
@@ -531,7 +553,7 @@
 
 	}
 
-#line 171 "hb-ot-shape-complex-use-machine.rl"
+#line 190 "hb-ot-shape-complex-use-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl
index 7702cd9..aca7ea6 100644
--- a/src/hb-ot-shape-complex-use-machine.rl
+++ b/src/hb-ot-shape-complex-use-machine.rl
@@ -49,7 +49,7 @@
 GB	= 5; # BASE_OTHER
 CGJ	= 6; # CGJ
 #F	= 7; # CONS_FINAL
-FM	= 8; # CONS_FINAL_MOD
+#FM	= 8; # CONS_FINAL_MOD
 #M	= 9; # CONS_MED
 #CM	= 10; # CONS_MOD
 SUB	= 11; # CONS_SUB
@@ -66,6 +66,9 @@
 VS	= 21; # VARIATION_SELECTOR
 #V	= 36; # VOWEL
 #VM	= 40; # VOWEL_MOD
+CS	= 43; # CONS_WITH_STACKER
+HVM	= 44; # HALANT_OR_VOWEL_MODIFIER
+Sk	= 48; # SAKOT
 
 FAbv	= 24; # CONS_FINAL_ABOVE
 FBlw	= 25; # CONS_FINAL_BELOW
@@ -86,11 +89,11 @@
 VMPre	= 23; # VOWEL_MOD_PRE
 SMAbv	= 41; # SYM_MOD_ABOVE
 SMBlw	= 42; # SYM_MOD_BELOW
-CS	= 43; # CONS_WITH_STACKER
+FMAbv	= 45; # CONS_FINAL_MOD	UIPC = Top
+FMBlw	= 46; # CONS_FINAL_MOD	UIPC = Bottom
+FMPst	= 47; # CONS_FINAL_MOD	UIPC = Not_Applicable
 
-HVM	= 44; # HALANT_OR_VOWEL_MODIFIER
-
-h = H | HVM; # https://github.com/harfbuzz/harfbuzz/issues/1102
+h = H | HVM | Sk;
 
 # Override: Adhoc ZWJ placement. https://github.com/harfbuzz/harfbuzz/issues/542#issuecomment-353169729
 consonant_modifiers = CMAbv* CMBlw* ((ZWJ?.h.ZWJ? B | SUB) VS? CMAbv? CMBlw*)*;
@@ -98,39 +101,55 @@
 medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?;
 dependent_vowels = VPre* VAbv* VBlw* VPst*;
 vowel_modifiers = HVM? VMPre* VMAbv* VMBlw* VMPst*;
-final_consonants = FAbv* FBlw* FPst* FM?;
+final_consonants = FAbv* FBlw* FPst*;
+final_modifiers = FMAbv* FMBlw* | FMPst?;
 
-complex_syllable_tail =
+complex_syllable_start = (R | CS)? (B | GB) VS?;
+complex_syllable_middle =
 	consonant_modifiers
 	medial_consonants
 	dependent_vowels
 	vowel_modifiers
-	final_consonants
+	(Sk B)*
 ;
+complex_syllable_tail =
+	complex_syllable_middle
+	final_consonants
+	final_modifiers
+;
+number_joiner_terminated_cluster_tail = (HN N VS?)* HN;
+numeral_cluster_tail = (HN N VS?)+;
+symbol_cluster_tail = SMAbv+ SMBlw* | SMBlw+;
 
 virama_terminated_cluster =
-	(R|CS)? (B | GB) VS?
+	complex_syllable_start
 	consonant_modifiers
 	ZWJ?.h.ZWJ?
 ;
+sakot_terminated_cluster =
+	complex_syllable_start
+	complex_syllable_middle
+	Sk
+;
 standard_cluster =
-	(R|CS)? (B | GB) VS?
+	complex_syllable_start
 	complex_syllable_tail
 ;
 broken_cluster =
 	R?
-	complex_syllable_tail
+	(complex_syllable_tail | number_joiner_terminated_cluster_tail | numeral_cluster_tail | symbol_cluster_tail)
 ;
 
-number_joiner_terminated_cluster = N VS? (HN N VS?)* HN;
-numeral_cluster = N VS? (HN N VS?)*;
-symbol_cluster = S VS? SMAbv* SMBlw*;
+number_joiner_terminated_cluster = N VS? number_joiner_terminated_cluster_tail;
+numeral_cluster = N VS? numeral_cluster_tail?;
+symbol_cluster = (S | GB) VS? symbol_cluster_tail?;
 independent_cluster = (IND | O | Rsv | WJ) VS?;
 other = any;
 
 main := |*
 	independent_cluster			=> { found_syllable (independent_cluster); };
 	virama_terminated_cluster		=> { found_syllable (virama_terminated_cluster); };
+	sakot_terminated_cluster		=> { found_syllable (sakot_terminated_cluster); };
 	standard_cluster			=> { found_syllable (standard_cluster); };
 	number_joiner_terminated_cluster	=> { found_syllable (number_joiner_terminated_cluster); };
 	numeral_cluster				=> { found_syllable (numeral_cluster); };
diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc
index ddf7053..0247469 100644
--- a/src/hb-ot-shape-complex-use-table.cc
+++ b/src/hb-ot-shape-complex-use-table.cc
@@ -22,7 +22,6 @@
 #define B	USE_B	/* BASE */
 #define CGJ	USE_CGJ	/* CGJ */
 #define CS	USE_CS	/* CONS_WITH_STACKER */
-#define FM	USE_FM	/* CONS_FINAL_MOD */
 #define GB	USE_GB	/* BASE_OTHER */
 #define H	USE_H	/* HALANT */
 #define HN	USE_HN	/* HALANT_NUM */
@@ -34,6 +33,7 @@
 #define Rsv	USE_Rsv	/* Reserved */
 #define S	USE_S	/* SYM */
 #define SUB	USE_SUB	/* CONS_SUB */
+#define Sk	USE_Sk	/* SAKOT */
 #define VS	USE_VS	/* VARIATION_SELECTOR */
 #define WJ	USE_WJ	/* Word_Joiner */
 #define ZWJ	USE_ZWJ	/* ZWJ */
@@ -43,6 +43,9 @@
 #define FBlw	USE_FBlw
 #define FPst	USE_FPst
 #define FAbv	USE_FAbv
+#define FMBlw	USE_FMBlw
+#define FMPst	USE_FMPst
+#define FMAbv	USE_FMAbv
 #define MPre	USE_MPre
 #define MBlw	USE_MBlw
 #define MPst	USE_MPst
@@ -75,7 +78,7 @@
   /* Latin-1 Supplement */
 
   /* 00A0 */    GB,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 00B0 */     O,     O,    FM,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 00B0 */     O,     O, FMPst, FMPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 00C0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 00D0 */     O,     O,     O,     O,     O,     O,     O,    GB,
 
@@ -108,7 +111,7 @@
   /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,     H,   IND,     O,
   /* 09D0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 09E0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,    FM,     O,
+  /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O, FMAbv,     O,
 
   /* Gurmukhi */
 
@@ -204,7 +207,7 @@
   /* Tibetan */
                                                                       VBlw,  VBlw,     O,     O,     O,     O,     O,     O,
   /* 0F20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0F30 */     B,     B,     B,     B,     O,    FM,     O,    FM,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
+  /* 0F30 */     B,     B,     B,     B,     O, FMBlw,     O, FMBlw,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
   /* 0F40 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
   /* 0F50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0F60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
@@ -213,7 +216,7 @@
   /* 0F90 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 0FA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 0FB0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,     O,     O,
-  /* 0FC0 */     O,     O,     O,     O,     O,     O,    FM,     O,
+  /* 0FC0 */     O,     O,     O,     O,     O,     O, FMBlw,     O,
 
 #define use_offset_0x1000u 1536
 
@@ -260,8 +263,8 @@
   /* 1790 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 17A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPst,  VPst,
-  /* 17C0 */  VPst,  VPre,  VPre,  VPre,  VPst,  VPst, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
-  /* 17D0 */    FM,  VAbv,     H,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     B,    FM,     O,     O,
+  /* 17C0 */  VPst,  VPre,  VPre,  VPre,  VPst,  VPst, VMAbv, VMPst,  VPst, VMAbv, VMAbv, FMAbv,  FAbv, CMAbv, FMAbv, FMAbv,
+  /* 17D0 */ FMAbv,  VAbv,     H, FMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     B, FMAbv,     O,     O,
   /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
 #define use_offset_0x1900u 1936
@@ -272,7 +275,7 @@
   /* 1900 */    GB,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1910 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,
   /* 1920 */  VAbv,  VAbv,  VBlw,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,   SUB,   SUB,   SUB,     O,     O,     O,     O,
-  /* 1930 */  FPst,  FPst, VMBlw,  FPst,  FPst,  FPst,  FPst,  FPst,  FPst,  FBlw,  VAbv,    FM,     O,     O,     O,     O,
+  /* 1930 */  FPst,  FPst, VMBlw,  FPst,  FPst,  FPst,  FPst,  FPst,  FPst,  FBlw,  VAbv, FMBlw,     O,     O,     O,     O,
   /* 1940 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
 
   /* Tai Le */
@@ -302,9 +305,9 @@
   /* 1A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1A30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1A50 */     B,     B,     B,     B,     B,  MPre,  MBlw,   SUB,  FAbv,  FAbv,  FAbv,   SUB,   SUB,   SUB,   SUB,     O,
-  /* 1A60 */     H,  VPst,  VAbv,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VAbv,  VBlw,  VPst,  VPre,  VPre,
-  /* 1A70 */  VPre,  VPre,  VPre,  VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,  VAbv,    FM,    FM,     O,     O,  FBlw,
+  /* 1A50 */     B,     B,     B,     B,     B,  MPre,  MBlw,   SUB,  FAbv,  FAbv,  MAbv,   SUB,   SUB,   SUB,   SUB,     O,
+  /* 1A60 */    Sk,  VPst,  VAbv,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VAbv,  VBlw,  VPst,  VPre,  VPre,
+  /* 1A70 */  VPre,  VPre,  VPre,  VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,  VAbv, FMAbv, FMAbv,     O,     O, FMBlw,
   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
@@ -319,7 +322,7 @@
   /* 1B30 */     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VPre,
   /* 1B40 */  VPst,  VPst,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
   /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,    GB,    GB,     O,     O,    GB,
-  /* 1B60 */     O,     O,    GB,     O,     O,     O,     O,     O,    GB,     O,     O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
+  /* 1B60 */     O,     S,    GB,     S,     S,     S,     S,     S,    GB,     S,     S, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
   /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Sundanese */
@@ -341,7 +344,7 @@
   /* 1C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPst,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
-  /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre,    FM, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre, FMAbv, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
 
 #define use_offset_0x1cd0u 2688
@@ -357,7 +360,7 @@
 
 
   /* Combining Diacritical Marks Supplement */
-                                                                         O,     O,     O,    FM,     O,     O,     O,     O,
+                                                                         O,     O,     O, FMAbv,     O,     O,     O,     O,
 
 #define use_offset_0x2008u 2744
 
@@ -372,8 +375,8 @@
 
   /* Superscripts and Subscripts */
 
-  /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
+  /* 2070 */     O,     O,     O,     O, FMPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 2080 */     O,     O, FMPst, FMPst, FMPst,     O,     O,     O,
 
 #define use_offset_0x20f0u 2800
 
@@ -547,7 +550,7 @@
   /* 11190 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111B0 */     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,
-  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,    GB,  FBlw, CMBlw,  VAbv,  VBlw,     O,     O,     O,
+  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,    GB, FMBlw, CMBlw,  VAbv,  VBlw,     O,     O,     O,
   /* 111D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
   /* Sinhala Archaic Numbers */
@@ -600,7 +603,7 @@
   /* 11420 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11430 */     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,
   /* 11440 */  VPst,  VPst,     H, VMAbv, VMAbv, VMPst, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,
-  /* 11450 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,    FM,     B,
+  /* 11450 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O, FMAbv,     B,
   /* 11460 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11470 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
@@ -683,7 +686,7 @@
   /* 11A00 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     B,     B,     B,     B,     B,
   /* 11A10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11A30 */     B,     B,     B,    FM,  VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst,     R,  MBlw,  MBlw,  MBlw,  MBlw,    GB,
+  /* 11A30 */     B,     B,     B, FMBlw,  VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst,     R,  MBlw,  MBlw,  MBlw,  MBlw,    GB,
   /* 11A40 */     O,     O,     O,     O,     O,    GB,     O,     H,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Soyombo */
@@ -809,7 +812,6 @@
 #undef B
 #undef CGJ
 #undef CS
-#undef FM
 #undef GB
 #undef H
 #undef HN
@@ -821,6 +823,7 @@
 #undef Rsv
 #undef S
 #undef SUB
+#undef Sk
 #undef VS
 #undef WJ
 #undef ZWJ
@@ -830,6 +833,9 @@
 #undef FBlw
 #undef FPst
 #undef FAbv
+#undef FMBlw
+#undef FMPst
+#undef FMAbv
 #undef MPre
 #undef MBlw
 #undef MPst
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc
index ec4d4aa..2cc5ea2 100644
--- a/src/hb-ot-shape-complex-use.cc
+++ b/src/hb-ot-shape-complex-use.cc
@@ -246,6 +246,7 @@
 enum syllable_type_t {
   independent_cluster,
   virama_terminated_cluster,
+  sakot_terminated_cluster,
   standard_cluster,
   number_joiner_terminated_cluster,
   numeral_cluster,
@@ -294,7 +295,7 @@
 
   foreach_syllable (buffer, start, end)
   {
-    unsigned int limit = info[start].use_category() == USE_R ? 1 : MIN (3u, end - start);
+    unsigned int limit = info[start].use_category() == USE_R ? 1 : hb_min (3u, end - start);
     for (unsigned int i = start; i < start + limit; i++)
       info[i].mask |= mask;
   }
@@ -337,6 +338,7 @@
 	break;
 
       case virama_terminated_cluster:
+      case sakot_terminated_cluster:
       case standard_cluster:
       case number_joiner_terminated_cluster:
       case numeral_cluster:
@@ -443,6 +445,7 @@
   /* Only a few syllable types need reordering. */
   if (unlikely (!(FLAG_UNSAFE (syllable_type) &
 		  (FLAG (virama_terminated_cluster) |
+		   FLAG (sakot_terminated_cluster) |
 		   FLAG (standard_cluster) |
 		   FLAG (broken_cluster) |
 		   0))))
diff --git a/src/hb-ot-shape-complex-use.hh b/src/hb-ot-shape-complex-use.hh
index ab56e1b..ce6645e 100644
--- a/src/hb-ot-shape-complex-use.hh
+++ b/src/hb-ot-shape-complex-use.hh
@@ -68,6 +68,12 @@
   USE_VS	= 21,	/* VARIATION_SELECTOR */
 //  USE_V	= 36,	/* VOWEL */
 //  USE_VM	= 40,	/* VOWEL_MOD */
+  USE_CS	= 43,	/* CONS_WITH_STACKER */
+
+  /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
+  USE_HVM	= 44,	/* HALANT_OR_VOWEL_MODIFIER */
+
+  USE_Sk	= 48,	/* SAKOT */
 
   USE_FAbv	= 24,	/* CONS_FINAL_ABOVE */
   USE_FBlw	= 25,	/* CONS_FINAL_BELOW */
@@ -88,10 +94,9 @@
   USE_VMPre	= 23,	/* VOWEL_MOD_PRE */
   USE_SMAbv	= 41,	/* SYM_MOD_ABOVE */
   USE_SMBlw	= 42,	/* SYM_MOD_BELOW */
-  USE_CS	= 43,	/* CONS_WITH_STACKER */
-
-  /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
-  USE_HVM	= 44,	/* HALANT_OR_VOWEL_MODIFIER */
+  USE_FMAbv	= 45,	/* CONS_FINAL_MOD	UIPC = Top */
+  USE_FMBlw	= 46,	/* CONS_FINAL_MOD	UIPC = Bottom */
+  USE_FMPst	= 47,	/* CONS_FINAL_MOD	UIPC = Not_Applicable */
 };
 
 HB_INTERNAL USE_TABLE_ELEMENT_TYPE
diff --git a/src/hb-ot-shape-complex-vowel-constraints.cc b/src/hb-ot-shape-complex-vowel-constraints.cc
index 2eb313a..912ee35 100644
--- a/src/hb-ot-shape-complex-vowel-constraints.cc
+++ b/src/hb-ot-shape-complex-vowel-constraints.cc
@@ -34,7 +34,7 @@
 				       hb_buffer_t              *buffer,
 				       hb_font_t                *font HB_UNUSED)
 {
-#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS)
+#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
   return;
 #endif
   if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)
diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc
index b10eec6..573af8e 100644
--- a/src/hb-ot-shape-fallback.cc
+++ b/src/hb-ot-shape-fallback.cc
@@ -166,7 +166,7 @@
 						        hb_font_t *font HB_UNUSED,
 						        hb_buffer_t  *buffer)
 {
-#if defined(HB_NO_OT_SHAPE_FALLBACK)
+#ifdef HB_NO_OT_SHAPE_FALLBACK
   return;
 #endif
 
@@ -438,7 +438,7 @@
 				     hb_buffer_t  *buffer,
 				     bool adjust_offsets_when_zeroing)
 {
-#if defined(HB_NO_OT_SHAPE_FALLBACK)
+#ifdef HB_NO_OT_SHAPE_FALLBACK
   return;
 #endif
 
@@ -456,6 +456,7 @@
 }
 
 
+#ifndef HB_DISABLE_DEPRECATED
 struct hb_ot_shape_fallback_kern_driver_t
 {
   hb_ot_shape_fallback_kern_driver_t (hb_font_t   *font_,
@@ -474,6 +475,7 @@
   hb_font_t *font;
   hb_direction_t direction;
 };
+#endif
 
 /* Performs font-assisted kerning. */
 void
@@ -481,10 +483,11 @@
 			    hb_font_t *font,
 			    hb_buffer_t *buffer)
 {
-#if defined(HB_NO_OT_SHAPE_FALLBACK)
+#ifdef HB_NO_OT_SHAPE_FALLBACK
   return;
 #endif
 
+#ifndef HB_DISABLE_DEPRECATED
   if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
       !font->has_glyph_h_kerning_func () :
       !font->has_glyph_v_kerning_func ())
@@ -501,6 +504,7 @@
 
   if (reverse)
     buffer->reverse ();
+#endif
 }
 
 
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 7fff305..c63c3ad 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -55,7 +55,8 @@
 			      const hb_feature_t             *user_features,
 			      unsigned int                    num_user_features);
 
-static bool
+#ifndef HB_NO_SHAPE_AAT
+static inline bool
 _hb_apply_morx (hb_face_t *face)
 {
   if (hb_options ().aat &&
@@ -69,14 +70,17 @@
 					       0, nullptr, nullptr)) &&
 	 hb_aat_layout_has_substitution (face);
 }
+#endif
 
 hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t                     *face,
 					      const hb_segment_properties_t *props) :
 						face (face),
 						props (*props),
 						map (face, props),
-						aat_map (face, props),
-						apply_morx (_hb_apply_morx (face))
+						aat_map (face, props)
+#ifndef HB_NO_SHAPE_AAT
+						, apply_morx (_hb_apply_morx (face))
+#endif
 {
   shaper = hb_ot_shape_complex_categorize (this);
 
@@ -124,24 +128,36 @@
    * Decide who does substitutions. GSUB, morx, or fallback.
    */
 
+#ifndef HB_NO_SHAPE_AAT
   plan.apply_morx = apply_morx;
+#endif
 
   /*
    * Decide who does positioning. GPOS, kerx, kern, or fallback.
    */
 
-  if (hb_options ().aat && hb_aat_layout_has_positioning (face))
+  if (0)
+    ;
+#ifndef HB_NO_SHAPE_AAT
+  else if (hb_options ().aat && hb_aat_layout_has_positioning (face))
     plan.apply_kerx = true;
+#endif
   else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
     plan.apply_gpos = true;
+#ifndef HB_NO_SHAPE_AAT
   else if (hb_aat_layout_has_positioning (face))
     plan.apply_kerx = true;
+#endif
 
   if (!plan.apply_kerx && !has_gpos_kern)
   {
     /* Apparently Apple applies kerx if GPOS kern was not applied. */
-    if (hb_aat_layout_has_positioning (face))
+    if (0)
+      ;
+#ifndef HB_NO_SHAPE_AAT
+    else if (hb_aat_layout_has_positioning (face))
       plan.apply_kerx = true;
+#endif
     else if (hb_ot_layout_has_kerning (face))
       plan.apply_kern = true;
   }
@@ -158,8 +174,10 @@
   plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
 				   script_fallback_mark_positioning;
 
+#ifndef HB_NO_SHAPE_AAT
   /* Currently we always apply trak. */
   plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
+#endif
 }
 
 bool
@@ -962,12 +980,12 @@
   c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
   if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
   {
-    c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
+    c->buffer->max_len = hb_max (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
 			      (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
   if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
   {
-    c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
+    c->buffer->max_ops = hb_max (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
 			      (unsigned) HB_BUFFER_MAX_OPS_MIN);
   }
 
diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh
index 73a11e1..b7c0f10 100644
--- a/src/hb-ot-shape.hh
+++ b/src/hb-ot-shape.hh
@@ -80,10 +80,16 @@
   bool adjust_mark_positioning_when_zeroing : 1;
 
   bool apply_gpos : 1;
-  bool apply_kerx : 1;
   bool apply_kern : 1;
+#ifndef HB_NO_SHAPE_AAT
+  bool apply_kerx : 1;
   bool apply_morx : 1;
   bool apply_trak : 1;
+#else
+  static constexpr bool apply_kerx = false;
+  static constexpr bool apply_morx = false;
+  static constexpr bool apply_trak = false;
+#endif
 
   void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
   {
@@ -113,7 +119,11 @@
   hb_segment_properties_t props;
   hb_ot_map_builder_t map;
   hb_aat_map_builder_t aat_map;
+#ifndef HB_NO_SHAPE_AAT
   bool apply_morx : 1;
+#else
+  static constexpr bool apply_morx = false;
+#endif
   bool script_zero_marks : 1;
   bool script_fallback_mark_positioning : 1;
   const struct hb_ot_complex_shaper_t *shaper;
diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh
index 04a2ee9..03604a0 100644
--- a/src/hb-ot-stat-table.hh
+++ b/src/hb-ot-stat-table.hh
@@ -65,6 +65,8 @@
     return_trace (likely (c->check_struct (this)));
   }
 
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   protected:
   HBUINT16	format;		/* Format identifier — set to 1. */
   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
@@ -88,6 +90,8 @@
     return_trace (likely (c->check_struct (this)));
   }
 
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   protected:
   HBUINT16	format;		/* Format identifier — set to 2. */
   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
@@ -115,6 +119,8 @@
     return_trace (likely (c->check_struct (this)));
   }
 
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   protected:
   HBUINT16	format;		/* Format identifier — set to 3. */
   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
@@ -157,6 +163,8 @@
     return_trace (likely (c->check_struct (this)));
   }
 
+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+
   protected:
   HBUINT16	format;		/* Format identifier — set to 4. */
   HBUINT16	axisCount;	/* The total number of axes contributing to
@@ -178,7 +186,7 @@
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (c->check_struct (this)))
+    if (unlikely (!c->check_struct (this)))
       return_trace (false);
 
     switch (u.format)
@@ -191,6 +199,18 @@
     }
   }
 
+  hb_ot_name_id_t get_value_name_id () const
+  {
+    switch (u.format)
+    {
+      case 1: return u.format1.get_value_name_id ();
+      case 2: return u.format2.get_value_name_id ();
+      case 3: return u.format3.get_value_name_id ();
+      case 4: return u.format4.get_value_name_id ();
+      default: return HB_OT_NAME_ID_INVALID;
+    }
+  }
+
   protected:
   union
   {
@@ -212,6 +232,8 @@
     return_trace (likely (c->check_struct (this)));
   }
 
+  hb_ot_name_id_t get_name_id () const { return nameID; }
+
   protected:
   Tag		tag;		/* A tag identifying the axis of design variation. */
   NameID	nameID;		/* The name ID for entries in the 'name' table that
@@ -231,17 +253,59 @@
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-			  majorVersion == 1 &&
-			  minorVersion > 0 &&
+			  version.major == 1 &&
+                          version.minor > 0 &&
 			  designAxesOffset.sanitize (c, this, designAxisCount) &&
 			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
   }
 
+  bool has_data () const { return version.to_int (); }
+
+  unsigned get_design_axis_count () const { return designAxisCount; }
+
+  hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const
+  {
+    if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID;
+    const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index];
+    return axis_record.get_name_id ();
+  }
+
+  unsigned get_axis_value_count () const { return axisValueCount; }
+
+  hb_ot_name_id_t get_axis_value_name_id (unsigned axis_value_index) const
+  {
+    if (unlikely (axis_value_index >= axisValueCount)) return HB_OT_NAME_ID_INVALID;
+    const AxisValue &axis_value = (this + get_axis_value_offsets ()[axis_value_index]);
+    return axis_value.get_value_name_id ();
+  }
+
+  void collect_name_ids (hb_set_t *nameids_to_retain) const
+  {
+    if (!has_data ()) return;
+
+    + get_design_axes ()
+    | hb_map (&StatAxisRecord::get_name_id)
+    | hb_sink (nameids_to_retain)
+    ;
+
+    + get_axis_value_offsets ()
+    | hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
+    | hb_map (&AxisValue::get_value_name_id)
+    | hb_sink (nameids_to_retain)
+    ;
+  }
+
   protected:
-  HBUINT16	majorVersion;	/* Major version number of the style attributes
-				 * table — set to 1. */
-  HBUINT16	minorVersion;	/* Minor version number of the style attributes
-				 * table — set to 2. */
+  hb_array_t<const StatAxisRecord> const get_design_axes () const
+  { return (this+designAxesOffset).as_array (designAxisCount); }
+
+  hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const
+  { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }
+
+
+  protected:
+  FixedVersion<>version;        /* Version of the stat table
+                                 * initially set to 0x00010002u */
   HBUINT16	designAxisSize;	/* The size in bytes of each axis record. */
   HBUINT16	designAxisCount;/* The number of design axis records. In a
 				 * font with an 'fvar' table, this value must be
@@ -249,7 +313,7 @@
 				 * in the 'fvar' table. In all fonts, must
 				 * be greater than zero if axisValueCount
 				 * is greater than zero. */
-  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord> >
+  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord>>
 		designAxesOffset;
 				/* Offset in bytes from the beginning of
 				 * the STAT table to the start of the design
@@ -257,7 +321,7 @@
 				 * set to zero; if designAxisCount is greater
 				 * than zero, must be greater than zero. */
   HBUINT16	axisValueCount;	/* The number of axis value tables. */
-  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue> > >
+  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue>>>
 		offsetToAxisValueOffsets;
 				/* Offset in bytes from the beginning of
 				 * the STAT table to the start of the design
diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc
index c57c688..ad3635b 100644
--- a/src/hb-ot-tag.cc
+++ b/src/hb-ot-tag.cc
@@ -113,6 +113,7 @@
   return HB_SCRIPT_UNKNOWN;
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 void
 hb_ot_tags_from_script (hb_script_t  script,
 			hb_tag_t    *script_tag_1,
@@ -124,6 +125,7 @@
   *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT;
   *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT;
 }
+#endif
 
 /*
  * Complete list at:
@@ -212,7 +214,7 @@
     p = strchr (b, '-');
     db = p ? (unsigned int) (p - b) : strlen (b);
 
-    return strncmp (a, b, MAX (da, db));
+    return strncmp (a, b, hb_max (da, db));
   }
   int cmp (const LangTag *that) const
   { return cmp (that->language); }
@@ -230,6 +232,7 @@
 /*{"??",	{HB_TAG('Y','I','C',' ')}},*/	/* Yi Classic */
 /*{"zh?",	{HB_TAG('Z','H','P',' ')}},*/	/* Chinese Phonetic */
 
+#ifndef HB_DISABLE_DEPRECATED
 hb_tag_t
 hb_ot_tag_from_language (hb_language_t language)
 {
@@ -238,6 +241,7 @@
   hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
   return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE;
 }
+#endif
 
 static void
 hb_ot_tags_from_language (const char   *lang_str,
diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh
index c4a192d..57a3a6d 100644
--- a/src/hb-ot-var-avar-table.hh
+++ b/src/hb-ot-var-avar-table.hh
@@ -123,7 +123,7 @@
 
   void map_coords (int *coords, unsigned int coords_length) const
   {
-    unsigned int count = MIN<unsigned int> (coords_length, axisCount);
+    unsigned int count = hb_min (coords_length, axisCount);
 
     const SegmentMaps *map = &firstAxisSegmentMaps;
     for (unsigned int i = 0; i < count; i++)
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
index 78cb3c8..7df8142 100644
--- a/src/hb-ot-var-fvar-table.hh
+++ b/src/hb-ot-var-fvar-table.hh
@@ -114,17 +114,19 @@
 
   unsigned int get_axis_count () const { return axisCount; }
 
+#ifndef HB_DISABLE_DEPRECATED
   void get_axis_deprecated (unsigned int axis_index,
 				   hb_ot_var_axis_t *info) const
   {
     const AxisRecord &axis = get_axes ()[axis_index];
     info->tag = axis.axisTag;
     info->name_id =  axis.axisNameID;
-    info->default_value = axis.defaultValue / 65536.;
+    info->default_value = axis.defaultValue / 65536.f;
     /* Ensure order, to simplify client math. */
-    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
-    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
+    info->min_value = hb_min (info->default_value, axis.minValue / 65536.f);
+    info->max_value = hb_max (info->default_value, axis.maxValue / 65536.f);
   }
+#endif
 
   void get_axis_info (unsigned int axis_index,
 		      hb_ot_var_axis_info_t *info) const
@@ -134,13 +136,14 @@
     info->tag = axis.axisTag;
     info->name_id =  axis.axisNameID;
     info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
-    info->default_value = axis.defaultValue / 65536.;
+    info->default_value = axis.defaultValue / 65536.f;
     /* Ensure order, to simplify client math. */
-    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
-    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
+    info->min_value = hb_min (info->default_value, axis.minValue / 65536.f);
+    info->max_value = hb_max (info->default_value, axis.maxValue / 65536.f);
     info->reserved = 0;
   }
 
+#ifndef HB_DISABLE_DEPRECATED
   unsigned int get_axes_deprecated (unsigned int      start_offset,
 				    unsigned int     *axes_count /* IN/OUT */,
 				    hb_ot_var_axis_t *axes_array /* OUT */) const
@@ -149,12 +152,12 @@
     {
       /* TODO Rewrite as hb_array_t<>::sub-array() */
       unsigned int count = axisCount;
-      start_offset = MIN (start_offset, count);
+      start_offset = hb_min (start_offset, count);
 
       count -= start_offset;
       axes_array += start_offset;
 
-      count = MIN (count, *axes_count);
+      count = hb_min (count, *axes_count);
       *axes_count = count;
 
       for (unsigned int i = 0; i < count; i++)
@@ -162,6 +165,7 @@
     }
     return axisCount;
   }
+#endif
 
   unsigned int get_axis_infos (unsigned int           start_offset,
 			       unsigned int          *axes_count /* IN/OUT */,
@@ -171,12 +175,12 @@
     {
       /* TODO Rewrite as hb_array_t<>::sub-array() */
       unsigned int count = axisCount;
-      start_offset = MIN (start_offset, count);
+      start_offset = hb_min (start_offset, count);
 
       count -= start_offset;
       axes_array += start_offset;
 
-      count = MIN (count, *axes_count);
+      count = hb_min (count, *axes_count);
       *axes_count = count;
 
       for (unsigned int i = 0; i < count; i++)
@@ -185,6 +189,7 @@
     return axisCount;
   }
 
+#ifndef HB_DISABLE_DEPRECATED
   bool find_axis_deprecated (hb_tag_t tag,
 			     unsigned int *axis_index,
 			     hb_ot_var_axis_t *info) const
@@ -203,6 +208,7 @@
       *axis_index = HB_OT_VAR_NO_AXIS_INDEX;
     return false;
   }
+#endif
 
   bool find_axis_info (hb_tag_t tag,
 		       hb_ot_var_axis_info_t *info) const
@@ -223,7 +229,7 @@
     hb_ot_var_axis_info_t axis;
     get_axis_info (axis_index, &axis);
 
-    v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
+    v = hb_max (hb_min (v, axis.max_value), axis.min_value); /* Clamp. */
 
     if (v == axis.default_value)
       return 0;
@@ -253,8 +259,8 @@
   }
 
   unsigned int get_instance_coords (unsigned int  instance_index,
-					   unsigned int *coords_length, /* IN/OUT */
-					   float        *coords         /* OUT */) const
+				    unsigned int *coords_length, /* IN/OUT */
+				    float        *coords         /* OUT */) const
   {
     const InstanceRecord *instance = get_instance (instance_index);
     if (unlikely (!instance))
@@ -274,6 +280,27 @@
     return axisCount;
   }
 
+  void collect_name_ids (hb_set_t *nameids) const
+  {
+    if (!has_data ()) return;
+
+    + get_axes ()
+    | hb_map (&AxisRecord::axisNameID)
+    | hb_sink (nameids)
+    ;
+
+    + hb_range ((unsigned) instanceCount)
+    | hb_map ([this] (const unsigned _) { return get_instance_subfamily_name_id (_); })
+    | hb_sink (nameids)
+    ;
+
+    + hb_range ((unsigned) instanceCount)
+    | hb_map ([this] (const unsigned _) { return get_instance_postscript_name_id (_); })
+    | hb_sink (nameids)
+    ;
+  }
+
+
   protected:
   hb_array_t<const AxisRecord> get_axes () const
   { return hb_array (&(this+firstAxis), axisCount); }
diff --git a/src/hb-ot-var-mvar-table.hh b/src/hb-ot-var-mvar-table.hh
index 0dd63e5..5a9d2af 100644
--- a/src/hb-ot-var-mvar-table.hh
+++ b/src/hb-ot-var-mvar-table.hh
@@ -77,9 +77,9 @@
 		 const int *coords, unsigned int coord_count) const
   {
     const VariationValueRecord *record;
-    record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,
-					       valueRecordCount, valueRecordSize,
-					       tag_compare);
+    record = (VariationValueRecord *) hb_bsearch (&tag, valuesZ.arrayZ,
+						  valueRecordCount, valueRecordSize,
+						  tag_compare);
     if (!record)
       return 0.;
 
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
index e327fb7..25a246a 100644
--- a/src/hb-ot-var.cc
+++ b/src/hb-ot-var.cc
@@ -75,6 +75,7 @@
   return face->table.fvar->get_axis_count ();
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_ot_var_get_axes:
  *
@@ -104,6 +105,7 @@
 {
   return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info);
 }
+#endif
 
 /**
  * hb_ot_var_get_axis_infos:
diff --git a/src/hb-sanitize.hh b/src/hb-sanitize.hh
index e58202c..5f5b4bd 100644
--- a/src/hb-sanitize.hh
+++ b/src/hb-sanitize.hh
@@ -130,12 +130,23 @@
   template <typename T, typename F>
   bool may_dispatch (const T *obj HB_UNUSED, const F *format)
   { return format->sanitize (this); }
-  template <typename T>
-  return_t dispatch (const T &obj) { return obj.sanitize (this); }
   static return_t default_return_value () { return true; }
   static return_t no_dispatch_return_value () { return false; }
   bool stop_sublookup_iteration (const return_t r) const { return !r; }
 
+  private:
+  template <typename T, typename ...Ts> auto
+  _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
+  ( obj.sanitize (this, hb_forward<Ts> (ds)...) )
+  template <typename T, typename ...Ts> auto
+  _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
+  ( obj.dispatch (this, hb_forward<Ts> (ds)...) )
+  public:
+  template <typename T, typename ...Ts> auto
+  dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
+  ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
+
+
   void init (hb_blob_t *b)
   {
     this->blob = hb_blob_reference (b);
@@ -164,7 +175,7 @@
     else
     {
       this->start = obj_start;
-      this->end   = obj_start + MIN<uintptr_t> (this->end - obj_start, obj->get_size ());
+      this->end   = obj_start + hb_min (size_t (this->end - obj_start), obj->get_size ());
     }
   }
 
@@ -178,7 +189,7 @@
   void start_processing ()
   {
     reset_object ();
-    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+    this->max_ops = hb_max ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
 			 (unsigned) HB_SANITIZE_MAX_OPS_MIN);
     this->edit_count = 0;
     this->debug_depth = 0;
@@ -200,6 +211,8 @@
     this->start = this->end = nullptr;
   }
 
+  unsigned get_edit_count () { return edit_count; }
+
   bool check_range (const void *base,
 		    unsigned int len) const
   {
diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh
index 7566881..76f7016 100644
--- a/src/hb-serialize.hh
+++ b/src/hb-serialize.hh
@@ -71,7 +71,7 @@
     {
       bool is_wide: 1;
       unsigned position : 31;
-      int bias;
+      unsigned bias;
       objidx_t objidx;
     };
 
@@ -132,9 +132,9 @@
   { return check_equal (v1 = v2, v2); }
 
   template <typename T> bool propagate_error (T &&obj)
-  { return check_success (!hb_deref_pointer (obj).in_error ()); }
+  { return check_success (!hb_deref (obj).in_error ()); }
 
-  template <typename T1, typename... Ts> bool propagate_error (T1 &&o1, Ts &&...os)
+  template <typename T1, typename... Ts> bool propagate_error (T1 &&o1, Ts&&... os)
   { return propagate_error (hb_forward<T1> (o1)) &&
 	   propagate_error (hb_forward<Ts> (os)...); }
 
@@ -165,7 +165,7 @@
 
     /* Only "pack" if there exist other objects... Otherwise, don't bother.
      * Saves a move. */
-    if (packed.length == 1)
+    if (packed.length <= 1)
       return;
 
     pop_pack ();
@@ -285,27 +285,28 @@
 
   void resolve_links ()
   {
+    if (unlikely (in_error ())) return;
+
     assert (!current);
+    assert (packed.length > 1);
 
-    for (auto obj_it = ++hb_iter (packed); obj_it; ++obj_it)
+    for (const object_t* parent : ++hb_iter (packed))
     {
-      const object_t &parent = **obj_it;
-
-      for (auto link_it = parent.links.iter (); link_it; ++link_it)
+      for (const object_t::link_t &link : parent->links)
       {
-        const object_t::link_t &link = *link_it;
-	const object_t &child = *packed[link.objidx];
-	unsigned offset = (child.head - parent.head) - link.bias;
+	const object_t* child = packed[link.objidx];
+	assert (link.bias <= (size_t) (parent->tail - parent->head));
+	unsigned offset = (child->head - parent->head) - link.bias;
 
 	if (link.is_wide)
 	{
-	  auto &off = * ((BEInt<uint32_t, 4> *) (parent.head + link.position));
+	  auto &off = * ((BEInt<uint32_t, 4> *) (parent->head + link.position));
 	  assert (0 == off);
 	  check_assign (off, offset);
 	}
 	else
 	{
-	  auto &off = * ((BEInt<uint16_t, 2> *) (parent.head + link.position));
+	  auto &off = * ((BEInt<uint16_t, 2> *) (parent->head + link.position));
 	  assert (0 == off);
 	  check_assign (off, offset);
 	}
@@ -322,12 +323,12 @@
       allocate_size<void> (alignment - l);
   }
 
+  template <typename Type = void>
+  Type *start_embed (const Type *obj HB_UNUSED = nullptr) const
+  { return reinterpret_cast<Type *> (this->head); }
   template <typename Type>
-  Type *start_embed (const Type *_ HB_UNUSED = nullptr) const
-  {
-    Type *ret = reinterpret_cast<Type *> (this->head);
-    return ret;
-  }
+  Type *start_embed (const Type &obj) const
+  { return start_embed (hb_addressof (obj)); }
 
   /* Following two functions exist to allow setting breakpoint on. */
   void err_ran_out_of_room () { this->ran_out_of_room = true; }
@@ -357,50 +358,67 @@
   }
 
   template <typename Type>
-  Type *embed (const Type &obj)
+  Type *embed (const Type *obj)
   {
-    unsigned int size = obj.get_size ();
+    unsigned int size = obj->get_size ();
     Type *ret = this->allocate_size<Type> (size);
     if (unlikely (!ret)) return nullptr;
-    memcpy (ret, &obj, size);
+    memcpy (ret, obj, size);
     return ret;
   }
+  template <typename Type>
+  Type *embed (const Type &obj)
+  { return embed (hb_addressof (obj)); }
+
+  template <typename Type, typename ...Ts> auto
+  _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN
+  (Type *, src.copy (this, hb_forward<Ts> (ds)...))
 
   template <typename Type> auto
-  _copy (const Type &obj, hb_priority<1>) const HB_RETURN (Type *, obj.copy (this))
-
-  template <typename Type> auto
-  _copy (const Type &obj, hb_priority<0>) const -> decltype (&(obj = obj))
+  _copy (const Type &src, hb_priority<0>) -> decltype (&(src = src))
   {
     Type *ret = this->allocate_size<Type> (sizeof (Type));
     if (unlikely (!ret)) return nullptr;
-    *ret = obj;
+    *ret = src;
     return ret;
   }
 
   /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
    * instead of memcpy(). */
-  template <typename Type>
-  Type *copy (const Type &obj) { return _copy (obj, hb_prioritize); }
+  template <typename Type, typename ...Ts>
+  Type *copy (const Type &src, Ts&&... ds)
+  { return _copy (src, hb_prioritize, hb_forward<Ts> (ds)...); }
+  template <typename Type, typename ...Ts>
+  Type *copy (const Type *src, Ts&&... ds)
+  { return copy (*src, hb_forward<Ts> (ds)...); }
 
   template <typename Type>
-  hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; }
+  hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
 
   template <typename Type>
+  Type *extend_size (Type *obj, unsigned int size)
+  {
+    assert (this->start <= (char *) obj);
+    assert ((char *) obj <= this->head);
+    assert ((char *) obj + size >= this->head);
+    if (unlikely (!this->allocate_size<Type> (((char *) obj) + size - this->head))) return nullptr;
+    return reinterpret_cast<Type *> (obj);
+  }
+  template <typename Type>
   Type *extend_size (Type &obj, unsigned int size)
-  {
-    assert (this->start <= (char *) &obj);
-    assert ((char *) &obj <= this->head);
-    assert ((char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
+  { return extend_size (hb_addressof (obj), size); }
 
   template <typename Type>
-  Type *extend_min (Type &obj) { return extend_size (obj, obj.min_size); }
-
+  Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
   template <typename Type>
-  Type *extend (Type &obj) { return extend_size (obj, obj.get_size ()); }
+  Type *extend_min (Type &obj) { return extend_min (hb_addressof (obj)); }
+
+  template <typename Type, typename ...Ts>
+  Type *extend (Type *obj, Ts&&... ds)
+  { return extend_size (obj, obj->get_size (hb_forward<Ts> (ds)...)); }
+  template <typename Type, typename ...Ts>
+  Type *extend (Type &obj, Ts&&... ds)
+  { return extend (hb_addressof (obj), hb_forward<Ts> (ds)...); }
 
   /* Output routines. */
   hb_bytes_t copy_bytes () const
diff --git a/src/hb-set.cc b/src/hb-set.cc
index 0682362..fa98688 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -389,6 +389,7 @@
   set->symmetric_difference (other);
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_set_invert:
  * @set: a set.
@@ -403,6 +404,7 @@
 hb_set_invert (hb_set_t *set HB_UNUSED)
 {
 }
+#endif
 
 /**
  * hb_set_get_population:
diff --git a/src/hb-set.hh b/src/hb-set.hh
index 76100f6..ad449d0 100644
--- a/src/hb-set.hh
+++ b/src/hb-set.hh
@@ -28,6 +28,7 @@
 #define HB_SET_HH
 
 #include "hb.hh"
+#include "hb-machinery.hh"
 
 
 /*
@@ -308,7 +309,7 @@
       {
 	page->add (g);
 
-	array = (const T *) ((const char *) array + stride);
+	array = &StructAtOffsetUnaligned<T> (array, stride);
 	count--;
       }
       while (count && (g = *array, start <= g && g < end));
@@ -440,8 +441,8 @@
     return true;
   }
 
-  template <class Op>
-  void process (const hb_set_t *other)
+  template <typename Op>
+  void process (const Op& op, const hb_set_t *other)
   {
     if (unlikely (!successful)) return;
 
@@ -495,7 +496,7 @@
 	b--;
 	count--;
 	page_map[count] = page_map[a];
-	Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
+	page_at (count).v = op (page_at (a).v, other->page_at (b).v);
       }
       else if (page_map[a - 1].major > other->page_map[b - 1].major)
       {
@@ -541,19 +542,19 @@
 
   void union_ (const hb_set_t *other)
   {
-    process<HbOpOr> (other);
+    process (hb_bitwise_or, other);
   }
   void intersect (const hb_set_t *other)
   {
-    process<HbOpAnd> (other);
+    process (hb_bitwise_and, other);
   }
   void subtract (const hb_set_t *other)
   {
-    process<HbOpMinus> (other);
+    process (hb_bitwise_sub, other);
   }
   void symmetric_difference (const hb_set_t *other)
   {
-    process<HbOpXor> (other);
+    process (hb_bitwise_xor, other);
   }
   bool next (hb_codepoint_t *codepoint) const
   {
@@ -701,6 +702,9 @@
     void __next__ () { s->next (&v); if (l) l--; }
     void __prev__ () { s->previous (&v); }
     unsigned __len__ () const { return l; }
+    iter_t end () const { return iter_t (*s); }
+    bool operator != (const iter_t& o) const
+    { return s != o.s || v != o.v; }
 
     protected:
     const hb_set_t *s;
diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc
index 20a01a5..9720594 100644
--- a/src/hb-subset-cff1.cc
+++ b/src/hb-subset-cff1.cc
@@ -32,6 +32,8 @@
 #include "hb-subset-cff-common.hh"
 #include "hb-cff1-interp-cs.hh"
 
+#ifndef HB_NO_SUBSET_CFF
+
 using namespace CFF;
 
 struct remap_sid_t : hb_bimap_t
@@ -351,7 +353,7 @@
       case OpCode_return:
 	param.current_parsed_str->add_op (op, env.str_ref);
 	param.current_parsed_str->set_parsed ();
-	env.returnFromSubr ();
+	env.return_from_subr ();
 	param.set_current_str (env, false);
 	break;
 
@@ -382,7 +384,7 @@
 				 cff1_biased_subrs_t& subrs, hb_set_t *closure)
   {
     byte_str_ref_t    str_ref = env.str_ref;
-    env.callSubr (subrs, type);
+    env.call_subr (subrs, type);
     param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
     hb_set_add (closure, env.context.subr_num);
     param.set_current_str (env, true);
@@ -394,8 +396,8 @@
 
 struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t, OpCode_endchar>
 {
-  cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc, const hb_subset_plan_t *plan)
-    : subr_subsetter_t (acc, plan) {}
+  cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
+    : subr_subsetter_t (acc_, plan_) {}
 
   static void complete_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
   {
@@ -909,7 +911,7 @@
   /* top dict INDEX */
   {
     assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start));
-    CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
+    CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict>> ();
     if (dest == nullptr) return false;
     cff1_top_dict_op_serializer_t topSzr;
     top_dict_modifiers_t  modifier (plan.offsets, plan.topDictModSIDs);
@@ -1061,7 +1063,7 @@
   return true;
 }
 
-static bool
+static inline bool
 _hb_subset_cff1 (const OT::cff1::accelerator_subset_t  &acc,
 		const char		*data,
 		hb_subset_plan_t	*plan,
@@ -1115,3 +1117,5 @@
 
   return result;
 }
+
+#endif
diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc
index b93e5d7..400f19f 100644
--- a/src/hb-subset-cff2.cc
+++ b/src/hb-subset-cff2.cc
@@ -32,6 +32,8 @@
 #include "hb-subset-cff-common.hh"
 #include "hb-cff2-interp-cs.hh"
 
+#ifndef HB_NO_SUBSET_CFF
+
 using namespace CFF;
 
 struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
@@ -183,7 +185,7 @@
 
       case OpCode_return:
 	param.current_parsed_str->set_parsed ();
-	env.returnFromSubr ();
+	env.return_from_subr ();
 	param.set_current_str (env, false);
 	break;
 
@@ -213,7 +215,7 @@
 				 cff2_biased_subrs_t& subrs, hb_set_t *closure)
   {
     byte_str_ref_t    str_ref = env.str_ref;
-    env.callSubr (subrs, type);
+    env.call_subr (subrs, type);
     param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
     hb_set_add (closure, env.context.subr_num);
     param.set_current_str (env, true);
@@ -225,8 +227,8 @@
 
 struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
 {
-  cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc, const hb_subset_plan_t *plan)
-    : subr_subsetter_t (acc, plan) {}
+  cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
+    : subr_subsetter_t (acc_, plan_) {}
 
   static void complete_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
   {
@@ -569,7 +571,7 @@
   return true;
 }
 
-static bool
+static inline bool
 _hb_subset_cff2 (const OT::cff2::accelerator_subset_t  &acc,
 		const char		      *data,
 		hb_subset_plan_t		*plan,
@@ -624,3 +626,5 @@
 
   return result;
 }
+
+#endif
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
deleted file mode 100644
index 9095e9f..0000000
--- a/src/hb-subset-glyf.cc
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger, Roderick Sheeter
- */
-
-#include "hb-open-type.hh"
-#include "hb-ot-glyf-table.hh"
-#include "hb-set.h"
-#include "hb-subset-glyf.hh"
-
-struct loca_data_t
-{
-  bool          is_short;
-  void         *data;
-  unsigned int  size;
-
-  inline bool
-  _write_loca_entry (unsigned int  id,
-                     unsigned int  offset)
-  {
-    unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
-    if ((id + 1) * entry_size <= size)
-    {
-      if (is_short) {
-        ((OT::HBUINT16*) data) [id] = offset / 2;
-      } else {
-        ((OT::HBUINT32*) data) [id] = offset;
-      }
-      return true;
-    }
-
-    // Offset was not written because the write is out of bounds.
-    DEBUG_MSG(SUBSET,
-              nullptr,
-              "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
-              id,
-              size);
-    return false;
-  }
-};
-
-/**
- * If hints are being dropped find the range which in glyf at which
- * the hinting instructions are located. Add them to the instruction_ranges
- * vector.
- */
-static bool
-_add_instructions_range (const OT::glyf::accelerator_t &glyf,
-                         hb_codepoint_t                 glyph_id,
-                         unsigned int                   glyph_start_offset,
-                         unsigned int                   glyph_end_offset,
-                         bool                           drop_hints,
-                         hb_vector_t<unsigned int>     *instruction_ranges /* OUT */)
-{
-  if (!instruction_ranges->resize (instruction_ranges->length + 2))
-  {
-    DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
-    return false;
-  }
-  unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
-  *instruction_start = 0;
-  unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
-  *instruction_end = 0;
-
-  if (drop_hints)
-  {
-    if (unlikely (!glyf.get_instruction_offsets (glyph_start_offset, glyph_end_offset,
-                                                 instruction_start, instruction_end)))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", glyph_id);
-      return false;
-    }
-  }
-
-  return true;
-}
-
-static bool
-_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
-                                     const hb_subset_plan_t        *plan,
-                                     loca_data_t                   *loca_data, /* OUT */
-				     unsigned int                  *glyf_size /* OUT */,
-				     hb_vector_t<unsigned int>     *instruction_ranges /* OUT */)
-{
-  unsigned int total = 0;
-
-  hb_codepoint_t next_glyph = HB_SET_VALUE_INVALID;
-  while (plan->glyphset ()->next (&next_glyph))
-  {
-    unsigned int start_offset, end_offset;
-    if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) &&
-		    glyf.remove_padding (start_offset, &end_offset))))
-    {
-      DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
-      start_offset = end_offset = 0;
-    }
-
-    bool is_zero_length = end_offset - start_offset < OT::glyf::GlyphHeader::static_size;
-    if (!_add_instructions_range (glyf,
-                                  next_glyph,
-                                  start_offset,
-                                  end_offset,
-                                  plan->drop_hints && !is_zero_length,
-                                  instruction_ranges))
-      return false;
-
-    if (is_zero_length)
-      continue; /* 0-length glyph */
-
-    total += end_offset - start_offset
-             - ((*instruction_ranges)[instruction_ranges->length - 1]
-                - (*instruction_ranges)[instruction_ranges->length - 2]);
-    /* round2 so short loca will work */
-    total += total % 2;
-  }
-
-  *glyf_size = total;
-  loca_data->is_short = (total <= 131070);
-  loca_data->size = (plan->num_output_glyphs () + 1)
-      * (loca_data->is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
-
-  DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
-	    total,
-	    loca_data->size,
-	    loca_data->is_short ? "short" : "long");
-  return true;
-}
-
-static void
-_update_components (const hb_subset_plan_t *plan,
-		    char                   *glyph_start,
-		    unsigned int            length)
-{
-  OT::glyf::CompositeGlyphHeader::Iterator iterator;
-  if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
-						    length,
-						    &iterator))
-  {
-    do
-    {
-      hb_codepoint_t new_gid;
-      if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
-				      &new_gid))
-	continue;
-
-      ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex = new_gid;
-    } while (iterator.move_to_next ());
-  }
-}
-
-static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int length)
-{
-  /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
-  OT::glyf::CompositeGlyphHeader::Iterator composite_it;
-  if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (glyf_prime, length, &composite_it))) return false;
-  const OT::glyf::CompositeGlyphHeader *glyph;
-  do {
-    glyph = composite_it.current;
-    OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&glyph->flags);
-    *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS;
-  } while (composite_it.move_to_next ());
-  return true;
-}
-
-static bool
-_write_glyf_and_loca_prime (const hb_subset_plan_t        *plan,
-			    const OT::glyf::accelerator_t &glyf,
-			    const char                    *glyf_data,
-			    hb_vector_t<unsigned int>     &instruction_ranges,
-			    unsigned int                   glyf_prime_size,
-			    char                          *glyf_prime_data /* OUT */,
-			    loca_data_t                   *loca_prime /* OUT */)
-{
-  char *glyf_prime_data_next = glyf_prime_data;
-
-  bool success = true;
-
-
-  unsigned int i = 0;
-  hb_codepoint_t new_gid;
-  for (new_gid = 0; new_gid < plan->num_output_glyphs (); new_gid++)
-  {
-    hb_codepoint_t old_gid;
-    if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
-    {
-      // Empty glyph, add a loca entry and carry on.
-      loca_prime->_write_loca_entry (new_gid,
-                                     glyf_prime_data_next - glyf_prime_data);
-      continue;
-    }
-
-
-    unsigned int start_offset, end_offset;
-    if (unlikely (!(glyf.get_offsets (old_gid, &start_offset, &end_offset) &&
-		    glyf.remove_padding (start_offset, &end_offset))))
-      end_offset = start_offset = 0;
-
-    unsigned int instruction_start = instruction_ranges[i * 2];
-    unsigned int instruction_end = instruction_ranges[i * 2 + 1];
-
-    int length = end_offset - start_offset - (instruction_end - instruction_start);
-
-    if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
-    {
-      DEBUG_MSG(SUBSET,
-                nullptr,
-                "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
-                i, length);
-      return false;
-    }
-
-    if (instruction_start == instruction_end)
-      memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
-    else
-    {
-      memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset);
-      memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end);
-      /* if the instructions end at the end this was a composite glyph, else simple */
-      if (instruction_end == end_offset)
-      {
-	if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false;
-      }
-      else
-	/* zero instruction length, which is just before instruction_start */
-	memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
-    }
-
-    success = success && loca_prime->_write_loca_entry (new_gid,
-                                                        glyf_prime_data_next - glyf_prime_data);
-    _update_components (plan, glyf_prime_data_next, length);
-
-    // TODO: don't align to two bytes if using long loca.
-    glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.
-
-    i++;
-  }
-
-  // loca table has n+1 entries where the last entry signifies the end location of the last
-  // glyph.
-  success = success && loca_prime->_write_loca_entry (new_gid,
-                                                      glyf_prime_data_next - glyf_prime_data);
-  return success;
-}
-
-static bool
-_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
-			  const char                     *glyf_data,
-			  hb_subset_plan_t               *plan,
-			  bool                           *use_short_loca,
-			  hb_blob_t                     **glyf_prime_blob /* OUT */,
-			  hb_blob_t                     **loca_prime_blob /* OUT */)
-{
-  // TODO(grieger): Sanity check allocation size for the new table.
-  loca_data_t loca_prime;
-  unsigned int glyf_prime_size;
-  hb_vector_t<unsigned int> instruction_ranges;
-  instruction_ranges.init ();
-
-  if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
-                                                      plan,
-                                                      &loca_prime,
-						      &glyf_prime_size,
-						      &instruction_ranges))) {
-    instruction_ranges.fini ();
-    return false;
-  }
-  *use_short_loca = loca_prime.is_short;
-
-  char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
-  loca_prime.data = (void *) calloc (1, loca_prime.size);
-  if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
-					     instruction_ranges,
-					     glyf_prime_size, glyf_prime_data,
-					     &loca_prime))) {
-    free (glyf_prime_data);
-    free (loca_prime.data);
-    instruction_ranges.fini ();
-    return false;
-  }
-  instruction_ranges.fini ();
-
-  *glyf_prime_blob = hb_blob_create (glyf_prime_data,
-                                     glyf_prime_size,
-                                     HB_MEMORY_MODE_READONLY,
-                                     glyf_prime_data,
-                                     free);
-  *loca_prime_blob = hb_blob_create ((char *) loca_prime.data,
-                                     loca_prime.size,
-                                     HB_MEMORY_MODE_READONLY,
-                                     loca_prime.data,
-                                     free);
-  return true;
-}
-
-/**
- * hb_subset_glyf:
- * Subsets the glyph table according to a provided plan.
- *
- * Return value: subsetted glyf table.
- *
- * Since: 1.7.5
- **/
-bool
-hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
-			 bool             *use_short_loca, /* OUT */
-			 hb_blob_t       **glyf_prime, /* OUT */
-			 hb_blob_t       **loca_prime /* OUT */)
-{
-  hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
-  const char *glyf_data = hb_blob_get_data (glyf_blob, nullptr);
-
-  OT::glyf::accelerator_t glyf;
-  glyf.init (plan->source);
-  bool result = _hb_subset_glyf_and_loca (glyf,
-					  glyf_data,
-					  plan,
-					  use_short_loca,
-					  glyf_prime,
-					  loca_prime);
-
-  hb_blob_destroy (glyf_blob);
-  glyf.fini ();
-
-  return result;
-}
diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh
deleted file mode 100644
index 99cf8f0..0000000
--- a/src/hb-subset-glyf.hh
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger
- */
-
-#ifndef HB_SUBSET_GLYF_HH
-#define HB_SUBSET_GLYF_HH
-
-#include "hb.hh"
-
-#include "hb-subset.hh"
-
-HB_INTERNAL bool
-hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
-			 bool             *use_short_loca, /* OUT */
-			 hb_blob_t       **glyf_prime      /* OUT */,
-			 hb_blob_t       **loca_prime      /* OUT */);
-
-#endif /* HB_SUBSET_GLYF_HH */
diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
index b3b27d4..34f1cb8 100644
--- a/src/hb-subset-input.cc
+++ b/src/hb-subset-input.cc
@@ -45,11 +45,44 @@
   input->unicodes = hb_set_create ();
   input->glyphs = hb_set_create ();
   input->name_ids = hb_set_create ();
+  hb_set_add_range (input->name_ids, 0, 6);
+  input->drop_tables = hb_set_create ();
   input->drop_hints = false;
-  input->drop_layout = true;
   input->desubroutinize = false;
   input->retain_gids = false;
 
+  hb_tag_t default_drop_tables[] = {
+    // Layout disabled by default
+    HB_TAG ('G', 'S', 'U', 'B'),
+    HB_TAG ('G', 'P', 'O', 'S'),
+    HB_TAG ('G', 'D', 'E', 'F'),
+    HB_TAG ('m', 'o', 'r', 'x'),
+    HB_TAG ('m', 'o', 'r', 't'),
+    HB_TAG ('k', 'e', 'r', 'x'),
+    HB_TAG ('k', 'e', 'r', 'n'),
+
+    // Copied from fontTools:
+    HB_TAG ('B', 'A', 'S', 'E'),
+    HB_TAG ('J', 'S', 'T', 'F'),
+    HB_TAG ('D', 'S', 'I', 'G'),
+    HB_TAG ('E', 'B', 'D', 'T'),
+    HB_TAG ('E', 'B', 'L', 'C'),
+    HB_TAG ('E', 'B', 'S', 'C'),
+    HB_TAG ('S', 'V', 'G', ' '),
+    HB_TAG ('P', 'C', 'L', 'T'),
+    HB_TAG ('L', 'T', 'S', 'H'),
+    // Graphite tables
+    HB_TAG ('F', 'e', 'a', 't'),
+    HB_TAG ('G', 'l', 'a', 't'),
+    HB_TAG ('G', 'l', 'o', 'c'),
+    HB_TAG ('S', 'i', 'l', 'f'),
+    HB_TAG ('S', 'i', 'l', 'l'),
+    // Colour
+    HB_TAG ('s', 'b', 'i', 'x')
+  };
+
+  input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
+
   return input;
 }
 
@@ -83,6 +116,7 @@
   hb_set_destroy (subset_input->unicodes);
   hb_set_destroy (subset_input->glyphs);
   hb_set_destroy (subset_input->name_ids);
+  hb_set_destroy (subset_input->drop_tables);
 
   free (subset_input);
 }
@@ -117,6 +151,12 @@
   return subset_input->name_ids;
 }
 
+HB_EXTERN hb_set_t *
+hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input)
+{
+  return subset_input->drop_tables;
+}
+
 HB_EXTERN void
 hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
 				hb_bool_t drop_hints)
@@ -131,19 +171,6 @@
 }
 
 HB_EXTERN void
-hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
-				 hb_bool_t drop_layout)
-{
-  subset_input->drop_layout = drop_layout;
-}
-
-HB_EXTERN hb_bool_t
-hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input)
-{
-  return subset_input->drop_layout;
-}
-
-HB_EXTERN void
 hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
         hb_bool_t desubroutinize)
 {
diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh
index d01fece..f6dd4ac 100644
--- a/src/hb-subset-input.hh
+++ b/src/hb-subset-input.hh
@@ -41,11 +41,11 @@
   hb_set_t *unicodes;
   hb_set_t *glyphs;
   hb_set_t *name_ids;
+  hb_set_t *drop_tables;
 
-  bool drop_hints : 1;
-  bool drop_layout : 1;
-  bool desubroutinize : 1;
-  bool retain_gids : 1;
+  bool drop_hints;
+  bool desubroutinize;
+  bool retain_gids;
   /* TODO
    *
    * features
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index fe636b1..7c1ed87 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -31,8 +31,10 @@
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
 #include "hb-ot-cff1-table.hh"
+#include "hb-ot-var-fvar-table.hh"
+#include "hb-ot-stat-table.hh"
 
-static void
+static inline void
 _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
 		       hb_codepoint_t gid,
 		       hb_set_t *gids_to_retain)
@@ -53,7 +55,8 @@
   }
 }
 
-static void
+#ifndef HB_NO_SUBSET_CFF
+static inline void
 _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
            hb_codepoint_t gid,
            hb_set_t *gids_to_retain)
@@ -65,8 +68,10 @@
     hb_set_add (gids_to_retain, accent_gid);
   }
 }
+#endif
 
-static void
+#ifndef HB_NO_SUBSET_LAYOUT
+static inline void
 _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
 {
   hb_set_t lookup_indices;
@@ -80,8 +85,9 @@
 					   &lookup_indices,
 					   gids_to_retain);
 }
+#endif
 
-static void
+static inline void
 _remove_invalid_gids (hb_set_t *glyphs,
 		      unsigned int num_glyphs)
 {
@@ -93,24 +99,21 @@
   }
 }
 
-static hb_set_t *
-_populate_gids_to_retain (hb_face_t *face,
+static void
+_populate_gids_to_retain (hb_subset_plan_t* plan,
 			  const hb_set_t *unicodes,
                           const hb_set_t *input_glyphs_to_retain,
-			  bool close_over_gsub,
-			  hb_set_t *unicodes_to_retain,
-			  hb_map_t *codepoint_to_glyph)
+			  bool close_over_gsub)
 {
   OT::cmap::accelerator_t cmap;
   OT::glyf::accelerator_t glyf;
   OT::cff1::accelerator_t cff;
-  cmap.init (face);
-  glyf.init (face);
-  cff.init (face);
+  cmap.init (plan->source);
+  glyf.init (plan->source);
+  cff.init (plan->source);
 
-  hb_set_t *initial_gids_to_retain = hb_set_create ();
-  initial_gids_to_retain->add (0); // Not-def
-  hb_set_union (initial_gids_to_retain, input_glyphs_to_retain);
+  plan->_glyphset_gsub->add (0); // Not-def
+  hb_set_union (plan->_glyphset_gsub, input_glyphs_to_retain);
 
   hb_codepoint_t cp = HB_SET_VALUE_INVALID;
   while (unicodes->next (&cp))
@@ -121,67 +124,92 @@
       DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
       continue;
     }
-    unicodes_to_retain->add (cp);
-    codepoint_to_glyph->set (cp, gid);
-    initial_gids_to_retain->add (gid);
+    plan->unicodes->add (cp);
+    plan->codepoint_to_glyph->set (cp, gid);
+    plan->_glyphset_gsub->add (gid);
   }
 
+#ifndef HB_NO_SUBSET_LAYOUT
   if (close_over_gsub)
     // Add all glyphs needed for GSUB substitutions.
-    _gsub_closure (face, initial_gids_to_retain);
+    _gsub_closure (plan->source, plan->_glyphset_gsub);
+#endif
+  _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
 
   // Populate a full set of glyphs to retain by adding all referenced
   // composite glyphs.
   hb_codepoint_t gid = HB_SET_VALUE_INVALID;
-  hb_set_t *all_gids_to_retain = hb_set_create ();
-  while (initial_gids_to_retain->next (&gid))
+  while (plan->_glyphset_gsub->next (&gid))
   {
-    _add_gid_and_children (glyf, gid, all_gids_to_retain);
+    _add_gid_and_children (glyf, gid, plan->_glyphset);
+#ifndef HB_NO_SUBSET_CFF
     if (cff.is_valid ())
-      _add_cff_seac_components (cff, gid, all_gids_to_retain);
+      _add_cff_seac_components (cff, gid, plan->_glyphset);
+#endif
   }
-  hb_set_destroy (initial_gids_to_retain);
 
-  _remove_invalid_gids (all_gids_to_retain, face->get_num_glyphs ());
-
+  _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
 
   cff.fini ();
   glyf.fini ();
   cmap.fini ();
-
-  return all_gids_to_retain;
 }
 
 static void
-_create_old_gid_to_new_gid_map (const hb_face_t                   *face,
-                                bool                               retain_gids,
-				hb_set_t                          *all_gids_to_retain,
-                                hb_map_t                          *glyph_map, /* OUT */
-                                hb_map_t                          *reverse_glyph_map, /* OUT */
-                                unsigned int                      *num_glyphs /* OUT */)
+_create_old_gid_to_new_gid_map (const hb_face_t *face,
+                                bool             retain_gids,
+				const hb_set_t  *all_gids_to_retain,
+                                hb_map_t        *glyph_map, /* OUT */
+                                hb_map_t        *reverse_glyph_map, /* OUT */
+                                unsigned int    *num_glyphs /* OUT */)
 {
-  hb_codepoint_t gid = HB_SET_VALUE_INVALID;
-  unsigned int length = 0;
-  for (unsigned int i = 0; all_gids_to_retain->next (&gid); i++) {
-    if (!retain_gids)
-    {
-      glyph_map->set (gid, i);
-      reverse_glyph_map->set (i, gid);
-    }
-    else
-    {
-      glyph_map->set (gid, gid);
-      reverse_glyph_map->set (gid, gid);
-    }
-    ++length;
-  }
-  if (!retain_gids || length == 0)
+  if (!retain_gids)
   {
-    *num_glyphs = length;
+    + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
+    | hb_sink (reverse_glyph_map)
+    ;
+    *num_glyphs = reverse_glyph_map->get_population ();
+  } else {
+    + hb_iter (all_gids_to_retain)
+    | hb_map ([] (hb_codepoint_t _) {
+		return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
+	      })
+    | hb_sink (reverse_glyph_map)
+    ;
+
+    unsigned max_glyph =
+    + hb_iter (all_gids_to_retain)
+    | hb_reduce (hb_max, 0)
+    ;
+    *num_glyphs = max_glyph + 1;
   }
-  else
+
+  + reverse_glyph_map->iter ()
+  | hb_map (&hb_pair_t<hb_codepoint_t, hb_codepoint_t>::reverse)
+  | hb_sink (glyph_map)
+  ;
+}
+
+static void
+_nameid_closure (hb_face_t           *face,
+                 hb_set_t            *nameids)
+{
+  hb_tag_t table_tags[32];
+  unsigned count = ARRAY_LENGTH (table_tags);
+  hb_face_get_table_tags (face, 0, &count, table_tags);
+  for (unsigned int i = 0; i < count; i++)
   {
-    *num_glyphs = face->get_num_glyphs ();
+    hb_tag_t tag = table_tags[i];
+    switch (tag) {
+      case HB_OT_TAG_STAT:
+        face->table.STAT->collect_name_ids (nameids);
+        break;
+      case HB_OT_TAG_fvar:
+        face->table.fvar->collect_name_ids (nameids);
+        break;
+      default:
+        break;
+    }
   }
 }
 
@@ -202,22 +230,25 @@
   hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
 
   plan->drop_hints = input->drop_hints;
-  plan->drop_layout = input->drop_layout;
   plan->desubroutinize = input->desubroutinize;
   plan->retain_gids = input->retain_gids;
   plan->unicodes = hb_set_create ();
   plan->name_ids = hb_set_reference (input->name_ids);
+  _nameid_closure (face, plan->name_ids);
+  plan->drop_tables = hb_set_reference (input->drop_tables);
   plan->source = hb_face_reference (face);
   plan->dest = hb_face_builder_create ();
+
+  plan->_glyphset = hb_set_create ();
+  plan->_glyphset_gsub = hb_set_create ();
   plan->codepoint_to_glyph = hb_map_create ();
   plan->glyph_map = hb_map_create ();
   plan->reverse_glyph_map = hb_map_create ();
-  plan->_glyphset = _populate_gids_to_retain (face,
-                                              input->unicodes,
-                                              input->glyphs,
-                                              !plan->drop_layout,
-                                              plan->unicodes,
-                                              plan->codepoint_to_glyph);
+
+  _populate_gids_to_retain (plan,
+                            input->unicodes,
+                            input->glyphs,
+                            !input->drop_tables->has (HB_OT_TAG_GSUB));
 
   _create_old_gid_to_new_gid_map (face,
                                   input->retain_gids,
@@ -241,12 +272,14 @@
 
   hb_set_destroy (plan->unicodes);
   hb_set_destroy (plan->name_ids);
+  hb_set_destroy (plan->drop_tables);
   hb_face_destroy (plan->source);
   hb_face_destroy (plan->dest);
   hb_map_destroy (plan->codepoint_to_glyph);
   hb_map_destroy (plan->glyph_map);
   hb_map_destroy (plan->reverse_glyph_map);
   hb_set_destroy (plan->_glyphset);
+  hb_set_destroy (plan->_glyphset_gsub);
 
   free (plan);
 }
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index abbab5e..ee44b63 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -40,16 +40,18 @@
   hb_object_header_t header;
 
   bool drop_hints : 1;
-  bool drop_layout : 1;
   bool desubroutinize : 1;
   bool retain_gids : 1;
 
   // For each cp that we'd like to retain maps to the corresponding gid.
   hb_set_t *unicodes;
 
-  //name_ids we would like to retain
+  // name_ids we would like to retain
   hb_set_t *name_ids;
 
+  // Tables which should be dropped.
+  hb_set_t *drop_tables;
+
   // The glyph subset
   hb_map_t *codepoint_to_glyph;
 
@@ -63,11 +65,14 @@
 
   unsigned int _num_output_glyphs;
   hb_set_t *_glyphset;
+  hb_set_t *_glyphset_gsub;
 
  public:
 
   /*
    * The set of input glyph ids which will be retained in the subset.
+   * Does NOT include ids kept due to retain_gids. You probably want to use
+   * glyph_map/reverse_glyph_map.
    */
   inline const hb_set_t *
   glyphset () const
@@ -76,6 +81,15 @@
   }
 
   /*
+   * The set of input glyph ids which will be retained in the subset.
+   */
+  inline const hb_set_t *
+  glyphset_gsub () const
+  {
+    return _glyphset_gsub;
+  }
+
+  /*
    * The total number of output glyphs in the final subset.
    */
   inline unsigned int
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 80d1628..19f46d1 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -28,7 +28,6 @@
 #include "hb-open-type.hh"
 
 #include "hb-subset.hh"
-#include "hb-subset-glyf.hh"
 
 #include "hb-open-file.hh"
 #include "hb-ot-cmap-table.hh"
@@ -70,7 +69,7 @@
 static bool
 _subset2 (hb_subset_plan_t *plan)
 {
-  bool result = true;
+  bool result = false;
   hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
   const TableType *table = source_blob->as<TableType> ();
 
@@ -78,6 +77,8 @@
   if (source_blob->data)
   {
     hb_vector_t<char> buf;
+    /* TODO Not all tables are glyph-related.  'name' table size for example should not be
+     * affected by number of glyphs.  Accommodate that. */
     unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
     DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
     if (unlikely (!buf.alloc (buf_size)))
@@ -156,10 +157,10 @@
   bool result = true;
   switch (tag) {
     case HB_OT_TAG_glyf:
-      result = _subset<const OT::glyf> (plan);
+      result = _subset2<const OT::glyf> (plan);
       break;
     case HB_OT_TAG_hdmx:
-      result = _subset<const OT::hdmx> (plan);
+      result = _subset2<const OT::hdmx> (plan);
       break;
     case HB_OT_TAG_name:
       result = _subset2<const OT::name> (plan);
@@ -173,13 +174,13 @@
       DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
       return true;
     case HB_OT_TAG_hmtx:
-      result = _subset<const OT::hmtx> (plan);
+      result = _subset2<const OT::hmtx> (plan);
       break;
     case HB_OT_TAG_vhea:
       DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx");
       return true;
     case HB_OT_TAG_vmtx:
-      result = _subset<const OT::vmtx> (plan);
+      result = _subset2<const OT::vmtx> (plan);
       break;
     case HB_OT_TAG_maxp:
       result = _subset<const OT::maxp> (plan);
@@ -196,6 +197,8 @@
     case HB_OT_TAG_post:
       result = _subset<const OT::post> (plan);
       break;
+
+#ifndef HB_NO_SUBSET_CFF
     case HB_OT_TAG_cff1:
       result = _subset<const OT::cff1> (plan);
       break;
@@ -205,8 +208,9 @@
     case HB_OT_TAG_VORG:
       result = _subset<const OT::VORG> (plan);
       break;
+#endif
 
-#if !defined(HB_NO_SUBSET_LAYOUT)
+#ifndef HB_NO_SUBSET_LAYOUT
     case HB_OT_TAG_GDEF:
       result = _subset2<const OT::GDEF> (plan);
       break;
@@ -243,6 +247,9 @@
 static bool
 _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
 {
+  if (plan->drop_tables->has (tag))
+    return true;
+
   switch (tag) {
     case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
     case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */
@@ -252,35 +259,18 @@
     case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
       return plan->drop_hints;
 
+#ifdef HB_NO_SUBSET_LAYOUT
     // Drop Layout Tables if requested.
     case HB_OT_TAG_GDEF:
     case HB_OT_TAG_GPOS:
     case HB_OT_TAG_GSUB:
-#if defined(HB_NO_SUBSET_LAYOUT)
+    case HB_TAG ('m', 'o', 'r', 'x'):
+    case HB_TAG ('m', 'o', 'r', 't'):
+    case HB_TAG ('k', 'e', 'r', 'x'):
+    case HB_TAG ('k', 'e', 'r', 'n'):
       return true;
 #endif
-      return plan->drop_layout;
 
-    // Drop these tables below by default, list pulled
-    // from fontTools:
-    case HB_TAG ('B', 'A', 'S', 'E'):
-    case HB_TAG ('J', 'S', 'T', 'F'):
-    case HB_TAG ('D', 'S', 'I', 'G'):
-    case HB_TAG ('E', 'B', 'D', 'T'):
-    case HB_TAG ('E', 'B', 'L', 'C'):
-    case HB_TAG ('E', 'B', 'S', 'C'):
-    case HB_TAG ('S', 'V', 'G', ' '):
-    case HB_TAG ('P', 'C', 'L', 'T'):
-    case HB_TAG ('L', 'T', 'S', 'H'):
-    // Graphite tables:
-    case HB_TAG ('F', 'e', 'a', 't'):
-    case HB_TAG ('G', 'l', 'a', 't'):
-    case HB_TAG ('G', 'l', 'o', 'c'):
-    case HB_TAG ('S', 'i', 'l', 'f'):
-    case HB_TAG ('S', 'i', 'l', 'l'):
-    // Colour
-    case HB_TAG ('s', 'b', 'i', 'x'):
-      return true;
     default:
       return false;
   }
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 5034506..c778896 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -57,6 +57,9 @@
 HB_EXTERN hb_set_t *
 hb_subset_input_nameid_set (hb_subset_input_t *subset_input);
 
+HB_EXTERN hb_set_t *
+hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input);
+
 HB_EXTERN void
 hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
 				hb_bool_t drop_hints);
@@ -64,12 +67,6 @@
 hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);
 
 HB_EXTERN void
-hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
-				 hb_bool_t drop_layout);
-HB_EXTERN hb_bool_t
-hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input);
-
-HB_EXTERN void
 hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
         hb_bool_t desubroutinize);
 HB_EXTERN hb_bool_t
diff --git a/src/hb-subset.hh b/src/hb-subset.hh
index 45cb763..b8dd07a 100644
--- a/src/hb-subset.hh
+++ b/src/hb-subset.hh
@@ -40,9 +40,19 @@
        hb_dispatch_context_t<hb_subset_context_t, bool, HB_DEBUG_SUBSET>
 {
   const char *get_name () { return "SUBSET"; }
-  template <typename T>
-  bool dispatch (const T &obj) { return obj.subset (this); }
-  static bool default_return_value () { return true; }
+  static return_t default_return_value () { return true; }
+
+  private:
+  template <typename T, typename ...Ts> auto
+  _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
+  ( obj.subset (this, hb_forward<Ts> (ds)...) )
+  template <typename T, typename ...Ts> auto
+  _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
+  ( obj.dispatch (this, hb_forward<Ts> (ds)...) )
+  public:
+  template <typename T, typename ...Ts> auto
+  dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
+  ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
 
   hb_subset_plan_t *plan;
   hb_serialize_context_t *serializer;
diff --git a/src/hb-ucd-table.hh b/src/hb-ucd-table.hh
new file mode 100644
index 0000000..95c4bf8
--- /dev/null
+++ b/src/hb-ucd-table.hh
@@ -0,0 +1,5160 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml
+ *
+ * on file with this description: Unicode 12.1.0
+ */
+
+#ifndef HB_UCD_TABLE_HH
+#define HB_UCD_TABLE_HH
+
+
+#include "hb.hh"
+
+static const hb_script_t
+_hb_ucd_sc_map[138] =
+{
+                   HB_SCRIPT_COMMON,              HB_SCRIPT_INHERITED,
+                  HB_SCRIPT_UNKNOWN,                 HB_SCRIPT_ARABIC,
+                 HB_SCRIPT_ARMENIAN,                HB_SCRIPT_BENGALI,
+                 HB_SCRIPT_CYRILLIC,             HB_SCRIPT_DEVANAGARI,
+                 HB_SCRIPT_GEORGIAN,                  HB_SCRIPT_GREEK,
+                 HB_SCRIPT_GUJARATI,               HB_SCRIPT_GURMUKHI,
+                   HB_SCRIPT_HANGUL,                    HB_SCRIPT_HAN,
+                   HB_SCRIPT_HEBREW,               HB_SCRIPT_HIRAGANA,
+                  HB_SCRIPT_KANNADA,               HB_SCRIPT_KATAKANA,
+                      HB_SCRIPT_LAO,                  HB_SCRIPT_LATIN,
+                HB_SCRIPT_MALAYALAM,                  HB_SCRIPT_ORIYA,
+                    HB_SCRIPT_TAMIL,                 HB_SCRIPT_TELUGU,
+                     HB_SCRIPT_THAI,                HB_SCRIPT_TIBETAN,
+                 HB_SCRIPT_BOPOMOFO,                HB_SCRIPT_BRAILLE,
+       HB_SCRIPT_CANADIAN_SYLLABICS,               HB_SCRIPT_CHEROKEE,
+                 HB_SCRIPT_ETHIOPIC,                  HB_SCRIPT_KHMER,
+                HB_SCRIPT_MONGOLIAN,                HB_SCRIPT_MYANMAR,
+                    HB_SCRIPT_OGHAM,                  HB_SCRIPT_RUNIC,
+                  HB_SCRIPT_SINHALA,                 HB_SCRIPT_SYRIAC,
+                   HB_SCRIPT_THAANA,                     HB_SCRIPT_YI,
+                  HB_SCRIPT_DESERET,                 HB_SCRIPT_GOTHIC,
+               HB_SCRIPT_OLD_ITALIC,                  HB_SCRIPT_BUHID,
+                  HB_SCRIPT_HANUNOO,                HB_SCRIPT_TAGALOG,
+                 HB_SCRIPT_TAGBANWA,                HB_SCRIPT_CYPRIOT,
+                    HB_SCRIPT_LIMBU,               HB_SCRIPT_LINEAR_B,
+                  HB_SCRIPT_OSMANYA,                HB_SCRIPT_SHAVIAN,
+                   HB_SCRIPT_TAI_LE,               HB_SCRIPT_UGARITIC,
+                 HB_SCRIPT_BUGINESE,                 HB_SCRIPT_COPTIC,
+               HB_SCRIPT_GLAGOLITIC,             HB_SCRIPT_KHAROSHTHI,
+              HB_SCRIPT_NEW_TAI_LUE,            HB_SCRIPT_OLD_PERSIAN,
+             HB_SCRIPT_SYLOTI_NAGRI,               HB_SCRIPT_TIFINAGH,
+                 HB_SCRIPT_BALINESE,              HB_SCRIPT_CUNEIFORM,
+                      HB_SCRIPT_NKO,               HB_SCRIPT_PHAGS_PA,
+               HB_SCRIPT_PHOENICIAN,                 HB_SCRIPT_CARIAN,
+                     HB_SCRIPT_CHAM,               HB_SCRIPT_KAYAH_LI,
+                   HB_SCRIPT_LEPCHA,                 HB_SCRIPT_LYCIAN,
+                   HB_SCRIPT_LYDIAN,               HB_SCRIPT_OL_CHIKI,
+                   HB_SCRIPT_REJANG,             HB_SCRIPT_SAURASHTRA,
+                HB_SCRIPT_SUNDANESE,                    HB_SCRIPT_VAI,
+                  HB_SCRIPT_AVESTAN,                  HB_SCRIPT_BAMUM,
+     HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,       HB_SCRIPT_IMPERIAL_ARAMAIC,
+    HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
+                 HB_SCRIPT_JAVANESE,                 HB_SCRIPT_KAITHI,
+                     HB_SCRIPT_LISU,           HB_SCRIPT_MEETEI_MAYEK,
+        HB_SCRIPT_OLD_SOUTH_ARABIAN,             HB_SCRIPT_OLD_TURKIC,
+                HB_SCRIPT_SAMARITAN,               HB_SCRIPT_TAI_THAM,
+                 HB_SCRIPT_TAI_VIET,                  HB_SCRIPT_BATAK,
+                   HB_SCRIPT_BRAHMI,                HB_SCRIPT_MANDAIC,
+                   HB_SCRIPT_CHAKMA,       HB_SCRIPT_MEROITIC_CURSIVE,
+     HB_SCRIPT_MEROITIC_HIEROGLYPHS,                   HB_SCRIPT_MIAO,
+                  HB_SCRIPT_SHARADA,           HB_SCRIPT_SORA_SOMPENG,
+                    HB_SCRIPT_TAKRI,              HB_SCRIPT_BASSA_VAH,
+       HB_SCRIPT_CAUCASIAN_ALBANIAN,               HB_SCRIPT_DUPLOYAN,
+                  HB_SCRIPT_ELBASAN,                HB_SCRIPT_GRANTHA,
+                   HB_SCRIPT_KHOJKI,              HB_SCRIPT_KHUDAWADI,
+                 HB_SCRIPT_LINEAR_A,               HB_SCRIPT_MAHAJANI,
+               HB_SCRIPT_MANICHAEAN,          HB_SCRIPT_MENDE_KIKAKUI,
+                     HB_SCRIPT_MODI,                    HB_SCRIPT_MRO,
+                HB_SCRIPT_NABATAEAN,      HB_SCRIPT_OLD_NORTH_ARABIAN,
+               HB_SCRIPT_OLD_PERMIC,           HB_SCRIPT_PAHAWH_HMONG,
+                HB_SCRIPT_PALMYRENE,            HB_SCRIPT_PAU_CIN_HAU,
+          HB_SCRIPT_PSALTER_PAHLAVI,                HB_SCRIPT_SIDDHAM,
+                  HB_SCRIPT_TIRHUTA,            HB_SCRIPT_WARANG_CITI,
+                     HB_SCRIPT_AHOM,  HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
+                   HB_SCRIPT_HATRAN,                HB_SCRIPT_MULTANI,
+            HB_SCRIPT_OLD_HUNGARIAN,            HB_SCRIPT_SIGNWRITING,
+                    HB_SCRIPT_ADLAM,              HB_SCRIPT_BHAIKSUKI,
+                  HB_SCRIPT_MARCHEN,                  HB_SCRIPT_OSAGE,
+                   HB_SCRIPT_TANGUT,                   HB_SCRIPT_NEWA,
+};
+static const hb_codepoint_t
+_hb_ucd_dm1_map[935] =
+{
+   0x003Bu, 0x004Bu, 0x0060u, 0x00B4u, 0x00B7u, 0x00C5u, 0x02B9u, 0x0300u,
+   0x0301u, 0x0313u, 0x0385u, 0x0386u, 0x0388u, 0x0389u, 0x038Au, 0x038Cu,
+   0x038Eu, 0x038Fu, 0x0390u, 0x03A9u, 0x03ACu, 0x03ADu, 0x03AEu, 0x03AFu,
+   0x03B0u, 0x03B9u, 0x03CCu, 0x03CDu, 0x03CEu, 0x2002u, 0x2003u, 0x3008u,
+   0x3009u, 0x349Eu, 0x34B9u, 0x34BBu, 0x34DFu, 0x3515u, 0x36EEu, 0x36FCu,
+   0x3781u, 0x382Fu, 0x3862u, 0x387Cu, 0x38C7u, 0x38E3u, 0x391Cu, 0x393Au,
+   0x3A2Eu, 0x3A6Cu, 0x3AE4u, 0x3B08u, 0x3B19u, 0x3B49u, 0x3B9Du, 0x3C18u,
+   0x3C4Eu, 0x3D33u, 0x3D96u, 0x3EACu, 0x3EB8u, 0x3F1Bu, 0x3FFCu, 0x4008u,
+   0x4018u, 0x4039u, 0x4046u, 0x4096u, 0x40E3u, 0x412Fu, 0x4202u, 0x4227u,
+   0x42A0u, 0x4301u, 0x4334u, 0x4359u, 0x43D5u, 0x43D9u, 0x440Bu, 0x446Bu,
+   0x452Bu, 0x455Du, 0x4561u, 0x456Bu, 0x45D7u, 0x45F9u, 0x4635u, 0x46BEu,
+   0x46C7u, 0x4995u, 0x49E6u, 0x4A6Eu, 0x4A76u, 0x4AB2u, 0x4B33u, 0x4BCEu,
+   0x4CCEu, 0x4CEDu, 0x4CF8u, 0x4D56u, 0x4E0Du, 0x4E26u, 0x4E32u, 0x4E38u,
+   0x4E39u, 0x4E3Du, 0x4E41u, 0x4E82u, 0x4E86u, 0x4EAEu, 0x4EC0u, 0x4ECCu,
+   0x4EE4u, 0x4F60u, 0x4F80u, 0x4F86u, 0x4F8Bu, 0x4FAEu, 0x4FBBu, 0x4FBFu,
+   0x5002u, 0x502Bu, 0x507Au, 0x5099u, 0x50CFu, 0x50DAu, 0x50E7u, 0x5140u,
+   0x5145u, 0x514Du, 0x5154u, 0x5164u, 0x5167u, 0x5168u, 0x5169u, 0x516Du,
+   0x5177u, 0x5180u, 0x518Du, 0x5192u, 0x5195u, 0x5197u, 0x51A4u, 0x51ACu,
+   0x51B5u, 0x51B7u, 0x51C9u, 0x51CCu, 0x51DCu, 0x51DEu, 0x51F5u, 0x5203u,
+   0x5207u, 0x5217u, 0x5229u, 0x523Au, 0x523Bu, 0x5246u, 0x5272u, 0x5277u,
+   0x5289u, 0x529Bu, 0x52A3u, 0x52B3u, 0x52C7u, 0x52C9u, 0x52D2u, 0x52DEu,
+   0x52E4u, 0x52F5u, 0x52FAu, 0x5305u, 0x5306u, 0x5317u, 0x533Fu, 0x5349u,
+   0x5351u, 0x535Au, 0x5373u, 0x5375u, 0x537Du, 0x537Fu, 0x53C3u, 0x53CAu,
+   0x53DFu, 0x53E5u, 0x53EBu, 0x53F1u, 0x5406u, 0x540Fu, 0x541Du, 0x5438u,
+   0x5442u, 0x5448u, 0x5468u, 0x549Eu, 0x54A2u, 0x54BDu, 0x54F6u, 0x5510u,
+   0x5553u, 0x5555u, 0x5563u, 0x5584u, 0x5587u, 0x5599u, 0x559Du, 0x55ABu,
+   0x55B3u, 0x55C0u, 0x55C2u, 0x55E2u, 0x5606u, 0x5651u, 0x5668u, 0x5674u,
+   0x56F9u, 0x5716u, 0x5717u, 0x578Bu, 0x57CEu, 0x57F4u, 0x580Du, 0x5831u,
+   0x5832u, 0x5840u, 0x585Au, 0x585Eu, 0x58A8u, 0x58ACu, 0x58B3u, 0x58D8u,
+   0x58DFu, 0x58EEu, 0x58F2u, 0x58F7u, 0x5906u, 0x591Au, 0x5922u, 0x5944u,
+   0x5948u, 0x5951u, 0x5954u, 0x5962u, 0x5973u, 0x59D8u, 0x59ECu, 0x5A1Bu,
+   0x5A27u, 0x5A62u, 0x5A66u, 0x5AB5u, 0x5B08u, 0x5B28u, 0x5B3Eu, 0x5B85u,
+   0x5BC3u, 0x5BD8u, 0x5BE7u, 0x5BEEu, 0x5BF3u, 0x5BFFu, 0x5C06u, 0x5C22u,
+   0x5C3Fu, 0x5C60u, 0x5C62u, 0x5C64u, 0x5C65u, 0x5C6Eu, 0x5C8Du, 0x5CC0u,
+   0x5D19u, 0x5D43u, 0x5D50u, 0x5D6Bu, 0x5D6Eu, 0x5D7Cu, 0x5DB2u, 0x5DBAu,
+   0x5DE1u, 0x5DE2u, 0x5DFDu, 0x5E28u, 0x5E3Du, 0x5E69u, 0x5E74u, 0x5EA6u,
+   0x5EB0u, 0x5EB3u, 0x5EB6u, 0x5EC9u, 0x5ECAu, 0x5ED2u, 0x5ED3u, 0x5ED9u,
+   0x5EECu, 0x5EFEu, 0x5F04u, 0x5F22u, 0x5F53u, 0x5F62u, 0x5F69u, 0x5F6Bu,
+   0x5F8Bu, 0x5F9Au, 0x5FA9u, 0x5FADu, 0x5FCDu, 0x5FD7u, 0x5FF5u, 0x5FF9u,
+   0x6012u, 0x601Cu, 0x6075u, 0x6081u, 0x6094u, 0x60C7u, 0x60D8u, 0x60E1u,
+   0x6108u, 0x6144u, 0x6148u, 0x614Cu, 0x614Eu, 0x6160u, 0x6168u, 0x617Au,
+   0x618Eu, 0x6190u, 0x61A4u, 0x61AFu, 0x61B2u, 0x61DEu, 0x61F2u, 0x61F6u,
+   0x6200u, 0x6210u, 0x621Bu, 0x622Eu, 0x6234u, 0x625Du, 0x62B1u, 0x62C9u,
+   0x62CFu, 0x62D3u, 0x62D4u, 0x62FCu, 0x62FEu, 0x633Du, 0x6350u, 0x6368u,
+   0x637Bu, 0x6383u, 0x63A0u, 0x63A9u, 0x63C4u, 0x63C5u, 0x63E4u, 0x641Cu,
+   0x6422u, 0x6452u, 0x6469u, 0x6477u, 0x647Eu, 0x649Au, 0x649Du, 0x64C4u,
+   0x654Fu, 0x6556u, 0x656Cu, 0x6578u, 0x6599u, 0x65C5u, 0x65E2u, 0x65E3u,
+   0x6613u, 0x6649u, 0x6674u, 0x6688u, 0x6691u, 0x669Cu, 0x66B4u, 0x66C6u,
+   0x66F4u, 0x66F8u, 0x6700u, 0x6717u, 0x671Bu, 0x6721u, 0x674Eu, 0x6753u,
+   0x6756u, 0x675Eu, 0x677Bu, 0x6785u, 0x6797u, 0x67F3u, 0x67FAu, 0x6817u,
+   0x681Fu, 0x6852u, 0x6881u, 0x6885u, 0x688Eu, 0x68A8u, 0x6914u, 0x6942u,
+   0x69A3u, 0x69EAu, 0x6A02u, 0x6A13u, 0x6AA8u, 0x6AD3u, 0x6ADBu, 0x6B04u,
+   0x6B21u, 0x6B54u, 0x6B72u, 0x6B77u, 0x6B79u, 0x6B9Fu, 0x6BAEu, 0x6BBAu,
+   0x6BBBu, 0x6C4Eu, 0x6C67u, 0x6C88u, 0x6CBFu, 0x6CCCu, 0x6CCDu, 0x6CE5u,
+   0x6D16u, 0x6D1Bu, 0x6D1Eu, 0x6D34u, 0x6D3Eu, 0x6D41u, 0x6D69u, 0x6D6Au,
+   0x6D77u, 0x6D78u, 0x6D85u, 0x6DCBu, 0x6DDAu, 0x6DEAu, 0x6DF9u, 0x6E1Au,
+   0x6E2Fu, 0x6E6Eu, 0x6E9Cu, 0x6EBAu, 0x6EC7u, 0x6ECBu, 0x6ED1u, 0x6EDBu,
+   0x6F0Fu, 0x6F22u, 0x6F23u, 0x6F6Eu, 0x6FC6u, 0x6FEBu, 0x6FFEu, 0x701Bu,
+   0x701Eu, 0x7039u, 0x704Au, 0x7070u, 0x7077u, 0x707Du, 0x7099u, 0x70ADu,
+   0x70C8u, 0x70D9u, 0x7145u, 0x7149u, 0x716Eu, 0x719Cu, 0x71CEu, 0x71D0u,
+   0x7210u, 0x721Bu, 0x7228u, 0x722Bu, 0x7235u, 0x7250u, 0x7262u, 0x7280u,
+   0x7295u, 0x72AFu, 0x72C0u, 0x72FCu, 0x732Au, 0x7375u, 0x737Au, 0x7387u,
+   0x738Bu, 0x73A5u, 0x73B2u, 0x73DEu, 0x7406u, 0x7409u, 0x7422u, 0x7447u,
+   0x745Cu, 0x7469u, 0x7471u, 0x7485u, 0x7489u, 0x7498u, 0x74CAu, 0x7506u,
+   0x7524u, 0x753Bu, 0x753Eu, 0x7559u, 0x7565u, 0x7570u, 0x75E2u, 0x7610u,
+   0x761Du, 0x761Fu, 0x7642u, 0x7669u, 0x76CAu, 0x76DBu, 0x76E7u, 0x76F4u,
+   0x7701u, 0x771Eu, 0x771Fu, 0x7740u, 0x774Au, 0x778Bu, 0x77A7u, 0x784Eu,
+   0x786Bu, 0x788Cu, 0x7891u, 0x78CAu, 0x78CCu, 0x78FBu, 0x792Au, 0x793Cu,
+   0x793Eu, 0x7948u, 0x7949u, 0x7950u, 0x7956u, 0x795Du, 0x795Eu, 0x7965u,
+   0x797Fu, 0x798Du, 0x798Eu, 0x798Fu, 0x79AEu, 0x79CAu, 0x79EBu, 0x7A1Cu,
+   0x7A40u, 0x7A4Au, 0x7A4Fu, 0x7A81u, 0x7AB1u, 0x7ACBu, 0x7AEEu, 0x7B20u,
+   0x7BC0u, 0x7BC6u, 0x7BC9u, 0x7C3Eu, 0x7C60u, 0x7C7Bu, 0x7C92u, 0x7CBEu,
+   0x7CD2u, 0x7CD6u, 0x7CE3u, 0x7CE7u, 0x7CE8u, 0x7D00u, 0x7D10u, 0x7D22u,
+   0x7D2Fu, 0x7D5Bu, 0x7D63u, 0x7DA0u, 0x7DBEu, 0x7DC7u, 0x7DF4u, 0x7E02u,
+   0x7E09u, 0x7E37u, 0x7E41u, 0x7E45u, 0x7F3Eu, 0x7F72u, 0x7F79u, 0x7F7Au,
+   0x7F85u, 0x7F95u, 0x7F9Au, 0x7FBDu, 0x7FFAu, 0x8001u, 0x8005u, 0x8046u,
+   0x8060u, 0x806Fu, 0x8070u, 0x807Eu, 0x808Bu, 0x80ADu, 0x80B2u, 0x8103u,
+   0x813Eu, 0x81D8u, 0x81E8u, 0x81EDu, 0x8201u, 0x8204u, 0x8218u, 0x826Fu,
+   0x8279u, 0x828Bu, 0x8291u, 0x829Du, 0x82B1u, 0x82B3u, 0x82BDu, 0x82E5u,
+   0x82E6u, 0x831Du, 0x8323u, 0x8336u, 0x8352u, 0x8353u, 0x8363u, 0x83ADu,
+   0x83BDu, 0x83C9u, 0x83CAu, 0x83CCu, 0x83DCu, 0x83E7u, 0x83EFu, 0x83F1u,
+   0x843Du, 0x8449u, 0x8457u, 0x84EEu, 0x84F1u, 0x84F3u, 0x84FCu, 0x8516u,
+   0x8564u, 0x85CDu, 0x85FAu, 0x8606u, 0x8612u, 0x862Du, 0x863Fu, 0x8650u,
+   0x865Cu, 0x8667u, 0x8669u, 0x8688u, 0x86A9u, 0x86E2u, 0x870Eu, 0x8728u,
+   0x876Bu, 0x8779u, 0x8786u, 0x87BAu, 0x87E1u, 0x8801u, 0x881Fu, 0x884Cu,
+   0x8860u, 0x8863u, 0x88C2u, 0x88CFu, 0x88D7u, 0x88DEu, 0x88E1u, 0x88F8u,
+   0x88FAu, 0x8910u, 0x8941u, 0x8964u, 0x8986u, 0x898Bu, 0x8996u, 0x8AA0u,
+   0x8AAAu, 0x8ABFu, 0x8ACBu, 0x8AD2u, 0x8AD6u, 0x8AEDu, 0x8AF8u, 0x8AFEu,
+   0x8B01u, 0x8B39u, 0x8B58u, 0x8B80u, 0x8B8Au, 0x8C48u, 0x8C55u, 0x8CABu,
+   0x8CC1u, 0x8CC2u, 0x8CC8u, 0x8CD3u, 0x8D08u, 0x8D1Bu, 0x8D77u, 0x8DBCu,
+   0x8DCBu, 0x8DEFu, 0x8DF0u, 0x8ECAu, 0x8ED4u, 0x8F26u, 0x8F2Au, 0x8F38u,
+   0x8F3Bu, 0x8F62u, 0x8F9Eu, 0x8FB0u, 0x8FB6u, 0x9023u, 0x9038u, 0x9072u,
+   0x907Cu, 0x908Fu, 0x9094u, 0x90CEu, 0x90DEu, 0x90F1u, 0x90FDu, 0x9111u,
+   0x911Bu, 0x916Au, 0x9199u, 0x91B4u, 0x91CCu, 0x91CFu, 0x91D1u, 0x9234u,
+   0x9238u, 0x9276u, 0x927Cu, 0x92D7u, 0x92D8u, 0x9304u, 0x934Au, 0x93F9u,
+   0x9415u, 0x958Bu, 0x95ADu, 0x95B7u, 0x962Eu, 0x964Bu, 0x964Du, 0x9675u,
+   0x9678u, 0x967Cu, 0x9686u, 0x96A3u, 0x96B7u, 0x96B8u, 0x96C3u, 0x96E2u,
+   0x96E3u, 0x96F6u, 0x96F7u, 0x9723u, 0x9732u, 0x9748u, 0x9756u, 0x97DBu,
+   0x97E0u, 0x97FFu, 0x980Bu, 0x9818u, 0x9829u, 0x983Bu, 0x985Eu, 0x98E2u,
+   0x98EFu, 0x98FCu, 0x9928u, 0x9929u, 0x99A7u, 0x99C2u, 0x99F1u, 0x99FEu,
+   0x9A6Au, 0x9B12u, 0x9B6Fu, 0x9C40u, 0x9C57u, 0x9CFDu, 0x9D67u, 0x9DB4u,
+   0x9DFAu, 0x9E1Eu, 0x9E7Fu, 0x9E97u, 0x9E9Fu, 0x9EBBu, 0x9ECEu, 0x9EF9u,
+   0x9EFEu, 0x9F05u, 0x9F0Fu, 0x9F16u, 0x9F3Bu, 0x9F43u, 0x9F8Du, 0x9F8Eu,
+   0x9F9Cu,0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu,
+  0x20A2Cu,0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu,
+  0x21DE4u,0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au,
+  0x22B0Cu,0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u,
+  0x233D5u,0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu,
+  0x23ED1u,0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u,
+  0x24814u,0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u,
+  0x25119u,0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu,
+  0x25AA7u,0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u,
+  0x262D9u,0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu,
+  0x26C36u,0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u,
+  0x278AEu,0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu,
+  0x28BFAu,0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u,
+  0x29B30u,0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u,
+};
+static const uint64_t
+_hb_ucd_dm2_map[1025] =
+{
+     HB_CODEPOINT_ENCODE3 (0x003Cu, 0x0338u, 0x226Eu),   HB_CODEPOINT_ENCODE3 (0x003Du, 0x0338u, 0x2260u),
+     HB_CODEPOINT_ENCODE3 (0x003Eu, 0x0338u, 0x226Fu),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0300u, 0x00C0u),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0301u, 0x00C1u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0302u, 0x00C2u),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0303u, 0x00C3u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0304u, 0x0100u),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0306u, 0x0102u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0307u, 0x0226u),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0308u, 0x00C4u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0309u, 0x1EA2u),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Au, 0x00C5u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Cu, 0x01CDu),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Fu, 0x0200u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0311u, 0x0202u),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0323u, 0x1EA0u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0325u, 0x1E00u),
+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0328u, 0x0104u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0307u, 0x1E02u),
+     HB_CODEPOINT_ENCODE3 (0x0042u, 0x0323u, 0x1E04u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0331u, 0x1E06u),
+     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0301u, 0x0106u),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x0302u, 0x0108u),
+     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0307u, 0x010Au),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x030Cu, 0x010Cu),
+     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0327u, 0x00C7u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0307u, 0x1E0Au),
+     HB_CODEPOINT_ENCODE3 (0x0044u, 0x030Cu, 0x010Eu),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0323u, 0x1E0Cu),
+     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0327u, 0x1E10u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x032Du, 0x1E12u),
+     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0331u, 0x1E0Eu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0300u, 0x00C8u),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0301u, 0x00C9u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0302u, 0x00CAu),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0303u, 0x1EBCu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0304u, 0x0112u),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0306u, 0x0114u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0307u, 0x0116u),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0308u, 0x00CBu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0309u, 0x1EBAu),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Cu, 0x011Au),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Fu, 0x0204u),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0311u, 0x0206u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0323u, 0x1EB8u),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0327u, 0x0228u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0328u, 0x0118u),
+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x032Du, 0x1E18u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0330u, 0x1E1Au),
+     HB_CODEPOINT_ENCODE3 (0x0046u, 0x0307u, 0x1E1Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0301u, 0x01F4u),
+     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0302u, 0x011Cu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0304u, 0x1E20u),
+     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0306u, 0x011Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0307u, 0x0120u),
+     HB_CODEPOINT_ENCODE3 (0x0047u, 0x030Cu, 0x01E6u),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0327u, 0x0122u),
+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0302u, 0x0124u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0307u, 0x1E22u),
+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0308u, 0x1E26u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x030Cu, 0x021Eu),
+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0323u, 0x1E24u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0327u, 0x1E28u),
+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x032Eu, 0x1E2Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0300u, 0x00CCu),
+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0301u, 0x00CDu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0302u, 0x00CEu),
+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0303u, 0x0128u),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0304u, 0x012Au),
+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0306u, 0x012Cu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0307u, 0x0130u),
+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0308u, 0x00CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0309u, 0x1EC8u),
+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Cu, 0x01CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Fu, 0x0208u),
+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0311u, 0x020Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0323u, 0x1ECAu),
+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0328u, 0x012Eu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0330u, 0x1E2Cu),
+     HB_CODEPOINT_ENCODE3 (0x004Au, 0x0302u, 0x0134u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0301u, 0x1E30u),
+     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x030Cu, 0x01E8u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0323u, 0x1E32u),
+     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0327u, 0x0136u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0331u, 0x1E34u),
+     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0301u, 0x0139u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x030Cu, 0x013Du),
+     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0323u, 0x1E36u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0327u, 0x013Bu),
+     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x032Du, 0x1E3Cu),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0331u, 0x1E3Au),
+     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0301u, 0x1E3Eu),   HB_CODEPOINT_ENCODE3 (0x004Du, 0x0307u, 0x1E40u),
+     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0323u, 0x1E42u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0300u, 0x01F8u),
+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0301u, 0x0143u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0303u, 0x00D1u),
+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0307u, 0x1E44u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x030Cu, 0x0147u),
+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0323u, 0x1E46u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0327u, 0x0145u),
+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x032Du, 0x1E4Au),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0331u, 0x1E48u),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0300u, 0x00D2u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0301u, 0x00D3u),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0302u, 0x00D4u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0303u, 0x00D5u),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0304u, 0x014Cu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0306u, 0x014Eu),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0307u, 0x022Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0308u, 0x00D6u),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0309u, 0x1ECEu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Bu, 0x0150u),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Cu, 0x01D1u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Fu, 0x020Cu),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0311u, 0x020Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x031Bu, 0x01A0u),
+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0323u, 0x1ECCu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0328u, 0x01EAu),
+     HB_CODEPOINT_ENCODE3 (0x0050u, 0x0301u, 0x1E54u),   HB_CODEPOINT_ENCODE3 (0x0050u, 0x0307u, 0x1E56u),
+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0301u, 0x0154u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0307u, 0x1E58u),
+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Cu, 0x0158u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Fu, 0x0210u),
+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0311u, 0x0212u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0323u, 0x1E5Au),
+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0327u, 0x0156u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0331u, 0x1E5Eu),
+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0301u, 0x015Au),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0302u, 0x015Cu),
+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0307u, 0x1E60u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x030Cu, 0x0160u),
+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0323u, 0x1E62u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0326u, 0x0218u),
+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0327u, 0x015Eu),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0307u, 0x1E6Au),
+     HB_CODEPOINT_ENCODE3 (0x0054u, 0x030Cu, 0x0164u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0323u, 0x1E6Cu),
+     HB_CODEPOINT_ENCODE3 (0x0054u, 0x0326u, 0x021Au),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0327u, 0x0162u),
+     HB_CODEPOINT_ENCODE3 (0x0054u, 0x032Du, 0x1E70u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0331u, 0x1E6Eu),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0300u, 0x00D9u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0301u, 0x00DAu),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0302u, 0x00DBu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0303u, 0x0168u),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0304u, 0x016Au),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0306u, 0x016Cu),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0308u, 0x00DCu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0309u, 0x1EE6u),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Au, 0x016Eu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Bu, 0x0170u),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Cu, 0x01D3u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Fu, 0x0214u),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0311u, 0x0216u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x031Bu, 0x01AFu),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0323u, 0x1EE4u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0324u, 0x1E72u),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0328u, 0x0172u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x032Du, 0x1E76u),
+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0330u, 0x1E74u),   HB_CODEPOINT_ENCODE3 (0x0056u, 0x0303u, 0x1E7Cu),
+     HB_CODEPOINT_ENCODE3 (0x0056u, 0x0323u, 0x1E7Eu),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0300u, 0x1E80u),
+     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0301u, 0x1E82u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0302u, 0x0174u),
+     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0307u, 0x1E86u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0308u, 0x1E84u),
+     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0323u, 0x1E88u),   HB_CODEPOINT_ENCODE3 (0x0058u, 0x0307u, 0x1E8Au),
+     HB_CODEPOINT_ENCODE3 (0x0058u, 0x0308u, 0x1E8Cu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0300u, 0x1EF2u),
+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0301u, 0x00DDu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0302u, 0x0176u),
+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0303u, 0x1EF8u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0304u, 0x0232u),
+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0307u, 0x1E8Eu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0308u, 0x0178u),
+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0309u, 0x1EF6u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0323u, 0x1EF4u),
+     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0301u, 0x0179u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0302u, 0x1E90u),
+     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0307u, 0x017Bu),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x030Cu, 0x017Du),
+     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0323u, 0x1E92u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0331u, 0x1E94u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0300u, 0x00E0u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0301u, 0x00E1u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0302u, 0x00E2u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0303u, 0x00E3u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0304u, 0x0101u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0306u, 0x0103u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0307u, 0x0227u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0308u, 0x00E4u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0309u, 0x1EA3u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Au, 0x00E5u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Cu, 0x01CEu),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Fu, 0x0201u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0311u, 0x0203u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0323u, 0x1EA1u),
+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0325u, 0x1E01u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0328u, 0x0105u),
+     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0307u, 0x1E03u),   HB_CODEPOINT_ENCODE3 (0x0062u, 0x0323u, 0x1E05u),
+     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0331u, 0x1E07u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0301u, 0x0107u),
+     HB_CODEPOINT_ENCODE3 (0x0063u, 0x0302u, 0x0109u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0307u, 0x010Bu),
+     HB_CODEPOINT_ENCODE3 (0x0063u, 0x030Cu, 0x010Du),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0327u, 0x00E7u),
+     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0307u, 0x1E0Bu),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x030Cu, 0x010Fu),
+     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0323u, 0x1E0Du),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0327u, 0x1E11u),
+     HB_CODEPOINT_ENCODE3 (0x0064u, 0x032Du, 0x1E13u),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0331u, 0x1E0Fu),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0300u, 0x00E8u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0301u, 0x00E9u),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0302u, 0x00EAu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0303u, 0x1EBDu),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0304u, 0x0113u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0306u, 0x0115u),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0307u, 0x0117u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0308u, 0x00EBu),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0309u, 0x1EBBu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Cu, 0x011Bu),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Fu, 0x0205u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0311u, 0x0207u),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0323u, 0x1EB9u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0327u, 0x0229u),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0328u, 0x0119u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x032Du, 0x1E19u),
+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0330u, 0x1E1Bu),   HB_CODEPOINT_ENCODE3 (0x0066u, 0x0307u, 0x1E1Fu),
+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0301u, 0x01F5u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0302u, 0x011Du),
+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0304u, 0x1E21u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0306u, 0x011Fu),
+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0307u, 0x0121u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x030Cu, 0x01E7u),
+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0327u, 0x0123u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0302u, 0x0125u),
+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0307u, 0x1E23u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0308u, 0x1E27u),
+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x030Cu, 0x021Fu),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0323u, 0x1E25u),
+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0327u, 0x1E29u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x032Eu, 0x1E2Bu),
+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0331u, 0x1E96u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0300u, 0x00ECu),
+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0301u, 0x00EDu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0302u, 0x00EEu),
+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0303u, 0x0129u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0304u, 0x012Bu),
+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0306u, 0x012Du),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0308u, 0x00EFu),
+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0309u, 0x1EC9u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Cu, 0x01D0u),
+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Fu, 0x0209u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0311u, 0x020Bu),
+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0323u, 0x1ECBu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0328u, 0x012Fu),
+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0330u, 0x1E2Du),   HB_CODEPOINT_ENCODE3 (0x006Au, 0x0302u, 0x0135u),
+     HB_CODEPOINT_ENCODE3 (0x006Au, 0x030Cu, 0x01F0u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0301u, 0x1E31u),
+     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x030Cu, 0x01E9u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0323u, 0x1E33u),
+     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0327u, 0x0137u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0331u, 0x1E35u),
+     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0301u, 0x013Au),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x030Cu, 0x013Eu),
+     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0323u, 0x1E37u),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0327u, 0x013Cu),
+     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x032Du, 0x1E3Du),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0331u, 0x1E3Bu),
+     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0301u, 0x1E3Fu),   HB_CODEPOINT_ENCODE3 (0x006Du, 0x0307u, 0x1E41u),
+     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0323u, 0x1E43u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0300u, 0x01F9u),
+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0301u, 0x0144u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0303u, 0x00F1u),
+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0307u, 0x1E45u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x030Cu, 0x0148u),
+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0323u, 0x1E47u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0327u, 0x0146u),
+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x032Du, 0x1E4Bu),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0331u, 0x1E49u),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0300u, 0x00F2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0301u, 0x00F3u),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0302u, 0x00F4u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0303u, 0x00F5u),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0304u, 0x014Du),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0306u, 0x014Fu),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0307u, 0x022Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0308u, 0x00F6u),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0309u, 0x1ECFu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Bu, 0x0151u),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Cu, 0x01D2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Fu, 0x020Du),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0311u, 0x020Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x031Bu, 0x01A1u),
+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0323u, 0x1ECDu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0328u, 0x01EBu),
+     HB_CODEPOINT_ENCODE3 (0x0070u, 0x0301u, 0x1E55u),   HB_CODEPOINT_ENCODE3 (0x0070u, 0x0307u, 0x1E57u),
+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0301u, 0x0155u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0307u, 0x1E59u),
+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Cu, 0x0159u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Fu, 0x0211u),
+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0311u, 0x0213u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0323u, 0x1E5Bu),
+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0327u, 0x0157u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0331u, 0x1E5Fu),
+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0301u, 0x015Bu),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0302u, 0x015Du),
+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0307u, 0x1E61u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x030Cu, 0x0161u),
+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0323u, 0x1E63u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0326u, 0x0219u),
+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0327u, 0x015Fu),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0307u, 0x1E6Bu),
+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0308u, 0x1E97u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x030Cu, 0x0165u),
+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0323u, 0x1E6Du),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0326u, 0x021Bu),
+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0327u, 0x0163u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x032Du, 0x1E71u),
+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0331u, 0x1E6Fu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0300u, 0x00F9u),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0301u, 0x00FAu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0302u, 0x00FBu),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0303u, 0x0169u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0304u, 0x016Bu),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0306u, 0x016Du),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0308u, 0x00FCu),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0309u, 0x1EE7u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Au, 0x016Fu),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Bu, 0x0171u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Cu, 0x01D4u),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Fu, 0x0215u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0311u, 0x0217u),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x031Bu, 0x01B0u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0323u, 0x1EE5u),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0324u, 0x1E73u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0328u, 0x0173u),
+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x032Du, 0x1E77u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0330u, 0x1E75u),
+     HB_CODEPOINT_ENCODE3 (0x0076u, 0x0303u, 0x1E7Du),   HB_CODEPOINT_ENCODE3 (0x0076u, 0x0323u, 0x1E7Fu),
+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0300u, 0x1E81u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0301u, 0x1E83u),
+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0302u, 0x0175u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0307u, 0x1E87u),
+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0308u, 0x1E85u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x030Au, 0x1E98u),
+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0323u, 0x1E89u),   HB_CODEPOINT_ENCODE3 (0x0078u, 0x0307u, 0x1E8Bu),
+     HB_CODEPOINT_ENCODE3 (0x0078u, 0x0308u, 0x1E8Du),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0300u, 0x1EF3u),
+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0301u, 0x00FDu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0302u, 0x0177u),
+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0303u, 0x1EF9u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0304u, 0x0233u),
+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0307u, 0x1E8Fu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0308u, 0x00FFu),
+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0309u, 0x1EF7u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x030Au, 0x1E99u),
+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0323u, 0x1EF5u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0301u, 0x017Au),
+     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0302u, 0x1E91u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0307u, 0x017Cu),
+     HB_CODEPOINT_ENCODE3 (0x007Au, 0x030Cu, 0x017Eu),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0323u, 0x1E93u),
+     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0331u, 0x1E95u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0300u, 0x1FEDu),
+     HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0301u, 0x0385u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0342u, 0x1FC1u),
+     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0300u, 0x1EA6u),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0301u, 0x1EA4u),
+     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0303u, 0x1EAAu),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0309u, 0x1EA8u),
+     HB_CODEPOINT_ENCODE3 (0x00C4u, 0x0304u, 0x01DEu),   HB_CODEPOINT_ENCODE3 (0x00C5u, 0x0301u, 0x01FAu),
+     HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0301u, 0x01FCu),   HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0304u, 0x01E2u),
+     HB_CODEPOINT_ENCODE3 (0x00C7u, 0x0301u, 0x1E08u),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0300u, 0x1EC0u),
+     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0301u, 0x1EBEu),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0303u, 0x1EC4u),
+     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0309u, 0x1EC2u),   HB_CODEPOINT_ENCODE3 (0x00CFu, 0x0301u, 0x1E2Eu),
+     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0300u, 0x1ED2u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0301u, 0x1ED0u),
+     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0303u, 0x1ED6u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0309u, 0x1ED4u),
+     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0301u, 0x1E4Cu),   HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0304u, 0x022Cu),
+     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0308u, 0x1E4Eu),   HB_CODEPOINT_ENCODE3 (0x00D6u, 0x0304u, 0x022Au),
+     HB_CODEPOINT_ENCODE3 (0x00D8u, 0x0301u, 0x01FEu),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0300u, 0x01DBu),
+     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0301u, 0x01D7u),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0304u, 0x01D5u),
+     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x030Cu, 0x01D9u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0300u, 0x1EA7u),
+     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0301u, 0x1EA5u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0303u, 0x1EABu),
+     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0309u, 0x1EA9u),   HB_CODEPOINT_ENCODE3 (0x00E4u, 0x0304u, 0x01DFu),
+     HB_CODEPOINT_ENCODE3 (0x00E5u, 0x0301u, 0x01FBu),   HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0301u, 0x01FDu),
+     HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0304u, 0x01E3u),   HB_CODEPOINT_ENCODE3 (0x00E7u, 0x0301u, 0x1E09u),
+     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0300u, 0x1EC1u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0301u, 0x1EBFu),
+     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0303u, 0x1EC5u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0309u, 0x1EC3u),
+     HB_CODEPOINT_ENCODE3 (0x00EFu, 0x0301u, 0x1E2Fu),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0300u, 0x1ED3u),
+     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0301u, 0x1ED1u),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0303u, 0x1ED7u),
+     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0309u, 0x1ED5u),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0301u, 0x1E4Du),
+     HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0304u, 0x022Du),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0308u, 0x1E4Fu),
+     HB_CODEPOINT_ENCODE3 (0x00F6u, 0x0304u, 0x022Bu),   HB_CODEPOINT_ENCODE3 (0x00F8u, 0x0301u, 0x01FFu),
+     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0300u, 0x01DCu),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0301u, 0x01D8u),
+     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0304u, 0x01D6u),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x030Cu, 0x01DAu),
+     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0300u, 0x1EB0u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0301u, 0x1EAEu),
+     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0303u, 0x1EB4u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0309u, 0x1EB2u),
+     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0300u, 0x1EB1u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0301u, 0x1EAFu),
+     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0303u, 0x1EB5u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0309u, 0x1EB3u),
+     HB_CODEPOINT_ENCODE3 (0x0112u, 0x0300u, 0x1E14u),   HB_CODEPOINT_ENCODE3 (0x0112u, 0x0301u, 0x1E16u),
+     HB_CODEPOINT_ENCODE3 (0x0113u, 0x0300u, 0x1E15u),   HB_CODEPOINT_ENCODE3 (0x0113u, 0x0301u, 0x1E17u),
+     HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0300u, 0x1E50u),   HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0301u, 0x1E52u),
+     HB_CODEPOINT_ENCODE3 (0x014Du, 0x0300u, 0x1E51u),   HB_CODEPOINT_ENCODE3 (0x014Du, 0x0301u, 0x1E53u),
+     HB_CODEPOINT_ENCODE3 (0x015Au, 0x0307u, 0x1E64u),   HB_CODEPOINT_ENCODE3 (0x015Bu, 0x0307u, 0x1E65u),
+     HB_CODEPOINT_ENCODE3 (0x0160u, 0x0307u, 0x1E66u),   HB_CODEPOINT_ENCODE3 (0x0161u, 0x0307u, 0x1E67u),
+     HB_CODEPOINT_ENCODE3 (0x0168u, 0x0301u, 0x1E78u),   HB_CODEPOINT_ENCODE3 (0x0169u, 0x0301u, 0x1E79u),
+     HB_CODEPOINT_ENCODE3 (0x016Au, 0x0308u, 0x1E7Au),   HB_CODEPOINT_ENCODE3 (0x016Bu, 0x0308u, 0x1E7Bu),
+     HB_CODEPOINT_ENCODE3 (0x017Fu, 0x0307u, 0x1E9Bu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0300u, 0x1EDCu),
+     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0301u, 0x1EDAu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0303u, 0x1EE0u),
+     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0309u, 0x1EDEu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0323u, 0x1EE2u),
+     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0300u, 0x1EDDu),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0301u, 0x1EDBu),
+     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0303u, 0x1EE1u),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0309u, 0x1EDFu),
+     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0323u, 0x1EE3u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0300u, 0x1EEAu),
+     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0301u, 0x1EE8u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0303u, 0x1EEEu),
+     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0309u, 0x1EECu),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0323u, 0x1EF0u),
+     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0300u, 0x1EEBu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0301u, 0x1EE9u),
+     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0303u, 0x1EEFu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0309u, 0x1EEDu),
+     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0323u, 0x1EF1u),   HB_CODEPOINT_ENCODE3 (0x01B7u, 0x030Cu, 0x01EEu),
+     HB_CODEPOINT_ENCODE3 (0x01EAu, 0x0304u, 0x01ECu),   HB_CODEPOINT_ENCODE3 (0x01EBu, 0x0304u, 0x01EDu),
+     HB_CODEPOINT_ENCODE3 (0x0226u, 0x0304u, 0x01E0u),   HB_CODEPOINT_ENCODE3 (0x0227u, 0x0304u, 0x01E1u),
+     HB_CODEPOINT_ENCODE3 (0x0228u, 0x0306u, 0x1E1Cu),   HB_CODEPOINT_ENCODE3 (0x0229u, 0x0306u, 0x1E1Du),
+     HB_CODEPOINT_ENCODE3 (0x022Eu, 0x0304u, 0x0230u),   HB_CODEPOINT_ENCODE3 (0x022Fu, 0x0304u, 0x0231u),
+     HB_CODEPOINT_ENCODE3 (0x0292u, 0x030Cu, 0x01EFu),   HB_CODEPOINT_ENCODE3 (0x0308u, 0x0301u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0300u, 0x1FBAu),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0301u, 0x0386u),
+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0304u, 0x1FB9u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0306u, 0x1FB8u),
+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0313u, 0x1F08u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0314u, 0x1F09u),
+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0345u, 0x1FBCu),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0300u, 0x1FC8u),
+     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0301u, 0x0388u),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0313u, 0x1F18u),
+     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0314u, 0x1F19u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0300u, 0x1FCAu),
+     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0301u, 0x0389u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0313u, 0x1F28u),
+     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0314u, 0x1F29u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0345u, 0x1FCCu),
+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0300u, 0x1FDAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0301u, 0x038Au),
+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0304u, 0x1FD9u),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0306u, 0x1FD8u),
+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0308u, 0x03AAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0313u, 0x1F38u),
+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0314u, 0x1F39u),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0300u, 0x1FF8u),
+     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0301u, 0x038Cu),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0313u, 0x1F48u),
+     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0314u, 0x1F49u),   HB_CODEPOINT_ENCODE3 (0x03A1u, 0x0314u, 0x1FECu),
+     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0300u, 0x1FEAu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0301u, 0x038Eu),
+     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0304u, 0x1FE9u),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0306u, 0x1FE8u),
+     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0308u, 0x03ABu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0314u, 0x1F59u),
+     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0300u, 0x1FFAu),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0301u, 0x038Fu),
+     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0313u, 0x1F68u),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0314u, 0x1F69u),
+     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0345u, 0x1FFCu),   HB_CODEPOINT_ENCODE3 (0x03ACu, 0x0345u, 0x1FB4u),
+     HB_CODEPOINT_ENCODE3 (0x03AEu, 0x0345u, 0x1FC4u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0300u, 0x1F70u),
+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0301u, 0x03ACu),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0304u, 0x1FB1u),
+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0306u, 0x1FB0u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0313u, 0x1F00u),
+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0314u, 0x1F01u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0342u, 0x1FB6u),
+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0345u, 0x1FB3u),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0300u, 0x1F72u),
+     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0301u, 0x03ADu),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0313u, 0x1F10u),
+     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0314u, 0x1F11u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0300u, 0x1F74u),
+     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0301u, 0x03AEu),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0313u, 0x1F20u),
+     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0314u, 0x1F21u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0342u, 0x1FC6u),
+     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0345u, 0x1FC3u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0300u, 0x1F76u),
+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0301u, 0x03AFu),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0304u, 0x1FD1u),
+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0306u, 0x1FD0u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0308u, 0x03CAu),
+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0313u, 0x1F30u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0314u, 0x1F31u),
+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0342u, 0x1FD6u),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0300u, 0x1F78u),
+     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0301u, 0x03CCu),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0313u, 0x1F40u),
+     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0314u, 0x1F41u),   HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0313u, 0x1FE4u),
+     HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0314u, 0x1FE5u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0300u, 0x1F7Au),
+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0301u, 0x03CDu),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0304u, 0x1FE1u),
+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0306u, 0x1FE0u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0308u, 0x03CBu),
+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0313u, 0x1F50u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0314u, 0x1F51u),
+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0342u, 0x1FE6u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0300u, 0x1F7Cu),
+     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0301u, 0x03CEu),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0313u, 0x1F60u),
+     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0314u, 0x1F61u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0342u, 0x1FF6u),
+     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0345u, 0x1FF3u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0300u, 0x1FD2u),
+     HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0301u, 0x0390u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0342u, 0x1FD7u),
+     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0300u, 0x1FE2u),   HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0301u, 0x03B0u),
+     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0342u, 0x1FE7u),   HB_CODEPOINT_ENCODE3 (0x03CEu, 0x0345u, 0x1FF4u),
+     HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0301u, 0x03D3u),   HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0308u, 0x03D4u),
+     HB_CODEPOINT_ENCODE3 (0x0406u, 0x0308u, 0x0407u),   HB_CODEPOINT_ENCODE3 (0x0410u, 0x0306u, 0x04D0u),
+     HB_CODEPOINT_ENCODE3 (0x0410u, 0x0308u, 0x04D2u),   HB_CODEPOINT_ENCODE3 (0x0413u, 0x0301u, 0x0403u),
+     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0300u, 0x0400u),   HB_CODEPOINT_ENCODE3 (0x0415u, 0x0306u, 0x04D6u),
+     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0308u, 0x0401u),   HB_CODEPOINT_ENCODE3 (0x0416u, 0x0306u, 0x04C1u),
+     HB_CODEPOINT_ENCODE3 (0x0416u, 0x0308u, 0x04DCu),   HB_CODEPOINT_ENCODE3 (0x0417u, 0x0308u, 0x04DEu),
+     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0300u, 0x040Du),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0304u, 0x04E2u),
+     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0306u, 0x0419u),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0308u, 0x04E4u),
+     HB_CODEPOINT_ENCODE3 (0x041Au, 0x0301u, 0x040Cu),   HB_CODEPOINT_ENCODE3 (0x041Eu, 0x0308u, 0x04E6u),
+     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0304u, 0x04EEu),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x0306u, 0x040Eu),
+     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0308u, 0x04F0u),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x030Bu, 0x04F2u),
+     HB_CODEPOINT_ENCODE3 (0x0427u, 0x0308u, 0x04F4u),   HB_CODEPOINT_ENCODE3 (0x042Bu, 0x0308u, 0x04F8u),
+     HB_CODEPOINT_ENCODE3 (0x042Du, 0x0308u, 0x04ECu),   HB_CODEPOINT_ENCODE3 (0x0430u, 0x0306u, 0x04D1u),
+     HB_CODEPOINT_ENCODE3 (0x0430u, 0x0308u, 0x04D3u),   HB_CODEPOINT_ENCODE3 (0x0433u, 0x0301u, 0x0453u),
+     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0300u, 0x0450u),   HB_CODEPOINT_ENCODE3 (0x0435u, 0x0306u, 0x04D7u),
+     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0308u, 0x0451u),   HB_CODEPOINT_ENCODE3 (0x0436u, 0x0306u, 0x04C2u),
+     HB_CODEPOINT_ENCODE3 (0x0436u, 0x0308u, 0x04DDu),   HB_CODEPOINT_ENCODE3 (0x0437u, 0x0308u, 0x04DFu),
+     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0300u, 0x045Du),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0304u, 0x04E3u),
+     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0306u, 0x0439u),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0308u, 0x04E5u),
+     HB_CODEPOINT_ENCODE3 (0x043Au, 0x0301u, 0x045Cu),   HB_CODEPOINT_ENCODE3 (0x043Eu, 0x0308u, 0x04E7u),
+     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0304u, 0x04EFu),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x0306u, 0x045Eu),
+     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0308u, 0x04F1u),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x030Bu, 0x04F3u),
+     HB_CODEPOINT_ENCODE3 (0x0447u, 0x0308u, 0x04F5u),   HB_CODEPOINT_ENCODE3 (0x044Bu, 0x0308u, 0x04F9u),
+     HB_CODEPOINT_ENCODE3 (0x044Du, 0x0308u, 0x04EDu),   HB_CODEPOINT_ENCODE3 (0x0456u, 0x0308u, 0x0457u),
+     HB_CODEPOINT_ENCODE3 (0x0474u, 0x030Fu, 0x0476u),   HB_CODEPOINT_ENCODE3 (0x0475u, 0x030Fu, 0x0477u),
+     HB_CODEPOINT_ENCODE3 (0x04D8u, 0x0308u, 0x04DAu),   HB_CODEPOINT_ENCODE3 (0x04D9u, 0x0308u, 0x04DBu),
+     HB_CODEPOINT_ENCODE3 (0x04E8u, 0x0308u, 0x04EAu),   HB_CODEPOINT_ENCODE3 (0x04E9u, 0x0308u, 0x04EBu),
+     HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BFu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D2u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05D3u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D4u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05B9u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05D6u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D8u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05B4u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05DAu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BFu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05DCu, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05DEu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E0u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05E1u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E3u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05E4u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E4u, 0x05BFu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05E6u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E7u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05E8u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05C1u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05C2u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x05EAu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05F2u, 0x05B7u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0627u, 0x0653u, 0x0622u),   HB_CODEPOINT_ENCODE3 (0x0627u, 0x0654u, 0x0623u),
+     HB_CODEPOINT_ENCODE3 (0x0627u, 0x0655u, 0x0625u),   HB_CODEPOINT_ENCODE3 (0x0648u, 0x0654u, 0x0624u),
+     HB_CODEPOINT_ENCODE3 (0x064Au, 0x0654u, 0x0626u),   HB_CODEPOINT_ENCODE3 (0x06C1u, 0x0654u, 0x06C2u),
+     HB_CODEPOINT_ENCODE3 (0x06D2u, 0x0654u, 0x06D3u),   HB_CODEPOINT_ENCODE3 (0x06D5u, 0x0654u, 0x06C0u),
+     HB_CODEPOINT_ENCODE3 (0x0915u, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0916u, 0x093Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0917u, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x091Cu, 0x093Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0921u, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0922u, 0x093Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0928u, 0x093Cu, 0x0929u),   HB_CODEPOINT_ENCODE3 (0x092Bu, 0x093Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x092Fu, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0930u, 0x093Cu, 0x0931u),
+     HB_CODEPOINT_ENCODE3 (0x0933u, 0x093Cu, 0x0934u),   HB_CODEPOINT_ENCODE3 (0x09A1u, 0x09BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x09A2u, 0x09BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x09AFu, 0x09BCu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x09C7u, 0x09BEu, 0x09CBu),   HB_CODEPOINT_ENCODE3 (0x09C7u, 0x09D7u, 0x09CCu),
+     HB_CODEPOINT_ENCODE3 (0x0A16u, 0x0A3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0A17u, 0x0A3Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0A1Cu, 0x0A3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0A2Bu, 0x0A3Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0A32u, 0x0A3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0A38u, 0x0A3Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0B21u, 0x0B3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0B22u, 0x0B3Cu, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B3Eu, 0x0B4Bu),   HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B56u, 0x0B48u),
+     HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B57u, 0x0B4Cu),   HB_CODEPOINT_ENCODE3 (0x0B92u, 0x0BD7u, 0x0B94u),
+     HB_CODEPOINT_ENCODE3 (0x0BC6u, 0x0BBEu, 0x0BCAu),   HB_CODEPOINT_ENCODE3 (0x0BC6u, 0x0BD7u, 0x0BCCu),
+     HB_CODEPOINT_ENCODE3 (0x0BC7u, 0x0BBEu, 0x0BCBu),   HB_CODEPOINT_ENCODE3 (0x0C46u, 0x0C56u, 0x0C48u),
+     HB_CODEPOINT_ENCODE3 (0x0CBFu, 0x0CD5u, 0x0CC0u),   HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CC2u, 0x0CCAu),
+     HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CD5u, 0x0CC7u),   HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CD6u, 0x0CC8u),
+     HB_CODEPOINT_ENCODE3 (0x0CCAu, 0x0CD5u, 0x0CCBu),   HB_CODEPOINT_ENCODE3 (0x0D46u, 0x0D3Eu, 0x0D4Au),
+     HB_CODEPOINT_ENCODE3 (0x0D46u, 0x0D57u, 0x0D4Cu),   HB_CODEPOINT_ENCODE3 (0x0D47u, 0x0D3Eu, 0x0D4Bu),
+     HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DCAu, 0x0DDAu),   HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DCFu, 0x0DDCu),
+     HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DDFu, 0x0DDEu),   HB_CODEPOINT_ENCODE3 (0x0DDCu, 0x0DCAu, 0x0DDDu),
+     HB_CODEPOINT_ENCODE3 (0x0F40u, 0x0FB5u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F42u, 0x0FB7u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0F4Cu, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F51u, 0x0FB7u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0F56u, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F5Bu, 0x0FB7u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F72u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F74u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F80u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F90u, 0x0FB5u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0F92u, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F9Cu, 0x0FB7u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0FA1u, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0FA6u, 0x0FB7u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0FABu, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0FB2u, 0x0F80u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x0FB3u, 0x0F80u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x1025u, 0x102Eu, 0x1026u),
+     HB_CODEPOINT_ENCODE3 (0x1B05u, 0x1B35u, 0x1B06u),   HB_CODEPOINT_ENCODE3 (0x1B07u, 0x1B35u, 0x1B08u),
+     HB_CODEPOINT_ENCODE3 (0x1B09u, 0x1B35u, 0x1B0Au),   HB_CODEPOINT_ENCODE3 (0x1B0Bu, 0x1B35u, 0x1B0Cu),
+     HB_CODEPOINT_ENCODE3 (0x1B0Du, 0x1B35u, 0x1B0Eu),   HB_CODEPOINT_ENCODE3 (0x1B11u, 0x1B35u, 0x1B12u),
+     HB_CODEPOINT_ENCODE3 (0x1B3Au, 0x1B35u, 0x1B3Bu),   HB_CODEPOINT_ENCODE3 (0x1B3Cu, 0x1B35u, 0x1B3Du),
+     HB_CODEPOINT_ENCODE3 (0x1B3Eu, 0x1B35u, 0x1B40u),   HB_CODEPOINT_ENCODE3 (0x1B3Fu, 0x1B35u, 0x1B41u),
+     HB_CODEPOINT_ENCODE3 (0x1B42u, 0x1B35u, 0x1B43u),   HB_CODEPOINT_ENCODE3 (0x1E36u, 0x0304u, 0x1E38u),
+     HB_CODEPOINT_ENCODE3 (0x1E37u, 0x0304u, 0x1E39u),   HB_CODEPOINT_ENCODE3 (0x1E5Au, 0x0304u, 0x1E5Cu),
+     HB_CODEPOINT_ENCODE3 (0x1E5Bu, 0x0304u, 0x1E5Du),   HB_CODEPOINT_ENCODE3 (0x1E62u, 0x0307u, 0x1E68u),
+     HB_CODEPOINT_ENCODE3 (0x1E63u, 0x0307u, 0x1E69u),   HB_CODEPOINT_ENCODE3 (0x1EA0u, 0x0302u, 0x1EACu),
+     HB_CODEPOINT_ENCODE3 (0x1EA0u, 0x0306u, 0x1EB6u),   HB_CODEPOINT_ENCODE3 (0x1EA1u, 0x0302u, 0x1EADu),
+     HB_CODEPOINT_ENCODE3 (0x1EA1u, 0x0306u, 0x1EB7u),   HB_CODEPOINT_ENCODE3 (0x1EB8u, 0x0302u, 0x1EC6u),
+     HB_CODEPOINT_ENCODE3 (0x1EB9u, 0x0302u, 0x1EC7u),   HB_CODEPOINT_ENCODE3 (0x1ECCu, 0x0302u, 0x1ED8u),
+     HB_CODEPOINT_ENCODE3 (0x1ECDu, 0x0302u, 0x1ED9u),   HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0300u, 0x1F02u),
+     HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0301u, 0x1F04u),   HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0342u, 0x1F06u),
+     HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0345u, 0x1F80u),   HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0300u, 0x1F03u),
+     HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0301u, 0x1F05u),   HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0342u, 0x1F07u),
+     HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0345u, 0x1F81u),   HB_CODEPOINT_ENCODE3 (0x1F02u, 0x0345u, 0x1F82u),
+     HB_CODEPOINT_ENCODE3 (0x1F03u, 0x0345u, 0x1F83u),   HB_CODEPOINT_ENCODE3 (0x1F04u, 0x0345u, 0x1F84u),
+     HB_CODEPOINT_ENCODE3 (0x1F05u, 0x0345u, 0x1F85u),   HB_CODEPOINT_ENCODE3 (0x1F06u, 0x0345u, 0x1F86u),
+     HB_CODEPOINT_ENCODE3 (0x1F07u, 0x0345u, 0x1F87u),   HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0300u, 0x1F0Au),
+     HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0301u, 0x1F0Cu),   HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0342u, 0x1F0Eu),
+     HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0345u, 0x1F88u),   HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0300u, 0x1F0Bu),
+     HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0301u, 0x1F0Du),   HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0342u, 0x1F0Fu),
+     HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0345u, 0x1F89u),   HB_CODEPOINT_ENCODE3 (0x1F0Au, 0x0345u, 0x1F8Au),
+     HB_CODEPOINT_ENCODE3 (0x1F0Bu, 0x0345u, 0x1F8Bu),   HB_CODEPOINT_ENCODE3 (0x1F0Cu, 0x0345u, 0x1F8Cu),
+     HB_CODEPOINT_ENCODE3 (0x1F0Du, 0x0345u, 0x1F8Du),   HB_CODEPOINT_ENCODE3 (0x1F0Eu, 0x0345u, 0x1F8Eu),
+     HB_CODEPOINT_ENCODE3 (0x1F0Fu, 0x0345u, 0x1F8Fu),   HB_CODEPOINT_ENCODE3 (0x1F10u, 0x0300u, 0x1F12u),
+     HB_CODEPOINT_ENCODE3 (0x1F10u, 0x0301u, 0x1F14u),   HB_CODEPOINT_ENCODE3 (0x1F11u, 0x0300u, 0x1F13u),
+     HB_CODEPOINT_ENCODE3 (0x1F11u, 0x0301u, 0x1F15u),   HB_CODEPOINT_ENCODE3 (0x1F18u, 0x0300u, 0x1F1Au),
+     HB_CODEPOINT_ENCODE3 (0x1F18u, 0x0301u, 0x1F1Cu),   HB_CODEPOINT_ENCODE3 (0x1F19u, 0x0300u, 0x1F1Bu),
+     HB_CODEPOINT_ENCODE3 (0x1F19u, 0x0301u, 0x1F1Du),   HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0300u, 0x1F22u),
+     HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0301u, 0x1F24u),   HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0342u, 0x1F26u),
+     HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0345u, 0x1F90u),   HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0300u, 0x1F23u),
+     HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0301u, 0x1F25u),   HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0342u, 0x1F27u),
+     HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0345u, 0x1F91u),   HB_CODEPOINT_ENCODE3 (0x1F22u, 0x0345u, 0x1F92u),
+     HB_CODEPOINT_ENCODE3 (0x1F23u, 0x0345u, 0x1F93u),   HB_CODEPOINT_ENCODE3 (0x1F24u, 0x0345u, 0x1F94u),
+     HB_CODEPOINT_ENCODE3 (0x1F25u, 0x0345u, 0x1F95u),   HB_CODEPOINT_ENCODE3 (0x1F26u, 0x0345u, 0x1F96u),
+     HB_CODEPOINT_ENCODE3 (0x1F27u, 0x0345u, 0x1F97u),   HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0300u, 0x1F2Au),
+     HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0301u, 0x1F2Cu),   HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0342u, 0x1F2Eu),
+     HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0345u, 0x1F98u),   HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0300u, 0x1F2Bu),
+     HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0301u, 0x1F2Du),   HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0342u, 0x1F2Fu),
+     HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0345u, 0x1F99u),   HB_CODEPOINT_ENCODE3 (0x1F2Au, 0x0345u, 0x1F9Au),
+     HB_CODEPOINT_ENCODE3 (0x1F2Bu, 0x0345u, 0x1F9Bu),   HB_CODEPOINT_ENCODE3 (0x1F2Cu, 0x0345u, 0x1F9Cu),
+     HB_CODEPOINT_ENCODE3 (0x1F2Du, 0x0345u, 0x1F9Du),   HB_CODEPOINT_ENCODE3 (0x1F2Eu, 0x0345u, 0x1F9Eu),
+     HB_CODEPOINT_ENCODE3 (0x1F2Fu, 0x0345u, 0x1F9Fu),   HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0300u, 0x1F32u),
+     HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0301u, 0x1F34u),   HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0342u, 0x1F36u),
+     HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0300u, 0x1F33u),   HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0301u, 0x1F35u),
+     HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0342u, 0x1F37u),   HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0300u, 0x1F3Au),
+     HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0301u, 0x1F3Cu),   HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0342u, 0x1F3Eu),
+     HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0300u, 0x1F3Bu),   HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0301u, 0x1F3Du),
+     HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0342u, 0x1F3Fu),   HB_CODEPOINT_ENCODE3 (0x1F40u, 0x0300u, 0x1F42u),
+     HB_CODEPOINT_ENCODE3 (0x1F40u, 0x0301u, 0x1F44u),   HB_CODEPOINT_ENCODE3 (0x1F41u, 0x0300u, 0x1F43u),
+     HB_CODEPOINT_ENCODE3 (0x1F41u, 0x0301u, 0x1F45u),   HB_CODEPOINT_ENCODE3 (0x1F48u, 0x0300u, 0x1F4Au),
+     HB_CODEPOINT_ENCODE3 (0x1F48u, 0x0301u, 0x1F4Cu),   HB_CODEPOINT_ENCODE3 (0x1F49u, 0x0300u, 0x1F4Bu),
+     HB_CODEPOINT_ENCODE3 (0x1F49u, 0x0301u, 0x1F4Du),   HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0300u, 0x1F52u),
+     HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0301u, 0x1F54u),   HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0342u, 0x1F56u),
+     HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0300u, 0x1F53u),   HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0301u, 0x1F55u),
+     HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0342u, 0x1F57u),   HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0300u, 0x1F5Bu),
+     HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0301u, 0x1F5Du),   HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0342u, 0x1F5Fu),
+     HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0300u, 0x1F62u),   HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0301u, 0x1F64u),
+     HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0342u, 0x1F66u),   HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0345u, 0x1FA0u),
+     HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0300u, 0x1F63u),   HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0301u, 0x1F65u),
+     HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0342u, 0x1F67u),   HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0345u, 0x1FA1u),
+     HB_CODEPOINT_ENCODE3 (0x1F62u, 0x0345u, 0x1FA2u),   HB_CODEPOINT_ENCODE3 (0x1F63u, 0x0345u, 0x1FA3u),
+     HB_CODEPOINT_ENCODE3 (0x1F64u, 0x0345u, 0x1FA4u),   HB_CODEPOINT_ENCODE3 (0x1F65u, 0x0345u, 0x1FA5u),
+     HB_CODEPOINT_ENCODE3 (0x1F66u, 0x0345u, 0x1FA6u),   HB_CODEPOINT_ENCODE3 (0x1F67u, 0x0345u, 0x1FA7u),
+     HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0300u, 0x1F6Au),   HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0301u, 0x1F6Cu),
+     HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0342u, 0x1F6Eu),   HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0345u, 0x1FA8u),
+     HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0300u, 0x1F6Bu),   HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0301u, 0x1F6Du),
+     HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0342u, 0x1F6Fu),   HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0345u, 0x1FA9u),
+     HB_CODEPOINT_ENCODE3 (0x1F6Au, 0x0345u, 0x1FAAu),   HB_CODEPOINT_ENCODE3 (0x1F6Bu, 0x0345u, 0x1FABu),
+     HB_CODEPOINT_ENCODE3 (0x1F6Cu, 0x0345u, 0x1FACu),   HB_CODEPOINT_ENCODE3 (0x1F6Du, 0x0345u, 0x1FADu),
+     HB_CODEPOINT_ENCODE3 (0x1F6Eu, 0x0345u, 0x1FAEu),   HB_CODEPOINT_ENCODE3 (0x1F6Fu, 0x0345u, 0x1FAFu),
+     HB_CODEPOINT_ENCODE3 (0x1F70u, 0x0345u, 0x1FB2u),   HB_CODEPOINT_ENCODE3 (0x1F74u, 0x0345u, 0x1FC2u),
+     HB_CODEPOINT_ENCODE3 (0x1F7Cu, 0x0345u, 0x1FF2u),   HB_CODEPOINT_ENCODE3 (0x1FB6u, 0x0345u, 0x1FB7u),
+     HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0300u, 0x1FCDu),   HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0301u, 0x1FCEu),
+     HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0342u, 0x1FCFu),   HB_CODEPOINT_ENCODE3 (0x1FC6u, 0x0345u, 0x1FC7u),
+     HB_CODEPOINT_ENCODE3 (0x1FF6u, 0x0345u, 0x1FF7u),   HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0300u, 0x1FDDu),
+     HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0301u, 0x1FDEu),   HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0342u, 0x1FDFu),
+     HB_CODEPOINT_ENCODE3 (0x2190u, 0x0338u, 0x219Au),   HB_CODEPOINT_ENCODE3 (0x2192u, 0x0338u, 0x219Bu),
+     HB_CODEPOINT_ENCODE3 (0x2194u, 0x0338u, 0x21AEu),   HB_CODEPOINT_ENCODE3 (0x21D0u, 0x0338u, 0x21CDu),
+     HB_CODEPOINT_ENCODE3 (0x21D2u, 0x0338u, 0x21CFu),   HB_CODEPOINT_ENCODE3 (0x21D4u, 0x0338u, 0x21CEu),
+     HB_CODEPOINT_ENCODE3 (0x2203u, 0x0338u, 0x2204u),   HB_CODEPOINT_ENCODE3 (0x2208u, 0x0338u, 0x2209u),
+     HB_CODEPOINT_ENCODE3 (0x220Bu, 0x0338u, 0x220Cu),   HB_CODEPOINT_ENCODE3 (0x2223u, 0x0338u, 0x2224u),
+     HB_CODEPOINT_ENCODE3 (0x2225u, 0x0338u, 0x2226u),   HB_CODEPOINT_ENCODE3 (0x223Cu, 0x0338u, 0x2241u),
+     HB_CODEPOINT_ENCODE3 (0x2243u, 0x0338u, 0x2244u),   HB_CODEPOINT_ENCODE3 (0x2245u, 0x0338u, 0x2247u),
+     HB_CODEPOINT_ENCODE3 (0x2248u, 0x0338u, 0x2249u),   HB_CODEPOINT_ENCODE3 (0x224Du, 0x0338u, 0x226Du),
+     HB_CODEPOINT_ENCODE3 (0x2261u, 0x0338u, 0x2262u),   HB_CODEPOINT_ENCODE3 (0x2264u, 0x0338u, 0x2270u),
+     HB_CODEPOINT_ENCODE3 (0x2265u, 0x0338u, 0x2271u),   HB_CODEPOINT_ENCODE3 (0x2272u, 0x0338u, 0x2274u),
+     HB_CODEPOINT_ENCODE3 (0x2273u, 0x0338u, 0x2275u),   HB_CODEPOINT_ENCODE3 (0x2276u, 0x0338u, 0x2278u),
+     HB_CODEPOINT_ENCODE3 (0x2277u, 0x0338u, 0x2279u),   HB_CODEPOINT_ENCODE3 (0x227Au, 0x0338u, 0x2280u),
+     HB_CODEPOINT_ENCODE3 (0x227Bu, 0x0338u, 0x2281u),   HB_CODEPOINT_ENCODE3 (0x227Cu, 0x0338u, 0x22E0u),
+     HB_CODEPOINT_ENCODE3 (0x227Du, 0x0338u, 0x22E1u),   HB_CODEPOINT_ENCODE3 (0x2282u, 0x0338u, 0x2284u),
+     HB_CODEPOINT_ENCODE3 (0x2283u, 0x0338u, 0x2285u),   HB_CODEPOINT_ENCODE3 (0x2286u, 0x0338u, 0x2288u),
+     HB_CODEPOINT_ENCODE3 (0x2287u, 0x0338u, 0x2289u),   HB_CODEPOINT_ENCODE3 (0x2291u, 0x0338u, 0x22E2u),
+     HB_CODEPOINT_ENCODE3 (0x2292u, 0x0338u, 0x22E3u),   HB_CODEPOINT_ENCODE3 (0x22A2u, 0x0338u, 0x22ACu),
+     HB_CODEPOINT_ENCODE3 (0x22A8u, 0x0338u, 0x22ADu),   HB_CODEPOINT_ENCODE3 (0x22A9u, 0x0338u, 0x22AEu),
+     HB_CODEPOINT_ENCODE3 (0x22ABu, 0x0338u, 0x22AFu),   HB_CODEPOINT_ENCODE3 (0x22B2u, 0x0338u, 0x22EAu),
+     HB_CODEPOINT_ENCODE3 (0x22B3u, 0x0338u, 0x22EBu),   HB_CODEPOINT_ENCODE3 (0x22B4u, 0x0338u, 0x22ECu),
+     HB_CODEPOINT_ENCODE3 (0x22B5u, 0x0338u, 0x22EDu),   HB_CODEPOINT_ENCODE3 (0x2ADDu, 0x0338u, 0x0000u),
+     HB_CODEPOINT_ENCODE3 (0x3046u, 0x3099u, 0x3094u),   HB_CODEPOINT_ENCODE3 (0x304Bu, 0x3099u, 0x304Cu),
+     HB_CODEPOINT_ENCODE3 (0x304Du, 0x3099u, 0x304Eu),   HB_CODEPOINT_ENCODE3 (0x304Fu, 0x3099u, 0x3050u),
+     HB_CODEPOINT_ENCODE3 (0x3051u, 0x3099u, 0x3052u),   HB_CODEPOINT_ENCODE3 (0x3053u, 0x3099u, 0x3054u),
+     HB_CODEPOINT_ENCODE3 (0x3055u, 0x3099u, 0x3056u),   HB_CODEPOINT_ENCODE3 (0x3057u, 0x3099u, 0x3058u),
+     HB_CODEPOINT_ENCODE3 (0x3059u, 0x3099u, 0x305Au),   HB_CODEPOINT_ENCODE3 (0x305Bu, 0x3099u, 0x305Cu),
+     HB_CODEPOINT_ENCODE3 (0x305Du, 0x3099u, 0x305Eu),   HB_CODEPOINT_ENCODE3 (0x305Fu, 0x3099u, 0x3060u),
+     HB_CODEPOINT_ENCODE3 (0x3061u, 0x3099u, 0x3062u),   HB_CODEPOINT_ENCODE3 (0x3064u, 0x3099u, 0x3065u),
+     HB_CODEPOINT_ENCODE3 (0x3066u, 0x3099u, 0x3067u),   HB_CODEPOINT_ENCODE3 (0x3068u, 0x3099u, 0x3069u),
+     HB_CODEPOINT_ENCODE3 (0x306Fu, 0x3099u, 0x3070u),   HB_CODEPOINT_ENCODE3 (0x306Fu, 0x309Au, 0x3071u),
+     HB_CODEPOINT_ENCODE3 (0x3072u, 0x3099u, 0x3073u),   HB_CODEPOINT_ENCODE3 (0x3072u, 0x309Au, 0x3074u),
+     HB_CODEPOINT_ENCODE3 (0x3075u, 0x3099u, 0x3076u),   HB_CODEPOINT_ENCODE3 (0x3075u, 0x309Au, 0x3077u),
+     HB_CODEPOINT_ENCODE3 (0x3078u, 0x3099u, 0x3079u),   HB_CODEPOINT_ENCODE3 (0x3078u, 0x309Au, 0x307Au),
+     HB_CODEPOINT_ENCODE3 (0x307Bu, 0x3099u, 0x307Cu),   HB_CODEPOINT_ENCODE3 (0x307Bu, 0x309Au, 0x307Du),
+     HB_CODEPOINT_ENCODE3 (0x309Du, 0x3099u, 0x309Eu),   HB_CODEPOINT_ENCODE3 (0x30A6u, 0x3099u, 0x30F4u),
+     HB_CODEPOINT_ENCODE3 (0x30ABu, 0x3099u, 0x30ACu),   HB_CODEPOINT_ENCODE3 (0x30ADu, 0x3099u, 0x30AEu),
+     HB_CODEPOINT_ENCODE3 (0x30AFu, 0x3099u, 0x30B0u),   HB_CODEPOINT_ENCODE3 (0x30B1u, 0x3099u, 0x30B2u),
+     HB_CODEPOINT_ENCODE3 (0x30B3u, 0x3099u, 0x30B4u),   HB_CODEPOINT_ENCODE3 (0x30B5u, 0x3099u, 0x30B6u),
+     HB_CODEPOINT_ENCODE3 (0x30B7u, 0x3099u, 0x30B8u),   HB_CODEPOINT_ENCODE3 (0x30B9u, 0x3099u, 0x30BAu),
+     HB_CODEPOINT_ENCODE3 (0x30BBu, 0x3099u, 0x30BCu),   HB_CODEPOINT_ENCODE3 (0x30BDu, 0x3099u, 0x30BEu),
+     HB_CODEPOINT_ENCODE3 (0x30BFu, 0x3099u, 0x30C0u),   HB_CODEPOINT_ENCODE3 (0x30C1u, 0x3099u, 0x30C2u),
+     HB_CODEPOINT_ENCODE3 (0x30C4u, 0x3099u, 0x30C5u),   HB_CODEPOINT_ENCODE3 (0x30C6u, 0x3099u, 0x30C7u),
+     HB_CODEPOINT_ENCODE3 (0x30C8u, 0x3099u, 0x30C9u),   HB_CODEPOINT_ENCODE3 (0x30CFu, 0x3099u, 0x30D0u),
+     HB_CODEPOINT_ENCODE3 (0x30CFu, 0x309Au, 0x30D1u),   HB_CODEPOINT_ENCODE3 (0x30D2u, 0x3099u, 0x30D3u),
+     HB_CODEPOINT_ENCODE3 (0x30D2u, 0x309Au, 0x30D4u),   HB_CODEPOINT_ENCODE3 (0x30D5u, 0x3099u, 0x30D6u),
+     HB_CODEPOINT_ENCODE3 (0x30D5u, 0x309Au, 0x30D7u),   HB_CODEPOINT_ENCODE3 (0x30D8u, 0x3099u, 0x30D9u),
+     HB_CODEPOINT_ENCODE3 (0x30D8u, 0x309Au, 0x30DAu),   HB_CODEPOINT_ENCODE3 (0x30DBu, 0x3099u, 0x30DCu),
+     HB_CODEPOINT_ENCODE3 (0x30DBu, 0x309Au, 0x30DDu),   HB_CODEPOINT_ENCODE3 (0x30EFu, 0x3099u, 0x30F7u),
+     HB_CODEPOINT_ENCODE3 (0x30F0u, 0x3099u, 0x30F8u),   HB_CODEPOINT_ENCODE3 (0x30F1u, 0x3099u, 0x30F9u),
+     HB_CODEPOINT_ENCODE3 (0x30F2u, 0x3099u, 0x30FAu),   HB_CODEPOINT_ENCODE3 (0x30FDu, 0x3099u, 0x30FEu),
+     HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C1u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C2u, 0x0000u),
+  HB_CODEPOINT_ENCODE3 (0x11099u, 0x110BAu, 0x1109Au),HB_CODEPOINT_ENCODE3 (0x1109Bu, 0x110BAu, 0x1109Cu),
+  HB_CODEPOINT_ENCODE3 (0x110A5u, 0x110BAu, 0x110ABu),HB_CODEPOINT_ENCODE3 (0x11131u, 0x11127u, 0x1112Eu),
+  HB_CODEPOINT_ENCODE3 (0x11132u, 0x11127u, 0x1112Fu),HB_CODEPOINT_ENCODE3 (0x11347u, 0x1133Eu, 0x1134Bu),
+  HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu),
+  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu),
+  HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu),
+   HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D158u, 0x1D165u, 0x0000u),
+   HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Eu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Fu, 0x0000u),
+   HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D170u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D171u, 0x0000u),
+   HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D172u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1B9u, 0x1D165u, 0x0000u),
+   HB_CODEPOINT_ENCODE3 (0x1D1BAu, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Eu, 0x0000u),
+   HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Eu, 0x0000u),
+   HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Fu, 0x0000u),
+};
+
+#ifndef HB_OPTIMIZE_SIZE
+
+static const uint8_t
+_hb_ucd_u8[31814] =
+{
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 28,
+   29, 26, 30, 31, 32, 33, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 34, 35, 35, 35, 35,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 38, 39, 40,
+   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+   26, 57, 58, 59, 59, 59, 59, 59, 26, 26, 60, 59, 59, 59, 59, 59,
+   59, 59, 26, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 26, 62, 59, 63, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 64, 26, 65, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 66, 67, 59, 59, 59, 59, 68, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 69, 70, 71, 72, 73, 74, 59, 59,
+   75, 76, 59, 59, 77, 59, 78, 79, 80, 81, 73, 82, 83, 84, 59, 59,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 85, 26, 26, 26, 26, 26, 26, 26, 86, 87, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 88, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 89, 59, 59, 59, 59, 59, 59, 26, 90, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   91, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 92,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 93,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   29, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 25, 25, 25, 21,
+   21,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 22, 21, 18, 24, 16,
+   24,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 22, 25, 18, 25,  0,
+   29, 21, 23, 23, 23, 23, 26, 21, 24, 26,  7, 20, 25,  1, 26, 24,
+   26, 25, 15, 15, 24,  5, 21, 21, 24, 15,  7, 19, 15, 15, 15, 21,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9, 25,  9,  9,  9,  9,  9,  9,  9,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5, 25,  5,  5,  5,  5,  5,  5,  5,  5,
+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
+    9,  5,  9,  5,  9,  5,  9,  5,  5,  9,  5,  9,  5,  9,  5,  9,
+    5,  9,  5,  9,  5,  9,  5,  9,  5,  5,  9,  5,  9,  5,  9,  5,
+    9,  5,  9,  5,  9,  5,  9,  5,  9,  9,  5,  9,  5,  9,  5,  5,
+    5,  9,  9,  5,  9,  5,  9,  9,  5,  9,  9,  9,  5,  5,  9,  9,
+    9,  9,  5,  9,  9,  5,  9,  9,  9,  5,  5,  5,  9,  9,  5,  9,
+    9,  5,  9,  5,  9,  5,  9,  9,  5,  9,  5,  5,  9,  5,  9,  9,
+    5,  9,  9,  9,  5,  9,  5,  9,  9,  5,  5,  7,  9,  5,  5,  5,
+    7,  7,  7,  7,  9,  8,  5,  9,  8,  5,  9,  8,  5,  9,  5,  9,
+    5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  5,  9,  5,
+    5,  9,  8,  5,  9,  5,  9,  9,  9,  5,  9,  5,  9,  5,  9,  5,
+    9,  5,  9,  5,  5,  5,  5,  5,  5,  5,  9,  9,  5,  9,  9,  5,
+    5,  9,  5,  9,  9,  9,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
+    5,  5,  5,  5,  7,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+    6,  6, 24, 24, 24, 24,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+    6,  6, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    6,  6,  6,  6,  6, 24, 24, 24, 24, 24, 24, 24,  6, 24,  6, 24,
+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    9,  5,  9,  5,  6, 24,  9,  5,  2,  2,  6,  5,  5,  5, 21,  9,
+    2,  2,  2,  2, 24, 24,  9, 21,  9,  9,  9,  2,  9,  2,  9,  9,
+    5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,
+    5,  5,  9,  9,  9,  5,  5,  5,  9,  5,  9,  5,  9,  5,  9,  5,
+    5,  5,  5,  5,  9,  5, 25,  9,  5,  9,  9,  5,  5,  9,  9,  9,
+    9,  5, 26, 12, 12, 12, 12, 12, 11, 11,  9,  5,  9,  5,  9,  5,
+    9,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  5,
+    2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  2,  2,  6, 21, 21, 21, 21, 21, 21,
+    5,  5,  5,  5,  5,  5,  5,  5,  5, 21, 17,  2,  2, 26, 26, 23,
+    2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 17, 12,
+   21, 12, 12, 21, 12, 12, 21, 12,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  7,
+    7,  7,  7, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    1,  1,  1,  1,  1,  1, 25, 25, 25, 21, 21, 23, 21, 21, 26, 26,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21,  1,  2, 21, 21,
+    6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21,  7,  7,
+   12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7, 21,  7, 12, 12, 12, 12, 12, 12, 12,  1, 26, 12,
+   12, 12, 12, 12, 12,  6,  6, 12, 12, 26, 12, 12, 12, 12,  7,  7,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  7, 26, 26,  7,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  1,
+    7, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  7,  7,  7,
+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12,
+   12, 12, 12, 12,  6,  6, 26, 21, 21, 21,  6,  2,  2, 12, 23, 23,
+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12,  6, 12, 12, 12, 12, 12,
+   12, 12, 12, 12,  6, 12, 12, 12,  6, 12, 12, 12, 12, 12,  2,  2,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12,  2,  2, 21,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,
+    2,  2,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12,  1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 10, 12,  7, 10, 10,
+   10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 12, 10, 10,
+    7, 12, 12, 12, 12, 12, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7, 12, 12, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   21,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,
+    7,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,
+    7,  2,  7,  2,  2,  2,  7,  7,  7,  7,  2,  2, 12,  7, 10, 10,
+   10, 12, 12, 12, 12,  2,  2, 10, 10,  2,  2, 10, 10, 12,  7,  2,
+    2,  2,  2,  2,  2,  2,  2, 10,  2,  2,  2,  2,  7,  7,  2,  7,
+    7,  7, 12, 12,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    7,  7, 23, 23, 15, 15, 15, 15, 15, 15, 26, 23,  7, 21, 12,  2,
+    2, 12, 12, 10,  2,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  7,
+    7,  2,  7,  7,  2,  7,  7,  2,  7,  7,  2,  2, 12,  2, 10, 10,
+   10, 12, 12,  2,  2,  2,  2, 12, 12,  2,  2, 12, 12, 12,  2,  2,
+    2, 12,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  2,  7,  2,
+    2,  2,  2,  2,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   12, 12,  7,  7,  7, 12, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2, 12, 12, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,
+    7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  2,  2, 12,  7, 10, 10,
+   10, 12, 12, 12, 12, 12,  2, 12, 12, 10,  2, 10, 10, 12,  2,  2,
+    7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   21, 23,  2,  2,  2,  2,  2,  2,  2,  7, 12, 12, 12, 12, 12, 12,
+    2, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,
+    7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  2,  2, 12,  7, 10, 12,
+   10, 12, 12, 12, 12,  2,  2, 10, 10,  2,  2, 10, 10, 12,  2,  2,
+    2,  2,  2,  2,  2,  2, 12, 10,  2,  2,  2,  2,  7,  7,  2,  7,
+   26,  7, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2, 12,  7,  2,  7,  7,  7,  7,  7,  7,  2,  2,  2,  7,  7,
+    7,  2,  7,  7,  7,  7,  2,  2,  2,  7,  7,  2,  7,  2,  7,  7,
+    2,  2,  2,  7,  7,  2,  2,  2,  7,  7,  7,  2,  2,  2,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2, 10, 10,
+   12, 10, 10,  2,  2,  2, 10, 10, 10,  2, 10, 10, 10, 12,  2,  2,
+    7,  2,  2,  2,  2,  2,  2, 10,  2,  2,  2,  2,  2,  2,  2,  2,
+   15, 15, 15, 26, 26, 26, 26, 26, 26, 23, 26,  2,  2,  2,  2,  2,
+   12, 10, 10, 10, 12,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
+    7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  7, 12, 12,
+   12, 10, 10, 10, 10,  2, 12, 12, 12,  2, 12, 12, 12, 12,  2,  2,
+    2,  2,  2,  2,  2, 12, 12,  2,  7,  7,  7,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2, 21, 15, 15, 15, 15, 15, 15, 15, 26,
+    7, 12, 10, 10, 21,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
+    7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  2,  2, 12,  7, 10, 12,
+   10, 10, 10, 10, 10,  2, 12, 10, 10,  2, 10, 10, 12, 12,  2,  2,
+    2,  2,  2,  2,  2, 10, 10,  2,  2,  2,  2,  2,  2,  2,  7,  2,
+    2,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   12, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12,  7, 10, 10,
+   10, 12, 12, 12, 12,  2, 10, 10, 10,  2, 10, 10, 10, 12,  7, 26,
+    2,  2,  2,  2,  7,  7,  7, 10, 15, 15, 15, 15, 15, 15, 15,  7,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 26,  7,  7,  7,  7,  7,  7,
+    2,  2, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  7,  7,  7,  7,  7,  7,
+    7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2, 12,  2,  2,  2,  2, 10,
+   10, 10, 12, 12, 12,  2, 12,  2, 10, 10, 10, 10, 10, 10, 10, 10,
+    2,  2, 10, 10, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7, 12,  7,  7, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2, 23,
+    7,  7,  7,  7,  7,  7,  6, 12, 12, 12, 12, 12, 12, 12, 12, 21,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21,  2,  2,  2,  2,
+    2,  7,  7,  2,  7,  2,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,
+    7,  7,  7,  7,  2,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7, 12,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 12,  7,  2,  2,
+    7,  7,  7,  7,  7,  2,  6,  2, 12, 12, 12, 12, 12, 12,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  7,  7,  7,  7,
+    7, 26, 26, 26, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 26, 21, 26, 26, 26, 12, 12, 26, 26, 26, 26, 26, 26,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 26, 12, 26, 12, 26, 12, 22, 18, 22, 18, 10, 10,
+    7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,
+    2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
+   12, 12, 12, 12, 12, 21, 12, 12,  7,  7,  7,  7,  7, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2, 26, 26,
+   26, 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26,  2, 26, 26,
+   21, 21, 21, 21, 21, 26, 26, 26, 26, 21, 21,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 10, 12, 12, 12,
+   12, 10, 12, 12, 12, 12, 12, 12, 10, 12, 12, 10, 10, 12, 12,  7,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, 21,
+    7,  7,  7,  7,  7,  7, 10, 10, 12, 12,  7,  7,  7,  7, 12, 12,
+   12,  7, 10, 10, 10,  7,  7, 10, 10, 10, 10, 10, 10, 10,  7,  7,
+    7, 12, 12, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7, 12, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 12,  7, 10,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 12, 26, 26,
+    9,  9,  9,  9,  9,  9,  2,  9,  2,  2,  2,  2,  2,  9,  2,  2,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 21,  6,  5,  5,  5,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  2,  7,  2,  7,  7,  7,  7,  2,  2,
+    7,  2,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,  7,  2,
+    7,  2,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2, 12, 12, 12,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,
+    9,  9,  9,  9,  9,  9,  2,  2,  5,  5,  5,  5,  5,  5,  2,  2,
+   17,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 26, 21,  7,
+   29,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 22, 18,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 21, 21, 21, 14, 14,
+   14,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
+    7,  7, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7, 12, 12, 12, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  2, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 10, 10,
+   10, 10, 10, 10, 10, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 21, 21, 21,  6, 21, 21, 21, 23,  7, 12,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  2,  2,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,
+   21, 21, 21, 21, 21, 21, 17, 21, 21, 21, 21, 12, 12, 12,  1,  2,
+    7,  7,  7,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7, 12,  7,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,
+   12, 12, 12, 10, 10, 10, 10, 12, 12, 10, 10, 10,  2,  2,  2,  2,
+   10, 10, 12, 10, 10, 10, 10, 10, 10, 12, 12, 12,  2,  2,  2,  2,
+   26,  2,  2,  2, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,
+    7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15,  2,  2,  2, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+    7,  7,  7,  7,  7,  7,  7, 12, 12, 10, 10, 12,  2,  2, 21, 21,
+    7,  7,  7,  7,  7, 10, 12, 10, 12, 12, 12, 12, 12, 12, 12,  2,
+   12, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10,
+   10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2, 12,
+   21, 21, 21, 21, 21, 21, 21,  6, 21, 21, 21, 21, 21, 21,  2,  2,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11,  2,
+   12, 12, 12, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7, 12, 10, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10,
+   10, 10, 12, 10, 10,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,
+   21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,
+   12, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 12, 12, 12,  7,  7,
+    7,  7,  7,  7,  7,  7, 12, 10, 12, 12, 10, 10, 10, 12, 10, 12,
+   12, 12, 10, 10,  2,  2,  2,  2,  2,  2,  2,  2, 21, 21, 21, 21,
+    7,  7,  7,  7, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12,
+   12, 12, 12, 12, 10, 10, 12, 12,  2,  2,  2, 21, 21, 21, 21, 21,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6, 21, 21,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,
+   21, 21, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,
+   12, 12, 12, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 10, 12, 12, 12, 12, 12, 12, 12,  7,  7,  7,  7, 12,  7,  7,
+    7,  7,  7,  7, 12,  7,  7, 10, 12, 12,  7,  2,  2,  2,  2,  2,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,
+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  6,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12,
+    9,  5,  9,  5,  9,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,  9,  9,  9,  9,
+    5,  5,  5,  5,  5,  5,  2,  2,  9,  9,  9,  9,  9,  9,  2,  2,
+    5,  5,  5,  5,  5,  5,  5,  5,  2,  9,  2,  9,  2,  9,  2,  9,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,
+    5,  5,  5,  5,  5,  5,  5,  5,  8,  8,  8,  8,  8,  8,  8,  8,
+    5,  5,  5,  5,  5,  2,  5,  5,  9,  9,  9,  9,  8, 24,  5, 24,
+   24, 24,  5,  5,  5,  2,  5,  5,  9,  9,  9,  9,  8, 24, 24, 24,
+    5,  5,  5,  5,  2,  2,  5,  5,  9,  9,  9,  9,  2, 24, 24, 24,
+    5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,  9, 24, 24, 24,
+    2,  2,  5,  5,  5,  2,  5,  5,  9,  9,  9,  9,  8, 24, 24,  2,
+   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,  1,  1,  1,  1,  1,
+   17, 17, 17, 17, 17, 17, 21, 21, 20, 19, 22, 20, 20, 19, 22, 20,
+   21, 21, 21, 21, 21, 21, 21, 21, 27, 28,  1,  1,  1,  1,  1, 29,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 21, 21, 21, 21, 16,
+   16, 21, 21, 21, 25, 22, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 25, 21, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29,
+    1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+   15,  6,  2,  2, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18,  6,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18,  2,
+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  2,  2,  2,
+   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
+   11, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26,  9, 26, 26, 26, 26,  9, 26, 26,  5,  9,  9,  9,  5,  5,
+    9,  9,  9,  5, 26,  9, 26, 26, 25,  9,  9,  9,  9,  9, 26, 26,
+   26, 26, 26, 26,  9, 26,  9, 26,  9, 26,  9,  9,  9,  9, 26,  5,
+    9,  9,  9,  9,  5,  7,  7,  7,  7,  5, 26, 26,  5,  5,  9,  9,
+   25, 25, 25, 25, 25,  9,  5,  5,  5,  5, 26, 25, 26, 26,  5, 26,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14,  9,  5, 14, 14, 14, 14, 15, 26, 26,  2,  2,  2,  2,
+   25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 25, 25, 26, 26, 26, 26,
+   25, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 25, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25,
+   26, 26, 25, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 26, 26, 26, 26,
+   25, 25, 26, 26, 26, 26, 26, 26, 26, 22, 18, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25,
+   25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15,
+   26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25,
+   26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18,
+   22, 18, 22, 18, 22, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   25, 25, 25, 25, 25, 22, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18,
+   25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
+   18, 22, 18, 22, 18, 22, 18, 22, 18, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 25, 25,
+   25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 26, 26, 26,
+   26, 26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
+    9,  5,  9,  9,  9,  5,  5,  9,  5,  9,  5,  9,  5,  9,  9,  9,
+    9,  5,  9,  5,  5,  9,  5,  5,  5,  5,  5,  5,  6,  6,  9,  9,
+    9,  5,  9,  5,  5, 26, 26, 26, 26, 26, 26,  9,  5,  9,  5, 12,
+   12, 12,  9,  5,  2,  2,  2,  2,  2, 21, 21, 21, 21, 15, 21, 21,
+    5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  2,  2,  5,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  6,
+   21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12,
+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  2,
+   21, 21, 20, 19, 20, 19, 21, 21, 21, 20, 19, 21, 20, 19, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 17, 21, 21, 17, 21, 20, 19, 21, 21,
+   20, 19, 22, 18, 22, 18, 22, 18, 22, 18, 21, 21, 21, 21, 21,  6,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 17, 17, 21, 21, 21, 21,
+   17, 21, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 26, 26, 26, 26, 26,
+   26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,
+   29, 21, 21, 21, 26,  6,  7, 14, 22, 18, 22, 18, 22, 18, 22, 18,
+   22, 18, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, 17, 22, 18, 18,
+   26, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 10, 10,
+   17,  6,  6,  6,  6,  6, 26, 26, 14, 14, 14,  6,  7, 21, 26, 26,
+    7,  7,  7,  7,  7,  7,  7,  2,  2, 12, 12, 24, 24,  6,  6,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 21,  6,  6,  6,  7,
+    2,  2,  2,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+   26, 26, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, 15, 15,
+   26, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    7,  7,  7,  7,  7,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6, 21, 21, 21,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  2,  2,  2,  2,
+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  7, 12,
+   11, 11, 11, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21,  6,
+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  6,  6, 12, 12,
+    7,  7,  7,  7,  7,  7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   12, 12, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,
+   24, 24, 24, 24, 24, 24, 24,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+   24, 24,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
+    5,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
+    6,  5,  5,  5,  5,  5,  5,  5,  5,  9,  5,  9,  5,  9,  9,  5,
+    9,  5,  9,  5,  9,  5,  9,  5,  6, 24, 24,  9,  5,  9,  5,  7,
+    9,  5,  9,  5,  5,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  9,  9,  9,  9,  5,
+    9,  9,  9,  9,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
+    2,  2,  9,  5,  9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  7,  6,  6,  5,  7,  7,  7,  7,  7,
+    7,  7, 12,  7,  7,  7, 12,  7,  7,  7,  7, 12,  7,  7,  7,  7,
+    7,  7,  7, 10, 10, 12, 12, 10, 26, 26, 26, 26,  2,  2,  2,  2,
+   15, 15, 15, 15, 15, 15, 26, 26, 23, 26,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,
+   10, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+   10, 10, 10, 10, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2, 21, 21,
+   12, 12,  7,  7,  7,  7,  7,  7, 21, 21, 21,  7, 21,  7,  7, 12,
+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 21, 21,
+    7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 10, 10,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 21,
+    7,  7,  7, 12, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 10,
+   10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  6,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 21, 21,
+    7,  7,  7,  7,  7, 12,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  7,  7,  7,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 10,
+   10, 12, 12, 10, 10, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7, 12,  7,  7,  7,  7,  7,  7,  7,  7, 12, 10,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2, 21, 21, 21, 21,
+    6,  7,  7,  7,  7,  7,  7, 26, 26, 26,  7, 10, 12, 10,  7,  7,
+   12,  7, 12, 12, 12,  7,  7, 12, 12,  7,  7,  7,  7,  7, 12, 12,
+    7, 12,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  6, 21, 21,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 12, 12, 10, 10,
+   21, 21,  7,  6,  6, 10, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,  2,
+    2,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 24,  6,  6,  6,  6,
+    5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7, 10, 10, 12, 10, 10, 12, 10, 10, 21, 10, 12,  2,  2,
+    7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  7,  7,  7,  7,  7,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  7, 12,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7, 25,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  2,  7,  2,
+    7,  7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+   24, 24,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 18, 22,
+    2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 23, 26,  2,  2,
+   21, 21, 21, 21, 21, 21, 21, 22, 18, 21,  2,  2,  2,  2,  2,  2,
+   21, 17, 17, 16, 16, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
+   18, 22, 18, 22, 18, 21, 21, 22, 18, 21, 21, 21, 21, 16, 16, 16,
+   21, 21, 21,  2, 21, 21, 21, 21, 17, 22, 18, 22, 18, 22, 18, 21,
+   21, 21, 25, 17, 25, 25, 25,  2, 21, 23, 21, 21,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  1,
+    2, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 22, 25, 18, 25, 22,
+   18, 21, 22, 18, 21, 21,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,
+    2,  2,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,
+    2,  2,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  2,  2,  2,
+   23, 23, 25, 24, 26, 23, 23,  2, 26, 25, 25, 25, 25, 26, 26,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1, 26, 26,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  7,
+   21, 21, 21,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15,  2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   14, 14, 14, 14, 14, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 26, 26, 26,  2,
+   26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12,  2,  2,
+   12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,
+   15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,
+    7, 14,  7,  7,  7,  7,  7,  7,  7,  7, 14,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2, 21,
+    7,  7,  7,  7,  2,  2,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,
+   21, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    9,  9,  9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  5,  5,  5,  5,
+    9,  9,  9,  9,  2,  2,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,
+    7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 21,
+    7,  7,  7,  7,  7,  7,  2,  2,  7,  2,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  2,  2,  7,  2,  2,  7,
+    7,  7,  7,  7,  7,  7,  2, 21, 15, 15, 15, 15, 15, 15, 15, 15,
+    7,  7,  7,  7,  7,  7,  7, 26, 26, 15, 15, 15, 15, 15, 15, 15,
+    2,  2,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    7,  7,  7,  2,  7,  7,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15,
+    7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15,  2,  2,  2, 21,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2, 21,
+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2, 15, 15,  7,  7,
+    2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    7, 12, 12, 12,  2, 12, 12,  2,  2,  2,  2,  2, 12, 12, 12, 12,
+    7,  7,  7,  7,  2,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  2,  2, 12, 12, 12,  2,  2,  2,  2, 12,
+   15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,
+   21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 15, 15, 21,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 15, 15, 15,
+    7,  7,  7,  7,  7,  7,  7,  7, 26,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7, 12, 12,  2,  2,  2,  2, 15, 15, 15, 15, 15,
+   21, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  2,  2,  2, 21, 21, 21, 21, 21, 21, 21,
+    7,  7,  7,  7,  7,  7,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15,
+    7,  7,  7,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15,
+    7,  7,  2,  2,  2,  2,  2,  2,  2, 21, 21, 21, 21,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15,
+    9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    5,  5,  5,  2,  2,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15,
+    7,  7,  7,  7, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,
+   15, 15, 15, 15, 15, 15, 15,  7,  2,  2,  2,  2,  2,  2,  2,  2,
+   12, 15, 15, 15, 15, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,
+   10, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 21, 21,  2,  2,
+   15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12,
+   10, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 21, 21,  1, 21, 21,
+   21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  2,  2,
+   12, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 10, 12, 12, 12,
+   12, 12, 12, 12, 12,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   21, 21, 21, 21,  7, 10, 10,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7, 12, 21, 21,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
+   10,  7,  7,  7,  7, 21, 21, 21, 21, 12, 12, 12, 12, 21,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7, 21,  7, 21, 21, 21,
+    2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 10, 10, 12,
+   12, 12, 10, 10, 12, 10, 12, 12, 21, 21, 21, 21, 21, 21, 12,  2,
+    7,  7,  7,  7,  7,  7,  7,  2,  7,  2,  7,  7,  7,  7,  2,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7, 21,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12,
+   10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,
+   12, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,
+    7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  2, 12, 12,  7, 10, 10,
+   12, 10, 10, 10, 10,  2,  2, 10, 10,  2,  2, 10, 10, 10,  2,  2,
+    7,  2,  2,  2,  2,  2,  2, 10,  2,  2,  2,  2,  2,  7,  7,  7,
+    7,  7, 10, 10,  2,  2, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,
+   12, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,
+   10, 10, 12, 12, 12, 10, 12,  7,  7,  7,  7, 21, 21, 21, 21, 21,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2, 21,  2, 21, 12,  7,
+   10, 10, 10, 12, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, 10, 12,
+   12, 10, 12, 12,  7,  7, 21,  7,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10,
+   10, 10, 12, 12, 12, 12,  2,  2, 10, 10, 10, 10, 12, 12, 10, 12,
+   12, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21,  7,  7,  7,  7, 12, 12,  2,  2,
+   10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 12, 10, 12,
+   12, 21, 21, 21,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 10, 12, 10, 10,
+   12, 12, 12, 12, 12, 12, 10, 12,  7,  2,  2,  2,  2,  2,  2,  2,
+   10, 10, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12,  2,  2,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 21, 21, 21, 26,
+   12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21,  2,  2,  2,  2,
+   15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,
+    7, 10, 10, 10, 12, 12, 12, 12,  2,  2, 12, 12, 10, 10, 10, 10,
+   12,  7, 21,  7, 10,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  7,  7,  7,  7,  7,
+    7,  7,  7, 12, 12, 12, 12, 12, 12, 10,  7, 12, 12, 12, 12, 21,
+   21, 21, 21, 21, 21, 21, 21, 12,  2,  2,  2,  2,  2,  2,  2,  2,
+    7, 12, 12, 12, 12, 12, 12, 10, 10, 12, 12, 12,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 21, 21,  7, 21, 21,
+   21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12, 12, 10, 12,
+    7, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   21, 21,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    2,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12,  2, 10, 12, 12, 12, 12, 12, 12,
+   12, 10, 12, 12, 10, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  7,  7,  7,  7,  7,
+    7, 12, 12, 12, 12, 12, 12,  2,  2,  2, 12,  2, 12, 12,  2, 12,
+   12, 12, 12, 12, 12, 12,  7, 12,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 10, 10, 10, 10,  2,
+   12, 12,  2, 10, 10, 12, 10, 12,  7,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7, 12, 12, 10, 10, 21, 21,  2,  2,  2,  2,  2,  2,  2,
+   15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 23, 23, 23,
+   23, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 21,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2,
+   21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
+   12, 12, 12, 12, 12, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 26, 26, 26, 26,
+    6,  6,  6,  6, 21, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2, 15, 15, 15, 15, 15,
+   15, 15,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  7,  7,  7,
+   15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2, 12,
+    7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+   10, 10, 10, 10, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 12,
+   12, 12, 12,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+    6,  6, 21,  6,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2, 26, 12, 12, 21,
+    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 26, 26, 26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 10, 10, 12, 12, 12, 26, 26, 26, 10, 10, 10,
+   10, 10, 10,  1,  1,  1,  1,  1,  1,  1,  1, 12, 12, 12, 12, 12,
+   12, 12, 12, 26, 26, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 12, 12, 12, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  5,  5,
+    5,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    9,  9,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,  2,  9,  9,
+    2,  2,  9,  2,  2,  9,  9,  2,  2,  9,  9,  9,  9,  2,  9,  9,
+    9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  2,  5,  2,  5,  5,  5,
+    5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  9,  9,  2,  9,  9,  9,  9,  2,  2,  9,  9,  9,
+    9,  9,  9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  2,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  2,  9,  9,  9,  9,  2,
+    9,  9,  9,  9,  9,  2,  9,  2,  2,  2,  9,  9,  9,  9,  9,  9,
+    9,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  2,  2,  9,  9,  9,  9,  9,  9,  9,  9,
+    9, 25,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 25,  5,  5,  5,  5,
+    5,  5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  5,  5,  5,  5,
+    5,  5,  5,  5,  5, 25,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,
+    9,  9,  9,  9,  9, 25,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 25,
+    5,  5,  5,  5,  5,  5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,
+    5,  5,  5,  5,  5,  5,  5,  5,  5, 25,  5,  5,  5,  5,  5,  5,
+    9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  5,  5,  5,  5,  5,  5,
+    5,  5,  5, 25,  5,  5,  5,  5,  5,  5,  9,  5,  2,  2, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26,
+   26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 12, 26, 26, 21, 21, 21, 21, 21,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2, 12, 12, 12, 12, 12,
+   12, 12,  2, 12, 12,  2, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,
+   12, 12, 12, 12, 12, 12, 12,  6,  6,  6,  6,  6,  6,  6,  2,  2,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  7, 26,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  2, 23,
+    7,  7,  7,  7,  7,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    5,  5,  5,  5, 12, 12, 12, 12, 12, 12, 12,  6,  2,  2,  2,  2,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, 15, 15,
+   23, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,
+    7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    2,  7,  7,  2,  7,  2,  2,  7,  2,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  2,  7,  7,  7,  7,  2,  7,  2,  7,  2,  2,  2,  2,
+    2,  2,  7,  2,  2,  2,  2,  7,  2,  7,  2,  7,  2,  7,  7,  7,
+    2,  7,  7,  2,  7,  2,  2,  7,  2,  7,  2,  7,  2,  7,  2,  7,
+    2,  7,  7,  2,  7,  2,  2,  7,  7,  7,  7,  2,  7,  7,  7,  7,
+    7,  7,  7,  2,  7,  7,  7,  7,  2,  7,  7,  7,  7,  2,  7,  2,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,
+    2,  7,  7,  7,  2,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,
+   25, 25,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,
+    2,  2,  2,  2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24,
+   26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 26, 26, 26,
+   26, 26,  2, 26, 26, 26, 26,  2,  2,  2, 26, 26, 26, 26, 26, 26,
+   26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26,  2,  2,  2, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2, 26, 26, 26,
+   26, 26, 26, 26,  2,  2,  2,  2, 26, 26, 26,  2,  2,  2,  2,  2,
+    7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,
+    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+   14,  0,  0, 15,  0,  0,  0, 16, 17, 18, 19, 20, 21, 22,  0,  0,
+   23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 24, 25,  0,  0,
+   26,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 27,  0, 28, 29, 30, 31,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  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,  0,  0, 33,  0,
+    0, 34, 35, 36,  0,  0,  0,  0,  0,  0, 37,  0,  0, 38,  0, 39,
+   40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,  0, 51, 52,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 53, 54,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 55,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0, 56, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   58, 54, 59,  0,  0,  0,  0,  0, 60, 61,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,
+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0, 14, 15,
+    0, 16,  0,  0,  0,  0,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,
+    0,  0,  0,  0,  0,  0,  0, 27, 28, 29,  0,  0,  0, 30, 31, 32,
+    0,  0,  0,  0,  0, 30, 31,  0,  0, 33,  0,  0,  0, 30, 31,  0,
+    0,  0,  0,  0,  0, 30, 31,  0,  0,  0,  0,  0,  0, 30, 31,  0,
+    0,  0,  0,  0,  0,  0, 31,  0,  0,  0,  0,  0,  0,  0, 31, 34,
+    0,  0,  0,  0,  0, 30, 31,  0,  0,  0,  0,  0,  0, 35, 31,  0,
+    0,  0,  0,  0,  0,  0, 36,  0,  0,  0,  0,  0,  0, 37, 38,  0,
+    0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0, 41,  0, 42,  0,  0,
+    0, 43, 44,  0,  0,  0, 45,  0,  0,  0,  0,  0,  0, 46,  0,  0,
+    0,  0, 47,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 48,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 49,  0, 49,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 50,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 51,  0,  0,  0,  0,  0,  0,  0,  0, 52,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 53,  0,  0,  0,  0,
+   54, 55,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0, 57, 49,  0,
+   58, 59,  0,  0, 60,  0,  0,  0, 61, 62,  0,  0,  0, 63,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 64, 65, 66,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 67, 68,  1, 69,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 70, 71, 72,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 73, 74,  0,  0,  0,  0,  0,  0,
+    0, 75,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0, 76,  0,  0,  0,
+    0,  0,  0, 77,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   73, 78,  0, 79,  0,  0,  0,  0,  0, 74, 80,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 49,  0,  1, 74,  0,  0, 81,  0,  0, 82,
+    0,  0,  0,  0,  0, 83, 54,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 84, 85,  0,  0, 80,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 31,  0,  0, 86,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 87,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 47,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 88,  0,  0,  0,  0,  0,  0,  0,
+    0, 89,  0,  0,  0,  0,  0,  0,  0,  0, 90,  0,  0, 91,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 92,  0,  0,  0, 93,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 94, 88,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 80,  0,
+    0, 75,  0,  0,  0, 95,  0,  0,  0,  0, 96,  0,  0, 97,  0,  0,
+    0, 83,  0,  0,  0,  0, 98,  0,  0,  0,  0,  0,  0, 99,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,100,  0,  0,  0,  0,101, 31,  0,
+  102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,104, 33,
+    0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 75,106,  0,  0,  0,  0,  0,  0, 75,  0,  0,
+    0,  0,  0,  0,  0,107,  0,  0,  0,  0,  0,  0,108,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 95,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0, 49,109,  0,
+    0,  0,  0,110,  0,  0,  0,  0,  0,  0,  0,  0,  0, 75,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,111,  0,
+    0,  0,  0,109,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,113,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,114,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  115,116,117,  0,118,  0,  0,  0,  0,  0,  0,  0,  0,  0,119,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,120,121,122,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,123,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,124,  0,  0,  0,  0,  0,  0,125,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
+  230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,232,
+  220,220,220,220,232,216,220,220,220,220,220,202,202,220,220,220,
+  220,202,202,220,220,220,220,220,220,220,220,220,220,220,  1,  1,
+    1,  1,  1,220,220,220,220,230,230,230,230,230,230,230,230,240,
+  230,220,220,220,230,230,230,220,220,  0,230,230,230,220,220,220,
+  220,230,232,220,220,230,233,234,234,233,234,234,233,230,230,230,
+  230,230,230,230,230,230,230,230,230,230,  0,  0,  0,230,230,230,
+  230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,220,230,230,230,230,
+  220,230,230,230,222,220,230,230,230,230,230,230,220,220,220,220,
+  220,220,230,230,220,230,230,222,228,230, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,230,220,
+    0, 18,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
+  230,230, 30, 31, 32,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,
+  220,230,230,230,230,230,220,230,230,220, 35,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  230,230,230,230,230,230,230,  0,  0,230,230,230,230,220,230,  0,
+    0,230,230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,220,230,230,220,230,
+  230,220,220,220,230,220,220,230,220,230,230,230,220,230,220,230,
+  220,230,220,230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,230,230,230,230,230,230,230,220,230,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,220,  0,  0,  0,  0,  0,  0,  0,  0,
+  230,230,230,230,  0,230,230,230,230,230,230,230,230,230,  0,230,
+  230,230,  0,230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,220,220,220,  0,  0,  0,  0,  0,  0,  0,220,230,230,
+  230,230,230,230,230,230,230,230,230,230,230,230,  0,220,230,230,
+  220,230,230,220,230,230,230,220,220,220, 27, 28, 29,230,230,230,
+  220,230,230,220,220,230,230,230,230,230,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,230,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,230,  0,  0,  0,  0,  0,  0, 84,
+   91,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,103,103,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,107,107,107,107,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,118,118,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,122,122,122,122,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,220,220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,220,
+    0,220,  0,216,  0,  0,  0,  0,  0,  0,  0,129,130,  0,132,  0,
+    0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,  9,  0,
+  230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  7,  0,  9,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,220,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,230,230,230,  0,  0,  0,  0,  9,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,230,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,228,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,222,230,220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,230,220,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,
+  230,230,230,230,230,230,230,  0,  0,220,230,230,230,230,230,220,
+  220,220,220,220,220,230,230,220,  0,  0,  0,  0,  0,  0,  7,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,230,220,230,230,230,230,230,230,230,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  9,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  7,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,  0,  1,220,
+  220,220,220,220,230,230,220,220,220,220,230,  0,  1,  1,  1,  1,
+    1,  1,  1,  0,  0,  0,  0,220,  0,  0,  0,  0,  0,  0,230,  0,
+    0,  0,230,230,  0,  0,  0,  0,  0,  0,230,230,220,230,230,230,
+  230,230,230,230,220,230,230,234,214,220,202,230,230,230,230,230,
+  230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,
+  232,228,228,220,  0,230,233,220,230,220,230,230,  1,  1,230,230,
+  230,230,  1,  1,  1,230,230,  0,  0,  0,  0,230,  0,  0,  0,  1,
+    1,230,220,230,  1,  1,220,220,220,220,230,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,218,228,232,222,224,224,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  8,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,
+  230,230,230,230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,230,230,  0,  0,  0,  0,  0,  0,
+    9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,220,220,220,  0,  0,  0,  0,  0,  9,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,  0,230,230,220,  0,
+    0,230,230,  0,  0,  0,  0,  0,230,230,  0,230,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 26,  0,230,230,230,230,230,230,
+  230,220,220,220,220,220,220,220,230,230,220,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,220,  0,230,  0,  0,  0,  0,  0,  0,
+    0,  0,230,  1,220,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,230,
+  220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,
+  230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  220,220,230,230,230,220,230,220,220,220,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  9,  7,  0,  0,  0,  0,  0,230,230,230,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  9,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,
+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  7,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  7,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+  230,230,230,230,230,230,230,  0,  0,  0,230,230,230,230,230,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,
+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  7,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    9,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  9,  9,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
+  230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,216,
+  216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,  0,  0,
+    0,  0,  0,  0,  0,220,220,220,220,220,220,220,220,  0,  0,230,
+  230,230,230,230,220,220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,230,230,230,230,  0,  0,  0,  0,230,230,230,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
+  230,  0,230,230,230,230,230,230,230,230,230,230,230,230,230,230,
+  230,230,230,  0,  0,230,230,230,230,230,230,230,  0,230,230,  0,
+  230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,230,230,230,230,220,220,220,220,220,220,
+  220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,
+  230,230,230,230,  7,  0,  0,  0,  0,  0, 16, 17, 17, 17, 17, 17,
+   17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169,
+   17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17,237,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
+    3,  4,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  5,  0,  0,  0,  6,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  7,  1,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    8,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0, 10,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0,  0, 10,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 11, 12,  0, 13,
+    0, 14, 15, 16,  0,  0,  0,  0,  0,  1, 17, 18,  0, 19,  7,  1,
+    0,  0,  0, 20, 20,  7, 20, 20, 20, 20, 20, 20, 20,  8, 21,  0,
+   22,  0,  7, 23, 24,  0, 20, 20, 25,  0,  0,  0, 26, 27,  1,  7,
+   20, 20, 20, 20, 20,  1, 28, 29, 30, 31,  0,  0, 20,  0,  0,  0,
+    0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 20, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  8, 21, 32,  4,  0, 10,
+    0, 33,  7, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  8, 34, 34, 35, 36, 34,
+   37,  0, 38,  1, 20, 20,  0,  0, 39,  0,  1,  1,  0,  8, 21,  1,
+   20,  0,  0,  0,  1,  0,  0, 40,  1,  1,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  8, 21,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  1,  0,  0,  0,  0, 26, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 21,  7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,
+    0, 42, 43, 44,  0, 45,  0,  8, 21,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 46,  7,  1, 10,  1,  0,  0,
+    0,  1, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20,  1, 20,
+   20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   26, 21,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,
+    0,  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  0,  0,
+    3, 47, 48,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
+    3,  4,  0,  0,  0,  0,  0,  0,  3,  4,  0,  1,  2,  3,  4,  5,
+    6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 17, 19, 20,
+   21, 22, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 27, 28, 28, 29, 30, 31, 32,
+   33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+   33, 33, 33, 33, 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+   46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 35, 35, 35,
+   35, 35, 59, 59, 60, 35, 35, 35, 35, 35, 35, 35, 61, 62, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 63, 64,
+   35, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 66, 68,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 69, 70, 35, 35, 35, 35, 71, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 72, 73, 74, 75, 76, 77, 35, 35, 78, 79, 35, 35, 80, 35,
+   81, 82, 83, 84, 17, 85, 86, 87, 35, 35, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 88, 25, 25,
+   25, 25, 25, 25, 25, 89, 90, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 91, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 92,
+   35, 35, 35, 35, 35, 35, 25, 93, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 94,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0, 19, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0, 19, 19, 19, 19,
+   19,  0,  0,  0,  0,  0, 26, 26,  0,  0,  0,  0,  1,  1,  1,  1,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  9,  9,  9,  9,
+    0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,  2,  2,
+    9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 55, 55,
+   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,  6,  6,  6,  6,
+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+    6,  1,  1,  6,  6,  6,  6,  6,  6,  6,  6,  6,  2,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  2,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  0,  4,  2,  2,  4,  4,  4,  2, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14,  2,  2,  2,  2, 14, 14, 14, 14, 14,
+   14,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  0,  3,  2,  3,  0,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+    1,  1,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  1,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  3, 37, 37, 37, 37,
+   37, 37, 37, 37, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37, 37, 37,
+   37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+   37, 37, 37, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38, 38, 38,
+   38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 64, 64, 64, 64,
+   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+   64, 64, 64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90, 90, 90,
+   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+   90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90, 90, 90,
+   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2, 95, 95, 95, 95,
+   95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+   95, 95, 95, 95, 95, 95, 95, 95,  2,  2, 95,  2, 37, 37, 37, 37,
+   37, 37, 37, 37, 37, 37, 37,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,  1,  1,
+    1,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    0,  0,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  5,  5,  5,  5,
+    2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,  2,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  2,  5,  2,
+    2,  2,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  2,  2,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,  2,  2,
+    2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,  5,  5,
+    2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11, 11, 11,
+    2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,  2, 11,
+   11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11,  2, 11, 11, 11, 11, 11, 11, 11,  2, 11, 11,
+    2, 11, 11,  2, 11, 11,  2,  2, 11,  2, 11, 11, 11, 11, 11,  2,
+    2,  2,  2, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,  2,  2,
+    2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,  2,  2,
+    2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 10, 10, 10,
+    2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2, 10,
+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+   10, 10, 10, 10, 10,  2, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10,
+    2, 10, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10, 10, 10, 10, 10,
+   10, 10,  2, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10,
+    2,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,  2,
+    2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21, 21, 21,
+    2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,  2, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21,  2, 21, 21, 21, 21, 21, 21, 21,  2, 21, 21,
+    2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21, 21, 21, 21, 21, 21,
+   21,  2,  2, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,  2,  2,
+    2,  2, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21, 21, 21,
+    2,  2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 22,
+    2, 22, 22, 22, 22, 22, 22,  2,  2,  2, 22, 22, 22,  2, 22, 22,
+   22, 22,  2,  2,  2, 22, 22,  2, 22,  2, 22, 22,  2,  2,  2, 22,
+   22,  2,  2,  2, 22, 22, 22,  2,  2,  2, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22, 22, 22,  2,
+    2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2, 22,  2,  2,  2,
+    2,  2,  2, 22,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2,  2, 23, 23, 23, 23,
+   23, 23, 23, 23, 23, 23, 23, 23, 23,  2, 23, 23, 23,  2, 23, 23,
+   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+   23, 23, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+   23, 23, 23, 23, 23, 23,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23,
+   23,  2, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,  2,  2,
+    2, 23, 23,  2, 23, 23, 23,  2,  2,  2,  2,  2, 23, 23, 23, 23,
+    2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  2,  2,  2,  2,
+    2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2, 16, 16,
+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    2, 16, 16, 16, 16, 16,  2,  2, 16, 16, 16, 16, 16, 16, 16, 16,
+   16,  2, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,  2,  2,
+    2, 16, 16,  2,  2,  2,  2,  2,  2,  2, 16,  2, 16, 16, 16, 16,
+    2,  2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 20, 20, 20, 20,
+    2, 20, 20, 20, 20, 20, 20, 20, 20,  2, 20, 20, 20,  2, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20,  2, 20, 20, 20,  2, 20, 20, 20, 20, 20, 20,  2,  2,  2,  2,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+    2,  2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 36, 36,
+    2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,
+   36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2, 36, 36, 36, 36,
+   36, 36, 36,  2,  2,  2, 36,  2,  2,  2,  2, 36, 36, 36, 36, 36,
+   36,  2, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,  2,
+    2,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2, 36, 36,
+   36,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 24, 24, 24,
+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+   24, 24, 24, 24, 24, 24, 24,  2,  2,  2,  2,  0, 24, 24, 24, 24,
+   24, 24, 24, 24, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18, 18,  2,
+   18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18, 18, 18,
+   18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+    2, 18,  2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2,  2, 18, 18, 18, 18,
+   18,  2, 18,  2, 18, 18, 18, 18, 18, 18,  2,  2, 18, 18, 18, 18,
+   18, 18, 18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25,  2,  2,  2,  2, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25,
+   25,  0,  0,  0,  0, 25, 25,  2,  2,  2,  2,  2, 33, 33, 33, 33,
+   33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,  8,  8,  8,  8,
+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+    8,  8,  2,  8,  2,  2,  2,  2,  2,  8,  2,  2,  8,  8,  8,  8,
+    8,  8,  8,  8,  8,  8,  8,  0,  8,  8,  8,  8, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30, 30, 30,
+   30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+   30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30, 30, 30,
+   30, 30, 30,  2, 30,  2, 30, 30, 30, 30,  2,  2, 30,  2, 30, 30,
+   30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,  2, 30,  2, 30, 30,
+   30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+   30, 30, 30,  2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+   30, 30, 30, 30, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,
+   30, 30, 30, 30, 30, 30, 30, 30, 30,  2,  2,  2, 30, 30, 30, 30,
+   30, 30, 30, 30, 30, 30,  2,  2,  2,  2,  2,  2, 29, 29, 29, 29,
+   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+   29, 29,  2,  2, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28, 28, 28,
+   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35, 35, 35, 35,
+   35, 35, 35, 35, 35,  2,  2,  2,  2,  2,  2,  2, 45, 45, 45, 45,
+   45, 45, 45, 45, 45, 45, 45, 45, 45,  2, 45, 45, 45, 45, 45, 45,
+   45,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 44, 44, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+   44,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2, 43, 43, 43, 43,
+   43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 46, 46, 46, 46,
+   46, 46, 46, 46, 46, 46, 46, 46, 46,  2, 46, 46, 46,  2, 46, 46,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 31, 31, 31, 31,
+   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+   31, 31, 31, 31, 31, 31, 31, 31, 31, 31,  2,  2, 31, 31, 31, 31,
+   31, 31, 31, 31, 31, 31,  2,  2,  2,  2,  2,  2, 32, 32,  0,  0,
+   32,  0, 32, 32, 32, 32, 32, 32, 32, 32, 32,  2, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28, 28, 28,
+   28, 28,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 48, 48, 48, 48,
+   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,  2, 48, 48, 48, 48,
+   48, 48, 48, 48, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,  2,  2,
+   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 52, 52, 52, 52,
+   52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+   52, 52, 52, 52, 52, 52, 52, 52, 52, 52,  2,  2, 52, 52, 52, 52,
+   52,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 58, 58, 58, 58,
+   58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+   58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58, 58, 58,
+   58, 58, 58, 58, 58, 58,  2,  2,  2,  2,  2,  2, 58, 58, 58, 58,
+   58, 58, 58, 58, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54, 54, 54,
+   54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+   54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91, 91, 91,
+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91, 91, 91,
+   91, 91, 91, 91, 91, 91, 91, 91, 91,  2,  2, 91, 91, 91, 91, 91,
+   91, 91, 91, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91, 91, 91,
+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2,  2,  1,  1,  1,  1,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62, 62, 62,
+   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+   62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2,  2, 62, 62, 62, 62,
+   62, 62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2, 76, 76, 76, 76,
+   76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, 93, 93,
+   93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+    2,  2,  2,  2,  2,  2,  2,  2, 93, 93, 93, 93, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73, 73, 73,
+   73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,  6,  6,  6,  6,
+    6,  6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
+    8,  8,  8,  8,  8,  8,  8,  2,  2,  8,  8,  8, 76, 76, 76, 76,
+   76, 76, 76, 76,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  0,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,
+    1,  1,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
+    1,  0,  0,  0,  1,  1,  0,  2,  2,  2,  2,  2, 19, 19, 19, 19,
+   19, 19,  9,  9,  9,  9,  9,  6, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  9,  9,  9,  9, 19, 19,
+   19, 19,  9,  9,  9,  9,  9, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19,  6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  1,  1,  1,  1,
+    1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  9,  9,  9,  9,
+    9,  9,  2,  2,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
+    9,  9,  9,  9,  2,  9,  2,  9,  2,  9,  2,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
+    9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    2,  2,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  2,  2,  9,  9,
+    9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  0,  0,
+    0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  2,  2,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, 19, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2,  2,  1,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  9,  0,  0,  0, 19, 19,  0,  0,  0,  0,  0,  0, 19,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  0, 19, 19, 19, 19,
+   19, 19, 19, 19, 19,  0,  0,  0,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2, 27, 27, 27, 27,
+   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,
+    2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0, 56, 56, 56, 56,
+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,  2, 55, 55, 55, 55,
+   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+    2,  2,  2,  2,  2, 55, 55, 55, 55, 55, 55, 55, 61, 61, 61, 61,
+   61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+   61, 61, 61, 61,  2,  2,  2,  2,  2,  2,  2, 61, 61,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 61, 30, 30, 30, 30,
+   30, 30, 30,  2,  2,  2,  2,  2,  2,  2,  2,  2, 30, 30, 30, 30,
+   30, 30, 30,  2, 30, 30, 30, 30, 30, 30, 30,  2, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
+   13, 13,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  0,  0,  0,  0,
+    0, 13,  0, 13,  0,  0,  0,  0,  0,  0,  0,  0,  0, 13, 13, 13,
+   13, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,  0,  0,  0,  0,
+    0,  0,  0,  0, 13, 13, 13, 13,  0,  0,  0,  0,  2, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17,  0,  0, 17, 17, 17,  2,  2,  2,  2,
+    2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  0, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  0, 17, 17, 17, 17,
+   17, 17, 17, 17,  0,  0,  0,  0,  0,  0,  0,  0, 39, 39, 39, 39,
+   39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+   39, 39, 39, 39, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39, 39, 39,
+   39, 39, 39,  2,  2,  2,  2,  2,  2,  2,  2,  2, 86, 86, 86, 86,
+   86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, 77, 77,
+   77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+   77, 77, 77, 77, 77, 77, 77, 77,  2,  2,  2,  2, 79, 79, 79, 79,
+   79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
+   79, 79, 79, 79,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0, 19, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19,  0,  0,  0, 19, 19, 19, 19, 19,  2,  2, 19, 19,
+   19, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 60, 60, 60, 60,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+   60, 60, 60, 60, 60, 60, 60, 60,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  2, 65, 65, 65, 65,
+   65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+   65, 65, 65, 65,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75,
+   75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+   75, 75,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75, 75, 75,
+   75, 75, 75, 75, 75, 75,  2,  2,  2,  2,  2,  2, 69, 69, 69, 69,
+   69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+   69, 69, 69, 69, 69, 69, 69, 69, 69, 69,  0, 69, 74, 74, 74, 74,
+   74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 74, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2, 84, 84, 84, 84,
+   84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+   84, 84, 84, 84, 84, 84, 84, 84, 84, 84,  2,  0, 84, 84, 84, 84,
+   84, 84, 84, 84, 84, 84,  2,  2,  2,  2, 84, 84, 33, 33, 33, 33,
+   33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,  2, 68, 68, 68, 68,
+   68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+   68, 68, 68,  2,  2,  2,  2,  2,  2,  2,  2,  2, 68, 68, 68, 68,
+   68, 68, 68, 68, 68, 68, 68, 68, 68, 68,  2,  2, 68, 68, 68, 68,
+   68, 68, 68, 68, 68, 68,  2,  2, 68, 68, 68, 68, 92, 92, 92, 92,
+   92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2, 92, 92, 92, 92, 92, 87, 87, 87, 87,
+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+   87, 87, 87,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 30, 30, 30,
+   30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30,  2,  2, 30, 30, 30,
+   30, 30, 30,  2,  2,  2,  2,  2,  2,  2,  2,  2, 19, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19,  0, 19, 19, 19, 19, 19, 19, 19, 19,
+   19,  9, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2, 87, 87, 87, 87,
+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87,  2,  2, 87, 87, 87, 87,
+   87, 87, 87, 87, 87, 87,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12,
+   12, 12, 12,  2,  2,  2,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  2,  2, 19, 19, 19, 19,
+   19, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  4,
+    4,  4,  4,  4,  2,  2,  2,  2,  2, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14,  2, 14, 14, 14, 14, 14,  2, 14,  2, 14, 14,  2, 14,
+   14,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  3,  3,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  2,  2,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  1,  1,  1,  1,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  6,  6,  0,  0,  0,  2,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  2,  0,  0,  0,  0,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0,  2,  2, 12, 12,
+   12, 12, 12, 12,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2, 12, 12,
+   12, 12, 12, 12,  2,  2, 12, 12, 12,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49, 49, 49,
+   49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49, 49, 49,
+   49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+   49, 49, 49,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+   49, 49, 49, 49, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49, 49, 49,
+   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2,  2, 49, 49, 49, 49,
+   49, 49, 49, 49, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,  0,  2,
+    2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  2, 71, 71, 71, 71,
+   71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+   71, 71, 71, 71, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67, 67, 67,
+   67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 42, 42, 42, 42,
+   42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+    2,  2,  2,  2,  2,  2,  2,  2,  2, 42, 42, 42, 41, 41, 41, 41,
+   41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+   41, 41, 41, 41, 41, 41, 41,  2,  2,  2,  2,  2,118,118,118,118,
+  118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,
+  118,118,118,118,118,118,118,  2,  2,  2,  2,  2, 53, 53, 53, 53,
+   53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+   53, 53, 53, 53, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+    2,  2,  2,  2, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 40, 40, 40, 40,
+   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51, 51, 51,
+   51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50,
+   50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+   50, 50, 50, 50, 50, 50, 50, 50, 50, 50,  2,  2, 50, 50, 50, 50,
+   50, 50, 50, 50, 50, 50,  2,  2,  2,  2,  2,  2,135,135,135,135,
+  135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
+    2,  2,  2,  2,135,135,135,135,135,135,135,135,135,135,135,135,
+  135,135,135,135,135,135,135,135,  2,  2,  2,  2,106,106,106,106,
+  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+  106,106,106,106,  2,  2,  2,  2,  2,  2,  2,  2,104,104,104,104,
+  104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,104,110,110,110,110,
+  110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+  110,110,110,  2,  2,  2,  2,  2,  2,  2,  2,  2,110,110,110,110,
+  110,110,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,110,110,110,110,
+  110,110,110,110,  2,  2,  2,  2,  2,  2,  2,  2, 47, 47, 47, 47,
+   47, 47,  2,  2, 47,  2, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+   47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+   47, 47,  2, 47, 47,  2,  2,  2, 47,  2,  2, 47, 81, 81, 81, 81,
+   81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+   81, 81,  2, 81, 81, 81, 81, 81, 81, 81, 81, 81,120,120,120,120,
+  120,120,120,120,120,120,120,120,120,120,120,120,116,116,116,116,
+  116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+  116,116,116,116,116,116,116,116,116,116,116,  2,  2,  2,  2,  2,
+    2,  2,  2,116,116,116,116,116,116,116,116,116,128,128,128,128,
+  128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,  2,
+  128,128,  2,  2,  2,  2,  2,128,128,128,128,128, 66, 66, 66, 66,
+   66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+   66, 66, 66, 66, 66, 66, 66, 66,  2,  2,  2, 66, 72, 72, 72, 72,
+   72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+   72, 72, 72, 72, 72, 72,  2,  2,  2,  2,  2, 72, 98, 98, 98, 98,
+   98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+   97, 97, 97, 97,  2,  2,  2,  2, 97, 97, 97, 97,  2,  2, 97, 97,
+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 57, 57, 57, 57,
+    2, 57, 57,  2,  2,  2,  2,  2, 57, 57, 57, 57, 57, 57, 57, 57,
+    2, 57, 57, 57,  2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+   57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+   57, 57,  2,  2, 57, 57, 57,  2,  2,  2,  2, 57, 57, 57, 57, 57,
+   57, 57, 57, 57, 57,  2,  2,  2,  2,  2,  2,  2, 88, 88, 88, 88,
+   88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,117,117,117,117,
+  117,117,117,117,117,117,117,117,117,117,117,117,112,112,112,112,
+  112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
+  112,112,112,  2,  2,  2,  2,112,112,112,112,112,112,112,112,112,
+  112,112,112,  2,  2,  2,  2,  2,  2,  2,  2,  2, 78, 78, 78, 78,
+   78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+   78, 78,  2,  2,  2, 78, 78, 78, 78, 78, 78, 78, 83, 83, 83, 83,
+   83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+   83, 83,  2,  2, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 82, 82,
+   82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,  2,
+    2,  2,  2,  2, 82, 82, 82, 82, 82, 82, 82, 82,122,122,122,122,
+  122,122,122,122,122,122,122,122,122,122,122,122,122,122,  2,  2,
+    2,  2,  2,  2,  2,122,122,122,122,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,122,122,122,122,122,122,122, 89, 89, 89, 89,
+   89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+   89, 89, 89, 89, 89,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,
+  130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,130,130,130,  2,
+    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,  0,  0,  0,  0,
+    0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  1,  1,  1,  1,
+    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 94, 94, 94,
+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2, 94, 94,
+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85, 85, 85,
+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,101,101,
+  101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
+  101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,101,101,
+  101,101,101,101,101,101,  2,  2,  2,  2,  2,  2, 96, 96, 96, 96,
+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+   96,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96,  2,  2,  2,  2,  2,  2,  2,  2,  2,111,111,111,111,
+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+  111,111,111,  2,  2,  2,  2,  2,  2,  2,  2,  2,100,100,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
+  100,100,100,100,100,100,100,100,100,100,  2,  2,  2, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,108,108,108,108,
+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,  2,108,
+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
+  108,108,108,108,108,108,108,108,108,108,108,  2,129,129,129,129,
+  129,129,129,  2,129,  2,129,129,129,129,  2,129,129,129,129,129,
+  129,129,129,129,129,129,129,129,129,129,  2,129,129,129,129,129,
+  129,129,129,129,129,129,  2,  2,  2,  2,  2,  2,109,109,109,109,
+  109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+  109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,109,109,
+  109,109,109,109,109,109,  2,  2,  2,  2,  2,  2,107,107,107,107,
+    2,107,107,107,107,107,107,107,107,  2,  2,107,107,  2,  2,107,
+  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+  107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,107,107,
+    2,107,107,107,107,107,  2,  1,107,107,107,107,107,107,107,107,
+  107,  2,  2,107,107,  2,  2,107,107,107,  2,  2,107,  2,  2,  2,
+    2,  2,  2,107,  2,  2,  2,  2,  2,107,107,107,107,107,107,107,
+    2,  2,107,107,107,107,107,107,107,  2,  2,  2,107,107,107,107,
+  107,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,137,137,137,137,
+  137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
+  137,137,137,137,137,137,  2,137,  2,137,137,137,124,124,124,124,
+  124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
+  124,124,124,124,  2,  2,  2,  2,  2,  2,  2,  2,124,124,124,124,
+  124,124,124,124,124,124,  2,  2,  2,  2,  2,  2,123,123,123,123,
+  123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
+  123,123,  2,  2,123,123,123,123,123,123,123,123,123,123,123,123,
+  123,123,123,123,123,123,123,123,123,123,  2,  2,114,114,114,114,
+  114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+  114,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,114,114,114,114,
+  114,114,114,114,114,114,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,102,102,102,102,
+  102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
+  102,102,102,102,102,  2,  2,  2,  2,  2,  2,  2,102,102,102,102,
+  102,102,102,102,102,102,  2,  2,  2,  2,  2,  2,126,126,126,126,
+  126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
+  126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,126,126,
+  126,126,126,126,126,126,126,126,  2,  2,  2,  2,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,125,125,125,125,
+  125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,  5,  5,  5,  5,
+    5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,  6,  6,  6,
+    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,121,121,121,121,
+  121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
+  121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
+  133,133,133,133,133,  2,133,133,133,133,133,133,133,133,133,133,
+  133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
+  133,133,133,  2,133,133,133,133,133,133,133,133,133,133,133,133,
+  133,133,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
+  133,133,133,133,133,133,133,133,133,  2,  2,  2,134,134,134,134,
+  134,134,134,134,134,134,134,134,134,134,134,134,  2,  2,134,134,
+  134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
+  134,134,134,134,  2,134,134,134,134,134,134,134,134,134,134,134,
+  134,134,134,  2,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
+    8,  8,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+    8,  8,  8,  2,  2,  2,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,
+    8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
+    8,  8,  8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
+    9,  9,  2,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,
+    9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10,
+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+   10, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63, 63, 63,
+   63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+   63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63, 63, 63,
+   63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,  2, 63, 63, 63, 63,
+   63,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 63, 63, 63, 63,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 80, 80, 80, 80,
+   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,  2, 80, 80, 80, 80,
+   80, 80, 80, 80, 80,  2,  2,  2,  2,  2,  2,  2,127,127,127,127,
+  127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
+  127,127,127,  2,  2,  2,  2,  2,  2,  2,  2,  2, 79, 79, 79, 79,
+   79, 79, 79, 79, 79,  2,  2,  2,  2,  2,  2,  2,115,115,115,115,
+  115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+  115,115,115,115,115,115,115,115,115,115,115,  2,115,115,115,115,
+  115,115,115,115,115,115,  2,  2,  2,  2,115,115,103,103,103,103,
+  103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
+  103,103,103,103,103,103,103,103,103,103,  2,  2,103,103,103,103,
+  103,103,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,119,119,119,119,
+  119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+  119,119,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,119,119,119,119,
+  119,119,119,119,119,119,  2,119,119,119,119,119,119,119,  2,119,
+  119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
+  119,119,119,119,  2,  2,  2,  2,  2,119,119,119, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2,  2, 99, 99, 99, 99,
+   99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+   99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99, 99, 99, 99, 99,
+   99, 99, 99, 99,  2,  2,  2,  2,  2,  2,  2, 99,136, 12,  0,  0,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,136,136,136,136,
+  136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
+  136,136,136,136,  2,  2,  2,  2,  2,  2,  2,  2,136,136,136,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 17, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2, 15, 15, 15,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+   17, 17, 17, 17,  2,  2,  2,  2,  2,  2,  2,  2,105,105,105,105,
+  105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
+  105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,105,105,
+  105,105,105,105,105,105,105,105,105,  2,  2,  2,105,105,105,105,
+  105,105,105,105,105,  2,  2,  2,  2,  2,  2,  2,105,105,105,105,
+  105,105,105,105,105,105,  2,  2,105,105,105,105,  0,  0,  0,  0,
+    0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  0,
+    0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
+    9,  9,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  2,  2,  0,  2,
+    2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  2,  0,  2,  0,  0,  0,  0,  0,  0,  0,
+    2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  2,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,
+    0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
+    0,  2,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,131,131,131,131,
+  131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
+  131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,131,131,
+  131,131,131,131,131,131,131,131,131,131,131,131, 56, 56, 56, 56,
+   56, 56, 56,  2, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+   56, 56, 56, 56, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,  2, 56,
+   56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2, 14,113,113,113,113,
+  113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+  113,  2,  2,113,113,113,113,113,113,113,113,113,113,113,113,113,
+  113,113,113,  2,  2,  2,  2,  2,  2,  2,  2,  2,132,132,132,132,
+  132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
+  132,132,132,132,132,132,132,132,  2,  2,  2,  2,132,132,132,132,
+  132,132,132,132,132,132,  2,  2,  2,  2,132,132,  0,  0,  0,  0,
+    0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  3,  3,  3,  3,
+    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,  2,
+    3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,
+    3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,  3,  2,
+    2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,  3,  2,
+    3,  2,  2,  3,  2,  3,  2,  3,  2,  3,  2,  3,  2,  3,  3,  2,
+    3,  2,  2,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  2,
+    3,  3,  3,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,  3,  3,
+    2,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 15,  0,  0,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,
+    0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,
+    2,  0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,
+    2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  2,  0,  0,  0,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
+   13, 13, 13,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
+   13,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13,  2,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  2,  2,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  1,
+    2,  3,  4,  5,  6,  0,  0,  0,  0,  7,  8,  9, 10, 11,  0, 12,
+    0,  0,  0,  0, 13,  0,  0, 14,  0,  0,  0,  0,  0,  0,  0,  0,
+   15, 16,  0, 17, 18, 19,  0,  0,  0, 20, 21, 22,  0, 23,  0, 24,
+    0, 25,  0, 26,  0,  0,  0,  0,  0, 27, 28,  0, 29,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 30, 31,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 32, 33, 34, 35, 36, 37, 38, 39, 40,  0,  0,  0,
+   41,  0, 42, 43, 44, 45, 46, 47, 48,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51, 52,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   53, 54, 55, 56, 57, 58, 59, 60, 61, 62,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 63,  0,
+   64,  0,  0,  0,  0,  0,  0,  0,  0, 65,  0,  0,  0,  0, 66,  0,
+    0,  0, 67,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0, 68, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 71, 72, 73, 74,
+   75, 76, 77, 78, 79,  0,
+};
+static const uint16_t
+_hb_ucd_u16[11168] =
+{
+     0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
+    13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
+    13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
+    32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
+     9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
+    13,  13,  13,  42,   9,  43,  11,  11,  44,  45,  32,  46,  47,  48,  49,  50,
+    51,  52,  48,  48,  53,  32,  54,  55,  48,  48,  48,  48,  48,  56,  57,  58,
+    59,  60,  48,  32,  61,  48,  48,  48,  48,  48,  62,  63,  64,  48,  65,  66,
+    48,  67,  68,  69,  48,  70,  71,  72,  72,  72,  48,  73,  72,  74,  75,  32,
+    76,  48,  48,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
+    90,  83,  84,  91,  92,  93,  94,  95,  96,  97,  84,  98,  99, 100,  88, 101,
+   102,  83,  84, 103, 104, 105,  88, 106, 107, 108, 109, 110, 111, 112,  94, 113,
+   114, 115,  84, 116, 117, 118,  88, 119, 120, 115,  84, 121, 122, 123,  88, 124,
+   125, 115,  48, 126, 127, 128,  88, 129, 130, 131,  48, 132, 133, 134,  94, 135,
+   136,  48,  48, 137, 138, 139,  72,  72, 140,  48, 141, 142, 143, 144,  72,  72,
+   145, 146, 147, 148, 149,  48, 150, 151, 152, 153,  32, 154, 155, 156,  72,  72,
+    48,  48, 157, 158, 159, 160, 161, 162, 163, 164,   9,   9, 165,  11,  11, 166,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48, 167, 168,  48,  48, 167,  48,  48, 169, 170, 171,  48,  48,
+    48, 170,  48,  48,  48, 172, 173, 174,  48, 175,   9,   9,   9,   9,   9, 176,
+   177,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48, 178,  48, 179, 180,  48,  48,  48,  48, 181, 182,
+   183, 184,  48, 185,  48, 186, 183, 187,  48,  48,  48, 188, 189, 190, 191, 192,
+   193, 191,  48,  48, 194,  48,  48, 195, 196,  48, 197,  48,  48,  48,  48, 198,
+    48, 199, 200, 201, 202,  48, 203, 204,  48,  48, 205,  48, 206, 207, 208, 208,
+    48, 209,  48,  48,  48, 210, 211, 212, 191, 191, 213, 214,  72,  72,  72,  72,
+   215,  48,  48, 216, 217, 159, 218, 219, 220,  48, 221,  64,  48,  48, 222, 223,
+    48,  48, 224, 225, 226,  64,  48, 227, 228,   9,   9, 229, 230, 231, 232, 233,
+    11,  11, 234,  27,  27,  27, 235, 236,  11, 237,  27,  27,  32,  32,  32, 238,
+    13,  13,  13,  13,  13,  13,  13,  13,  13, 239,  13,  13,  13,  13,  13,  13,
+   240, 241, 240, 240, 241, 242, 240, 243, 244, 244, 244, 245, 246, 247, 248, 249,
+   250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 260,  72, 261, 262, 263,
+   264, 265, 266, 267, 268, 269, 270, 270, 271, 272, 273, 208, 274, 275, 208, 276,
+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+   278, 208, 279, 208, 208, 208, 208, 280, 208, 281, 277, 282, 208, 283, 284, 208,
+   208, 208, 285,  72, 286,  72, 269, 269, 269, 287, 208, 208, 208, 208, 288, 269,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 289, 290, 208, 208, 291,
+   208, 208, 208, 208, 208, 208, 292, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+   208, 208, 208, 208, 208, 208, 293, 294, 269, 295, 208, 208, 296, 277, 297, 277,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+   277, 277, 277, 277, 277, 277, 277, 277, 298, 299, 277, 277, 277, 300, 277, 301,
+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+   208, 208, 208, 277, 302, 208, 208, 303, 208, 304, 208, 208, 208, 208, 208, 208,
+     9,   9, 305,  11,  11, 306, 307, 308,  13,  13,  13,  13,  13,  13, 309, 310,
+    11,  11, 311,  48,  48,  48, 312, 313,  48, 314, 315, 315, 315, 315,  32,  32,
+   316, 317, 318, 319, 320,  72,  72,  72, 208, 321, 208, 208, 208, 208, 208, 322,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323,  72, 324,
+   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 177,  48,  48,  48,  48, 330,
+   331,  48,  48, 136,  48,  48,  48,  48, 199, 332,  48,  71, 208, 208, 322,  48,
+   208, 333, 334, 208, 335, 336, 208, 208, 334, 208, 208, 336, 208, 208, 208, 208,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 198, 208, 208, 208, 208,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  72,
+    48, 337,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48, 150, 208, 208, 208, 285,  48,  48, 227,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+   338,  48, 339,  72,  13,  13, 340, 341,  13, 342,  48,  48,  48,  48, 343, 344,
+    31, 345, 346, 347,  13,  13,  13, 348, 349, 350, 351, 352, 353,  72,  72, 354,
+   355,  48, 356, 357,  48,  48,  48, 358, 359,  48,  48, 360, 361, 191,  32, 362,
+    64,  48, 363,  48, 364, 365,  48, 150,  76,  48,  48, 366, 367, 368, 369, 370,
+    48,  48, 371, 372, 373, 374,  48, 375,  48,  48,  48, 376, 377, 378, 379, 380,
+   381, 382, 315,  11,  11, 383, 384,  11,  11,  11,  11,  11,  48,  48, 385, 191,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 386,  48, 387,  48,  48, 205,
+   388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
+   388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48, 203,  48,  48,  48,  48,  48,  48, 206,  72,  72,
+   390, 391, 392, 393, 394,  48,  48,  48,  48,  48,  48, 395, 396, 397,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48, 398,  72,  48,  48,  48,  48, 399,  48,  48, 400,  72,  72, 401,
+    32, 402,  32, 403, 404, 405, 406, 407,  48,  48,  48,  48,  48,  48,  48, 408,
+   409,   2,   3,   4,   5, 410, 411, 412,  48, 413,  48, 199, 414, 415, 416, 417,
+   418,  48, 171, 419, 203, 203,  72,  72,  48,  48,  48,  48,  48,  48,  48,  71,
+   420, 269, 269, 421, 270, 270, 270, 422, 423, 324, 424,  72,  72, 208, 208, 425,
+    72,  72,  72,  72,  72,  72,  72,  72,  48, 150,  48,  48,  48, 100, 426, 427,
+    48,  48, 428,  48, 429,  48,  48, 430,  48, 431,  48,  48, 432, 433,  72,  72,
+     9,   9, 434,  11,  11,  48,  48,  48,  48, 203, 191,   9,   9, 435,  11, 436,
+    48,  48, 400,  48,  48,  48, 437,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48, 314,  48, 198, 400,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+   438,  48,  48, 439,  48, 440,  48, 441,  48, 199, 442,  72,  72,  72,  48, 443,
+    48, 444,  48, 445,  72,  72,  72,  72,  48,  48,  48, 446, 269, 447, 269, 269,
+   448, 449,  48, 450, 451, 452,  48, 453,  48, 454,  72,  72, 455,  48, 456, 457,
+    48,  48,  48, 458,  48, 459,  48, 460,  48, 461, 462,  72,  72,  72,  72,  72,
+    48,  48,  48,  48, 195,  72,  72,  72,   9,   9,   9, 463,  11,  11,  11, 464,
+    48,  48, 465, 191,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72, 269, 466,  72,  72,  72,  72,  72,  72,  72,  72,
+    48, 454, 467,  48,  62, 468,  72,  72,  72,  72,  72,  72,  72,  72,  48, 314,
+   469,  48,  48, 470, 471, 447, 472, 473, 220,  48,  48, 474, 475,  48, 195, 191,
+   476,  48, 477, 478, 479,  48,  48, 480, 220,  48,  48, 481, 482, 483, 484, 485,
+    48,  97, 486, 487,  72,  72,  72,  72, 488, 489, 490,  48,  48, 491, 492, 191,
+   493,  83,  84, 494, 495, 496, 497, 498,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48, 499, 500, 501,  72,  72,  48,  48,  48, 502, 503, 191,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  48,  48, 504, 505, 506, 507,  72,  72,
+    48,  48,  48, 508, 509, 191, 510,  72,  48,  48, 511, 512, 191,  72,  72,  72,
+    48, 172, 513, 514,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48, 486, 515,  72,  72,  72,  72,  72,  72,   9,   9,  11,  11, 147, 516,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72, 517,  48,  48, 518, 519,  72,
+   520,  48,  48, 521, 522, 523,  48,  48, 524, 525, 526,  72,  48,  48,  48, 195,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    84,  48, 504, 527, 528, 147, 174, 529,  48, 530, 531, 532,  72,  72,  72,  72,
+   533,  48,  48, 534, 535, 191, 536,  48, 537, 538, 191,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  48, 539,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72, 269, 540, 541, 542,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48, 206,  72,  72,  72,  72,  72,  72,
+   270, 270, 270, 270, 270, 270, 543, 544,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48, 386,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48, 199, 545,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48, 314,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48, 195,  48, 199, 368,  72,  72,  72,  72,  72,  72,  48, 203, 546,
+    48,  48,  48, 547, 548, 549, 550, 551,  48,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,   9,   9,  11,  11, 269, 552,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48, 553, 554, 555, 555, 556, 557,  72,  72,  72,  72, 558,  72,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 400,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 559,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48, 199,  72,  72,  72, 559, 560,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 205,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48,  48,  48,  71, 150, 195, 561, 562,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323,
+   208, 208, 563, 208, 208, 208, 564, 565, 566, 208, 567, 208, 208, 208, 568,  72,
+   208, 208, 208, 208, 569,  72,  72,  72,  72,  72,  72,  72,  72,  72, 269, 570,
+   208, 208, 208, 208, 208, 285, 269, 451,  72,  72,  72,  72,  72,  72,  72,  72,
+     9, 571,  11, 572, 573, 574, 240,   9, 575, 576, 577, 578, 579,   9, 571,  11,
+   580, 581,  11, 582, 583, 584, 585,   9, 586,  11,   9, 571,  11, 572, 573,  11,
+   240,   9, 575, 585,   9, 586,  11,   9, 571,  11, 587,   9, 588, 589, 590, 591,
+    11, 592,   9, 593, 594, 595, 596,  11, 597,   9, 598,  11, 599, 600, 600, 600,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+    32,  32,  32, 601,  32,  32, 602, 603, 604, 605,  45,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+   606, 607, 608,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48, 150, 609, 610,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  48,  48, 611, 612,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 613, 614,  72,  72,
+     9,   9, 575,  11, 615, 368,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72, 484, 269, 269, 616, 617,  72,  72,  72,  72,
+   484, 269, 618, 619,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+   620,  48, 621, 622, 623, 624, 625, 626, 627, 205, 628, 205,  72,  72,  72, 629,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+   208, 208, 324, 208, 208, 208, 208, 208, 208, 322, 333, 630, 630, 630, 208, 323,
+   174, 208, 208, 208, 208, 208, 631, 208, 208, 208, 631,  72,  72,  72, 632, 208,
+   633, 208, 208, 324, 568, 634, 323,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 635,
+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323, 631, 286,
+   208, 208, 208, 208, 208, 208, 208, 322, 208, 208, 208, 208, 208, 568, 324,  72,
+   324, 208, 208, 208, 636, 175, 208, 208, 636, 208, 637,  72,  72,  72,  72,  72,
+   638, 208, 208, 208, 208, 208, 208, 639, 208, 208, 640, 208, 641, 208, 208, 208,
+   208, 208, 208, 208, 208, 322, 637, 642, 633, 323,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 314,  72,  72,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48, 204,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48, 203,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 643,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  72,
+    48, 203,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
+   644,  72, 645, 645, 645, 645, 645, 645,  72,  72,  72,  72,  72,  72,  72,  72,
+    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  72,
+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 646,
+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 647,
+     0,   0,   0,   0,   1,   2,   1,   2,   0,   0,   3,   3,   4,   5,   4,   5,
+     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
+     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   6,   0,   0,   7,   0,
+     8,   8,   8,   8,   8,   8,   8,   9,  10,  11,  12,  11,  11,  11,  13,  11,
+    14,  14,  14,  14,  14,  14,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,
+    14,  14,  14,  16,  17,  18,  17,  17,  19,  20,  21,  21,  22,  21,  23,  24,
+    25,  26,  27,  27,  28,  29,  27,  30,  27,  27,  27,  27,  27,  31,  27,  27,
+    32,  33,  33,  33,  34,  27,  27,  27,  35,  35,  35,  36,  37,  37,  37,  38,
+    39,  39,  40,  41,  42,  43,  44,  45,  45,  45,  27,  46,  45,  47,  48,  27,
+    49,  49,  49,  49,  49,  50,  51,  49,  52,  53,  54,  55,  56,  57,  58,  59,
+    60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
+    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,
+    92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107,
+   108, 109, 110, 110, 111, 112, 113, 110, 114, 115, 116, 117, 118, 119, 120, 121,
+   122, 123, 123, 124, 123, 125,  45,  45, 126, 127, 128, 129, 130, 131,  45,  45,
+   132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137,  45,  45,
+   138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141,
+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+   143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143,
+   143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153,
+   154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+   154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
+   154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159,
+   160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170,
+   171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176,
+   177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168,
+   188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 195,  45,  45,  45,  45,
+   196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201,
+   202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211,
+     4,   4, 212,   4,   4, 213, 214, 215,   4,   4,   4, 216,   8,   8,   8, 217,
+     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
+    11, 218,  11,  11, 218, 219,  11, 220,  11,  11,  11, 221, 221, 222,  11, 223,
+   224,   0,   0,   0,   0,   0, 225, 226, 227, 228,   0,   0,  45,   8,   8, 229,
+     0,   0, 230, 231, 232,   0,   4,   4, 233,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0, 234,  45, 235,  45,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0, 237,   0, 238,   0,   0,   0,   0,   0,   0,
+   239, 239, 240, 239, 239, 240,   4,   4, 241, 241, 241, 241, 241, 241, 241, 242,
+   139, 139, 140, 243, 243, 243, 244, 245, 143, 246, 247, 247, 247, 247,  14,  14,
+     0,   0,   0,   0,   0,  45,  45,  45, 248, 249, 248, 248, 248, 248, 248, 250,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251,  45, 252,
+   253,   0, 254, 255, 256, 257, 257, 257, 257, 258, 259, 260, 260, 260, 260, 261,
+   262, 263, 263, 264, 142, 142, 142, 142, 265,   0, 263, 266,   0,   0, 267, 260,
+   142, 265,   0,   0,   0,   0, 142, 268,   0,   0,   0,   0,   0, 260, 260, 269,
+   260, 260, 260, 260, 260, 270,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251,   0,   0,   0,   0,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,  45,
+   271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
+   271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
+   271, 271, 271, 271, 271, 271, 271, 271, 272, 271, 271, 271, 273, 274, 274, 274,
+   275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+   275, 275, 276,  45,  14,  14,  14,  14,  14,  14, 277, 277, 277, 277, 277, 278,
+     0,   0, 279,   4,   4,   4,   4,   4, 280,   4,   4,   4, 281,  45,  45, 282,
+   283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290,  49,  49,
+   291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299,
+   300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308,
+   309, 310, 247,   4,   4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314,
+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 315, 142, 316, 142, 142, 317,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319,  45,  45,
+   320, 321,  21, 322, 323,  27,  27,  27,  27,  27,  27,  27, 324,  47,  27,  27,
+    27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,
+    27,  27,  27, 325,  45,  27,  27,  27,  27, 326,  27,  27, 327,  45,  45, 328,
+     8, 285, 329,   0,   0, 330, 331, 332,  27,  27,  27,  27,  27,  27,  27, 333,
+   334,   0,   1,   2,   1,   2, 335, 259, 260, 336, 142, 265, 337, 338, 339, 340,
+   341, 342, 343, 344, 345, 345,  45,  45, 342, 342, 342, 342, 342, 342, 342, 346,
+   347,   0,   0, 348,  11,  11,  11,  11, 349, 252, 350,  45,  45,   0,   0, 351,
+    45,  45,  45,  45,  45,  45,  45,  45, 352, 353, 354, 354, 354, 355, 356, 252,
+   357, 357, 358, 359, 360, 361, 361, 362, 363, 364, 365, 365, 366, 367,  45,  45,
+   368, 368, 368, 368, 368, 369, 369, 369, 370, 371, 372, 373, 373, 374, 373, 375,
+   376, 376, 377, 378, 378, 378, 379,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380,
+   380, 380, 380, 381, 380, 382, 383,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   384, 385, 385, 386, 387, 388, 389, 389, 390, 391, 392,  45,  45,  45, 393, 394,
+   395, 396, 397, 398,  45,  45,  45,  45, 399, 399, 400, 401, 400, 402, 400, 400,
+   403, 404, 405, 406, 407, 407, 408, 408, 409, 409,  45,  45, 410, 410, 411, 412,
+   413, 413, 413, 414, 415, 416, 417, 418, 419, 420, 421,  45,  45,  45,  45,  45,
+   422, 422, 422, 422, 423,  45,  45,  45, 424, 424, 424, 425, 424, 424, 424, 426,
+     0,   0, 427, 285,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  27, 428,  45,  45,  45,  45,  45,  45,  45,  45,
+     8,   8, 429,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  27, 430,
+   431, 431, 431, 431, 432, 433, 431, 434, 435, 435, 435, 435, 436, 437, 438, 439,
+   440, 440, 440, 441, 442, 443, 443, 444, 445, 445, 445, 445, 446, 445, 447, 448,
+   449, 450, 449, 451,  45,  45,  45,  45, 452, 453, 454, 455, 455, 455, 456, 457,
+   458, 459, 460, 461, 462, 463, 464, 465,  45,  45,  45,  45,  45,  45,  45,  45,
+   466, 466, 466, 466, 466, 467,  45,  45, 468, 468, 468, 468, 469, 470,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45, 471, 471, 471, 472, 471, 473,  45,  45,
+   474, 474, 474, 474, 475, 476, 477,  45, 478, 478, 478, 479, 480,  45,  45,  45,
+   481, 482, 483, 481,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    17,  17,  17, 484,  45,  45,  45,  45,  45,  45, 485, 485, 485, 485, 485, 486,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 487, 488, 488, 487, 489,  45,
+    14,  14,  14,  14, 490,  49,  49,  49,  49,  49, 491,  45, 492, 492, 492, 493,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   494, 495, 495, 496, 497, 495, 498, 499, 499, 500, 501, 502,  45,  45,  45,  45,
+   503, 139, 139, 504, 505, 506, 507,  11, 349, 508, 509,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 510, 511,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 512, 512, 512, 513,
+   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+   514, 514, 514, 514, 514, 514, 514, 514, 514, 515,  45,  45,  45,  45,  45,  45,
+   514, 514, 514, 514, 514, 514, 516, 517, 514, 514, 514, 514, 514, 514, 514, 514,
+   514, 514, 514, 514, 518,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519,
+   519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519,
+   519, 519, 520, 521,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522,
+   522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522,
+   522, 522, 522, 522, 523,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+   277, 277, 277, 524, 525, 526, 527,  45,  45,  45,  45,  45,  45, 528, 529, 530,
+   531, 531, 531, 531, 532, 533, 534, 535, 531,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45, 536, 536, 536, 536, 536, 537,  45,  45,  45,  45,  45,  45,
+   538, 538, 538, 538, 539, 538, 538, 538, 540, 538,  45,  45,  45,  45, 541,  45,
+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 543,
+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 544,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   545, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+   257, 546,  45,  45,  45, 547, 548, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 317,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   549, 549, 549, 549, 549, 549, 550, 551, 552, 553, 267,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 554,
+     0,   0, 555,   0,   0,   0, 556, 557, 558,   0, 559,   0,   0,   0, 560,  45,
+    11,  11,  11,  11, 561,  45,  45,  45,  45,  45,  45,  45,  45,  45,   0, 267,
+     0,   0,   0,   0,   0, 234,   0, 560,  45,  45,  45,  45,  45,  45,  45,  45,
+     0,   0,   0,   0,   0, 225,   0,   0,   0, 562, 563, 564, 565,   0,   0,   0,
+   566, 567,   0, 568, 569, 570,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 238,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 571,   0,   0,   0,
+   572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572,
+   572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572,
+   572, 572, 572, 572, 572, 572, 572, 572, 573, 574, 575,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   576, 577, 578,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   248, 248, 579, 318, 580,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  21,  21,  21, 581,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 584,  45,  45,
+   585, 585, 585, 585, 586, 587,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45, 334,   0,   0,   0, 588,  45,  45,  45,  45,
+   334,   0,   0, 589,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   590,  27, 591, 592, 593, 594, 595, 596, 597, 598, 599, 598,  45,  45,  45, 324,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+     0,   0, 252,   0,   0,   0,   0,   0,   0, 267, 227, 334, 334, 334,   0, 554,
+   600,   0,   0,   0,   0,   0, 600,   0,   0,   0, 600,  45,  45,  45, 601,   0,
+   602,   0,   0, 252, 560, 603, 554,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 554, 600, 235,
+     0,   0,   0,   0,   0,   0,   0, 267,   0,   0,   0,   0,   0, 560, 252,  45,
+   252,   0,   0,   0, 427, 285,   0,   0, 427,   0, 589,  45,  45,  45,  45,  45,
+   604,   0,   0,   0,   0,   0,   0, 605,   0,   0, 606,   0, 607,   0,   0,   0,
+     0,   0,   0,   0,   0, 267, 589, 608, 609, 554,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 610,  45,  45,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 611, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 612, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 613,  45,
+   248, 318,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
+   614,  45,   0,   0,   0,   0,   0,   0,  45,  45,  45,  45,  45,  45,  45,  45,
+     8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
+     0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
+  1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
+     0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303,
+   943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
+     0,   0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
+   991,1176, 993,1178, 994,1179,   0,   0,1004,1190,1005,1191,1006,1192,1014,1199,
+  1007,   0,   0,   0,1016,1201,1020,1206,   0,1022,1208,1025,1211,1023,1209,   0,
+     0,   0,   0,1032,1218,1037,1223,1035,1221,   0,   0,   0,1044,1230,1045,1231,
+  1049,1235,   0,   0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
+  1069,1255,1077,1264,1074,1261,   0,   0,1083,1270,1084,1271,1085,1272,1088,1275,
+  1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1053,1239,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1093,
+  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, 949,1134,1010,
+  1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366,   0,1320,1347,
+  1418,1419,1323,1350,   0,   0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
+  1202,   0,   0,   0, 987,1172,   0,   0,1031,1217,1321,1348,1322,1349,1338,1365,
+   950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
+  1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263,   0,   0, 997,1182,
+     0,   0,   0,   0,   0,   0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
+  1422,1423,1113,1301,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     8,   9,   0,  10,1425,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,
+     0,   0,   0,   0,   0,1314,1427,   5,1434,1438,1443,   0,1450,   0,1455,1461,
+  1514,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1446,1458,1468,1476,1480,1486,
+  1517,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1489,1503,1494,1500,1508,   0,
+     0,   0,   0,1520,1521,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1526,1528,   0,1525,   0,   0,   0,1522,   0,   0,   0,   0,1536,1532,1539,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1534,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1556,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1548,1550,   0,1547,   0,   0,   0,1567,   0,   0,   0,   0,1558,1554,1561,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1568,1569,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1529,1551,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1523,1545,1524,1546,   0,   0,1527,1549,   0,   0,1570,1571,1530,1552,1531,1553,
+     0,   0,1533,1555,1535,1557,1537,1559,   0,   0,1572,1573,1544,1566,1538,1560,
+  1540,1562,1541,1563,1542,1564,   0,   0,1543,1565,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1606,1607,1609,1608,1610,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1613,   0,1611,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1612,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1620,   0,   0,   0,   0,   0,   0,
+     0,1623,   0,   0,1624,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1614,1615,1616,1617,1618,1619,1621,1622,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1628,1629,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1625,1626,   0,1627,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1634,   0,   0,1635,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1630,1631,1632,   0,   0,1633,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1639,   0,   0,1638,1640,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1636,1637,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1641,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1642,1644,1643,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1645,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1646,   0,   0,   0,   0,   0,   0,1648,1649,   0,1647,1650,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1651,1653,1652,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1654,   0,1655,1657,1656,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1659,   0,   0,   0,   0,   0,   0,   0,   0,   0,1660,   0,   0,
+     0,   0,1661,   0,   0,   0,   0,1662,   0,   0,   0,   0,1663,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1658,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1664,   0,1665,1673,   0,1674,   0,   0,   0,   0,   0,   0,   0,
+     0,1666,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1668,   0,   0,   0,   0,   0,   0,   0,   0,   0,1669,   0,   0,
+     0,   0,1670,   0,   0,   0,   0,1671,   0,   0,   0,   0,1672,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1667,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1675,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1676,   0,1677,   0,1678,   0,1679,   0,1680,   0,
+     0,   0,1681,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1682,   0,1683,   0,   0,
+  1684,1685,   0,1686,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
+   966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
+   989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
+  1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
+  1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
+  1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
+  1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
+  1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
+  1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
+  1119,1308,1122,1311,1123,1312,1186,1260,1293,1305,   0,1394,   0,   0,   0,   0,
+   952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
+  1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
+  1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
+  1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
+  1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
+  1409,1414,1109,1297,1117,1306,1116,1304,1112,1300,   0,   0,   0,   0,   0,   0,
+  1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
+  1477,1478,1729,1731,1730,1732,   0,   0,1435,1436,1733,1735,1734,1736,   0,   0,
+  1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
+  1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
+  1495,1496,1777,1779,1778,1780,   0,   0,1451,1452,1781,1783,1782,1784,   0,   0,
+  1504,1505,1785,1788,1786,1789,1787,1790,   0,1459,   0,1791,   0,1792,   0,1793,
+  1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
+  1467,  21,1475,  22,1479,  23,1485,  24,1493,  27,1499,  28,1507,  29,   0,   0,
+  1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
+  1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
+  1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
+  1470,1469,1822,1474,1465,   0,1473,1825,1429,1428,1426,  12,1432,   0,  26,   0,
+     0,1315,1823,1484,1466,   0,1483,1829,1433,  13,1437,  14,1441,1826,1827,1828,
+  1488,1487,1513,  19,   0,   0,1492,1515,1445,1444,1442,  15,   0,1831,1832,1833,
+  1502,1501,1516,  25,1497,1498,1506,1518,1457,1456,1454,  17,1453,1313,  11,   3,
+     0,   0,1824,1512,1519,   0,1511,1830,1449,  16,1460,  18,1464,   4,   0,   0,
+    30,  31,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,  20,   0,   0,   0,   2,   6,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1834,1835,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1836,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1837,1839,1838,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1840,   0,   0,   0,   0,1841,   0,   0,1842,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1843,   0,1844,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1845,   0,   0,1846,   0,   0,1847,   0,1848,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   937,   0,1850,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1849, 936, 938,
+  1851,1852,   0,   0,1853,1854,   0,   0,1855,1856,   0,   0,   0,   0,   0,   0,
+  1857,1858,   0,   0,1861,1862,   0,   0,1863,1864,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1867,1868,1869,1870,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1859,1860,1865,1866,   0,   0,   0,   0,   0,   0,1871,1872,1873,1874,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   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,  33,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1875,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1877,   0,1878,   0,
+  1879,   0,1880,   0,1881,   0,1882,   0,1883,   0,1884,   0,1885,   0,1886,   0,
+  1887,   0,1888,   0,   0,1889,   0,1890,   0,1891,   0,   0,   0,   0,   0,   0,
+  1892,1893,   0,1894,1895,   0,1896,1897,   0,1898,1899,   0,1900,1901,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1876,   0,   0,   0,   0,   0,   0,   0,   0,   0,1902,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1904,   0,1905,   0,
+  1906,   0,1907,   0,1908,   0,1909,   0,1910,   0,1911,   0,1912,   0,1913,   0,
+  1914,   0,1915,   0,   0,1916,   0,1917,   0,1918,   0,   0,   0,   0,   0,   0,
+  1919,1920,   0,1921,1922,   0,1923,1924,   0,1925,1926,   0,1927,1928,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1903,   0,   0,1929,1930,1931,1932,   0,   0,   0,1933,   0,
+   710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
+   663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
+   810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
+   368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
+   811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
+   594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
+   313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
+   424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
+   193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
+   337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
+   683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
+   608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
+   479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
+   791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
+   377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
+   659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
+   153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210,   0,   0,
+   227,   0, 379,   0,   0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604,   0,
+   661,   0, 703,   0,   0, 735, 743,   0,   0,   0, 793, 794, 795, 808, 741, 773,
+   118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
+   335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
+   549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
+   690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623,   0,   0,
+   102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
+   250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
+   370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
+   493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
+   591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
+   709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
+   847, 857,  55,  65,  66, 883, 892, 916, 822, 824,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1586,   0,1605,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,
+  1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,
+  1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1948,1949,
+  1950,1951,1952,1953,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,1957,1959,1958,
+  1960,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131,
+   132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37,
+   157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
+   181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
+   197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
+   153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
+   836, 837, 247, 248, 249, 246, 251,  39,  40, 253, 255, 255, 838, 257, 258, 259,
+   261, 839, 262, 263, 301, 264,  41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
+   278, 281, 282,  42, 283, 284, 285, 286,  43, 843,  44, 289, 290, 291, 293, 934,
+   298, 845, 845, 621, 300, 300,  45, 852, 894, 302, 304,  46, 306, 309, 310, 312,
+   316,  48,  47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
+   335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
+   358, 356,  49, 363, 365, 367, 364,  50, 369, 371, 851, 376, 386, 378,  53, 381,
+    52,  51, 140, 141, 387, 382, 614,  78, 388, 389, 390, 394, 392, 856,  54, 399,
+   396, 402, 404, 858, 405, 401, 407,  55, 408, 409, 410, 413, 859, 415,  56, 417,
+   860, 418,  57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
+   437, 441, 438, 439, 442, 443, 864, 436, 449, 450,  58, 454, 453, 865, 447, 460,
+   866, 867, 461, 466, 465, 464,  59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
+   483, 485, 486, 871, 488, 489, 872, 873, 495, 497,  60, 498,  61,  61, 504, 505,
+   507, 508, 511,  62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878,  63,  64,
+   528, 880, 879, 881, 882, 530, 531, 531, 533,  66, 534,  67,  68, 884, 536, 538,
+   541,  69, 885, 549, 886, 887, 556, 559,  70, 561, 562, 563, 888, 889, 889, 567,
+    71, 890, 570, 571,  72, 891, 577,  73, 581, 579, 582, 893, 587,  74, 590, 592,
+   596,  75, 895, 896,  76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
+   853,  77, 615, 616,  79, 617, 252, 902, 903, 854, 855, 621, 622, 731,  80, 627,
+   626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
+   638, 643, 644, 645, 905, 907, 906,  81, 653, 654, 656, 911, 657, 908,  82,  83,
+   909, 910,  84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675,  85,
+   677, 678,  86, 681, 682, 912, 685, 686,  87, 689,  36, 913, 914,  88,  89, 696,
+   702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
+   918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762,  90,
+   764, 922,  91, 775, 279, 780, 923, 925,  92,  93, 785, 926,  94, 927, 787, 787,
+   789, 928, 792,  95, 796, 797, 798, 800,  96, 929, 802, 804, 806,  97,  98, 807,
+   930,  99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+};
+static const int16_t
+_hb_ucd_i16[196] =
+{
+      0,    0,    0,    0,    1,   -1,    0,    0,    2,    0,   -2,    0,    0,    0,    0,    2,
+      0,   -2,    0,    0,    0,    0,    0,   16,    0,    0,    0,  -16,    0,    0,    1,   -1,
+      0,    0,    0,    1,   -1,    0,    0,    0,    0,    1,   -1,    0,    3,    3,    3,   -3,
+     -3,   -3,    0,    0,    0, 2016,    0,    0,    0,    0,    0, 2527, 1923, 1914, 1918,    0,
+   2250,    0,    0,    0,    0,    0,    0,  138,    0,    7,    0,    0,   -7,    0,    0,    0,
+      1,   -1,    1,   -1,   -1,    1,   -1,    0, 1824,    0,    0,    0,    0,    0, 2104,    0,
+   2108, 2106,    0, 2106, 1316,    0,    0,    0,    0,    1,   -1,    1,   -1, -138,    0,    0,
+      1,   -1,    8,    8,    8,    0,    7,    7,    0,    0,   -8,   -8,   -8,   -7,   -7,    0,
+      1,   -1,    0,    2,-1316,    1,   -1,    0,   -1,    1,   -1,    1,   -1,    3,    1,   -1,
+     -3,    1,   -1,    1,   -1,    0,    0,-1914,-1918,    0,    0,-1923,-1824,    0,    0,    0,
+      0,-2016,    0,    0,    1,   -1,    0,    1,    0,    0,-2104,    0,    0,    0,    0,-2106,
+  -2108,-2106,    0,    0,    1,   -1,-2250,    0,    0,    0,-2527,    0,    0,   -2,    0,    1,
+     -1,    0,    1,   -1,
+};
+
+static inline uint_fast8_t
+_hb_ucd_gc (unsigned u)
+{
+  return u<1114110u?_hb_ucd_u8[2176+(((_hb_ucd_u16[((_hb_ucd_u8[u>>4>>5])<<5)+((u>>4)&31u)])<<4)+((u)&15u))]:2;
+}
+static inline uint_fast8_t
+_hb_ucd_ccc (unsigned u)
+{
+  return u<125259u?_hb_ucd_u8[14026+(((_hb_ucd_u8[13034+(((_hb_ucd_u8[12544+(u>>4>>4)])<<4)+((u>>4)&15u))])<<4)+((u)&15u))]:0;
+}
+static inline unsigned
+_hb_ucd_b4 (const uint8_t* a, unsigned i)
+{
+  return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline int_fast16_t
+_hb_ucd_bmg (unsigned u)
+{
+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[16170+(((_hb_ucd_b4(16042+_hb_ucd_u8,u>>2>>6))<<6)+((u>>2)&63u))])<<2)+((u)&3u)]:0;
+}
+static inline uint_fast8_t
+_hb_ucd_sc (unsigned u)
+{
+  return u<918000u?_hb_ucd_u8[18924+(((_hb_ucd_u16[3008+(((_hb_ucd_u8[17130+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2;
+}
+static inline uint_fast16_t
+_hb_ucd_dm (unsigned u)
+{
+  return u<195102u?_hb_ucd_u16[6048+(((_hb_ucd_u8[28764+(u>>6)])<<6)+((u)&63u))]:0;
+}
+
+
+#else
+
+static const uint8_t
+_hb_ucd_u8[16998] =
+{
+    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  9, 10, 11,  7,  7,  7,  7, 12, 13, 14, 14, 14, 15,
+   16, 17, 18, 19, 20, 21, 22, 21, 23, 21, 21, 21, 21, 24,  7,  7,
+   25, 26, 21, 21, 21, 21, 27, 28, 21, 21, 29, 30, 31, 32, 33, 34,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7, 35,  7, 36, 37,  7, 38,  7,  7,  7, 39, 21, 40,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   41, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 42,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 43,
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
+   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
+   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
+   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 91,
+   92, 34, 34, 34, 34, 34, 34, 34, 34, 93, 34, 34, 94, 95, 96, 97,
+   98, 99,100,101,102,103,104,105, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,106,
+  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
+  108,108, 34, 34,109,110,111,112, 34, 34,113,114,115,116,117,118,
+  119,120,121,122,123,124,125,126,127,128,129,123, 34, 34,130,123,
+  131,132,133,134,135,136,137,138,139,140,141,123,142,123,143,144,
+  145,146,147,148,149,150,151,123,152,153,123,154,155,156,157,123,
+  158,159,123,160,161,162,123,123,163,164,165,166,123,167,123,168,
+   34, 34, 34, 34, 34, 34, 34,169,170, 34,171,123,123,123,123,123,
+  123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
+   34, 34, 34, 34, 34, 34, 34, 34,172,123,123,123,123,123,123,123,
+  123,123,123,123,123,123,123,123, 34, 34, 34, 34,173,123,123,123,
+   34, 34, 34, 34,174,175,176,177,123,123,123,123,178,179,180,181,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,182,
+   34, 34, 34, 34, 34,183,123,123,123,123,123,123,123,123,123,123,
+   34, 34,184, 34, 34,185,123,123,123,123,123,123,123,123,123,123,
+  123,123,123,123,123,123,123,123,186,187,123,123,123,123,123,123,
+   69,188,189,190,191,192,193,123,194,195,196,197,198,199,200,201,
+   69, 69, 69, 69,202,203,123,123,123,123,123,123,123,123,123,123,
+  204,123,205,123,123,206,123,123,123,123,123,123,123,123,123,123,
+   34,207,208,123,123,123,123,123,209,210,211,123,212,213,123,123,
+  214,215,216,217,218,123, 69,219, 69, 69, 69, 69, 69,220,221,222,
+  223,224,225,226,227,228,123,123,123,123,123,123,123,123,123,123,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,229, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,230, 34,
+  231, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,232, 34, 34,
+   34, 34, 34, 34, 34, 34, 34,233,123,123,123,123,123,123,123,123,
+   34, 34, 34, 34,234,123,123,123,123,123,123,123,123,123,123,123,
+  235,123,236,237,123,123,123,123,123,123,123,123,123,123,123,123,
+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,238,
+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,239,
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
+    7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 17, 18, 19,  1, 20, 20, 21, 22, 23, 24, 25,
+   26, 27, 15,  2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
+   32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
+   11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
+   34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
+   34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
+   32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
+   16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
+   40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
+   40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
+   43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10,
+   44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11,
+   11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
+   16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11,
+   32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
+   48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52,  2,  2,  2,
+   16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43,
+   43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62,
+   36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65,  8,  9, 66,  2, 67,
+   43, 43, 43, 43, 43, 60, 68,  2, 69, 36, 36, 36, 36, 70, 43, 43,
+    7,  7,  7,  7,  7,  2,  2, 36, 71, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36,
+    7,  7,  7,  7,  7, 36, 77, 78,  2,  2,  2,  2,  2,  2,  2, 79,
+   70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36,
+   36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44,
+    7,  7,  7,  7,  7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43,
+   43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
+   43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
+   36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 36, 36, 61, 36, 36, 36, 36, 44,
+   44, 57, 43, 43, 43, 43, 43, 43, 43, 82, 43, 43, 43, 43, 43, 43,
+   43, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 83, 71, 84,
+   85, 43, 43, 43, 83, 84, 85, 84, 70, 43, 43, 43, 36, 36, 36, 36,
+   36, 43,  2,  7,  7,  7,  7,  7, 86, 36, 36, 36, 36, 36, 36, 36,
+   70, 84, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 84,
+   85, 43, 80, 87, 88, 87, 85, 61, 44, 44, 44, 87, 44, 44, 36, 62,
+   36, 43, 44,  7,  7,  7,  7,  7, 36, 20, 27, 27, 27, 56, 63, 80,
+   57, 83, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 84,
+   85, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61,
+   44, 44, 44,  7,  7,  7,  7,  7, 43, 36, 70, 64, 44, 44, 44, 44,
+   57, 83, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36,
+   61, 36, 62, 36, 36, 44, 71, 84, 85, 43, 43, 57, 83, 87, 85, 44,
+   61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43,
+   57, 84, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 85,
+   85, 43, 80, 87, 88, 87, 85, 44, 44, 44, 44, 83, 44, 44, 36, 62,
+   78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36,
+   61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36,
+   36, 36, 36, 36, 36, 44, 44, 84, 83, 88, 44, 84, 88, 84, 85, 44,
+   61, 44, 44, 87, 44, 44, 44, 44, 27, 89, 67, 67, 56, 90, 44, 44,
+   83, 84, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 44, 62, 43, 83, 84, 88, 43, 80, 43, 43, 44,
+   44, 44, 57, 80, 36, 61, 44, 44, 44, 44, 44, 91, 27, 27, 27, 89,
+   70, 84, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 85,
+   84, 84, 88, 83, 88, 84, 43, 44, 44, 44, 87, 88, 44, 44, 44, 61,
+   62, 61, 44, 44, 44, 44, 44, 44, 43, 84, 62, 36, 36, 36, 61, 36,
+   36, 36, 36, 36, 36, 70, 71, 84, 85, 43, 80, 84, 88, 84, 85, 77,
+   44, 44, 36, 92, 27, 27, 27, 93, 27, 27, 27, 27, 89, 36, 36, 36,
+   44, 84, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
+   36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 87,
+   84, 43, 80, 80, 84, 84, 84, 84, 44, 84, 64, 44, 44, 44, 44, 44,
+   62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 94,
+   36, 36, 36, 75, 43, 43, 43, 60,  7,  7,  7,  7,  7,  2, 44, 44,
+   62, 61, 61, 36, 36, 61, 36, 36, 36, 36, 62, 62, 36, 36, 36, 36,
+   70, 36, 43, 43, 43, 43, 71, 44, 36, 36, 61, 81, 43, 43, 43, 44,
+    7,  7,  7,  7,  7, 44, 36, 36, 77, 67,  2,  2,  2,  2,  2,  2,
+    2, 95, 95, 67, 43, 67, 67, 67,  7,  7,  7,  7,  7, 27, 27, 27,
+   27, 27, 50, 50, 50,  4,  4, 84, 36, 36, 36, 36, 62, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 61, 44, 57, 43, 43, 43, 43, 43, 43, 83,
+   43, 43, 60, 43, 36, 36, 70, 43, 43, 43, 43, 43, 57, 43, 43, 43,
+   43, 43, 43, 43, 43, 43, 80, 67, 67, 67, 67, 76, 67, 67, 90, 67,
+    2,  2, 95, 67, 21, 64, 44, 44, 36, 36, 36, 36, 36, 92, 85, 43,
+   83, 43, 43, 43, 85, 83, 85, 71,  7,  7,  7,  7,  7,  2,  2,  2,
+   36, 36, 36, 84, 43, 36, 36, 43, 71, 84, 96, 92, 84, 84, 84, 36,
+   70, 43, 71, 36, 36, 36, 36, 36, 36, 83, 85, 83, 84, 84, 85, 92,
+    7,  7,  7,  7,  7, 84, 85, 67, 11, 11, 11, 48, 44, 44, 48, 44,
+   16, 16, 16, 16, 16, 53, 45, 16, 36, 36, 36, 36, 61, 36, 36, 44,
+   36, 36, 36, 61, 61, 36, 36, 44, 61, 36, 36, 44, 36, 36, 36, 61,
+   61, 36, 36, 44, 36, 36, 36, 36, 36, 36, 36, 61, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 61, 57, 43,  2,  2,  2,  2, 97, 27, 27, 27,
+   27, 27, 27, 27, 27, 27, 98, 44, 67, 67, 67, 67, 67, 44, 44, 44,
+   11, 11, 11, 44, 16, 16, 16, 44, 99, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 77, 72,100, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36,101,102, 44, 36, 36, 36, 36, 36, 63,  2,103,
+  104, 36, 36, 36, 61, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36,
+   36, 43, 80, 44, 44, 44, 44, 44, 36, 43, 60, 64, 44, 44, 44, 44,
+   36, 43, 44, 44, 44, 44, 44, 44, 61, 43, 44, 44, 44, 44, 44, 44,
+   36, 36, 43, 85, 43, 43, 43, 84, 84, 84, 84, 83, 85, 43, 43, 43,
+   43, 43,  2, 86,  2, 66, 70, 44,  7,  7,  7,  7,  7, 44, 44, 44,
+   27, 27, 27, 27, 27, 44, 44, 44,  2,  2,  2,105,  2, 59, 43, 68,
+   36,106, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 44, 44,
+   36, 36, 70, 71, 36, 36, 36, 36, 36, 36, 36, 36, 70, 61, 44, 44,
+   36, 36, 36, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 61,
+   43, 83, 84, 85, 83, 84, 44, 44, 84, 83, 84, 84, 85, 43, 44, 44,
+   90, 44,  2,  7,  7,  7,  7,  7, 36, 36, 36, 36, 36, 36, 36, 44,
+   36, 36, 61, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 44, 44,
+   36, 36, 36, 36, 36, 44, 44, 44,  7,  7,  7,  7,  7, 98, 44, 67,
+   67, 67, 67, 67, 67, 67, 67, 67, 36, 36, 36, 70, 83, 85, 44,  2,
+   36, 36, 92, 83, 43, 43, 43, 80, 83, 83, 85, 43, 43, 43, 83, 84,
+   84, 85, 43, 43, 43, 43, 80, 57,  2,  2,  2, 86,  2,  2,  2, 44,
+   43, 43, 43, 43, 43, 43, 43,107, 43, 43, 96, 36, 36, 36, 36, 36,
+   36, 36, 83, 43, 43, 83, 83, 84, 84, 83, 96, 36, 36, 36, 44, 44,
+   95, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 90, 44,
+   43, 96, 36, 36, 36, 36, 36, 36, 92, 43, 43, 84, 43, 85, 43, 36,
+   36, 36, 36, 83, 43, 84, 85, 85, 43, 84, 44, 44, 44, 44,  2,  2,
+   36, 36, 84, 84, 84, 84, 43, 43, 43, 43, 84, 43, 44, 91,  2,  2,
+    7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
+   16, 16, 16, 16,108, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+    2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
+   83, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 92, 43, 61, 44, 44,
+   16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
+   16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,109, 40, 40,
+   43, 43, 43, 43, 43, 57, 43, 43, 32, 32, 32, 16, 16, 16, 16, 32,
+   16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 44, 11, 11, 11, 44,
+   16, 16, 16, 16, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 44,
+   16, 16, 16, 16,110,110,110,110, 16, 16,108, 16, 11, 11,111,112,
+   41, 16,108, 16, 11, 11,111, 41, 16, 16, 44, 16, 11, 11,113, 41,
+   16, 16, 16, 16, 11, 11,114, 41, 44, 16,108, 16, 11, 11,111,115,
+  116,116,116,116,116,117, 65, 65,118,118,118,  2,119,120,119,120,
+    2,  2,  2,  2,121, 65, 65,122,  2,  2,  2,  2,123,124,  2,125,
+  126,  2,127,128,  2,  2,  2,  2,  2,  9,126,  2,  2,  2,  2,129,
+   65, 65, 68, 65, 65, 65, 65, 65,130, 44, 27, 27, 27,  8,127,131,
+   27, 27, 27, 27, 27,  8,127,102, 40, 40, 40, 40, 40, 40, 81, 44,
+   20, 20, 20, 20, 20, 20, 20, 20, 43, 43, 43, 43, 43, 43,132, 51,
+  133, 51,133, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44,
+   67,134, 67,135, 67, 34, 11, 16, 11, 32,135, 67, 49, 11, 11, 67,
+   67, 67,134,134,134, 11, 11,136, 11, 11, 35, 36, 39, 67, 16, 11,
+    8,  8, 49, 16, 16, 26, 67,137, 27, 27, 27, 27, 27, 27, 27, 27,
+  103,103,103,103,103,103,103,103,103,138,139,103,140, 67, 44, 44,
+    8,  8,141, 67, 67,  8, 67, 67,141, 26, 67,141, 67, 67, 67,141,
+   67, 67, 67, 67, 67, 67, 67,  8, 67,141,141, 67, 67, 67, 67, 67,
+   67, 67,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+   67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,142,143, 67, 67,
+   67, 67, 67, 67, 67, 67,141, 67, 67, 67, 67, 67, 67, 26,  8,  8,
+    8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
+    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 90, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
+   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
+   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
+   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
+    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
+    8,  8,127,144,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
+    8,127,145,145,145,145,145,145,145,145,145,145,144,  8,  8,  8,
+    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
+    8,  8,141, 26,  8,  8,141, 67, 67, 67, 44, 67, 67, 67, 67, 67,
+   67, 67, 67, 44, 67, 67, 67, 67, 11, 11, 11, 11, 11, 11, 11, 47,
+   16, 16, 16, 16, 16, 16, 16,108, 32, 11, 32, 34, 34, 34, 34, 11,
+   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,137, 67, 67,135, 34,146,
+   43, 32, 44, 44, 91,  2, 97,  2, 16, 16, 16,147, 44, 44,147, 44,
+   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
+   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
+    2,119,119,  2,123,124,119,  2,  2,  2,  2,  6,  2,105,119,  2,
+  119,  4,  4,  4,  4,  2,  2, 86,  2,  2,  2,  2,  2,118,  2,  2,
+  105,148,  2,  2,  2,  2,  2,  2, 67, 67, 67, 67, 67, 55, 67, 67,
+   67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 67, 44, 44,  1,  2,149,150,  4,  4,  4,  4,
+    4, 67,  4,  4,  4,  4,151,152,153,103,103,103,103, 43, 43, 84,
+  154, 40, 40, 67,103,155, 63, 67, 36, 36, 36, 61, 57,156,157, 69,
+   36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36,
+   67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90,
+   27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27,
+  158, 27, 27, 27, 27, 27, 27, 27, 36, 36,106, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36,159,  2,  7,  7,  7,  7,  7, 36, 44, 44,
+   32, 32, 32, 32, 32, 32, 32, 70, 51,160, 43, 43, 43, 43, 43, 86,
+   32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36,103,103,103,103,103,
+   43,  2,  2,  2, 44, 44, 44, 44, 41, 41, 41,157, 40, 40, 40, 40,
+   41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32,
+   45, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,161, 34, 35,
+   32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32,
+   11, 11, 32, 32, 32, 32, 32, 32, 44, 32, 11, 47, 44, 44, 44, 44,
+   44, 44, 44, 62, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
+   36, 92, 85, 83, 67, 67, 44, 44, 27, 27, 27, 67,162, 44, 44, 44,
+   36, 36,  2,  2, 44, 44, 44, 44, 84, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 84, 84, 84, 84, 84, 84, 84, 84, 43, 44, 44, 44, 44,  2,
+   43, 36, 36, 36,  2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43,  2,
+   36, 36, 36, 70, 43, 43, 43, 43, 43, 84, 44, 44, 44, 44, 44, 91,
+   36, 70, 84, 43, 43, 84, 43, 84,163,  2,  2,  2,  2,  2,  2, 52,
+    7,  7,  7,  7,  7, 44, 44,  2, 36, 36, 70, 69, 36, 36, 36, 36,
+    7,  7,  7,  7,  7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 83,
+   85, 83, 85, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 83, 44,
+    7,  7,  7,  7,  7, 44,  2,  2, 69, 36, 36, 77, 67, 92, 83, 36,
+   71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44,
+   44, 44, 44, 44, 44, 62,106,  2, 36, 36, 36, 36, 36, 92, 43, 84,
+    2,106,164, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61,
+   62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,112, 40, 40,
+   16, 16, 16, 16, 44, 44, 44, 44, 36, 92, 85, 84, 83,163, 85, 44,
+   36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36,
+  165,165,165,165,165,165,165,165,166,166,166,166,166,166,166,166,
+   16, 16, 16,108, 44, 44, 44, 44, 44,147, 16, 16, 44, 44, 62, 71,
+   36, 36, 36, 36,167, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61,
+   36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
+   41, 44, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36,145, 44, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,162, 44,
+    2,  2,  2,168,128, 44, 44, 44,  6,169,170,145,145,145,145,145,
+  145,145,128,168,128,  2,125,171,  2, 64,  2,  2,151,145,145,128,
+    2,172,  8,173, 66,  2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 61, 79, 91,  2,  3,  2,  4,  5,  6,  2,
+   16, 16, 16, 16, 16, 17, 18,127,128,  4,  2, 36, 36, 36, 36, 36,
+   69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
+   44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44,
+   20,174, 56,175, 26,  8,141, 90, 44, 44, 44, 44, 79, 65, 67, 44,
+   36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62,
+    2, 64, 44,176, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67,
+  103,103,140, 27, 89, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 90,
+   90, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 50, 44,
+  177, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 44, 44,
+   27, 27, 44, 44, 44, 44, 62, 36,150, 36, 36, 36, 36,178, 44, 44,
+   36, 36, 36, 43, 43, 80, 44, 44, 36, 36, 36, 36, 36, 36, 36, 91,
+   36, 36, 44, 44, 36, 36, 36, 36,179,103,103, 44, 44, 44, 44, 44,
+   11, 11, 11, 11, 16, 16, 16, 16, 11, 11, 44, 44, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 44, 44, 36, 36, 44, 44, 44, 44, 44, 91,
+   36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62,
+   36, 36, 36, 91, 27, 27, 27, 27, 36, 36, 36, 77,158, 27, 27, 27,
+   44, 44, 44,176, 27, 27, 27, 27, 36, 61, 36, 44, 44,176, 27, 27,
+   36, 36, 36, 27, 27, 27, 44, 91, 36, 36, 36, 36, 36, 44, 44, 91,
+   36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27,
+   70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36,
+   36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27, 98, 44, 44, 44,
+    2,  2,  2,  2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,180, 30,
+   36, 36, 36, 36, 36, 36,180, 27, 36, 36, 36, 36, 78, 36, 36, 36,
+   36, 36, 70, 80, 44,176, 27, 27,  2,  2,  2, 64, 44, 44, 44, 44,
+   36, 36, 36, 44, 91,  2,  2,  2, 36, 36, 36, 44, 27, 27, 27, 27,
+   36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 91,  2, 64, 44,
+   44, 44, 44, 44,176, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
+   16,108, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
+   27, 27, 27, 27, 27, 27, 27, 98, 27, 27, 27, 93, 44, 44, 44, 44,
+  177, 27, 30,  2,  2, 44, 44, 44, 85, 96, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 43, 60,  2,  2,  2, 44,
+   27, 27, 27,  7,  7,  7,  7,  7, 44, 44, 44, 44, 44, 44, 44, 57,
+   84, 85, 43, 83, 85, 60,181,  2,  2, 44, 44, 44, 44, 44, 79, 44,
+   43, 71, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, 85, 43,
+   43, 43, 80,  7,  7,  7,  7,  7,  2,  2, 92, 88, 44, 44, 44, 44,
+   36, 70,  2, 61, 44, 44, 44, 44, 36, 92, 84, 43, 43, 43, 43, 83,
+   96, 36, 63,  2, 59, 43, 60, 44,  7,  7,  7,  7,  7, 63, 63,  2,
+  176, 27, 27, 27, 27, 27, 27, 27, 27, 27, 98, 44, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 36, 84, 85, 43, 84, 83, 43,  2,  2,  2, 80,
+   36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
+   36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
+   84, 85, 43, 43, 43, 80, 44, 44, 43, 84, 62, 36, 36, 36, 61, 62,
+   61, 36, 62, 36, 36, 57, 71, 84, 83, 84, 88, 87, 88, 87, 84, 44,
+   61, 44, 44, 87, 44, 44, 62, 36, 36, 84, 44, 43, 43, 43, 80, 44,
+   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 92, 84, 43, 43, 43, 43,
+   84, 43, 83, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7, 91, 91, 71,
+   84, 85, 43, 43, 83, 83, 84, 85, 83, 43, 36, 72, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 36, 36, 92, 84, 43, 43, 44, 84, 84, 43, 85,
+   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
+   84, 85, 43, 43, 43, 83, 85, 85, 60,  2, 61, 44, 44, 44, 44, 44,
+    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 85, 84,
+   43, 43, 43, 85, 61, 44, 44, 44, 84, 43, 43, 85, 43, 43, 44, 44,
+    7,  7,  7,  7,  7, 27,  2, 95, 43, 43, 43, 43, 85, 60, 44, 44,
+   27, 98, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 44, 36, 36, 36,
+   92, 84, 43, 43, 44, 43, 84, 84, 71, 72, 88, 44, 44, 44, 44, 44,
+   70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 83, 70, 43, 60,
+    2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 83, 85, 43, 36, 36,
+   36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 83, 43,  2, 72,  2,
+    2, 64, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 85,
+   63,  2,  2, 44, 44, 44, 44, 44,  2, 36, 36, 36, 36, 36, 36, 36,
+   44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 87, 43, 43, 43,
+   83, 43, 85, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
+   70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
+   36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 84, 84, 88,
+   43, 87, 85, 85, 61, 44, 44, 44, 36, 70, 83,163, 64, 44, 44, 44,
+   27, 27, 89, 67, 67, 67, 56, 20,162, 67, 67, 67, 67, 67, 67, 67,
+   67, 44, 44, 44, 44, 44, 44, 91,103,103,103,103,103,103,103,178,
+    2,  2, 64, 44, 44, 44, 44, 44, 65, 65, 65, 65, 68, 44, 44, 44,
+   43, 43, 60, 44, 44, 44, 44, 44, 43, 43, 43, 60,  2,  2, 67, 67,
+   40, 40, 95, 44, 44, 44, 44, 44,  7,  7,  7,  7,  7,176, 27, 27,
+   27, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 44, 44, 62, 36,
+   27, 27, 27, 30,  2, 64, 44, 44, 36, 36, 36, 36, 36, 61, 44, 57,
+   92, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+   84, 84, 84, 84, 44, 44, 44, 57, 43, 74, 40, 40, 40, 40, 40, 40,
+   40, 86, 44, 44, 44, 44, 44, 44, 36, 61, 44, 44, 44, 44, 44, 44,
+   44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60,
+   65, 65, 44, 44, 44, 44, 44, 44, 67, 67, 67, 90, 55, 67, 67, 67,
+   67, 67,182, 85, 43, 67,182, 84, 84,183, 65, 65, 65, 82, 43, 43,
+   43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67,
+   67, 67, 67, 67, 90, 44, 44, 44, 67, 43, 76, 44, 44, 44, 44, 44,
+   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
+   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+   16, 16,108, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
+   11, 11, 11, 16, 16,147,147, 16, 16, 16,147, 16, 16, 16, 16, 16,
+   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
+   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
+   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
+   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
+    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
+   43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
+   67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
+   43, 43, 43, 80, 43, 43, 43, 43, 43, 43, 43, 43, 80, 57, 43, 43,
+   43, 57, 80, 43, 43, 80, 44, 44, 43, 43, 43, 74, 40, 40, 40, 44,
+    7,  7,  7,  7,  7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 43, 43,
+    7,  7,  7,  7,  7, 44, 44, 94, 36, 36, 61,176, 27, 27, 27, 27,
+   43, 43, 43, 80, 44, 44, 44, 44, 16, 16, 43, 43, 43, 74, 44, 44,
+   27, 27, 27, 27, 27, 27,158, 27,184, 27, 98, 44, 44, 44, 44, 44,
+   27, 27, 27, 27, 27, 27, 27,158, 27, 27, 27, 27, 27, 27, 27, 44,
+   36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36,
+   36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36,
+   62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36,
+   36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36,
+   62, 36, 62, 36, 36, 62, 36, 36,  8, 44, 44, 44, 44, 44, 44, 44,
+   55, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90, 44,
+   44, 44, 44, 67, 67, 67, 67, 67, 67, 90, 44, 44, 44, 44, 44, 44,
+   67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41,
+   67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 44,
+   67, 67, 67, 67, 67, 67, 55, 67, 67, 55, 67, 90, 44, 67, 67, 67,
+   67, 90, 55, 67, 67, 90, 44, 67, 67, 67, 67, 67, 67, 90, 55, 67,
+   67, 67, 44, 44, 67, 90, 44, 44, 36, 44, 44, 44, 44, 44, 44, 44,
+   79, 44, 44, 44, 44, 44, 44, 44, 65, 65, 65, 65, 65, 65, 65, 65,
+  166,166,166,166,166,166,166, 44,166,166,166,166,166,166,166,  0,
+    0,  0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13,
+   25, 25, 25, 21, 21,  9,  9,  9,  9, 22, 21, 18, 24, 16, 24,  5,
+    5,  5,  5, 22, 25, 18, 25,  0, 23, 23, 26, 21, 24, 26,  7, 20,
+   25,  1, 26, 24, 26, 25, 15, 15, 24, 15,  7, 19, 15, 21,  9, 25,
+    9,  5,  5, 25,  5,  9,  5,  7,  7,  7,  9,  8,  8,  5,  7,  5,
+    6,  6, 24, 24,  6, 24, 12, 12,  2,  2,  6,  5,  9, 21,  9,  2,
+    2,  9, 25,  9, 26, 12, 11, 11,  2,  6,  5, 21, 17,  2,  2, 26,
+   26, 23,  2, 12, 17, 12, 21, 12, 12, 21,  7,  2,  2,  7,  7, 21,
+   21,  2,  1,  1, 21, 23, 26, 26,  1,  2,  6,  7,  7, 12, 12,  7,
+   21,  7, 12,  1, 12,  6,  6, 12, 12, 26,  7, 26, 26,  7,  2,  1,
+   12,  2,  6,  2,  1, 12, 12, 10, 10, 10, 10, 12, 21,  6,  2, 10,
+   10,  2, 15, 26, 26,  2,  2, 21,  7, 10, 15,  7,  2, 23, 21, 26,
+   10,  7, 21, 15, 15,  2, 17,  7, 29,  7,  7, 22, 18,  2, 14, 14,
+   14,  7, 17, 21,  7,  6, 11,  2,  5,  2,  5,  6,  8,  8,  8, 24,
+    5, 24,  2, 24,  9, 24, 24,  2, 29, 29, 29,  1, 17, 17, 20, 19,
+   22, 20, 27, 28,  1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22,
+   18, 21, 21, 29, 15,  6, 18,  6, 12, 11, 11, 12,  9, 26, 26,  9,
+   26,  5,  5, 26, 14,  9,  5, 14, 14, 15, 25, 26, 26, 22, 18, 26,
+   18, 25, 18, 22,  5, 12,  2,  5, 22, 21, 26,  6,  7, 14, 17, 22,
+   18, 18, 26, 14, 17,  6, 14,  6, 12, 24, 24,  6, 26, 15,  6, 21,
+   11, 21, 24,  9, 23, 26, 10, 21,  6, 10,  4,  4,  3,  3,  7, 25,
+   21, 22, 17, 16, 16, 22, 16, 16, 25, 17, 25,  2, 25, 24, 23,  2,
+    2, 15, 12, 15, 14,  2, 21, 14,  7, 15, 21,  1, 26, 10, 10,  1,
+   23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12,
+   13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,
+    0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+   33,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 34,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   35,  0,  0,  0,  0,  0,  0,  0,  0,  0, 36, 37,  0,  0,  0,  0,
+    0,  0, 38, 39,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    1,  2,  3,  4,  0,  0,  0,  0,  0,  0,  0,  0,  5,  0,  0,  0,
+    0,  0,  0,  0,  6,  7,  8,  0,  9,  0, 10, 11,  0,  0, 12, 13,
+   14, 15, 16,  0,  0,  0,  0, 17, 18, 19, 20,  0,  0,  0, 21, 22,
+    0, 23, 24,  0,  0, 23, 25, 26,  0, 23, 25,  0,  0, 23, 25,  0,
+    0, 23, 25,  0,  0,  0, 25,  0,  0,  0, 27,  0,  0, 23, 25,  0,
+    0, 28, 25,  0,  0,  0, 29,  0,  0, 30, 31,  0,  0, 32, 33,  0,
+   34, 35,  0, 36, 37,  0, 38,  0,  0, 39,  0,  0, 40,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0, 41,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   42, 42,  0,  0,  0,  0, 43,  0,  0,  0,  0,  0,  0, 44,  0,  0,
+    0, 45,  0,  0,  0,  0,  0,  0, 46,  0,  0, 47,  0, 48,  0,  0,
+    0, 49, 50, 51,  0, 52,  0, 53,  0, 54,  0,  0,  0,  0, 55, 56,
+    0,  0,  0,  0,  0,  0, 57, 58,  0,  0,  0,  0,  0,  0, 59, 60,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 61,
+    0,  0,  0, 62,  0,  0,  0, 63,  0, 64,  0,  0, 65,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 66, 67,  0,  0, 68,
+    0,  0,  0,  0,  0,  0,  0,  0, 69,  0,  0,  0,  0,  0, 50, 70,
+    0, 71, 72,  0,  0, 73, 74,  0,  0,  0,  0,  0,  0, 75, 76, 77,
+    0,  0,  0,  0,  0,  0,  0, 25,  0,  0,  0,  0,  0,  0,  0,  0,
+   78,  0,  0,  0,  0,  0,  0,  0,  0, 79,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 80,  0,  0,  0,  0,  0,  0,  0, 81,
+    0,  0,  0, 82,  0,  0,  0,  0, 83, 84,  0,  0,  0,  0,  0, 85,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0, 86,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0, 87,  0,  0,  0,  0,  0,  0,  0, 69, 62,  0, 88,  0,  0,
+   89, 90,  0, 73,  0,  0, 91,  0,  0, 92,  0,  0,  0,  0,  0, 93,
+    0, 94, 25, 95,  0,  0,  0,  0,  0,  0, 96,  0,  0,  0, 97,  0,
+    0,  0,  0,  0,  0, 62, 98,  0,  0, 62,  0,  0,  0, 99,  0,  0,
+    0,100,  0,  0,  0,  0,  0,  0,  0, 88,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 74,  0, 42,101,  0,102,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0,  0,  0,  0,
+    0,  0,103,  0,104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,
+    0,106,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,108,109,110,  0,  0,  0,  0,111,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,112,113,  0,  0,  0,  0,  0,  0,
+    0,106,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,114,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,115,  0,
+    0,  0,116,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,  4,  8,  9, 10,
+    1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1,  0,  0,  0,  0,
+   19,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 21, 22,  1,
+   23,  4, 21, 24, 25, 26, 27, 28, 29, 30,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36,
+    0,  0,  0,  0, 37,  0,  0,  0,  0,  0,  0,  0,  0, 38,  1, 39,
+   14, 39, 40, 41,  0,  0,  0,  0,  0,  0,  0,  0, 42,  0,  0,  0,
+    0,  0,  0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0,  0,  0,
+    0,  0, 19,  1, 21,  0,  0, 47,  0,  0,  0,  0,  0, 38, 48,  1,
+    1, 49, 49, 50,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 51,  0,
+    0,  0,  0,  0, 52,  1,  1,  1, 53, 21, 43, 54, 55, 21, 35,  1,
+    0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0, 57, 58, 59,  0,  0,
+    0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 60,
+    0,  0,  0, 57,  0, 61,  0,  0,  0,  0,  0,  0,  0,  0, 62, 63,
+    0,  0, 64,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 65,  0,
+    0,  0, 66,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 67,  0,
+    0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,  0,
+    0,  0,  0,  0,  0, 70, 71,  0,  0,  0,  0,  0, 72, 73, 74, 75,
+   76, 77,  0,  0,  0,  0,  0,  0,  0, 78,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 79, 80,  0,  0,  0,  0, 47,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 49,  0,  0,  0,  0,  0, 63,  0,  0,
+    0,  0,  0,  0, 64,  0,  0, 81,  0,  0, 82,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 83,  0,  0,  0,  0,  0,  0, 19, 84,  0,
+   63,  0,  0,  0,  0, 49,  1, 85,  0,  0,  0,  0,  1, 54, 15, 41,
+    0,  0,  0,  0,  0, 56,  0,  0,  0, 63,  0,  0,  0,  0,  0,  0,
+    0,  0, 19, 10,  1,  0,  0,  0,  0,  0, 86,  0,  0,  0,  0,  0,
+    0, 87,  0,  0, 86,  0,  0,  0,  0,  0,  0,  0,  0, 79,  0,  0,
+    0,  0,  0,  0, 88,  9, 12,  4, 89,  8, 90, 47,  0, 59, 50,  0,
+   21,  1, 21, 91, 92,  1,  1,  1,  1,  1,  1,  1,  1, 93, 94, 95,
+    0,  0,  0,  0, 96,  1, 97, 59, 81, 98, 99,  4, 59,  0,  0,  0,
+    0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,
+    1,  1,  1,  1,  1,  1,  1,  1,  0,  0,100,101,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,102,  0,  0,  0,  0, 19,  0,  1,  1, 50,
+    0,  0,  0,  0,  0,  0,  0, 38,  0,  0,  0,  0, 50,  0,  0,  0,
+    0, 64,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1, 50,  0,  0,  0,
+    0,  0, 52, 69,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0,
+    0,  0,  0,  0, 79,  0,  0,  0, 63,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,103,104, 59, 38, 81,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 64,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,
+    1, 14,  4, 12,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 47,
+   84,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 88,  0,
+    0,  0,  0,106,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,107, 62,
+    0,108,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
+    0,109, 14, 54, 84,  0,  0,  0,  0,  0,  0,  0,  0,  0,110,  0,
+   88,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62, 63,  0,  0,
+   63,  0, 87,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,110,  0,  0,
+    0,  0,111,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 79, 56,
+    0, 38,  1, 59,  1, 59,  0,  0, 64, 87,  0,  0,  0,  0,  0, 60,
+  112,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,112,  0,  0,  0,  0, 62,  0,  0,  0,  0,  0,
+    0, 62,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 57,  0,
+   87,113,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,
+    0,  0,  0,  0,  8, 90,  0,  0,  0,  0,  0,  0,  1, 88,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,114,  0,115,116,117,118,  0, 52,  4,
+  119, 49, 23,  0,  0,  0,  0,  0,  0,  0, 38, 50,  0,  0,  0,  0,
+   38, 59,  0,  0,  0,  0,  0,  0,  1, 88,  1,  1,  1,  1, 39,  1,
+   48,103, 88,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,
+    0,  0,  0,  0,  4,119,  0,  0,  0,  1,120,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,230,230,230,230,230,232,220,220,220,220,232,216,
+  220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
+    1,  1,  1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,
+  220,220,230,230,230,220,220,  0,230,230,230,220,220,220,220,230,
+  232,220,220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,
+    0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220,
+  230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
+   21, 22,  0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,
+    0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,
+  220,230,230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,
+  230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,
+  220,220,230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,
+  230,230,  0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,
+    0,  0,  0,220,230,230,  0,220,230,220,220,220, 27, 28, 29,230,
+    7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,
+    0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,
+    0,  0,  9,  0,103,103,  9,  0,107,107,107,107,118,118,  9,  0,
+  122,122,122,122,220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,
+    0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,
+  130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,
+    0,  9,  9,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,
+  220,  0,  0,  0,230,  0,  0,220,  0,  0,  9,  9,  0,  0,  7,  0,
+  230,230,230,  0,230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,
+  202,230,230,230,230,230,232,228,228,220,  0,230,233,220,230,220,
+  230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,
+    0,  0,218,228,232,222,224,224,  0,  8,  8,  0,230,  0,230,230,
+  220,  0,  0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,
+    0,230,220,  0,  0,  0,220,220,  0,  9,  7,  0,  0,  7,  9,  0,
+    0,  0,  9,  7,  9,  9,  0,  0,  0,  0,  1,  0,  0,216,216,  1,
+    1,  1,  0,  0,  0,226,216,216,216,216,216,  0,220,220,220,  0,
+  230,230,  7,  0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
+   17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17,237,  0,  1,  2,  2,  0,  3,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    5,  0,  0,  0,  0,  6,  7,  8,  9,  0,  0,  0, 10, 11, 12, 13,
+   14, 15, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,
+    0,  0, 21, 22,  0,  0,  0,  0, 23, 24, 25, 26,  0, 27,  0, 28,
+   29, 30, 31, 32,  0,  0,  0,  0,  0,  0,  0, 33, 34, 35,  0,  0,
+    0,  0,  0,  0, 36,  0,  0,  0,  0,  0,  0,  0,  0,  0, 37, 38,
+    0,  0,  0,  0,  1,  2, 39, 40,  0,  1,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,
+    0,  0,  3,  4,  0,  0,  5,  0,  0,  0,  6,  0,  0,  0,  0,  0,
+    0,  0,  7,  1,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,
+    0,  0, 10,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0, 10,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0, 11, 12,
+    0, 13,  0, 14, 15, 16,  0,  0,  0,  0,  0,  1, 17, 18,  0, 19,
+    7,  1,  0,  0,  0, 20, 20,  7, 20, 20, 20, 20, 20, 20, 20,  8,
+   21,  0, 22,  0,  7, 23, 24,  0, 20, 20, 25,  0,  0,  0, 26, 27,
+    1,  7, 20, 20, 20, 20, 20,  1, 28, 29, 30, 31,  0,  0, 20,  0,
+    0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0, 20, 20,
+   20,  1,  0,  0,  8, 21, 32,  4,  0, 10,  0, 33,  7, 20, 20, 20,
+    0,  0,  0,  0,  8, 34, 34, 35, 36, 34, 37,  0, 38,  1, 20, 20,
+    0,  0, 39,  0,  1,  1,  0,  8, 21,  1, 20,  0,  0,  0,  1,  0,
+    0, 40,  1,  1,  0,  0,  8, 21,  0,  1,  0,  1,  0,  1,  0,  0,
+    0,  0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  7, 20, 41,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  0, 42, 43, 44,  0, 45,
+    0,  8, 21,  0,  0,  0,  0,  0,  0,  0,  0, 46,  7,  1, 10,  1,
+    0,  0,  0,  1, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0, 20, 20,
+    1, 20, 20,  0,  0,  0,  0,  0,  0,  0, 26, 21,  0,  1,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3, 47, 48,  0,  0,  0,
+    0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  9, 10, 11, 12, 12, 12, 12, 13, 14,
+   14, 14, 14, 15, 16, 17, 18, 19, 20, 14, 21, 14, 22, 14, 14, 14,
+   14, 23, 24, 24, 25, 26, 14, 14, 14, 14, 27, 28, 14, 14, 29, 30,
+   31, 32, 33, 34,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  7, 35,  7, 36, 37,  7, 38,  7,  7,
+    7, 39, 14, 40, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 41,  0,  0,  1,  2,  2,  2,  3,  4,  5,  6,  7,
+    8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+   24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37,
+   37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+   51, 52,  2,  2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59,
+   59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65,
+   66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 79, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 82,
+   83, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97, 97, 97, 70, 70, 98, 99,100,101,102,102,
+  103,104,105,106,107,108,109,110,111,112, 97,113,114,115,116,117,
+  118, 97,119,119,120, 97,121,122,123,124,125,126,127,128,129,130,
+  131, 97,132, 97,133,134,135,136,137,138,139,140,141, 97,142,143,
+   97,144,145,146,147, 97,148,149, 97,150,151,152, 97, 97,153,154,
+  155,156, 97,157, 97,158,159,159,159,159,159,159,159,160,161,159,
+  162, 97, 97, 97, 97, 97,163,163,163,163,163,163,163,163,164, 97,
+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,165,165,
+  165,165,166, 97, 97, 97,167,167,167,167,168,169,170,171, 97, 97,
+   97, 97,172,173,174,175,176,176,176,176,176,176,176,176,176,176,
+  176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
+  176,176,176,176,176,177,176,176,176,176,176,178, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97,179,180,181, 32, 32,182, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,183,184,
+   97, 97, 97, 97, 97, 97, 59,185,186,187,188,189,190, 97,191,192,
+  193, 59, 59,194, 59,195,196,196,196,196,196,197, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97,198, 97,199, 97, 97,200, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97,201,202,203, 97, 97, 97, 97, 97,204,205,
+  206, 97,207,208, 97, 97,209,210,211,212,213, 97, 59, 59, 59, 59,
+   59, 59, 59,214,215,216,217,218,219,220,221,222, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70,223, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70,224, 70,225, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+   70, 70, 70,226, 70, 70, 70, 70, 70, 70, 70, 70, 70,227, 97, 97,
+   97, 97, 97, 97, 97, 97, 70, 70, 70, 70,228, 97, 97, 97, 97, 97,
+   97, 97, 97, 97, 97, 97,229, 97,230,231,  0,  1,  2,  2,  0,  1,
+    2,  2,  2,  3,  4,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0, 19, 19,
+   19, 19, 19, 19, 19,  0, 19,  0,  0,  0,  0,  0,  0,  0, 19, 19,
+   19, 19, 19,  0,  0,  0,  0,  0, 26, 26,  0,  0,  0,  0,  1,  1,
+    1,  1,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,  2,  2,
+    9,  9,  9,  9,  0,  9,  2,  2,  2,  2,  9,  0,  9,  0,  9,  9,
+    9,  2,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    2,  9,  9,  9,  9,  9,  9,  9, 55, 55, 55, 55, 55, 55, 55, 55,
+   55, 55, 55, 55, 55, 55,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+    6,  6,  6,  1,  1,  6,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  4,  0,
+    4,  2,  2,  4,  4,  4,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2, 14, 14,
+   14,  2,  2,  2,  2, 14, 14, 14, 14, 14, 14,  2,  2,  2,  3,  3,
+    3,  3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  2,  3,  0,  0,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  1,
+    1,  1,  1,  1,  3,  3,  1,  3,  3,  3,  3,  3,  3,  3, 37, 37,
+   37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37,
+   37,  2,  2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+    2,  2,  2,  2,  2,  2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+   64,  2,  2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+   90, 90, 90, 90,  2,  2, 90, 90, 90, 90, 90, 90, 90,  2, 95, 95,
+   95, 95, 95, 95, 95, 95, 95, 95, 95, 95,  2,  2, 95,  2, 37, 37,
+   37,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,
+    3,  3,  3,  3,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,
+    0,  3,  3,  3,  3,  3,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,
+    1,  1,  1,  7,  7,  7,  7,  7,  7,  7,  0,  0,  7,  7,  5,  5,
+    5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,
+    2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
+    5,  5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,
+    2,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,
+    2,  2,  2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,
+    5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11,
+   11, 11,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
+    2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,
+   11, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
+    2,  2, 11,  2, 11, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,
+    2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,
+    2,  2,  2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,  2, 10,
+   10, 10,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,
+    2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,
+   10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10, 10,
+    2,  2, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,
+    2,  2,  2,  2,  2,  2, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10,
+    2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21,
+   21, 21,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
+    2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
+   21, 21, 21, 21, 21, 21, 21,  2, 21, 21,  2, 21, 21, 21, 21, 21,
+    2,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,
+    2,  2,  2,  2, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21,
+   21, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
+   22,  2,  2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22,
+   22,  2, 22,  2, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22,  2,
+    2,  2,  2,  2,  2, 22,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
+   22,  2,  2,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+   23, 23, 23,  2, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23,
+    2,  2,  2, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,
+    2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2,  2,  2,  2, 23, 23,
+   23, 23,  2,  2, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 16, 16,
+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2,
+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16,
+    2,  2, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,
+    2,  2,  2, 16, 16,  2,  2,  2,  2,  2,  2,  2, 16,  2, 16, 16,
+   16, 16,  2,  2, 16, 16,  2, 16, 16,  2,  2,  2,  2,  2, 20, 20,
+   20, 20,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2, 20, 20, 20,  2,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2,
+    2,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 20, 20,  2,  2,
+   36, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36,
+    2, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,  2,
+   36,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,
+    2,  2,  2,  2, 36, 36,  2,  2, 36, 36, 36,  2,  2,  2,  2, 24,
+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+   24,  2,  2,  2,  2,  0, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18,
+   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18,
+   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,
+   18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18,
+    2,  2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25,  2, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,  2,  2,  2, 25, 25,
+   25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25,  0,  0,  0,  0, 25,
+   25,  2,  2,  2,  2,  2, 33, 33, 33, 33, 33, 33, 33, 33,  8,  8,
+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  8,  2,  2,
+    2,  2,  2,  8,  2,  2,  8,  8,  8,  0,  8,  8,  8,  8, 12, 12,
+   12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30,  2,
+   30, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,  2, 30, 30,
+   30,  2,  2, 30, 30, 30, 30, 30, 30, 30, 30,  2,  2,  2, 30, 30,
+    2,  2,  2,  2,  2,  2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+   29, 29, 29, 29,  2,  2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35,  2,
+    2,  2,  2,  2,  2,  2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+   45, 45, 45,  2, 45, 45, 45, 45, 45, 45, 45,  2,  2,  2, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,  0,  0,  2, 43, 43,
+   43, 43, 43, 43, 43, 43, 43, 43, 43, 43,  2,  2,  2,  2, 46, 46,
+   46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,  2, 46, 46, 46,  2,
+   46, 46,  2,  2,  2,  2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+   31, 31, 31, 31,  2,  2, 31, 31,  2,  2,  2,  2,  2,  2, 32, 32,
+    0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 32, 32, 32,  2, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32,  2,
+    2,  2,  2,  2,  2,  2, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28,
+   28, 28, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+   48, 48, 48, 48, 48,  2, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,
+    2,  2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+   52, 52, 52, 52,  2,  2, 52, 52, 52, 52, 52,  2,  2,  2, 58, 58,
+   58, 58, 58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58,
+    2,  2,  2,  2,  2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54,
+   54, 54, 54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91,
+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91,
+   91, 91, 91,  2,  2, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91,
+   91, 91, 91, 91,  2,  2,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62,
+   62, 62, 62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2,  2, 62, 62,
+   62, 62, 62,  2,  2,  2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93,
+   93, 93, 93, 93, 93, 93, 93, 93, 93, 93,  2,  2,  2,  2,  2,  2,
+    2,  2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70,  2,  2,
+    2, 70, 70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73,
+   73, 73, 73, 73, 73, 73,  6,  2,  2,  2,  2,  2,  2,  2,  8,  8,
+    8,  2,  2,  8,  8,  8,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,
+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,
+    0,  0,  1,  0,  0,  0,  1,  1,  0,  2,  2,  2,  2,  2, 19, 19,
+   19, 19, 19, 19,  9,  9,  9,  9,  9,  6, 19, 19, 19, 19, 19, 19,
+   19, 19, 19,  9,  9,  9,  9,  9, 19, 19, 19, 19,  9,  9,  9,  9,
+    9, 19, 19, 19, 19, 19,  6, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19, 19,  9,  1,  1,  2,  1,  1,  1,  1,  1,  9,  9,
+    9,  9,  9,  9,  2,  2,  2,  9,  2,  9,  2,  9,  2,  9,  9,  9,
+    9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
+    9,  9,  2,  9,  9,  9,  2,  2,  9,  9,  9,  2,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  2,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,
+    0,  0,  0,  2,  0,  0,  0, 19,  2,  2,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0,  0,  0,  2, 19, 19,
+   19, 19, 19,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  2,  0,  0,
+    0,  0,  0,  0,  9,  0,  0,  0, 19, 19,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 19,  0, 19,  0,  0,  0,  2,  2,  2,  2,  0,  0,
+    0,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,
+    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2, 56, 56,
+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,  2, 55, 55,
+   55, 55,  2,  2,  2,  2,  2, 55, 55, 55, 55, 55, 55, 55, 61, 61,
+   61, 61, 61, 61, 61, 61,  2,  2,  2,  2,  2,  2,  2, 61, 61,  2,
+    2,  2,  2,  2,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    2, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13,
+   13, 13, 13, 13,  2,  2,  0,  0,  0,  0,  2,  2,  2,  2,  0,  0,
+    0,  0,  0, 13,  0, 13,  0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    1,  1,  1,  1, 12, 12, 13, 13, 13, 13,  0,  0,  0,  0,  2, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17,  0,  0, 17, 17, 17,  2,  2,  2,  2,  2, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12,  2, 26, 26, 26,  2,  2,  2,  2,  2, 12, 12,
+   12, 12, 12, 12, 12,  0, 17, 17, 17, 17, 17, 17, 17,  0, 39, 39,
+   39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39,
+   39, 39, 39, 39, 39,  2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77,
+   77, 77, 77, 77, 77, 77, 77, 77, 77, 77,  2,  2,  2,  2, 79, 79,
+   79, 79, 79, 79, 79, 79,  0,  0, 19, 19, 19, 19, 19, 19,  0,  0,
+    0, 19, 19, 19, 19, 19,  2,  2, 19, 19, 19, 19, 19,  2,  2,  2,
+    2,  2,  2,  2,  2, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+   60, 60,  2,  2,  2,  2,  0,  0,  2,  2,  2,  2,  2,  2, 65, 65,
+   65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+   75, 75, 75, 75,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75,
+    2,  2,  2,  2,  2,  2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+   69, 69, 69, 69,  0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+   74, 74,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 74, 12, 12,
+   12, 12, 12,  2,  2,  2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+   84, 84, 84, 84,  2,  0, 84, 84,  2,  2,  2,  2, 84, 84, 33, 33,
+   33, 33, 33, 33, 33,  2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+   68, 68, 68, 68, 68,  2, 68, 68, 68, 68, 68, 68,  2,  2, 68, 68,
+    2,  2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+   92,  2,  2,  2,  2,  2,  2,  2,  2, 92, 92, 92, 92, 92, 87, 87,
+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,  2,  2, 30,
+   30, 30, 30, 30, 30,  2, 19, 19, 19,  0, 19, 19, 19, 19, 19, 19,
+   19, 19, 19,  9, 19, 19, 87, 87, 87, 87, 87, 87,  2,  2, 87, 87,
+    2,  2,  2,  2,  2,  2, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,
+    2, 12, 12, 12, 12, 12, 13, 13,  2,  2,  2,  2,  2,  2, 19, 19,
+   19, 19, 19, 19, 19,  2,  2,  2,  2,  4,  4,  4,  4,  4,  2,  2,
+    2,  2,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2, 14, 14,
+   14, 14, 14,  2, 14,  2, 14, 14,  2, 14, 14,  2, 14, 14,  3,  3,
+    2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  0,  0,  2,  2,
+    3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  6,  6,  0,  0,
+    0,  2,  0,  0,  0,  0,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17,
+   17, 17, 17, 17,  0,  0,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2,
+   12, 12, 12,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49,
+   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
+   49, 49, 49, 49, 49,  2, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49,
+   49, 49, 49, 49,  2,  2, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,
+    0,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2,  2,  0,  9,  2,
+    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  1,  2,  2, 71, 71,
+   71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67,
+   67, 67, 67, 67, 67, 67, 67,  2,  2,  2,  2,  2,  2,  2,  1,  0,
+    0,  0,  0,  0,  0,  0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+   42, 42,  2,  2,  2,  2,  2,  2,  2,  2,  2, 42, 42, 42, 41, 41,
+   41, 41, 41, 41, 41, 41, 41, 41, 41,  2,  2,  2,  2,  2,118,118,
+  118,118,118,118,118,118,118,118,118,  2,  2,  2,  2,  2, 53, 53,
+   53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59,  2,  2,  2,  2, 59, 59,
+   59, 59, 59, 59,  2,  2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51,
+   51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+   50, 50, 50, 50,  2,  2, 50, 50,  2,  2,  2,  2,  2,  2,135,135,
+  135,135,135,135,135,135,135,135,135,135,  2,  2,  2,  2,106,106,
+  106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,
+  104,104,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,104,110,110,
+  110,110,110,110,110,110,110,110,110,110,110,110,110,  2,110,110,
+  110,110,110,110,  2,  2, 47, 47, 47, 47, 47, 47,  2,  2, 47,  2,
+   47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+   47, 47, 47, 47,  2, 47, 47,  2,  2,  2, 47,  2,  2, 47, 81, 81,
+   81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,  2, 81,120,120,
+  120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116,
+  116,116,116,116,116,  2,  2,  2,  2,  2,  2,  2,  2,116,128,128,
+  128,128,128,128,128,128,128,128,128,  2,128,128,  2,  2,  2,  2,
+    2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+   66, 66,  2,  2,  2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+    2,  2,  2,  2,  2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97,
+   97, 97, 97, 97, 97, 97,  2,  2,  2,  2, 97, 97, 97, 97,  2,  2,
+   97, 97, 97, 97, 97, 97, 57, 57, 57, 57,  2, 57, 57,  2,  2,  2,
+    2,  2, 57, 57, 57, 57, 57, 57, 57, 57,  2, 57, 57, 57,  2, 57,
+   57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+   57, 57, 57, 57,  2,  2, 57, 57, 57,  2,  2,  2,  2, 57, 57,  2,
+    2,  2,  2,  2,  2,  2, 88, 88, 88, 88, 88, 88, 88, 88,117,117,
+  117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112,
+  112,112,112,112,112,  2,  2,  2,  2,112,112,112,112,112, 78, 78,
+   78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,  2,  2,  2, 78,
+   78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+   83, 83, 83, 83,  2,  2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+   82,  2,  2,  2,  2,  2,122,122,122,122,122,122,122,122,122,122,
+    2,  2,  2,  2,  2,  2,  2,122,122,122,122,  2,  2,  2,  2,122,
+  122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89,  2,
+    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,130,130,130,130,
+  130,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,130,130,  3,  3,
+    3,  3,  3,  3,  3,  2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+   94, 94, 94, 94,  2,  2,  2,  2, 94, 94, 94, 94, 94, 94,  2,  2,
+    2,  2,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,
+  101,101,101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,
+    2,  2,  2,  2,  2,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96,  2,111,111,
+  111,111,111,111,111,111,111,111,111,111,111,111,111,  2,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,  2,  2,  2, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,108,108,
+  108,108,108,108,108,108,108,108,  2,108,108,108,108,108,108,108,
+  108,108,108,108,108,  2,129,129,129,129,129,129,129,  2,129,  2,
+  129,129,129,129,  2,129,129,129,129,129,129,129,129,129,129,129,
+  129,129,129,129,  2,129,129,129,  2,  2,  2,  2,  2,  2,109,109,
+  109,109,109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,
+    2,  2,  2,  2,  2,  2,107,107,107,107,  2,107,107,107,107,107,
+  107,107,107,  2,  2,107,107,  2,  2,107,107,107,107,107,107,107,
+  107,107,107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,
+  107,107,  2,107,107,107,107,107,  2,  1,107,107,107,107,107,  2,
+    2,107,107,107,  2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,
+    2,  2,  2,107,107,107,107,107,107,107,  2,  2,107,107,107,107,
+  107,107,107,  2,  2,  2,137,137,137,137,137,137,137,137,137,137,
+    2,137,  2,137,137,137,124,124,124,124,124,124,124,124,124,124,
+    2,  2,  2,  2,  2,  2,123,123,123,123,123,123,123,123,123,123,
+  123,123,123,123,  2,  2,114,114,114,114,114,114,114,114,114,114,
+  114,114,114,  2,  2,  2,114,114,  2,  2,  2,  2,  2,  2, 32, 32,
+   32, 32, 32,  2,  2,  2,102,102,102,102,102,102,102,102,102,  2,
+    2,  2,  2,  2,  2,  2,102,102,  2,  2,  2,  2,  2,  2,126,126,
+  126,126,126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,
+  126,126,  2,  2,  2,  2,  4,  4,  4,  4,  2,  2,  2,  2,125,125,
+  125,125,125,125,125,125,125,125,125,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,125,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  2,  2,  2,  7,  7,  7,  2,  2,  2,  2,  2,121,121,
+  121,121,121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,133,133,
+  133,133,133,133,133,133,133,  2,133,133,133,133,133,133,133,133,
+  133,133,133,133,133,  2,133,133,133,133,133,133,  2,  2,133,133,
+  133,133,133,  2,  2,  2,134,134,134,134,134,134,134,134,  2,  2,
+  134,134,134,134,134,134,  2,134,134,134,134,134,134,134,134,134,
+  134,134,134,134,134,  2,  8,  8,  8,  8,  8,  8,  8,  2,  8,  8,
+    2,  8,  8,  8,  8,  8,  2,  2,  8,  2,  8,  8,  2,  8,  8,  8,
+    2,  2,  2,  2,  2,  2,  9,  9,  9,  9,  9,  9,  2,  9,  9,  2,
+    9,  9,  9,  9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2, 22, 22,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63,
+   63, 63, 63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63,
+   63, 63, 63, 63, 63,  2, 63, 63, 63, 63, 63,  2,  2,  2, 63, 63,
+   63, 63,  2,  2,  2,  2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+   80, 80, 80, 80, 80,  2, 80,  2,  2,  2,  2,  2,  2,  2,127,127,
+  127,127,127,127,127,127,127,127,127,127,127,127,127,  2, 79,  2,
+    2,  2,  2,  2,  2,  2,115,115,115,115,115,115,115,115,115,115,
+  115,115,115,115,115,  2,115,115,  2,  2,  2,  2,115,115,103,103,
+  103,103,103,103,103,103,103,103,103,103,103,103,  2,  2,119,119,
+  119,119,119,119,119,119,119,119,119,119,119,119,  2,  2,119,119,
+    2,119,119,119,119,119,  2,  2,  2,  2,  2,119,119,119, 11, 11,
+   11,  2,  2,  2,  2,  2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+   99,  2,  2,  2,  2, 99,  2,  2,  2,  2,  2,  2,  2, 99,136, 12,
+    0,  0,  2,  2,  2,  2,136,136,136,136,136,136,136,136,136,136,
+  136,  2,  2,  2,  2,  2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15,  2,  2,  2,  2,  2,  2,  2,  2,  2, 17, 17, 17, 17,105,105,
+  105,105,105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,
+  105,105,105,  2,  2,  2,105,  2,  2,  2,  2,  2,  2,  2,105,105,
+    2,  2,105,105,105,105,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
+    1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
+    1,  1,  1,  1,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+    0,  2,  2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
+    2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,
+    2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,  2,  2,  2,
+    0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,131,131,
+  131,131,131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,
+    2,131,131,131,131,131,  2,131,131,131,131,131,131,131, 56,  2,
+    2, 56, 56, 56, 56, 56, 56, 56,  2, 56, 56,  2, 56, 56, 56, 56,
+   56,  2,  2,  2,  2,  2, 13, 13, 13, 13, 13,  2,  2,  2, 13, 13,
+    2,  2,  2,  2, 13, 13, 14, 14,  2,  2,  2,  2,  2, 14,113,113,
+  113,113,113,113,113,113,113,113,113,113,113,  2,  2,113,113,113,
+  113,113,113,113,113,  2,132,132,132,132,132,132,132,132,132,132,
+  132,132,  2,  2,  2,  2,132,132,  2,  2,  2,  2,132,132,  0,  0,
+    0,  0,  0,  2,  2,  2,  3,  3,  3,  3,  2,  3,  3,  3,  2,  3,
+    3,  2,  3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,
+    3,  2,  2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,
+    2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,
+    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
+    3,  3,  2,  3,  3,  3,  2,  2,  2,  2,  2,  2,  0,  0, 15,  0,
+    0,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  0,  0, 13, 13,
+   13, 13, 13, 13, 13,  2, 13,  2,  2,  2,  2,  2,  2,  2,  2,  0,
+    2,  2,  2,  2,  2,  2, 16, 50, 84,118, 88, 89, 90, 85, 85, 85,
+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+   85, 85, 85, 85, 85, 91, 85, 85,220, 85, 85, 85, 85, 85, 85, 85,
+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+   94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+   85, 85, 85, 85, 85, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0,
+   13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26,
+   27, 28, 29, 30,  0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,
+    0,  0, 36, 37, 38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,
+    0,  0, 41, 42,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 43, 44,  0, 45,  0,  0,  0,  0,
+    0,  0, 46, 47,  0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,
+    0,  0, 53,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,
+    0,  0, 55,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,
+    0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63,
+   64, 65,  0,  0,  0,  0,  0,  0, 66,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+   97, 98, 99,100,101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,
+  106,  0,107,  0,  0,  0,108,  0,109,  0,110,  0,111,112,113,  0,
+  114,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,117,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,
+  123,124,125,126,  0,127,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,128,129,130,131,132,133,134,135,136,137,
+  138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
+  154,155,156,157,  0,  0,  0,158,159,160,161,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,162,
+  163,  0,  0,  0,  0,  0,  0,  0,164,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,165,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,166,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,167,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,169,  0,  0,  0,
+    0,170,171,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,172,173,174,175,176,177,178,179,180,181,
+  182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
+  198,199,200,201,202,203,204,205,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  1,  2,  3,  4,
+};
+static const uint16_t
+_hb_ucd_u16[8928] =
+{
+     0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
+    13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
+    13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
+    32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
+     9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
+    13,  13,  13,  42,   9,  43,  11,  11,  44,  45,  32,  46,  47,  48,  49,  50,
+    51,  52,  48,  48,  53,  32,  54,  55,  48,  48,  48,  48,  48,  56,  57,  58,
+    59,  60,  48,  32,  61,  48,  48,  48,  48,  48,  62,  63,  64,  48,  65,  66,
+    48,  67,  68,  69,  48,  70,  71,  72,  72,  72,  48,  73,  72,  74,  75,  32,
+    76,  48,  48,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
+    90,  83,  84,  91,  92,  93,  94,  95,  96,  97,  84,  98,  99, 100,  88, 101,
+   102,  83,  84, 103, 104, 105,  88, 106, 107, 108, 109, 110, 111, 112,  94, 113,
+   114, 115,  84, 116, 117, 118,  88, 119, 120, 115,  84, 121, 122, 123,  88, 124,
+   125, 115,  48, 126, 127, 128,  88, 129, 130, 131,  48, 132, 133, 134,  94, 135,
+   136,  48,  48, 137, 138, 139,  72,  72, 140,  48, 141, 142, 143, 144,  72,  72,
+   145, 146, 147, 148, 149,  48, 150, 151, 152, 153,  32, 154, 155, 156,  72,  72,
+    48,  48, 157, 158, 159, 160, 161, 162, 163, 164,   9,   9, 165,  11,  11, 166,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 167, 168,  48,  48,
+   167,  48,  48, 169, 170, 171,  48,  48,  48, 170,  48,  48,  48, 172, 173, 174,
+    48, 175,   9,   9,   9,   9,   9, 176, 177,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48, 178,  48, 179, 180,  48,  48,  48,  48, 181, 182,
+   183, 184,  48, 185,  48, 186, 183, 187,  48,  48,  48, 188, 189, 190, 191, 192,
+   193, 191,  48,  48, 194,  48,  48, 195, 196,  48, 197,  48,  48,  48,  48, 198,
+    48, 199, 200, 201, 202,  48, 203, 204,  48,  48, 205,  48, 206, 207, 208, 208,
+    48, 209,  48,  48,  48, 210, 211, 212, 191, 191, 213, 214,  72,  72,  72,  72,
+   215,  48,  48, 216, 217, 159, 218, 219, 220,  48, 221,  64,  48,  48, 222, 223,
+    48,  48, 224, 225, 226,  64,  48, 227, 228,   9,   9, 229, 230, 231, 232, 233,
+    11,  11, 234,  27,  27,  27, 235, 236,  11, 237,  27,  27,  32,  32,  32, 238,
+    13,  13,  13,  13,  13,  13,  13,  13,  13, 239,  13,  13,  13,  13,  13,  13,
+   240, 241, 240, 240, 241, 242, 240, 243, 244, 244, 244, 245, 246, 247, 248, 249,
+   250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 260,  72, 261, 262, 263,
+   264, 265, 266, 267, 268, 269, 270, 270, 271, 272, 273, 208, 274, 275, 208, 276,
+   277, 277, 277, 277, 277, 277, 277, 277, 278, 208, 279, 208, 208, 208, 208, 280,
+   208, 281, 277, 282, 208, 283, 284, 208, 208, 208, 285,  72, 286,  72, 269, 269,
+   269, 287, 208, 208, 208, 208, 288, 269, 208, 208, 208, 208, 208, 208, 208, 208,
+   208, 208, 208, 289, 290, 208, 208, 291, 208, 208, 208, 208, 208, 208, 292, 208,
+   208, 208, 208, 208, 208, 208, 293, 294, 269, 295, 208, 208, 296, 277, 297, 277,
+   298, 299, 277, 277, 277, 300, 277, 301, 208, 208, 208, 277, 302, 208, 208, 303,
+   208, 304, 208, 208, 208, 208, 208, 208,   9,   9, 305,  11,  11, 306, 307, 308,
+    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
+    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320,  72,  72,  72,
+   208, 321, 208, 208, 208, 208, 208, 322, 208, 208, 208, 208, 208, 323,  72, 324,
+   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 177,  48,  48,  48,  48, 330,
+   331,  48,  48, 136,  48,  48,  48,  48, 199, 332,  48,  71, 208, 208, 322,  48,
+   208, 333, 334, 208, 335, 336, 208, 208, 334, 208, 208, 336, 208, 208, 208, 208,
+    48,  48,  48, 198, 208, 208, 208, 208,  48,  48,  48,  48,  48,  48,  48,  72,
+    48, 337,  48,  48,  48,  48,  48,  48, 150, 208, 208, 208, 285,  48,  48, 227,
+   338,  48, 339,  72,  13,  13, 340, 341,  13, 342,  48,  48,  48,  48, 343, 344,
+    31, 345, 346, 347,  13,  13,  13, 348, 349, 350, 351, 352, 353,  72,  72, 354,
+   355,  48, 356, 357,  48,  48,  48, 358, 359,  48,  48, 360, 361, 191,  32, 362,
+    64,  48, 363,  48, 364, 365,  48, 150,  76,  48,  48, 366, 367, 368, 369, 370,
+    48,  48, 371, 372, 373, 374,  48, 375,  48,  48,  48, 376, 377, 378, 379, 380,
+   381, 382, 315,  11,  11, 383, 384,  11,  11,  11,  11,  11,  48,  48, 385, 191,
+    48,  48, 386,  48, 387,  48,  48, 205, 388, 388, 388, 388, 388, 388, 388, 388,
+   389, 389, 389, 389, 389, 389, 389, 389,  48,  48,  48,  48,  48,  48, 203,  48,
+    48,  48,  48,  48,  48, 206,  72,  72, 390, 391, 392, 393, 394,  48,  48,  48,
+    48,  48,  48, 395, 396, 397,  48,  48,  48,  48,  48, 398,  72,  48,  48,  48,
+    48, 399,  48,  48, 400,  72,  72, 401,  32, 402,  32, 403, 404, 405, 406, 407,
+    48,  48,  48,  48,  48,  48,  48, 408, 409,   2,   3,   4,   5, 410, 411, 412,
+    48, 413,  48, 199, 414, 415, 416, 417, 418,  48, 171, 419, 203, 203,  72,  72,
+    48,  48,  48,  48,  48,  48,  48,  71, 420, 269, 269, 421, 270, 270, 270, 422,
+   423, 324, 424,  72,  72, 208, 208, 425,  72,  72,  72,  72,  72,  72,  72,  72,
+    48, 150,  48,  48,  48, 100, 426, 427,  48,  48, 428,  48, 429,  48,  48, 430,
+    48, 431,  48,  48, 432, 433,  72,  72,   9,   9, 434,  11,  11,  48,  48,  48,
+    48, 203, 191,   9,   9, 435,  11, 436,  48,  48, 400,  48,  48,  48, 437,  72,
+    48,  48,  48, 314,  48, 198, 400,  72, 438,  48,  48, 439,  48, 440,  48, 441,
+    48, 199, 442,  72,  72,  72,  48, 443,  48, 444,  48, 445,  72,  72,  72,  72,
+    48,  48,  48, 446, 269, 447, 269, 269, 448, 449,  48, 450, 451, 452,  48, 453,
+    48, 454,  72,  72, 455,  48, 456, 457,  48,  48,  48, 458,  48, 459,  48, 460,
+    48, 461, 462,  72,  72,  72,  72,  72,  48,  48,  48,  48, 195,  72,  72,  72,
+     9,   9,   9, 463,  11,  11,  11, 464,  48,  48, 465, 191,  72,  72,  72,  72,
+    72,  72,  72,  72,  72,  72, 269, 466,  48, 454, 467,  48,  62, 468,  72,  72,
+    72,  72,  72,  72,  72,  72,  48, 314, 469,  48,  48, 470, 471, 447, 472, 473,
+   220,  48,  48, 474, 475,  48, 195, 191, 476,  48, 477, 478, 479,  48,  48, 480,
+   220,  48,  48, 481, 482, 483, 484, 485,  48,  97, 486, 487,  72,  72,  72,  72,
+   488, 489, 490,  48,  48, 491, 492, 191, 493,  83,  84, 494, 495, 496, 497, 498,
+    48,  48,  48, 499, 500, 501,  72,  72,  48,  48,  48, 502, 503, 191,  72,  72,
+    48,  48, 504, 505, 506, 507,  72,  72,  48,  48,  48, 508, 509, 191, 510,  72,
+    48,  48, 511, 512, 191,  72,  72,  72,  48, 172, 513, 514,  72,  72,  72,  72,
+    48,  48, 486, 515,  72,  72,  72,  72,  72,  72,   9,   9,  11,  11, 147, 516,
+    72,  72, 517,  48,  48, 518, 519,  72, 520,  48,  48, 521, 522, 523,  48,  48,
+   524, 525, 526,  72,  48,  48,  48, 195,  84,  48, 504, 527, 528, 147, 174, 529,
+    48, 530, 531, 532,  72,  72,  72,  72, 533,  48,  48, 534, 535, 191, 536,  48,
+   537, 538, 191,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  48, 539,
+    72,  72,  72,  72, 269, 540, 541, 542,  48, 206,  72,  72,  72,  72,  72,  72,
+   270, 270, 270, 270, 270, 270, 543, 544,  48,  48,  48,  48, 386,  72,  72,  72,
+    48,  48, 199, 545,  72,  72,  72,  72,  48,  48,  48,  48, 314,  72,  72,  72,
+    48,  48,  48, 195,  48, 199, 368,  72,  72,  72,  72,  72,  72,  48, 203, 546,
+    48,  48,  48, 547, 548, 549, 550, 551,  48,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72,  72,   9,   9,  11,  11, 269, 552,  72,  72,  72,  72,  72,  72,
+    48,  48,  48,  48, 553, 554, 555, 555, 556, 557,  72,  72,  72,  72, 558,  72,
+    48,  48,  48,  48,  48,  48,  48, 400,  48,  48,  48,  48,  48,  48,  48, 559,
+    48, 199,  72,  72,  72, 559, 560,  48,  48,  48,  48,  48,  48,  48,  48, 205,
+    48,  48,  48,  48,  48,  48,  71, 150, 195, 561, 562,  72,  72,  72,  72,  72,
+   208, 208, 208, 208, 208, 208, 208, 323, 208, 208, 563, 208, 208, 208, 564, 565,
+   566, 208, 567, 208, 208, 208, 568,  72, 208, 208, 208, 208, 569,  72,  72,  72,
+    72,  72,  72,  72,  72,  72, 269, 570, 208, 208, 208, 208, 208, 285, 269, 451,
+     9, 571,  11, 572, 573, 574, 240,   9, 575, 576, 577, 578, 579,   9, 571,  11,
+   580, 581,  11, 582, 583, 584, 585,   9, 586,  11,   9, 571,  11, 572, 573,  11,
+   240,   9, 575, 585,   9, 586,  11,   9, 571,  11, 587,   9, 588, 589, 590, 591,
+    11, 592,   9, 593, 594, 595, 596,  11, 597,   9, 598,  11, 599, 600, 600, 600,
+    32,  32,  32, 601,  32,  32, 602, 603, 604, 605,  45,  72,  72,  72,  72,  72,
+   606, 607, 608,  72,  72,  72,  72,  72,  48,  48, 150, 609, 610,  72,  72,  72,
+    72,  72,  72,  72,  48,  48, 611, 612,  48,  48,  48,  48, 613, 614,  72,  72,
+     9,   9, 575,  11, 615, 368,  72,  72,  72,  72,  72,  72,  72,  72,  72, 484,
+   269, 269, 616, 617,  72,  72,  72,  72, 484, 269, 618, 619,  72,  72,  72,  72,
+   620,  48, 621, 622, 623, 624, 625, 626, 627, 205, 628, 205,  72,  72,  72, 629,
+   208, 208, 324, 208, 208, 208, 208, 208, 208, 322, 333, 630, 630, 630, 208, 323,
+   174, 208, 208, 208, 208, 208, 631, 208, 208, 208, 631,  72,  72,  72, 632, 208,
+   633, 208, 208, 324, 568, 634, 323,  72, 208, 208, 208, 208, 208, 208, 208, 635,
+   208, 208, 208, 208, 208, 323, 631, 286, 208, 208, 208, 208, 208, 208, 208, 322,
+   208, 208, 208, 208, 208, 568, 324,  72, 324, 208, 208, 208, 636, 175, 208, 208,
+   636, 208, 637,  72,  72,  72,  72,  72, 638, 208, 208, 208, 208, 208, 208, 639,
+   208, 208, 640, 208, 641, 208, 208, 208, 208, 208, 208, 208, 208, 322, 637, 642,
+   633, 323,  72,  72,  72,  72,  72,  72,  48,  48,  48,  48,  48, 314,  72,  72,
+    48,  48,  48, 204,  48,  48,  48,  48,  48, 203,  48,  48,  48,  48,  48,  48,
+    48,  48, 643,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  72,
+    48, 203,  72,  72,  72,  72,  72,  72, 644,  72, 645, 645, 645, 645, 645, 645,
+    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  72,
+   389, 389, 389, 389, 389, 389, 389, 646, 389, 389, 389, 389, 389, 389, 389, 647,
+     0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3,
+     0,   0,   0,   0,   0,   4,   0,   4,   2,   2,   5,   2,   2,   2,   5,   2,
+     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+     2,   2,   2,   2,   2,   2,   2,   6,   0,   0,   0,   0,   7,   8,   0,   0,
+     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,  10,  11,
+    12,  13,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,  16,  17,  14,  14,
+    18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
+    19,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
+    18,  18,  18,  18,  18,  18,  20,  21,  21,  21,  22,  20,  21,  21,  21,  21,
+    21,  23,  24,  25,  25,  25,  25,  25,  25,  26,  25,  25,  25,  27,  28,  26,
+    29,  30,  31,  32,  31,  31,  31,  31,  33,  34,  35,  31,  31,  31,  36,  31,
+    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  29,  31,  31,  31,  31,
+    37,  38,  37,  37,  37,  37,  37,  37,  37,  39,  31,  31,  31,  31,  31,  31,
+    40,  40,  40,  40,  40,  40,  41,  26,  42,  42,  42,  42,  42,  42,  42,  43,
+    44,  44,  44,  44,  44,  45,  44,  46,  47,  47,  47,  48,  37,  49,  26,  26,
+    26,  26,  26,  26,  31,  31,  50,  51,  26,  26,  52,  31,  53,  31,  31,  31,
+    54,  54,  54,  54,  54,  54,  54,  54,  54,  54,  55,  54,  56,  54,  54,  54,
+    57,  58,  59,  60,  60,  61,  62,  63,  58,  64,  65,  66,  67,  60,  60,  68,
+    69,  70,  71,  72,  72,  73,  74,  75,  70,  76,  77,  78,  79,  72,  80,  26,
+    81,  82,  83,  84,  84,  85,  86,  87,  82,  88,  89,  26,  90,  84,  91,  92,
+    93,  94,  95,  96,  96,  97,  98,  99,  94, 100, 101, 102, 103,  96,  96,  26,
+   104, 105, 106, 107, 108, 105, 109, 110, 105, 106, 111,  26, 112, 109, 109, 113,
+   114, 115, 116, 114, 114, 116, 114, 117, 115, 118, 119, 120, 121, 114, 122, 114,
+   123, 124, 125, 123, 123, 125, 126, 127, 124, 128, 129, 130, 131, 123, 132,  26,
+   133, 134, 135, 136, 136, 136, 136, 136, 134, 135, 137, 136, 138, 136, 136, 136,
+   139, 140, 141, 142, 140, 140, 143, 144, 141, 145, 146, 140, 147, 140, 148,  26,
+   149, 150, 150, 150, 150, 150, 150, 151, 150, 150, 150, 152,  26,  26,  26,  26,
+   153, 154, 155, 155, 156, 155, 155, 157, 158, 157, 155, 159,  26,  26,  26,  26,
+   160, 160, 160, 160, 160, 160, 160, 160, 160, 161, 160, 160, 160, 162, 161, 160,
+   160, 160, 160, 161, 160, 160, 160, 163, 160, 163, 164, 165,  26,  26,  26,  26,
+   166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166,
+   166, 166, 166, 166, 167, 167, 167, 167, 168, 169, 167, 167, 167, 167, 167, 170,
+   171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
+   172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 174, 173, 172, 172, 172, 172,
+   172, 173, 172, 172, 172, 172, 173, 174, 173, 172, 174, 172, 172, 172, 172, 172,
+   172, 172, 173, 172, 172, 172, 172, 172, 172, 172, 172, 175, 172, 172, 172, 176,
+   172, 172, 172, 177, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 179, 179,
+   180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180,
+   181, 181, 181, 182, 183, 183, 183, 183, 183, 183, 183, 183, 183, 184, 183, 185,
+   186, 187, 188,  26, 189, 189, 190,  26, 191, 191, 192,  26, 193, 194, 195,  26,
+   196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 197, 196, 198, 196, 198,
+   199, 200, 201, 202, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 203,
+   201, 201, 201, 201, 201, 204, 180, 180, 180, 180, 180, 180, 180, 180, 205,  26,
+   206, 206, 206, 207, 206, 208, 206, 208, 209, 206, 210, 210, 210, 211, 212,  26,
+   213, 213, 213, 213, 213, 214, 213, 213, 213, 215, 213, 216, 196, 196, 196, 196,
+   217, 217, 217, 218, 219, 219, 219, 219, 219, 219, 219, 220, 219, 219, 219, 221,
+   219, 222, 219, 222, 219, 223,   9, 224,  26,  26,  26,  26,  26,  26,  26,  26,
+   225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 225, 225, 225, 225, 225, 227,
+   228, 228, 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 230, 231,
+   232, 232, 232, 232, 232, 232, 232, 233, 232, 234, 235, 235, 235, 235, 235, 235,
+    18, 236, 167, 167, 167, 167, 167, 237, 228,  26, 238,   9, 239, 240, 241, 242,
+     2,   2,   2,   2, 243, 244,   2,   2,   2,   2,   2, 245, 246, 247,   2, 248,
+     2,   2,   2,   2,   2,   2,   2, 249,   9,   9,   9,   9,   9,   9,   9, 250,
+    14,  14, 251, 251,  14,  14,  14,  14, 251, 251,  14, 252,  14,  14,  14, 251,
+    14,  14,  14,  14,  14,  14, 253,  14, 253,  14, 254, 255,  14,  14, 256, 257,
+     0, 258,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 259,   0, 260, 261,
+     0, 262,   2, 263,   0,   0,   0,   0,  26,  26,   9,   9,   9,   9, 264,  26,
+     0,   0,   0,   0, 265, 266,   4,   0,   0, 267,   0,   0,   2,   2,   2,   2,
+     2, 268,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 262,  26,  26,  26,   0, 269,  26,  26,   0,   0,   0,   0,
+   270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 271,   0,
+     0,   0, 272,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   273, 273, 273, 273, 273, 274, 273, 273, 273, 273, 273, 274,   2,   2,   2,   2,
+    17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17, 275, 276,
+   167, 167, 167, 167, 168, 169, 277, 277, 277, 277, 277, 277, 277, 278, 279, 278,
+   172, 172, 174,  26, 174, 174, 174, 174, 174, 174, 174, 174,  18,  18,  18,  18,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  26,  26,  26,  26,  26,  26,
+   280, 280, 280, 281, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 282,  26,
+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 283,  26,  26,  26,   0, 284,
+   285,   0,   0,   0, 286, 287,   0, 288, 289, 290, 290, 290, 290, 290, 290, 290,
+   290, 290, 291, 292, 293, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 295,
+   296, 297, 297, 297, 297, 297, 298, 171, 171, 171, 171, 171, 171, 171, 171, 171,
+   171, 299,   0,   0, 297, 297, 297, 300,   0,   0,   0,   0, 284,  26, 294, 294,
+   171, 171, 171, 299,   0,   0,   0,   0,   0,   0,   0,   0, 171, 171, 171, 301,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 294, 294, 294, 294, 294, 302,
+   294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294,   0,   0,   0,   0,   0,
+   280, 280, 280, 280, 280, 280, 283,  26,   0,   0,   0,   0,   0,   0,   0,   0,
+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,  26,  26,
+   303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
+   303, 304, 303, 303, 303, 303, 303, 303, 305,  26, 306, 306, 306, 306, 306, 306,
+   307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
+   307, 307, 307, 307, 307, 308,  26,  26,  18,  18,  18,  18,  18,  18,  18,  18,
+    18,  18,  18,  18, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,  26,
+     0,   0,   0,   0, 310,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+     2, 311,   2,   2,   2,   2,   2,   2, 312,  26,  26,  26,  26,  26, 313,   2,
+   314, 314, 314, 314, 314, 315,   0, 316, 317, 317, 317, 317, 317, 317, 317,  26,
+   318, 318, 318, 318, 318, 318, 318, 318, 319, 320, 318, 321,  54,  54,  54,  54,
+   322, 322, 322, 322, 322, 323, 324, 324, 324, 324, 325, 326, 171, 171, 171, 327,
+   328, 328, 328, 328, 328, 328, 328, 328, 328, 329, 328, 330, 166, 166, 166, 331,
+   332, 332, 332, 332, 332, 332, 333,  26, 332, 334, 332, 335, 166, 166, 166, 166,
+   336, 336, 336, 336, 336, 336, 336, 336, 337,  26,  26, 338, 339, 339, 340,  26,
+   341, 341, 341,  26, 174, 174,   2,   2,   2,   2,   2, 342, 343,  26, 178, 178,
+   178, 178, 178, 178, 178, 178, 178, 178, 339, 339, 339, 339, 339, 344, 339, 345,
+   171, 171, 171, 171, 346,  26, 171, 171, 299, 347, 171, 171, 171, 171, 171, 346,
+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 283, 280, 280,
+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 348,  26,  26,  26,  26,
+   349,  26, 350, 351,  25,  25, 352, 353, 354,  25,  31,  31,  31,  31,  31,  31,
+    31,  31,  31,  31,  31,  31,  31,  31, 355,  26,  52,  31,  31,  31,  31,  31,
+    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,
+    31,  31,  31,  31,  31,  31,  31, 356,  26,  26,  31,  31,  31,  31,  31,  31,
+    31,  31, 357,  31,  31,  31,  31,  31,  31,  26,  26,  26,  26,  26,  31,  51,
+     9,   9,   0, 316,   9, 358,   0,   0,   0,   0, 359,   0, 262, 284,  50,  31,
+    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31, 360,
+   361,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3, 362, 294, 293, 294,
+   294, 294, 294, 363, 171, 171, 171, 299, 364, 364, 364, 365, 262, 262,  26, 366,
+   367, 368, 367, 367, 369, 367, 367, 370, 367, 371, 367, 371,  26,  26,  26,  26,
+   367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 372,
+   373,   0,   0,   0,   0,   0, 374,   0,  14,  14,  14,  14,  14,  14,  14,  14,
+    14, 257,   0, 284, 375,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0, 376,
+   377, 377, 377, 378, 379, 379, 379, 379, 379, 379, 380,  26, 381,   0,   0, 284,
+   382, 382, 382, 382, 383, 384, 385, 385, 385, 386, 387, 387, 387, 387, 387, 388,
+   389, 389, 389, 390, 391, 391, 391, 391, 392, 391, 393,  26,  26,  26,  26,  26,
+   394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 395, 395, 395, 395, 395, 395,
+   396, 396, 396, 397, 396, 398, 399, 399, 399, 399, 400, 399, 399, 399, 399, 400,
+   401, 401, 401, 401, 401,  26, 402, 402, 402, 402, 402, 402, 403, 404,  26,  26,
+   405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405,
+   405, 405, 405, 405, 405, 405, 406,  26, 405, 405, 407,  26, 405,  26,  26,  26,
+   408, 409, 410, 410, 410, 410, 411, 412, 413, 413, 414, 413, 415, 415, 415, 415,
+   416, 416, 416, 417, 418, 416,  26,  26,  26,  26,  26,  26, 419, 419, 420, 421,
+   422, 422, 422, 423, 424, 424, 424, 425,  26,  26,  26,  26,  26,  26,  26,  26,
+   426, 426, 426, 426, 427, 427, 427, 428, 427, 427, 429, 427, 427, 427, 427, 427,
+   430, 431, 432, 433, 434, 434, 435, 436, 434, 437, 434, 437, 438, 438, 438, 438,
+   439, 439, 439, 439,  26,  26,  26,  26, 440, 440, 440, 440, 441, 442, 441,  26,
+   443, 443, 443, 443, 443, 443, 444, 445, 446, 446, 447, 446, 448, 448, 449, 448,
+   450, 450, 451, 452,  26, 453,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   454, 454, 454, 454, 454, 454, 454, 454, 454, 455,  26,  26,  26,  26,  26,  26,
+   456, 456, 456, 456, 456, 456, 457,  26, 456, 456, 456, 456, 456, 456, 457, 458,
+     0,   0,   0,   0,   0,  26,   0, 316,  26,  26,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31, 459,
+     9,   9,   9,   9,   9,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31, 459,  26,
+   460, 460, 460, 460, 460, 460, 460, 460, 460, 461, 462, 460, 460, 460,  26, 463,
+   464, 464, 464, 464, 464, 464, 464, 464, 465, 466, 467, 467, 467, 468, 467, 469,
+   470, 470, 470, 470, 470, 470, 471, 470, 472,  26, 473, 473, 473, 473, 474,  26,
+   475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 475, 475, 477, 140, 478,  26,
+   479, 479, 480, 479, 479, 479, 479, 481,  26,  26,  26,  26,  26,  26,  26,  26,
+   482, 483, 484, 485, 484, 486, 487, 487, 487, 487, 487, 487, 487, 488, 487, 489,
+   490, 491, 492, 493, 493, 494, 495, 496, 491, 497, 498, 499, 500, 501, 501,  26,
+   502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 503,  26,  26,  26,  26,
+   504, 504, 504, 504, 504, 504, 504, 504, 504,  26, 504, 505,  26,  26,  26,  26,
+   506, 506, 506, 506, 506, 506, 507, 506, 506, 506, 506, 507,  26,  26,  26,  26,
+   508, 508, 508, 508, 508, 508, 508, 508, 509,  26, 508, 510, 201, 511,  26,  26,
+   512, 512, 512, 512, 512, 512, 512, 513, 512, 514,  26,  26,  26,  26,  26,  26,
+   515, 515, 515, 516, 515, 517, 515, 515,  26,  26,  26,  26,  26,  26,  26,  26,
+    21,  21,  21,  21,  21,  21,  21, 518,  26,  26,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 520, 521,
+    26,  26,  26,  26,  60, 522,  60,  60,  60,  60,  60, 522, 523,  26,  26,  26,
+    18,  18,  18,  18,  18,  18,  18,  18,  18,  26,  54,  54,  54,  54,  54,  54,
+    54,  54,  54,  54, 524,  26,  26,  26, 525, 525, 525, 525, 525, 525, 525, 526,
+   527, 528, 527, 527, 527, 527, 529, 527, 530,  26, 527, 527, 527, 531, 532, 532,
+   532, 532, 533, 532, 532, 534, 535,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   536, 537, 167, 167, 167, 167, 536, 538, 167,  26, 167, 539, 540, 541,  14,  14,
+    14, 257,  15, 375,  14, 542,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  84,  84,  84,  89,
+    26,  26,  26,  26,  26,  26,  26,  26, 109, 109, 109, 109, 109, 109, 543, 544,
+   545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545,
+   545, 545, 545, 546,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 547, 548,  26,
+   545, 545, 545, 545, 545, 545, 545, 545, 549,  26,  26,  26,  26,  26,  26,  26,
+   550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550,
+   550, 550, 550, 550, 550, 551, 550, 552,  26,  26,  26,  26,  26,  26,  26,  26,
+   553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
+   553, 553, 553, 553, 553, 553, 553, 553, 554,  26,  26,  26,  26,  26,  26,  26,
+   309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+   309, 309, 309, 309, 309, 309, 309, 555, 556, 556, 556, 557, 556, 558,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 559, 559, 559, 560, 560,  26,
+   561, 561, 561, 561, 561, 561, 561, 561, 562,  26, 561, 563, 563, 561, 561, 564,
+   561, 561,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  72,  72,  72,  72,  72,  72,  72,  72,
+    72,  72,  72, 565,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   566, 566, 566, 566, 566, 566, 566, 566, 566, 567, 566, 566, 566, 566, 566, 566,
+   566, 568, 566, 566,  26,  26,  26,  26,  26,  26,  26,  26, 569,  26,  26,  26,
+   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570,
+   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570,  26,
+   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 571,  26,
+   572, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
+   290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
+   290, 290, 290, 291,  26,  26,  26,  26,  26,  26, 573,  26, 574,  26, 171, 171,
+   171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 346,
+   575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 576, 575, 577,
+   575, 578, 575, 579, 284,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 272,  26,
+     0,   0,   0,   0, 262, 361,   0,   0,   0,   0,   0,   0, 580, 581,   0, 582,
+   583, 584,   0,   0,   0, 585,   0,   0,   0,   0,   0,   0,   0, 586,  26,  26,
+    14,  14,  14,  14,  14,  14,  14,  14, 251,  26,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,   0,   0, 284,  26,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 262,  26,   0,   0,   0, 586,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 259,   0,   0,   0,   0,   0,
+     0,   0,   0, 259, 587, 588,   0, 589, 590,   0,   0,   0,   0,   0,   0,   0,
+   591, 592, 259, 259,   0,   0,   0, 593, 594, 595, 596,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 272,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0, 271,   0,   0,   0,   0,   0,   0,
+   597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597,
+   597, 598,  26, 599, 600, 597,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   274, 273, 273, 601, 602, 603,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   280, 280, 280, 280, 280, 604, 280, 283, 280, 605,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  25,  25,  25,  25,  25,  25,  25, 606,
+   607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607,
+   607, 607, 607, 607, 607, 607, 607, 607, 608, 607, 609,  26,  26,  26,  26,  26,
+   610, 610, 610, 610, 610, 610, 610, 610, 610, 611, 610, 612,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 361,   0,
+     0,   0,   0,   0,   0,   0, 613,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   361,   0,   0,   0,   0,   0,   0, 272,  26,  26,  26,  26,  26,  26,  26,  26,
+   614,  31,  31,  31, 615, 616, 617, 618, 619, 620, 615, 621, 615, 617, 617, 622,
+    31, 623,  31, 624, 625, 623,  31, 624,  26,  26,  26,  26,  26,  26, 355,  26,
+     0,   0,   0,   0,   0, 284,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0, 284,  26,   0, 262, 361,   0, 361,   0, 361,   0,   0,   0, 272,  26,
+     0, 613,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 613,   0,   0,
+     0,   0,   0,   0,   0, 613,  26,  26,  26,  26,  26,  26, 626,   0,   0,   0,
+   627,  26,   0,   0,   0,   0,   0, 284,   0, 586, 316,  26, 272,  26,  26,  26,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 272,  26,   0, 613,   0, 269,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 284,  26,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 586,   0, 284,  26,  26,
+     0, 284,   0,   0,   0,   0,   0,   0,   0,  26,   0, 316,   0,   0,   0,   0,
+     0,  26,   0,   0,   0, 272,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+     0, 590,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 593, 595,
+     0,   0,   0,   0, 592, 628,   0,   0,   0, 592,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 284,  26,   0, 272, 284, 269,
+   269,  26, 272,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 629,  26,  26,  26,  26,  26,
+   280, 280, 280, 280, 280, 280, 604,  26, 280, 280, 280, 280, 280, 280, 280, 280,
+   280, 280, 280, 283, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+   280, 280, 280, 280, 348,  26, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 630,  26,  26,  26,
+   280, 280, 280, 283,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+   631,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,
+     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
+     0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
+  1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
+     0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303,
+   943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
+     0,   0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
+   991,1176, 993,1178, 994,1179,   0,   0,1004,1190,1005,1191,1006,1192,1014,1199,
+  1007,   0,   0,   0,1016,1201,1020,1206,   0,1022,1208,1025,1211,1023,1209,   0,
+     0,   0,   0,1032,1218,1037,1223,1035,1221,   0,   0,   0,1044,1230,1045,1231,
+  1049,1235,   0,   0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
+  1069,1255,1077,1264,1074,1261,   0,   0,1083,1270,1084,1271,1085,1272,1088,1275,
+  1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310,   0,
+  1053,1239,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1093,
+  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, 949,1134,1010,
+  1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366,   0,1320,1347,
+  1418,1419,1323,1350,   0,   0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
+  1202,   0,   0,   0, 987,1172,   0,   0,1031,1217,1321,1348,1322,1349,1338,1365,
+   950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
+  1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263,   0,   0, 997,1182,
+     0,   0,   0,   0,   0,   0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
+  1422,1423,1113,1301,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     8,   9,   0,  10,1425,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,
+     0,   0,   0,   0,   0,1314,1427,   5,1434,1438,1443,   0,1450,   0,1455,1461,
+  1514,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1446,1458,1468,1476,1480,1486,
+  1517,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1489,1503,1494,1500,1508,   0,
+     0,   0,   0,1520,1521,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1526,1528,   0,1525,   0,   0,   0,1522,   0,   0,   0,   0,1536,1532,1539,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1534,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1556,   0,   0,   0,   0,   0,   0,
+  1548,1550,   0,1547,   0,   0,   0,1567,   0,   0,   0,   0,1558,1554,1561,   0,
+     0,   0,   0,   0,   0,   0,1568,1569,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1529,1551,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1523,1545,1524,1546,   0,   0,1527,1549,   0,   0,1570,1571,1530,1552,1531,1553,
+     0,   0,1533,1555,1535,1557,1537,1559,   0,   0,1572,1573,1544,1566,1538,1560,
+  1540,1562,1541,1563,1542,1564,   0,   0,1543,1565,   0,   0,   0,   0,   0,   0,
+     0,   0,1606,1607,1609,1608,1610,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1613,   0,1611,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1612,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1620,   0,   0,   0,   0,   0,   0,
+     0,1623,   0,   0,1624,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1614,1615,1616,1617,1618,1619,1621,1622,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1628,1629,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1625,1626,   0,1627,
+     0,   0,   0,1634,   0,   0,1635,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1630,1631,1632,   0,   0,1633,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1639,   0,   0,1638,1640,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1636,1637,   0,   0,
+     0,   0,   0,   0,1641,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1642,1644,1643,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1645,   0,   0,   0,   0,   0,   0,   0,
+  1646,   0,   0,   0,   0,   0,   0,1648,1649,   0,1647,1650,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1651,1653,1652,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1654,   0,1655,1657,1656,   0,
+     0,   0,   0,1659,   0,   0,   0,   0,   0,   0,   0,   0,   0,1660,   0,   0,
+     0,   0,1661,   0,   0,   0,   0,1662,   0,   0,   0,   0,1663,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1658,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1664,   0,1665,1673,   0,1674,   0,   0,   0,   0,   0,   0,   0,
+     0,1666,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1668,   0,   0,   0,   0,   0,   0,   0,   0,   0,1669,   0,   0,
+     0,   0,1670,   0,   0,   0,   0,1671,   0,   0,   0,   0,1672,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1667,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1675,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1676,   0,1677,   0,1678,   0,1679,   0,1680,   0,
+     0,   0,1681,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1682,   0,1683,   0,   0,
+  1684,1685,   0,1686,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
+   966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
+   989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
+  1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
+  1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
+  1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
+  1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
+  1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
+  1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
+  1119,1308,1122,1311,1123,1312,1186,1260,1293,1305,   0,1394,   0,   0,   0,   0,
+   952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
+  1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
+  1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
+  1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
+  1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
+  1409,1414,1109,1297,1117,1306,1116,1304,1112,1300,   0,   0,   0,   0,   0,   0,
+  1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
+  1477,1478,1729,1731,1730,1732,   0,   0,1435,1436,1733,1735,1734,1736,   0,   0,
+  1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
+  1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
+  1495,1496,1777,1779,1778,1780,   0,   0,1451,1452,1781,1783,1782,1784,   0,   0,
+  1504,1505,1785,1788,1786,1789,1787,1790,   0,1459,   0,1791,   0,1792,   0,1793,
+  1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
+  1467,  21,1475,  22,1479,  23,1485,  24,1493,  27,1499,  28,1507,  29,   0,   0,
+  1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
+  1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
+  1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
+  1470,1469,1822,1474,1465,   0,1473,1825,1429,1428,1426,  12,1432,   0,  26,   0,
+     0,1315,1823,1484,1466,   0,1483,1829,1433,  13,1437,  14,1441,1826,1827,1828,
+  1488,1487,1513,  19,   0,   0,1492,1515,1445,1444,1442,  15,   0,1831,1832,1833,
+  1502,1501,1516,  25,1497,1498,1506,1518,1457,1456,1454,  17,1453,1313,  11,   3,
+     0,   0,1824,1512,1519,   0,1511,1830,1449,  16,1460,  18,1464,   4,   0,   0,
+    30,  31,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,  20,   0,   0,   0,   2,   6,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1834,1835,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1836,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1837,1839,1838,
+     0,   0,   0,   0,1840,   0,   0,   0,   0,1841,   0,   0,1842,   0,   0,   0,
+     0,   0,   0,   0,1843,   0,1844,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1845,   0,   0,1846,   0,   0,1847,   0,1848,   0,   0,   0,   0,   0,   0,
+   937,   0,1850,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1849, 936, 938,
+  1851,1852,   0,   0,1853,1854,   0,   0,1855,1856,   0,   0,   0,   0,   0,   0,
+  1857,1858,   0,   0,1861,1862,   0,   0,1863,1864,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1867,1868,1869,1870,
+  1859,1860,1865,1866,   0,   0,   0,   0,   0,   0,1871,1872,1873,1874,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,  32,  33,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1875,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1877,   0,1878,   0,
+  1879,   0,1880,   0,1881,   0,1882,   0,1883,   0,1884,   0,1885,   0,1886,   0,
+  1887,   0,1888,   0,   0,1889,   0,1890,   0,1891,   0,   0,   0,   0,   0,   0,
+  1892,1893,   0,1894,1895,   0,1896,1897,   0,1898,1899,   0,1900,1901,   0,   0,
+     0,   0,   0,   0,1876,   0,   0,   0,   0,   0,   0,   0,   0,   0,1902,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1904,   0,1905,   0,
+  1906,   0,1907,   0,1908,   0,1909,   0,1910,   0,1911,   0,1912,   0,1913,   0,
+  1914,   0,1915,   0,   0,1916,   0,1917,   0,1918,   0,   0,   0,   0,   0,   0,
+  1919,1920,   0,1921,1922,   0,1923,1924,   0,1925,1926,   0,1927,1928,   0,   0,
+     0,   0,   0,   0,1903,   0,   0,1929,1930,1931,1932,   0,   0,   0,1933,   0,
+   710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
+   663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
+   810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
+   368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
+   811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
+   594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
+   313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
+   424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
+   193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
+   337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
+   683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
+   608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
+   479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
+   791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
+   377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
+   659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
+   153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210,   0,   0,
+   227,   0, 379,   0,   0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604,   0,
+   661,   0, 703,   0,   0, 735, 743,   0,   0,   0, 793, 794, 795, 808, 741, 773,
+   118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
+   335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
+   549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
+   690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623,   0,   0,
+   102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
+   250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
+   370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
+   493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
+   591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
+   709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
+   847, 857,  55,  65,  66, 883, 892, 916, 822, 824,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1586,   0,1605,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,
+  1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,
+  1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1948,1949,
+  1950,1951,1952,1953,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,1957,1959,1958,
+  1960,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131,
+   132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37,
+   157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
+   181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
+   197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
+   153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
+   836, 837, 247, 248, 249, 246, 251,  39,  40, 253, 255, 255, 838, 257, 258, 259,
+   261, 839, 262, 263, 301, 264,  41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
+   278, 281, 282,  42, 283, 284, 285, 286,  43, 843,  44, 289, 290, 291, 293, 934,
+   298, 845, 845, 621, 300, 300,  45, 852, 894, 302, 304,  46, 306, 309, 310, 312,
+   316,  48,  47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
+   335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
+   358, 356,  49, 363, 365, 367, 364,  50, 369, 371, 851, 376, 386, 378,  53, 381,
+    52,  51, 140, 141, 387, 382, 614,  78, 388, 389, 390, 394, 392, 856,  54, 399,
+   396, 402, 404, 858, 405, 401, 407,  55, 408, 409, 410, 413, 859, 415,  56, 417,
+   860, 418,  57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
+   437, 441, 438, 439, 442, 443, 864, 436, 449, 450,  58, 454, 453, 865, 447, 460,
+   866, 867, 461, 466, 465, 464,  59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
+   483, 485, 486, 871, 488, 489, 872, 873, 495, 497,  60, 498,  61,  61, 504, 505,
+   507, 508, 511,  62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878,  63,  64,
+   528, 880, 879, 881, 882, 530, 531, 531, 533,  66, 534,  67,  68, 884, 536, 538,
+   541,  69, 885, 549, 886, 887, 556, 559,  70, 561, 562, 563, 888, 889, 889, 567,
+    71, 890, 570, 571,  72, 891, 577,  73, 581, 579, 582, 893, 587,  74, 590, 592,
+   596,  75, 895, 896,  76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
+   853,  77, 615, 616,  79, 617, 252, 902, 903, 854, 855, 621, 622, 731,  80, 627,
+   626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
+   638, 643, 644, 645, 905, 907, 906,  81, 653, 654, 656, 911, 657, 908,  82,  83,
+   909, 910,  84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675,  85,
+   677, 678,  86, 681, 682, 912, 685, 686,  87, 689,  36, 913, 914,  88,  89, 696,
+   702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
+   918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762,  90,
+   764, 922,  91, 775, 279, 780, 923, 925,  92,  93, 785, 926,  94, 927, 787, 787,
+   789, 928, 792,  95, 796, 797, 798, 800,  96, 929, 802, 804, 806,  97,  98, 807,
+   930,  99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935,   0,   0,
+};
+static const int16_t
+_hb_ucd_i16[196] =
+{
+      0,    0,    0,    0,    1,   -1,    0,    0,    2,    0,   -2,    0,    0,    0,    0,    2,
+      0,   -2,    0,    0,    0,    0,    0,   16,    0,    0,    0,  -16,    0,    0,    1,   -1,
+      0,    0,    0,    1,   -1,    0,    0,    0,    0,    1,   -1,    0,    3,    3,    3,   -3,
+     -3,   -3,    0,    0,    0, 2016,    0,    0,    0,    0,    0, 2527, 1923, 1914, 1918,    0,
+   2250,    0,    0,    0,    0,    0,    0,  138,    0,    7,    0,    0,   -7,    0,    0,    0,
+      1,   -1,    1,   -1,   -1,    1,   -1,    0, 1824,    0,    0,    0,    0,    0, 2104,    0,
+   2108, 2106,    0, 2106, 1316,    0,    0,    0,    0,    1,   -1,    1,   -1, -138,    0,    0,
+      1,   -1,    8,    8,    8,    0,    7,    7,    0,    0,   -8,   -8,   -8,   -7,   -7,    0,
+      1,   -1,    0,    2,-1316,    1,   -1,    0,   -1,    1,   -1,    1,   -1,    3,    1,   -1,
+     -3,    1,   -1,    1,   -1,    0,    0,-1914,-1918,    0,    0,-1923,-1824,    0,    0,    0,
+      0,-2016,    0,    0,    1,   -1,    0,    1,    0,    0,-2104,    0,    0,    0,    0,-2106,
+  -2108,-2106,    0,    0,    1,   -1,-2250,    0,    0,    0,-2527,    0,    0,   -2,    0,    1,
+     -1,    0,    1,   -1,
+};
+
+static inline uint_fast8_t
+_hb_ucd_gc (unsigned u)
+{
+  return u<1114110u?_hb_ucd_u8[6432+(((_hb_ucd_u8[1248+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+}
+static inline uint_fast8_t
+_hb_ucd_ccc (unsigned u)
+{
+  return u<125259u?_hb_ucd_u8[8640+(((_hb_ucd_u8[7704+(((_hb_ucd_u8[7048+(((_hb_ucd_u8[6802+(u>>2>>3>>4)])<<4)+((u>>2>>3)&15u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u))]:0;
+}
+static inline unsigned
+_hb_ucd_b4 (const uint8_t* a, unsigned i)
+{
+  return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline int_fast16_t
+_hb_ucd_bmg (unsigned u)
+{
+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9372+(((_hb_ucd_u8[9252+(((_hb_ucd_b4(9124+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+}
+static inline uint_fast8_t
+_hb_ucd_sc (unsigned u)
+{
+  return u<918000u?_hb_ucd_u8[10822+(((_hb_ucd_u16[1920+(((_hb_ucd_u8[10150+(((_hb_ucd_u8[9700+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
+}
+static inline uint_fast16_t
+_hb_ucd_dm (unsigned u)
+{
+  return u<195102u?_hb_ucd_u16[5632+(((_hb_ucd_u8[15974+(((_hb_ucd_b4(15878+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0;
+}
+
+#endif
+
+
+#endif /* HB_UCD_TABLE_HH */
+
+/* == End of generated table == */
diff --git a/src/hb-ucd.cc b/src/hb-ucd.cc
new file mode 100644
index 0000000..134e043
--- /dev/null
+++ b/src/hb-ucd.cc
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hb.hh"
+#include "hb-machinery.hh"
+
+#include "hb-ucd-table.hh"
+
+static hb_unicode_combining_class_t
+hb_ucd_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+			hb_codepoint_t unicode,
+			void *user_data HB_UNUSED)
+{
+  return (hb_unicode_combining_class_t) _hb_ucd_ccc (unicode);
+}
+
+static hb_unicode_general_category_t
+hb_ucd_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+			 hb_codepoint_t unicode,
+			 void *user_data HB_UNUSED)
+{
+  return (hb_unicode_general_category_t) _hb_ucd_gc (unicode);
+}
+
+static hb_codepoint_t
+hb_ucd_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+		  hb_codepoint_t unicode,
+		  void *user_data HB_UNUSED)
+{
+  return unicode + _hb_ucd_bmg (unicode);
+}
+
+static hb_script_t
+hb_ucd_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+	       hb_codepoint_t unicode,
+	       void *user_data HB_UNUSED)
+{
+  return _hb_ucd_sc_map[_hb_ucd_sc (unicode)];
+}
+
+
+#define SBASE 0xAC00u
+#define LBASE 0x1100u
+#define VBASE 0x1161u
+#define TBASE 0x11A7u
+#define SCOUNT 11172u
+#define LCOUNT 19u
+#define VCOUNT 21u
+#define TCOUNT 28u
+#define NCOUNT (VCOUNT * TCOUNT)
+
+static inline bool
+_hb_ucd_decompose_hangul (hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b)
+{
+  unsigned si = ab - SBASE;
+
+  if (si >= SCOUNT)
+    return false;
+
+  if (si % TCOUNT)
+  {
+    /* LV,T */
+    *a = SBASE + (si / TCOUNT) * TCOUNT;
+    *b = TBASE + (si % TCOUNT);
+    return true;
+  } else {
+    /* L,V */
+    *a = LBASE + (si / NCOUNT);
+    *b = VBASE + (si % NCOUNT) / TCOUNT;
+    return true;
+  }
+}
+
+static inline bool
+_hb_ucd_compose_hangul (hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab)
+{
+  if (a >= SBASE && a < (SBASE + SCOUNT) && b > TBASE && b < (TBASE + TCOUNT) &&
+    !((a - SBASE) % TCOUNT))
+  {
+    /* LV,T */
+    *ab = a + (b - TBASE);
+    return true;
+  }
+  else if (a >= LBASE && a < (LBASE + LCOUNT) && b >= VBASE && b < (VBASE + VCOUNT))
+  {
+    /* L,V */
+    int li = a - LBASE;
+    int vi = b - VBASE;
+    *ab = SBASE + li * NCOUNT + vi * TCOUNT;
+    return true;
+  }
+  else
+    return false;
+}
+
+static int
+_cmp_pair (const void *_key, const void *_item)
+{
+  uint64_t& a = * (uint64_t*) _key;
+  uint64_t b = (* (uint64_t*) _item) & HB_CODEPOINT_ENCODE3(0x1FFFFFu, 0x1FFFFFu, 0);
+
+  return a < b ? -1 : a > b ? +1 : 0;
+}
+
+static hb_bool_t
+hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
+		void *user_data HB_UNUSED)
+{
+  if (_hb_ucd_compose_hangul (a, b, ab)) return true;
+
+  uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
+  uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_map,
+					ARRAY_LENGTH (_hb_ucd_dm2_map),
+					sizeof (*_hb_ucd_dm2_map),
+					_cmp_pair);
+  if (likely (!v)) return false;
+
+  hb_codepoint_t u = HB_CODEPOINT_DECODE3_3 (*v);
+  if (unlikely (!u)) return false;
+
+  *ab = u;
+  return true;
+}
+
+static hb_bool_t
+hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
+		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
+		  void *user_data HB_UNUSED)
+{
+  if (_hb_ucd_decompose_hangul (ab, a, b)) return true;
+
+  unsigned i = _hb_ucd_dm (ab);
+
+  if (likely (!i)) return false;
+  i--;
+
+  if (i < ARRAY_LENGTH (_hb_ucd_dm1_map))
+  {
+    *a = _hb_ucd_dm1_map[i];
+    *b = 0;
+    return true;
+  }
+  i -= ARRAY_LENGTH (_hb_ucd_dm1_map);
+
+  uint64_t v = _hb_ucd_dm2_map[i];
+  *a = HB_CODEPOINT_DECODE3_1 (v);
+  *b = HB_CODEPOINT_DECODE3_2 (v);
+  return true;
+}
+
+
+#if HB_USE_ATEXIT
+static void free_static_ucd_funcs ();
+#endif
+
+static struct hb_ucd_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucd_unicode_funcs_lazy_loader_t>
+{
+  static hb_unicode_funcs_t *create ()
+  {
+    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
+
+    hb_unicode_funcs_set_combining_class_func (funcs, hb_ucd_combining_class, nullptr, nullptr);
+    hb_unicode_funcs_set_general_category_func (funcs, hb_ucd_general_category, nullptr, nullptr);
+    hb_unicode_funcs_set_mirroring_func (funcs, hb_ucd_mirroring, nullptr, nullptr);
+    hb_unicode_funcs_set_script_func (funcs, hb_ucd_script, nullptr, nullptr);
+    hb_unicode_funcs_set_compose_func (funcs, hb_ucd_compose, nullptr, nullptr);
+    hb_unicode_funcs_set_decompose_func (funcs, hb_ucd_decompose, nullptr, nullptr);
+
+    hb_unicode_funcs_make_immutable (funcs);
+
+#if HB_USE_ATEXIT
+    atexit (free_static_ucd_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ucd_funcs;
+
+#if HB_USE_ATEXIT
+static
+void free_static_ucd_funcs ()
+{
+  static_ucd_funcs.free_instance ();
+}
+#endif
+
+extern "C" HB_INTERNAL
+hb_unicode_funcs_t *
+hb_ucd_get_unicode_funcs ();
+
+hb_unicode_funcs_t *
+hb_ucd_get_unicode_funcs ()
+{
+#ifdef HB_NO_UCD
+  return hb_unicode_funcs_get_empty ();
+#endif
+  return static_ucd_funcs.get_unconst ();
+}
diff --git a/src/hb-ucdn.cc b/src/hb-ucdn.cc
deleted file mode 100644
index 8230bf1..0000000
--- a/src/hb-ucdn.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "hb.hh"
-
-#include "hb-machinery.hh"
-
-#include "ucdn.h"
-
-static const hb_script_t ucdn_script_translate[] =
-{
-    HB_SCRIPT_COMMON,
-    HB_SCRIPT_LATIN,
-    HB_SCRIPT_GREEK,
-    HB_SCRIPT_CYRILLIC,
-    HB_SCRIPT_ARMENIAN,
-    HB_SCRIPT_HEBREW,
-    HB_SCRIPT_ARABIC,
-    HB_SCRIPT_SYRIAC,
-    HB_SCRIPT_THAANA,
-    HB_SCRIPT_DEVANAGARI,
-    HB_SCRIPT_BENGALI,
-    HB_SCRIPT_GURMUKHI,
-    HB_SCRIPT_GUJARATI,
-    HB_SCRIPT_ORIYA,
-    HB_SCRIPT_TAMIL,
-    HB_SCRIPT_TELUGU,
-    HB_SCRIPT_KANNADA,
-    HB_SCRIPT_MALAYALAM,
-    HB_SCRIPT_SINHALA,
-    HB_SCRIPT_THAI,
-    HB_SCRIPT_LAO,
-    HB_SCRIPT_TIBETAN,
-    HB_SCRIPT_MYANMAR,
-    HB_SCRIPT_GEORGIAN,
-    HB_SCRIPT_HANGUL,
-    HB_SCRIPT_ETHIOPIC,
-    HB_SCRIPT_CHEROKEE,
-    HB_SCRIPT_CANADIAN_SYLLABICS,
-    HB_SCRIPT_OGHAM,
-    HB_SCRIPT_RUNIC,
-    HB_SCRIPT_KHMER,
-    HB_SCRIPT_MONGOLIAN,
-    HB_SCRIPT_HIRAGANA,
-    HB_SCRIPT_KATAKANA,
-    HB_SCRIPT_BOPOMOFO,
-    HB_SCRIPT_HAN,
-    HB_SCRIPT_YI,
-    HB_SCRIPT_OLD_ITALIC,
-    HB_SCRIPT_GOTHIC,
-    HB_SCRIPT_DESERET,
-    HB_SCRIPT_INHERITED,
-    HB_SCRIPT_TAGALOG,
-    HB_SCRIPT_HANUNOO,
-    HB_SCRIPT_BUHID,
-    HB_SCRIPT_TAGBANWA,
-    HB_SCRIPT_LIMBU,
-    HB_SCRIPT_TAI_LE,
-    HB_SCRIPT_LINEAR_B,
-    HB_SCRIPT_UGARITIC,
-    HB_SCRIPT_SHAVIAN,
-    HB_SCRIPT_OSMANYA,
-    HB_SCRIPT_CYPRIOT,
-    HB_SCRIPT_BRAILLE,
-    HB_SCRIPT_BUGINESE,
-    HB_SCRIPT_COPTIC,
-    HB_SCRIPT_NEW_TAI_LUE,
-    HB_SCRIPT_GLAGOLITIC,
-    HB_SCRIPT_TIFINAGH,
-    HB_SCRIPT_SYLOTI_NAGRI,
-    HB_SCRIPT_OLD_PERSIAN,
-    HB_SCRIPT_KHAROSHTHI,
-    HB_SCRIPT_BALINESE,
-    HB_SCRIPT_CUNEIFORM,
-    HB_SCRIPT_PHOENICIAN,
-    HB_SCRIPT_PHAGS_PA,
-    HB_SCRIPT_NKO,
-    HB_SCRIPT_SUNDANESE,
-    HB_SCRIPT_LEPCHA,
-    HB_SCRIPT_OL_CHIKI,
-    HB_SCRIPT_VAI,
-    HB_SCRIPT_SAURASHTRA,
-    HB_SCRIPT_KAYAH_LI,
-    HB_SCRIPT_REJANG,
-    HB_SCRIPT_LYCIAN,
-    HB_SCRIPT_CARIAN,
-    HB_SCRIPT_LYDIAN,
-    HB_SCRIPT_CHAM,
-    HB_SCRIPT_TAI_THAM,
-    HB_SCRIPT_TAI_VIET,
-    HB_SCRIPT_AVESTAN,
-    HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,
-    HB_SCRIPT_SAMARITAN,
-    HB_SCRIPT_LISU,
-    HB_SCRIPT_BAMUM,
-    HB_SCRIPT_JAVANESE,
-    HB_SCRIPT_MEETEI_MAYEK,
-    HB_SCRIPT_IMPERIAL_ARAMAIC,
-    HB_SCRIPT_OLD_SOUTH_ARABIAN,
-    HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
-    HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
-    HB_SCRIPT_OLD_TURKIC,
-    HB_SCRIPT_KAITHI,
-    HB_SCRIPT_BATAK,
-    HB_SCRIPT_BRAHMI,
-    HB_SCRIPT_MANDAIC,
-    HB_SCRIPT_CHAKMA,
-    HB_SCRIPT_MEROITIC_CURSIVE,
-    HB_SCRIPT_MEROITIC_HIEROGLYPHS,
-    HB_SCRIPT_MIAO,
-    HB_SCRIPT_SHARADA,
-    HB_SCRIPT_SORA_SOMPENG,
-    HB_SCRIPT_TAKRI,
-    HB_SCRIPT_UNKNOWN,
-    HB_SCRIPT_BASSA_VAH,
-    HB_SCRIPT_CAUCASIAN_ALBANIAN,
-    HB_SCRIPT_DUPLOYAN,
-    HB_SCRIPT_ELBASAN,
-    HB_SCRIPT_GRANTHA,
-    HB_SCRIPT_KHOJKI,
-    HB_SCRIPT_KHUDAWADI,
-    HB_SCRIPT_LINEAR_A,
-    HB_SCRIPT_MAHAJANI,
-    HB_SCRIPT_MANICHAEAN,
-    HB_SCRIPT_MENDE_KIKAKUI,
-    HB_SCRIPT_MODI,
-    HB_SCRIPT_MRO,
-    HB_SCRIPT_NABATAEAN,
-    HB_SCRIPT_OLD_NORTH_ARABIAN,
-    HB_SCRIPT_OLD_PERMIC,
-    HB_SCRIPT_PAHAWH_HMONG,
-    HB_SCRIPT_PALMYRENE,
-    HB_SCRIPT_PAU_CIN_HAU,
-    HB_SCRIPT_PSALTER_PAHLAVI,
-    HB_SCRIPT_SIDDHAM,
-    HB_SCRIPT_TIRHUTA,
-    HB_SCRIPT_WARANG_CITI,
-    HB_SCRIPT_AHOM,
-    HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
-    HB_SCRIPT_HATRAN,
-    HB_SCRIPT_MULTANI,
-    HB_SCRIPT_OLD_HUNGARIAN,
-    HB_SCRIPT_SIGNWRITING,
-    HB_SCRIPT_ADLAM,
-    HB_SCRIPT_BHAIKSUKI,
-    HB_SCRIPT_MARCHEN,
-    HB_SCRIPT_NEWA,
-    HB_SCRIPT_OSAGE,
-    HB_SCRIPT_TANGUT,
-    HB_SCRIPT_MASARAM_GONDI,
-    HB_SCRIPT_NUSHU,
-    HB_SCRIPT_SOYOMBO,
-    HB_SCRIPT_ZANABAZAR_SQUARE,
-    HB_SCRIPT_DOGRA,
-    HB_SCRIPT_GUNJALA_GONDI,
-    HB_SCRIPT_HANIFI_ROHINGYA,
-    HB_SCRIPT_MAKASAR,
-    HB_SCRIPT_MEDEFAIDRIN,
-    HB_SCRIPT_OLD_SOGDIAN,
-    HB_SCRIPT_SOGDIAN,
-    HB_SCRIPT_ELYMAIC,
-    HB_SCRIPT_NANDINAGARI,
-    HB_SCRIPT_NYIAKENG_PUACHUE_HMONG,
-    HB_SCRIPT_WANCHO,
-};
-
-static hb_unicode_combining_class_t
-hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			hb_codepoint_t unicode,
-			void *user_data HB_UNUSED)
-{
-    return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode);
-}
-
-static hb_unicode_general_category_t
-hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-			 hb_codepoint_t unicode,
-			 void *user_data HB_UNUSED)
-{
-    return (hb_unicode_general_category_t)ucdn_get_general_category(unicode);
-}
-
-static hb_codepoint_t
-hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-		  hb_codepoint_t unicode,
-		  void *user_data HB_UNUSED)
-{
-    return ucdn_mirror(unicode);
-}
-
-static hb_script_t
-hb_ucdn_script(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-	       hb_codepoint_t unicode,
-	       void *user_data HB_UNUSED)
-{
-    return ucdn_script_translate[ucdn_get_script(unicode)];
-}
-
-static hb_bool_t
-hb_ucdn_compose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
-		void *user_data HB_UNUSED)
-{
-    return ucdn_compose(ab, a, b);
-}
-
-static hb_bool_t
-hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
-		  void *user_data HB_UNUSED)
-{
-    return ucdn_decompose(ab, a, b);
-}
-
-
-#if HB_USE_ATEXIT
-static void free_static_ucdn_funcs ();
-#endif
-
-static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucdn_unicode_funcs_lazy_loader_t>
-{
-  static hb_unicode_funcs_t *create ()
-  {
-    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
-
-    hb_unicode_funcs_set_combining_class_func (funcs, hb_ucdn_combining_class, nullptr, nullptr);
-    hb_unicode_funcs_set_general_category_func (funcs, hb_ucdn_general_category, nullptr, nullptr);
-    hb_unicode_funcs_set_mirroring_func (funcs, hb_ucdn_mirroring, nullptr, nullptr);
-    hb_unicode_funcs_set_script_func (funcs, hb_ucdn_script, nullptr, nullptr);
-    hb_unicode_funcs_set_compose_func (funcs, hb_ucdn_compose, nullptr, nullptr);
-    hb_unicode_funcs_set_decompose_func (funcs, hb_ucdn_decompose, nullptr, nullptr);
-
-    hb_unicode_funcs_make_immutable (funcs);
-
-#if HB_USE_ATEXIT
-    atexit (free_static_ucdn_funcs);
-#endif
-
-    return funcs;
-  }
-} static_ucdn_funcs;
-
-#if HB_USE_ATEXIT
-static
-void free_static_ucdn_funcs ()
-{
-  static_ucdn_funcs.free_instance ();
-}
-#endif
-
-extern "C" HB_INTERNAL
-hb_unicode_funcs_t *
-hb_ucdn_get_unicode_funcs ();
-
-hb_unicode_funcs_t *
-hb_ucdn_get_unicode_funcs ()
-{
-  return static_ucdn_funcs.get_unconst ();
-}
diff --git a/src/hb-ucdn/COPYING b/src/hb-ucdn/COPYING
deleted file mode 100644
index be5205c..0000000
--- a/src/hb-ucdn/COPYING
+++ /dev/null
@@ -1,13 +0,0 @@
-The contents of this directory are licensed under the following terms:
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/hb-ucdn/Makefile.am b/src/hb-ucdn/Makefile.am
deleted file mode 100644
index 73b5502..0000000
--- a/src/hb-ucdn/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-noinst_LTLIBRARIES = libhb-ucdn.la
-
-include Makefile.sources
-
-libhb_ucdn_la_SOURCES = $(LIBHB_UCDN_sources)
-libhb_ucdn_la_CPPFLAGS = \
-	-I$(top_srcdir) \
-	-I$(top_srcdir)/src \
-	-I$(top_builddir)/src
-libhb_ucdn_la_LIBADD =
-
-EXTRA_DIST = README COPYING
-
--include $(top_srcdir)/git.mk
diff --git a/src/hb-ucdn/Makefile.sources b/src/hb-ucdn/Makefile.sources
deleted file mode 100644
index cb823b6..0000000
--- a/src/hb-ucdn/Makefile.sources
+++ /dev/null
@@ -1,7 +0,0 @@
-NULL =
-
-LIBHB_UCDN_sources = \
-	ucdn.h \
-	ucdn.c \
-	ucdn_db.h \
-	$(NULL)
diff --git a/src/hb-ucdn/README b/src/hb-ucdn/README
deleted file mode 100644
index 2203ae6..0000000
--- a/src/hb-ucdn/README
+++ /dev/null
@@ -1,40 +0,0 @@
-Contents of this directory are derived from UCDN:
-
-  https://github.com/grigorig/ucdn
-
-The original README follows:
-
-
-UCDN - Unicode Database and Normalization
-
-UCDN is a Unicode support library. Currently, it provides access
-to basic character properties contained in the Unicode Character
-Database and low-level normalization functions (pairwise canonical
-composition/decomposition and compatibility decomposition). More
-functionality might be provided in the future, such as additional
-properties, string normalization and encoding conversion.
-
-UCDN uses standard C89 with no particular dependencies or requirements
-except for stdint.h, and can be easily integrated into existing
-projects. However, it can also be used as a standalone library,
-and a CMake build script is provided for this. The first motivation
-behind UCDN development was to provide a standalone set of Unicode
-functions for the HarfBuzz OpenType shaping library. For this purpose,
-a HarfBuzz-specific wrapper is shipped along with it (hb-ucdn.h).
-
-UCDN is published under the ISC license, please see the license header
-in the C source code for more information. The makeunicodata.py script
-required for parsing Unicode database files is licensed under the
-PSF license, please see PYTHON-LICENSE for more information.
-
-UCDN was written by Grigori Goronzy <greg@kinoho.net>.
-
-How to Use
-
-Include ucdn.c, ucdn.h and ucdn_db.h in your project. Now, just use the
-functions as documented in ucdn.h.
-
-In some cases, it might be necessary to regenerate the Unicode
-database file. The script makeunicodedata.py (Python 3.x required)
-fetches the appropriate files and dumps the compressed database into
-ucdn_db.h.
diff --git a/src/hb-ucdn/ucdn.c b/src/hb-ucdn/ucdn.c
deleted file mode 100644
index 30747fe..0000000
--- a/src/hb-ucdn/ucdn.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "ucdn.h"
-
-typedef struct {
-    unsigned char category;
-    unsigned char combining;
-    unsigned char bidi_class;
-    unsigned char east_asian_width;
-    unsigned char script;
-    unsigned char linebreak_class;
-} UCDRecord;
-
-typedef struct {
-    unsigned short from, to;
-} MirrorPair;
-
-typedef struct {
-  unsigned short from, to;
-  unsigned char type;
-} BracketPair;
-
-typedef struct {
-    unsigned int start;
-    short count, index;
-} Reindex;
-
-#include "ucdn_db.h"
-
-/* constants required for Hangul (de)composition */
-#define SBASE 0xAC00
-#define LBASE 0x1100
-#define VBASE 0x1161
-#define TBASE 0x11A7
-#define SCOUNT 11172
-#define LCOUNT 19
-#define VCOUNT 21
-#define TCOUNT 28
-#define NCOUNT (VCOUNT * TCOUNT)
-
-static const UCDRecord *get_ucd_record(uint32_t code)
-{
-    int index, offset;
-
-    if (code >= 0x110000)
-        index = 0;
-    else {
-        index  = index0[code >> (SHIFT1+SHIFT2)] << SHIFT1;
-        offset = (code >> SHIFT2) & ((1<<SHIFT1) - 1);
-        index  = index1[index + offset] << SHIFT2;
-        offset = code & ((1<<SHIFT2) - 1);
-        index  = index2[index + offset];
-    }
-
-    return &ucd_records[index];
-}
-
-static const unsigned short *get_decomp_record(uint32_t code)
-{
-    int index, offset;
-
-    if (code >= 0x110000)
-        index = 0;
-    else {
-        index  = decomp_index0[code >> (DECOMP_SHIFT1+DECOMP_SHIFT2)]
-            << DECOMP_SHIFT1;
-        offset = (code >> DECOMP_SHIFT2) & ((1<<DECOMP_SHIFT1) - 1);
-        index  = decomp_index1[index + offset] << DECOMP_SHIFT2;
-        offset = code & ((1<<DECOMP_SHIFT2) - 1);
-        index  = decomp_index2[index + offset];
-    }
-
-    return &decomp_data[index];
-}
-
-static int compare_reindex(const void *a, const void *b)
-{
-    Reindex *ra = (Reindex *)a;
-    Reindex *rb = (Reindex *)b;
-
-    if (ra->start < rb->start)
-        return -1;
-    else if (ra->start > (rb->start + rb->count))
-        return 1;
-    else
-        return 0;
-}
-
-static int get_comp_index(uint32_t code, const Reindex *idx, size_t len)
-{
-    Reindex *res;
-    Reindex r = {0, 0, 0};
-    r.start = code;
-    res = (Reindex *) bsearch(&r, idx, len, sizeof(Reindex), compare_reindex);
-
-    if (res != NULL)
-        return res->index + (code - res->start);
-    else
-        return -1;
-}
-
-static int compare_mp(const void *a, const void *b)
-{
-    MirrorPair *mpa = (MirrorPair *)a;
-    MirrorPair *mpb = (MirrorPair *)b;
-    return mpa->from - mpb->from;
-}
-
-static int compare_bp(const void *a, const void *b)
-{
-    BracketPair *bpa = (BracketPair *)a;
-    BracketPair *bpb = (BracketPair *)b;
-    return bpa->from - bpb->from;
-}
-
-static BracketPair *search_bp(uint32_t code)
-{
-    BracketPair bp = {0,0,2};
-    BracketPair *res;
-
-    bp.from = code;
-    res = (BracketPair *) bsearch(&bp, bracket_pairs, BIDI_BRACKET_LEN,
-                                 sizeof(BracketPair), compare_bp);
-    return res;
-}
-
-static int hangul_pair_decompose(uint32_t code, uint32_t *a, uint32_t *b)
-{
-    int si = code - SBASE;
-
-    if (si < 0 || si >= SCOUNT)
-        return 0;
-
-    if (si % TCOUNT) {
-        /* LV,T */
-        *a = SBASE + (si / TCOUNT) * TCOUNT;
-        *b = TBASE + (si % TCOUNT);
-        return 3;
-    } else {
-        /* L,V */
-        *a = LBASE + (si / NCOUNT);
-        *b = VBASE + (si % NCOUNT) / TCOUNT;
-        return 2;
-    }
-}
-
-static int hangul_pair_compose(uint32_t *code, uint32_t a, uint32_t b)
-{
-    if (a >= SBASE && a < (SBASE + SCOUNT) && b >= TBASE && b < (TBASE + TCOUNT)) {
-        /* LV,T */
-        *code = a + (b - TBASE);
-        return 3;
-    } else if (a >= LBASE && a < (LBASE + LCOUNT) && b >= VBASE && b < (VBASE + VCOUNT)) {
-        /* L,V */
-        int li = a - LBASE;
-        int vi = b - VBASE;
-        *code = SBASE + li * NCOUNT + vi * TCOUNT;
-        return 2;
-    } else {
-        return 0;
-    }
-}
-
-static uint32_t decode_utf16(const unsigned short **code_ptr)
-{
-    const unsigned short *code = *code_ptr;
-
-    if (code[0] < 0xd800 || code[0] > 0xdc00) {
-        *code_ptr += 1;
-        return (uint32_t)code[0];
-    } else {
-        *code_ptr += 2;
-        return 0x10000 + ((uint32_t)code[1] - 0xdc00) +
-            (((uint32_t)code[0] - 0xd800) << 10);
-    }
-}
-
-const char *ucdn_get_unicode_version(void)
-{
-    return UNIDATA_VERSION;
-}
-
-int ucdn_get_combining_class(uint32_t code)
-{
-    return get_ucd_record(code)->combining;
-}
-
-int ucdn_get_east_asian_width(uint32_t code)
-{
-    return get_ucd_record(code)->east_asian_width;
-}
-
-int ucdn_get_general_category(uint32_t code)
-{
-    return get_ucd_record(code)->category;
-}
-
-int ucdn_get_bidi_class(uint32_t code)
-{
-    return get_ucd_record(code)->bidi_class;
-}
-
-int ucdn_get_mirrored(uint32_t code)
-{
-    return ucdn_mirror(code) != code;
-}
-
-int ucdn_get_script(uint32_t code)
-{
-    return get_ucd_record(code)->script;
-}
-
-int ucdn_get_linebreak_class(uint32_t code)
-{
-    return get_ucd_record(code)->linebreak_class;
-}
-
-int ucdn_get_resolved_linebreak_class(uint32_t code)
-{
-    const UCDRecord *record = get_ucd_record(code);
-
-    switch (record->linebreak_class)
-    {
-    case UCDN_LINEBREAK_CLASS_AI:
-    case UCDN_LINEBREAK_CLASS_SG:
-    case UCDN_LINEBREAK_CLASS_XX:
-        return UCDN_LINEBREAK_CLASS_AL;
-
-    case UCDN_LINEBREAK_CLASS_SA:
-        if (record->category == UCDN_GENERAL_CATEGORY_MC ||
-                record->category == UCDN_GENERAL_CATEGORY_MN)
-            return UCDN_LINEBREAK_CLASS_CM;
-        return UCDN_LINEBREAK_CLASS_AL;
-
-    case UCDN_LINEBREAK_CLASS_CJ:
-        return UCDN_LINEBREAK_CLASS_NS;
-
-    case UCDN_LINEBREAK_CLASS_CB:
-        return UCDN_LINEBREAK_CLASS_B2;
-
-    case UCDN_LINEBREAK_CLASS_NL:
-        return UCDN_LINEBREAK_CLASS_BK;
-
-    default:
-        return record->linebreak_class;
-    }
-}
-
-uint32_t ucdn_mirror(uint32_t code)
-{
-    MirrorPair mp = {0};
-    MirrorPair *res;
-
-    mp.from = code;
-    res = (MirrorPair *) bsearch(&mp, mirror_pairs, BIDI_MIRROR_LEN,
-                                sizeof(MirrorPair), compare_mp);
-
-    if (res == NULL)
-        return code;
-    else
-        return res->to;
-}
-
-uint32_t ucdn_paired_bracket(uint32_t code)
-{
-    BracketPair *res = search_bp(code);
-    if (res == NULL)
-        return code;
-    else
-        return res->to;
-}
-
-int ucdn_paired_bracket_type(uint32_t code)
-{
-    BracketPair *res = search_bp(code);
-    if (res == NULL)
-        return UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE;
-    else
-        return res->type;
-}
-
-int ucdn_decompose(uint32_t code, uint32_t *a, uint32_t *b)
-{
-    const unsigned short *rec;
-    int len;
-
-    if (hangul_pair_decompose(code, a, b))
-        return 1;
-
-    rec = get_decomp_record(code);
-    len = rec[0] >> 8;
-
-    if ((rec[0] & 0xff) != 0 || len == 0)
-        return 0;
-
-    rec++;
-    *a = decode_utf16(&rec);
-    if (len > 1)
-        *b = decode_utf16(&rec);
-    else
-        *b = 0;
-
-    return 1;
-}
-
-int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b)
-{
-    int l, r, index, indexi, offset;
-
-    if (hangul_pair_compose(code, a, b))
-        return 1;
-
-    l = get_comp_index(a, nfc_first, sizeof(nfc_first) / sizeof(Reindex));
-    r = get_comp_index(b, nfc_last, sizeof(nfc_last) / sizeof(Reindex));
-
-    if (l < 0 || r < 0)
-        return 0;
-
-    indexi = l * TOTAL_LAST + r;
-    index  = comp_index0[indexi >> (COMP_SHIFT1+COMP_SHIFT2)] << COMP_SHIFT1;
-    offset = (indexi >> COMP_SHIFT2) & ((1<<COMP_SHIFT1) - 1);
-    index  = comp_index1[index + offset] << COMP_SHIFT2;
-    offset = indexi & ((1<<COMP_SHIFT2) - 1);
-    *code  = comp_data[index + offset];
-
-    return *code != 0;
-}
-
-int ucdn_compat_decompose(uint32_t code, uint32_t *decomposed)
-{
-    int i, len;
-    const unsigned short *rec = get_decomp_record(code);
-    len = rec[0] >> 8;
-
-    if (len == 0)
-        return 0;
-
-    rec++;
-    for (i = 0; i < len; i++)
-        decomposed[i] = decode_utf16(&rec);
-
-    return len;
-}
diff --git a/src/hb-ucdn/ucdn.h b/src/hb-ucdn/ucdn.h
deleted file mode 100644
index 1317d4f..0000000
--- a/src/hb-ucdn/ucdn.h
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UCDN_H
-#define UCDN_H
-
-
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
-# define HB_BEGIN_VISIBILITY _Pragma ("GCC visibility push(hidden)")
-# define HB_END_VISIBILITY _Pragma ("GCC visibility pop")
-#else
-# define HB_BEGIN_VISIBILITY
-# define HB_END_VISIBILITY
-#endif
-#ifdef __cplusplus
-# define HB_BEGIN_HEADER  extern "C" { HB_BEGIN_VISIBILITY
-# define HB_END_HEADER  HB_END_VISIBILITY }
-#else
-# define HB_BEGIN_HEADER  HB_BEGIN_VISIBILITY
-# define HB_END_HEADER  HB_END_VISIBILITY
-#endif
-
-HB_BEGIN_HEADER
-
-#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
-    defined (_sgi) || defined (__sun) || defined (sun) || \
-    defined (__digital__) || defined (__HP_cc)
-#  include <inttypes.h>
-#elif defined (_AIX)
-#  include <sys/inttypes.h>
-#elif defined (_MSC_VER) && _MSC_VER < 1600
-/* VS 2010 (_MSC_VER 1600) has stdint.h */
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-#else
-#  include <stdint.h>
-#endif
-
-
-#define UCDN_EAST_ASIAN_F 0
-#define UCDN_EAST_ASIAN_H 1
-#define UCDN_EAST_ASIAN_W 2
-#define UCDN_EAST_ASIAN_NA 3
-#define UCDN_EAST_ASIAN_A 4
-#define UCDN_EAST_ASIAN_N 5
-
-#define UCDN_SCRIPT_COMMON 0
-#define UCDN_SCRIPT_LATIN 1
-#define UCDN_SCRIPT_GREEK 2
-#define UCDN_SCRIPT_CYRILLIC 3
-#define UCDN_SCRIPT_ARMENIAN 4
-#define UCDN_SCRIPT_HEBREW 5
-#define UCDN_SCRIPT_ARABIC 6
-#define UCDN_SCRIPT_SYRIAC 7
-#define UCDN_SCRIPT_THAANA 8
-#define UCDN_SCRIPT_DEVANAGARI 9
-#define UCDN_SCRIPT_BENGALI 10
-#define UCDN_SCRIPT_GURMUKHI 11
-#define UCDN_SCRIPT_GUJARATI 12
-#define UCDN_SCRIPT_ORIYA 13
-#define UCDN_SCRIPT_TAMIL 14
-#define UCDN_SCRIPT_TELUGU 15
-#define UCDN_SCRIPT_KANNADA 16
-#define UCDN_SCRIPT_MALAYALAM 17
-#define UCDN_SCRIPT_SINHALA 18
-#define UCDN_SCRIPT_THAI 19
-#define UCDN_SCRIPT_LAO 20
-#define UCDN_SCRIPT_TIBETAN 21
-#define UCDN_SCRIPT_MYANMAR 22
-#define UCDN_SCRIPT_GEORGIAN 23
-#define UCDN_SCRIPT_HANGUL 24
-#define UCDN_SCRIPT_ETHIOPIC 25
-#define UCDN_SCRIPT_CHEROKEE 26
-#define UCDN_SCRIPT_CANADIAN_ABORIGINAL 27
-#define UCDN_SCRIPT_OGHAM 28
-#define UCDN_SCRIPT_RUNIC 29
-#define UCDN_SCRIPT_KHMER 30
-#define UCDN_SCRIPT_MONGOLIAN 31
-#define UCDN_SCRIPT_HIRAGANA 32
-#define UCDN_SCRIPT_KATAKANA 33
-#define UCDN_SCRIPT_BOPOMOFO 34
-#define UCDN_SCRIPT_HAN 35
-#define UCDN_SCRIPT_YI 36
-#define UCDN_SCRIPT_OLD_ITALIC 37
-#define UCDN_SCRIPT_GOTHIC 38
-#define UCDN_SCRIPT_DESERET 39
-#define UCDN_SCRIPT_INHERITED 40
-#define UCDN_SCRIPT_TAGALOG 41
-#define UCDN_SCRIPT_HANUNOO 42
-#define UCDN_SCRIPT_BUHID 43
-#define UCDN_SCRIPT_TAGBANWA 44
-#define UCDN_SCRIPT_LIMBU 45
-#define UCDN_SCRIPT_TAI_LE 46
-#define UCDN_SCRIPT_LINEAR_B 47
-#define UCDN_SCRIPT_UGARITIC 48
-#define UCDN_SCRIPT_SHAVIAN 49
-#define UCDN_SCRIPT_OSMANYA 50
-#define UCDN_SCRIPT_CYPRIOT 51
-#define UCDN_SCRIPT_BRAILLE 52
-#define UCDN_SCRIPT_BUGINESE 53
-#define UCDN_SCRIPT_COPTIC 54
-#define UCDN_SCRIPT_NEW_TAI_LUE 55
-#define UCDN_SCRIPT_GLAGOLITIC 56
-#define UCDN_SCRIPT_TIFINAGH 57
-#define UCDN_SCRIPT_SYLOTI_NAGRI 58
-#define UCDN_SCRIPT_OLD_PERSIAN 59
-#define UCDN_SCRIPT_KHAROSHTHI 60
-#define UCDN_SCRIPT_BALINESE 61
-#define UCDN_SCRIPT_CUNEIFORM 62
-#define UCDN_SCRIPT_PHOENICIAN 63
-#define UCDN_SCRIPT_PHAGS_PA 64
-#define UCDN_SCRIPT_NKO 65
-#define UCDN_SCRIPT_SUNDANESE 66
-#define UCDN_SCRIPT_LEPCHA 67
-#define UCDN_SCRIPT_OL_CHIKI 68
-#define UCDN_SCRIPT_VAI 69
-#define UCDN_SCRIPT_SAURASHTRA 70
-#define UCDN_SCRIPT_KAYAH_LI 71
-#define UCDN_SCRIPT_REJANG 72
-#define UCDN_SCRIPT_LYCIAN 73
-#define UCDN_SCRIPT_CARIAN 74
-#define UCDN_SCRIPT_LYDIAN 75
-#define UCDN_SCRIPT_CHAM 76
-#define UCDN_SCRIPT_TAI_THAM 77
-#define UCDN_SCRIPT_TAI_VIET 78
-#define UCDN_SCRIPT_AVESTAN 79
-#define UCDN_SCRIPT_EGYPTIAN_HIEROGLYPHS 80
-#define UCDN_SCRIPT_SAMARITAN 81
-#define UCDN_SCRIPT_LISU 82
-#define UCDN_SCRIPT_BAMUM 83
-#define UCDN_SCRIPT_JAVANESE 84
-#define UCDN_SCRIPT_MEETEI_MAYEK 85
-#define UCDN_SCRIPT_IMPERIAL_ARAMAIC 86
-#define UCDN_SCRIPT_OLD_SOUTH_ARABIAN 87
-#define UCDN_SCRIPT_INSCRIPTIONAL_PARTHIAN 88
-#define UCDN_SCRIPT_INSCRIPTIONAL_PAHLAVI 89
-#define UCDN_SCRIPT_OLD_TURKIC 90
-#define UCDN_SCRIPT_KAITHI 91
-#define UCDN_SCRIPT_BATAK 92
-#define UCDN_SCRIPT_BRAHMI 93
-#define UCDN_SCRIPT_MANDAIC 94
-#define UCDN_SCRIPT_CHAKMA 95
-#define UCDN_SCRIPT_MEROITIC_CURSIVE 96
-#define UCDN_SCRIPT_MEROITIC_HIEROGLYPHS 97
-#define UCDN_SCRIPT_MIAO 98
-#define UCDN_SCRIPT_SHARADA 99
-#define UCDN_SCRIPT_SORA_SOMPENG 100
-#define UCDN_SCRIPT_TAKRI 101
-#define UCDN_SCRIPT_UNKNOWN 102
-#define UCDN_SCRIPT_BASSA_VAH 103
-#define UCDN_SCRIPT_CAUCASIAN_ALBANIAN 104
-#define UCDN_SCRIPT_DUPLOYAN 105
-#define UCDN_SCRIPT_ELBASAN 106
-#define UCDN_SCRIPT_GRANTHA 107
-#define UCDN_SCRIPT_KHOJKI 108
-#define UCDN_SCRIPT_KHUDAWADI 109
-#define UCDN_SCRIPT_LINEAR_A 110
-#define UCDN_SCRIPT_MAHAJANI 111
-#define UCDN_SCRIPT_MANICHAEAN 112
-#define UCDN_SCRIPT_MENDE_KIKAKUI 113
-#define UCDN_SCRIPT_MODI 114
-#define UCDN_SCRIPT_MRO 115
-#define UCDN_SCRIPT_NABATAEAN 116
-#define UCDN_SCRIPT_OLD_NORTH_ARABIAN 117
-#define UCDN_SCRIPT_OLD_PERMIC 118
-#define UCDN_SCRIPT_PAHAWH_HMONG 119
-#define UCDN_SCRIPT_PALMYRENE 120
-#define UCDN_SCRIPT_PAU_CIN_HAU 121
-#define UCDN_SCRIPT_PSALTER_PAHLAVI 122
-#define UCDN_SCRIPT_SIDDHAM 123
-#define UCDN_SCRIPT_TIRHUTA 124
-#define UCDN_SCRIPT_WARANG_CITI 125
-#define UCDN_SCRIPT_AHOM 126
-#define UCDN_SCRIPT_ANATOLIAN_HIEROGLYPHS 127
-#define UCDN_SCRIPT_HATRAN 128
-#define UCDN_SCRIPT_MULTANI 129
-#define UCDN_SCRIPT_OLD_HUNGARIAN 130
-#define UCDN_SCRIPT_SIGNWRITING 131
-#define UCDN_SCRIPT_ADLAM 132
-#define UCDN_SCRIPT_BHAIKSUKI 133
-#define UCDN_SCRIPT_MARCHEN 134
-#define UCDN_SCRIPT_NEWA 135
-#define UCDN_SCRIPT_OSAGE 136
-#define UCDN_SCRIPT_TANGUT 137
-#define UCDN_SCRIPT_MASARAM_GONDI 138
-#define UCDN_SCRIPT_NUSHU 139
-#define UCDN_SCRIPT_SOYOMBO 140
-#define UCDN_SCRIPT_ZANABAZAR_SQUARE 141
-#define UCDN_SCRIPT_DOGRA 142
-#define UCDN_SCRIPT_GUNJALA_GONDI 143
-#define UCDN_SCRIPT_HANIFI_ROHINGYA 144
-#define UCDN_SCRIPT_MAKASAR 145
-#define UCDN_SCRIPT_MEDEFAIDRIN 146
-#define UCDN_SCRIPT_OLD_SOGDIAN 147
-#define UCDN_SCRIPT_SOGDIAN 148
-#define UCDN_SCRIPT_ELYMAIC 149
-#define UCDN_SCRIPT_NANDINAGARI 150
-#define UCDN_SCRIPT_NYIAKENG_PUACHUE_HMONG 151
-#define UCDN_SCRIPT_WANCHO 152
-
-#define UCDN_LINEBREAK_CLASS_OP 0
-#define UCDN_LINEBREAK_CLASS_CL 1
-#define UCDN_LINEBREAK_CLASS_CP 2
-#define UCDN_LINEBREAK_CLASS_QU 3
-#define UCDN_LINEBREAK_CLASS_GL 4
-#define UCDN_LINEBREAK_CLASS_NS 5
-#define UCDN_LINEBREAK_CLASS_EX 6
-#define UCDN_LINEBREAK_CLASS_SY 7
-#define UCDN_LINEBREAK_CLASS_IS 8
-#define UCDN_LINEBREAK_CLASS_PR 9
-#define UCDN_LINEBREAK_CLASS_PO 10
-#define UCDN_LINEBREAK_CLASS_NU 11
-#define UCDN_LINEBREAK_CLASS_AL 12
-#define UCDN_LINEBREAK_CLASS_HL 13
-#define UCDN_LINEBREAK_CLASS_ID 14
-#define UCDN_LINEBREAK_CLASS_IN 15
-#define UCDN_LINEBREAK_CLASS_HY 16
-#define UCDN_LINEBREAK_CLASS_BA 17
-#define UCDN_LINEBREAK_CLASS_BB 18
-#define UCDN_LINEBREAK_CLASS_B2 19
-#define UCDN_LINEBREAK_CLASS_ZW 20
-#define UCDN_LINEBREAK_CLASS_CM 21
-#define UCDN_LINEBREAK_CLASS_WJ 22
-#define UCDN_LINEBREAK_CLASS_H2 23
-#define UCDN_LINEBREAK_CLASS_H3 24
-#define UCDN_LINEBREAK_CLASS_JL 25
-#define UCDN_LINEBREAK_CLASS_JV 26
-#define UCDN_LINEBREAK_CLASS_JT 27
-#define UCDN_LINEBREAK_CLASS_RI 28
-#define UCDN_LINEBREAK_CLASS_AI 29
-#define UCDN_LINEBREAK_CLASS_BK 30
-#define UCDN_LINEBREAK_CLASS_CB 31
-#define UCDN_LINEBREAK_CLASS_CJ 32
-#define UCDN_LINEBREAK_CLASS_CR 33
-#define UCDN_LINEBREAK_CLASS_LF 34
-#define UCDN_LINEBREAK_CLASS_NL 35
-#define UCDN_LINEBREAK_CLASS_SA 36
-#define UCDN_LINEBREAK_CLASS_SG 37
-#define UCDN_LINEBREAK_CLASS_SP 38
-#define UCDN_LINEBREAK_CLASS_XX 39
-#define UCDN_LINEBREAK_CLASS_ZWJ 40
-#define UCDN_LINEBREAK_CLASS_EB 41
-#define UCDN_LINEBREAK_CLASS_EM 42
-
-#define UCDN_GENERAL_CATEGORY_CC 0
-#define UCDN_GENERAL_CATEGORY_CF 1
-#define UCDN_GENERAL_CATEGORY_CN 2
-#define UCDN_GENERAL_CATEGORY_CO 3
-#define UCDN_GENERAL_CATEGORY_CS 4
-#define UCDN_GENERAL_CATEGORY_LL 5
-#define UCDN_GENERAL_CATEGORY_LM 6
-#define UCDN_GENERAL_CATEGORY_LO 7
-#define UCDN_GENERAL_CATEGORY_LT 8
-#define UCDN_GENERAL_CATEGORY_LU 9
-#define UCDN_GENERAL_CATEGORY_MC 10
-#define UCDN_GENERAL_CATEGORY_ME 11
-#define UCDN_GENERAL_CATEGORY_MN 12
-#define UCDN_GENERAL_CATEGORY_ND 13
-#define UCDN_GENERAL_CATEGORY_NL 14
-#define UCDN_GENERAL_CATEGORY_NO 15
-#define UCDN_GENERAL_CATEGORY_PC 16
-#define UCDN_GENERAL_CATEGORY_PD 17
-#define UCDN_GENERAL_CATEGORY_PE 18
-#define UCDN_GENERAL_CATEGORY_PF 19
-#define UCDN_GENERAL_CATEGORY_PI 20
-#define UCDN_GENERAL_CATEGORY_PO 21
-#define UCDN_GENERAL_CATEGORY_PS 22
-#define UCDN_GENERAL_CATEGORY_SC 23
-#define UCDN_GENERAL_CATEGORY_SK 24
-#define UCDN_GENERAL_CATEGORY_SM 25
-#define UCDN_GENERAL_CATEGORY_SO 26
-#define UCDN_GENERAL_CATEGORY_ZL 27
-#define UCDN_GENERAL_CATEGORY_ZP 28
-#define UCDN_GENERAL_CATEGORY_ZS 29
-
-#define UCDN_BIDI_CLASS_L 0
-#define UCDN_BIDI_CLASS_LRE 1
-#define UCDN_BIDI_CLASS_LRO 2
-#define UCDN_BIDI_CLASS_R 3
-#define UCDN_BIDI_CLASS_AL 4
-#define UCDN_BIDI_CLASS_RLE 5
-#define UCDN_BIDI_CLASS_RLO 6
-#define UCDN_BIDI_CLASS_PDF 7
-#define UCDN_BIDI_CLASS_EN 8
-#define UCDN_BIDI_CLASS_ES 9
-#define UCDN_BIDI_CLASS_ET 10
-#define UCDN_BIDI_CLASS_AN 11
-#define UCDN_BIDI_CLASS_CS 12
-#define UCDN_BIDI_CLASS_NSM 13
-#define UCDN_BIDI_CLASS_BN 14
-#define UCDN_BIDI_CLASS_B 15
-#define UCDN_BIDI_CLASS_S 16
-#define UCDN_BIDI_CLASS_WS 17
-#define UCDN_BIDI_CLASS_ON 18
-#define UCDN_BIDI_CLASS_LRI 19
-#define UCDN_BIDI_CLASS_RLI 20
-#define UCDN_BIDI_CLASS_FSI 21
-#define UCDN_BIDI_CLASS_PDI 22
-
-#define UCDN_BIDI_PAIRED_BRACKET_TYPE_OPEN 0
-#define UCDN_BIDI_PAIRED_BRACKET_TYPE_CLOSE 1
-#define UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE 2
-
-/**
- * Return version of the Unicode database.
- *
- * @return Unicode database version
- */
-const char *ucdn_get_unicode_version(void);
-
-/**
- * Get combining class of a codepoint.
- *
- * @param code Unicode codepoint
- * @return combining class value, as defined in UAX#44
- */
-int ucdn_get_combining_class(uint32_t code);
-
-/**
- * Get east-asian width of a codepoint.
- *
- * @param code Unicode codepoint
- * @return value according to UCDN_EAST_ASIAN_* and as defined in UAX#11.
- */
-int ucdn_get_east_asian_width(uint32_t code);
-
-/**
- * Get general category of a codepoint.
- *
- * @param code Unicode codepoint
- * @return value according to UCDN_GENERAL_CATEGORY_* and as defined in
- * UAX#44.
- */
-int ucdn_get_general_category(uint32_t code);
-
-/**
- * Get bidirectional class of a codepoint.
- *
- * @param code Unicode codepoint
- * @return value according to UCDN_BIDI_CLASS_* and as defined in UAX#44.
- */
-int ucdn_get_bidi_class(uint32_t code);
-
-/**
- * Get script of a codepoint.
- *
- * @param code Unicode codepoint
- * @return value according to UCDN_SCRIPT_* and as defined in UAX#24.
- */
-int ucdn_get_script(uint32_t code);
-
-/**
- * Get unresolved linebreak class of a codepoint. This does not take
- * rule LB1 of UAX#14 into account. See ucdn_get_resolved_linebreak_class()
- * for resolved linebreak classes.
- *
- * @param code Unicode codepoint
- * @return value according to UCDN_LINEBREAK_* and as defined in UAX#14.
- */
-int ucdn_get_linebreak_class(uint32_t code);
-
-/**
- * Get resolved linebreak class of a codepoint. This resolves characters
- * in the AI, SG, XX, SA and CJ classes according to rule LB1 of UAX#14.
- * In addition the CB class is resolved as the equivalent B2 class and
- * the NL class is resolved as the equivalent BK class.
- *
- * @param code Unicode codepoint
- * @return value according to UCDN_LINEBREAK_* and as defined in UAX#14.
- */
-int ucdn_get_resolved_linebreak_class(uint32_t code);
-
-/**
- * Check if codepoint can be mirrored.
- *
- * @param code Unicode codepoint
- * @return 1 if mirrored character exists, otherwise 0
- */
-int ucdn_get_mirrored(uint32_t code);
-
-/**
- * Mirror a codepoint.
- *
- * @param code Unicode codepoint
- * @return mirrored codepoint or the original codepoint if no
- * mirrored character exists
- */
-uint32_t ucdn_mirror(uint32_t code);
-
-/**
- * Get paired bracket for a codepoint.
- *
- * @param code Unicode codepoint
- * @return paired bracket codepoint or the original codepoint if no
- * paired bracket character exists
- */
-uint32_t ucdn_paired_bracket(uint32_t code);
-
-/**
- * Get paired bracket type for a codepoint.
- *
- * @param code Unicode codepoint
- * @return value according to UCDN_BIDI_PAIRED_BRACKET_TYPE_* and as defined
- * in UAX#9.
- *
- */
-int ucdn_paired_bracket_type(uint32_t code);
-
-/**
- * Pairwise canonical decomposition of a codepoint. This includes
- * Hangul Jamo decomposition (see chapter 3.12 of the Unicode core
- * specification).
- *
- * Hangul is decomposed into L and V jamos for LV forms, and an
- * LV precomposed syllable and a T jamo for LVT forms.
- *
- * @param code Unicode codepoint
- * @param a filled with first codepoint of decomposition
- * @param b filled with second codepoint of decomposition, or 0
- * @return success
- */
-int ucdn_decompose(uint32_t code, uint32_t *a, uint32_t *b);
-
-/**
- * Compatibility decomposition of a codepoint.
- *
- * @param code Unicode codepoint
- * @param decomposed filled with decomposition, must be able to hold 18
- * characters
- * @return length of decomposition or 0 in case none exists
- */
-int ucdn_compat_decompose(uint32_t code, uint32_t *decomposed);
-
-/**
- * Pairwise canonical composition of two codepoints. This includes
- * Hangul Jamo composition (see chapter 3.12 of the Unicode core
- * specification).
- *
- * Hangul composition expects either L and V jamos, or an LV
- * precomposed syllable and a T jamo. This is exactly the inverse
- * of pairwise Hangul decomposition.
- *
- * @param code filled with composition
- * @param a first codepoint
- * @param b second codepoint
- * @return success
- */
-int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b);
-
-HB_END_HEADER
-
-#endif
diff --git a/src/hb-ucdn/ucdn_db.h b/src/hb-ucdn/ucdn_db.h
deleted file mode 100644
index 8f1310f..0000000
--- a/src/hb-ucdn/ucdn_db.h
+++ /dev/null
@@ -1,5790 +0,0 @@
-/* this file was generated by makeunicodedata.py 3.2 */
-
-#define UNIDATA_VERSION "12.0.0"
-/* a list of unique database records */
-static const UCDRecord ucd_records[] = {
-    {2, 0, 18, 5, 102, 39},
-    {0, 0, 14, 5, 0, 21},
-    {0, 0, 16, 5, 0, 17},
-    {0, 0, 15, 5, 0, 34},
-    {0, 0, 16, 5, 0, 30},
-    {0, 0, 17, 5, 0, 30},
-    {0, 0, 15, 5, 0, 33},
-    {0, 0, 15, 5, 0, 21},
-    {0, 0, 16, 5, 0, 21},
-    {29, 0, 17, 3, 0, 38},
-    {21, 0, 18, 3, 0, 6},
-    {21, 0, 18, 3, 0, 3},
-    {21, 0, 10, 3, 0, 12},
-    {23, 0, 10, 3, 0, 9},
-    {21, 0, 10, 3, 0, 10},
-    {21, 0, 18, 3, 0, 12},
-    {22, 0, 18, 3, 0, 0},
-    {18, 0, 18, 3, 0, 2},
-    {25, 0, 9, 3, 0, 9},
-    {21, 0, 12, 3, 0, 8},
-    {17, 0, 9, 3, 0, 16},
-    {21, 0, 12, 3, 0, 7},
-    {13, 0, 8, 3, 0, 11},
-    {21, 0, 18, 3, 0, 8},
-    {25, 0, 18, 3, 0, 12},
-    {9, 0, 0, 3, 1, 12},
-    {21, 0, 18, 3, 0, 9},
-    {24, 0, 18, 3, 0, 12},
-    {16, 0, 18, 3, 0, 12},
-    {5, 0, 0, 3, 1, 12},
-    {25, 0, 18, 3, 0, 17},
-    {18, 0, 18, 3, 0, 1},
-    {0, 0, 15, 5, 0, 35},
-    {29, 0, 12, 5, 0, 4},
-    {21, 0, 18, 4, 0, 0},
-    {23, 0, 10, 3, 0, 10},
-    {23, 0, 10, 4, 0, 9},
-    {26, 0, 18, 3, 0, 12},
-    {21, 0, 18, 4, 0, 29},
-    {24, 0, 18, 4, 0, 29},
-    {26, 0, 18, 5, 0, 12},
-    {7, 0, 0, 4, 1, 29},
-    {20, 0, 18, 5, 0, 3},
-    {1, 0, 14, 4, 0, 17},
-    {26, 0, 18, 4, 0, 12},
-    {26, 0, 10, 4, 0, 10},
-    {25, 0, 10, 4, 0, 9},
-    {15, 0, 8, 4, 0, 29},
-    {24, 0, 18, 4, 0, 18},
-    {5, 0, 0, 5, 0, 12},
-    {19, 0, 18, 5, 0, 3},
-    {15, 0, 18, 4, 0, 29},
-    {9, 0, 0, 5, 1, 12},
-    {9, 0, 0, 4, 1, 12},
-    {25, 0, 18, 4, 0, 29},
-    {5, 0, 0, 4, 1, 12},
-    {5, 0, 0, 5, 1, 12},
-    {7, 0, 0, 5, 1, 12},
-    {8, 0, 0, 5, 1, 12},
-    {6, 0, 0, 5, 1, 12},
-    {6, 0, 18, 5, 0, 12},
-    {6, 0, 0, 5, 0, 12},
-    {24, 0, 18, 5, 0, 12},
-    {24, 0, 18, 4, 0, 12},
-    {6, 0, 18, 4, 0, 29},
-    {6, 0, 18, 5, 0, 18},
-    {6, 0, 0, 4, 0, 29},
-    {24, 0, 18, 5, 34, 12},
-    {12, 230, 13, 4, 40, 21},
-    {12, 232, 13, 4, 40, 21},
-    {12, 220, 13, 4, 40, 21},
-    {12, 216, 13, 4, 40, 21},
-    {12, 202, 13, 4, 40, 21},
-    {12, 1, 13, 4, 40, 21},
-    {12, 240, 13, 4, 40, 21},
-    {12, 0, 13, 4, 40, 4},
-    {12, 233, 13, 4, 40, 4},
-    {12, 234, 13, 4, 40, 4},
-    {9, 0, 0, 5, 2, 12},
-    {5, 0, 0, 5, 2, 12},
-    {24, 0, 18, 5, 2, 12},
-    {2, 0, 18, 5, 102, 39},
-    {6, 0, 0, 5, 2, 12},
-    {21, 0, 18, 5, 0, 8},
-    {21, 0, 18, 5, 0, 12},
-    {9, 0, 0, 4, 2, 12},
-    {5, 0, 0, 4, 2, 12},
-    {9, 0, 0, 5, 54, 12},
-    {5, 0, 0, 5, 54, 12},
-    {25, 0, 18, 5, 2, 12},
-    {9, 0, 0, 5, 3, 12},
-    {9, 0, 0, 4, 3, 12},
-    {5, 0, 0, 4, 3, 12},
-    {5, 0, 0, 5, 3, 12},
-    {26, 0, 0, 5, 3, 12},
-    {12, 230, 13, 5, 3, 21},
-    {12, 230, 13, 5, 40, 21},
-    {11, 0, 13, 5, 3, 21},
-    {9, 0, 0, 5, 4, 12},
-    {6, 0, 0, 5, 4, 12},
-    {21, 0, 0, 5, 4, 12},
-    {5, 0, 0, 5, 4, 12},
-    {21, 0, 0, 5, 0, 8},
-    {17, 0, 18, 5, 4, 17},
-    {26, 0, 18, 5, 4, 12},
-    {23, 0, 10, 5, 4, 9},
-    {12, 220, 13, 5, 5, 21},
-    {12, 230, 13, 5, 5, 21},
-    {12, 222, 13, 5, 5, 21},
-    {12, 228, 13, 5, 5, 21},
-    {12, 10, 13, 5, 5, 21},
-    {12, 11, 13, 5, 5, 21},
-    {12, 12, 13, 5, 5, 21},
-    {12, 13, 13, 5, 5, 21},
-    {12, 14, 13, 5, 5, 21},
-    {12, 15, 13, 5, 5, 21},
-    {12, 16, 13, 5, 5, 21},
-    {12, 17, 13, 5, 5, 21},
-    {12, 18, 13, 5, 5, 21},
-    {12, 19, 13, 5, 5, 21},
-    {12, 20, 13, 5, 5, 21},
-    {12, 21, 13, 5, 5, 21},
-    {12, 22, 13, 5, 5, 21},
-    {17, 0, 3, 5, 5, 17},
-    {12, 23, 13, 5, 5, 21},
-    {21, 0, 3, 5, 5, 12},
-    {12, 24, 13, 5, 5, 21},
-    {12, 25, 13, 5, 5, 21},
-    {21, 0, 3, 5, 5, 6},
-    {7, 0, 3, 5, 5, 13},
-    {1, 0, 11, 5, 6, 12},
-    {1, 0, 11, 5, 0, 12},
-    {25, 0, 18, 5, 6, 12},
-    {25, 0, 4, 5, 6, 12},
-    {21, 0, 10, 5, 6, 10},
-    {23, 0, 4, 5, 6, 10},
-    {21, 0, 12, 5, 0, 8},
-    {21, 0, 4, 5, 6, 8},
-    {26, 0, 18, 5, 6, 12},
-    {12, 230, 13, 5, 6, 21},
-    {12, 30, 13, 5, 6, 21},
-    {12, 31, 13, 5, 6, 21},
-    {12, 32, 13, 5, 6, 21},
-    {21, 0, 4, 5, 0, 6},
-    {1, 0, 4, 5, 6, 21},
-    {21, 0, 4, 5, 6, 6},
-    {7, 0, 4, 5, 6, 12},
-    {6, 0, 4, 5, 0, 12},
-    {12, 27, 13, 5, 40, 21},
-    {12, 28, 13, 5, 40, 21},
-    {12, 29, 13, 5, 40, 21},
-    {12, 30, 13, 5, 40, 21},
-    {12, 31, 13, 5, 40, 21},
-    {12, 32, 13, 5, 40, 21},
-    {12, 33, 13, 5, 40, 21},
-    {12, 34, 13, 5, 40, 21},
-    {12, 220, 13, 5, 40, 21},
-    {12, 220, 13, 5, 6, 21},
-    {13, 0, 11, 5, 6, 11},
-    {21, 0, 11, 5, 6, 11},
-    {21, 0, 4, 5, 6, 12},
-    {12, 35, 13, 5, 40, 21},
-    {6, 0, 4, 5, 6, 12},
-    {13, 0, 8, 5, 6, 11},
-    {26, 0, 4, 5, 6, 12},
-    {21, 0, 4, 5, 7, 12},
-    {1, 0, 4, 5, 7, 12},
-    {7, 0, 4, 5, 7, 12},
-    {12, 36, 13, 5, 7, 21},
-    {12, 230, 13, 5, 7, 21},
-    {12, 220, 13, 5, 7, 21},
-    {7, 0, 4, 5, 8, 12},
-    {12, 0, 13, 5, 8, 21},
-    {13, 0, 3, 5, 65, 11},
-    {7, 0, 3, 5, 65, 12},
-    {12, 230, 13, 5, 65, 21},
-    {12, 220, 13, 5, 65, 21},
-    {6, 0, 3, 5, 65, 12},
-    {26, 0, 18, 5, 65, 12},
-    {21, 0, 18, 5, 65, 12},
-    {21, 0, 18, 5, 65, 8},
-    {21, 0, 18, 5, 65, 6},
-    {23, 0, 3, 5, 65, 9},
-    {7, 0, 3, 5, 81, 12},
-    {12, 230, 13, 5, 81, 21},
-    {6, 0, 3, 5, 81, 12},
-    {21, 0, 3, 5, 81, 12},
-    {7, 0, 3, 5, 94, 12},
-    {12, 220, 13, 5, 94, 21},
-    {21, 0, 3, 5, 94, 12},
-    {12, 27, 13, 5, 6, 21},
-    {12, 28, 13, 5, 6, 21},
-    {12, 29, 13, 5, 6, 21},
-    {12, 0, 13, 5, 9, 21},
-    {10, 0, 0, 5, 9, 21},
-    {7, 0, 0, 5, 9, 12},
-    {12, 7, 13, 5, 9, 21},
-    {12, 9, 13, 5, 9, 21},
-    {21, 0, 0, 5, 0, 17},
-    {13, 0, 0, 5, 9, 11},
-    {21, 0, 0, 5, 9, 12},
-    {6, 0, 0, 5, 9, 12},
-    {7, 0, 0, 5, 10, 12},
-    {12, 0, 13, 5, 10, 21},
-    {10, 0, 0, 5, 10, 21},
-    {12, 7, 13, 5, 10, 21},
-    {12, 9, 13, 5, 10, 21},
-    {13, 0, 0, 5, 10, 11},
-    {23, 0, 10, 5, 10, 10},
-    {15, 0, 0, 5, 10, 12},
-    {15, 0, 0, 5, 10, 10},
-    {26, 0, 0, 5, 10, 12},
-    {23, 0, 10, 5, 10, 9},
-    {21, 0, 0, 5, 10, 12},
-    {12, 230, 13, 5, 10, 21},
-    {12, 0, 13, 5, 11, 21},
-    {10, 0, 0, 5, 11, 21},
-    {7, 0, 0, 5, 11, 12},
-    {12, 7, 13, 5, 11, 21},
-    {12, 9, 13, 5, 11, 21},
-    {13, 0, 0, 5, 11, 11},
-    {21, 0, 0, 5, 11, 12},
-    {12, 0, 13, 5, 12, 21},
-    {10, 0, 0, 5, 12, 21},
-    {7, 0, 0, 5, 12, 12},
-    {12, 7, 13, 5, 12, 21},
-    {12, 9, 13, 5, 12, 21},
-    {13, 0, 0, 5, 12, 11},
-    {21, 0, 0, 5, 12, 12},
-    {23, 0, 10, 5, 12, 9},
-    {12, 0, 13, 5, 13, 21},
-    {10, 0, 0, 5, 13, 21},
-    {7, 0, 0, 5, 13, 12},
-    {12, 7, 13, 5, 13, 21},
-    {12, 9, 13, 5, 13, 21},
-    {13, 0, 0, 5, 13, 11},
-    {26, 0, 0, 5, 13, 12},
-    {15, 0, 0, 5, 13, 12},
-    {12, 0, 13, 5, 14, 21},
-    {7, 0, 0, 5, 14, 12},
-    {10, 0, 0, 5, 14, 21},
-    {12, 9, 13, 5, 14, 21},
-    {13, 0, 0, 5, 14, 11},
-    {15, 0, 0, 5, 14, 12},
-    {26, 0, 18, 5, 14, 12},
-    {23, 0, 10, 5, 14, 9},
-    {12, 0, 13, 5, 15, 21},
-    {10, 0, 0, 5, 15, 21},
-    {7, 0, 0, 5, 15, 12},
-    {12, 9, 13, 5, 15, 21},
-    {12, 84, 13, 5, 15, 21},
-    {12, 91, 13, 5, 15, 21},
-    {13, 0, 0, 5, 15, 11},
-    {21, 0, 0, 5, 15, 18},
-    {15, 0, 18, 5, 15, 12},
-    {26, 0, 0, 5, 15, 12},
-    {7, 0, 0, 5, 16, 12},
-    {12, 0, 13, 5, 16, 21},
-    {10, 0, 0, 5, 16, 21},
-    {21, 0, 0, 5, 16, 18},
-    {12, 7, 13, 5, 16, 21},
-    {12, 0, 0, 5, 16, 21},
-    {12, 9, 13, 5, 16, 21},
-    {13, 0, 0, 5, 16, 11},
-    {12, 0, 13, 5, 17, 21},
-    {10, 0, 0, 5, 17, 21},
-    {7, 0, 0, 5, 17, 12},
-    {12, 9, 13, 5, 17, 21},
-    {26, 0, 0, 5, 17, 12},
-    {15, 0, 0, 5, 17, 12},
-    {13, 0, 0, 5, 17, 11},
-    {26, 0, 0, 5, 17, 10},
-    {10, 0, 0, 5, 18, 21},
-    {7, 0, 0, 5, 18, 12},
-    {12, 9, 13, 5, 18, 21},
-    {12, 0, 13, 5, 18, 21},
-    {13, 0, 0, 5, 18, 11},
-    {21, 0, 0, 5, 18, 12},
-    {7, 0, 0, 5, 19, 36},
-    {12, 0, 13, 5, 19, 36},
-    {12, 103, 13, 5, 19, 36},
-    {12, 9, 13, 5, 19, 36},
-    {23, 0, 10, 5, 0, 9},
-    {6, 0, 0, 5, 19, 36},
-    {12, 107, 13, 5, 19, 36},
-    {21, 0, 0, 5, 19, 12},
-    {13, 0, 0, 5, 19, 11},
-    {21, 0, 0, 5, 19, 17},
-    {7, 0, 0, 5, 20, 36},
-    {12, 0, 13, 5, 20, 36},
-    {12, 118, 13, 5, 20, 36},
-    {12, 9, 13, 5, 20, 36},
-    {6, 0, 0, 5, 20, 36},
-    {12, 122, 13, 5, 20, 36},
-    {13, 0, 0, 5, 20, 11},
-    {7, 0, 0, 5, 21, 12},
-    {26, 0, 0, 5, 21, 18},
-    {21, 0, 0, 5, 21, 18},
-    {21, 0, 0, 5, 21, 12},
-    {21, 0, 0, 5, 21, 4},
-    {21, 0, 0, 5, 21, 17},
-    {21, 0, 0, 5, 21, 6},
-    {26, 0, 0, 5, 21, 12},
-    {12, 220, 13, 5, 21, 21},
-    {13, 0, 0, 5, 21, 11},
-    {15, 0, 0, 5, 21, 12},
-    {26, 0, 0, 5, 21, 17},
-    {12, 216, 13, 5, 21, 21},
-    {22, 0, 18, 5, 21, 0},
-    {18, 0, 18, 5, 21, 1},
-    {10, 0, 0, 5, 21, 21},
-    {12, 129, 13, 5, 21, 21},
-    {12, 130, 13, 5, 21, 21},
-    {12, 0, 13, 5, 21, 21},
-    {12, 132, 13, 5, 21, 21},
-    {10, 0, 0, 5, 21, 17},
-    {12, 230, 13, 5, 21, 21},
-    {12, 9, 13, 5, 21, 21},
-    {26, 0, 0, 5, 0, 12},
-    {7, 0, 0, 5, 22, 36},
-    {10, 0, 0, 5, 22, 36},
-    {12, 0, 13, 5, 22, 36},
-    {12, 7, 13, 5, 22, 36},
-    {12, 9, 13, 5, 22, 36},
-    {13, 0, 0, 5, 22, 11},
-    {21, 0, 0, 5, 22, 17},
-    {21, 0, 0, 5, 22, 12},
-    {12, 220, 13, 5, 22, 36},
-    {26, 0, 0, 5, 22, 36},
-    {9, 0, 0, 5, 23, 12},
-    {5, 0, 0, 5, 23, 12},
-    {21, 0, 0, 5, 0, 12},
-    {6, 0, 0, 5, 23, 12},
-    {7, 0, 0, 2, 24, 25},
-    {7, 0, 0, 5, 24, 26},
-    {7, 0, 0, 5, 24, 27},
-    {7, 0, 0, 5, 25, 12},
-    {12, 230, 13, 5, 25, 21},
-    {21, 0, 0, 5, 25, 12},
-    {21, 0, 0, 5, 25, 17},
-    {15, 0, 0, 5, 25, 12},
-    {26, 0, 18, 5, 25, 12},
-    {9, 0, 0, 5, 26, 12},
-    {5, 0, 0, 5, 26, 12},
-    {17, 0, 18, 5, 27, 17},
-    {7, 0, 0, 5, 27, 12},
-    {26, 0, 0, 5, 27, 12},
-    {21, 0, 0, 5, 27, 12},
-    {29, 0, 17, 5, 28, 17},
-    {7, 0, 0, 5, 28, 12},
-    {22, 0, 18, 5, 28, 0},
-    {18, 0, 18, 5, 28, 1},
-    {7, 0, 0, 5, 29, 12},
-    {14, 0, 0, 5, 29, 12},
-    {7, 0, 0, 5, 41, 12},
-    {12, 0, 13, 5, 41, 21},
-    {12, 9, 13, 5, 41, 21},
-    {7, 0, 0, 5, 42, 12},
-    {12, 0, 13, 5, 42, 21},
-    {12, 9, 13, 5, 42, 21},
-    {7, 0, 0, 5, 43, 12},
-    {12, 0, 13, 5, 43, 21},
-    {7, 0, 0, 5, 44, 12},
-    {12, 0, 13, 5, 44, 21},
-    {7, 0, 0, 5, 30, 36},
-    {12, 0, 13, 5, 30, 36},
-    {10, 0, 0, 5, 30, 36},
-    {12, 9, 13, 5, 30, 36},
-    {21, 0, 0, 5, 30, 17},
-    {21, 0, 0, 5, 30, 5},
-    {6, 0, 0, 5, 30, 36},
-    {21, 0, 0, 5, 30, 12},
-    {23, 0, 10, 5, 30, 9},
-    {12, 230, 13, 5, 30, 36},
-    {13, 0, 0, 5, 30, 11},
-    {15, 0, 18, 5, 30, 12},
-    {21, 0, 18, 5, 31, 12},
-    {21, 0, 18, 5, 0, 6},
-    {21, 0, 18, 5, 31, 17},
-    {21, 0, 18, 5, 0, 17},
-    {17, 0, 18, 5, 31, 18},
-    {21, 0, 18, 5, 31, 6},
-    {12, 0, 13, 5, 31, 21},
-    {1, 0, 14, 5, 31, 4},
-    {13, 0, 0, 5, 31, 11},
-    {7, 0, 0, 5, 31, 12},
-    {6, 0, 0, 5, 31, 12},
-    {12, 228, 13, 5, 31, 21},
-    {7, 0, 0, 5, 45, 12},
-    {12, 0, 13, 5, 45, 21},
-    {10, 0, 0, 5, 45, 21},
-    {12, 222, 13, 5, 45, 21},
-    {12, 230, 13, 5, 45, 21},
-    {12, 220, 13, 5, 45, 21},
-    {26, 0, 18, 5, 45, 12},
-    {21, 0, 18, 5, 45, 6},
-    {13, 0, 0, 5, 45, 11},
-    {7, 0, 0, 5, 46, 36},
-    {7, 0, 0, 5, 55, 36},
-    {13, 0, 0, 5, 55, 11},
-    {15, 0, 0, 5, 55, 36},
-    {26, 0, 18, 5, 55, 36},
-    {26, 0, 18, 5, 30, 12},
-    {7, 0, 0, 5, 53, 12},
-    {12, 230, 13, 5, 53, 21},
-    {12, 220, 13, 5, 53, 21},
-    {10, 0, 0, 5, 53, 21},
-    {12, 0, 13, 5, 53, 21},
-    {21, 0, 0, 5, 53, 12},
-    {7, 0, 0, 5, 77, 36},
-    {10, 0, 0, 5, 77, 36},
-    {12, 0, 13, 5, 77, 36},
-    {12, 9, 13, 5, 77, 36},
-    {12, 230, 13, 5, 77, 36},
-    {12, 220, 13, 5, 77, 21},
-    {13, 0, 0, 5, 77, 11},
-    {21, 0, 0, 5, 77, 36},
-    {6, 0, 0, 5, 77, 36},
-    {11, 0, 13, 5, 40, 21},
-    {12, 0, 13, 5, 61, 21},
-    {10, 0, 0, 5, 61, 21},
-    {7, 0, 0, 5, 61, 12},
-    {12, 7, 13, 5, 61, 21},
-    {10, 9, 0, 5, 61, 21},
-    {13, 0, 0, 5, 61, 11},
-    {21, 0, 0, 5, 61, 17},
-    {21, 0, 0, 5, 61, 12},
-    {26, 0, 0, 5, 61, 12},
-    {12, 230, 13, 5, 61, 21},
-    {12, 220, 13, 5, 61, 21},
-    {12, 0, 13, 5, 66, 21},
-    {10, 0, 0, 5, 66, 21},
-    {7, 0, 0, 5, 66, 12},
-    {10, 9, 0, 5, 66, 21},
-    {12, 9, 13, 5, 66, 21},
-    {13, 0, 0, 5, 66, 11},
-    {7, 0, 0, 5, 92, 12},
-    {12, 7, 13, 5, 92, 21},
-    {10, 0, 0, 5, 92, 21},
-    {12, 0, 13, 5, 92, 21},
-    {10, 9, 0, 5, 92, 21},
-    {21, 0, 0, 5, 92, 12},
-    {7, 0, 0, 5, 67, 12},
-    {10, 0, 0, 5, 67, 21},
-    {12, 0, 13, 5, 67, 21},
-    {12, 7, 13, 5, 67, 21},
-    {21, 0, 0, 5, 67, 17},
-    {13, 0, 0, 5, 67, 11},
-    {13, 0, 0, 5, 68, 11},
-    {7, 0, 0, 5, 68, 12},
-    {6, 0, 0, 5, 68, 12},
-    {21, 0, 0, 5, 68, 17},
-    {21, 0, 0, 5, 66, 12},
-    {12, 1, 13, 5, 40, 21},
-    {10, 0, 0, 5, 0, 21},
-    {7, 0, 0, 5, 0, 12},
-    {6, 0, 0, 5, 3, 12},
-    {12, 234, 13, 5, 40, 21},
-    {12, 214, 13, 5, 40, 21},
-    {12, 202, 13, 5, 40, 21},
-    {12, 232, 13, 5, 40, 21},
-    {12, 228, 13, 5, 40, 21},
-    {12, 233, 13, 5, 40, 21},
-    {8, 0, 0, 5, 2, 12},
-    {24, 0, 18, 5, 2, 18},
-    {29, 0, 17, 5, 0, 17},
-    {29, 0, 17, 5, 0, 4},
-    {1, 0, 14, 5, 0, 20},
-    {1, 0, 14, 5, 40, 21},
-    {1, 0, 14, 5, 40, 40},
-    {1, 0, 0, 5, 0, 21},
-    {1, 0, 3, 5, 0, 21},
-    {17, 0, 18, 4, 0, 17},
-    {17, 0, 18, 5, 0, 4},
-    {17, 0, 18, 5, 0, 17},
-    {17, 0, 18, 4, 0, 19},
-    {17, 0, 18, 4, 0, 29},
-    {20, 0, 18, 4, 0, 3},
-    {19, 0, 18, 4, 0, 3},
-    {22, 0, 18, 5, 0, 0},
-    {21, 0, 18, 4, 0, 12},
-    {21, 0, 18, 4, 0, 15},
-    {21, 0, 18, 4, 0, 17},
-    {27, 0, 17, 5, 0, 30},
-    {28, 0, 15, 5, 0, 30},
-    {1, 0, 1, 5, 0, 21},
-    {1, 0, 5, 5, 0, 21},
-    {1, 0, 7, 5, 0, 21},
-    {1, 0, 2, 5, 0, 21},
-    {1, 0, 6, 5, 0, 21},
-    {21, 0, 10, 4, 0, 10},
-    {21, 0, 10, 5, 0, 10},
-    {21, 0, 18, 4, 0, 10},
-    {21, 0, 18, 5, 0, 10},
-    {21, 0, 18, 5, 0, 5},
-    {16, 0, 18, 5, 0, 12},
-    {25, 0, 12, 5, 0, 8},
-    {18, 0, 18, 5, 0, 1},
-    {25, 0, 18, 5, 0, 12},
-    {1, 0, 14, 5, 0, 22},
-    {1, 0, 14, 5, 0, 12},
-    {1, 0, 19, 5, 0, 21},
-    {1, 0, 20, 5, 0, 21},
-    {1, 0, 21, 5, 0, 21},
-    {1, 0, 22, 5, 0, 21},
-    {1, 0, 14, 5, 0, 21},
-    {15, 0, 8, 5, 0, 12},
-    {25, 0, 9, 5, 0, 12},
-    {6, 0, 0, 4, 1, 29},
-    {23, 0, 10, 5, 0, 10},
-    {23, 0, 10, 1, 0, 9},
-    {2, 0, 18, 5, 102, 9},
-    {9, 0, 0, 5, 0, 12},
-    {26, 0, 18, 4, 0, 10},
-    {26, 0, 18, 4, 0, 29},
-    {5, 0, 0, 4, 0, 29},
-    {26, 0, 18, 4, 0, 9},
-    {9, 0, 0, 4, 1, 29},
-    {26, 0, 10, 5, 0, 12},
-    {15, 0, 18, 5, 0, 12},
-    {15, 0, 18, 4, 0, 12},
-    {15, 0, 18, 5, 0, 29},
-    {14, 0, 0, 4, 1, 29},
-    {14, 0, 0, 5, 1, 12},
-    {25, 0, 9, 5, 0, 9},
-    {25, 0, 10, 5, 0, 9},
-    {25, 0, 18, 5, 0, 15},
-    {26, 0, 18, 2, 0, 14},
-    {22, 0, 18, 2, 0, 0},
-    {18, 0, 18, 2, 0, 1},
-    {26, 0, 18, 2, 0, 12},
-    {26, 0, 18, 5, 0, 14},
-    {26, 0, 0, 4, 0, 29},
-    {26, 0, 18, 5, 0, 29},
-    {25, 0, 18, 2, 0, 12},
-    {26, 0, 18, 4, 0, 14},
-    {26, 0, 18, 5, 0, 41},
-    {26, 0, 18, 4, 0, 41},
-    {26, 0, 18, 2, 0, 41},
-    {26, 0, 18, 2, 0, 29},
-    {26, 0, 18, 5, 0, 3},
-    {26, 0, 18, 5, 0, 6},
-    {26, 0, 0, 5, 52, 12},
-    {9, 0, 0, 5, 56, 12},
-    {5, 0, 0, 5, 56, 12},
-    {26, 0, 18, 5, 54, 12},
-    {12, 230, 13, 5, 54, 21},
-    {21, 0, 18, 5, 54, 6},
-    {21, 0, 18, 5, 54, 17},
-    {15, 0, 18, 5, 54, 12},
-    {7, 0, 0, 5, 57, 12},
-    {6, 0, 0, 5, 57, 12},
-    {21, 0, 0, 5, 57, 17},
-    {12, 9, 13, 5, 57, 21},
-    {21, 0, 18, 5, 0, 3},
-    {21, 0, 18, 5, 0, 0},
-    {17, 0, 18, 5, 0, 12},
-    {17, 0, 18, 5, 0, 19},
-    {26, 0, 18, 2, 35, 14},
-    {29, 0, 17, 0, 0, 17},
-    {21, 0, 18, 2, 0, 1},
-    {21, 0, 18, 2, 0, 14},
-    {6, 0, 0, 2, 35, 5},
-    {7, 0, 0, 2, 0, 14},
-    {14, 0, 0, 2, 35, 14},
-    {17, 0, 18, 2, 0, 5},
-    {12, 218, 13, 2, 40, 21},
-    {12, 228, 13, 2, 40, 21},
-    {12, 232, 13, 2, 40, 21},
-    {12, 222, 13, 2, 40, 21},
-    {10, 224, 0, 2, 24, 21},
-    {17, 0, 18, 2, 0, 14},
-    {6, 0, 0, 2, 0, 14},
-    {6, 0, 0, 2, 0, 21},
-    {7, 0, 0, 2, 0, 5},
-    {7, 0, 0, 2, 32, 32},
-    {7, 0, 0, 2, 32, 14},
-    {12, 8, 13, 2, 40, 21},
-    {24, 0, 18, 2, 0, 5},
-    {6, 0, 0, 2, 32, 5},
-    {7, 0, 0, 2, 33, 32},
-    {7, 0, 0, 2, 33, 14},
-    {21, 0, 18, 2, 0, 5},
-    {6, 0, 0, 2, 0, 32},
-    {6, 0, 0, 2, 33, 5},
-    {7, 0, 0, 2, 34, 14},
-    {7, 0, 0, 2, 24, 14},
-    {26, 0, 0, 2, 0, 14},
-    {15, 0, 0, 2, 0, 14},
-    {26, 0, 0, 2, 24, 14},
-    {26, 0, 18, 2, 24, 14},
-    {15, 0, 0, 4, 0, 29},
-    {15, 0, 18, 2, 0, 14},
-    {26, 0, 0, 2, 33, 14},
-    {7, 0, 0, 2, 35, 14},
-    {2, 0, 18, 2, 102, 14},
-    {7, 0, 0, 2, 36, 14},
-    {6, 0, 0, 2, 36, 5},
-    {26, 0, 18, 2, 36, 14},
-    {7, 0, 0, 5, 82, 12},
-    {6, 0, 0, 5, 82, 12},
-    {21, 0, 0, 5, 82, 17},
-    {7, 0, 0, 5, 69, 12},
-    {6, 0, 0, 5, 69, 12},
-    {21, 0, 18, 5, 69, 17},
-    {21, 0, 18, 5, 69, 6},
-    {13, 0, 0, 5, 69, 11},
-    {7, 0, 0, 5, 3, 12},
-    {21, 0, 18, 5, 3, 12},
-    {6, 0, 18, 5, 3, 12},
-    {7, 0, 0, 5, 83, 12},
-    {14, 0, 0, 5, 83, 12},
-    {12, 230, 13, 5, 83, 21},
-    {21, 0, 0, 5, 83, 12},
-    {21, 0, 0, 5, 83, 17},
-    {24, 0, 0, 5, 0, 12},
-    {7, 0, 0, 5, 58, 12},
-    {12, 0, 13, 5, 58, 21},
-    {12, 9, 13, 5, 58, 21},
-    {10, 0, 0, 5, 58, 21},
-    {26, 0, 18, 5, 58, 12},
-    {15, 0, 0, 5, 0, 12},
-    {7, 0, 0, 5, 64, 12},
-    {21, 0, 18, 5, 64, 18},
-    {21, 0, 18, 5, 64, 6},
-    {10, 0, 0, 5, 70, 21},
-    {7, 0, 0, 5, 70, 12},
-    {12, 9, 13, 5, 70, 21},
-    {12, 0, 13, 5, 70, 21},
-    {21, 0, 0, 5, 70, 17},
-    {13, 0, 0, 5, 70, 11},
-    {12, 230, 13, 5, 9, 21},
-    {21, 0, 0, 5, 9, 18},
-    {13, 0, 0, 5, 71, 11},
-    {7, 0, 0, 5, 71, 12},
-    {12, 0, 13, 5, 71, 21},
-    {12, 220, 13, 5, 71, 21},
-    {21, 0, 0, 5, 71, 17},
-    {7, 0, 0, 5, 72, 12},
-    {12, 0, 13, 5, 72, 21},
-    {10, 0, 0, 5, 72, 21},
-    {10, 9, 0, 5, 72, 21},
-    {21, 0, 0, 5, 72, 12},
-    {12, 0, 13, 5, 84, 21},
-    {10, 0, 0, 5, 84, 21},
-    {7, 0, 0, 5, 84, 12},
-    {12, 7, 13, 5, 84, 21},
-    {10, 9, 0, 5, 84, 21},
-    {21, 0, 0, 5, 84, 12},
-    {21, 0, 0, 5, 84, 17},
-    {13, 0, 0, 5, 84, 11},
-    {6, 0, 0, 5, 22, 36},
-    {7, 0, 0, 5, 76, 12},
-    {12, 0, 13, 5, 76, 21},
-    {10, 0, 0, 5, 76, 21},
-    {13, 0, 0, 5, 76, 11},
-    {21, 0, 0, 5, 76, 12},
-    {21, 0, 0, 5, 76, 17},
-    {7, 0, 0, 5, 78, 36},
-    {12, 230, 13, 5, 78, 36},
-    {12, 220, 13, 5, 78, 36},
-    {6, 0, 0, 5, 78, 36},
-    {21, 0, 0, 5, 78, 36},
-    {7, 0, 0, 5, 85, 12},
-    {10, 0, 0, 5, 85, 21},
-    {12, 0, 13, 5, 85, 21},
-    {21, 0, 0, 5, 85, 17},
-    {6, 0, 0, 5, 85, 12},
-    {12, 9, 13, 5, 85, 21},
-    {13, 0, 0, 5, 85, 11},
-    {7, 0, 0, 2, 24, 23},
-    {7, 0, 0, 2, 24, 24},
-    {4, 0, 0, 5, 102, 37},
-    {3, 0, 0, 4, 102, 39},
-    {12, 26, 13, 5, 5, 21},
-    {25, 0, 9, 5, 5, 12},
-    {24, 0, 4, 5, 6, 12},
-    {12, 0, 13, 4, 40, 21},
-    {21, 0, 18, 2, 0, 8},
-    {21, 0, 18, 2, 0, 6},
-    {21, 0, 18, 2, 0, 15},
-    {16, 0, 18, 2, 0, 14},
-    {21, 0, 12, 2, 0, 1},
-    {21, 0, 12, 2, 0, 5},
-    {21, 0, 10, 2, 0, 14},
-    {25, 0, 9, 2, 0, 14},
-    {17, 0, 9, 2, 0, 14},
-    {25, 0, 18, 2, 0, 14},
-    {23, 0, 10, 2, 0, 9},
-    {21, 0, 10, 2, 0, 10},
-    {21, 0, 18, 0, 0, 6},
-    {21, 0, 18, 0, 0, 14},
-    {21, 0, 10, 0, 0, 14},
-    {23, 0, 10, 0, 0, 9},
-    {21, 0, 10, 0, 0, 10},
-    {22, 0, 18, 0, 0, 0},
-    {18, 0, 18, 0, 0, 1},
-    {25, 0, 9, 0, 0, 14},
-    {21, 0, 12, 0, 0, 1},
-    {17, 0, 9, 0, 0, 14},
-    {21, 0, 12, 0, 0, 14},
-    {13, 0, 8, 0, 0, 14},
-    {21, 0, 12, 0, 0, 5},
-    {21, 0, 18, 0, 0, 5},
-    {25, 0, 18, 0, 0, 14},
-    {9, 0, 0, 0, 1, 14},
-    {24, 0, 18, 0, 0, 14},
-    {16, 0, 18, 0, 0, 14},
-    {5, 0, 0, 0, 1, 14},
-    {21, 0, 18, 1, 0, 1},
-    {22, 0, 18, 1, 0, 0},
-    {18, 0, 18, 1, 0, 1},
-    {21, 0, 18, 1, 0, 5},
-    {7, 0, 0, 1, 33, 14},
-    {7, 0, 0, 1, 33, 32},
-    {6, 0, 0, 1, 0, 32},
-    {6, 0, 0, 1, 0, 5},
-    {7, 0, 0, 1, 24, 14},
-    {23, 0, 10, 0, 0, 10},
-    {26, 0, 18, 0, 0, 14},
-    {26, 0, 18, 1, 0, 12},
-    {25, 0, 18, 1, 0, 12},
-    {1, 0, 18, 5, 0, 21},
-    {26, 0, 18, 5, 0, 31},
-    {7, 0, 0, 5, 47, 12},
-    {14, 0, 18, 5, 2, 12},
-    {15, 0, 18, 5, 2, 12},
-    {26, 0, 18, 5, 2, 12},
-    {26, 0, 0, 5, 2, 12},
-    {7, 0, 0, 5, 73, 12},
-    {7, 0, 0, 5, 74, 12},
-    {7, 0, 0, 5, 37, 12},
-    {15, 0, 0, 5, 37, 12},
-    {7, 0, 0, 5, 38, 12},
-    {14, 0, 0, 5, 38, 12},
-    {7, 0, 0, 5, 118, 12},
-    {12, 230, 13, 5, 118, 21},
-    {7, 0, 0, 5, 48, 12},
-    {21, 0, 0, 5, 48, 17},
-    {7, 0, 0, 5, 59, 12},
-    {21, 0, 0, 5, 59, 17},
-    {14, 0, 0, 5, 59, 12},
-    {9, 0, 0, 5, 39, 12},
-    {5, 0, 0, 5, 39, 12},
-    {7, 0, 0, 5, 49, 12},
-    {7, 0, 0, 5, 50, 12},
-    {13, 0, 0, 5, 50, 11},
-    {9, 0, 0, 5, 136, 12},
-    {5, 0, 0, 5, 136, 12},
-    {7, 0, 0, 5, 106, 12},
-    {7, 0, 0, 5, 104, 12},
-    {21, 0, 0, 5, 104, 12},
-    {7, 0, 0, 5, 110, 12},
-    {7, 0, 3, 5, 51, 12},
-    {7, 0, 3, 5, 86, 12},
-    {21, 0, 3, 5, 86, 17},
-    {15, 0, 3, 5, 86, 12},
-    {7, 0, 3, 5, 120, 12},
-    {26, 0, 3, 5, 120, 12},
-    {15, 0, 3, 5, 120, 12},
-    {7, 0, 3, 5, 116, 12},
-    {15, 0, 3, 5, 116, 12},
-    {7, 0, 3, 5, 128, 12},
-    {15, 0, 3, 5, 128, 12},
-    {7, 0, 3, 5, 63, 12},
-    {15, 0, 3, 5, 63, 12},
-    {21, 0, 18, 5, 63, 17},
-    {7, 0, 3, 5, 75, 12},
-    {21, 0, 3, 5, 75, 12},
-    {7, 0, 3, 5, 97, 12},
-    {7, 0, 3, 5, 96, 12},
-    {15, 0, 3, 5, 96, 12},
-    {7, 0, 3, 5, 60, 12},
-    {12, 0, 13, 5, 60, 21},
-    {12, 220, 13, 5, 60, 21},
-    {12, 230, 13, 5, 60, 21},
-    {12, 1, 13, 5, 60, 21},
-    {12, 9, 13, 5, 60, 21},
-    {15, 0, 3, 5, 60, 12},
-    {21, 0, 3, 5, 60, 17},
-    {21, 0, 3, 5, 60, 12},
-    {7, 0, 3, 5, 87, 12},
-    {15, 0, 3, 5, 87, 12},
-    {21, 0, 3, 5, 87, 12},
-    {7, 0, 3, 5, 117, 12},
-    {15, 0, 3, 5, 117, 12},
-    {7, 0, 3, 5, 112, 12},
-    {26, 0, 3, 5, 112, 12},
-    {12, 230, 13, 5, 112, 21},
-    {12, 220, 13, 5, 112, 21},
-    {15, 0, 3, 5, 112, 12},
-    {21, 0, 3, 5, 112, 17},
-    {21, 0, 3, 5, 112, 15},
-    {7, 0, 3, 5, 79, 12},
-    {21, 0, 18, 5, 79, 17},
-    {7, 0, 3, 5, 88, 12},
-    {15, 0, 3, 5, 88, 12},
-    {7, 0, 3, 5, 89, 12},
-    {15, 0, 3, 5, 89, 12},
-    {7, 0, 3, 5, 122, 12},
-    {21, 0, 3, 5, 122, 12},
-    {15, 0, 3, 5, 122, 12},
-    {7, 0, 3, 5, 90, 12},
-    {9, 0, 3, 5, 130, 12},
-    {5, 0, 3, 5, 130, 12},
-    {15, 0, 3, 5, 130, 12},
-    {7, 0, 4, 5, 144, 12},
-    {12, 230, 13, 5, 144, 21},
-    {13, 0, 11, 5, 144, 11},
-    {15, 0, 11, 5, 6, 12},
-    {7, 0, 3, 5, 147, 12},
-    {15, 0, 3, 5, 147, 12},
-    {7, 0, 4, 5, 148, 12},
-    {12, 220, 13, 5, 148, 21},
-    {12, 230, 13, 5, 148, 21},
-    {15, 0, 4, 5, 148, 12},
-    {21, 0, 4, 5, 148, 12},
-    {7, 0, 3, 5, 149, 12},
-    {10, 0, 0, 5, 93, 21},
-    {12, 0, 13, 5, 93, 21},
-    {7, 0, 0, 5, 93, 12},
-    {12, 9, 13, 5, 93, 21},
-    {21, 0, 0, 5, 93, 17},
-    {21, 0, 0, 5, 93, 12},
-    {15, 0, 18, 5, 93, 12},
-    {13, 0, 0, 5, 93, 11},
-    {12, 0, 13, 5, 91, 21},
-    {10, 0, 0, 5, 91, 21},
-    {7, 0, 0, 5, 91, 12},
-    {12, 9, 13, 5, 91, 21},
-    {12, 7, 13, 5, 91, 21},
-    {21, 0, 0, 5, 91, 12},
-    {1, 0, 0, 5, 91, 12},
-    {21, 0, 0, 5, 91, 17},
-    {7, 0, 0, 5, 100, 12},
-    {13, 0, 0, 5, 100, 11},
-    {12, 230, 13, 5, 95, 21},
-    {7, 0, 0, 5, 95, 12},
-    {12, 0, 13, 5, 95, 21},
-    {10, 0, 0, 5, 95, 21},
-    {12, 9, 13, 5, 95, 21},
-    {13, 0, 0, 5, 95, 11},
-    {21, 0, 0, 5, 95, 17},
-    {7, 0, 0, 5, 111, 12},
-    {12, 7, 13, 5, 111, 21},
-    {21, 0, 0, 5, 111, 12},
-    {21, 0, 0, 5, 111, 18},
-    {12, 0, 13, 5, 99, 21},
-    {10, 0, 0, 5, 99, 21},
-    {7, 0, 0, 5, 99, 12},
-    {10, 9, 0, 5, 99, 21},
-    {21, 0, 0, 5, 99, 17},
-    {21, 0, 0, 5, 99, 12},
-    {12, 7, 13, 5, 99, 21},
-    {13, 0, 0, 5, 99, 11},
-    {21, 0, 0, 5, 99, 18},
-    {15, 0, 0, 5, 18, 12},
-    {7, 0, 0, 5, 108, 12},
-    {10, 0, 0, 5, 108, 21},
-    {12, 0, 13, 5, 108, 21},
-    {10, 9, 0, 5, 108, 21},
-    {12, 7, 13, 5, 108, 21},
-    {21, 0, 0, 5, 108, 17},
-    {21, 0, 0, 5, 108, 12},
-    {7, 0, 0, 5, 129, 12},
-    {21, 0, 0, 5, 129, 17},
-    {7, 0, 0, 5, 109, 12},
-    {12, 0, 13, 5, 109, 21},
-    {10, 0, 0, 5, 109, 21},
-    {12, 7, 13, 5, 109, 21},
-    {12, 9, 13, 5, 109, 21},
-    {13, 0, 0, 5, 109, 11},
-    {12, 0, 13, 5, 107, 21},
-    {10, 0, 0, 5, 107, 21},
-    {7, 0, 0, 5, 107, 12},
-    {12, 7, 13, 5, 40, 21},
-    {12, 7, 13, 5, 107, 21},
-    {10, 9, 0, 5, 107, 21},
-    {12, 230, 13, 5, 107, 21},
-    {7, 0, 0, 5, 135, 12},
-    {10, 0, 0, 5, 135, 21},
-    {12, 0, 13, 5, 135, 21},
-    {12, 9, 13, 5, 135, 21},
-    {12, 7, 13, 5, 135, 21},
-    {21, 0, 0, 5, 135, 17},
-    {21, 0, 0, 5, 135, 12},
-    {13, 0, 0, 5, 135, 11},
-    {12, 230, 13, 5, 135, 21},
-    {7, 0, 0, 5, 124, 12},
-    {10, 0, 0, 5, 124, 21},
-    {12, 0, 13, 5, 124, 21},
-    {12, 9, 13, 5, 124, 21},
-    {12, 7, 13, 5, 124, 21},
-    {21, 0, 0, 5, 124, 12},
-    {13, 0, 0, 5, 124, 11},
-    {7, 0, 0, 5, 123, 12},
-    {10, 0, 0, 5, 123, 21},
-    {12, 0, 13, 5, 123, 21},
-    {12, 9, 13, 5, 123, 21},
-    {12, 7, 13, 5, 123, 21},
-    {21, 0, 0, 5, 123, 18},
-    {21, 0, 0, 5, 123, 17},
-    {21, 0, 0, 5, 123, 6},
-    {21, 0, 0, 5, 123, 12},
-    {7, 0, 0, 5, 114, 12},
-    {10, 0, 0, 5, 114, 21},
-    {12, 0, 13, 5, 114, 21},
-    {12, 9, 13, 5, 114, 21},
-    {21, 0, 0, 5, 114, 17},
-    {21, 0, 0, 5, 114, 12},
-    {13, 0, 0, 5, 114, 11},
-    {21, 0, 18, 5, 31, 18},
-    {7, 0, 0, 5, 101, 12},
-    {12, 0, 13, 5, 101, 21},
-    {10, 0, 0, 5, 101, 21},
-    {10, 9, 0, 5, 101, 21},
-    {12, 7, 13, 5, 101, 21},
-    {13, 0, 0, 5, 101, 11},
-    {7, 0, 0, 5, 126, 36},
-    {12, 0, 13, 5, 126, 36},
-    {10, 0, 0, 5, 126, 36},
-    {12, 9, 13, 5, 126, 36},
-    {13, 0, 0, 5, 126, 11},
-    {15, 0, 0, 5, 126, 36},
-    {21, 0, 0, 5, 126, 17},
-    {26, 0, 0, 5, 126, 36},
-    {7, 0, 0, 5, 142, 12},
-    {10, 0, 0, 5, 142, 21},
-    {12, 0, 13, 5, 142, 21},
-    {12, 9, 13, 5, 142, 21},
-    {12, 7, 13, 5, 142, 21},
-    {21, 0, 0, 5, 142, 12},
-    {9, 0, 0, 5, 125, 12},
-    {5, 0, 0, 5, 125, 12},
-    {13, 0, 0, 5, 125, 11},
-    {15, 0, 0, 5, 125, 12},
-    {7, 0, 0, 5, 125, 12},
-    {7, 0, 0, 5, 150, 12},
-    {10, 0, 0, 5, 150, 21},
-    {12, 0, 13, 5, 150, 21},
-    {12, 9, 13, 5, 150, 21},
-    {21, 0, 0, 5, 150, 18},
-    {7, 0, 0, 5, 141, 12},
-    {12, 0, 13, 5, 141, 21},
-    {12, 0, 0, 5, 141, 21},
-    {12, 9, 13, 5, 141, 21},
-    {10, 0, 0, 5, 141, 21},
-    {21, 0, 0, 5, 141, 18},
-    {21, 0, 0, 5, 141, 12},
-    {21, 0, 0, 5, 141, 17},
-    {7, 0, 0, 5, 140, 12},
-    {12, 0, 13, 5, 140, 21},
-    {10, 0, 0, 5, 140, 21},
-    {12, 9, 13, 5, 140, 21},
-    {21, 0, 0, 5, 140, 17},
-    {21, 0, 0, 5, 140, 18},
-    {7, 0, 0, 5, 121, 12},
-    {7, 0, 0, 5, 133, 12},
-    {10, 0, 0, 5, 133, 21},
-    {12, 0, 13, 5, 133, 21},
-    {12, 9, 0, 5, 133, 21},
-    {21, 0, 0, 5, 133, 17},
-    {13, 0, 0, 5, 133, 11},
-    {15, 0, 0, 5, 133, 12},
-    {21, 0, 0, 5, 134, 18},
-    {21, 0, 0, 5, 134, 6},
-    {7, 0, 0, 5, 134, 12},
-    {12, 0, 13, 5, 134, 21},
-    {10, 0, 0, 5, 134, 21},
-    {7, 0, 0, 5, 138, 12},
-    {12, 0, 13, 5, 138, 21},
-    {12, 7, 13, 5, 138, 21},
-    {12, 9, 13, 5, 138, 21},
-    {13, 0, 0, 5, 138, 11},
-    {7, 0, 0, 5, 143, 12},
-    {10, 0, 0, 5, 143, 21},
-    {12, 0, 13, 5, 143, 21},
-    {12, 9, 13, 5, 143, 21},
-    {13, 0, 0, 5, 143, 11},
-    {7, 0, 0, 5, 145, 12},
-    {12, 0, 13, 5, 145, 21},
-    {10, 0, 0, 5, 145, 21},
-    {21, 0, 0, 5, 145, 12},
-    {23, 0, 10, 5, 14, 10},
-    {21, 0, 0, 5, 14, 17},
-    {7, 0, 0, 5, 62, 12},
-    {14, 0, 0, 5, 62, 12},
-    {21, 0, 0, 5, 62, 17},
-    {7, 0, 0, 5, 80, 12},
-    {7, 0, 0, 5, 80, 0},
-    {7, 0, 0, 5, 80, 1},
-    {1, 0, 0, 5, 80, 4},
-    {1, 0, 0, 5, 80, 0},
-    {1, 0, 0, 5, 80, 1},
-    {7, 0, 0, 5, 127, 12},
-    {7, 0, 0, 5, 127, 0},
-    {7, 0, 0, 5, 127, 1},
-    {7, 0, 0, 5, 115, 12},
-    {13, 0, 0, 5, 115, 11},
-    {21, 0, 0, 5, 115, 17},
-    {7, 0, 0, 5, 103, 12},
-    {12, 1, 13, 5, 103, 21},
-    {21, 0, 0, 5, 103, 17},
-    {7, 0, 0, 5, 119, 12},
-    {12, 230, 13, 5, 119, 21},
-    {21, 0, 0, 5, 119, 17},
-    {21, 0, 0, 5, 119, 12},
-    {26, 0, 0, 5, 119, 12},
-    {6, 0, 0, 5, 119, 12},
-    {13, 0, 0, 5, 119, 11},
-    {15, 0, 0, 5, 119, 12},
-    {9, 0, 0, 5, 146, 12},
-    {5, 0, 0, 5, 146, 12},
-    {15, 0, 0, 5, 146, 12},
-    {21, 0, 0, 5, 146, 17},
-    {21, 0, 0, 5, 146, 12},
-    {7, 0, 0, 5, 98, 12},
-    {12, 0, 13, 5, 98, 21},
-    {10, 0, 0, 5, 98, 21},
-    {6, 0, 0, 5, 98, 12},
-    {6, 0, 0, 2, 137, 5},
-    {6, 0, 0, 2, 139, 5},
-    {6, 0, 0, 2, 0, 5},
-    {7, 0, 0, 2, 137, 14},
-    {7, 0, 0, 2, 139, 14},
-    {7, 0, 0, 5, 105, 12},
-    {26, 0, 0, 5, 105, 12},
-    {12, 0, 13, 5, 105, 21},
-    {12, 1, 13, 5, 105, 21},
-    {21, 0, 0, 5, 105, 17},
-    {10, 216, 0, 5, 0, 21},
-    {10, 226, 0, 5, 0, 21},
-    {12, 230, 13, 5, 2, 21},
-    {25, 0, 0, 5, 0, 12},
-    {13, 0, 8, 5, 0, 11},
-    {26, 0, 0, 5, 131, 12},
-    {12, 0, 13, 5, 131, 21},
-    {21, 0, 0, 5, 131, 17},
-    {21, 0, 0, 5, 131, 12},
-    {12, 230, 13, 5, 56, 21},
-    {7, 0, 0, 5, 151, 12},
-    {12, 230, 13, 5, 151, 21},
-    {6, 0, 0, 5, 151, 12},
-    {13, 0, 0, 5, 151, 11},
-    {26, 0, 0, 5, 151, 12},
-    {7, 0, 0, 5, 152, 12},
-    {12, 230, 13, 5, 152, 21},
-    {13, 0, 0, 5, 152, 11},
-    {23, 0, 10, 5, 152, 9},
-    {7, 0, 3, 5, 113, 12},
-    {15, 0, 3, 5, 113, 12},
-    {12, 220, 13, 5, 113, 21},
-    {9, 0, 3, 5, 132, 12},
-    {5, 0, 3, 5, 132, 12},
-    {12, 230, 13, 5, 132, 21},
-    {12, 7, 13, 5, 132, 21},
-    {6, 0, 3, 5, 132, 12},
-    {13, 0, 3, 5, 132, 11},
-    {21, 0, 3, 5, 132, 0},
-    {15, 0, 4, 5, 0, 12},
-    {26, 0, 4, 5, 0, 10},
-    {23, 0, 4, 5, 0, 10},
-    {26, 0, 4, 5, 0, 12},
-    {2, 0, 18, 5, 102, 14},
-    {26, 0, 0, 2, 0, 29},
-    {26, 0, 0, 5, 0, 28},
-    {26, 0, 0, 2, 32, 14},
-    {24, 0, 18, 2, 0, 42},
-    {26, 0, 18, 5, 0, 5},
-};
-
-#define BIDI_MIRROR_LEN 420
-static const MirrorPair mirror_pairs[] = {
-    {40, 41},
-    {41, 40},
-    {60, 62},
-    {62, 60},
-    {91, 93},
-    {93, 91},
-    {123, 125},
-    {125, 123},
-    {171, 187},
-    {187, 171},
-    {3898, 3899},
-    {3899, 3898},
-    {3900, 3901},
-    {3901, 3900},
-    {5787, 5788},
-    {5788, 5787},
-    {8249, 8250},
-    {8250, 8249},
-    {8261, 8262},
-    {8262, 8261},
-    {8317, 8318},
-    {8318, 8317},
-    {8333, 8334},
-    {8334, 8333},
-    {8712, 8715},
-    {8713, 8716},
-    {8714, 8717},
-    {8715, 8712},
-    {8716, 8713},
-    {8717, 8714},
-    {8725, 10741},
-    {8735, 11262},
-    {8736, 10659},
-    {8737, 10651},
-    {8738, 10656},
-    {8740, 10990},
-    {8764, 8765},
-    {8765, 8764},
-    {8771, 8909},
-    {8773, 8780},
-    {8780, 8773},
-    {8786, 8787},
-    {8787, 8786},
-    {8788, 8789},
-    {8789, 8788},
-    {8804, 8805},
-    {8805, 8804},
-    {8806, 8807},
-    {8807, 8806},
-    {8808, 8809},
-    {8809, 8808},
-    {8810, 8811},
-    {8811, 8810},
-    {8814, 8815},
-    {8815, 8814},
-    {8816, 8817},
-    {8817, 8816},
-    {8818, 8819},
-    {8819, 8818},
-    {8820, 8821},
-    {8821, 8820},
-    {8822, 8823},
-    {8823, 8822},
-    {8824, 8825},
-    {8825, 8824},
-    {8826, 8827},
-    {8827, 8826},
-    {8828, 8829},
-    {8829, 8828},
-    {8830, 8831},
-    {8831, 8830},
-    {8832, 8833},
-    {8833, 8832},
-    {8834, 8835},
-    {8835, 8834},
-    {8836, 8837},
-    {8837, 8836},
-    {8838, 8839},
-    {8839, 8838},
-    {8840, 8841},
-    {8841, 8840},
-    {8842, 8843},
-    {8843, 8842},
-    {8847, 8848},
-    {8848, 8847},
-    {8849, 8850},
-    {8850, 8849},
-    {8856, 10680},
-    {8866, 8867},
-    {8867, 8866},
-    {8870, 10974},
-    {8872, 10980},
-    {8873, 10979},
-    {8875, 10981},
-    {8880, 8881},
-    {8881, 8880},
-    {8882, 8883},
-    {8883, 8882},
-    {8884, 8885},
-    {8885, 8884},
-    {8886, 8887},
-    {8887, 8886},
-    {8888, 10204},
-    {8905, 8906},
-    {8906, 8905},
-    {8907, 8908},
-    {8908, 8907},
-    {8909, 8771},
-    {8912, 8913},
-    {8913, 8912},
-    {8918, 8919},
-    {8919, 8918},
-    {8920, 8921},
-    {8921, 8920},
-    {8922, 8923},
-    {8923, 8922},
-    {8924, 8925},
-    {8925, 8924},
-    {8926, 8927},
-    {8927, 8926},
-    {8928, 8929},
-    {8929, 8928},
-    {8930, 8931},
-    {8931, 8930},
-    {8932, 8933},
-    {8933, 8932},
-    {8934, 8935},
-    {8935, 8934},
-    {8936, 8937},
-    {8937, 8936},
-    {8938, 8939},
-    {8939, 8938},
-    {8940, 8941},
-    {8941, 8940},
-    {8944, 8945},
-    {8945, 8944},
-    {8946, 8954},
-    {8947, 8955},
-    {8948, 8956},
-    {8950, 8957},
-    {8951, 8958},
-    {8954, 8946},
-    {8955, 8947},
-    {8956, 8948},
-    {8957, 8950},
-    {8958, 8951},
-    {8968, 8969},
-    {8969, 8968},
-    {8970, 8971},
-    {8971, 8970},
-    {9001, 9002},
-    {9002, 9001},
-    {10088, 10089},
-    {10089, 10088},
-    {10090, 10091},
-    {10091, 10090},
-    {10092, 10093},
-    {10093, 10092},
-    {10094, 10095},
-    {10095, 10094},
-    {10096, 10097},
-    {10097, 10096},
-    {10098, 10099},
-    {10099, 10098},
-    {10100, 10101},
-    {10101, 10100},
-    {10179, 10180},
-    {10180, 10179},
-    {10181, 10182},
-    {10182, 10181},
-    {10184, 10185},
-    {10185, 10184},
-    {10187, 10189},
-    {10189, 10187},
-    {10197, 10198},
-    {10198, 10197},
-    {10204, 8888},
-    {10205, 10206},
-    {10206, 10205},
-    {10210, 10211},
-    {10211, 10210},
-    {10212, 10213},
-    {10213, 10212},
-    {10214, 10215},
-    {10215, 10214},
-    {10216, 10217},
-    {10217, 10216},
-    {10218, 10219},
-    {10219, 10218},
-    {10220, 10221},
-    {10221, 10220},
-    {10222, 10223},
-    {10223, 10222},
-    {10627, 10628},
-    {10628, 10627},
-    {10629, 10630},
-    {10630, 10629},
-    {10631, 10632},
-    {10632, 10631},
-    {10633, 10634},
-    {10634, 10633},
-    {10635, 10636},
-    {10636, 10635},
-    {10637, 10640},
-    {10638, 10639},
-    {10639, 10638},
-    {10640, 10637},
-    {10641, 10642},
-    {10642, 10641},
-    {10643, 10644},
-    {10644, 10643},
-    {10645, 10646},
-    {10646, 10645},
-    {10647, 10648},
-    {10648, 10647},
-    {10651, 8737},
-    {10656, 8738},
-    {10659, 8736},
-    {10660, 10661},
-    {10661, 10660},
-    {10664, 10665},
-    {10665, 10664},
-    {10666, 10667},
-    {10667, 10666},
-    {10668, 10669},
-    {10669, 10668},
-    {10670, 10671},
-    {10671, 10670},
-    {10680, 8856},
-    {10688, 10689},
-    {10689, 10688},
-    {10692, 10693},
-    {10693, 10692},
-    {10703, 10704},
-    {10704, 10703},
-    {10705, 10706},
-    {10706, 10705},
-    {10708, 10709},
-    {10709, 10708},
-    {10712, 10713},
-    {10713, 10712},
-    {10714, 10715},
-    {10715, 10714},
-    {10728, 10729},
-    {10729, 10728},
-    {10741, 8725},
-    {10744, 10745},
-    {10745, 10744},
-    {10748, 10749},
-    {10749, 10748},
-    {10795, 10796},
-    {10796, 10795},
-    {10797, 10798},
-    {10798, 10797},
-    {10804, 10805},
-    {10805, 10804},
-    {10812, 10813},
-    {10813, 10812},
-    {10852, 10853},
-    {10853, 10852},
-    {10873, 10874},
-    {10874, 10873},
-    {10875, 10876},
-    {10876, 10875},
-    {10877, 10878},
-    {10878, 10877},
-    {10879, 10880},
-    {10880, 10879},
-    {10881, 10882},
-    {10882, 10881},
-    {10883, 10884},
-    {10884, 10883},
-    {10885, 10886},
-    {10886, 10885},
-    {10887, 10888},
-    {10888, 10887},
-    {10889, 10890},
-    {10890, 10889},
-    {10891, 10892},
-    {10892, 10891},
-    {10893, 10894},
-    {10894, 10893},
-    {10895, 10896},
-    {10896, 10895},
-    {10897, 10898},
-    {10898, 10897},
-    {10899, 10900},
-    {10900, 10899},
-    {10901, 10902},
-    {10902, 10901},
-    {10903, 10904},
-    {10904, 10903},
-    {10905, 10906},
-    {10906, 10905},
-    {10907, 10908},
-    {10908, 10907},
-    {10909, 10910},
-    {10910, 10909},
-    {10911, 10912},
-    {10912, 10911},
-    {10913, 10914},
-    {10914, 10913},
-    {10918, 10919},
-    {10919, 10918},
-    {10920, 10921},
-    {10921, 10920},
-    {10922, 10923},
-    {10923, 10922},
-    {10924, 10925},
-    {10925, 10924},
-    {10927, 10928},
-    {10928, 10927},
-    {10929, 10930},
-    {10930, 10929},
-    {10931, 10932},
-    {10932, 10931},
-    {10933, 10934},
-    {10934, 10933},
-    {10935, 10936},
-    {10936, 10935},
-    {10937, 10938},
-    {10938, 10937},
-    {10939, 10940},
-    {10940, 10939},
-    {10941, 10942},
-    {10942, 10941},
-    {10943, 10944},
-    {10944, 10943},
-    {10945, 10946},
-    {10946, 10945},
-    {10947, 10948},
-    {10948, 10947},
-    {10949, 10950},
-    {10950, 10949},
-    {10951, 10952},
-    {10952, 10951},
-    {10953, 10954},
-    {10954, 10953},
-    {10955, 10956},
-    {10956, 10955},
-    {10957, 10958},
-    {10958, 10957},
-    {10959, 10960},
-    {10960, 10959},
-    {10961, 10962},
-    {10962, 10961},
-    {10963, 10964},
-    {10964, 10963},
-    {10965, 10966},
-    {10966, 10965},
-    {10974, 8870},
-    {10979, 8873},
-    {10980, 8872},
-    {10981, 8875},
-    {10988, 10989},
-    {10989, 10988},
-    {10990, 8740},
-    {10999, 11000},
-    {11000, 10999},
-    {11001, 11002},
-    {11002, 11001},
-    {11262, 8735},
-    {11778, 11779},
-    {11779, 11778},
-    {11780, 11781},
-    {11781, 11780},
-    {11785, 11786},
-    {11786, 11785},
-    {11788, 11789},
-    {11789, 11788},
-    {11804, 11805},
-    {11805, 11804},
-    {11808, 11809},
-    {11809, 11808},
-    {11810, 11811},
-    {11811, 11810},
-    {11812, 11813},
-    {11813, 11812},
-    {11814, 11815},
-    {11815, 11814},
-    {11816, 11817},
-    {11817, 11816},
-    {12296, 12297},
-    {12297, 12296},
-    {12298, 12299},
-    {12299, 12298},
-    {12300, 12301},
-    {12301, 12300},
-    {12302, 12303},
-    {12303, 12302},
-    {12304, 12305},
-    {12305, 12304},
-    {12308, 12309},
-    {12309, 12308},
-    {12310, 12311},
-    {12311, 12310},
-    {12312, 12313},
-    {12313, 12312},
-    {12314, 12315},
-    {12315, 12314},
-    {65113, 65114},
-    {65114, 65113},
-    {65115, 65116},
-    {65116, 65115},
-    {65117, 65118},
-    {65118, 65117},
-    {65124, 65125},
-    {65125, 65124},
-    {65288, 65289},
-    {65289, 65288},
-    {65308, 65310},
-    {65310, 65308},
-    {65339, 65341},
-    {65341, 65339},
-    {65371, 65373},
-    {65373, 65371},
-    {65375, 65376},
-    {65376, 65375},
-    {65378, 65379},
-    {65379, 65378},
-};
-
-#define BIDI_BRACKET_LEN 120
-static const BracketPair bracket_pairs[] = {
-    {40, 41, 0},
-    {41, 40, 1},
-    {91, 93, 0},
-    {93, 91, 1},
-    {123, 125, 0},
-    {125, 123, 1},
-    {3898, 3899, 0},
-    {3899, 3898, 1},
-    {3900, 3901, 0},
-    {3901, 3900, 1},
-    {5787, 5788, 0},
-    {5788, 5787, 1},
-    {8261, 8262, 0},
-    {8262, 8261, 1},
-    {8317, 8318, 0},
-    {8318, 8317, 1},
-    {8333, 8334, 0},
-    {8334, 8333, 1},
-    {8968, 8969, 0},
-    {8969, 8968, 1},
-    {8970, 8971, 0},
-    {8971, 8970, 1},
-    {9001, 9002, 0},
-    {9002, 9001, 1},
-    {10088, 10089, 0},
-    {10089, 10088, 1},
-    {10090, 10091, 0},
-    {10091, 10090, 1},
-    {10092, 10093, 0},
-    {10093, 10092, 1},
-    {10094, 10095, 0},
-    {10095, 10094, 1},
-    {10096, 10097, 0},
-    {10097, 10096, 1},
-    {10098, 10099, 0},
-    {10099, 10098, 1},
-    {10100, 10101, 0},
-    {10101, 10100, 1},
-    {10181, 10182, 0},
-    {10182, 10181, 1},
-    {10214, 10215, 0},
-    {10215, 10214, 1},
-    {10216, 10217, 0},
-    {10217, 10216, 1},
-    {10218, 10219, 0},
-    {10219, 10218, 1},
-    {10220, 10221, 0},
-    {10221, 10220, 1},
-    {10222, 10223, 0},
-    {10223, 10222, 1},
-    {10627, 10628, 0},
-    {10628, 10627, 1},
-    {10629, 10630, 0},
-    {10630, 10629, 1},
-    {10631, 10632, 0},
-    {10632, 10631, 1},
-    {10633, 10634, 0},
-    {10634, 10633, 1},
-    {10635, 10636, 0},
-    {10636, 10635, 1},
-    {10637, 10640, 0},
-    {10638, 10639, 1},
-    {10639, 10638, 0},
-    {10640, 10637, 1},
-    {10641, 10642, 0},
-    {10642, 10641, 1},
-    {10643, 10644, 0},
-    {10644, 10643, 1},
-    {10645, 10646, 0},
-    {10646, 10645, 1},
-    {10647, 10648, 0},
-    {10648, 10647, 1},
-    {10712, 10713, 0},
-    {10713, 10712, 1},
-    {10714, 10715, 0},
-    {10715, 10714, 1},
-    {10748, 10749, 0},
-    {10749, 10748, 1},
-    {11810, 11811, 0},
-    {11811, 11810, 1},
-    {11812, 11813, 0},
-    {11813, 11812, 1},
-    {11814, 11815, 0},
-    {11815, 11814, 1},
-    {11816, 11817, 0},
-    {11817, 11816, 1},
-    {12296, 12297, 0},
-    {12297, 12296, 1},
-    {12298, 12299, 0},
-    {12299, 12298, 1},
-    {12300, 12301, 0},
-    {12301, 12300, 1},
-    {12302, 12303, 0},
-    {12303, 12302, 1},
-    {12304, 12305, 0},
-    {12305, 12304, 1},
-    {12308, 12309, 0},
-    {12309, 12308, 1},
-    {12310, 12311, 0},
-    {12311, 12310, 1},
-    {12312, 12313, 0},
-    {12313, 12312, 1},
-    {12314, 12315, 0},
-    {12315, 12314, 1},
-    {65113, 65114, 0},
-    {65114, 65113, 1},
-    {65115, 65116, 0},
-    {65116, 65115, 1},
-    {65117, 65118, 0},
-    {65118, 65117, 1},
-    {65288, 65289, 0},
-    {65289, 65288, 1},
-    {65339, 65341, 0},
-    {65341, 65339, 1},
-    {65371, 65373, 0},
-    {65373, 65371, 1},
-    {65375, 65376, 0},
-    {65376, 65375, 1},
-    {65378, 65379, 0},
-    {65379, 65378, 1},
-};
-
-/* Reindexing of NFC first characters. */
-#define TOTAL_FIRST 376
-#define TOTAL_LAST 62
-static const Reindex nfc_first[] = {
-  { 60, 2, 0},
-  { 65, 15, 3},
-  { 82, 8, 19},
-  { 97, 15, 28},
-  { 114, 8, 44},
-  { 168, 0, 53},
-  { 194, 0, 54},
-  { 196, 3, 55},
-  { 202, 0, 59},
-  { 207, 0, 60},
-  { 212, 2, 61},
-  { 216, 0, 64},
-  { 220, 0, 65},
-  { 226, 0, 66},
-  { 228, 3, 67},
-  { 234, 0, 71},
-  { 239, 0, 72},
-  { 244, 2, 73},
-  { 248, 0, 76},
-  { 252, 0, 77},
-  { 258, 1, 78},
-  { 274, 1, 80},
-  { 332, 1, 82},
-  { 346, 1, 84},
-  { 352, 1, 86},
-  { 360, 3, 88},
-  { 383, 0, 92},
-  { 416, 1, 93},
-  { 431, 1, 95},
-  { 439, 0, 97},
-  { 490, 1, 98},
-  { 550, 3, 100},
-  { 558, 1, 104},
-  { 658, 0, 106},
-  { 913, 0, 107},
-  { 917, 0, 108},
-  { 919, 0, 109},
-  { 921, 0, 110},
-  { 927, 0, 111},
-  { 929, 0, 112},
-  { 933, 0, 113},
-  { 937, 0, 114},
-  { 940, 0, 115},
-  { 942, 0, 116},
-  { 945, 0, 117},
-  { 949, 0, 118},
-  { 951, 0, 119},
-  { 953, 0, 120},
-  { 959, 0, 121},
-  { 961, 0, 122},
-  { 965, 0, 123},
-  { 969, 2, 124},
-  { 974, 0, 127},
-  { 978, 0, 128},
-  { 1030, 0, 129},
-  { 1040, 0, 130},
-  { 1043, 0, 131},
-  { 1045, 3, 132},
-  { 1050, 0, 136},
-  { 1054, 0, 137},
-  { 1059, 0, 138},
-  { 1063, 0, 139},
-  { 1067, 0, 140},
-  { 1069, 0, 141},
-  { 1072, 0, 142},
-  { 1075, 0, 143},
-  { 1077, 3, 144},
-  { 1082, 0, 148},
-  { 1086, 0, 149},
-  { 1091, 0, 150},
-  { 1095, 0, 151},
-  { 1099, 0, 152},
-  { 1101, 0, 153},
-  { 1110, 0, 154},
-  { 1140, 1, 155},
-  { 1240, 1, 157},
-  { 1256, 1, 159},
-  { 1575, 0, 161},
-  { 1608, 0, 162},
-  { 1610, 0, 163},
-  { 1729, 0, 164},
-  { 1746, 0, 165},
-  { 1749, 0, 166},
-  { 2344, 0, 167},
-  { 2352, 0, 168},
-  { 2355, 0, 169},
-  { 2503, 0, 170},
-  { 2887, 0, 171},
-  { 2962, 0, 172},
-  { 3014, 1, 173},
-  { 3142, 0, 175},
-  { 3263, 0, 176},
-  { 3270, 0, 177},
-  { 3274, 0, 178},
-  { 3398, 1, 179},
-  { 3545, 0, 181},
-  { 3548, 0, 182},
-  { 4133, 0, 183},
-  { 6917, 0, 184},
-  { 6919, 0, 185},
-  { 6921, 0, 186},
-  { 6923, 0, 187},
-  { 6925, 0, 188},
-  { 6929, 0, 189},
-  { 6970, 0, 190},
-  { 6972, 0, 191},
-  { 6974, 1, 192},
-  { 6978, 0, 194},
-  { 7734, 1, 195},
-  { 7770, 1, 197},
-  { 7778, 1, 199},
-  { 7840, 1, 201},
-  { 7864, 1, 203},
-  { 7884, 1, 205},
-  { 7936, 17, 207},
-  { 7960, 1, 225},
-  { 7968, 17, 227},
-  { 7992, 1, 245},
-  { 8000, 1, 247},
-  { 8008, 1, 249},
-  { 8016, 1, 251},
-  { 8025, 0, 253},
-  { 8032, 16, 254},
-  { 8052, 0, 271},
-  { 8060, 0, 272},
-  { 8118, 0, 273},
-  { 8127, 0, 274},
-  { 8134, 0, 275},
-  { 8182, 0, 276},
-  { 8190, 0, 277},
-  { 8592, 0, 278},
-  { 8594, 0, 279},
-  { 8596, 0, 280},
-  { 8656, 0, 281},
-  { 8658, 0, 282},
-  { 8660, 0, 283},
-  { 8707, 0, 284},
-  { 8712, 0, 285},
-  { 8715, 0, 286},
-  { 8739, 0, 287},
-  { 8741, 0, 288},
-  { 8764, 0, 289},
-  { 8771, 0, 290},
-  { 8773, 0, 291},
-  { 8776, 0, 292},
-  { 8781, 0, 293},
-  { 8801, 0, 294},
-  { 8804, 1, 295},
-  { 8818, 1, 297},
-  { 8822, 1, 299},
-  { 8826, 3, 301},
-  { 8834, 1, 305},
-  { 8838, 1, 307},
-  { 8849, 1, 309},
-  { 8866, 0, 311},
-  { 8872, 1, 312},
-  { 8875, 0, 314},
-  { 8882, 3, 315},
-  { 12358, 0, 319},
-  { 12363, 0, 320},
-  { 12365, 0, 321},
-  { 12367, 0, 322},
-  { 12369, 0, 323},
-  { 12371, 0, 324},
-  { 12373, 0, 325},
-  { 12375, 0, 326},
-  { 12377, 0, 327},
-  { 12379, 0, 328},
-  { 12381, 0, 329},
-  { 12383, 0, 330},
-  { 12385, 0, 331},
-  { 12388, 0, 332},
-  { 12390, 0, 333},
-  { 12392, 0, 334},
-  { 12399, 0, 335},
-  { 12402, 0, 336},
-  { 12405, 0, 337},
-  { 12408, 0, 338},
-  { 12411, 0, 339},
-  { 12445, 0, 340},
-  { 12454, 0, 341},
-  { 12459, 0, 342},
-  { 12461, 0, 343},
-  { 12463, 0, 344},
-  { 12465, 0, 345},
-  { 12467, 0, 346},
-  { 12469, 0, 347},
-  { 12471, 0, 348},
-  { 12473, 0, 349},
-  { 12475, 0, 350},
-  { 12477, 0, 351},
-  { 12479, 0, 352},
-  { 12481, 0, 353},
-  { 12484, 0, 354},
-  { 12486, 0, 355},
-  { 12488, 0, 356},
-  { 12495, 0, 357},
-  { 12498, 0, 358},
-  { 12501, 0, 359},
-  { 12504, 0, 360},
-  { 12507, 0, 361},
-  { 12527, 3, 362},
-  { 12541, 0, 366},
-  { 69785, 0, 367},
-  { 69787, 0, 368},
-  { 69797, 0, 369},
-  { 69937, 1, 370},
-  { 70471, 0, 372},
-  { 70841, 0, 373},
-  { 71096, 1, 374},
-  {0,0,0}
-};
-
-static const Reindex nfc_last[] = {
-  { 768, 4, 0},
-  { 774, 6, 5},
-  { 783, 0, 12},
-  { 785, 0, 13},
-  { 787, 1, 14},
-  { 795, 0, 16},
-  { 803, 5, 17},
-  { 813, 1, 23},
-  { 816, 1, 25},
-  { 824, 0, 27},
-  { 834, 0, 28},
-  { 837, 0, 29},
-  { 1619, 2, 30},
-  { 2364, 0, 33},
-  { 2494, 0, 34},
-  { 2519, 0, 35},
-  { 2878, 0, 36},
-  { 2902, 1, 37},
-  { 3006, 0, 39},
-  { 3031, 0, 40},
-  { 3158, 0, 41},
-  { 3266, 0, 42},
-  { 3285, 1, 43},
-  { 3390, 0, 45},
-  { 3415, 0, 46},
-  { 3530, 0, 47},
-  { 3535, 0, 48},
-  { 3551, 0, 49},
-  { 4142, 0, 50},
-  { 6965, 0, 51},
-  { 12441, 1, 52},
-  { 69818, 0, 54},
-  { 69927, 0, 55},
-  { 70462, 0, 56},
-  { 70487, 0, 57},
-  { 70832, 0, 58},
-  { 70842, 0, 59},
-  { 70845, 0, 60},
-  { 71087, 0, 61},
-  {0,0,0}
-};
-
-#define UCDN_EAST_ASIAN_F 0
-#define UCDN_EAST_ASIAN_H 1
-#define UCDN_EAST_ASIAN_W 2
-#define UCDN_EAST_ASIAN_NA 3
-#define UCDN_EAST_ASIAN_A 4
-#define UCDN_EAST_ASIAN_N 5
-
-#define UCDN_SCRIPT_COMMON 0
-#define UCDN_SCRIPT_LATIN 1
-#define UCDN_SCRIPT_GREEK 2
-#define UCDN_SCRIPT_CYRILLIC 3
-#define UCDN_SCRIPT_ARMENIAN 4
-#define UCDN_SCRIPT_HEBREW 5
-#define UCDN_SCRIPT_ARABIC 6
-#define UCDN_SCRIPT_SYRIAC 7
-#define UCDN_SCRIPT_THAANA 8
-#define UCDN_SCRIPT_DEVANAGARI 9
-#define UCDN_SCRIPT_BENGALI 10
-#define UCDN_SCRIPT_GURMUKHI 11
-#define UCDN_SCRIPT_GUJARATI 12
-#define UCDN_SCRIPT_ORIYA 13
-#define UCDN_SCRIPT_TAMIL 14
-#define UCDN_SCRIPT_TELUGU 15
-#define UCDN_SCRIPT_KANNADA 16
-#define UCDN_SCRIPT_MALAYALAM 17
-#define UCDN_SCRIPT_SINHALA 18
-#define UCDN_SCRIPT_THAI 19
-#define UCDN_SCRIPT_LAO 20
-#define UCDN_SCRIPT_TIBETAN 21
-#define UCDN_SCRIPT_MYANMAR 22
-#define UCDN_SCRIPT_GEORGIAN 23
-#define UCDN_SCRIPT_HANGUL 24
-#define UCDN_SCRIPT_ETHIOPIC 25
-#define UCDN_SCRIPT_CHEROKEE 26
-#define UCDN_SCRIPT_CANADIAN_ABORIGINAL 27
-#define UCDN_SCRIPT_OGHAM 28
-#define UCDN_SCRIPT_RUNIC 29
-#define UCDN_SCRIPT_KHMER 30
-#define UCDN_SCRIPT_MONGOLIAN 31
-#define UCDN_SCRIPT_HIRAGANA 32
-#define UCDN_SCRIPT_KATAKANA 33
-#define UCDN_SCRIPT_BOPOMOFO 34
-#define UCDN_SCRIPT_HAN 35
-#define UCDN_SCRIPT_YI 36
-#define UCDN_SCRIPT_OLD_ITALIC 37
-#define UCDN_SCRIPT_GOTHIC 38
-#define UCDN_SCRIPT_DESERET 39
-#define UCDN_SCRIPT_INHERITED 40
-#define UCDN_SCRIPT_TAGALOG 41
-#define UCDN_SCRIPT_HANUNOO 42
-#define UCDN_SCRIPT_BUHID 43
-#define UCDN_SCRIPT_TAGBANWA 44
-#define UCDN_SCRIPT_LIMBU 45
-#define UCDN_SCRIPT_TAI_LE 46
-#define UCDN_SCRIPT_LINEAR_B 47
-#define UCDN_SCRIPT_UGARITIC 48
-#define UCDN_SCRIPT_SHAVIAN 49
-#define UCDN_SCRIPT_OSMANYA 50
-#define UCDN_SCRIPT_CYPRIOT 51
-#define UCDN_SCRIPT_BRAILLE 52
-#define UCDN_SCRIPT_BUGINESE 53
-#define UCDN_SCRIPT_COPTIC 54
-#define UCDN_SCRIPT_NEW_TAI_LUE 55
-#define UCDN_SCRIPT_GLAGOLITIC 56
-#define UCDN_SCRIPT_TIFINAGH 57
-#define UCDN_SCRIPT_SYLOTI_NAGRI 58
-#define UCDN_SCRIPT_OLD_PERSIAN 59
-#define UCDN_SCRIPT_KHAROSHTHI 60
-#define UCDN_SCRIPT_BALINESE 61
-#define UCDN_SCRIPT_CUNEIFORM 62
-#define UCDN_SCRIPT_PHOENICIAN 63
-#define UCDN_SCRIPT_PHAGS_PA 64
-#define UCDN_SCRIPT_NKO 65
-#define UCDN_SCRIPT_SUNDANESE 66
-#define UCDN_SCRIPT_LEPCHA 67
-#define UCDN_SCRIPT_OL_CHIKI 68
-#define UCDN_SCRIPT_VAI 69
-#define UCDN_SCRIPT_SAURASHTRA 70
-#define UCDN_SCRIPT_KAYAH_LI 71
-#define UCDN_SCRIPT_REJANG 72
-#define UCDN_SCRIPT_LYCIAN 73
-#define UCDN_SCRIPT_CARIAN 74
-#define UCDN_SCRIPT_LYDIAN 75
-#define UCDN_SCRIPT_CHAM 76
-#define UCDN_SCRIPT_TAI_THAM 77
-#define UCDN_SCRIPT_TAI_VIET 78
-#define UCDN_SCRIPT_AVESTAN 79
-#define UCDN_SCRIPT_EGYPTIAN_HIEROGLYPHS 80
-#define UCDN_SCRIPT_SAMARITAN 81
-#define UCDN_SCRIPT_LISU 82
-#define UCDN_SCRIPT_BAMUM 83
-#define UCDN_SCRIPT_JAVANESE 84
-#define UCDN_SCRIPT_MEETEI_MAYEK 85
-#define UCDN_SCRIPT_IMPERIAL_ARAMAIC 86
-#define UCDN_SCRIPT_OLD_SOUTH_ARABIAN 87
-#define UCDN_SCRIPT_INSCRIPTIONAL_PARTHIAN 88
-#define UCDN_SCRIPT_INSCRIPTIONAL_PAHLAVI 89
-#define UCDN_SCRIPT_OLD_TURKIC 90
-#define UCDN_SCRIPT_KAITHI 91
-#define UCDN_SCRIPT_BATAK 92
-#define UCDN_SCRIPT_BRAHMI 93
-#define UCDN_SCRIPT_MANDAIC 94
-#define UCDN_SCRIPT_CHAKMA 95
-#define UCDN_SCRIPT_MEROITIC_CURSIVE 96
-#define UCDN_SCRIPT_MEROITIC_HIEROGLYPHS 97
-#define UCDN_SCRIPT_MIAO 98
-#define UCDN_SCRIPT_SHARADA 99
-#define UCDN_SCRIPT_SORA_SOMPENG 100
-#define UCDN_SCRIPT_TAKRI 101
-#define UCDN_SCRIPT_UNKNOWN 102
-#define UCDN_SCRIPT_BASSA_VAH 103
-#define UCDN_SCRIPT_CAUCASIAN_ALBANIAN 104
-#define UCDN_SCRIPT_DUPLOYAN 105
-#define UCDN_SCRIPT_ELBASAN 106
-#define UCDN_SCRIPT_GRANTHA 107
-#define UCDN_SCRIPT_KHOJKI 108
-#define UCDN_SCRIPT_KHUDAWADI 109
-#define UCDN_SCRIPT_LINEAR_A 110
-#define UCDN_SCRIPT_MAHAJANI 111
-#define UCDN_SCRIPT_MANICHAEAN 112
-#define UCDN_SCRIPT_MENDE_KIKAKUI 113
-#define UCDN_SCRIPT_MODI 114
-#define UCDN_SCRIPT_MRO 115
-#define UCDN_SCRIPT_NABATAEAN 116
-#define UCDN_SCRIPT_OLD_NORTH_ARABIAN 117
-#define UCDN_SCRIPT_OLD_PERMIC 118
-#define UCDN_SCRIPT_PAHAWH_HMONG 119
-#define UCDN_SCRIPT_PALMYRENE 120
-#define UCDN_SCRIPT_PAU_CIN_HAU 121
-#define UCDN_SCRIPT_PSALTER_PAHLAVI 122
-#define UCDN_SCRIPT_SIDDHAM 123
-#define UCDN_SCRIPT_TIRHUTA 124
-#define UCDN_SCRIPT_WARANG_CITI 125
-#define UCDN_SCRIPT_AHOM 126
-#define UCDN_SCRIPT_ANATOLIAN_HIEROGLYPHS 127
-#define UCDN_SCRIPT_HATRAN 128
-#define UCDN_SCRIPT_MULTANI 129
-#define UCDN_SCRIPT_OLD_HUNGARIAN 130
-#define UCDN_SCRIPT_SIGNWRITING 131
-#define UCDN_SCRIPT_ADLAM 132
-#define UCDN_SCRIPT_BHAIKSUKI 133
-#define UCDN_SCRIPT_MARCHEN 134
-#define UCDN_SCRIPT_NEWA 135
-#define UCDN_SCRIPT_OSAGE 136
-#define UCDN_SCRIPT_TANGUT 137
-#define UCDN_SCRIPT_MASARAM_GONDI 138
-#define UCDN_SCRIPT_NUSHU 139
-#define UCDN_SCRIPT_SOYOMBO 140
-#define UCDN_SCRIPT_ZANABAZAR_SQUARE 141
-#define UCDN_SCRIPT_DOGRA 142
-#define UCDN_SCRIPT_GUNJALA_GONDI 143
-#define UCDN_SCRIPT_HANIFI_ROHINGYA 144
-#define UCDN_SCRIPT_MAKASAR 145
-#define UCDN_SCRIPT_MEDEFAIDRIN 146
-#define UCDN_SCRIPT_OLD_SOGDIAN 147
-#define UCDN_SCRIPT_SOGDIAN 148
-#define UCDN_SCRIPT_ELYMAIC 149
-#define UCDN_SCRIPT_NANDINAGARI 150
-#define UCDN_SCRIPT_NYIAKENG_PUACHUE_HMONG 151
-#define UCDN_SCRIPT_WANCHO 152
-
-#define UCDN_GENERAL_CATEGORY_CC 0
-#define UCDN_GENERAL_CATEGORY_CF 1
-#define UCDN_GENERAL_CATEGORY_CN 2
-#define UCDN_GENERAL_CATEGORY_CO 3
-#define UCDN_GENERAL_CATEGORY_CS 4
-#define UCDN_GENERAL_CATEGORY_LL 5
-#define UCDN_GENERAL_CATEGORY_LM 6
-#define UCDN_GENERAL_CATEGORY_LO 7
-#define UCDN_GENERAL_CATEGORY_LT 8
-#define UCDN_GENERAL_CATEGORY_LU 9
-#define UCDN_GENERAL_CATEGORY_MC 10
-#define UCDN_GENERAL_CATEGORY_ME 11
-#define UCDN_GENERAL_CATEGORY_MN 12
-#define UCDN_GENERAL_CATEGORY_ND 13
-#define UCDN_GENERAL_CATEGORY_NL 14
-#define UCDN_GENERAL_CATEGORY_NO 15
-#define UCDN_GENERAL_CATEGORY_PC 16
-#define UCDN_GENERAL_CATEGORY_PD 17
-#define UCDN_GENERAL_CATEGORY_PE 18
-#define UCDN_GENERAL_CATEGORY_PF 19
-#define UCDN_GENERAL_CATEGORY_PI 20
-#define UCDN_GENERAL_CATEGORY_PO 21
-#define UCDN_GENERAL_CATEGORY_PS 22
-#define UCDN_GENERAL_CATEGORY_SC 23
-#define UCDN_GENERAL_CATEGORY_SK 24
-#define UCDN_GENERAL_CATEGORY_SM 25
-#define UCDN_GENERAL_CATEGORY_SO 26
-#define UCDN_GENERAL_CATEGORY_ZL 27
-#define UCDN_GENERAL_CATEGORY_ZP 28
-#define UCDN_GENERAL_CATEGORY_ZS 29
-
-#define UCDN_BIDI_CLASS_L 0
-#define UCDN_BIDI_CLASS_LRE 1
-#define UCDN_BIDI_CLASS_LRO 2
-#define UCDN_BIDI_CLASS_R 3
-#define UCDN_BIDI_CLASS_AL 4
-#define UCDN_BIDI_CLASS_RLE 5
-#define UCDN_BIDI_CLASS_RLO 6
-#define UCDN_BIDI_CLASS_PDF 7
-#define UCDN_BIDI_CLASS_EN 8
-#define UCDN_BIDI_CLASS_ES 9
-#define UCDN_BIDI_CLASS_ET 10
-#define UCDN_BIDI_CLASS_AN 11
-#define UCDN_BIDI_CLASS_CS 12
-#define UCDN_BIDI_CLASS_NSM 13
-#define UCDN_BIDI_CLASS_BN 14
-#define UCDN_BIDI_CLASS_B 15
-#define UCDN_BIDI_CLASS_S 16
-#define UCDN_BIDI_CLASS_WS 17
-#define UCDN_BIDI_CLASS_ON 18
-#define UCDN_BIDI_CLASS_LRI 19
-#define UCDN_BIDI_CLASS_RLI 20
-#define UCDN_BIDI_CLASS_FSI 21
-#define UCDN_BIDI_CLASS_PDI 22
-
-/* index tables for the database records */
-#define SHIFT1 5
-#define SHIFT2 3
-static const unsigned char index0[] = {
-    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 
-    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 
-    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 54, 55, 56, 56, 56, 57, 
-    58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, 
-    69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, 
-    66, 67, 68, 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, 72, 73, 73, 73, 
-    73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 52, 75, 76, 77, 78, 79, 
-    80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 
-    98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 
-    113, 113, 113, 114, 115, 116, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 117, 117, 118, 119, 120, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 121, 122, 123, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 124, 124, 125, 126, 108, 108, 127, 128, 129, 129, 129, 129, 
-    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 
-    129, 129, 129, 129, 129, 130, 129, 129, 131, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 132, 133, 134, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 135, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 136, 137, 138, 139, 140, 141, 
-    142, 143, 144, 144, 145, 108, 108, 108, 108, 108, 146, 147, 148, 108, 
-    108, 108, 108, 108, 149, 150, 108, 108, 151, 152, 153, 108, 154, 155, 
-    156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 165, 165, 165, 166, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 167, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 168, 169, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 170, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
-    171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 52, 52, 
-    173, 172, 172, 172, 172, 174, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 
-    172, 172, 172, 172, 172, 172, 172, 172, 172, 174, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 175, 176, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 
-    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    177, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 
-    74, 74, 74, 74, 177, 
-};
-
-static const unsigned short index1[] = {
-    0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13, 0, 0, 0, 14, 15, 
-    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 29, 31, 32, 
-    33, 34, 35, 27, 30, 29, 27, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 
-    47, 48, 27, 27, 49, 27, 27, 27, 27, 27, 27, 27, 50, 51, 52, 27, 53, 54, 
-    53, 54, 54, 54, 54, 54, 55, 54, 54, 54, 56, 57, 58, 59, 60, 61, 62, 63, 
-    64, 64, 65, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 65, 77, 78, 
-    79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 
-    97, 97, 97, 97, 98, 98, 98, 98, 99, 100, 101, 101, 101, 101, 102, 103, 
-    101, 101, 101, 101, 101, 101, 104, 105, 101, 101, 101, 101, 101, 101, 
-    101, 101, 101, 101, 101, 101, 106, 107, 107, 107, 108, 109, 110, 110, 
-    110, 110, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 120, 
-    120, 121, 122, 119, 123, 124, 125, 126, 127, 127, 127, 127, 128, 129, 
-    130, 131, 132, 133, 134, 127, 127, 127, 127, 127, 127, 127, 127, 127, 
-    127, 127, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 144, 
-    145, 146, 147, 148, 127, 127, 127, 127, 127, 127, 149, 149, 149, 149, 
-    150, 151, 152, 119, 153, 154, 155, 155, 155, 156, 157, 158, 159, 159, 
-    160, 161, 162, 163, 164, 165, 166, 166, 166, 167, 144, 168, 119, 119, 
-    119, 119, 119, 119, 127, 127, 169, 170, 119, 119, 171, 125, 172, 173, 
-    174, 175, 176, 177, 177, 177, 177, 177, 177, 178, 179, 180, 181, 177, 
-    182, 183, 184, 177, 185, 186, 187, 188, 188, 189, 190, 191, 192, 193, 
-    194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206, 
-    207, 208, 209, 210, 211, 212, 213, 119, 214, 215, 216, 217, 217, 218, 
-    219, 220, 221, 222, 223, 119, 224, 225, 226, 227, 228, 229, 230, 231, 
-    231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 119, 242, 243, 
-    244, 245, 246, 243, 247, 248, 249, 250, 251, 119, 252, 253, 254, 255, 
-    256, 257, 258, 259, 259, 258, 259, 260, 261, 262, 263, 264, 265, 266, 
-    267, 268, 269, 270, 271, 272, 272, 271, 273, 274, 275, 276, 277, 278, 
-    279, 280, 281, 119, 282, 283, 284, 285, 285, 285, 285, 286, 287, 288, 
-    289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 296, 296, 299, 300, 
-    297, 301, 302, 303, 304, 305, 306, 119, 307, 308, 308, 308, 308, 308, 
-    309, 310, 311, 312, 313, 314, 119, 119, 119, 119, 315, 316, 317, 317, 
-    318, 317, 319, 320, 321, 322, 323, 324, 119, 119, 119, 119, 325, 326, 
-    327, 328, 329, 330, 331, 332, 333, 334, 333, 333, 333, 335, 336, 337, 
-    338, 339, 340, 341, 340, 340, 340, 342, 343, 344, 345, 346, 119, 119, 
-    119, 119, 347, 347, 347, 347, 347, 348, 349, 350, 351, 352, 353, 354, 
-    355, 356, 357, 347, 358, 359, 351, 360, 361, 361, 361, 361, 362, 363, 
-    364, 364, 364, 364, 364, 365, 366, 366, 366, 366, 366, 366, 366, 366, 
-    366, 366, 366, 366, 367, 367, 367, 367, 367, 367, 367, 367, 367, 368, 
-    368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 369, 369, 369, 369, 
-    369, 369, 369, 369, 369, 370, 371, 370, 369, 369, 369, 369, 369, 370, 
-    369, 369, 369, 369, 370, 371, 370, 369, 371, 369, 369, 369, 369, 369, 
-    369, 369, 370, 369, 369, 369, 369, 369, 369, 369, 369, 372, 373, 374, 
-    375, 376, 369, 369, 377, 378, 379, 379, 379, 379, 379, 379, 379, 379, 
-    379, 379, 380, 381, 382, 383, 383, 383, 383, 383, 383, 383, 383, 383, 
-    383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 
-    383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 
-    383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 
-    383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 
-    383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 384, 383, 383, 
-    385, 386, 386, 387, 388, 388, 388, 388, 388, 388, 388, 388, 388, 389, 
-    390, 391, 392, 393, 394, 119, 395, 395, 396, 119, 397, 397, 398, 119, 
-    399, 400, 401, 119, 402, 402, 402, 402, 402, 402, 403, 404, 405, 406, 
-    407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 417, 417, 417, 
-    418, 417, 417, 417, 417, 417, 417, 419, 420, 417, 417, 417, 417, 421, 
-    383, 383, 383, 383, 383, 383, 383, 383, 422, 119, 423, 423, 423, 424, 
-    425, 426, 427, 428, 429, 430, 431, 431, 431, 432, 433, 119, 434, 434, 
-    434, 434, 434, 435, 434, 434, 434, 436, 437, 438, 439, 439, 439, 439, 
-    440, 440, 441, 442, 443, 443, 443, 443, 443, 443, 444, 445, 446, 447, 
-    448, 449, 450, 451, 450, 451, 452, 453, 454, 455, 119, 119, 119, 119, 
-    119, 119, 119, 119, 456, 457, 457, 457, 457, 457, 458, 459, 460, 461, 
-    462, 463, 464, 465, 466, 467, 468, 469, 469, 469, 470, 471, 472, 473, 
-    474, 474, 474, 474, 475, 476, 477, 478, 479, 479, 479, 479, 480, 481, 
-    482, 483, 484, 485, 486, 487, 488, 488, 488, 489, 100, 490, 361, 361, 
-    361, 361, 361, 491, 492, 119, 493, 494, 495, 496, 497, 498, 54, 54, 54, 
-    54, 499, 500, 56, 56, 56, 56, 56, 501, 502, 503, 54, 504, 54, 54, 54, 
-    505, 56, 56, 56, 506, 507, 508, 509, 510, 510, 510, 511, 512, 27, 27, 27, 
-    27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 513, 514, 27, 
-    27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 515, 516, 517, 518, 515, 516, 
-    515, 516, 517, 518, 515, 519, 515, 516, 515, 517, 515, 520, 515, 520, 
-    515, 520, 521, 522, 523, 524, 525, 526, 515, 527, 528, 529, 530, 531, 
-    532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 
-    546, 547, 56, 548, 549, 550, 551, 552, 553, 553, 554, 555, 556, 557, 558, 
-    119, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 
-    572, 571, 573, 574, 575, 576, 577, 578, 579, 580, 581, 580, 582, 583, 
-    580, 584, 580, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 586, 
-    595, 596, 586, 597, 598, 586, 586, 598, 586, 599, 600, 599, 586, 586, 
-    601, 586, 586, 586, 586, 586, 602, 586, 586, 580, 603, 604, 605, 606, 
-    607, 608, 609, 609, 609, 609, 609, 609, 609, 609, 610, 580, 580, 611, 
-    612, 586, 586, 613, 580, 580, 580, 580, 585, 606, 614, 615, 580, 580, 
-    580, 580, 580, 616, 119, 119, 119, 580, 617, 119, 119, 618, 618, 618, 
-    618, 618, 619, 619, 620, 621, 621, 621, 621, 621, 621, 621, 621, 621, 
-    622, 618, 623, 624, 624, 624, 624, 624, 624, 624, 624, 624, 625, 624, 
-    624, 624, 624, 626, 580, 624, 624, 627, 580, 628, 629, 630, 631, 632, 
-    633, 629, 580, 627, 634, 580, 635, 636, 637, 638, 639, 580, 580, 580, 
-    640, 641, 642, 643, 580, 644, 645, 580, 646, 580, 580, 647, 648, 649, 
-    650, 580, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 580, 
-    580, 580, 662, 580, 663, 580, 664, 665, 666, 667, 668, 669, 618, 670, 
-    670, 671, 580, 580, 580, 662, 672, 673, 586, 586, 586, 674, 675, 586, 
-    586, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 
-    676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 
-    676, 676, 676, 676, 676, 586, 586, 586, 586, 586, 586, 586, 586, 586, 
-    586, 586, 586, 586, 586, 586, 586, 677, 678, 678, 679, 586, 586, 586, 
-    586, 586, 586, 586, 680, 586, 586, 586, 681, 586, 586, 586, 586, 586, 
-    586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 
-    586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 580, 
-    580, 580, 682, 580, 580, 586, 586, 683, 684, 685, 629, 580, 580, 686, 
-    580, 580, 580, 687, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 
-    580, 580, 580, 688, 688, 688, 688, 688, 689, 690, 690, 690, 690, 690, 
-    691, 692, 693, 694, 695, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 
-    696, 697, 698, 699, 364, 364, 364, 364, 700, 701, 702, 702, 702, 702, 
-    702, 702, 702, 703, 704, 705, 369, 369, 371, 119, 371, 371, 371, 371, 
-    371, 371, 371, 371, 706, 706, 706, 706, 707, 708, 709, 710, 711, 712, 
-    713, 714, 715, 716, 119, 119, 119, 119, 119, 119, 717, 717, 717, 718, 
-    717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 719, 119, 717, 717, 
-    717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 
-    717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 720, 119, 119, 119, 
-    721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 733, 
-    734, 733, 733, 733, 735, 736, 737, 738, 739, 740, 741, 741, 742, 741, 
-    741, 741, 743, 744, 745, 746, 747, 748, 748, 748, 748, 748, 749, 750, 
-    750, 750, 750, 750, 750, 750, 750, 750, 750, 751, 752, 753, 748, 748, 
-    748, 754, 721, 721, 721, 721, 722, 119, 755, 755, 756, 756, 756, 757, 
-    758, 759, 753, 753, 753, 760, 761, 762, 756, 756, 756, 763, 758, 759, 
-    753, 753, 753, 753, 764, 762, 753, 765, 766, 766, 766, 766, 766, 767, 
-    766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 753, 753, 753, 
-    768, 769, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 770, 
-    753, 753, 753, 768, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 772, 773, 580, 580, 580, 580, 580, 580, 580, 580, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    773, 773, 774, 774, 775, 774, 774, 774, 774, 774, 774, 774, 774, 774, 
-    774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 
-    774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 
-    774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 
-    774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 
-    774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 776, 
-    777, 777, 777, 777, 777, 777, 778, 119, 779, 779, 779, 779, 779, 780, 
-    781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 
-    781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 
-    781, 781, 781, 781, 781, 782, 781, 781, 783, 784, 119, 119, 101, 101, 
-    101, 101, 101, 785, 786, 787, 101, 101, 101, 788, 789, 789, 789, 789, 
-    789, 789, 789, 789, 790, 791, 792, 119, 64, 64, 793, 794, 795, 27, 796, 
-    27, 27, 27, 27, 27, 27, 27, 797, 798, 27, 799, 800, 27, 27, 801, 802, 27, 
-    803, 119, 119, 119, 119, 119, 804, 805, 806, 807, 808, 808, 809, 810, 
-    811, 812, 813, 813, 813, 813, 813, 813, 814, 119, 815, 816, 816, 816, 
-    816, 816, 817, 818, 819, 820, 821, 822, 823, 823, 824, 825, 826, 827, 
-    828, 828, 829, 830, 831, 831, 832, 833, 834, 835, 366, 366, 366, 836, 
-    837, 838, 838, 838, 838, 838, 839, 840, 841, 842, 843, 844, 845, 347, 
-    351, 846, 847, 847, 847, 847, 847, 848, 849, 119, 850, 851, 852, 853, 
-    347, 347, 854, 855, 856, 856, 856, 856, 856, 856, 857, 858, 859, 119, 
-    119, 860, 861, 862, 863, 119, 864, 864, 864, 119, 371, 371, 54, 54, 54, 
-    54, 54, 865, 866, 119, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 
-    861, 861, 861, 861, 868, 869, 870, 871, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 
-    873, 872, 873, 873, 874, 873, 873, 873, 873, 873, 873, 872, 873, 873, 
-    874, 873, 873, 873, 872, 873, 873, 874, 873, 873, 873, 872, 873, 873, 
-    875, 119, 367, 367, 876, 877, 368, 368, 368, 368, 368, 878, 879, 879, 
-    879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 
-    879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 
-    879, 879, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 
-    880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 
-    880, 880, 880, 880, 880, 880, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 772, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 881, 773, 773, 773, 773, 882, 119, 883, 884, 
-    120, 885, 886, 887, 888, 120, 127, 127, 127, 127, 127, 127, 127, 127, 
-    127, 127, 127, 127, 889, 890, 891, 119, 892, 127, 127, 127, 127, 127, 
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 893, 119, 119, 
-    127, 127, 127, 127, 127, 127, 127, 127, 894, 127, 127, 127, 127, 127, 
-    127, 119, 119, 119, 119, 119, 127, 895, 896, 896, 897, 898, 899, 900, 
-    901, 902, 903, 904, 905, 906, 907, 908, 169, 127, 127, 127, 127, 127, 
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 909, 910, 911, 
-    912, 913, 914, 915, 915, 916, 917, 918, 918, 919, 920, 921, 922, 923, 
-    923, 923, 923, 924, 925, 925, 925, 926, 927, 927, 927, 928, 929, 930, 
-    119, 931, 932, 933, 932, 932, 934, 932, 932, 935, 932, 936, 932, 936, 
-    119, 119, 119, 119, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 
-    932, 932, 932, 932, 932, 937, 938, 939, 939, 939, 939, 939, 940, 609, 
-    941, 941, 941, 941, 941, 941, 942, 943, 944, 945, 580, 946, 947, 119, 
-    119, 119, 119, 119, 609, 609, 609, 609, 609, 948, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 949, 949, 
-    949, 950, 951, 951, 951, 951, 951, 951, 952, 119, 953, 954, 954, 955, 
-    956, 956, 956, 956, 957, 958, 959, 959, 960, 961, 962, 962, 962, 962, 
-    963, 964, 965, 965, 965, 966, 967, 967, 967, 967, 968, 967, 969, 119, 
-    119, 119, 119, 119, 970, 970, 970, 970, 970, 971, 971, 971, 971, 971, 
-    972, 972, 972, 972, 972, 972, 973, 973, 973, 974, 975, 976, 977, 977, 
-    977, 977, 978, 979, 979, 979, 979, 980, 981, 981, 981, 981, 981, 119, 
-    982, 982, 982, 982, 982, 982, 983, 984, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 985, 985, 
-    985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 
-    985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 
-    985, 985, 985, 985, 985, 985, 985, 985, 986, 119, 985, 985, 987, 119, 
-    985, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 988, 989, 990, 990, 990, 990, 991, 992, 
-    993, 993, 994, 995, 996, 996, 997, 998, 999, 999, 999, 1000, 1001, 1002, 
-    119, 119, 119, 119, 119, 119, 1003, 1003, 1004, 1005, 1006, 1006, 1007, 
-    1008, 1009, 1009, 1009, 1010, 119, 119, 119, 119, 119, 119, 119, 119, 
-    1011, 1011, 1011, 1011, 1012, 1012, 1012, 1013, 1014, 1014, 1015, 1014, 
-    1014, 1014, 1014, 1014, 1016, 1017, 1018, 1019, 1020, 1020, 1021, 1022, 
-    1023, 1024, 1025, 1026, 1027, 1027, 1027, 1028, 1029, 1029, 1029, 1030, 
-    119, 119, 119, 119, 1031, 1032, 1031, 1031, 1033, 1034, 1035, 119, 1036, 
-    1036, 1036, 1036, 1036, 1036, 1037, 1038, 1039, 1039, 1040, 1041, 1042, 
-    1042, 1043, 1044, 1045, 1045, 1046, 1047, 119, 1048, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 
-    1049, 1049, 1050, 119, 119, 119, 119, 119, 119, 1051, 1051, 1051, 1051, 
-    1051, 1051, 1052, 119, 1053, 1053, 1053, 1053, 1053, 1053, 1054, 1055, 
-    1056, 1056, 1056, 1056, 1057, 119, 1058, 1059, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 1060, 1060, 1060, 1061, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 1062, 1062, 1062, 1063, 
-    1064, 119, 1065, 1065, 1066, 1067, 1068, 1069, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1070, 1070, 1071, 
-    119, 1072, 1073, 1073, 1073, 1073, 1073, 1073, 1074, 1075, 1076, 1077, 
-    1078, 1079, 1080, 119, 1081, 1082, 1083, 1083, 1083, 1083, 1083, 1084, 
-    1085, 1086, 1087, 1088, 1088, 1088, 1089, 1090, 1091, 1092, 1093, 1093, 
-    1093, 1094, 1095, 1096, 1097, 1098, 119, 1099, 1099, 1099, 1099, 1100, 
-    119, 1101, 1102, 1102, 1102, 1102, 1102, 1103, 1104, 1105, 1106, 1107, 
-    1108, 1109, 1110, 1111, 119, 1112, 1112, 1113, 1112, 1112, 1114, 1115, 
-    1116, 119, 119, 119, 119, 119, 119, 119, 119, 1117, 1118, 1119, 1120, 
-    1119, 1121, 1122, 1122, 1122, 1122, 1122, 1123, 1124, 1125, 1126, 1127, 
-    1128, 1129, 1130, 1131, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 
-    1139, 1140, 1140, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 1141, 1141, 1141, 1141, 1141, 1141, 1142, 
-    1143, 1144, 1145, 1146, 1147, 119, 119, 119, 119, 1148, 1148, 1148, 1148, 
-    1148, 1148, 1149, 1150, 1151, 119, 1152, 1153, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 1154, 1154, 1154, 1154, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 
-    1161, 119, 119, 119, 119, 1162, 1162, 1162, 1162, 1162, 1162, 1163, 1164, 
-    1165, 119, 1166, 1167, 1168, 1169, 119, 119, 1170, 1170, 1170, 1170, 
-    1170, 1171, 1172, 1173, 1174, 1175, 119, 119, 119, 119, 119, 119, 1176, 
-    1176, 1176, 1177, 1178, 1179, 1180, 1181, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 1182, 1182, 1182, 1182, 1182, 1183, 1184, 1185, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1186, 1186, 1186, 
-    1186, 1187, 1187, 1187, 1187, 1188, 1189, 1190, 1191, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 1192, 1193, 1192, 1192, 1192, 1192, 1194, 1195, 1196, 119, 119, 
-    119, 1197, 1198, 1199, 1199, 1199, 1199, 1200, 1201, 1202, 119, 1203, 
-    1204, 1205, 1205, 1205, 1205, 1205, 1206, 1207, 1208, 1209, 119, 119, 
-    119, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1211, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    1212, 1213, 1212, 1212, 1212, 1214, 1215, 1216, 1217, 119, 1218, 1219, 
-    1220, 1221, 1222, 1223, 1223, 1223, 1224, 1225, 1225, 1226, 1227, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 1228, 1229, 1230, 1230, 1230, 
-    1230, 1231, 1232, 1233, 119, 1234, 1235, 1236, 1237, 1238, 1238, 1238, 
-    1239, 1240, 1241, 1242, 1243, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 1244, 1244, 1245, 1246, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 1247, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1254, 
-    1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 
-    1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 
-    1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 
-    1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 
-    1254, 1255, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 
-    1256, 1257, 1258, 119, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 
-    1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 
-    1254, 1254, 1254, 1254, 1259, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 
-    1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 
-    1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 
-    1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1261, 1260, 1260, 1260, 
-    1260, 1262, 1263, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 
-    1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 
-    1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1264, 1260, 1260, 1260, 
-    1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 1260, 
-    1260, 1260, 1260, 1260, 1260, 1260, 1265, 1266, 1267, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 
-    1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 
-    1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 
-    1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 
-    1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 
-    1268, 1268, 1269, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 
-    1268, 1268, 1268, 1268, 1268, 1270, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 
-    789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 
-    789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 1271, 
-    1272, 1272, 1272, 1273, 1274, 1275, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 1276, 1276, 1276, 1277, 1278, 119, 1279, 1279, 
-    1279, 1279, 1279, 1279, 1280, 1281, 1282, 119, 1283, 1284, 1285, 1279, 
-    1279, 1286, 1279, 1279, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1287, 1287, 
-    1287, 1287, 1288, 1288, 1288, 1288, 1289, 1289, 1290, 1291, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1292, 1292, 1292, 1292, 
-    1292, 1292, 1292, 1292, 1292, 1293, 1294, 1295, 1295, 1295, 1295, 1295, 
-    1295, 1296, 1297, 1298, 119, 119, 119, 119, 119, 119, 119, 119, 1299, 
-    119, 119, 119, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1300, 1300, 1300, 1300, 1300, 119, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 
-    1300, 1301, 119, 1302, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 
-    733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 
-    733, 733, 733, 733, 733, 733, 733, 733, 733, 733, 1303, 119, 119, 119, 
-    119, 119, 119, 1304, 119, 1305, 119, 1306, 1306, 1306, 1306, 1306, 1306, 
-    1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 
-    1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 
-    1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1306, 
-    1306, 1306, 1306, 1306, 1306, 1306, 1306, 1307, 1308, 1308, 1308, 1308, 
-    1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1309, 1308, 1310, 
-    1308, 1311, 1308, 1312, 1313, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 
-    609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 
-    609, 609, 609, 609, 609, 1314, 119, 609, 609, 609, 609, 1315, 1316, 609, 
-    609, 609, 609, 609, 609, 1317, 1318, 1319, 1320, 1321, 1322, 609, 609, 
-    609, 1323, 609, 609, 609, 609, 609, 609, 609, 1324, 119, 119, 944, 944, 
-    944, 944, 944, 944, 944, 944, 1325, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 939, 939, 
-    1326, 119, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 616, 119, 
-    939, 939, 939, 1327, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 1328, 1328, 1328, 1329, 1330, 1330, 1331, 
-    1328, 1328, 1332, 1333, 1330, 1330, 1328, 1328, 1328, 1329, 1330, 1330, 
-    1334, 1335, 1336, 1332, 1337, 1338, 1330, 1328, 1328, 1328, 1329, 1330, 
-    1330, 1339, 1340, 1341, 1342, 1330, 1330, 1330, 1343, 1344, 1345, 1346, 
-    1330, 1330, 1331, 1328, 1328, 1332, 1330, 1330, 1330, 1328, 1328, 1328, 
-    1329, 1330, 1330, 1331, 1328, 1328, 1332, 1330, 1330, 1330, 1328, 1328, 
-    1328, 1329, 1330, 1330, 1331, 1328, 1328, 1332, 1330, 1330, 1330, 1328, 
-    1328, 1328, 1329, 1330, 1330, 1347, 1328, 1328, 1328, 1348, 1330, 1330, 
-    1349, 1350, 1328, 1328, 1351, 1330, 1330, 1352, 1331, 1328, 1328, 1353, 
-    1330, 1330, 1354, 1355, 1328, 1328, 1356, 1330, 1330, 1330, 1357, 1328, 
-    1328, 1328, 1348, 1330, 1330, 1349, 1358, 1359, 1359, 1359, 1359, 1359, 
-    1359, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 
-    1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 
-    1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1360, 1361, 1361, 1361, 
-    1361, 1361, 1361, 1362, 1363, 1361, 1361, 1361, 1361, 1361, 1364, 1365, 
-    1360, 1366, 1367, 119, 1368, 1369, 1361, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 1370, 1371, 1371, 1372, 1373, 1374, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 1375, 1375, 1375, 1375, 
-    1375, 1376, 1377, 1378, 1379, 1380, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1381, 1381, 1381, 
-    1381, 1381, 1382, 1383, 1384, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 
-    1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 
-    1385, 1385, 1385, 1385, 1385, 1386, 1387, 1388, 119, 119, 119, 119, 119, 
-    1389, 1389, 1389, 1389, 1390, 1391, 1391, 1391, 1392, 1393, 1394, 1395, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 1396, 1397, 1397, 1397, 1397, 1397, 1397, 
-    1398, 1399, 119, 119, 119, 119, 119, 119, 119, 119, 119, 1396, 1397, 
-    1397, 1397, 1397, 1400, 1397, 1401, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 119, 1402, 127, 127, 127, 1403, 1404, 1405, 1406, 1407, 1408, 
-    1403, 1409, 1403, 1405, 1405, 1410, 127, 1411, 127, 1412, 1413, 1411, 
-    127, 1412, 119, 119, 119, 119, 119, 119, 1414, 119, 1415, 1416, 1416, 
-    1416, 1416, 1417, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 
-    1416, 1416, 1416, 1417, 1418, 1416, 1419, 1420, 1416, 1420, 1421, 1420, 
-    1416, 1416, 1416, 1422, 1418, 619, 1423, 621, 621, 621, 1424, 621, 621, 
-    621, 621, 621, 621, 621, 1425, 621, 621, 621, 1426, 1427, 1428, 621, 
-    1429, 1418, 1418, 1418, 1418, 1418, 1418, 1430, 1431, 1431, 1431, 1432, 
-    1418, 753, 753, 753, 753, 753, 1433, 753, 1434, 1435, 1418, 1436, 1418, 
-    1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 1418, 1418, 1418, 1418, 1418, 721, 721, 721, 721, 1437, 1438, 1439, 
-    721, 721, 721, 721, 721, 721, 721, 721, 1440, 1441, 721, 1442, 1443, 721, 
-    721, 1444, 1445, 1446, 1447, 1442, 1416, 721, 721, 1448, 1449, 721, 721, 
-    721, 721, 721, 721, 721, 1450, 1451, 1452, 1453, 721, 1454, 1452, 1452, 
-    1455, 1456, 1457, 1458, 721, 1459, 1460, 1461, 721, 721, 721, 721, 721, 
-    721, 721, 721, 1462, 1463, 721, 1464, 642, 1465, 721, 1466, 1467, 580, 
-    1468, 721, 721, 721, 1416, 1469, 1470, 1416, 1416, 1471, 1416, 1415, 
-    1416, 1416, 1416, 1416, 1416, 1472, 1473, 1416, 1416, 1472, 1474, 721, 
-    721, 721, 721, 721, 721, 721, 721, 1475, 1476, 580, 580, 580, 580, 1477, 
-    1478, 721, 721, 721, 721, 1479, 721, 1480, 721, 1481, 1482, 1483, 1418, 
-    1416, 1484, 1485, 1486, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 
-    580, 580, 580, 580, 1487, 1418, 580, 580, 580, 580, 580, 580, 580, 580, 
-    580, 580, 1488, 1489, 721, 1490, 1418, 1418, 580, 1487, 580, 580, 580, 
-    580, 580, 580, 580, 1418, 580, 1491, 580, 580, 580, 580, 580, 1418, 580, 
-    580, 580, 1492, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 580, 1493, 721, 1452, 1494, 721, 1452, 1495, 721, 721, 721, 721, 
-    721, 721, 1496, 1497, 721, 721, 721, 721, 1498, 1499, 1500, 1501, 721, 
-    1502, 1503, 1504, 721, 721, 721, 721, 580, 580, 580, 580, 580, 580, 580, 
-    580, 580, 580, 1487, 1418, 1416, 1422, 1490, 1486, 1486, 1418, 1436, 
-    1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 1418, 
-    1418, 1418, 1418, 1418, 1505, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 1506, 773, 773, 773, 773, 773, 771, 771, 771, 771, 
-    771, 771, 1507, 773, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 772, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 881, 773, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 
-    771, 771, 771, 771, 771, 771, 771, 771, 1508, 773, 773, 773, 773, 773, 
-    773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 
-    773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 
-    773, 773, 771, 771, 771, 772, 773, 773, 773, 773, 773, 773, 773, 773, 
-    773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 
-    773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 
-    773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 
-    773, 773, 773, 773, 773, 773, 773, 773, 773, 1509, 1510, 119, 119, 119, 
-    1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511, 
-    119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 
-    119, 119, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 
-    896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 
-    896, 896, 896, 896, 119, 119, 880, 880, 880, 880, 880, 880, 880, 880, 
-    880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 
-    880, 880, 880, 880, 880, 880, 880, 880, 880, 1512, 
-};
-
-static const unsigned short index2[] = {
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1, 7, 7, 7, 8, 
-    9, 10, 11, 12, 13, 14, 15, 11, 16, 17, 15, 18, 19, 20, 19, 21, 22, 22, 
-    22, 22, 22, 22, 22, 22, 22, 22, 19, 23, 24, 24, 24, 10, 15, 25, 25, 25, 
-    25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 16, 26, 17, 
-    27, 28, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 
-    29, 29, 29, 16, 30, 31, 24, 1, 1, 1, 1, 1, 1, 32, 1, 1, 33, 34, 35, 13, 
-    36, 13, 37, 38, 39, 40, 41, 42, 24, 43, 44, 27, 45, 46, 47, 47, 48, 49, 
-    38, 38, 39, 47, 41, 50, 51, 51, 51, 34, 52, 52, 52, 52, 52, 52, 53, 52, 
-    52, 52, 52, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 52, 54, 53, 52, 
-    52, 52, 52, 52, 53, 55, 55, 55, 56, 56, 56, 56, 55, 56, 55, 55, 55, 56, 
-    55, 55, 56, 56, 55, 56, 55, 55, 56, 56, 56, 54, 55, 55, 55, 56, 55, 56, 
-    55, 56, 52, 55, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, 
-    52, 55, 52, 55, 52, 56, 52, 56, 52, 56, 52, 55, 52, 56, 52, 56, 52, 56, 
-    52, 56, 52, 56, 53, 55, 52, 55, 53, 55, 52, 56, 52, 56, 55, 52, 56, 52, 
-    56, 52, 56, 53, 55, 53, 55, 52, 55, 52, 56, 52, 55, 55, 53, 55, 52, 55, 
-    52, 56, 52, 56, 53, 55, 52, 56, 52, 56, 52, 52, 56, 52, 56, 52, 56, 56, 
-    56, 52, 52, 56, 52, 56, 52, 52, 56, 52, 52, 52, 56, 56, 52, 52, 52, 52, 
-    56, 52, 52, 56, 52, 52, 52, 56, 56, 56, 52, 52, 56, 52, 52, 56, 52, 56, 
-    52, 56, 52, 52, 56, 52, 56, 56, 52, 56, 52, 52, 56, 52, 52, 52, 56, 52, 
-    56, 52, 52, 56, 56, 57, 52, 56, 56, 56, 57, 57, 57, 57, 52, 58, 56, 52, 
-    58, 56, 52, 58, 56, 52, 55, 52, 55, 52, 55, 52, 55, 52, 55, 52, 55, 52, 
-    55, 52, 55, 56, 52, 56, 56, 52, 58, 56, 52, 56, 52, 52, 52, 56, 52, 56, 
-    56, 56, 56, 56, 56, 56, 52, 52, 56, 52, 52, 56, 56, 52, 56, 52, 52, 52, 
-    52, 56, 56, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 
-    56, 56, 56, 56, 57, 56, 56, 56, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 
-    60, 61, 61, 61, 61, 61, 61, 61, 62, 62, 63, 62, 60, 64, 65, 64, 64, 64, 
-    65, 64, 60, 60, 66, 61, 62, 62, 62, 62, 62, 62, 39, 39, 39, 39, 62, 39, 
-    62, 48, 59, 59, 59, 59, 59, 62, 62, 62, 62, 62, 67, 67, 60, 62, 61, 62, 
-    62, 62, 62, 62, 62, 62, 62, 62, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 
-    68, 68, 68, 69, 70, 70, 70, 70, 69, 71, 70, 70, 70, 70, 70, 72, 72, 70, 
-    70, 70, 70, 72, 72, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 73, 73, 
-    73, 73, 73, 70, 70, 70, 70, 68, 68, 68, 68, 68, 68, 68, 68, 74, 68, 70, 
-    70, 70, 68, 68, 68, 70, 70, 75, 68, 68, 68, 70, 70, 70, 70, 68, 69, 70, 
-    70, 68, 76, 77, 77, 76, 77, 77, 76, 68, 68, 68, 68, 68, 78, 79, 78, 79, 
-    60, 80, 78, 79, 81, 81, 82, 79, 79, 79, 83, 78, 81, 81, 81, 81, 80, 62, 
-    78, 84, 78, 78, 78, 81, 78, 81, 78, 78, 79, 85, 85, 85, 85, 85, 85, 85, 
-    85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 81, 85, 85, 85, 85, 85, 85, 85, 
-    78, 78, 79, 79, 79, 79, 79, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 
-    86, 86, 86, 86, 86, 86, 79, 86, 86, 86, 86, 86, 86, 86, 79, 79, 79, 79, 
-    79, 78, 79, 79, 78, 78, 78, 79, 79, 79, 78, 79, 78, 79, 78, 79, 78, 79, 
-    78, 79, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 79, 79, 
-    79, 79, 78, 79, 89, 78, 79, 78, 78, 79, 79, 78, 78, 78, 90, 91, 90, 90, 
-    90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 
-    91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 93, 92, 93, 93, 93, 93, 93, 93, 
-    93, 93, 93, 93, 93, 93, 93, 93, 90, 93, 90, 93, 90, 93, 90, 93, 90, 93, 
-    94, 95, 95, 96, 96, 95, 97, 97, 90, 93, 90, 93, 90, 93, 90, 90, 93, 90, 
-    93, 90, 93, 90, 93, 90, 93, 90, 93, 90, 93, 93, 81, 98, 98, 98, 98, 98, 
-    98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 81, 
-    81, 99, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 
-    101, 101, 102, 103, 81, 81, 104, 104, 105, 81, 106, 107, 107, 107, 107, 
-    106, 107, 107, 107, 108, 106, 107, 107, 107, 107, 107, 107, 106, 106, 
-    106, 106, 106, 106, 107, 107, 106, 107, 107, 108, 109, 107, 110, 111, 
-    112, 113, 114, 115, 116, 117, 118, 119, 119, 120, 121, 122, 123, 124, 
-    125, 126, 127, 125, 107, 106, 128, 118, 81, 81, 81, 81, 81, 81, 81, 81, 
-    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 81, 81, 81, 81, 
-    129, 129, 129, 129, 125, 125, 81, 81, 81, 130, 130, 130, 130, 130, 131, 
-    132, 132, 133, 134, 134, 135, 136, 137, 138, 138, 139, 139, 139, 139, 
-    139, 139, 139, 139, 140, 141, 142, 143, 144, 81, 145, 143, 146, 146, 146, 
-    146, 146, 146, 146, 146, 147, 146, 146, 146, 146, 146, 146, 146, 146, 
-    146, 146, 148, 149, 150, 151, 152, 153, 154, 155, 96, 96, 156, 157, 139, 
-    139, 139, 139, 139, 157, 139, 139, 157, 158, 158, 158, 158, 158, 158, 
-    158, 158, 158, 158, 134, 159, 159, 160, 146, 146, 161, 146, 146, 146, 
-    146, 146, 146, 146, 146, 146, 146, 146, 145, 146, 139, 139, 139, 139, 
-    139, 139, 139, 131, 138, 139, 139, 139, 139, 157, 139, 162, 162, 139, 
-    139, 138, 157, 139, 139, 157, 146, 146, 163, 163, 163, 163, 163, 163, 
-    163, 163, 163, 163, 146, 146, 146, 164, 164, 146, 165, 165, 165, 165, 
-    165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 81, 166, 167, 168, 167, 
-    167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 169, 
-    170, 169, 169, 170, 169, 169, 170, 170, 170, 169, 170, 170, 169, 170, 
-    169, 169, 169, 170, 169, 170, 169, 170, 169, 170, 169, 169, 81, 81, 167, 
-    167, 167, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 
-    171, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 171, 81, 
-    81, 81, 81, 81, 81, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 
-    174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 
-    174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 176, 175, 177, 177, 
-    178, 179, 180, 181, 177, 81, 81, 176, 182, 182, 183, 183, 183, 183, 183, 
-    183, 183, 183, 183, 183, 183, 183, 183, 183, 184, 184, 184, 184, 185, 
-    184, 184, 184, 184, 184, 184, 184, 184, 184, 185, 184, 184, 184, 185, 
-    184, 184, 184, 184, 184, 81, 81, 186, 186, 186, 186, 186, 186, 186, 186, 
-    186, 186, 186, 186, 186, 186, 186, 81, 187, 187, 187, 187, 187, 187, 187, 
-    187, 187, 188, 188, 188, 81, 81, 189, 81, 167, 167, 167, 81, 81, 81, 81, 
-    81, 146, 146, 146, 146, 146, 81, 146, 146, 146, 146, 146, 146, 146, 146, 
-    81, 81, 81, 81, 81, 157, 139, 139, 139, 139, 139, 139, 131, 157, 139, 
-    139, 157, 139, 139, 157, 139, 139, 139, 157, 157, 157, 190, 191, 192, 
-    139, 139, 139, 157, 139, 139, 157, 157, 139, 139, 139, 139, 139, 193, 
-    193, 193, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 
-    195, 195, 195, 193, 194, 196, 195, 194, 194, 194, 193, 193, 193, 193, 
-    193, 193, 193, 193, 194, 194, 194, 194, 197, 194, 194, 195, 96, 156, 96, 
-    96, 193, 193, 193, 195, 195, 193, 193, 198, 198, 199, 199, 199, 199, 199, 
-    199, 199, 199, 199, 199, 200, 201, 195, 195, 195, 195, 195, 195, 202, 
-    203, 204, 204, 81, 202, 202, 202, 202, 202, 202, 202, 202, 81, 81, 202, 
-    202, 81, 81, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 
-    202, 202, 81, 202, 202, 202, 202, 202, 202, 202, 81, 202, 81, 81, 81, 
-    202, 202, 202, 202, 81, 81, 205, 202, 204, 204, 204, 203, 203, 203, 203, 
-    81, 81, 204, 204, 81, 81, 204, 204, 206, 202, 81, 81, 81, 81, 81, 81, 81, 
-    81, 204, 81, 81, 81, 81, 202, 202, 81, 202, 202, 202, 203, 203, 81, 81, 
-    207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 202, 202, 208, 208, 
-    209, 209, 209, 209, 209, 210, 211, 212, 202, 213, 214, 81, 81, 215, 215, 
-    216, 81, 217, 217, 217, 217, 217, 217, 81, 81, 81, 81, 217, 217, 81, 81, 
-    217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 81, 
-    217, 217, 217, 217, 217, 217, 217, 81, 217, 217, 81, 217, 217, 81, 217, 
-    217, 81, 81, 218, 81, 216, 216, 216, 215, 215, 81, 81, 81, 81, 215, 215, 
-    81, 81, 215, 215, 219, 81, 81, 81, 215, 81, 81, 81, 81, 81, 81, 81, 217, 
-    217, 217, 217, 81, 217, 81, 81, 81, 81, 81, 81, 81, 220, 220, 220, 220, 
-    220, 220, 220, 220, 220, 220, 215, 215, 217, 217, 217, 215, 221, 81, 81, 
-    222, 222, 223, 81, 224, 224, 224, 224, 224, 224, 224, 224, 224, 81, 224, 
-    224, 224, 81, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 
-    224, 224, 81, 224, 224, 224, 224, 224, 224, 224, 81, 224, 224, 81, 224, 
-    224, 224, 224, 224, 81, 81, 225, 224, 223, 223, 223, 222, 222, 222, 222, 
-    222, 81, 222, 222, 223, 81, 223, 223, 226, 81, 81, 224, 81, 81, 81, 81, 
-    81, 81, 81, 224, 224, 222, 222, 81, 81, 227, 227, 227, 227, 227, 227, 
-    227, 227, 227, 227, 228, 229, 81, 81, 81, 81, 81, 81, 81, 224, 222, 222, 
-    222, 222, 222, 222, 81, 230, 231, 231, 81, 232, 232, 232, 232, 232, 232, 
-    232, 232, 81, 81, 232, 232, 81, 81, 232, 232, 232, 232, 232, 232, 232, 
-    232, 232, 232, 232, 232, 232, 232, 81, 232, 232, 232, 232, 232, 232, 232, 
-    81, 232, 232, 81, 232, 232, 232, 232, 232, 81, 81, 233, 232, 231, 230, 
-    231, 230, 230, 230, 230, 81, 81, 231, 231, 81, 81, 231, 231, 234, 81, 81, 
-    81, 81, 81, 81, 81, 81, 230, 231, 81, 81, 81, 81, 232, 232, 81, 232, 232, 
-    232, 230, 230, 81, 81, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 
-    236, 232, 237, 237, 237, 237, 237, 237, 81, 81, 238, 239, 81, 239, 239, 
-    239, 239, 239, 239, 81, 81, 81, 239, 239, 239, 81, 239, 239, 239, 239, 
-    81, 81, 81, 239, 239, 81, 239, 81, 239, 239, 81, 81, 81, 239, 239, 81, 
-    81, 81, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 81, 81, 81, 81, 
-    240, 240, 238, 240, 240, 81, 81, 81, 240, 240, 240, 81, 240, 240, 240, 
-    241, 81, 81, 239, 81, 81, 81, 81, 81, 81, 240, 81, 81, 81, 81, 81, 81, 
-    242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 244, 
-    244, 244, 244, 244, 244, 245, 244, 81, 81, 81, 81, 81, 246, 247, 247, 
-    247, 246, 248, 248, 248, 248, 248, 248, 248, 248, 81, 248, 248, 248, 81, 
-    248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 
-    248, 248, 81, 81, 81, 248, 246, 246, 246, 247, 247, 247, 247, 81, 246, 
-    246, 246, 81, 246, 246, 246, 249, 81, 81, 81, 81, 81, 81, 81, 250, 251, 
-    81, 248, 248, 248, 81, 81, 81, 81, 81, 248, 248, 246, 246, 81, 81, 252, 
-    252, 252, 252, 252, 252, 252, 252, 252, 252, 81, 81, 81, 81, 81, 81, 81, 
-    253, 254, 254, 254, 254, 254, 254, 254, 255, 256, 257, 258, 258, 259, 
-    256, 256, 256, 256, 256, 256, 256, 256, 81, 256, 256, 256, 81, 256, 256, 
-    256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 
-    256, 256, 81, 256, 256, 256, 256, 256, 81, 81, 260, 256, 258, 261, 258, 
-    258, 258, 258, 258, 81, 261, 258, 258, 81, 258, 258, 257, 262, 81, 81, 
-    81, 81, 81, 81, 81, 258, 258, 81, 81, 81, 81, 81, 81, 81, 256, 81, 256, 
-    256, 257, 257, 81, 81, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 
-    81, 256, 256, 81, 81, 81, 81, 81, 264, 264, 265, 265, 81, 266, 266, 266, 
-    266, 266, 266, 266, 266, 81, 266, 266, 266, 81, 266, 266, 266, 266, 266, 
-    266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 267, 267, 
-    266, 265, 265, 265, 264, 264, 264, 264, 81, 265, 265, 265, 81, 265, 265, 
-    265, 267, 266, 268, 81, 81, 81, 81, 266, 266, 266, 265, 269, 269, 269, 
-    269, 269, 269, 269, 266, 266, 266, 264, 264, 81, 81, 270, 270, 270, 270, 
-    270, 270, 270, 270, 270, 270, 269, 269, 269, 269, 269, 269, 269, 269, 
-    269, 271, 266, 266, 266, 266, 266, 266, 81, 81, 272, 272, 81, 273, 273, 
-    273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 
-    273, 273, 81, 81, 81, 273, 273, 273, 273, 273, 273, 273, 273, 81, 273, 
-    273, 273, 273, 273, 273, 273, 273, 273, 81, 273, 81, 81, 81, 81, 274, 81, 
-    81, 81, 81, 272, 272, 272, 275, 275, 275, 81, 275, 81, 272, 272, 272, 
-    272, 272, 272, 272, 272, 81, 81, 81, 81, 81, 81, 276, 276, 276, 276, 276, 
-    276, 276, 276, 276, 276, 81, 81, 272, 272, 277, 81, 81, 81, 81, 278, 278, 
-    278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 
-    279, 278, 278, 279, 279, 279, 279, 280, 280, 281, 81, 81, 81, 81, 282, 
-    278, 278, 278, 278, 278, 278, 283, 279, 284, 284, 284, 284, 279, 279, 
-    279, 285, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 287, 287, 81, 
-    81, 81, 81, 81, 288, 288, 81, 288, 81, 288, 288, 288, 288, 288, 81, 288, 
-    288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, 
-    288, 81, 288, 81, 288, 288, 289, 288, 288, 289, 289, 289, 289, 290, 290, 
-    291, 289, 289, 288, 81, 81, 288, 288, 288, 288, 288, 81, 292, 81, 293, 
-    293, 293, 293, 289, 289, 81, 81, 294, 294, 294, 294, 294, 294, 294, 294, 
-    294, 294, 81, 81, 288, 288, 288, 288, 295, 296, 296, 296, 297, 298, 297, 
-    297, 299, 297, 297, 300, 299, 301, 301, 301, 301, 301, 299, 302, 301, 
-    302, 302, 302, 303, 303, 302, 302, 302, 302, 302, 302, 304, 304, 304, 
-    304, 304, 304, 304, 304, 304, 304, 305, 305, 305, 305, 305, 305, 305, 
-    305, 305, 305, 306, 303, 302, 303, 302, 307, 308, 309, 308, 309, 310, 
-    310, 295, 295, 295, 295, 295, 295, 295, 295, 81, 295, 295, 295, 295, 295, 
-    295, 295, 295, 295, 295, 295, 295, 81, 81, 81, 81, 311, 312, 313, 314, 
-    313, 313, 313, 313, 313, 312, 312, 312, 312, 313, 315, 312, 313, 316, 
-    316, 317, 300, 316, 316, 295, 295, 295, 295, 295, 313, 313, 313, 313, 
-    313, 313, 313, 313, 313, 313, 313, 81, 313, 313, 313, 313, 313, 313, 313, 
-    313, 313, 313, 313, 313, 81, 306, 306, 302, 302, 302, 302, 302, 302, 303, 
-    302, 302, 302, 302, 302, 302, 81, 302, 302, 297, 297, 300, 297, 298, 318, 
-    318, 318, 318, 299, 299, 81, 81, 81, 81, 81, 319, 319, 319, 319, 319, 
-    319, 319, 319, 319, 319, 319, 320, 320, 321, 321, 321, 321, 320, 321, 
-    321, 321, 321, 321, 322, 320, 323, 323, 320, 320, 321, 321, 319, 324, 
-    324, 324, 324, 324, 324, 324, 324, 324, 324, 325, 325, 326, 326, 326, 
-    326, 319, 319, 319, 319, 319, 319, 320, 320, 321, 321, 319, 319, 319, 
-    319, 321, 321, 321, 319, 320, 320, 320, 319, 319, 320, 320, 320, 320, 
-    320, 320, 320, 319, 319, 319, 321, 321, 321, 321, 319, 319, 319, 319, 
-    319, 321, 320, 320, 321, 321, 320, 320, 320, 320, 320, 320, 327, 319, 
-    320, 324, 324, 320, 320, 320, 321, 328, 328, 329, 329, 329, 329, 329, 
-    329, 329, 329, 329, 329, 329, 329, 329, 329, 81, 329, 81, 81, 81, 81, 81, 
-    329, 81, 81, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 331, 
-    332, 330, 330, 330, 333, 333, 333, 333, 333, 333, 333, 333, 334, 334, 
-    334, 334, 334, 334, 334, 334, 335, 335, 335, 335, 335, 335, 335, 335, 
-    336, 336, 336, 336, 336, 336, 336, 336, 336, 81, 336, 336, 336, 336, 81, 
-    81, 336, 336, 336, 336, 336, 336, 336, 81, 336, 336, 336, 81, 81, 337, 
-    337, 337, 338, 339, 338, 338, 338, 338, 338, 338, 338, 340, 340, 340, 
-    340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 
-    340, 340, 340, 81, 81, 81, 341, 341, 341, 341, 341, 341, 341, 341, 341, 
-    341, 81, 81, 81, 81, 81, 81, 342, 342, 342, 342, 342, 342, 342, 342, 342, 
-    342, 342, 342, 342, 342, 81, 81, 343, 343, 343, 343, 343, 343, 81, 81, 
-    344, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 
-    345, 345, 345, 345, 345, 345, 345, 346, 347, 345, 348, 349, 349, 349, 
-    349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 
-    349, 350, 351, 81, 81, 81, 352, 352, 352, 352, 352, 352, 352, 352, 352, 
-    352, 352, 198, 198, 198, 353, 353, 353, 352, 352, 352, 352, 352, 352, 
-    352, 352, 81, 81, 81, 81, 81, 81, 81, 354, 354, 354, 354, 354, 354, 354, 
-    354, 354, 354, 354, 354, 354, 81, 354, 354, 354, 354, 355, 355, 356, 81, 
-    81, 81, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 358, 358, 359, 
-    198, 198, 81, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 361, 361, 
-    81, 81, 81, 81, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 
-    362, 362, 81, 362, 362, 362, 81, 363, 363, 81, 81, 81, 81, 364, 364, 364, 
-    364, 364, 364, 364, 364, 364, 364, 364, 364, 365, 365, 366, 365, 365, 
-    365, 365, 365, 365, 365, 366, 366, 366, 366, 366, 366, 366, 366, 365, 
-    366, 366, 365, 365, 365, 365, 365, 365, 365, 365, 365, 367, 365, 368, 
-    368, 369, 370, 368, 371, 368, 372, 364, 373, 81, 81, 374, 374, 374, 374, 
-    374, 374, 374, 374, 374, 374, 81, 81, 81, 81, 81, 81, 375, 375, 375, 375, 
-    375, 375, 375, 375, 375, 375, 81, 81, 81, 81, 81, 81, 376, 376, 377, 377, 
-    378, 379, 380, 376, 381, 381, 376, 382, 382, 382, 383, 81, 384, 384, 384, 
-    384, 384, 384, 384, 384, 384, 384, 81, 81, 81, 81, 81, 81, 385, 385, 385, 
-    385, 385, 385, 385, 385, 385, 385, 385, 386, 385, 385, 385, 385, 385, 81, 
-    81, 81, 81, 81, 81, 81, 385, 385, 385, 385, 385, 382, 382, 385, 385, 387, 
-    385, 81, 81, 81, 81, 81, 345, 345, 345, 345, 345, 345, 81, 81, 388, 388, 
-    388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 81, 389, 
-    389, 389, 390, 390, 390, 390, 389, 389, 390, 390, 390, 81, 81, 81, 81, 
-    390, 390, 389, 390, 390, 390, 390, 390, 390, 391, 392, 393, 81, 81, 81, 
-    81, 394, 81, 81, 81, 395, 395, 396, 396, 396, 396, 396, 396, 396, 396, 
-    396, 396, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 
-    397, 397, 81, 81, 397, 397, 397, 397, 397, 81, 81, 81, 398, 398, 398, 
-    398, 398, 398, 398, 398, 398, 398, 398, 398, 81, 81, 81, 81, 398, 398, 
-    81, 81, 81, 81, 81, 81, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 
-    400, 81, 81, 81, 401, 401, 402, 402, 402, 402, 402, 402, 402, 402, 403, 
-    403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 
-    404, 405, 406, 406, 407, 81, 81, 408, 408, 409, 409, 409, 409, 409, 409, 
-    409, 409, 409, 409, 409, 409, 409, 410, 411, 410, 411, 411, 411, 411, 
-    411, 411, 411, 81, 412, 410, 411, 410, 410, 411, 411, 411, 411, 411, 411, 
-    411, 411, 410, 410, 410, 410, 410, 410, 411, 411, 413, 413, 413, 413, 
-    413, 413, 413, 413, 81, 81, 414, 415, 415, 415, 415, 415, 415, 415, 415, 
-    415, 415, 81, 81, 81, 81, 81, 81, 416, 416, 416, 416, 416, 416, 416, 417, 
-    416, 416, 416, 416, 416, 416, 81, 81, 96, 96, 96, 96, 96, 156, 156, 156, 
-    156, 156, 156, 96, 96, 156, 418, 81, 419, 419, 419, 419, 420, 421, 421, 
-    421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 421, 422, 
-    420, 419, 419, 419, 419, 419, 420, 419, 420, 420, 420, 420, 420, 419, 
-    420, 423, 421, 421, 421, 421, 421, 421, 421, 81, 81, 81, 81, 424, 424, 
-    424, 424, 424, 424, 424, 424, 424, 424, 425, 425, 426, 425, 425, 425, 
-    425, 427, 427, 427, 427, 427, 427, 427, 427, 427, 427, 428, 429, 428, 
-    428, 428, 428, 428, 428, 428, 427, 427, 427, 427, 427, 427, 427, 427, 
-    427, 81, 81, 81, 430, 430, 431, 432, 432, 432, 432, 432, 432, 432, 432, 
-    432, 432, 432, 432, 432, 432, 431, 430, 430, 430, 430, 431, 431, 430, 
-    430, 433, 434, 430, 430, 432, 432, 435, 435, 435, 435, 435, 435, 435, 
-    435, 435, 435, 432, 432, 432, 432, 432, 432, 436, 436, 436, 436, 436, 
-    436, 436, 436, 436, 436, 436, 436, 436, 436, 437, 438, 439, 439, 438, 
-    438, 438, 439, 438, 439, 439, 439, 440, 440, 81, 81, 81, 81, 81, 81, 81, 
-    81, 441, 441, 441, 441, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 
-    442, 442, 443, 443, 443, 443, 443, 443, 443, 443, 444, 444, 444, 444, 
-    444, 444, 444, 444, 443, 443, 444, 445, 81, 81, 81, 446, 446, 446, 446, 
-    446, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 81, 81, 81, 442, 
-    442, 442, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 449, 449, 
-    449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 450, 450, 
-    450, 450, 450, 450, 451, 451, 93, 81, 81, 81, 81, 81, 81, 81, 329, 329, 
-    329, 81, 81, 329, 329, 329, 452, 452, 452, 452, 452, 452, 452, 452, 96, 
-    96, 96, 331, 453, 156, 156, 156, 156, 156, 96, 96, 156, 156, 156, 156, 
-    96, 454, 453, 453, 453, 453, 453, 453, 453, 455, 455, 455, 455, 156, 455, 
-    455, 455, 455, 455, 455, 96, 455, 455, 454, 96, 96, 455, 81, 81, 81, 81, 
-    81, 56, 56, 56, 56, 56, 56, 79, 79, 79, 79, 79, 93, 59, 59, 59, 59, 59, 
-    59, 59, 59, 59, 82, 82, 82, 82, 82, 59, 59, 59, 59, 82, 82, 82, 82, 82, 
-    56, 56, 56, 56, 56, 456, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 59, 59, 
-    59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 82, 96, 96, 156, 96, 96, 96, 96, 
-    96, 96, 96, 156, 96, 96, 457, 458, 156, 459, 96, 96, 96, 96, 96, 96, 96, 
-    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 460, 461, 461, 
-    156, 81, 96, 462, 156, 96, 156, 52, 56, 52, 56, 52, 56, 56, 56, 56, 56, 
-    56, 56, 56, 56, 52, 56, 79, 79, 79, 79, 79, 79, 79, 79, 78, 78, 78, 78, 
-    78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 81, 81, 78, 78, 78, 78, 78, 78, 
-    81, 81, 81, 78, 81, 78, 81, 78, 81, 78, 463, 463, 463, 463, 463, 463, 
-    463, 463, 79, 79, 79, 79, 79, 81, 79, 79, 78, 78, 78, 78, 463, 80, 79, 
-    80, 80, 80, 79, 79, 79, 81, 79, 79, 78, 78, 78, 78, 463, 80, 80, 80, 79, 
-    79, 79, 79, 81, 81, 79, 79, 78, 78, 78, 78, 81, 80, 80, 80, 78, 78, 78, 
-    78, 78, 80, 80, 80, 81, 81, 79, 79, 79, 81, 79, 79, 78, 78, 78, 78, 463, 
-    464, 80, 81, 465, 465, 465, 465, 465, 465, 465, 466, 465, 465, 465, 467, 
-    468, 469, 470, 471, 472, 473, 474, 472, 475, 476, 38, 84, 477, 478, 479, 
-    42, 477, 478, 479, 42, 38, 38, 480, 84, 481, 481, 481, 482, 483, 484, 
-    485, 486, 487, 488, 489, 33, 490, 491, 490, 490, 491, 492, 493, 493, 84, 
-    42, 50, 38, 494, 494, 480, 495, 495, 84, 84, 84, 496, 479, 497, 494, 494, 
-    494, 84, 84, 84, 84, 84, 84, 84, 84, 498, 84, 495, 84, 379, 84, 379, 379, 
-    379, 379, 84, 379, 379, 465, 499, 500, 500, 500, 500, 81, 501, 502, 503, 
-    504, 505, 505, 505, 505, 505, 505, 506, 59, 81, 81, 47, 506, 506, 506, 
-    506, 506, 507, 507, 498, 479, 497, 508, 506, 47, 47, 47, 47, 506, 506, 
-    506, 506, 506, 507, 507, 498, 479, 497, 81, 59, 59, 59, 59, 59, 81, 81, 
-    81, 282, 282, 282, 282, 282, 282, 282, 509, 282, 510, 282, 282, 36, 282, 
-    282, 282, 282, 282, 282, 282, 282, 282, 509, 282, 282, 282, 282, 509, 
-    282, 282, 509, 282, 511, 511, 511, 511, 511, 511, 511, 511, 96, 96, 453, 
-    453, 96, 96, 96, 96, 453, 453, 453, 96, 96, 418, 418, 418, 418, 96, 418, 
-    418, 418, 453, 453, 96, 156, 96, 453, 453, 156, 156, 156, 156, 96, 81, 
-    81, 81, 81, 81, 81, 81, 40, 40, 512, 513, 40, 514, 40, 512, 40, 513, 49, 
-    512, 512, 512, 49, 49, 512, 512, 512, 515, 40, 512, 516, 40, 498, 512, 
-    512, 512, 512, 512, 40, 40, 40, 514, 514, 40, 512, 40, 85, 40, 512, 40, 
-    52, 517, 512, 512, 518, 49, 512, 512, 52, 512, 49, 455, 455, 455, 455, 
-    49, 40, 40, 49, 49, 512, 512, 498, 498, 498, 498, 498, 512, 49, 49, 49, 
-    49, 40, 498, 40, 40, 56, 318, 519, 519, 519, 520, 51, 521, 519, 519, 519, 
-    519, 519, 51, 520, 520, 51, 519, 522, 522, 522, 522, 522, 522, 522, 522, 
-    522, 522, 522, 522, 523, 523, 523, 523, 522, 522, 523, 523, 523, 523, 
-    523, 523, 523, 523, 523, 52, 56, 523, 523, 523, 523, 51, 40, 40, 81, 81, 
-    81, 81, 54, 54, 54, 54, 54, 514, 514, 514, 514, 514, 498, 498, 40, 40, 
-    40, 40, 498, 40, 40, 498, 40, 40, 498, 40, 40, 40, 40, 40, 40, 40, 498, 
-    40, 40, 40, 40, 40, 40, 40, 40, 40, 44, 44, 40, 40, 40, 40, 40, 40, 40, 
-    40, 40, 40, 40, 40, 498, 498, 40, 40, 54, 40, 54, 40, 40, 40, 40, 40, 40, 
-    40, 40, 40, 40, 44, 40, 40, 40, 40, 498, 498, 498, 498, 498, 498, 498, 
-    498, 498, 498, 498, 498, 54, 498, 54, 54, 498, 498, 498, 54, 54, 498, 
-    498, 54, 498, 498, 498, 54, 498, 54, 524, 525, 498, 54, 498, 498, 498, 
-    498, 54, 498, 498, 54, 54, 54, 54, 498, 498, 54, 498, 54, 498, 54, 54, 
-    54, 54, 54, 54, 498, 54, 498, 498, 498, 498, 498, 54, 54, 54, 54, 498, 
-    498, 498, 498, 54, 54, 498, 498, 54, 498, 498, 498, 54, 498, 498, 498, 
-    498, 498, 54, 498, 498, 498, 498, 498, 54, 54, 498, 498, 54, 54, 54, 54, 
-    498, 498, 54, 54, 498, 498, 54, 54, 498, 498, 498, 498, 498, 54, 498, 
-    498, 498, 54, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 
-    498, 54, 498, 498, 498, 498, 498, 498, 498, 526, 479, 497, 479, 497, 40, 
-    40, 40, 40, 40, 40, 514, 40, 40, 40, 40, 40, 40, 40, 527, 527, 40, 40, 
-    40, 40, 498, 498, 40, 40, 40, 40, 40, 40, 40, 528, 529, 40, 40, 40, 40, 
-    40, 40, 40, 40, 40, 40, 40, 318, 318, 318, 318, 318, 318, 318, 318, 318, 
-    318, 318, 318, 318, 40, 498, 40, 40, 40, 40, 40, 40, 40, 40, 318, 40, 40, 
-    40, 40, 40, 498, 498, 498, 498, 498, 498, 498, 498, 498, 40, 40, 40, 40, 
-    40, 530, 530, 530, 530, 40, 40, 40, 527, 531, 531, 527, 40, 40, 40, 40, 
-    40, 40, 40, 40, 40, 40, 40, 81, 40, 40, 40, 81, 81, 81, 81, 81, 51, 51, 
-    51, 51, 51, 51, 51, 51, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
-    532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 
-    521, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 520, 514, 514, 514, 
-    514, 514, 514, 514, 514, 514, 514, 514, 514, 40, 40, 40, 40, 514, 514, 
-    514, 514, 533, 40, 40, 40, 40, 40, 514, 514, 514, 514, 40, 40, 514, 514, 
-    40, 514, 514, 514, 514, 514, 514, 514, 40, 40, 40, 40, 40, 40, 40, 40, 
-    514, 514, 40, 40, 514, 54, 40, 40, 40, 40, 514, 514, 40, 40, 514, 54, 40, 
-    40, 40, 40, 514, 514, 514, 40, 40, 514, 40, 40, 514, 514, 40, 40, 40, 40, 
-    40, 40, 40, 514, 498, 498, 498, 498, 498, 534, 534, 498, 531, 531, 531, 
-    531, 40, 514, 514, 40, 40, 514, 40, 40, 40, 40, 514, 514, 40, 40, 40, 40, 
-    527, 527, 533, 533, 531, 40, 531, 531, 535, 536, 535, 531, 40, 531, 531, 
-    531, 40, 40, 40, 40, 514, 40, 514, 40, 40, 40, 40, 40, 530, 530, 530, 
-    530, 530, 530, 530, 530, 530, 530, 530, 530, 40, 40, 40, 40, 514, 514, 
-    40, 514, 514, 514, 40, 514, 535, 514, 514, 40, 514, 514, 40, 54, 40, 40, 
-    40, 40, 40, 40, 40, 527, 40, 40, 40, 530, 40, 40, 40, 40, 40, 40, 40, 40, 
-    40, 40, 514, 514, 40, 530, 40, 40, 40, 40, 40, 40, 40, 40, 530, 530, 318, 
-    40, 40, 40, 40, 40, 40, 40, 40, 527, 527, 535, 531, 531, 531, 531, 527, 
-    527, 535, 535, 535, 514, 514, 514, 514, 535, 530, 535, 535, 535, 514, 
-    535, 527, 514, 514, 514, 535, 535, 514, 514, 535, 514, 514, 535, 535, 
-    535, 40, 514, 40, 40, 40, 40, 514, 514, 527, 514, 514, 514, 514, 514, 
-    514, 535, 527, 527, 535, 527, 514, 535, 535, 537, 527, 514, 514, 527, 
-    535, 535, 531, 531, 531, 531, 531, 530, 40, 40, 531, 531, 538, 538, 536, 
-    536, 40, 40, 530, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 44, 40, 
-    40, 40, 40, 40, 40, 530, 40, 530, 40, 40, 40, 40, 530, 530, 530, 40, 539, 
-    40, 40, 40, 540, 540, 540, 540, 540, 540, 40, 541, 541, 531, 40, 40, 40, 
-    479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 51, 
-    51, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 40, 530, 
-    530, 530, 40, 40, 40, 40, 40, 40, 40, 530, 498, 498, 498, 498, 498, 479, 
-    497, 498, 498, 498, 498, 498, 498, 498, 16, 31, 16, 31, 16, 31, 16, 31, 
-    479, 497, 542, 542, 542, 542, 542, 542, 542, 542, 498, 498, 498, 479, 
-    497, 16, 31, 479, 497, 479, 497, 479, 497, 479, 497, 479, 497, 498, 498, 
-    498, 498, 498, 498, 498, 479, 497, 479, 497, 498, 498, 498, 498, 498, 
-    498, 498, 498, 479, 497, 498, 498, 40, 40, 40, 530, 530, 40, 40, 40, 498, 
-    498, 498, 498, 498, 40, 40, 498, 498, 498, 498, 498, 498, 40, 40, 40, 
-    530, 40, 40, 40, 40, 539, 514, 514, 40, 40, 40, 40, 81, 81, 40, 40, 40, 
-    40, 40, 40, 40, 40, 81, 81, 543, 543, 543, 543, 543, 543, 543, 543, 543, 
-    543, 543, 543, 543, 543, 543, 81, 544, 544, 544, 544, 544, 544, 544, 544, 
-    544, 544, 544, 544, 544, 544, 544, 81, 52, 56, 52, 52, 52, 56, 56, 52, 
-    56, 52, 56, 52, 56, 52, 52, 52, 52, 56, 52, 56, 56, 52, 56, 56, 56, 56, 
-    56, 56, 59, 59, 52, 52, 87, 88, 87, 88, 88, 545, 545, 545, 545, 545, 545, 
-    87, 88, 87, 88, 546, 546, 546, 87, 88, 81, 81, 81, 81, 81, 547, 548, 548, 
-    548, 549, 547, 548, 330, 330, 330, 330, 330, 330, 81, 330, 81, 81, 81, 
-    81, 81, 330, 81, 81, 550, 550, 550, 550, 550, 550, 550, 550, 81, 81, 81, 
-    81, 81, 81, 81, 551, 552, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 
-    81, 81, 553, 95, 95, 95, 95, 95, 95, 95, 95, 554, 554, 42, 50, 42, 50, 
-    554, 554, 554, 42, 50, 554, 42, 50, 379, 379, 379, 379, 379, 379, 379, 
-    379, 84, 474, 555, 379, 556, 84, 42, 50, 84, 84, 42, 50, 479, 497, 479, 
-    497, 479, 497, 479, 497, 379, 379, 379, 379, 377, 60, 379, 379, 84, 379, 
-    379, 84, 84, 84, 84, 84, 557, 557, 379, 379, 379, 84, 474, 379, 479, 379, 
-    379, 379, 379, 379, 379, 379, 379, 84, 379, 84, 379, 379, 558, 558, 558, 
-    558, 558, 558, 558, 558, 558, 558, 81, 558, 558, 558, 558, 558, 558, 558, 
-    558, 558, 81, 81, 81, 81, 558, 558, 558, 558, 558, 558, 81, 81, 527, 527, 
-    527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 81, 81, 81, 81, 559, 
-    560, 560, 561, 527, 562, 563, 564, 528, 529, 528, 529, 528, 529, 528, 
-    529, 528, 529, 527, 527, 528, 529, 528, 529, 528, 529, 528, 529, 565, 
-    528, 529, 529, 527, 564, 564, 564, 564, 564, 564, 564, 564, 564, 566, 
-    567, 568, 569, 570, 570, 571, 572, 572, 572, 572, 573, 527, 527, 564, 
-    564, 564, 562, 574, 561, 527, 531, 81, 575, 576, 575, 576, 575, 576, 575, 
-    576, 575, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 
-    576, 576, 576, 576, 576, 575, 576, 576, 576, 576, 576, 576, 576, 575, 
-    576, 575, 576, 575, 576, 576, 576, 576, 576, 576, 575, 576, 576, 576, 
-    576, 576, 576, 575, 575, 81, 81, 577, 577, 578, 578, 579, 579, 576, 565, 
-    580, 581, 580, 581, 580, 581, 580, 581, 580, 581, 581, 581, 581, 581, 
-    581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 580, 581, 
-    581, 581, 581, 581, 581, 581, 580, 581, 580, 581, 580, 581, 581, 581, 
-    581, 581, 581, 580, 581, 581, 581, 581, 581, 581, 580, 580, 581, 581, 
-    581, 581, 582, 583, 584, 584, 581, 81, 81, 81, 81, 81, 585, 585, 585, 
-    585, 585, 585, 585, 585, 585, 585, 585, 81, 586, 586, 586, 586, 586, 586, 
-    586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 
-    586, 586, 81, 587, 587, 588, 588, 588, 588, 587, 587, 587, 587, 587, 587, 
-    587, 587, 587, 587, 585, 585, 585, 81, 81, 81, 81, 81, 580, 580, 580, 
-    580, 580, 580, 580, 580, 589, 589, 589, 589, 589, 589, 589, 589, 589, 
-    589, 589, 589, 589, 590, 590, 81, 588, 588, 588, 588, 588, 588, 588, 588, 
-    588, 588, 587, 587, 587, 587, 587, 587, 591, 591, 591, 591, 591, 591, 
-    591, 591, 527, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 
-    592, 592, 592, 592, 589, 589, 589, 589, 590, 590, 590, 587, 587, 592, 
-    592, 592, 592, 592, 592, 592, 587, 587, 587, 587, 527, 527, 527, 527, 
-    593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 
-    593, 81, 587, 587, 587, 587, 587, 587, 587, 527, 527, 527, 527, 587, 587, 
-    587, 587, 587, 587, 587, 587, 587, 587, 587, 527, 527, 594, 594, 594, 
-    594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 595, 595, 595, 
-    595, 595, 595, 595, 595, 595, 595, 596, 596, 596, 596, 596, 596, 596, 
-    596, 596, 596, 596, 596, 596, 597, 596, 596, 596, 596, 596, 596, 596, 81, 
-    81, 81, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 
-    598, 598, 81, 599, 599, 599, 599, 599, 599, 599, 599, 600, 600, 600, 600, 
-    600, 600, 601, 601, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 
-    602, 602, 603, 604, 605, 604, 606, 606, 606, 606, 606, 606, 606, 606, 
-    606, 606, 602, 602, 81, 81, 81, 81, 90, 93, 90, 93, 90, 93, 607, 95, 97, 
-    97, 97, 608, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 608, 609, 90, 93, 
-    90, 93, 456, 456, 95, 95, 610, 610, 610, 610, 610, 610, 610, 610, 610, 
-    610, 610, 610, 610, 610, 611, 611, 611, 611, 611, 611, 611, 611, 611, 
-    611, 612, 612, 613, 614, 614, 614, 614, 614, 62, 62, 62, 62, 62, 62, 62, 
-    60, 60, 60, 60, 60, 60, 60, 60, 60, 62, 62, 52, 56, 52, 56, 52, 56, 56, 
-    56, 52, 56, 52, 56, 52, 56, 59, 56, 56, 56, 56, 56, 56, 56, 56, 52, 56, 
-    52, 56, 52, 52, 56, 60, 615, 615, 52, 56, 52, 56, 57, 52, 56, 52, 56, 56, 
-    56, 52, 56, 52, 56, 52, 52, 52, 52, 52, 56, 52, 52, 52, 52, 52, 56, 52, 
-    56, 81, 81, 52, 56, 52, 52, 52, 81, 81, 81, 81, 81, 81, 81, 81, 57, 59, 
-    59, 56, 57, 57, 57, 57, 57, 616, 616, 617, 616, 616, 616, 618, 616, 616, 
-    616, 616, 617, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 
-    616, 616, 616, 616, 619, 619, 617, 617, 619, 620, 620, 620, 620, 81, 81, 
-    81, 81, 621, 621, 621, 621, 621, 621, 318, 318, 509, 518, 81, 81, 81, 81, 
-    81, 81, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, 623, 
-    623, 624, 624, 625, 625, 626, 626, 626, 626, 626, 626, 626, 626, 626, 
-    626, 626, 626, 626, 626, 626, 626, 626, 626, 625, 625, 625, 625, 625, 
-    625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 627, 628, 81, 81, 
-    81, 81, 81, 81, 81, 81, 629, 629, 630, 630, 630, 630, 630, 630, 630, 630, 
-    630, 630, 81, 81, 81, 81, 81, 81, 631, 631, 631, 631, 631, 631, 631, 631, 
-    631, 631, 195, 195, 195, 195, 195, 195, 200, 200, 200, 195, 632, 195, 
-    195, 193, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 634, 634, 
-    634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 
-    634, 634, 634, 634, 635, 635, 635, 635, 635, 636, 636, 636, 198, 637, 
-    638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 
-    638, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 640, 641, 81, 
-    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 642, 333, 333, 333, 333, 333, 81, 
-    81, 81, 643, 643, 643, 644, 645, 645, 645, 645, 645, 645, 645, 645, 645, 
-    645, 645, 645, 645, 645, 645, 646, 644, 644, 643, 643, 643, 643, 644, 
-    644, 643, 643, 644, 644, 647, 648, 648, 648, 648, 648, 648, 649, 649, 
-    649, 648, 648, 648, 648, 81, 61, 650, 650, 650, 650, 650, 650, 650, 650, 
-    650, 650, 81, 81, 81, 81, 648, 648, 319, 319, 319, 319, 319, 321, 651, 
-    319, 324, 324, 319, 319, 319, 319, 319, 81, 652, 652, 652, 652, 652, 652, 
-    652, 652, 652, 653, 653, 653, 653, 653, 653, 654, 654, 653, 653, 654, 
-    654, 653, 653, 81, 652, 652, 652, 653, 652, 652, 652, 652, 652, 652, 652, 
-    652, 653, 654, 81, 81, 655, 655, 655, 655, 655, 655, 655, 655, 655, 655, 
-    81, 81, 656, 657, 657, 657, 651, 319, 319, 319, 319, 319, 319, 328, 328, 
-    328, 319, 320, 321, 320, 319, 319, 658, 658, 658, 658, 658, 658, 658, 
-    658, 659, 658, 659, 659, 660, 658, 658, 659, 659, 658, 658, 658, 658, 
-    658, 659, 659, 658, 659, 658, 81, 81, 81, 81, 81, 81, 81, 81, 658, 658, 
-    661, 662, 662, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 
-    664, 665, 665, 664, 664, 666, 666, 663, 667, 667, 664, 668, 81, 81, 336, 
-    336, 336, 336, 336, 336, 81, 56, 56, 56, 615, 59, 59, 59, 59, 56, 56, 56, 
-    56, 56, 79, 56, 56, 343, 343, 343, 343, 343, 343, 343, 343, 663, 663, 
-    663, 664, 664, 665, 664, 664, 665, 664, 664, 666, 664, 668, 81, 81, 669, 
-    669, 669, 669, 669, 669, 669, 669, 669, 669, 81, 81, 81, 81, 81, 81, 670, 
-    671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 
-    671, 671, 671, 671, 671, 670, 671, 671, 671, 671, 671, 671, 671, 81, 81, 
-    81, 81, 334, 334, 334, 334, 334, 334, 334, 81, 81, 81, 81, 335, 335, 335, 
-    335, 335, 335, 335, 335, 335, 81, 81, 81, 81, 672, 672, 672, 672, 672, 
-    672, 672, 672, 673, 673, 673, 673, 673, 673, 673, 673, 594, 594, 595, 
-    595, 595, 595, 595, 595, 56, 56, 56, 56, 56, 56, 56, 81, 81, 81, 81, 101, 
-    101, 101, 101, 101, 81, 81, 81, 81, 81, 129, 674, 129, 129, 675, 129, 
-    129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 81, 129, 129, 
-    129, 129, 129, 81, 129, 81, 129, 129, 81, 129, 129, 81, 129, 129, 146, 
-    146, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 
-    676, 676, 676, 81, 81, 81, 81, 81, 81, 81, 81, 81, 146, 146, 146, 146, 
-    146, 146, 146, 146, 146, 146, 146, 497, 479, 81, 81, 146, 146, 146, 146, 
-    146, 146, 146, 146, 146, 146, 135, 138, 81, 81, 677, 677, 677, 677, 677, 
-    677, 677, 677, 678, 560, 560, 678, 678, 679, 679, 528, 529, 680, 81, 81, 
-    81, 81, 81, 81, 96, 96, 96, 96, 96, 96, 96, 156, 156, 156, 156, 156, 156, 
-    156, 95, 95, 561, 571, 571, 681, 681, 528, 529, 528, 529, 528, 529, 528, 
-    529, 528, 529, 528, 529, 528, 529, 528, 529, 561, 561, 528, 529, 561, 
-    561, 561, 561, 681, 681, 681, 682, 561, 682, 81, 582, 683, 679, 679, 571, 
-    528, 529, 528, 529, 528, 529, 684, 561, 561, 685, 686, 687, 687, 687, 81, 
-    561, 688, 689, 561, 81, 81, 81, 81, 146, 146, 146, 146, 146, 81, 81, 499, 
-    81, 690, 691, 692, 693, 694, 691, 691, 695, 696, 691, 697, 698, 699, 698, 
-    700, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 702, 703, 704, 
-    704, 704, 690, 691, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 
-    705, 705, 705, 705, 705, 705, 705, 705, 695, 691, 696, 706, 707, 706, 
-    708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 
-    708, 708, 708, 708, 695, 704, 696, 704, 695, 696, 709, 710, 711, 709, 
-    712, 713, 714, 714, 714, 714, 714, 714, 714, 714, 714, 715, 713, 713, 
-    713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 
-    713, 713, 713, 713, 713, 716, 716, 717, 717, 717, 717, 717, 717, 717, 
-    717, 717, 717, 717, 717, 717, 717, 717, 81, 81, 81, 717, 717, 717, 717, 
-    717, 717, 81, 81, 717, 717, 717, 81, 81, 81, 718, 693, 704, 706, 719, 
-    693, 693, 81, 720, 721, 721, 721, 721, 720, 720, 81, 81, 722, 722, 722, 
-    723, 514, 81, 81, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 
-    724, 81, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 81, 724, 724, 
-    724, 81, 724, 724, 81, 724, 724, 724, 724, 724, 724, 724, 81, 81, 724, 
-    724, 724, 81, 81, 81, 81, 81, 198, 379, 198, 81, 81, 81, 81, 621, 621, 
-    621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 81, 81, 81, 318, 
-    725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 726, 
-    726, 726, 726, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 
-    727, 727, 727, 727, 727, 727, 726, 726, 727, 728, 728, 81, 40, 40, 40, 
-    40, 81, 81, 81, 81, 727, 81, 81, 81, 81, 81, 81, 81, 318, 318, 318, 318, 
-    318, 156, 81, 81, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 
-    729, 729, 81, 81, 81, 730, 730, 730, 730, 730, 730, 730, 730, 730, 81, 
-    81, 81, 81, 81, 81, 81, 156, 506, 506, 506, 506, 506, 506, 506, 506, 506, 
-    506, 506, 506, 506, 506, 506, 506, 506, 506, 506, 81, 81, 81, 81, 731, 
-    731, 731, 731, 731, 731, 731, 731, 732, 732, 732, 732, 81, 81, 81, 81, 
-    81, 81, 81, 81, 81, 731, 731, 731, 733, 733, 733, 733, 733, 733, 733, 
-    733, 733, 734, 733, 733, 733, 733, 733, 733, 733, 733, 734, 81, 81, 81, 
-    81, 81, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, 735, 
-    735, 736, 736, 736, 736, 736, 81, 81, 81, 81, 81, 737, 737, 737, 737, 
-    737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 81, 738, 739, 739, 739, 
-    739, 739, 739, 739, 739, 739, 739, 739, 739, 81, 81, 81, 81, 740, 741, 
-    741, 741, 741, 741, 81, 81, 742, 742, 742, 742, 742, 742, 742, 742, 743, 
-    743, 743, 743, 743, 743, 743, 743, 744, 744, 744, 744, 744, 744, 744, 
-    744, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 745, 
-    745, 81, 81, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 81, 81, 
-    81, 81, 81, 81, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 
-    747, 81, 81, 81, 81, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 
-    748, 748, 81, 81, 81, 81, 749, 749, 749, 749, 749, 749, 749, 749, 750, 
-    750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 81, 81, 81, 81, 
-    81, 81, 81, 81, 81, 81, 81, 751, 752, 752, 752, 752, 752, 752, 752, 752, 
-    752, 752, 752, 752, 752, 752, 752, 81, 752, 752, 752, 752, 752, 752, 81, 
-    81, 753, 753, 753, 753, 753, 753, 81, 81, 753, 81, 753, 753, 753, 753, 
-    753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 
-    753, 753, 81, 753, 753, 81, 81, 81, 753, 81, 81, 753, 754, 754, 754, 754, 
-    754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 81, 755, 756, 756, 756, 
-    756, 756, 756, 756, 756, 757, 757, 757, 757, 757, 757, 757, 757, 757, 
-    757, 757, 757, 757, 757, 757, 758, 758, 759, 759, 759, 759, 759, 759, 
-    759, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 
-    760, 760, 81, 81, 81, 81, 81, 81, 81, 81, 761, 761, 761, 761, 761, 761, 
-    761, 761, 761, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 81, 
-    762, 762, 81, 81, 81, 81, 81, 763, 763, 763, 763, 763, 764, 764, 764, 
-    764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 765, 765, 765, 
-    765, 765, 765, 81, 81, 81, 766, 767, 767, 767, 767, 767, 767, 767, 767, 
-    767, 767, 81, 81, 81, 81, 81, 768, 769, 769, 769, 769, 769, 769, 769, 
-    769, 770, 770, 770, 770, 770, 770, 770, 770, 81, 81, 81, 81, 771, 771, 
-    770, 770, 771, 771, 771, 771, 771, 771, 771, 771, 81, 81, 771, 771, 771, 
-    771, 771, 771, 772, 773, 773, 773, 81, 773, 773, 81, 81, 81, 81, 81, 773, 
-    774, 773, 775, 772, 772, 772, 772, 81, 772, 772, 772, 81, 772, 772, 772, 
-    772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 
-    772, 772, 772, 772, 81, 81, 775, 776, 774, 81, 81, 81, 81, 777, 778, 778, 
-    778, 778, 778, 778, 778, 778, 778, 81, 81, 81, 81, 81, 81, 81, 779, 779, 
-    779, 779, 779, 779, 779, 779, 780, 81, 81, 81, 81, 81, 81, 81, 781, 781, 
-    781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 782, 782, 783, 
-    784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 785, 
-    785, 785, 786, 786, 786, 786, 786, 786, 786, 786, 787, 786, 786, 786, 
-    786, 786, 786, 786, 786, 786, 786, 786, 786, 788, 789, 81, 81, 81, 81, 
-    790, 790, 790, 790, 790, 791, 791, 791, 791, 791, 791, 792, 81, 793, 793, 
-    793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 81, 81, 81, 
-    794, 794, 794, 794, 794, 794, 794, 795, 795, 795, 795, 795, 795, 795, 
-    795, 795, 795, 795, 795, 795, 795, 81, 81, 796, 796, 796, 796, 796, 796, 
-    796, 796, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 81, 81, 
-    81, 81, 81, 798, 798, 798, 798, 798, 798, 798, 798, 799, 799, 799, 799, 
-    799, 799, 799, 799, 799, 799, 81, 81, 81, 81, 81, 81, 81, 800, 800, 800, 
-    800, 81, 81, 81, 81, 801, 801, 801, 801, 801, 801, 801, 802, 802, 802, 
-    802, 802, 802, 802, 802, 802, 81, 81, 81, 81, 81, 81, 81, 803, 803, 803, 
-    803, 803, 803, 803, 803, 803, 803, 803, 81, 81, 81, 81, 81, 804, 804, 
-    804, 804, 804, 804, 804, 804, 804, 804, 804, 81, 81, 81, 81, 81, 81, 81, 
-    805, 805, 805, 805, 805, 805, 806, 806, 806, 806, 806, 806, 806, 806, 
-    806, 806, 806, 806, 807, 807, 807, 807, 808, 808, 808, 808, 808, 808, 
-    808, 808, 808, 808, 81, 81, 81, 81, 81, 81, 809, 809, 809, 809, 809, 809, 
-    809, 809, 809, 809, 809, 809, 809, 809, 809, 81, 810, 810, 810, 810, 810, 
-    810, 810, 810, 810, 810, 810, 810, 810, 811, 811, 811, 811, 811, 811, 
-    811, 811, 811, 811, 810, 812, 812, 812, 812, 812, 812, 812, 812, 812, 
-    812, 812, 812, 812, 812, 813, 813, 814, 814, 814, 813, 814, 813, 813, 
-    813, 813, 815, 815, 815, 815, 816, 816, 816, 816, 816, 81, 81, 81, 81, 
-    81, 81, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 817, 
-    817, 817, 81, 818, 819, 818, 820, 820, 820, 820, 820, 820, 820, 820, 820, 
-    820, 820, 820, 820, 819, 819, 819, 819, 819, 819, 819, 819, 819, 819, 
-    819, 819, 819, 819, 821, 822, 822, 823, 823, 823, 823, 823, 81, 81, 81, 
-    81, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 824, 
-    824, 824, 824, 824, 824, 824, 825, 825, 825, 825, 825, 825, 825, 825, 
-    825, 825, 81, 81, 81, 81, 81, 81, 81, 821, 826, 826, 827, 828, 828, 828, 
-    828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 827, 827, 827, 826, 
-    826, 826, 826, 827, 827, 829, 830, 831, 831, 832, 833, 833, 833, 833, 81, 
-    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 832, 81, 81, 834, 834, 834, 834, 
-    834, 834, 834, 834, 834, 81, 81, 81, 81, 81, 81, 81, 835, 835, 835, 835, 
-    835, 835, 835, 835, 835, 835, 81, 81, 81, 81, 81, 81, 836, 836, 836, 837, 
-    837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 
-    837, 837, 837, 837, 837, 838, 838, 838, 838, 838, 839, 838, 838, 838, 
-    838, 838, 838, 840, 840, 81, 841, 841, 841, 841, 841, 841, 841, 841, 841, 
-    841, 842, 842, 842, 842, 837, 839, 839, 81, 843, 843, 843, 843, 843, 843, 
-    843, 843, 843, 843, 843, 844, 845, 846, 843, 81, 847, 847, 848, 849, 849, 
-    849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 
-    848, 848, 848, 847, 847, 847, 847, 847, 847, 847, 847, 847, 848, 850, 
-    849, 849, 849, 849, 851, 851, 852, 851, 847, 853, 847, 847, 852, 81, 81, 
-    854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 849, 855, 849, 851, 
-    851, 851, 81, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 
-    856, 856, 856, 856, 856, 856, 856, 856, 81, 81, 81, 857, 857, 857, 857, 
-    857, 857, 857, 857, 857, 857, 81, 857, 857, 857, 857, 857, 857, 857, 857, 
-    857, 858, 858, 858, 859, 859, 859, 858, 858, 859, 860, 861, 859, 862, 
-    862, 863, 862, 862, 863, 859, 81, 864, 864, 864, 864, 864, 864, 864, 81, 
-    864, 81, 864, 864, 864, 864, 81, 864, 864, 864, 864, 864, 864, 864, 864, 
-    864, 864, 864, 864, 864, 864, 864, 81, 864, 864, 865, 81, 81, 81, 81, 81, 
-    81, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, 
-    866, 867, 868, 868, 868, 867, 867, 867, 867, 867, 867, 869, 870, 81, 81, 
-    81, 81, 81, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 81, 81, 81, 
-    81, 81, 81, 872, 872, 873, 873, 81, 874, 874, 874, 874, 874, 874, 874, 
-    874, 81, 81, 874, 874, 81, 81, 874, 874, 874, 874, 874, 874, 874, 874, 
-    874, 874, 874, 874, 874, 874, 81, 874, 874, 874, 874, 874, 874, 874, 81, 
-    874, 874, 81, 874, 874, 874, 874, 874, 81, 875, 876, 874, 873, 873, 872, 
-    873, 873, 873, 873, 81, 81, 873, 873, 81, 81, 873, 873, 877, 81, 81, 874, 
-    81, 81, 81, 81, 81, 81, 873, 81, 81, 81, 81, 81, 874, 874, 874, 874, 874, 
-    873, 873, 81, 81, 878, 878, 878, 878, 878, 878, 878, 81, 81, 81, 879, 
-    879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 880, 880, 
-    880, 881, 881, 881, 881, 881, 881, 881, 881, 880, 880, 882, 881, 881, 
-    880, 883, 879, 879, 879, 879, 884, 884, 884, 884, 885, 886, 886, 886, 
-    886, 886, 886, 886, 886, 886, 886, 81, 884, 81, 885, 887, 879, 888, 888, 
-    888, 888, 888, 888, 888, 888, 889, 889, 889, 890, 890, 890, 890, 890, 
-    890, 889, 890, 889, 889, 889, 889, 890, 890, 889, 891, 892, 888, 888, 
-    893, 888, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 81, 81, 81, 
-    81, 81, 81, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 
-    895, 895, 895, 896, 896, 896, 897, 897, 897, 897, 81, 81, 896, 896, 896, 
-    896, 897, 897, 896, 898, 899, 900, 901, 901, 902, 902, 903, 903, 903, 
-    901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 
-    901, 895, 895, 895, 895, 897, 897, 81, 81, 904, 904, 904, 904, 904, 904, 
-    904, 904, 905, 905, 905, 906, 906, 906, 906, 906, 906, 906, 906, 905, 
-    905, 906, 905, 907, 906, 908, 908, 909, 904, 81, 81, 81, 910, 910, 910, 
-    910, 910, 910, 910, 910, 910, 910, 81, 81, 81, 81, 81, 81, 911, 911, 911, 
-    911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 81, 81, 81, 912, 912, 
-    912, 912, 912, 912, 912, 912, 912, 912, 912, 913, 914, 913, 914, 914, 
-    913, 913, 913, 913, 913, 913, 915, 916, 912, 81, 81, 81, 81, 81, 81, 81, 
-    917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 81, 81, 81, 81, 81, 81, 
-    918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 81, 81, 919, 919, 
-    919, 920, 920, 919, 919, 919, 919, 920, 919, 919, 919, 919, 921, 81, 81, 
-    81, 81, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 923, 923, 924, 
-    924, 924, 925, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 
-    926, 927, 927, 927, 928, 928, 928, 928, 928, 928, 928, 928, 928, 927, 
-    929, 930, 931, 81, 81, 81, 81, 932, 932, 932, 932, 932, 932, 932, 932, 
-    933, 933, 933, 933, 933, 933, 933, 933, 934, 934, 934, 934, 934, 934, 
-    934, 934, 934, 934, 935, 935, 935, 935, 935, 935, 935, 935, 935, 81, 81, 
-    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 936, 937, 937, 937, 937, 937, 
-    937, 937, 937, 81, 81, 937, 937, 937, 937, 937, 937, 937, 938, 938, 938, 
-    939, 939, 939, 939, 81, 81, 939, 939, 938, 938, 938, 938, 940, 937, 941, 
-    937, 938, 81, 81, 81, 942, 943, 943, 943, 943, 943, 943, 944, 944, 943, 
-    943, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 
-    942, 942, 942, 943, 945, 943, 943, 943, 943, 946, 942, 943, 943, 943, 
-    943, 947, 948, 949, 949, 949, 949, 947, 948, 945, 950, 951, 951, 951, 
-    951, 951, 951, 952, 952, 951, 951, 951, 950, 950, 950, 950, 950, 950, 
-    950, 950, 950, 950, 950, 950, 950, 950, 951, 951, 951, 951, 951, 951, 
-    951, 951, 951, 951, 951, 951, 951, 952, 951, 953, 954, 954, 954, 950, 
-    955, 955, 955, 954, 954, 81, 81, 81, 81, 81, 956, 956, 956, 956, 956, 
-    956, 956, 956, 956, 81, 81, 81, 81, 81, 81, 81, 957, 957, 957, 957, 957, 
-    957, 957, 957, 957, 81, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 
-    957, 957, 957, 958, 959, 959, 959, 959, 959, 959, 959, 81, 959, 959, 959, 
-    959, 959, 959, 958, 960, 957, 961, 961, 961, 961, 961, 81, 81, 962, 962, 
-    962, 962, 962, 962, 962, 962, 962, 962, 963, 963, 963, 963, 963, 963, 
-    963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 81, 81, 
-    81, 964, 965, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 
-    966, 966, 81, 81, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 
-    967, 967, 967, 81, 968, 967, 967, 967, 967, 967, 967, 967, 968, 967, 967, 
-    968, 967, 967, 81, 969, 969, 969, 969, 969, 969, 969, 81, 969, 969, 81, 
-    969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 
-    970, 970, 970, 970, 970, 970, 81, 81, 81, 970, 81, 970, 970, 81, 970, 
-    970, 970, 971, 970, 972, 972, 969, 970, 973, 973, 973, 973, 973, 973, 
-    973, 973, 973, 973, 81, 81, 81, 81, 81, 81, 974, 974, 974, 974, 974, 974, 
-    81, 974, 974, 81, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 
-    974, 974, 974, 974, 974, 975, 975, 975, 975, 975, 81, 976, 976, 81, 975, 
-    975, 976, 975, 977, 974, 81, 81, 81, 81, 81, 81, 81, 978, 978, 978, 978, 
-    978, 978, 978, 978, 978, 978, 81, 81, 81, 81, 81, 81, 979, 979, 979, 979, 
-    979, 979, 979, 979, 979, 979, 979, 980, 980, 981, 981, 982, 982, 81, 81, 
-    81, 81, 81, 81, 81, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 
-    243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 983, 983, 983, 
-    983, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 
-    244, 244, 244, 244, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 
-    984, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 81, 81, 81, 81, 
-    81, 81, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 
-    986, 986, 81, 987, 987, 987, 987, 987, 81, 81, 81, 985, 985, 985, 985, 
-    81, 81, 81, 81, 988, 988, 988, 988, 988, 988, 988, 988, 989, 989, 989, 
-    990, 990, 990, 988, 988, 988, 988, 990, 988, 988, 988, 989, 990, 989, 
-    990, 988, 988, 988, 988, 988, 988, 988, 989, 990, 990, 988, 988, 988, 
-    988, 988, 988, 988, 988, 988, 988, 988, 81, 991, 991, 991, 991, 991, 991, 
-    991, 992, 993, 81, 81, 81, 81, 81, 81, 81, 994, 994, 994, 994, 994, 994, 
-    994, 994, 994, 994, 994, 994, 994, 994, 995, 996, 994, 994, 994, 994, 
-    994, 994, 994, 81, 610, 81, 81, 81, 81, 81, 81, 81, 997, 997, 997, 997, 
-    997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 81, 998, 998, 998, 
-    998, 998, 998, 998, 998, 998, 998, 81, 81, 81, 81, 999, 999, 1000, 1000, 
-    1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 
-    81, 81, 1001, 1001, 1001, 1001, 1001, 1002, 81, 81, 1003, 1003, 1003, 
-    1003, 1003, 1003, 1003, 1003, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 
-    1005, 1005, 1005, 1006, 1006, 1007, 1007, 1007, 1007, 1008, 1008, 1008, 
-    1008, 1005, 1007, 81, 81, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 
-    1009, 1009, 81, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 81, 1003, 1003, 
-    1003, 1003, 1003, 81, 81, 81, 81, 81, 1003, 1003, 1003, 1011, 1011, 1011, 
-    1011, 1011, 1011, 1011, 1011, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 
-    1012, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 
-    1013, 1013, 1013, 1013, 1014, 1014, 1015, 1015, 81, 81, 81, 81, 81, 1016, 
-    1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 81, 81, 81, 
-    81, 1017, 1016, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 
-    1018, 1018, 1018, 1018, 1018, 1018, 81, 81, 81, 81, 81, 81, 81, 1017, 
-    1017, 1017, 1017, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 
-    1019, 1019, 1019, 1019, 1020, 1021, 582, 1022, 81, 81, 81, 81, 1023, 
-    1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 81, 81, 81, 
-    81, 81, 581, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 
-    576, 576, 81, 575, 575, 575, 81, 81, 81, 81, 81, 81, 81, 81, 81, 580, 
-    580, 580, 580, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 
-    1024, 1024, 1024, 81, 81, 81, 81, 1025, 1025, 1025, 1025, 1025, 1025, 
-    1025, 1025, 1025, 1025, 1025, 81, 81, 81, 81, 81, 1025, 1025, 1025, 1025, 
-    1025, 81, 81, 81, 1025, 81, 81, 81, 81, 81, 81, 81, 1025, 1025, 81, 81, 
-    1026, 1027, 1028, 1029, 505, 505, 505, 505, 81, 81, 81, 81, 318, 318, 
-    318, 318, 318, 318, 81, 81, 318, 318, 318, 318, 318, 318, 318, 81, 81, 
-    318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 1030, 1030, 
-    453, 453, 453, 318, 318, 318, 1031, 1030, 1030, 1030, 1030, 1030, 505, 
-    505, 505, 505, 505, 505, 505, 505, 156, 156, 156, 156, 156, 156, 156, 
-    156, 318, 318, 96, 96, 96, 96, 96, 156, 156, 318, 318, 318, 318, 318, 
-    318, 96, 96, 96, 96, 318, 318, 318, 81, 81, 81, 81, 81, 81, 81, 727, 727, 
-    1032, 1032, 1032, 727, 81, 81, 621, 621, 621, 621, 81, 81, 81, 81, 621, 
-    81, 81, 81, 81, 81, 81, 81, 512, 512, 512, 512, 512, 512, 512, 512, 512, 
-    512, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 
-    49, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 49, 49, 49, 49, 49, 
-    49, 49, 81, 49, 49, 49, 49, 49, 49, 512, 81, 512, 512, 81, 81, 512, 81, 
-    81, 512, 512, 81, 81, 512, 512, 512, 512, 81, 512, 512, 49, 49, 81, 49, 
-    81, 49, 49, 49, 49, 49, 49, 49, 81, 49, 49, 49, 49, 49, 49, 49, 512, 512, 
-    81, 512, 512, 512, 512, 81, 81, 512, 512, 512, 512, 512, 512, 512, 512, 
-    81, 512, 512, 512, 512, 512, 512, 512, 81, 49, 49, 512, 512, 81, 512, 
-    512, 512, 512, 81, 512, 512, 512, 512, 512, 81, 512, 81, 81, 81, 512, 
-    512, 512, 512, 512, 512, 512, 81, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 
-    49, 49, 81, 81, 512, 1033, 49, 49, 49, 49, 49, 49, 49, 49, 49, 498, 49, 
-    49, 49, 49, 49, 49, 512, 512, 512, 512, 512, 512, 512, 512, 512, 1033, 
-    49, 49, 49, 49, 49, 49, 49, 49, 49, 498, 49, 49, 512, 512, 512, 512, 512, 
-    1033, 49, 49, 49, 49, 49, 49, 49, 49, 49, 498, 49, 49, 49, 49, 49, 49, 
-    512, 512, 512, 512, 512, 512, 512, 512, 512, 1033, 49, 498, 49, 49, 49, 
-    49, 49, 49, 49, 49, 512, 49, 81, 81, 1034, 1034, 1034, 1034, 1034, 1034, 
-    1034, 1034, 1034, 1034, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 
-    1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 
-    1036, 1036, 1036, 1035, 1035, 1035, 1035, 1036, 1036, 1036, 1036, 1036, 
-    1036, 1036, 1036, 1036, 1036, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 
-    1035, 1036, 1035, 1035, 1035, 1035, 1035, 1035, 1036, 1035, 1035, 1037, 
-    1037, 1037, 1037, 1038, 81, 81, 81, 81, 81, 81, 81, 1036, 1036, 1036, 
-    1036, 1036, 81, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1039, 1039, 
-    1039, 1039, 1039, 1039, 1039, 81, 1039, 1039, 1039, 1039, 1039, 1039, 
-    1039, 1039, 1039, 81, 81, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 81, 
-    1039, 1039, 81, 1039, 1039, 1039, 1039, 1039, 81, 81, 81, 81, 81, 1040, 
-    1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 
-    81, 81, 81, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1042, 1042, 1042, 
-    1042, 1042, 1042, 1042, 81, 81, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 
-    1043, 1043, 1043, 81, 81, 81, 81, 1040, 1044, 1045, 1045, 1045, 1045, 
-    1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1046, 1046, 1046, 1046, 
-    1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 81, 81, 81, 
-    81, 81, 1048, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 
-    1049, 1049, 1049, 81, 81, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
-    1050, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 81, 1052, 1052, 1052, 
-    1052, 1052, 1052, 1052, 1052, 1052, 1052, 1053, 1053, 1053, 1053, 1053, 
-    1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 
-    1053, 1054, 1054, 1054, 1054, 1054, 1054, 1055, 1056, 81, 81, 81, 81, 
-    1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 81, 81, 81, 
-    81, 1058, 1058, 81, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 
-    1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1060, 1059, 
-    1059, 1059, 1061, 1059, 1059, 1059, 1059, 81, 81, 81, 1059, 1059, 1059, 
-    1059, 1059, 1059, 1062, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 81, 81, 
-    146, 146, 146, 146, 81, 146, 146, 146, 81, 146, 146, 81, 146, 81, 81, 
-    146, 81, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 81, 146, 146, 
-    146, 146, 81, 146, 81, 146, 81, 81, 81, 81, 81, 81, 146, 81, 81, 81, 81, 
-    146, 81, 146, 81, 146, 81, 146, 146, 146, 81, 146, 81, 146, 81, 146, 81, 
-    146, 81, 146, 146, 146, 146, 81, 146, 81, 146, 146, 81, 146, 146, 146, 
-    146, 146, 146, 146, 146, 146, 81, 81, 81, 81, 81, 146, 146, 146, 81, 146, 
-    146, 146, 132, 132, 81, 81, 81, 81, 81, 81, 531, 531, 531, 531, 527, 531, 
-    531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 
-    1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 
-    531, 531, 531, 531, 531, 531, 531, 1063, 1063, 531, 531, 531, 531, 531, 
-    531, 531, 531, 531, 531, 531, 531, 531, 531, 527, 531, 531, 531, 531, 
-    531, 531, 1063, 1063, 47, 47, 47, 521, 521, 1063, 1063, 1063, 532, 532, 
-    532, 532, 532, 532, 318, 40, 532, 532, 40, 40, 40, 1063, 1063, 1063, 532, 
-    532, 532, 532, 532, 532, 1064, 532, 532, 1064, 1064, 1064, 1064, 1064, 
-    1064, 1064, 1064, 1064, 1064, 532, 532, 532, 532, 532, 532, 532, 532, 
-    532, 532, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1065, 
-    1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1066, 587, 587, 
-    1063, 1063, 1063, 1063, 1063, 587, 587, 587, 587, 1063, 1063, 1063, 1063, 
-    587, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 587, 587, 1063, 1063, 
-    1063, 1063, 1063, 1063, 527, 527, 527, 527, 527, 527, 1063, 1063, 527, 
-    531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 527, 527, 
-    527, 527, 527, 527, 527, 527, 527, 531, 527, 527, 527, 527, 527, 527, 
-    531, 527, 527, 527, 527, 527, 527, 527, 538, 527, 527, 527, 527, 527, 
-    527, 531, 531, 531, 531, 531, 531, 531, 531, 40, 40, 531, 531, 527, 527, 
-    527, 527, 527, 530, 530, 527, 527, 527, 527, 527, 530, 527, 527, 527, 
-    527, 527, 538, 538, 538, 527, 527, 538, 527, 527, 538, 536, 536, 531, 
-    531, 527, 527, 531, 531, 531, 527, 531, 531, 531, 527, 527, 527, 1067, 
-    1067, 1067, 1067, 1067, 527, 527, 527, 527, 527, 527, 527, 531, 527, 531, 
-    538, 538, 527, 527, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 
-    538, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 
-    538, 538, 538, 527, 527, 527, 538, 527, 527, 527, 527, 538, 538, 538, 
-    527, 538, 538, 538, 527, 527, 527, 527, 527, 527, 527, 538, 527, 538, 
-    527, 527, 527, 527, 527, 527, 530, 527, 530, 527, 530, 527, 527, 527, 
-    527, 527, 538, 527, 527, 527, 527, 530, 527, 530, 530, 527, 527, 527, 
-    527, 527, 527, 527, 527, 527, 527, 531, 531, 527, 530, 530, 530, 530, 
-    530, 530, 530, 527, 527, 527, 527, 527, 527, 527, 527, 530, 530, 530, 
-    530, 530, 530, 527, 527, 527, 527, 527, 530, 530, 530, 530, 530, 530, 
-    530, 530, 530, 530, 530, 530, 40, 40, 40, 40, 531, 527, 527, 527, 527, 
-    531, 531, 531, 531, 531, 536, 536, 531, 531, 531, 531, 538, 531, 531, 
-    531, 531, 531, 536, 531, 531, 531, 531, 538, 538, 531, 531, 531, 531, 
-    531, 40, 40, 40, 40, 40, 40, 40, 40, 531, 531, 531, 531, 40, 40, 531, 
-    527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 538, 538, 538, 527, 
-    527, 527, 538, 538, 538, 538, 538, 40, 40, 40, 40, 40, 40, 540, 540, 540, 
-    1068, 1068, 1068, 40, 40, 40, 40, 527, 527, 527, 538, 527, 527, 527, 527, 
-    527, 527, 527, 527, 538, 538, 538, 527, 538, 527, 527, 527, 527, 527, 
-    531, 531, 531, 531, 531, 531, 538, 531, 531, 531, 527, 527, 527, 531, 
-    531, 527, 1063, 1063, 531, 531, 531, 527, 527, 1063, 1063, 1063, 531, 
-    531, 531, 531, 527, 527, 527, 527, 527, 527, 527, 1063, 1063, 1063, 1063, 
-    1063, 40, 40, 40, 40, 1063, 1063, 1063, 1063, 40, 40, 40, 40, 40, 531, 
-    531, 531, 531, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 527, 527, 527, 
-    527, 1063, 1063, 1063, 1063, 40, 40, 1063, 1063, 1063, 1063, 1063, 1063, 
-    40, 40, 40, 40, 40, 40, 1063, 1063, 40, 40, 40, 40, 1063, 527, 527, 538, 
-    527, 527, 527, 527, 527, 527, 538, 527, 538, 538, 527, 527, 538, 538, 
-    538, 527, 527, 527, 1063, 527, 527, 527, 527, 1063, 1063, 1063, 527, 527, 
-    527, 527, 527, 527, 527, 527, 527, 1063, 1063, 527, 527, 527, 527, 527, 
-    527, 1063, 1063, 1063, 527, 527, 527, 527, 527, 527, 527, 538, 538, 527, 
-    538, 538, 527, 538, 527, 527, 527, 527, 527, 527, 527, 1063, 1063, 538, 
-    538, 538, 527, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 
-    538, 538, 527, 527, 1063, 1063, 1063, 1063, 1063, 1063, 81, 81, 594, 594, 
-    594, 594, 594, 594, 594, 595, 594, 594, 594, 594, 594, 595, 595, 595, 
-    594, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 81, 
-    81, 81, 505, 81, 81, 81, 81, 81, 81, 505, 505, 505, 505, 505, 505, 505, 
-    505, 673, 673, 673, 673, 673, 673, 81, 81, 
-};
-
-/* decomposition data */
-static const unsigned short decomp_data[] = {
-    0, 257, 32, 514, 32, 776, 259, 97, 514, 32, 772, 259, 50, 259, 51, 514, 
-    32, 769, 258, 956, 514, 32, 807, 259, 49, 259, 111, 772, 49, 8260, 52, 
-    772, 49, 8260, 50, 772, 51, 8260, 52, 512, 65, 768, 512, 65, 769, 512, 
-    65, 770, 512, 65, 771, 512, 65, 776, 512, 65, 778, 512, 67, 807, 512, 69, 
-    768, 512, 69, 769, 512, 69, 770, 512, 69, 776, 512, 73, 768, 512, 73, 
-    769, 512, 73, 770, 512, 73, 776, 512, 78, 771, 512, 79, 768, 512, 79, 
-    769, 512, 79, 770, 512, 79, 771, 512, 79, 776, 512, 85, 768, 512, 85, 
-    769, 512, 85, 770, 512, 85, 776, 512, 89, 769, 512, 97, 768, 512, 97, 
-    769, 512, 97, 770, 512, 97, 771, 512, 97, 776, 512, 97, 778, 512, 99, 
-    807, 512, 101, 768, 512, 101, 769, 512, 101, 770, 512, 101, 776, 512, 
-    105, 768, 512, 105, 769, 512, 105, 770, 512, 105, 776, 512, 110, 771, 
-    512, 111, 768, 512, 111, 769, 512, 111, 770, 512, 111, 771, 512, 111, 
-    776, 512, 117, 768, 512, 117, 769, 512, 117, 770, 512, 117, 776, 512, 
-    121, 769, 512, 121, 776, 512, 65, 772, 512, 97, 772, 512, 65, 774, 512, 
-    97, 774, 512, 65, 808, 512, 97, 808, 512, 67, 769, 512, 99, 769, 512, 67, 
-    770, 512, 99, 770, 512, 67, 775, 512, 99, 775, 512, 67, 780, 512, 99, 
-    780, 512, 68, 780, 512, 100, 780, 512, 69, 772, 512, 101, 772, 512, 69, 
-    774, 512, 101, 774, 512, 69, 775, 512, 101, 775, 512, 69, 808, 512, 101, 
-    808, 512, 69, 780, 512, 101, 780, 512, 71, 770, 512, 103, 770, 512, 71, 
-    774, 512, 103, 774, 512, 71, 775, 512, 103, 775, 512, 71, 807, 512, 103, 
-    807, 512, 72, 770, 512, 104, 770, 512, 73, 771, 512, 105, 771, 512, 73, 
-    772, 512, 105, 772, 512, 73, 774, 512, 105, 774, 512, 73, 808, 512, 105, 
-    808, 512, 73, 775, 514, 73, 74, 514, 105, 106, 512, 74, 770, 512, 106, 
-    770, 512, 75, 807, 512, 107, 807, 512, 76, 769, 512, 108, 769, 512, 76, 
-    807, 512, 108, 807, 512, 76, 780, 512, 108, 780, 514, 76, 183, 514, 108, 
-    183, 512, 78, 769, 512, 110, 769, 512, 78, 807, 512, 110, 807, 512, 78, 
-    780, 512, 110, 780, 514, 700, 110, 512, 79, 772, 512, 111, 772, 512, 79, 
-    774, 512, 111, 774, 512, 79, 779, 512, 111, 779, 512, 82, 769, 512, 114, 
-    769, 512, 82, 807, 512, 114, 807, 512, 82, 780, 512, 114, 780, 512, 83, 
-    769, 512, 115, 769, 512, 83, 770, 512, 115, 770, 512, 83, 807, 512, 115, 
-    807, 512, 83, 780, 512, 115, 780, 512, 84, 807, 512, 116, 807, 512, 84, 
-    780, 512, 116, 780, 512, 85, 771, 512, 117, 771, 512, 85, 772, 512, 117, 
-    772, 512, 85, 774, 512, 117, 774, 512, 85, 778, 512, 117, 778, 512, 85, 
-    779, 512, 117, 779, 512, 85, 808, 512, 117, 808, 512, 87, 770, 512, 119, 
-    770, 512, 89, 770, 512, 121, 770, 512, 89, 776, 512, 90, 769, 512, 122, 
-    769, 512, 90, 775, 512, 122, 775, 512, 90, 780, 512, 122, 780, 258, 115, 
-    512, 79, 795, 512, 111, 795, 512, 85, 795, 512, 117, 795, 514, 68, 381, 
-    514, 68, 382, 514, 100, 382, 514, 76, 74, 514, 76, 106, 514, 108, 106, 
-    514, 78, 74, 514, 78, 106, 514, 110, 106, 512, 65, 780, 512, 97, 780, 
-    512, 73, 780, 512, 105, 780, 512, 79, 780, 512, 111, 780, 512, 85, 780, 
-    512, 117, 780, 512, 220, 772, 512, 252, 772, 512, 220, 769, 512, 252, 
-    769, 512, 220, 780, 512, 252, 780, 512, 220, 768, 512, 252, 768, 512, 
-    196, 772, 512, 228, 772, 512, 550, 772, 512, 551, 772, 512, 198, 772, 
-    512, 230, 772, 512, 71, 780, 512, 103, 780, 512, 75, 780, 512, 107, 780, 
-    512, 79, 808, 512, 111, 808, 512, 490, 772, 512, 491, 772, 512, 439, 780, 
-    512, 658, 780, 512, 106, 780, 514, 68, 90, 514, 68, 122, 514, 100, 122, 
-    512, 71, 769, 512, 103, 769, 512, 78, 768, 512, 110, 768, 512, 197, 769, 
-    512, 229, 769, 512, 198, 769, 512, 230, 769, 512, 216, 769, 512, 248, 
-    769, 512, 65, 783, 512, 97, 783, 512, 65, 785, 512, 97, 785, 512, 69, 
-    783, 512, 101, 783, 512, 69, 785, 512, 101, 785, 512, 73, 783, 512, 105, 
-    783, 512, 73, 785, 512, 105, 785, 512, 79, 783, 512, 111, 783, 512, 79, 
-    785, 512, 111, 785, 512, 82, 783, 512, 114, 783, 512, 82, 785, 512, 114, 
-    785, 512, 85, 783, 512, 117, 783, 512, 85, 785, 512, 117, 785, 512, 83, 
-    806, 512, 115, 806, 512, 84, 806, 512, 116, 806, 512, 72, 780, 512, 104, 
-    780, 512, 65, 775, 512, 97, 775, 512, 69, 807, 512, 101, 807, 512, 214, 
-    772, 512, 246, 772, 512, 213, 772, 512, 245, 772, 512, 79, 775, 512, 111, 
-    775, 512, 558, 772, 512, 559, 772, 512, 89, 772, 512, 121, 772, 259, 104, 
-    259, 614, 259, 106, 259, 114, 259, 633, 259, 635, 259, 641, 259, 119, 
-    259, 121, 514, 32, 774, 514, 32, 775, 514, 32, 778, 514, 32, 808, 514, 
-    32, 771, 514, 32, 779, 259, 611, 259, 108, 259, 115, 259, 120, 259, 661, 
-    256, 768, 256, 769, 256, 787, 512, 776, 769, 256, 697, 514, 32, 837, 256, 
-    59, 514, 32, 769, 512, 168, 769, 512, 913, 769, 256, 183, 512, 917, 769, 
-    512, 919, 769, 512, 921, 769, 512, 927, 769, 512, 933, 769, 512, 937, 
-    769, 512, 970, 769, 512, 921, 776, 512, 933, 776, 512, 945, 769, 512, 
-    949, 769, 512, 951, 769, 512, 953, 769, 512, 971, 769, 512, 953, 776, 
-    512, 965, 776, 512, 959, 769, 512, 965, 769, 512, 969, 769, 258, 946, 
-    258, 952, 258, 933, 512, 978, 769, 512, 978, 776, 258, 966, 258, 960, 
-    258, 954, 258, 961, 258, 962, 258, 920, 258, 949, 258, 931, 512, 1045, 
-    768, 512, 1045, 776, 512, 1043, 769, 512, 1030, 776, 512, 1050, 769, 512, 
-    1048, 768, 512, 1059, 774, 512, 1048, 774, 512, 1080, 774, 512, 1077, 
-    768, 512, 1077, 776, 512, 1075, 769, 512, 1110, 776, 512, 1082, 769, 512, 
-    1080, 768, 512, 1091, 774, 512, 1140, 783, 512, 1141, 783, 512, 1046, 
-    774, 512, 1078, 774, 512, 1040, 774, 512, 1072, 774, 512, 1040, 776, 512, 
-    1072, 776, 512, 1045, 774, 512, 1077, 774, 512, 1240, 776, 512, 1241, 
-    776, 512, 1046, 776, 512, 1078, 776, 512, 1047, 776, 512, 1079, 776, 512, 
-    1048, 772, 512, 1080, 772, 512, 1048, 776, 512, 1080, 776, 512, 1054, 
-    776, 512, 1086, 776, 512, 1256, 776, 512, 1257, 776, 512, 1069, 776, 512, 
-    1101, 776, 512, 1059, 772, 512, 1091, 772, 512, 1059, 776, 512, 1091, 
-    776, 512, 1059, 779, 512, 1091, 779, 512, 1063, 776, 512, 1095, 776, 512, 
-    1067, 776, 512, 1099, 776, 514, 1381, 1410, 512, 1575, 1619, 512, 1575, 
-    1620, 512, 1608, 1620, 512, 1575, 1621, 512, 1610, 1620, 514, 1575, 1652, 
-    514, 1608, 1652, 514, 1735, 1652, 514, 1610, 1652, 512, 1749, 1620, 512, 
-    1729, 1620, 512, 1746, 1620, 512, 2344, 2364, 512, 2352, 2364, 512, 2355, 
-    2364, 512, 2325, 2364, 512, 2326, 2364, 512, 2327, 2364, 512, 2332, 2364, 
-    512, 2337, 2364, 512, 2338, 2364, 512, 2347, 2364, 512, 2351, 2364, 512, 
-    2503, 2494, 512, 2503, 2519, 512, 2465, 2492, 512, 2466, 2492, 512, 2479, 
-    2492, 512, 2610, 2620, 512, 2616, 2620, 512, 2582, 2620, 512, 2583, 2620, 
-    512, 2588, 2620, 512, 2603, 2620, 512, 2887, 2902, 512, 2887, 2878, 512, 
-    2887, 2903, 512, 2849, 2876, 512, 2850, 2876, 512, 2962, 3031, 512, 3014, 
-    3006, 512, 3015, 3006, 512, 3014, 3031, 512, 3142, 3158, 512, 3263, 3285, 
-    512, 3270, 3285, 512, 3270, 3286, 512, 3270, 3266, 512, 3274, 3285, 512, 
-    3398, 3390, 512, 3399, 3390, 512, 3398, 3415, 512, 3545, 3530, 512, 3545, 
-    3535, 512, 3548, 3530, 512, 3545, 3551, 514, 3661, 3634, 514, 3789, 3762, 
-    514, 3755, 3737, 514, 3755, 3745, 257, 3851, 512, 3906, 4023, 512, 3916, 
-    4023, 512, 3921, 4023, 512, 3926, 4023, 512, 3931, 4023, 512, 3904, 4021, 
-    512, 3953, 3954, 512, 3953, 3956, 512, 4018, 3968, 514, 4018, 3969, 512, 
-    4019, 3968, 514, 4019, 3969, 512, 3953, 3968, 512, 3986, 4023, 512, 3996, 
-    4023, 512, 4001, 4023, 512, 4006, 4023, 512, 4011, 4023, 512, 3984, 4021, 
-    512, 4133, 4142, 259, 4316, 512, 6917, 6965, 512, 6919, 6965, 512, 6921, 
-    6965, 512, 6923, 6965, 512, 6925, 6965, 512, 6929, 6965, 512, 6970, 6965, 
-    512, 6972, 6965, 512, 6974, 6965, 512, 6975, 6965, 512, 6978, 6965, 259, 
-    65, 259, 198, 259, 66, 259, 68, 259, 69, 259, 398, 259, 71, 259, 72, 259, 
-    73, 259, 74, 259, 75, 259, 76, 259, 77, 259, 78, 259, 79, 259, 546, 259, 
-    80, 259, 82, 259, 84, 259, 85, 259, 87, 259, 97, 259, 592, 259, 593, 259, 
-    7426, 259, 98, 259, 100, 259, 101, 259, 601, 259, 603, 259, 604, 259, 
-    103, 259, 107, 259, 109, 259, 331, 259, 111, 259, 596, 259, 7446, 259, 
-    7447, 259, 112, 259, 116, 259, 117, 259, 7453, 259, 623, 259, 118, 259, 
-    7461, 259, 946, 259, 947, 259, 948, 259, 966, 259, 967, 261, 105, 261, 
-    114, 261, 117, 261, 118, 261, 946, 261, 947, 261, 961, 261, 966, 261, 
-    967, 259, 1085, 259, 594, 259, 99, 259, 597, 259, 240, 259, 604, 259, 
-    102, 259, 607, 259, 609, 259, 613, 259, 616, 259, 617, 259, 618, 259, 
-    7547, 259, 669, 259, 621, 259, 7557, 259, 671, 259, 625, 259, 624, 259, 
-    626, 259, 627, 259, 628, 259, 629, 259, 632, 259, 642, 259, 643, 259, 
-    427, 259, 649, 259, 650, 259, 7452, 259, 651, 259, 652, 259, 122, 259, 
-    656, 259, 657, 259, 658, 259, 952, 512, 65, 805, 512, 97, 805, 512, 66, 
-    775, 512, 98, 775, 512, 66, 803, 512, 98, 803, 512, 66, 817, 512, 98, 
-    817, 512, 199, 769, 512, 231, 769, 512, 68, 775, 512, 100, 775, 512, 68, 
-    803, 512, 100, 803, 512, 68, 817, 512, 100, 817, 512, 68, 807, 512, 100, 
-    807, 512, 68, 813, 512, 100, 813, 512, 274, 768, 512, 275, 768, 512, 274, 
-    769, 512, 275, 769, 512, 69, 813, 512, 101, 813, 512, 69, 816, 512, 101, 
-    816, 512, 552, 774, 512, 553, 774, 512, 70, 775, 512, 102, 775, 512, 71, 
-    772, 512, 103, 772, 512, 72, 775, 512, 104, 775, 512, 72, 803, 512, 104, 
-    803, 512, 72, 776, 512, 104, 776, 512, 72, 807, 512, 104, 807, 512, 72, 
-    814, 512, 104, 814, 512, 73, 816, 512, 105, 816, 512, 207, 769, 512, 239, 
-    769, 512, 75, 769, 512, 107, 769, 512, 75, 803, 512, 107, 803, 512, 75, 
-    817, 512, 107, 817, 512, 76, 803, 512, 108, 803, 512, 7734, 772, 512, 
-    7735, 772, 512, 76, 817, 512, 108, 817, 512, 76, 813, 512, 108, 813, 512, 
-    77, 769, 512, 109, 769, 512, 77, 775, 512, 109, 775, 512, 77, 803, 512, 
-    109, 803, 512, 78, 775, 512, 110, 775, 512, 78, 803, 512, 110, 803, 512, 
-    78, 817, 512, 110, 817, 512, 78, 813, 512, 110, 813, 512, 213, 769, 512, 
-    245, 769, 512, 213, 776, 512, 245, 776, 512, 332, 768, 512, 333, 768, 
-    512, 332, 769, 512, 333, 769, 512, 80, 769, 512, 112, 769, 512, 80, 775, 
-    512, 112, 775, 512, 82, 775, 512, 114, 775, 512, 82, 803, 512, 114, 803, 
-    512, 7770, 772, 512, 7771, 772, 512, 82, 817, 512, 114, 817, 512, 83, 
-    775, 512, 115, 775, 512, 83, 803, 512, 115, 803, 512, 346, 775, 512, 347, 
-    775, 512, 352, 775, 512, 353, 775, 512, 7778, 775, 512, 7779, 775, 512, 
-    84, 775, 512, 116, 775, 512, 84, 803, 512, 116, 803, 512, 84, 817, 512, 
-    116, 817, 512, 84, 813, 512, 116, 813, 512, 85, 804, 512, 117, 804, 512, 
-    85, 816, 512, 117, 816, 512, 85, 813, 512, 117, 813, 512, 360, 769, 512, 
-    361, 769, 512, 362, 776, 512, 363, 776, 512, 86, 771, 512, 118, 771, 512, 
-    86, 803, 512, 118, 803, 512, 87, 768, 512, 119, 768, 512, 87, 769, 512, 
-    119, 769, 512, 87, 776, 512, 119, 776, 512, 87, 775, 512, 119, 775, 512, 
-    87, 803, 512, 119, 803, 512, 88, 775, 512, 120, 775, 512, 88, 776, 512, 
-    120, 776, 512, 89, 775, 512, 121, 775, 512, 90, 770, 512, 122, 770, 512, 
-    90, 803, 512, 122, 803, 512, 90, 817, 512, 122, 817, 512, 104, 817, 512, 
-    116, 776, 512, 119, 778, 512, 121, 778, 514, 97, 702, 512, 383, 775, 512, 
-    65, 803, 512, 97, 803, 512, 65, 777, 512, 97, 777, 512, 194, 769, 512, 
-    226, 769, 512, 194, 768, 512, 226, 768, 512, 194, 777, 512, 226, 777, 
-    512, 194, 771, 512, 226, 771, 512, 7840, 770, 512, 7841, 770, 512, 258, 
-    769, 512, 259, 769, 512, 258, 768, 512, 259, 768, 512, 258, 777, 512, 
-    259, 777, 512, 258, 771, 512, 259, 771, 512, 7840, 774, 512, 7841, 774, 
-    512, 69, 803, 512, 101, 803, 512, 69, 777, 512, 101, 777, 512, 69, 771, 
-    512, 101, 771, 512, 202, 769, 512, 234, 769, 512, 202, 768, 512, 234, 
-    768, 512, 202, 777, 512, 234, 777, 512, 202, 771, 512, 234, 771, 512, 
-    7864, 770, 512, 7865, 770, 512, 73, 777, 512, 105, 777, 512, 73, 803, 
-    512, 105, 803, 512, 79, 803, 512, 111, 803, 512, 79, 777, 512, 111, 777, 
-    512, 212, 769, 512, 244, 769, 512, 212, 768, 512, 244, 768, 512, 212, 
-    777, 512, 244, 777, 512, 212, 771, 512, 244, 771, 512, 7884, 770, 512, 
-    7885, 770, 512, 416, 769, 512, 417, 769, 512, 416, 768, 512, 417, 768, 
-    512, 416, 777, 512, 417, 777, 512, 416, 771, 512, 417, 771, 512, 416, 
-    803, 512, 417, 803, 512, 85, 803, 512, 117, 803, 512, 85, 777, 512, 117, 
-    777, 512, 431, 769, 512, 432, 769, 512, 431, 768, 512, 432, 768, 512, 
-    431, 777, 512, 432, 777, 512, 431, 771, 512, 432, 771, 512, 431, 803, 
-    512, 432, 803, 512, 89, 768, 512, 121, 768, 512, 89, 803, 512, 121, 803, 
-    512, 89, 777, 512, 121, 777, 512, 89, 771, 512, 121, 771, 512, 945, 787, 
-    512, 945, 788, 512, 7936, 768, 512, 7937, 768, 512, 7936, 769, 512, 7937, 
-    769, 512, 7936, 834, 512, 7937, 834, 512, 913, 787, 512, 913, 788, 512, 
-    7944, 768, 512, 7945, 768, 512, 7944, 769, 512, 7945, 769, 512, 7944, 
-    834, 512, 7945, 834, 512, 949, 787, 512, 949, 788, 512, 7952, 768, 512, 
-    7953, 768, 512, 7952, 769, 512, 7953, 769, 512, 917, 787, 512, 917, 788, 
-    512, 7960, 768, 512, 7961, 768, 512, 7960, 769, 512, 7961, 769, 512, 951, 
-    787, 512, 951, 788, 512, 7968, 768, 512, 7969, 768, 512, 7968, 769, 512, 
-    7969, 769, 512, 7968, 834, 512, 7969, 834, 512, 919, 787, 512, 919, 788, 
-    512, 7976, 768, 512, 7977, 768, 512, 7976, 769, 512, 7977, 769, 512, 
-    7976, 834, 512, 7977, 834, 512, 953, 787, 512, 953, 788, 512, 7984, 768, 
-    512, 7985, 768, 512, 7984, 769, 512, 7985, 769, 512, 7984, 834, 512, 
-    7985, 834, 512, 921, 787, 512, 921, 788, 512, 7992, 768, 512, 7993, 768, 
-    512, 7992, 769, 512, 7993, 769, 512, 7992, 834, 512, 7993, 834, 512, 959, 
-    787, 512, 959, 788, 512, 8000, 768, 512, 8001, 768, 512, 8000, 769, 512, 
-    8001, 769, 512, 927, 787, 512, 927, 788, 512, 8008, 768, 512, 8009, 768, 
-    512, 8008, 769, 512, 8009, 769, 512, 965, 787, 512, 965, 788, 512, 8016, 
-    768, 512, 8017, 768, 512, 8016, 769, 512, 8017, 769, 512, 8016, 834, 512, 
-    8017, 834, 512, 933, 788, 512, 8025, 768, 512, 8025, 769, 512, 8025, 834, 
-    512, 969, 787, 512, 969, 788, 512, 8032, 768, 512, 8033, 768, 512, 8032, 
-    769, 512, 8033, 769, 512, 8032, 834, 512, 8033, 834, 512, 937, 787, 512, 
-    937, 788, 512, 8040, 768, 512, 8041, 768, 512, 8040, 769, 512, 8041, 769, 
-    512, 8040, 834, 512, 8041, 834, 512, 945, 768, 256, 940, 512, 949, 768, 
-    256, 941, 512, 951, 768, 256, 942, 512, 953, 768, 256, 943, 512, 959, 
-    768, 256, 972, 512, 965, 768, 256, 973, 512, 969, 768, 256, 974, 512, 
-    7936, 837, 512, 7937, 837, 512, 7938, 837, 512, 7939, 837, 512, 7940, 
-    837, 512, 7941, 837, 512, 7942, 837, 512, 7943, 837, 512, 7944, 837, 512, 
-    7945, 837, 512, 7946, 837, 512, 7947, 837, 512, 7948, 837, 512, 7949, 
-    837, 512, 7950, 837, 512, 7951, 837, 512, 7968, 837, 512, 7969, 837, 512, 
-    7970, 837, 512, 7971, 837, 512, 7972, 837, 512, 7973, 837, 512, 7974, 
-    837, 512, 7975, 837, 512, 7976, 837, 512, 7977, 837, 512, 7978, 837, 512, 
-    7979, 837, 512, 7980, 837, 512, 7981, 837, 512, 7982, 837, 512, 7983, 
-    837, 512, 8032, 837, 512, 8033, 837, 512, 8034, 837, 512, 8035, 837, 512, 
-    8036, 837, 512, 8037, 837, 512, 8038, 837, 512, 8039, 837, 512, 8040, 
-    837, 512, 8041, 837, 512, 8042, 837, 512, 8043, 837, 512, 8044, 837, 512, 
-    8045, 837, 512, 8046, 837, 512, 8047, 837, 512, 945, 774, 512, 945, 772, 
-    512, 8048, 837, 512, 945, 837, 512, 940, 837, 512, 945, 834, 512, 8118, 
-    837, 512, 913, 774, 512, 913, 772, 512, 913, 768, 256, 902, 512, 913, 
-    837, 514, 32, 787, 256, 953, 514, 32, 787, 514, 32, 834, 512, 168, 834, 
-    512, 8052, 837, 512, 951, 837, 512, 942, 837, 512, 951, 834, 512, 8134, 
-    837, 512, 917, 768, 256, 904, 512, 919, 768, 256, 905, 512, 919, 837, 
-    512, 8127, 768, 512, 8127, 769, 512, 8127, 834, 512, 953, 774, 512, 953, 
-    772, 512, 970, 768, 256, 912, 512, 953, 834, 512, 970, 834, 512, 921, 
-    774, 512, 921, 772, 512, 921, 768, 256, 906, 512, 8190, 768, 512, 8190, 
-    769, 512, 8190, 834, 512, 965, 774, 512, 965, 772, 512, 971, 768, 256, 
-    944, 512, 961, 787, 512, 961, 788, 512, 965, 834, 512, 971, 834, 512, 
-    933, 774, 512, 933, 772, 512, 933, 768, 256, 910, 512, 929, 788, 512, 
-    168, 768, 256, 901, 256, 96, 512, 8060, 837, 512, 969, 837, 512, 974, 
-    837, 512, 969, 834, 512, 8182, 837, 512, 927, 768, 256, 908, 512, 937, 
-    768, 256, 911, 512, 937, 837, 256, 180, 514, 32, 788, 256, 8194, 256, 
-    8195, 258, 32, 258, 32, 258, 32, 258, 32, 258, 32, 257, 32, 258, 32, 258, 
-    32, 258, 32, 257, 8208, 514, 32, 819, 258, 46, 514, 46, 46, 770, 46, 46, 
-    46, 257, 32, 514, 8242, 8242, 770, 8242, 8242, 8242, 514, 8245, 8245, 
-    770, 8245, 8245, 8245, 514, 33, 33, 514, 32, 773, 514, 63, 63, 514, 63, 
-    33, 514, 33, 63, 1026, 8242, 8242, 8242, 8242, 258, 32, 259, 48, 259, 
-    105, 259, 52, 259, 53, 259, 54, 259, 55, 259, 56, 259, 57, 259, 43, 259, 
-    8722, 259, 61, 259, 40, 259, 41, 259, 110, 261, 48, 261, 49, 261, 50, 
-    261, 51, 261, 52, 261, 53, 261, 54, 261, 55, 261, 56, 261, 57, 261, 43, 
-    261, 8722, 261, 61, 261, 40, 261, 41, 261, 97, 261, 101, 261, 111, 261, 
-    120, 261, 601, 261, 104, 261, 107, 261, 108, 261, 109, 261, 110, 261, 
-    112, 261, 115, 261, 116, 514, 82, 115, 770, 97, 47, 99, 770, 97, 47, 115, 
-    262, 67, 514, 176, 67, 770, 99, 47, 111, 770, 99, 47, 117, 258, 400, 514, 
-    176, 70, 262, 103, 262, 72, 262, 72, 262, 72, 262, 104, 262, 295, 262, 
-    73, 262, 73, 262, 76, 262, 108, 262, 78, 514, 78, 111, 262, 80, 262, 81, 
-    262, 82, 262, 82, 262, 82, 515, 83, 77, 770, 84, 69, 76, 515, 84, 77, 
-    262, 90, 256, 937, 262, 90, 256, 75, 256, 197, 262, 66, 262, 67, 262, 
-    101, 262, 69, 262, 70, 262, 77, 262, 111, 258, 1488, 258, 1489, 258, 
-    1490, 258, 1491, 262, 105, 770, 70, 65, 88, 262, 960, 262, 947, 262, 915, 
-    262, 928, 262, 8721, 262, 68, 262, 100, 262, 101, 262, 105, 262, 106, 
-    772, 49, 8260, 55, 772, 49, 8260, 57, 1028, 49, 8260, 49, 48, 772, 49, 
-    8260, 51, 772, 50, 8260, 51, 772, 49, 8260, 53, 772, 50, 8260, 53, 772, 
-    51, 8260, 53, 772, 52, 8260, 53, 772, 49, 8260, 54, 772, 53, 8260, 54, 
-    772, 49, 8260, 56, 772, 51, 8260, 56, 772, 53, 8260, 56, 772, 55, 8260, 
-    56, 516, 49, 8260, 258, 73, 514, 73, 73, 770, 73, 73, 73, 514, 73, 86, 
-    258, 86, 514, 86, 73, 770, 86, 73, 73, 1026, 86, 73, 73, 73, 514, 73, 88, 
-    258, 88, 514, 88, 73, 770, 88, 73, 73, 258, 76, 258, 67, 258, 68, 258, 
-    77, 258, 105, 514, 105, 105, 770, 105, 105, 105, 514, 105, 118, 258, 118, 
-    514, 118, 105, 770, 118, 105, 105, 1026, 118, 105, 105, 105, 514, 105, 
-    120, 258, 120, 514, 120, 105, 770, 120, 105, 105, 258, 108, 258, 99, 258, 
-    100, 258, 109, 772, 48, 8260, 51, 512, 8592, 824, 512, 8594, 824, 512, 
-    8596, 824, 512, 8656, 824, 512, 8660, 824, 512, 8658, 824, 512, 8707, 
-    824, 512, 8712, 824, 512, 8715, 824, 512, 8739, 824, 512, 8741, 824, 514, 
-    8747, 8747, 770, 8747, 8747, 8747, 514, 8750, 8750, 770, 8750, 8750, 
-    8750, 512, 8764, 824, 512, 8771, 824, 512, 8773, 824, 512, 8776, 824, 
-    512, 61, 824, 512, 8801, 824, 512, 8781, 824, 512, 60, 824, 512, 62, 824, 
-    512, 8804, 824, 512, 8805, 824, 512, 8818, 824, 512, 8819, 824, 512, 
-    8822, 824, 512, 8823, 824, 512, 8826, 824, 512, 8827, 824, 512, 8834, 
-    824, 512, 8835, 824, 512, 8838, 824, 512, 8839, 824, 512, 8866, 824, 512, 
-    8872, 824, 512, 8873, 824, 512, 8875, 824, 512, 8828, 824, 512, 8829, 
-    824, 512, 8849, 824, 512, 8850, 824, 512, 8882, 824, 512, 8883, 824, 512, 
-    8884, 824, 512, 8885, 824, 256, 12296, 256, 12297, 263, 49, 263, 50, 263, 
-    51, 263, 52, 263, 53, 263, 54, 263, 55, 263, 56, 263, 57, 519, 49, 48, 
-    519, 49, 49, 519, 49, 50, 519, 49, 51, 519, 49, 52, 519, 49, 53, 519, 49, 
-    54, 519, 49, 55, 519, 49, 56, 519, 49, 57, 519, 50, 48, 770, 40, 49, 41, 
-    770, 40, 50, 41, 770, 40, 51, 41, 770, 40, 52, 41, 770, 40, 53, 41, 770, 
-    40, 54, 41, 770, 40, 55, 41, 770, 40, 56, 41, 770, 40, 57, 41, 1026, 40, 
-    49, 48, 41, 1026, 40, 49, 49, 41, 1026, 40, 49, 50, 41, 1026, 40, 49, 51, 
-    41, 1026, 40, 49, 52, 41, 1026, 40, 49, 53, 41, 1026, 40, 49, 54, 41, 
-    1026, 40, 49, 55, 41, 1026, 40, 49, 56, 41, 1026, 40, 49, 57, 41, 1026, 
-    40, 50, 48, 41, 514, 49, 46, 514, 50, 46, 514, 51, 46, 514, 52, 46, 514, 
-    53, 46, 514, 54, 46, 514, 55, 46, 514, 56, 46, 514, 57, 46, 770, 49, 48, 
-    46, 770, 49, 49, 46, 770, 49, 50, 46, 770, 49, 51, 46, 770, 49, 52, 46, 
-    770, 49, 53, 46, 770, 49, 54, 46, 770, 49, 55, 46, 770, 49, 56, 46, 770, 
-    49, 57, 46, 770, 50, 48, 46, 770, 40, 97, 41, 770, 40, 98, 41, 770, 40, 
-    99, 41, 770, 40, 100, 41, 770, 40, 101, 41, 770, 40, 102, 41, 770, 40, 
-    103, 41, 770, 40, 104, 41, 770, 40, 105, 41, 770, 40, 106, 41, 770, 40, 
-    107, 41, 770, 40, 108, 41, 770, 40, 109, 41, 770, 40, 110, 41, 770, 40, 
-    111, 41, 770, 40, 112, 41, 770, 40, 113, 41, 770, 40, 114, 41, 770, 40, 
-    115, 41, 770, 40, 116, 41, 770, 40, 117, 41, 770, 40, 118, 41, 770, 40, 
-    119, 41, 770, 40, 120, 41, 770, 40, 121, 41, 770, 40, 122, 41, 263, 65, 
-    263, 66, 263, 67, 263, 68, 263, 69, 263, 70, 263, 71, 263, 72, 263, 73, 
-    263, 74, 263, 75, 263, 76, 263, 77, 263, 78, 263, 79, 263, 80, 263, 81, 
-    263, 82, 263, 83, 263, 84, 263, 85, 263, 86, 263, 87, 263, 88, 263, 89, 
-    263, 90, 263, 97, 263, 98, 263, 99, 263, 100, 263, 101, 263, 102, 263, 
-    103, 263, 104, 263, 105, 263, 106, 263, 107, 263, 108, 263, 109, 263, 
-    110, 263, 111, 263, 112, 263, 113, 263, 114, 263, 115, 263, 116, 263, 
-    117, 263, 118, 263, 119, 263, 120, 263, 121, 263, 122, 263, 48, 1026, 
-    8747, 8747, 8747, 8747, 770, 58, 58, 61, 514, 61, 61, 770, 61, 61, 61, 
-    512, 10973, 824, 261, 106, 259, 86, 259, 11617, 258, 27597, 258, 40863, 
-    258, 19968, 258, 20008, 258, 20022, 258, 20031, 258, 20057, 258, 20101, 
-    258, 20108, 258, 20128, 258, 20154, 258, 20799, 258, 20837, 258, 20843, 
-    258, 20866, 258, 20886, 258, 20907, 258, 20960, 258, 20981, 258, 20992, 
-    258, 21147, 258, 21241, 258, 21269, 258, 21274, 258, 21304, 258, 21313, 
-    258, 21340, 258, 21353, 258, 21378, 258, 21430, 258, 21448, 258, 21475, 
-    258, 22231, 258, 22303, 258, 22763, 258, 22786, 258, 22794, 258, 22805, 
-    258, 22823, 258, 22899, 258, 23376, 258, 23424, 258, 23544, 258, 23567, 
-    258, 23586, 258, 23608, 258, 23662, 258, 23665, 258, 24027, 258, 24037, 
-    258, 24049, 258, 24062, 258, 24178, 258, 24186, 258, 24191, 258, 24308, 
-    258, 24318, 258, 24331, 258, 24339, 258, 24400, 258, 24417, 258, 24435, 
-    258, 24515, 258, 25096, 258, 25142, 258, 25163, 258, 25903, 258, 25908, 
-    258, 25991, 258, 26007, 258, 26020, 258, 26041, 258, 26080, 258, 26085, 
-    258, 26352, 258, 26376, 258, 26408, 258, 27424, 258, 27490, 258, 27513, 
-    258, 27571, 258, 27595, 258, 27604, 258, 27611, 258, 27663, 258, 27668, 
-    258, 27700, 258, 28779, 258, 29226, 258, 29238, 258, 29243, 258, 29247, 
-    258, 29255, 258, 29273, 258, 29275, 258, 29356, 258, 29572, 258, 29577, 
-    258, 29916, 258, 29926, 258, 29976, 258, 29983, 258, 29992, 258, 30000, 
-    258, 30091, 258, 30098, 258, 30326, 258, 30333, 258, 30382, 258, 30399, 
-    258, 30446, 258, 30683, 258, 30690, 258, 30707, 258, 31034, 258, 31160, 
-    258, 31166, 258, 31348, 258, 31435, 258, 31481, 258, 31859, 258, 31992, 
-    258, 32566, 258, 32593, 258, 32650, 258, 32701, 258, 32769, 258, 32780, 
-    258, 32786, 258, 32819, 258, 32895, 258, 32905, 258, 33251, 258, 33258, 
-    258, 33267, 258, 33276, 258, 33292, 258, 33307, 258, 33311, 258, 33390, 
-    258, 33394, 258, 33400, 258, 34381, 258, 34411, 258, 34880, 258, 34892, 
-    258, 34915, 258, 35198, 258, 35211, 258, 35282, 258, 35328, 258, 35895, 
-    258, 35910, 258, 35925, 258, 35960, 258, 35997, 258, 36196, 258, 36208, 
-    258, 36275, 258, 36523, 258, 36554, 258, 36763, 258, 36784, 258, 36789, 
-    258, 37009, 258, 37193, 258, 37318, 258, 37324, 258, 37329, 258, 38263, 
-    258, 38272, 258, 38428, 258, 38582, 258, 38585, 258, 38632, 258, 38737, 
-    258, 38750, 258, 38754, 258, 38761, 258, 38859, 258, 38893, 258, 38899, 
-    258, 38913, 258, 39080, 258, 39131, 258, 39135, 258, 39318, 258, 39321, 
-    258, 39340, 258, 39592, 258, 39640, 258, 39647, 258, 39717, 258, 39727, 
-    258, 39730, 258, 39740, 258, 39770, 258, 40165, 258, 40565, 258, 40575, 
-    258, 40613, 258, 40635, 258, 40643, 258, 40653, 258, 40657, 258, 40697, 
-    258, 40701, 258, 40718, 258, 40723, 258, 40736, 258, 40763, 258, 40778, 
-    258, 40786, 258, 40845, 258, 40860, 258, 40864, 264, 32, 258, 12306, 258, 
-    21313, 258, 21316, 258, 21317, 512, 12363, 12441, 512, 12365, 12441, 512, 
-    12367, 12441, 512, 12369, 12441, 512, 12371, 12441, 512, 12373, 12441, 
-    512, 12375, 12441, 512, 12377, 12441, 512, 12379, 12441, 512, 12381, 
-    12441, 512, 12383, 12441, 512, 12385, 12441, 512, 12388, 12441, 512, 
-    12390, 12441, 512, 12392, 12441, 512, 12399, 12441, 512, 12399, 12442, 
-    512, 12402, 12441, 512, 12402, 12442, 512, 12405, 12441, 512, 12405, 
-    12442, 512, 12408, 12441, 512, 12408, 12442, 512, 12411, 12441, 512, 
-    12411, 12442, 512, 12358, 12441, 514, 32, 12441, 514, 32, 12442, 512, 
-    12445, 12441, 521, 12424, 12426, 512, 12459, 12441, 512, 12461, 12441, 
-    512, 12463, 12441, 512, 12465, 12441, 512, 12467, 12441, 512, 12469, 
-    12441, 512, 12471, 12441, 512, 12473, 12441, 512, 12475, 12441, 512, 
-    12477, 12441, 512, 12479, 12441, 512, 12481, 12441, 512, 12484, 12441, 
-    512, 12486, 12441, 512, 12488, 12441, 512, 12495, 12441, 512, 12495, 
-    12442, 512, 12498, 12441, 512, 12498, 12442, 512, 12501, 12441, 512, 
-    12501, 12442, 512, 12504, 12441, 512, 12504, 12442, 512, 12507, 12441, 
-    512, 12507, 12442, 512, 12454, 12441, 512, 12527, 12441, 512, 12528, 
-    12441, 512, 12529, 12441, 512, 12530, 12441, 512, 12541, 12441, 521, 
-    12467, 12488, 258, 4352, 258, 4353, 258, 4522, 258, 4354, 258, 4524, 258, 
-    4525, 258, 4355, 258, 4356, 258, 4357, 258, 4528, 258, 4529, 258, 4530, 
-    258, 4531, 258, 4532, 258, 4533, 258, 4378, 258, 4358, 258, 4359, 258, 
-    4360, 258, 4385, 258, 4361, 258, 4362, 258, 4363, 258, 4364, 258, 4365, 
-    258, 4366, 258, 4367, 258, 4368, 258, 4369, 258, 4370, 258, 4449, 258, 
-    4450, 258, 4451, 258, 4452, 258, 4453, 258, 4454, 258, 4455, 258, 4456, 
-    258, 4457, 258, 4458, 258, 4459, 258, 4460, 258, 4461, 258, 4462, 258, 
-    4463, 258, 4464, 258, 4465, 258, 4466, 258, 4467, 258, 4468, 258, 4469, 
-    258, 4448, 258, 4372, 258, 4373, 258, 4551, 258, 4552, 258, 4556, 258, 
-    4558, 258, 4563, 258, 4567, 258, 4569, 258, 4380, 258, 4573, 258, 4575, 
-    258, 4381, 258, 4382, 258, 4384, 258, 4386, 258, 4387, 258, 4391, 258, 
-    4393, 258, 4395, 258, 4396, 258, 4397, 258, 4398, 258, 4399, 258, 4402, 
-    258, 4406, 258, 4416, 258, 4423, 258, 4428, 258, 4593, 258, 4594, 258, 
-    4439, 258, 4440, 258, 4441, 258, 4484, 258, 4485, 258, 4488, 258, 4497, 
-    258, 4498, 258, 4500, 258, 4510, 258, 4513, 259, 19968, 259, 20108, 259, 
-    19977, 259, 22235, 259, 19978, 259, 20013, 259, 19979, 259, 30002, 259, 
-    20057, 259, 19993, 259, 19969, 259, 22825, 259, 22320, 259, 20154, 770, 
-    40, 4352, 41, 770, 40, 4354, 41, 770, 40, 4355, 41, 770, 40, 4357, 41, 
-    770, 40, 4358, 41, 770, 40, 4359, 41, 770, 40, 4361, 41, 770, 40, 4363, 
-    41, 770, 40, 4364, 41, 770, 40, 4366, 41, 770, 40, 4367, 41, 770, 40, 
-    4368, 41, 770, 40, 4369, 41, 770, 40, 4370, 41, 1026, 40, 4352, 4449, 41, 
-    1026, 40, 4354, 4449, 41, 1026, 40, 4355, 4449, 41, 1026, 40, 4357, 4449, 
-    41, 1026, 40, 4358, 4449, 41, 1026, 40, 4359, 4449, 41, 1026, 40, 4361, 
-    4449, 41, 1026, 40, 4363, 4449, 41, 1026, 40, 4364, 4449, 41, 1026, 40, 
-    4366, 4449, 41, 1026, 40, 4367, 4449, 41, 1026, 40, 4368, 4449, 41, 1026, 
-    40, 4369, 4449, 41, 1026, 40, 4370, 4449, 41, 1026, 40, 4364, 4462, 41, 
-    1794, 40, 4363, 4457, 4364, 4453, 4523, 41, 1538, 40, 4363, 4457, 4370, 
-    4462, 41, 770, 40, 19968, 41, 770, 40, 20108, 41, 770, 40, 19977, 41, 
-    770, 40, 22235, 41, 770, 40, 20116, 41, 770, 40, 20845, 41, 770, 40, 
-    19971, 41, 770, 40, 20843, 41, 770, 40, 20061, 41, 770, 40, 21313, 41, 
-    770, 40, 26376, 41, 770, 40, 28779, 41, 770, 40, 27700, 41, 770, 40, 
-    26408, 41, 770, 40, 37329, 41, 770, 40, 22303, 41, 770, 40, 26085, 41, 
-    770, 40, 26666, 41, 770, 40, 26377, 41, 770, 40, 31038, 41, 770, 40, 
-    21517, 41, 770, 40, 29305, 41, 770, 40, 36001, 41, 770, 40, 31069, 41, 
-    770, 40, 21172, 41, 770, 40, 20195, 41, 770, 40, 21628, 41, 770, 40, 
-    23398, 41, 770, 40, 30435, 41, 770, 40, 20225, 41, 770, 40, 36039, 41, 
-    770, 40, 21332, 41, 770, 40, 31085, 41, 770, 40, 20241, 41, 770, 40, 
-    33258, 41, 770, 40, 33267, 41, 263, 21839, 263, 24188, 263, 25991, 263, 
-    31631, 778, 80, 84, 69, 519, 50, 49, 519, 50, 50, 519, 50, 51, 519, 50, 
-    52, 519, 50, 53, 519, 50, 54, 519, 50, 55, 519, 50, 56, 519, 50, 57, 519, 
-    51, 48, 519, 51, 49, 519, 51, 50, 519, 51, 51, 519, 51, 52, 519, 51, 53, 
-    263, 4352, 263, 4354, 263, 4355, 263, 4357, 263, 4358, 263, 4359, 263, 
-    4361, 263, 4363, 263, 4364, 263, 4366, 263, 4367, 263, 4368, 263, 4369, 
-    263, 4370, 519, 4352, 4449, 519, 4354, 4449, 519, 4355, 4449, 519, 4357, 
-    4449, 519, 4358, 4449, 519, 4359, 4449, 519, 4361, 4449, 519, 4363, 4449, 
-    519, 4364, 4449, 519, 4366, 4449, 519, 4367, 4449, 519, 4368, 4449, 519, 
-    4369, 4449, 519, 4370, 4449, 1287, 4366, 4449, 4535, 4352, 4457, 1031, 
-    4364, 4462, 4363, 4468, 519, 4363, 4462, 263, 19968, 263, 20108, 263, 
-    19977, 263, 22235, 263, 20116, 263, 20845, 263, 19971, 263, 20843, 263, 
-    20061, 263, 21313, 263, 26376, 263, 28779, 263, 27700, 263, 26408, 263, 
-    37329, 263, 22303, 263, 26085, 263, 26666, 263, 26377, 263, 31038, 263, 
-    21517, 263, 29305, 263, 36001, 263, 31069, 263, 21172, 263, 31192, 263, 
-    30007, 263, 22899, 263, 36969, 263, 20778, 263, 21360, 263, 27880, 263, 
-    38917, 263, 20241, 263, 20889, 263, 27491, 263, 19978, 263, 20013, 263, 
-    19979, 263, 24038, 263, 21491, 263, 21307, 263, 23447, 263, 23398, 263, 
-    30435, 263, 20225, 263, 36039, 263, 21332, 263, 22812, 519, 51, 54, 519, 
-    51, 55, 519, 51, 56, 519, 51, 57, 519, 52, 48, 519, 52, 49, 519, 52, 50, 
-    519, 52, 51, 519, 52, 52, 519, 52, 53, 519, 52, 54, 519, 52, 55, 519, 52, 
-    56, 519, 52, 57, 519, 53, 48, 514, 49, 26376, 514, 50, 26376, 514, 51, 
-    26376, 514, 52, 26376, 514, 53, 26376, 514, 54, 26376, 514, 55, 26376, 
-    514, 56, 26376, 514, 57, 26376, 770, 49, 48, 26376, 770, 49, 49, 26376, 
-    770, 49, 50, 26376, 522, 72, 103, 778, 101, 114, 103, 522, 101, 86, 778, 
-    76, 84, 68, 263, 12450, 263, 12452, 263, 12454, 263, 12456, 263, 12458, 
-    263, 12459, 263, 12461, 263, 12463, 263, 12465, 263, 12467, 263, 12469, 
-    263, 12471, 263, 12473, 263, 12475, 263, 12477, 263, 12479, 263, 12481, 
-    263, 12484, 263, 12486, 263, 12488, 263, 12490, 263, 12491, 263, 12492, 
-    263, 12493, 263, 12494, 263, 12495, 263, 12498, 263, 12501, 263, 12504, 
-    263, 12507, 263, 12510, 263, 12511, 263, 12512, 263, 12513, 263, 12514, 
-    263, 12516, 263, 12518, 263, 12520, 263, 12521, 263, 12522, 263, 12523, 
-    263, 12524, 263, 12525, 263, 12527, 263, 12528, 263, 12529, 263, 12530, 
-    1034, 12450, 12497, 12540, 12488, 1034, 12450, 12523, 12501, 12449, 1034, 
-    12450, 12531, 12506, 12450, 778, 12450, 12540, 12523, 1034, 12452, 12491, 
-    12531, 12464, 778, 12452, 12531, 12481, 778, 12454, 12457, 12531, 1290, 
-    12456, 12473, 12463, 12540, 12489, 1034, 12456, 12540, 12459, 12540, 778, 
-    12458, 12531, 12473, 778, 12458, 12540, 12512, 778, 12459, 12452, 12522, 
-    1034, 12459, 12521, 12483, 12488, 1034, 12459, 12525, 12522, 12540, 778, 
-    12460, 12525, 12531, 778, 12460, 12531, 12510, 522, 12462, 12460, 778, 
-    12462, 12491, 12540, 1034, 12461, 12517, 12522, 12540, 1034, 12462, 
-    12523, 12480, 12540, 522, 12461, 12525, 1290, 12461, 12525, 12464, 12521, 
-    12512, 1546, 12461, 12525, 12513, 12540, 12488, 12523, 1290, 12461, 
-    12525, 12527, 12483, 12488, 778, 12464, 12521, 12512, 1290, 12464, 12521, 
-    12512, 12488, 12531, 1290, 12463, 12523, 12476, 12452, 12525, 1034, 
-    12463, 12525, 12540, 12493, 778, 12465, 12540, 12473, 778, 12467, 12523, 
-    12490, 778, 12467, 12540, 12509, 1034, 12469, 12452, 12463, 12523, 1290, 
-    12469, 12531, 12481, 12540, 12512, 1034, 12471, 12522, 12531, 12464, 778, 
-    12475, 12531, 12481, 778, 12475, 12531, 12488, 778, 12480, 12540, 12473, 
-    522, 12487, 12471, 522, 12489, 12523, 522, 12488, 12531, 522, 12490, 
-    12494, 778, 12494, 12483, 12488, 778, 12495, 12452, 12484, 1290, 12497, 
-    12540, 12475, 12531, 12488, 778, 12497, 12540, 12484, 1034, 12496, 12540, 
-    12524, 12523, 1290, 12500, 12450, 12473, 12488, 12523, 778, 12500, 12463, 
-    12523, 522, 12500, 12467, 522, 12499, 12523, 1290, 12501, 12449, 12521, 
-    12483, 12489, 1034, 12501, 12451, 12540, 12488, 1290, 12502, 12483, 
-    12471, 12455, 12523, 778, 12501, 12521, 12531, 1290, 12504, 12463, 12479, 
-    12540, 12523, 522, 12506, 12477, 778, 12506, 12491, 12498, 778, 12504, 
-    12523, 12484, 778, 12506, 12531, 12473, 778, 12506, 12540, 12472, 778, 
-    12505, 12540, 12479, 1034, 12509, 12452, 12531, 12488, 778, 12508, 12523, 
-    12488, 522, 12507, 12531, 778, 12509, 12531, 12489, 778, 12507, 12540, 
-    12523, 778, 12507, 12540, 12531, 1034, 12510, 12452, 12463, 12525, 778, 
-    12510, 12452, 12523, 778, 12510, 12483, 12495, 778, 12510, 12523, 12463, 
-    1290, 12510, 12531, 12471, 12519, 12531, 1034, 12511, 12463, 12525, 
-    12531, 522, 12511, 12522, 1290, 12511, 12522, 12496, 12540, 12523, 522, 
-    12513, 12460, 1034, 12513, 12460, 12488, 12531, 1034, 12513, 12540, 
-    12488, 12523, 778, 12516, 12540, 12489, 778, 12516, 12540, 12523, 778, 
-    12518, 12450, 12531, 1034, 12522, 12483, 12488, 12523, 522, 12522, 12521, 
-    778, 12523, 12500, 12540, 1034, 12523, 12540, 12502, 12523, 522, 12524, 
-    12512, 1290, 12524, 12531, 12488, 12466, 12531, 778, 12527, 12483, 12488, 
-    514, 48, 28857, 514, 49, 28857, 514, 50, 28857, 514, 51, 28857, 514, 52, 
-    28857, 514, 53, 28857, 514, 54, 28857, 514, 55, 28857, 514, 56, 28857, 
-    514, 57, 28857, 770, 49, 48, 28857, 770, 49, 49, 28857, 770, 49, 50, 
-    28857, 770, 49, 51, 28857, 770, 49, 52, 28857, 770, 49, 53, 28857, 770, 
-    49, 54, 28857, 770, 49, 55, 28857, 770, 49, 56, 28857, 770, 49, 57, 
-    28857, 770, 50, 48, 28857, 770, 50, 49, 28857, 770, 50, 50, 28857, 770, 
-    50, 51, 28857, 770, 50, 52, 28857, 778, 104, 80, 97, 522, 100, 97, 522, 
-    65, 85, 778, 98, 97, 114, 522, 111, 86, 522, 112, 99, 522, 100, 109, 778, 
-    100, 109, 178, 778, 100, 109, 179, 522, 73, 85, 522, 24179, 25104, 522, 
-    26157, 21644, 522, 22823, 27491, 522, 26126, 27835, 1034, 26666, 24335, 
-    20250, 31038, 522, 112, 65, 522, 110, 65, 522, 956, 65, 522, 109, 65, 
-    522, 107, 65, 522, 75, 66, 522, 77, 66, 522, 71, 66, 778, 99, 97, 108, 
-    1034, 107, 99, 97, 108, 522, 112, 70, 522, 110, 70, 522, 956, 70, 522, 
-    956, 103, 522, 109, 103, 522, 107, 103, 522, 72, 122, 778, 107, 72, 122, 
-    778, 77, 72, 122, 778, 71, 72, 122, 778, 84, 72, 122, 522, 956, 8467, 
-    522, 109, 8467, 522, 100, 8467, 522, 107, 8467, 522, 102, 109, 522, 110, 
-    109, 522, 956, 109, 522, 109, 109, 522, 99, 109, 522, 107, 109, 778, 109, 
-    109, 178, 778, 99, 109, 178, 522, 109, 178, 778, 107, 109, 178, 778, 109, 
-    109, 179, 778, 99, 109, 179, 522, 109, 179, 778, 107, 109, 179, 778, 109, 
-    8725, 115, 1034, 109, 8725, 115, 178, 522, 80, 97, 778, 107, 80, 97, 778, 
-    77, 80, 97, 778, 71, 80, 97, 778, 114, 97, 100, 1290, 114, 97, 100, 8725, 
-    115, 1546, 114, 97, 100, 8725, 115, 178, 522, 112, 115, 522, 110, 115, 
-    522, 956, 115, 522, 109, 115, 522, 112, 86, 522, 110, 86, 522, 956, 86, 
-    522, 109, 86, 522, 107, 86, 522, 77, 86, 522, 112, 87, 522, 110, 87, 522, 
-    956, 87, 522, 109, 87, 522, 107, 87, 522, 77, 87, 522, 107, 937, 522, 77, 
-    937, 1034, 97, 46, 109, 46, 522, 66, 113, 522, 99, 99, 522, 99, 100, 
-    1034, 67, 8725, 107, 103, 778, 67, 111, 46, 522, 100, 66, 522, 71, 121, 
-    522, 104, 97, 522, 72, 80, 522, 105, 110, 522, 75, 75, 522, 75, 77, 522, 
-    107, 116, 522, 108, 109, 522, 108, 110, 778, 108, 111, 103, 522, 108, 
-    120, 522, 109, 98, 778, 109, 105, 108, 778, 109, 111, 108, 522, 80, 72, 
-    1034, 112, 46, 109, 46, 778, 80, 80, 77, 522, 80, 82, 522, 115, 114, 522, 
-    83, 118, 522, 87, 98, 778, 86, 8725, 109, 778, 65, 8725, 109, 514, 49, 
-    26085, 514, 50, 26085, 514, 51, 26085, 514, 52, 26085, 514, 53, 26085, 
-    514, 54, 26085, 514, 55, 26085, 514, 56, 26085, 514, 57, 26085, 770, 49, 
-    48, 26085, 770, 49, 49, 26085, 770, 49, 50, 26085, 770, 49, 51, 26085, 
-    770, 49, 52, 26085, 770, 49, 53, 26085, 770, 49, 54, 26085, 770, 49, 55, 
-    26085, 770, 49, 56, 26085, 770, 49, 57, 26085, 770, 50, 48, 26085, 770, 
-    50, 49, 26085, 770, 50, 50, 26085, 770, 50, 51, 26085, 770, 50, 52, 
-    26085, 770, 50, 53, 26085, 770, 50, 54, 26085, 770, 50, 55, 26085, 770, 
-    50, 56, 26085, 770, 50, 57, 26085, 770, 51, 48, 26085, 770, 51, 49, 
-    26085, 778, 103, 97, 108, 259, 1098, 259, 1100, 259, 42863, 259, 294, 
-    259, 339, 259, 42791, 259, 43831, 259, 619, 259, 43858, 256, 35912, 256, 
-    26356, 256, 36554, 256, 36040, 256, 28369, 256, 20018, 256, 21477, 256, 
-    40860, 256, 40860, 256, 22865, 256, 37329, 256, 21895, 256, 22856, 256, 
-    25078, 256, 30313, 256, 32645, 256, 34367, 256, 34746, 256, 35064, 256, 
-    37007, 256, 27138, 256, 27931, 256, 28889, 256, 29662, 256, 33853, 256, 
-    37226, 256, 39409, 256, 20098, 256, 21365, 256, 27396, 256, 29211, 256, 
-    34349, 256, 40478, 256, 23888, 256, 28651, 256, 34253, 256, 35172, 256, 
-    25289, 256, 33240, 256, 34847, 256, 24266, 256, 26391, 256, 28010, 256, 
-    29436, 256, 37070, 256, 20358, 256, 20919, 256, 21214, 256, 25796, 256, 
-    27347, 256, 29200, 256, 30439, 256, 32769, 256, 34310, 256, 34396, 256, 
-    36335, 256, 38706, 256, 39791, 256, 40442, 256, 30860, 256, 31103, 256, 
-    32160, 256, 33737, 256, 37636, 256, 40575, 256, 35542, 256, 22751, 256, 
-    24324, 256, 31840, 256, 32894, 256, 29282, 256, 30922, 256, 36034, 256, 
-    38647, 256, 22744, 256, 23650, 256, 27155, 256, 28122, 256, 28431, 256, 
-    32047, 256, 32311, 256, 38475, 256, 21202, 256, 32907, 256, 20956, 256, 
-    20940, 256, 31260, 256, 32190, 256, 33777, 256, 38517, 256, 35712, 256, 
-    25295, 256, 27138, 256, 35582, 256, 20025, 256, 23527, 256, 24594, 256, 
-    29575, 256, 30064, 256, 21271, 256, 30971, 256, 20415, 256, 24489, 256, 
-    19981, 256, 27852, 256, 25976, 256, 32034, 256, 21443, 256, 22622, 256, 
-    30465, 256, 33865, 256, 35498, 256, 27578, 256, 36784, 256, 27784, 256, 
-    25342, 256, 33509, 256, 25504, 256, 30053, 256, 20142, 256, 20841, 256, 
-    20937, 256, 26753, 256, 31975, 256, 33391, 256, 35538, 256, 37327, 256, 
-    21237, 256, 21570, 256, 22899, 256, 24300, 256, 26053, 256, 28670, 256, 
-    31018, 256, 38317, 256, 39530, 256, 40599, 256, 40654, 256, 21147, 256, 
-    26310, 256, 27511, 256, 36706, 256, 24180, 256, 24976, 256, 25088, 256, 
-    25754, 256, 28451, 256, 29001, 256, 29833, 256, 31178, 256, 32244, 256, 
-    32879, 256, 36646, 256, 34030, 256, 36899, 256, 37706, 256, 21015, 256, 
-    21155, 256, 21693, 256, 28872, 256, 35010, 256, 35498, 256, 24265, 256, 
-    24565, 256, 25467, 256, 27566, 256, 31806, 256, 29557, 256, 20196, 256, 
-    22265, 256, 23527, 256, 23994, 256, 24604, 256, 29618, 256, 29801, 256, 
-    32666, 256, 32838, 256, 37428, 256, 38646, 256, 38728, 256, 38936, 256, 
-    20363, 256, 31150, 256, 37300, 256, 38584, 256, 24801, 256, 20102, 256, 
-    20698, 256, 23534, 256, 23615, 256, 26009, 256, 27138, 256, 29134, 256, 
-    30274, 256, 34044, 256, 36988, 256, 40845, 256, 26248, 256, 38446, 256, 
-    21129, 256, 26491, 256, 26611, 256, 27969, 256, 28316, 256, 29705, 256, 
-    30041, 256, 30827, 256, 32016, 256, 39006, 256, 20845, 256, 25134, 256, 
-    38520, 256, 20523, 256, 23833, 256, 28138, 256, 36650, 256, 24459, 256, 
-    24900, 256, 26647, 256, 29575, 256, 38534, 256, 21033, 256, 21519, 256, 
-    23653, 256, 26131, 256, 26446, 256, 26792, 256, 27877, 256, 29702, 256, 
-    30178, 256, 32633, 256, 35023, 256, 35041, 256, 37324, 256, 38626, 256, 
-    21311, 256, 28346, 256, 21533, 256, 29136, 256, 29848, 256, 34298, 256, 
-    38563, 256, 40023, 256, 40607, 256, 26519, 256, 28107, 256, 33256, 256, 
-    31435, 256, 31520, 256, 31890, 256, 29376, 256, 28825, 256, 35672, 256, 
-    20160, 256, 33590, 256, 21050, 256, 20999, 256, 24230, 256, 25299, 256, 
-    31958, 256, 23429, 256, 27934, 256, 26292, 256, 36667, 256, 34892, 256, 
-    38477, 256, 35211, 256, 24275, 256, 20800, 256, 21952, 256, 22618, 256, 
-    26228, 256, 20958, 256, 29482, 256, 30410, 256, 31036, 256, 31070, 256, 
-    31077, 256, 31119, 256, 38742, 256, 31934, 256, 32701, 256, 34322, 256, 
-    35576, 256, 36920, 256, 37117, 256, 39151, 256, 39164, 256, 39208, 256, 
-    40372, 256, 37086, 256, 38583, 256, 20398, 256, 20711, 256, 20813, 256, 
-    21193, 256, 21220, 256, 21329, 256, 21917, 256, 22022, 256, 22120, 256, 
-    22592, 256, 22696, 256, 23652, 256, 23662, 256, 24724, 256, 24936, 256, 
-    24974, 256, 25074, 256, 25935, 256, 26082, 256, 26257, 256, 26757, 256, 
-    28023, 256, 28186, 256, 28450, 256, 29038, 256, 29227, 256, 29730, 256, 
-    30865, 256, 31038, 256, 31049, 256, 31048, 256, 31056, 256, 31062, 256, 
-    31069, 256, 31117, 256, 31118, 256, 31296, 256, 31361, 256, 31680, 256, 
-    32244, 256, 32265, 256, 32321, 256, 32626, 256, 32773, 256, 33261, 256, 
-    33401, 256, 33401, 256, 33879, 256, 35088, 256, 35222, 256, 35585, 256, 
-    35641, 256, 36051, 256, 36104, 256, 36790, 256, 36920, 256, 38627, 256, 
-    38911, 256, 38971, 256, 24693, 256, 55376, 57070, 256, 33304, 256, 20006, 
-    256, 20917, 256, 20840, 256, 20352, 256, 20805, 256, 20864, 256, 21191, 
-    256, 21242, 256, 21917, 256, 21845, 256, 21913, 256, 21986, 256, 22618, 
-    256, 22707, 256, 22852, 256, 22868, 256, 23138, 256, 23336, 256, 24274, 
-    256, 24281, 256, 24425, 256, 24493, 256, 24792, 256, 24910, 256, 24840, 
-    256, 24974, 256, 24928, 256, 25074, 256, 25140, 256, 25540, 256, 25628, 
-    256, 25682, 256, 25942, 256, 26228, 256, 26391, 256, 26395, 256, 26454, 
-    256, 27513, 256, 27578, 256, 27969, 256, 28379, 256, 28363, 256, 28450, 
-    256, 28702, 256, 29038, 256, 30631, 256, 29237, 256, 29359, 256, 29482, 
-    256, 29809, 256, 29958, 256, 30011, 256, 30237, 256, 30239, 256, 30410, 
-    256, 30427, 256, 30452, 256, 30538, 256, 30528, 256, 30924, 256, 31409, 
-    256, 31680, 256, 31867, 256, 32091, 256, 32244, 256, 32574, 256, 32773, 
-    256, 33618, 256, 33775, 256, 34681, 256, 35137, 256, 35206, 256, 35222, 
-    256, 35519, 256, 35576, 256, 35531, 256, 35585, 256, 35582, 256, 35565, 
-    256, 35641, 256, 35722, 256, 36104, 256, 36664, 256, 36978, 256, 37273, 
-    256, 37494, 256, 38524, 256, 38627, 256, 38742, 256, 38875, 256, 38911, 
-    256, 38923, 256, 38971, 256, 39698, 256, 40860, 256, 55370, 56394, 256, 
-    55370, 56388, 256, 55372, 57301, 256, 15261, 256, 16408, 256, 16441, 256, 
-    55380, 56905, 256, 55383, 56528, 256, 55391, 57043, 256, 40771, 256, 
-    40846, 514, 102, 102, 514, 102, 105, 514, 102, 108, 770, 102, 102, 105, 
-    770, 102, 102, 108, 514, 383, 116, 514, 115, 116, 514, 1396, 1398, 514, 
-    1396, 1381, 514, 1396, 1387, 514, 1406, 1398, 514, 1396, 1389, 512, 1497, 
-    1460, 512, 1522, 1463, 262, 1506, 262, 1488, 262, 1491, 262, 1492, 262, 
-    1499, 262, 1500, 262, 1501, 262, 1512, 262, 1514, 262, 43, 512, 1513, 
-    1473, 512, 1513, 1474, 512, 64329, 1473, 512, 64329, 1474, 512, 1488, 
-    1463, 512, 1488, 1464, 512, 1488, 1468, 512, 1489, 1468, 512, 1490, 1468, 
-    512, 1491, 1468, 512, 1492, 1468, 512, 1493, 1468, 512, 1494, 1468, 512, 
-    1496, 1468, 512, 1497, 1468, 512, 1498, 1468, 512, 1499, 1468, 512, 1500, 
-    1468, 512, 1502, 1468, 512, 1504, 1468, 512, 1505, 1468, 512, 1507, 1468, 
-    512, 1508, 1468, 512, 1510, 1468, 512, 1511, 1468, 512, 1512, 1468, 512, 
-    1513, 1468, 512, 1514, 1468, 512, 1493, 1465, 512, 1489, 1471, 512, 1499, 
-    1471, 512, 1508, 1471, 514, 1488, 1500, 267, 1649, 268, 1649, 267, 1659, 
-    268, 1659, 269, 1659, 270, 1659, 267, 1662, 268, 1662, 269, 1662, 270, 
-    1662, 267, 1664, 268, 1664, 269, 1664, 270, 1664, 267, 1658, 268, 1658, 
-    269, 1658, 270, 1658, 267, 1663, 268, 1663, 269, 1663, 270, 1663, 267, 
-    1657, 268, 1657, 269, 1657, 270, 1657, 267, 1700, 268, 1700, 269, 1700, 
-    270, 1700, 267, 1702, 268, 1702, 269, 1702, 270, 1702, 267, 1668, 268, 
-    1668, 269, 1668, 270, 1668, 267, 1667, 268, 1667, 269, 1667, 270, 1667, 
-    267, 1670, 268, 1670, 269, 1670, 270, 1670, 267, 1671, 268, 1671, 269, 
-    1671, 270, 1671, 267, 1677, 268, 1677, 267, 1676, 268, 1676, 267, 1678, 
-    268, 1678, 267, 1672, 268, 1672, 267, 1688, 268, 1688, 267, 1681, 268, 
-    1681, 267, 1705, 268, 1705, 269, 1705, 270, 1705, 267, 1711, 268, 1711, 
-    269, 1711, 270, 1711, 267, 1715, 268, 1715, 269, 1715, 270, 1715, 267, 
-    1713, 268, 1713, 269, 1713, 270, 1713, 267, 1722, 268, 1722, 267, 1723, 
-    268, 1723, 269, 1723, 270, 1723, 267, 1728, 268, 1728, 267, 1729, 268, 
-    1729, 269, 1729, 270, 1729, 267, 1726, 268, 1726, 269, 1726, 270, 1726, 
-    267, 1746, 268, 1746, 267, 1747, 268, 1747, 267, 1709, 268, 1709, 269, 
-    1709, 270, 1709, 267, 1735, 268, 1735, 267, 1734, 268, 1734, 267, 1736, 
-    268, 1736, 267, 1655, 267, 1739, 268, 1739, 267, 1733, 268, 1733, 267, 
-    1737, 268, 1737, 267, 1744, 268, 1744, 269, 1744, 270, 1744, 269, 1609, 
-    270, 1609, 523, 1574, 1575, 524, 1574, 1575, 523, 1574, 1749, 524, 1574, 
-    1749, 523, 1574, 1608, 524, 1574, 1608, 523, 1574, 1735, 524, 1574, 1735, 
-    523, 1574, 1734, 524, 1574, 1734, 523, 1574, 1736, 524, 1574, 1736, 523, 
-    1574, 1744, 524, 1574, 1744, 525, 1574, 1744, 523, 1574, 1609, 524, 1574, 
-    1609, 525, 1574, 1609, 267, 1740, 268, 1740, 269, 1740, 270, 1740, 523, 
-    1574, 1580, 523, 1574, 1581, 523, 1574, 1605, 523, 1574, 1609, 523, 1574, 
-    1610, 523, 1576, 1580, 523, 1576, 1581, 523, 1576, 1582, 523, 1576, 1605, 
-    523, 1576, 1609, 523, 1576, 1610, 523, 1578, 1580, 523, 1578, 1581, 523, 
-    1578, 1582, 523, 1578, 1605, 523, 1578, 1609, 523, 1578, 1610, 523, 1579, 
-    1580, 523, 1579, 1605, 523, 1579, 1609, 523, 1579, 1610, 523, 1580, 1581, 
-    523, 1580, 1605, 523, 1581, 1580, 523, 1581, 1605, 523, 1582, 1580, 523, 
-    1582, 1581, 523, 1582, 1605, 523, 1587, 1580, 523, 1587, 1581, 523, 1587, 
-    1582, 523, 1587, 1605, 523, 1589, 1581, 523, 1589, 1605, 523, 1590, 1580, 
-    523, 1590, 1581, 523, 1590, 1582, 523, 1590, 1605, 523, 1591, 1581, 523, 
-    1591, 1605, 523, 1592, 1605, 523, 1593, 1580, 523, 1593, 1605, 523, 1594, 
-    1580, 523, 1594, 1605, 523, 1601, 1580, 523, 1601, 1581, 523, 1601, 1582, 
-    523, 1601, 1605, 523, 1601, 1609, 523, 1601, 1610, 523, 1602, 1581, 523, 
-    1602, 1605, 523, 1602, 1609, 523, 1602, 1610, 523, 1603, 1575, 523, 1603, 
-    1580, 523, 1603, 1581, 523, 1603, 1582, 523, 1603, 1604, 523, 1603, 1605, 
-    523, 1603, 1609, 523, 1603, 1610, 523, 1604, 1580, 523, 1604, 1581, 523, 
-    1604, 1582, 523, 1604, 1605, 523, 1604, 1609, 523, 1604, 1610, 523, 1605, 
-    1580, 523, 1605, 1581, 523, 1605, 1582, 523, 1605, 1605, 523, 1605, 1609, 
-    523, 1605, 1610, 523, 1606, 1580, 523, 1606, 1581, 523, 1606, 1582, 523, 
-    1606, 1605, 523, 1606, 1609, 523, 1606, 1610, 523, 1607, 1580, 523, 1607, 
-    1605, 523, 1607, 1609, 523, 1607, 1610, 523, 1610, 1580, 523, 1610, 1581, 
-    523, 1610, 1582, 523, 1610, 1605, 523, 1610, 1609, 523, 1610, 1610, 523, 
-    1584, 1648, 523, 1585, 1648, 523, 1609, 1648, 779, 32, 1612, 1617, 779, 
-    32, 1613, 1617, 779, 32, 1614, 1617, 779, 32, 1615, 1617, 779, 32, 1616, 
-    1617, 779, 32, 1617, 1648, 524, 1574, 1585, 524, 1574, 1586, 524, 1574, 
-    1605, 524, 1574, 1606, 524, 1574, 1609, 524, 1574, 1610, 524, 1576, 1585, 
-    524, 1576, 1586, 524, 1576, 1605, 524, 1576, 1606, 524, 1576, 1609, 524, 
-    1576, 1610, 524, 1578, 1585, 524, 1578, 1586, 524, 1578, 1605, 524, 1578, 
-    1606, 524, 1578, 1609, 524, 1578, 1610, 524, 1579, 1585, 524, 1579, 1586, 
-    524, 1579, 1605, 524, 1579, 1606, 524, 1579, 1609, 524, 1579, 1610, 524, 
-    1601, 1609, 524, 1601, 1610, 524, 1602, 1609, 524, 1602, 1610, 524, 1603, 
-    1575, 524, 1603, 1604, 524, 1603, 1605, 524, 1603, 1609, 524, 1603, 1610, 
-    524, 1604, 1605, 524, 1604, 1609, 524, 1604, 1610, 524, 1605, 1575, 524, 
-    1605, 1605, 524, 1606, 1585, 524, 1606, 1586, 524, 1606, 1605, 524, 1606, 
-    1606, 524, 1606, 1609, 524, 1606, 1610, 524, 1609, 1648, 524, 1610, 1585, 
-    524, 1610, 1586, 524, 1610, 1605, 524, 1610, 1606, 524, 1610, 1609, 524, 
-    1610, 1610, 525, 1574, 1580, 525, 1574, 1581, 525, 1574, 1582, 525, 1574, 
-    1605, 525, 1574, 1607, 525, 1576, 1580, 525, 1576, 1581, 525, 1576, 1582, 
-    525, 1576, 1605, 525, 1576, 1607, 525, 1578, 1580, 525, 1578, 1581, 525, 
-    1578, 1582, 525, 1578, 1605, 525, 1578, 1607, 525, 1579, 1605, 525, 1580, 
-    1581, 525, 1580, 1605, 525, 1581, 1580, 525, 1581, 1605, 525, 1582, 1580, 
-    525, 1582, 1605, 525, 1587, 1580, 525, 1587, 1581, 525, 1587, 1582, 525, 
-    1587, 1605, 525, 1589, 1581, 525, 1589, 1582, 525, 1589, 1605, 525, 1590, 
-    1580, 525, 1590, 1581, 525, 1590, 1582, 525, 1590, 1605, 525, 1591, 1581, 
-    525, 1592, 1605, 525, 1593, 1580, 525, 1593, 1605, 525, 1594, 1580, 525, 
-    1594, 1605, 525, 1601, 1580, 525, 1601, 1581, 525, 1601, 1582, 525, 1601, 
-    1605, 525, 1602, 1581, 525, 1602, 1605, 525, 1603, 1580, 525, 1603, 1581, 
-    525, 1603, 1582, 525, 1603, 1604, 525, 1603, 1605, 525, 1604, 1580, 525, 
-    1604, 1581, 525, 1604, 1582, 525, 1604, 1605, 525, 1604, 1607, 525, 1605, 
-    1580, 525, 1605, 1581, 525, 1605, 1582, 525, 1605, 1605, 525, 1606, 1580, 
-    525, 1606, 1581, 525, 1606, 1582, 525, 1606, 1605, 525, 1606, 1607, 525, 
-    1607, 1580, 525, 1607, 1605, 525, 1607, 1648, 525, 1610, 1580, 525, 1610, 
-    1581, 525, 1610, 1582, 525, 1610, 1605, 525, 1610, 1607, 526, 1574, 1605, 
-    526, 1574, 1607, 526, 1576, 1605, 526, 1576, 1607, 526, 1578, 1605, 526, 
-    1578, 1607, 526, 1579, 1605, 526, 1579, 1607, 526, 1587, 1605, 526, 1587, 
-    1607, 526, 1588, 1605, 526, 1588, 1607, 526, 1603, 1604, 526, 1603, 1605, 
-    526, 1604, 1605, 526, 1606, 1605, 526, 1606, 1607, 526, 1610, 1605, 526, 
-    1610, 1607, 782, 1600, 1614, 1617, 782, 1600, 1615, 1617, 782, 1600, 
-    1616, 1617, 523, 1591, 1609, 523, 1591, 1610, 523, 1593, 1609, 523, 1593, 
-    1610, 523, 1594, 1609, 523, 1594, 1610, 523, 1587, 1609, 523, 1587, 1610, 
-    523, 1588, 1609, 523, 1588, 1610, 523, 1581, 1609, 523, 1581, 1610, 523, 
-    1580, 1609, 523, 1580, 1610, 523, 1582, 1609, 523, 1582, 1610, 523, 1589, 
-    1609, 523, 1589, 1610, 523, 1590, 1609, 523, 1590, 1610, 523, 1588, 1580, 
-    523, 1588, 1581, 523, 1588, 1582, 523, 1588, 1605, 523, 1588, 1585, 523, 
-    1587, 1585, 523, 1589, 1585, 523, 1590, 1585, 524, 1591, 1609, 524, 1591, 
-    1610, 524, 1593, 1609, 524, 1593, 1610, 524, 1594, 1609, 524, 1594, 1610, 
-    524, 1587, 1609, 524, 1587, 1610, 524, 1588, 1609, 524, 1588, 1610, 524, 
-    1581, 1609, 524, 1581, 1610, 524, 1580, 1609, 524, 1580, 1610, 524, 1582, 
-    1609, 524, 1582, 1610, 524, 1589, 1609, 524, 1589, 1610, 524, 1590, 1609, 
-    524, 1590, 1610, 524, 1588, 1580, 524, 1588, 1581, 524, 1588, 1582, 524, 
-    1588, 1605, 524, 1588, 1585, 524, 1587, 1585, 524, 1589, 1585, 524, 1590, 
-    1585, 525, 1588, 1580, 525, 1588, 1581, 525, 1588, 1582, 525, 1588, 1605, 
-    525, 1587, 1607, 525, 1588, 1607, 525, 1591, 1605, 526, 1587, 1580, 526, 
-    1587, 1581, 526, 1587, 1582, 526, 1588, 1580, 526, 1588, 1581, 526, 1588, 
-    1582, 526, 1591, 1605, 526, 1592, 1605, 524, 1575, 1611, 523, 1575, 1611, 
-    781, 1578, 1580, 1605, 780, 1578, 1581, 1580, 781, 1578, 1581, 1580, 781, 
-    1578, 1581, 1605, 781, 1578, 1582, 1605, 781, 1578, 1605, 1580, 781, 
-    1578, 1605, 1581, 781, 1578, 1605, 1582, 780, 1580, 1605, 1581, 781, 
-    1580, 1605, 1581, 780, 1581, 1605, 1610, 780, 1581, 1605, 1609, 781, 
-    1587, 1581, 1580, 781, 1587, 1580, 1581, 780, 1587, 1580, 1609, 780, 
-    1587, 1605, 1581, 781, 1587, 1605, 1581, 781, 1587, 1605, 1580, 780, 
-    1587, 1605, 1605, 781, 1587, 1605, 1605, 780, 1589, 1581, 1581, 781, 
-    1589, 1581, 1581, 780, 1589, 1605, 1605, 780, 1588, 1581, 1605, 781, 
-    1588, 1581, 1605, 780, 1588, 1580, 1610, 780, 1588, 1605, 1582, 781, 
-    1588, 1605, 1582, 780, 1588, 1605, 1605, 781, 1588, 1605, 1605, 780, 
-    1590, 1581, 1609, 780, 1590, 1582, 1605, 781, 1590, 1582, 1605, 780, 
-    1591, 1605, 1581, 781, 1591, 1605, 1581, 781, 1591, 1605, 1605, 780, 
-    1591, 1605, 1610, 780, 1593, 1580, 1605, 780, 1593, 1605, 1605, 781, 
-    1593, 1605, 1605, 780, 1593, 1605, 1609, 780, 1594, 1605, 1605, 780, 
-    1594, 1605, 1610, 780, 1594, 1605, 1609, 780, 1601, 1582, 1605, 781, 
-    1601, 1582, 1605, 780, 1602, 1605, 1581, 780, 1602, 1605, 1605, 780, 
-    1604, 1581, 1605, 780, 1604, 1581, 1610, 780, 1604, 1581, 1609, 781, 
-    1604, 1580, 1580, 780, 1604, 1580, 1580, 780, 1604, 1582, 1605, 781, 
-    1604, 1582, 1605, 780, 1604, 1605, 1581, 781, 1604, 1605, 1581, 781, 
-    1605, 1581, 1580, 781, 1605, 1581, 1605, 780, 1605, 1581, 1610, 781, 
-    1605, 1580, 1581, 781, 1605, 1580, 1605, 781, 1605, 1582, 1580, 781, 
-    1605, 1582, 1605, 781, 1605, 1580, 1582, 781, 1607, 1605, 1580, 781, 
-    1607, 1605, 1605, 781, 1606, 1581, 1605, 780, 1606, 1581, 1609, 780, 
-    1606, 1580, 1605, 781, 1606, 1580, 1605, 780, 1606, 1580, 1609, 780, 
-    1606, 1605, 1610, 780, 1606, 1605, 1609, 780, 1610, 1605, 1605, 781, 
-    1610, 1605, 1605, 780, 1576, 1582, 1610, 780, 1578, 1580, 1610, 780, 
-    1578, 1580, 1609, 780, 1578, 1582, 1610, 780, 1578, 1582, 1609, 780, 
-    1578, 1605, 1610, 780, 1578, 1605, 1609, 780, 1580, 1605, 1610, 780, 
-    1580, 1581, 1609, 780, 1580, 1605, 1609, 780, 1587, 1582, 1609, 780, 
-    1589, 1581, 1610, 780, 1588, 1581, 1610, 780, 1590, 1581, 1610, 780, 
-    1604, 1580, 1610, 780, 1604, 1605, 1610, 780, 1610, 1581, 1610, 780, 
-    1610, 1580, 1610, 780, 1610, 1605, 1610, 780, 1605, 1605, 1610, 780, 
-    1602, 1605, 1610, 780, 1606, 1581, 1610, 781, 1602, 1605, 1581, 781, 
-    1604, 1581, 1605, 780, 1593, 1605, 1610, 780, 1603, 1605, 1610, 781, 
-    1606, 1580, 1581, 780, 1605, 1582, 1610, 781, 1604, 1580, 1605, 780, 
-    1603, 1605, 1605, 780, 1604, 1580, 1605, 780, 1606, 1580, 1581, 780, 
-    1580, 1581, 1610, 780, 1581, 1580, 1610, 780, 1605, 1580, 1610, 780, 
-    1601, 1605, 1610, 780, 1576, 1581, 1610, 781, 1603, 1605, 1605, 781, 
-    1593, 1580, 1605, 781, 1589, 1605, 1605, 780, 1587, 1582, 1610, 780, 
-    1606, 1580, 1610, 779, 1589, 1604, 1746, 779, 1602, 1604, 1746, 1035, 
-    1575, 1604, 1604, 1607, 1035, 1575, 1603, 1576, 1585, 1035, 1605, 1581, 
-    1605, 1583, 1035, 1589, 1604, 1593, 1605, 1035, 1585, 1587, 1608, 1604, 
-    1035, 1593, 1604, 1610, 1607, 1035, 1608, 1587, 1604, 1605, 779, 1589, 
-    1604, 1609, 4619, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, 
-    1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 2059, 1580, 1604, 32, 1580, 
-    1604, 1575, 1604, 1607, 1035, 1585, 1740, 1575, 1604, 265, 44, 265, 
-    12289, 265, 12290, 265, 58, 265, 59, 265, 33, 265, 63, 265, 12310, 265, 
-    12311, 265, 8230, 265, 8229, 265, 8212, 265, 8211, 265, 95, 265, 95, 265, 
-    40, 265, 41, 265, 123, 265, 125, 265, 12308, 265, 12309, 265, 12304, 265, 
-    12305, 265, 12298, 265, 12299, 265, 12296, 265, 12297, 265, 12300, 265, 
-    12301, 265, 12302, 265, 12303, 265, 91, 265, 93, 258, 8254, 258, 8254, 
-    258, 8254, 258, 8254, 258, 95, 258, 95, 258, 95, 271, 44, 271, 12289, 
-    271, 46, 271, 59, 271, 58, 271, 63, 271, 33, 271, 8212, 271, 40, 271, 41, 
-    271, 123, 271, 125, 271, 12308, 271, 12309, 271, 35, 271, 38, 271, 42, 
-    271, 43, 271, 45, 271, 60, 271, 62, 271, 61, 271, 92, 271, 36, 271, 37, 
-    271, 64, 523, 32, 1611, 526, 1600, 1611, 523, 32, 1612, 523, 32, 1613, 
-    523, 32, 1614, 526, 1600, 1614, 523, 32, 1615, 526, 1600, 1615, 523, 32, 
-    1616, 526, 1600, 1616, 523, 32, 1617, 526, 1600, 1617, 523, 32, 1618, 
-    526, 1600, 1618, 267, 1569, 267, 1570, 268, 1570, 267, 1571, 268, 1571, 
-    267, 1572, 268, 1572, 267, 1573, 268, 1573, 267, 1574, 268, 1574, 269, 
-    1574, 270, 1574, 267, 1575, 268, 1575, 267, 1576, 268, 1576, 269, 1576, 
-    270, 1576, 267, 1577, 268, 1577, 267, 1578, 268, 1578, 269, 1578, 270, 
-    1578, 267, 1579, 268, 1579, 269, 1579, 270, 1579, 267, 1580, 268, 1580, 
-    269, 1580, 270, 1580, 267, 1581, 268, 1581, 269, 1581, 270, 1581, 267, 
-    1582, 268, 1582, 269, 1582, 270, 1582, 267, 1583, 268, 1583, 267, 1584, 
-    268, 1584, 267, 1585, 268, 1585, 267, 1586, 268, 1586, 267, 1587, 268, 
-    1587, 269, 1587, 270, 1587, 267, 1588, 268, 1588, 269, 1588, 270, 1588, 
-    267, 1589, 268, 1589, 269, 1589, 270, 1589, 267, 1590, 268, 1590, 269, 
-    1590, 270, 1590, 267, 1591, 268, 1591, 269, 1591, 270, 1591, 267, 1592, 
-    268, 1592, 269, 1592, 270, 1592, 267, 1593, 268, 1593, 269, 1593, 270, 
-    1593, 267, 1594, 268, 1594, 269, 1594, 270, 1594, 267, 1601, 268, 1601, 
-    269, 1601, 270, 1601, 267, 1602, 268, 1602, 269, 1602, 270, 1602, 267, 
-    1603, 268, 1603, 269, 1603, 270, 1603, 267, 1604, 268, 1604, 269, 1604, 
-    270, 1604, 267, 1605, 268, 1605, 269, 1605, 270, 1605, 267, 1606, 268, 
-    1606, 269, 1606, 270, 1606, 267, 1607, 268, 1607, 269, 1607, 270, 1607, 
-    267, 1608, 268, 1608, 267, 1609, 268, 1609, 267, 1610, 268, 1610, 269, 
-    1610, 270, 1610, 523, 1604, 1570, 524, 1604, 1570, 523, 1604, 1571, 524, 
-    1604, 1571, 523, 1604, 1573, 524, 1604, 1573, 523, 1604, 1575, 524, 1604, 
-    1575, 264, 33, 264, 34, 264, 35, 264, 36, 264, 37, 264, 38, 264, 39, 264, 
-    40, 264, 41, 264, 42, 264, 43, 264, 44, 264, 45, 264, 46, 264, 47, 264, 
-    48, 264, 49, 264, 50, 264, 51, 264, 52, 264, 53, 264, 54, 264, 55, 264, 
-    56, 264, 57, 264, 58, 264, 59, 264, 60, 264, 61, 264, 62, 264, 63, 264, 
-    64, 264, 65, 264, 66, 264, 67, 264, 68, 264, 69, 264, 70, 264, 71, 264, 
-    72, 264, 73, 264, 74, 264, 75, 264, 76, 264, 77, 264, 78, 264, 79, 264, 
-    80, 264, 81, 264, 82, 264, 83, 264, 84, 264, 85, 264, 86, 264, 87, 264, 
-    88, 264, 89, 264, 90, 264, 91, 264, 92, 264, 93, 264, 94, 264, 95, 264, 
-    96, 264, 97, 264, 98, 264, 99, 264, 100, 264, 101, 264, 102, 264, 103, 
-    264, 104, 264, 105, 264, 106, 264, 107, 264, 108, 264, 109, 264, 110, 
-    264, 111, 264, 112, 264, 113, 264, 114, 264, 115, 264, 116, 264, 117, 
-    264, 118, 264, 119, 264, 120, 264, 121, 264, 122, 264, 123, 264, 124, 
-    264, 125, 264, 126, 264, 10629, 264, 10630, 272, 12290, 272, 12300, 272, 
-    12301, 272, 12289, 272, 12539, 272, 12530, 272, 12449, 272, 12451, 272, 
-    12453, 272, 12455, 272, 12457, 272, 12515, 272, 12517, 272, 12519, 272, 
-    12483, 272, 12540, 272, 12450, 272, 12452, 272, 12454, 272, 12456, 272, 
-    12458, 272, 12459, 272, 12461, 272, 12463, 272, 12465, 272, 12467, 272, 
-    12469, 272, 12471, 272, 12473, 272, 12475, 272, 12477, 272, 12479, 272, 
-    12481, 272, 12484, 272, 12486, 272, 12488, 272, 12490, 272, 12491, 272, 
-    12492, 272, 12493, 272, 12494, 272, 12495, 272, 12498, 272, 12501, 272, 
-    12504, 272, 12507, 272, 12510, 272, 12511, 272, 12512, 272, 12513, 272, 
-    12514, 272, 12516, 272, 12518, 272, 12520, 272, 12521, 272, 12522, 272, 
-    12523, 272, 12524, 272, 12525, 272, 12527, 272, 12531, 272, 12441, 272, 
-    12442, 272, 12644, 272, 12593, 272, 12594, 272, 12595, 272, 12596, 272, 
-    12597, 272, 12598, 272, 12599, 272, 12600, 272, 12601, 272, 12602, 272, 
-    12603, 272, 12604, 272, 12605, 272, 12606, 272, 12607, 272, 12608, 272, 
-    12609, 272, 12610, 272, 12611, 272, 12612, 272, 12613, 272, 12614, 272, 
-    12615, 272, 12616, 272, 12617, 272, 12618, 272, 12619, 272, 12620, 272, 
-    12621, 272, 12622, 272, 12623, 272, 12624, 272, 12625, 272, 12626, 272, 
-    12627, 272, 12628, 272, 12629, 272, 12630, 272, 12631, 272, 12632, 272, 
-    12633, 272, 12634, 272, 12635, 272, 12636, 272, 12637, 272, 12638, 272, 
-    12639, 272, 12640, 272, 12641, 272, 12642, 272, 12643, 264, 162, 264, 
-    163, 264, 172, 264, 175, 264, 166, 264, 165, 264, 8361, 272, 9474, 272, 
-    8592, 272, 8593, 272, 8594, 272, 8595, 272, 9632, 272, 9675, 512, 55300, 
-    56473, 55300, 56506, 512, 55300, 56475, 55300, 56506, 512, 55300, 56485, 
-    55300, 56506, 512, 55300, 56625, 55300, 56615, 512, 55300, 56626, 55300, 
-    56615, 512, 55300, 57159, 55300, 57150, 512, 55300, 57159, 55300, 57175, 
-    512, 55301, 56505, 55301, 56506, 512, 55301, 56505, 55301, 56496, 512, 
-    55301, 56505, 55301, 56509, 512, 55301, 56760, 55301, 56751, 512, 55301, 
-    56761, 55301, 56751, 512, 55348, 56663, 55348, 56677, 512, 55348, 56664, 
-    55348, 56677, 512, 55348, 56671, 55348, 56686, 512, 55348, 56671, 55348, 
-    56687, 512, 55348, 56671, 55348, 56688, 512, 55348, 56671, 55348, 56689, 
-    512, 55348, 56671, 55348, 56690, 512, 55348, 56761, 55348, 56677, 512, 
-    55348, 56762, 55348, 56677, 512, 55348, 56763, 55348, 56686, 512, 55348, 
-    56764, 55348, 56686, 512, 55348, 56763, 55348, 56687, 512, 55348, 56764, 
-    55348, 56687, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 
-    71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 
-    79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 
-    87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 
-    101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 
-    108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 
-    115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 
-    122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 
-    72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 
-    80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 
-    88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 
-    102, 262, 103, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 
-    110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 
-    117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 
-    262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 
-    262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 
-    262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 
-    262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 
-    104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 
-    111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 
-    118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 67, 262, 68, 
-    262, 71, 262, 74, 262, 75, 262, 78, 262, 79, 262, 80, 262, 81, 262, 83, 
-    262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 
-    262, 98, 262, 99, 262, 100, 262, 102, 262, 104, 262, 105, 262, 106, 262, 
-    107, 262, 108, 262, 109, 262, 110, 262, 112, 262, 113, 262, 114, 262, 
-    115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 
-    122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 
-    72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 
-    80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 
-    88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 
-    102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 
-    109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 
-    116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 
-    262, 66, 262, 68, 262, 69, 262, 70, 262, 71, 262, 74, 262, 75, 262, 76, 
-    262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 83, 262, 84, 262, 85, 
-    262, 86, 262, 87, 262, 88, 262, 89, 262, 97, 262, 98, 262, 99, 262, 100, 
-    262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 
-    262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 
-    262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 
-    262, 122, 262, 65, 262, 66, 262, 68, 262, 69, 262, 70, 262, 71, 262, 73, 
-    262, 74, 262, 75, 262, 76, 262, 77, 262, 79, 262, 83, 262, 84, 262, 85, 
-    262, 86, 262, 87, 262, 88, 262, 89, 262, 97, 262, 98, 262, 99, 262, 100, 
-    262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 
-    262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 
-    262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 
-    262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 
-    262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 
-    262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 
-    262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 
-    262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 
-    262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 
-    262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 
-    262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 
-    262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 
-    262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 
-    262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 
-    102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 
-    109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 
-    116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 
-    262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 
-    262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 
-    262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 
-    262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 
-    103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 
-    110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 
-    117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 
-    262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 
-    262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 
-    262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 
-    262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 
-    104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 
-    111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 
-    118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 
-    262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 
-    262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 
-    262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 
-    262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, 
-    105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, 
-    112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, 
-    119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 
-    262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 
-    262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 
-    262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 
-    262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 
-    106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 
-    113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 
-    120, 262, 121, 262, 122, 262, 305, 262, 567, 262, 913, 262, 914, 262, 
-    915, 262, 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, 921, 262, 
-    922, 262, 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, 928, 262, 
-    929, 262, 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, 935, 262, 
-    936, 262, 937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, 948, 262, 
-    949, 262, 950, 262, 951, 262, 952, 262, 953, 262, 954, 262, 955, 262, 
-    956, 262, 957, 262, 958, 262, 959, 262, 960, 262, 961, 262, 962, 262, 
-    963, 262, 964, 262, 965, 262, 966, 262, 967, 262, 968, 262, 969, 262, 
-    8706, 262, 1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, 982, 262, 
-    913, 262, 914, 262, 915, 262, 916, 262, 917, 262, 918, 262, 919, 262, 
-    920, 262, 921, 262, 922, 262, 923, 262, 924, 262, 925, 262, 926, 262, 
-    927, 262, 928, 262, 929, 262, 1012, 262, 931, 262, 932, 262, 933, 262, 
-    934, 262, 935, 262, 936, 262, 937, 262, 8711, 262, 945, 262, 946, 262, 
-    947, 262, 948, 262, 949, 262, 950, 262, 951, 262, 952, 262, 953, 262, 
-    954, 262, 955, 262, 956, 262, 957, 262, 958, 262, 959, 262, 960, 262, 
-    961, 262, 962, 262, 963, 262, 964, 262, 965, 262, 966, 262, 967, 262, 
-    968, 262, 969, 262, 8706, 262, 1013, 262, 977, 262, 1008, 262, 981, 262, 
-    1009, 262, 982, 262, 913, 262, 914, 262, 915, 262, 916, 262, 917, 262, 
-    918, 262, 919, 262, 920, 262, 921, 262, 922, 262, 923, 262, 924, 262, 
-    925, 262, 926, 262, 927, 262, 928, 262, 929, 262, 1012, 262, 931, 262, 
-    932, 262, 933, 262, 934, 262, 935, 262, 936, 262, 937, 262, 8711, 262, 
-    945, 262, 946, 262, 947, 262, 948, 262, 949, 262, 950, 262, 951, 262, 
-    952, 262, 953, 262, 954, 262, 955, 262, 956, 262, 957, 262, 958, 262, 
-    959, 262, 960, 262, 961, 262, 962, 262, 963, 262, 964, 262, 965, 262, 
-    966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, 1013, 262, 977, 262, 
-    1008, 262, 981, 262, 1009, 262, 982, 262, 913, 262, 914, 262, 915, 262, 
-    916, 262, 917, 262, 918, 262, 919, 262, 920, 262, 921, 262, 922, 262, 
-    923, 262, 924, 262, 925, 262, 926, 262, 927, 262, 928, 262, 929, 262, 
-    1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, 935, 262, 936, 262, 
-    937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, 948, 262, 949, 262, 
-    950, 262, 951, 262, 952, 262, 953, 262, 954, 262, 955, 262, 956, 262, 
-    957, 262, 958, 262, 959, 262, 960, 262, 961, 262, 962, 262, 963, 262, 
-    964, 262, 965, 262, 966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, 
-    1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, 982, 262, 913, 262, 
-    914, 262, 915, 262, 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, 
-    921, 262, 922, 262, 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, 
-    928, 262, 929, 262, 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, 
-    935, 262, 936, 262, 937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, 
-    948, 262, 949, 262, 950, 262, 951, 262, 952, 262, 953, 262, 954, 262, 
-    955, 262, 956, 262, 957, 262, 958, 262, 959, 262, 960, 262, 961, 262, 
-    962, 262, 963, 262, 964, 262, 965, 262, 966, 262, 967, 262, 968, 262, 
-    969, 262, 8706, 262, 1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, 
-    982, 262, 988, 262, 989, 262, 48, 262, 49, 262, 50, 262, 51, 262, 52, 
-    262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, 48, 262, 49, 262, 50, 
-    262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, 48, 
-    262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, 56, 
-    262, 57, 262, 48, 262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, 54, 
-    262, 55, 262, 56, 262, 57, 262, 48, 262, 49, 262, 50, 262, 51, 262, 52, 
-    262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, 1575, 262, 1576, 262, 
-    1580, 262, 1583, 262, 1608, 262, 1586, 262, 1581, 262, 1591, 262, 1610, 
-    262, 1603, 262, 1604, 262, 1605, 262, 1606, 262, 1587, 262, 1593, 262, 
-    1601, 262, 1589, 262, 1602, 262, 1585, 262, 1588, 262, 1578, 262, 1579, 
-    262, 1582, 262, 1584, 262, 1590, 262, 1592, 262, 1594, 262, 1646, 262, 
-    1722, 262, 1697, 262, 1647, 262, 1576, 262, 1580, 262, 1607, 262, 1581, 
-    262, 1610, 262, 1603, 262, 1604, 262, 1605, 262, 1606, 262, 1587, 262, 
-    1593, 262, 1601, 262, 1589, 262, 1602, 262, 1588, 262, 1578, 262, 1579, 
-    262, 1582, 262, 1590, 262, 1594, 262, 1580, 262, 1581, 262, 1610, 262, 
-    1604, 262, 1606, 262, 1587, 262, 1593, 262, 1589, 262, 1602, 262, 1588, 
-    262, 1582, 262, 1590, 262, 1594, 262, 1722, 262, 1647, 262, 1576, 262, 
-    1580, 262, 1607, 262, 1581, 262, 1591, 262, 1610, 262, 1603, 262, 1605, 
-    262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, 1602, 262, 
-    1588, 262, 1578, 262, 1579, 262, 1582, 262, 1590, 262, 1592, 262, 1594, 
-    262, 1646, 262, 1697, 262, 1575, 262, 1576, 262, 1580, 262, 1583, 262, 
-    1607, 262, 1608, 262, 1586, 262, 1581, 262, 1591, 262, 1610, 262, 1604, 
-    262, 1605, 262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, 
-    1602, 262, 1585, 262, 1588, 262, 1578, 262, 1579, 262, 1582, 262, 1584, 
-    262, 1590, 262, 1592, 262, 1594, 262, 1576, 262, 1580, 262, 1583, 262, 
-    1608, 262, 1586, 262, 1581, 262, 1591, 262, 1610, 262, 1604, 262, 1605, 
-    262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, 1602, 262, 
-    1585, 262, 1588, 262, 1578, 262, 1579, 262, 1582, 262, 1584, 262, 1590, 
-    262, 1592, 262, 1594, 514, 48, 46, 514, 48, 44, 514, 49, 44, 514, 50, 44, 
-    514, 51, 44, 514, 52, 44, 514, 53, 44, 514, 54, 44, 514, 55, 44, 514, 56, 
-    44, 514, 57, 44, 770, 40, 65, 41, 770, 40, 66, 41, 770, 40, 67, 41, 770, 
-    40, 68, 41, 770, 40, 69, 41, 770, 40, 70, 41, 770, 40, 71, 41, 770, 40, 
-    72, 41, 770, 40, 73, 41, 770, 40, 74, 41, 770, 40, 75, 41, 770, 40, 76, 
-    41, 770, 40, 77, 41, 770, 40, 78, 41, 770, 40, 79, 41, 770, 40, 80, 41, 
-    770, 40, 81, 41, 770, 40, 82, 41, 770, 40, 83, 41, 770, 40, 84, 41, 770, 
-    40, 85, 41, 770, 40, 86, 41, 770, 40, 87, 41, 770, 40, 88, 41, 770, 40, 
-    89, 41, 770, 40, 90, 41, 770, 12308, 83, 12309, 263, 67, 263, 82, 519, 
-    67, 68, 519, 87, 90, 266, 65, 266, 66, 266, 67, 266, 68, 266, 69, 266, 
-    70, 266, 71, 266, 72, 266, 73, 266, 74, 266, 75, 266, 76, 266, 77, 266, 
-    78, 266, 79, 266, 80, 266, 81, 266, 82, 266, 83, 266, 84, 266, 85, 266, 
-    86, 266, 87, 266, 88, 266, 89, 266, 90, 522, 72, 86, 522, 77, 86, 522, 
-    83, 68, 522, 83, 83, 778, 80, 80, 86, 522, 87, 67, 515, 77, 67, 515, 77, 
-    68, 515, 77, 82, 522, 68, 74, 522, 12411, 12363, 522, 12467, 12467, 266, 
-    12469, 266, 25163, 266, 23383, 266, 21452, 266, 12487, 266, 20108, 266, 
-    22810, 266, 35299, 266, 22825, 266, 20132, 266, 26144, 266, 28961, 266, 
-    26009, 266, 21069, 266, 24460, 266, 20877, 266, 26032, 266, 21021, 266, 
-    32066, 266, 29983, 266, 36009, 266, 22768, 266, 21561, 266, 28436, 266, 
-    25237, 266, 25429, 266, 19968, 266, 19977, 266, 36938, 266, 24038, 266, 
-    20013, 266, 21491, 266, 25351, 266, 36208, 266, 25171, 266, 31105, 266, 
-    31354, 266, 21512, 266, 28288, 266, 26377, 266, 26376, 266, 30003, 266, 
-    21106, 266, 21942, 266, 37197, 770, 12308, 26412, 12309, 770, 12308, 
-    19977, 12309, 770, 12308, 20108, 12309, 770, 12308, 23433, 12309, 770, 
-    12308, 28857, 12309, 770, 12308, 25171, 12309, 770, 12308, 30423, 12309, 
-    770, 12308, 21213, 12309, 770, 12308, 25943, 12309, 263, 24471, 263, 
-    21487, 256, 20029, 256, 20024, 256, 20033, 256, 55360, 56610, 256, 20320, 
-    256, 20398, 256, 20411, 256, 20482, 256, 20602, 256, 20633, 256, 20711, 
-    256, 20687, 256, 13470, 256, 55361, 56890, 256, 20813, 256, 20820, 256, 
-    20836, 256, 20855, 256, 55361, 56604, 256, 13497, 256, 20839, 256, 20877, 
-    256, 55361, 56651, 256, 20887, 256, 20900, 256, 20172, 256, 20908, 256, 
-    20917, 256, 55396, 56799, 256, 20981, 256, 20995, 256, 13535, 256, 21051, 
-    256, 21062, 256, 21106, 256, 21111, 256, 13589, 256, 21191, 256, 21193, 
-    256, 21220, 256, 21242, 256, 21253, 256, 21254, 256, 21271, 256, 21321, 
-    256, 21329, 256, 21338, 256, 21363, 256, 21373, 256, 21375, 256, 21375, 
-    256, 21375, 256, 55362, 56876, 256, 28784, 256, 21450, 256, 21471, 256, 
-    55362, 57187, 256, 21483, 256, 21489, 256, 21510, 256, 21662, 256, 21560, 
-    256, 21576, 256, 21608, 256, 21666, 256, 21750, 256, 21776, 256, 21843, 
-    256, 21859, 256, 21892, 256, 21892, 256, 21913, 256, 21931, 256, 21939, 
-    256, 21954, 256, 22294, 256, 22022, 256, 22295, 256, 22097, 256, 22132, 
-    256, 20999, 256, 22766, 256, 22478, 256, 22516, 256, 22541, 256, 22411, 
-    256, 22578, 256, 22577, 256, 22700, 256, 55365, 56548, 256, 22770, 256, 
-    22775, 256, 22790, 256, 22810, 256, 22818, 256, 22882, 256, 55365, 57000, 
-    256, 55365, 57066, 256, 23020, 256, 23067, 256, 23079, 256, 23000, 256, 
-    23142, 256, 14062, 256, 14076, 256, 23304, 256, 23358, 256, 23358, 256, 
-    55366, 56776, 256, 23491, 256, 23512, 256, 23527, 256, 23539, 256, 55366, 
-    57112, 256, 23551, 256, 23558, 256, 24403, 256, 23586, 256, 14209, 256, 
-    23648, 256, 23662, 256, 23744, 256, 23693, 256, 55367, 56804, 256, 23875, 
-    256, 55367, 56806, 256, 23918, 256, 23915, 256, 23932, 256, 24033, 256, 
-    24034, 256, 14383, 256, 24061, 256, 24104, 256, 24125, 256, 24169, 256, 
-    14434, 256, 55368, 56707, 256, 14460, 256, 24240, 256, 24243, 256, 24246, 
-    256, 24266, 256, 55400, 57234, 256, 24318, 256, 55368, 57137, 256, 55368, 
-    57137, 256, 33281, 256, 24354, 256, 24354, 256, 14535, 256, 55372, 57016, 
-    256, 55384, 56794, 256, 24418, 256, 24427, 256, 14563, 256, 24474, 256, 
-    24525, 256, 24535, 256, 24569, 256, 24705, 256, 14650, 256, 14620, 256, 
-    24724, 256, 55369, 57044, 256, 24775, 256, 24904, 256, 24908, 256, 24910, 
-    256, 24908, 256, 24954, 256, 24974, 256, 25010, 256, 24996, 256, 25007, 
-    256, 25054, 256, 25074, 256, 25078, 256, 25104, 256, 25115, 256, 25181, 
-    256, 25265, 256, 25300, 256, 25424, 256, 55370, 57100, 256, 25405, 256, 
-    25340, 256, 25448, 256, 25475, 256, 25572, 256, 55370, 57329, 256, 25634, 
-    256, 25541, 256, 25513, 256, 14894, 256, 25705, 256, 25726, 256, 25757, 
-    256, 25719, 256, 14956, 256, 25935, 256, 25964, 256, 55372, 56330, 256, 
-    26083, 256, 26360, 256, 26185, 256, 15129, 256, 26257, 256, 15112, 256, 
-    15076, 256, 20882, 256, 20885, 256, 26368, 256, 26268, 256, 32941, 256, 
-    17369, 256, 26391, 256, 26395, 256, 26401, 256, 26462, 256, 26451, 256, 
-    55372, 57283, 256, 15177, 256, 26618, 256, 26501, 256, 26706, 256, 26757, 
-    256, 55373, 56429, 256, 26766, 256, 26655, 256, 26900, 256, 15261, 256, 
-    26946, 256, 27043, 256, 27114, 256, 27304, 256, 55373, 56995, 256, 27355, 
-    256, 15384, 256, 27425, 256, 55374, 56487, 256, 27476, 256, 15438, 256, 
-    27506, 256, 27551, 256, 27578, 256, 27579, 256, 55374, 56973, 256, 55367, 
-    56587, 256, 55374, 57082, 256, 27726, 256, 55375, 56508, 256, 27839, 256, 
-    27853, 256, 27751, 256, 27926, 256, 27966, 256, 28023, 256, 27969, 256, 
-    28009, 256, 28024, 256, 28037, 256, 55375, 56606, 256, 27956, 256, 28207, 
-    256, 28270, 256, 15667, 256, 28363, 256, 28359, 256, 55375, 57041, 256, 
-    28153, 256, 28526, 256, 55375, 57182, 256, 55375, 57230, 256, 28614, 256, 
-    28729, 256, 28702, 256, 28699, 256, 15766, 256, 28746, 256, 28797, 256, 
-    28791, 256, 28845, 256, 55361, 56613, 256, 28997, 256, 55376, 56931, 256, 
-    29084, 256, 55376, 57259, 256, 29224, 256, 29237, 256, 29264, 256, 55377, 
-    56840, 256, 29312, 256, 29333, 256, 55377, 57141, 256, 55378, 56340, 256, 
-    29562, 256, 29579, 256, 16044, 256, 29605, 256, 16056, 256, 16056, 256, 
-    29767, 256, 29788, 256, 29809, 256, 29829, 256, 29898, 256, 16155, 256, 
-    29988, 256, 55379, 56374, 256, 30014, 256, 55379, 56466, 256, 30064, 256, 
-    55368, 56735, 256, 30224, 256, 55379, 57249, 256, 55379, 57272, 256, 
-    55380, 56388, 256, 16380, 256, 16392, 256, 30452, 256, 55380, 56563, 256, 
-    55380, 56562, 256, 55380, 56601, 256, 55380, 56627, 256, 30494, 256, 
-    30495, 256, 30495, 256, 30538, 256, 16441, 256, 30603, 256, 16454, 256, 
-    16534, 256, 55381, 56349, 256, 30798, 256, 30860, 256, 30924, 256, 16611, 
-    256, 55381, 56870, 256, 31062, 256, 55381, 56986, 256, 55381, 57029, 256, 
-    31119, 256, 31211, 256, 16687, 256, 31296, 256, 31306, 256, 31311, 256, 
-    55382, 56700, 256, 55382, 56999, 256, 55382, 56999, 256, 31470, 256, 
-    16898, 256, 55382, 57259, 256, 31686, 256, 31689, 256, 16935, 256, 55383, 
-    56448, 256, 31954, 256, 17056, 256, 31976, 256, 31971, 256, 32000, 256, 
-    55383, 57222, 256, 32099, 256, 17153, 256, 32199, 256, 32258, 256, 32325, 
-    256, 17204, 256, 55384, 56872, 256, 55384, 56903, 256, 17241, 256, 55384, 
-    57049, 256, 32634, 256, 55384, 57150, 256, 32661, 256, 32762, 256, 32773, 
-    256, 55385, 56538, 256, 55385, 56611, 256, 32864, 256, 55385, 56744, 256, 
-    32880, 256, 55372, 57183, 256, 17365, 256, 32946, 256, 33027, 256, 17419, 
-    256, 33086, 256, 23221, 256, 55385, 57255, 256, 55385, 57269, 256, 55372, 
-    57235, 256, 55372, 57244, 256, 33281, 256, 33284, 256, 36766, 256, 17515, 
-    256, 33425, 256, 33419, 256, 33437, 256, 21171, 256, 33457, 256, 33459, 
-    256, 33469, 256, 33510, 256, 55386, 57148, 256, 33509, 256, 33565, 256, 
-    33635, 256, 33709, 256, 33571, 256, 33725, 256, 33767, 256, 33879, 256, 
-    33619, 256, 33738, 256, 33740, 256, 33756, 256, 55387, 56374, 256, 55387, 
-    56683, 256, 55387, 56533, 256, 17707, 256, 34033, 256, 34035, 256, 34070, 
-    256, 55388, 57290, 256, 34148, 256, 55387, 57132, 256, 17757, 256, 17761, 
-    256, 55387, 57265, 256, 55388, 56530, 256, 17771, 256, 34384, 256, 34396, 
-    256, 34407, 256, 34409, 256, 34473, 256, 34440, 256, 34574, 256, 34530, 
-    256, 34681, 256, 34600, 256, 34667, 256, 34694, 256, 17879, 256, 34785, 
-    256, 34817, 256, 17913, 256, 34912, 256, 34915, 256, 55389, 56935, 256, 
-    35031, 256, 35038, 256, 17973, 256, 35066, 256, 13499, 256, 55390, 56494, 
-    256, 55390, 56678, 256, 18110, 256, 18119, 256, 35488, 256, 35565, 256, 
-    35722, 256, 35925, 256, 55391, 56488, 256, 36011, 256, 36033, 256, 36123, 
-    256, 36215, 256, 55391, 57135, 256, 55362, 56324, 256, 36299, 256, 36284, 
-    256, 36336, 256, 55362, 56542, 256, 36564, 256, 36664, 256, 55393, 56786, 
-    256, 55393, 56813, 256, 37012, 256, 37105, 256, 37137, 256, 55393, 57134, 
-    256, 37147, 256, 37432, 256, 37591, 256, 37592, 256, 37500, 256, 37881, 
-    256, 37909, 256, 55394, 57338, 256, 38283, 256, 18837, 256, 38327, 256, 
-    55395, 56695, 256, 18918, 256, 38595, 256, 23986, 256, 38691, 256, 55396, 
-    56645, 256, 55396, 56858, 256, 19054, 256, 19062, 256, 38880, 256, 55397, 
-    56330, 256, 19122, 256, 55397, 56470, 256, 38923, 256, 38923, 256, 38953, 
-    256, 55397, 56758, 256, 39138, 256, 19251, 256, 39209, 256, 39335, 256, 
-    39362, 256, 39422, 256, 19406, 256, 55398, 57136, 256, 39698, 256, 40000, 
-    256, 40189, 256, 19662, 256, 19693, 256, 40295, 256, 55400, 56526, 256, 
-    19704, 256, 55400, 56581, 256, 55400, 56846, 256, 55400, 56977, 256, 
-    40635, 256, 19798, 256, 40697, 256, 40702, 256, 40709, 256, 40719, 256, 
-    40726, 256, 40763, 256, 55401, 56832, 
-};
-
-/* index tables for the decomposition data */
-#define DECOMP_SHIFT1 6
-#define DECOMP_SHIFT2 4
-static const unsigned char decomp_index0[] = {
-    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 13, 14, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 16, 5, 5, 5, 5, 17, 18, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 19, 20, 
-    5, 5, 5, 5, 5, 21, 22, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    23, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-};
-
-static const unsigned short decomp_index1[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
-    14, 0, 0, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 
-    25, 0, 26, 27, 0, 0, 0, 0, 0, 28, 0, 0, 29, 30, 31, 32, 33, 34, 35, 0, 
-    36, 37, 38, 0, 39, 0, 40, 0, 41, 0, 0, 0, 0, 42, 43, 44, 45, 0, 0, 0, 0, 
-    0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 48, 0, 0, 0, 
-    0, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 52, 0, 53, 0, 0, 0, 0, 
-    0, 0, 54, 55, 0, 0, 0, 0, 0, 56, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 58, 59, 0, 0, 0, 60, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 
-    0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 
-    0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 67, 0, 68, 0, 0, 69, 0, 0, 0, 70, 
-    71, 72, 73, 74, 75, 76, 77, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 81, 0, 
-    82, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 84, 85, 86, 87, 88, 89, 0, 90, 91, 92, 0, 0, 0, 0, 
-    93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 
-    109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 
-    123, 124, 125, 126, 127, 128, 129, 130, 0, 131, 132, 133, 134, 0, 0, 0, 
-    0, 0, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 0, 
-    0, 0, 147, 0, 148, 149, 150, 0, 151, 152, 153, 0, 154, 0, 0, 0, 155, 0, 
-    0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 
-    158, 159, 160, 161, 162, 163, 164, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 0, 
-    0, 0, 0, 0, 0, 167, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    171, 0, 0, 0, 0, 0, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 
-    182, 183, 184, 185, 186, 0, 0, 187, 0, 0, 188, 189, 190, 191, 192, 0, 
-    193, 194, 195, 196, 197, 0, 198, 0, 0, 0, 199, 200, 201, 202, 203, 204, 
-    205, 0, 0, 0, 0, 0, 0, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 
-    216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 
-    230, 231, 232, 233, 234, 235, 236, 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 0, 0, 
-    0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 243, 244, 245, 246, 247, 
-    248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 
-    262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 0, 0, 272, 273, 274, 
-    275, 276, 277, 278, 279, 280, 281, 282, 283, 0, 284, 285, 286, 287, 288, 
-    289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 
-    303, 304, 305, 306, 0, 307, 308, 309, 310, 311, 312, 313, 314, 0, 0, 315, 
-    0, 316, 0, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 
-    329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 
-    343, 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 345, 346, 0, 0, 0, 0, 0, 0, 0, 
-    347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 351, 352, 0, 0, 0, 0, 353, 354, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 
-    365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 
-    379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 
-    393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 
-    407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 431, 432, 433, 434, 435, 0, 436, 0, 
-    0, 437, 0, 0, 0, 0, 0, 0, 438, 439, 440, 441, 442, 443, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 445, 
-    446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 
-    460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 
-    474, 475, 476, 477, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-};
-
-static const unsigned short decomp_index2[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
-    3, 0, 6, 0, 0, 0, 0, 8, 0, 0, 11, 13, 15, 18, 0, 0, 20, 23, 25, 0, 27, 
-    31, 35, 0, 39, 42, 45, 48, 51, 54, 0, 57, 60, 63, 66, 69, 72, 75, 78, 81, 
-    0, 84, 87, 90, 93, 96, 99, 0, 0, 102, 105, 108, 111, 114, 0, 0, 117, 120, 
-    123, 126, 129, 132, 0, 135, 138, 141, 144, 147, 150, 153, 156, 159, 0, 
-    162, 165, 168, 171, 174, 177, 0, 0, 180, 183, 186, 189, 192, 0, 195, 198, 
-    201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, 
-    243, 0, 0, 246, 249, 252, 255, 258, 261, 264, 267, 270, 273, 276, 279, 
-    282, 285, 288, 291, 294, 297, 300, 303, 0, 0, 306, 309, 312, 315, 318, 
-    321, 324, 327, 330, 0, 333, 336, 339, 342, 345, 348, 0, 351, 354, 357, 
-    360, 363, 366, 369, 372, 0, 0, 375, 378, 381, 384, 387, 390, 393, 0, 0, 
-    396, 399, 402, 405, 408, 411, 0, 0, 414, 417, 420, 423, 426, 429, 432, 
-    435, 438, 441, 444, 447, 450, 453, 456, 459, 462, 465, 0, 0, 468, 471, 
-    474, 477, 480, 483, 486, 489, 492, 495, 498, 501, 504, 507, 510, 513, 
-    516, 519, 522, 525, 528, 531, 534, 537, 539, 542, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 545, 548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 551, 554, 557, 560, 563, 566, 569, 572, 575, 578, 581, 584, 587, 
-    590, 593, 596, 599, 602, 605, 608, 611, 614, 617, 620, 623, 0, 626, 629, 
-    632, 635, 638, 641, 0, 0, 644, 647, 650, 653, 656, 659, 662, 665, 668, 
-    671, 674, 677, 680, 683, 686, 689, 0, 0, 692, 695, 698, 701, 704, 707, 
-    710, 713, 716, 719, 722, 725, 728, 731, 734, 737, 740, 743, 746, 749, 
-    752, 755, 758, 761, 764, 767, 770, 773, 776, 779, 782, 785, 788, 791, 
-    794, 797, 0, 0, 800, 803, 0, 0, 0, 0, 0, 0, 806, 809, 812, 815, 818, 821, 
-    824, 827, 830, 833, 836, 839, 842, 845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 848, 850, 852, 854, 856, 858, 860, 862, 864, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 866, 869, 872, 875, 878, 881, 0, 0, 884, 886, 888, 
-    890, 892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 894, 896, 0, 898, 900, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 903, 0, 0, 0, 0, 0, 905, 0, 0, 0, 
-    908, 0, 0, 0, 0, 0, 910, 913, 916, 919, 921, 924, 927, 0, 930, 0, 933, 
-    936, 939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 942, 945, 948, 951, 954, 957, 960, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 963, 966, 969, 972, 975, 
-    0, 978, 980, 982, 984, 987, 990, 992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 994, 
-    996, 998, 0, 1000, 1002, 0, 0, 0, 1004, 0, 0, 0, 0, 0, 0, 1006, 1009, 0, 
-    1012, 0, 0, 0, 1015, 0, 0, 0, 0, 1018, 1021, 1024, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 1027, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1030, 0, 0, 
-    0, 0, 0, 0, 1033, 1036, 0, 1039, 0, 0, 0, 1042, 0, 0, 0, 0, 1045, 1048, 
-    1051, 0, 0, 0, 0, 0, 0, 0, 1054, 1057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1060, 
-    1063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1066, 1069, 1072, 1075, 0, 
-    0, 1078, 1081, 0, 0, 1084, 1087, 1090, 1093, 1096, 1099, 0, 0, 1102, 
-    1105, 1108, 1111, 1114, 1117, 0, 0, 1120, 1123, 1126, 1129, 1132, 1135, 
-    1138, 1141, 1144, 1147, 1150, 1153, 0, 0, 1156, 1159, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 1162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1165, 1168, 
-    1171, 1174, 1177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1180, 1183, 
-    1186, 1189, 0, 0, 0, 0, 0, 0, 0, 1192, 0, 1195, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 1198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 1201, 0, 0, 0, 0, 0, 0, 0, 1204, 0, 0, 1207, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1210, 1213, 1216, 
-    1219, 1222, 1225, 1228, 1231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1234, 
-    1237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1240, 1243, 0, 1246, 
-    0, 0, 0, 1249, 0, 0, 1252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 1255, 1258, 1261, 0, 0, 1264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1267, 
-    0, 0, 1270, 1273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1276, 
-    1279, 0, 0, 0, 0, 0, 0, 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 1285, 1288, 1291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    1294, 0, 0, 0, 0, 0, 0, 0, 1297, 0, 0, 0, 0, 0, 0, 1300, 1303, 0, 1306, 
-    1309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1312, 1315, 1318, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1321, 0, 1324, 1327, 1330, 0, 0, 0, 0, 
-    1333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1336, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1339, 1342, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1345, 0, 0, 0, 0, 0, 0, 1347, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 1350, 0, 0, 0, 0, 1353, 0, 0, 0, 0, 1356, 0, 0, 
-    0, 0, 1359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1362, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 1365, 0, 1368, 1371, 1374, 1377, 1380, 0, 0, 0, 0, 0, 0, 0, 
-    1383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1386, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 1389, 0, 0, 0, 0, 1392, 0, 0, 0, 0, 1395, 0, 0, 0, 0, 
-    1398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1401, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 1404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 1407, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1409, 0, 1412, 0, 1415, 0, 
-    1418, 0, 1421, 0, 0, 0, 1424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1427, 0, 1430, 0, 0, 1433, 1436, 0, 1439, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    1442, 1444, 1446, 0, 1448, 1450, 1452, 1454, 1456, 1458, 1460, 1462, 
-    1464, 1466, 1468, 0, 1470, 1472, 1474, 1476, 1478, 1480, 1482, 1484, 
-    1486, 1488, 1490, 1492, 1494, 1496, 1498, 1500, 1502, 1504, 0, 1506, 
-    1508, 1510, 1512, 1514, 1516, 1518, 1520, 1522, 1524, 1526, 1528, 1530, 
-    1532, 1534, 1536, 1538, 1540, 1542, 1544, 1546, 1548, 1550, 1552, 1554, 
-    1556, 1558, 1560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1562, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1564, 1566, 1568, 1570, 
-    1572, 1574, 1576, 1578, 1580, 1582, 1584, 1586, 1588, 1590, 1592, 1594, 
-    1596, 1598, 1600, 1602, 1604, 1606, 1608, 1610, 1612, 1614, 1616, 1618, 
-    1620, 1622, 1624, 1626, 1628, 1630, 1632, 1634, 1636, 1638, 1641, 1644, 
-    1647, 1650, 1653, 1656, 1659, 1662, 1665, 1668, 1671, 1674, 1677, 1680, 
-    1683, 1686, 1689, 1692, 1695, 1698, 1701, 1704, 1707, 1710, 1713, 1716, 
-    1719, 1722, 1725, 1728, 1731, 1734, 1737, 1740, 1743, 1746, 1749, 1752, 
-    1755, 1758, 1761, 1764, 1767, 1770, 1773, 1776, 1779, 1782, 1785, 1788, 
-    1791, 1794, 1797, 1800, 1803, 1806, 1809, 1812, 1815, 1818, 1821, 1824, 
-    1827, 1830, 1833, 1836, 1839, 1842, 1845, 1848, 1851, 1854, 1857, 1860, 
-    1863, 1866, 1869, 1872, 1875, 1878, 1881, 1884, 1887, 1890, 1893, 1896, 
-    1899, 1902, 1905, 1908, 1911, 1914, 1917, 1920, 1923, 1926, 1929, 1932, 
-    1935, 1938, 1941, 1944, 1947, 1950, 1953, 1956, 1959, 1962, 1965, 1968, 
-    1971, 1974, 1977, 1980, 1983, 1986, 1989, 1992, 1995, 1998, 2001, 2004, 
-    2007, 2010, 2013, 2016, 2019, 2022, 2025, 2028, 2031, 2034, 2037, 2040, 
-    2043, 2046, 2049, 2052, 2055, 2058, 2061, 2064, 2067, 2070, 2073, 2076, 
-    2079, 2082, 2085, 2088, 2091, 2094, 2097, 2100, 2103, 0, 0, 0, 0, 2106, 
-    2109, 2112, 2115, 2118, 2121, 2124, 2127, 2130, 2133, 2136, 2139, 2142, 
-    2145, 2148, 2151, 2154, 2157, 2160, 2163, 2166, 2169, 2172, 2175, 2178, 
-    2181, 2184, 2187, 2190, 2193, 2196, 2199, 2202, 2205, 2208, 2211, 2214, 
-    2217, 2220, 2223, 2226, 2229, 2232, 2235, 2238, 2241, 2244, 2247, 2250, 
-    2253, 2256, 2259, 2262, 2265, 2268, 2271, 2274, 2277, 2280, 2283, 2286, 
-    2289, 2292, 2295, 2298, 2301, 2304, 2307, 2310, 2313, 2316, 2319, 2322, 
-    2325, 2328, 2331, 2334, 2337, 2340, 2343, 2346, 2349, 2352, 2355, 2358, 
-    2361, 2364, 2367, 2370, 2373, 0, 0, 0, 0, 0, 0, 2376, 2379, 2382, 2385, 
-    2388, 2391, 2394, 2397, 2400, 2403, 2406, 2409, 2412, 2415, 2418, 2421, 
-    2424, 2427, 2430, 2433, 2436, 2439, 0, 0, 2442, 2445, 2448, 2451, 2454, 
-    2457, 0, 0, 2460, 2463, 2466, 2469, 2472, 2475, 2478, 2481, 2484, 2487, 
-    2490, 2493, 2496, 2499, 2502, 2505, 2508, 2511, 2514, 2517, 2520, 2523, 
-    2526, 2529, 2532, 2535, 2538, 2541, 2544, 2547, 2550, 2553, 2556, 2559, 
-    2562, 2565, 2568, 2571, 0, 0, 2574, 2577, 2580, 2583, 2586, 2589, 0, 0, 
-    2592, 2595, 2598, 2601, 2604, 2607, 2610, 2613, 0, 2616, 0, 2619, 0, 
-    2622, 0, 2625, 2628, 2631, 2634, 2637, 2640, 2643, 2646, 2649, 2652, 
-    2655, 2658, 2661, 2664, 2667, 2670, 2673, 2676, 2679, 2681, 2684, 2686, 
-    2689, 2691, 2694, 2696, 2699, 2701, 2704, 2706, 2709, 0, 0, 2711, 2714, 
-    2717, 2720, 2723, 2726, 2729, 2732, 2735, 2738, 2741, 2744, 2747, 2750, 
-    2753, 2756, 2759, 2762, 2765, 2768, 2771, 2774, 2777, 2780, 2783, 2786, 
-    2789, 2792, 2795, 2798, 2801, 2804, 2807, 2810, 2813, 2816, 2819, 2822, 
-    2825, 2828, 2831, 2834, 2837, 2840, 2843, 2846, 2849, 2852, 2855, 2858, 
-    2861, 2864, 2867, 0, 2870, 2873, 2876, 2879, 2882, 2885, 2887, 2890, 
-    2893, 2895, 2898, 2901, 2904, 2907, 2910, 0, 2913, 2916, 2919, 2922, 
-    2924, 2927, 2929, 2932, 2935, 2938, 2941, 2944, 2947, 2950, 0, 0, 2952, 
-    2955, 2958, 2961, 2964, 2967, 0, 2969, 2972, 2975, 2978, 2981, 2984, 
-    2987, 2989, 2992, 2995, 2998, 3001, 3004, 3007, 3010, 3012, 3015, 3018, 
-    3020, 0, 0, 3022, 3025, 3028, 0, 3031, 3034, 3037, 3040, 3042, 3045, 
-    3047, 3050, 3052, 0, 3055, 3057, 3059, 3061, 3063, 3065, 3067, 3069, 
-    3071, 3073, 3075, 0, 0, 0, 0, 0, 0, 3077, 0, 0, 0, 0, 0, 3079, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 3082, 3084, 3087, 0, 0, 0, 0, 0, 0, 0, 0, 
-    3091, 0, 0, 0, 3093, 3096, 0, 3100, 3103, 0, 0, 0, 0, 3107, 0, 3110, 0, 
-    0, 0, 0, 0, 0, 0, 0, 3113, 3116, 3119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 3122, 0, 0, 0, 0, 0, 0, 0, 3127, 3129, 3131, 0, 0, 3133, 3135, 
-    3137, 3139, 3141, 3143, 3145, 3147, 3149, 3151, 3153, 3155, 3157, 3159, 
-    3161, 3163, 3165, 3167, 3169, 3171, 3173, 3175, 3177, 3179, 3181, 3183, 
-    3185, 0, 3187, 3189, 3191, 3193, 3195, 3197, 3199, 3201, 3203, 3205, 
-    3207, 3209, 3211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3213, 0, 0, 0, 0, 0, 
-    0, 0, 3216, 3220, 3224, 3226, 0, 3229, 3233, 3237, 0, 3239, 3242, 3244, 
-    3246, 3248, 3250, 3252, 3254, 3256, 3258, 3260, 0, 3262, 3264, 0, 0, 
-    3267, 3269, 3271, 3273, 3275, 0, 0, 3277, 3280, 3284, 0, 3287, 0, 3289, 
-    0, 3291, 0, 3293, 3295, 3297, 3299, 0, 3301, 3303, 3305, 0, 3307, 3309, 
-    3311, 3313, 3315, 3317, 3319, 0, 3321, 3325, 3327, 3329, 3331, 3333, 0, 
-    0, 0, 0, 3335, 3337, 3339, 3341, 3343, 0, 0, 0, 0, 0, 0, 3345, 3349, 
-    3353, 3358, 3362, 3366, 3370, 3374, 3378, 3382, 3386, 3390, 3394, 3398, 
-    3402, 3406, 3409, 3411, 3414, 3418, 3421, 3423, 3426, 3430, 3435, 3438, 
-    3440, 3443, 3447, 3449, 3451, 3453, 3455, 3457, 3460, 3464, 3467, 3469, 
-    3472, 3476, 3481, 3484, 3486, 3489, 3493, 3495, 3497, 3499, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 3501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    3505, 3508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3511, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3514, 3517, 3520, 0, 0, 0, 0, 
-    3523, 0, 0, 0, 0, 3526, 0, 0, 3529, 0, 0, 0, 0, 0, 0, 0, 3532, 0, 3535, 
-    0, 0, 0, 0, 0, 3538, 3541, 0, 3545, 3548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 3552, 0, 0, 3555, 0, 0, 3558, 0, 3561, 0, 0, 0, 0, 0, 
-    0, 3564, 0, 3567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3570, 3573, 3576, 3579, 
-    3582, 0, 0, 3585, 3588, 0, 0, 3591, 3594, 0, 0, 0, 0, 0, 0, 3597, 3600, 
-    0, 0, 3603, 3606, 0, 0, 3609, 3612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 3615, 3618, 3621, 3624, 3627, 3630, 3633, 3636, 0, 0, 
-    0, 0, 0, 0, 3639, 3642, 3645, 3648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    3651, 3653, 0, 0, 0, 0, 0, 3655, 3657, 3659, 3661, 3663, 3665, 3667, 
-    3669, 3671, 3673, 3676, 3679, 3682, 3685, 3688, 3691, 3694, 3697, 3700, 
-    3703, 3706, 3710, 3714, 3718, 3722, 3726, 3730, 3734, 3738, 3742, 3747, 
-    3752, 3757, 3762, 3767, 3772, 3777, 3782, 3787, 3792, 3797, 3800, 3803, 
-    3806, 3809, 3812, 3815, 3818, 3821, 3824, 3828, 3832, 3836, 3840, 3844, 
-    3848, 3852, 3856, 3860, 3864, 3868, 3872, 3876, 3880, 3884, 3888, 3892, 
-    3896, 3900, 3904, 3908, 3912, 3916, 3920, 3924, 3928, 3932, 3936, 3940, 
-    3944, 3948, 3952, 3956, 3960, 3964, 3968, 3972, 3974, 3976, 3978, 3980, 
-    3982, 3984, 3986, 3988, 3990, 3992, 3994, 3996, 3998, 4000, 4002, 4004, 
-    4006, 4008, 4010, 4012, 4014, 4016, 4018, 4020, 4022, 4024, 4026, 4028, 
-    4030, 4032, 4034, 4036, 4038, 4040, 4042, 4044, 4046, 4048, 4050, 4052, 
-    4054, 4056, 4058, 4060, 4062, 4064, 4066, 4068, 4070, 4072, 4074, 4076, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4078, 0, 0, 0, 0, 0, 
-    0, 0, 4083, 4087, 4090, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 4094, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4097, 
-    4099, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4101, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4103, 0, 0, 0, 4105, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 4107, 4109, 4111, 4113, 4115, 4117, 4119, 4121, 
-    4123, 4125, 4127, 4129, 4131, 4133, 4135, 4137, 4139, 4141, 4143, 4145, 
-    4147, 4149, 4151, 4153, 4155, 4157, 4159, 4161, 4163, 4165, 4167, 4169, 
-    4171, 4173, 4175, 4177, 4179, 4181, 4183, 4185, 4187, 4189, 4191, 4193, 
-    4195, 4197, 4199, 4201, 4203, 4205, 4207, 4209, 4211, 4213, 4215, 4217, 
-    4219, 4221, 4223, 4225, 4227, 4229, 4231, 4233, 4235, 4237, 4239, 4241, 
-    4243, 4245, 4247, 4249, 4251, 4253, 4255, 4257, 4259, 4261, 4263, 4265, 
-    4267, 4269, 4271, 4273, 4275, 4277, 4279, 4281, 4283, 4285, 4287, 4289, 
-    4291, 4293, 4295, 4297, 4299, 4301, 4303, 4305, 4307, 4309, 4311, 4313, 
-    4315, 4317, 4319, 4321, 4323, 4325, 4327, 4329, 4331, 4333, 4335, 4337, 
-    4339, 4341, 4343, 4345, 4347, 4349, 4351, 4353, 4355, 4357, 4359, 4361, 
-    4363, 4365, 4367, 4369, 4371, 4373, 4375, 4377, 4379, 4381, 4383, 4385, 
-    4387, 4389, 4391, 4393, 4395, 4397, 4399, 4401, 4403, 4405, 4407, 4409, 
-    4411, 4413, 4415, 4417, 4419, 4421, 4423, 4425, 4427, 4429, 4431, 4433, 
-    4435, 4437, 4439, 4441, 4443, 4445, 4447, 4449, 4451, 4453, 4455, 4457, 
-    4459, 4461, 4463, 4465, 4467, 4469, 4471, 4473, 4475, 4477, 4479, 4481, 
-    4483, 4485, 4487, 4489, 4491, 4493, 4495, 4497, 4499, 4501, 4503, 4505, 
-    4507, 4509, 4511, 4513, 4515, 4517, 4519, 4521, 4523, 4525, 4527, 4529, 
-    4531, 4533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4535, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4537, 0, 4539, 4541, 4543, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4545, 0, 4548, 0, 4551, 0, 
-    4554, 0, 4557, 0, 4560, 0, 4563, 0, 4566, 0, 4569, 0, 4572, 0, 4575, 0, 
-    4578, 0, 0, 4581, 0, 4584, 0, 4587, 0, 0, 0, 0, 0, 0, 4590, 4593, 0, 
-    4596, 4599, 0, 4602, 4605, 0, 4608, 4611, 0, 4614, 4617, 0, 0, 0, 0, 0, 
-    0, 4620, 0, 0, 0, 0, 0, 0, 4623, 4626, 0, 4629, 4632, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 4635, 0, 4638, 0, 4641, 0, 4644, 0, 4647, 0, 4650, 0, 
-    4653, 0, 4656, 0, 4659, 0, 4662, 0, 4665, 0, 4668, 0, 0, 4671, 0, 4674, 
-    0, 4677, 0, 0, 0, 0, 0, 0, 4680, 4683, 0, 4686, 4689, 0, 4692, 4695, 0, 
-    4698, 4701, 0, 4704, 4707, 0, 0, 0, 0, 0, 0, 4710, 0, 0, 4713, 4716, 
-    4719, 4722, 0, 0, 0, 4725, 4728, 0, 4731, 4733, 4735, 4737, 4739, 4741, 
-    4743, 4745, 4747, 4749, 4751, 4753, 4755, 4757, 4759, 4761, 4763, 4765, 
-    4767, 4769, 4771, 4773, 4775, 4777, 4779, 4781, 4783, 4785, 4787, 4789, 
-    4791, 4793, 4795, 4797, 4799, 4801, 4803, 4805, 4807, 4809, 4811, 4813, 
-    4815, 4817, 4819, 4821, 4823, 4825, 4827, 4829, 4831, 4833, 4835, 4837, 
-    4839, 4841, 4843, 4845, 4847, 4849, 4851, 4853, 4855, 4857, 4859, 4861, 
-    4863, 4865, 4867, 4869, 4871, 4873, 4875, 4877, 4879, 4881, 4883, 4885, 
-    4887, 4889, 4891, 4893, 4895, 4897, 4899, 4901, 4903, 4905, 4907, 4909, 
-    4911, 4913, 4915, 4917, 0, 0, 0, 4919, 4921, 4923, 4925, 4927, 4929, 
-    4931, 4933, 4935, 4937, 4939, 4941, 4943, 4945, 4947, 4951, 4955, 4959, 
-    4963, 4967, 4971, 4975, 4979, 4983, 4987, 4991, 4995, 4999, 5003, 5008, 
-    5013, 5018, 5023, 5028, 5033, 5038, 5043, 5048, 5053, 5058, 5063, 5068, 
-    5073, 5078, 5086, 0, 5093, 5097, 5101, 5105, 5109, 5113, 5117, 5121, 
-    5125, 5129, 5133, 5137, 5141, 5145, 5149, 5153, 5157, 5161, 5165, 5169, 
-    5173, 5177, 5181, 5185, 5189, 5193, 5197, 5201, 5205, 5209, 5213, 5217, 
-    5221, 5225, 5229, 5233, 5237, 5239, 5241, 5243, 0, 0, 0, 0, 0, 0, 0, 0, 
-    5245, 5249, 5252, 5255, 5258, 5261, 5264, 5267, 5270, 5273, 5276, 5279, 
-    5282, 5285, 5288, 5291, 5294, 5296, 5298, 5300, 5302, 5304, 5306, 5308, 
-    5310, 5312, 5314, 5316, 5318, 5320, 5322, 5325, 5328, 5331, 5334, 5337, 
-    5340, 5343, 5346, 5349, 5352, 5355, 5358, 5361, 5364, 5370, 5375, 0, 
-    5378, 5380, 5382, 5384, 5386, 5388, 5390, 5392, 5394, 5396, 5398, 5400, 
-    5402, 5404, 5406, 5408, 5410, 5412, 5414, 5416, 5418, 5420, 5422, 5424, 
-    5426, 5428, 5430, 5432, 5434, 5436, 5438, 5440, 5442, 5444, 5446, 5448, 
-    5450, 5452, 5454, 5456, 5458, 5460, 5462, 5464, 5466, 5468, 5470, 5472, 
-    5474, 5476, 5479, 5482, 5485, 5488, 5491, 5494, 5497, 5500, 5503, 5506, 
-    5509, 5512, 5515, 5518, 5521, 5524, 5527, 5530, 5533, 5536, 5539, 5542, 
-    5545, 5548, 5552, 5556, 5560, 5563, 5567, 5570, 5574, 5576, 5578, 5580, 
-    5582, 5584, 5586, 5588, 5590, 5592, 5594, 5596, 5598, 5600, 5602, 5604, 
-    5606, 5608, 5610, 5612, 5614, 5616, 5618, 5620, 5622, 5624, 5626, 5628, 
-    5630, 5632, 5634, 5636, 5638, 5640, 5642, 5644, 5646, 5648, 5650, 5652, 
-    5654, 5656, 5658, 5660, 5662, 5664, 5666, 0, 5668, 5673, 5678, 5683, 
-    5687, 5692, 5696, 5700, 5706, 5711, 5715, 5719, 5723, 5728, 5733, 5737, 
-    5741, 5744, 5748, 5753, 5758, 5761, 5767, 5774, 5780, 5784, 5790, 5796, 
-    5801, 5805, 5809, 5813, 5818, 5824, 5829, 5833, 5837, 5841, 5844, 5847, 
-    5850, 5853, 5857, 5861, 5867, 5871, 5876, 5882, 5886, 5889, 5892, 5898, 
-    5903, 5909, 5913, 5919, 5922, 5926, 5930, 5934, 5938, 5942, 5947, 5951, 
-    5954, 5958, 5962, 5966, 5971, 5975, 5979, 5983, 5989, 5994, 5997, 6003, 
-    6006, 6011, 6016, 6020, 6024, 6028, 6033, 6036, 6040, 6045, 6048, 6054, 
-    6058, 6061, 6064, 6067, 6070, 6073, 6076, 6079, 6082, 6085, 6088, 6092, 
-    6096, 6100, 6104, 6108, 6112, 6116, 6120, 6124, 6128, 6132, 6136, 6140, 
-    6144, 6148, 6152, 6155, 6158, 6162, 6165, 6168, 6171, 6175, 6179, 6182, 
-    6185, 6188, 6191, 6194, 6199, 6202, 6205, 6208, 6211, 6214, 6217, 6220, 
-    6223, 6227, 6232, 6235, 6238, 6241, 6244, 6247, 6250, 6253, 6257, 6261, 
-    6265, 6269, 6272, 6275, 6278, 6281, 6284, 6287, 6290, 6293, 6296, 6299, 
-    6303, 6307, 6310, 6314, 6318, 6322, 6325, 6329, 6333, 6338, 6341, 6345, 
-    6349, 6353, 6357, 6363, 6370, 6373, 6376, 6379, 6382, 6385, 6388, 6391, 
-    6394, 6397, 6400, 6403, 6406, 6409, 6412, 6415, 6418, 6421, 6424, 6429, 
-    6432, 6435, 6438, 6443, 6447, 6450, 6453, 6456, 6459, 6462, 6465, 6468, 
-    6471, 6474, 6477, 6481, 6484, 6487, 6491, 6495, 6498, 6503, 6507, 6510, 
-    6513, 6516, 6519, 6523, 6527, 6530, 6533, 6536, 6539, 6542, 6545, 6548, 
-    6551, 6554, 6558, 6562, 6566, 6570, 6574, 6578, 6582, 6586, 6590, 6594, 
-    6598, 6602, 6606, 6610, 6614, 6618, 6622, 6626, 6630, 6634, 6638, 6642, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6646, 6648, 0, 0, 6650, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6652, 6654, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6656, 6658, 6660, 
-    6662, 6664, 6666, 6668, 6670, 6672, 6674, 6676, 6678, 6680, 6682, 6684, 
-    6686, 6688, 6690, 6692, 6694, 6696, 6698, 6700, 6702, 6704, 6706, 6708, 
-    6710, 6712, 6714, 6716, 6718, 6720, 6722, 6724, 6726, 6728, 6730, 6732, 
-    6734, 6736, 6738, 6740, 6742, 6744, 6746, 6748, 6750, 6752, 6754, 6756, 
-    6758, 6760, 6762, 6764, 6766, 6768, 6770, 6772, 6774, 6776, 6778, 6780, 
-    6782, 6784, 6786, 6788, 6790, 6792, 6794, 6796, 6798, 6800, 6802, 6804, 
-    6806, 6808, 6810, 6812, 6814, 6816, 6818, 6820, 6822, 6824, 6826, 6828, 
-    6830, 6832, 6834, 6836, 6838, 6840, 6842, 6844, 6846, 6848, 6850, 6852, 
-    6854, 6856, 6858, 6860, 6862, 6864, 6866, 6868, 6870, 6872, 6874, 6876, 
-    6878, 6880, 6882, 6884, 6886, 6888, 6890, 6892, 6894, 6896, 6898, 6900, 
-    6902, 6904, 6906, 6908, 6910, 6912, 6914, 6916, 6918, 6920, 6922, 6924, 
-    6926, 6928, 6930, 6932, 6934, 6936, 6938, 6940, 6942, 6944, 6946, 6948, 
-    6950, 6952, 6954, 6956, 6958, 6960, 6962, 6964, 6966, 6968, 6970, 6972, 
-    6974, 6976, 6978, 6980, 6982, 6984, 6986, 6988, 6990, 6992, 6994, 6996, 
-    6998, 7000, 7002, 7004, 7006, 7008, 7010, 7012, 7014, 7016, 7018, 7020, 
-    7022, 7024, 7026, 7028, 7030, 7032, 7034, 7036, 7038, 7040, 7042, 7044, 
-    7046, 7048, 7050, 7052, 7054, 7056, 7058, 7060, 7062, 7064, 7066, 7068, 
-    7070, 7072, 7074, 7076, 7078, 7080, 7082, 7084, 7086, 7088, 7090, 7092, 
-    7094, 7096, 7098, 7100, 7102, 7104, 7106, 7108, 7110, 7112, 7114, 7116, 
-    7118, 7120, 7122, 7124, 7126, 7128, 7130, 7132, 7134, 7136, 7138, 7140, 
-    7142, 7144, 7146, 7148, 7150, 7152, 7154, 7156, 7158, 7160, 7162, 7164, 
-    7166, 7168, 7170, 7172, 7174, 7176, 7178, 7180, 7182, 7184, 7186, 7188, 
-    7190, 7192, 7194, 7196, 7198, 7200, 7202, 0, 0, 7204, 0, 7206, 0, 0, 
-    7208, 7210, 7212, 7214, 7216, 7218, 7220, 7222, 7224, 7226, 0, 7228, 0, 
-    7230, 0, 0, 7232, 7234, 0, 0, 0, 7236, 7238, 7240, 7242, 7244, 7246, 
-    7248, 7250, 7252, 7254, 7256, 7258, 7260, 7262, 7264, 7266, 7268, 7270, 
-    7272, 7274, 7276, 7278, 7280, 7282, 7284, 7286, 7288, 7290, 7292, 7294, 
-    7296, 7298, 7300, 7302, 7304, 7306, 7308, 7310, 7312, 7314, 7316, 7318, 
-    7320, 7322, 7324, 7326, 7328, 7330, 7332, 7334, 7336, 7338, 7340, 7342, 
-    7344, 7346, 7348, 7350, 7352, 7354, 7356, 7358, 7360, 7362, 7364, 7366, 
-    7368, 7371, 0, 0, 7373, 7375, 7377, 7379, 7381, 7383, 7385, 7387, 7389, 
-    7391, 7393, 7395, 7397, 7399, 7401, 7403, 7405, 7407, 7409, 7411, 7413, 
-    7415, 7417, 7419, 7421, 7423, 7425, 7427, 7429, 7431, 7433, 7435, 7437, 
-    7439, 7441, 7443, 7445, 7447, 7449, 7451, 7453, 7455, 7457, 7459, 7461, 
-    7463, 7465, 7467, 7469, 7471, 7473, 7475, 7477, 7479, 7481, 7483, 7485, 
-    7487, 7489, 7491, 7493, 7495, 7497, 7499, 7501, 7503, 7505, 7507, 7509, 
-    7511, 7513, 7515, 7517, 7519, 7521, 7523, 7525, 7527, 7529, 7531, 7533, 
-    7535, 7537, 7539, 7541, 7543, 7545, 7547, 7549, 7551, 7553, 7555, 7557, 
-    7559, 7561, 7563, 7566, 7569, 7572, 7574, 7576, 7578, 7581, 7584, 7587, 
-    7589, 0, 0, 0, 0, 0, 0, 7591, 7594, 7597, 7600, 7604, 7608, 7611, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7614, 7617, 7620, 7623, 7626, 0, 0, 0, 0, 
-    0, 7629, 0, 7632, 7635, 7637, 7639, 7641, 7643, 7645, 7647, 7649, 7651, 
-    7653, 7655, 7658, 7661, 7664, 7667, 7670, 7673, 7676, 7679, 7682, 7685, 
-    7688, 7691, 0, 7694, 7697, 7700, 7703, 7706, 0, 7709, 0, 7712, 7715, 0, 
-    7718, 7721, 0, 7724, 7727, 7730, 7733, 7736, 7739, 7742, 7745, 7748, 
-    7751, 7754, 7756, 7758, 7760, 7762, 7764, 7766, 7768, 7770, 7772, 7774, 
-    7776, 7778, 7780, 7782, 7784, 7786, 7788, 7790, 7792, 7794, 7796, 7798, 
-    7800, 7802, 7804, 7806, 7808, 7810, 7812, 7814, 7816, 7818, 7820, 7822, 
-    7824, 7826, 7828, 7830, 7832, 7834, 7836, 7838, 7840, 7842, 7844, 7846, 
-    7848, 7850, 7852, 7854, 7856, 7858, 7860, 7862, 7864, 7866, 7868, 7870, 
-    7872, 7874, 7876, 7878, 7880, 7882, 7884, 7886, 7888, 7890, 7892, 7894, 
-    7896, 7898, 7900, 7902, 7904, 7906, 7908, 7910, 7912, 7914, 7916, 7918, 
-    7920, 7922, 7924, 7926, 7928, 7930, 7932, 7934, 7936, 7938, 7940, 7942, 
-    7944, 7946, 7948, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    7950, 7952, 7954, 7956, 7958, 7960, 7962, 7964, 7966, 7968, 7970, 7972, 
-    7974, 7976, 7978, 7980, 7982, 7984, 7986, 7988, 7990, 7992, 7994, 7996, 
-    7999, 8002, 8005, 8008, 8011, 8014, 8017, 8020, 8023, 8026, 8029, 8032, 
-    8035, 8038, 8041, 8044, 8047, 8050, 8052, 8054, 8056, 8058, 8061, 8064, 
-    8067, 8070, 8073, 8076, 8079, 8082, 8085, 8088, 8091, 8094, 8097, 8100, 
-    8103, 8106, 8109, 8112, 8115, 8118, 8121, 8124, 8127, 8130, 8133, 8136, 
-    8139, 8142, 8145, 8148, 8151, 8154, 8157, 8160, 8163, 8166, 8169, 8172, 
-    8175, 8178, 8181, 8184, 8187, 8190, 8193, 8196, 8199, 8202, 8205, 8208, 
-    8211, 8214, 8217, 8220, 8223, 8226, 8229, 8232, 8235, 8238, 8241, 8244, 
-    8247, 8250, 8253, 8256, 8259, 8262, 8265, 8268, 8271, 8274, 8277, 8280, 
-    8283, 8286, 8289, 8292, 8295, 8298, 8301, 8304, 8307, 8310, 8313, 8316, 
-    8319, 8322, 8325, 8328, 8331, 8334, 8337, 8340, 8344, 8348, 8352, 8356, 
-    8360, 8364, 8367, 8370, 8373, 8376, 8379, 8382, 8385, 8388, 8391, 8394, 
-    8397, 8400, 8403, 8406, 8409, 8412, 8415, 8418, 8421, 8424, 8427, 8430, 
-    8433, 8436, 8439, 8442, 8445, 8448, 8451, 8454, 8457, 8460, 8463, 8466, 
-    8469, 8472, 8475, 8478, 8481, 8484, 8487, 8490, 8493, 8496, 8499, 8502, 
-    8505, 8508, 8511, 8514, 8517, 8520, 8523, 8526, 8529, 8532, 8535, 8538, 
-    8541, 8544, 8547, 8550, 8553, 8556, 8559, 8562, 8565, 8568, 8571, 8574, 
-    8577, 8580, 8583, 8586, 8589, 8592, 8595, 8598, 8601, 8604, 8607, 8610, 
-    8613, 8616, 8619, 8622, 8625, 8628, 8631, 8634, 8637, 8640, 8643, 8646, 
-    8649, 8652, 8655, 8658, 8661, 8664, 8667, 8670, 8673, 8676, 8679, 8682, 
-    8685, 8688, 8691, 8694, 8697, 8700, 8703, 8706, 8709, 8712, 8715, 8718, 
-    8721, 8724, 8727, 8730, 8733, 8736, 8739, 8742, 8745, 8748, 8751, 8754, 
-    8757, 8760, 8763, 8766, 8769, 8772, 8775, 8778, 8781, 8784, 8787, 8790, 
-    8794, 8798, 8802, 8805, 8808, 8811, 8814, 8817, 8820, 8823, 8826, 8829, 
-    8832, 8835, 8838, 8841, 8844, 8847, 8850, 8853, 8856, 8859, 8862, 8865, 
-    8868, 8871, 8874, 8877, 8880, 8883, 8886, 8889, 8892, 8895, 8898, 8901, 
-    8904, 8907, 8910, 8913, 8916, 8919, 8922, 8925, 8928, 8931, 8934, 8937, 
-    8940, 8943, 8946, 8949, 8952, 8955, 8958, 8961, 8964, 8967, 8970, 8973, 
-    8976, 8979, 8982, 8985, 8988, 8991, 8994, 8997, 9000, 9003, 9006, 9009, 
-    9012, 9015, 9018, 0, 0, 9021, 9025, 9029, 9033, 9037, 9041, 9045, 9049, 
-    9053, 9057, 9061, 9065, 9069, 9073, 9077, 9081, 9085, 9089, 9093, 9097, 
-    9101, 9105, 9109, 9113, 9117, 9121, 9125, 9129, 9133, 9137, 9141, 9145, 
-    9149, 9153, 9157, 9161, 9165, 9169, 9173, 9177, 9181, 9185, 9189, 9193, 
-    9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9233, 9237, 9241, 
-    9245, 9249, 9253, 9257, 9261, 9265, 9269, 9273, 0, 0, 9277, 9281, 9285, 
-    9289, 9293, 9297, 9301, 9305, 9309, 9313, 9317, 9321, 9325, 9329, 9333, 
-    9337, 9341, 9345, 9349, 9353, 9357, 9361, 9365, 9369, 9373, 9377, 9381, 
-    9385, 9389, 9393, 9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 
-    9433, 9437, 9441, 9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 
-    9481, 9485, 9489, 0, 0, 0, 0, 0, 0, 0, 0, 9493, 9497, 9501, 9506, 9511, 
-    9516, 9521, 9526, 9531, 9536, 9540, 9559, 9568, 0, 0, 0, 9573, 9575, 
-    9577, 9579, 9581, 9583, 9585, 9587, 9589, 9591, 0, 0, 0, 0, 0, 0, 9593, 
-    9595, 9597, 9599, 9601, 9603, 9605, 9607, 9609, 9611, 9613, 9615, 9617, 
-    9619, 9621, 9623, 9625, 9627, 9629, 9631, 9633, 0, 0, 9635, 9637, 9639, 
-    9641, 9643, 9645, 9647, 9649, 9651, 9653, 9655, 9657, 0, 9659, 9661, 
-    9663, 9665, 9667, 9669, 9671, 9673, 9675, 9677, 9679, 9681, 9683, 9685, 
-    9687, 9689, 9691, 9693, 9695, 0, 9697, 9699, 9701, 9703, 0, 0, 0, 0, 
-    9705, 9708, 9711, 0, 9714, 0, 9717, 9720, 9723, 9726, 9729, 9732, 9735, 
-    9738, 9741, 9744, 9747, 9749, 9751, 9753, 9755, 9757, 9759, 9761, 9763, 
-    9765, 9767, 9769, 9771, 9773, 9775, 9777, 9779, 9781, 9783, 9785, 9787, 
-    9789, 9791, 9793, 9795, 9797, 9799, 9801, 9803, 9805, 9807, 9809, 9811, 
-    9813, 9815, 9817, 9819, 9821, 9823, 9825, 9827, 9829, 9831, 9833, 9835, 
-    9837, 9839, 9841, 9843, 9845, 9847, 9849, 9851, 9853, 9855, 9857, 9859, 
-    9861, 9863, 9865, 9867, 9869, 9871, 9873, 9875, 9877, 9879, 9881, 9883, 
-    9885, 9887, 9889, 9891, 9893, 9895, 9897, 9899, 9901, 9903, 9905, 9907, 
-    9909, 9911, 9913, 9915, 9917, 9919, 9921, 9923, 9925, 9927, 9929, 9931, 
-    9933, 9935, 9937, 9939, 9941, 9943, 9945, 9947, 9949, 9951, 9953, 9955, 
-    9957, 9959, 9961, 9963, 9965, 9967, 9969, 9971, 9973, 9975, 9977, 9979, 
-    9981, 9984, 9987, 9990, 9993, 9996, 9999, 10002, 0, 0, 0, 0, 10005, 
-    10007, 10009, 10011, 10013, 10015, 10017, 10019, 10021, 10023, 10025, 
-    10027, 10029, 10031, 10033, 10035, 10037, 10039, 10041, 10043, 10045, 
-    10047, 10049, 10051, 10053, 10055, 10057, 10059, 10061, 10063, 10065, 
-    10067, 10069, 10071, 10073, 10075, 10077, 10079, 10081, 10083, 10085, 
-    10087, 10089, 10091, 10093, 10095, 10097, 10099, 10101, 10103, 10105, 
-    10107, 10109, 10111, 10113, 10115, 10117, 10119, 10121, 10123, 10125, 
-    10127, 10129, 10131, 10133, 10135, 10137, 10139, 10141, 10143, 10145, 
-    10147, 10149, 10151, 10153, 10155, 10157, 10159, 10161, 10163, 10165, 
-    10167, 10169, 10171, 10173, 10175, 10177, 10179, 10181, 10183, 10185, 
-    10187, 10189, 10191, 10193, 10195, 10197, 10199, 10201, 10203, 10205, 
-    10207, 10209, 10211, 10213, 10215, 10217, 10219, 10221, 10223, 10225, 
-    10227, 10229, 10231, 10233, 10235, 10237, 10239, 10241, 10243, 10245, 
-    10247, 10249, 10251, 10253, 10255, 10257, 10259, 10261, 10263, 10265, 
-    10267, 10269, 10271, 10273, 10275, 10277, 10279, 10281, 10283, 10285, 
-    10287, 10289, 10291, 10293, 10295, 10297, 10299, 10301, 10303, 10305, 
-    10307, 10309, 10311, 10313, 10315, 10317, 10319, 10321, 10323, 10325, 
-    10327, 10329, 10331, 10333, 10335, 10337, 10339, 10341, 10343, 10345, 
-    10347, 10349, 10351, 10353, 10355, 10357, 10359, 10361, 10363, 10365, 
-    10367, 10369, 10371, 10373, 10375, 10377, 10379, 10381, 10383, 0, 0, 0, 
-    10385, 10387, 10389, 10391, 10393, 10395, 0, 0, 10397, 10399, 10401, 
-    10403, 10405, 10407, 0, 0, 10409, 10411, 10413, 10415, 10417, 10419, 0, 
-    0, 10421, 10423, 10425, 0, 0, 0, 10427, 10429, 10431, 10433, 10435, 
-    10437, 10439, 0, 10441, 10443, 10445, 10447, 10449, 10451, 10453, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 10455, 0, 10460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 10465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    10470, 10475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10480, 10485, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10490, 10495, 0, 10500, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 10505, 10510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 10515, 10520, 10525, 10530, 10535, 10540, 10545, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10550, 10555, 10560, 
-    10565, 10570, 10575, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10580, 
-    10582, 10584, 10586, 10588, 10590, 10592, 10594, 10596, 10598, 10600, 
-    10602, 10604, 10606, 10608, 10610, 10612, 10614, 10616, 10618, 10620, 
-    10622, 10624, 10626, 10628, 10630, 10632, 10634, 10636, 10638, 10640, 
-    10642, 10644, 10646, 10648, 10650, 10652, 10654, 10656, 10658, 10660, 
-    10662, 10664, 10666, 10668, 10670, 10672, 10674, 10676, 10678, 10680, 
-    10682, 10684, 10686, 10688, 10690, 10692, 10694, 10696, 10698, 10700, 
-    10702, 10704, 10706, 10708, 10710, 10712, 10714, 10716, 10718, 10720, 
-    10722, 10724, 10726, 10728, 10730, 10732, 10734, 10736, 10738, 10740, 
-    10742, 10744, 10746, 10748, 0, 10750, 10752, 10754, 10756, 10758, 10760, 
-    10762, 10764, 10766, 10768, 10770, 10772, 10774, 10776, 10778, 10780, 
-    10782, 10784, 10786, 10788, 10790, 10792, 10794, 10796, 10798, 10800, 
-    10802, 10804, 10806, 10808, 10810, 10812, 10814, 10816, 10818, 10820, 
-    10822, 10824, 10826, 10828, 10830, 10832, 10834, 10836, 10838, 10840, 
-    10842, 10844, 10846, 10848, 10850, 10852, 10854, 10856, 10858, 10860, 
-    10862, 10864, 10866, 10868, 10870, 10872, 10874, 10876, 10878, 10880, 
-    10882, 10884, 10886, 10888, 10890, 0, 10892, 10894, 0, 0, 10896, 0, 0, 
-    10898, 10900, 0, 0, 10902, 10904, 10906, 10908, 0, 10910, 10912, 10914, 
-    10916, 10918, 10920, 10922, 10924, 10926, 10928, 10930, 10932, 0, 10934, 
-    0, 10936, 10938, 10940, 10942, 10944, 10946, 10948, 0, 10950, 10952, 
-    10954, 10956, 10958, 10960, 10962, 10964, 10966, 10968, 10970, 10972, 
-    10974, 10976, 10978, 10980, 10982, 10984, 10986, 10988, 10990, 10992, 
-    10994, 10996, 10998, 11000, 11002, 11004, 11006, 11008, 11010, 11012, 
-    11014, 11016, 11018, 11020, 11022, 11024, 11026, 11028, 11030, 11032, 
-    11034, 11036, 11038, 11040, 11042, 11044, 11046, 11048, 11050, 11052, 
-    11054, 11056, 11058, 11060, 11062, 11064, 11066, 11068, 11070, 11072, 
-    11074, 11076, 11078, 0, 11080, 11082, 11084, 11086, 0, 0, 11088, 11090, 
-    11092, 11094, 11096, 11098, 11100, 11102, 0, 11104, 11106, 11108, 11110, 
-    11112, 11114, 11116, 0, 11118, 11120, 11122, 11124, 11126, 11128, 11130, 
-    11132, 11134, 11136, 11138, 11140, 11142, 11144, 11146, 11148, 11150, 
-    11152, 11154, 11156, 11158, 11160, 11162, 11164, 11166, 11168, 11170, 
-    11172, 0, 11174, 11176, 11178, 11180, 0, 11182, 11184, 11186, 11188, 
-    11190, 0, 11192, 0, 0, 0, 11194, 11196, 11198, 11200, 11202, 11204, 
-    11206, 0, 11208, 11210, 11212, 11214, 11216, 11218, 11220, 11222, 11224, 
-    11226, 11228, 11230, 11232, 11234, 11236, 11238, 11240, 11242, 11244, 
-    11246, 11248, 11250, 11252, 11254, 11256, 11258, 11260, 11262, 11264, 
-    11266, 11268, 11270, 11272, 11274, 11276, 11278, 11280, 11282, 11284, 
-    11286, 11288, 11290, 11292, 11294, 11296, 11298, 11300, 11302, 11304, 
-    11306, 11308, 11310, 11312, 11314, 11316, 11318, 11320, 11322, 11324, 
-    11326, 11328, 11330, 11332, 11334, 11336, 11338, 11340, 11342, 11344, 
-    11346, 11348, 11350, 11352, 11354, 11356, 11358, 11360, 11362, 11364, 
-    11366, 11368, 11370, 11372, 11374, 11376, 11378, 11380, 11382, 11384, 
-    11386, 11388, 11390, 11392, 11394, 11396, 11398, 11400, 11402, 11404, 
-    11406, 11408, 11410, 11412, 11414, 11416, 11418, 11420, 11422, 11424, 
-    11426, 11428, 11430, 11432, 11434, 11436, 11438, 11440, 11442, 11444, 
-    11446, 11448, 11450, 11452, 11454, 11456, 11458, 11460, 11462, 11464, 
-    11466, 11468, 11470, 11472, 11474, 11476, 11478, 11480, 11482, 11484, 
-    11486, 11488, 11490, 11492, 11494, 11496, 11498, 11500, 11502, 11504, 
-    11506, 11508, 11510, 11512, 11514, 11516, 11518, 11520, 11522, 11524, 
-    11526, 11528, 11530, 11532, 11534, 11536, 11538, 11540, 11542, 11544, 
-    11546, 11548, 11550, 11552, 11554, 11556, 11558, 11560, 11562, 11564, 
-    11566, 11568, 11570, 11572, 11574, 11576, 11578, 11580, 11582, 11584, 
-    11586, 11588, 11590, 11592, 11594, 11596, 11598, 11600, 11602, 11604, 
-    11606, 11608, 11610, 11612, 11614, 11616, 11618, 11620, 11622, 11624, 
-    11626, 11628, 11630, 11632, 11634, 11636, 11638, 11640, 11642, 11644, 
-    11646, 11648, 11650, 11652, 11654, 11656, 11658, 11660, 11662, 11664, 
-    11666, 11668, 11670, 11672, 11674, 11676, 11678, 11680, 11682, 11684, 
-    11686, 11688, 11690, 11692, 11694, 11696, 11698, 11700, 11702, 11704, 
-    11706, 11708, 11710, 11712, 11714, 11716, 11718, 11720, 11722, 11724, 
-    11726, 11728, 11730, 11732, 11734, 11736, 11738, 11740, 11742, 11744, 
-    11746, 11748, 11750, 11752, 11754, 11756, 11758, 11760, 11762, 11764, 
-    11766, 11768, 11770, 11772, 11774, 11776, 11778, 11780, 11782, 11784, 
-    11786, 11788, 11790, 11792, 11794, 11796, 11798, 11800, 11802, 11804, 
-    11806, 11808, 11810, 11812, 11814, 11816, 11818, 11820, 11822, 11824, 
-    11826, 11828, 11830, 11832, 11834, 11836, 11838, 11840, 11842, 11844, 
-    11846, 11848, 11850, 11852, 11854, 11856, 11858, 11860, 11862, 11864, 
-    11866, 11868, 11870, 11872, 11874, 11876, 11878, 11880, 11882, 11884, 
-    11886, 0, 0, 11888, 11890, 11892, 11894, 11896, 11898, 11900, 11902, 
-    11904, 11906, 11908, 11910, 11912, 11914, 11916, 11918, 11920, 11922, 
-    11924, 11926, 11928, 11930, 11932, 11934, 11936, 11938, 11940, 11942, 
-    11944, 11946, 11948, 11950, 11952, 11954, 11956, 11958, 11960, 11962, 
-    11964, 11966, 11968, 11970, 11972, 11974, 11976, 11978, 11980, 11982, 
-    11984, 11986, 11988, 11990, 11992, 11994, 11996, 11998, 12000, 12002, 
-    12004, 12006, 12008, 12010, 12012, 12014, 12016, 12018, 12020, 12022, 
-    12024, 12026, 12028, 12030, 12032, 12034, 12036, 12038, 12040, 12042, 
-    12044, 12046, 12048, 12050, 12052, 12054, 12056, 12058, 12060, 12062, 
-    12064, 12066, 12068, 12070, 12072, 12074, 12076, 12078, 12080, 12082, 
-    12084, 12086, 12088, 12090, 12092, 12094, 12096, 12098, 12100, 12102, 
-    12104, 12106, 12108, 12110, 12112, 12114, 12116, 12118, 12120, 12122, 
-    12124, 12126, 12128, 12130, 12132, 12134, 12136, 12138, 12140, 12142, 
-    12144, 12146, 12148, 12150, 12152, 12154, 12156, 12158, 12160, 12162, 
-    12164, 12166, 12168, 12170, 12172, 12174, 12176, 12178, 12180, 12182, 
-    12184, 12186, 12188, 12190, 12192, 12194, 12196, 12198, 12200, 12202, 
-    12204, 12206, 12208, 12210, 12212, 12214, 12216, 12218, 12220, 12222, 
-    12224, 12226, 12228, 12230, 12232, 12234, 12236, 12238, 12240, 12242, 
-    12244, 12246, 12248, 12250, 12252, 12254, 12256, 12258, 12260, 12262, 
-    12264, 12266, 12268, 12270, 12272, 12274, 12276, 12278, 12280, 12282, 
-    12284, 12286, 12288, 12290, 12292, 12294, 12296, 12298, 12300, 12302, 
-    12304, 12306, 12308, 12310, 12312, 12314, 12316, 12318, 12320, 12322, 
-    12324, 12326, 12328, 12330, 12332, 12334, 12336, 12338, 12340, 12342, 
-    12344, 12346, 12348, 12350, 12352, 12354, 12356, 12358, 12360, 12362, 
-    12364, 12366, 12368, 12370, 12372, 12374, 12376, 12378, 12380, 12382, 
-    12384, 12386, 12388, 12390, 12392, 12394, 12396, 12398, 12400, 12402, 
-    12404, 12406, 12408, 12410, 12412, 12414, 12416, 12418, 12420, 12422, 
-    12424, 12426, 12428, 12430, 12432, 12434, 12436, 12438, 12440, 12442, 
-    12444, 12446, 12448, 12450, 12452, 12454, 12456, 12458, 12460, 12462, 
-    12464, 12466, 12468, 12470, 0, 0, 12472, 12474, 12476, 12478, 12480, 
-    12482, 12484, 12486, 12488, 12490, 12492, 12494, 12496, 12498, 12500, 
-    12502, 12504, 12506, 12508, 12510, 12512, 12514, 12516, 12518, 12520, 
-    12522, 12524, 12526, 12528, 12530, 12532, 12534, 12536, 12538, 12540, 
-    12542, 12544, 12546, 12548, 12550, 12552, 12554, 12556, 12558, 12560, 
-    12562, 12564, 12566, 12568, 12570, 12572, 12574, 12576, 12578, 0, 12580, 
-    12582, 12584, 12586, 12588, 12590, 12592, 12594, 12596, 12598, 12600, 
-    12602, 12604, 12606, 12608, 12610, 12612, 12614, 12616, 12618, 12620, 
-    12622, 12624, 12626, 12628, 12630, 12632, 0, 12634, 12636, 0, 12638, 0, 
-    0, 12640, 0, 12642, 12644, 12646, 12648, 12650, 12652, 12654, 12656, 
-    12658, 12660, 0, 12662, 12664, 12666, 12668, 0, 12670, 0, 12672, 0, 0, 0, 
-    0, 0, 0, 12674, 0, 0, 0, 0, 12676, 0, 12678, 0, 12680, 0, 12682, 12684, 
-    12686, 0, 12688, 12690, 0, 12692, 0, 0, 12694, 0, 12696, 0, 12698, 0, 
-    12700, 0, 12702, 0, 12704, 12706, 0, 12708, 0, 0, 12710, 12712, 12714, 
-    12716, 0, 12718, 12720, 12722, 12724, 12726, 12728, 12730, 0, 12732, 
-    12734, 12736, 12738, 0, 12740, 12742, 12744, 12746, 0, 12748, 0, 12750, 
-    12752, 12754, 12756, 12758, 12760, 12762, 12764, 12766, 12768, 0, 12770, 
-    12772, 12774, 12776, 12778, 12780, 12782, 12784, 12786, 12788, 12790, 
-    12792, 12794, 12796, 12798, 12800, 12802, 0, 0, 0, 0, 0, 12804, 12806, 
-    12808, 0, 12810, 12812, 12814, 12816, 12818, 0, 12820, 12822, 12824, 
-    12826, 12828, 12830, 12832, 12834, 12836, 12838, 12840, 12842, 12844, 
-    12846, 12848, 12850, 12852, 0, 0, 0, 0, 12854, 12857, 12860, 12863, 
-    12866, 12869, 12872, 12875, 12878, 12881, 12884, 0, 0, 0, 0, 0, 12887, 
-    12891, 12895, 12899, 12903, 12907, 12911, 12915, 12919, 12923, 12927, 
-    12931, 12935, 12939, 12943, 12947, 12951, 12955, 12959, 12963, 12967, 
-    12971, 12975, 12979, 12983, 12987, 12991, 12995, 12997, 12999, 13002, 0, 
-    13005, 13007, 13009, 13011, 13013, 13015, 13017, 13019, 13021, 13023, 
-    13025, 13027, 13029, 13031, 13033, 13035, 13037, 13039, 13041, 13043, 
-    13045, 13047, 13049, 13051, 13053, 13055, 13057, 13060, 13063, 13066, 
-    13069, 13073, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13076, 13079, 13082, 0, 0, 0, 
-    13085, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13088, 13091, 13094, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13096, 13098, 13100, 13102, 13104, 
-    13106, 13108, 13110, 13112, 13114, 13116, 13118, 13120, 13122, 13124, 
-    13126, 13128, 13130, 13132, 13134, 13136, 13138, 13140, 13142, 13144, 
-    13146, 13148, 13150, 13152, 13154, 13156, 13158, 13160, 13162, 13164, 
-    13166, 13168, 13170, 13172, 13174, 13176, 13178, 13180, 13182, 0, 0, 0, 
-    0, 13184, 13188, 13192, 13196, 13200, 13204, 13208, 13212, 13216, 0, 0, 
-    0, 0, 0, 0, 0, 13220, 13222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    13224, 13226, 13228, 13230, 13233, 13235, 13237, 13239, 13241, 13243, 
-    13245, 13247, 13249, 13251, 13254, 13256, 13258, 13260, 13262, 13265, 
-    13267, 13269, 13271, 13274, 13276, 13278, 13280, 13282, 13284, 13287, 
-    13289, 13291, 13293, 13295, 13297, 13299, 13301, 13303, 13305, 13307, 
-    13309, 13311, 13313, 13315, 13317, 13319, 13321, 13323, 13325, 13327, 
-    13329, 13331, 13333, 13336, 13338, 13340, 13342, 13345, 13347, 13349, 
-    13351, 13353, 13355, 13357, 13359, 13361, 13363, 13365, 13367, 13369, 
-    13371, 13373, 13375, 13377, 13379, 13381, 13383, 13385, 13387, 13389, 
-    13391, 13393, 13395, 13397, 13399, 13401, 13403, 13405, 13407, 13409, 
-    13412, 13414, 13416, 13418, 13420, 13422, 13424, 13427, 13430, 13432, 
-    13434, 13436, 13438, 13440, 13442, 13444, 13446, 13448, 13450, 13453, 
-    13455, 13457, 13459, 13461, 13464, 13466, 13468, 13470, 13472, 13474, 
-    13476, 13478, 13480, 13482, 13485, 13487, 13490, 13492, 13494, 13496, 
-    13498, 13500, 13502, 13504, 13506, 13508, 13510, 13512, 13515, 13517, 
-    13519, 13521, 13523, 13525, 13528, 13530, 13533, 13536, 13538, 13540, 
-    13542, 13544, 13547, 13550, 13552, 13554, 13556, 13558, 13560, 13562, 
-    13564, 13566, 13568, 13570, 13572, 13575, 13577, 13579, 13581, 13583, 
-    13585, 13587, 13589, 13591, 13593, 13595, 13597, 13599, 13601, 13603, 
-    13605, 13607, 13609, 13611, 13613, 13616, 13618, 13620, 13622, 13624, 
-    13626, 13629, 13631, 13633, 13635, 13637, 13639, 13641, 13643, 13645, 
-    13647, 13649, 13651, 13654, 13656, 13658, 13660, 13662, 13664, 13666, 
-    13668, 13670, 13672, 13674, 13676, 13678, 13680, 13682, 13684, 13686, 
-    13688, 13690, 13693, 13695, 13697, 13699, 13701, 13703, 13706, 13708, 
-    13710, 13712, 13714, 13716, 13718, 13720, 13722, 13725, 13727, 13729, 
-    13731, 13734, 13736, 13738, 13740, 13742, 13744, 13746, 13749, 13752, 
-    13755, 13757, 13760, 13762, 13764, 13766, 13768, 13770, 13772, 13774, 
-    13776, 13778, 13780, 13783, 13785, 13787, 13789, 13791, 13793, 13795, 
-    13798, 13800, 13802, 13805, 13808, 13810, 13812, 13814, 13816, 13818, 
-    13820, 13822, 13824, 13826, 13829, 13831, 13834, 13836, 13839, 13841, 
-    13843, 13845, 13848, 13850, 13852, 13855, 13858, 13860, 13862, 13864, 
-    13866, 13868, 13870, 13872, 13874, 13876, 13878, 13880, 13882, 13884, 
-    13887, 13889, 13892, 13894, 13897, 13899, 13902, 13905, 13908, 13910, 
-    13912, 13914, 13917, 13920, 13923, 13926, 13928, 13930, 13932, 13934, 
-    13936, 13938, 13940, 13942, 13945, 13947, 13949, 13951, 13953, 13956, 
-    13958, 13961, 13964, 13966, 13968, 13970, 13972, 13974, 13976, 13979, 
-    13982, 13985, 13987, 13989, 13992, 13994, 13996, 13998, 14001, 14003, 
-    14005, 14007, 14009, 14011, 14014, 14016, 14018, 14020, 14022, 14024, 
-    14026, 14029, 14032, 14034, 14037, 14039, 14042, 14044, 14046, 14048, 
-    14051, 14054, 14056, 14059, 14061, 14064, 14066, 14068, 14070, 14072, 
-    14074, 14076, 14079, 14082, 14085, 14088, 14090, 14092, 14094, 14096, 
-    14098, 14100, 14102, 14104, 14106, 14108, 14110, 14112, 14115, 14117, 
-    14119, 14121, 14123, 14125, 14127, 14129, 14131, 14133, 14135, 14137, 
-    14139, 14142, 14145, 14148, 14150, 14152, 14154, 14156, 14159, 14161, 
-    14164, 14166, 14168, 14171, 14174, 14176, 14178, 14180, 14182, 14184, 
-    14186, 14188, 14190, 14192, 14194, 14196, 14198, 14200, 14202, 14204, 
-    14206, 14208, 14210, 14212, 14215, 14217, 14219, 14221, 14223, 14225, 
-    14228, 14231, 14233, 14235, 14237, 14239, 14241, 14243, 14246, 14248, 
-    14250, 14252, 14254, 14257, 14260, 14262, 14264, 14266, 14269, 14271, 
-    14273, 14276, 14279, 14281, 14283, 14285, 14288, 14290, 14292, 14294, 
-    14296, 14298, 14300, 14302, 14305, 14307, 14309, 14311, 14314, 14316, 
-    14318, 14320, 14322, 14325, 14328, 14330, 14332, 14334, 14337, 14339, 
-    14342, 14344, 14346, 14348, 14351, 14353, 14355, 14357, 14359, 14361, 
-    14363, 14365, 14368, 14370, 14372, 14374, 14376, 14378, 14380, 14383, 
-    14385, 14388, 14391, 14394, 14396, 14398, 14400, 14402, 14404, 14406, 
-    14408, 14410, 0, 0, 
-};
-
-/* NFC pairs */
-#define COMP_SHIFT1 2
-#define COMP_SHIFT2 1
-static const unsigned short comp_index0[] = {
-    0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 
-    5, 6, 7, 0, 0, 0, 0, 8, 0, 9, 10, 0, 0, 0, 11, 12, 13, 14, 0, 0, 0, 0, 0, 
-    15, 16, 17, 0, 0, 0, 0, 18, 19, 20, 21, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 
-    23, 24, 25, 26, 0, 0, 0, 0, 27, 28, 29, 30, 0, 0, 0, 0, 31, 32, 33, 34, 
-    0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 36, 0, 37, 38, 39, 0, 0, 0, 40, 41, 42, 
-    43, 0, 0, 0, 0, 44, 45, 46, 0, 0, 0, 0, 0, 47, 48, 49, 50, 0, 0, 0, 51, 
-    52, 53, 54, 0, 0, 0, 0, 55, 56, 0, 0, 0, 0, 0, 0, 57, 58, 59, 60, 0, 0, 
-    0, 0, 61, 62, 63, 0, 0, 0, 0, 0, 64, 65, 66, 67, 0, 0, 0, 68, 69, 70, 71, 
-    0, 0, 0, 0, 72, 0, 73, 0, 0, 0, 0, 0, 74, 0, 75, 0, 0, 0, 0, 0, 76, 0, 0, 
-    0, 0, 0, 0, 77, 78, 79, 0, 0, 0, 0, 0, 80, 81, 82, 83, 0, 0, 0, 0, 84, 
-    85, 86, 0, 0, 0, 0, 0, 87, 88, 0, 89, 0, 0, 0, 90, 91, 0, 92, 0, 0, 0, 0, 
-    0, 93, 94, 95, 0, 0, 0, 0, 96, 97, 98, 99, 0, 0, 0, 0, 100, 0, 0, 0, 0, 
-    0, 0, 101, 102, 0, 103, 0, 0, 0, 0, 104, 105, 106, 107, 0, 0, 0, 0, 108, 
-    109, 110, 111, 0, 0, 0, 0, 112, 113, 0, 0, 0, 0, 0, 114, 115, 116, 117, 
-    0, 0, 0, 0, 118, 119, 120, 121, 0, 0, 0, 0, 122, 0, 123, 0, 0, 0, 0, 124, 
-    125, 126, 127, 128, 0, 0, 0, 129, 130, 131, 132, 0, 0, 0, 0, 133, 134, 0, 
-    0, 0, 0, 0, 0, 135, 136, 137, 138, 0, 0, 0, 139, 140, 141, 142, 0, 0, 0, 
-    0, 0, 143, 144, 145, 0, 0, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0, 150, 0, 
-    151, 0, 0, 0, 0, 152, 153, 154, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 
-    156, 157, 158, 0, 0, 0, 0, 0, 159, 160, 161, 162, 0, 0, 0, 163, 0, 0, 0, 
-    164, 0, 0, 0, 165, 166, 0, 0, 0, 0, 0, 0, 167, 0, 0, 0, 0, 0, 0, 0, 168, 
-    0, 0, 0, 0, 0, 0, 169, 170, 0, 0, 0, 0, 0, 0, 171, 0, 0, 0, 0, 0, 0, 0, 
-    172, 173, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 175, 176, 0, 0, 0, 0, 
-    0, 0, 177, 178, 0, 0, 0, 0, 0, 0, 179, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 
-    0, 0, 0, 181, 182, 183, 0, 0, 0, 0, 0, 184, 185, 0, 0, 0, 0, 0, 0, 186, 
-    0, 0, 0, 0, 0, 0, 0, 187, 0, 0, 0, 0, 0, 0, 188, 189, 0, 0, 0, 0, 0, 0, 
-    190, 0, 0, 0, 0, 0, 0, 0, 191, 192, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 
-    0, 194, 195, 0, 0, 0, 0, 0, 0, 196, 197, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 
-    0, 0, 0, 0, 199, 0, 0, 0, 0, 0, 0, 200, 201, 202, 0, 0, 0, 0, 0, 203, 
-    204, 0, 0, 0, 0, 0, 0, 205, 206, 0, 0, 0, 0, 0, 0, 207, 0, 0, 0, 0, 0, 0, 
-    208, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 0, 0, 0, 210, 0, 0, 0, 0, 0, 
-    0, 0, 211, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 
-    0, 0, 0, 0, 214, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 
-    0, 0, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 218, 0, 0, 0, 0, 0, 0, 219, 0, 
-    0, 0, 0, 0, 0, 220, 221, 222, 0, 0, 0, 0, 0, 223, 224, 225, 0, 0, 0, 0, 
-    0, 226, 227, 228, 0, 0, 0, 0, 0, 229, 230, 231, 0, 0, 0, 0, 0, 0, 232, 0, 
-    0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 235, 0, 
-    0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 0, 238, 
-    0, 0, 0, 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 
-    241, 0, 0, 0, 0, 0, 0, 242, 0, 243, 244, 0, 0, 0, 0, 245, 246, 0, 0, 0, 
-    0, 0, 247, 0, 248, 0, 249, 0, 0, 0, 250, 251, 252, 0, 0, 0, 0, 0, 253, 0, 
-    254, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 256, 257, 258, 0, 0, 0, 0, 0, 
-    259, 0, 260, 0, 261, 0, 0, 0, 0, 0, 0, 262, 0, 0, 0, 0, 0, 0, 0, 263, 0, 
-    0, 0, 264, 265, 266, 0, 267, 0, 0, 0, 268, 0, 269, 0, 0, 0, 0, 0, 270, 0, 
-    271, 272, 0, 0, 0, 0, 273, 274, 0, 275, 0, 0, 0, 276, 0, 277, 0, 0, 0, 0, 
-    0, 0, 0, 278, 0, 0, 0, 0, 0, 279, 280, 281, 282, 0, 0, 0, 0, 283, 284, 0, 
-    285, 0, 0, 0, 286, 0, 0, 0, 287, 0, 0, 0, 288, 0, 0, 0, 289, 0, 0, 0, 0, 
-    0, 0, 290, 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 292, 0, 0, 0, 0, 0, 0, 
-    0, 293, 0, 0, 0, 0, 0, 0, 294, 0, 0, 0, 0, 0, 0, 0, 295, 0, 0, 0, 0, 0, 
-    0, 0, 296, 0, 0, 0, 0, 0, 0, 0, 297, 0, 0, 0, 0, 0, 0, 298, 299, 0, 0, 0, 
-    0, 0, 0, 300, 0, 0, 0, 0, 0, 0, 0, 301, 0, 0, 0, 0, 0, 0, 0, 302, 0, 0, 
-    0, 0, 0, 0, 0, 303, 0, 0, 0, 0, 0, 0, 304, 0, 0, 0, 0, 0, 0, 0, 305, 0, 
-    0, 0, 0, 0, 0, 0, 306, 0, 0, 0, 0, 0, 0, 307, 0, 0, 0, 0, 0, 0, 0, 308, 
-    0, 0, 0, 0, 0, 0, 0, 309, 0, 0, 0, 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, 0, 
-    311, 312, 0, 0, 0, 0, 0, 0, 313, 0, 0, 0, 0, 0, 0, 0, 314, 0, 0, 0, 0, 0, 
-    0, 0, 315, 0, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 0, 317, 0, 0, 0, 0, 
-    0, 0, 0, 318, 0, 0, 0, 0, 0, 0, 0, 319, 0, 0, 0, 0, 0, 0, 0, 320, 0, 0, 
-    0, 0, 0, 0, 0, 321, 0, 0, 0, 0, 0, 0, 322, 0, 0, 0, 0, 0, 0, 0, 323, 0, 
-    0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 326, 0, 0, 0, 0, 0, 0, 0, 327, 0, 0, 0, 0, 0, 0, 0, 328, 0, 0, 0, 0, 
-    0, 0, 329, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 0, 0, 0, 0, 0, 331, 0, 0, 0, 
-    0, 0, 0, 0, 332, 0, 0, 0, 0, 0, 0, 0, 333, 0, 0, 0, 0, 0, 0, 334, 0, 0, 
-    0, 0, 0, 0, 0, 335, 0, 0, 0, 0, 0, 0, 0, 336, 337, 0, 0, 0, 0, 0, 0, 0, 
-    338, 0, 0, 0, 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, 0, 340, 0, 0, 0, 0, 0, 0, 
-    0, 341, 0, 0, 0, 0, 0, 0, 0, 342, 0, 0, 0, 0, 0, 0, 0, 343, 0, 0, 0, 0, 
-    0, 0, 344, 0, 0, 0, 0, 0, 0, 0, 345, 346, 0, 0, 0, 0, 0, 0, 347, 0, 0, 0, 
-    0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, 350, 0, 
-    0, 0, 0, 0, 0, 0, 351, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, 0, 0, 353, 
-    0, 0, 0, 0, 0, 0, 0, 354, 0, 0, 0, 0, 0, 0, 0, 355, 0, 0, 0, 0, 0, 0, 0, 
-    356, 0, 0, 0, 0, 0, 0, 357, 0, 0, 0, 0, 0, 0, 0, 358, 0, 0, 0, 0, 0, 0, 
-    0, 359, 0, 0, 0, 0, 0, 0, 0, 360, 0, 0, 0, 0, 0, 0, 361, 0, 362, 0, 0, 0, 
-    0, 0, 0, 0, 363, 0, 0, 0, 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, 0, 0, 365, 0, 
-    0, 0, 0, 0, 0, 0, 366, 0, 0, 0, 0, 0, 0, 367, 0, 0, 0, 0, 0, 0, 0, 368, 
-    0, 0, 0, 0, 0, 0, 369, 370, 0, 0, 0, 0, 0, 0, 371, 0, 0, 0, 0, 0, 0, 0, 
-    372, 0, 0, 0, 0, 0, 0, 0, 373, 0, 0, 0, 0, 0, 0, 374, 0, 0, 0, 0, 0, 0, 
-    0, 375, 0, 0, 376, 0, 0, 0, 0, 377, 0, 0, 378, 0, 0, 0, 0, 0, 0, 0, 379, 
-    0, 0, 0, 0, 0, 0, 0, 380, 0, 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, 0, 0, 0, 
-    382, 0, 0, 0, 0, 0, 0, 0, 383, 0, 0, 0, 0, 0, 0, 0, 384, 0, 0, 0, 385, 0, 
-    0, 386, 0, 0, 0, 0, 387, 0, 0, 388, 0, 0, 0, 0, 0, 0, 0, 389, 0, 0, 0, 0, 
-    0, 0, 0, 390, 0, 0, 0, 0, 0, 0, 391, 0, 0, 0, 0, 0, 0, 0, 392, 0, 0, 0, 
-    0, 0, 0, 0, 393, 0, 0, 0, 0, 0, 0, 0, 394, 0, 0, 0, 395, 0, 0, 0, 0, 0, 
-    0, 0, 396, 0, 0, 0, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, 0, 398, 0, 0, 0, 0, 
-    0, 0, 0, 399, 0, 0, 400, 0, 0, 0, 0, 401, 0, 0, 402, 0, 0, 0, 0, 0, 0, 0, 
-    403, 0, 0, 0, 0, 0, 0, 0, 404, 0, 0, 0, 0, 0, 0, 405, 0, 0, 0, 0, 0, 0, 
-    0, 406, 0, 0, 0, 0, 0, 0, 0, 407, 0, 0, 0, 0, 0, 0, 0, 408, 0, 0, 0, 409, 
-    0, 0, 410, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 0, 0, 0, 0, 413, 0, 0, 0, 
-    0, 0, 0, 0, 414, 0, 0, 0, 0, 0, 0, 415, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 
-    0, 0, 0, 0, 0, 417, 0, 0, 0, 0, 0, 0, 0, 418, 0, 0, 0, 419, 0, 0, 420, 0, 
-    0, 0, 0, 421, 0, 0, 422, 0, 0, 0, 423, 0, 0, 0, 424, 0, 0, 0, 425, 0, 0, 
-    0, 426, 0, 0, 0, 427, 0, 0, 0, 0, 0, 0, 0, 428, 0, 0, 0, 0, 0, 0, 429, 0, 
-    0, 0, 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, 0, 0, 431, 0, 0, 432, 0, 0, 0, 0, 
-    433, 0, 0, 434, 0, 0, 0, 435, 0, 0, 0, 436, 0, 0, 0, 437, 0, 0, 0, 438, 
-    0, 0, 0, 439, 0, 0, 440, 0, 0, 0, 0, 0, 0, 0, 441, 0, 0, 0, 0, 0, 0, 0, 
-    442, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 444, 0, 0, 0, 0, 0, 0, 
-    0, 445, 0, 0, 0, 0, 0, 0, 0, 446, 0, 0, 0, 447, 0, 0, 0, 448, 0, 0, 0, 
-    449, 0, 0, 450, 0, 0, 0, 0, 0, 0, 0, 451, 0, 0, 0, 0, 0, 0, 0, 452, 0, 0, 
-    0, 0, 0, 0, 0, 453, 0, 0, 0, 0, 0, 0, 454, 0, 0, 0, 0, 0, 0, 0, 455, 0, 
-    0, 0, 0, 0, 0, 0, 456, 0, 0, 0, 0, 0, 0, 0, 457, 0, 0, 0, 0, 0, 0, 458, 
-    0, 0, 0, 0, 0, 0, 0, 459, 0, 0, 0, 0, 0, 0, 0, 460, 0, 0, 0, 461, 0, 0, 
-    0, 462, 0, 0, 0, 0, 0, 0, 463, 0, 0, 0, 0, 0, 0, 0, 464, 0, 0, 0, 465, 0, 
-    0, 0, 466, 0, 0, 0, 0, 0, 0, 467, 0, 0, 0, 0, 0, 0, 0, 468, 0, 0, 0, 0, 
-    0, 0, 0, 469, 0, 0, 0, 0, 0, 0, 0, 470, 0, 0, 0, 0, 0, 0, 471, 0, 0, 0, 
-    0, 0, 0, 0, 472, 0, 0, 0, 0, 0, 0, 0, 473, 0, 0, 0, 0, 0, 0, 0, 474, 0, 
-    0, 0, 0, 0, 0, 475, 0, 0, 0, 0, 0, 0, 0, 476, 0, 0, 0, 0, 0, 0, 0, 477, 
-    0, 0, 0, 0, 0, 0, 0, 478, 0, 0, 0, 0, 0, 0, 479, 0, 0, 0, 0, 0, 0, 0, 
-    480, 0, 0, 0, 0, 0, 0, 0, 481, 0, 0, 0, 0, 0, 0, 0, 482, 0, 0, 0, 0, 0, 
-    0, 483, 0, 0, 0, 0, 0, 0, 0, 484, 0, 0, 0, 0, 0, 0, 0, 485, 0, 0, 0, 0, 
-    0, 0, 0, 486, 0, 0, 0, 0, 0, 0, 487, 0, 0, 0, 0, 0, 0, 0, 488, 0, 0, 0, 
-    0, 0, 0, 0, 489, 0, 0, 0, 0, 0, 0, 0, 490, 0, 0, 0, 0, 0, 0, 491, 0, 0, 
-    0, 0, 0, 0, 0, 492, 0, 0, 0, 0, 0, 0, 0, 493, 0, 0, 0, 0, 0, 0, 0, 494, 
-    0, 0, 0, 0, 0, 0, 495, 0, 0, 0, 0, 0, 0, 0, 496, 0, 0, 0, 0, 0, 0, 0, 
-    497, 0, 0, 0, 0, 0, 0, 0, 498, 0, 0, 0, 0, 0, 0, 499, 0, 0, 0, 0, 0, 0, 
-    0, 500, 0, 0, 0, 0, 0, 0, 0, 501, 0, 0, 0, 0, 0, 0, 0, 502, 0, 0, 0, 0, 
-    0, 0, 503, 0, 0, 0, 0, 0, 0, 0, 504, 0, 0, 0, 0, 0, 0, 0, 505, 0, 0, 0, 
-    0, 0, 0, 0, 506, 0, 0, 0, 0, 0, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    508, 0, 0, 0, 0, 0, 0, 0, 509, 0, 0, 0, 0, 0, 0, 0, 510, 0, 0, 0, 0, 0, 
-    0, 0, 511, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, 0, 0, 0, 0, 513, 0, 0, 0, 0, 
-    0, 0, 0, 514, 0, 0, 0, 0, 0, 0, 0, 515, 0, 0, 0, 0, 0, 0, 516, 0, 0, 0, 
-    0, 0, 0, 0, 517, 0, 0, 0, 0, 0, 0, 0, 518, 0, 0, 0, 0, 0, 0, 0, 519, 0, 
-    0, 0, 0, 0, 0, 520, 0, 0, 0, 0, 0, 0, 0, 521, 0, 0, 0, 0, 0, 0, 0, 522, 
-    0, 0, 0, 0, 0, 0, 0, 523, 0, 0, 0, 0, 0, 0, 524, 0, 0, 0, 0, 0, 0, 0, 
-    525, 0, 0, 0, 0, 0, 0, 0, 526, 0, 0, 0, 0, 0, 0, 0, 527, 0, 0, 0, 0, 0, 
-    0, 528, 0, 0, 0, 0, 0, 0, 0, 529, 0, 0, 0, 0, 0, 0, 0, 530, 0, 0, 0, 0, 
-    0, 0, 0, 531, 0, 0, 0, 0, 0, 0, 532, 0, 0, 0, 0, 0, 0, 0, 533, 0, 0, 0, 
-    0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 0, 0, 535, 0, 0, 0, 0, 0, 0, 536, 0, 0, 
-    0, 0, 0, 0, 0, 537, 0, 0, 0, 0, 0, 0, 0, 538, 0, 0, 0, 0, 0, 0, 0, 539, 
-    0, 0, 0, 0, 0, 0, 540, 0, 0, 0, 0, 0, 0, 0, 541, 0, 0, 0, 0, 0, 0, 0, 
-    542, 0, 0, 0, 0, 0, 0, 0, 543, 0, 0, 0, 0, 0, 0, 544, 0, 0, 0, 0, 0, 0, 
-    0, 545, 0, 0, 0, 0, 0, 0, 0, 546, 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, 0, 0, 
-    0, 0, 548, 0, 0, 0, 0, 0, 0, 0, 549, 0, 0, 0, 0, 0, 0, 0, 550, 0, 0, 0, 
-    0, 0, 0, 0, 551, 0, 0, 0, 0, 0, 0, 552, 0, 0, 0, 0, 0, 0, 0, 553, 0, 0, 
-    0, 0, 0, 0, 0, 554, 0, 0, 0, 0, 0, 0, 0, 555, 0, 0, 0, 0, 0, 0, 0, 556, 
-    0, 0, 0, 0, 0, 0, 557, 0, 0, 0, 0, 0, 0, 0, 558, 0, 0, 0, 0, 0, 0, 0, 
-    559, 0, 0, 0, 0, 0, 0, 0, 560, 0, 0, 0, 0, 0, 0, 0, 561, 0, 0, 0, 0, 0, 
-    0, 0, 562, 0, 0, 0, 0, 0, 0, 0, 563, 0, 0, 0, 0, 0, 0, 564, 
-};
-
-static const unsigned short comp_index1[] = {
-    0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 
-    0, 11, 12, 0, 13, 0, 0, 0, 0, 0, 0, 14, 15, 0, 0, 0, 0, 16, 0, 0, 0, 0, 
-    0, 17, 18, 0, 19, 0, 20, 0, 0, 0, 0, 21, 0, 0, 0, 22, 0, 23, 0, 0, 24, 0, 
-    25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 33, 34, 0, 35, 0, 36, 37, 38, 0, 0, 
-    0, 0, 0, 39, 0, 0, 0, 40, 41, 42, 43, 0, 44, 0, 0, 0, 0, 45, 0, 0, 0, 0, 
-    0, 46, 0, 47, 0, 48, 0, 0, 49, 0, 50, 0, 51, 0, 0, 52, 53, 54, 55, 56, 
-    57, 58, 0, 59, 0, 0, 60, 61, 0, 0, 0, 62, 0, 0, 0, 0, 0, 63, 64, 0, 0, 
-    65, 0, 66, 0, 0, 67, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 69, 0, 0, 70, 0, 71, 
-    72, 0, 73, 0, 74, 0, 0, 75, 0, 0, 0, 0, 76, 0, 0, 77, 78, 0, 79, 0, 80, 
-    0, 0, 81, 0, 82, 83, 0, 84, 0, 0, 0, 0, 0, 85, 86, 87, 88, 89, 90, 91, 0, 
-    92, 0, 0, 93, 0, 0, 0, 94, 0, 0, 95, 0, 0, 0, 96, 0, 0, 97, 0, 98, 99, 0, 
-    100, 0, 101, 0, 0, 102, 0, 103, 104, 0, 105, 0, 106, 0, 0, 107, 0, 108, 
-    0, 0, 0, 109, 0, 110, 0, 0, 111, 0, 112, 113, 0, 114, 0, 0, 0, 0, 0, 115, 
-    116, 117, 118, 119, 120, 121, 0, 122, 123, 0, 124, 125, 0, 0, 0, 126, 0, 
-    0, 127, 0, 0, 128, 129, 0, 130, 131, 0, 0, 0, 0, 0, 132, 0, 0, 0, 133, 
-    134, 135, 136, 137, 0, 0, 0, 138, 0, 0, 139, 140, 0, 141, 0, 142, 0, 0, 
-    143, 0, 0, 0, 0, 144, 0, 145, 146, 147, 148, 149, 150, 151, 0, 152, 153, 
-    0, 154, 0, 0, 155, 0, 0, 0, 0, 156, 157, 0, 0, 0, 0, 0, 158, 159, 0, 160, 
-    0, 161, 162, 0, 0, 0, 163, 0, 164, 0, 0, 165, 0, 166, 167, 0, 168, 0, 
-    169, 170, 171, 172, 173, 174, 175, 0, 176, 0, 177, 178, 179, 0, 0, 0, 0, 
-    0, 180, 0, 0, 0, 181, 182, 183, 184, 0, 185, 186, 0, 0, 0, 0, 0, 187, 0, 
-    188, 0, 189, 0, 0, 190, 0, 191, 0, 192, 193, 0, 194, 195, 196, 197, 198, 
-    199, 200, 0, 201, 0, 0, 202, 203, 0, 0, 0, 204, 0, 0, 0, 205, 0, 0, 0, 0, 
-    0, 206, 0, 0, 0, 0, 207, 0, 0, 208, 0, 209, 0, 0, 210, 0, 211, 0, 0, 0, 
-    0, 212, 0, 0, 213, 0, 214, 215, 0, 216, 0, 217, 0, 0, 218, 219, 0, 0, 0, 
-    0, 0, 0, 220, 221, 0, 222, 0, 223, 0, 0, 224, 0, 225, 226, 0, 227, 0, 0, 
-    0, 0, 0, 228, 229, 230, 231, 232, 233, 234, 0, 235, 0, 0, 236, 0, 0, 0, 
-    237, 0, 0, 238, 0, 0, 0, 239, 0, 0, 240, 0, 241, 242, 0, 243, 0, 244, 0, 
-    0, 245, 0, 0, 0, 0, 0, 246, 247, 0, 248, 0, 249, 0, 0, 250, 0, 251, 0, 0, 
-    0, 252, 0, 253, 0, 0, 254, 0, 255, 256, 0, 257, 0, 258, 259, 260, 261, 
-    262, 263, 264, 0, 265, 266, 0, 267, 268, 0, 0, 0, 269, 0, 0, 270, 0, 0, 
-    0, 0, 0, 0, 271, 272, 0, 273, 274, 0, 0, 0, 275, 0, 276, 0, 0, 0, 277, 
-    278, 279, 280, 281, 0, 0, 0, 282, 0, 0, 283, 284, 0, 285, 0, 286, 0, 0, 
-    287, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 289, 0, 290, 0, 0, 0, 0, 291, 292, 
-    0, 0, 293, 0, 0, 0, 0, 294, 295, 0, 0, 0, 0, 0, 0, 296, 0, 297, 0, 0, 0, 
-    0, 298, 0, 0, 299, 300, 0, 0, 301, 0, 0, 302, 0, 0, 0, 0, 0, 0, 303, 304, 
-    0, 0, 305, 0, 0, 306, 0, 307, 308, 0, 0, 0, 0, 0, 309, 310, 0, 0, 0, 0, 
-    0, 0, 311, 0, 312, 0, 0, 313, 0, 0, 0, 0, 0, 314, 315, 0, 0, 316, 0, 0, 
-    0, 0, 317, 318, 0, 0, 0, 0, 0, 0, 319, 0, 320, 0, 0, 0, 0, 321, 0, 0, 
-    322, 323, 0, 0, 324, 0, 0, 325, 0, 0, 0, 0, 0, 0, 326, 327, 0, 0, 328, 0, 
-    0, 329, 0, 330, 331, 0, 0, 0, 0, 0, 332, 333, 0, 0, 0, 0, 0, 0, 334, 0, 
-    335, 0, 0, 336, 0, 0, 0, 0, 0, 337, 338, 0, 0, 339, 0, 0, 340, 341, 0, 0, 
-    342, 0, 0, 343, 0, 0, 0, 0, 0, 0, 344, 0, 0, 345, 0, 0, 346, 0, 0, 0, 0, 
-    0, 347, 0, 0, 348, 0, 0, 349, 0, 0, 350, 0, 0, 0, 351, 0, 0, 0, 0, 0, 0, 
-    352, 0, 353, 0, 0, 354, 0, 0, 0, 0, 0, 0, 355, 0, 0, 0, 356, 357, 0, 0, 
-    358, 0, 0, 0, 359, 0, 0, 360, 361, 0, 0, 362, 0, 0, 0, 363, 0, 0, 364, 
-    365, 0, 0, 366, 0, 0, 0, 367, 0, 0, 368, 369, 0, 0, 370, 0, 0, 0, 371, 0, 
-    0, 0, 372, 0, 0, 0, 373, 0, 0, 0, 0, 0, 0, 374, 0, 0, 375, 0, 0, 376, 0, 
-    0, 377, 0, 0, 0, 0, 0, 0, 378, 0, 0, 379, 0, 0, 380, 0, 0, 0, 0, 0, 381, 
-    0, 382, 0, 383, 384, 0, 0, 0, 0, 0, 0, 385, 386, 0, 0, 0, 0, 0, 0, 387, 
-    0, 0, 0, 388, 0, 0, 389, 0, 0, 390, 0, 0, 0, 0, 391, 0, 392, 393, 0, 0, 
-    0, 394, 0, 0, 0, 395, 0, 0, 396, 0, 0, 0, 0, 0, 0, 397, 0, 0, 0, 398, 0, 
-    399, 400, 0, 0, 0, 401, 0, 0, 0, 402, 0, 0, 403, 0, 0, 404, 0, 0, 0, 0, 
-    0, 0, 405, 0, 0, 406, 0, 0, 0, 0, 407, 0, 408, 0, 0, 0, 0, 409, 0, 0, 
-    410, 0, 0, 0, 0, 411, 0, 0, 412, 0, 0, 0, 413, 0, 0, 414, 0, 0, 0, 0, 0, 
-    0, 415, 416, 0, 417, 418, 0, 0, 0, 419, 0, 0, 420, 0, 0, 0, 0, 421, 0, 0, 
-    422, 0, 0, 423, 0, 0, 0, 424, 0, 425, 426, 0, 0, 0, 427, 0, 0, 0, 0, 0, 
-    0, 428, 429, 0, 0, 0, 0, 0, 0, 430, 0, 0, 431, 0, 0, 0, 0, 432, 0, 433, 
-    0, 0, 0, 0, 434, 0, 435, 0, 0, 0, 0, 0, 0, 436, 437, 0, 0, 438, 0, 0, 
-    439, 0, 440, 441, 0, 0, 0, 442, 0, 0, 443, 0, 444, 445, 0, 446, 447, 0, 
-    0, 448, 0, 0, 0, 449, 0, 450, 451, 0, 0, 0, 452, 0, 0, 0, 0, 0, 453, 0, 
-    454, 455, 0, 456, 457, 0, 0, 0, 0, 0, 0, 458, 0, 0, 459, 0, 460, 461, 0, 
-    0, 0, 462, 0, 0, 463, 0, 464, 465, 0, 466, 467, 0, 0, 468, 0, 0, 0, 469, 
-    0, 470, 471, 0, 0, 0, 472, 0, 0, 0, 0, 0, 473, 0, 474, 475, 0, 476, 477, 
-    0, 0, 0, 0, 0, 0, 478, 0, 0, 479, 0, 0, 480, 0, 0, 0, 0, 0, 481, 0, 0, 
-    482, 0, 0, 0, 483, 0, 0, 484, 0, 0, 485, 0, 0, 0, 0, 0, 0, 486, 0, 0, 
-    487, 488, 0, 489, 0, 0, 490, 0, 0, 0, 0, 0, 0, 491, 0, 0, 492, 0, 0, 493, 
-    0, 0, 0, 494, 0, 0, 495, 0, 0, 0, 0, 0, 0, 496, 0, 0, 0, 497, 0, 0, 0, 
-    498, 499, 0, 0, 0, 500, 0, 0, 0, 0, 0, 501, 502, 0, 503, 0, 0, 0, 504, 0, 
-    0, 0, 505, 0, 0, 506, 507, 0, 0, 0, 0, 0, 508, 0, 0, 0, 509, 510, 0, 0, 
-    0, 0, 0, 511, 0, 0, 0, 512, 513, 0, 514, 0, 0, 0, 0, 515, 0, 0, 516, 0, 
-    0, 517, 0, 0, 0, 0, 0, 0, 518, 0, 0, 519, 0, 0, 520, 0, 0, 521, 0, 0, 0, 
-    0, 0, 0, 522, 0, 0, 523, 0, 0, 524, 0, 0, 525, 0, 0, 0, 0, 0, 0, 526, 0, 
-    0, 0, 527, 0, 0, 528, 0, 0, 529, 0, 0, 530, 0, 0, 0, 531, 0, 0, 0, 0, 0, 
-    0, 532, 533, 534, 0, 0, 0, 0, 0, 535, 536, 0, 0, 0, 0, 0, 537, 0, 0, 538, 
-    0, 0, 539, 0, 0, 0, 0, 0, 0, 540, 0, 541, 0, 0, 0, 0, 0, 542, 543, 0, 0, 
-    0, 0, 0, 544, 0, 0, 545, 0, 0, 546, 0, 0, 0, 0, 0, 0, 547, 0, 0, 548, 0, 
-    0, 549, 0, 0, 550, 0, 0, 0, 0, 551, 0, 0, 0, 0, 0, 552, 553, 0, 0, 0, 0, 
-    0, 554, 0, 0, 555, 0, 0, 556, 0, 0, 0, 0, 0, 0, 557, 0, 0, 558, 0, 0, 
-    559, 0, 0, 560, 0, 0, 0, 0, 561, 0, 0, 562, 0, 0, 0, 0, 0, 0, 563, 0, 0, 
-    564, 0, 0, 565, 0, 0, 0, 0, 0, 566, 567, 0, 0, 0, 0, 0, 568, 0, 0, 569, 
-    0, 0, 570, 0, 0, 0, 0, 0, 0, 571, 0, 0, 572, 0, 0, 573, 0, 0, 574, 0, 0, 
-    0, 0, 575, 0, 0, 0, 0, 0, 576, 577, 0, 0, 0, 0, 0, 578, 0, 0, 579, 0, 0, 
-    580, 0, 0, 0, 0, 0, 0, 581, 0, 0, 582, 0, 0, 583, 0, 0, 584, 0, 0, 0, 0, 
-    585, 0, 0, 0, 0, 0, 586, 587, 0, 0, 0, 0, 0, 588, 0, 0, 0, 0, 589, 0, 
-    590, 0, 0, 0, 0, 591, 0, 592, 0, 0, 0, 0, 593, 0, 0, 594, 0, 0, 0, 0, 0, 
-    0, 595, 0, 0, 596, 0, 0, 597, 0, 0, 0, 0, 0, 598, 599, 0, 0, 0, 0, 0, 
-    600, 0, 0, 0, 0, 601, 0, 602, 0, 0, 0, 0, 603, 0, 604, 0, 0, 0, 0, 605, 
-    0, 0, 0, 0, 0, 606, 0, 0, 607, 0, 0, 608, 0, 0, 609, 0, 0, 0, 0, 0, 0, 
-    610, 0, 0, 611, 0, 0, 612, 0, 0, 0, 0, 613, 0, 614, 0, 0, 0, 0, 615, 0, 
-    0, 0, 0, 0, 616, 0, 0, 617, 0, 0, 618, 0, 0, 619, 0, 0, 0, 0, 0, 0, 620, 
-    0, 0, 621, 0, 0, 622, 0, 0, 623, 0, 0, 0, 0, 0, 0, 624, 0, 0, 625, 0, 0, 
-    626, 0, 0, 0, 0, 627, 0, 628, 0, 0, 0, 0, 0, 0, 629, 0, 0, 630, 0, 0, 0, 
-    0, 631, 0, 632, 0, 0, 0, 0, 0, 633, 0, 0, 634, 0, 0, 635, 0, 0, 636, 0, 
-    0, 0, 0, 0, 0, 637, 0, 0, 638, 0, 0, 639, 0, 0, 640, 0, 0, 0, 0, 0, 0, 
-    641, 0, 0, 642, 0, 0, 643, 0, 0, 644, 0, 0, 0, 0, 0, 0, 645, 0, 0, 646, 
-    0, 0, 647, 0, 0, 648, 0, 0, 0, 0, 0, 0, 649, 0, 0, 650, 0, 0, 651, 0, 0, 
-    652, 0, 0, 0, 0, 0, 0, 653, 0, 0, 654, 0, 0, 655, 0, 0, 656, 0, 0, 0, 0, 
-    0, 0, 657, 0, 0, 658, 0, 0, 659, 0, 0, 660, 0, 0, 0, 0, 0, 0, 661, 0, 0, 
-    662, 0, 0, 663, 0, 0, 664, 0, 0, 0, 0, 0, 0, 665, 0, 0, 666, 0, 0, 667, 
-    0, 0, 668, 0, 0, 0, 0, 0, 0, 669, 0, 0, 670, 0, 0, 671, 0, 0, 672, 0, 0, 
-    0, 0, 0, 0, 673, 0, 0, 0, 674, 0, 0, 675, 0, 0, 676, 0, 0, 677, 0, 0, 0, 
-    0, 0, 0, 678, 0, 0, 679, 0, 0, 680, 0, 0, 681, 0, 0, 0, 0, 0, 0, 682, 0, 
-    0, 683, 0, 0, 684, 0, 0, 685, 0, 0, 0, 0, 0, 0, 686, 0, 0, 687, 0, 0, 
-    688, 0, 0, 689, 0, 0, 0, 0, 0, 0, 690, 0, 0, 691, 0, 0, 692, 0, 0, 693, 
-    0, 0, 0, 0, 0, 0, 694, 0, 0, 695, 0, 0, 696, 0, 0, 697, 0, 0, 0, 0, 0, 0, 
-    698, 0, 0, 699, 0, 0, 700, 0, 0, 701, 0, 0, 0, 0, 0, 0, 702, 0, 0, 703, 
-    0, 0, 704, 0, 0, 705, 0, 0, 0, 0, 0, 0, 706, 0, 0, 707, 0, 0, 708, 0, 0, 
-    709, 0, 0, 0, 0, 0, 0, 710, 0, 0, 711, 0, 0, 712, 0, 0, 713, 0, 0, 0, 0, 
-    0, 0, 714, 0, 0, 715, 0, 0, 716, 0, 0, 717, 0, 0, 0, 0, 0, 0, 718, 0, 0, 
-    719, 0, 0, 720, 0, 0, 721, 0, 0, 0, 722, 0, 0, 0, 0, 0, 0, 723, 0, 0, 
-    724, 0, 0, 725, 0, 0, 726, 0, 0, 0, 727, 0, 0, 0, 728, 729, 0, 0, 730, 0, 
-    0, 0, 0, 0, 0, 731, 
-};
-
-static const unsigned int comp_data[] = {
-    0, 0, 0, 8814, 0, 8800, 0, 8815, 192, 193, 194, 195, 256, 258, 550, 196, 
-    7842, 197, 0, 461, 512, 514, 0, 7840, 0, 7680, 260, 0, 7682, 0, 0, 7684, 
-    7686, 0, 0, 262, 264, 0, 266, 0, 0, 268, 0, 199, 7690, 0, 0, 270, 0, 
-    7692, 0, 7696, 0, 7698, 7694, 0, 200, 201, 202, 7868, 274, 276, 278, 203, 
-    7866, 0, 0, 282, 516, 518, 0, 7864, 0, 552, 280, 7704, 0, 7706, 7710, 0, 
-    0, 500, 284, 0, 7712, 286, 288, 0, 0, 486, 0, 290, 292, 0, 7714, 7718, 0, 
-    542, 0, 7716, 0, 7720, 7722, 0, 204, 205, 206, 296, 298, 300, 304, 207, 
-    7880, 0, 0, 463, 520, 522, 0, 7882, 302, 0, 0, 7724, 308, 0, 0, 7728, 0, 
-    488, 0, 7730, 0, 310, 7732, 0, 0, 313, 0, 317, 0, 7734, 0, 315, 0, 7740, 
-    7738, 0, 0, 7742, 7744, 0, 0, 7746, 504, 323, 0, 209, 7748, 0, 0, 327, 0, 
-    7750, 0, 325, 0, 7754, 7752, 0, 210, 211, 212, 213, 332, 334, 558, 214, 
-    7886, 0, 336, 465, 524, 526, 416, 7884, 490, 0, 0, 7764, 7766, 0, 0, 340, 
-    7768, 0, 0, 344, 528, 530, 0, 7770, 0, 342, 7774, 0, 0, 346, 348, 0, 
-    7776, 0, 0, 352, 0, 7778, 536, 350, 7786, 0, 0, 356, 0, 7788, 538, 354, 
-    0, 7792, 7790, 0, 217, 218, 219, 360, 362, 364, 0, 220, 7910, 366, 368, 
-    467, 532, 534, 431, 7908, 7794, 0, 370, 7798, 0, 7796, 0, 7804, 0, 7806, 
-    7808, 7810, 372, 0, 7814, 7812, 0, 7816, 7818, 7820, 7922, 221, 374, 
-    7928, 562, 0, 7822, 376, 7926, 0, 0, 7924, 0, 377, 7824, 0, 379, 0, 0, 
-    381, 0, 7826, 7828, 0, 224, 225, 226, 227, 257, 259, 551, 228, 7843, 229, 
-    0, 462, 513, 515, 0, 7841, 0, 7681, 261, 0, 7683, 0, 0, 7685, 7687, 0, 0, 
-    263, 265, 0, 267, 0, 0, 269, 0, 231, 7691, 0, 0, 271, 0, 7693, 0, 7697, 
-    0, 7699, 7695, 0, 232, 233, 234, 7869, 275, 277, 279, 235, 7867, 0, 0, 
-    283, 517, 519, 0, 7865, 0, 553, 281, 7705, 0, 7707, 7711, 0, 0, 501, 285, 
-    0, 7713, 287, 289, 0, 0, 487, 0, 291, 293, 0, 7715, 7719, 0, 543, 0, 
-    7717, 0, 7721, 7723, 0, 7830, 0, 236, 237, 238, 297, 299, 301, 0, 239, 
-    7881, 0, 0, 464, 521, 523, 0, 7883, 303, 0, 0, 7725, 309, 0, 0, 496, 0, 
-    7729, 0, 489, 0, 7731, 0, 311, 7733, 0, 0, 314, 0, 318, 0, 7735, 0, 316, 
-    0, 7741, 7739, 0, 0, 7743, 7745, 0, 0, 7747, 505, 324, 0, 241, 7749, 0, 
-    0, 328, 0, 7751, 0, 326, 0, 7755, 7753, 0, 242, 243, 244, 245, 333, 335, 
-    559, 246, 7887, 0, 337, 466, 525, 527, 417, 7885, 491, 0, 0, 7765, 7767, 
-    0, 0, 341, 7769, 0, 0, 345, 529, 531, 0, 7771, 0, 343, 7775, 0, 0, 347, 
-    349, 0, 7777, 0, 0, 353, 0, 7779, 537, 351, 7787, 7831, 0, 357, 0, 7789, 
-    539, 355, 0, 7793, 7791, 0, 249, 250, 251, 361, 363, 365, 0, 252, 7911, 
-    367, 369, 468, 533, 535, 432, 7909, 7795, 0, 371, 7799, 0, 7797, 0, 7805, 
-    0, 7807, 7809, 7811, 373, 0, 7815, 7813, 0, 7832, 0, 7817, 7819, 7821, 
-    7923, 253, 375, 7929, 563, 0, 7823, 255, 7927, 7833, 0, 7925, 0, 378, 
-    7825, 0, 380, 0, 0, 382, 0, 7827, 7829, 0, 8173, 901, 8129, 0, 7846, 
-    7844, 0, 7850, 7848, 0, 478, 0, 0, 506, 0, 508, 482, 0, 0, 7688, 7872, 
-    7870, 0, 7876, 7874, 0, 0, 7726, 7890, 7888, 0, 7894, 7892, 0, 0, 7756, 
-    556, 0, 0, 7758, 554, 0, 0, 510, 475, 471, 469, 0, 0, 473, 7847, 7845, 0, 
-    7851, 7849, 0, 479, 0, 0, 507, 0, 509, 483, 0, 0, 7689, 7873, 7871, 0, 
-    7877, 7875, 0, 0, 7727, 7891, 7889, 0, 7895, 7893, 0, 0, 7757, 557, 0, 0, 
-    7759, 555, 0, 0, 511, 476, 472, 470, 0, 0, 474, 7856, 7854, 0, 7860, 
-    7858, 0, 7857, 7855, 0, 7861, 7859, 0, 7700, 7702, 7701, 7703, 7760, 
-    7762, 7761, 7763, 7780, 0, 7781, 0, 7782, 0, 7783, 0, 0, 7800, 0, 7801, 
-    0, 7802, 0, 7803, 7835, 0, 7900, 7898, 0, 7904, 7902, 0, 0, 7906, 7901, 
-    7899, 0, 7905, 7903, 0, 0, 7907, 7914, 7912, 0, 7918, 7916, 0, 0, 7920, 
-    7915, 7913, 0, 7919, 7917, 0, 0, 7921, 0, 494, 492, 0, 493, 0, 480, 0, 
-    481, 0, 0, 7708, 0, 7709, 560, 0, 561, 0, 0, 495, 8122, 902, 8121, 8120, 
-    7944, 7945, 0, 8124, 8136, 904, 7960, 7961, 8138, 905, 7976, 7977, 0, 
-    8140, 8154, 906, 8153, 8152, 0, 938, 7992, 7993, 8184, 908, 8008, 8009, 
-    0, 8172, 8170, 910, 8169, 8168, 0, 939, 0, 8025, 8186, 911, 8040, 8041, 
-    0, 8188, 0, 8116, 0, 8132, 8048, 940, 8113, 8112, 7936, 7937, 8118, 8115, 
-    8050, 941, 7952, 7953, 8052, 942, 7968, 7969, 8134, 8131, 8054, 943, 
-    8145, 8144, 0, 970, 7984, 7985, 8150, 0, 8056, 972, 8000, 8001, 8164, 
-    8165, 8058, 973, 8161, 8160, 0, 971, 8016, 8017, 8166, 0, 8060, 974, 
-    8032, 8033, 8182, 8179, 8146, 912, 8151, 0, 8162, 944, 8167, 0, 0, 8180, 
-    0, 979, 0, 980, 0, 1031, 0, 1232, 0, 1234, 0, 1027, 1024, 0, 0, 1238, 0, 
-    1025, 0, 1217, 0, 1244, 0, 1246, 1037, 0, 1250, 1049, 0, 1252, 0, 1036, 
-    0, 1254, 1262, 1038, 0, 1264, 1266, 0, 0, 1268, 0, 1272, 0, 1260, 0, 
-    1233, 0, 1235, 0, 1107, 1104, 0, 0, 1239, 0, 1105, 0, 1218, 0, 1245, 0, 
-    1247, 1117, 0, 1251, 1081, 0, 1253, 0, 1116, 0, 1255, 1263, 1118, 0, 
-    1265, 1267, 0, 0, 1269, 0, 1273, 0, 1261, 0, 1111, 1142, 0, 1143, 0, 0, 
-    1242, 0, 1243, 0, 1258, 0, 1259, 1570, 1571, 1573, 0, 0, 1572, 0, 1574, 
-    0, 1730, 0, 1747, 0, 1728, 0, 2345, 0, 2353, 0, 2356, 2507, 2508, 2891, 
-    2888, 2892, 0, 2964, 0, 0, 3018, 3020, 0, 0, 3019, 0, 3144, 0, 3264, 
-    3274, 3271, 3272, 0, 0, 3275, 0, 3402, 3404, 0, 0, 3403, 0, 3546, 3548, 
-    3550, 0, 3549, 4134, 0, 0, 6918, 0, 6920, 0, 6922, 0, 6924, 0, 6926, 0, 
-    6930, 0, 6971, 0, 6973, 0, 6976, 0, 6977, 0, 6979, 7736, 0, 7737, 0, 
-    7772, 0, 7773, 0, 7784, 0, 7785, 0, 7852, 0, 0, 7862, 7853, 0, 0, 7863, 
-    7878, 0, 7879, 0, 7896, 0, 7897, 0, 7938, 7940, 7942, 8064, 7939, 7941, 
-    7943, 8065, 0, 8066, 0, 8067, 0, 8068, 0, 8069, 0, 8070, 0, 8071, 7946, 
-    7948, 7950, 8072, 7947, 7949, 7951, 8073, 0, 8074, 0, 8075, 0, 8076, 0, 
-    8077, 0, 8078, 0, 8079, 7954, 7956, 7955, 7957, 7962, 7964, 7963, 7965, 
-    7970, 7972, 7974, 8080, 7971, 7973, 7975, 8081, 0, 8082, 0, 8083, 0, 
-    8084, 0, 8085, 0, 8086, 0, 8087, 7978, 7980, 7982, 8088, 7979, 7981, 
-    7983, 8089, 0, 8090, 0, 8091, 0, 8092, 0, 8093, 0, 8094, 0, 8095, 7986, 
-    7988, 7990, 0, 7987, 7989, 7991, 0, 7994, 7996, 7998, 0, 7995, 7997, 
-    7999, 0, 8002, 8004, 8003, 8005, 8010, 8012, 8011, 8013, 8018, 8020, 
-    8022, 0, 8019, 8021, 8023, 0, 8027, 8029, 8031, 0, 8034, 8036, 8038, 
-    8096, 8035, 8037, 8039, 8097, 0, 8098, 0, 8099, 0, 8100, 0, 8101, 0, 
-    8102, 0, 8103, 8042, 8044, 8046, 8104, 8043, 8045, 8047, 8105, 0, 8106, 
-    0, 8107, 0, 8108, 0, 8109, 0, 8110, 0, 8111, 0, 8114, 0, 8130, 0, 8178, 
-    0, 8119, 8141, 8142, 8143, 0, 0, 8135, 0, 8183, 8157, 8158, 8159, 0, 0, 
-    8602, 0, 8603, 0, 8622, 0, 8653, 0, 8655, 0, 8654, 0, 8708, 0, 8713, 0, 
-    8716, 0, 8740, 0, 8742, 0, 8769, 0, 8772, 0, 8775, 0, 8777, 0, 8813, 0, 
-    8802, 0, 8816, 0, 8817, 0, 8820, 0, 8821, 0, 8824, 0, 8825, 0, 8832, 0, 
-    8833, 0, 8928, 0, 8929, 0, 8836, 0, 8837, 0, 8840, 0, 8841, 0, 8930, 0, 
-    8931, 0, 8876, 0, 8877, 0, 8878, 0, 8879, 0, 8938, 0, 8939, 0, 8940, 0, 
-    8941, 12436, 0, 12364, 0, 12366, 0, 12368, 0, 12370, 0, 12372, 0, 12374, 
-    0, 12376, 0, 12378, 0, 12380, 0, 12382, 0, 12384, 0, 12386, 0, 12389, 0, 
-    12391, 0, 12393, 0, 12400, 12401, 12403, 12404, 12406, 12407, 12409, 
-    12410, 12412, 12413, 12446, 0, 12532, 0, 12460, 0, 12462, 0, 12464, 0, 
-    12466, 0, 12468, 0, 12470, 0, 12472, 0, 12474, 0, 12476, 0, 12478, 0, 
-    12480, 0, 12482, 0, 12485, 0, 12487, 0, 12489, 0, 12496, 12497, 12499, 
-    12500, 12502, 12503, 12505, 12506, 12508, 12509, 12535, 0, 12536, 0, 
-    12537, 0, 12538, 0, 12542, 0, 69786, 0, 69788, 0, 69803, 0, 0, 69934, 0, 
-    69935, 70475, 70476, 70844, 70843, 70846, 0, 0, 71098, 0, 71099, 
-};
-
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index d32cace..9ec2d85 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -60,6 +60,7 @@
   return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 static unsigned int
 hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
 				hb_codepoint_t      unicode   HB_UNUSED,
@@ -67,6 +68,7 @@
 {
   return 1;
 }
+#endif
 
 static hb_unicode_general_category_t
 hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
@@ -113,6 +115,7 @@
 }
 
 
+#ifndef HB_DISABLE_DEPRECATED
 static unsigned int
 hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs     HB_UNUSED,
 					hb_codepoint_t      u          HB_UNUSED,
@@ -121,17 +124,18 @@
 {
   return 0;
 }
+#endif
 
 
+extern "C" hb_unicode_funcs_t *hb_ucd_get_unicode_funcs ();
 extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs ();
 extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs ();
-extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs ();
 
 hb_unicode_funcs_t *
 hb_unicode_funcs_get_default ()
 {
-#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_UCDN)
-  return hb_ucdn_get_unicode_funcs ();
+#if !defined(HB_NO_UNICODE_FUNCS) && !defined(HB_NO_UCD)
+  return hb_ucd_get_unicode_funcs ();
 #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB)
   return hb_glib_get_unicode_funcs ();
 #elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
@@ -144,7 +148,7 @@
 
 #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
 #error "Could not find any Unicode functions implementation, you have to provide your own"
-#error "Consider building hb-ucdn.c.  If you absolutely want to build without any, check the code."
+#error "Consider building hb-ucd.cc.  If you absolutely want to build without any, check the code."
 #endif
 
 /**
@@ -425,6 +429,7 @@
   return ufuncs->decompose (ab, a, b);
 }
 
+#ifndef HB_DISABLE_DEPRECATED
 /**
  * hb_unicode_decompose_compatibility:
  * @ufuncs: Unicode functions.
@@ -445,6 +450,7 @@
 {
   return ufuncs->decompose_compatibility (u, decomposed);
 }
+#endif
 
 
 /* See hb-unicode.hh for details. */
diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh
index 82ebb10..80624c0 100644
--- a/src/hb-unicode.hh
+++ b/src/hb-unicode.hh
@@ -42,19 +42,19 @@
 
 #define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
   HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
+  HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (eastasian_width)) \
   HB_UNICODE_FUNC_IMPLEMENT (general_category) \
   HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
   HB_UNICODE_FUNC_IMPLEMENT (script) \
   HB_UNICODE_FUNC_IMPLEMENT (compose) \
   HB_UNICODE_FUNC_IMPLEMENT (decompose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
+  HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility)) \
   /* ^--- Add new callbacks here */
 
 /* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
 #define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
   HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
+  HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width)) \
   HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
   HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
   HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
@@ -89,7 +89,11 @@
   unsigned int decompose_compatibility (hb_codepoint_t  u,
 					hb_codepoint_t *decomposed)
   {
+#ifdef HB_DISABLE_DEPRECATED
+    unsigned int ret  = 0;
+#else
     unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
+#endif
     if (ret == 1 && u == decomposed[0]) {
       decomposed[0] = 0;
       return 0;
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index 4bbbf61..f97ed91 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -698,7 +698,7 @@
       {
         active_feature_t *feature = active_features.find (&event->feature);
 	if (feature)
-	  active_features.remove (feature - active_features.arrayZ ());
+	  active_features.remove (feature - active_features.arrayZ);
       }
     }
 
@@ -728,12 +728,12 @@
 
 #define ALLOCATE_ARRAY(Type, name, len) \
   Type *name = (Type *) scratch; \
-  { \
+  do { \
     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
     assert (_consumed <= scratch_size); \
     scratch += _consumed; \
     scratch_size -= _consumed; \
-  }
+  } while (0)
 
 #define utf16_index() var1.u32
 
@@ -889,8 +889,8 @@
 				     &items[i].a,
 				     script_tags[i],
 				     language_tag,
-				     range_char_counts.arrayZ (),
-				     range_properties.arrayZ (),
+				     range_char_counts.arrayZ,
+				     range_properties.arrayZ,
 				     range_properties.length,
 				     pchars + chars_offset,
 				     item_chars_len,
@@ -930,8 +930,8 @@
 				     &items[i].a,
 				     script_tags[i],
 				     language_tag,
-				     range_char_counts.arrayZ (),
-				     range_properties.arrayZ (),
+				     range_char_counts.arrayZ,
+				     range_properties.arrayZ,
 				     range_properties.length,
 				     pchars + chars_offset,
 				     log_clusters + chars_offset,
@@ -967,7 +967,7 @@
     vis_clusters[i] = (uint32_t) -1;
   for (unsigned int i = 0; i < buffer->len; i++) {
     uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
-    *p = MIN (*p, buffer->info[i].cluster);
+    *p = hb_min (*p, buffer->info[i].cluster);
   }
   for (unsigned int i = 1; i < glyphs_len; i++)
     if (vis_clusters[i] == (uint32_t) -1)
diff --git a/src/hb-vector.hh b/src/hb-vector.hh
index e0b7fb0..de16c97 100644
--- a/src/hb-vector.hh
+++ b/src/hb-vector.hh
@@ -49,35 +49,34 @@
   {
     allocated = o.allocated;
     length = o.length;
-    arrayZ_ = o.arrayZ_;
+    arrayZ = o.arrayZ;
     o.init ();
   }
   ~hb_vector_t () { fini (); }
 
-  unsigned int length;
   private:
   int allocated; /* == -1 means allocation failed. */
-  Type *arrayZ_;
   public:
+  unsigned int length;
+  public:
+  Type *arrayZ;
 
   void init ()
   {
     allocated = length = 0;
-    arrayZ_ = nullptr;
+    arrayZ = nullptr;
   }
 
   void fini ()
   {
-    if (arrayZ_)
-      free (arrayZ_);
+    free (arrayZ);
     init ();
   }
   void fini_deep ()
   {
-    Type *array = arrayZ();
     unsigned int count = length;
     for (unsigned int i = 0; i < count; i++)
-      array[i].fini ();
+      arrayZ[i].fini ();
     fini ();
   }
 
@@ -95,33 +94,31 @@
     fini ();
     allocated = o.allocated;
     length = o.length;
-    arrayZ_ = o.arrayZ_;
+    arrayZ = o.arrayZ;
     o.init ();
     return *this;
   }
 
   hb_bytes_t as_bytes () const
-  { return hb_bytes_t ((const char *) arrayZ(), length * item_size); }
+  { return hb_bytes_t ((const char *) arrayZ, length * item_size); }
 
   bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); }
+  bool operator != (const hb_vector_t &o) const { return !(*this == o); }
   uint32_t hash () const { return as_array ().hash (); }
 
-  const Type * arrayZ () const { return arrayZ_; }
-        Type * arrayZ ()       { return arrayZ_; }
-
   Type& operator [] (int i_)
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= length))
       return Crap (Type);
-    return arrayZ()[i];
+    return arrayZ[i];
   }
   const Type& operator [] (int i_) const
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= length))
       return Null(Type);
-    return arrayZ()[i];
+    return arrayZ[i];
   }
 
   Type& tail () { return (*this)[length - 1]; }
@@ -134,8 +131,8 @@
   template <typename T>
   hb_vector_t& operator << (T&& v) { push (hb_forward<T> (v)); return *this; }
 
-  hb_array_t<      Type> as_array ()       { return hb_array (arrayZ(), length); }
-  hb_array_t<const Type> as_array () const { return hb_array (arrayZ(), length); }
+  hb_array_t<      Type> as_array ()       { return hb_array (arrayZ, length); }
+  hb_array_t<const Type> as_array () const { return hb_array (arrayZ, length); }
 
   /* Iterator. */
   typedef hb_array_t<const Type>   iter_t;
@@ -155,21 +152,21 @@
   { return as_array ().sub_array (start_offset, count);}
 
   hb_sorted_array_t<Type> as_sorted_array ()
-  { return hb_sorted_array (arrayZ(), length); }
+  { return hb_sorted_array (arrayZ, length); }
   hb_sorted_array_t<const Type> as_sorted_array () const
-  { return hb_sorted_array (arrayZ(), length); }
+  { return hb_sorted_array (arrayZ, length); }
 
-  template <typename T> explicit operator T * () { return arrayZ(); }
-  template <typename T> explicit operator const T * () const { return arrayZ(); }
+  template <typename T> explicit operator T * () { return arrayZ; }
+  template <typename T> explicit operator const T * () const { return arrayZ; }
 
-  Type * operator  + (unsigned int i) { return arrayZ() + i; }
-  const Type * operator  + (unsigned int i) const { return arrayZ() + i; }
+  Type * operator  + (unsigned int i) { return arrayZ + i; }
+  const Type * operator  + (unsigned int i) const { return arrayZ + i; }
 
   Type *push ()
   {
     if (unlikely (!resize (length + 1)))
       return &Crap(Type);
-    return &arrayZ()[length - 1];
+    return &arrayZ[length - 1];
   }
   template <typename T>
   Type *push (T&& v)
@@ -202,7 +199,7 @@
       (new_allocated < (unsigned) allocated) ||
       hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
     if (likely (!overflows))
-      new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type));
+      new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
 
     if (unlikely (!new_array))
     {
@@ -210,7 +207,7 @@
       return false;
     }
 
-    arrayZ_ = new_array;
+    arrayZ = new_array;
     allocated = new_allocated;
 
     return true;
@@ -223,7 +220,7 @@
       return false;
 
     if (size > length)
-      memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ()));
+      memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
 
     length = size;
     return true;
@@ -232,16 +229,15 @@
   Type pop ()
   {
     if (!length) return Null(Type);
-    return hb_move (arrayZ()[--length]); /* Does this move actually work? */
+    return hb_move (arrayZ[--length]); /* Does this move actually work? */
   }
 
   void remove (unsigned int i)
   {
     if (unlikely (i >= length))
       return;
-    Type *array = arrayZ();
-    memmove (static_cast<void *> (&array[i]),
-	     static_cast<void *> (&array[i + 1]),
+    memmove (static_cast<void *> (&arrayZ[i]),
+	     static_cast<void *> (&arrayZ[i + 1]),
 	     (length - i - 1) * sizeof (Type));
     length--;
   }
@@ -256,19 +252,17 @@
   template <typename T>
   Type *find (T v)
   {
-    Type *array = arrayZ();
     for (unsigned int i = 0; i < length; i++)
-      if (array[i] == v)
-	return &array[i];
+      if (arrayZ[i] == v)
+	return &arrayZ[i];
     return nullptr;
   }
   template <typename T>
   const Type *find (T v) const
   {
-    const Type *array = arrayZ();
     for (unsigned int i = 0; i < length; i++)
-      if (array[i] == v)
-	return &array[i];
+      if (arrayZ[i] == v)
+	return &arrayZ[i];
     return nullptr;
   }
 
@@ -288,8 +282,8 @@
 template <typename Type>
 struct hb_sorted_vector_t : hb_vector_t<Type>
 {
-  hb_sorted_array_t<      Type> as_array ()       { return hb_sorted_array (this->arrayZ(), this->length); }
-  hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ(), this->length); }
+  hb_sorted_array_t<      Type> as_array ()       { return hb_sorted_array (this->arrayZ, this->length); }
+  hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->length); }
 
   /* Iterator. */
   typedef hb_sorted_array_t<const Type> const_iter_t;
diff --git a/src/hb-version.h b/src/hb-version.h
index 783e37b..1eca37a 100644
--- a/src/hb-version.h
+++ b/src/hb-version.h
@@ -37,10 +37,10 @@
 
 
 #define HB_VERSION_MAJOR 2
-#define HB_VERSION_MINOR 4
-#define HB_VERSION_MICRO 0
+#define HB_VERSION_MINOR 5
+#define HB_VERSION_MICRO 1
 
-#define HB_VERSION_STRING "2.4.0"
+#define HB_VERSION_STRING "2.5.1"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
diff --git a/src/hb-warning.cc b/src/hb-warning.cc
index 9fb4100..60c7445 100644
--- a/src/hb-warning.cc
+++ b/src/hb-warning.cc
@@ -26,12 +26,12 @@
 
 #include "hb.hh"
 
-#if defined(HB_ATOMIC_INT_NIL)
+#ifdef HB_ATOMIC_INT_NIL
 #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
 #error "Check hb-atomic.hh for possible resolutions."
 #endif
 
-#if defined(HB_MUTEX_IMPL_NIL)
+#ifdef HB_MUTEX_IMPL_NIL
 #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
 #error "Check hb-mutex.hh for possible resolutions."
 #endif
diff --git a/src/hb.hh b/src/hb.hh
index 0336ed5..e6d22fe 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -29,8 +29,9 @@
 #ifndef HB_HH
 #define HB_HH
 
+
 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
-#if defined(_MSC_VER)
+#ifdef _MSC_VER
 #pragma warning( disable: 4068 ) /* Unknown pragma */
 #endif
 #if defined(__GNUC__) || defined(__clang__)
@@ -65,6 +66,8 @@
 #pragma GCC diagnostic error   "-Wcast-align"
 #pragma GCC diagnostic error   "-Wcast-function-type"
 #pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
+#pragma GCC diagnostic error   "-Wdouble-promotion"
+#pragma GCC diagnostic error   "-Wextra-semi-stmt"
 #pragma GCC diagnostic error   "-Wformat-security"
 #pragma GCC diagnostic error   "-Wimplicit-function-declaration"
 #pragma GCC diagnostic error   "-Winit-self"
@@ -94,6 +97,7 @@
 /* Warning.  To be investigated if happens. */
 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
 #pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
+#pragma GCC diagnostic warning "-Wdeprecated"
 #pragma GCC diagnostic warning "-Wdisabled-optimization"
 #pragma GCC diagnostic warning "-Wformat=2"
 #pragma GCC diagnostic warning "-Wignored-pragma-optimize"
@@ -121,14 +125,15 @@
 #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #pragma GCC diagnostic ignored "-Wtype-limits"
+#pragma GCC diagnostic ignored "-Wc++11-compat" // only gcc raises it
 #endif
 
 #endif
 #endif
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+
+#include "hb-config.hh"
+
 
 /*
  * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to
@@ -200,7 +205,7 @@
 #define realloc hb_realloc_impl
 #define free hb_free_impl
 
-#if defined(hb_memalign_impl)
+#ifdef hb_memalign_impl
 extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
 #define posix_memalign hb_memalign_impl
 #else
@@ -312,7 +317,7 @@
 #  define HB_FALLTHROUGH /* FALLTHROUGH */
 #endif
 
-#if defined(__clang__)
+#ifdef __clang__
 /* Disable certain sanitizer errors. */
 /* https://github.com/harfbuzz/harfbuzz/issues/1247 */
 #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow")))
@@ -343,19 +348,27 @@
 #  if defined(_WIN32_WCE)
      /* Some things not defined on Windows CE. */
 #    define vsnprintf _vsnprintf
-#    define getenv(Name) nullptr
+#    ifndef HB_NO_GETENV
+#      define HB_NO_GETENV
+#    endif
 #    if _WIN32_WCE < 0x800
 #      define setlocale(Category, Locale) "C"
 static int errno = 0; /* Use something better? */
 #    endif
 #  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#    define getenv(Name) nullptr
+#    ifndef HB_NO_GETENV
+#      define HB_NO_GETENV
+#    endif
 #  endif
 #  if defined(_MSC_VER) && _MSC_VER < 1900
 #    define snprintf _snprintf
 #  endif
 #endif
 
+#ifdef HB_NO_GETENV
+#define getenv(Name) nullptr
+#endif
+
 #if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
 /* atexit() is only safe to be called from shared libraries on certain
  * platforms.  Whitelist.
@@ -434,12 +447,12 @@
  *
  * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
  */
-#if !defined(HB_VECTOR_SIZE)
+#ifndef HB_VECTOR_SIZE
 #  define HB_VECTOR_SIZE 0
 #endif
 
 /* The `vector_size' attribute was introduced in gcc 3.1. */
-#if !defined(HB_VECTOR_SIZE)
+#ifndef HB_VECTOR_SIZE
 #  if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
 #    define HB_VECTOR_SIZE 128
 #  else
@@ -455,16 +468,6 @@
 #endif
 
 
-/* HB_NDEBUG disables some sanity checks that are very safe to disable and
- * should be disabled in production systems.  If NDEBUG is defined, enable
- * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
- * light-weight) to be enabled, then HB_DEBUG can be defined to disable
- * the costlier checks. */
-#ifdef NDEBUG
-#define HB_NDEBUG 1
-#endif
-
-
 /* Flags */
 
 /* Enable bitwise ops on enums marked as flags_t */
diff --git a/src/test-algs.cc b/src/test-algs.cc
index 163a79a..333a892 100644
--- a/src/test-algs.cc
+++ b/src/test-algs.cc
@@ -62,5 +62,30 @@
   A a;
   hb_invoke (&A::a, a);
 
+  assert (1 == hb_min (8, 1));
+  assert (8 == hb_max (8, 1));
+
+  int x = 1, y = 2;
+  hb_min (x, 3);
+  hb_min (3, x);
+  hb_min (x, 4 + 3);
+  int &z = hb_min (x, y);
+  z = 3;
+  assert (x == 3);
+
+  hb_pair_t<const int*, int> xp = hb_pair_t<int *, long> (nullptr, 0);
+  xp = hb_pair_t<int *, double> (nullptr, 1);
+  xp = hb_pair_t<const int*, int> (nullptr, 1);
+
+  assert (3 == hb_partial (hb_min, 3) (4));
+  assert (3 == hb_partial<1> (hb_min, 4) (3));
+
+  auto M0 = hb_partial<2> (hb_max, 0);
+  assert (M0 (-2) == 0);
+  assert (M0 (+2) == 2);
+
+  assert (hb_add (2) (5) == 7);
+  assert (hb_add (5) (2) == 7);
+
   return 0;
 }
diff --git a/src/test-iter.cc b/src/test-iter.cc
index 3de3401..156a5fc 100644
--- a/src/test-iter.cc
+++ b/src/test-iter.cc
@@ -43,6 +43,7 @@
   void __forward__ (unsigned n) { arr += n; }
   void __rewind__ (unsigned n) { arr -= n; }
   unsigned __len__ () const { return arr.length; }
+  bool operator != (const array_iter_t& o) { return arr != o.arr; }
 
   private:
   hb_array_t<T> arr;
@@ -56,7 +57,7 @@
   typedef array_iter_t<T> iter_t;
   array_iter_t<T> iter () { return array_iter_t<T> (arr); }
   operator array_iter_t<T> () { return iter (); }
-  operator hb_iter_t<array_iter_t<T> > () { return iter (); }
+  operator hb_iter_t<array_iter_t<T>> () { return iter (); }
 
   private:
   hb_array_t<T> arr;
@@ -64,14 +65,10 @@
 
 
 template <typename Iter,
-	  hb_enable_if (hb_is_iterator (Iter))>
+	  hb_requires (hb_is_iterator (Iter))>
 static void
-test_iterator (Iter it)
+test_iterator_non_default_constructable (Iter it)
 {
-  Iter default_constructed;
-
-  assert (!default_constructed);
-
   /* Iterate over a copy of it. */
   for (auto c = it.iter (); c; c++)
     *c;
@@ -80,6 +77,10 @@
   for (auto c = +it; c; c++)
     *c;
 
+  /* Range-based for over a copy. */
+  for (auto _ : +it)
+    (void) _;
+
   it += it.len ();
   it = it + 10;
   it = 10 + it;
@@ -90,11 +91,25 @@
   static_assert (true || it.is_sorted_iterator, "");
 }
 
+template <typename Iter,
+	  hb_requires (hb_is_iterator (Iter))>
+static void
+test_iterator (Iter it)
+{
+  Iter default_constructed;
+  assert (!default_constructed);
+
+  test_iterator_non_default_constructable (it);
+}
+
 template <typename Iterable,
-	  hb_enable_if (hb_is_iterable (Iterable))>
+	  hb_requires (hb_is_iterable (Iterable))>
 static void
 test_iterable (const Iterable &lst = Null(Iterable))
 {
+  for (auto _ : lst)
+    (void) _;
+
   // Test that can take iterator from.
   test_iterator (lst.iter ());
 }
@@ -110,7 +125,7 @@
   array_iter_t<const int> s2 (v); /* Implicit conversion from vector. */
   array_iter_t<int> t (dst);
 
-  static_assert (hb_is_random_access_iterator (array_iter_t<int>), "");
+  static_assert (array_iter_t<int>::is_random_access_iterator, "");
 
   some_array_t<const int> a (src);
 
@@ -125,6 +140,7 @@
 
   test_iterable (v);
   hb_set_t st;
+  st << 1 << 15 << 43;
   test_iterable (st);
   hb_sorted_array_t<int> sa;
   (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::item_t>&> (sa);
@@ -134,34 +150,80 @@
   (void) static_cast<hb_iter_t<hb_array_t<int>, int&>&> (sa);
   test_iterable (sa);
 
-  test_iterable<hb_array_t<int> > ();
-  test_iterable<hb_sorted_array_t<const int> > ();
-  test_iterable<hb_vector_t<float> > ();
+  test_iterable<hb_array_t<int>> ();
+  test_iterable<hb_sorted_array_t<const int>> ();
+  test_iterable<hb_vector_t<float>> ();
   test_iterable<hb_set_t> ();
   test_iterable<OT::Coverage> ();
 
   test_iterator (hb_zip (st, v));
+  test_iterator_non_default_constructable (hb_enumerate (st));
+  test_iterator_non_default_constructable (hb_enumerate (st, -5));
+  test_iterator_non_default_constructable (hb_enumerate (hb_iter (st)));
+  test_iterator_non_default_constructable (hb_enumerate (hb_iter (st) + 1));
+  test_iterator_non_default_constructable (hb_iter (st) | hb_filter ());
+  test_iterator_non_default_constructable (hb_iter (st) | hb_map (hb_lidentity));
 
-  hb_any (st);
+  assert (true == hb_all (st));
+  assert (false == hb_all (st, 42u));
+  assert (true == hb_any (st));
+  assert (false == hb_any (st, 14u));
+  assert (true == hb_any (st, 14u, [] (unsigned _) { return _ - 1u; }));
+  assert (true == hb_any (st, [] (unsigned _) { return _ == 15u; }));
+  assert (true == hb_any (st, 15u));
+  assert (false == hb_none (st));
+  assert (false == hb_none (st, 15u));
+  assert (true == hb_none (st, 17u));
 
-  hb_array_t<hb_vector_t<int> > pa;
+  hb_array_t<hb_vector_t<int>> pa;
   pa->as_array ();
 
+  hb_map_t m;
+
+  hb_iter (st);
+  hb_iter (&st);
+
   + hb_iter (src)
-  | hb_map (hb_identity)
+  | hb_map (m)
+  | hb_map (&m)
   | hb_filter ()
+  | hb_filter (st)
+  | hb_filter (&st)
   | hb_filter (hb_bool)
   | hb_filter (hb_bool, hb_identity)
   | hb_sink (st)
   ;
 
   + hb_iter (src)
+  | hb_sink (hb_array (dst))
+  ;
+
+  + hb_iter (src)
   | hb_apply (&st)
   ;
 
   + hb_iter (src)
-  | hb_map ([&] (int i) -> int { return 1; })
-  | hb_reduce ([&] (int acc, int value) -> int { return acc; }, 2)
+  | hb_map ([] (int i) { return 1; })
+  | hb_reduce ([=] (int acc, int value) { return acc; }, 2)
+  ;
+
+  using map_pair_t = hb_item_type<hb_map_t>;
+  + hb_iter (m)
+  | hb_map ([] (map_pair_t p) { return p.first * p.second; })
+  ;
+
+  m.keys ();
+  using map_key_t = decltype (*m.keys());
+  + hb_iter (m.keys ())
+  | hb_filter ([] (map_key_t k) { return k < 42; })
+  | hb_drain
+  ;
+
+  m.values ();
+  using map_value_t = decltype (*m.values());
+  + hb_iter (m.values ())
+  | hb_filter ([] (map_value_t k) { return k < 42; })
+  | hb_drain
   ;
 
   unsigned int temp1 = 10;
@@ -189,8 +251,8 @@
 
   unsigned int temp3 = 0;
   + hb_iter(src)
-  | hb_map([&] (int i) -> int { return ++temp3; })
-  | hb_reduce([&] (float acc, int value) -> float { return acc + value; }, 0)
+  | hb_map([&] (int i) { return ++temp3; })
+  | hb_reduce([&] (float acc, int value) { return acc + value; }, 0)
   ;
   hb_map_destroy (result);
 
@@ -202,5 +264,18 @@
   long vl;
   s >> vl;
 
+  hb_iota ();
+  hb_iota (3);
+  hb_iota (3, 2);
+  hb_range ();
+  assert (hb_range (9).len () == 9);
+  assert (hb_range (2, 9).len () == 7);
+  assert (hb_range (2, 9, 3).len () == 3);
+  assert (hb_range (2, 8, 3).len () == 2);
+  assert (hb_range (2, 7, 3).len () == 2);
+  assert (hb_range (-2, -9, -3).len () == 3);
+  assert (hb_range (-2, -8, -3).len () == 2);
+  assert (hb_range (-2, -7, -3).len () == 2);
+
   return 0;
 }
diff --git a/src/test-meta.cc b/src/test-meta.cc
new file mode 100644
index 0000000..0b6e02c
--- /dev/null
+++ b/src/test-meta.cc
@@ -0,0 +1,128 @@
+/*
+ * Copyright © 2019  Facebook, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Facebook Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+#include "hb-meta.hh"
+
+#include <type_traits>
+
+int
+main (int argc, char **argv)
+{
+  static_assert (hb_is_convertible (void, void), "");
+  static_assert (hb_is_convertible (void, const void), "");
+  static_assert (hb_is_convertible (const void, void), "");
+
+  static_assert (hb_is_convertible (int,  int), "");
+  static_assert (hb_is_convertible (char, int), "");
+  static_assert (hb_is_convertible (long, int), "");
+
+  static_assert (hb_is_convertible (int, int), "");
+
+  static_assert (hb_is_convertible (const int, int), "");
+  static_assert (hb_is_convertible (int, const int), "");
+  static_assert (hb_is_convertible (const int, const int), "");
+
+  static_assert (hb_is_convertible (int&, int), "");
+  static_assert (!hb_is_convertible (int, int&), "");
+
+  static_assert (hb_is_convertible (int, const int&), "");
+  static_assert (!hb_is_convertible (const int, int&), "");
+  static_assert (hb_is_convertible (const int, const int&), "");
+  static_assert (hb_is_convertible (int&, const int), "");
+  static_assert (hb_is_convertible (const int&, int), "");
+  static_assert (hb_is_convertible (const int&, const int), "");
+  static_assert (hb_is_convertible (const int&, const int), "");
+
+  struct X {};
+  struct Y : X {};
+
+  static_assert (hb_is_convertible (const X &, const X), "");
+  static_assert (hb_is_convertible (X &, const X), "");
+  static_assert (hb_is_convertible (X &, const X &), "");
+  static_assert (hb_is_convertible (X, const X &), "");
+  static_assert (hb_is_convertible (const X, const X &), "");
+  static_assert (!hb_is_convertible (const X, X &), "");
+  static_assert (!hb_is_convertible (X, X &), "");
+  static_assert (hb_is_convertible (X &, X &), "");
+
+  static_assert (hb_is_convertible (int&, long), "");
+  static_assert (!hb_is_convertible (int&, long&), "");
+
+  static_assert (hb_is_convertible (int *, int *), "");
+  static_assert (hb_is_convertible (int *, const int *), "");
+  static_assert (!hb_is_convertible (const int *, int *), "");
+  static_assert (!hb_is_convertible (int *, long *), "");
+  static_assert (hb_is_convertible (int *, void *), "");
+  static_assert (!hb_is_convertible (void *, int *), "");
+
+  static_assert (hb_is_base_of (void, void), "");
+  static_assert (hb_is_base_of (void, int), "");
+  static_assert (!hb_is_base_of (int, void), "");
+
+  static_assert (hb_is_base_of (int, int), "");
+  static_assert (hb_is_base_of (const int, int), "");
+  static_assert (hb_is_base_of (int, const int), "");
+
+  static_assert (hb_is_base_of (X, X), "");
+  static_assert (hb_is_base_of (X, Y), "");
+  static_assert (hb_is_base_of (const X, Y), "");
+  static_assert (hb_is_base_of (X, const Y), "");
+  static_assert (!hb_is_base_of (Y, X), "");
+
+  static_assert (hb_is_constructible (int), "");
+  static_assert (hb_is_constructible (int, int), "");
+  static_assert (hb_is_constructible (int, char), "");
+  static_assert (hb_is_constructible (int, long), "");
+  static_assert (!hb_is_constructible (int, X), "");
+  static_assert (!hb_is_constructible (int, int, int), "");
+  static_assert (hb_is_constructible (X), "");
+  static_assert (!hb_is_constructible (X, int), "");
+  static_assert (hb_is_constructible (X, X), "");
+  static_assert (!hb_is_constructible (X, X, X), "");
+  static_assert (hb_is_constructible (X, Y), "");
+  static_assert (!hb_is_constructible (Y, X), "");
+
+  static_assert (hb_is_trivially_default_constructible (X), "");
+  static_assert (hb_is_trivially_default_constructible (Y), "");
+  static_assert (hb_is_trivially_copy_constructible (X), "");
+  static_assert (hb_is_trivially_copy_constructible (Y), "");
+  static_assert (hb_is_trivially_move_constructible (X), "");
+  static_assert (hb_is_trivially_move_constructible (Y), "");
+  static_assert (hb_is_trivially_destructible (Y), "");
+
+  static_assert (hb_is_trivially_copyable (int), "");
+  static_assert (hb_is_trivially_copyable (X), "");
+  static_assert (hb_is_trivially_copyable (Y), "");
+
+  static_assert (hb_is_trivial (int), "");
+  static_assert (hb_is_trivial (X), "");
+  static_assert (hb_is_trivial (Y), "");
+
+  /* TODO Add more meaningful tests. */
+
+  return 0;
+}
diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc
index 4050a66..26931fe 100644
--- a/src/test-ot-color.cc
+++ b/src/test-ot-color.cc
@@ -133,7 +133,7 @@
   unsigned glyph_count = hb_face_get_glyph_count (face);
   for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid)
   {
-    unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, NULL, NULL);
+    unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr);
     if (!num_layers)
       continue;
 
@@ -169,7 +169,7 @@
       unsigned int palette_count = hb_ot_color_palette_get_count (face);
       for (unsigned int palette = 0; palette < palette_count; palette++)
       {
-	unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, NULL, NULL);
+	unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr);
 	if (!num_colors)
 	  continue;
 
@@ -271,14 +271,14 @@
 
 
   FILE *font_name_file = fopen ("out/.dumped_font_name", "r");
-  if (font_name_file != NULL)
+  if (font_name_file != nullptr)
   {
     fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n");
     exit (1);
   }
 
   font_name_file = fopen ("out/.dumped_font_name", "w");
-  if (font_name_file == NULL)
+  if (font_name_file == nullptr)
   {
     fprintf (stderr, "./out is not accessible as a folder, create it please\n");
     exit (1);
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 70a9fda..85f2f6f 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -42,6 +42,7 @@
 	test-shape \
 	test-subset \
 	test-subset-cmap \
+	test-subset-drop-tables \
 	test-subset-glyf \
 	test-subset-hdmx \
 	test-subset-hmtx \
@@ -60,6 +61,7 @@
 
 test_subset_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_cmap_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_drop_tables_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_glyf_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_hdmx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_hmtx_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
diff --git a/test/api/fonts/Roboto-Regular.a.retaingids.ttf b/test/api/fonts/Roboto-Regular.a.retaingids.ttf
new file mode 100644
index 0000000..183b148
--- /dev/null
+++ b/test/api/fonts/Roboto-Regular.a.retaingids.ttf
Binary files differ
diff --git a/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf b/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf
index 906bdbe..fa2a0e4 100644
--- a/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf
+++ b/test/api/fonts/SourceHanSans-Regular.41,4C2E.retaingids.otf
Binary files differ
diff --git a/test/api/fonts/nameID.expected.ttf b/test/api/fonts/nameID.expected.ttf
index ccd4b8b..00aecc0 100644
--- a/test/api/fonts/nameID.expected.ttf
+++ b/test/api/fonts/nameID.expected.ttf
Binary files differ
diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h
index 8f32aee..25cf1e3 100644
--- a/test/api/hb-subset-test.h
+++ b/test/api/hb-subset-test.h
@@ -70,7 +70,7 @@
 {
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_set_t * input_name_ids  = hb_subset_input_nameid_set (input);
-  hb_set_union (input_name_ids, name_ids);
+  hb_set_set (input_name_ids, name_ids);
   return input;
 }
 
@@ -91,9 +91,9 @@
                       hb_tag_t   table)
 {
   hb_blob_t *expected_blob, *actual_blob;
-  //fprintf(stderr, "comparing %c%c%c%c ", HB_UNTAG(table));
   expected_blob = hb_face_reference_table (expected, table);
   actual_blob = hb_face_reference_table (actual, table);
+  fprintf(stderr, "comparing %c%c%c%c, expected %d bytes, actual %d bytes\n", HB_UNTAG(table), hb_blob_get_length(expected_blob), hb_blob_get_length (actual_blob));
   hb_test_assert_blobs_equal (expected_blob, actual_blob);
   hb_blob_destroy (expected_blob);
   hb_blob_destroy (actual_blob);
diff --git a/test/api/hb-test.h b/test/api/hb-test.h
index 872f45c..b866e44 100644
--- a/test/api/hb-test.h
+++ b/test/api/hb-test.h
@@ -173,6 +173,16 @@
   const char *raw_expected = hb_blob_get_data (expected_blob, &expected_length);
   const char *raw_actual = hb_blob_get_data (actual_blob, &actual_length);
   g_assert_cmpint(expected_length, ==, actual_length);
+  if (memcmp (raw_expected, raw_actual, expected_length) != 0)
+  {
+    for (unsigned int i = 0; i < expected_length; i++)
+    {
+      int expected = *(raw_expected + i);
+      int actual = *(raw_actual + i);
+      if (expected != actual) fprintf(stderr, "+%u %02x != %02x\n", i, expected, actual);
+      else fprintf(stderr, "+%u %02x\n", i, expected);
+    }
+  }
   g_assert_cmpint(0, ==, memcmp(raw_expected, raw_actual, expected_length));
 }
 
diff --git a/test/api/test-aat-layout.c b/test/api/test-aat-layout.c
index 1384556..d9dd8a3 100644
--- a/test/api/test-aat-layout.c
+++ b/test/api/test-aat-layout.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2018  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
diff --git a/test/api/test-font.c b/test/api/test-font.c
index 6690194..c6738b4 100644
--- a/test/api/test-font.c
+++ b/test/api/test-font.c
@@ -146,9 +146,6 @@
   glyph = 3;
   g_assert (!hb_font_get_glyph (font, 17, 2, &glyph));
   g_assert_cmpint (glyph, ==, 0);
-
-  x = hb_font_get_glyph_h_kerning (font, 17, 19);
-  g_assert_cmpint (x, ==, 0);
 }
 
 static void
diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c
index 7f50015..000b0a2 100644
--- a/test/api/test-ot-math.c
+++ b/test/api/test-ot-math.c
@@ -629,19 +629,19 @@
   g_assert_cmpint(parts[0].start_connector_length, ==, 800);
   g_assert_cmpint(parts[0].end_connector_length, ==, 384);
   g_assert_cmpint(parts[0].full_advance, ==, 2000);
-  g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(!(parts[0].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
   g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph));
   g_assert_cmpint(parts[1].glyph, ==, glyph);
   g_assert_cmpint(parts[1].start_connector_length, ==, 524);
   g_assert_cmpint(parts[1].end_connector_length, ==, 800);
   g_assert_cmpint(parts[1].full_advance, ==, 2000);
-  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
+  g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER);
   g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph));
   g_assert_cmpint(parts[2].glyph, ==, glyph);
   g_assert_cmpint(parts[2].start_connector_length, ==, 316);
   g_assert_cmpint(parts[2].end_connector_length, ==, 454);
   g_assert_cmpint(parts[2].full_advance, ==, 2000);
-  g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(!(parts[2].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
 
   g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph));
   offset = 0;
@@ -662,20 +662,20 @@
   g_assert_cmpint(parts[0].start_connector_length, ==, 365);
   g_assert_cmpint(parts[0].end_connector_length, ==, 158);
   g_assert_cmpint(parts[0].full_advance, ==, 1000);
-  g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(!(parts[0].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
   g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
   g_assert_cmpint(parts[1].glyph, ==, glyph);
   g_assert_cmpint(parts[1].glyph, ==, glyph);
   g_assert_cmpint(parts[1].start_connector_length, ==, 227);
   g_assert_cmpint(parts[1].end_connector_length, ==, 365);
   g_assert_cmpint(parts[1].full_advance, ==, 1000);
-  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
+  g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER);
   g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph));
   g_assert_cmpint(parts[2].glyph, ==, glyph);
   g_assert_cmpint(parts[2].start_connector_length, ==, 54);
   g_assert_cmpint(parts[2].end_connector_length, ==, 158);
   g_assert_cmpint(parts[2].full_advance, ==, 1000);
-  g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(!(parts[2].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
   g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph));
   g_assert_cmpint(parts[3].glyph, ==, glyph);
   g_assert_cmpint(parts[3].glyph, ==, glyph);
@@ -683,13 +683,13 @@
   g_assert_cmpint(parts[3].start_connector_length, ==, 400);
   g_assert_cmpint(parts[3].end_connector_length, ==, 296);
   g_assert_cmpint(parts[3].full_advance, ==, 1000);
-  g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER);
+  g_assert(parts[1].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER);
   g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph));
   g_assert_cmpint(parts[4].glyph, ==, glyph);
   g_assert_cmpint(parts[4].start_connector_length, ==, 123);
   g_assert_cmpint(parts[4].end_connector_length, ==, 192);
   g_assert_cmpint(parts[4].full_advance, ==, 1000);
-  g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER));
+  g_assert(!(parts[4].flags & HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER));
 
   closeFont();
 
diff --git a/test/api/test-shape.c b/test/api/test-shape.c
index 146cf0f..8fbe7f7 100644
--- a/test/api/test-shape.c
+++ b/test/api/test-shape.c
@@ -67,17 +67,6 @@
   return FALSE;
 }
 
-static hb_position_t
-glyph_h_kerning_func (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED,
-		      hb_codepoint_t left, hb_codepoint_t right,
-		      void *user_data HB_UNUSED)
-{
-  if (left == 1 && right == 2)
-    return -2;
-
-  return 0;
-}
-
 static const char TesT[] = "TesT";
 
 static void
@@ -102,7 +91,6 @@
   ffuncs = hb_font_funcs_create ();
   hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL);
   hb_font_funcs_set_nominal_glyph_func (ffuncs, glyph_func, malloc (10), free);
-  hb_font_funcs_set_glyph_h_kerning_func (ffuncs, glyph_h_kerning_func, NULL, NULL);
   hb_font_set_funcs (font, ffuncs, NULL, NULL);
   hb_font_funcs_destroy (ffuncs);
 
@@ -118,8 +106,8 @@
 
   {
     const hb_codepoint_t output_glyphs[] = {1, 2, 3, 1};
-    const hb_position_t output_x_advances[] = {9, 5, 5, 10};
-    const hb_position_t output_x_offsets[] = {0, -1, 0, 0};
+    const hb_position_t output_x_advances[] = {10, 6, 5, 10};
+    const hb_position_t output_x_offsets[] = {0, 0, 0, 0};
     unsigned int i;
     g_assert_cmpint (len, ==, 4);
     for (i = 0; i < len; i++) {
diff --git a/test/api/test-subset-drop-tables.c b/test/api/test-subset-drop-tables.c
new file mode 100644
index 0000000..e234080
--- /dev/null
+++ b/test/api/test-subset-drop-tables.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2019  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+/* Unit tests for hb-subset.cc drop tables functionality */
+
+static void
+test_subset_drop_tables (void)
+{
+  hb_face_t *face = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+
+  hb_set_t *codepoints = hb_set_create();
+  hb_set_add (codepoints, 97);
+  hb_set_add (codepoints, 99);
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG ('h', 'd', 'm', 'x'));
+  hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG ('h', 'm', 't', 'x'));
+  hb_set_destroy (codepoints);
+
+  hb_face_t* subset = hb_subset (face, input);
+
+  hb_blob_t *hdmx = hb_face_reference_table (subset, HB_TAG ('h', 'd', 'm', 'x'));
+  hb_blob_t *hmtx = hb_face_reference_table (subset, HB_TAG ('h', 'm', 't', 'x'));
+  hb_blob_t *cmap = hb_face_reference_table (subset, HB_TAG ('c', 'm', 'a', 'p'));
+  g_assert (!hb_blob_get_length (hdmx));
+  g_assert (!hb_blob_get_length (hmtx));
+  g_assert ( hb_blob_get_length (cmap));
+  hb_blob_destroy (hdmx);
+  hb_blob_destroy (hmtx);
+  hb_blob_destroy (cmap);
+
+  hb_face_destroy (subset);
+  hb_subset_input_destroy (input);
+  hb_face_destroy (face);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_subset_drop_tables);
+
+  return hb_test_run();
+}
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index 4671156..2b330ce 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -70,9 +70,9 @@
   face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
-  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
-  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
   check_maxp_num_glyphs(face_abc_subset, 3, true);
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
 
   hb_face_destroy (face_abc_subset);
   hb_face_destroy (face_abc);
@@ -137,7 +137,9 @@
 
   input = hb_subset_test_create_input (codepoints);
   hb_set_destroy (codepoints);
-  hb_subset_input_set_drop_layout (input, false);
+  hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'S', 'U', 'B'));
+  hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'P', 'O', 'S'));
+  hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'D', 'E', 'F'));
 
   face_subset = hb_subset_test_create_subset (face_fil, input);
 
@@ -164,7 +166,9 @@
 
   input = hb_subset_test_create_input (codepoints);
   hb_set_destroy (codepoints);
-  hb_subset_input_set_drop_layout (input, true);
+  hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'S', 'U', 'B'));
+  hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'P', 'O', 'S'));
+  hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'D', 'E', 'F'));
 
   face_subset = hb_subset_test_create_subset (face_fil, input);
 
@@ -190,9 +194,9 @@
   face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
-  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('g','l','y','f'));
-  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('l','o','c', 'a'));
   check_maxp_num_glyphs(face_abc_subset, 4, true);
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('l','o','c', 'a'));
+  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('g','l','y','f'));
 
   hb_face_destroy (face_abc_subset);
   hb_face_destroy (face_abc);
@@ -214,9 +218,9 @@
   face_abc_subset = hb_subset_test_create_subset (face_abc, input);
   hb_set_destroy (codepoints);
 
+  check_maxp_num_glyphs(face_abc_subset, 3, false);
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
-  check_maxp_num_glyphs(face_abc_subset, 3, false);
 
   hb_face_destroy (face_abc_subset);
   hb_face_destroy (face_abc);
@@ -239,9 +243,9 @@
   face_generated_subset = hb_subset_test_create_subset (face_components, input);
   hb_set_destroy (codepoints);
 
-  hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f'));
-  hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('l','o','c', 'a'));
   check_maxp_num_glyphs(face_generated_subset, 4, false);
+  hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('l','o','c', 'a'));
+  hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f'));
 
   hb_face_destroy (face_generated_subset);
   hb_face_destroy (face_subset);
@@ -296,15 +300,39 @@
   face_abc_subset = hb_subset_test_create_subset (face_abc, input);
   hb_set_destroy (codepoints);
 
-  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
-  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
   check_maxp_num_glyphs(face_abc_subset, 4, true);
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
 
   hb_face_destroy (face_abc_subset);
   hb_face_destroy (face_abc);
   hb_face_destroy (face_ac);
 }
 
+static void
+test_subset_glyf_retain_gids_truncates (void)
+{
+  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_a = hb_test_open_font_file ("fonts/Roboto-Regular.a.retaingids.ttf");
+
+  hb_set_t *codepoints = hb_set_create();
+  hb_face_t *face_abc_subset;
+  hb_set_add (codepoints, 97);
+
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  hb_subset_input_set_retain_gids (input, true);
+  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  check_maxp_num_glyphs(face_abc_subset, 2, true);
+  hb_subset_test_check (face_a, face_abc_subset, HB_TAG ('l','o','c', 'a'));
+  hb_subset_test_check (face_a, face_abc_subset, HB_TAG ('g','l','y','f'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_a);
+}
+
 // TODO(grieger): test for long loca generation.
 
 int
@@ -322,6 +350,7 @@
   hb_test_add (test_subset_glyf_with_gsub);
   hb_test_add (test_subset_glyf_without_gsub);
   hb_test_add (test_subset_glyf_retain_gids);
+  hb_test_add (test_subset_glyf_retain_gids_truncates);
 
   return hb_test_run();
 }
diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c
index 44e579a..7178833 100644
--- a/test/api/test-subset-hdmx.c
+++ b/test/api/test-subset-hdmx.c
@@ -92,28 +92,6 @@
 }
 
 static void
-test_subset_hdmx_fails_sanitize (void)
-{
-  hb_face_t *face = hb_test_open_font_file ("../fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016");
-
-  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
-  hb_set_t *codepoints = hb_subset_input_unicode_set (input);
-  hb_face_t *subset;
-
-  hb_set_add (codepoints, 'a');
-  hb_set_add (codepoints, 'b');
-  hb_set_add (codepoints, 'c');
-
-  subset = hb_subset (face, input);
-  g_assert (subset);
-  g_assert (subset == hb_face_get_empty ());
-
-  hb_subset_input_destroy (input);
-  hb_face_destroy (subset);
-  hb_face_destroy (face);
-}
-
-static void
 test_subset_hdmx_noop (void)
 {
   hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
@@ -140,7 +118,6 @@
   hb_test_add (test_subset_hdmx_simple_subset);
   hb_test_add (test_subset_hdmx_multiple_device_records);
   hb_test_add (test_subset_hdmx_invalid);
-  hb_test_add (test_subset_hdmx_fails_sanitize);
   hb_test_add (test_subset_hdmx_noop);
 
   return hb_test_run();
diff --git a/test/api/test-unicode.c b/test/api/test-unicode.c
index 6195bb2..0587c6e 100644
--- a/test/api/test-unicode.c
+++ b/test/api/test-unicode.c
@@ -755,6 +755,10 @@
   g_assert (hb_unicode_compose (uf, 0xCE20, 0x11B8, &ab) && ab == 0xCE31);
   g_assert (hb_unicode_compose (uf, 0x110E, 0x1173, &ab) && ab == 0xCE20);
 
+  g_assert (!hb_unicode_compose (uf, 0xAC00, 0x11A7, &ab));
+  g_assert (hb_unicode_compose (uf, 0xAC00, 0x11A8, &ab) && ab == 0xAC01);
+  g_assert (!hb_unicode_compose (uf, 0xAC01, 0x11A8, &ab));
+
 
   /* Test decompose() */
 
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5702671124791296 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5702671124791296
new file mode 100644
index 0000000..9ecc7f1
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5702671124791296
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-6252118652092416 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-6252118652092416
new file mode 100644
index 0000000..e2dd6a3
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-6252118652092416
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5077547978588160 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5077547978588160
new file mode 100644
index 0000000..37bb009
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5077547978588160
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5634197349203968 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5634197349203968
new file mode 100644
index 0000000..39e8bd9
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5634197349203968
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5676773460672512 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5676773460672512
new file mode 100644
index 0000000..4fc920b
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5676773460672512
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696825891225600 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696825891225600
new file mode 100644
index 0000000..30515a4
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5696825891225600
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5761434614497280 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5761434614497280
new file mode 100644
index 0000000..0060ade
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5761434614497280
Binary files differ
diff --git a/test/fuzzing/hb-shape-fuzzer.cc b/test/fuzzing/hb-shape-fuzzer.cc
index 5723db9..64a6b12 100644
--- a/test/fuzzing/hb-shape-fuzzer.cc
+++ b/test/fuzzing/hb-shape-fuzzer.cc
@@ -10,7 +10,7 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
   hb_blob_t *blob = hb_blob_create ((const char *)data, size,
-				    HB_MEMORY_MODE_READONLY, NULL, NULL);
+				    HB_MEMORY_MODE_READONLY, nullptr, nullptr);
   hb_face_t *face = hb_face_create (blob, 0);
   hb_font_t *font = hb_font_create (face);
   hb_ot_font_set_funcs (font);
@@ -21,7 +21,7 @@
     hb_buffer_t *buffer = hb_buffer_create ();
     hb_buffer_add_utf8 (buffer, text, -1, 0, -1);
     hb_buffer_guess_segment_properties (buffer);
-    hb_shape (font, buffer, NULL, 0);
+    hb_shape (font, buffer, nullptr, 0);
     hb_buffer_destroy (buffer);
   }
 
@@ -34,7 +34,7 @@
   hb_buffer_t *buffer = hb_buffer_create ();
   hb_buffer_add_utf32 (buffer, text32, sizeof (text32) / sizeof (text32[0]), 0, -1);
   hb_buffer_guess_segment_properties (buffer);
-  hb_shape (font, buffer, NULL, 0);
+  hb_shape (font, buffer, nullptr, 0);
   hb_buffer_destroy (buffer);
 
   /* Misc calls on face. */
diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index 56ffd22..73c95b2 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -16,10 +16,16 @@
 {
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
   hb_subset_input_set_drop_hints (input, drop_hints);
-  hb_subset_input_set_drop_layout (input, drop_layout);
   hb_subset_input_set_retain_gids (input, retain_gids);
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
 
+  if (!drop_layout)
+  {
+    hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'S', 'U', 'B'));
+    hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'P', 'O', 'S'));
+    hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'D', 'E', 'F'));
+  }
+
   for (int i = 0; i < text_length; i++)
   {
     hb_set_add (codepoints, text[i]);
@@ -47,7 +53,7 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
   hb_blob_t *blob = hb_blob_create ((const char *)data, size,
-				    HB_MEMORY_MODE_READONLY, NULL, NULL);
+				    HB_MEMORY_MODE_READONLY, nullptr, nullptr);
   hb_face_t *face = hb_face_create (blob, 0);
 
   /* Just test this API here quickly. */
diff --git a/test/fuzzing/main.cc b/test/fuzzing/main.cc
index f15247c..5318f64 100644
--- a/test/fuzzing/main.cc
+++ b/test/fuzzing/main.cc
@@ -4,8 +4,10 @@
 #include <stdlib.h>
 #include <assert.h>
 
-int main(int argc, char **argv) {
+int main (int argc, char **argv)
+{
   hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
+
   unsigned int len;
   const char *font_data = hb_blob_get_data (blob, &len);
   if (len == 0)
@@ -14,10 +16,13 @@
     exit (1);
   }
 
-  for (int i = 1; i < argc; i++) {
+  for (int i = 1; i < argc; i++)
+  {
     printf ("%s\n", argv[i]);
-    LLVMFuzzerTestOneInput((const uint8_t *) font_data, len);
+    LLVMFuzzerTestOneInput ((const uint8_t *) font_data, len);
   }
 
   hb_blob_destroy (blob);
+
+  return 0;
 }
diff --git a/test/shaping/data/in-house/fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf b/test/shaping/data/in-house/fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf
new file mode 100644
index 0000000..945d698
--- /dev/null
+++ b/test/shaping/data/in-house/fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf
Binary files differ
diff --git a/test/shaping/data/in-house/tests/use-syllable.tests b/test/shaping/data/in-house/tests/use-syllable.tests
index 6a247ed..9056008 100644
--- a/test/shaping/data/in-house/tests/use-syllable.tests
+++ b/test/shaping/data/in-house/tests/use-syllable.tests
@@ -10,3 +10,7 @@
 ../fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf::U+11013,U+11044,U+11046:[brm_KA=0+754|brm_vowelOO=0@-647,0+0|brm_virama=0@-524,0+0]
 ../fonts/28f497629c04ceb15546c9a70e0730125ed6698d.ttf::U+11013,U+1103C:[brm_KA=0+754|brm_vowelU=0@-403,0+0]
 ../fonts/86cdd983c4e4c4d7f27dd405d6ceb7d4b9ed3d35.ttf::U+111C8,U+111C9,U+111C9:[u111C8=0+500|u111C9=0@-500,0+0|u111C9=0@-500,0+0]
+../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A5A,U+1A63:[uni1A3D=0+250|uni1A5A=0+0|uni1A63=0+250]
+../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A60,U+1A3D,U+1A63,U+1A60,U+1A3D,U+1A59:[uni1A3D=0+250|uni1A60=0+0|uni1A3D=2+250|uni1A63=2+250|uni1A60=2+0|uni1A3D=5+250|uni1A59=5+0]
+../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A60,U+1A3D,U+1A63,U+1A60,U+1A3D,U+1A5A:[uni1A3D=0+250|uni1A60=0+0|uni1A3D=2+250|uni1A63=2+250|uni1A60=2+0|uni1A3D=5+250|uni25CC=5+250|uni1A5A=5+0]
+../fonts/3cc01fede4debd4b7794ccb1b16cdb9987ea7571.ttf::U+1A3D,U+1A60,U+1A3D,U+1A63,U+1A60,U+1A3D,U+1A60:[uni1A3D=0+250|uni1A60=0+0|uni1A3D=2+250|uni1A63=2+250|uni1A60=2+0|uni1A3D=5+250|uni1A60=5+0]
diff --git a/test/shaping/record-test.sh b/test/shaping/record-test.sh
index 4ab74f0..7f24354 100755
--- a/test/shaping/record-test.sh
+++ b/test/shaping/record-test.sh
@@ -2,6 +2,17 @@
 
 dir=`mktemp -d`
 
+if which sha1sum 2>/dev/null >/dev/null; then
+	SHA1SUM=sha1sum
+elif which shasum 2>/dev/null >/dev/null; then
+	SHA1SUM='shasum -a 1'
+elif which digest 2>/dev/null >/dev/null; then
+	SHA1SUM='digest -a sha1'
+else
+	echo "'sha1sum' not found"
+	exit 2
+fi
+
 out=/dev/stdout
 if test "x$1" == 'x-o'; then
 	shift
@@ -90,7 +101,7 @@
 	glyphs=$glyphs_subset
 fi
 
-sha1sum=`sha1sum "$dir/font.subset.ttf" | cut -d' ' -f1`
+sha1sum=`$SHA1SUM "$dir/font.subset.ttf" | cut -d' ' -f1`
 subset="data/in-house/fonts/$sha1sum.ttf"
 mv "$dir/font.subset.ttf" "$subset"
 
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index 0677120..3439588 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -10,6 +10,7 @@
 	expected/basics \
 	expected/full-font \
 	expected/japanese \
+	expected/layout \
 	fonts \
 	profiles \
 	$(NULL)
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index dd1bcfe..75913fd 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -2,6 +2,7 @@
 	tests/basics.tests \
 	tests/full-font.tests \
 	tests/japanese.tests \
+	tests/layout.tests \
 	$(NULL)
 
 XFAIL_TESTS = \
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf
new file mode 100644
index 0000000..efe5bcb
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf
new file mode 100644
index 0000000..8e12241
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf
new file mode 100644
index 0000000..bd802a5
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf
new file mode 100644
index 0000000..9fbebb5
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf
new file mode 100644
index 0000000..7391741
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf
new file mode 100644
index 0000000..05d83d8
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf
new file mode 100644
index 0000000..f47887e
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf
new file mode 100644
index 0000000..bfa9267
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf
new file mode 100644
index 0000000..8c12158
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf
new file mode 100644
index 0000000..6a47c39
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf
new file mode 100644
index 0000000..36a4b9a
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf
new file mode 100644
index 0000000..251794c
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf
new file mode 100644
index 0000000..9e65c83
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf
new file mode 100644
index 0000000..ada1649
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf
new file mode 100644
index 0000000..6b0dc6c
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf
new file mode 100644
index 0000000..90e49be
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf
new file mode 100644
index 0000000..5277d15
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf
new file mode 100644
index 0000000..de06660
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf
new file mode 100644
index 0000000..effad7b
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf
new file mode 100644
index 0000000..21c8205
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf
new file mode 100644
index 0000000..3c0f4cd
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf
new file mode 100644
index 0000000..a5ce9e0
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf
new file mode 100644
index 0000000..1b84335
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf
new file mode 100644
index 0000000..97eaa26
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf
new file mode 100644
index 0000000..f42edb7
--- /dev/null
+++ b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.63.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf
index 1a0d5bd..128eae0 100644
--- a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf
+++ b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf
index 257184b..2d2b65b 100644
--- a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf
+++ b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf
index d3a67ea..a699eea 100644
--- a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf
+++ b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.61.ttf
Binary files differ
diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf
index 4ff6e33..eb84f9c 100644
--- a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf
+++ b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.62.ttf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf
index 1bd287d..f0ea3ca 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf
index 328c6ee..7ea55a2 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf
index 4602847..07b9aa2 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.default.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf
index ca54654..8ce5fdb 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf
index 0f52e66..a1487ff 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf
index 170c151..9168bc8 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf
index 18a9bcc..cf0fbf6 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf
index edd389b..8ab8294 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf
index 65fa1da..de475e6 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.desubroutinize.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf
index 87c8f00..7cca489 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf
index f381f13..06f0c1f 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf
index f32a1fc..556861c 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize-retain-gids.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf
index 604e140..cf3228d 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf
index 419dfa0..1bafff1 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf
index 8055328..34303e7 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-desubroutinize.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf
index 9a5c09a..5177c14 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf
index f5b4ebd..c70b82a 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf
index 57f9a8d..b14b3eb 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints-retain-gids.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf
index 53109e2..112dec7 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf
index dd908c2..929c4e2 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf
index 5422d32..939a565 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.drop-hints.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf
index 2caee79..02529e3 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.1FC,21,41,20,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf
index b428a7b..76e5cc5 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.61,62,63.otf
Binary files differ
diff --git a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf
index ccb4428..a1178c2 100644
--- a/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf
+++ b/test/subset/data/expected/cff-full-font/SourceSansPro-Regular.retain-gids.D7,D8,D9,DA,DE.otf
Binary files differ
diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf
index 93efe65..e8b7b37 100644
--- a/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf
+++ b/test/subset/data/expected/full-font/Roboto-Regular.default.1FC,21,41,20,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf
index d4d26d7..912e1fb 100644
--- a/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf
+++ b/test/subset/data/expected/full-font/Roboto-Regular.default.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf
index 7e271f2..6f19df6 100644
--- a/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf
+++ b/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf
index 99b91bd..9ea42ab 100644
--- a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf
+++ b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.1FC,21,41,20,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf
index eb94906..4d12593 100644
--- a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf
+++ b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.61,62,63.ttf
Binary files differ
diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf
index ff361ba..281b475 100644
--- a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf
+++ b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf
index 3398999..6770dac 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,3048,304A,304B.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf
index 66b98a6..0c66219 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.default.3042,3044,3046,73E0,5EA6,8F38.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf
index 22d1bb3..4a5a6f8 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.default.61,63,65,6B.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf
index 2804359..465ce34 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E,6975,73E0,5EA6,8F38,6E05.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf
index 333ca51..28f3c37 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.default.660E.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf
index c84b20c..1bebda7 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,3048,304A,304B.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf
index e757b9e..a43998d 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.3042,3044,3046,73E0,5EA6,8F38.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf
index e869ff1..34c7788 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.61,63,65,6B.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf
index ed4ed4c..92ec10b 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E,6975,73E0,5EA6,8F38,6E05.ttf
Binary files differ
diff --git a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf
index cb50238..b9bb539 100644
--- a/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf
+++ b/test/subset/data/expected/japanese/Mplus1p-Regular.drop-hints.660E.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,42,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,42,43.ttf
new file mode 100644
index 0000000..aa007ba
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,42,43.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,43.ttf
new file mode 100644
index 0000000..f3be30c
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41,43.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41.ttf
new file mode 100644
index 0000000..44c329e
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.41.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.43.ttf
new file mode 100644
index 0000000..b0a1ea3
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.43.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.CA,CB.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.CA,CB.ttf
new file mode 100644
index 0000000..16ad9d5
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout-retain-gids.CA,CB.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,42,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,42,43.ttf
new file mode 100644
index 0000000..d0d9d5a
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,42,43.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,43.ttf
new file mode 100644
index 0000000..f4d881f
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41,43.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41.ttf
new file mode 100644
index 0000000..9e6dd28
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.41.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.43.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.43.ttf
new file mode 100644
index 0000000..50260c5
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.43.ttf
Binary files differ
diff --git a/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.CA,CB.ttf b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.CA,CB.ttf
new file mode 100644
index 0000000..22d5b61
--- /dev/null
+++ b/test/subset/data/expected/layout/Roboto-Regular.smallcaps.keep-layout.CA,CB.ttf
Binary files differ
diff --git a/test/subset/data/fonts/Comfortaa-Regular-new.ttf b/test/subset/data/fonts/Comfortaa-Regular-new.ttf
new file mode 100644
index 0000000..4965fbe
--- /dev/null
+++ b/test/subset/data/fonts/Comfortaa-Regular-new.ttf
Binary files differ
diff --git a/test/subset/data/fonts/Roboto-Regular.smallcaps.ttf b/test/subset/data/fonts/Roboto-Regular.smallcaps.ttf
new file mode 100644
index 0000000..fc58299
--- /dev/null
+++ b/test/subset/data/fonts/Roboto-Regular.smallcaps.ttf
Binary files differ
diff --git a/test/subset/data/profiles/keep-layout-retain-gids.txt b/test/subset/data/profiles/keep-layout-retain-gids.txt
new file mode 100644
index 0000000..f4787ad
--- /dev/null
+++ b/test/subset/data/profiles/keep-layout-retain-gids.txt
@@ -0,0 +1,2 @@
+--drop-tables-=GSUB,GPOS
+--retain-gids
diff --git a/test/subset/data/profiles/keep-layout.txt b/test/subset/data/profiles/keep-layout.txt
new file mode 100644
index 0000000..56da0ff
--- /dev/null
+++ b/test/subset/data/profiles/keep-layout.txt
@@ -0,0 +1 @@
+--drop-tables-=GSUB,GPOS
diff --git a/test/subset/data/tests/basics.tests b/test/subset/data/tests/basics.tests
index 794510d..c310722 100644
--- a/test/subset/data/tests/basics.tests
+++ b/test/subset/data/tests/basics.tests
@@ -1,5 +1,6 @@
 FONTS:
 Roboto-Regular.abc.ttf
+Comfortaa-Regular-new.ttf
 
 PROFILES:
 default.txt
diff --git a/test/subset/data/tests/full-font.tests b/test/subset/data/tests/full-font.tests
index 28ae084..d9519b6 100644
--- a/test/subset/data/tests/full-font.tests
+++ b/test/subset/data/tests/full-font.tests
@@ -10,4 +10,3 @@
 abc
 Ǽ!A bc
 ×ØÙÚÞ
-
diff --git a/test/subset/data/tests/layout.tests b/test/subset/data/tests/layout.tests
new file mode 100644
index 0000000..dd1c26e
--- /dev/null
+++ b/test/subset/data/tests/layout.tests
@@ -0,0 +1,13 @@
+FONTS:
+Roboto-Regular.smallcaps.ttf
+
+PROFILES:
+keep-layout.txt
+keep-layout-retain-gids.txt
+
+SUBSETS:
+ABC
+AC
+C
+A
+ÊË
diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py
index 6d11cbf..6c65627 100755
--- a/test/subset/generate-expected-outputs.py
+++ b/test/subset/generate-expected-outputs.py
@@ -19,14 +19,14 @@
 
 def generate_expected_output(input_file, unicodes, profile_flags, output_path):
 	args = ["fonttools", "subset", input_file]
-	args.extend(profile_flags)
 	args.extend(["--notdef-outline",
-		     "--name-IDs=*",
 		     "--name-languages=*",
 		     "--name-legacy",
-		     "--drop-tables+=DSIG,GPOS,GSUB,GDEF",
+                     "--layout-features=*",
+		     "--drop-tables+=DSIG,GPOS,GSUB,GDEF,gvar,avar,MVAR,HVAR",
 		     "--unicodes=%s" % unicodes,
 		     "--output-file=%s" % output_path])
+	args.extend(profile_flags)
 	check_call(args)
 
 
diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py
index fb4684c..5d221e6 100755
--- a/test/subset/run-tests.py
+++ b/test/subset/run-tests.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-# Runs a subsetting test suite. Compares the results of subsetting via harfbuz
+# Runs a subsetting test suite. Compares the results of subsetting via harfbuzz
 # to subsetting via fonttools.
 
 from __future__ import print_function, division, absolute_import
@@ -16,27 +16,27 @@
 from subset_test_suite import SubsetTestSuite
 
 # https://stackoverflow.com/a/377028
-def which(program):
-	def is_exe(fpath):
-		return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+def which (program):
+	def is_exe (fpath):
+		return os.path.isfile (fpath) and os.access (fpath, os.X_OK)
 
-	fpath, _ = os.path.split(program)
+	fpath, _ = os.path.split (program)
 	if fpath:
-		if is_exe(program):
+		if is_exe (program):
 			return program
 	else:
-		for path in os.environ["PATH"].split(os.pathsep):
-			exe_file = os.path.join(path, program)
-			if is_exe(exe_file):
+		for path in os.environ["PATH"].split (os.pathsep):
+			exe_file = os.path.join (path, program)
+			if is_exe (exe_file):
 				return exe_file
 
 	return None
 
-ttx = which ("ttx")
+fonttools = which ("fonttools")
 ots_sanitize = which ("ots-sanitize")
 
-if not ttx:
-	print("TTX is not present, skipping test.")
+if not fonttools:
+	print ("fonttools is not present, skipping test.")
 	sys.exit (77)
 
 def cmd(command):
@@ -50,7 +50,7 @@
 	with open (file_path, 'rb') as f:
 		return f.read ()
 
-def fail_test(test, cli_args, message):
+def fail_test (test, cli_args, message):
 	print ('ERROR: %s' % message)
 	print ('Test State:')
 	print ('  test.font_path    %s' % os.path.abspath (test.font_path))
@@ -61,12 +61,13 @@
 	print ('  expected_file	    %s' % os.path.abspath (expected_file))
 	return 1
 
-def run_test(test, should_check_ots):
-	out_file = os.path.join(tempfile.mkdtemp (), test.get_font_name () + '-subset' + test.get_font_extension ())
+def run_test (test, should_check_ots):
+	out_file = os.path.join (tempfile.mkdtemp (), test.get_font_name () + '-subset' + test.get_font_extension ())
 	cli_args = [hb_subset,
 		    "--font-file=" + test.font_path,
 		    "--output-file=" + out_file,
-		    "--unicodes=%s" % test.unicodes ()]
+		    "--unicodes=%s" % test.unicodes (),
+		    "--drop-tables+=DSIG,GPOS,GSUB,GDEF,gvar,avar,MVAR,HVAR"]
 	cli_args.extend (test.get_profile_flags ())
 	print (' '.join (cli_args))
 	_, return_code = cmd (cli_args)
@@ -75,11 +76,11 @@
 		return fail_test (test, cli_args, "%s returned %d" % (' '.join (cli_args), return_code))
 
 	expected_ttx, return_code = run_ttx (os.path.join (test_suite.get_output_directory (),
-					    test.get_font_name ()))
+					     test.get_font_name ()))
 	if return_code:
 		return fail_test (test, cli_args, "ttx (expected) returned %d" % (return_code))
 
-	actual_ttx, return_code = run_ttx(out_file)
+	actual_ttx, return_code = run_ttx (out_file)
 	if return_code:
 		return fail_test (test, cli_args, "ttx (actual) returned %d" % (return_code))
 
@@ -91,7 +92,7 @@
 		for line in unified_diff (expected_ttx.splitlines (1), actual_ttx.splitlines (1)):
 			sys.stdout.write (line)
 		sys.stdout.flush ()
-		return fail_test(test, cli_args, 'ttx for expected and actual does not match.')
+		return fail_test (test, cli_args, 'ttx for expected and actual does not match.')
 
 	if should_check_ots:
 		print ("Checking output with ots-sanitize.")
@@ -101,8 +102,8 @@
 	return 0
 
 def run_ttx (file):
-	print ("ttx %s" % file)
-	return cmd([ttx, "-q", "-o-", file])
+	print ("fonttools ttx %s" % file)
+	return cmd ([fonttools, "ttx", "-q", "-o-", file])
 
 def strip_check_sum (ttx_string):
 	return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]',
@@ -123,7 +124,7 @@
 	return True
 
 args = sys.argv[1:]
-if not args or sys.argv[1].find('hb-subset') == -1 or not os.path.exists (sys.argv[1]):
+if not args or sys.argv[1].find ('hb-subset') == -1 or not os.path.exists (sys.argv[1]):
 	print ("First argument does not seem to point to usable hb-subset.")
 	sys.exit (1)
 hb_subset, args = args[0], args[1:]
@@ -138,7 +139,7 @@
 for path in args:
 	with io.open (path, mode="r", encoding="utf-8") as f:
 		print ("Running tests in " + path)
-		test_suite = SubsetTestSuite (path, f.read())
+		test_suite = SubsetTestSuite (path, f.read ())
 		for test in test_suite.tests ():
 			fails += run_test (test, has_ots)
 
diff --git a/util/Makefile.am b/util/Makefile.am
index e24a6f3..5298e77 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -50,8 +50,9 @@
 
 hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
 hb_subset_LDADD = \
-	$(LDADD) \
-	$(top_builddir)/src/libharfbuzz-subset.la
+	$(top_builddir)/src/libharfbuzz-subset.la \
+	$(LDADD)
+
 bin_PROGRAMS += hb-subset
 
 hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)
diff --git a/util/Makefile.sources b/util/Makefile.sources
index 6c815d2..bcf85f5 100644
--- a/util/Makefile.sources
+++ b/util/Makefile.sources
@@ -32,6 +32,7 @@
 HB_SUBSET_CLI_sources = \
 	hb-subset.cc \
 	options.cc \
+	options-subset.cc \
 	options.hh \
 	main-font-text.hh \
 	$(NULL)
diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc
index 77ca201..33f531b 100644
--- a/util/hb-ot-shape-closure.cc
+++ b/util/hb-ot-shape-closure.cc
@@ -39,7 +39,7 @@
     add_options (parser);
   }
 
-  void add_options (struct option_parser_t *parser)
+  void add_options (struct option_parser_t *parser) override
   {
     GOptionEntry entries[] =
     {
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 682ca4c..4b7af8e 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -43,7 +43,7 @@
              const font_options_t *font_opts)
   {
     font = hb_font_reference (font_opts->get_font ());
-    input = hb_subset_input_create_or_fail ();
+    input = hb_subset_input_reference (subset_options.input);
   }
 
   void consume_line (const char   *text,
@@ -89,12 +89,6 @@
 
   void finish (const font_options_t *font_opts)
   {
-    hb_subset_input_set_drop_layout (input, !subset_options.keep_layout);
-    hb_subset_input_set_drop_hints (input, subset_options.drop_hints);
-    hb_subset_input_set_retain_gids (input, subset_options.retain_gids);
-    hb_subset_input_set_desubroutinize (input, subset_options.desubroutinize);
-    hb_set_set (hb_subset_input_nameid_set (input), subset_options.name_ids);
-
     hb_face_t *face = hb_font_get_face (font);
 
     hb_face_t *new_face = hb_subset (face, input);
diff --git a/util/options-subset.cc b/util/options-subset.cc
new file mode 100644
index 0000000..b2f4db0
--- /dev/null
+++ b/util/options-subset.cc
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2019  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "options.hh"
+
+#include "hb-subset-input.hh"
+
+static gboolean
+parse_nameids (const char *name,
+               const char *arg,
+               gpointer    data,
+               GError    **error G_GNUC_UNUSED)
+{
+  subset_options_t *subset_opts = (subset_options_t *) data;
+  hb_set_t *name_ids = subset_opts->input->name_ids;
+
+  char last_name_char = name[strlen (name) - 1];
+
+  if (last_name_char != '+' && last_name_char != '-')
+    hb_set_clear (name_ids);
+
+  if (0 == strcmp (arg, "*"))
+  {
+    if (last_name_char == '-')
+      hb_set_del_range (name_ids, 0, 0x7FFF);
+    else 
+      hb_set_add_range (name_ids, 0, 0x7FFF);
+    return true;
+  }
+
+  char *s = (char *) arg;
+  char *p;
+
+  while (s && *s)
+  {
+    while (*s && strchr (", ", *s))
+      s++;
+    if (!*s)
+      break;
+
+    errno = 0;
+    hb_codepoint_t u = strtoul (s, &p, 10);
+    if (errno || s == p)
+    {
+      hb_set_destroy (name_ids);
+      g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+                   "Failed parsing nameID values at: '%s'", s);
+      return false;
+    }
+
+    if (last_name_char != '-')
+    {
+      hb_set_add (name_ids, u);
+    } else {
+      hb_set_del (name_ids, u);
+    }
+
+    s = p;
+  }
+
+  return true;
+}
+
+static gboolean
+parse_drop_tables (const char *name,
+                   const char *arg,
+                   gpointer    data,
+                   GError    **error G_GNUC_UNUSED)
+{
+  subset_options_t *subset_opts = (subset_options_t *) data;
+  hb_set_t *drop_tables = subset_opts->input->drop_tables;
+
+  char last_name_char = name[strlen (name) - 1];
+
+  if (last_name_char != '+' && last_name_char != '-')
+    hb_set_clear (drop_tables);
+
+  char *s = strtok((char *) arg, ", ");
+  while (s)
+  {
+    if (strlen (s) > 4) // Table tags are at most 4 bytes.
+    {
+      g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+                   "Failed parsing table tag values at: '%s'", s);
+      return false;
+    }
+
+    hb_tag_t tag = hb_tag_from_string (s, strlen (s));
+
+    if (last_name_char != '-')
+      hb_set_add (drop_tables, tag);
+    else
+      hb_set_del (drop_tables, tag);
+
+    s = strtok(nullptr, ", ");
+  }
+
+  return true;
+}
+
+void
+subset_options_t::add_options (option_parser_t *parser)
+{
+  GOptionEntry entries[] =
+  {
+    {"no-hinting", 0, 0, G_OPTION_ARG_NONE,  &this->input->drop_hints,   "Whether to drop hints",   nullptr},
+    {"retain-gids", 0, 0, G_OPTION_ARG_NONE,  &this->input->retain_gids,   "If set don't renumber glyph ids in the subset.",   nullptr},
+    {"desubroutinize", 0, 0, G_OPTION_ARG_NONE,  &this->input->desubroutinize,   "Remove CFF/CFF2 use of subroutines",   nullptr},
+    {"name-IDs", 0, 0, G_OPTION_ARG_CALLBACK,  (gpointer) &parse_nameids,  "Subset specified nameids", "list of int numbers"},
+    {"drop-tables", 0, 0, G_OPTION_ARG_CALLBACK,  (gpointer) &parse_drop_tables,  "Drop the specified tables.", "list of string table tags."},
+    {"drop-tables+", 0, 0, G_OPTION_ARG_CALLBACK,  (gpointer) &parse_drop_tables,  "Drop the specified tables.", "list of string table tags."},
+    {"drop-tables-", 0, 0, G_OPTION_ARG_CALLBACK,  (gpointer) &parse_drop_tables,  "Drop the specified tables.", "list of string table tags."},
+
+    {nullptr}
+  };
+  parser->add_group (entries,
+         "subset",
+         "Subset options:",
+         "Options subsetting",
+         this);
+}
diff --git a/util/options.cc b/util/options.cc
index a9b3fc7..4e6ca57 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -31,6 +31,8 @@
 #endif
 #include <hb-ot.h>
 
+#define DELIMITERS "<+>{},;&#\\xXuUnNiI\n\t\v\f\r "
+
 static struct supported_font_funcs_t {
 	char name[4];
 	void (*func) (hb_font_t *);
@@ -352,7 +354,7 @@
 
   while (s && *s)
   {
-    while (*s && strchr ("<+>{},;&#\\xXuUnNiI\n\t\v\f\r ", *s))
+    while (*s && strchr (DELIMITERS, *s))
       s++;
     if (!*s)
       break;
@@ -970,67 +972,3 @@
   serialize_glyphs (buffer, font, output_format, format_flags, gs);
   g_string_append_c (gs, '\n');
 }
-
-static gboolean
-parse_nameids (const char *name G_GNUC_UNUSED,
-               const char *arg,
-               gpointer    data,
-               GError    **error G_GNUC_UNUSED)
-{
-  subset_options_t *subset_opts = (subset_options_t *) data;
-
-  hb_set_t *name_ids = hb_set_create ();
-  char *s = (char *) arg;
-  char *p;
-
-  while (s && *s)
-  {
-    while (*s && strchr ("<+>{},;&#\\xXuUnNiI\n\t\v\f\r ", *s))
-      s++;
-    if (!*s)
-      break;
-
-    errno = 0;
-    hb_codepoint_t u = strtoul (s, &p, 10);
-    if (errno || s == p)
-    {
-      hb_set_destroy (name_ids);
-      g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
-                   "Failed parsing nameID values at: '%s'", s);
-      return false;
-    }
-
-    hb_set_add (name_ids, u);
-
-    s = p;
-  }
-
-  hb_set_t *prev = subset_opts->name_ids;
-  subset_opts->name_ids = hb_set_reference (name_ids);
-  hb_set_destroy (prev);
-  hb_set_destroy (name_ids);
-
-  return true;
-}
-
-
-void
-subset_options_t::add_options (option_parser_t *parser)
-{
-  GOptionEntry entries[] =
-  {
-    {"layout", 0, 0, G_OPTION_ARG_NONE,  &this->keep_layout,   "Keep OpenType Layout tables",   nullptr},
-    {"no-hinting", 0, 0, G_OPTION_ARG_NONE,  &this->drop_hints,   "Whether to drop hints",   nullptr},
-    {"retain-gids", 0, 0, G_OPTION_ARG_NONE,  &this->retain_gids,   "If set don't renumber glyph ids in the subset.",   nullptr},
-    {"desubroutinize", 0, 0, G_OPTION_ARG_NONE,  &this->desubroutinize,   "Remove CFF/CFF2 use of subroutines",   nullptr},
-    {"name-IDs", 0, 0, G_OPTION_ARG_CALLBACK,  (gpointer) &parse_nameids,  "Subset specified nameids", "list of int numbers"},
-
-    {nullptr}
-  };
-  parser->add_group (entries,
-         "subset",
-         "Subset options:",
-         "Options subsetting",
-         this);
-}
-
diff --git a/util/options.hh b/util/options.hh
index 2691e22..63360ca 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -28,6 +28,7 @@
 #define OPTIONS_HH
 
 #include "hb.hh"
+#include "hb-subset.h"
 
 #include <stdlib.h>
 #include <stddef.h>
@@ -128,13 +129,13 @@
 
     add_options (parser);
   }
-  virtual ~view_options_t ()
+  ~view_options_t () override
   {
     g_free (fore);
     g_free (back);
   }
 
-  void add_options (option_parser_t *parser);
+  void add_options (option_parser_t *parser) override;
 
   hb_bool_t annotate;
   char *fore;
@@ -164,7 +165,7 @@
 
     add_options (parser);
   }
-  virtual ~shape_options_t ()
+  ~shape_options_t () override
   {
     g_free (direction);
     g_free (language);
@@ -173,7 +174,7 @@
     g_strfreev (shapers);
   }
 
-  void add_options (option_parser_t *parser);
+  void add_options (option_parser_t *parser) override;
 
   void setup_buffer (hb_buffer_t *buffer)
   {
@@ -470,7 +471,7 @@
 
     add_options (parser);
   }
-  virtual ~font_options_t ()
+  ~font_options_t () override
   {
     g_free (font_file);
     free (variations);
@@ -478,7 +479,7 @@
     hb_font_destroy (font);
   }
 
-  void add_options (option_parser_t *parser);
+  void add_options (option_parser_t *parser) override;
 
   hb_font_t *get_font () const;
 
@@ -520,7 +521,7 @@
 
     add_options (parser);
   }
-  virtual ~text_options_t ()
+  ~text_options_t () override
   {
     g_free (text_before);
     g_free (text_after);
@@ -532,9 +533,9 @@
       fclose (fp);
   }
 
-  void add_options (option_parser_t *parser);
+  void add_options (option_parser_t *parser) override;
 
-  void post_parse (GError **error G_GNUC_UNUSED) {
+  void post_parse (GError **error G_GNUC_UNUSED) override {
     if (text && text_file)
       g_set_error (error,
 		   G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
@@ -571,7 +572,7 @@
 
     add_options (parser);
   }
-  virtual ~output_options_t ()
+  ~output_options_t () override
   {
     g_free (output_file);
     g_free (output_format);
@@ -579,9 +580,9 @@
       fclose (fp);
   }
 
-  void add_options (option_parser_t *parser);
+  void add_options (option_parser_t *parser) override;
 
-  void post_parse (GError **error G_GNUC_UNUSED)
+  void post_parse (GError **error G_GNUC_UNUSED) override
   {
     if (output_format)
       explicit_output_format = true;
@@ -626,7 +627,7 @@
     add_options (parser);
   }
 
-  void add_options (option_parser_t *parser);
+  void add_options (option_parser_t *parser) override;
 
   void serialize_unicode (hb_buffer_t  *buffer,
 			  GString      *gs);
@@ -673,28 +674,18 @@
 {
   subset_options_t (option_parser_t *parser)
   {
-    keep_layout = false;
-    drop_hints = false;
-    retain_gids = false;
-    desubroutinize = false;
-    name_ids = hb_set_create ();
-
+    input = hb_subset_input_create_or_fail ();
     add_options (parser);
   }
 
-  virtual ~subset_options_t ()
+  ~subset_options_t () override
   {
-    hb_set_destroy (name_ids);
+    hb_subset_input_destroy (input);
   }
 
+  void add_options (option_parser_t *parser) override;
 
-  void add_options (option_parser_t *parser);
-
-  hb_bool_t keep_layout;
-  hb_bool_t drop_hints;
-  hb_bool_t retain_gids;
-  hb_bool_t desubroutinize;
-  hb_set_t *name_ids;
+  hb_subset_input_t *input;
 };
 
 /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */