From 78bf3c74b6fd8a89858b13170e4cee47f0402586 Mon Sep 17 00:00:00 2001 From: Mikhail Romanko Date: Sun, 14 Jun 2026 22:51:45 +0300 Subject: [PATCH] Initial commit --- .gitignore | 68 ++ CMakeLists.txt | 29 + CgeStr.h | 76 ++ LICENSE | 12 + Makefile.mingw | 23 + Makefile.posix | 33 + Makefile.win32 | 23 + README.md | 56 + Rune.c | 176 +++ Str.c | 307 ++++++ UCD.c | 2350 +++++++++++++++++++++++++++++++++++++++++ Utf16.c | 64 ++ Utf8.c | 101 ++ generator/Blocks.h | 168 +++ generator/README.md | 28 + generator/Tables.c | 465 ++++++++ generator/TextProc.h | 76 ++ generator/ValueList.h | 41 + 18 files changed, 4096 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 CgeStr.h create mode 100644 LICENSE create mode 100644 Makefile.mingw create mode 100644 Makefile.posix create mode 100644 Makefile.win32 create mode 100644 README.md create mode 100644 Rune.c create mode 100644 Str.c create mode 100644 UCD.c create mode 100644 Utf16.c create mode 100644 Utf8.c create mode 100644 generator/Blocks.h create mode 100644 generator/README.md create mode 100644 generator/Tables.c create mode 100644 generator/TextProc.h create mode 100644 generator/ValueList.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f765426 --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +# ---> C +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# ---> CMake +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +CMakeUserPresets.json + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a3c4c78 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.10) +project(CgeStr LANGUAGES C) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) + +set(SOURCES + Rune.c + Str.c + UCD.c + Utf8.c + Utf16.c +) + +set(HEADERS + CgeStr.h +) + +add_library(CgeStr STATIC ${SOURCES} ${HEADERS}) + +target_include_directories(CgeStr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +install(TARGETS CgeStr + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) + +install(FILES ${HEADERS} DESTINATION include) diff --git a/CgeStr.h b/CgeStr.h new file mode 100644 index 0000000..2b32af4 --- /dev/null +++ b/CgeStr.h @@ -0,0 +1,76 @@ +#ifndef CGE_STR_H +#define CGE_STR_H + +#include + +typedef struct CgeStr { + const char* data; + size_t size; +} CgeStr; + +#define CGE_STR_LIT(s) \ + {(s), sizeof(s) - 1} + +typedef void (*CgeStrIterCb)(uint32_t rune, void* user); +typedef void (*CgeStrWriteCb)(const char* data, size_t size, void* user); + +enum CgeCat { + CGE_CAT_LU, CGE_CAT_LL, CGE_CAT_LT, CGE_CAT_LM, CGE_CAT_LO, CGE_CAT_MN, + CGE_CAT_MC, CGE_CAT_ME, CGE_CAT_ND, CGE_CAT_NL, CGE_CAT_NO, CGE_CAT_PC, + CGE_CAT_PD, CGE_CAT_PS, CGE_CAT_PE, CGE_CAT_PI, CGE_CAT_PF, CGE_CAT_PO, + CGE_CAT_SM, CGE_CAT_SC, CGE_CAT_SK, CGE_CAT_SO, CGE_CAT_ZS, CGE_CAT_ZL, + CGE_CAT_ZP, CGE_CAT_CC, CGE_CAT_CF, CGE_CAT_CS, CGE_CAT_CO, CGE_CAT_CN +}; + +int CgeRuneCategory(uint32_t rune); +uint32_t CgeRuneLower(uint32_t rune); +uint32_t CgeRuneUpper(uint32_t rune); +uint32_t CgeRuneTitle(uint32_t rune); +uint32_t CgeRuneFold(uint32_t rune); +size_t CgeRuneLowerFull(uint32_t rune, uint32_t* out); +size_t CgeRuneUpperFull(uint32_t rune, uint32_t* out); +size_t CgeRuneTitleFull(uint32_t rune, uint32_t* out); +size_t CgeRuneFoldFull(uint32_t rune, uint32_t* out); + +int CgeRuneIsControl(uint32_t rune); +int CgeRuneIsDigit(uint32_t rune); +int CgeRuneIsGraphic(uint32_t rune); +int CgeRuneIsLetter(uint32_t rune); +int CgeRuneIsLower(uint32_t rune); +int CgeRuneIsMark(uint32_t rune); +int CgeRuneIsNumber(uint32_t rune); +int CgeRuneIsPrint(uint32_t rune); +int CgeRuneIsPunct(uint32_t rune); +int CgeRuneIsSpace(uint32_t rune); +int CgeRuneIsSymbol(uint32_t rune); +int CgeRuneIsTitle(uint32_t rune); +int CgeRuneIsUpper(uint32_t rune); + +int CgeUtf8Encode(uint32_t rune, char* data); +int CgeUtf8EncodeLax(uint32_t rune, char* data); +int CgeUtf8Decode(const char* data, size_t size, uint32_t* rune); +int CgeUtf8DecodeLax(const char* data, size_t size, uint32_t* rune); + +int CgeUtf16Encode(uint32_t rune, uint16_t* data); +int CgeUtf16EncodeLax(uint32_t rune, uint16_t* data); +int CgeUtf16Decode(const uint16_t* data, size_t size, uint32_t* rune); +int CgeUtf16DecodeLax(const uint16_t* data, size_t size, uint32_t* rune); + +void CgeStrIter(CgeStr str, CgeStrIterCb cb, void* user); +void CgeStrToLower(CgeStr str, CgeStrWriteCb cb, void* user); +void CgeStrToUpper(CgeStr str, CgeStrWriteCb cb, void* user); +void CgeStrFold(CgeStr str, CgeStrWriteCb cb, void* user); +int CgeStrCmp(CgeStr lhs, CgeStr rhs); +int CgeStrICmp(CgeStr lhs, CgeStr rhs); +size_t CgeStrIndexRune(CgeStr str, uint32_t rune); +size_t CgeStrLastIndexRune(CgeStr str, uint32_t rune); +size_t CgeStrIndexStr(CgeStr str, CgeStr substr); +size_t CgeStrLastIndexStr(CgeStr str, CgeStr substr); +int CgeStrHasPrefix(CgeStr str, CgeStr prefix); +int CgeStrHasSuffix(CgeStr str, CgeStr suffix); +CgeStr CgeStrTrimLeft(CgeStr str); +CgeStr CgeStrTrimRight(CgeStr str); +CgeStr CgeStrTrim(CgeStr str); +CgeStr CgeStrSplit(CgeStr *s, uint32_t delim); + +#endif /* CGE_STR_H */ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3d44ffd --- /dev/null +++ b/LICENSE @@ -0,0 +1,12 @@ +Copyright (C) 2026 by blankhex me@blankhex.com + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +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/Makefile.mingw b/Makefile.mingw new file mode 100644 index 0000000..73df4e3 --- /dev/null +++ b/Makefile.mingw @@ -0,0 +1,23 @@ +# MinGW Makefile for CgeStr + +CC = gcc +AR = ar +CFLAGS = -std=c99 -O2 -Wall -Wextra +ARFLAGS = rcs +TARGET = libCgeStr.a + +SOURCES = Rune.c Str.c UCD.c Utf8.c Utf16.c +OBJECTS = $(SOURCES:.c=.o) + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $^ + +%.o: %.c CgeStr.h + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + del $(OBJECTS) $(TARGET) 2>nul || exit 0 diff --git a/Makefile.posix b/Makefile.posix new file mode 100644 index 0000000..e542d9d --- /dev/null +++ b/Makefile.posix @@ -0,0 +1,33 @@ +# POSIX Makefile for CgeStr + +CC = gcc +AR = ar +CFLAGS = -std=c99 -O2 -Wall -Wextra -fPIC +ARFLAGS = rcs +TARGET = libCgeStr.a + +SOURCES = Rune.c Str.c UCD.c Utf8.c Utf16.c +OBJECTS = $(SOURCES:.c=.o) + +.PHONY: all clean install + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $^ + +%.o: %.c CgeStr.h + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJECTS) $(TARGET) + +install: $(TARGET) + cp $(TARGET) /usr/local/lib/ + cp CgeStr.h /usr/local/include/ + ldconfig || echo "Run ldconfig manually if needed" + +uninstall: + rm -f /usr/local/lib/libCgeStr.a + rm -f /usr/local/include/CgeStr.h + ldconfig || true diff --git a/Makefile.win32 b/Makefile.win32 new file mode 100644 index 0000000..318d64d --- /dev/null +++ b/Makefile.win32 @@ -0,0 +1,23 @@ +# Makefile.win32 for MSVC (NMake) +# Usage: Open "x86 Native Tools Command Prompt", then: +# nmake -f Makefile.win32 + +CC = cl +LIB = lib +CFLAGS = /c /nologo /W3 /O2 +LIBFLAGS = /nologo +TARGET = CgeStr.lib + +SOURCES = Rune.c Str.c UCD.c Utf8.c Utf16.c +OBJECTS = $(SOURCES:.c=.obj) + +$(TARGET): $(OBJECTS) + $(LIB) $(LIBFLAGS) /OUT:$(TARGET) $(OBJECTS) + +{.}.c{}.obj: + $(CC) $(CFLAGS) /Fo$@ $< + +clean: + del $(OBJECTS) $(TARGET) 2>nul + +.PHONY: clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..59b5f47 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# CgeStr - Unicode String Library for C + +A lightweight, dependency-free C library for UTF-8 string processing with full +Unicode support. + +## Features + +- UTF-8 encoding and decoding +- UTF-16 encoding and decoding +- Unicode case mapping: lowercase, uppercase, titlecase, case folding +- Full case mapping functions returning multiple runes when needed +- Character classification: isControl, isDigit, isLetter, isSpace, and others +- Unicode category lookup via `CgeRuneCategory` +- Case-sensitive and case-insensitive string comparison +- Substring and rune search +- Prefix and suffix checking +- String trimming (left, right, both) +- String splitting by rune +- Iteration over Unicode code points using callback interface + +## Build Systems + +- CMake - supports Linux, macOS, Windows (MSVC, MinGW) +- Makefile.posix - for GCC/Clang on POSIX systems +- Makefile.mingw - for MinGW on Windows +- Makefile.win32 - for MSVC with NMake + +Builds a static library. No shared library or external dependencies. + +## Usage Example + +```c +#include "CgeStr.h" +#include + +void print_rune(uint32_t rune, void* user) { + printf("U+%04X ", rune); +} + +int main() { + CgeStr str = CGE_STR_LIT("Héllo, 世界!"); + CgeStrIter(str, print_rune, NULL); + printf("\n"); + return 0; +} +``` + +## Portability + +- Written in C89+stdint.h +- No dynamic memory allocation +- No external dependencies + +## License + +0BSD - a permissive license with no attribution required. diff --git a/Rune.c b/Rune.c new file mode 100644 index 0000000..baebb19 --- /dev/null +++ b/Rune.c @@ -0,0 +1,176 @@ +#include "CgeStr.h" + +int CgeRuneIsControl(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_CC: + return 1; + } + return 0; +} + +int CgeRuneIsDigit(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_ND: + return 1; + } + return 0; +} + +int CgeRuneIsGraphic(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_LL: + case CGE_CAT_LM: + case CGE_CAT_LO: + case CGE_CAT_LT: + case CGE_CAT_LU: + case CGE_CAT_MC: + case CGE_CAT_ME: + case CGE_CAT_MN: + case CGE_CAT_ND: + case CGE_CAT_NL: + case CGE_CAT_NO: + case CGE_CAT_PC: + case CGE_CAT_PD: + case CGE_CAT_PE: + case CGE_CAT_PF: + case CGE_CAT_PI: + case CGE_CAT_PO: + case CGE_CAT_PS: + case CGE_CAT_SC: + case CGE_CAT_SK: + case CGE_CAT_SM: + case CGE_CAT_SO: + case CGE_CAT_ZS: + return 1; + } + return 0; +} + +int CgeRuneIsLetter(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_LL: + case CGE_CAT_LM: + case CGE_CAT_LO: + case CGE_CAT_LT: + case CGE_CAT_LU: + return 1; + } + return 0; +} + +int CgeRuneIsLower(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_LL: + return 1; + } + return 0; +} + +int CgeRuneIsMark(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_MC: + case CGE_CAT_ME: + case CGE_CAT_MN: + return 1; + } + return 0; +} + +int CgeRuneIsNumber(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_ND: + case CGE_CAT_NL: + case CGE_CAT_NO: + return 1; + } + return 0; +} + +int CgeRuneIsPrint(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_LL: + case CGE_CAT_LM: + case CGE_CAT_LO: + case CGE_CAT_LT: + case CGE_CAT_LU: + case CGE_CAT_MC: + case CGE_CAT_ME: + case CGE_CAT_MN: + case CGE_CAT_ND: + case CGE_CAT_NL: + case CGE_CAT_NO: + case CGE_CAT_PC: + case CGE_CAT_PD: + case CGE_CAT_PE: + case CGE_CAT_PF: + case CGE_CAT_PI: + case CGE_CAT_PO: + case CGE_CAT_PS: + case CGE_CAT_SC: + case CGE_CAT_SK: + case CGE_CAT_SM: + case CGE_CAT_SO: + return 1; + } + return rune == ' '; +} + +int CgeRuneIsPunct(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_PC: + case CGE_CAT_PD: + case CGE_CAT_PE: + case CGE_CAT_PF: + case CGE_CAT_PI: + case CGE_CAT_PO: + case CGE_CAT_PS: + return 1; + } + return 0; +} + +int CgeRuneIsSpace(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_ZL: + case CGE_CAT_ZP: + case CGE_CAT_ZS: + return 1; + } + + switch (rune) { + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + return 1; + } + return 0; +} + +int CgeRuneIsSymbol(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_SC: + case CGE_CAT_SK: + case CGE_CAT_SM: + case CGE_CAT_SO: + return 1; + } + return 0; +} + +int CgeRuneIsTitle(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_LT: + return 1; + } + return 0; +} + +int CgeRuneIsUpper(uint32_t rune) { + switch (CgeRuneCategory(rune)) { + case CGE_CAT_LU: + return 1; + } + return 0; +} diff --git a/Str.c b/Str.c new file mode 100644 index 0000000..3259bfd --- /dev/null +++ b/Str.c @@ -0,0 +1,307 @@ +#include "CgeStr.h" +#include +#include + +#define INVALID_RUNE 0xFFFD +#define MAX_UNI_STREAM 4 + +struct UniStream { + uint32_t data[MAX_UNI_STREAM]; + size_t head; + size_t tail; + size_t size; +}; + +static int uniStreamPut(struct UniStream* stream, uint32_t rune) { + if (stream->size >= MAX_UNI_STREAM) + return 0; + + stream->data[stream->tail] = rune; + stream->tail = (stream->tail + 1) & (MAX_UNI_STREAM - 1); + stream->size++; + return 1; +} + +static int uniStreamGet(struct UniStream* stream, uint32_t* rune) { + if (!stream->size) + return 0; + + *rune = stream->data[stream->head]; + stream->head = (stream->head + 1) & (MAX_UNI_STREAM - 1); + stream->size--; + return 1; +} + +void CgeStrIter(CgeStr str, CgeStrIterCb cb, void* user) { + const char* current = str.data; + const char* end = str.data + str.size; + + while (current < end) { + uint32_t rune; + + current += CgeUtf8DecodeLax(current, end - current, &rune); + cb(rune, user); + } +} + +void CgeStrToLower(CgeStr str, CgeStrWriteCb cb, void* user) { + const char* current = str.data; + const char* end = str.data + str.size; + + while (current < end) { + uint32_t rune; + uint32_t mapped[3]; + int count, i; + + current += CgeUtf8DecodeLax(current, end - current, &rune); + count = (int)CgeRuneLowerFull(rune, mapped); + for (i = 0; i < count; i++) { + char scratch[4]; + + cb(scratch, CgeUtf8EncodeLax(mapped[i], scratch), user); + } + } +} + +void CgeStrToUpper(CgeStr str, CgeStrWriteCb cb, void* user) { + const char* current = str.data; + const char* end = str.data + str.size; + + while (current < end) { + uint32_t rune; + uint32_t mapped[3]; + int count, i; + + current += CgeUtf8DecodeLax(current, end - current, &rune); + count = (int)CgeRuneUpperFull(rune, mapped); + for (i = 0; i < count; i++) { + char scratch[4]; + + cb(scratch, CgeUtf8EncodeLax(mapped[i], scratch), user); + } + } +} + +void CgeStrFold(CgeStr str, CgeStrWriteCb cb, void* user) { + const char* current = str.data; + const char* end = str.data + str.size; + + while (current < end) { + uint32_t rune; + uint32_t mapped[3]; + int count, i; + + current += CgeUtf8DecodeLax(current, end - current, &rune); + count = (int)CgeRuneFoldFull(rune, mapped); + for (i = 0; i < count; i++) { + char scratch[4]; + + cb(scratch, CgeUtf8EncodeLax(mapped[i], scratch), user); + } + } +} + +int CgeStrCmp(CgeStr lhs, CgeStr rhs) { + size_t leastSize; + int result; + + leastSize = (lhs.size < rhs.size) ? lhs.size : rhs.size; + result = memcmp(lhs.data, rhs.data, leastSize); + if (result < 0) + return -1; + else if (result > 0) + return 1; + + if (lhs.size < rhs.size) + return -1; + else if (lhs.size > rhs.size) + return 1; + + return 0; +} + +int CgeStrICmp(CgeStr lhs, CgeStr rhs) { + struct UniStream buf1 = {{0}, 0, 0, 0}; + struct UniStream buf2 = {{0}, 0, 0, 0}; + + const char* current1 = lhs.data; + const char* current2 = rhs.data; + const char* end1 = lhs.data + lhs.size; + const char* end2 = rhs.data + rhs.size; + + while (1) { + uint32_t rune1, rune2; + + if (!buf1.size && current1 < end1) { + uint32_t scratch, folded[3]; + int i, count; + + current1 += CgeUtf8DecodeLax(current1, end1 - current1, &scratch); + count = (int)CgeRuneFoldFull(scratch, folded); + for (i = 0; i < count; i++) + uniStreamPut(&buf1, folded[i]); + } + + if (!buf2.size && current2 < end2) { + uint32_t scratch, folded[3]; + int i, count; + + current2 += CgeUtf8DecodeLax(current2, end2 - current2, &scratch); + count = (int)CgeRuneFoldFull(scratch, folded); + for (i = 0; i < count; i++) + uniStreamPut(&buf2, folded[i]); + } + + if (!buf1.size && !buf2.size) + return 0; + + if (!uniStreamGet(&buf1, &rune1)) + return -1; + + if (!uniStreamGet(&buf2, &rune2)) + return 1; + + if (rune1 < rune2) + return -1; + if (rune1 > rune2) + return 1; + } +} + +size_t CgeStrIndexRune(CgeStr str, uint32_t rune) { + size_t i = 0; + while (i < str.size) { + uint32_t r; + int count; + + count = CgeUtf8DecodeLax(str.data + i, str.size - i, &r); + if (r == rune) + return i; + i += count; + } + return (size_t)-1; +} + +size_t CgeStrLastIndexRune(CgeStr str, uint32_t rune) { + size_t i = str.size; + + while (i > 0) { + size_t current = i; + uint32_t r; + + while (current > 0 && (str.data[current - 1] & 0xC0) == 0x80) + current--; + if (!current) + current = i - 1; + + CgeUtf8DecodeLax(str.data + current, i - current, &r); + if (r == rune) + return current; + i = current; + } + return (size_t)-1; +} + +size_t CgeStrIndexStr(CgeStr str, CgeStr substr) { + size_t i; + + if (!substr.size) + return 0; + if (str.size < substr.size) + return (size_t)-1; + + for (i = 0; i <= str.size - substr.size; i++) { + if (!memcmp(str.data + i, substr.data, substr.size)) + return i; + } + return (size_t)-1; +} + +size_t CgeStrLastIndexStr(CgeStr str, CgeStr substr) { + size_t i; + + if (!substr.size) + return str.size; + if (str.size < substr.size) + return (size_t)-1; + + for (i = str.size - substr.size; i != (size_t)-1; i--) { + if (!memcmp(str.data + i, substr.data, substr.size)) + return i; + } + return (size_t)-1; +} + +int CgeStrHasPrefix(CgeStr str, CgeStr prefix) { + if (prefix.size > str.size) + return 0; + + return !memcmp(str.data, prefix.data, prefix.size); +} + +int CgeStrHasSuffix(CgeStr str, CgeStr suffix) { + if (suffix.size > str.size) + return 0; + + return !memcmp(str.data + str.size - suffix.size, suffix.data, suffix.size); +} + +CgeStr CgeStrTrimLeft(CgeStr str) { + while (str.size) { + uint32_t rune; + int count; + + count = CgeUtf8DecodeLax(str.data, str.size, &rune); + if (!CgeRuneIsSpace(rune)) + break; + + str.data += count; + str.size -= count; + } + return str; +} + +CgeStr CgeStrTrimRight(CgeStr str) { + while (str.size) { + size_t pos = str.size; + uint32_t rune; + + while (pos > 0 && (str.data[pos - 1] & 0xC0) == 0x80) + pos--; + if (pos == 0) + pos = 1; + + CgeUtf8DecodeLax(str.data + pos - 1, str.size - (pos - 1), &rune); + if (!CgeRuneIsSpace(rune)) + break; + + str.size = pos - 1; + } + return str; +} + +CgeStr CgeStrTrim(CgeStr str) { + return CgeStrTrimRight(CgeStrTrimLeft(str)); +} + +CgeStr CgeStrSplit(CgeStr *s, uint32_t delim) { + size_t pos; + int count; + uint32_t r; + CgeStr result; + + pos = CgeStrIndexRune(*s, delim); + if (pos == (size_t)-1) { + result = *s; + s->size = 0; + return result; + } + + count = CgeUtf8DecodeLax(s->data + pos, s->size - pos, &r); + + result.data = s->data; + result.size = pos; + s->data += pos + count; + s->size -= pos + count; + return result; +} diff --git a/UCD.c b/UCD.c new file mode 100644 index 0000000..074af31 --- /dev/null +++ b/UCD.c @@ -0,0 +1,2350 @@ +/* Auto-generated case mapping tables */ + +#include + +static const uint8_t cat1[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, + 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 18, 19, 19, 20, 20, 20, 20, + 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 13, 35, 13, 13, 36, 37, 33, 33, 33, 33, 33, 33, 38, 33, + 39, 40, 13, 13, 13, 13, 13, 13, 13, 41, 33, 33, 33, 33, 33, + 33, 33, 42, 43, 33, 33, 44, 33, 33, 33, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 33, 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, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 57, 13, 13, 13, 13, 58, 13, 13, 13, 13, 59, + 13, 13, 13, 13, 13, 13, 60, 61, 33, 33, 62, 33, 13, 13, 13, + 13, 63, 13, 13, 13, 13, 13, 13, 13, 13, 64, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 65, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 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, 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, 66, 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, 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, 66, +}; + +static const uint16_t cat2[] = { + 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, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 26, 26, 26, 26, 26, 68, 69, + 70, 71, 72, 73, 74, 75, 26, 26, 26, 26, 26, 26, 26, 26, 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, 12, + 106, 106, 107, 106, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 120, 120, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 129, + 130, 131, 129, 132, 129, 129, 129, 133, 134, 135, 129, 129, 129, 129, 120, + 120, 136, 137, 120, 120, 120, 120, 138, 139, 129, 129, 16, 140, 106, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 129, 129, 129, 150, 151, 152, 153, + 154, 155, 26, 156, 157, 158, 159, 160, 129, 129, 129, 129, 129, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 129, 26, 26, 26, 26, 26, 26, 26, 26, + 161, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 162, 163, 26, 26, 26, 26, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 188, 189, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 190, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 26, 26, 26, 26, 26, + 192, 26, 193, 194, 195, 196, 197, 26, 26, 26, 26, 198, 199, 200, 201, + 202, 203, 26, 204, 205, 206, 207, 208, 209, 210, 26, 211, 212, 213, 214, + 215, 216, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 26, 26, 26, 26, 231, 232, 233, 216, 234, 235, 236, 237, 238, + 193, 239, 240, 241, 242, 243, 244, 245, 246, 247, 216, 26, 248, 249, 250, + 251, 252, 253, 216, 216, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 216, 216, 281, 282, 283, 284, 285, 286, 287, 288, 216, 216, 289, + 216, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 216, 302, + 303, 304, 305, 216, 306, 307, 308, 309, 216, 216, 216, 310, 311, 312, 313, + 314, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 193, 216, 315, 316, 26, 26, 26, 317, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 318, 319, 320, 321, 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, 211, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 288, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 322, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 26, 26, 26, 26, 26, 26, + 26, 26, 299, 323, 324, 325, 326, 327, 328, 216, 216, 216, 216, 216, 216, + 329, 216, 216, 216, 330, 331, 332, 26, 333, 334, 335, 26, 26, 26, 336, + 337, 216, 26, 338, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 339, 26, 26, + 26, 26, 340, 341, 26, 26, 26, 26, 26, 342, 216, 216, 216, 216, 26, + 343, 344, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 129, 129, 129, 345, 129, 129, 129, 129, 129, 129, 346, 347, 348, 349, 129, + 350, 129, 129, 129, 351, 352, 353, 354, 355, 129, 356, 216, 357, 129, 358, + 216, 216, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 129, 129, 129, 129, 129, 129, 129, 129, 375, 376, 377, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 378, 216, 216, 216, 379, 380, 381, 216, 382, 383, 216, 216, 216, 216, + 384, 385, 216, 216, 216, 216, 216, 216, 216, 386, 216, 216, 216, 387, 216, + 216, 216, 388, 216, 216, 216, 389, 26, 26, 26, 390, 391, 392, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 393, 394, 216, 395, 216, 216, + 216, 396, 397, 398, 399, 216, 216, 216, 216, 400, 129, 401, 402, 403, 129, + 404, 405, 406, 407, 216, 216, 129, 129, 129, 408, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 409, 129, 129, 129, 410, 411, 412, 413, 414, + 129, 129, 129, 129, 129, 415, 416, 417, 129, 129, 418, 419, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 420, 26, 26, 26, 26, 421, 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, 192, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 422, 26, 26, 26, 26, 26, 26, 26, 26, 26, 423, 216, 216, 216, 216, + 216, 216, 26, 26, 26, 26, 26, 26, 26, 26, 423, 216, 216, 216, 216, + 216, 216, 216, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 424, 26, 26, 26, 425, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 426, 427, 216, 216, 12, 12, 12, 428, 216, 216, + 216, 216, 216, 216, 216, 216, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 429, +}; + +static const uint16_t cat3[] = { + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9, + 10, 0, 0, 0, 0, 11, 12, 13, 14, 6, 6, 15, 16, 9, 9, + 17, 9, 18, 18, 18, 18, 18, 18, 18, 19, 19, 20, 18, 18, 18, + 18, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 19, 32, + 18, 18, 33, 18, 18, 18, 18, 18, 18, 18, 34, 35, 36, 18, 9, + 9, 9, 9, 9, 9, 9, 9, 37, 9, 9, 9, 38, 38, 39, 38, + 40, 41, 42, 43, 41, 41, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 45, 46, 47, 48, 49, 6, 50, 51, 9, 9, + 9, 52, 53, 18, 18, 18, 54, 55, 6, 6, 6, 6, 6, 6, 9, + 9, 9, 9, 9, 9, 18, 18, 18, 18, 56, 57, 18, 18, 18, 18, + 18, 18, 58, 59, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 60, 6, 6, 6, 61, 62, 9, 9, 9, 9, 9, 63, 64, 44, + 44, 44, 44, 65, 66, 67, 68, 68, 68, 69, 70, 67, 71, 72, 44, + 73, 68, 68, 68, 68, 74, 75, 44, 44, 3, 76, 77, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 78, 79, 80, 81, 3, 82, 83, + 84, 85, 68, 68, 68, 44, 44, 44, 86, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 87, 44, 88, 67, 3, 89, 68, 68, 68, 75, 90, + 91, 68, 68, 87, 92, 93, 94, 83, 95, 68, 68, 68, 96, 68, 97, + 68, 68, 68, 98, 99, 44, 68, 68, 68, 68, 68, 100, 44, 44, 101, + 44, 44, 44, 102, 68, 68, 68, 68, 68, 68, 103, 104, 105, 106, 68, + 107, 3, 108, 68, 109, 110, 111, 68, 68, 112, 113, 114, 115, 116, 117, + 118, 119, 3, 120, 121, 122, 69, 111, 68, 68, 112, 123, 124, 125, 126, + 127, 128, 129, 3, 130, 67, 122, 131, 132, 68, 68, 112, 133, 114, 134, + 135, 136, 67, 119, 3, 137, 138, 139, 110, 111, 68, 68, 112, 133, 140, + 115, 141, 142, 118, 119, 3, 143, 67, 144, 145, 146, 147, 148, 145, 68, + 149, 150, 151, 152, 67, 129, 3, 153, 154, 155, 156, 112, 68, 68, 112, + 68, 157, 158, 159, 160, 161, 119, 3, 162, 163, 164, 156, 112, 68, 68, + 112, 165, 140, 166, 167, 168, 169, 119, 3, 170, 67, 171, 156, 112, 68, + 68, 68, 68, 172, 173, 174, 175, 176, 119, 3, 177, 178, 139, 68, 179, + 180, 68, 68, 132, 181, 179, 182, 183, 184, 129, 3, 185, 67, 186, 68, + 68, 68, 68, 68, 187, 188, 189, 190, 3, 191, 67, 67, 67, 67, 147, + 192, 68, 68, 193, 68, 187, 194, 195, 196, 3, 197, 67, 67, 67, 67, + 198, 83, 199, 200, 3, 201, 202, 203, 68, 186, 68, 68, 68, 204, 64, + 205, 206, 207, 44, 64, 44, 44, 44, 208, 209, 210, 211, 212, 67, 67, + 67, 67, 68, 68, 68, 68, 68, 213, 214, 215, 3, 216, 217, 218, 219, + 220, 221, 68, 222, 223, 3, 224, 6, 6, 6, 6, 225, 226, 9, 9, + 9, 9, 9, 227, 68, 146, 179, 146, 68, 68, 68, 68, 68, 146, 68, + 68, 68, 68, 146, 179, 146, 68, 179, 68, 68, 68, 68, 68, 68, 68, + 146, 68, 68, 68, 68, 68, 68, 68, 68, 228, 83, 229, 177, 230, 68, + 68, 231, 232, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 233, 234, + 235, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 236, 68, + 68, 237, 68, 68, 238, 68, 68, 68, 68, 68, 68, 68, 68, 68, 239, + 240, 136, 68, 68, 241, 242, 68, 68, 243, 67, 68, 68, 244, 67, 68, + 156, 245, 67, 68, 68, 68, 68, 68, 68, 246, 247, 248, 104, 249, 250, + 3, 251, 177, 252, 253, 254, 3, 251, 68, 68, 68, 68, 255, 68, 68, + 68, 68, 68, 68, 136, 256, 68, 68, 68, 68, 257, 68, 68, 68, 68, + 68, 68, 68, 68, 258, 67, 68, 68, 68, 179, 259, 260, 261, 262, 263, + 3, 68, 68, 68, 258, 204, 67, 68, 68, 68, 68, 68, 264, 68, 68, + 68, 265, 3, 266, 231, 231, 231, 231, 68, 68, 267, 268, 68, 68, 68, + 68, 68, 68, 269, 196, 270, 271, 272, 273, 3, 251, 3, 251, 274, 275, + 44, 276, 44, 44, 44, 277, 44, 278, 67, 67, 279, 68, 68, 68, 68, + 68, 280, 281, 282, 283, 3, 216, 284, 285, 286, 287, 288, 68, 68, 68, + 289, 290, 3, 89, 68, 68, 68, 68, 291, 292, 293, 294, 68, 68, 68, + 68, 295, 296, 297, 298, 3, 299, 3, 89, 68, 68, 68, 300, 9, 301, + 6, 6, 6, 6, 6, 302, 83, 67, 303, 44, 214, 304, 305, 306, 9, + 9, 9, 9, 9, 307, 38, 38, 38, 38, 38, 38, 38, 308, 9, 309, + 9, 9, 9, 310, 38, 38, 38, 38, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 311, 312, 18, 18, 18, 18, 9, 6, 234, 233, 9, 6, + 9, 6, 234, 233, 9, 313, 9, 6, 9, 234, 9, 314, 9, 314, 9, + 314, 315, 316, 317, 318, 319, 320, 9, 321, 322, 323, 324, 325, 326, 327, + 83, 328, 83, 329, 330, 83, 331, 332, 333, 334, 335, 336, 177, 337, 38, + 338, 339, 339, 339, 339, 340, 67, 44, 341, 342, 44, 343, 67, 344, 345, + 346, 347, 348, 349, 350, 351, 352, 353, 177, 177, 354, 354, 354, 354, 355, + 356, 357, 358, 359, 360, 231, 231, 231, 361, 362, 231, 231, 231, 363, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 231, 365, 231, 231, 366, 367, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 368, 231, 231, 231, 369, 364, 364, + 370, 231, 231, 231, 231, 363, 366, 231, 231, 231, 231, 231, 231, 231, 231, + 232, 67, 67, 231, 371, 67, 67, 177, 177, 177, 177, 177, 177, 177, 372, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 373, 177, 177, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 374, 231, 375, 231, + 231, 231, 231, 231, 231, 364, 231, 231, 231, 231, 231, 374, 231, 231, 231, + 231, 231, 231, 231, 376, 377, 177, 177, 177, 372, 231, 231, 231, 231, 231, + 378, 364, 364, 364, 379, 376, 364, 364, 380, 381, 381, 382, 364, 364, 364, + 364, 364, 364, 364, 383, 364, 364, 364, 384, 231, 231, 231, 231, 231, 231, + 364, 364, 385, 357, 231, 231, 231, 231, 386, 231, 9, 9, 9, 9, 387, + 388, 389, 390, 18, 18, 18, 18, 391, 392, 393, 394, 9, 9, 9, 9, + 395, 396, 68, 68, 68, 68, 68, 68, 68, 397, 398, 399, 68, 68, 179, + 67, 179, 179, 179, 179, 179, 179, 179, 179, 44, 44, 44, 44, 400, 401, + 402, 403, 404, 405, 83, 406, 407, 83, 408, 409, 67, 67, 67, 67, 231, + 231, 231, 410, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 411, 67, + 231, 231, 412, 67, 67, 67, 231, 231, 413, 376, 414, 415, 416, 417, 418, + 419, 186, 68, 68, 68, 68, 68, 68, 68, 68, 68, 179, 420, 235, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 421, 422, 68, 68, 68, 68, + 68, 186, 68, 68, 179, 423, 231, 68, 68, 68, 68, 231, 231, 231, 231, + 412, 424, 68, 68, 231, 231, 231, 425, 177, 426, 231, 231, 231, 177, 427, + 177, 231, 231, 231, 231, 177, 426, 231, 231, 231, 231, 427, 177, 68, 68, + 428, 68, 68, 68, 68, 68, 68, 204, 231, 231, 231, 231, 231, 231, 425, + 67, 68, 68, 68, 68, 68, 300, 68, 429, 68, 68, 3, 430, 67, 67, + 18, 18, 18, 18, 18, 431, 432, 433, 18, 18, 18, 434, 68, 68, 68, + 68, 68, 68, 68, 68, 435, 354, 436, 67, 41, 41, 437, 38, 438, 18, + 20, 18, 18, 18, 18, 18, 18, 18, 309, 439, 18, 440, 441, 18, 18, + 442, 443, 18, 444, 445, 18, 446, 67, 67, 447, 448, 449, 450, 68, 68, + 451, 452, 453, 454, 68, 68, 68, 68, 68, 68, 455, 67, 456, 68, 68, + 68, 68, 68, 295, 184, 457, 458, 3, 251, 44, 44, 459, 460, 3, 89, + 68, 68, 87, 461, 68, 68, 267, 44, 293, 162, 68, 68, 68, 204, 102, + 68, 68, 68, 68, 68, 462, 463, 464, 465, 3, 466, 467, 68, 3, 468, + 68, 68, 68, 68, 68, 469, 470, 67, 450, 471, 3, 472, 68, 68, 473, + 474, 68, 68, 68, 68, 68, 68, 475, 476, 257, 67, 67, 477, 68, 478, + 479, 67, 480, 480, 480, 67, 179, 179, 9, 9, 9, 9, 9, 481, 9, + 482, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 68, 68, 68, 68, + 483, 484, 3, 251, 68, 68, 68, 68, 264, 67, 68, 68, 179, 485, 68, + 68, 68, 68, 68, 264, 486, 486, 486, 486, 486, 486, 486, 486, 487, 487, + 487, 487, 487, 487, 487, 487, 68, 68, 68, 68, 68, 258, 68, 68, 68, + 68, 68, 265, 67, 67, 67, 67, 488, 67, 489, 490, 68, 491, 179, 492, + 493, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 494, + 41, 495, 231, 496, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 497, 231, 231, 68, 68, 68, 68, 68, 68, 68, 68, 498, 68, 68, + 68, 68, 68, 68, 231, 67, 67, 67, 67, 68, 499, 44, 44, 500, 501, + 44, 44, 502, 381, 503, 504, 505, 506, 507, 508, 156, 68, 68, 68, 68, + 68, 68, 68, 68, 509, 510, 2, 3, 4, 5, 6, 6, 7, 8, 9, + 9, 511, 512, 68, 74, 68, 68, 68, 68, 513, 68, 68, 68, 179, 180, + 180, 180, 514, 515, 516, 67, 517, 68, 165, 68, 68, 179, 68, 68, 518, + 68, 258, 68, 258, 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, + 97, 519, 177, 177, 177, 177, 177, 520, 231, 354, 354, 354, 354, 354, 354, + 521, 522, 231, 523, 231, 524, 525, 67, 67, 67, 67, 67, 231, 231, 231, + 231, 231, 526, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 68, 204, + 68, 68, 68, 68, 68, 68, 136, 67, 527, 177, 177, 528, 68, 68, 68, + 68, 528, 422, 68, 68, 529, 530, 68, 68, 68, 68, 87, 531, 68, 68, + 68, 532, 68, 68, 68, 68, 264, 68, 533, 67, 67, 67, 67, 67, 6, + 6, 6, 6, 6, 9, 9, 9, 9, 9, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 258, 3, 251, 6, 6, 6, 6, 534, 9, 9, 9, 9, + 535, 68, 68, 68, 68, 68, 67, 68, 68, 68, 68, 68, 68, 264, 162, + 6, 536, 6, 536, 537, 9, 538, 9, 538, 539, 68, 68, 68, 68, 68, + 68, 264, 67, 68, 68, 68, 68, 68, 68, 179, 67, 68, 68, 258, 67, + 68, 67, 67, 67, 540, 38, 38, 38, 38, 38, 541, 542, 258, 112, 68, + 68, 68, 68, 131, 543, 68, 68, 532, 177, 68, 68, 544, 427, 68, 68, + 68, 179, 545, 177, 67, 67, 67, 67, 67, 67, 68, 68, 161, 546, 68, + 68, 547, 548, 68, 68, 68, 549, 68, 68, 68, 68, 68, 68, 68, 550, + 177, 177, 551, 177, 177, 177, 177, 177, 552, 553, 165, 186, 68, 68, 258, + 554, 177, 555, 83, 398, 68, 68, 68, 556, 68, 68, 68, 557, 67, 67, + 67, 67, 68, 558, 68, 68, 559, 546, 95, 67, 68, 68, 68, 68, 68, + 68, 258, 560, 68, 68, 258, 177, 68, 68, 97, 177, 68, 68, 265, 561, + 67, 562, 67, 67, 68, 136, 67, 67, 67, 67, 67, 67, 6, 6, 6, + 6, 6, 6, 563, 67, 9, 9, 9, 9, 9, 9, 564, 551, 68, 68, + 68, 68, 565, 67, 3, 251, 3, 566, 6, 6, 233, 567, 9, 9, 234, + 568, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 177, 177, 177, 569, + 68, 68, 68, 68, 68, 570, 265, 67, 571, 67, 284, 525, 67, 67, 67, + 572, 68, 68, 68, 557, 176, 67, 68, 68, 87, 44, 573, 574, 67, 67, + 68, 68, 575, 574, 67, 67, 67, 67, 68, 68, 557, 528, 67, 67, 68, + 68, 179, 67, 576, 68, 68, 68, 68, 68, 68, 44, 190, 275, 551, 177, + 577, 3, 578, 399, 288, 68, 68, 68, 68, 68, 579, 580, 581, 582, 68, + 68, 68, 136, 3, 251, 583, 68, 68, 68, 267, 584, 585, 3, 586, 67, + 68, 68, 68, 68, 587, 67, 288, 68, 68, 68, 68, 68, 588, 205, 589, + 590, 3, 591, 562, 177, 230, 67, 68, 68, 132, 68, 68, 592, 593, 594, + 595, 67, 67, 67, 67, 67, 67, 67, 179, 596, 68, 131, 68, 597, 68, + 68, 68, 68, 68, 267, 272, 531, 3, 251, 598, 110, 111, 68, 68, 112, + 133, 599, 600, 601, 152, 422, 602, 603, 603, 67, 68, 604, 68, 68, 68, + 68, 131, 272, 605, 606, 607, 398, 608, 67, 67, 67, 68, 68, 68, 68, + 68, 68, 609, 44, 610, 611, 3, 612, 265, 67, 67, 67, 68, 68, 68, + 68, 68, 68, 272, 613, 614, 67, 3, 251, 67, 67, 67, 67, 68, 68, + 68, 68, 68, 615, 616, 617, 618, 83, 83, 619, 67, 67, 67, 67, 68, + 68, 68, 68, 68, 68, 272, 620, 621, 67, 3, 251, 83, 622, 67, 67, + 68, 68, 68, 68, 68, 623, 624, 597, 3, 251, 3, 3, 625, 67, 67, + 67, 68, 68, 68, 626, 627, 278, 3, 628, 179, 67, 67, 67, 67, 67, + 67, 67, 68, 68, 68, 68, 68, 592, 44, 629, 67, 67, 67, 67, 6, + 6, 6, 6, 9, 9, 9, 9, 3, 201, 630, 242, 179, 631, 632, 68, + 68, 68, 633, 634, 635, 67, 3, 251, 67, 67, 67, 67, 67, 67, 67, + 67, 68, 180, 68, 68, 68, 68, 636, 637, 638, 67, 67, 67, 106, 583, + 68, 68, 68, 68, 75, 639, 640, 67, 469, 641, 68, 68, 68, 68, 68, + 642, 205, 643, 644, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 136, + 83, 574, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 645, 67, 67, + 67, 68, 68, 68, 68, 597, 67, 3, 251, 68, 112, 68, 68, 68, 615, + 196, 624, 646, 67, 3, 201, 177, 230, 647, 68, 68, 68, 572, 44, 44, + 648, 649, 67, 179, 132, 68, 68, 68, 68, 650, 651, 652, 67, 3, 251, + 131, 112, 68, 68, 68, 653, 654, 136, 3, 251, 68, 68, 68, 68, 68, + 655, 3, 251, 67, 67, 67, 67, 67, 67, 68, 68, 656, 398, 657, 68, + 112, 68, 68, 68, 658, 659, 660, 83, 3, 661, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 136, 67, 177, 177, 662, 663, 664, 231, 232, 162, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 665, 622, + 67, 264, 67, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 666, 67, 68, 68, 68, 68, 68, + 68, 334, 334, 667, 44, 277, 67, 68, 68, 68, 68, 68, 68, 68, 87, + 44, 668, 3, 251, 68, 68, 68, 179, 3, 466, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 179, 3, 251, 68, 68, 68, 258, 669, 67, 68, 68, + 68, 68, 68, 68, 190, 670, 671, 67, 3, 672, 673, 68, 68, 422, 68, + 68, 67, 67, 67, 67, 67, 67, 674, 68, 68, 68, 68, 675, 3, 251, + 6, 6, 6, 6, 9, 9, 9, 9, 177, 177, 676, 644, 6, 6, 6, + 677, 9, 9, 535, 67, 67, 67, 67, 67, 68, 678, 679, 184, 184, 184, + 184, 184, 184, 399, 680, 38, 67, 67, 67, 67, 67, 67, 67, 67, 681, + 67, 682, 67, 68, 68, 258, 67, 67, 67, 67, 242, 68, 68, 68, 179, + 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 97, 67, 67, 67, 67, + 67, 67, 67, 683, 684, 68, 68, 68, 68, 97, 67, 685, 67, 67, 67, + 686, 67, 687, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 264, 68, + 68, 68, 68, 68, 97, 68, 204, 68, 136, 68, 688, 689, 67, 67, 67, + 231, 231, 231, 231, 231, 231, 3, 690, 231, 231, 231, 231, 231, 231, 411, + 691, 231, 231, 525, 67, 231, 231, 692, 67, 44, 44, 44, 44, 44, 277, + 44, 44, 196, 67, 231, 231, 231, 231, 231, 231, 411, 67, 67, 67, 67, + 67, 67, 67, 231, 231, 231, 231, 231, 231, 412, 67, 231, 231, 231, 231, + 425, 693, 231, 231, 231, 231, 231, 231, 694, 695, 696, 697, 698, 286, 231, + 231, 231, 699, 231, 231, 231, 231, 231, 231, 231, 371, 67, 67, 700, 67, + 67, 67, 67, 67, 67, 67, 177, 177, 528, 67, 177, 177, 528, 67, 231, + 231, 425, 67, 177, 177, 177, 555, 6, 6, 6, 701, 9, 9, 702, 6, + 6, 703, 315, 9, 9, 6, 6, 6, 701, 9, 9, 704, 705, 706, 703, + 707, 708, 9, 6, 6, 6, 701, 9, 9, 709, 302, 710, 711, 9, 9, + 9, 712, 713, 714, 715, 9, 9, 702, 6, 6, 703, 9, 9, 9, 6, + 6, 6, 701, 9, 9, 702, 6, 6, 703, 9, 9, 9, 6, 6, 6, + 701, 9, 9, 702, 6, 6, 703, 9, 9, 9, 6, 6, 6, 701, 9, + 9, 234, 6, 6, 6, 716, 9, 9, 717, 718, 6, 6, 719, 9, 9, + 720, 702, 6, 6, 721, 9, 9, 17, 722, 6, 6, 15, 9, 9, 9, + 723, 6, 6, 6, 716, 9, 9, 717, 724, 3, 3, 3, 3, 3, 3, + 44, 44, 44, 44, 44, 44, 725, 285, 44, 44, 44, 44, 44, 726, 727, + 231, 728, 729, 67, 730, 64, 44, 67, 67, 9, 731, 9, 488, 732, 564, + 67, 67, 196, 44, 44, 733, 734, 531, 38, 38, 38, 38, 38, 38, 38, + 735, 67, 67, 67, 399, 67, 67, 67, 67, 67, 67, 68, 68, 68, 68, + 68, 204, 736, 735, 3, 737, 67, 67, 67, 67, 67, 67, 67, 67, 68, + 68, 68, 738, 67, 67, 68, 68, 68, 68, 68, 565, 3, 739, 67, 67, + 68, 68, 68, 740, 3, 251, 67, 67, 68, 68, 68, 87, 741, 742, 68, + 68, 68, 179, 743, 87, 744, 745, 67, 67, 67, 67, 179, 632, 68, 179, + 746, 177, 196, 67, 67, 67, 67, 67, 6, 6, 6, 6, 701, 9, 9, + 9, 747, 748, 3, 466, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 562, 177, 177, 177, 177, 177, 177, 749, 750, 67, 562, 177, 177, 177, 177, + 751, 177, 752, 165, 68, 68, 68, 753, 186, 192, 754, 755, 756, 753, 757, + 753, 192, 192, 128, 68, 132, 68, 264, 758, 132, 68, 264, 67, 67, 67, + 67, 67, 67, 759, 67, 231, 231, 231, 231, 231, 411, 231, 231, 231, 231, + 411, 67, 231, 425, 693, 231, 693, 231, 693, 231, 231, 231, 412, 67, 177, + 662, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 412, 67, 67, + 67, 67, 67, 67, 760, 231, 231, 231, 371, 67, 231, 231, 231, 231, 231, + 411, 231, 525, 232, 67, 412, 67, 67, 67, 231, 231, 231, 231, 231, 231, + 231, 761, 231, 231, 231, 762, 231, 524, 231, 524, 231, 231, 231, 232, 231, + 411, 525, 67, 231, 411, 231, 231, 231, 231, 231, 231, 231, 67, 231, 232, + 231, 231, 231, 231, 231, 67, 231, 231, 231, 412, 231, 411, 232, 67, 364, + 692, 67, 67, 67, 67, 231, 231, 231, 67, 231, 412, 231, 524, 231, 763, + 231, 231, 231, 231, 231, 231, 425, 764, 231, 765, 231, 766, 231, 525, 231, + 231, 767, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 3, 768, + 68, 68, 68, 68, 67, 67, 67, 67, 68, 68, 68, 258, 68, 68, 68, + 68, 68, 68, 68, 68, 136, 67, 68, 68, 68, 68, 68, 258, 67, 67, + 67, 67, 68, 97, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 265, 769, 67, 67, 67, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 44, 44, 44, 44, 44, 44, 67, 67, 487, 487, 487, + 487, 487, 487, 487, 770, +}; + +static const uint8_t cat4[] = { + 25, 25, 25, 25, 25, 25, 25, 25, 22, 17, 17, 17, 19, 17, 17, + 17, 13, 14, 17, 18, 17, 12, 17, 17, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 17, 17, 18, 18, 18, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 17, 14, 20, 11, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 13, 18, 14, 18, 25, 22, 17, + 19, 19, 19, 19, 21, 17, 20, 21, 4, 15, 18, 26, 21, 20, 21, + 18, 10, 10, 20, 1, 17, 17, 20, 10, 4, 16, 10, 10, 10, 17, + 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 18, 0, 1, 0, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, + 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, + 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, + 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, + 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 4, 0, 1, 1, 1, + 4, 4, 4, 4, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 2, 1, 0, 1, + 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, + 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 4, 4, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 20, + 20, 20, 20, 3, 3, 3, 3, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 3, 3, 3, 3, 3, 20, 20, 20, 20, + 20, 20, 20, 3, 20, 3, 20, 5, 5, 5, 5, 5, 5, 5, 5, + 0, 1, 0, 1, 3, 20, 0, 1, 29, 29, 3, 1, 1, 1, 17, + 0, 29, 29, 29, 29, 20, 20, 0, 17, 0, 0, 0, 29, 0, 29, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 18, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, + 21, 5, 5, 5, 5, 5, 7, 7, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, + 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 29, 29, 3, 17, 17, 17, 17, 17, 17, 1, 17, 12, 29, 29, 21, + 21, 19, 29, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 12, 5, 17, 5, 5, 17, 5, 5, 17, 5, 29, 29, 29, 29, + 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 29, 29, 29, 29, 4, 4, 4, 4, 17, 17, 29, 29, 29, 26, 26, + 26, 26, 26, 26, 18, 18, 18, 17, 17, 19, 17, 17, 21, 21, 5, + 5, 5, 17, 26, 17, 17, 17, 3, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 8, 8, 17, 17, 17, 17, 4, + 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 17, 4, + 5, 5, 5, 5, 5, 5, 5, 26, 21, 5, 5, 5, 5, 5, 5, + 3, 3, 5, 5, 21, 5, 5, 5, 5, 4, 4, 8, 8, 4, 4, + 4, 21, 21, 4, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 29, 26, 4, 5, 4, 4, 4, 4, 4, 4, 5, 5, + 5, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, + 4, 29, 29, 29, 29, 29, 29, 8, 8, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 3, 3, 21, 17, 17, 17, 3, 29, 29, 5, 19, + 19, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, + 5, 5, 3, 5, 5, 5, 5, 5, 29, 29, 17, 17, 17, 17, 17, + 17, 17, 29, 4, 5, 5, 5, 29, 29, 17, 29, 4, 4, 4, 29, + 29, 29, 29, 29, 20, 4, 4, 4, 4, 4, 4, 4, 26, 26, 29, + 29, 29, 29, 29, 5, 4, 3, 5, 5, 5, 5, 5, 5, 5, 5, + 26, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 4, 4, 4, 4, + 4, 5, 6, 5, 4, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 5, 6, 6, 4, 5, 5, 5, 5, 5, 5, + 5, 4, 4, 5, 5, 17, 17, 8, 8, 17, 3, 4, 4, 4, 4, + 4, 4, 4, 5, 6, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, + 29, 29, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 29, 4, 4, + 4, 4, 4, 4, 4, 29, 4, 29, 29, 29, 4, 4, 4, 4, 29, + 29, 5, 4, 6, 6, 6, 5, 5, 5, 5, 29, 29, 6, 6, 29, + 29, 6, 6, 5, 4, 29, 29, 29, 29, 29, 29, 29, 29, 6, 29, + 29, 29, 29, 4, 4, 29, 4, 4, 4, 5, 5, 29, 29, 8, 8, + 4, 4, 19, 19, 10, 10, 10, 10, 10, 10, 21, 19, 4, 17, 5, + 29, 29, 5, 5, 6, 29, 4, 4, 4, 4, 29, 4, 4, 29, 4, + 4, 29, 4, 4, 29, 29, 5, 29, 6, 6, 6, 5, 5, 29, 29, + 29, 29, 5, 5, 29, 29, 5, 5, 5, 29, 29, 29, 5, 29, 29, + 29, 29, 29, 29, 29, 4, 4, 4, 4, 29, 4, 29, 29, 29, 29, + 29, 29, 29, 8, 8, 5, 5, 4, 4, 4, 5, 17, 29, 4, 4, + 4, 4, 4, 4, 29, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, + 29, 4, 4, 29, 4, 4, 4, 6, 5, 5, 5, 5, 5, 29, 5, + 5, 6, 29, 6, 6, 5, 29, 29, 4, 29, 29, 29, 29, 29, 29, + 29, 17, 19, 29, 29, 29, 29, 29, 29, 29, 4, 5, 5, 5, 5, + 5, 5, 29, 5, 6, 6, 29, 4, 4, 4, 4, 4, 29, 29, 5, + 4, 6, 5, 6, 29, 29, 6, 6, 5, 29, 29, 29, 29, 29, 29, + 29, 5, 5, 6, 21, 4, 10, 10, 10, 10, 10, 10, 29, 29, 5, + 4, 29, 4, 4, 4, 4, 4, 4, 29, 29, 29, 4, 4, 4, 29, + 4, 4, 4, 4, 29, 29, 29, 4, 4, 29, 4, 29, 4, 4, 29, + 29, 29, 4, 4, 29, 29, 29, 4, 4, 29, 29, 29, 29, 6, 6, + 5, 6, 6, 29, 29, 29, 6, 6, 6, 29, 6, 6, 6, 5, 29, + 29, 4, 29, 29, 29, 29, 29, 29, 6, 10, 10, 10, 21, 21, 21, + 21, 21, 21, 19, 21, 29, 29, 29, 29, 29, 5, 6, 6, 6, 5, + 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 29, 29, + 5, 4, 5, 5, 5, 6, 6, 6, 6, 29, 5, 5, 5, 29, 5, + 5, 5, 5, 29, 29, 29, 29, 29, 29, 29, 5, 5, 29, 4, 4, + 4, 29, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 17, 10, + 10, 10, 10, 10, 10, 10, 21, 4, 5, 6, 6, 17, 4, 4, 4, + 4, 4, 4, 4, 29, 4, 4, 4, 6, 6, 6, 6, 6, 29, 5, + 6, 6, 29, 6, 6, 5, 5, 29, 29, 29, 29, 29, 29, 29, 6, + 6, 29, 29, 29, 29, 29, 4, 4, 4, 29, 29, 4, 4, 6, 29, + 29, 29, 29, 5, 5, 6, 6, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 4, 6, 6, 6, 5, 5, 5, 5, 29, 6, 6, 6, 29, 6, + 6, 6, 5, 4, 21, 29, 29, 29, 29, 4, 4, 4, 6, 10, 10, + 10, 10, 10, 10, 10, 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 21, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, + 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 29, + 29, 29, 29, 5, 29, 29, 29, 29, 6, 6, 6, 5, 5, 5, 29, + 5, 29, 6, 6, 6, 6, 6, 6, 6, 6, 29, 29, 6, 6, 17, + 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 29, 29, 29, 29, 19, 4, 4, 4, + 4, 4, 4, 3, 5, 5, 5, 5, 5, 5, 5, 5, 17, 8, 8, + 17, 17, 29, 29, 29, 29, 4, 4, 4, 29, 4, 4, 4, 4, 4, + 4, 4, 4, 29, 4, 29, 4, 5, 5, 5, 5, 5, 4, 29, 29, + 4, 4, 4, 4, 4, 29, 3, 29, 5, 5, 5, 5, 5, 5, 5, + 29, 8, 8, 29, 29, 4, 4, 4, 4, 4, 21, 21, 21, 17, 17, + 17, 17, 17, 17, 17, 21, 17, 21, 21, 21, 5, 5, 21, 21, 21, + 21, 21, 21, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 21, 5, 21, 5, 21, 5, 13, 14, 13, 14, 6, 6, 4, 4, 4, + 4, 4, 29, 29, 29, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, + 5, 5, 5, 17, 5, 5, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 5, 5, 5, 5, 29, 21, 21, 21, 21, 21, 21, 21, 21, 5, 21, + 21, 21, 21, 21, 21, 29, 21, 21, 17, 17, 17, 17, 17, 21, 21, + 21, 21, 17, 17, 29, 29, 29, 29, 29, 4, 4, 4, 6, 6, 5, + 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 6, + 5, 5, 4, 8, 8, 17, 17, 17, 17, 17, 17, 4, 4, 4, 4, + 4, 4, 6, 6, 5, 5, 4, 4, 4, 4, 5, 5, 5, 4, 6, + 6, 6, 4, 4, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, + 5, 5, 5, 4, 4, 4, 4, 4, 5, 6, 6, 5, 5, 6, 6, + 6, 6, 6, 6, 5, 4, 6, 8, 8, 6, 6, 6, 5, 21, 21, + 0, 0, 0, 0, 0, 0, 29, 0, 29, 29, 29, 29, 29, 0, 29, + 29, 1, 1, 1, 17, 3, 1, 1, 1, 4, 4, 4, 29, 29, 5, + 5, 5, 17, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 29, 29, 29, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, + 29, 29, 29, 29, 0, 0, 0, 0, 0, 0, 29, 29, 1, 1, 1, + 1, 1, 1, 29, 29, 12, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 21, 17, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 13, 14, 29, 29, 29, 4, 4, 4, 17, 17, 17, 9, 9, + 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 5, 5, 6, 17, + 17, 29, 4, 4, 5, 5, 29, 29, 29, 29, 4, 29, 5, 5, 29, + 29, 29, 29, 4, 4, 4, 4, 5, 5, 6, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 5, 5, 5, + 5, 17, 17, 17, 3, 17, 17, 17, 19, 4, 5, 29, 29, 8, 8, + 29, 29, 29, 29, 29, 29, 10, 10, 29, 29, 29, 29, 29, 29, 17, + 17, 17, 17, 17, 17, 12, 17, 17, 17, 17, 5, 5, 5, 26, 5, + 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, + 4, 4, 5, 4, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, + 29, 29, 5, 5, 5, 6, 6, 6, 6, 5, 5, 6, 6, 6, 29, + 29, 29, 29, 6, 6, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, + 29, 29, 29, 29, 21, 29, 29, 29, 17, 17, 8, 8, 4, 4, 4, + 4, 29, 29, 29, 29, 4, 4, 29, 29, 29, 29, 29, 29, 8, 8, + 10, 29, 29, 29, 21, 21, 4, 4, 4, 4, 4, 4, 4, 5, 5, + 6, 6, 5, 29, 29, 17, 17, 4, 4, 4, 4, 4, 6, 5, 6, + 5, 6, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, + 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 29, + 29, 5, 17, 17, 17, 17, 17, 17, 17, 3, 17, 17, 17, 17, 17, + 17, 29, 29, 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, + 5, 5, 29, 29, 5, 5, 5, 5, 29, 29, 29, 29, 5, 5, 5, + 5, 6, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5, 5, 5, + 5, 6, 5, 6, 6, 6, 6, 6, 5, 6, 6, 4, 4, 4, 4, + 4, 4, 4, 4, 29, 17, 17, 17, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 17, 17, 17, 5, 5, 6, 4, 4, 4, + 4, 4, 4, 6, 5, 5, 5, 5, 6, 6, 5, 5, 6, 5, 5, + 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5, 6, 6, + 6, 5, 6, 5, 5, 5, 6, 6, 29, 29, 29, 29, 29, 29, 29, + 29, 17, 17, 17, 17, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, + 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 29, + 29, 29, 17, 17, 17, 17, 17, 8, 8, 29, 29, 29, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 17, 17, 1, 0, 1, 29, 29, 29, 29, + 29, 0, 0, 0, 29, 29, 0, 0, 0, 5, 5, 5, 17, 5, 5, + 5, 5, 5, 4, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 5, + 4, 4, 6, 5, 5, 4, 29, 29, 29, 29, 29, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 0, 1, + 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 29, + 0, 29, 0, 29, 0, 29, 0, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 29, 1, 1, 0, 0, 0, 0, 2, 20, 1, + 20, 20, 20, 1, 1, 1, 29, 1, 1, 0, 0, 0, 0, 2, 20, + 20, 20, 1, 1, 1, 1, 29, 29, 1, 1, 0, 0, 0, 0, 29, + 20, 20, 20, 0, 0, 0, 0, 0, 20, 20, 20, 29, 29, 1, 1, + 1, 29, 1, 1, 0, 0, 0, 0, 2, 20, 20, 29, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 26, 26, 26, 26, 26, 12, 12, + 12, 12, 12, 12, 17, 17, 15, 16, 13, 15, 15, 16, 13, 15, 23, + 24, 26, 26, 26, 26, 26, 22, 17, 15, 16, 17, 17, 17, 17, 11, + 11, 17, 17, 17, 18, 13, 14, 17, 17, 17, 18, 17, 11, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 22, 26, 26, 26, 26, 26, 29, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 10, 3, 29, 29, 10, + 10, 10, 10, 10, 10, 18, 18, 18, 13, 14, 3, 10, 10, 18, 18, + 18, 13, 14, 29, 3, 3, 3, 3, 3, 29, 29, 29, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 29, 29, 29, 29, 29, 29, 5, 5, + 5, 5, 5, 7, 7, 7, 7, 5, 7, 7, 7, 5, 5, 5, 5, + 29, 29, 29, 29, 29, 29, 29, 21, 21, 0, 21, 21, 21, 21, 0, + 21, 21, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 21, 0, 21, + 21, 18, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 0, 21, + 0, 21, 0, 21, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 1, + 4, 4, 4, 4, 1, 21, 21, 1, 1, 0, 0, 18, 18, 18, 18, + 18, 0, 1, 1, 1, 1, 21, 18, 21, 21, 1, 21, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 9, 9, 9, 10, + 21, 21, 29, 29, 29, 29, 18, 18, 18, 18, 18, 21, 21, 21, 21, + 21, 18, 18, 21, 21, 21, 21, 18, 21, 21, 18, 21, 21, 18, 21, + 21, 21, 21, 21, 21, 21, 18, 21, 21, 21, 21, 21, 21, 21, 18, + 18, 21, 21, 18, 21, 18, 21, 21, 21, 21, 21, 21, 21, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 13, 14, 13, 14, 21, + 21, 21, 21, 18, 18, 21, 21, 21, 21, 21, 21, 21, 13, 14, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 18, 21, 21, 21, 21, 21, 21, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 21, 21, 21, 21, 21, 21, + 21, 29, 29, 29, 29, 29, 10, 10, 10, 10, 21, 21, 21, 21, 21, + 21, 10, 10, 10, 10, 10, 10, 21, 21, 21, 21, 21, 21, 21, 18, + 21, 18, 21, 21, 21, 21, 21, 21, 13, 14, 13, 14, 13, 14, 13, + 14, 13, 14, 13, 14, 13, 14, 10, 10, 18, 18, 18, 18, 18, 13, + 14, 18, 18, 18, 18, 18, 18, 18, 13, 14, 18, 18, 18, 13, 14, + 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 13, 14, 18, 18, 18, + 18, 18, 18, 18, 13, 14, 13, 14, 18, 18, 18, 18, 18, 18, 18, + 18, 13, 14, 18, 18, 18, 18, 18, 18, 18, 21, 21, 18, 21, 21, + 21, 21, 29, 29, 21, 21, 0, 1, 0, 0, 0, 1, 1, 0, 1, + 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 3, 3, 0, 0, 0, 1, 0, 1, 1, 21, 21, + 21, 21, 21, 21, 0, 1, 0, 1, 5, 5, 5, 0, 1, 29, 29, + 29, 29, 29, 17, 17, 17, 17, 10, 17, 17, 1, 1, 1, 1, 1, + 1, 29, 1, 29, 29, 29, 29, 29, 1, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 3, 17, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 5, 17, 17, 15, 16, 15, 16, 17, 17, 17, 15, + 16, 17, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 12, 17, + 17, 12, 17, 15, 16, 17, 17, 15, 16, 13, 14, 13, 14, 13, 14, + 13, 14, 17, 17, 17, 17, 17, 3, 17, 17, 12, 12, 17, 17, 17, + 17, 12, 17, 13, 17, 17, 17, 17, 17, 21, 21, 17, 17, 17, 13, + 14, 13, 14, 13, 14, 13, 14, 12, 29, 29, 21, 21, 29, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 21, 21, 21, 21, + 21, 21, 29, 29, 22, 17, 17, 17, 21, 3, 4, 9, 13, 14, 21, + 21, 13, 14, 13, 14, 13, 14, 13, 14, 12, 13, 14, 14, 21, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 6, 6, 12, + 3, 3, 3, 3, 3, 21, 21, 9, 9, 9, 3, 4, 17, 21, 21, + 29, 5, 5, 20, 20, 3, 3, 4, 4, 4, 4, 17, 3, 3, 3, + 4, 29, 29, 29, 29, 29, 4, 4, 4, 21, 21, 10, 10, 10, 10, + 21, 21, 29, 29, 29, 29, 29, 29, 29, 21, 21, 21, 21, 21, 21, + 21, 21, 29, 10, 10, 21, 21, 21, 21, 21, 21, 21, 10, 10, 10, + 10, 10, 10, 10, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, + 4, 3, 17, 17, 17, 8, 8, 4, 4, 29, 29, 29, 29, 0, 1, + 0, 1, 0, 1, 4, 5, 7, 7, 7, 17, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 17, 3, 0, 1, 0, 1, 3, 3, 5, 5, + 4, 4, 4, 4, 4, 4, 9, 9, 5, 5, 17, 17, 17, 17, 17, + 17, 20, 20, 20, 20, 20, 20, 20, 3, 20, 20, 0, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 3, 20, 20, 0, 1, + 0, 1, 4, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 29, 29, 29, 29, 3, 3, 3, 3, 0, 1, 4, 3, + 3, 1, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 5, 4, + 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5, + 6, 21, 21, 21, 21, 5, 29, 29, 29, 10, 10, 10, 10, 10, 10, + 21, 21, 19, 21, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 17, + 17, 17, 17, 6, 6, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, + 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 17, 17, 5, 5, 4, + 4, 4, 4, 4, 4, 17, 17, 17, 4, 17, 4, 4, 5, 5, 5, + 5, 5, 5, 5, 17, 17, 4, 4, 4, 5, 6, 6, 5, 5, 5, + 5, 6, 6, 5, 5, 6, 6, 6, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 29, 3, 8, 8, 29, 29, 29, 29, 17, + 17, 4, 4, 4, 4, 4, 5, 3, 4, 8, 8, 4, 4, 4, 4, + 4, 29, 4, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 6, 6, + 5, 5, 29, 4, 4, 4, 4, 5, 6, 29, 29, 8, 8, 29, 29, + 17, 17, 17, 17, 3, 4, 4, 4, 4, 4, 4, 21, 21, 21, 4, + 6, 5, 6, 4, 4, 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, + 4, 4, 4, 4, 5, 5, 29, 29, 29, 4, 4, 3, 17, 17, 4, + 4, 4, 6, 5, 5, 6, 6, 17, 17, 4, 3, 3, 6, 5, 29, + 29, 4, 4, 4, 4, 4, 4, 29, 1, 1, 1, 20, 3, 3, 3, + 3, 1, 3, 20, 20, 29, 29, 29, 29, 4, 4, 4, 6, 6, 5, + 6, 6, 5, 6, 6, 17, 6, 5, 29, 29, 29, 29, 29, 4, 4, + 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, + 28, 28, 28, 28, 1, 1, 1, 1, 1, 1, 1, 29, 29, 29, 29, + 1, 1, 1, 1, 1, 29, 29, 29, 29, 29, 4, 5, 4, 4, 18, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 29, 4, + 4, 29, 4, 4, 29, 4, 4, 4, 4, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 14, 13, 21, 21, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 19, 21, 21, 21, 17, 17, 17, 17, 17, + 17, 17, 13, 14, 17, 29, 29, 29, 29, 29, 29, 17, 12, 12, 11, + 11, 13, 14, 13, 14, 13, 14, 13, 14, 17, 17, 13, 14, 17, 17, + 17, 17, 11, 11, 11, 17, 17, 17, 29, 17, 17, 17, 17, 12, 13, + 14, 13, 14, 13, 14, 17, 17, 17, 18, 12, 18, 18, 18, 29, 17, + 19, 17, 17, 29, 29, 29, 29, 4, 4, 4, 4, 4, 29, 29, 26, + 29, 17, 17, 17, 19, 17, 17, 17, 1, 1, 1, 13, 18, 14, 18, + 13, 14, 17, 13, 14, 17, 17, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 29, 29, 4, 4, 4, 29, 29, 29, 19, 19, 18, 20, 21, + 19, 19, 29, 21, 18, 18, 18, 18, 21, 21, 29, 29, 26, 26, 26, + 21, 21, 29, 29, 4, 4, 4, 29, 4, 4, 29, 4, 17, 17, 17, + 29, 29, 29, 29, 10, 10, 10, 10, 10, 29, 29, 29, 21, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 10, 10, 21, 21, 21, 29, 21, 21, 21, 21, 21, 29, 29, 29, + 21, 29, 29, 29, 29, 29, 29, 29, 21, 21, 21, 21, 21, 5, 29, + 29, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 29, 29, + 29, 29, 4, 9, 4, 4, 4, 4, 4, 4, 4, 4, 9, 29, 29, + 29, 29, 29, 5, 5, 5, 29, 29, 29, 29, 29, 4, 4, 4, 4, + 4, 4, 29, 17, 17, 9, 9, 9, 9, 9, 29, 29, 0, 0, 0, + 0, 29, 29, 29, 29, 1, 1, 1, 1, 29, 29, 29, 29, 0, 0, + 0, 29, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 29, 1, 1, + 1, 29, 1, 1, 1, 1, 1, 1, 1, 29, 1, 1, 29, 29, 29, + 3, 3, 3, 3, 3, 3, 29, 3, 3, 29, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 29, 29, 29, 29, 29, 4, 29, 29, 29, 4, 29, + 29, 4, 4, 4, 4, 4, 4, 4, 4, 21, 29, 29, 29, 29, 29, + 29, 29, 10, 29, 29, 29, 10, 10, 10, 10, 10, 4, 4, 4, 4, + 4, 4, 10, 10, 10, 10, 10, 10, 29, 29, 29, 17, 4, 4, 29, + 29, 29, 29, 29, 17, 29, 29, 29, 29, 10, 10, 4, 4, 29, 29, + 10, 10, 10, 10, 10, 10, 4, 5, 5, 5, 29, 5, 5, 29, 29, + 29, 29, 29, 5, 5, 5, 5, 5, 5, 5, 29, 29, 29, 29, 5, + 10, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 10, 10, + 17, 4, 4, 4, 4, 4, 10, 10, 10, 21, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 5, 5, 29, 29, 17, 17, 17, 17, + 17, 17, 17, 29, 17, 17, 17, 17, 29, 29, 29, 29, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 29, 29, 29, 29, 29, 1, 1, 1, + 29, 29, 29, 29, 29, 4, 4, 4, 4, 5, 5, 5, 5, 8, 8, + 4, 4, 4, 4, 3, 4, 29, 5, 5, 5, 5, 5, 12, 3, 29, + 29, 29, 29, 29, 29, 18, 18, 10, 10, 10, 10, 10, 10, 10, 29, + 4, 4, 29, 5, 5, 12, 29, 29, 29, 29, 4, 4, 4, 3, 4, + 4, 29, 29, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 17, + 17, 17, 17, 17, 29, 29, 29, 29, 29, 29, 4, 4, 5, 5, 5, + 5, 17, 17, 6, 5, 6, 4, 4, 4, 4, 4, 10, 10, 10, 10, + 10, 10, 8, 8, 5, 4, 4, 5, 5, 4, 29, 29, 6, 6, 6, + 5, 5, 5, 5, 6, 6, 5, 5, 17, 17, 26, 17, 17, 17, 17, + 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 26, 29, 29, 5, + 5, 5, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 5, 5, 5, + 5, 5, 5, 5, 5, 29, 8, 8, 17, 17, 17, 17, 4, 6, 6, + 4, 4, 4, 4, 5, 17, 17, 4, 29, 4, 4, 4, 6, 6, 6, + 5, 5, 6, 4, 4, 4, 4, 17, 17, 17, 17, 5, 5, 5, 5, + 17, 6, 5, 8, 8, 4, 17, 4, 17, 17, 17, 4, 4, 4, 4, + 6, 6, 6, 5, 5, 5, 6, 6, 5, 6, 5, 5, 17, 17, 17, + 17, 17, 17, 5, 4, 4, 5, 29, 29, 29, 29, 29, 29, 4, 29, + 4, 4, 4, 4, 29, 4, 4, 17, 29, 29, 29, 29, 29, 29, 5, + 5, 6, 6, 29, 4, 4, 4, 4, 4, 29, 5, 5, 4, 6, 6, + 5, 6, 6, 6, 6, 29, 29, 6, 6, 29, 29, 6, 6, 6, 29, + 29, 4, 4, 6, 6, 29, 29, 5, 5, 5, 5, 5, 5, 5, 29, + 29, 29, 4, 4, 29, 4, 29, 29, 4, 29, 5, 29, 6, 29, 29, + 6, 29, 6, 6, 6, 6, 29, 6, 6, 5, 6, 5, 4, 5, 4, + 17, 17, 29, 17, 29, 5, 5, 29, 29, 29, 29, 29, 4, 4, 4, + 4, 4, 6, 6, 6, 6, 6, 5, 5, 5, 6, 5, 4, 4, 4, + 4, 17, 17, 17, 17, 17, 8, 8, 17, 17, 29, 17, 5, 4, 5, + 6, 5, 6, 6, 6, 6, 5, 5, 6, 5, 5, 4, 4, 17, 4, + 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 5, 5, 5, 5, 29, + 29, 6, 6, 6, 6, 5, 5, 6, 5, 5, 17, 17, 17, 17, 17, + 17, 17, 4, 4, 4, 4, 5, 5, 29, 29, 5, 5, 5, 6, 6, + 5, 6, 5, 5, 17, 17, 17, 4, 29, 29, 29, 17, 17, 17, 17, + 17, 29, 29, 29, 4, 4, 4, 5, 6, 5, 6, 6, 5, 5, 5, + 5, 5, 5, 6, 5, 8, 8, 8, 8, 29, 29, 29, 29, 4, 4, + 4, 29, 29, 5, 6, 5, 6, 6, 5, 5, 5, 5, 6, 5, 8, + 8, 10, 10, 17, 17, 17, 21, 6, 5, 5, 17, 29, 29, 29, 29, + 10, 10, 10, 29, 29, 29, 29, 29, 29, 4, 29, 29, 4, 4, 4, + 4, 4, 4, 4, 4, 29, 4, 4, 29, 6, 6, 6, 6, 6, 6, + 29, 6, 6, 29, 29, 5, 5, 6, 5, 4, 6, 4, 6, 5, 17, + 17, 17, 29, 4, 6, 6, 6, 5, 5, 5, 5, 29, 29, 5, 5, + 6, 6, 6, 6, 5, 4, 17, 4, 6, 29, 29, 29, 5, 6, 4, + 5, 5, 5, 5, 17, 17, 17, 17, 17, 17, 17, 17, 5, 6, 5, + 5, 5, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 17, 17, 17, 4, 17, 17, 17, 17, 17, 29, 29, 29, 29, 29, + 5, 6, 5, 5, 5, 6, 5, 6, 4, 17, 17, 17, 17, 17, 29, + 29, 17, 17, 4, 4, 4, 4, 4, 4, 29, 6, 5, 5, 5, 5, + 5, 5, 5, 6, 5, 5, 6, 5, 5, 29, 4, 5, 5, 5, 5, + 5, 5, 29, 29, 29, 5, 29, 5, 5, 29, 5, 5, 5, 5, 5, + 5, 5, 4, 5, 4, 4, 6, 6, 6, 6, 6, 29, 5, 5, 29, + 6, 6, 5, 6, 5, 4, 3, 4, 4, 29, 29, 29, 29, 4, 4, + 4, 5, 5, 6, 6, 17, 5, 5, 4, 6, 4, 4, 4, 4, 4, + 4, 4, 4, 6, 6, 5, 5, 5, 5, 5, 29, 29, 29, 6, 6, + 5, 6, 5, 17, 17, 17, 17, 17, 8, 8, 5, 29, 29, 29, 29, + 29, 10, 10, 10, 10, 10, 21, 21, 21, 21, 21, 21, 21, 21, 19, + 19, 19, 19, 21, 21, 21, 21, 21, 21, 21, 9, 9, 9, 9, 9, + 9, 9, 29, 4, 17, 17, 29, 29, 29, 29, 29, 5, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 5, + 5, 5, 17, 29, 29, 17, 17, 17, 17, 21, 21, 21, 21, 3, 3, + 3, 3, 17, 21, 29, 29, 8, 8, 29, 10, 10, 10, 10, 10, 10, + 10, 29, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 3, 3, 17, 17, 17, 10, 10, 10, 10, 10, 10, 10, + 17, 0, 29, 29, 1, 1, 1, 1, 1, 4, 4, 4, 29, 29, 29, + 29, 5, 4, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 3, 3, + 3, 3, 3, 3, 3, 17, 3, 5, 29, 29, 29, 6, 6, 3, 3, + 9, 9, 9, 29, 3, 3, 3, 3, 29, 3, 3, 3, 3, 3, 3, + 3, 29, 3, 3, 29, 29, 29, 4, 29, 29, 29, 29, 29, 4, 4, + 4, 29, 29, 4, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, + 4, 29, 29, 21, 5, 5, 17, 26, 26, 26, 26, 29, 29, 29, 29, + 8, 8, 21, 21, 21, 29, 29, 29, 29, 29, 21, 21, 21, 21, 21, + 21, 18, 29, 29, 29, 29, 29, 29, 29, 29, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 6, 6, 5, 5, 5, 21, 21, 21, + 6, 6, 6, 6, 6, 6, 26, 26, 26, 26, 26, 26, 26, 26, 5, + 5, 5, 5, 5, 5, 5, 5, 21, 21, 5, 5, 5, 21, 21, 5, + 5, 5, 5, 21, 21, 21, 21, 5, 5, 5, 21, 29, 29, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 29, 0, 0, + 29, 29, 0, 29, 29, 0, 0, 29, 29, 0, 0, 0, 0, 29, 0, + 0, 1, 1, 29, 1, 29, 1, 1, 1, 1, 1, 1, 1, 29, 1, + 1, 1, 1, 1, 1, 1, 0, 0, 29, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 0, 0, 0, 0, 29, 1, 1, 0, 0, 29, 0, + 0, 0, 0, 29, 0, 0, 0, 0, 0, 29, 0, 29, 29, 29, 0, + 0, 0, 0, 0, 0, 0, 29, 1, 1, 1, 1, 1, 1, 0, 18, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 18, 1, 1, 0, 0, 0, 0, 0, 18, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 18, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 29, 29, 8, 8, 5, 5, 5, 5, 5, + 5, 5, 21, 5, 5, 5, 5, 5, 21, 21, 21, 21, 21, 21, 21, + 21, 5, 21, 21, 21, 21, 21, 21, 5, 21, 21, 17, 17, 17, 17, + 17, 29, 29, 29, 29, 29, 29, 29, 5, 5, 5, 5, 5, 1, 1, + 4, 1, 1, 1, 1, 1, 29, 29, 29, 29, 29, 1, 1, 1, 5, + 29, 29, 5, 5, 5, 5, 5, 5, 5, 29, 5, 5, 29, 5, 5, + 3, 3, 3, 3, 3, 3, 29, 29, 5, 5, 5, 5, 5, 5, 5, + 3, 8, 8, 29, 29, 29, 29, 4, 21, 4, 4, 4, 4, 4, 4, + 5, 29, 8, 8, 29, 29, 29, 29, 29, 19, 4, 4, 4, 3, 5, + 5, 5, 5, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, + 29, 29, 29, 17, 4, 4, 4, 5, 4, 4, 5, 4, 4, 4, 4, + 4, 4, 5, 29, 29, 29, 29, 29, 29, 29, 29, 4, 3, 4, 4, + 4, 4, 4, 29, 29, 10, 1, 1, 1, 1, 5, 5, 5, 5, 5, + 5, 5, 3, 29, 29, 29, 29, 10, 10, 10, 10, 21, 10, 10, 10, + 19, 10, 10, 10, 10, 29, 29, 29, 10, 10, 10, 10, 10, 10, 21, + 10, 10, 10, 10, 10, 10, 10, 29, 29, 29, 4, 4, 29, 4, 29, + 29, 4, 29, 4, 29, 4, 29, 29, 29, 29, 29, 29, 4, 29, 29, + 29, 29, 4, 29, 4, 29, 4, 29, 4, 4, 4, 29, 4, 29, 4, + 29, 4, 29, 4, 29, 4, 4, 4, 29, 4, 4, 4, 18, 18, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 21, 21, 21, 21, + 21, 20, 20, 20, 20, 20, 21, 29, 29, 29, 21, 21, 21, 21, 21, + 21, 21, 29, 29, 29, 21, 21, 21, 29, 29, 29, 29, 21, 21, 21, + 21, 21, 21, 21, 21, 29, 29, 21, 21, 21, 21, 29, 29, 29, 29, + 21, 21, 21, 21, 29, 21, 21, 21, 21, 8, 8, 21, 29, 29, 29, + 29, 29, 29, 26, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, + 28, 29, 29, +}; + +static const uint8_t low1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 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, 2, 2, 2, 2, 2, 8, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 9, 2, 10, 2, 11, 2, 2, 12, 2, 2, 2, 2, + 2, 2, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, +}; + +static const uint8_t low2[] = { + 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, + 0, 5, 5, 5, 6, 7, 5, 5, 8, 9, 10, 11, 12, 13, 14, + 5, 15, 5, 5, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, 1, 21, 0, + 22, 23, 5, 24, 25, 3, 3, 0, 0, 0, 5, 5, 26, 5, 5, + 5, 27, 5, 5, 5, 5, 5, 5, 28, 29, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 31, 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 33, 33, 33, 33, + 34, 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 36, 37, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 38, 5, 5, + 5, 5, 5, 5, 39, 40, 39, 39, 40, 41, 39, 0, 39, 39, 39, + 42, 43, 44, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 47, 48, 0, 0, 49, 0, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 29, + 29, 0, 0, 0, 53, 54, 5, 5, 5, 5, 5, 5, 55, 56, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 57, 0, 5, 58, 0, + 0, 0, 0, 0, 0, 0, 0, 59, 59, 5, 5, 5, 60, 61, 62, + 63, 64, 65, 66, 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, 1, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 68, 69, 0, 0, + 0, 0, 0, 0, 0, 0, 68, 68, 70, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 71, 71, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 73, 73, 73, 74, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 75, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, + 0, 0, 0, 0, 76, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 78, 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, +}; + +static const uint8_t low3[] = { + 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, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 4, 2, 0, 2, 0, 2, 0, 0, 0, 5, 2, 0, 2, 0, + 6, 2, 0, 7, 7, 2, 0, 0, 8, 9, 10, 2, 0, 7, 11, + 0, 12, 13, 2, 0, 0, 0, 12, 14, 0, 15, 2, 0, 2, 0, + 2, 0, 16, 2, 0, 16, 0, 0, 2, 0, 16, 2, 0, 17, 17, + 2, 0, 2, 0, 18, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 19, 2, 0, 19, 2, 0, 19, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 2, 0, + 0, 19, 2, 0, 2, 0, 20, 21, 2, 0, 2, 0, 2, 0, 2, + 0, 22, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 23, 2, 0, + 24, 25, 0, 0, 2, 0, 26, 27, 28, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 30, 0, 31, 31, + 31, 0, 32, 0, 33, 33, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 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, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 35, 0, + 0, 2, 0, 36, 2, 0, 0, 22, 22, 22, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 38, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 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, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 0, 40, 0, 0, 0, 0, 0, + 40, 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 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, 42, 42, 42, 42, + 42, 42, 42, 0, 0, 42, 42, 42, 2, 0, 2, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, + 0, 0, 0, 44, 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 44, 0, 44, 0, 44, 0, 44, 0, 0, 0, + 0, 0, 0, 0, 0, 44, 44, 45, 45, 46, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 46, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 44, 44, 48, 48, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 49, 49, 36, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 51, 51, 46, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 53, 54, 0, + 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 58, 59, 60, 0, 0, + 2, 0, 2, 0, 2, 0, 61, 62, 63, 64, 0, 2, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 65, 65, 2, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 66, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 67, + 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 68, 69, + 70, 71, 68, 0, 72, 73, 74, 75, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 76, 77, 78, 2, 0, 2, + 0, 79, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 0, 0, 0, 0, 0, 0, 0, 0, 81, 81, 81, 81, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 0, 82, 82, 82, 82, 82, 82, 82, + 0, 82, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, + 0, 0, 0, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, +}; + +static const uint32_t low4[] = { + 0, 32, 1, -199, -121, 210, 206, 205, 79, 202, 203, 207, 211, 209, 213, + 214, 218, 217, 219, 2, -97, -56, -130, 10795, -163, 10792, -195, 69, 71, 116, + 38, 37, 64, 63, 8, -60, -7, 80, 15, 48, 7264, 38864, -3008, -7615, -8, + -74, -9, -86, -100, -112, -128, -126, -7517, -8383, -8262, 28, 16, 26, -10743, -3814, + -10727, -10780, -10749, -10783, -10782, -10815, -35332, -42280, -42308, -42319, -42315, -42305, -42258, -42282, -42261, + 928, -48, -42307, -35384, -42343, -42561, 40, 39, 27, 34, +}; + +static const uint8_t upp1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 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, 2, 2, 2, 2, 2, 8, 9, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 10, 2, 11, 2, 12, 2, 2, 13, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, +}; + +static const uint8_t upp2[] = { + 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 0, 0, 4, + 5, 6, 6, 6, 7, 8, 6, 6, 9, 10, 11, 12, 13, 14, 15, + 6, 16, 6, 6, 17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 26, 0, 0, 27, 1, + 28, 29, 6, 30, 0, 0, 0, 4, 4, 31, 6, 6, 32, 6, 6, + 6, 33, 6, 6, 6, 6, 6, 6, 0, 0, 0, 34, 35, 36, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 37, 38, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 43, 6, 6, + 6, 6, 6, 6, 44, 45, 44, 44, 45, 46, 44, 47, 44, 44, 44, + 48, 49, 50, 51, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 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, 55, 56, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, 35, 35, 57, 58, 6, 6, 6, 6, 6, 6, 59, 60, 61, + 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, 6, 6, 63, 0, 6, 64, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 17, 6, 6, 6, 65, 66, 67, + 68, 69, 70, 64, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 73, 73, 73, 73, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 75, 75, 0, 0, 0, 0, 0, 0, 0, 0, 74, 75, 76, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 78, 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, + 80, 80, 80, 81, 0, 0, 0, 0, 0, 0, 0, 4, 82, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 0, 0, 0, 83, 84, 85, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 86, 87, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 uint8_t upp3[] = { + 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, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 3, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 4, 0, 4, 0, 5, 0, 4, 0, 4, 0, 4, + 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 0, 4, 0, 4, 0, 4, 6, 7, 0, 0, 4, 0, + 4, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 4, 0, + 0, 8, 0, 0, 0, 4, 9, 10, 0, 0, 11, 0, 0, 4, 0, + 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 4, 0, + 0, 0, 4, 0, 4, 0, 0, 4, 0, 0, 0, 4, 0, 12, 0, + 0, 0, 0, 0, 4, 13, 0, 4, 13, 0, 4, 13, 0, 4, 0, + 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 14, 0, + 4, 0, 0, 4, 13, 0, 4, 0, 0, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 15, 15, 0, 4, 0, 0, 0, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 4, 16, 17, 18, 19, 20, 0, 21, 21, 0, 22, + 0, 23, 24, 0, 0, 0, 21, 25, 0, 26, 27, 28, 29, 0, 30, + 31, 29, 32, 33, 0, 0, 31, 0, 34, 35, 0, 0, 36, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 0, 38, 0, 39, 38, 0, 0, 0, + 40, 38, 41, 42, 42, 43, 0, 0, 0, 0, 0, 44, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 45, 46, 0, 0, 0, 0, 0, 0, + 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, + 0, 0, 0, 4, 0, 0, 0, 11, 11, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 49, 49, 1, 1, + 50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51, 52, 52, 0, 53, + 54, 0, 0, 0, 55, 56, 57, 0, 4, 0, 4, 0, 4, 0, 4, + 58, 59, 60, 61, 0, 62, 0, 0, 4, 0, 0, 4, 0, 0, 0, + 0, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 4, 0, 4, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 4, 63, 0, 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, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 0, 0, 65, 65, 65, 0, 0, 0, 0, 0, 0, + 0, 0, 57, 57, 57, 57, 57, 57, 0, 0, 66, 67, 68, 69, 69, + 70, 71, 72, 73, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 74, 0, 0, 0, 75, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 4, + 0, 4, 0, 4, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 78, + 78, 78, 78, 78, 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, 0, + 78, 78, 78, 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 78, 0, 78, 0, 78, 0, 78, 0, 0, 0, 0, 0, 0, + 0, 0, 79, 79, 80, 80, 80, 80, 81, 81, 82, 82, 83, 83, 84, + 84, 0, 0, 78, 78, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 86, 0, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 78, 78, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 78, 78, 0, 0, 0, 60, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 87, 0, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 89, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 90, 91, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 0, 92, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 4, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 4, 0, 4, 93, 0, 0, 4, + 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 0, 0, 0, 4, 0, 4, 0, 0, 4, 0, 4, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 0, 97, 97, 97, 97, 97, 97, 97, 0, + 97, 97, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 99, 99, 99, 99, 99, + 99, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint32_t upp4[] = { + 0, -32, 743, 121, -1, -232, -300, 195, 97, 163, 42561, 130, 56, -2, -79, + 10815, 10783, 10780, 10782, -210, -206, -205, -202, -203, 42319, 42315, -207, 42343, 42280, 42308, + -209, -211, 10743, 42305, 10749, -213, -214, 10727, -218, 42307, 42282, -69, -217, -71, -219, + 42261, 42258, 84, -38, -37, -31, -64, -63, -62, -57, -47, -54, -8, -86, -80, + 7, -116, -96, -15, -48, 3008, -6254, -6253, -6244, -6242, -6243, -6236, -6181, 35266, 35332, + 3814, 35384, -59, 8, 74, 86, 100, 128, 112, 126, 9, -7205, -28, -16, -26, + -10795, -10792, -7264, 48, -928, -38864, -40, -39, -27, -34, +}; + +static const uint8_t tit1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 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, 2, 2, 2, 2, 2, 8, 9, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 10, 2, 11, 2, 12, 2, 2, 13, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, +}; + +static const uint8_t tit2[] = { + 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 3, 0, 0, 4, + 5, 6, 6, 6, 7, 8, 6, 6, 9, 10, 11, 12, 13, 14, 15, + 6, 16, 6, 6, 17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 26, 0, 0, 27, 1, + 28, 29, 6, 30, 0, 0, 0, 4, 4, 31, 6, 6, 32, 6, 6, + 6, 33, 6, 6, 6, 6, 6, 6, 0, 0, 0, 34, 35, 36, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 37, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 41, 6, 6, + 6, 6, 6, 6, 42, 43, 42, 42, 43, 44, 42, 45, 42, 42, 42, + 46, 47, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 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, 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, 35, 35, 35, 55, 56, 6, 6, 6, 6, 6, 6, 57, 58, 59, + 59, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 61, 0, 6, 62, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 17, 6, 6, 6, 63, 64, 65, + 66, 67, 68, 62, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, + 0, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 72, 73, 73, 0, 0, 0, 0, 0, 0, 0, 0, 72, 73, 74, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 77, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 78, 78, 78, 79, 0, 0, 0, 0, 0, 0, 0, 4, 80, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 0, 0, 0, 81, 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, 0, 0, 0, 0, + 0, 0, 0, 84, 85, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 uint8_t tit3[] = { + 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, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 3, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 4, 0, 4, 0, 5, 0, 4, 0, 4, 0, 4, + 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 0, 4, 0, 4, 0, 4, 6, 7, 0, 0, 4, 0, + 4, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 4, 0, + 0, 8, 0, 0, 0, 4, 9, 10, 0, 0, 11, 0, 0, 4, 0, + 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 4, 0, + 0, 0, 4, 0, 4, 0, 0, 4, 0, 0, 0, 4, 0, 12, 0, + 0, 0, 0, 13, 0, 4, 13, 0, 4, 13, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 14, 0, + 4, 0, 13, 0, 4, 0, 4, 0, 0, 0, 4, 0, 4, 0, 4, + 0, 4, 0, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 15, 15, 0, 4, 0, 0, 0, 0, 4, 0, 4, 0, + 4, 0, 4, 0, 4, 16, 17, 18, 19, 20, 0, 21, 21, 0, 22, + 0, 23, 24, 0, 0, 0, 21, 25, 0, 26, 27, 28, 29, 0, 30, + 31, 29, 32, 33, 0, 0, 31, 0, 34, 35, 0, 0, 36, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 0, 38, 0, 39, 38, 0, 0, 0, + 40, 38, 41, 42, 42, 43, 0, 0, 0, 0, 0, 44, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 45, 46, 0, 0, 0, 0, 0, 0, + 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, + 0, 0, 0, 4, 0, 0, 0, 11, 11, 11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 49, 49, 1, 1, + 50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51, 52, 52, 0, 53, + 54, 0, 0, 0, 55, 56, 57, 0, 4, 0, 4, 0, 4, 0, 4, + 58, 59, 60, 61, 0, 62, 0, 0, 4, 0, 0, 4, 0, 0, 0, + 0, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 4, 0, 4, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 4, 63, 0, 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, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 57, 57, 57, 57, 57, 57, 0, 0, 65, 66, 67, 68, 68, 69, 70, + 71, 72, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 4, 0, 4, + 0, 4, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 77, 77, 77, + 77, 77, 77, 77, 77, 0, 0, 0, 0, 0, 0, 0, 0, 77, 77, + 77, 77, 77, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 77, 0, 77, 0, 77, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, + 78, 78, 79, 79, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 0, + 0, 77, 77, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 77, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 77, 77, 0, 0, 0, 60, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 89, 90, 0, 4, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 0, 91, 0, 0, 0, 0, 0, 91, 0, + 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, + 0, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 4, 0, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 4, 0, 4, 92, 0, 0, 4, 0, 4, + 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, + 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 0, 0, + 0, 4, 0, 4, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 0, 0, 0, + 0, 0, 0, 0, 0, 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, 95, 95, 95, 95, 95, 95, 95, 95, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 0, 96, 96, 96, 96, 96, 96, 96, 0, 96, 96, + 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint32_t tit4[] = { + 0, -32, 743, 121, -1, -232, -300, 195, 97, 163, 42561, 130, 56, 1, -79, + 10815, 10783, 10780, 10782, -210, -206, -205, -202, -203, 42319, 42315, -207, 42343, 42280, 42308, + -209, -211, 10743, 42305, 10749, -213, -214, 10727, -218, 42307, 42282, -69, -217, -71, -219, + 42261, 42258, 84, -38, -37, -31, -64, -63, -62, -57, -47, -54, -8, -86, -80, + 7, -116, -96, -15, -48, -6254, -6253, -6244, -6242, -6243, -6236, -6181, 35266, 35332, 3814, + 35384, -59, 8, 74, 86, 100, 128, 112, 126, 9, -7205, -28, -16, -26, -10795, + -10792, -7264, 48, -928, -38864, -40, -39, -27, -34, +}; + +static const uint8_t fod1[] = { + 0, 1, 2, 2, 3, 2, 2, 4, 5, 6, 2, 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, 2, 2, 2, 2, 2, 8, 9, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 10, 11, 2, 12, 2, 13, 2, 2, 14, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, +}; + +static const uint8_t fod2[] = { + 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, + 0, 6, 6, 6, 7, 8, 6, 6, 9, 10, 11, 12, 13, 14, 15, + 6, 16, 6, 6, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 1, 23, 0, + 24, 25, 6, 26, 27, 4, 4, 0, 0, 0, 6, 6, 28, 6, 6, + 6, 29, 6, 6, 6, 6, 6, 6, 30, 31, 32, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 33, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 37, 38, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 39, 6, 6, + 6, 6, 6, 6, 40, 35, 40, 40, 35, 41, 40, 0, 40, 40, 40, + 42, 43, 44, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 47, 48, 0, 0, 49, 0, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, + 31, 0, 0, 0, 53, 54, 6, 6, 6, 6, 6, 6, 55, 56, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 57, 0, 6, 58, 0, + 0, 0, 0, 0, 0, 0, 0, 59, 59, 6, 6, 6, 60, 61, 62, + 63, 64, 65, 66, 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, 68, 68, 68, 68, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 69, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 69, + 69, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 72, 73, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 74, 74, 74, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 76, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 77, 78, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 79, 79, 80, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 uint8_t fod3[] = { + 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, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 0, 0, 3, 0, 3, 0, 3, 0, + 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, + 3, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, + 3, 0, 4, 3, 0, 3, 0, 3, 0, 5, 0, 6, 3, 0, 3, + 0, 7, 3, 0, 8, 8, 3, 0, 0, 9, 10, 11, 3, 0, 8, + 12, 0, 13, 14, 3, 0, 0, 0, 13, 15, 0, 16, 3, 0, 3, + 0, 3, 0, 17, 3, 0, 17, 0, 0, 3, 0, 17, 3, 0, 18, + 18, 3, 0, 3, 0, 19, 3, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 20, 3, 0, 20, 3, 0, 20, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 3, + 0, 0, 20, 3, 0, 3, 0, 21, 22, 3, 0, 3, 0, 3, 0, + 3, 0, 23, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 24, 3, + 0, 25, 26, 0, 0, 3, 0, 27, 28, 29, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 31, 0, + 32, 32, 32, 0, 33, 0, 34, 34, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 37, 0, 0, 0, + 38, 39, 0, 3, 0, 3, 0, 3, 0, 3, 0, 40, 41, 0, 0, + 42, 43, 0, 3, 0, 44, 3, 0, 0, 23, 23, 23, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 46, + 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, + 0, 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, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 0, 0, + 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, + 49, 49, 49, 49, 0, 0, 50, 51, 52, 53, 53, 54, 55, 56, 57, + 3, 0, 0, 0, 0, 0, 0, 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, 0, 0, 58, 58, 58, 3, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 59, 0, 0, 60, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 49, 0, 49, 0, 49, 0, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 49, 49, 61, 61, 62, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 64, 64, 64, 64, 62, 0, 0, 0, 0, + 0, 0, 65, 0, 0, 0, 0, 49, 49, 66, 66, 0, 0, 0, 0, + 0, 0, 0, 67, 0, 0, 0, 0, 49, 49, 68, 68, 44, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 69, 70, 70, 62, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 0, 0, 0, 72, 73, 0, + 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 3, 0, 77, 78, 79, 0, 0, + 3, 0, 3, 0, 3, 0, 80, 81, 82, 83, 0, 3, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 84, 3, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 3, 0, + 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 85, 3, + 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 3, 0, 86, + 0, 0, 3, 0, 3, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 87, 88, + 89, 90, 87, 0, 91, 92, 93, 94, 3, 0, 3, 0, 3, 0, 3, + 0, 3, 0, 3, 0, 3, 0, 3, 0, 41, 95, 96, 3, 0, 3, + 0, 97, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, + 0, 3, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 0, 101, 101, 101, 101, 101, 101, + 101, 0, 101, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 0, 0, 0, + 0, 0, 0, 0, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +static const uint32_t fod4[] = { + 0, 32, 775, 1, -121, -268, 210, 206, 205, 79, 202, 203, 207, 211, 209, + 213, 214, 218, 217, 219, 2, -97, -56, -130, 10795, -163, 10792, -195, 69, 71, + 116, 38, 37, 64, 63, 8, -30, -25, -15, -22, -54, -48, -60, -64, -7, + 80, 15, 48, 7264, -8, -6222, -6221, -6212, -6210, -6211, -6204, -6180, 35267, -3008, -58, + -7615, -74, -9, -7173, -86, -7235, -100, -7219, -112, -128, -126, -7517, -8383, -8262, 28, + 16, 26, -10743, -3814, -10727, -10780, -10749, -10783, -10782, -10815, -35332, -42280, -42308, -42319, -42315, + -42305, -42258, -42282, -42261, 928, -42307, -35384, -42343, -42561, -38864, 40, 39, 27, 34, +}; + +static const uint8_t lfx1[] = { + 0, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, + 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, 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, 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, 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, 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, +}; + +static const uint8_t lfx2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 uint8_t lfx3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +static const uint32_t lfx4[] = { + -1, 3, +}; + +static const uint8_t ufx1[] = { + 0, 1, 1, 2, 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, 3, 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, 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, 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, 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, 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, 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, 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, + 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, 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, 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, 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, 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, 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, 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, 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, 1, 1, +}; + +static const uint8_t ufx2[] = { + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, + 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 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, 8, 0, 9, 10, 11, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const uint8_t ufx3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 7, 8, 9, 10, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 13, 0, 14, 0, 15, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 32, 33, + 34, 35, 36, 37, 38, 39, 0, 0, 40, 41, 42, 0, 43, 44, 0, + 0, 0, 0, 41, 0, 0, 0, 0, 0, 45, 46, 47, 0, 48, 49, + 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 50, 4, 0, 0, 51, + 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 5, 54, 0, + 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 58, 59, + 0, 60, 61, 0, 0, 0, 0, 58, 0, 0, 0, 62, 63, 64, 65, + 66, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 69, 70, 71, 72, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint32_t ufx4[] = { + -1, 0, 4, 6, 8, 10, 12, 15, 17, 19, 21, 23, 25, 27, 29, + 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, + 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 84, 86, 89, 91, + 94, 97, 99, 102, 104, 107, 109, 111, 113, 115, 117, 119, 121, 124, 126, + 129, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, +}; + +static const uint8_t tfx1[] = { + 0, 1, 1, 2, 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, 3, 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, 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, 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, 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, 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, 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, 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, + 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, 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, 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, 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, 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, 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, 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, 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, 1, 1, +}; + +static const uint8_t tfx2[] = { + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, + 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 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, 8, 0, 0, 9, 10, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const uint8_t tfx3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 7, 8, 9, 10, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 13, 0, 14, 0, 15, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 0, 17, 0, 18, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 0, 21, 0, 22, 23, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 4, 0, 0, 25, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 5, 28, 0, 29, 30, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 32, 0, 33, + 34, 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 37, 38, 39, 40, + 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, + 43, 44, 45, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint32_t tfx4[] = { + -1, 1, 4, 6, 8, 10, 13, 15, 17, 19, 21, 23, 25, 27, 29, + 31, 82, 87, 89, 92, 95, 100, 102, 105, 107, 109, 111, 113, 115, 117, + 119, 122, 127, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156, 159, 162, + 165, +}; + +static const uint8_t ffx1[] = { + 0, 1, 1, 2, 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, 3, 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, 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, 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, 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, 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, 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, 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, + 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, 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, 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, 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, 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, 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, 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, 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, 1, 1, +}; + +static const uint8_t ffx2[] = { + 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 3, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, + 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, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 9, 0, 10, 11, 12, 13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const uint8_t ffx3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 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, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 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, 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, 8, 9, 10, 11, 12, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, 14, 0, 15, 0, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 18, 19, 20, 21, 22, 23, 24, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 33, 34, 35, 36, 37, 38, 39, 40, 0, 0, 41, 42, 43, 0, 44, + 45, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 46, 47, 48, 0, + 49, 50, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 51, 5, 0, + 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 6, + 55, 0, 56, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, + 59, 60, 0, 61, 62, 0, 0, 0, 0, 59, 0, 0, 0, 63, 64, + 65, 66, 67, 68, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 69, 70, 71, 72, 73, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint32_t ffx4[] = { + -1, 2, 3, 5, 7, 9, 11, 14, 16, 18, 20, 22, 24, 26, 28, + 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 83, 85, 88, 90, + 93, 96, 98, 101, 103, 106, 108, 110, 112, 114, 116, 118, 120, 123, 125, + 128, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, +}; + +static const int32_t case_data[][3] = { + {83, 83, 0}, {83, 115, 0}, {115, 115, 0}, {105, 775, 0}, + {700, 78, 0}, {700, 110, 0}, {74, 780, 0}, {106, 780, 0}, + {921, 776, 769}, {953, 776, 769}, {933, 776, 769}, {965, 776, 769}, + {1333, 1362, 0}, {1333, 1410, 0}, {1381, 1410, 0}, {72, 817, 0}, + {104, 817, 0}, {84, 776, 0}, {116, 776, 0}, {87, 778, 0}, + {119, 778, 0}, {89, 778, 0}, {121, 778, 0}, {65, 702, 0}, + {97, 702, 0}, {933, 787, 0}, {965, 787, 0}, {933, 787, 768}, + {965, 787, 768}, {933, 787, 769}, {965, 787, 769}, {933, 787, 834}, + {965, 787, 834}, {7944, 921, 0}, {7936, 953, 0}, {7945, 921, 0}, + {7937, 953, 0}, {7946, 921, 0}, {7938, 953, 0}, {7947, 921, 0}, + {7939, 953, 0}, {7948, 921, 0}, {7940, 953, 0}, {7949, 921, 0}, + {7941, 953, 0}, {7950, 921, 0}, {7942, 953, 0}, {7951, 921, 0}, + {7943, 953, 0}, {7976, 921, 0}, {7968, 953, 0}, {7977, 921, 0}, + {7969, 953, 0}, {7978, 921, 0}, {7970, 953, 0}, {7979, 921, 0}, + {7971, 953, 0}, {7980, 921, 0}, {7972, 953, 0}, {7981, 921, 0}, + {7973, 953, 0}, {7982, 921, 0}, {7974, 953, 0}, {7983, 921, 0}, + {7975, 953, 0}, {8040, 921, 0}, {8032, 953, 0}, {8041, 921, 0}, + {8033, 953, 0}, {8042, 921, 0}, {8034, 953, 0}, {8043, 921, 0}, + {8035, 953, 0}, {8044, 921, 0}, {8036, 953, 0}, {8045, 921, 0}, + {8037, 953, 0}, {8046, 921, 0}, {8038, 953, 0}, {8047, 921, 0}, + {8039, 953, 0}, {8122, 921, 0}, {8122, 837, 0}, {8048, 953, 0}, + {913, 921, 0}, {945, 953, 0}, {902, 921, 0}, {902, 837, 0}, + {940, 953, 0}, {913, 834, 0}, {945, 834, 0}, {913, 834, 921}, + {913, 834, 837}, {945, 834, 953}, {8138, 921, 0}, {8138, 837, 0}, + {8052, 953, 0}, {919, 921, 0}, {951, 953, 0}, {905, 921, 0}, + {905, 837, 0}, {942, 953, 0}, {919, 834, 0}, {951, 834, 0}, + {919, 834, 921}, {919, 834, 837}, {951, 834, 953}, {921, 776, 768}, + {953, 776, 768}, {921, 834, 0}, {953, 834, 0}, {921, 776, 834}, + {953, 776, 834}, {933, 776, 768}, {965, 776, 768}, {929, 787, 0}, + {961, 787, 0}, {933, 834, 0}, {965, 834, 0}, {933, 776, 834}, + {965, 776, 834}, {8186, 921, 0}, {8186, 837, 0}, {8060, 953, 0}, + {937, 921, 0}, {969, 953, 0}, {911, 921, 0}, {911, 837, 0}, + {974, 953, 0}, {937, 834, 0}, {969, 834, 0}, {937, 834, 921}, + {937, 834, 837}, {969, 834, 953}, {70, 70, 0}, {70, 102, 0}, + {102, 102, 0}, {70, 73, 0}, {70, 105, 0}, {102, 105, 0}, + {70, 76, 0}, {70, 108, 0}, {102, 108, 0}, {70, 70, 73}, + {70, 102, 105}, {102, 102, 105}, {70, 70, 76}, {70, 102, 108}, + {102, 102, 108}, {83, 84, 0}, {83, 116, 0}, {115, 116, 0}, + {1348, 1350, 0}, {1348, 1398, 0}, {1396, 1398, 0}, {1348, 1333, 0}, + {1348, 1381, 0}, {1396, 1381, 0}, {1348, 1339, 0}, {1348, 1387, 0}, + {1396, 1387, 0}, {1358, 1350, 0}, {1358, 1398, 0}, {1406, 1398, 0}, + {1348, 1341, 0}, {1348, 1389, 0}, {1396, 1389, 0}, +}; + +int CgeRuneCategory(uint32_t r){ + long t; + if(r>1114111ul)return 29; + t = (long)cat1[(r>>10)]; + t = (long)cat2[(t<<4)+((r>>6)&15)]; + t = (long)cat3[(t<<3)+((r>>3)&7)]; + t = (long)cat4[(t<<3)+(r&7)]; + return t; +} + +uint32_t CgeRuneLower(uint32_t r){ + long t; + if(r>1114111ul)return r; + t = (long)low1[(r>>10)]; + t = (long)low2[(t<<6)+((r>>4)&63)]; + t = (long)low3[(t<<4)+(r&15)]; + t = (long)low4[t]; + return t?t+r:r; +} + +uint32_t CgeRuneUpper(uint32_t r){ + long t; + if(r>1114111ul)return r; + t = (long)upp1[(r>>10)]; + t = (long)upp2[(t<<6)+((r>>4)&63)]; + t = (long)upp3[(t<<4)+(r&15)]; + t = (long)upp4[t]; + return t?t+r:r; +} + +uint32_t CgeRuneTitle(uint32_t r){ + long t; + if(r>1114111ul)return r; + t = (long)tit1[(r>>10)]; + t = (long)tit2[(t<<6)+((r>>4)&63)]; + t = (long)tit3[(t<<4)+(r&15)]; + t = (long)tit4[t]; + return t?t+r:r; +} + +uint32_t CgeRuneFold(uint32_t r){ + long t; + if(r>1114111ul)return r; + t = (long)fod1[(r>>10)]; + t = (long)fod2[(t<<6)+((r>>4)&63)]; + t = (long)fod3[(t<<4)+(r&15)]; + t = (long)fod4[t]; + return t?t+r:r; +} + +size_t CgeRuneLowerFull(uint32_t r, uint32_t* out){ + long t; + if(r>1114111ul){ + *out=r; + return 1; + } + t = (long)lfx1[(r>>11)]; + t = (long)lfx2[(t<<6)+((r>>5)&63)]; + t = (long)lfx3[(t<<5)+(r&31)]; + t = (long)lfx4[t]; + if(t>=0){ + const int32_t* p=case_data[t]; + size_t i=0; + while(p[i] && i<3){out[i]=p[i];i++;} + return i; + } + *out=CgeRuneLower(r); + return 1; +} + +size_t CgeRuneUpperFull(uint32_t r, uint32_t* out){ + long t; + if(r>1114111ul){ + *out=r; + return 1; + } + t = (long)ufx1[(r>>11)]; + t = (long)ufx2[(t<<6)+((r>>5)&63)]; + t = (long)ufx3[(t<<5)+(r&31)]; + t = (long)ufx4[t]; + if(t>=0){ + const int32_t* p=case_data[t]; + size_t i=0; + while(p[i] && i<3){out[i]=p[i];i++;} + return i; + } + *out=CgeRuneUpper(r); + return 1; +} + +size_t CgeRuneTitleFull(uint32_t r, uint32_t* out){ + long t; + if(r>1114111ul){ + *out=r; + return 1; + } + t = (long)tfx1[(r>>11)]; + t = (long)tfx2[(t<<6)+((r>>5)&63)]; + t = (long)tfx3[(t<<5)+(r&31)]; + t = (long)tfx4[t]; + if(t>=0){ + const int32_t* p=case_data[t]; + size_t i=0; + while(p[i] && i<3){out[i]=p[i];i++;} + return i; + } + *out=CgeRuneTitle(r); + return 1; +} + +size_t CgeRuneFoldFull(uint32_t r, uint32_t* out){ + long t; + if(r>1114111ul){ + *out=r; + return 1; + } + t = (long)ffx1[(r>>11)]; + t = (long)ffx2[(t<<6)+((r>>5)&63)]; + t = (long)ffx3[(t<<5)+(r&31)]; + t = (long)ffx4[t]; + if(t>=0){ + const int32_t* p=case_data[t]; + size_t i=0; + while(p[i] && i<3){out[i]=p[i];i++;} + return i; + } + *out=CgeRuneFold(r); + return 1; +} + diff --git a/Utf16.c b/Utf16.c new file mode 100644 index 0000000..fbefd2b --- /dev/null +++ b/Utf16.c @@ -0,0 +1,64 @@ +#include "CgeStr.h" + +#define INVALID_RUNE 0xFFFD + +int CgeUtf16Encode(uint32_t rune, uint16_t* data) { + if (rune <= 0xFFFF) { + if (rune >= 0xD800 && rune <= 0xDFFF) + return -1; + data[0] = (uint16_t)rune; + return 1; + } + if (rune <= 0x10FFFF) { + uint32_t x = rune - 0x10000; + data[0] = (uint16_t)(0xD800 + (x >> 10)); + data[1] = (uint16_t)(0xDC00 + (x & 0x3FF)); + return 2; + } + return -1; +} + +int CgeUtf16EncodeLax(uint32_t rune, uint16_t* data) { + int result; + + result = CgeUtf16Encode(rune, data); + if (result == -1) + result = CgeUtf16Encode(INVALID_RUNE, data); + + return result; +} + +int CgeUtf16Decode(const uint16_t* data, size_t size, uint32_t* rune) { + uint16_t trail, lead = data[0]; + + if (size == 0) + return -1; + + if (lead < 0xD800 || lead > 0xDFFF) { + *rune = lead; + return 1; + } else if (lead >= 0xD800 && lead <= 0xDBFF) { + if (size < 2) + return -1; + + trail = data[1]; + if (trail >= 0xDC00 && trail <= 0xDFFF) { + *rune = 0x10000 + ((lead & 0x3FF) << 10) + (trail & 0x3FF); + return 2; + } + } + + return -1; +} + +int CgeUtf16DecodeLax(const uint16_t* data, size_t size, uint32_t* rune) { + int result; + + result = CgeUtf16Decode(data, size, rune); + if (result == -1) { + *rune = INVALID_RUNE; + result = 1; + } + + return result; +} diff --git a/Utf8.c b/Utf8.c new file mode 100644 index 0000000..b571c6e --- /dev/null +++ b/Utf8.c @@ -0,0 +1,101 @@ +#include "CgeStr.h" + +#define INVALID_RUNE 0xFFFD + +int CgeUtf8Encode(uint32_t rune, char* data) { + if (rune < 0x80) { + data[0] = (char)rune; + return 1; + } + if (rune < 0x800) { + data[0] = (char)(0xC0 | (rune >> 6)); + data[1] = (char)(0x80 | (rune & 0x3F)); + return 2; + } + if (rune < 0x10000) { + if (rune >= 0xD800 && rune <= 0xDFFF) + return -1; + data[0] = (char)(0xE0 | (rune >> 12)); + data[1] = (char)(0x80 | ((rune >> 6) & 0x3F)); + data[2] = (char)(0x80 | (rune & 0x3F)); + return 3; + } + if (rune <= 0x10FFFF) { + data[0] = (char)(0xF0 | (rune >> 18)); + data[1] = (char)(0x80 | ((rune >> 12) & 0x3F)); + data[2] = (char)(0x80 | ((rune >> 6) & 0x3F)); + data[3] = (char)(0x80 | (rune & 0x3F)); + return 4; + } + return -1; +} + +int CgeUtf8EncodeLax(uint32_t rune, char* data) { + int result; + + result = CgeUtf8Encode(rune, data); + if (result == -1) + result = CgeUtf8Encode(INVALID_RUNE, data); + + return result; +} + +int CgeUtf8Decode(const char* data, size_t size, uint32_t* rune) { + unsigned char byte = (unsigned char)data[0]; + int i, n; + + if (size == 0) + return -1; + + if (byte < 0x80) { + *rune = byte; + return 1; + } + + if ((byte & 0xE0) == 0xC0) { + n = 2; + *rune = byte & 0x1F; + } else if ((byte & 0xF0) == 0xE0) { + n = 3; + *rune = byte & 0x0F; + } else if ((byte & 0xF8) == 0xF0) { + n = 4; + *rune = byte & 0x07; + } else { + return -1; + } + + if (size < (size_t)n) + return -1; + + for (i = 1; i < n; i++) { + byte = (unsigned char)data[i]; + if ((byte & 0xC0) != 0x80) + return -1; + *rune = (*rune << 6) | (byte & 0x3F); + } + + if ((n == 2 && *rune < 0x80) || + (n == 3 && *rune < 0x800) || + (n == 4 && *rune < 0x10000)) { + return -1; + } + + if (*rune > 0x10FFFF || (*rune >= 0xD800 && *rune <= 0xDFFF)) { + return -1; + } + + return n; +} + +int CgeUtf8DecodeLax(const char* data, size_t size, uint32_t* rune) { + int result; + + result = CgeUtf8Decode(data, size, rune); + if (result == -1) { + *rune = INVALID_RUNE; + result = 1; + } + + return result; +} diff --git a/generator/Blocks.h b/generator/Blocks.h new file mode 100644 index 0000000..0ad7901 --- /dev/null +++ b/generator/Blocks.h @@ -0,0 +1,168 @@ +#ifndef BLOCKS_H +#define BLOCKS_H + +#include +#include +#include "ValueList.h" + +struct BlockLevel { + long* data; + size_t size; + size_t capacity; + struct ValueList* list; +}; + +struct Blocks { + struct BlockLevel* levels; + size_t depth; +}; + +static int ilog2(unsigned long value) { + int result = -1; + while (value) value >>= 1, result++; + return result; +} + +static long blockInsert(struct Blocks* blocks, long value, size_t depth) { + struct BlockLevel* level = blocks->levels + depth; + + if (blocks->depth - 1 != depth) { + if ((value = blockInsert(blocks, value, depth + 1)) == -1) + return -1; + } + + level->data[level->size++] = value; + if (level->size >= level->capacity) { + level->size = 0; + + if (depth == 0 || (value = valueListFind(level->list, level->data, level->capacity)) == -1) { + value = valueListIntern(&level->list, level->data, level->capacity); + } + return value; + } + + return -1; +} + +static long blockFindR(struct Blocks* blocks, long value, long offset, size_t depth) { + struct BlockLevel* level = &blocks->levels[depth]; + struct ValueList* current; + size_t i, bits = 0; + + for (i = depth + 1; i < blocks->depth; i++) { + bits += ilog2(blocks->levels[i].capacity); + } + + current = level->list; + while (offset--) current = current->next; + + offset = (value >> bits) & ((unsigned long)level->capacity - 1); + offset = current->data[offset]; + + if (depth != blocks->depth - 1) + return blockFindR(blocks, value, offset, depth + 1); + + return offset; +} + +static long blockFind(struct Blocks* blocks, long value) { + size_t i, bits = 0; + long offset; + + for (i = 0; i < blocks->depth; i++) { + bits += ilog2(blocks->levels[i].capacity); + } + + offset = value >> bits; + return blockFindR(blocks, value, offset, 0); +} + +static void blockInit(struct Blocks* blocks, size_t depth, ...) { + va_list args; + + blocks->depth = 0; + if (!(blocks->levels = malloc(sizeof(struct BlockLevel) * depth))) + abort(); + + va_start(args, depth); + + while (blocks->depth < depth) { + struct BlockLevel* level = &blocks->levels[blocks->depth]; + + level->list = NULL; + level->size = 0; + level->capacity = va_arg(args, int); + if (!(level->data = malloc(level->capacity * sizeof(long)))) + abort(); + blocks->depth++; + } + + va_end(args); +} + +static void blockDump(struct Blocks* blocks, size_t depth, FILE* out, + const char* name, const char* type) { + struct BlockLevel* level = &blocks->levels[depth]; + struct ValueList* current; + size_t i, j, printed = 0; + + fprintf(out, "static const %s %s[] = {\n ", type, name); + current = level->list; + for (current = level->list; current; current = current->next) { + for (i = 0; i < level->capacity; i++) { + if (printed++ >= 15) { + fprintf(out, "\n "); + printed = 1; + } + fprintf(out, "%ld, ", current->data[i]); + } + } + fprintf(out, "\n};\n\n"); +} + +static void blockAccess(struct Blocks* blocks, size_t depth, FILE* out, + const char* var, const char* arg, const char* name) { + struct BlockLevel* level = &blocks->levels[depth]; + long i, bits = 0, offset, mask; + + for (i = depth + 1; i < blocks->depth; i++) { + bits += ilog2(blocks->levels[i].capacity); + } + + offset = ilog2(blocks->levels[depth].capacity); + mask = level->capacity - 1; + + fprintf(out, " %s = (long)%s", var, name); + if (depth) { + if (offset) { + fprintf(out, "[(%s<<%ld)", var, offset); + } else { + fprintf(out, "[%s", var); + } + } + else + fprintf(out, "["); + + if (mask || !depth) { + if (depth) + fprintf(out, "+"); + + if (mask) + fprintf(out, "("); + + if (bits) + fprintf(out, "(%s>>%ld)", arg, (long)bits); + else + fprintf(out, "%s", arg); + + if (depth) + fprintf(out, "&%ld", mask); + + if (mask) + fprintf(out, ")"); + } + + fprintf(out, "];\n"); +} + +#endif /* BLOCKS_H */ diff --git a/generator/README.md b/generator/README.md new file mode 100644 index 0000000..9231bb6 --- /dev/null +++ b/generator/README.md @@ -0,0 +1,28 @@ +# Generator + +This utility should be used to regenerate tables based on Unicode Character +Database (UCD). + +Current version of this utility builds tables and functions for the following +properties: + +- Case mappings for lower, upper, title cases (1:1 and 1:M) +- Case folding (1:1 and 1:M) +- General category + +## Usage + +Compile `Tables.c` + +``` +gcc Tables.c -o Tables +``` + +Download and put `UnicodeData.txt`, `CaseFolding.txt`, `SpecialCasing.txt` near +the compiled `Tables` program, run it and pipe output into `UCD.c`. + +``` +Tables > ../UCD.c +``` + +You can download required files from [here](https://www.unicode.org/Public/UCD/latest/ucd) diff --git a/generator/Tables.c b/generator/Tables.c new file mode 100644 index 0000000..8020602 --- /dev/null +++ b/generator/Tables.c @@ -0,0 +1,465 @@ +#include +#include +#include +#include +#include +#include + +#include "Blocks.h" +#include "TextProc.h" + +#define MAX_LINE 512 + +struct CaseInfo { + long rune; + struct { + long lower; + long upper; + long title; + long fold; + } simple; + struct { + long lower[4]; + long upper[4]; + long title[4]; + long fold[4]; + } full; + struct CaseInfo* prev; + struct CaseInfo* next; +}; + +typedef int (*EntryCb)(long rune, int fill, char** fields, size_t size); + +static void entryProcess(FILE* in, EntryCb cb, const char* globStart, + const char* globEnd, size_t globField, + size_t codeField, size_t minFields) { + long code, startCode, prevCode = -1; + char line[MAX_LINE]; + char* fields[MAX_FIELDS]; + int emitted = 0; + size_t columns; + + while ((columns = processLine(in, line, sizeof(line), fields))) { + if (columns < minFields) + continue; + + code = strtol(fields[codeField], NULL, 16); + while (prevCode + 1 < code) + emitted = cb(++prevCode, 1, fields, columns); + + if (globStart && globEnd && columns >= globField && + glob(globStart, fields[globField])) { + startCode = code; + while ((columns = processLine(in, line, sizeof(line), fields))) { + if (columns < minFields) + continue; + break; + } + if (!glob(globEnd, fields[globField])) { + fprintf(stderr, "Abnormal input - can find last element\n"); + abort(); + } + code = strtol(fields[codeField], NULL, 16); + while (startCode <= code) { + emitted = cb(startCode, 0, fields, columns); + startCode++; + } + } else { + emitted = cb(code, 0, fields, columns); + } + prevCode = code; + } + + while (prevCode + 1 < 0x110000) + emitted = cb(++prevCode, 1, fields, columns); + while (emitted == -1) + emitted = cb(code++, 1, fields, columns); +} + +static struct CaseInfo* caseInfoSort(struct CaseInfo* head) { + struct CaseInfo* current; + struct CaseInfo* next; + int swapped; + + if (!head || !head->next) + return head; + + do { + swapped = 0; + current = head; + while (current->next) { + next = current->next; + if (current->rune > next->rune) { + swapped = 1; + + if (current->prev) + current->prev->next = next; + if (next->next) + next->next->prev = current; + + current->next = next->next; + next->prev = current->prev; + current->prev = next; + next->next = current; + + if (current == head) + head = next; + } else + current = current->next; + } + } while (swapped); + + return head; +} + +static struct CaseInfo* caseInfoGet(struct CaseInfo** head, long rune) { + struct CaseInfo* current = *head; + struct CaseInfo* node; + + while (current != NULL) { + if (current->rune == rune) + return current; + current = current->next; + } + + if (!(node = malloc(sizeof(*node)))) + return NULL; + + memset(node, 0, sizeof(*node)); + node->rune = rune; + node->next = *head; + node->prev = NULL; + if (*head) + (*head)->prev = node; + *head = node; + return node; +} + +static size_t categoryClassify(const char* name) { + static const char *categories[] = { + "Lu", "Ll", "Lt", "Lm", "Lo", "Mn", "Mc", "Me", "Nd", "Nl", "No", "Pc", + "Pd", "Ps", "Pe", "Pi", "Pf", "Po", "Sm", "Sc", "Sk", "So", "Zs", "Zl", + "Zp", "Cc", "Cf", "Cs", "Co", "Cn", NULL, + }; + size_t index = 0; + + while (categories[index]) { + if (!strncmp(categories[index], name, 2)) + return index; + ++index; + } + + return categoryClassify("Cn"); +} + +FILE* in; +FILE* out; + +struct Blocks categoryBlocks; +struct CaseInfo* caseInfo = NULL; + +static int entryUnicodeData(long rune, int fill, char** fields, size_t size) { + long lowercase, uppercase, titlecase; + struct CaseInfo* node; + + if (fill) { + return blockInsert(&categoryBlocks, categoryClassify("Cn"), 0); + } else { + lowercase = strtol(fields[13], NULL, 16); + uppercase = strtol(fields[12], NULL, 16); + titlecase = strtol(fields[14], NULL, 16); + + if (lowercase || uppercase || titlecase) { + node = caseInfoGet(&caseInfo, rune); + node->simple.lower = lowercase; + node->simple.upper = uppercase; + node->simple.title = titlecase; + } + + return blockInsert(&categoryBlocks, categoryClassify(fields[2]), 0); + } +} + +static void arrayParseFromStr(const char* field, long* array) { + char* endptr = (char*)field; + size_t written = 0; + + while (1) { + array[written] = strtol(endptr, &endptr, 16); + if (!array[written]) + break; + written++; + } +} + +static int entryCaseFolding(long rune, int fill, char** fields, size_t size) { + struct CaseInfo* node; + + if (fill || !strcmp("T", fields[1])) + return 1; + + node = caseInfoGet(&caseInfo, rune); + if (strcmp("F", fields[1])) { + node->simple.fold = strtol(fields[2], NULL, 16); + } else { + arrayParseFromStr(fields[2], node->full.fold); + } + return 1; +} + +static int entrySpecialCasing(long rune, int fill, char** fields, size_t size) { + struct CaseInfo* node; + + if (fill || strcmp("", fields[4])) + return 1; + + node = caseInfoGet(&caseInfo, rune); + arrayParseFromStr(fields[1], node->full.lower); + arrayParseFromStr(fields[3], node->full.upper); + arrayParseFromStr(fields[2], node->full.title); + + return 1; +} + +static void mappingRemoveSingle(long* array) { + if (array[0] && !array[1]) + array[0] = 0; +} + +static void caseInfoReduce(void) { + struct CaseInfo* current = caseInfo; + while (current) { + if (!current->simple.title && current->simple.upper) + current->simple.title = current->simple.upper; + if (!current->full.title[0] && current->full.upper[0]) + memcpy(current->full.title, current->full.upper, 4 * sizeof(long)); + + mappingRemoveSingle(current->full.lower); + mappingRemoveSingle(current->full.upper); + mappingRemoveSingle(current->full.title); + mappingRemoveSingle(current->full.fold); + current = current->next; + } +} + +struct Blocks lowerBlocks, upperBlocks, titleBlocks, foldBlocks; +struct Blocks lowerFullBlocks, upperFullBlocks, titleFullBlocks, foldFullBlocks; + +long longIndexData[1024][4]; +size_t longIndexSize = 0; + +static long longIndexGet(long* array) { + size_t i; + + for (i = 0; i < longIndexSize; i++) { + if (!memcmp(array, longIndexData[i], 4 * sizeof(long))) + return i; + } + + memcpy(longIndexData[longIndexSize], array, 4 * sizeof(long)); + return longIndexSize++; +} + +static void blocksBuild(void) { + struct CaseInfo* current = caseInfo; + int emitted; + long last = -1; + + blockInit(&lowerBlocks, 4, 1, 64, 16, 1); + blockInit(&upperBlocks, 4, 1, 64, 16, 1); + blockInit(&titleBlocks, 4, 1, 64, 16, 1); + blockInit(&foldBlocks, 4, 1, 64, 16, 1); + blockInit(&lowerFullBlocks, 4, 1, 64, 32, 1); + blockInit(&upperFullBlocks, 4, 1, 64, 32, 1); + blockInit(&titleFullBlocks, 4, 1, 64, 32, 1); + blockInit(&foldFullBlocks, 4, 1, 64, 32, 1); + + while (current) { + while (last + 1 < current->rune) { + blockInsert(&lowerBlocks, 0, 0); + blockInsert(&upperBlocks, 0, 0); + blockInsert(&titleBlocks, 0, 0); + blockInsert(&foldBlocks, 0, 0); + blockInsert(&lowerFullBlocks, -1, 0); + blockInsert(&upperFullBlocks, -1, 0); + blockInsert(&titleFullBlocks, -1, 0); + blockInsert(&foldFullBlocks, -1, 0); + last++; + } + + if (current->simple.lower) + blockInsert(&lowerBlocks, current->simple.lower - current->rune, 0); + else + blockInsert(&lowerBlocks, 0, 0); + + if (current->simple.upper) + blockInsert(&upperBlocks, current->simple.upper - current->rune, 0); + else + blockInsert(&upperBlocks, 0, 0); + + if (current->simple.title) + blockInsert(&titleBlocks, current->simple.title - current->rune, 0); + else + blockInsert(&titleBlocks, 0, 0); + + if (current->simple.fold) + blockInsert(&foldBlocks, current->simple.fold - current->rune, 0); + else + blockInsert(&foldBlocks, 0, 0); + + if (current->full.lower[0]) + blockInsert(&lowerFullBlocks, longIndexGet(current->full.lower), 0); + else + blockInsert(&lowerFullBlocks, -1, 0); + + if (current->full.upper[0]) + blockInsert(&upperFullBlocks, longIndexGet(current->full.upper), 0); + else + blockInsert(&upperFullBlocks, -1, 0); + + if (current->full.title[0]) + blockInsert(&titleFullBlocks, longIndexGet(current->full.title), 0); + else + blockInsert(&titleFullBlocks, -1, 0); + + if (current->full.fold[0]) + emitted = blockInsert(&foldFullBlocks, longIndexGet(current->full.fold), 0); + else + emitted = blockInsert(&foldFullBlocks, -1, 0); + + last = current->rune; + current = current->next; + } + + while (last + 1 < 0x110000 || emitted == -1) { + blockInsert(&lowerBlocks, 0, 0); + blockInsert(&upperBlocks, 0, 0); + blockInsert(&titleBlocks, 0, 0); + blockInsert(&foldBlocks, 0, 0); + blockInsert(&lowerFullBlocks, -1, 0); + blockInsert(&upperFullBlocks, -1, 0); + blockInsert(&titleFullBlocks, -1, 0); + emitted = blockInsert(&foldFullBlocks, -1, 0); + last++; + } +} + +static void outputCode(void) { +#define DUMP(NAME, BLOCK, TYPE1, TYPE2, TYPE3, TYPE4) \ + blockDump(&BLOCK, 0, out, NAME "1", TYPE1); \ + blockDump(&BLOCK, 1, out, NAME "2", TYPE2); \ + blockDump(&BLOCK, 2, out, NAME "3", TYPE3); \ + blockDump(&BLOCK, 3, out, NAME "4", TYPE4) + + fprintf(out, "/* Auto-generated case mapping tables */\n\n"); + fprintf(out, "#include \n\n"); + + DUMP("cat", categoryBlocks, "uint8_t", "uint16_t", "uint16_t", "uint8_t"); + DUMP("low", lowerBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + DUMP("upp", upperBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + DUMP("tit", titleBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + DUMP("fod", foldBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + DUMP("lfx", lowerFullBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + DUMP("ufx", upperFullBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + DUMP("tfx", titleFullBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + DUMP("ffx", foldFullBlocks, "uint8_t", "uint8_t", "uint8_t", "uint32_t"); + + fprintf(out, "static const int32_t case_data[][3] = {"); + { + size_t i; + for (i = 0; i < longIndexSize; ++i) { + if (i % 4 == 0) + fprintf(out, "\n "); + fprintf(out, "{%ld, %ld, %ld}, ", + longIndexData[i][0], longIndexData[i][1], + longIndexData[i][2]); + } + } + fprintf(out, "\n};\n\n"); + +#define EMIT_SIMPLE(FUNC, BLOCKS, BASE) do { \ + fprintf(out, "uint32_t CgeRune" #FUNC "(uint32_t r){\n"); \ + fprintf(out, " long t;\n if(r>1114111ul)return r;\n"); \ + blockAccess(&BLOCKS, 0, out, "t", "r", BASE "1"); \ + blockAccess(&BLOCKS, 1, out, "t", "r", BASE "2"); \ + blockAccess(&BLOCKS, 2, out, "t", "r", BASE "3"); \ + blockAccess(&BLOCKS, 3, out, "t", "r", BASE "4"); \ + fprintf(out, " return t?t+r:r;\n}\n\n"); \ +} while(0) + +#define EMIT_FULL(FUNC, SIMPLE, FULL_BLOCKS, FULL_BASE, SIMPLE_FUNC) do { \ + fprintf(out, "size_t CgeRune" #FUNC "Full(uint32_t r, uint32_t* out){\n"); \ + fprintf(out, " long t;\n if(r>1114111ul){\n *out=r;\n return 1;\n }\n"); \ + blockAccess(&FULL_BLOCKS, 0, out, "t", "r", FULL_BASE "1"); \ + blockAccess(&FULL_BLOCKS, 1, out, "t", "r", FULL_BASE "2"); \ + blockAccess(&FULL_BLOCKS, 2, out, "t", "r", FULL_BASE "3"); \ + blockAccess(&FULL_BLOCKS, 3, out, "t", "r", FULL_BASE "4"); \ + fprintf(out, " if(t>=0){\n"); \ + fprintf(out, " const int32_t* p=case_data[t];\n"); \ + fprintf(out, " size_t i=0;\n"); \ + fprintf(out, " while(p[i] && i<3){out[i]=p[i];i++;}\n"); \ + fprintf(out, " return i;\n }\n"); \ + fprintf(out, " *out=CgeRune" #SIMPLE "(r);\n return 1;\n}\n\n"); \ +} while(0) + + fprintf(out, "int CgeRuneCategory(uint32_t r){\n"); + fprintf(out, " long t;\n if(r>1114111ul)return %d;\n", (int)categoryClassify("Cn")); + blockAccess(&categoryBlocks, 0, out, "t", "r", "cat1"); + blockAccess(&categoryBlocks, 1, out, "t", "r", "cat2"); + blockAccess(&categoryBlocks, 2, out, "t", "r", "cat3"); + blockAccess(&categoryBlocks, 3, out, "t", "r", "cat4"); + fprintf(out, " return t;\n}\n\n"); \ + + EMIT_SIMPLE(Lower, lowerBlocks, "low"); + EMIT_SIMPLE(Upper, upperBlocks, "upp"); + EMIT_SIMPLE(Title, titleBlocks, "tit"); + EMIT_SIMPLE(Fold, foldBlocks, "fod"); + + EMIT_FULL(Lower, Lower, lowerFullBlocks, "lfx", Lower); + EMIT_FULL(Upper, Upper, upperFullBlocks, "ufx", Upper); + EMIT_FULL(Title, Title, titleFullBlocks, "tfx", Title); + EMIT_FULL(Fold, Fold, foldFullBlocks, "ffx", Fold); +} + +#undef DUMP +#undef EMIT_SIMPLE +#undef EMIT_FULL + +int main() { + if (!(in = fopen("UnicodeData.txt", "r"))) { + fprintf(stderr, "UnicodeData.txt not found. Download it from:\n"); + fprintf(stderr, "https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt\n"); + return -1; + } + out = stdout; + + fprintf(stderr, "Processing UnicodeData.txt\n"); + blockInit(&categoryBlocks, 4, 1, 16, 8, 8); + entryProcess(in, entryUnicodeData, "<*, First>", "<*, Last>", 1, 0, 15); + fclose(in); + + if (!(in = fopen("CaseFolding.txt", "r"))) { + fprintf(stderr, "CaseFolding.txt not found. Download it from:\n"); + fprintf(stderr, "https://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt\n"); + return -1; + } + fprintf(stderr, "Processing CaseFolding.txt\n"); + entryProcess(in, entryCaseFolding, NULL, NULL, 0, 0, 3); + fclose(in); + + fprintf(stderr, "Processing SpecialCasing.txt\n"); + if (!(in = fopen("SpecialCasing.txt", "r"))) { + fprintf(stderr, "SpecialCasing.txt not found. Download it from:\n"); + fprintf(stderr, "https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt\n"); + return -1; + } + entryProcess(in, entrySpecialCasing, NULL, NULL, 0, 0, 4); + fclose(in); + + caseInfo = caseInfoSort(caseInfo); + caseInfoReduce(); + blocksBuild(); + outputCode(); + + return 0; +} diff --git a/generator/TextProc.h b/generator/TextProc.h new file mode 100644 index 0000000..2071aae --- /dev/null +++ b/generator/TextProc.h @@ -0,0 +1,76 @@ +#ifndef TEXTPROC_H +#define TEXTPROC_H + +#include +#include +#include +#include + +#define MAX_FIELDS 16 + +static int glob(const char* pattern, const char* text) { + const char* star = NULL; + const char* restart = text; + + while (*text) { + if (*pattern == *text || *pattern == '?') + pattern++, text++; + else if (*pattern == '*') + star = ++pattern, restart = text; + else if (star) + pattern = star, text = ++restart; + else + return 0; + } + while (*pattern == '*') + pattern++; + return (*pattern == '\0'); +} + +static char* trimLeft(char* line) { + for (; *line && isspace(*line); ++line); + return line; +} + +static void trimRight(char* line) { + char* last = line; + + for (; *line; ++line) + if (!isspace(*line)) + last = line + 1; + *last = '\0'; +} + +static void trimComment(char* line) { + char* separator = strchr(line, '#'); + if (separator) *separator = '\0'; +} + +static char* trim(char* line) { + trimRight(line); + return trimLeft(line); +} + +static size_t fieldParse(char* line, char** fields, char separator) { + size_t index = 0; + + do { + fields[index] = line; + if ((line = strchr(line, separator))) + *(line++) = '\0'; + fields[index] = trim(fields[index]); + index++; + } while (line && index < MAX_FIELDS); + + return index; +} + +static int processLine(FILE* in, char* line, size_t size, char** fields) { + if (!fgets(line, size, in)) + return 0; + + trimComment(line); + return fieldParse(line, fields, ';'); +} + +#endif /* TEXTPROC_H */ diff --git a/generator/ValueList.h b/generator/ValueList.h new file mode 100644 index 0000000..b8863ae --- /dev/null +++ b/generator/ValueList.h @@ -0,0 +1,41 @@ +#ifndef VALUELIST_H +#define VALUELIST_H + +#include +#include +#include + +struct ValueList { + long* data; + size_t size; + struct ValueList* next; +}; + +static long valueListFind(struct ValueList* list, long* data, size_t size) { + long index = 0; + + while (list) { + if (list->size == size && !memcmp(list->data, data, size * sizeof(long))) + return index; + index++, list = list->next; + } + return -1; +} + +static long valueListIntern(struct ValueList** list, long* data, size_t size) { + long index = 0; + + while (*list) ++index, list = &(*list)->next; + if (!(*list = malloc(sizeof(struct ValueList)))) + abort(); + if (!((*list)->data = malloc(size * sizeof(long)))) + abort(); + + memcpy((*list)->data, data, size * sizeof(long)); + (*list)->size = size; + (*list)->next = NULL; + + return index; +} + +#endif /* VALUELIST_H */ \ No newline at end of file