OSDN Git Service

Initial commit.
authorLoRd_MuldeR <mulder2@gmx.de>
Sun, 8 Dec 2019 19:32:46 +0000 (20:32 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Sun, 8 Dec 2019 19:32:46 +0000 (20:32 +0100)
59 files changed:
.gitignore [new file with mode: 0644]
COPYING.txt [new file with mode: 0644]
MHash384.sln [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
build.cmd [new file with mode: 0644]
build.ini.EXAMPLE [new file with mode: 0644]
etc/css/style.inc [new file with mode: 0644]
etc/gentable_FIN/gentable_FIN.filters [new file with mode: 0644]
etc/gentable_FIN/gentable_FIN.sln [new file with mode: 0644]
etc/gentable_FIN/gentable_FIN.vcxproj [new file with mode: 0644]
etc/gentable_FIN/src/gentable_fin.cpp [new file with mode: 0644]
etc/gentable_MIX/GenerateMixTable.vcxproj [new file with mode: 0644]
etc/gentable_MIX/GenerateMixTable.vcxproj.filters [new file with mode: 0644]
etc/gentable_MIX/gentable_MIX.sln [new file with mode: 0644]
etc/gentable_MIX/src/gentable_mix.cpp [new file with mode: 0644]
etc/utils/date.exe [new file with mode: 0644]
etc/utils/inifile.exe [new file with mode: 0644]
etc/utils/rchhdrrsr.exe [new file with mode: 0644]
etc/utils/zip.exe [new file with mode: 0644]
frontend/MHash384.vcxproj [new file with mode: 0644]
frontend/MHash384.vcxproj.filters [new file with mode: 0644]
frontend/Makefile [new file with mode: 0644]
frontend/res/compat.manifest [new file with mode: 0644]
frontend/res/versioninfo.rc [new file with mode: 0644]
frontend/src/common.h [new file with mode: 0644]
frontend/src/main.cpp [new file with mode: 0644]
frontend/src/self_test.cpp [new file with mode: 0644]
frontend/src/self_test.h [new file with mode: 0644]
frontend/src/sys_info.h [new file with mode: 0644]
frontend/src/utils.cpp [new file with mode: 0644]
frontend/src/utils.h [new file with mode: 0644]
img/mhash384/MHash-384.jpg [new file with mode: 0644]
libmhash384/LibMHash384.vcxproj [new file with mode: 0644]
libmhash384/LibMHash384.vcxproj.filters [new file with mode: 0644]
libmhash384/Makefile [new file with mode: 0644]
libmhash384/include/mhash384.h [new file with mode: 0644]
libmhash384/src/mhash384.cpp [new file with mode: 0644]
ports/c-sharp/MHash384_DotNet.sln [new file with mode: 0644]
ports/c-sharp/libmhash384/MHash384.cs [new file with mode: 0644]
ports/c-sharp/libmhash384/MHash384.csproj [new file with mode: 0644]
ports/c-sharp/libmhash384/Properties/AssemblyInfo.cs [new file with mode: 0644]
ports/c-sharp/test/MHash384Test.cs [new file with mode: 0644]
ports/c-sharp/test/MHash384Test.csproj [new file with mode: 0644]
ports/c-sharp/test/MHash384Test.runsettings [new file with mode: 0644]
ports/c-sharp/test/Main.cs [new file with mode: 0644]
ports/c-sharp/test/Properties/AssemblyInfo.cs [new file with mode: 0644]
ports/delphi/libmhash384/mhash384.pas [new file with mode: 0644]
ports/delphi/test/MHash384Test.cfg [new file with mode: 0644]
ports/delphi/test/MHash384Test.dof [new file with mode: 0644]
ports/delphi/test/MHash384Test.dpr [new file with mode: 0644]
ports/java/.classpath [new file with mode: 0644]
ports/java/.project [new file with mode: 0644]
ports/java/build.xml [new file with mode: 0644]
ports/java/lib/ant-contrib-1.0b3.jar [new file with mode: 0644]
ports/java/src/com/muldersoft/mhash384/MHash384.java [new file with mode: 0644]
ports/java/src/com/muldersoft/mhash384/package-info.java [new file with mode: 0644]
ports/java/test/com/muldersoft/mhash384/test/MHash384Test.java [new file with mode: 0644]
testdata/testdata.xz [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..573542d
--- /dev/null
@@ -0,0 +1,38 @@
+*.opensdf
+*.sdf
+*.suo
+*.user
+/*.html
+/.vs
+/bin
+/build.ini
+/etc/gentable_FIN/.vs
+/etc/gentable_FIN/bin
+/etc/gentable_FIN/ipch
+/etc/gentable_FIN/obj
+/etc/gentable_MIX/.vs
+/etc/gentable_MIX/bin
+/etc/gentable_MIX/ipch
+/etc/gentable_MIX/obj
+/frontend/bin
+/frontend/obj
+/frontend/obj
+/ipch
+/libmhash384/lib
+/libmhash384/obj
+/obj
+/out
+/ports/c-sharp/.vs
+/ports/c-sharp/TestResults
+/ports/c-sharp/libmhash384/bin
+/ports/c-sharp/libmhash384/obj
+/ports/c-sharp/test/bin
+/ports/c-sharp/test/obj
+/ports/delphi/**/*.dcu
+/ports/delphi/**/*.exe
+/ports/delphi/**/*.~dpr
+/ports/delphi/**/*.~pas
+/ports/java/bin
+/ports/java/out
+/testdata/*.sha256
+/testdata/*.txt
diff --git a/COPYING.txt b/COPYING.txt
new file mode 100644 (file)
index 0000000..2b73481
--- /dev/null
@@ -0,0 +1,17 @@
+MHash-384 - Simple fast portable secure hashing library
+Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+and associated documentation files(the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MHash384.sln b/MHash384.sln
new file mode 100644 (file)
index 0000000..104a533
--- /dev/null
@@ -0,0 +1,36 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MHash384", "frontend\MHash384.vcxproj", "{595A7D48-D3CD-4289-90EC-EB524B5050EB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibMHash384", "LibMHash384\LibMHash384.vcxproj", "{6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Debug|x64 = Debug|x64
+               Release|Win32 = Release|Win32
+               Release|x64 = Release|x64
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Debug|Win32.ActiveCfg = Debug|Win32
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Debug|Win32.Build.0 = Debug|Win32
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Debug|x64.ActiveCfg = Debug|x64
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Debug|x64.Build.0 = Debug|x64
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Release|Win32.ActiveCfg = Release|Win32
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Release|Win32.Build.0 = Release|Win32
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Release|x64.ActiveCfg = Release|x64
+               {595A7D48-D3CD-4289-90EC-EB524B5050EB}.Release|x64.Build.0 = Release|x64
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Debug|Win32.ActiveCfg = Debug|Win32
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Debug|Win32.Build.0 = Debug|Win32
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Debug|x64.ActiveCfg = Debug|x64
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Debug|x64.Build.0 = Debug|x64
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Release|Win32.ActiveCfg = Release|Win32
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Release|Win32.Build.0 = Release|Win32
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Release|x64.ActiveCfg = Release|x64
+               {6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}.Release|x64.Build.0 = Release|x64
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..5d7f058
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,69 @@
+# -----------------------------------------------
+# OPTIONS
+# -----------------------------------------------
+
+DEBUG ?= 0
+
+# -----------------------------------------------
+# SYSTEM DETECTION
+# -----------------------------------------------
+
+ISODATE := $(shell date +%Y-%m-%d)
+OS_TYPE := $(shell uname -s | tr '[:upper:]' '[:lower:]')
+OS_ARCH := $(shell uname -m | tr '[:upper:]' '[:lower:]')
+
+# -----------------------------------------------
+# DIRECTORIES
+# -----------------------------------------------
+
+SUBDIRS = libmhash384 frontend
+CLEANUP = $(addsuffix .cleanup,$(SUBDIRS))
+
+# -----------------------------------------------
+# FILE NAMES
+# -----------------------------------------------
+
+OUTDIR = out
+BINDIR = frontend/bin
+
+ifeq ($(DEBUG),0)
+  APPNAME = mhash384
+else
+  APPNAME = mhash384g
+endif
+
+ifeq ($(words $(filter mingw% cygwin%,$(OS_TYPE))),0)
+  SUFFIX = run
+else
+  SUFFIX = exe
+endif
+
+EXEFILE = $(APPNAME).$(SUFFIX)
+TARFILE = $(OUTDIR)/$(APPNAME).$(ISODATE).$(firstword $(subst _, ,$(OS_TYPE)))-$(OS_ARCH).tgz
+
+# -----------------------------------------------
+# MAKE RULES
+# -----------------------------------------------
+
+.PHONY: all clean $(SUBDIRS) $(CLEANUP)
+
+all: $(TARFILE)
+
+clean: $(CLEANUP)
+
+$(TARFILE): $(SUBDIRS)
+       @printf "\033[1;36m===[Make package]===\033[0m\n" $@
+       @mkdir -p $(dir $@)
+       rm -f $@
+       tar -czvf $@ COPYING.txt -C $(BINDIR) $(EXEFILE) BUILD_TAG.txt
+       @printf "\033[1;32mCompleted.\033[0m\n"
+
+$(SUBDIRS):
+       @printf "\033[1;36m===[Make %s]===\033[0m\n" $@
+       $(MAKE) -B -C $@
+       @printf "\033[1;32mCompleted.\033[0m\n"
+       
+$(CLEANUP):
+       @printf "\033[1;31m===[Clean %s]===\033[0m\n" $(basename $@)
+       $(MAKE) -B -C $(basename $@) clean
+       @printf "\033[1;32mExtinguished.\033[0m\n"
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..46cd235
--- /dev/null
+++ b/README.md
@@ -0,0 +1,97 @@
+% ![](img/mhash384/MHash-384.jpg)  
+MHash-384
+% Simple fast portable secure hashing library
+
+# Introduction
+
+**MHash-384** is a fast, portable and secure hashing library, released under the *MIT license*.
+
+The MHash-384 core library has been written in plain **C**, and the CLI front-end has been written in **C++**. The core library provides a simple "stream processing" API, that is available in two flavors: a plain C99 version and an *object-oriented* C++ wrapper. Either way, the MHash-384 library produces hash values with a fixed length of 384 bits (48 bytes).
+
+MHash-384 supports a wide range of compilers, including MSVC++, GCC (MinGW/Cygwin), Clang/LLVM and Intel C++. It also runs on many platforms, including Windows and Linux. Furthermore, the MHash-384 library has already been *ported* to various other programming languages, including **Microsoft.NET**, **Java**, **Delphi** and **Free Pascal** as well as **Python**.
+
+
+# Quick Start Guide
+
+In order to use the *MHash-384* library, simply include the header file `mhash384.h` in your code:
+
+       #include <mhash384.h>
+
+## Example for C language
+
+If you source code is written in **C**, use the **`mhash384_t`** struct and the **`mhash384_XYZ()`** functions:
+
+       /*variables*/
+       uint8_t buffer[BUFFSIZE];
+       size_t len;
+       uint8_t result[MHASH384_SIZE];
+       mhash384_t mhash384;
+       
+       /*initialization*/
+       mhash384_init(&mhash384);
+       
+       /*input data processing*/
+       while(more_data())
+       {
+               len = read_data(buffer, BUFFSIZE);
+               mhash384_update(&mhash384, buffer, len);
+       }
+       
+       /*finalization*/
+       mhash384_final(&mhash384, result);
+
+## Example for C++ language
+
+Or, if you source code is written in **C++**, use the provided **`MHash384`** wrapper class:
+
+       /*instance*/
+       MHash384 mhash384;
+       
+       /*input data processing*/
+       while(more_data())
+       {
+               const std::vector<uint8_t> buffer = read_data();
+               mhash384.update(buffer);
+       }
+       
+       /*finalization*/
+       const uint8_t *result = mhash384.finish();
+
+
+# Command-line Usage
+
+**TODO**
+
+
+# License
+
+**MHash-384 - Simple fast portable secure hashing library**  
+**Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>**
+
+       Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+       and associated documentation files (the "Software"), to deal in the Software without
+       restriction, including without limitation the rights to use, copy, modify, merge, publish,
+       distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+       Software is furnished to do so, subject to the following conditions:
+
+       The above copyright notice and this permission notice shall be included in all copies or
+       substantial portions of the Software.
+
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+       BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+       NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+       DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+       OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+<https://opensource.org/licenses/MIT>
+
+
+# Version History
+
+## Version 2.0.0 [????-??-??]
+
+* Initial release of the 2.x development cycle
+
+&nbsp;
+
+[■](https://www.youtube.com/watch?v=dng06ZqI4Ss)
diff --git a/build.cmd b/build.cmd
new file mode 100644 (file)
index 0000000..1f2cd0c
--- /dev/null
+++ b/build.cmd
@@ -0,0 +1,277 @@
+@echo off
+setlocal enabledelayedexpansion
+
+REM =========================================================================
+REM READ CONFIGURATION
+REM =========================================================================
+
+if not exist "%~dpn0.ini" (
+       echo Configuration file "%~dpn0.ini" not found^^!
+       pause
+       goto:eof
+)
+
+set "CONFVARS_TMP=%TMP%\~%RANDOM%$%RANDOM%$%RANDOM%.cmd"
+"%~dp0\etc\utils\inifile.exe" "%~dpn0.ini" [PATHS] > "%CONFVARS_TMP%"
+
+call "%CONFVARS_TMP%"
+del  "%CONFVARS_TMP%"
+
+REM =========================================================================
+REM CHECK PATHS
+REM =========================================================================
+
+if not exist "%MSVC_PATH%\vcvarsall.bat" (
+       echo MSVC not found. Please check MSVC_PATH and try again^^!
+       pause
+       goto:eof
+)
+
+if not exist "%GIT_PATH%\bin\git.exe" (
+       echo Git not found. Please check GIT_PATH and try again^^!
+       pause
+       goto:eof
+)
+
+if not exist "%PANDOC_PATH%\pandoc.exe" (
+       echo Pandoc not found. Please check PANDOC_PATH and try again^^!
+       pause
+       goto:eof
+)
+
+
+if not exist "%JAVA_HOME%\bin\java.exe" (
+       echo Java not found. Please check JAVA_HOME and try again^^!
+       pause
+       goto:eof
+)
+
+if not exist "%ANT_HOME%\bin\ant.bat" (
+       echo Ant not found. Please check ANT_HOME and try again^^!
+       pause
+       goto:eof
+)
+
+REM =========================================================================
+REM SET UP ENVIRONMENT
+REM =========================================================================
+
+set "PATH=%GIT_PATH%\bin;%ANT_HOME%\bin;%JAVA_HOME%\bin;%PATH%"
+
+set VCINSTALLDIR=
+call "%MSVC_PATH%\vcvarsall.bat" x86
+
+if "%VCINSTALLDIR%"=="" (
+       echo Error: Failed to set up MSVC environment^^!
+       pause
+       goto:eof
+)
+
+REM =========================================================================
+REM DETECT BUILD DATE
+REM =========================================================================
+
+set "ISO_DATE="
+
+for /F "tokens=1,2 delims=:" %%a in ('"%~dp0\etc\utils\date.exe" +ISODATE:%%Y-%%m-%%d') do (
+       if "%%a"=="ISODATE" set "ISO_DATE=%%b"
+)
+
+if "%ISO_DATE%"=="" (
+       echo Error: Failed to determine build date^^!
+       pause
+       goto:eof
+)
+
+REM =========================================================================
+REM REMOVE EXISTING BINARIES
+REM =========================================================================
+
+if exist "%~dp0\bin\" (
+       rmdir /S /Q "%~dp0\bin"
+)
+
+if exist "%~dp0\obj\" (
+       rmdir /S /Q "%~dp0\obj"
+)
+
+REM =========================================================================
+REM BUILD BINARIES
+REM =========================================================================
+
+echo.
+echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+echo BUILD BINARIES
+echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+echo.
+
+for %%p in (Win32,x64) do (
+       for %%t in (Clean,Rebuild) do (
+               MSBuild.exe /property:Configuration=Release /property:Platform=%%p /target:%%t /verbosity:normal "%~dp0\MHash384.sln"
+               if not "!ERRORLEVEL!"=="0" (
+                       echo Error: Build has failed^^!
+                       pause
+                       goto:eof
+               )
+       )
+)
+
+"%~dp0\etc\utils\rchhdrrsr.exe" "%~dp0\bin\Win32\Release\*.exe"
+"%~dp0\etc\utils\rchhdrrsr.exe" "%~dp0\bin\.\x64\Release\*.exe"
+
+for %%p in (Win32,x64) do (
+       for %%t in (Clean,Rebuild) do (
+               MSBuild.exe /property:Configuration=Release /property:Platform=%%p /target:%%t /verbosity:normal "%~dp0\MHash384.sln"
+               if not "!ERRORLEVEL!"=="0" (
+                       echo Error: Build has failed^^!
+                       pause
+                       goto:eof
+               )
+       )
+)
+
+REM -----------------------------------------------------------
+REM C# PORT
+REM -----------------------------------------------------------
+
+pushd "%~dp0\ports\c-sharp"
+
+for %%t in (Clean,Rebuild) do (
+       MSBuild.exe /property:Configuration=Release /property:Platform="Any CPU" /target:%%t /verbosity:normal ".\MHash384_DotNet.sln"
+       if not "!ERRORLEVEL!"=="0" (
+               echo Error: Build has failed^^!
+               pause
+               goto:eof
+       )
+)
+
+popd
+
+REM -----------------------------------------------------------
+REM JAVA PORT
+REM -----------------------------------------------------------
+
+pushd "%~dp0\ports\java"
+
+call ant
+if not "%ERRORLEVEL%"=="0" (
+       echo Error: Build has failed^^!
+       pause
+       goto:eof
+)
+
+popd
+
+REM =========================================================================
+REM COPY DISTRIBUTION FILES
+REM =========================================================================
+
+echo.
+echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+echo CREATE PACKAGE
+echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+echo.
+
+set "PACK_PATH=%TMP%\~%RANDOM%$%RANDOM%$%RANDOM%.tmp"
+
+mkdir "%PACK_PATH%"
+for %%p in (win-x86,win-x64,java,dotnet) do (
+       mkdir "%PACK_PATH%\%%p"
+)
+
+copy /Y "%~dp0\bin\Win32\Release\MHash384.exe"                      "%PACK_PATH%\win-x86"
+copy /Y "%~dp0\bin\x64\Release\MHash384.exe"                        "%PACK_PATH%\win-x64"
+copy /Y "%~dp0\ports\java\out\mhash384*.jar"                        "%PACK_PATH%\java"
+copy /Y "%~dp0\ports\c-sharp\libmhash384\bin\Release\mhash384*.dll" "%PACK_PATH%\dotnet"
+
+REM =========================================================================
+REM CREATE DOCUMENTS
+REM =========================================================================
+
+"%PANDOC_PATH%\pandoc.exe" --from markdown_github+pandoc_title_block+header_attributes+implicit_figures --to html5 --toc -N --standalone -H "%~dp0\..\Prerequisites\Pandoc\css\github-pandoc.inc" -o %~dp0\README.html "%~dp0\README.md"
+if not "%ERRORLEVEL%"=="0" (
+       echo Error: Failed to generate documents^^!
+       pause
+       goto:eof
+)
+
+for %%p in (win-x86,win-x64,java,dotnet) do (
+       mkdir                              "%PACK_PATH%\%%p\img"
+       mkdir                              "%PACK_PATH%\%%p\img\mhash384"
+       copy /Y "%~dp0\README.html"        "%PACK_PATH%\%%p"
+       copy /Y "%~dp0\COPYING.txt"        "%PACK_PATH%\%%p"
+       copy /Y "%~dp0\img\mhash384\*.jpg" "%PACK_PATH%\%%p\img\mhash384"
+       attrib +R "%PACK_PATH%\%%p\*.*" /S
+)
+
+for %%p in (win-x86,win-x64) do (
+       "%PACK_PATH%\%%p\MHash384.exe" --version > "%PACK_PATH%\%%p\BUILD_TAG.txt"
+)
+
+REM =========================================================================
+REM GENERATE OUTNAME
+REM =========================================================================
+
+if not exist "%~dp0\out\" (
+       mkdir "%~dp0\out"
+)
+
+set "OUTNAME=MHash384.%ISO_DATE%"
+
+:validate_outname
+for %%p in (win-x86,win-x64,java,dotnet) do (
+       if exist "%~dp0\out\%OUTNAME%.%%p.zip" goto:next_outname
+)
+goto:outname_generated
+
+:next_outname
+set "OUTNAME=%OUTNAME%.new"
+goto:validate_outname
+
+:outname_generated
+
+REM =========================================================================
+REM CREATE PACKAGE
+REM =========================================================================
+
+for %%p in (win-x86,win-x64,java,dotnet) do (
+       pushd "%PACK_PATH%\%%p"
+       if not "!ERRORLEVEL!"=="0" (
+               echo Error: Failed to change directory to PACK_PATH^^!
+               pause
+               goto:eof
+       )
+       "%~dp0\etc\utils\zip.exe" -r -9 -z "%~dp0\out\%OUTNAME%.%%p.zip" "*.*" < "%~dp0\COPYING.txt"
+       if not "!ERRORLEVEL!"=="0" (
+               echo Error: Failed to create ZIP package^^!
+               pause
+               goto:eof
+       )
+       popd
+)
+
+"%GIT_PATH%\bin\git.exe" archive --verbose --format=tar.gz --output "%~dp0\out\%OUTNAME%.source.tgz" HEAD
+if not "%ERRORLEVEL%"=="0" (
+       echo Error: Failed to export source codes^^!
+       pause
+       goto:eof
+)
+
+attrib +R "%~dp0\out\%OUTNAME%.*.zip"
+attrib +R "%~dp0\out\%OUTNAME%.source.tgz"
+
+REM =========================================================================
+REM FINAL CLEAN-UP
+REM =========================================================================
+
+rmdir /Q /S "%PACK_PATH%"
+
+REM =========================================================================
+REM COMPLETED
+REM =========================================================================
+
+echo.
+echo COMPLETED
+echo.
+
+pause
diff --git a/build.ini.EXAMPLE b/build.ini.EXAMPLE
new file mode 100644 (file)
index 0000000..14838d6
--- /dev/null
@@ -0,0 +1,6 @@
+[PATHS]
+MSVC_PATH=C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC
+GIT_PATH=C:\Program Files\Git
+PANDOC_PATH=C:\Program Files\Pandoc
+JAVA_HOME=C:\AdoptOpenJDK\jdk-8.0.232.09-hotspot
+ANT_HOME=C:\Program Files\Ant
diff --git a/etc/css/style.inc b/etc/css/style.inc
new file mode 100644 (file)
index 0000000..dec307a
--- /dev/null
@@ -0,0 +1,3 @@
+<style type="text/css">
+/*!normalize.css v3.0.1 | MIT License | git.io/normalize*/body,h1,h2,html,mark{color:#000}blockquote,h6{color:#777}code,table tr:nth-child(2n),tt{background-color:#f8f8f8}code,h3,h4,h5,tt{color:#333}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0;color:#4183c4;text-decoration:none}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,optgroup,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0}small{font-size:80%}sup{top:-.5em}img{border:0;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:1em 12px}hr{-moz-box-sizing:content-box;box-sizing:content-box}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}td,th{padding:0}.caption{margin-bottom:5em}body,html{margin:auto;padding-right:1em;padding-left:1em;max-width:57em}:not('#mkdbuttons'){margin:0;padding:0}body{font:13.34px helvetica,arial,freesans,clean,sans-serif;-webkit-font-smoothing:subpixel-antialiased;background:#fff;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;padding:30px;margin:15px;font-size:14px;line-height:1.6}dl dt,h1,h2,h3,h4,h5,h6{font-weight:700;padding:0}body>:first-child{margin-top:0!important}body>:last-child{margin-bottom:0!important}h1,h2,h3,h4,h5,h6{margin:20px 0 10px;-webkit-font-smoothing:subpixel-antialiased;cursor:text}h1{font-size:28px}h2{font-size:24px;border-bottom:1px solid #ccc}h3{font-size:18px}h4{font-size:16px}dl dt,h5,h6{font-size:14px}blockquote,p,pre,table{margin:15px 0}ol,ul{padding-left:30px}blockquote>:first-child,dl dd>:first-child,dl dt>:first-child,h1+p,h2+p,h3+p,h4+p,h5+p,h6+p,ol li ul:first-of-type,ol li>:first-child,ul li>:first-child{margin-top:0}hr{background:url('data:image/png; base64, iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC') repeat-x;border:0;color:#ccc;height:4px;padding:0}a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6,body>h1:first-child,body>h1:first-child+h2,body>h2:first-child,body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child{margin-top:0;padding-top:0}table td,table th{border:1px solid #ccc;padding:6px 13px}dl,dl dt:first-child{padding:0}dl dt{font-style:italic;margin:15px 0 5px}blockquote>:last-child,dl dd>:last-child,dl dt>:last-child{margin-bottom:0}dl dd{margin:0 0 15px;padding:0 15px}blockquote{border-left:4px solid #DDD;padding:0 15px}table{border-collapse:collapse;border-spacing:0;font:inherit}.highlight .c,.highlight .c1,.highlight .cm,.highlight .cs,.highlight .ge,.poetry pre{font-style:italic}.highlight .cp,.highlight .cs,.highlight .gs,.highlight .k,.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt,.highlight .nc,.highlight .ne,.highlight .nf,.highlight .o,.highlight .ow,table th{font-weight:700}table tr{border-top:1px solid #ccc;background-color:#fff}code,tt{margin:0 2px;padding:0 5px;white-space:nowrap;border:1px solid #eaeaea;border-radius:3px;font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px}.poetry pre,.poetry pre code{font-family:Georgia,Garamond,serif!important}pre>code{margin:0;padding:0;white-space:pre;border:0;background:0 0}.highlight pre,pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre code,pre tt{background-color:transparent;border:0}.poetry pre{font-size:110%!important;line-height:1.6em;display:block;margin-left:1em}.poetry pre code{word-break:break-all;word-break:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto;white-space:pre-wrap}a.footnote,sub,sup{font-size:1.4ex;height:0;line-height:1;vertical-align:super;position:relative}sub{bottom:-.25em;vertical-align:sub;top:-1px}@media print{body,pre{background:#fff}body{border:0}blockquote,figure,img,pre,table{page-break-inside:avoid}code{background-color:#fff;color:#333!important;padding:0 .2em;border:1px solid #dedede}pre code{background-color:#fff!important;overflow:visible}}@media screen{body{box-shadow:0 0 0 1px #cacaca,0 0 0 4px #eee}.inverted .math,.inverted blockquote,.inverted body,.inverted caption,.inverted dd,.inverted dt,.inverted h1,.inverted h2,.inverted h3,.inverted h4,.inverted h5,.inverted h6,.inverted hr .inverted p,.inverted li,.inverted td,.inverted th,body.inverted{color:#eee!important;border-color:#555;box-shadow:none}.inverted td,.inverted th{background:#333}.inverted h2{border-color:#555}.inverted hr{border-color:#777;border-width:1px!important}::selection{background:rgba(157,193,200,.5)}h1::selection{background-color:rgba(45,156,208,.3)}h2::selection{background-color:rgba(90,182,224,.3)}h3::selection,h4::selection,h5::selection,h6::selection,li::selection,ol::selection{background-color:rgba(133,201,232,.3)}code::selection{background-color:rgba(0,0,0,.7);color:#eee}code span::selection{background-color:rgba(0,0,0,.7)!important;color:#eee!important}a::selection{background-color:rgba(255,230,102,.2)}.inverted a::selection{background-color:rgba(255,230,102,.6)}caption::selection,td::selection,th::selection{background-color:rgba(180,237,95,.5)}.inverted,.inverted body{background:#252a2a}.inverted a{color:#acd1d5}}.highlight .c{color:#998}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .cm{color:#998}.highlight .cp{color:#999}.highlight .c1{color:#998}.highlight .cs{color:#999}.highlight .gd{color:#000;background-color:#fdd}.highlight .gd .x{color:#000;background-color:#faa}.highlight .gr{color:#a00}.highlight .gh{color:#999}.highlight .gi{color:#000;background-color:#dfd}.highlight .gi .x{color:#000;background-color:#afa}.highlight .go{color:#888}.highlight .gp{color:#555}.highlight .gu{color:purple;font-weight:700}.highlight .gt{color:#a00}.highlight .kt{color:#458}.highlight .m{color:#099}.highlight .s{color:#d14}.highlight .na{color:teal}.highlight .nb{color:#0086b3}.highlight .nc{color:#458}.highlight .no{color:teal}.highlight .ni{color:purple}.highlight .ne,.highlight .nf{color:#900}.highlight .nn{color:#555}.highlight .nt{color:navy}.highlight .nv{color:teal}.highlight .w{color:#bbb}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#099}.highlight .s2,.highlight .sb,.highlight .sc,.highlight .sd,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999}.highlight .vc,.highlight .vg,.highlight .vi{color:teal}.highlight .il{color:#099}.highlight .gc{color:#999;background-color:#eaf2f5}.type-csharp .highlight .k,.type-csharp .highlight .kt{color:#00F}.type-csharp .highlight .nf{color:#000;font-weight:400}.type-csharp .highlight .nc{color:#2b91af}.type-csharp .highlight .nn{color:#000}.type-csharp .highlight .s,.type-csharp .highlight .sc{color:#a31515}
+</style>
\ No newline at end of file
diff --git a/etc/gentable_FIN/gentable_FIN.filters b/etc/gentable_FIN/gentable_FIN.filters
new file mode 100644 (file)
index 0000000..1b69462
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\gentable_mix.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/etc/gentable_FIN/gentable_FIN.sln b/etc/gentable_FIN/gentable_FIN.sln
new file mode 100644 (file)
index 0000000..7953399
--- /dev/null
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gentable_FIN", "gentable_FIN.vcxproj", "{579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Debug|Win32.ActiveCfg = Debug|Win32
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Debug|Win32.Build.0 = Debug|Win32
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Release|Win32.ActiveCfg = Release|Win32
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Release|Win32.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/etc/gentable_FIN/gentable_FIN.vcxproj b/etc/gentable_FIN/gentable_FIN.vcxproj
new file mode 100644 (file)
index 0000000..c542f7b
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\gentable_fin.cpp" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>gentable_FIN</RootNamespace>
+    <ProjectName>gentable_FIN</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>Full</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/etc/gentable_FIN/src/gentable_fin.cpp b/etc/gentable_FIN/src/gentable_fin.cpp
new file mode 100644 (file)
index 0000000..f9d0164
--- /dev/null
@@ -0,0 +1,96 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#define _CRT_RAND_S 1
+#include <cstdlib>
+#include <cstdio>
+#include <cstdint>
+#include <cstring>
+#include <algorithm>
+
+#define MASH384_SIZE 48U
+
+static uint32_t next_rand(const uint32_t max)
+{
+       uint32_t rnd;
+       if(rand_s(&rnd) != 0)
+       {
+               abort();
+       }
+       return rnd % max;
+}
+
+static bool create_permutation(uint32_t *const out, const uint32_t max_retry)
+{
+       bool map[MASH384_SIZE];
+       memset(map, 0U, sizeof(bool) * MASH384_SIZE);
+       uint32_t retry = 0U;
+       for(size_t i = 0U; i < MASH384_SIZE; ++i)
+       {
+               uint32_t index;
+               do
+               {
+                       index = next_rand(MASH384_SIZE);
+                       if(++retry > max_retry)
+                       {
+                               return false;
+                       }
+               }
+               while(map[index] || ((i > 0U) && (((index / 8U) == (out[i - 1U] / 8U)) || ((index % 8U) == (out[i - 1U] % 8U)))));
+               out[i] = index;
+               map[index] = true;
+       }
+       return true;
+}
+
+static void create_permutation(uint32_t *const out)
+{
+}
+
+int main()
+{
+       uint32_t permutation[MASH384_SIZE];
+
+       for(uint32_t i = 997U; i < UINT32_MAX; ++i)
+       {
+               if(create_permutation(permutation, i))
+               {
+                       break; /*success*/
+               }
+       }
+
+       for(size_t i = 0U; i < MASH384_SIZE; ++i)
+       {
+               printf("%02u %02u %02u\n", permutation[i], permutation[i] / 8U, permutation[i] % 8U);
+       }
+       puts("");
+
+       for(size_t i = 0U; i < MASH384_SIZE; ++i)
+       {
+               printf(((i % 16) > 0U) ? ", 0x%02X" : "0x%02X", permutation[i]);
+               if((i % 16U) == 15U)
+               {
+                       puts(",");
+               }
+       }
+
+       puts("\nCompleted.\n");
+       return EXIT_SUCCESS;
+}
diff --git a/etc/gentable_MIX/GenerateMixTable.vcxproj b/etc/gentable_MIX/GenerateMixTable.vcxproj
new file mode 100644 (file)
index 0000000..3604fab
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\gentable_mix.cpp" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>GenerateMixTable</RootNamespace>
+    <ProjectName>gentable_MIX</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>Full</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/etc/gentable_MIX/GenerateMixTable.vcxproj.filters b/etc/gentable_MIX/GenerateMixTable.vcxproj.filters
new file mode 100644 (file)
index 0000000..1b69462
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\gentable_mix.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/etc/gentable_MIX/gentable_MIX.sln b/etc/gentable_MIX/gentable_MIX.sln
new file mode 100644 (file)
index 0000000..ffcbb55
--- /dev/null
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GenerateMixTable", "GenerateMixTable.vcxproj", "{579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Debug|Win32.ActiveCfg = Debug|Win32
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Debug|Win32.Build.0 = Debug|Win32
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Release|Win32.ActiveCfg = Release|Win32
+               {579E7209-F88C-4D5B-A8D6-6FBAF923ABD1}.Release|Win32.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/etc/gentable_MIX/src/gentable_mix.cpp b/etc/gentable_MIX/src/gentable_mix.cpp
new file mode 100644 (file)
index 0000000..af84d31
--- /dev/null
@@ -0,0 +1,133 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#define _CRT_RAND_S 1
+#include <cstdlib>
+#include <cstdio>
+#include <cstdint>
+#include <cstring>
+#include <algorithm>
+
+#define MASH384_WORDS 6U
+#define MIN_DIFF 2U
+
+static uint32_t mix_table[256U][MASH384_WORDS];
+
+static uint32_t next_rand(const uint32_t max)
+{
+       uint32_t rnd;
+       if(rand_s(&rnd) != 0)
+       {
+               abort();
+       }
+       return rnd % max;
+}
+
+static bool _create_permutation(uint32_t *const out, const uint32_t max_retry)
+{
+       bool map[MASH384_WORDS];
+       memset(map, 0U, sizeof(bool) * MASH384_WORDS);
+       uint32_t retry = 0U;
+       for(size_t i = 0U; i < MASH384_WORDS; ++i)
+       {
+               uint32_t index;
+               do
+               {
+                       index = next_rand(MASH384_WORDS);
+                       if(++retry > max_retry)
+                       {
+                               return false;
+                       }
+               }
+               while((index == i) || map[index]);
+               out[i] = index;
+               map[index] = true;
+       }
+       return true;
+}
+
+static void create_permutation(uint32_t *const out)
+{
+       for(uint32_t i = 13U; i < UINT32_MAX; ++i)
+       {
+               if(_create_permutation(out, i))
+               {
+                       return; /*success*/
+               }
+       }
+       abort();
+}
+
+static uint32_t check_difference_row(const size_t row_1, const size_t row_2)
+{
+       uint32_t diff = 0U;
+       for(size_t j = 0U; j < MASH384_WORDS; ++j)
+       {
+               if(mix_table[row_1][j] != mix_table[row_2][j])
+               {
+                       ++diff;
+               }
+       }
+       return diff;
+}
+
+static uint32_t check_difference_table(const size_t max_row)
+{
+       uint32_t min_diff = UINT32_MAX;
+       for(size_t i = 0U; i < max_row; ++i)
+       {
+               min_diff = std::min(min_diff, check_difference_row(i, max_row));
+       }
+       return min_diff;
+}
+
+static void print_row(const size_t row)
+{
+       for(size_t j = 0U; j < MASH384_WORDS; ++j)
+       {
+               printf((j > 0U) ? ", 0x%02X" : "{ 0x%02X", mix_table[row][j]);
+       }
+       printf(" }, /*%02X*/\n", row & 0xFF);
+}
+
+int main()
+{
+       create_permutation(mix_table[0U]);
+       print_row(0U);
+
+       for(size_t i = 1U; i < 256U; ++i)
+       {
+               uint32_t retry = 0U;
+               do
+               {
+                       if(++retry >= 999983U)
+                       {
+                               puts("\nFailed !!!\n");
+                               return EXIT_FAILURE;
+                       }
+                       create_permutation(mix_table[i]);
+               }
+               while((check_difference_row(i, i - 1U) < MASH384_WORDS) || ((i == 255U) && (check_difference_row(i, 0U) < MASH384_WORDS)) || (check_difference_table(i) < MIN_DIFF));
+               print_row(i);
+       }
+
+       puts("\nCompleted.\n");
+       return EXIT_SUCCESS;
+}
diff --git a/etc/utils/date.exe b/etc/utils/date.exe
new file mode 100644 (file)
index 0000000..069bae1
Binary files /dev/null and b/etc/utils/date.exe differ
diff --git a/etc/utils/inifile.exe b/etc/utils/inifile.exe
new file mode 100644 (file)
index 0000000..e44621f
Binary files /dev/null and b/etc/utils/inifile.exe differ
diff --git a/etc/utils/rchhdrrsr.exe b/etc/utils/rchhdrrsr.exe
new file mode 100644 (file)
index 0000000..eb007aa
Binary files /dev/null and b/etc/utils/rchhdrrsr.exe differ
diff --git a/etc/utils/zip.exe b/etc/utils/zip.exe
new file mode 100644 (file)
index 0000000..55be81d
Binary files /dev/null and b/etc/utils/zip.exe differ
diff --git a/frontend/MHash384.vcxproj b/frontend/MHash384.vcxproj
new file mode 100644 (file)
index 0000000..65aa2bd
--- /dev/null
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{595A7D48-D3CD-4289-90EC-EB524B5050EB}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>MHash384</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)libmhash384\include</AdditionalIncludeDirectories>
+      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <PreBuildEvent>
+      <Command>findstr /B /C:"#define MHASH384_VERSION_" "$(SolutionDir)libmhash384\src\mhash384.cpp" &gt; "$(IntDir)resource.h"
+"$(SolutionDir)etc\utils\date.exe" +"#define MHASH384_VERSION_BUILD %%y%%W%%w" &gt;&gt; "$(IntDir)resource.h"</Command>
+    </PreBuildEvent>
+    <ResourceCompile />
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)libmhash384\include</AdditionalIncludeDirectories>
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <PreBuildEvent>
+      <Command>findstr /B /C:"#define MHASH384_VERSION_" "$(SolutionDir)libmhash384\src\mhash384.cpp" &gt; "$(IntDir)resource.h"
+"$(SolutionDir)etc\utils\date.exe" +"#define MHASH384_VERSION_BUILD %%y%%W%%w" &gt;&gt; "$(IntDir)resource.h"</Command>
+    </PreBuildEvent>
+    <ResourceCompile />
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>Full</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <OmitFramePointers>true</OmitFramePointers>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+      <AdditionalIncludeDirectories>$(SolutionDir)libmhash384\include</AdditionalIncludeDirectories>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <FloatingPointModel>Fast</FloatingPointModel>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>wsetargv.obj;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>findstr /B /C:"#define MHASH384_VERSION_" "$(SolutionDir)libmhash384\src\mhash384.cpp" &gt; "$(IntDir)resource.h"
+"$(SolutionDir)etc\utils\date.exe" +"#define MHASH384_VERSION_BUILD %%y%%W%%w" &gt;&gt; "$(IntDir)resource.h"</Command>
+    </PreBuildEvent>
+    <ResourceCompile />
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level4</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>Full</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <OmitFramePointers>true</OmitFramePointers>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+      <AdditionalIncludeDirectories>$(SolutionDir)libmhash384\include</AdditionalIncludeDirectories>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <FloatingPointModel>Fast</FloatingPointModel>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>wsetargv.obj;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>findstr /B /C:"#define MHASH384_VERSION_" "$(SolutionDir)libmhash384\src\mhash384.cpp" &gt; "$(IntDir)resource.h"
+"$(SolutionDir)etc\utils\date.exe" +"#define MHASH384_VERSION_BUILD %%y%%W%%w" &gt;&gt; "$(IntDir)resource.h"</Command>
+    </PreBuildEvent>
+    <ResourceCompile />
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="src\main.cpp" />
+    <ClCompile Include="src\self_test.cpp" />
+    <ClCompile Include="src\utils.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\LibMHash384\LibMHash384.vcxproj">
+      <Project>{6b8b0be1-c9b7-4a2e-926a-7d0378a5a01a}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="src\common.h" />
+    <ClInclude Include="src\self_test.h" />
+    <ClInclude Include="src\sys_info.h" />
+    <ClInclude Include="src\utils.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="res\versioninfo.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\compat.manifest" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/frontend/MHash384.vcxproj.filters b/frontend/MHash384.vcxproj.filters
new file mode 100644 (file)
index 0000000..a5f9ba6
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\utils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\self_test.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="src\utils.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\self_test.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\common.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\sys_info.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="res\versioninfo.rc">
+      <Filter>Resource Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Manifest Include="res\compat.manifest">
+      <Filter>Resource Files</Filter>
+    </Manifest>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/frontend/Makefile b/frontend/Makefile
new file mode 100644 (file)
index 0000000..ed0f426
--- /dev/null
@@ -0,0 +1,108 @@
+# -----------------------------------------------
+# OPTIONS
+# -----------------------------------------------
+
+DEBUG  ?= 0
+STATIC ?= 0
+MARCH  ?= native
+MTUNE  ?= native
+
+# -----------------------------------------------
+# SYSTEM DETECTION
+# -----------------------------------------------
+
+OS_TYPE := $(shell uname -s | tr '[:upper:]' '[:lower:]')
+
+# -----------------------------------------------
+# FILES
+# -----------------------------------------------
+
+SRCDIR = src
+RESDIR = res
+OBJDIR = obj
+BINDIR = bin
+LIBDIR = ../libmhash384
+
+SRCFILES = $(wildcard $(SRCDIR)/*.cpp)
+RESFILES = $(wildcard $(RESDIR)/*.rc)
+OBJFILES = $(addprefix $(OBJDIR)/,$(patsubst %.cpp,%.o,$(notdir $(SRCFILES))))
+
+ifeq ($(DEBUG),0)
+  EXENAME = mhash384
+else
+  EXENAME = mhash384g
+endif
+
+ifeq ($(words $(filter mingw% cygwin%,$(OS_TYPE))),0)
+  SUFFIX = run
+else
+  SUFFIX = exe
+  OBJFILES += $(addprefix $(OBJDIR)/,$(patsubst %.rc, %.o,$(notdir $(RESFILES))))
+endif
+
+CORFILE = $(LIBDIR)/src/mhash384.cpp
+RSCFILE = $(OBJDIR)/resource.h
+EXEFILE = $(BINDIR)/$(EXENAME).$(SUFFIX)
+TAGFILE = $(BINDIR)/BUILD_TAG.txt
+
+# -----------------------------------------------
+# FLAGS
+# -----------------------------------------------
+
+CXXFLAGS += -std=gnu++11 -I$(LIBDIR)/include
+LDFLAGS += -L$(LIBDIR)/lib
+
+ifeq ($(STATIC),1)
+  LDFLAGS += -static
+endif
+
+ifneq ($(words $(filter mingw%,$(OS_TYPE))),0)
+  LDFLAGS += -municode
+endif
+
+ifeq ($(DEBUG),0)
+  CXXFLAGS += -O3 -DNDEBUG -march=$(MARCH) -mtune=$(MTUNE)
+  LDFLAGS  += -lmhash384-2
+else
+  CXXFLAGS += -g
+  LDFLAGS  += -lmhash384g-2
+endif
+
+# -----------------------------------------------
+# MAKE RULES
+# -----------------------------------------------
+
+.DELETE_ON_ERROR:
+
+.PHONY: all clean
+
+all: $(EXEFILE) $(TAGFILE)
+
+$(EXEFILE): $(OBJFILES)
+       @mkdir -p $(dir $@)
+       $(CXX) $+ -o $@ $(LDFLAGS)
+ifeq ($(DEBUG),0)
+       strip -s $@
+endif
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
+       @mkdir -p $(dir $@)
+       $(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/%.o: $(RESDIR)/%.rc $(RSCFILE)
+       @mkdir -p $(dir $@)
+       windres -I$(OBJDIR) -o $@ $<
+
+$(RSCFILE): $(CORFILE)
+       @mkdir -p $(dir $@)
+       grep -E '^#define[[:space:]]+MHASH384_VERSION' $< > $@
+       date +'#define MHASH384_VERSION_BUILD %y%W%w' >> $@
+
+$(TAGFILE): $(EXEFILE)
+       @mkdir -p $(dir $@)
+       $< --version > $@
+
+clean:
+       rm -rf $(OBJDIR)/*.o
+       rm -rf $(OBJDIR)/*.h
+       rm -rf $(BINDIR)/*.$(SUFFIX)
diff --git a/frontend/res/compat.manifest b/frontend/res/compat.manifest
new file mode 100644 (file)
index 0000000..b540fc2
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/></application></compatibility></assembly>
\ No newline at end of file
diff --git a/frontend/res/versioninfo.rc b/frontend/res/versioninfo.rc
new file mode 100644 (file)
index 0000000..6a0b9fb
--- /dev/null
@@ -0,0 +1,73 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#include "WinResrc.h"
+#include "resource.h"
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+// Version
+
+#define __VERSION_STR__(X,Y,Z) #X "." #Y #Z
+#define _VERSION_STR_(X,Y,Z) __VERSION_STR__(X,Y,Z)
+#define VERSION_STR _VERSION_STR_(MHASH384_VERSION_MAJOR,MHASH384_VERSION_MINOR,MHASH384_VERSION_PATCH)
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION    MHASH384_VERSION_MAJOR,MHASH384_VERSION_MINOR,MHASH384_VERSION_PATCH,MHASH384_VERSION_BUILD
+ PRODUCTVERSION MHASH384_VERSION_MAJOR,MHASH384_VERSION_MINOR,MHASH384_VERSION_PATCH,MHASH384_VERSION_BUILD
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+  FILEFLAGS 0x3L
+#else
+  FILEFLAGS 0x2L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "000004b0"
+        BEGIN
+            VALUE "ProductName",      "MHash-384"
+            VALUE "FileDescription",  "Simple fast portable secure hashing library"
+            VALUE "FileVersion",      VERSION_STR
+            VALUE "ProductVersion",   VERSION_STR
+            VALUE "InternalName",     "MHash384"
+            VALUE "OriginalFilename", "MHash384.exe"
+            VALUE "CompanyName",      "Muldersoft <mulder2@gmx.de>"
+            VALUE "LegalCopyright",   "Created by LoRd_MuldeR <mulder2@gmx.de>"
+            VALUE "LegalTrademarks",  "MuldeRsoft"
+            VALUE "Comments",         "This program is free software; you can redistribute it and/or modify it under the terms of the MIT license."
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0, 1200
+    END
+END
+
+#endif    // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
diff --git a/frontend/src/common.h b/frontend/src/common.h
new file mode 100644 (file)
index 0000000..bf708a3
--- /dev/null
@@ -0,0 +1,68 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#ifndef INC_MHASH384_COMMON_H
+#define INC_MHASH384_COMMON_H
+
+#include <cstring>
+#include <cstdio>
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1600)
+#define PRIu64 "llu"
+#else
+#include <cinttypes>
+#endif
+
+#ifdef _WIN32
+#define CHAR_T wchar_t
+#define EXTRY_POINT wmain
+#define _STR_(X) L##X
+#define FPRINTF fwprintf
+#define FPUTS fputws
+#define STRPBRK wcspbrk
+#define STRICMP _wcsicmp
+#define STRNICMP _wcsnicmp
+#define FOPEN _wfopen
+#define FORCE_EXIT _exit
+#ifdef __USE_MINGW_ANSI_STDIO
+#define PRI_char L"hs"
+#define PRI_CHAR L"ls"
+#else
+#define PRI_char L"S"
+#define PRI_CHAR L"s"
+#endif
+#else
+#define CHAR_T char
+#define EXTRY_POINT main
+#define _STR_(X) X
+#define FPRINTF fprintf
+#define FPUTS fputs
+#define STRPBRK strpbrk
+#define STRICMP strcasecmp
+#define STRNICMP strncasecmp
+#define FOPEN fopen
+#define FORCE_EXIT _Exit
+#define PRI_char "s"
+#define PRI_CHAR "s"
+#endif
+
+#define STR(X) _STR_(X)
+
+#endif /*INC_MHASH384_COMMON_H*/
diff --git a/frontend/src/main.cpp b/frontend/src/main.cpp
new file mode 100644 (file)
index 0000000..6569617
--- /dev/null
@@ -0,0 +1,372 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#include "mhash384.h"
+#include "common.h"
+#include "self_test.h"
+#include "utils.h"
+#include "sys_info.h"
+#include <ctime>
+#include <sys/stat.h>
+
+/* Win32 I/O stuff */
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#define fstat  _fstat
+#define stat   _stat
+#define fileno _fileno
+#endif
+
+/* fstat(2) macros */
+#if !defined(S_IFMT) && !defined(S_IFDIR) && defined(_S_IFMT) && defined(_S_IFDIR)
+#define S_IFMT  _S_IFMT
+#define S_IFDIR _S_IFDIR
+#endif
+
+/* System type */
+#define SYSTEM_TYPE STR(SYSTEM_NAME) STR("-") STR(SYSTEM_ARCH)
+
+/* Buffer size */
+static const size_t BUFFER_SIZE = 8192U;
+
+/* Mode of operation */
+typedef enum
+{
+       MODE_DEFAULT  =  0,
+       MODE_MANPAGE  =  1,
+       MODE_VERSION  =  2,
+       MODE_SELFTEST =  3,
+       MODE_STRESS   =  4,
+       MODE_UNKNOWN  = -1
+}
+opmode_t;
+
+/*
+ * Print the logo
+ */
+static void print_logo(void)
+{
+       uint16_t ver_major, ver_minor, ver_patch;
+       mhash384_version(&ver_major, &ver_minor, &ver_patch);
+       FPRINTF(stderr, ver_patch ? STR("MHash-384 v%u.%02u-%u") : STR("MHash-384 v%u.%02u"), ver_major, ver_minor, ver_patch);
+       FPUTS(STR(", ") SYSTEM_TYPE STR(" [") STR(__DATE__) STR("]\n"), stderr);
+       FPUTS(STR("Created by LoRd_MuldeR <mulder2@gmx.de>, released under the MIT license.\n\n"), stderr);
+       fflush(stderr);
+}
+
+/*
+ * Print the version
+ */
+static void print_version(void)
+{
+       uint16_t ver_major, ver_minor, ver_patch;
+       mhash384_version(&ver_major, &ver_minor, &ver_patch);
+       FPRINTF(stdout, STR("MHash-384 v%u.%02u-%u, ") SYSTEM_TYPE STR("\n"), ver_major, ver_minor, ver_patch);
+       FPRINTF(stdout, STR("Built on ") STR(__DATE__) STR(" at ") STR(__TIME__) STR(", using ") STR(COMPILER_FMT) STR("\n"), COMPILER_ARG);
+}
+
+/*
+ * Print the manpage
+ */
+static void print_manpage(const CHAR_T *const argv0)
+{
+       const CHAR_T *const program_name = get_basename(argv0);
+       print_logo();
+       FPUTS(STR("Usage:\n"), stderr);
+       FPRINTF(stderr, STR("   %") PRI_CHAR STR(" [OPTIONS] [<FILE_1> <FILE_2> ... <FILE_N>]\n\n"), program_name);
+       FPUTS(STR("Options:\n"), stderr);
+       FPUTS(STR("   --keep-going  Try to proceed with the remaining files, if a file has failed\n"), stderr);
+       FPUTS(STR("   --short       Print the digest in short format (no file names)\n"), stderr);
+       FPUTS(STR("   --lower-case  Print the digest in lower-case letters (default: upper-case)\n"), stderr);
+       FPUTS(STR("   --help        Print help screen and exit\n"), stderr);
+       FPUTS(STR("   --version     Print program version and exit\n"), stderr);
+       FPUTS(STR("   --self-test   Run self-test and exit\n"), stderr);
+       FPUTS(STR("   --stress      Enable stress test mode; strings are read from the input file\n"), stderr);
+       FPUTS(STR("   --benchmark   Measure the overall time required for the operation\n\n"), stderr);
+       FPUTS(STR("If *no* input file is specified, data is read from the standard input (stdin)\n"), stderr);
+}
+
+/*
+ * Parse command-line options
+ */
+static opmode_t parse_options(int &arg_offset, const int argc, const CHAR_T *const *const argv, bool &keep_going, bool &short_format, bool &lower_case, bool &benchmark)
+{
+       opmode_t mode = MODE_DEFAULT;
+       keep_going = short_format = lower_case = benchmark = false;
+       bool stop_here = false;
+
+       while((!stop_here) && (arg_offset < argc) && (!STRNICMP(argv[arg_offset], STR("--"), 2U)))
+       {
+               const CHAR_T *const argstr = argv[arg_offset] + 2U;
+               if(!(*argstr))
+               {
+                       stop_here = true;
+               }
+               else if(!STRICMP(argstr, STR("keep-going")))
+               {
+                       keep_going = true;
+               }
+               else if(!STRICMP(argstr, STR("short")))
+               {
+                       short_format = true;
+               }
+               else if(!STRICMP(argstr, STR("lower-case")))
+               {
+                       lower_case = true;
+               }
+               else if(!STRICMP(argstr, STR("help")))
+               {
+                       mode = MODE_MANPAGE;
+               }
+               else if(!STRICMP(argstr, STR("version")))
+               {
+                       mode = MODE_VERSION;
+               }
+               else if(!STRICMP(argstr, STR("self-test")))
+               {
+                       mode = MODE_SELFTEST;
+               }
+               else if(!STRICMP(argstr, STR("stress")))
+               {
+                       mode = MODE_STRESS;
+               }
+               else if(!STRICMP(argstr, STR("benchmark")))
+               {
+                       benchmark = true;
+               }
+               else
+               {
+                       print_logo();
+                       FPRINTF(stderr, STR("Error: Specified option \"%") PRI_CHAR STR("\" is unknown. Please use option --help for details!\n"), argv[arg_offset]);
+                       fflush(stderr);
+                       return MODE_UNKNOWN;
+               }
+               ++arg_offset;
+       }
+
+       return mode;
+}
+
+/*
+ * Process input file
+ */
+static bool process_file(const CHAR_T *const file_name, const bool short_format, const bool lower_case)
+{
+       /* File description */
+       const CHAR_T *const file_description = file_name ? file_name : STR("<STDIN>");
+
+       /* Open the input file */
+       errno = 0;
+       FILE *const input = file_name ? FOPEN(file_name, STR("rb")) : stdin;
+       if(!input)
+       {
+               FPRINTF(stderr, STR("Error: File \"%") PRI_CHAR STR("\" could not be opened for reading! [errno: %d]\n"), file_description, errno);
+               fflush(stderr);
+               return false;
+       }
+
+       /* Check if file is directory (this is required for Linux!)*/
+       struct stat file_info;
+       if(!fstat(fileno(input), &file_info))
+       {
+               if((file_info.st_mode & S_IFMT) == S_IFDIR)
+               {
+                       FPRINTF(stderr, STR("Error: File \"%") PRI_CHAR STR("\" is a directory!\n"), file_description);
+                       fclose(input);
+                       fflush(stderr);
+                       return false;
+               }
+       }
+
+       /* Initialize hash state */
+       MHash384 mhash384;
+       uint8_t buffer[BUFFER_SIZE];
+       bool success = true;
+
+       /* Process complete input */
+       for(;;)
+       {
+               const size_t length = fread(buffer, sizeof(uint8_t), BUFFER_SIZE, input);
+               if(!length)
+               {
+                       break; /*EOF or error*/
+               }
+               mhash384.update(buffer, length);
+       }
+
+       /* Print the final digest */
+       if(!ferror(input))
+       {
+               const std::string digest = bytes_to_hex(mhash384.finish(), MHASH384_SIZE, lower_case);
+               const CHAR_T *const source_name = file_name ? file_name : STR("-");
+               const CHAR_T *const format = short_format ? STR("%") PRI_char STR("\n") : STR("%") PRI_char STR(" %") PRI_CHAR STR("\n");
+               FPRINTF(stdout, format, digest.c_str(), source_name);
+               fflush(stdout);
+       }
+       else
+       {
+               FPRINTF(stderr, STR("Error: File \"%") PRI_CHAR STR("\" encountered an I/O error!\n"), file_description);
+               fflush(stderr);
+               success = false;
+       }
+
+       /* Close the input file */
+       if(file_name)
+       {
+               fclose(input);
+       }
+
+       return success;
+}
+
+/*
+ * Main function
+ */
+static int mhash384_main(int argc, CHAR_T* argv[])
+{
+#ifdef _WIN32
+       _setmode(_fileno(stdout), _O_U8TEXT);
+       _setmode(_fileno(stderr), _O_U8TEXT);
+       _setmode(_fileno(stdin ), _O_BINARY);
+#endif /*_WIN32*/
+
+       /* Parse all command-line options */
+       bool keep_going = false, short_format = false, lower_case= false, benchmark = false, success = false;
+       int arg_offset = 1;
+       const opmode_t mode = parse_options(arg_offset, argc, argv, keep_going, short_format, lower_case, benchmark);
+       if(mode == MODE_UNKNOWN)
+       {
+               return EXIT_FAILURE;
+       }
+
+       /* Remember startup time */
+       const clock_t time_start = benchmark ? clock() : 0U;
+
+       /* Select mode of operation */
+       switch(mode)
+       {
+       case MODE_MANPAGE:
+               /* Print help screen and exit* */
+               print_manpage(argv[0U]);
+               success = true;
+               break;
+
+       case MODE_VERSION:
+               /* Print program version and exit */
+               print_version();
+               success = true;
+               break;
+
+       case MODE_SELFTEST:
+               /* Run the self-test */
+               print_logo();
+               success = self_test(keep_going, lower_case);
+               break;
+
+       case MODE_STRESS:
+               /* Enable stress-test mode*/
+               print_logo();
+               success = stress_test((arg_offset < argc) ? argv[arg_offset] : NULL, keep_going, lower_case);
+               break;
+
+       default:
+               /* Process all input files */
+               if(arg_offset < argc)
+               {
+                       while(arg_offset < argc)
+                       {
+                               if(process_file(argv[arg_offset++], short_format, lower_case))
+                               {
+                                       success = true;
+                               }
+                               else if(!keep_going)
+                               {
+                                       success = false;
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       success = process_file(NULL, short_format, lower_case); /*stdin*/
+               }
+       }
+
+       /* Print total time */
+       if(benchmark && ((mode == MODE_DEFAULT) || ((mode >= MODE_SELFTEST) && (mode <= MODE_STRESS))))
+       {
+               const clock_t total_time = clock() - time_start;
+               FPRINTF(stderr, STR("Operation took %.1f second(s).\n"), total_time / ((double)CLOCKS_PER_SEC));
+       }
+
+       /* Completed */
+       return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+/*
+ * Global exception handler
+ */
+static int _main_(int argc, CHAR_T* argv[])
+{
+#ifdef NDEBUG
+       try
+       {
+               return mhash384_main(argc, argv);
+       }
+       catch (std::exception& ex)
+       {
+               FPRINTF(stderr, STR("\nEXCEPTION: %") PRI_char STR("\n"), ex.what());
+               FORCE_EXIT(-1);
+       }
+       catch (const char *const ex)
+       {
+               FPRINTF(stderr, STR("\nEXCEPTION: %") PRI_char STR("\n"), ex);
+               FORCE_EXIT(-1);
+       }
+       catch (...)
+       {
+               FPUTS(STR("\nEXCEPTION: An unknown exception has been caught!\n"), stderr);
+               FORCE_EXIT(-1);
+       }
+#else
+       return mhash384_main(argc, argv);
+#endif
+}
+
+/*
+ * Entry point function
+ */
+int EXTRY_POINT(int argc, CHAR_T* argv[])
+{
+#if defined(_WIN32) && !defined(__GNUC__) && defined(NDEBUG)
+       __try
+       {
+               return _main_(argc, argv);
+       }
+       __except(1)
+       {
+               FPUTS(STR("\nEXCEPTION: Unhandeled structured exception caught!\n"), stderr);
+               FORCE_EXIT(-1);
+       }
+#else
+       return _main_(argc, argv);
+#endif
+}
diff --git a/frontend/src/self_test.cpp b/frontend/src/self_test.cpp
new file mode 100644 (file)
index 0000000..7d4f33f
--- /dev/null
@@ -0,0 +1,289 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#include "self_test.h"
+#include "utils.h"
+#include "mhash384.h"
+
+#include <cstring>
+#include <unordered_set>
+#include <array>
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+
+/*
+ * Test-case specification
+ */
+typedef struct _test_case_t
+{
+       uint32_t count;
+       const char *string;
+}
+test_case_t;
+
+/*
+ * Pre-defined test-cases
+ */
+static const test_case_t SELFTEST_INPUT[] =
+{
+       { 0x00000001, "" },
+       { 0x00000001, "abc" },
+       { 0x00000001, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+       { 0x00000001, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+       { 0x000186A0, "aaaaaaaaaa" },
+       { 0x01000000, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" },
+       { 0x00000001, "The quick brown fox jumps over the lazy dog" },
+       { 0x00000001, "The quick brown fox jumps over the lazy cog" },
+       { 0x00000001, "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern" },
+       { 0x00000001, "Frank jagt im komplett verwahrlosten Taxi quer durch Bayern" },
+       { 0x00000001, "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." },
+       { 0x00000001, "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamc0 laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." },
+       { 0x00000000, NULL} /*EOL*/
+};
+
+/*
+ * Expected hash values
+ */
+static const uint8_t SELFTEST_EXPECTED[][MHASH384_SIZE] =
+{
+       { 0xD6, 0x29, 0xCB, 0x37, 0xF7, 0x61, 0x56, 0x62, 0x1E, 0x09, 0xC9, 0x3B, 0x8D, 0x10, 0x29, 0xC5, 0xF0, 0xF7, 0xB7, 0x78, 0xDE, 0x5B, 0xD9, 0x57, 0x82, 0x30, 0x67, 0x3F, 0xE7, 0xFA, 0x4C, 0x45, 0xA2, 0x30, 0x8A, 0xB4, 0xE9, 0xD9, 0x9A, 0xA0, 0xEA, 0x19, 0x4C, 0xBF, 0x62, 0x30, 0xC2, 0x02 },
+       { 0x1D, 0x7B, 0x15, 0x93, 0xD7, 0xAA, 0x4D, 0xD7, 0xDC, 0x8D, 0xA6, 0xD6, 0xBD, 0x59, 0x1D, 0x8B, 0x50, 0x7C, 0xA5, 0x14, 0xE1, 0xC7, 0xEC, 0x37, 0xF4, 0x3E, 0x78, 0xDD, 0x6B, 0x83, 0x25, 0x3C, 0x35, 0x54, 0x03, 0xF6, 0x10, 0x09, 0x58, 0x28, 0x90, 0x48, 0x0C, 0x4C, 0xD5, 0x27, 0xF4, 0x05 },
+       { 0x9B, 0x98, 0xCE, 0x4C, 0x3F, 0x4E, 0xA9, 0x01, 0x8E, 0x1E, 0xD3, 0x03, 0x47, 0x17, 0xE3, 0xE5, 0xD8, 0xDA, 0x20, 0xAB, 0x37, 0x5B, 0xAF, 0xE3, 0x72, 0xD0, 0x77, 0x80, 0xFF, 0xDE, 0xFD, 0xA3, 0x2B, 0xA3, 0xC8, 0x22, 0x15, 0x5E, 0x28, 0x83, 0xE3, 0x33, 0xAF, 0xCA, 0xAE, 0xAF, 0xA6, 0x14 },
+       { 0x45, 0x41, 0x6D, 0x1F, 0xFD, 0x44, 0xD3, 0x94, 0x0C, 0x5A, 0xF5, 0xB4, 0x25, 0xB5, 0xDA, 0x07, 0xFD, 0x8C, 0x06, 0xBA, 0xB7, 0xC5, 0x8C, 0xD1, 0x33, 0x89, 0xBC, 0x28, 0x46, 0x50, 0xED, 0x60, 0x90, 0xA9, 0xA1, 0x95, 0x2C, 0x29, 0xFE, 0xB1, 0xB2, 0xC6, 0xAF, 0xBF, 0x5F, 0x99, 0x61, 0x08 },
+       { 0x20, 0x77, 0x4C, 0x57, 0x0A, 0xE2, 0xE6, 0xA4, 0x9A, 0x01, 0xDA, 0xE9, 0x48, 0x67, 0x2A, 0xE9, 0x4D, 0x46, 0x5D, 0x91, 0x67, 0x13, 0x0F, 0xE8, 0x7B, 0xF2, 0x41, 0x48, 0x64, 0x9C, 0xF1, 0x21, 0xE8, 0xA5, 0x07, 0x59, 0x50, 0x7B, 0xF9, 0x71, 0x34, 0xF0, 0xD2, 0x8C, 0xEE, 0x91, 0xDC, 0xA2 },
+       { 0xC1, 0x88, 0x43, 0xD4, 0xDD, 0x9E, 0x04, 0x79, 0xD3, 0x8A, 0x55, 0xE8, 0xC7, 0x5E, 0x22, 0x01, 0xF0, 0xE9, 0x3B, 0x6E, 0xF1, 0xF9, 0x16, 0xEB, 0xAF, 0x3C, 0x40, 0x74, 0xD1, 0x88, 0x94, 0x5C, 0x7B, 0x96, 0x57, 0xF4, 0x52, 0x69, 0xA1, 0xDA, 0xAB, 0x4A, 0x8F, 0xB6, 0xF6, 0x3D, 0x0B, 0xEE },
+       { 0xE2, 0x90, 0x1E, 0xDB, 0x76, 0xAA, 0x83, 0xF2, 0xD5, 0x2F, 0xEA, 0x9A, 0x34, 0xEB, 0x2B, 0xC0, 0x5E, 0xDF, 0xA9, 0x57, 0x1C, 0x81, 0x26, 0x20, 0x24, 0x5B, 0xBE, 0xBA, 0x95, 0xFA, 0x2D, 0x82, 0xCB, 0xB5, 0xBA, 0xD9, 0x3E, 0xB6, 0x4D, 0x4B, 0x72, 0xB4, 0x66, 0x35, 0xD5, 0x65, 0x40, 0x0B },
+       { 0x8B, 0x81, 0xCD, 0x9C, 0x1D, 0xEE, 0x8B, 0xCC, 0x64, 0x2F, 0x8B, 0x1E, 0xA9, 0x82, 0xCE, 0x79, 0xD1, 0x5F, 0x50, 0xE6, 0x69, 0x39, 0xFF, 0x34, 0x29, 0x4E, 0x63, 0xD9, 0x3A, 0xE3, 0xC6, 0x10, 0xF9, 0x46, 0x4F, 0xEF, 0xEF, 0x30, 0x29, 0x74, 0x09, 0xB6, 0x22, 0x31, 0xF0, 0x28, 0xAB, 0xC0 },
+       { 0xA5, 0x45, 0xE6, 0x31, 0x9F, 0x6A, 0xCE, 0x0C, 0xEF, 0x62, 0xBC, 0xAA, 0xF5, 0xD4, 0x88, 0x85, 0x87, 0x51, 0xB9, 0x6C, 0x2A, 0x48, 0x8D, 0x5B, 0xE6, 0xEC, 0x63, 0xD5, 0x00, 0x06, 0xC9, 0xD5, 0x4D, 0xAD, 0x66, 0x16, 0x84, 0x88, 0xF0, 0x3B, 0x4A, 0x86, 0x8D, 0x3B, 0xA6, 0x10, 0xCC, 0xF8 },
+       { 0x2B, 0xEC, 0xB8, 0x9D, 0xD5, 0x5F, 0xC9, 0xF2, 0xF3, 0x38, 0x4D, 0xF6, 0x1D, 0x62, 0x40, 0xDD, 0xA5, 0x4F, 0xC2, 0x75, 0xD1, 0x86, 0xA4, 0x5A, 0x88, 0x3C, 0x03, 0xAA, 0x87, 0x3D, 0xDA, 0xF4, 0xFA, 0xD4, 0x74, 0x42, 0x12, 0xB9, 0x2D, 0x26, 0x05, 0x4B, 0x92, 0x85, 0x2D, 0xEA, 0x5F, 0x1D },
+       { 0x62, 0x83, 0xCE, 0x91, 0xDA, 0x8A, 0xF5, 0x09, 0x1C, 0x7B, 0x06, 0xE1, 0x35, 0x2D, 0xC9, 0x47, 0xB9, 0xE3, 0xB8, 0x96, 0x14, 0x80, 0x7C, 0x04, 0xC4, 0x3D, 0xA3, 0x22, 0x32, 0x1F, 0xBA, 0xDA, 0xD3, 0xCC, 0xCA, 0xBE, 0xCB, 0x5C, 0x1B, 0x1B, 0x26, 0x54, 0x32, 0xA6, 0x03, 0x91, 0x21, 0xE1 },
+       { 0x5D, 0xCB, 0x7C, 0x4B, 0x27, 0xBA, 0x84, 0x16, 0x88, 0xFB, 0x6A, 0x86, 0x0E, 0x97, 0xA4, 0x52, 0x56, 0x91, 0x75, 0x33, 0xF6, 0x34, 0x48, 0xCF, 0x66, 0x67, 0x81, 0xEA, 0x4B, 0x5F, 0xAB, 0x20, 0xE1, 0xC7, 0x46, 0xC8, 0x82, 0x10, 0x99, 0xA9, 0x15, 0x22, 0x2E, 0x0D, 0x77, 0x62, 0x40, 0x98 }
+};
+
+/*
+ * Hash function helper class for std::unordered_set
+ */
+struct KeyHasher
+{
+       std::size_t operator()(const std::array<std::uint8_t,MHASH384_SIZE> &key) const
+       {
+               if(key.size() >= sizeof(std::size_t))
+               {
+                       return *reinterpret_cast<const size_t*>(key.data());
+               }
+               else if(key.size() >= sizeof(uint32_t))
+               {
+                       return *reinterpret_cast<const uint32_t*>(key.data());
+               }
+               else if(key.size() >= sizeof(uint16_t))
+               {
+                       return *reinterpret_cast<const uint16_t*>(key.data());
+               }
+               else
+               {
+                       return (key.size() > 0U) ? key[0U] : 0U;
+               }
+       }
+};
+
+/*
+ * Comparison function helper class for std::unordered_set
+ */
+struct KeyEqualTo
+{
+       bool operator()(const std::array<std::uint8_t,MHASH384_SIZE> &a, const std::array<std::uint8_t,MHASH384_SIZE> &b) const
+       {
+               if (a.size() == b.size())
+               {
+                       return (memcmp(a.data(), b.data(), a.size()) == 0);
+               }
+               return false;
+       }
+};
+
+/*
+ * Unordered set of hash values
+ */
+typedef std::unordered_set<std::array<std::uint8_t,MHASH384_SIZE>, KeyHasher, KeyEqualTo> UnorderedHashSet;
+typedef UnorderedHashSet::iterator HashSetIter;
+
+/*
+ * Compute hash and compare against reference
+ */
+static bool test_string(const uint32_t count, const char *const text, const uint8_t *const expected, const bool lower_case)
+{
+       MHash384 mhash384;
+       for(uint32_t i = 0U; i < count; ++i)
+       {
+               mhash384.update(text);
+       }
+
+       const uint8_t *const digest = mhash384.finish();
+       const bool success = (!memcmp(digest, expected, MHASH384_SIZE));
+
+       const std::string digest_hexstr = bytes_to_hex(digest, MHASH384_SIZE, lower_case);
+       const CHAR_T *const result = success ? STR("OK") : STR("Error!");
+       FPRINTF(stderr, STR("%") PRI_char STR(" - %") PRI_CHAR STR("\n"), digest_hexstr.c_str(), result);
+       
+       fflush(stderr);
+       return success;
+}
+
+/*
+ * Compute hash and append to hashset
+ */
+static bool append_string(UnorderedHashSet &hash_set, std::vector<std::array<uint64_t,256U>> &stats, const char *const text, const bool lower_case)
+{
+       std::array<uint8_t, MHASH384_SIZE> digest;
+       mhash384_get(digest.data(), reinterpret_cast<const uint8_t*>(text), strlen(text));
+
+       const std::string digest_hexstr = bytes_to_hex(digest.data(), MHASH384_SIZE, lower_case);
+       FPRINTF(stderr, STR("%") PRI_char STR("\n"), digest_hexstr.c_str());
+       
+       for(size_t i = 0U; i < MHASH384_SIZE; ++i)
+       {
+               stats[i][digest[i]]++;
+       }
+
+       std::pair<HashSetIter, bool> result = hash_set.insert(digest);
+       if(!result.second)
+       {
+               FPRINTF(stderr, STR("Collision detected: \"%") PRI_char STR("\"\n"), text);
+       }
+       
+       fflush(stderr);
+       return result.second;
+}
+
+/*
+ * Self-testing routine
+ */
+bool self_test(const bool keep_going, const bool lower_case)
+{
+       bool success = true;
+       for(size_t i = 0U; SELFTEST_INPUT[i].count > 0U; ++i)
+       {
+               if(!test_string(SELFTEST_INPUT[i].count, SELFTEST_INPUT[i].string, SELFTEST_EXPECTED[i], lower_case))
+               {
+                       success = false;
+                       if(!keep_going)
+                       {
+                               break; /*failure*/
+                       }
+               }
+       }
+
+       if(success)
+       {
+               FPUTS(STR("\nSelf-test completed successfully :-)\n"), stderr);
+       }
+       else
+       {
+               FPUTS(STR("\nError: Self-test has failed! :-(\n"), stderr);
+       }
+
+       return success;
+}
+
+/*
+ * Stress-testing routine
+ */
+bool stress_test(const CHAR_T *const file_name, const bool keep_going, const bool lower_case)
+{
+       std::ifstream infile;
+       if(file_name)
+       {
+               infile.open(file_name);
+       }
+
+       std::istream &instream = file_name ? infile : std::cin;
+       if(!instream.good())
+       {
+               FPUTS(STR("Error: Failed to open input file for reading!\n"), stderr);
+               return false;
+       }
+
+       std::vector<std::array<uint64_t,256U>> stats(MHASH384_SIZE);
+       for(size_t i = 0U; i < MHASH384_SIZE; ++i)
+       {
+               stats[i].fill(0U);
+       }
+
+       bool success = true;
+       UnorderedHashSet hash_set;
+       std::string line;
+
+       while(instream.good())
+       {
+               std::getline(instream, line);
+               if(!instream.fail()) 
+               {
+                       //FPRINTF(stderr, STR("\"%") PRI_char STR("\"\n"), line.c_str());
+                       if(!append_string(hash_set, stats, line.c_str(), lower_case))
+                       {
+                               success = false;
+                               if(!keep_going)
+                               {
+                                       break; /*collison*/
+                               }
+                       }
+               }
+       }
+
+       FPUTS(STR("\n[STATS]\n"), stderr);
+       for(size_t i = 0U; i < MHASH384_SIZE; ++i)
+       {
+               uint64_t min_value = UINT64_MAX;
+               uint64_t max_value = 0U;
+               for(size_t j = 0U; j < 256U; ++j)
+               {
+                       min_value = std::min(min_value, stats[i][j]);
+                       max_value = std::max(max_value, stats[i][j]);
+               }
+               const double ratio = (max_value > 0U) ? min_value / static_cast<double>(max_value): 0.0;
+               FPRINTF(stderr, STR("%02u: %06") STR(PRIu64) STR(" <-> %06") STR(PRIu64) STR(" [%.2f]"), static_cast<unsigned int>(i), min_value, max_value, ratio);
+               FPUTS(((i % 3U) == 2U) ? STR("\n") : STR("  "), stderr);
+       }
+
+       if(success)
+       {
+               if(instream.eof() && (!instream.bad()))
+               {
+                       FPRINTF(stderr, STR("\nStress-test completed successfully. [%") STR(PRIu64) STR("]\n"), static_cast<uint64_t>(hash_set.size()));
+               }
+               else
+               {
+                       FPUTS(STR("\nError: File read error has occurred!\n"), stderr);
+                       success = false;
+               }
+       }
+       else
+       {
+               FPRINTF(stderr, STR("\nStress-test ended *with* collision! [%") STR(PRIu64) STR("]\n"), static_cast<uint64_t>(hash_set.size()));
+       }
+       
+       if(file_name && infile.is_open())
+       {
+               infile.close();
+       }
+
+       return success;
+}
diff --git a/frontend/src/self_test.h b/frontend/src/self_test.h
new file mode 100644 (file)
index 0000000..213b9ba
--- /dev/null
@@ -0,0 +1,29 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#ifndef INC_MHASH384_SELF_TEST_H
+#define INC_MHASH384_SELF_TEST_H
+
+#include "common.h"
+
+bool self_test(const bool keep_going, const bool lower_case);
+bool stress_test(const CHAR_T *const file_name, const bool keep_going, const bool lower_case);
+
+#endif /*INC_MHASH384_SELF_TEST_H*/
diff --git a/frontend/src/sys_info.h b/frontend/src/sys_info.h
new file mode 100644 (file)
index 0000000..61b58d5
--- /dev/null
@@ -0,0 +1,97 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#ifndef INC_MHASH384_SYSINFO_H
+#define INC_MHASH384_SYSINFO_H
+
+/*
+ * Detect operating system
+ */
+#if defined(_WIN32)
+#      define SYSTEM_NAME "Win"
+#elif defined(__CYGWIN__)
+#      define SYSTEM_NAME "Cygwin"
+#elif defined(__linux__)
+#      define SYSTEM_NAME "Linux"
+#else
+#      error Unknonw platform!
+#endif
+
+/*
+ * Detect CPU architecture
+ */
+#if defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__amd64)
+#      define SYSTEM_ARCH "x64"
+#elif defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(__X86__) || defined(_X86_)
+#      define SYSTEM_ARCH "x86"
+#elif defined(_M_ARM) || defined(__arm__) || defined(__arm) || defined(_ARM)
+#      define SYSTEM_ARCH "ARM"
+#elif defined(_M_ARM64) || defined(__aarch64__)
+#      define SYSTEM_ARCH "ARM64"
+#elif defined(_M_PPC) || defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC)
+#      define SYSTEM_ARCH "PPC"
+#elif defined(__powerpc64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
+#      define SYSTEM_ARCH "PPC64"
+#else
+#      error Unknonw architecture!
+#endif
+
+/*
+ * Detect compiler and version
+ */
+#if defined(__clang__)
+#      if defined(__llvm__)
+#              define COMPILER_FMT "Clang/LLVM %u.%u.%u"
+#      elif defined(__c2__)
+#              define COMPILER_FMT "Clang/C2 %u.%u.%u"
+#      else
+#              error Unknown Clang-based compiler detected!
+#      endif
+#      define COMPILER_ARG __clang_major__, __clang_minor__, __clang_patchlevel__
+#elif defined(__INTEL_COMPILER)
+#      if defined(__INTEL_COMPILER_UPDATE) && (__INTEL_COMPILER_UPDATE > 0)
+#              define COMPILER_FMT "Intel C++ %u.%02u.%u"
+#              define COMPILER_ARG __INTEL_COMPILER / 100U, (__INTEL_COMPILER % 100U), __INTEL_COMPILER_UPDATE
+#      else
+#              define COMPILER_FMT "Intel C++ %u.%02u"
+#              define COMPILER_ARG __INTEL_COMPILER / 100U, (__INTEL_COMPILER % 100U)
+#      endif
+#elif defined(__GNUC__)
+#      if defined(__MINGW32__)
+#              define COMPILER_FMT "MinGW/GCC %u.%u.%u"
+#      elif defined(__CYGWIN__)
+#              define COMPILER_FMT "Cygwin/GCC %u.%u.%u"
+#      else
+#              define COMPILER_FMT "GCC %u.%u.%u"
+#      endif
+#      define COMPILER_ARG __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__
+#elif defined(_MSC_VER)
+#      if defined(_MSC_BUILD) && (_MSC_BUILD > 0)
+#              define COMPILER_FMT "MSVC++ %u.%02u.%u.%u"
+#              define COMPILER_ARG _MSC_VER / 100U, _MSC_VER % 100U, _MSC_FULL_VER % 1000000U, _MSC_BUILD
+#      else
+#              define COMPILER_FMT "MSVC++ %u.%02u.%u"
+#              define COMPILER_ARG _MSC_VER / 100U, _MSC_VER % 100U, _MSC_FULL_VER % 1000000U
+#      endif
+#else
+#      error Unknonw compiler type!
+#endif
+
+#endif /*INC_MHASH384_SYSINFO_H*/
diff --git a/frontend/src/utils.cpp b/frontend/src/utils.cpp
new file mode 100644 (file)
index 0000000..4089b11
--- /dev/null
@@ -0,0 +1,57 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#include "mhash384.h"
+#include "utils.h"
+
+#include <sstream>
+
+/*
+ * Get base name from path
+ */
+const CHAR_T * get_basename(const CHAR_T *const path)
+{
+       const CHAR_T *basename = path;
+       while(const CHAR_T *const offset = STRPBRK(basename, STR("/\\")))
+       {
+               basename = offset + 1U;
+       }
+       
+       return basename;
+}
+
+/*
+ * Convert byte array to Hex-string
+ */
+std::string bytes_to_hex(const uint8_t *const data, const size_t len, const bool lower_case)
+{
+       static const char *const HEXCHARS_UPR = "0123456789ABCDEF";
+       static const char *const HEXCHARS_LWR = "0123456789abcdef";
+       
+       const char *const hexchars = lower_case ? HEXCHARS_LWR : HEXCHARS_UPR;
+       std::ostringstream result;
+       for(size_t i = 0U; i < len; ++i)
+       {
+               result << hexchars[(data[i] >> 4) & 0x0F];
+               result << hexchars[       data[i] & 0x0F];
+       }
+       
+       return result.str();
+}
diff --git a/frontend/src/utils.h b/frontend/src/utils.h
new file mode 100644 (file)
index 0000000..5e68eb0
--- /dev/null
@@ -0,0 +1,32 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#ifndef INC_MHASH384_UTILS_H
+#define INC_MHASH384_UTILS_H
+
+#include "common.h"
+#include <cstdlib>
+#include <cstdint>
+#include <string>
+
+const CHAR_T * get_basename(const CHAR_T *const path);
+std::string bytes_to_hex(const uint8_t *const data, const size_t len, const bool lower_case);
+
+#endif /*INC_MHASH384_UTILS_H*/
diff --git a/img/mhash384/MHash-384.jpg b/img/mhash384/MHash-384.jpg
new file mode 100644 (file)
index 0000000..9214da4
Binary files /dev/null and b/img/mhash384/MHash-384.jpg differ
diff --git a/libmhash384/LibMHash384.vcxproj b/libmhash384/LibMHash384.vcxproj
new file mode 100644 (file)
index 0000000..5aec411
--- /dev/null
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="include\mhash384.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\mhash384.cpp" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{6B8B0BE1-C9B7-4A2E-926A-7D0378A5A01A}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>LibMHash384</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)include</AdditionalIncludeDirectories>
+      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)include</AdditionalIncludeDirectories>
+      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>Full</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)include</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FloatingPointModel>Fast</FloatingPointModel>
+      <DisableSpecificWarnings>4127</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level4</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>Full</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)include</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FloatingPointModel>Fast</FloatingPointModel>
+      <DisableSpecificWarnings>4127</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/libmhash384/LibMHash384.vcxproj.filters b/libmhash384/LibMHash384.vcxproj.filters
new file mode 100644 (file)
index 0000000..9562583
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="include\mhash384.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\mhash384.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/libmhash384/Makefile b/libmhash384/Makefile
new file mode 100644 (file)
index 0000000..acb7de0
--- /dev/null
@@ -0,0 +1,61 @@
+# -----------------------------------------------
+# OPTIONS
+# -----------------------------------------------
+
+DEBUG ?= 0
+MARCH ?= native
+MTUNE ?= native
+
+# -----------------------------------------------
+# FILES
+# -----------------------------------------------
+
+SRCDIR = src
+OBJDIR = obj
+LIBDIR = lib
+
+SRCFILES = $(wildcard $(SRCDIR)/*.cpp)
+OBJFILES = $(addprefix $(OBJDIR)/,$(patsubst %.cpp,%.o,$(notdir $(SRCFILES))))
+
+ifeq ($(DEBUG),0)
+  LIBNAME = libmhash384-2
+else
+  LIBNAME = libmhash384g-2
+endif
+
+LIBFILE = $(LIBDIR)/$(LIBNAME).a
+
+# -----------------------------------------------
+# FLAGS
+# -----------------------------------------------
+
+CXXFLAGS += -std=gnu++11 -Iinclude
+
+ifeq ($(DEBUG),0)
+  CXXFLAGS += -O3 -DNDEBUG -march=$(MARCH) -mtune=$(MTUNE)
+else
+  CXXFLAGS += -g
+endif
+
+# -----------------------------------------------
+# MAKE RULES
+# -----------------------------------------------
+
+.DELETE_ON_ERROR:
+
+.PHONY: all clean
+
+all: $(LIBFILE)
+
+$(LIBFILE): $(OBJFILES)
+       @mkdir -p $(dir $@)
+       rm -f $@
+       $(AR) rcs $@ $+
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
+       @mkdir -p $(dir $@)
+       $(CXX) $(CXXFLAGS) -o $@ -c $<
+
+clean:
+       rm -rf $(OBJDIR)/*.o
+       rm -rf $(LIBDIR)/*.a
diff --git a/libmhash384/include/mhash384.h b/libmhash384/include/mhash384.h
new file mode 100644 (file)
index 0000000..4db88be
--- /dev/null
@@ -0,0 +1,123 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#ifndef INC_MHASH384_H
+#define INC_MHASH384_H
+
+#ifdef __cplusplus
+#include <cstdlib>
+#include <cstdint>
+#include <stdexcept>
+#include <vector>
+#include <string>
+#else
+#include <stdlib.h>
+#include <stdint.h>
+#endif
+
+/*
+ * MHash-384 digest size: 48 bytes
+ */
+#define MHASH384_WORDS 6U
+#define MHASH384_SIZE (sizeof(uint64_t) * MHASH384_WORDS)
+
+/*
+ * Enable "extern C" on C++ compilers
+ */
+#ifdef __cplusplus
+#define MHASH384_API extern "C"
+#else
+#define MHASH384_API
+#endif
+
+/*
+ * Context for hash computation: 384-bit status + 8-bit counter
+ */
+typedef struct _mhash_384_t
+{
+       uint8_t rnd;
+       uint64_t hash[MHASH384_WORDS];
+}
+mhash384_t;
+
+/*
+ * MHash-384 public functions
+ */
+MHASH384_API void mhash384_init   (mhash384_t *const ctx);
+MHASH384_API void mhash384_update (mhash384_t *const ctx, const uint8_t *const data_in, const size_t len);
+MHASH384_API void mhash384_final  (mhash384_t *const ctx, uint8_t *const digest_out);
+MHASH384_API void mhash384_get    (uint8_t *const digest_out, const uint8_t *const data_in, const size_t len);
+MHASH384_API void mhash384_version(uint16_t *const major, uint16_t *const minor, uint16_t *const patch);
+
+/*
+ * MHash384 wrapper class for C++
+ */
+#ifdef __cplusplus
+class MHash384
+{
+public:
+       MHash384(void) : finished(false)
+       {
+               ::mhash384_init(&ctx);
+       }
+
+       void update(const std::uint8_t *const data, const size_t len)
+       {
+               if(finished)
+               {
+                       throw new std::logic_error("Hash computation is finished. Must call reset() first!");
+               }
+               ::mhash384_update(&ctx, data, len);
+       }
+
+       void update(const std::vector<std::uint8_t> &data)
+       {
+               update(data.data(), data.size());
+       }
+
+       void update(const std::string &text)
+       {
+               update(reinterpret_cast<const std::uint8_t*>(text.c_str()), text.length());
+       }
+
+       const std::uint8_t *finish(void)
+       {
+               if(!finished)
+               {
+                       ::mhash384_final(&ctx, digest);
+                       finished = true;
+               }
+               return digest;
+       }
+
+       void reset(void)
+       {
+               ::mhash384_init(&ctx);
+               finished = false;
+       }
+
+protected:
+       ::mhash384_t ctx;
+       std::uint8_t digest[MHASH384_SIZE];
+       bool finished;
+};
+#endif /*__cplusplus*/
+
+#endif /*INC_MHASH384_H*/
diff --git a/libmhash384/src/mhash384.cpp b/libmhash384/src/mhash384.cpp
new file mode 100644 (file)
index 0000000..b824b78
--- /dev/null
@@ -0,0 +1,959 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+#include "mhash384.h"
+#include <memory.h>
+
+/*
+ * Version info
+ */
+#define MHASH384_VERSION_MAJOR 2
+#define MHASH384_VERSION_MINOR 0
+#define MHASH384_VERSION_PATCH 0
+
+/*
+ * C/C++ compiler support
+ */
+#if defined(__GNUC__) || defined(__clang__)
+#      define ALWAYS_INLINE __attribute__((always_inline)) inline
+#elif defined(_MSC_VER)
+#      define ALWAYS_INLINE __forceinline
+#else
+#      define ALWAYS_INLINE inline
+#endif
+
+/*
+ * Types
+ */
+typedef uint64_t ui64_t;
+typedef uint32_t ui32_t;
+typedef uint16_t ui16_t;
+typedef uint8_t  byte_t;
+
+/*
+ * Const
+ */
+static const ui64_t KMUL = 0x9DDFEA08EB382D69;
+
+/* Table INI
+ * 48 byte initialization vector containing the first 384 bits of the number PI
+ */
+static const ui64_t MHASH384_INI[MHASH384_WORDS] =
+{
+       0x243F6A8885A308D3, 0x13198A2E03707344, 0xA4093822299F31D0,
+       0x082EFA98EC4E6C89, 0x452821E638D01377, 0xBE5466CF34E90C6C
+};
+
+/* Table XOR
+ * 257x48 byte matrix containing pre-computed 384-bit words with HamD(a,b) >= 182 for each possible pair (a,b) with a != b
+ */
+static const ui64_t MHASH384_XOR[257U][MHASH384_WORDS] =
+{
+       { 0x01DCDF00414B3037, 0xB1B3AF661B8E96F8, 0x944D2873DB393121, 0x73DA9A36662AE755, 0x1F4F318C4ECB56B1, 0xF09743D99C2AA5BC }, /*00*/
+       { 0xA81FBBC6CBBFC954, 0x39DE43648959EDDB, 0x1A641A0BDA01822F, 0xB52E607266932658, 0x2C5B1731AC802084, 0xC2EF10671FC79DD4 }, /*01*/
+       { 0xCF2A8D8E08810046, 0x8B7E9B2089E268F6, 0x930461652C5D2DEC, 0xF096E42223BFC8B9, 0x8DD338964CFE0970, 0x269C342F7CEC60BD }, /*02*/
+       { 0xB970A920D2ED0552, 0x010F894A254DA7E1, 0x8D5F205F9D1A40D8, 0x50C33DCCC3FD5F58, 0xB49F31BDE7D82C57, 0x7CDE04F62A959033 }, /*03*/
+       { 0x49FAB2822B9C84AC, 0x34B8648CD68CBEF1, 0xE5121147BB4126DE, 0xC0B31F54B2FFE00F, 0x2F193DA38E8CC632, 0x058C984B429B8AFC }, /*04*/
+       { 0xE07F9DA44D8C9942, 0xBE2AF9B39ACA65F2, 0x5D3D8FB1466DC295, 0xC0051E3EC3F962C7, 0xF8FDC3CCD4CE2BB6, 0x9024C0EFC6199937 }, /*05*/
+       { 0xA3111377EF01F5EF, 0x31F59B366C02A3FF, 0x61B82949760D16DC, 0xF6B958AF92BD3BDF, 0x7297AAEFEC69C0B2, 0xFE8A50AD9E8684CD }, /*06*/
+       { 0x3D3DD0C829EA9AA0, 0x3E77597EEC96C7A3, 0x8FD038231E7F1684, 0x64617B131FB7EDE0, 0x85C99CE4C5405874, 0xA58735D41F19C5E3 }, /*07*/
+       { 0x8028628ACAF91B9A, 0x194A640538C97064, 0x04A15E018A4F1680, 0xF4BE1B04C2360955, 0xDFB24D4CEF581A20, 0x3C59D0A0FD15879D }, /*08*/
+       { 0x88F8E2ECE78AF1BC, 0xB46B6E22297364C2, 0x9339F17F926B99F3, 0x31293489B3B8F07C, 0x3909CE1649C9BCF1, 0x0C46103BFA31BCE9 }, /*09*/
+       { 0x4D1A0B8CC7EFE2A9, 0xAFD7878CAD55E871, 0xC89CFBC858CF4153, 0xC4739486C74F75D6, 0x0BF7192C130AC9F2, 0x0084F2BC5E81BD9A }, /*0A*/
+       { 0x4AFBE975014FCACF, 0x41DEAF8CFACC41E4, 0x3C1EC23B53ED16E9, 0x78B06EB30F1C3248, 0xDD11165D04285C72, 0x6546D9B5609491E4 }, /*0B*/
+       { 0xFFD1E2E04DC8D260, 0x07B186948A74ECCE, 0xB5120E45121AC531, 0xBD0BC86330810C85, 0xDE93AFDDDB487730, 0x78DEB0DE6EB99196 }, /*0C*/
+       { 0x79BAA2AC3FDEBA55, 0xB1B7E3E1C92A567E, 0xA53F69AB4A5B0794, 0xF0DA7499954F6DDD, 0x58117C89E1132248, 0xD95DF5F794C51A6E }, /*0D*/
+       { 0x89BC8A0C65091C33, 0xB04EEAEE063135C2, 0xF53267E04AB6E689, 0xB4C579B7207E8BF2, 0x3FD31E51343CD2DF, 0x119E523E2F8197FE }, /*0E*/
+       { 0x2E10CB1C6060F32D, 0xBC92E732A94E6B63, 0xF3220D831FD04267, 0x502C5F7414BCE87F, 0x89E0651DE91D2457, 0x759E56B04482D915 }, /*0F*/
+       { 0x43AEE32C6A84E803, 0x0C5007202C0BD7E3, 0xB4F464474205D32A, 0x7D17FC95DE386C06, 0xE8DFBF64567AA545, 0x55BD889D5853046F }, /*10*/
+       { 0x687ABE14EAB8DA27, 0x397B3AB50D72C344, 0x505EAA6D1FDE618D, 0x61BE79865DA13F69, 0x17BBAB29B5E90E2D, 0x010C921972FA8B2F }, /*11*/
+       { 0x8B7223A4F56FF453, 0x291B7B5CB98B6FE1, 0xFD421625786FBF7D, 0xE33D1020D0E8CDC8, 0xCA530C708B739E87, 0x878AF1F304B8A12F }, /*12*/
+       { 0x7ECE1F24E56DD711, 0x2E0869241B2FA6DF, 0x84B834DCC459B2FD, 0xE022EDA6319E7D3B, 0x59839D8CA03C9928, 0x644790F491BBC774 }, /*13*/
+       { 0xCBDC6F49E6B0DD0D, 0x44BA2F8D00346732, 0x86BCC821586AE61C, 0xC7B7491285CEE55B, 0xED3912FFD97F3851, 0xF4AF0186BEBEBCBF }, /*14*/
+       { 0xCA8A48E54ECCE516, 0xBEDF1864B7F8F506, 0xD56A1F60A4B36AA4, 0x49B25AB5FE0DD9D9, 0x21377DBB5E49FCE1, 0x708F64F5D59D99E7 }, /*15*/
+       { 0xE9F873A569AFE02C, 0xDA66BC05CA997390, 0x8C88174756D35385, 0xEAAAF16CF4FDA730, 0xB39F7A55653A3512, 0xF10AB727BC23E852 }, /*16*/
+       { 0x93E96FF8C5BBE2AF, 0xA47785420253E97C, 0x704B25D1F77D074C, 0xC0B2093F1470559C, 0x8D5BFDD4E364AACF, 0x550518673F5B1BF7 }, /*17*/
+       { 0x8DAC832E5BE81ACB, 0x588BFB202B7583D8, 0xA34D8A70DFD1D7E4, 0xD03B0627B687033E, 0xE3D0BE7EDBDC75CF, 0x818EE8C5B09F8BEA }, /*18*/
+       { 0x8E3B02E1489D7D31, 0x5336752B64E3B532, 0xE4D4CC795C580A65, 0x6DAB08F313ED767E, 0x8E567E88FDBA36BF, 0x259490F1D8E933D0 }, /*19*/
+       { 0xEAB437D0D62CAA62, 0xC090AD28B982B003, 0xE255D768D25704EC, 0xA048511AF6256A43, 0xE79F078F4D498B5F, 0xC41735FB75B357FE }, /*1A*/
+       { 0x70DA9FC3504FF29D, 0xB9AB1F388673FF25, 0x36922F4CD17357BA, 0xF09C3AB292E7E04A, 0x90CE0BC3D9BA13EC, 0x647C4CA63C918DE3 }, /*1B*/
+       { 0xD834A38DD1ECD688, 0xA97A0020DE46AB6A, 0x9CDEC7F6E62EA71F, 0x288A5A6FD74DC47E, 0xD44A2E2765CE50F1, 0xBB9B50B5DB9E4F3C }, /*1C*/
+       { 0xC66DA90E41DDF2E6, 0x5A3FE86F160C5C09, 0x6F6AF0405108CCBE, 0xF938382EB627FC7F, 0x163DD634617F006C, 0x5184B1FEDC908497 }, /*1D*/
+       { 0xC95719ED07FCB21C, 0x5112DF043F6EE7EB, 0x50F9FD60012334CE, 0x589FA85104D96579, 0xB7129E44D71905A7, 0x3314766E0733528D }, /*1E*/
+       { 0xDC6C8014C5457CB8, 0xD635FDCD286A69B6, 0xD66F232CE27D01BF, 0x56AF4AC0F682EC0F, 0x57DF1D55B64328F5, 0x651ED4C52A87CACA }, /*1F*/
+       { 0x26D9D1CC79EEC502, 0x69BF340A34B1EBFE, 0xFAA5AAAC8E397174, 0xD0A8F9BD426BCF6F, 0x5B131F464D6D2452, 0x122DD15660D0D6DA }, /*20*/
+       { 0x6E389AEC5F51A22F, 0x7EF68F1C54C127FB, 0x986D4D46E0485C30, 0xF0A47B39E7CF8A31, 0x1D398DFDB7F2A78F, 0x2FC651D1FBB10D2E }, /*21*/
+       { 0xA44E4E8D1B49DCB0, 0x07A4822049C2F343, 0xC40AC04A8D6505BA, 0xD9B91D3F0729B16C, 0xAAF39951B50F9015, 0x966EF5D3AD3F9076 }, /*22*/
+       { 0xEA78CBAC0EB6D009, 0xA0FEA6725A23DEAB, 0xCE729C7444CB94D9, 0x40A994626627AA0D, 0x37F738CDE3D018D5, 0x4C29491C01CDB3C5 }, /*23*/
+       { 0x7C9792AEA745C87A, 0xD1FF5620C5BD8FD4, 0x9ECA84E3004B56B9, 0x5AFD3923C228B1D6, 0xE5DBF79EB3FD283B, 0x441712E354084B9F }, /*24*/
+       { 0xE35D288BD8E249BC, 0x91776C1453A366E5, 0xF5D1E1684E95EFEC, 0x9108E117D7DDF606, 0x81B30F9DA2CE7C8C, 0x6497DBD786818C0D }, /*25*/
+       { 0xC2F891FF45044BE0, 0x75A1A76D2B87E2EB, 0x85CE65798AF3C2BF, 0x213F532B4EFD09DC, 0x0DAA1DF5A53A6C88, 0x3028606A50D826B2 }, /*26*/
+       { 0x609A62616379F33A, 0xA339A3BC53E4516D, 0xD7AD92616A5ADBEC, 0xD043726D86E924AA, 0x8555B564F4C29865, 0x56AA12AB31C1D6B0 }, /*27*/
+       { 0xCED9ED85C1C17BFF, 0xEB522325ACBAFFC2, 0x04D3D8F4B2D15394, 0xD271504C04756EEA, 0x2DDBA4A91AF827F1, 0x1F67D5C28F8002E4 }, /*28*/
+       { 0x8B9C08AD432DC08F, 0x5A7543E29796BBC7, 0x34A6DB5B3C1967DE, 0x016E3BC2A2804EE4, 0x5B9BCACCE5172F75, 0x7549598B80ADBDBA }, /*29*/
+       { 0x6F3FB117C5CDD155, 0x16C3B0A59CD6EEC5, 0xD9A1A411DE538769, 0x938C54979F4AC37C, 0x3737BCC1D55284DB, 0x6CAD9F8AF9156BB7 }, /*2A*/
+       { 0xEBBF284F9C75EBDF, 0xB383EBB406753DE8, 0xAA86127AEE7C403C, 0x10BFDD10523DE027, 0x138BF6C4EB4A8A13, 0xB1EFF67DDB78B067 }, /*2B*/
+       { 0xF6D1138D7AA3DA5E, 0xBAA8098D8FB66371, 0xDAE76D1B8B6CAAF2, 0x400F1034368D1EDC, 0x7C937F5172E8D277, 0x7D05BBF83CADE6EF }, /*2C*/
+       { 0x0E9C2EA6CF34B081, 0x9036B30D58F60BA0, 0xDB3A2C5848F08BCA, 0xC87AD1B94250D564, 0x7C892E09EEF96166, 0x26DB85CF571085F3 }, /*2D*/
+       { 0x251EE3F58718C12A, 0xF9438D81178A2AE4, 0xF0929A889039A8A8, 0xF06B65225EBDCCFD, 0x2E4D14EDF7BF73C6, 0xA9369895BC1DFACF }, /*2E*/
+       { 0xCAE302B41D6979CB, 0xBBFA5A58B51EE623, 0x5113B99DC81AB52F, 0x6093795BEC17A056, 0x8F71FB4D2E5E355E, 0x762F92EDBA34A2F2 }, /*2F*/
+       { 0xD130015265A4D9FF, 0x09BEA253D71F26C8, 0x81B6EAEDC46521E6, 0xFAE268165682B8A9, 0xA89C3EC4774AB623, 0x0D2E45E055219DB2 }, /*30*/
+       { 0x2B560284C3A692AB, 0x37008AD0B379A7B8, 0xAF11CD2C30F90BFC, 0x7FE87A250F2762ED, 0xC3FBD711647242C3, 0x74ED8264F6B322BD }, /*31*/
+       { 0x28195CC8A7AD3943, 0x53CBE808464C4FC4, 0xD58E3D7A765F8726, 0xD83052F60185AA4F, 0xEFCB0D85223BB4E7, 0x5A31305E787FAC28 }, /*32*/
+       { 0x725D0EE230F19543, 0x9091D2C6BDDF34E0, 0xE3BE49C6C2754601, 0x61BE300BA4AD566B, 0x02D79D7551FA7CC1, 0x6543910F5F1CDA58 }, /*33*/
+       { 0x4099ADC44481B43F, 0xFE1361922FD9EB81, 0xA989C09E441FCEAC, 0x449B3A13D3CB9019, 0x45A9BE396F201134, 0xDC1AD05A046633FE }, /*34*/
+       { 0x1A563A6D522F3E69, 0xBE589E079F475A9E, 0x75A2A9638E4C0038, 0xDA3B6202577A0362, 0x211D3F1E0D727AF6, 0x5E1FFC529AD99233 }, /*35*/
+       { 0x47B61E86C6D6D01B, 0x437D6F83ADADC318, 0xD5A361028DED738C, 0xA00D4C630425164B, 0x1A69AFA5AF4C9DD2, 0xF99E1C67F951B582 }, /*36*/
+       { 0xA66A7740B6BDEA79, 0xFEF7FF1496AF80A3, 0x05AFD43EEACD898C, 0xB00C78ED31AD7134, 0x0ED31A1AD7846673, 0x74B96844161499BE }, /*37*/
+       { 0x46FA8D6CCBF6D12E, 0x31C2FC147F303956, 0x707F4401DE5F067F, 0x3AE5FEC7E33594E9, 0x28E39F8A63531714, 0xB7B329EA1E9FCAB2 }, /*38*/
+       { 0xEFD8F755825C7804, 0x1F5A93870BD30CD1, 0xEFBF894671FF8716, 0x28ED617FF22BDA58, 0x411289CCAE5CB62E, 0x95DD42F41801F2F9 }, /*39*/
+       { 0xA8525B8645FC59E1, 0x75E62DC00A5F7F0C, 0x09C56785210416AC, 0x50EF76E9B30D7626, 0x2B3B2CDC19F5D665, 0xA41297CD11D8F4FF }, /*3A*/
+       { 0xEAC99A649EEE5039, 0xA593C92F143C0065, 0xB314735203071206, 0xEA2761A0C764A4EC, 0x02AA7FD46CAC25B3, 0xC68CC182A96D03BF }, /*3B*/
+       { 0xB2873F024EC83CA8, 0x97470AB8FD8853EB, 0x18FE15C159B305BD, 0xB0AB08F687EAEAFD, 0x510A3FDE73602E43, 0x03E1B84DCCF0FCF0 }, /*3C*/
+       { 0xD85BBBDC8033C0D8, 0x9223D9C39CA9F34F, 0x7D3BCB6D5B63C3FD, 0x1C30F974DA0C0FB5, 0x8B24BC9EBEFB5143, 0xC58954925B7B84FC }, /*3D*/
+       { 0x6ABD7C2E0844D7A7, 0xCCF2EA456CDF530D, 0xE8938CF52B3921B8, 0xBA023CA2F281657C, 0xEC635DA675D1EDAE, 0xB4AA52F22EE1BE6C }, /*3E*/
+       { 0x981C3AC677CB5904, 0x6A92B54C84877B49, 0x745BA6BB40C55815, 0xB7AF550D22A371ED, 0xD5E8BD87C65F5374, 0x67874A37F0F538F5 }, /*3F*/
+       { 0xC23BBA2A9DECC021, 0x4E610E930B0E3450, 0x1A681AA91477577E, 0x38A3209714EDC376, 0x0FD15563EEEB4AB6, 0x7D57668A01D42178 }, /*40*/
+       { 0x6AF88CE145A098B5, 0x1AEB858CD88B8B46, 0xE8B733AFB8E2D6E8, 0x313FAA8C10A7EBFA, 0x127D375E77557CEA, 0x96BDA2F70B2F2155 }, /*41*/
+       { 0xEC8903978FAFB636, 0xC7213C425C079763, 0x760384036AB6D17C, 0xE0C63A26385F1F49, 0x299877D6811A6DF5, 0x876F90FC5304B88D }, /*42*/
+       { 0xA6FABBC2D6E0BA16, 0x9B70C9640080E6BC, 0x29B2D5265598B27B, 0x4A9657C726E4397E, 0xA801CCC6766678D5, 0x800EF7CC72619998 }, /*43*/
+       { 0x235931A8CF5490BF, 0xE798F98E0E8F879F, 0xC6EEE29C38F30CA7, 0x929A79F2D53E0024, 0x88F2E12749587A45, 0x0B85B28F38891965 }, /*44*/
+       { 0x165E0303E4A4D827, 0x67994F42D1E8436A, 0xE6CC8BCF6E130D1B, 0x50101711709DDEFC, 0x373BDEC40CD05328, 0x40B274A4AA5109F6 }, /*45*/
+       { 0xA9F88BA008FDF8C8, 0xECC897E3476EE05A, 0xBCE290AB69D57A74, 0xFA44DB1811E3115D, 0x6267AEFD64480C88, 0x2697D04A2D3AECEB }, /*46*/
+       { 0xC0782AF2ABCD3313, 0x02BA1290F2F96273, 0x63C82F1A56ADC2B9, 0x10F8E8C03EFE51C4, 0xE3EB348625CCAFFD, 0x93D607969CB8E7AE }, /*47*/
+       { 0xCC6E179443E58FBC, 0xD21C93C655A7B8EE, 0x2B9834A31F2B8BA4, 0xC83B69516025ECEE, 0x9176EB7B427AAE94, 0x8CB65B9E30B7A76E }, /*48*/
+       { 0xC1A33A0AD6EDD989, 0x18B3C5D95813B5F7, 0xB024BD263B359A8B, 0xC8C17C2216A99B50, 0x71F9A11D58237729, 0x3AA67C7618284290 }, /*49*/
+       { 0x99B7465E09201C7B, 0x9AF89FA01CA4FA81, 0xFC2EC63E761AD123, 0xE2A9A39585B17D14, 0x08394DE529F94E81, 0x479448E69794FAA4 }, /*4A*/
+       { 0x23CA3D1C4CBDCABB, 0xE3265436CE1A37E4, 0x1BBF10F69E8A4CC9, 0x05A66708048F5C4D, 0xE259DCDD9C5BFEFE, 0x439E65FAFD936EFD }, /*4B*/
+       { 0xA24D73B6978F719C, 0x3F53F343CCB0BB8E, 0xBE3C72769EE07C6A, 0xFACB9E539CF558DD, 0x67B91D4E30DE986A, 0x1DB913D11698913A }, /*4C*/
+       { 0x98BD4E140DC3C3C6, 0x142B1592BF3263E8, 0xCDBEAC59ED095B0E, 0x900763F0F625896A, 0xE213550F30324E39, 0x8A13A4417A803195 }, /*4D*/
+       { 0x2ACD98ED8C626073, 0x1CAAA6B4C4CF3238, 0x04DCB41EB677EB5D, 0xF88B5844A8105B68, 0x981D9E951A061A4D, 0xBC9471894C878EDB }, /*4E*/
+       { 0x4959FEAD5D6C2DBD, 0x6ABD59E28C503049, 0x06D2C5494CAF8B34, 0x70E4541304A4293C, 0x520F3416CAF2F503, 0xB23D09D92613DB85 }, /*4F*/
+       { 0x26B5A815C32D1791, 0x2C99E7555BB033C6, 0x09CE9D6A0002514F, 0xD485282B2B8D7997, 0x9C5B792F4A4A14C6, 0x851D9D02DC0BB4E7 }, /*50*/
+       { 0x62FEB6CACFB060EC, 0x9D977D69D5C661EA, 0xBF08EFD806D81556, 0x25F1EEA460EA5718, 0xA25346B51F5A9665, 0xD92F9ADC358CA274 }, /*51*/
+       { 0x27E63DFC63E8FFA6, 0xCDB9CCE2CE99FDA3, 0x979D5B754974830D, 0x3298C8407D6693BE, 0x629D5FADA39B42B7, 0x2654D31271CD84E1 }, /*52*/
+       { 0xAB1FA4DAF66E583C, 0xEEB6B7A236D24766, 0xA90738CDFDF5C6B3, 0x28CBA9E5648E2D4C, 0xFDE5BF6C0CFE0DA3, 0x9D00B863D7D78485 }, /*53*/
+       { 0x75FBBF094EEA16AA, 0x48931F027CD729F2, 0x5D360679009B2E7F, 0xDDFCD148BD3DE21A, 0x4DBFF544B094D0E1, 0x9C0E5C6294352C22 }, /*54*/
+       { 0x283A27FF968853D2, 0xB0960C6CEA0D03F2, 0x172BBA07A473DB38, 0x688C87D296E6F4BB, 0x5CB7E9BC5D68CF0F, 0x57A5D71B0E47BFB4 }, /*55*/
+       { 0xDE0108AAC1E4FF2F, 0xD346CFABEAC62B99, 0xB72E203F98B5F608, 0x81853D8CA54B29BE, 0xA6AED7C89FAA1680, 0xD2093B155C39D7ED }, /*56*/
+       { 0x0BAEAC99D4974B84, 0xC7F258A699C9B4DA, 0x6F622C5E4ACCF5C1, 0x58AB397D9781BEAA, 0xBF811F67E101FFE3, 0xAFBCC2881C3C0EF3 }, /*57*/
+       { 0x26B211FB518D6C3E, 0x64BADAD51A10784A, 0xE6BE4E06A587186C, 0xD471F5C61343CD5C, 0x8389BB0DD6AAED5D, 0xC88112678914A17D }, /*58*/
+       { 0x2B2D0BC3BB88D27D, 0xC5A7D1FAFF517AD2, 0x96F39056A09F82AD, 0xFB38A61A6CED4D4E, 0x9D308E4EA6F9B264, 0x9097CE294AECC6B3 }, /*59*/
+       { 0x8FCA2B950690B1A2, 0x293EFCBF03D422DF, 0x8C9125B3E76353AB, 0x3D402092A1A70173, 0x9BAB974CAB9BF676, 0x5EA8FCC55D8C586E }, /*5A*/
+       { 0x408C92E8C2E1EC8C, 0x4AF4C914B71B4350, 0x5186AEE0CDFB1069, 0x2385EAFAB9657C67, 0xF708E4D3C898CA80, 0x1EC8B9F89884907E }, /*5B*/
+       { 0x46E8958B6A2C1878, 0x2172FD410F78A647, 0x9D8E9DD83A299004, 0x390913C3265AD025, 0xD231F1E23077CBF1, 0xE7EE3E574E80D7F3 }, /*5C*/
+       { 0x5A8567A3D85E40B2, 0x16ECF161133FCF73, 0x52DA5C6FBA3C0DD7, 0x56E57983DEB34BFB, 0x83254FDCB768D153, 0x9A14F95F35C6B82D }, /*5D*/
+       { 0x498A29C6E19D4AE6, 0x2EF4AAF46027BA11, 0xBDBA7DAA84F39505, 0x940B2A04F6DC944D, 0x4E7ED35610FC0D53, 0xBADD94C2907E59E1 }, /*5E*/
+       { 0x14DF0FC43F475F80, 0x17E2AA8D264BF82F, 0x92625BDFE58B934D, 0x8384F415A4ACEA81, 0x8E9C5EAEC5D8642B, 0x4D8EF55F1C826687 }, /*5F*/
+       { 0x4A2335C4F77128D9, 0x544E1476D29ABA94, 0x654EC86321785044, 0xB04AD9B02F80445A, 0xB0E01B6480C8D020, 0x596E325E88A3CBBF }, /*60*/
+       { 0x896955157448D062, 0x0DB08C4C0F236D68, 0x3BA8FC5B3CD1C4A2, 0x04F57C53E144535B, 0xB7D04DCC7BE46840, 0x4BBE993192334646 }, /*61*/
+       { 0x1D7837E6AB02CE27, 0x3EA35BAED4493EA4, 0xD1CAFDB5DF94FABE, 0x98B580BB62170C4F, 0xC3C57A6CA9421C43, 0x68D65FC2C1201634 }, /*62*/
+       { 0xFAEABABC48717536, 0x454251E8F62F7315, 0xB318E8A7FDCDC523, 0x7C2E832013C91344, 0x4D9E5DAFD1699052, 0x12262E8C870537A7 }, /*63*/
+       { 0x8A3E5D0BEF8402A2, 0xA33BC5FAFA019909, 0x63CBE8ACD00762F5, 0xEA26A3F181984178, 0x6EEB78D1BB4AF6BB, 0x7ECF9671300E845F }, /*64*/
+       { 0x0811B67CCCF5D0FC, 0x9F8CAB3F3496BD6B, 0x57CB7D24F1355C2D, 0x58218594165BDE80, 0xFAF3368A653A78F8, 0xC04CD80176267762 }, /*65*/
+       { 0xE6417CE75AAA23B0, 0x34A7BFE3CBA61761, 0x8C13E396F8C9B6ED, 0x5C9066464B09ED63, 0x76CB6A642C5CE283, 0x498E082A3EB449C6 }, /*66*/
+       { 0x6F2ADEA6357B5AA0, 0x54DA382B15557B69, 0x302BD81946237AAE, 0x8F0CBB82111EFEDC, 0x45DD2DADCE20F2D3, 0x8A77A5E9E8A2D1D8 }, /*67*/
+       { 0xE1EC332735862A28, 0x92B68B1A7E9C7C44, 0xF45618DC99E963E3, 0x7CAC984502DD1A73, 0xC8650598CD70840D, 0x9A5DA584A26D4EFD }, /*68*/
+       { 0x16B19B010740C15C, 0xB4544AC01016439A, 0x221F749C9E2F99A5, 0xA63E8A279A65570F, 0xC7231669ADD072AD, 0xC5BC35BA740BC801 }, /*69*/
+       { 0x6C44E75A4F378694, 0xD27ACE108A577647, 0x17C487FAFA7E15D6, 0x6A3654D5C8E29EDF, 0x0CE35EEDCC611FFA, 0xD88A8C03C0095093 }, /*6A*/
+       { 0xCF106948BC4B1F2C, 0x91C0DC9990B99712, 0x193B21E3E109AB32, 0x3340DE0608DD1666, 0x8A5BB677BF602828, 0x402C410B1197B771 }, /*6B*/
+       { 0xEB080FF49CA5543E, 0xB4B9429542D6CA27, 0x5999D45DC1533205, 0xF7EA9E398A1BEF3E, 0xBE8817775476DEC6, 0x17064D7790C84100 }, /*6C*/
+       { 0xF3328E9150A7F8D6, 0x52E3E61B04ACFDF8, 0x51D82010F3CEB015, 0x59D673336676D5D8, 0x4CB3BCEF1D91C342, 0x0C589AB58033BE49 }, /*6D*/
+       { 0x54B8E70EDCE03855, 0x7BB590E99687FD57, 0x6CFF08688D2B1FDD, 0xFD0F6D068BFE994F, 0xEB9BCE302489AE44, 0x66B21F200661E3E4 }, /*6E*/
+       { 0x2F5E0060189669AD, 0x473AF1D03C00CAE4, 0x0278299268D1F3B4, 0x888714BC3A7EC9D2, 0x9FF9C7F071EBD2D9, 0x875A5DC25DFFDB10 }, /*6F*/
+       { 0xE2A97A3E468399D8, 0x3BF7EACA32C80DA1, 0x13DCAC8EB6C2231D, 0x227EC90E1102EE97, 0xB2344832F0381434, 0x8613888303B190EB }, /*70*/
+       { 0x3A3D3B6CE026BFFE, 0x18D4953B9A68ED59, 0x24BB7B574AB777A0, 0xE0CB7DD64983DCB1, 0xCF768C439869AC97, 0x8062BC7A900E6033 }, /*71*/
+       { 0x39D4C3B78A7A33C7, 0x43D72EF22AB0B4EB, 0x54AE8184DDA50394, 0x0C2A7DA083C38536, 0x9DBC6F921D4AD822, 0x2CBB61FE182EAA42 }, /*72*/
+       { 0xD8CE9A806C0BD24D, 0xF69D65A65845727C, 0xC3FF81CC76F2B048, 0x76B1FDC3CA67CE58, 0xCED0970AFBCBE78A, 0x57502941B726F5F3 }, /*73*/
+       { 0xE006AEC17FCEFCF9, 0x05CAA1629E003591, 0xB7050CC99F585312, 0x669260401E159490, 0x8442D25AA757CC5A, 0x228655CD4038770C }, /*74*/
+       { 0x93EE8D67D3F1F3A1, 0xBEA46D48DBF8D7F4, 0x3C91F02B8646453C, 0x6C3D7C1F04188A58, 0xEFA97287F89CEF84, 0xCB40364E108BFF4B }, /*75*/
+       { 0xC6DCE3730D4FF825, 0x02AF54F87D972790, 0x7D69D20F6F4F788F, 0x90C255C64C166E8F, 0xA3529FBF4BF9C9A2, 0x3ECEC41136694F6B }, /*76*/
+       { 0x3DE10A5EC6CA7B3F, 0x7E196081D085ACAA, 0xDF5F0DE3705D60F7, 0x393E7C83DCC57075, 0xA5F33BC2DCB98F97, 0x0AEB7F050D1204C0 }, /*77*/
+       { 0x6F3B3B3D11A8BC05, 0xB52269AB2B95B8DC, 0x12EDE24EB1385F13, 0x202BBA6B5836B5E1, 0xEE3636C5925ACC49, 0x42224CF6EEB509BF }, /*78*/
+       { 0x5F0CC3BBC4BE9A92, 0x584313FCCC54DD2E, 0xC11FE90F00394036, 0x3371667C72FC9723, 0x9611990B62AC8D9F, 0x4CFCB9EB3C317FAD }, /*79*/
+       { 0xCA8E520A894A3FBA, 0xBD9ED1B80098CC40, 0xBDF24507DFF3757C, 0x47AEC572E68D35EC, 0xF3D4523D27B373E4, 0x1AB11E16973A05AB }, /*7A*/
+       { 0xFFC293A6C26B817D, 0x2C9E9D134959D828, 0x7FA5216408199BBF, 0xA6F002DE0DCCD861, 0xBE8F9DC57F2CF35D, 0x1352E2DF86A47647 }, /*7B*/
+       { 0x84B55BE101708E74, 0x3ADEC53721209F3E, 0xB18F9A1E68DFADBD, 0x09A050819774CF2D, 0xE4AB295D380A8762, 0xA3605B0C689C239F }, /*7C*/
+       { 0xDDC7031FBFDFFE8F, 0x0B175DE65B832F0A, 0x31162ABC65719685, 0x51215E534BBC36B1, 0x9F2F7D3B5D01AE44, 0xCF43A2426E83B61B }, /*7D*/
+       { 0x7E32DB672B16F04A, 0xCE6F45DE0E6AB788, 0x25718548B8E70B41, 0xD7368BCF39A0FAC4, 0x956863EC49880C47, 0x720E335796341674 }, /*7E*/
+       { 0x06707A8E33D9D6C6, 0xB684BFE26CD576C6, 0x44F47E5ECD5FC46C, 0xAF1B23A856D844B7, 0x98A627916AC5657E, 0x040C3964A1127E19 }, /*7F*/
+       { 0xA5DAEC3134C0A39B, 0x0CA04160BD5ADB1F, 0xB50EC5A9F29E1ACB, 0xBE2FA1126AF7BFAF, 0xBEFC0AC4C9C5A4B3, 0x994739C71FB1EB29 }, /*80*/
+       { 0x6FEC2D343E83A763, 0x5BDBA5715757F50C, 0xD6F6282EE46A11B3, 0xA8B501F5922A5524, 0xA782A21006B605CA, 0xA10BD2E896975C81 }, /*81*/
+       { 0xB8AAE0532226D0ED, 0x891831C0470E84B7, 0x74C824D648E8FF28, 0xB5E4E02EAD3906EB, 0x5ABB086ADA60A713, 0xA80C57666A9E29F1 }, /*82*/
+       { 0x529E3E52B1E7230A, 0x0C148861C9F08E26, 0x0CFC8A131BAD803D, 0x8C09F324902FAA9F, 0x0231EE4987999848, 0x3B0688492E2B5457 }, /*83*/
+       { 0xEFA6EAC5036814CD, 0x02773C1F8DAA5DF5, 0x0E4EEDBD0702DE31, 0xBA7FD757D0D740EF, 0xA8805F0C74005F8B, 0x1448467BFF3E1EF8 }, /*84*/
+       { 0x2A07B766016AC70D, 0x64215C35364219E9, 0xCD6F7EFE35FCF6F1, 0xF05CC06084C29267, 0xAB3BF2F32579A444, 0xAC75F42D9A25B9C9 }, /*85*/
+       { 0xEF3A14B5EDDB8464, 0x2314E0802D2DD0E9, 0x14DEAEA9F928762A, 0x5763EBB480E15A02, 0x25F7CA14E8CDF5E6, 0x8E594510DC61E6BC }, /*86*/
+       { 0xE62C38DCFD21000B, 0x7BB32AE917EE3DA7, 0xE49F15E24CC9B656, 0x56E28259DCA361D8, 0xB43B8008A9285F48, 0x0DC6B4AF7E4AE61B }, /*87*/
+       { 0x703C64241142DCAE, 0x732D33342C45063A, 0x37877EA1624567CB, 0x2871D534614DD114, 0xE748092A1D94F5D1, 0x4524056F0C6D1CB7 }, /*88*/
+       { 0xE325B1823A595DF9, 0x742D0DD5C96F397C, 0x44361C9540A9F451, 0x02382F9BF6331FB9, 0x8ECBAFBBE91A0467, 0x528EBF3811F904A8 }, /*89*/
+       { 0xFD2BC6534631FB0D, 0x27A5F036FEEB9A6C, 0xD0F876D7911D0775, 0x12EFB3A29C6E0B72, 0xDC4BCA3D5E871DA1, 0x028FB6E6E608F46F }, /*8A*/
+       { 0xEF17ECC8930A7B4A, 0x9D97B34672FB273D, 0xC6AE835F35A25D8F, 0x6C27469530C21F5B, 0x2FBC16A26150E795, 0x02AD93AAE0B5C71A }, /*8B*/
+       { 0x6D24BE43CF07DD56, 0x63681D62A38D2A2F, 0x9872C9B411724AA0, 0xB882B4857C19690A, 0x87B1BA8D2804C6F4, 0xD7B199CC36F40B49 }, /*8C*/
+       { 0xEEFB8D8573FD9E0F, 0x933403199B91560A, 0xFF0DB41665D5248C, 0x322EE105EA984196, 0xDB8CE0F83890D89B, 0x3A32F8983C901F80 }, /*8D*/
+       { 0x082CDAF93F215BAC, 0x67C118A1B9274FAC, 0xAF74501CFB93198A, 0x53525CABA0E812D3, 0xC9AF3A005EFE8A6E, 0xF242DCB60DA7B2FE }, /*8E*/
+       { 0xD3887FBFBB7314DF, 0xDDDCCCF0F720C342, 0xB2C4331C33C8C415, 0x1666010767F4785B, 0x8455B7C1FD5DE487, 0xA821C5EA181875F2 }, /*8F*/
+       { 0x7E289831418562F0, 0x2AD12E3042B185C3, 0x7C20D0D735A6AE96, 0xA68BEF98E22CBD41, 0xA1411D22F8D93243, 0xD813FB404F3D2F38 }, /*90*/
+       { 0xE13FC0A76F664294, 0x7E21C9D9F7FDDDCB, 0x161E68B366D6B1F8, 0x55BF957EB5743874, 0xB23213EF8364D766, 0x529BB98AF96643D4 }, /*91*/
+       { 0x036D7ADDAADB5C33, 0x0525835F802D032E, 0x7DF7D0D8D7A2BEF2, 0x84927644B27696B7, 0x215E21E4D1F9B5B9, 0x77743669C40EB7FD }, /*92*/
+       { 0xA9B3534BE8897784, 0x5BFD4283541A5090, 0x97AFFCCD121C9778, 0xC146C4C9637989C7, 0x0820E72FCBDA59C7, 0x5526E2F4A0AE4F4F }, /*93*/
+       { 0xA4739E20FD72BDC2, 0x6D6EE5A5C1A54CA6, 0x70A97A6FCB884E5C, 0x2B6108339E979C48, 0x93A63730D6BB23A7, 0x5B1DCEAB00045EE5 }, /*94*/
+       { 0x427C14E4F88C8BDB, 0x1D8630868E039BC2, 0x33DB40A251502D1B, 0xE043C9CCB45D2B3D, 0x292B67B6EE077B2D, 0x1C3A2FBDE24C742A }, /*95*/
+       { 0x3DED69F37016D86A, 0x9A947B13AC66D7C3, 0x822D8645DF4CB39C, 0x2BA20F98F19E10DA, 0x6703138D422AC4C4, 0x8D34D6138FA04A1D }, /*96*/
+       { 0x28E59C8B257D112C, 0x8747068CC5499FCF, 0xD6C16EB780F9191A, 0xB416151633F7AF08, 0xA230E00D6BA1A1C3, 0xFD066FB9965B83D2 }, /*97*/
+       { 0x70F4BC1B7F8FFC37, 0x38DC0331E56B0FDC, 0xA9AB7290AD2B0BBD, 0xB307973C3D0783C6, 0xBDC455F6CDCA111F, 0x23F0E08317B8F0DC }, /*98*/
+       { 0x0AEEC24E9285C50F, 0x3BCDA47833B61ACE, 0x839986F959EE0723, 0xC959034A8D7F5EB9, 0xD4AD7E05B05C4FB5, 0x6C37A3D39F7A0EC4 }, /*99*/
+       { 0x0227B7230FBF2D07, 0x28D7D2AD632BED47, 0x07BD8F8B5012EFD0, 0x48A0D43AE0403442, 0x9B8939207F1449A1, 0x351EAD01B9FDF219 }, /*9A*/
+       { 0xA7119D2E311CEF25, 0x1E532CD0C4ED0479, 0x2272F878D8D30A0B, 0x769C412CED9C4C42, 0x262FFBFA65CBDDF5, 0xDB73D86721EA368E }, /*9B*/
+       { 0x4BDBE90B3FBADCB2, 0x1324EC3A8D6FEA57, 0x6D9EFBE530850D00, 0x401A88AFF8A4C8F4, 0x655CB76B8A2E271C, 0x35505B6DBDE16F43 }, /*9C*/
+       { 0x6E15E57E23F57037, 0x4962737362C1FA26, 0xC962372D1829B80B, 0xA1FE6832EA4D6211, 0x6726E307F96E7763, 0x04C761081677505B }, /*9D*/
+       { 0x42E2FF3A8A6FC164, 0xFB85B2BC9D28B268, 0xC559CFF024533A28, 0x2EC83F3911DAB3CE, 0xAE0FC74A9D736A27, 0xDB9CDD048BAB4CCF }, /*9E*/
+       { 0xD79C52221D20E765, 0x499EDD73903CE704, 0x9B016D987DF48349, 0xFCFAB44AD12FC5C1, 0x811293F3B800FDF9, 0x511DC619CA53CEBE }, /*9F*/
+       { 0xA059EE78B826EDDF, 0x4673AF294D17C85A, 0x5E527D4E4DF282B5, 0xDB5B9A2693F95CE3, 0x6551D304FB54F296, 0xAB3EB70D65912FCC }, /*A0*/
+       { 0x7D0C4F67B6C78135, 0x390CAEA7DE304D37, 0x49E19FABC8D494FE, 0x1A9E1B6437A04516, 0x886CC4BDAB6AF35A, 0x0529217344F502FE }, /*A1*/
+       { 0x3CEDF34141B52CEE, 0x8133BA924753573F, 0xCB32BE22BC66025A, 0x0C480183DE403CB3, 0xBF5B84B427DFCF31, 0x7251428DB0232156 }, /*A2*/
+       { 0x86FCE831C58E25CB, 0x5CC43FFE45CBFC75, 0x33877CC042F199BE, 0x1212FA7F0CC22E1C, 0x448EAB4B7D1F9823, 0xA7B1363A9FA7599E }, /*A3*/
+       { 0x2D8C2FEDA0E5106D, 0x192E366838BBEB3F, 0x36226AA60ACEA0AF, 0xE7E1285DC1F3926A, 0x900371FA1883D9EC, 0xBAC33B1AF360EB66 }, /*A4*/
+       { 0xD4A2A11612BDE0E3, 0x82AB0DA614CB4CB8, 0x189A4D50AC01F4C6, 0xE36A5DA1D9F6A647, 0xE43120D6B16B11B6, 0x7D395F4236E75378 }, /*A5*/
+       { 0xC0C155CD47F3877F, 0x4B03BFE5C334CA71, 0x77710F1F4B844FF7, 0x3443BBAB720E8DC5, 0xF03F8868C5863406, 0x0FD60511C872EB50 }, /*A6*/
+       { 0x8C253DAAB5286306, 0x9AA438F54A6196AC, 0x181D08C723A22C5E, 0x633C49C88E3910A1, 0xC9F54A67992675B0, 0x1FDD98ACBD38D976 }, /*A7*/
+       { 0xA10893DA7575A9F7, 0x8F5F4A025AB2A018, 0xD80538F0336BFFC0, 0x0F9751D33889626F, 0x30383EB925BF911A, 0xE6149F68CE19CC60 }, /*A8*/
+       { 0xB9081DBAC6BE0598, 0x785DD9BC69C71492, 0x8B035A0CA56E172B, 0x8946783500724888, 0xAF1E57C958650569, 0xE1DE4E944FF22261 }, /*A9*/
+       { 0xEA5EDC4D2718C0D2, 0xCB1C5D4DA15A8AE4, 0xC6272382F8163015, 0x94A934E5057B54CE, 0x658E481A3D68D10D, 0xE8F24929E50A46A0 }, /*AA*/
+       { 0x7DF146281AF482CD, 0x014B68E726407B06, 0x6CE564938C70DDBC, 0x36DAD2DE72A5DAA2, 0x6D573BF69C0B2980, 0x684DAB14B4AA0329 }, /*AB*/
+       { 0x9C69DC064E738B5F, 0x83CC16BD5A1C36F5, 0xA99B365E6E141B12, 0x2748FA5AD0FACCE8, 0x26D073A047D99C49, 0xB005B182505B0C0C }, /*AC*/
+       { 0x15B6A2A20ED0FD1C, 0x9333AF729BD65A25, 0x22CC333293BD2C1B, 0xD724D949B15E8BE1, 0x69D0DB0512B97117, 0x85ACA8980DD7653C }, /*AD*/
+       { 0x230EC629D77BB3F2, 0x43115B991D297CB2, 0xA2F955792C53C76F, 0x48A76728EBE25BA7, 0x7CE662A405384400, 0xDDC06B7E6BF49D66 }, /*AE*/
+       { 0x20DDB9BD7644410B, 0x056391B1FA2E8C06, 0xCA4EDE51CF167C00, 0x46602B550536F870, 0x5040672597C21FF4, 0x0AF8EC6E8AFB844B }, /*AF*/
+       { 0x0023C5749251B883, 0x335A4F86D66B7E00, 0xAE353DED3EFACE8F, 0x3FC80526D67B35DE, 0x0D9078FBDA80BC53, 0x467900DFF3FE4C14 }, /*B0*/
+       { 0x0F9CB2BE6A448113, 0xE38D541B6A9A5829, 0x673953DAF354FC0E, 0x3C818A277F8569E9, 0x8D16EA77DB122A3B, 0xE40A860318B6EA84 }, /*B1*/
+       { 0x78CE11F42D7D5E50, 0x84F76DFF199C998D, 0x999B578E3AE935CB, 0xD9FD092C1BE63212, 0x31F33C63ACD316D8, 0x5AA08030B8D65C0C }, /*B2*/
+       { 0x0098DBE19CA84FE9, 0xE2426617D1142137, 0x63C3C4166A78E21B, 0x74B145353E03B0E4, 0xF43C0824EAE508C4, 0x58C1E6622528602A }, /*B3*/
+       { 0x9E27EBE6D1426A6F, 0x2A6A600A6B5FA342, 0x8FF7E2306BA90370, 0xDF83D91A683EDDDD, 0x29572442F0225388, 0xE9CC0F1B6437320A }, /*B4*/
+       { 0x054DF380E896064E, 0xFAB81A4AA3AD88A4, 0xF87426486CCA156F, 0xBB1B3C8237472960, 0x7EC0B87CF73F960A, 0x5C57D7E6470F7808 }, /*B5*/
+       { 0x5758E103AC614A1A, 0x766AEE86F81358DF, 0x203FBA51DC74396A, 0x78C93DF969C5721F, 0xE69E32E230196597, 0xE287C6CECD8AB95B }, /*B6*/
+       { 0x2A06A7C10C0DCC97, 0x99D5298268A6745F, 0xF2D818BB774858B3, 0xD52A820D4F64D886, 0x2F808EF87A263981, 0xBB91206E6347C676 }, /*B7*/
+       { 0x0847C6D71CE0C746, 0x86FD451B447C1E11, 0xC20623B0E2856FCC, 0x3ADDFA2D0398181E, 0x6736A0A06B336B46, 0xD1C70AEEB2B1257D }, /*B8*/
+       { 0x5633260D141A9776, 0xD530805F596CA3DB, 0x8CE33EF69437CE46, 0xF62D54E97E747088, 0xDF5C9318489B45EA, 0xA4AAD29F0BA850CA }, /*B9*/
+       { 0xBDBD7B16767F6D9F, 0xF7968427F1B7B6DD, 0x58C76599B35276EE, 0x286F4C7F6CADD791, 0x8188C0401742117B, 0xCEC4F1964266D163 }, /*BA*/
+       { 0x97E4E8A6B5135B24, 0x8A8BD785E5297977, 0x4545C1A0975BC5BB, 0x13FAE3BD9F59E37D, 0xAFD5627C0E91DE2B, 0xA223AC778474E1A9 }, /*BB*/
+       { 0xDE1BF1EAF86C6B3B, 0xA246A3ACD50035FE, 0x6F80179DD96A21CD, 0x3F8DB7CB17300D03, 0x497A798B5D94506C, 0xAD52DCC6F61AE841 }, /*BC*/
+       { 0xF4A4E1D08E1F440B, 0x5E27633CD56422E0, 0x1465C14F1DB41420, 0x9A939043988D37C2, 0xCBE65CFA245DB368, 0x6340AEDE28DDA855 }, /*BD*/
+       { 0x1F7AB65A3F892454, 0xD70AB4167EBEB5A1, 0x9B2631E824C2028D, 0xD5D97BDEE31519BC, 0xEA2DC77449E4058C, 0xEB204F2D6D2FBAFF }, /*BE*/
+       { 0x6537E69171A2665D, 0x3FD2F835435A3F23, 0xADD5DD3E622D6C8A, 0xC522CDD5E5E243F8, 0x5AEC27F3DBFDA8A2, 0x477A65ED570E1445 }, /*BF*/
+       { 0x3BA7CB01D32E9D63, 0x9E335734E7B5416B, 0x0ED96A84F94539F6, 0x45CEE2E46DF5A70D, 0xDE142EE1E9AFEC1C, 0x78D6121C4FDC72DD }, /*C0*/
+       { 0x7BB30AF653390B77, 0x2D394F2B7F8F7BB6, 0x0277A3C213AF3489, 0x7DF6E674DD56D084, 0x5643CD3073C42451, 0xFAB15F8BD1A1DC18 }, /*C1*/
+       { 0x42B453ABF5150D8B, 0x913F109C1188E18C, 0xC27BB7631FB43BF9, 0xEBDDE685EF108419, 0x76D67C87C56D33EA, 0x95EC73C0AF40F084 }, /*C2*/
+       { 0xBCE43D59A1F50BFB, 0xBA7027CA04D84600, 0xFB6FDB98A2BE644B, 0xD5DE777E993DED4A, 0xFCA39F1EDF710F3A, 0xA5E5893C858D8841 }, /*C3*/
+       { 0xC68AC776E6AEACFC, 0x538067C7866106EB, 0xD27B4A352F4EFDE3, 0x847DA2B3BF01E378, 0x3C79E3C136926D58, 0xF957BC8726AA1610 }, /*C4*/
+       { 0x95492C4203C7C612, 0x0DD60DB1EE8321FC, 0xE1D9EBA902F62B42, 0xEA2DBF7D0E37A4F2, 0xE11FB9098BF5DA48, 0xDBFE213F818EA338 }, /*C5*/
+       { 0x17CB21316D4756DD, 0xB88952498140146A, 0x648112F580844288, 0x4947ADC3F7D58F35, 0x651CCE28E26A5377, 0x0B3803DAF337F89B }, /*C6*/
+       { 0xBEAB16E2DCE6B6E3, 0x8F39ECC8E39172DF, 0x607CC9553FF29C0E, 0x4BFD15154F4F0BA7, 0xEE6230B6BD408CE4, 0x35B654110D164E99 }, /*C7*/
+       { 0xADDDFF1BD2C11CD4, 0x2A1A262CBA6E1AA0, 0x0BF2291D09475A46, 0x4C93A0ABADF4DE32, 0x73EE8E1327333E63, 0xF3AE2031F5D13B28 }, /*C8*/
+       { 0x246C7CABB2D9A55C, 0x50E9C7282C1EE0F6, 0x2FBDA09565A0D3D7, 0x196552679C04A4EB, 0x137C66DA29A6DD82, 0x08A76B6B4BDA56BF }, /*C9*/
+       { 0x7CA3C59BE3E28610, 0x6ADD75CF1F7AE248, 0x01747450737A6435, 0xA1F2259CB2B4923B, 0xE0C8F55E8ECE7210, 0xD7964398F350B69B }, /*CA*/
+       { 0xE045864ED1825101, 0xAC54969193E1A1C5, 0x23D85A934D0794C7, 0xB4FA88CB734A4213, 0x7C5CBFD6BDA3D5F9, 0x66607FE938748825 }, /*CB*/
+       { 0xBAF36FD2A180D481, 0xEAC440AC1B9598F7, 0x9AA24D80FFB7B06C, 0x79601F517358F163, 0xD1071831418BB63B, 0x819609A6AE7D3A03 }, /*CC*/
+       { 0x3E9152D8CDBAE551, 0x86AD793F203DD016, 0xBE3AEB778AD4A891, 0x2810254DD76B6618, 0x9B5DCDE36636C327, 0x0A8AAD65868BC58C }, /*CD*/
+       { 0x6D0672780D93152A, 0xEEE705247B828091, 0x9EBDB976F137463F, 0xA7DE3E73A2D0C1BF, 0xF871A00BA0046AC7, 0x484C96A803F23486 }, /*CE*/
+       { 0x0FC7BCDABB06BFFB, 0xF75C3FFB3D6309B3, 0xECA305D103109162, 0x373F503B204FFF61, 0xCE332C9F54963FA2, 0x9A4420A52242CDB4 }, /*CF*/
+       { 0xC71D481179D198C1, 0x505A2845CEE92569, 0xF339BFF6DD6755B5, 0x8BEAD52B8DE89245, 0x4B686E65920DCA2B, 0x99593FA43EE68A37 }, /*D0*/
+       { 0xD90A68D717E61501, 0x9BB920AEA19161A6, 0x2F3D6F96D90EB1E4, 0xDF15ECBA10513D7D, 0xE6E5D539B4F01831, 0xC7D17A7528FECE36 }, /*D1*/
+       { 0xA04FF0BEB4EBFBAF, 0xE5E90A5B3DDAA3CA, 0x8453542209F4A145, 0x80A6FFD72BB5A707, 0x14E0C4705A1ABF6A, 0xD699EC1FC18A677D }, /*D2*/
+       { 0x7021A124E3181575, 0xDC7AAE2817AD945F, 0x8BB5521E7F0D565A, 0x6671D3792F0805EE, 0xD3888EA394413A1A, 0xCE4D7E47B55BF9CC }, /*D3*/
+       { 0x22F440263CAADE68, 0xE77BB287772EAC7B, 0x29493775962A40E9, 0x1E06A27FA68CB91B, 0xDDEF02932ABDB9C7, 0x79F03B88DC175233 }, /*D4*/
+       { 0x65F6D517B53E2391, 0x97DB65A2F00B1C39, 0x1D77AE9B85AA4855, 0x19133B9B3E9B0771, 0x6376D9F11A7DB3D4, 0x949AD02F5AE16184 }, /*D5*/
+       { 0xFE4434CDE09D923B, 0x03B0FCFD713B7052, 0x2D713290D4A67238, 0x2B56946FF629EE96, 0x60A15D01B2B3C428, 0x0B1D5EAF793933A0 }, /*D6*/
+       { 0xBC40FCFB0E0D494B, 0xA31C4648C7B3D1DE, 0xF1113C219A07EC8D, 0x2378BEB1A5C2BD1C, 0x190CC3478070A194, 0x63DAB6E1CCF56329 }, /*D7*/
+       { 0x901B6B9E82BABF91, 0x872A234C45D61001, 0x6CA46A95C1CC6D6C, 0x22779315E0F02295, 0x60A59396346BE6AC, 0xFB67A503CB488846 }, /*D8*/
+       { 0x50D440F74C97660B, 0xE71ECABF64EDFE0C, 0x80201B895718CE22, 0xA05D89804D35D306, 0x8F700402A2B0D086, 0x326FCB334CA4DFC0 }, /*D9*/
+       { 0xBCFBD02EA005CDD5, 0xF0225A4675553115, 0x08E18B3692A7AF62, 0x05D34A820C8CED0A, 0x51A8D7CEC33E80EA, 0x0AC007503FAE879C }, /*DA*/
+       { 0xF43EEFB5C83C521A, 0xE5E9B05FC48841AC, 0x79C52C38BF85B5F9, 0x26CD0818AE3BF7A9, 0x4F385C32CA8F5F74, 0xF17B22107B954752 }, /*DB*/
+       { 0x1A48FC969198A4B0, 0xD9A78940BB0C4E1C, 0x42781D9BE60E7691, 0x87D1CAF3680F8A30, 0xD09FF193606AAF29, 0x4518DABC60048793 }, /*DC*/
+       { 0xF05D48134A56A034, 0x89A65EEB91DC69B9, 0x8FC7F43960E63C62, 0xFA1C6B9FF9415E92, 0x7E219D4E56347935, 0x2B6A48D6DE0AEF85 }, /*DD*/
+       { 0x1A7FF9C54B045FFD, 0x44A0A9562E9468B2, 0xF11425A22D1EBF92, 0x208D33120BD28E0E, 0xF2D74197AF80E162, 0xCEEDCA73DFE66C93 }, /*DE*/
+       { 0xD57190439D29C9A4, 0x44C007DC2B5EAF9D, 0xEF6DDF48A780CEDC, 0x61B205E4A96024B1, 0x1885B6CE84C3FE5D, 0xB8B56986B6E2CE21 }, /*DF*/
+       { 0xF36DACFA34237E99, 0xBE45EB5253BCFED0, 0x402C6946B8B21AC0, 0x2460A6FCE7E9CD67, 0xF89A6D5B162629FC, 0xF66CCEA374DB821E }, /*E0*/
+       { 0x16E06074DCC31A1D, 0xF172017AC3FA38C3, 0xBBC1CE4BB784ED60, 0xDA89A8BCE82AE671, 0xA6DACFFB8D26C0BB, 0x185181AE9609F6D6 }, /*E1*/
+       { 0xF110DBDD94D17661, 0xF59FBB4CBA69F393, 0x463B60FB3F3C5E00, 0x1C60B896FE8E78AC, 0x5EB3E26795DE5AB6, 0x997328D4654D6219 }, /*E2*/
+       { 0x21069118ABE24B61, 0x811CB8C48FCEFC6A, 0x483B032CFB56F902, 0xFB32E848198CC057, 0xA620815462A04F70, 0x900038D1894959E2 }, /*E3*/
+       { 0x5AD509789BFFECD0, 0xDDCD5E8325F69CA0, 0x154D8F1ACD9B8C82, 0xAC7DF75E94CE3CAF, 0x6D6554D1B38754BE, 0xB5DB64AF738486E7 }, /*E4*/
+       { 0x35A308A1AC9A43BF, 0x2647805AB3E6E492, 0x4BB74A616F61588F, 0xFA4602EE5BDBF54E, 0x3FDD62470A7174DB, 0x5795433CA808FAAC }, /*E5*/
+       { 0x51A094B8774CA605, 0x5F07974C74EEF225, 0x022AFEF7AD81A953, 0x0967C44BBA336FD6, 0x8AA327918AECBA3D, 0xF70B8436573C3F0A }, /*E6*/
+       { 0xCF374F83420766C3, 0x71F31901A13EF07C, 0x63AD56C7DEF9DC0F, 0x9E5BB5E859F5A231, 0xD0BF453BB9893E4C, 0xA1E14B66C2719760 }, /*E7*/
+       { 0xB41861CC73FD3E48, 0x461D79A138B04BE1, 0x4010D37D37FBA817, 0x7D9622AA693225A4, 0x2204454B8126799A, 0x33A5D487DCCD6EB6 }, /*E8*/
+       { 0xD291D0317A053320, 0xE27678F1E50D1F76, 0x9A3D663A63159FC7, 0xAD7B4D3F67BAB452, 0x269CC05E2B33CE1C, 0x0FB8261CD734BCC3 }, /*E9*/
+       { 0xF3D0546D3D4A25EE, 0xB42874AD28C9B7F2, 0x73EC788B29962D28, 0x4AE73A48132B8553, 0x756C99D7A0910B66, 0xECA7E2C2712D555C }, /*EA*/
+       { 0x559FA5BF24911FDD, 0xA1DDF5DE3770554B, 0xC7C3FD139366B946, 0x6E7ECC0C881D2BA4, 0x14E76D6A27E54B87, 0x7352D5FBC4FAB878 }, /*EB*/
+       { 0xF19A622BED8DAC0A, 0x35548E5D7EFC5A2E, 0xCAC84974B4F057B2, 0xAB317ED03D0335AE, 0x710FC138F2C51738, 0x9C90CC495A403416 }, /*EC*/
+       { 0x9FA7DEB936F10461, 0xA1529B0B58462F9D, 0x9F109111C8B9EC65, 0x23A3EB28444E33EA, 0x554084CA75118937, 0x599D58A7C946EAC2 }, /*ED*/
+       { 0x6EC3AABB7856AC4E, 0x980E6907C1CBCCAF, 0x1F8557ADC700CBF5, 0x7DCB1CE0AF48D9F4, 0x7FB3DADF8199AB8A, 0xE6B36DB8FADBF312 }, /*EE*/
+       { 0xC00F0D3F7A101660, 0x605B94B12DB6C697, 0x79944F7BA2B65F38, 0x40858ADEDD47E2BC, 0x1E044BDB0E9FB02B, 0x86C79D01A3109539 }, /*EF*/
+       { 0x9731893D5B98482A, 0xFB8DE267F9790326, 0x8780F407143A505D, 0xA41CAEFCCCD3A8E3, 0xA042F0B3D7B7A7FE, 0x3E3151FEBB19A1AC }, /*F0*/
+       { 0xE7EDF679003A6950, 0xBAFC97D4A8C6AB12, 0x13C096B49C79559A, 0xC3052501434B5019, 0x1280FB23E7ADFB09, 0x1959905D31BD2FC0 }, /*F1*/
+       { 0x575C0C46FCFCC65B, 0xFE625E873F34B419, 0x1696FDCC7F51B8A3, 0xC79C56F30E5AE7C0, 0x14E3461CD27FAD15, 0x1B7BCCB9CB472859 }, /*F2*/
+       { 0x3806FE58E5CC8F16, 0xF8244ED76734C1BF, 0x4E04940E0F5DDB56, 0x5BD0AFDDC4158B7B, 0xA4C6BA949911C5C9, 0xFF6E2AC155AE9726 }, /*F3*/
+       { 0x49C7C844B8114144, 0xB450E41BCA35CB00, 0x302450EC67BEF97C, 0xA8662049DB1E0D8B, 0xDA69C022528EB8FA, 0x6ABBF16585C1A2F7 }, /*F4*/
+       { 0x37BB420DF67F044E, 0xDCC0E9F3E2EF07B3, 0x4D10088618777841, 0x0492E5379305DAAE, 0x3DA4791C37E4128F, 0x80688445CBA4EA17 }, /*F5*/
+       { 0x51398A7CE4CF8D9D, 0x49A5FCD891A69CA5, 0x3D72A60EC2392DA5, 0x0E8296B879AB5539, 0x6BCB00AF2EDC0BDE, 0xBEB93848E54B3E90 }, /*F6*/
+       { 0x7AD7C52A18922E19, 0x29292C57C4F5B8F5, 0xF0CF1F98A577C10B, 0x072B9F293BB660CD, 0x09B8604F5575B6FB, 0xDECB396A81B9FCDB }, /*F7*/
+       { 0x254AD7ADB4C220DE, 0x6C62E20F95A0070D, 0xADEB89F339309BD8, 0xA2F685CC178B289F, 0x9343905B5DEE95A5, 0xE0C30F34A2977C86 }, /*F8*/
+       { 0x669CD51AF7CFBFAA, 0xE3E0806F6880271D, 0x6934C259E098BF90, 0x5DFEEAF0FBCA7249, 0x89F74B948B4118B6, 0x53640AEAFB6807C3 }, /*F9*/
+       { 0xDD3BACDCC04BE120, 0x6D4949BD64198E51, 0x31FDB39666598A74, 0xBBBC6DE9C0C15A81, 0xF27F201C61C06279, 0x2738AFE3E84E5CDD }, /*FA*/
+       { 0xCDD71FD35A6411DE, 0x3CC012793E87523F, 0xB0CFF8720FCA36F3, 0x93E85FE07300F012, 0xE894A085263F090B, 0x2DF60A01DAFA90EC }, /*FB*/
+       { 0x9DA50DB1EEB4FADD, 0xE524E49C9974799A, 0xDE09FFF26A24CBB9, 0xAF9D71E9F3ACE7CD, 0xEB62B1A62566EC9D, 0x06D02AB1217D3553 }, /*FC*/
+       { 0xDD31E6391AE03522, 0x93ACD1065B35E915, 0xF4EB56CC03E79218, 0x0717815C850C97F1, 0xBF4F6A8AC0540A6F, 0xFCF8AE5DE9507FF0 }, /*FD*/
+       { 0xAB45B413DC50B207, 0x40B417369551D8D5, 0xCA32286A108E7210, 0x03225E54D8D093AF, 0x4B6CA5591EA576E9, 0x4E12AB774DC4E062 }, /*FE*/
+       { 0xD9F4F850DF6CB96C, 0x8ABAD81B1667335D, 0xCB4079CFE79C72E5, 0xE5542F763E316996, 0x303E4B79B9D397C4, 0xE46933038B945111 }, /*FF*/
+       { 0x75B15CC53B0D2502, 0xDA1BCA6BA0524358, 0x9EDA977556C06B7E, 0x6C57727ECF0A1325, 0xDC613D5A78E5C3F8, 0xCE062D94A3B4945A }  /*ZZ*/
+};
+
+/* Table MIX
+ * 257x6 matrix containing pre-computed mixing indices with HamD(a,b) >= 2 for each possible pair (a,b) with a != b
+ */
+static const byte_t MHASH384_MIX[256U][MHASH384_WORDS] =
+{
+       { 0x05, 0x03, 0x04, 0x01, 0x02, 0x00 }, /*00*/
+       { 0x02, 0x05, 0x00, 0x04, 0x03, 0x01 }, /*01*/
+       { 0x04, 0x03, 0x01, 0x02, 0x05, 0x00 }, /*02*/
+       { 0x03, 0x05, 0x04, 0x00, 0x02, 0x01 }, /*03*/
+       { 0x02, 0x03, 0x05, 0x01, 0x00, 0x04 }, /*04*/
+       { 0x04, 0x00, 0x03, 0x05, 0x02, 0x01 }, /*05*/
+       { 0x03, 0x02, 0x05, 0x01, 0x00, 0x04 }, /*06*/
+       { 0x04, 0x05, 0x03, 0x02, 0x01, 0x00 }, /*07*/
+       { 0x03, 0x04, 0x01, 0x05, 0x00, 0x02 }, /*08*/
+       { 0x01, 0x02, 0x04, 0x00, 0x05, 0x03 }, /*09*/
+       { 0x05, 0x04, 0x03, 0x01, 0x00, 0x02 }, /*0A*/
+       { 0x04, 0x02, 0x01, 0x05, 0x03, 0x00 }, /*0B*/
+       { 0x05, 0x03, 0x04, 0x01, 0x00, 0x02 }, /*0C*/
+       { 0x04, 0x00, 0x01, 0x05, 0x02, 0x03 }, /*0D*/
+       { 0x02, 0x05, 0x03, 0x04, 0x00, 0x01 }, /*0E*/
+       { 0x05, 0x02, 0x01, 0x00, 0x03, 0x04 }, /*0F*/
+       { 0x04, 0x05, 0x03, 0x01, 0x00, 0x02 }, /*10*/
+       { 0x01, 0x00, 0x04, 0x02, 0x05, 0x03 }, /*11*/
+       { 0x02, 0x05, 0x01, 0x04, 0x03, 0x00 }, /*12*/
+       { 0x04, 0x02, 0x00, 0x01, 0x05, 0x03 }, /*13*/
+       { 0x01, 0x03, 0x05, 0x02, 0x00, 0x04 }, /*14*/
+       { 0x04, 0x00, 0x01, 0x05, 0x03, 0x02 }, /*15*/
+       { 0x01, 0x05, 0x04, 0x02, 0x00, 0x03 }, /*16*/
+       { 0x03, 0x04, 0x05, 0x00, 0x01, 0x02 }, /*17*/
+       { 0x01, 0x02, 0x00, 0x05, 0x03, 0x04 }, /*18*/
+       { 0x04, 0x05, 0x03, 0x02, 0x00, 0x01 }, /*19*/
+       { 0x05, 0x03, 0x00, 0x04, 0x01, 0x02 }, /*1A*/
+       { 0x02, 0x05, 0x04, 0x01, 0x00, 0x03 }, /*1B*/
+       { 0x05, 0x00, 0x03, 0x04, 0x02, 0x01 }, /*1C*/
+       { 0x04, 0x03, 0x00, 0x01, 0x05, 0x02 }, /*1D*/
+       { 0x01, 0x02, 0x04, 0x05, 0x03, 0x00 }, /*1E*/
+       { 0x04, 0x00, 0x03, 0x02, 0x05, 0x01 }, /*1F*/
+       { 0x02, 0x03, 0x00, 0x05, 0x01, 0x04 }, /*20*/
+       { 0x03, 0x04, 0x01, 0x00, 0x05, 0x02 }, /*21*/
+       { 0x05, 0x00, 0x03, 0x01, 0x02, 0x04 }, /*22*/
+       { 0x04, 0x03, 0x00, 0x02, 0x05, 0x01 }, /*23*/
+       { 0x05, 0x02, 0x03, 0x01, 0x00, 0x04 }, /*24*/
+       { 0x02, 0x04, 0x05, 0x00, 0x01, 0x03 }, /*25*/
+       { 0x04, 0x03, 0x00, 0x05, 0x02, 0x01 }, /*26*/
+       { 0x05, 0x02, 0x01, 0x04, 0x00, 0x03 }, /*27*/
+       { 0x03, 0x05, 0x04, 0x01, 0x02, 0x00 }, /*28*/
+       { 0x02, 0x03, 0x05, 0x00, 0x01, 0x04 }, /*29*/
+       { 0x04, 0x05, 0x00, 0x01, 0x02, 0x03 }, /*2A*/
+       { 0x05, 0x03, 0x01, 0x02, 0x00, 0x04 }, /*2B*/
+       { 0x02, 0x05, 0x00, 0x04, 0x01, 0x03 }, /*2C*/
+       { 0x05, 0x02, 0x04, 0x01, 0x03, 0x00 }, /*2D*/
+       { 0x04, 0x05, 0x03, 0x00, 0x01, 0x02 }, /*2E*/
+       { 0x05, 0x00, 0x01, 0x02, 0x03, 0x04 }, /*2F*/
+       { 0x03, 0x05, 0x04, 0x01, 0x00, 0x02 }, /*30*/
+       { 0x01, 0x00, 0x05, 0x02, 0x03, 0x04 }, /*31*/
+       { 0x05, 0x04, 0x03, 0x00, 0x01, 0x02 }, /*32*/
+       { 0x03, 0x00, 0x04, 0x05, 0x02, 0x01 }, /*33*/
+       { 0x05, 0x02, 0x00, 0x04, 0x01, 0x03 }, /*34*/
+       { 0x01, 0x04, 0x05, 0x00, 0x03, 0x02 }, /*35*/
+       { 0x03, 0x00, 0x01, 0x05, 0x02, 0x04 }, /*36*/
+       { 0x01, 0x05, 0x04, 0x00, 0x03, 0x02 }, /*37*/
+       { 0x03, 0x02, 0x01, 0x05, 0x00, 0x04 }, /*38*/
+       { 0x02, 0x00, 0x05, 0x04, 0x01, 0x03 }, /*39*/
+       { 0x04, 0x02, 0x03, 0x01, 0x05, 0x00 }, /*3A*/
+       { 0x03, 0x05, 0x01, 0x04, 0x00, 0x02 }, /*3B*/
+       { 0x05, 0x00, 0x04, 0x02, 0x01, 0x03 }, /*3C*/
+       { 0x04, 0x03, 0x05, 0x00, 0x02, 0x01 }, /*3D*/
+       { 0x05, 0x02, 0x01, 0x04, 0x03, 0x00 }, /*3E*/
+       { 0x01, 0x05, 0x03, 0x02, 0x00, 0x04 }, /*3F*/
+       { 0x05, 0x00, 0x01, 0x04, 0x03, 0x02 }, /*40*/
+       { 0x02, 0x05, 0x03, 0x01, 0x00, 0x04 }, /*41*/
+       { 0x03, 0x04, 0x05, 0x02, 0x01, 0x00 }, /*42*/
+       { 0x01, 0x05, 0x04, 0x00, 0x02, 0x03 }, /*43*/
+       { 0x02, 0x04, 0x01, 0x05, 0x03, 0x00 }, /*44*/
+       { 0x04, 0x00, 0x05, 0x01, 0x02, 0x03 }, /*45*/
+       { 0x03, 0x05, 0x00, 0x02, 0x01, 0x04 }, /*46*/
+       { 0x05, 0x00, 0x04, 0x01, 0x02, 0x03 }, /*47*/
+       { 0x03, 0x02, 0x00, 0x05, 0x01, 0x04 }, /*48*/
+       { 0x02, 0x03, 0x01, 0x04, 0x05, 0x00 }, /*49*/
+       { 0x01, 0x04, 0x03, 0x05, 0x00, 0x02 }, /*4A*/
+       { 0x03, 0x05, 0x00, 0x01, 0x02, 0x04 }, /*4B*/
+       { 0x02, 0x00, 0x03, 0x04, 0x05, 0x01 }, /*4C*/
+       { 0x05, 0x04, 0x01, 0x02, 0x00, 0x03 }, /*4D*/
+       { 0x03, 0x00, 0x05, 0x01, 0x02, 0x04 }, /*4E*/
+       { 0x01, 0x03, 0x04, 0x02, 0x05, 0x00 }, /*4F*/
+       { 0x03, 0x04, 0x05, 0x00, 0x02, 0x01 }, /*50*/
+       { 0x04, 0x02, 0x00, 0x05, 0x01, 0x03 }, /*51*/
+       { 0x01, 0x05, 0x03, 0x04, 0x00, 0x02 }, /*52*/
+       { 0x03, 0x02, 0x00, 0x01, 0x05, 0x04 }, /*53*/
+       { 0x04, 0x03, 0x05, 0x00, 0x01, 0x02 }, /*54*/
+       { 0x05, 0x02, 0x03, 0x04, 0x00, 0x01 }, /*55*/
+       { 0x03, 0x00, 0x05, 0x02, 0x01, 0x04 }, /*56*/
+       { 0x01, 0x03, 0x04, 0x00, 0x05, 0x02 }, /*57*/
+       { 0x02, 0x04, 0x03, 0x05, 0x01, 0x00 }, /*58*/
+       { 0x05, 0x03, 0x00, 0x04, 0x02, 0x01 }, /*59*/
+       { 0x04, 0x02, 0x03, 0x05, 0x01, 0x00 }, /*5A*/
+       { 0x05, 0x04, 0x00, 0x01, 0x03, 0x02 }, /*5B*/
+       { 0x03, 0x05, 0x01, 0x00, 0x02, 0x04 }, /*5C*/
+       { 0x04, 0x03, 0x05, 0x02, 0x00, 0x01 }, /*5D*/
+       { 0x03, 0x00, 0x01, 0x04, 0x05, 0x02 }, /*5E*/
+       { 0x05, 0x03, 0x04, 0x02, 0x01, 0x00 }, /*5F*/
+       { 0x04, 0x05, 0x01, 0x00, 0x02, 0x03 }, /*60*/
+       { 0x01, 0x03, 0x00, 0x02, 0x05, 0x04 }, /*61*/
+       { 0x02, 0x05, 0x04, 0x01, 0x03, 0x00 }, /*62*/
+       { 0x05, 0x04, 0x03, 0x02, 0x00, 0x01 }, /*63*/
+       { 0x01, 0x00, 0x04, 0x05, 0x03, 0x02 }, /*64*/
+       { 0x02, 0x04, 0x05, 0x01, 0x00, 0x03 }, /*65*/
+       { 0x03, 0x02, 0x01, 0x04, 0x05, 0x00 }, /*66*/
+       { 0x02, 0x05, 0x00, 0x01, 0x03, 0x04 }, /*67*/
+       { 0x03, 0x02, 0x05, 0x04, 0x00, 0x01 }, /*68*/
+       { 0x01, 0x05, 0x03, 0x00, 0x02, 0x04 }, /*69*/
+       { 0x02, 0x00, 0x04, 0x01, 0x05, 0x03 }, /*6A*/
+       { 0x01, 0x02, 0x03, 0x05, 0x00, 0x04 }, /*6B*/
+       { 0x04, 0x05, 0x00, 0x02, 0x01, 0x03 }, /*6C*/
+       { 0x02, 0x04, 0x05, 0x01, 0x03, 0x00 }, /*6D*/
+       { 0x04, 0x03, 0x01, 0x05, 0x00, 0x02 }, /*6E*/
+       { 0x05, 0x02, 0x00, 0x04, 0x03, 0x01 }, /*6F*/
+       { 0x02, 0x03, 0x04, 0x05, 0x01, 0x00 }, /*70*/
+       { 0x04, 0x00, 0x03, 0x01, 0x05, 0x02 }, /*71*/
+       { 0x01, 0x03, 0x05, 0x00, 0x02, 0x04 }, /*72*/
+       { 0x02, 0x00, 0x04, 0x05, 0x03, 0x01 }, /*73*/
+       { 0x04, 0x03, 0x05, 0x02, 0x01, 0x00 }, /*74*/
+       { 0x01, 0x04, 0x03, 0x00, 0x05, 0x02 }, /*75*/
+       { 0x05, 0x00, 0x01, 0x04, 0x02, 0x03 }, /*76*/
+       { 0x02, 0x03, 0x04, 0x05, 0x00, 0x01 }, /*77*/
+       { 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }, /*78*/
+       { 0x04, 0x03, 0x05, 0x01, 0x00, 0x02 }, /*79*/
+       { 0x05, 0x04, 0x00, 0x02, 0x03, 0x01 }, /*7A*/
+       { 0x01, 0x00, 0x04, 0x05, 0x02, 0x03 }, /*7B*/
+       { 0x02, 0x05, 0x03, 0x00, 0x01, 0x04 }, /*7C*/
+       { 0x01, 0x04, 0x00, 0x02, 0x05, 0x03 }, /*7D*/
+       { 0x05, 0x02, 0x03, 0x04, 0x01, 0x00 }, /*7E*/
+       { 0x04, 0x05, 0x00, 0x01, 0x03, 0x02 }, /*7F*/
+       { 0x01, 0x02, 0x03, 0x04, 0x05, 0x00 }, /*80*/
+       { 0x05, 0x00, 0x04, 0x02, 0x03, 0x01 }, /*81*/
+       { 0x01, 0x02, 0x03, 0x00, 0x05, 0x04 }, /*82*/
+       { 0x04, 0x00, 0x05, 0x01, 0x03, 0x02 }, /*83*/
+       { 0x02, 0x04, 0x03, 0x05, 0x00, 0x01 }, /*84*/
+       { 0x05, 0x02, 0x00, 0x01, 0x03, 0x04 }, /*85*/
+       { 0x02, 0x03, 0x05, 0x04, 0x01, 0x00 }, /*86*/
+       { 0x04, 0x05, 0x00, 0x02, 0x03, 0x01 }, /*87*/
+       { 0x02, 0x04, 0x03, 0x01, 0x05, 0x00 }, /*88*/
+       { 0x03, 0x02, 0x05, 0x00, 0x01, 0x04 }, /*89*/
+       { 0x01, 0x05, 0x00, 0x04, 0x03, 0x02 }, /*8A*/
+       { 0x04, 0x03, 0x01, 0x05, 0x02, 0x00 }, /*8B*/
+       { 0x03, 0x05, 0x04, 0x02, 0x00, 0x01 }, /*8C*/
+       { 0x02, 0x04, 0x00, 0x01, 0x05, 0x03 }, /*8D*/
+       { 0x03, 0x05, 0x04, 0x00, 0x01, 0x02 }, /*8E*/
+       { 0x01, 0x04, 0x05, 0x02, 0x00, 0x03 }, /*8F*/
+       { 0x04, 0x05, 0x01, 0x00, 0x03, 0x02 }, /*90*/
+       { 0x02, 0x00, 0x04, 0x05, 0x01, 0x03 }, /*91*/
+       { 0x04, 0x03, 0x05, 0x01, 0x02, 0x00 }, /*92*/
+       { 0x02, 0x00, 0x01, 0x04, 0x05, 0x03 }, /*93*/
+       { 0x03, 0x04, 0x05, 0x02, 0x00, 0x01 }, /*94*/
+       { 0x02, 0x05, 0x03, 0x04, 0x01, 0x00 }, /*95*/
+       { 0x05, 0x03, 0x04, 0x02, 0x00, 0x01 }, /*96*/
+       { 0x02, 0x05, 0x01, 0x00, 0x03, 0x04 }, /*97*/
+       { 0x04, 0x03, 0x00, 0x05, 0x01, 0x02 }, /*98*/
+       { 0x01, 0x00, 0x05, 0x04, 0x02, 0x03 }, /*99*/
+       { 0x03, 0x04, 0x01, 0x02, 0x05, 0x00 }, /*9A*/
+       { 0x05, 0x00, 0x03, 0x04, 0x01, 0x02 }, /*9B*/
+       { 0x03, 0x05, 0x01, 0x02, 0x00, 0x04 }, /*9C*/
+       { 0x04, 0x02, 0x00, 0x05, 0x03, 0x01 }, /*9D*/
+       { 0x03, 0x00, 0x05, 0x04, 0x01, 0x02 }, /*9E*/
+       { 0x04, 0x05, 0x01, 0x02, 0x03, 0x00 }, /*9F*/
+       { 0x02, 0x00, 0x03, 0x05, 0x01, 0x04 }, /*A0*/
+       { 0x01, 0x03, 0x00, 0x04, 0x05, 0x02 }, /*A1*/
+       { 0x02, 0x00, 0x05, 0x01, 0x03, 0x04 }, /*A2*/
+       { 0x04, 0x02, 0x01, 0x00, 0x05, 0x03 }, /*A3*/
+       { 0x05, 0x03, 0x00, 0x02, 0x01, 0x04 }, /*A4*/
+       { 0x02, 0x04, 0x05, 0x00, 0x03, 0x01 }, /*A5*/
+       { 0x01, 0x00, 0x03, 0x04, 0x05, 0x02 }, /*A6*/
+       { 0x05, 0x03, 0x01, 0x00, 0x02, 0x04 }, /*A7*/
+       { 0x01, 0x05, 0x04, 0x02, 0x03, 0x00 }, /*A8*/
+       { 0x02, 0x03, 0x00, 0x01, 0x05, 0x04 }, /*A9*/
+       { 0x04, 0x02, 0x01, 0x05, 0x00, 0x03 }, /*AA*/
+       { 0x03, 0x00, 0x05, 0x04, 0x02, 0x01 }, /*AB*/
+       { 0x05, 0x04, 0x01, 0x00, 0x03, 0x02 }, /*AC*/
+       { 0x02, 0x03, 0x05, 0x04, 0x00, 0x01 }, /*AD*/
+       { 0x03, 0x02, 0x04, 0x05, 0x01, 0x00 }, /*AE*/
+       { 0x02, 0x00, 0x05, 0x04, 0x03, 0x01 }, /*AF*/
+       { 0x05, 0x02, 0x03, 0x00, 0x01, 0x04 }, /*B0*/
+       { 0x03, 0x04, 0x05, 0x01, 0x00, 0x02 }, /*B1*/
+       { 0x02, 0x00, 0x01, 0x05, 0x03, 0x04 }, /*B2*/
+       { 0x03, 0x05, 0x04, 0x02, 0x01, 0x00 }, /*B3*/
+       { 0x01, 0x00, 0x03, 0x05, 0x02, 0x04 }, /*B4*/
+       { 0x02, 0x05, 0x04, 0x00, 0x01, 0x03 }, /*B5*/
+       { 0x05, 0x04, 0x01, 0x02, 0x03, 0x00 }, /*B6*/
+       { 0x04, 0x02, 0x05, 0x00, 0x01, 0x03 }, /*B7*/
+       { 0x03, 0x05, 0x01, 0x04, 0x02, 0x00 }, /*B8*/
+       { 0x05, 0x00, 0x04, 0x01, 0x03, 0x02 }, /*B9*/
+       { 0x04, 0x02, 0x03, 0x05, 0x00, 0x01 }, /*BA*/
+       { 0x02, 0x03, 0x01, 0x00, 0x05, 0x04 }, /*BB*/
+       { 0x01, 0x05, 0x03, 0x04, 0x02, 0x00 }, /*BC*/
+       { 0x02, 0x04, 0x01, 0x05, 0x00, 0x03 }, /*BD*/
+       { 0x03, 0x02, 0x04, 0x01, 0x05, 0x00 }, /*BE*/
+       { 0x05, 0x04, 0x01, 0x00, 0x02, 0x03 }, /*BF*/
+       { 0x02, 0x00, 0x03, 0x01, 0x05, 0x04 }, /*C0*/
+       { 0x05, 0x04, 0x00, 0x02, 0x01, 0x03 }, /*C1*/
+       { 0x04, 0x02, 0x05, 0x00, 0x03, 0x01 }, /*C2*/
+       { 0x05, 0x03, 0x00, 0x01, 0x02, 0x04 }, /*C3*/
+       { 0x02, 0x05, 0x01, 0x04, 0x00, 0x03 }, /*C4*/
+       { 0x04, 0x00, 0x05, 0x02, 0x03, 0x01 }, /*C5*/
+       { 0x03, 0x04, 0x01, 0x05, 0x02, 0x00 }, /*C6*/
+       { 0x04, 0x00, 0x05, 0x02, 0x01, 0x03 }, /*C7*/
+       { 0x03, 0x02, 0x04, 0x00, 0x05, 0x01 }, /*C8*/
+       { 0x01, 0x04, 0x05, 0x02, 0x03, 0x00 }, /*C9*/
+       { 0x03, 0x00, 0x04, 0x05, 0x01, 0x02 }, /*CA*/
+       { 0x05, 0x03, 0x01, 0x04, 0x02, 0x00 }, /*CB*/
+       { 0x03, 0x04, 0x00, 0x01, 0x05, 0x02 }, /*CC*/
+       { 0x01, 0x03, 0x04, 0x05, 0x02, 0x00 }, /*CD*/
+       { 0x05, 0x00, 0x03, 0x02, 0x01, 0x04 }, /*CE*/
+       { 0x01, 0x02, 0x04, 0x05, 0x00, 0x03 }, /*CF*/
+       { 0x02, 0x03, 0x00, 0x04, 0x05, 0x01 }, /*D0*/
+       { 0x05, 0x02, 0x04, 0x00, 0x01, 0x03 }, /*D1*/
+       { 0x02, 0x03, 0x01, 0x05, 0x00, 0x04 }, /*D2*/
+       { 0x01, 0x05, 0x00, 0x04, 0x02, 0x03 }, /*D3*/
+       { 0x02, 0x04, 0x03, 0x00, 0x05, 0x01 }, /*D4*/
+       { 0x01, 0x03, 0x00, 0x05, 0x02, 0x04 }, /*D5*/
+       { 0x03, 0x00, 0x04, 0x02, 0x05, 0x01 }, /*D6*/
+       { 0x01, 0x03, 0x05, 0x04, 0x00, 0x02 }, /*D7*/
+       { 0x04, 0x05, 0x03, 0x01, 0x02, 0x00 }, /*D8*/
+       { 0x02, 0x03, 0x04, 0x00, 0x05, 0x01 }, /*D9*/
+       { 0x03, 0x02, 0x05, 0x04, 0x01, 0x00 }, /*DA*/
+       { 0x04, 0x03, 0x01, 0x00, 0x05, 0x02 }, /*DB*/
+       { 0x01, 0x02, 0x05, 0x04, 0x03, 0x00 }, /*DC*/
+       { 0x03, 0x04, 0x00, 0x02, 0x05, 0x01 }, /*DD*/
+       { 0x01, 0x03, 0x05, 0x04, 0x02, 0x00 }, /*DE*/
+       { 0x02, 0x04, 0x01, 0x00, 0x05, 0x03 }, /*DF*/
+       { 0x03, 0x05, 0x00, 0x04, 0x01, 0x02 }, /*E0*/
+       { 0x05, 0x03, 0x04, 0x00, 0x02, 0x01 }, /*E1*/
+       { 0x03, 0x04, 0x00, 0x05, 0x01, 0x02 }, /*E2*/
+       { 0x04, 0x05, 0x01, 0x02, 0x00, 0x03 }, /*E3*/
+       { 0x03, 0x04, 0x00, 0x05, 0x02, 0x01 }, /*E4*/
+       { 0x01, 0x00, 0x05, 0x04, 0x03, 0x02 }, /*E5*/
+       { 0x03, 0x02, 0x04, 0x05, 0x00, 0x01 }, /*E6*/
+       { 0x01, 0x04, 0x05, 0x00, 0x02, 0x03 }, /*E7*/
+       { 0x04, 0x00, 0x03, 0x05, 0x01, 0x02 }, /*E8*/
+       { 0x03, 0x02, 0x00, 0x04, 0x05, 0x01 }, /*E9*/
+       { 0x05, 0x03, 0x04, 0x00, 0x01, 0x02 }, /*EA*/
+       { 0x04, 0x02, 0x05, 0x01, 0x00, 0x03 }, /*EB*/
+       { 0x01, 0x05, 0x00, 0x02, 0x03, 0x04 }, /*EC*/
+       { 0x04, 0x02, 0x03, 0x00, 0x05, 0x01 }, /*ED*/
+       { 0x01, 0x04, 0x00, 0x05, 0x02, 0x03 }, /*EE*/
+       { 0x05, 0x03, 0x01, 0x04, 0x00, 0x02 }, /*EF*/
+       { 0x01, 0x04, 0x03, 0x05, 0x02, 0x00 }, /*F0*/
+       { 0x05, 0x02, 0x04, 0x01, 0x00, 0x03 }, /*F1*/
+       { 0x03, 0x00, 0x01, 0x02, 0x05, 0x04 }, /*F2*/
+       { 0x05, 0x02, 0x04, 0x00, 0x03, 0x01 }, /*F3*/
+       { 0x02, 0x04, 0x00, 0x05, 0x01, 0x03 }, /*F4*/
+       { 0x01, 0x02, 0x05, 0x00, 0x03, 0x04 }, /*F5*/
+       { 0x05, 0x04, 0x03, 0x01, 0x02, 0x00 }, /*F6*/
+       { 0x01, 0x02, 0x05, 0x04, 0x00, 0x03 }, /*F7*/
+       { 0x02, 0x04, 0x00, 0x05, 0x03, 0x01 }, /*F8*/
+       { 0x04, 0x00, 0x01, 0x02, 0x05, 0x03 }, /*F9*/
+       { 0x03, 0x04, 0x05, 0x01, 0x02, 0x00 }, /*FA*/
+       { 0x01, 0x00, 0x03, 0x02, 0x05, 0x04 }, /*FB*/
+       { 0x03, 0x05, 0x00, 0x04, 0x02, 0x01 }, /*FC*/
+       { 0x02, 0x03, 0x04, 0x01, 0x05, 0x00 }, /*FD*/
+       { 0x04, 0x05, 0x03, 0x00, 0x02, 0x01 }, /*FE*/
+       { 0x01, 0x04, 0x00, 0x05, 0x03, 0x02 }  /*FF*/
+};
+
+/* Table ADD
+ * 257x24 byte matrix containing pre-computed random 32-Bit numbers to be used as addend
+ */
+static const ui32_t MHASH384_ADD[257U][MHASH384_WORDS] =
+{
+       { 0x13B2C18C, 0xAF30E30D, 0x5F10AD61, 0xE8F5FFA6, 0x7952A3AC, 0xF215E976 }, /*00*/
+       { 0xA7C9CBBA, 0xBF3C579D, 0x8C2062B3, 0x55AAFE8D, 0xF8151801, 0x281703B4 }, /*01*/
+       { 0xEE69CC38, 0x74AC54A9, 0x84C8483B, 0x059B5078, 0x3F3319EE, 0x4B248CD1 }, /*02*/
+       { 0xEE7E0264, 0x3D788335, 0xD4865073, 0x1B74418F, 0xC65AF6E0, 0xA30D5853 }, /*03*/
+       { 0xA2C86BBD, 0xB7A852D3, 0x5F97613C, 0x5F75197A, 0xD78805E8, 0x153532A9 }, /*04*/
+       { 0xF2D5318B, 0x5C30FD1E, 0x3877136D, 0xC46F4EDD, 0x97A40BBE, 0x9FCFEE6E }, /*05*/
+       { 0xDAB8050C, 0x651C9456, 0x7210B2E0, 0xEAB621CF, 0x60F2036E, 0xDBF9CFC0 }, /*06*/
+       { 0xD8575E14, 0xF084AA1C, 0x9C1E76C0, 0x336F6CA9, 0x8771CBFE, 0xC2132D38 }, /*07*/
+       { 0x86A377A0, 0xBFF921DA, 0x16AD6B57, 0xC8880A45, 0xAEA6CEDD, 0xF79BA939 }, /*08*/
+       { 0xA008749B, 0x293CFB8A, 0x7E8A4C92, 0x5E84F211, 0x3CCF7485, 0x8E54C33E }, /*09*/
+       { 0x9A78176F, 0x7872ECAB, 0x7EE61199, 0xF739F0CD, 0x8B2BA20D, 0x72B339A5 }, /*0A*/
+       { 0xF9B79F6C, 0x27F44D63, 0xD0E5A65B, 0x06092C7E, 0xC4EB60E6, 0x8304D410 }, /*0B*/
+       { 0x9C9A92DA, 0xF8E68CD1, 0x6DA77F4A, 0x2013EB87, 0xD5D48685, 0xD0D7A557 }, /*0C*/
+       { 0x12608877, 0x5B6310FD, 0x41296D3D, 0x57435D83, 0xA906DFDC, 0x3A1A6D72 }, /*0D*/
+       { 0x5112C7E6, 0xEBF6D751, 0xFD3026A5, 0x08A39D23, 0x54134FF1, 0xEC5B2C8A }, /*0E*/
+       { 0x2F52EEE6, 0x40A853D3, 0x358BED81, 0xC76B62DF, 0x8E786E4F, 0x75F63677 }, /*0F*/
+       { 0x54ABD27E, 0xB7EE2BB8, 0x17756DC1, 0xB6DE3BBB, 0xA992B540, 0x66A4E44A }, /*10*/
+       { 0x9B8C6F0B, 0x3CA2CEB1, 0xBD583C09, 0x14713651, 0xAA79A7DE, 0x28C3D1C5 }, /*11*/
+       { 0xABB4F78B, 0xD3E194D8, 0xAA0A85E3, 0xC9C7B196, 0x3885710F, 0x0392E30B }, /*12*/
+       { 0xA122EA90, 0xC71A2436, 0x223F5C82, 0x8CB0A4FF, 0x5B9B57D1, 0xF16A689D }, /*13*/
+       { 0x7AFA3B0D, 0x75E05D93, 0xBE7D07A1, 0x89C88598, 0xFBDBF0C1, 0x6C47F63E }, /*14*/
+       { 0xD3D2BA3F, 0x61C4F0CF, 0x9F4B127D, 0xEAAFA57A, 0x08CE931D, 0xC9EC6985 }, /*15*/
+       { 0xB0792CA2, 0x39D65B2C, 0x7D2FE4DD, 0xF4C6E55F, 0x6F26B34B, 0x392C16F2 }, /*16*/
+       { 0x59EFBF60, 0x056FAD5A, 0x206CBB30, 0xDCAE65BE, 0xD679DCAE, 0xDD4EE6DB }, /*17*/
+       { 0x3FE0CBE3, 0x3D16C1AE, 0x2E10E8AA, 0xEC4D3C7F, 0x3EC26B8C, 0xC1952F33 }, /*18*/
+       { 0xD515AA2F, 0x2400E7A5, 0x4E71FE3A, 0xD78DFE09, 0xB3CD989D, 0xA031E3EB }, /*19*/
+       { 0x684B950C, 0x1F449B7A, 0xD5BDEF26, 0xEB6562AD, 0x2B28F5F3, 0x0A3DF9F9 }, /*1A*/
+       { 0xEC3811B9, 0x7F53DD87, 0x0BA9B287, 0xB3D46AAF, 0xD30D9034, 0x8F0AEEF9 }, /*1B*/
+       { 0x76366768, 0x81F9D6A1, 0x3386DB56, 0xD9B20BBF, 0x5601E297, 0x30646236 }, /*1C*/
+       { 0x7FDA5C84, 0x953B0881, 0xAC4ACC72, 0x35565AEE, 0xD3540FDB, 0x072C64DD }, /*1D*/
+       { 0x5F19ABAA, 0xC91EE5F5, 0xF5AFB55E, 0x2BE896A1, 0xE1C409D5, 0x74E9FA0F }, /*1E*/
+       { 0xD372CD9F, 0x5B676E7C, 0x4CFB5AF8, 0xAF377F22, 0xC931858C, 0x5445CE0D }, /*1F*/
+       { 0x423B2C7F, 0x58695641, 0x53F7F865, 0xDD8FF14B, 0x3787B012, 0x769070D6 }, /*20*/
+       { 0xDCD0417D, 0xF914813A, 0x3841DBBF, 0x601B29BE, 0xB4B7B901, 0xDCC3A649 }, /*21*/
+       { 0x3BE29DEB, 0xEDF9A0D0, 0xF2DDFA0F, 0x922F23CC, 0xC4563BC3, 0xE4122F72 }, /*22*/
+       { 0xE88B4666, 0xDDCEBA90, 0x5B7B313D, 0xBE0FDC0A, 0x5D4431D9, 0x6D05CEB5 }, /*23*/
+       { 0x6BF2646B, 0x9E4BEF14, 0xB17DAA68, 0x731EB896, 0xB47996F6, 0x3C0699E9 }, /*24*/
+       { 0x3E88E294, 0x66F97202, 0x701DBD04, 0x91CF6F7E, 0xBC81A5D4, 0xD5B632EB }, /*25*/
+       { 0x5F0C32D5, 0x0118B38F, 0x7C72778B, 0x45E251C9, 0x0EE9A676, 0xE18CED9A }, /*26*/
+       { 0x0DEC4615, 0xBCFACA34, 0x7A33CF9B, 0x7FFC4202, 0x3C036C98, 0x2FB0117F }, /*27*/
+       { 0x4BE81882, 0xD12BC6B9, 0xFAAC1942, 0xC825B793, 0x3D235059, 0x0C0DB0B2 }, /*28*/
+       { 0x1D4049E2, 0x2A84B86A, 0x537FDB7E, 0xEC81B40E, 0x7DDA393F, 0xAFA3D7D0 }, /*29*/
+       { 0x036B6D44, 0x9BDE4C03, 0x805ECC65, 0x2FB48667, 0x894CB979, 0x8B79B9CF }, /*2A*/
+       { 0x26A1E724, 0xC041E47B, 0xC552045C, 0x5DF502CC, 0x86B77E47, 0xCC37F33D }, /*2B*/
+       { 0xF8733714, 0x8049E9F7, 0x00262BDF, 0xD6E324DB, 0xA286C1A4, 0xF44E998B }, /*2C*/
+       { 0x2AB8AD83, 0x71FE5EF6, 0x4905D6E8, 0x16DAAD77, 0x04750CAC, 0x00EE14E7 }, /*2D*/
+       { 0xC9E482E1, 0x54B04F45, 0x05C6636B, 0xA3501ED2, 0xF9FB2A23, 0x895FBECC }, /*2E*/
+       { 0xAD3D24C5, 0xD0017ECC, 0xDFA881B8, 0x48DC3C52, 0x97E69D2D, 0xEFC5D21C }, /*2F*/
+       { 0xCC56C844, 0x875BF026, 0x8AF0DB7A, 0xC8AA9F7B, 0x7977E1D8, 0x96557C38 }, /*30*/
+       { 0x51704FD2, 0xC451174E, 0x1DC0C5FC, 0x3C690432, 0xEE113D49, 0x1C2F3BE1 }, /*31*/
+       { 0xE67BA4D2, 0x1CA12AD0, 0x4C5E09B0, 0x8CC90A26, 0x6BB15CEF, 0x04A20BCF }, /*32*/
+       { 0xF3A8861E, 0xABA8B64B, 0xA71D73C1, 0xB33F5566, 0xD780C2BB, 0x35A4F1B3 }, /*33*/
+       { 0x3AC6E50E, 0x058237EE, 0x28CCD3E2, 0x65C138E9, 0x36165F62, 0xBA461352 }, /*34*/
+       { 0xC190A454, 0x3BB14A4B, 0x6EAA4F8B, 0xC454F8AF, 0x23FB09D9, 0xCC8B3B7A }, /*35*/
+       { 0x9A7B55A8, 0xB97F3D39, 0xBD95F71C, 0xF8765FE4, 0x60E434BF, 0x4D43C8E3 }, /*36*/
+       { 0x7449A794, 0x17C054E4, 0x031E4411, 0xCB8AD1A1, 0x49ADAE58, 0xBBC53D1E }, /*37*/
+       { 0x44D4328B, 0x609D1567, 0x1D278E05, 0x5ADD1AA9, 0x98C8FD64, 0x56B954FF }, /*38*/
+       { 0x22BF5E54, 0xDAF9D8A6, 0x6D232343, 0x488EF3C1, 0xF0147776, 0x4185C674 }, /*39*/
+       { 0xBEBF70A3, 0x1EC08D69, 0x404E9F1B, 0x445D9117, 0x3CB72E80, 0x475685E5 }, /*3A*/
+       { 0x563E64AC, 0x71D3014A, 0x72741CFB, 0xF22ECB26, 0x4551C41A, 0x0023EC43 }, /*3B*/
+       { 0xE3E9DD2B, 0x37C31996, 0xE55E66A0, 0xD12D1F0D, 0x342599B5, 0xC56F482F }, /*3C*/
+       { 0xF1A9E9E3, 0x770E2D8D, 0x4B0BA236, 0x797D4C71, 0x5514E96F, 0xBD938686 }, /*3D*/
+       { 0x2A55DF59, 0xCC18982D, 0x093B8D26, 0x78F7470A, 0x4F719A03, 0x4A437F9E }, /*3E*/
+       { 0x97AB2269, 0xAC22A233, 0x5D3D1D17, 0x7906351E, 0x3DC9583A, 0x7FEB2192 }, /*3F*/
+       { 0x7911E3A5, 0xD3BC66BF, 0x70B96F33, 0x13C364F7, 0x6BE4373D, 0x95EE1CA3 }, /*40*/
+       { 0x624B1BB9, 0xB1D57F69, 0x23D6BEDA, 0x14C47359, 0x53C61BBE, 0xA2630CBA }, /*41*/
+       { 0x8614B657, 0x30CD13F1, 0xDCFFBAC2, 0x091A6966, 0xD18999EC, 0xAEA3C354 }, /*42*/
+       { 0xCEBB00CB, 0x44C14586, 0x97BA2ADE, 0x58E0E16F, 0xEFD68B88, 0x757742C8 }, /*43*/
+       { 0xADD6619B, 0xC64480CE, 0x9A15BE92, 0x7E2C055C, 0xE0E34FFF, 0x53B744DD }, /*44*/
+       { 0x18598EB8, 0xB9108E1F, 0x94B5C815, 0x79FA3053, 0xE01C1377, 0x7967D7F2 }, /*45*/
+       { 0xAFFFBD10, 0x0DEAAEF3, 0x1C66243F, 0xDD6601F3, 0x2012069B, 0x43045C84 }, /*46*/
+       { 0x542CCA4B, 0x5878A842, 0x292F30B6, 0xAABB827D, 0xD8230B3D, 0x3262082F }, /*47*/
+       { 0xD964DDF0, 0x4D8351A6, 0xFC140DD6, 0x2D6B8672, 0x0532D394, 0xCA677441 }, /*48*/
+       { 0x9B58B961, 0x9BF99AF4, 0x478A9887, 0x4A77DE7C, 0x0560B7D4, 0xB1A31887 }, /*49*/
+       { 0x3C3415CC, 0xAC4B8189, 0xB06793FA, 0xC0B9C0F2, 0x479D1B15, 0x1FA353D8 }, /*4A*/
+       { 0x5307D37A, 0x8E7684EB, 0xE9392362, 0x6D06BA38, 0xC1843AB6, 0xA7ECDDCE }, /*4B*/
+       { 0xAB93AC3F, 0xB8C34E0D, 0x17479CBE, 0x39B9FF22, 0xCB2532B3, 0xB4169E93 }, /*4C*/
+       { 0x6C7B4787, 0x295048F3, 0x27401801, 0x592ECAB0, 0x8D36903A, 0xCDC7255A }, /*4D*/
+       { 0x1BE412A4, 0x726A831D, 0xEB00B75F, 0x173BFCCA, 0x952FAEDB, 0x43EA817D }, /*4E*/
+       { 0xFBC40010, 0xD10BDB17, 0xAE3D20AE, 0x20347FD2, 0xAFF07636, 0xA586CC6E }, /*4F*/
+       { 0x03000F48, 0x2C7332CC, 0xB0020AAD, 0x09ECB64D, 0xDBB82864, 0x8A9CF7C0 }, /*50*/
+       { 0xC0D05E64, 0x11921D7D, 0x92F79AD0, 0x4C1F5EC5, 0xB38AA2C9, 0x0511831C }, /*51*/
+       { 0x8D190938, 0x6F3AE8FB, 0xC8EDF48F, 0xF26CAB54, 0xB0E7FAA4, 0x16C2AA21 }, /*52*/
+       { 0x359C9C58, 0x889140C3, 0x5E70BCB7, 0x58ACF356, 0xC3BDB2FB, 0xA888D5D5 }, /*53*/
+       { 0x84F6B9EF, 0x5C554168, 0x4A8DCAB7, 0x5DEDC340, 0x44C57BF7, 0x31BFADDB }, /*54*/
+       { 0xC42C7720, 0x94DAD11B, 0x29FC745D, 0x3C1F4639, 0xE52F6DFC, 0x97DDAE2E }, /*55*/
+       { 0x0C8B14C2, 0xB0D980FE, 0x135623B6, 0x5C72D71F, 0x5B5B8DCA, 0xDB4A99C0 }, /*56*/
+       { 0x5E7BDF3F, 0xD2885F09, 0xCF46F88F, 0x1EB9EFCD, 0x3CBB6BE0, 0x907C7544 }, /*57*/
+       { 0xBD9BD888, 0xA6806C72, 0xE6C0B60F, 0x7B5B2DCE, 0xE7AB0E6C, 0xE220CDC2 }, /*58*/
+       { 0x8C55577B, 0xA5023515, 0xC6630DE7, 0x3D3C780A, 0x3650EECC, 0xC14EEBCB }, /*59*/
+       { 0x709661B9, 0xAE770422, 0xA6CF70C5, 0xB33FA2FE, 0xEB3AF10A, 0xF4228B91 }, /*5A*/
+       { 0x244EA452, 0x1580EB30, 0xDFC147E7, 0xF96FC12E, 0x17F51E9B, 0xE0E70E7D }, /*5B*/
+       { 0x344FD50E, 0x8F84DFB7, 0x8539197A, 0x2FFA298A, 0x58E522A5, 0x6B46761B }, /*5C*/
+       { 0x00047013, 0x4663B6F3, 0x58184E79, 0xCA5F3449, 0x9607C508, 0x27FA414C }, /*5D*/
+       { 0xEFC168C3, 0xDC017B33, 0x7F31A48D, 0x6B4B3C6E, 0x3CD05242, 0x653C3728 }, /*5E*/
+       { 0xAAC9448A, 0x25BFB909, 0x42213EB3, 0x0B6EE0F7, 0x70321152, 0x40B5B6EA }, /*5F*/
+       { 0x4F2547E3, 0x84C88B48, 0xC789D44C, 0xE8317D46, 0xFB1E318E, 0xA3338DD8 }, /*60*/
+       { 0xD80FB73E, 0x8144D28C, 0x33A441CC, 0xB7736354, 0xA91B2A6E, 0x3C973147 }, /*61*/
+       { 0xD0C2FF1D, 0xF80BAB81, 0x7E006359, 0x5A050090, 0x928374BC, 0xE636C5E9 }, /*62*/
+       { 0x29C96D66, 0xAEE27C6C, 0x267CE151, 0x40747378, 0xB04CD4D9, 0x5140C1F3 }, /*63*/
+       { 0x156B775E, 0x9A4D35D0, 0x84DA5F3B, 0x1E794E7A, 0x6C15952D, 0xBE34D677 }, /*64*/
+       { 0x95FBF1EB, 0x4BCA6744, 0x72F0776C, 0x7C11B4CD, 0xA5674E3C, 0xA7022DA4 }, /*65*/
+       { 0x6C7098F6, 0x3535A203, 0x63224F93, 0x4FE5F6F1, 0x4FD60AC0, 0x6284F031 }, /*66*/
+       { 0xB5F1757D, 0xF0A2E1A9, 0x4046267D, 0x2365E6CA, 0xF01C84B7, 0xA27177F5 }, /*67*/
+       { 0xF7A8A55F, 0x28E4D223, 0x6933DBB2, 0xC06E657C, 0x404C94B7, 0xCDC9278E }, /*68*/
+       { 0xB88FDB49, 0xDB3C1CB0, 0x6643719A, 0xA78A1157, 0x74895649, 0x9B35EA26 }, /*69*/
+       { 0xE05200A6, 0xAF8CBC8F, 0x76366935, 0x8C653672, 0x10A3F99B, 0x382F29AA }, /*6A*/
+       { 0x29AB3900, 0x289C44C4, 0x1563E45F, 0xA90A65DE, 0x30A0BFEC, 0xAB9FDCCE }, /*6B*/
+       { 0xE1F20AA6, 0xEC9D69CA, 0x03256EA4, 0xD7BFB23B, 0x9A838907, 0x2CAD4277 }, /*6C*/
+       { 0xDD6B37C3, 0x816E8914, 0x50F5D946, 0x392C3B93, 0x3F2362CD, 0x5BFEF741 }, /*6D*/
+       { 0x6D758401, 0xDACC8B90, 0x290771BB, 0xED79A318, 0x1A87526F, 0x2F2E3E76 }, /*6E*/
+       { 0x3383AD16, 0x0F4744FA, 0x8A1C7B37, 0x8ECC2413, 0x7732295A, 0xA3F6A1AF }, /*6F*/
+       { 0xF1B25367, 0x233EEB5B, 0x279D52B0, 0x9A046CCA, 0xB0D76507, 0x885963AB }, /*70*/
+       { 0xEC73E1F9, 0x6FAED772, 0xEC780F72, 0x46C50E26, 0x6221DB5B, 0x89CA75E6 }, /*71*/
+       { 0xDAD89F5D, 0x59DB2678, 0xA579C018, 0x90DA08F5, 0xBE9E795E, 0x11E4D988 }, /*72*/
+       { 0x2373AF1F, 0xCCCFD9AD, 0x365E9E15, 0x743A1FF1, 0x13057CED, 0x6DD11662 }, /*73*/
+       { 0xE32ACFAB, 0xEC659E78, 0x0CB472F2, 0xDD02907E, 0xFFCE3802, 0xB91F1963 }, /*74*/
+       { 0x43CC1C2D, 0xA4239D99, 0x776E306B, 0xF5749A88, 0x9CED6490, 0x2D9DF0DC }, /*75*/
+       { 0x3D8A32E9, 0xF3DB557E, 0xA7D3EEF1, 0x329C6341, 0x3A6D3C73, 0x09D021F8 }, /*76*/
+       { 0x74DE7662, 0x8FB0F13A, 0x6793D109, 0xEFE86A86, 0x9A396326, 0xEF96D376 }, /*77*/
+       { 0x7C921DE2, 0xC24C55D5, 0x3544D45B, 0x5686D9A2, 0x5DF25635, 0xEFC7E954 }, /*78*/
+       { 0x6C48781D, 0xEA8C8306, 0x757AAD29, 0x40115C87, 0xA92EC03D, 0xF36D3EC2 }, /*79*/
+       { 0x8A48EC01, 0x6AC7EEC6, 0xE0FF1268, 0x0A5127C7, 0x0244071E, 0xAFB6D0ED }, /*7A*/
+       { 0x99B29D33, 0x5E8DCDCB, 0xDA2ED4A8, 0xD9CCFD7E, 0x668BE4DA, 0x081858C3 }, /*7B*/
+       { 0xDDDC6207, 0xB52329C3, 0x341DB972, 0x4FAB30E8, 0xFF821F4D, 0x47B68C9D }, /*7C*/
+       { 0xD59521A6, 0xEB85350D, 0xCCF547C6, 0xEF50E0A2, 0xB549AF5A, 0xFBB0C484 }, /*7D*/
+       { 0x5217E9F4, 0xB27C2313, 0xC82B22AF, 0x619A46D0, 0x4E0FF4FA, 0x1AB7FED5 }, /*7E*/
+       { 0x913EBFA5, 0xBE552440, 0xB81E27A5, 0xFEF80DA9, 0x5C100864, 0xBC3F8EEE }, /*7F*/
+       { 0x27627613, 0xDD53D691, 0x19BAA1BD, 0xD179E811, 0x921BFDA0, 0x3E1AC539 }, /*80*/
+       { 0x17CAC507, 0x6AA98FE0, 0xFB02E085, 0xF6D0EEFB, 0x676799F4, 0x12359D40 }, /*81*/
+       { 0x554D9AEE, 0xDEA25249, 0xC4BC501C, 0xF011B4B2, 0x58B984DC, 0x929C6B5A }, /*82*/
+       { 0x3217ADC8, 0xFD9A6DEE, 0xC3921E15, 0xABD659C1, 0xABD33969, 0x93306767 }, /*83*/
+       { 0x35328CAF, 0xF3C4D7A2, 0x07B0347E, 0x3DF627E5, 0xB273C78C, 0xADF208CD }, /*84*/
+       { 0x2BD7721F, 0xF5783803, 0x1BBB9624, 0x55B4B105, 0xFFB3F3CF, 0x4CF2E1B3 }, /*85*/
+       { 0xD165DD68, 0xB1C01D6D, 0x1D101E62, 0x3A0A5662, 0x3C8722D2, 0xB744FF5A }, /*86*/
+       { 0x449B8418, 0x29C5CEEB, 0x974403CD, 0xE49660AB, 0x82145199, 0x20CEB67B }, /*87*/
+       { 0x7C2BA473, 0xE7AE8079, 0x31432DD8, 0x8787F5A9, 0xE04228B5, 0x33392F2F }, /*88*/
+       { 0x962716FA, 0x0A6F1D12, 0x46B3F858, 0x62E219C7, 0x861E2AF1, 0x5866B232 }, /*89*/
+       { 0x57B30251, 0x62F51A37, 0x59324168, 0xF0836E30, 0xC083BC01, 0x778BB1AE }, /*8A*/
+       { 0x71A1C89E, 0xECAC3A4C, 0x3CBBCE64, 0xD1F58D2F, 0x6A5C6E06, 0x61C64195 }, /*8B*/
+       { 0x7C05A21C, 0x155BEAD9, 0x7EDDFF5C, 0x78BB8C98, 0xA8E84E11, 0xC5EEB1F9 }, /*8C*/
+       { 0x439FFFB3, 0xF1AD1346, 0x9C898BB1, 0xFAB4D098, 0x30EF7863, 0x8B7646E8 }, /*8D*/
+       { 0x07B9817C, 0x96A9A389, 0x4698863E, 0x024356E1, 0x38AFF21A, 0xF4117D09 }, /*8E*/
+       { 0xA70B2873, 0x488A3145, 0x43A5C731, 0x12A49FD3, 0xBD0000E5, 0x9B5E9001 }, /*8F*/
+       { 0x17D6630F, 0xF3AE0FCC, 0x36D04FEB, 0x20B8C4A8, 0x717582B9, 0x48538D7C }, /*90*/
+       { 0x91B045FE, 0x3FDCF695, 0x356D0D5C, 0x2EB8808E, 0xFD4E4CE3, 0x1DC99A76 }, /*91*/
+       { 0x44F1E72A, 0x4530F446, 0xB25545D6, 0x5080498D, 0xB8C6D8B2, 0xCB32B8F4 }, /*92*/
+       { 0xA8062C57, 0x3F3EDD44, 0x48EEE98C, 0xE25EB954, 0x1712BDDB, 0x5270DFE1 }, /*93*/
+       { 0x12F901C2, 0x9DE6D999, 0xC5728969, 0x062C5DE5, 0x3C49C5E4, 0x5B344AAD }, /*94*/
+       { 0x7B41A9D4, 0x0017D3BD, 0xAC5A46D5, 0xAFAF2284, 0x45EFCEA8, 0x33CEC63F }, /*95*/
+       { 0xB3EAA2A4, 0x15908324, 0xDCB5FE00, 0xD0F1E9D7, 0x51E362BC, 0xFECBB788 }, /*96*/
+       { 0x2FD5E605, 0xC6FDCADA, 0xE4DF9EEB, 0x22A39E17, 0x94EE60C9, 0xF2CE4D87 }, /*97*/
+       { 0x5E627410, 0xDD58EAC8, 0x76FF0DD4, 0xA51ACFF9, 0x406E5D9A, 0x41F6C488 }, /*98*/
+       { 0x910860F9, 0x8C88E2FB, 0x6F3E3B4A, 0xB563F5D9, 0x3F0FE042, 0xF3BB7251 }, /*99*/
+       { 0xC4720898, 0x174B8899, 0xD027627E, 0xC75E54E5, 0xFE3A0F70, 0xB83A697C }, /*9A*/
+       { 0x97B3FDFB, 0xDE80D5E2, 0x974DAFD3, 0x83506833, 0x51AA7EF0, 0x2751E9A9 }, /*9B*/
+       { 0x486AB0AE, 0x39C74A47, 0x8BE5059E, 0xD306D21F, 0x466C2587, 0xB0C35B18 }, /*9C*/
+       { 0x53D44A4C, 0x4D5C4EDD, 0xEF47022B, 0x03F49875, 0x58EA6784, 0x1DB8F4A6 }, /*9D*/
+       { 0xF36D6C63, 0x283FCE64, 0x1F277678, 0xDA4D0B72, 0x4EEC07D6, 0x8BED9511 }, /*9E*/
+       { 0x5125D019, 0x31DF9C3D, 0x558F39A8, 0x2E823985, 0x360F63D9, 0x61FEB82F }, /*9F*/
+       { 0xE47C41B8, 0xA70EADF2, 0xEE5A94B4, 0x9AA96718, 0x467AF85B, 0x46A2071D }, /*A0*/
+       { 0xEE121014, 0x2EF7A126, 0x63B12F85, 0xAA52F030, 0x8CCF5A69, 0x2EF4C5D0 }, /*A1*/
+       { 0x56E30275, 0x9C3EC92D, 0x03C0ABA6, 0x10816DEA, 0x75ABE59E, 0xA9060355 }, /*A2*/
+       { 0x8C319B84, 0xCDFFB55A, 0x9602A044, 0x4183058F, 0x6C50CAC6, 0x76A12BBC }, /*A3*/
+       { 0x1C25A145, 0x041EF5B5, 0x07420A60, 0x30A79DCE, 0x9AC49851, 0xBA509884 }, /*A4*/
+       { 0xC076D4D4, 0xD5E8731E, 0xAEF1C167, 0x52CE4D69, 0x461243C2, 0x59124BE8 }, /*A5*/
+       { 0xD179B2C7, 0x06EE1498, 0x86EF65D0, 0xC447768F, 0x87F4BF53, 0x00D002C5 }, /*A6*/
+       { 0xFBB7BFA7, 0x83E7FE96, 0xC08A6777, 0x05F43892, 0xB0217F85, 0x2CC91FC3 }, /*A7*/
+       { 0xE8032675, 0xA17040D9, 0xA98BD110, 0x7B746D5B, 0x71AAAD57, 0xCF70C5C0 }, /*A8*/
+       { 0x0732A5B6, 0x08A88647, 0x63EA848B, 0x8922AE62, 0x00377824, 0xE6B642F0 }, /*A9*/
+       { 0x941FF159, 0x0C6FA82A, 0x55D7B637, 0xD5A512AE, 0x47A6A530, 0xB36D7D46 }, /*AA*/
+       { 0xCA49B481, 0xF3788B26, 0x16C0E515, 0x2DAEF7D9, 0x6247A75B, 0x78484BB5 }, /*AB*/
+       { 0x65104E93, 0xAA602717, 0x36EECD02, 0x843F8EE5, 0x29A1ACCE, 0xBDC90BD5 }, /*AC*/
+       { 0x0F62269D, 0x6D370AC7, 0x1A16E7F8, 0x463448CB, 0xB8B864FB, 0xCC9EAA14 }, /*AD*/
+       { 0xA05ADD64, 0xD1544F88, 0x808E890E, 0xAD4307FE, 0xDB9DA315, 0x0A3C9088 }, /*AE*/
+       { 0xDBB49743, 0x821DC0E2, 0xE57A2CD8, 0xE9F06FC7, 0x363E1070, 0x295AA9D5 }, /*AF*/
+       { 0xA326B444, 0x621F4637, 0x92616801, 0xFD1F5FBB, 0xDC6FFEAC, 0x58B11C80 }, /*B0*/
+       { 0x212E49C7, 0xD151D095, 0x4B36A276, 0x2AD77D66, 0xCF1AAC37, 0xF77B7920 }, /*B1*/
+       { 0xA2AB4280, 0x3971A920, 0xB906F07C, 0xD913BA8C, 0x0429D1C6, 0x070BB87C }, /*B2*/
+       { 0x34ABFAAD, 0x8D662459, 0x9C5D03C9, 0xB386D713, 0xAD737CE3, 0x72F9F913 }, /*B3*/
+       { 0x2E8D78B7, 0xA30453D0, 0xF4C54371, 0xD18E0B82, 0x2B2D1995, 0x0333AC78 }, /*B4*/
+       { 0xE1E6FE04, 0x9804A75D, 0xFB1F11DE, 0xD220B6D9, 0x7CB4BC91, 0x6EF76861 }, /*B5*/
+       { 0xBE87A55A, 0x00D797E6, 0x0F6281D1, 0x242235BC, 0xF7A4054F, 0xEA57BBDB }, /*B6*/
+       { 0x987D0049, 0x03C098D8, 0xC0C966D5, 0xD68B7202, 0x0EC76AA0, 0xCE4A6659 }, /*B7*/
+       { 0x701714D3, 0xCC2B4D3A, 0xCA8E5A83, 0x1AE4DF4C, 0x59EDB778, 0x33C0ACF9 }, /*B8*/
+       { 0xE90B0122, 0xE8002693, 0x152B3944, 0x22F42540, 0xC6574494, 0x46C28CE2 }, /*B9*/
+       { 0x72B182AC, 0xA901F7F6, 0x5CFDD45B, 0x39A97979, 0xC1E75D8D, 0x7B3C5A41 }, /*BA*/
+       { 0x639C71B4, 0xBE0FCFF8, 0x526CF104, 0x54FAE329, 0x032098BB, 0xE7B55777 }, /*BB*/
+       { 0xFEAB769B, 0x296C0749, 0xA63BF06F, 0x0C2D627C, 0x84607425, 0xA4F94069 }, /*BC*/
+       { 0xF2C938A7, 0x27D41E44, 0x7E56AA59, 0x6DE46E6C, 0xDBEDFC6D, 0x04401409 }, /*BD*/
+       { 0x32FC8801, 0x8516D260, 0x64D61AFE, 0x96594532, 0x1EBACA12, 0x6F093C6B }, /*BE*/
+       { 0x4DCDBDAC, 0x4DE66599, 0x2794AABC, 0x93FF2F9D, 0x7E2AA11A, 0xF0CF874A }, /*BF*/
+       { 0xDE166A6B, 0xBAC8ED71, 0x36FE1A68, 0xC0F096DF, 0x85B741C5, 0x96BB9548 }, /*C0*/
+       { 0xF1DAF2D2, 0x8BD22114, 0xE6909F91, 0x767E60EF, 0x4CF7FAF2, 0xBB801A57 }, /*C1*/
+       { 0x46BAA05B, 0x20DD6D7A, 0x4B6774B5, 0x9D9DDDED, 0xFDD60142, 0x5351A50A }, /*C2*/
+       { 0x1154D2B9, 0x6243A3C8, 0xEFBA1A3C, 0xD880D653, 0x59CD5256, 0x4BEF63AC }, /*C3*/
+       { 0xBB7F0FCA, 0x8BCF3DEE, 0xEF7CD3E8, 0x409A6EA5, 0xD05B2A11, 0xCB3F8B7D }, /*C4*/
+       { 0x5CDF0286, 0x15AA322B, 0x82F74519, 0x19762535, 0x10AEEA00, 0xA6C6BB13 }, /*C5*/
+       { 0x4F8CCF64, 0xC175F9A2, 0x458A2088, 0x334E560B, 0x3ED94A31, 0xC36FFEA0 }, /*C6*/
+       { 0x2A749029, 0xA780E916, 0x32183706, 0x932F528E, 0x1D50C3E4, 0xE089FC18 }, /*C7*/
+       { 0xAA26728F, 0xC29D086D, 0x61F88E5C, 0x2CEFEA8D, 0xEE88F1DD, 0xC89BBA0F }, /*C8*/
+       { 0xA5E2CD57, 0x629DC4B7, 0xC7726079, 0xEEA440B1, 0x507D7674, 0xA03EED7F }, /*C9*/
+       { 0x23B73098, 0x7BE996C7, 0x6C8BBDDA, 0x7D881A37, 0x12447B37, 0x112E9D40 }, /*CA*/
+       { 0xC21D0A92, 0xD09A010A, 0xCD357AF3, 0x0526B63F, 0xD1E2DF26, 0x4FF48234 }, /*CB*/
+       { 0x950D59CD, 0x0639DBE1, 0x9C332783, 0xFA49C746, 0x953DC7EB, 0x8EB136E4 }, /*CC*/
+       { 0x99A8F4FE, 0x896A1686, 0xDE1BE583, 0x20E3A642, 0x0E65E5D5, 0x0FACDACC }, /*CD*/
+       { 0x4F8ADD7D, 0xC27A7DFF, 0x65438661, 0x04BE6BB2, 0xDF80958C, 0x67369A32 }, /*CE*/
+       { 0x104E92CE, 0x94E19F20, 0x6FAA86F3, 0x9A25E48D, 0x0482204E, 0x912C2D1B }, /*CF*/
+       { 0x28AC8824, 0x81DD3CBF, 0xD4003B0A, 0x5FA83632, 0x5F485E0A, 0x5F819A8A }, /*D0*/
+       { 0xE6D0E6AB, 0x09E97DC8, 0x5E946DBE, 0x7DD90573, 0xF5ECA786, 0xB0BBD0BC }, /*D1*/
+       { 0xB8D377F1, 0x8FA2B637, 0x2B35180A, 0x28464162, 0xC455D035, 0x7DFA9021 }, /*D2*/
+       { 0x6AC52907, 0x2749E4C6, 0x6AD6A4D0, 0x3B7174DA, 0xFE19E3EF, 0xF9F1F40A }, /*D3*/
+       { 0xDB100345, 0xF5D5FFFE, 0x5AAF4546, 0xA95A6CC5, 0xB172E231, 0x92B8E45F }, /*D4*/
+       { 0x617D2C5B, 0xE133BB0C, 0x95CE7C6F, 0xE859BBF1, 0xE12576F7, 0x74D28A61 }, /*D5*/
+       { 0xC284CA4E, 0xCCF3DCDE, 0xC69CF9DB, 0xD397A5D3, 0x02809CDC, 0x7FBC873F }, /*D6*/
+       { 0x177158DC, 0x2B30DC6A, 0xAF526BD8, 0x79E783CB, 0xC8D635C5, 0x68B89A41 }, /*D7*/
+       { 0x350FDBE3, 0x909AA71C, 0xC199C6F3, 0x970566A2, 0x58BF37DA, 0x62CA0756 }, /*D8*/
+       { 0x8B629171, 0x83C60BD9, 0x55E7DE9D, 0x0A87FD89, 0x63165A91, 0xC4BE5C85 }, /*D9*/
+       { 0x7B8B02E2, 0x98B5A8CC, 0x97BE12B3, 0xEFC17CC8, 0x620E1180, 0xBBE6B9D2 }, /*DA*/
+       { 0x97936B90, 0x3059A8D7, 0x99242C99, 0x5212715B, 0x3B40E4A2, 0x47B330FF }, /*DB*/
+       { 0xDEE82F48, 0x9C5862A5, 0x46C98152, 0xDE26C0C1, 0xA07CDCE2, 0xBC69F20C }, /*DC*/
+       { 0xAAEA3141, 0xF840354A, 0x7EE1A095, 0x498F6DAC, 0xEAE8216D, 0xB65E96A0 }, /*DD*/
+       { 0x12D75D9C, 0x6AAA1531, 0xAE20DF76, 0xFE257981, 0x434EE77B, 0x549C7579 }, /*DE*/
+       { 0x1B2FC468, 0x0940E108, 0x60DE1A9E, 0x41D46F89, 0xCF0DD612, 0x7AA0386B }, /*DF*/
+       { 0xA56433F6, 0x789100BA, 0x50CDB7E9, 0x3A11AE6C, 0x8224361A, 0x1F8B3C14 }, /*E0*/
+       { 0xFD6D3A1C, 0xE92DA632, 0x08B35A14, 0x6DF921CD, 0xBE887850, 0xEE1AD2A4 }, /*E1*/
+       { 0x772C59F4, 0xB9570E21, 0x7448E01C, 0xA632B61E, 0x4A0218E4, 0x48D4936B }, /*E2*/
+       { 0x001CB7C4, 0x642511D7, 0x5E1457A9, 0x1BD71C53, 0xF88EBB30, 0xAAF79F12 }, /*E3*/
+       { 0x3B29999C, 0x61F2A87B, 0xA71C8C84, 0x0B3FD74B, 0x991AC230, 0x1CD5189C }, /*E4*/
+       { 0x97F0DB05, 0x4166DBCB, 0xF9CD085B, 0x083FF569, 0xCD95CEBD, 0xA0A4AC2C }, /*E5*/
+       { 0x8C28FED9, 0x0BA76739, 0xD7C81E03, 0x28EC9369, 0xF47EB379, 0x4E03C624 }, /*E6*/
+       { 0x88EF27AD, 0x17971236, 0x4DE8CC38, 0xD468926B, 0x8BE392B3, 0x56394091 }, /*E7*/
+       { 0xAD7B6B0C, 0xE6086D38, 0x74CC103E, 0x734FC4AB, 0x18963383, 0xF5D7FD09 }, /*E8*/
+       { 0x36B40975, 0x7E419219, 0xD109DB23, 0xDD569F6F, 0xCC5DF3F2, 0x637C2AAC }, /*E9*/
+       { 0xC354E0FF, 0x711DABE3, 0x3808EEEA, 0x6C206679, 0xD75040EA, 0x40FB6C41 }, /*EA*/
+       { 0xDD9AAB46, 0x41E64E67, 0x261A425B, 0x80CB3F7C, 0xA531A139, 0x75934DFA }, /*EB*/
+       { 0x14E44A08, 0x1F8CA28B, 0xFFC69542, 0xB3511A69, 0xF8AA034C, 0x26E52E01 }, /*EC*/
+       { 0x5C5B2089, 0xB37C0B0F, 0xD8D0BD18, 0x40932C2F, 0xDCEE2FEF, 0x52829953 }, /*ED*/
+       { 0x37EA566F, 0x089C4DD1, 0x9F60D762, 0xF2785486, 0xA93A6B0D, 0x6503063D }, /*EE*/
+       { 0xC0CBE2C7, 0x4E23C526, 0x606B72F0, 0x884B7A05, 0xA66EF67B, 0xF30DD80A }, /*EF*/
+       { 0xF3F276E0, 0x3591C692, 0xB2BB885B, 0xDBC22E58, 0x786DCA29, 0x15EA0D06 }, /*F0*/
+       { 0x90B7A296, 0x2CC1EC9D, 0x20922AE6, 0x350B8EDF, 0x580DB6C1, 0x901E6725 }, /*F1*/
+       { 0xC099DE21, 0x1DE1594E, 0x48D23351, 0xD1CE1FE8, 0x76E26671, 0x805E744A }, /*F2*/
+       { 0x89071E13, 0xE8E8A47A, 0x2CE727B9, 0xBEFABBF6, 0x3F74A756, 0x5AE23E2D }, /*F3*/
+       { 0xFD08E5DC, 0x8B66E48C, 0x49CD25B2, 0x356BD7E7, 0x932AE9BA, 0xC0CF4D42 }, /*F4*/
+       { 0xAD61073E, 0x146D10C0, 0x15B984C6, 0x07EB3FA4, 0xAFBCA5F1, 0x0AA183BF }, /*F5*/
+       { 0xF82147A4, 0xDF3D897C, 0xAA3B554A, 0xE36AD282, 0xADB5E14B, 0x554584CA }, /*F6*/
+       { 0x84EC67B4, 0xD84B3426, 0x2BF0A6C9, 0x8BA3F8EF, 0xD62D5A8B, 0x17D965CA }, /*F7*/
+       { 0x03B5AB0C, 0x286A2AF1, 0x3DB59FB3, 0xFD8F8BF1, 0x68BE8B49, 0x5202D21E }, /*F8*/
+       { 0x214C307C, 0xD465D180, 0xC48070A1, 0x94677855, 0x5C6718B7, 0x7D664FB3 }, /*F9*/
+       { 0x0BADDFF8, 0x4CCC4ECC, 0xE1316FCC, 0xCA0A5855, 0x1E0D8CF4, 0x0C1EE3D8 }, /*FA*/
+       { 0xF36A2187, 0x9C5E64DB, 0x4C5AF0E2, 0x8A45458F, 0x8204D381, 0x4CE31874 }, /*FB*/
+       { 0x4F76AFA5, 0xFF63720D, 0x1F09FE8C, 0x88D7E902, 0x6FC04CD8, 0x5529EB97 }, /*FC*/
+       { 0x63844962, 0x85F09D22, 0x10E25062, 0x9C0BE84F, 0x039440B5, 0x8FBEBA32 }, /*FD*/
+       { 0xC447A427, 0xBADC88EB, 0x3EC48572, 0x294CE83C, 0x43E4CA7D, 0xD5AFDCFE }, /*FE*/
+       { 0xCC7D264F, 0xDB754D7E, 0x0D20575C, 0x0DD2BA81, 0x8B6ED8AA, 0xAE865123 }, /*FF*/
+       { 0x636A5244, 0x203CB521, 0x06F933FF, 0xB99B48DC, 0xB765E439, 0x8BA82256 }  /*ZZ*/
+};
+
+/* Table FIN
+ * 48 entries vector containing pre-computed indices to be used for extracting the final digest
+ */
+static const byte_t MHASH384_FIN[MHASH384_SIZE] =
+{
+       0x19, 0x12, 0x23, 0x16, 0x01, 0x1F, 0x09, 0x00, 0x0C, 0x2A, 0x05, 0x11, 0x07, 0x13, 0x0D, 0x02,
+       0x14, 0x2E, 0x0A, 0x26, 0x2B, 0x1C, 0x20, 0x17, 0x2D, 0x04, 0x29, 0x1A, 0x21, 0x06, 0x22, 0x28,
+       0x0F, 0x1E, 0x25, 0x10, 0x0B, 0x2F, 0x1B, 0x0E, 0x15, 0x2C, 0x1D, 0x27, 0x08, 0x03, 0x24, 0x18
+};
+
+/*
+ * CityHash 128-Bit to 64-Bit mixing function (Murmur-inspired)
+ */
+static ALWAYS_INLINE ui64_t mix128to64(const ui64_t u, ui64_t v)
+{
+       v = (v ^ u) * KMUL;
+       v ^= (v >> 47U);
+       v = (v ^ u) * KMUL;
+       v ^= (v >> 47U);
+       return (v * KMUL);
+}
+
+/*
+ * Extract output byte from the context array
+ */
+static byte_t ALWAYS_INLINE get_byte(const ui64_t *const hash, const ui32_t idx)
+{
+       return (byte_t)(hash[idx / 8U] >> ((idx % 8U) * 8U));
+}
+
+/*
+ * Apply next "ADD-then-MIX-then-XOR" iteration on the context array
+ */
+#define MHASH384_UPDATE() do \
+{ \
+       ui64_t temp[MHASH384_WORDS]; \
+       size_t j; \
+       for(j = 0U; j < MHASH384_WORDS; ++j) \
+       { \
+               temp[j] = mix128to64(ctx->hash[j] + p_add[j], ctx->hash[p_mix[j]]) ^ p_xor[j]; \
+       } \
+       memcpy(ctx->hash, temp, MHASH384_SIZE); \
+} \
+while(0)
+
+/*
+ * Initialize hash computation
+ */
+void mhash384_init(mhash384_t *const ctx)
+{
+       ctx->rnd = 0U;
+       memcpy(ctx->hash, MHASH384_INI, MHASH384_SIZE);
+}
+
+/*
+ * Process next block of input data
+ */
+void mhash384_update(mhash384_t *const ctx, const byte_t *const data_in, const size_t len)
+{
+       size_t i;
+       for(i = 0U; i < len; ++i)
+       {
+               const ui64_t *const p_xor = MHASH384_XOR[data_in[i]];
+               const byte_t *const p_mix = MHASH384_MIX[ctx->rnd++];
+               const ui32_t *const p_add = MHASH384_ADD[data_in[i]];
+               MHASH384_UPDATE();
+       }
+}
+
+/*
+ * Compute the final hash value
+ */
+void mhash384_final(mhash384_t *const ctx, byte_t *const digest_out)
+{
+       const ui64_t *const p_xor = MHASH384_XOR[256U];
+       const ui32_t *const p_add = MHASH384_ADD[256U];
+       size_t i;
+       for(i = 0U; i < MHASH384_SIZE; ++i)
+       {
+               const byte_t *const p_mix = MHASH384_MIX[ctx->rnd++];
+               MHASH384_UPDATE();
+               digest_out[i] = get_byte(ctx->hash, MHASH384_FIN[i]);
+       }
+}
+
+/*
+ * Get hash value for given input at once
+ */
+void mhash384_get(byte_t *const digest_out, const byte_t *const data_in, const size_t len)
+{
+       mhash384_t ctx;
+       mhash384_init  (&ctx);
+       mhash384_update(&ctx, data_in, len);
+       mhash384_final (&ctx, digest_out);
+}
+
+/*
+ * Query version information
+ */
+void mhash384_version(ui16_t *const major, ui16_t *const minor, ui16_t *const patch)
+{
+       *major = MHASH384_VERSION_MAJOR;
+       *minor = MHASH384_VERSION_MINOR;
+       *patch = MHASH384_VERSION_PATCH;
+}
diff --git a/ports/c-sharp/MHash384_DotNet.sln b/ports/c-sharp/MHash384_DotNet.sln
new file mode 100644 (file)
index 0000000..86fcfb9
--- /dev/null
@@ -0,0 +1,39 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.902
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MHash384", "libmhash384\MHash384.csproj", "{4D49C06B-385E-47C4-B206-732B48B2F34E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MHash384Test", "test\MHash384Test.csproj", "{65520FD4-4567-4A9D-BC00-AC38DC52D8A4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E9B02B9A-C7FA-409A-8D48-41BD99647FB2}"
+       ProjectSection(SolutionItems) = preProject
+               test\MHash384Test.runsettings = test\MHash384Test.runsettings
+       EndProjectSection
+EndProject
+Global
+       GlobalSection(Performance) = preSolution
+               HasPerformanceSessions = true
+       EndGlobalSection
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Any CPU = Debug|Any CPU
+               Release|Any CPU = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {4D49C06B-385E-47C4-B206-732B48B2F34E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {4D49C06B-385E-47C4-B206-732B48B2F34E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {4D49C06B-385E-47C4-B206-732B48B2F34E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {4D49C06B-385E-47C4-B206-732B48B2F34E}.Release|Any CPU.Build.0 = Release|Any CPU
+               {65520FD4-4567-4A9D-BC00-AC38DC52D8A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {65520FD4-4567-4A9D-BC00-AC38DC52D8A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {65520FD4-4567-4A9D-BC00-AC38DC52D8A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {65520FD4-4567-4A9D-BC00-AC38DC52D8A4}.Release|Any CPU.Build.0 = Release|Any CPU
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+               SolutionGuid = {F896D120-E5F0-45E6-93DB-AEE0A2A6B514}
+       EndGlobalSection
+EndGlobal
diff --git a/ports/c-sharp/libmhash384/MHash384.cs b/ports/c-sharp/libmhash384/MHash384.cs
new file mode 100644 (file)
index 0000000..3221d89
--- /dev/null
@@ -0,0 +1,1125 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+using System;
+using System.Text;
+using System.Runtime.CompilerServices;
+
+namespace com.muldersoft.mhash384
+{
+    /// <summary>
+    /// <para>MHash384 – Simple fast portable secure hashing library</para>
+    /// <para>Copyright(c) 2016-2019 LoRd_MuldeR &lt;mulder2@gmx.de&gt;</para>
+    /// </summary>
+    public class MHash384
+    {
+        public const int MHASH384_WORDS = 6;
+        public const int MHASH384_SIZE = MHASH384_WORDS * sizeof(ulong);
+
+        public static readonly short VERSION_MAJOR = 2;
+        public static readonly short VERSION_MINOR = 0;
+        public static readonly short VERSION_PATCH = 0;
+
+        //=======================================================================
+        // HELPER CLASSES
+        //=======================================================================
+
+        private class Row<T>
+        {
+            private Row(T[] data)
+            {
+                this.data = data;
+            }
+
+            public static Row<T> Wrap(T[] data)
+            {
+                return new Row<T>(data);
+            }
+
+            public T this[int index]
+            {
+                [MethodImpl(MethodImplOptions.AggressiveInlining)]
+                get => data[index];
+            }
+
+            public int Length
+            {
+                [MethodImpl(MethodImplOptions.AggressiveInlining)]
+                get => data.Length;
+            }
+
+            public T[] ToArray()
+            {
+                return (T[]) data.Clone();
+            }
+
+            private readonly T[] data;
+        }
+
+        private class Table<T>
+        {
+            private Table(Row<T>[] data)
+            {
+                this.data = data;
+            }
+            
+            public static Table<T> Wrap(Row<T>[] data)
+            {
+                return new Table<T>(data);
+            }
+
+            public Row<T> this[int index]
+            {
+                [MethodImpl(MethodImplOptions.AggressiveInlining)]
+                get => data[index];
+            }
+
+            public int Length
+            {
+                [MethodImpl(MethodImplOptions.AggressiveInlining)]
+                get => data.Length;
+            }
+
+            private readonly Row<T>[] data;
+        }
+
+        //=======================================================================
+        // CONST TABLES
+        //=======================================================================
+
+        private static class Tables
+        {
+            public static readonly Row<ulong> INI = CreateRow<ulong>
+            (
+                "0wijhYhqPyREc3ADLooZE9AxnykiOAmkiWxO7Jj6Lgh3E9A45iEoRWwM6TTPZlS+"
+            );
+
+            public static readonly Table<ulong> XOR = CreateTable<ulong>
+            (
+                "NzBLQQDf3AH4lo4bZq+zsSExOdtzKE2UVecqZjaa2nOxVstOjDFPH7ylKpzZQ5fw", /*00*/
+                "VMm/y8a7H6jb7VmJZEPeOS+CAdoLGmQaWCaTZnJgLrWEIICsMRdbLNSdxx9nEO/C", /*01*/
+                "RgCBCI6NKs/2aOKJIJt+i+wtXSxlYQSTuci/IyLklvBwCf5MljjTjb1g7HwvNJwm", /*02*/
+                "UgXt0iCpcLnhp00lSokPAdhAGp1fIF+NWF/9w8w9w1BXLNjnvTGftDOQlSr2BN58", /*03*/
+                "rIScK4Ky+knxvozWjGS4NN4mQbtHERLlD+D/slQfs8AyxoyOoz0ZL/yKm0JLmIwF", /*04*/
+                "QpmMTaSdf+DyZcqas/kqvpXCbUaxjz1dx2L5wz4eBcC2K87UzMP9+DeZGcbvwCSQ", /*05*/
+                "7/UB73cTEaP/owJsNpv1MdwWDXZJKbhh3zu9kq9YufaywGns76qXcs2Ehp6tUIr+", /*06*/
+                "oJrqKcjQPT2jx5bsfll3PoQWfx4jONCP4O23HxN7YWR0WEDF5JzJhePFGR/UNYel", /*07*/
+                "mhv5yopiKIBkcMk4BWRKGYAWT4oBXqEEVQk2wgQbvvQgGljvTE2y352HFf2g0Fk8", /*08*/
+                "vPGK5+zi+IjCZHMpIm5rtPOZa5J/8TmTfPC4s4k0KTHxvMlJFs4JOem8Mfo7EEYM", /*09*/
+                "qeLvx4wLGk1x6FWtjIfXr1NBz1jI+5zI1nVPx4aUc8TyyQoTLBn3C5q9gV688oQA", /*0A*/
+                "z8pPAXXp+0rkQcz6jK/eQekW7VM7wh48SDIcD7NusHhyXCgEXRYR3eSRlGC12UZl", /*0B*/
+                "YNLITeDi0f/O7HSKlIaxBzHFGhJFDhK1hQyBMGPIC70wd0jb3a+T3paRuW7esN54", /*0C*/
+                "VbreP6yiunl+VirJ4eO3sZQHW0qraT+l3W1PlZl02vBIIhPhiXwRWG4axZT39V3Z", /*0D*/
+                "MxwJZQyKvInCNTEG7upOsInmtkrgZzL18ot+ILd5xbTf0jw0UR7TP/6XgS8+Up4R", /*0E*/
+                "LfNgYBzLEC5ja06pMueSvGdC0B+DDSLzf+i8FHRfLFBXJB3pHWXgiRXZgkSwVp51", /*0F*/
+                "A+iEaizjrkPj1wssIAdQDCrTBUJHZPS0Bmw43pX8F31FpXpWZL/f6G8EU1idiL1V", /*10*/
+                "J9q46hS+emhEw3INtTp7OY1h3h9tql5QaT+hXYZ5vmEtDum1Kau7Fy+L+nIZkgwB", /*11*/
+                "U/Rv9aQjcovhb4u5XHsbKX2/b3glFkL9yM3o0CAQPeOHnnOLcAxTyi+huATz8YqH", /*12*/
+                "Eddt5SQfzn7fpi8bJGkILv2yWcTcNLiEO32eMabtIuAomTygjJ2DWXTHu5H0kEdk", /*13*/
+                "Dd2w5klv3MsyZzQAjS+6RBzmalghyLyGW+XOhRJJt8dROH/Z/xI57b+8vr6GAa/0", /*14*/
+                "FuXMTuVIisoG9fi3ZBjfvqRqs6RgH2rV2dkN/rVasknh/Eleu303IeeZndX1ZI9w", /*15*/
+                "LOCvaaVz+OmQc5nKBbxm2oVT01ZHF4iMMKf99GzxquoSNTplVXqfs1LoI7wntwrx", /*16*/
+                "r+K7xfhv6ZN86VMCQoV3pEwHfffRJUtwnFVwFD8JssDPqmTj1P1bjfcbWz9nGAVV", /*17*/
+                "yxroWy6DrI3Yg3UrIPuLWOTX0d9wik2jPgOHticGO9DPddzbfr7Q4+qLn7DF6I6B", /*18*/
+                "MX2dSOECO44yteNkK3U2U2UKWFx5zNTkfnbtE/MIq22/Nrr9iH5WjtAz6djxkJQl", /*19*/
+                "Yqos1tA3tOoDsIK5KK2QwOwEV9Jo11XiQ2ol9hpRSKBfi0lNjwef5/5Xs3X7NRfE", /*1A*/
+                "nfJPUMOf2nAl/3OGOB+rubpXc9FML5I2SuDnkrI6nPDsE7rZwwvOkOONkTymTHxk", /*1B*/
+                "iNbs0Y2jNNhqq0beIAB6qR+nLub2x96cfsRN129aiijxUM5lJy5K1DxPntu1UJu7", /*1C*/
+                "5vLdQQ6pbcYJXAwWb+g/Wr7MCFFA8Gpvf/wnti44OPlsAH9hNNY9FpeEkNz+sYRR", /*1D*/
+                "HLL8B+0ZV8nr524/BN8SUc40IwFg/flQeWXZBFGon1inBRnXRJ4St41SMwdudhQz", /*1E*/
+                "uHxFxRSAbNy2aWoozf011r8BfeIsI2/WD+yC9sBKr1b1KEO2VR3fV8rKhyrF1B5l", /*1F*/
+                "AsXueczR2Sb+67E0CjS/aXRxOY6sqqX6b89rQr35qNBSJG1NRh8TW9rW0GBW0S0S", /*20*/
+                "L6JRX+yaOG77J8FUHI/2fjBcSOBGTW2YMYrP5zl7pPCPp/K3/Y05HS4NsfvRUcYv", /*21*/
+                "sNxJG41OTqRD88JJIIKkB7oFZY1KwArEbLEpBz8dudkVkA+1UZnzqnaQP63T9W6W", /*22*/
+                "CdC2DqzLeOqr3iNacqb+oNmUy0R0nHLODaonZmKUqUDVGNDjzTj3N8WzzQEcSSlM", /*23*/
+                "eshFp66Sl3zUj73FIFb/0blWSwDjhMqe1rEowiM5/Vo7KP2znvfb5Z9LCFTjEhdE", /*24*/
+                "vEni2IsoXePlZqNTFGx3kezvlU5o4dH1Bvbd1xfhCJGMfM6inQ+zgQ2MgYbX25dk", /*25*/
+                "4EsERf+R+MLr4ocrbaehdb/C84p5Zc6F3An9TitTPyGIbDql9R2qDbIm2FBqYCgw", /*26*/
+                "OvN5Y2FimmBtUeRTvKM5o+zbWmphkq3XqiTphm1yQ9BlmML0ZLVVhbDWwTGrEqpW", /*27*/
+                "/3vBwYXt2c7C/7qsJSNS65RT0bL02NME6m51BExQcdLxJ/gaqaTbLeQCgI/C1Wcf", /*28*/
+                "j8AtQ60InIvHu5aX4kN1Wt5nGTxb26Y05E6AosI7bgF1LxflzMqbW7q9rYCLWUl1", /*29*/
+                "VdHNxRexP2/F7tacpbDDFmmHU94RpKHZfMNKn5dUjJPbhFLVwbw3N7drFfmKn61s", /*2A*/
+                "3+t1nE8ov+voPXUGtOuDszxAfO56EoaqJ+A9UhDdvxATikrrxPaLE2eweNt99u+x", /*2B*/
+                "Xtqjeo0T0fZxY7aPjQmouvKqbIsbbefa3B6NNjQQD0B30uhyUX+TfO/mrTz4uwV9", /*2C*/
+                "gbA0z6YunA6gC/ZYDbM2kMqL8EhYLDrbZNVQQrnReshmYfnuCS6JfPOFEFfPhdsm", /*2D*/
+                "KsEYh/XjHiXkKooXgY1D+aioOZCImpLw/cy9XiJla/DGc7/37RRNLs/6HbyVmDap", /*2E*/
+                "y3lpHbQC48oj5h61WFr6uy+1GsiduRNRVqAX7Ft5k2BeNV4uTftxj/KiNLrtki92", /*2F*/
+                "/9mkZVIBMNHIJh/XU6K+CeYhZcTt6raBqbiCVhZo4vojtkp3xD6cqLKdIVXgRS4N", /*30*/
+                "q5Kmw4QCViu4p3mz0IoAN/wL+TAszRGv7WInDyV66H/DQnJkEdf7w70is/Zkgu10", /*31*/
+                "Qzmtp8hcGSjET0xGCOjLUyaHX3Z6PY7VT6qFAfZSMNjntDsihQ3L7yisf3heMDFa", /*32*/
+                "Q5XxMOIOXXLgNN+9xtKRkAFGdcLGSb7ja1atpAswvmHBfPpRdZ3XAljaHF8PkUNl", /*33*/
+                "P7SBRMStmUCB69kvkmET/qzOH0SewImpGZDL0xM6m0Q0ESBvOb6pRf4zZgRa0Brc", /*34*/
+                "aT4vUm06VhqeWkefB55YvjgATI5jqaJ1YgN6VwJiO9r2enINHj8dITOS2ZpS/B9e", /*35*/
+                "G9DWxoYetkcYw62tg299Q4xz7Y0CYaPVSxYlBGNMDaDSnUyvpa9pGoK1UflnHJ75", /*36*/
+                "eeq9tkB3aqajgK+WFP/3/oyJzeo+1K8FNHGtMe14DLBzZoTXGhrTDr6ZFBZEaLl0", /*37*/
+                "LtH2y2yN+kZWOTB/FPzCMX8GX94BRH9w6ZQ148f+5ToUF1Njip/jKLLKnx7qKbO3", /*38*/
+                "BHhcglX32O/RDNMLh5NaHxaH/3FGib/vWNor8n9h7SgutlyuzIkSQfnyARj0Qt2V", /*39*/
+                "4Vn8RYZbUqgMf18KwC3mdawWBCGFZ8UJJnYNs+l271Bl1vUZ3Cw7K//02BHNlxKk", /*3A*/
+                "OVDunmSayeplADwUL8mTpQYSBwNScxSz7KRkx6BhJ+qzJaxs1H+qAr8DbamCwYzG", /*3B*/
+                "qDzITgI/h7LrU4j9uApHl70Fs1nBFf4Y/erqh/YIq7BDLmBz3j8KUfD88MxNuOED", /*3C*/
+                "2MAzgNy7W9hP86mcw9kjkv3DY1ttyzt9tQ8M2nT5MBxDUfu+nrwki/yEe1uSVInF", /*3D*/
+                "p9dECC58vWoNU99sReryzLghOSv1jJPofGWB8qI8Arqu7dF1pl1j7Gy+4S7yUqq0", /*3E*/
+                "BFnLd8Y6HJhJe4eETLWSahVYxUC7plt07XGjIg1Vr7d0U1/Gh73o1fU49fA3Sodn", /*3F*/
+                "IcDsnSq6O8JQNA4Lkw5hTn5XdxSpGmgadsPtFJcgozi2SuvuY1XRD3gh1AGKZld9", /*40*/
+                "tZigReGM+GpGi4vYjIXrGujW4rivM7fo+uunEIyqPzHqfFV3Xjd9ElUhLwv3or2W", /*41*/
+                "Nravj5cDiexjlwdcQjwhx3zRtmoDhAN2SR9fOCY6xuD1bRqB1neYKY24BFP8kG+H", /*42*/
+                "Frrg1sK7+qa85oAAZMlwm3uymFUm1bIpfjnkJsdXlkrVeGZ2xswBqJiZYXLM9w6A", /*43*/
+                "v5BUz6gxWSOfh48OjvmY56cM8zic4u7GJAA+1fJ5mpJFelhJJ+HyiGUZiTiPsoUL", /*44*/
+                "J9ik5AMDXhZqQ+jRQk+ZZxsNE27Pi8zm/N6dcBEXEFAoU9AMxN47N/YJUaqkdLJA", /*45*/
+                "yPj9CKCL+Kla4G5H45fI7HR61WmrkOK8XRHjERjbRPqIDEhk/a5nYuvsOi1K0Jcm", /*46*/
+                "EzPNq/IqeMBzYvnykBK6ArnCrVYaL8hjxFH+PsDo+BD9r8wlhjTr467nuJyWB9aT", /*47*/
+                "vI/lQ5QXbszuuKdVxpMc0qSLKx+jNJgr7uwlYFFpO8iUrnpCe+t2kW6ntzCeW7aM", /*48*/
+                "idnt1go6o8H3tRNY2cWzGIuaNTsmvSSwUJupFiJ8wcgpdyNYHaH5cZBCKBh2fKY6", /*49*/
+                "exwgCV5Gt5mB+qQcoJ/4miPRGnY+xi78FH2xhZWjqeKBTvkp5U05CKT6lJfmSJRH", /*4A*/
+                "u8q9TBw9yiPkNxrONlQm48lMip72EL8bTVyPBAhnpgX+/luc3dxZ4v1uk/36ZZ5D", /*4B*/
+                "nHGPl7ZzTaKOu7DMQ/NTP2p84J52cjy+3Vj1nFOey/pqmN4wTh25ZzqRmBbRE7kd", /*4C*/
+                "xsPDDRROvZjoYzK/khUrFA5bCe1ZrL7Naokl9vBjB5A5TjIwD1UT4pUxgHpBpBOK", /*4D*/
+                "c2BijO2YzSo4Ms/EtKaqHF3rd7YetNwEaFsQqERYi/hNGgYalZ4dmNuOh0yJcZS8", /*4E*/
+                "vS1sXa3+WUlJMFCM4lm9ajSLr0xJxdIGPCmkBBNU5HAD9fLKFjQPUoXbEybZCT2y", /*4F*/
+                "kRctwxWotSbGM7BbVeeZLE9RAgBqnc4Jl3mNKysohdTGFEpKL3lbnOe0C9wCnR2F", /*50*/
+                "7GCwz8q2/mLqYcbVaX2XnVYV2AbY7wi/GFfqYKTu8SVllloftUZTonSijDXcmi/Z", /*51*/
+                "pv/oY/w95iej/ZnO4sy5zQ2DdEl1W52XvpNmfUDImDK3QpujrV+dYuGEzXES01Qm", /*52*/
+                "PFhu9tqkH6tmR9I2ore27rPG9f3NOAepTC2OZOWpyyijDf4MbL/l/YWE19djuACd", /*53*/
+                "qhbqTgm/+3XyKdd8Ah+TSH8umwB5BjZdGuI9vUjR/N3h0JSwRPW/TSIsNZRiXA6c", /*54*/
+                "0lOIlv8nOijyAw3qbAyWsDjbc6QHuisXu/TmltKHjGgPz2hdvOm3XLS/Rw4b16VX", /*55*/
+                "L//kwaoIAd6ZK8bqq89G0wj2tZg/IC63vilLpYw9hYGAFqqfyNeupu3XOVwVOwnS", /*56*/
+                "hEuX1JmsrgvatMmZpljyx8H1zEpeLGJvqr6Bl305q1jj/wHhZx+Bv/MOPByIwryv", /*57*/
+                "PmyNUfsRsiZKeBAa1dq6ZGwYh6UGTr7mXM1DE8b1cdRd7arWDbuJg32hFIlnEoHI", /*58*/
+                "fdKIu8MLLSvSelH/+tGnxa2Cn6BWkPOWTk3tbBqmOPtksvmmTo4wnbPG7EopzpeQ", /*59*/
+                "orGQBpUryo/fItQDv/w+KatTY+ezJZGMcwGnoZIgQD129purTJerm25YjF3F/Khe", /*5A*/
+                "jOzhwuiSjEBQQxu3FMn0SmkQ+83groZRZ3xlufrqhSOAypjI0+QI936QhJj4ucge", /*5B*/
+                "eBgsaouV6EZHpngPQf1yIQSQKTrYnY6dJdBaJsMTCTnxy3cw4vEx0vPXgE5XPu7n", /*5C*/
+                "skBe2KNnhVpzzz8TYfHsFtcNPLpvXNpS+0uz3oN55VZT0Wi33E8lgy24xjVf+RSa", /*5D*/
+                "5kqd4cYpikkRuidg9Kr0LgWV84Sqfbq9TZTc9gQqC5RTDfwQVtN+TuFZfpDClN26", /*5E*/
+                "gF9HP8QP3xQv+EsmjariF02Ti+XfW2KSgeqspBX0hIMrZNjFrl6cjodmghxf9Y5N", /*5F*/
+                "2Shx98Q1I0qUuprSdhROVERQeCFjyE5lWkSAL7DZSrAg0MiAZBvgsL/Lo4heMm5Z", /*60*/
+                "YtBIdBVVaYlobSMPTIywDaLE0Txb/Kg7W1NE4VN89QRAaOR7zE3Qt0ZGM5Ixmb5L", /*61*/
+                "J84Cq+Y3eB2kPknUrlujPr76lN+1/crRTwwXYruAtZhDHEKpbHrFwzQWIMHCX9Zo", /*62*/
+                "NnVxSLy66voVcy/26FFCRSPFzf2n6BizRBPJEyCDLnxSkGnRr12eTac3BYeMLiYS", /*63*/
+                "ogKE7wtdPooJmQH6+sU7o/ViB9Cs6MtjeEGYgfGjJuq79kq70Xjrbl+EDjBxls9+", /*64*/
+                "/ND1zHy2EQhrvZY0P6uMny1cNfEkfctXgN5bFpSFIVj4eDplijbz+mJ3JnYB2EzA", /*65*/
+                "sCOqWud8QeZhF6bL47+nNO22yfiW4xOMY+0JS0ZmkFyD4lwsZGrLdsZJtD4qCI5J", /*66*/
+                "oFp7NabeKm9pe1UVKzjaVK56I0YZ2Csw3P4eEYK7DI/T8iDOrS3dRdjRoujppXeK", /*67*/
+                "KCqGNScz7OFEfJx+Gou2kuNj6ZncGFb0cxrdAkWYrHwNhHDNmAVlyP1ObaKEpV2a", /*68*/
+                "XMFABwGbsRaaQxYQwEpUtKWZL56cdB8iD1dlmieKPqatctCtaRYjxwHIC3S6NbzF", /*69*/
+                "lIY3T1rnRGxHdleKEM560tYVfvr6h8QX357iyNVUNmr6H2HM7V7jDJNQCcADjIrY", /*6A*/
+                "LB9LvEhpEM8Sl7mQmdzAkTKrCeHjITsZZhbdCAbeQDMoKGC/d7ZbinG3lxELQSxA", /*6B*/
+                "PlSlnPQPCOsnytZClUK5tAUyU8Fd1JlZPu8bijme6vfG3nZUdxeIvgBByJB3TQYX", /*6C*/
+                "1vinUJGOMvP4/awEG+bjUhWwzvMQINhR2NV2ZjNz1llCw5Ed77yzTEm+M4C1mlgM", /*6D*/
+                "VTjg3A7nuFRX/YeW6ZC1e90fK41oCP9sT5n+iwZtD/1ErokkMM6b6+TjYQYgH7Jm", /*6E*/
+                "rWmWGGAAXi/kygA80PE6R7Tz0WiSKXgC0sl+OrwUh4jZ0utx8Mf5nxDb/13CXVqH", /*6F*/
+                "2JmDRj56qeKhDcgyyur3Ox0jwraOrNwTl+4CEQ7JfiI0FDjwMkg0suuQsQODiBOG", /*70*/
+                "/r8m4Gw7PTpZ7WiaO5XUGKB3t0pXe7sksdyDSdZ9y+CXrGmYQ4x2zzNgDpB6vGKA", /*71*/
+                "xzN6irfD1DnrtLAq8i7XQ5QDpd2Ega5UNoXDg6B9Kgwi2Eodkm+8nUKqLhj+Ybss", /*72*/
+                "TdILbICazth8ckVYpmWd9kiw8nbMgf/DWM5nysP9sXaK58v7CpfQzvP1JrdBKVBX", /*73*/
+                "+fzOf8GuBuCRNQCeYqHKBRJTWJ/JDAW3kJQVHkBgkmZazFenWtJChAx3OEDNVYYi", /*74*/
+                "ofPx02eN7pP01/jbSG2kvjxFRoYr8JE8WIoYBB98PWyE75z4h3Kp70v/ixBONkDL", /*75*/
+                "JfhPDXPj3MaQJ5d9+FSvAo94T28P0ml9j24WTMZVwpCiyflLv59So2tPaTYRxM4+", /*76*/
+                "P3vKxl4K4T2qrIXQgWAZfvdgXXDjDV/fdXDF3IN8PjmXj7ncwjvzpcAEEg0Ff+sK", /*77*/
+                "BbyoET07O2/cuJUrq2kitRNfOLFO4u0S4bU2WGu6KyBJzFqSxTY27r8Jte72TCJC", /*78*/
+                "kpq+xLvDDF8u3VTM/BNDWDZAOQAP6R/BI5f8cnxmcTOfjaxiC5kRlq1/MTzrufxM", /*79*/
+                "uj9KiQpSjspAzJgAuNGevXx1898HRfK97DWN5nLFrkfkc7MnPVLU86sFOpcWHrEa", /*7A*/
+                "fYFrwqaTwv8o2FlJE52eLL+bGQhkIaV/YdjMDd4C8KZd8yx/xZ2Pvkd2pIbf4lIT", /*7B*/
+                "dI5wAeFbtYQ+nyAhN8XeOr2t32gemo+xLc90l4FQoAlihwo4XSmr5J8jnGgMW2Cj", /*7C*/
+                "j/7fvx8Dx90KL4Nb5l0XC4WWcWW8KhYxsTa8S1NeIVFErgFdO30vnxu2g25CokPP", /*7D*/
+                "SvAWK2fbMn6It2oO3kVvzkEL57hIhXElxPqgOc+LNtdHDIhJ7GNolXQWNJZXMw5y", /*7E*/
+                "xtbZM456cAbGdtVs4r+EtmzEX81efvREt0TYVqgjG69+ZcVqkSemmBl+EqFkOQwE", /*7F*/
+                "m6PANDHs2qUf21q9YEGgDMsanvKpxQ61r7/3ahKhL76zpMXJxAr8vinrsR/HOUeZ", /*80*/
+                "Y6eDPjQt7G8M9VdXcaXbW7MRauQuKPbWJFUqkvUBtajKBbYGEKKCp4Fcl5bo0guh", /*81*/
+                "7dAmIlPgqri3hA5HwDEYiSj/6EjWJMh06wY5rS7g5LUTp2Daagi7WvEpnmpmVwyo", /*82*/
+                "CiPnsVI+nlImjvDJYYgUDD2ArRsTivwMn6ovkCTzCYxImJmHSe4xAldUKy5JiAY7", /*83*/
+                "zRRoA8Xqpu/1XaqNHzx3AjHeAge97U4O70DX0FfXf7qLXwB0DF+AqPgePv97RkgU", /*84*/
+                "DcdqAWa3ByrpGUI2NVwhZPH2/DX+fm/NZ5LChGDAXPBEpHkl8/I7q8m5JZot9HWs", /*85*/
+                "ZITb7bUUOu/p0C0tgOAUIyp2KPmprt4UAlrhgLTrY1fm9c3oFMr3JbzmYdwQRVmO", /*86*/
+                "CwAh/dw4LOanPe4X6Sqze1a2yUziFZ/k2GGj3FmC4lZIXyipCIA7tBvmSn6vtMYN", /*87*/
+                "rtxCESRkPHA6BkUsNDMtc8tnRWKhfoc3FNFNYTTVcSjR9ZQdKglI57ccbQxvBSRF", /*88*/
+                "+V1ZOoKxJeN8OW/J1Q0tdFH0qUCVHDZEuR8z9psvOAJnBBrpu6/LjqgE+RE4v45S", /*89*/
+                "DfsxRlPGK/1smuv+NvClJ3UHHZHXdvjQcgtunKKz7xKhHYdePcpL3G/0CObmto8C", /*8A*/
+                "SnsKk8jsF+89J/tyRrOXnY9dojVfg67GWx/CMJVGJ2yV51Bhoha8LxrHteCqk60C", /*8B*/
+                "Vt0Hz0O+JG0vKo2jYh1oY6BKchG0yXKYCmkZfIW0grj0xgQojbqxh0kL9DbMmbHX", /*8C*/
+                "D579c4WN++4KVpGbGQM0k4wk1WUWtA3/lkGY6gXhLjKb2JA4+OCM24AfkDyY+DI6", /*8D*/
+                "rFshP/naLAisTye5oRjBZ4oZk/scUHSv0xLooKtcUlNuiv5eADqvyf6ypw223ELy", /*8E*/
+                "3xRzu79/iNNCwyD38Mzc3RXEyDMcM8SyW3j0ZwcBZhaH5F39wbdVhPJ1GBjqxSGo", /*8F*/
+                "8GKFQTGYKH7DhbFCMC7RKpaupjXX0CB8Qb0s4pjvi6ZDMtn4Ih1BoTgvPU9A+xPY", /*90*/
+                "lEJmb6fAP+HL3f332ckhfvix1mazaB4WdDh0tX6Vv1Vm12SD7xMystRDZvmKuZtS", /*91*/
+                "M1zbqt16bQMuAy2AX4MlBfK+otfY0Pd9t5Z2skR2koS5tfnR5CFeIf23DsRpNnR3", /*92*/
+                "hHeJ6EtTs6mQUBpUg0L9W3iXHBLN/K+Xx4l5Y8nERsHHWdrLL+cgCE9PrqD04iZV", /*93*/
+                "wr1y/SCec6SmTKXBpeVubVxOiMtveqlwSJyXnjMIYSunI7vWMDemk+VeBACrzh1b", /*94*/
+                "24uM+OQUfELCmwOOhjCGHRstUFGiQNszPStdtMzJQ+AtewfutmcrKSp0TOK9Lzoc", /*95*/
+                "atgWcPNp7T3D12asE3uUmpyzTN9Fhi2C2hCe8ZgPoivExCpCjRMDZx1KoI8T1jSN", /*96*/
+                "LBF9JYuc5SjPn0nFjAZHhxoZ+YC3bsHWCK/3MxYVFrTDoaFrDeAwotKDW5a5bwb9", /*97*/
+                "N/yPfxu89HDcD2vlMQPcOL0LK62QcqupxoMHPTyXB7MfEcrN9lXEvdzwuBeD4PAj", /*98*/
+                "D8WFkk7C7grOGrYzeKTNOyMH7ln5hpmDuV5/jUoDWcm1T1ywBX6t1MQOep/Tozds", /*99*/
+                "By2/DyO3JwJH7StjrdLXKNDvElCLj70HQjRA4DrUoEihSRR/IDmJmxny/bkBrR41", /*9A*/
+                "Je8cMS6dEad5BO3E0CxTHgsK09h4+HIiQkyc7SxBnHb13ctl+vsvJo426iFn2HPb", /*9B*/
+                "sty6Pwvp20tX6m+NOuwkEwANhTDl+55t9Mik+K+IGkAcJy6Ka7dcZUNv4b1tW1A1", /*9C*/
+                "N3D1I37lFW4m+sFic3NiSQu4KRgtN2LJEWJN6jJo/qFjd275B+MmZ1tQdxYIYccE", /*9D*/
+                "ZMFvijr/4kJosiidvLKF+yg6UyTwz1nFzrPaETk/yC4nanOdSscPrs9Mq4sE3Zzb", /*9E*/
+                "ZecgHSJSnNcE5zyQc92eSUmD9H2YbQGbwcUv0Uq0+vz5/QC485MSgb7OU8oZxh1R", /*9F*/
+                "3+0muHjuWaBayBdNKa9zRrWC8k1OfVJe41z5kyaaW9uW8lT7BNNRZcwvkWUNtz6r", /*A0*/
+                "NYHHtmdPDH03TTDep64MOf6U1Mirn+FJFkWgN2Qbnhpa82qrvcRsiP4C9URzISkF", /*A1*/
+                "7iy1QUHz7Tw/V1NHkrozgVoCZrwivjLLszxA3oMBSAwxz98ntIRbv1YhI7CNQlFy", /*A2*/
+                "yyWOxTHo/IZ1/MtF/j/EXL6Z8ULAfIczHC7CDH/6EhIjmB99S6uORJ5Zp586NrGn", /*A3*/
+                "bRDloO0vjC0/67s4aDYuGa+gzgqmaiI2apLzwV0o4efs2YMY+nEDkGbrYPMaO8O6", /*A4*/
+                "4+C9EhahotS4TMsUpg2rgsb0AaxQTZoYR6b22aFdauO2EWux1iAx5HhT5zZCXzl9", /*A5*/
+                "f4fzR81VwcBxyjTD5b8DS/dPhEsfD3F3xY0Ocqu7QzQGNIbFaIg/8FDrcsgRBdYP", /*A6*/
+                "BmMotao9JYyslmFK9Tikml4soiPHCB0YoRA5jshJPGOwdSaZZ0r1yXbZOL2smN0f", /*A7*/
+                "96l1ddqTCKEYoLJaAkpfj8D/azPwOAXYb2KJONNRlw8akb8luT44MGDMGc5onxTm", /*A8*/
+                "mAW+xrodCLmSFMdpvNldeCsXbqUMWgOLiEhyADV4RolpBWVYyVcer2Ei8k+UTt7h", /*A9*/
+                "0sAYJ03cXurkilqhTV0cyxUwFviCIyfGzlR7BeU0qZQN0Wg9GkiOZaBGCuUpSfLo", /*AA*/
+                "zYL0GihG8X0Ge0Am52hLAbzdcIyTZOVsotqlct7S2jaAKQuc9jtXbSkDqrQUq01o", /*AB*/
+                "X4tzTgbcaZz1NhxavRbMgxIbFG5eNpup6Mz60Fr6SCdJnNlHoHPQJgwMW1CCsQWw", /*AC*/
+                "HP3QDqKithUlWtabcq8zkxssvZMyM8wi4YtesUnZJNcXcbkSBdvQaTxl1w2YqKyF", /*AD*/
+                "8rN71ynGDiOyfCkdmVsRQ2/HUyx5Vfmip1vi6yhnp0gARDgFpGLmfGad9Gt+a8Dd", /*AE*/
+                "C0FEdr253SAGjC76sZFjBQB8Fs9R3k7KcPg2BVUrYEb0H8KXJWdAUEuE+4pu7PgK", /*AF*/
+                "g7hRknTFIwAAfmvWhk9aM4/O+j7tPTWu3jV71iYFyD9TvIDa+3iQDRRM/vPfAHlG", /*B0*/
+                "E4FEar6ynA8pWJpqG1SN4w78VPPaUzln6WmFfyeKgTw7KhLbd+oWjYTqthgDhgrk", /*B1*/
+                "UF59LfQRzniNmZwZ/233hMs16TqOV5uZEjLmGywJ/dnYFtOsYzzzMQxc1rgwgKBa", /*B2*/
+                "6U+onOHbmAA3IRTRF2ZC4hvieGoWxMNj5LADPjVFsXTECOXqJAg89CpgKCVi5sFY", /*B3*/
+                "b2pC0ebrJ55Co19rCmBqKnADqWsw4veP3d0+aBrZg9+IUyLwQiRXKQoyN2QbD8zp", /*B4*/
+                "TgaW6IDzTQWkiK2jShq4+m8VymxIJnT4YClHN4I8G7sKlj/3fLjAfgh4D0fm11dc", /*B5*/
+                "GkphrAPhWFffWBP4hu5qdmo5dNxRuj8gH3LFafk9yXiXZRkw4jKe5lu5is3Oxofi", /*B6*/
+                "l8wNDMGnBipfdKZoginVmbNYSHe7GNjyhthkTw2CKtWBOSZ6+I6AL3bGR2NuIJG7", /*B7*/
+                "RsfgHNfGRwgRHnxEG0X9hsxvheKwIwbCHhiYAy363TpGazNroKA2Z30lsbLuCsfR", /*B8*/
+                "dpcaFA0mM1bbo2xZX4Aw1UbON5T2PuOMiHB0fulULfbqRZtIGJNc38pQqAuf0qqk", /*B9*/
+                "n21/dhZ7vb3dtrfxJ4SW9+52UrOZZcdYkdetbH9Mbyh7EUIXQMCIgWPRZkKW8cTO", /*BA*/
+                "JFsTtabo5Jd3eSnlhdeLirvFW5egwUVFfeNZn73j+hMr3pEOfGLVr6nhdIR3rCOi", /*BB*/
+                "O2ts+OrxG97+NQDVrKNGos0hatmdF4BvAw0wF8u3jT9sUJRdi3l6SUHoGvbG3FKt", /*BC*/
+                "C0QfjtDhpPTgImTVPGMnXiAUtB1PwWUUwjeNmEOQk5pos10k+lzmy1Wo3SjerkBj", /*BD*/
+                "VCSJP1q2eh+htb5+FrQK140CwiToMSabvBkV49572dWMBeRJdMct6v+6L20tTyDr", /*BE*/
+                "XWaicZHmN2UjP1pDNfjSP4psLWI+3dWt+EPi5dXNIsWiqP3b8yfsWkUUDlftZXpH", /*BF*/
+                "Y50u0wHLpztrQbXnNFcznvY5RfmEatkODaf1beTizkUc7K/p4S4U3t1y3E8cEtZ4", /*C0*/
+                "dws5U/YKs3u2e49/K085LYk0rxPCo3cChNBW3XTm9n1RJMRzMM1DVhjcodGLX7H6", /*C1*/
+                "iw0V9atTtEKM4YgRnBA/kfk7tB9jt3vCGYQQ74Xm3evqM23Fh3zWdoTwQK/Ac+yV", /*C2*/
+                "+wv1oVk95LwARtgEyidwuktkvqKY22/7Su09mX533tU6D3HfHp+j/EGIjYU8ieWl", /*C3*/
+                "/Kyu5nbHisbrBmGGx2eAU+P9Ti81SnvSeOMBv7OifYRYbZI2weN5PBAWqiaHvFf5", /*C4*/
+                "EsbHA0IsSZX8IYPusQ3WDUIr9gKp69nh8qQ3Dn2/LepI2vWLCbkf4TijjoE/If7b", /*C5*/
+                "3VZHbTEhyxdqFECBSVKJuIhChID1EoFkNY/V98OtR0l3U2riKM4cZZv4N/PaAzgL", /*C6*/
+                "47bm3OIWq77fcpHjyOw5jw6c8j9VyXxgpwtPTxUV/UvkjEC9tjBi7plOFg0RVLY1", /*C7*/
+                "1BzB0hv/3a2gGm66LCYaKkZaRwkdKfILMt70raugk0xjPjMnE47ucyg70fUxIK7z", /*C8*/
+                "XKXZsqt8bCT24B4sKMfpUNfToGWVoL0v66QEnGdSZRmC3aYp2mZ8E79W2ktra6cI", /*C9*/
+                "EIbi45vFo3xI4nofz3XdajVkenNQdHQBO5K0spwl8qEQcs6OXvXI4Ju2UPOYQ5bX", /*CA*/
+                "AVGC0U6GReDFoeGTkZZUrMeUB02TWtgjE0JKc8uI+rT51aO91r9cfCWIdDjpf2Bm", /*CB*/
+                "gdSAodJv87r3mJUbrEDE6mywt/+ATaKaY/FYc1EfYHk7totBMRgH0QM6fa6mCZaB", /*CC*/
+                "UeW6zdhSkT4W0D0gP3mthpGo1Ip36zq+GGZr100lECgnwzZm481dm4zFi4ZlrYoK", /*CD*/
+                "KhWTDXhyBm2RgIJ7JAXn7j9GN/F2ub2ev8HQonM+3qfHagSgC6Bx+IY08gOolkxI", /*CE*/
+                "+78Gu9q8xw+zCWM9+z9c92KREAPRBaPsYf9PIDtQPzeiP5ZUnywzzrTNQiKlIESa", /*CF*/
+                "wZjReRFIHcdpJenORShaULVVZ932vznzRZLojSvV6osryg2SZW5oSzeK5j6kP1mZ", /*D0*/
+                "ARXmF9doCtmmYZGhriC5m+SxDtmWbz0vfT1RELrsFd8xGPC0OdXl5jbO/ih1etHH", /*D1*/
+                "r/vrtL7wT6DKo9o9Wwrp5UWh9AkiVFOEB6e1K9f/poBqvxpacMTgFH1nisEf7JnW", /*D2*/
+                "dRUY4yShIXBflK0XKK563FpWDX8eUrWL7gUIL3nTcWYaOkGUo46I08z5W7VHfk3O", /*D3*/
+                "aN6qPCZA9CJ7rC53h7J75+lAKpZ1N0kpG7mMpn+iBh7Hub0qkwLv3TNSF9yIO/B5", /*D4*/
+                "kSM+tRfV9mU5HAvwomXbl1VIqoWbrncdcQebPps7ExnUs30a8dl2Y4Rh4Vov0JqU", /*D5*/
+                "O5Kd4M00RP5ScDtx/fywAzhyptSQMnEtlu4p9m+UVisoxLOyAV2hYKAzOXmvXh0L", /*D6*/
+                "S0kNDvv8QLze0bPHSEYco43sB5ohPBHxHL3CpbG+eCOUoXCAR8MMGSlj9czhttpj", /*D7*/
+                "kb+6gp5rG5ABENZFTCMqh2xtzMGVaqRslSLw4BWTdyKs5ms0lpOlYEaISMsDpWf7", /*D8*/
+                "C2aXTPdA1FAM/u1kv8oe5yLOGFeJGyCABtM1TYCJXaCG0LCiAgRwj8DfpEwzy28y", /*D9*/
+                "1c0FoC7Q+7wVMVV1Rloi8GKvp5I2i+EICu2MDIJK0wXqgD7DzteoUZyHrj9QB8AK", /*DA*/
+                "GlI8yLXvPvSsQYjEX7Dp5fm1hb84LMV5qfc7rhgIzSZ0X4/KMlw4T1JHlXsQInvx", /*DB*/
+                "sKSYkZb8SBocTgy7QImn2ZF2DuabHXhCMIoPaPPK0Ycpr2pgk/Gf0JOHBGC82hhF", /*DC*/
+                "NKBWShNIXfC5adyR616miWI85mA59MePkl5B+Z9rHPo1eTRWTp0hfoXvCt7WSGor", /*DD*/
+                "/V8ES8X5fxqyaJQuVqmgRJK/Hi2iJRTxDo7SCxIzjSBi4YCvl0HX8pNs5t9zyu3O", /*DE*/
+                "pMkpnUOQcdWdr14r3AfARNzOgKdI323vsSRgqeQFsmFd/sOEzraFGCHO4raGabW4", /*DF*/
+                "mX4jNPqsbfPQ/rxTUutFvsAasrhGaSxAZ83p5/ymYCT8KSYWW22a+B6C23Sjzmz2", /*E0*/
+                "HRrD3HRg4BbDOPrDegFy8WDthLdLzsG7ceYq6Lyoidq7wCaN+8/aptb2CZaugVEY", /*E1*/
+                "YXbRlN3bEPGT82m6TLuf9QBePD/7YDtGrHiO/pa4YBy2Wt6VZ+KzXhliTWXUKHOZ", /*E2*/
+                "YUviqxiRBiFq/M6PxLgcgQL5VvssAztIV8CMGUjoMvtwT6BiVIEgpuJZSYnROACQ", /*E3*/
+                "0Oz/m3gJ1VqgnPYlg17N3YKMm80aj00VrzzOlF73fay+VIez0VRlbeeGhHOvZNu1", /*E4*/
+                "v0OarKEIozWS5OazWoBHJo9YYW9hSrdLTvXbW+4CRvrbdHEKR2LdP6z6CKg8Q5VX", /*E5*/
+                "BaZMd7iUoFEl8u50TJcHX1Opga33/ioC1m8zukvEZwk9uuyKkSejigo/PFc2hAv3", /*E6*/
+                "w2YHQoNPN8988D6hARnzcQ/c+d7HVq1jMaL1Wei1W55MPom5O0W/0GCXccJmS+Gh", /*E7*/
+                "SD79c8xhGLThS7A4oXkdRheo+zd90xBApCUyaaoiln2aeSaBS0UEIrZuzdyH1KUz", /*E8*/
+                "IDMFejHQkdJ2Hw3l8Xh24sefFWM6Zj2aUrS6Zz9Ne60czjMrXsCcJsO8NNccJrgP", /*E9*/
+                "7iVKPW1U0PPyt8korXQotCgtlimLeOxzU4UrE0g650pmC5Gg15lsdVxVLXHC4qfs", /*EA*/
+                "3R+RJL+ln1VLVXA33vXdoUa5ZpMT/cPHpCsdiAzMfm6HS+Unam3nFHi4+sT71VJz", /*EB*/
+                "CqyN7StimvEuWvx+XY5UNbJX8LR0ScjKrjUDPdB+Mas4F8XyOMEPcRY0QFpJzJCc", /*EC*/
+                "YQTxNrnep5+dL0ZYC5tSoWXsucgRkRCf6jNORCjroyM3iRF1yoRAVcLqRsmnWJ1Z", /*ED*/
+                "TqxWeLuqw26vzMvBB2kOmPXLAMetV4Uf9NlIr+Acy32Kq5mB39qzfxLz2/q4bbPm", /*EE*/
+                "YBYQej8ND8CXxrYtsZRbYDhftqJ7T5R5vOJH3d6KhUArsJ8O20sEHjmVEKMBnceG", /*EF*/
+                "KkiYWz2JMZcmA3n5Z+KN+11QOhQH9ICH46jTzPyuHKT+p7fXs/BCoKyhGbv+UTE+", /*F0*/
+                "UGk6AHn27ecSq8ao1Jf8uppVeZy0lsATGVBLQwElBcMJ+63nI/uAEsAvvTFdkFkZ", /*F1*/
+                "W8b8/EYMXFcZtDQ/h15i/qO4UX/M/ZYWwOdaDvNWnMcVrX/SHEbjFFkoR8u5zHsb", /*F2*/
+                "Fo/M5Vj+Bji/wTRn104k+FbbXQ8OlAROe4sVxN2v0FvJxRGZlLrGpCaXrlXBKm7/", /*F3*/
+                "REERuETIx0kAyzXKG+RQtHz5vmfsUCQwiw0e20kgZqj6uI5SIsBp2veiwYVl8btq", /*F4*/
+                "TgR/9g1CuzezB+/i8+nA3EF4dxiGCBBNrtoFkzflkgSPEuQ3HHmkPRfqpMtFhGiA", /*F5*/
+                "nY3P5HyKOVGlnKaR2PylSaUtOcIOpnI9OVWrebiWgg7eC9wurwDLa5A+S+VIOLm+", /*F6*/
+                "GS6SGCrF13r1uPXEVywpKQvBd6WYH8/wzWC2OymfKwf7tnVVT2C4Cdv8uYFqOcve", /*F7*/
+                "3iDCtK3XSiUNB6CVD+JibNibMDnzieutnyiLF8yF9qKlle5dW5BDk4Z8l6I0D8Pg", /*F8*/
+                "qr/P9xrVnGYdJ4Bob4Dg45C/mOBZwjRpSXLK+/Dq/l22GEGLlEv3icMHaPvqCmRT", /*F9*/
+                "IOFLwNysO91RjhlkvUlJbXSKWWaWs/0xgVrBwOltvLt5YsBhHCB/8t1cTujjrzgn", /*FA*/
+                "3hFkWtMf180/Uoc+eRLAPPM2yg9y+M+wEvAAc+Bf6JMLCT8mhaCU6OyQ+toBCvYt", /*FB*/
+                "3fq07rENpZ2aeXSZnOQk5bnLJGry/wnezees8+lxna+d7GYlprFi61M1fSGxKtAG", /*FC*/
+                "IjXgGjnmMd0V6TVbBtGskxiS5wPMVuv08ZcMhVyBFwdvClTAimpPv/B/UOldrvj8", /*FD*/
+                "B7JQ3BO0RavV2FGVNhe0QBByjhBqKDLKr5PQ2FReIgPpdqUeWaVsS2LgxE13qxJO", /*FE*/
+                "bLls31D49NldM2cWG9i6iuVynOfPeUDLlmkxPnYvVOXEl9O5eUs+MBFRlIsDM2nk", /*FF*/
+                "AiUNO8VcsXVYQ1Kga8ob2n5rwFZ1l9qeJRMKz35yV2z4w+V4Wj1h3FqUtKOULQbO"  /*00*/
+            );
+
+            public static readonly Table<byte> MIX = CreateTable<byte>
+            (
+                "BQMEAQIA", /*00*/
+                "AgUABAMB", /*01*/
+                "BAMBAgUA", /*02*/
+                "AwUEAAIB", /*03*/
+                "AgMFAQAE", /*04*/
+                "BAADBQIB", /*05*/
+                "AwIFAQAE", /*06*/
+                "BAUDAgEA", /*07*/
+                "AwQBBQAC", /*08*/
+                "AQIEAAUD", /*09*/
+                "BQQDAQAC", /*0A*/
+                "BAIBBQMA", /*0B*/
+                "BQMEAQAC", /*0C*/
+                "BAABBQID", /*0D*/
+                "AgUDBAAB", /*0E*/
+                "BQIBAAME", /*0F*/
+                "BAUDAQAC", /*10*/
+                "AQAEAgUD", /*11*/
+                "AgUBBAMA", /*12*/
+                "BAIAAQUD", /*13*/
+                "AQMFAgAE", /*14*/
+                "BAABBQMC", /*15*/
+                "AQUEAgAD", /*16*/
+                "AwQFAAEC", /*17*/
+                "AQIABQME", /*18*/
+                "BAUDAgAB", /*19*/
+                "BQMABAEC", /*1A*/
+                "AgUEAQAD", /*1B*/
+                "BQADBAIB", /*1C*/
+                "BAMAAQUC", /*1D*/
+                "AQIEBQMA", /*1E*/
+                "BAADAgUB", /*1F*/
+                "AgMABQEE", /*20*/
+                "AwQBAAUC", /*21*/
+                "BQADAQIE", /*22*/
+                "BAMAAgUB", /*23*/
+                "BQIDAQAE", /*24*/
+                "AgQFAAED", /*25*/
+                "BAMABQIB", /*26*/
+                "BQIBBAAD", /*27*/
+                "AwUEAQIA", /*28*/
+                "AgMFAAEE", /*29*/
+                "BAUAAQID", /*2A*/
+                "BQMBAgAE", /*2B*/
+                "AgUABAED", /*2C*/
+                "BQIEAQMA", /*2D*/
+                "BAUDAAEC", /*2E*/
+                "BQABAgME", /*2F*/
+                "AwUEAQAC", /*30*/
+                "AQAFAgME", /*31*/
+                "BQQDAAEC", /*32*/
+                "AwAEBQIB", /*33*/
+                "BQIABAED", /*34*/
+                "AQQFAAMC", /*35*/
+                "AwABBQIE", /*36*/
+                "AQUEAAMC", /*37*/
+                "AwIBBQAE", /*38*/
+                "AgAFBAED", /*39*/
+                "BAIDAQUA", /*3A*/
+                "AwUBBAAC", /*3B*/
+                "BQAEAgED", /*3C*/
+                "BAMFAAIB", /*3D*/
+                "BQIBBAMA", /*3E*/
+                "AQUDAgAE", /*3F*/
+                "BQABBAMC", /*40*/
+                "AgUDAQAE", /*41*/
+                "AwQFAgEA", /*42*/
+                "AQUEAAID", /*43*/
+                "AgQBBQMA", /*44*/
+                "BAAFAQID", /*45*/
+                "AwUAAgEE", /*46*/
+                "BQAEAQID", /*47*/
+                "AwIABQEE", /*48*/
+                "AgMBBAUA", /*49*/
+                "AQQDBQAC", /*4A*/
+                "AwUAAQIE", /*4B*/
+                "AgADBAUB", /*4C*/
+                "BQQBAgAD", /*4D*/
+                "AwAFAQIE", /*4E*/
+                "AQMEAgUA", /*4F*/
+                "AwQFAAIB", /*50*/
+                "BAIABQED", /*51*/
+                "AQUDBAAC", /*52*/
+                "AwIAAQUE", /*53*/
+                "BAMFAAEC", /*54*/
+                "BQIDBAAB", /*55*/
+                "AwAFAgEE", /*56*/
+                "AQMEAAUC", /*57*/
+                "AgQDBQEA", /*58*/
+                "BQMABAIB", /*59*/
+                "BAIDBQEA", /*5A*/
+                "BQQAAQMC", /*5B*/
+                "AwUBAAIE", /*5C*/
+                "BAMFAgAB", /*5D*/
+                "AwABBAUC", /*5E*/
+                "BQMEAgEA", /*5F*/
+                "BAUBAAID", /*60*/
+                "AQMAAgUE", /*61*/
+                "AgUEAQMA", /*62*/
+                "BQQDAgAB", /*63*/
+                "AQAEBQMC", /*64*/
+                "AgQFAQAD", /*65*/
+                "AwIBBAUA", /*66*/
+                "AgUAAQME", /*67*/
+                "AwIFBAAB", /*68*/
+                "AQUDAAIE", /*69*/
+                "AgAEAQUD", /*6A*/
+                "AQIDBQAE", /*6B*/
+                "BAUAAgED", /*6C*/
+                "AgQFAQMA", /*6D*/
+                "BAMBBQAC", /*6E*/
+                "BQIABAMB", /*6F*/
+                "AgMEBQEA", /*70*/
+                "BAADAQUC", /*71*/
+                "AQMFAAIE", /*72*/
+                "AgAEBQMB", /*73*/
+                "BAMFAgEA", /*74*/
+                "AQQDAAUC", /*75*/
+                "BQABBAID", /*76*/
+                "AgMEBQAB", /*77*/
+                "BQQDAgEA", /*78*/
+                "BAMFAQAC", /*79*/
+                "BQQAAgMB", /*7A*/
+                "AQAEBQID", /*7B*/
+                "AgUDAAEE", /*7C*/
+                "AQQAAgUD", /*7D*/
+                "BQIDBAEA", /*7E*/
+                "BAUAAQMC", /*7F*/
+                "AQIDBAUA", /*80*/
+                "BQAEAgMB", /*81*/
+                "AQIDAAUE", /*82*/
+                "BAAFAQMC", /*83*/
+                "AgQDBQAB", /*84*/
+                "BQIAAQME", /*85*/
+                "AgMFBAEA", /*86*/
+                "BAUAAgMB", /*87*/
+                "AgQDAQUA", /*88*/
+                "AwIFAAEE", /*89*/
+                "AQUABAMC", /*8A*/
+                "BAMBBQIA", /*8B*/
+                "AwUEAgAB", /*8C*/
+                "AgQAAQUD", /*8D*/
+                "AwUEAAEC", /*8E*/
+                "AQQFAgAD", /*8F*/
+                "BAUBAAMC", /*90*/
+                "AgAEBQED", /*91*/
+                "BAMFAQIA", /*92*/
+                "AgABBAUD", /*93*/
+                "AwQFAgAB", /*94*/
+                "AgUDBAEA", /*95*/
+                "BQMEAgAB", /*96*/
+                "AgUBAAME", /*97*/
+                "BAMABQEC", /*98*/
+                "AQAFBAID", /*99*/
+                "AwQBAgUA", /*9A*/
+                "BQADBAEC", /*9B*/
+                "AwUBAgAE", /*9C*/
+                "BAIABQMB", /*9D*/
+                "AwAFBAEC", /*9E*/
+                "BAUBAgMA", /*9F*/
+                "AgADBQEE", /*A0*/
+                "AQMABAUC", /*A1*/
+                "AgAFAQME", /*A2*/
+                "BAIBAAUD", /*A3*/
+                "BQMAAgEE", /*A4*/
+                "AgQFAAMB", /*A5*/
+                "AQADBAUC", /*A6*/
+                "BQMBAAIE", /*A7*/
+                "AQUEAgMA", /*A8*/
+                "AgMAAQUE", /*A9*/
+                "BAIBBQAD", /*AA*/
+                "AwAFBAIB", /*AB*/
+                "BQQBAAMC", /*AC*/
+                "AgMFBAAB", /*AD*/
+                "AwIEBQEA", /*AE*/
+                "AgAFBAMB", /*AF*/
+                "BQIDAAEE", /*B0*/
+                "AwQFAQAC", /*B1*/
+                "AgABBQME", /*B2*/
+                "AwUEAgEA", /*B3*/
+                "AQADBQIE", /*B4*/
+                "AgUEAAED", /*B5*/
+                "BQQBAgMA", /*B6*/
+                "BAIFAAED", /*B7*/
+                "AwUBBAIA", /*B8*/
+                "BQAEAQMC", /*B9*/
+                "BAIDBQAB", /*BA*/
+                "AgMBAAUE", /*BB*/
+                "AQUDBAIA", /*BC*/
+                "AgQBBQAD", /*BD*/
+                "AwIEAQUA", /*BE*/
+                "BQQBAAID", /*BF*/
+                "AgADAQUE", /*C0*/
+                "BQQAAgED", /*C1*/
+                "BAIFAAMB", /*C2*/
+                "BQMAAQIE", /*C3*/
+                "AgUBBAAD", /*C4*/
+                "BAAFAgMB", /*C5*/
+                "AwQBBQIA", /*C6*/
+                "BAAFAgED", /*C7*/
+                "AwIEAAUB", /*C8*/
+                "AQQFAgMA", /*C9*/
+                "AwAEBQEC", /*CA*/
+                "BQMBBAIA", /*CB*/
+                "AwQAAQUC", /*CC*/
+                "AQMEBQIA", /*CD*/
+                "BQADAgEE", /*CE*/
+                "AQIEBQAD", /*CF*/
+                "AgMABAUB", /*D0*/
+                "BQIEAAED", /*D1*/
+                "AgMBBQAE", /*D2*/
+                "AQUABAID", /*D3*/
+                "AgQDAAUB", /*D4*/
+                "AQMABQIE", /*D5*/
+                "AwAEAgUB", /*D6*/
+                "AQMFBAAC", /*D7*/
+                "BAUDAQIA", /*D8*/
+                "AgMEAAUB", /*D9*/
+                "AwIFBAEA", /*DA*/
+                "BAMBAAUC", /*DB*/
+                "AQIFBAMA", /*DC*/
+                "AwQAAgUB", /*DD*/
+                "AQMFBAIA", /*DE*/
+                "AgQBAAUD", /*DF*/
+                "AwUABAEC", /*E0*/
+                "BQMEAAIB", /*E1*/
+                "AwQABQEC", /*E2*/
+                "BAUBAgAD", /*E3*/
+                "AwQABQIB", /*E4*/
+                "AQAFBAMC", /*E5*/
+                "AwIEBQAB", /*E6*/
+                "AQQFAAID", /*E7*/
+                "BAADBQEC", /*E8*/
+                "AwIABAUB", /*E9*/
+                "BQMEAAEC", /*EA*/
+                "BAIFAQAD", /*EB*/
+                "AQUAAgME", /*EC*/
+                "BAIDAAUB", /*ED*/
+                "AQQABQID", /*EE*/
+                "BQMBBAAC", /*EF*/
+                "AQQDBQIA", /*F0*/
+                "BQIEAQAD", /*F1*/
+                "AwABAgUE", /*F2*/
+                "BQIEAAMB", /*F3*/
+                "AgQABQED", /*F4*/
+                "AQIFAAME", /*F5*/
+                "BQQDAQIA", /*F6*/
+                "AQIFBAAD", /*F7*/
+                "AgQABQMB", /*F8*/
+                "BAABAgUD", /*F9*/
+                "AwQFAQIA", /*FA*/
+                "AQADAgUE", /*FB*/
+                "AwUABAIB", /*FC*/
+                "AgMEAQUA", /*FD*/
+                "BAUDAAIB", /*FE*/
+                "AQQABQMC"  /*FF*/
+            );
+
+            public static readonly Table<uint> ADD = CreateTable<uint>
+            (
+                "jMGyEw3jMK9hrRBfpv/16KyjUnl26RXy", /*00*/
+                "usvJp51XPL+zYiCMjf6qVQEYFfi0Axco", /*01*/
+                "OMxp7qlUrHQ7SMiEeFCbBe4ZMz/RjCRL", /*02*/
+                "ZAJ+7jWDeD1zUIbUj0F0G+D2WsZTWA2j", /*03*/
+                "vWvIotNSqLc8YZdfehl1X+gFiNepMjUV", /*04*/
+                "izHV8h79MFxtE3c43U5vxL4LpJdu7s+f", /*05*/
+                "DAW42laUHGXgshByzyG26m4D8mDAz/nb", /*06*/
+                "FF5X2ByqhPDAdh6cqWxvM/7LcYc4LRPC", /*07*/
+                "oHejhtoh+b9Xa60WRQqIyN3Opq45qZv3", /*08*/
+                "m3QIoIr7PCmSTIp+EfKEXoV0zzw+w1SO", /*09*/
+                "bxd4mqvscniZEeZ+zfA59w2iK4ulObNy", /*0A*/
+                "bJ+3+WNN9CdbpuXQfiwJBuZg68QQ1ASD", /*0B*/
+                "2pKanNGM5vhKf6dth+sTIIWG1NVXpdfQ", /*0C*/
+                "d4hgEv0QY1s9bSlBg11DV9zfBqlybRo6", /*0D*/
+                "5scSUVHX9uulJjD9I52jCPFPE1SKLFvs", /*0E*/
+                "5u5SL9NTqECB7Ys132Jrx09ueI53NvZ1", /*0F*/
+                "ftKrVLgr7rfBbXUXuzvetkC1kqlK5KRm", /*10*/
+                "C2+Mm7HOojwJPFi9UTZxFN6nearF0cMo", /*11*/
+                "i/e0q9iU4dPjhQqqlrHHyQ9xhTgL45ID", /*12*/
+                "kOoioTYkGseCXD8i/6SwjNFXm1udaGrx", /*13*/
+                "DTv6epNd4HWhB32+mIXIicHw2/s+9kds", /*14*/
+                "P7rS08/wxGF9EkufeqWv6h2TzgiFaezJ", /*15*/
+                "oix5sCxb1jnd5C99X+XG9EuzJm/yFiw5", /*16*/
+                "YL/vWVqtbwUwu2wgvmWu3K7cedbb5k7d", /*17*/
+                "48vgP67BFj2q6BAufzxN7Ixrwj4zL5XB", /*18*/
+                "L6oV1aXnACQ6/nFOCf6N152YzbPr4zGg", /*19*/
+                "DJVLaHqbRB8m773VrWJl6/P1KCv5+T0K", /*1A*/
+                "uRE47IfdU3+HsqkLr2rUszSQDdP57gqP", /*1B*/
+                "aGc2dqHW+YFW24Yzvwuy2ZfiAVY2YmQw", /*1C*/
+                "hFzaf4EIO5VyzEqs7lpWNdsPVNPdZCwH", /*1D*/
+                "qqsZX/XlHsleta/1oZboK9UJxOEP+ul0", /*1E*/
+                "n81y03xuZ1v4WvtMIn83r4yFMckNzkVU", /*1F*/
+                "fyw7QkFWaVhl+PdTS/GP3RKwhzfWcJB2", /*20*/
+                "fUHQ3DqBFPm/20E4vikbYAG5t7RJpsPc", /*21*/
+                "653iO9Cg+e0P+t3yzCMvksM7VsRyLxLk", /*22*/
+                "ZkaL6JC6zt09MXtbCtwPvtkxRF21zgVt", /*23*/
+                "a2TyaxTvS55oqn2xlrgec/aWebTpmQY8", /*24*/
+                "lOKIPgJy+WYEvR1wfm/PkdSlgbzrMrbV", /*25*/
+                "1TIMX4+zGAGLd3J8yVHiRXam6Q6a7Yzh", /*26*/
+                "FUbsDTTK+rybzzN6AkL8f5hsAzx/EbAv", /*27*/
+                "ghjoS7nGK9FCGaz6k7clyFlQIz2ysA0M", /*28*/
+                "4klAHWq4hCp+239TDrSB7D852n3Q16Ov", /*29*/
+                "RG1rAwNM3ptlzF6AZ4a0L3m5TInPuXmL", /*2A*/
+                "JOehJnvkQcBcBFLFzAL1XUd+t4Y98zfM", /*2B*/
+                "FDdz+PfpSYDfKyYA2yTj1qTBhqKLmU70", /*2C*/
+                "g624KvZe/nHo1gVJd63aFqwMdQTnFO4A", /*2D*/
+                "4YLkyUVPsFRrY8YF0h5QoyMq+/nMvl+J", /*2E*/
+                "xSQ9rcx+AdC4gajfUjzcSC2d5pcc0sXv", /*2F*/
+                "RMhWzCbwW4d62/CKe5+qyNjhd3k4fFWW", /*30*/
+                "0k9wUU4XUcT8xcAdMgRpPEk9Ee7hOy8c", /*31*/
+                "0qR75tAqoRywCV5MJgrJjO9csWvPC6IE", /*32*/
+                "Hoao80u2qKvBcx2nZlU/s7vCgNez8aQ1", /*33*/
+                "DuXGOu43ggXi08wo6TjBZWJfFjZSE0a6", /*34*/
+                "VKSQwUtKsTuLT6pur/hUxNkJ+yN6O4vM", /*35*/
+                "qFV7mjk9f7kc95W95F92+L805GDjyENN", /*36*/
+                "lKdJdORUwBcRRB4DodGKy1iurUkePcW7", /*37*/
+                "izLURGcVnWAFjicdqRrdWmT9yJj/VLlW", /*38*/
+                "VF6/IqbY+dpDIyNtwfOOSHZ3FPB0xoVB", /*39*/
+                "o3C/vmmNwB4bn05AF5FdRIAutzzlhVZH", /*3A*/
+                "rGQ+VkoB03H7HHRyJssu8hrEUUVD7CMA", /*3B*/
+                "K93p45YZwzegZl7lDR8t0bWZJTQvSG/F", /*3C*/
+                "4+mp8Y0tDnc2ogtLcUx9eW/pFFWGhpO9", /*3D*/
+                "Wd9VKi2YGMwmjTsJCkf3eAOacU+ef0NK", /*3E*/
+                "aSKrlzOiIqwXHT1dHjUGeTpYyT2SIet/", /*3F*/
+                "peMReb9mvNMzb7lw92TDEz035GujHO6V", /*40*/
+                "uRtLYml/1bHavtYjWXPEFL4bxlO6DGOi", /*41*/
+                "V7YUhvETzTDCuv/cZmkaCeyZidFUw6Ou", /*42*/
+                "ywC7zoZFwUTeKrqXb+HgWIiL1u/IQnd1", /*43*/
+                "m2HWrc6ARMaSvhWaXAUsfv9P4+DdRLdT", /*44*/
+                "uI5ZGB+OELkVyLWUUzD6eXcTHODy12d5", /*45*/
+                "EL3/r/Ou6g0/JGYc8wFm3ZsGEiCEXARD", /*46*/
+                "S8osVEKoeFi2MC8pfYK7qj0LI9gvCGIy", /*47*/
+                "8N1k2aZRg03WDRT8coZrLZTTMgVBdGfK", /*48*/
+                "YblYm/Sa+ZuHmIpHfN53StS3YAWHGKOx", /*49*/
+                "zBU0PImBS6z6k2ew8sC5wBUbnUfYU6Mf", /*4A*/
+                "etMHU+uEdo5iIznpOLoGbbY6hMHO3eyn", /*4B*/
+                "P6yTqw1Ow7i+nEcXIv+5ObMyJcuTnha0", /*4C*/
+                "h0d7bPNIUCkBGEAnsMouWTqQNo1aJcfN", /*4D*/
+                "pBLkGx2DanJftwDryvw7F9uuL5V9gepD", /*4E*/
+                "EADE+xfbC9GuID2u0n80IDZ28K9uzIal", /*4F*/
+                "SA8AA8wycyytCgKwTbbsCWQouNvA95yK", /*50*/
+                "ZF7QwH0dkhHQmveSxV4fTMmiirMcgxEF", /*51*/
+                "OAkZjfvoOm+P9O3IVKts8qT657AhqsIW", /*52*/
+                "WJycNcNAkYi3vHBeVvOsWPuyvcPV1Yio", /*53*/
+                "77n2hGhBVVy3yo1KQMPtXfd7xUTbrb8x", /*54*/
+                "IHcsxBvR2pRddPwpOUYfPPxtL+Uurt2X", /*55*/
+                "whSLDP6A2bC2I1YTH9dyXMqNW1vAmUrb", /*56*/
+                "P997XglfiNKP+EbPze+5HuBruzxEdXyQ", /*57*/
+                "iNibvXJsgKYPtsDmzi1be2wOq+fCzSDi", /*58*/
+                "e1dVjBU1AqXnDWPGCng8PczuUDbL607B", /*59*/
+                "uWGWcCIEd67FcM+m/qI/swrxOuuRiyL0", /*5A*/
+                "UqROJDDrgBXnR8HfLsFv+Zse9Rd9Dufg", /*5B*/
+                "DtVPNLffhI96GTmFiin6L6Ui5VgbdkZr", /*5C*/
+                "E3AEAPO2Y0Z5ThhYSTRfygjFB5ZMQfon", /*5D*/
+                "w2jB7zN7AdyNpDF/bjxLa0JS0DwoNzxl", /*5E*/
+                "ikTJqgm5vyWzPiFC9+BuC1IRMnDqtrVA", /*5F*/
+                "40clT0iLyIRM1InHRn0x6I4xHvvYjTOj", /*60*/
+                "PrcP2IzSRIHMQaQzVGNzt24qG6lHMZc8", /*61*/
+                "Hf/C0IGrC/hZYwB+kAAFWrx0g5LpxTbm", /*62*/
+                "Zm3JKWx84q5R4XwmeHN0QNnUTLDzwUBR", /*63*/
+                "XndrFdA1TZo7X9qEek55Hi2VFWx31jS+", /*64*/
+                "6/H7lURnyktsd/ByzbQRfDxOZ6WkLQKn", /*65*/
+                "9phwbAOiNTWTTyJj8fblT8AK1k8x8IRi", /*66*/
+                "fXXxtanhovB9JkZAyuZlI7eEHPD1d3Gi", /*67*/
+                "X6Wo9yPS5Ciy2zNpfGVuwLeUTECOJ8nN", /*68*/
+                "SduPuLAcPNuacUNmVxGKp0lWiXQm6jWb", /*69*/
+                "pgBS4I+8jK81aTZ2cjZljJv5oxCqKS84", /*6A*/
+                "ADmrKcREnChf5GMV3mUKqey/oDDO3J+r", /*6B*/
+                "pgry4cppneykbiUDO7K/1weJg5p3Qq0s", /*6C*/
+                "wzdr3RSJboFG2fVQkzssOc1iIz9B9/5b", /*6D*/
+                "AYR1bZCLzNq7cQcpGKN57W9Shxp2Pi4v", /*6E*/
+                "Fq2DM/pERw83exyKEyTMjlopMnevofaj", /*6F*/
+                "Z1Oy8VvrPiOwUp0nymwEmgdl17CrY1mI", /*70*/
+                "+eFz7HLXrm9yD3jsJg7FRlvbIWLmdcqJ", /*71*/
+                "XZ/Y2ngm21kYwHml9QjakF55nr6I2eQR", /*72*/
+                "H69zI63Zz8wVnl428R86dO18BRNiFtFt", /*73*/
+                "q88q43ieZezycrQMfpAC3QI4zv9jGR+5", /*74*/
+                "LRzMQ5mdI6RrMG53iJp09ZBk7Zzc8J0t", /*75*/
+                "6TKKPX5V2/Px7tOnQWOcMnM8bTr4IdAJ", /*76*/
+                "YnbedDrxsI8J0ZNnhmro7yZjOZp205bv", /*77*/
+                "4h2SfNVVTMJb1EQ1otmGVjVW8l1U6cfv", /*78*/
+                "HXhIbAaDjOoprXp1h1wRQD3ALqnCPm3z", /*79*/
+                "AexIisbux2poEv/gxydRCh4HRALt0Lav", /*7A*/
+                "M52ymcvNjV6o1C7afv3M2drki2bDWBgI", /*7B*/
+                "B2Lc3cMpI7VyuR006DCrT00fgv+djLZH", /*7C*/
+                "piGV1Q01hevGR/XMouBQ71qvSbWExLD7", /*7D*/
+                "9OkXUhMjfLKvIivI0EaaYfr0D07V/rca", /*7E*/
+                "pb8+kUAkVb6lJx64qQ34/mQIEFzujj+8", /*7F*/
+                "E3ZiJ5HWU929oboZEeh50aD9G5I5xRo+", /*80*/
+                "B8XKF+CPqWqF4AL7++7Q9vSZZ2dAnTUS", /*81*/
+                "7ppNVUlSot4cULzEsrQR8NyEuVhaa5yS", /*82*/
+                "yK0XMu5tmv0VHpLDwVnWq2k506tnZzCT", /*83*/
+                "r4wyNaLXxPN+NLAH5Sf2PYzHc7LNCPKt", /*84*/
+                "H3LXKwM4ePUklrsbBbG0Vc/zs/+z4fJM", /*85*/
+                "aN1l0W0dwLFiHhAdYlYKOtIihzxa/0S3", /*86*/
+                "GISbROvOxSnNA0SXq2CW5JlRFIJ7ts4g", /*87*/
+                "c6QrfHmArufYLUMxqfWHh7UoQuAvLzkz", /*88*/
+                "+hYnlhIdbwpY+LNGxxniYvEqHoYysmZY", /*89*/
+                "UQKzVzca9WJoQTJZMG6D8AG8g8CusYt3", /*8A*/
+                "nsihcUw6rOxkzrs8L4310QZuXGqVQcZh", /*8B*/
+                "HKIFfNnqWxVc/91+mIy7eBFO6Kj5se7F", /*8C*/
+                "s/+fQ0YTrfGxi4mcmNC0+mN47zDoRnaL", /*8D*/
+                "fIG5B4mjqZY+hphG4VZDAhryrzgJfRH0", /*8E*/
+                "cygLp0Uxikgxx6VD05+kEuUAAL0BkF6b", /*8F*/
+                "D2PWF8wPrvPrT9A2qMS4ILmCdXF8jVNI", /*90*/
+                "/kWwkZX23D9cDW01joC4LuNMTv12mskd", /*91*/
+                "KufxREb0MEXWRVWyjUmAULLYxrj0uDLL", /*92*/
+                "VywGqETdPj+M6e5IVLle4tu9Ehfh33BS", /*93*/
+                "wgH5EpnZ5p1piXLF5V0sBuTFSTytSjRb", /*94*/
+                "1KlBe73TFwDVRlqshCKvr6jO70U/xs4z", /*95*/
+                "pKLqsySDkBUA/rXc1+nx0Lxi41GIt8v+", /*96*/
+                "BebVL9rK/cbrnt/kF56jIslg7pSHTc7y", /*97*/
+                "EHRiXsjqWN3UDf92+c8apZpdbkCIxPZB", /*98*/
+                "+WAIkfviiIxKOz5v2fVjtULgDz9Rcrvz", /*99*/
+                "mAhyxJmISxd+YifQ5VRex3APOv58aTq4", /*9A*/
+                "+/2zl+LVgN7Tr02XM2hQg/B+qlGp6VEn", /*9B*/
+                "rrBqSEdKxzmeBeWLH9IG04clbEYYW8Ow", /*9C*/
+                "TErUU91OXE0rAkfvdZj0A4Rn6lim9Lgd", /*9D*/
+                "Y2xt82TOPyh4dicfcgtN2tYH7E4Rle2L", /*9E*/
+                "GdAlUT2c3zGoOY9VhTmCLtljDzYvuP5h", /*9F*/
+                "uEF85PKtDqe0lFruGGepmlv4ekYdB6JG", /*A0*/
+                "FBAS7iah9y6FL7FjMPBSqmlaz4zQxfQu", /*A1*/
+                "dQLjVi3JPpymq8AD6m2BEJ7lq3VVAwap", /*A2*/
+                "hJsxjFq1/81EoAKWjwWDQcbKUGy8K6F2", /*A3*/
+                "RaElHLX1HgRgCkIHzp2nMFGYxJqEmFC6", /*A4*/
+                "1NR2wB5z6NVnwfGuaU3OUsJDEkboSxJZ", /*A5*/
+                "x7J50ZgU7gbQZe+Gj3ZHxFO/9IfFAtAA", /*A6*/
+                "p7+3+5b+54N3Z4rAkjj0BYV/IbDDH8ks", /*A7*/
+                "dSYD6NlAcKEQ0YupW210e1etqnHAxXDP", /*A8*/
+                "tqUyB0eGqAiLhOpjYq4iiSR4NwDwQrbm", /*A9*/
+                "WfEflCqobww3ttdVrhKl1TClpkdGfW2z", /*AA*/
+                "gbRJyiaLePMV5cAW2feuLVunR2K1S0h4", /*AB*/
+                "k04QZRcnYKoCze425Y4/hM6soSnVC8m9", /*AC*/
+                "nSZiD8cKN2345xYay0g0RvtkuLgUqp7M", /*AD*/
+                "ZN1aoIhPVNEOiY6A/gdDrRWjnduIkDwK", /*AE*/
+                "Q5e02+LAHYLYLHrlx2/w6XAQPjbVqVop", /*AF*/
+                "RLQmozdGH2IBaGGSu18f/az+b9yAHLFY", /*B0*/
+                "x0kuIZXQUdF2ojZLZn3XKjesGs8geXv3", /*B1*/
+                "gEKroiCpcTl88Aa5jLoT2cbRKQR8uAsH", /*B2*/
+                "rfqrNFkkZo3JA12cE9eGs+N8c60T+fly", /*B3*/
+                "t3iNLtBTBKNxQ8X0gguO0ZUZLSt4rDMD", /*B4*/
+                "BP7m4V2nBJjeER/72bYg0pG8tHxhaPdu", /*B5*/
+                "WqWHvuaX1wDRgWIPvDUiJE8FpPfbu1fq", /*B6*/
+                "SQB9mNiYwAPVZsnAAnKL1qBqxw5ZZkrO", /*B7*/
+                "0xQXcDpNK8yDWo7KTN/kGni37Vn5rMAz", /*B8*/
+                "IgEL6ZMmAOhEOSsVQCX0IpREV8bijMJG", /*B9*/
+                "rIKxcvb3Aalb1P1ceXmpOY1d58FBWjx7", /*BA*/
+                "tHGcY/jPD74E8WxSKeP6VLuYIAN3V7Xn", /*BB*/
+                "m3ar/kkHbClv8DumfGItDCV0YIRpQPmk", /*BC*/
+                "pzjJ8kQe1CdZqlZ+bG7kbW387dsJFEAE", /*BD*/
+                "AYj8MmDSFoX+GtZkMkVZlhLKuh5rPAlv", /*BE*/
+                "rL3NTZll5k28qpQnnS//kxqhKn5Kh8/w", /*BF*/
+                "a2oW3nHtyLpoGv4235bwwMVBt4VIlbuW", /*C0*/
+                "0vLa8RQh0ouRn5Dm72B+dvL690xXGoC7", /*C1*/
+                "W6C6Rnpt3SC1dGdL7d2dnUIB1v0KpVFT", /*C2*/
+                "udJUEcijQ2I8GrrvU9aA2FZSzVmsY+9L", /*C3*/
+                "yg9/u+49z4vo03zvpW6aQBEqW9B9iz/L", /*C4*/
+                "hgLfXCsyqhUZRfeCNSV2GQDqrhATu8am", /*C5*/
+                "ZM+MT6L5dcGIIIpFC1ZOMzFK2T6g/m/D", /*C6*/
+                "KZB0KhbpgKcGNxgyjlIvk+TDUB0Y/Ing", /*C7*/
+                "j3Imqm0IncJcjvhhjervLN3xiO4PupvI", /*C8*/
+                "V83ipbfEnWJ5YHLHsUCk7nR2fVB/7T6g", /*C9*/
+                "mDC3I8eW6XvavYtsNxqIfTd7RBJAnS4R", /*CA*/
+                "kgodwgoBmtDzejXNP7YmBSbf4tE0gvRP", /*CB*/
+                "zVkNleHbOQaDJzOcRsdJ+uvHPZXkNrGO", /*CC*/
+                "/vSomYYWaomD5RveQqbjINXlZQ7M2qwP", /*CD*/
+                "fd2KT/99esJhhkNlsmu+BIyVgN8ymjZn", /*CE*/
+                "zpJOECCf4ZTzhqpvjeQlmk4gggQbLSyR", /*CF*/
+                "JIisKL883YEKOwDUMjaoXwpeSF+KmoFf", /*D0*/
+                "q+bQ5sh96Qm+bZRecwXZfYan7PW80Luw", /*D1*/
+                "8XfTuDe2oo8KGDUrYkFGKDXQVcQhkPp9", /*D2*/
+                "BynFasbkSSfQpNZq2nRxO+/jGf4K9PH5", /*D3*/
+                "RQMQ2/7/1fVGRa9axWxaqTHicrFf5LiS", /*D4*/
+                "Wyx9YQy7M+FvfM6V8btZ6Pd2JeFhitJ0", /*D5*/
+                "TsqEwt7c88zb+ZzG06WX09ycgAI/h7x/", /*D6*/
+                "3FhxF2rcMCvYa1Kvy4PnecU11shBmrho", /*D7*/
+                "49sPNRynmpDzxpnBomYFl9o3v1hWB8pi", /*D8*/
+                "cZFii9kLxoOd3udVif2HCpFaFmOFXL7E", /*D9*/
+                "4gKLe8yotZizEr6XyHzB74ARDmLSuea7", /*DA*/
+                "kGuTl9eoWTCZLCSZW3ESUqLkQDv/MLNH", /*DB*/
+                "SC/o3qViWJxSgclGwcAm3uLcfKAM8mm8", /*DC*/
+                "QTHqqko1QPiVoOF+rG2PSW0h6Oqgll62", /*DD*/
+                "nF3XEjEVqmp23yCugXkl/nvnTkN5dZxU", /*DE*/
+                "aMQvGwjhQAmeGt5giW/UQRLWDc9rOKB6", /*DF*/
+                "9jNkpboAkXjpt81QbK4ROho2JIIUPIsf", /*E0*/
+                "HDpt/TKmLekUWrMIzSH5bVB4iL6k0hru", /*E1*/
+                "9FksdyEOV7kc4Eh0HrYypuQYAkprk9RI", /*E2*/
+                "xLccANcRJWSpVxReUxzXGzC7jvgSn/eq", /*E3*/
+                "nJkpO3uo8mGEjBynS9c/CzDCGpmcGNUc", /*E4*/
+                "Bdvwl8vbZkFbCM35afU/CL3Olc0srKSg", /*E5*/
+                "2f4ojDlnpwsDHsjXaZPsKHmzfvQkxgNO", /*E6*/
+                "rSfviDYSlxc4zOhNa5Jo1LOS44uRQDlW", /*E7*/
+                "DGt7rThtCOY+EMx0q8RPc4MzlhgJ/df1", /*E8*/
+                "dQm0NhmSQX4j2wnRb59W3fLzXcysKnxj", /*E9*/
+                "/+BUw+OrHXHq7gg4eWYgbOpAUNdBbPtA", /*EA*/
+                "Rqua3WdO5kFbQhomfD/LgDmhMaX6TZN1", /*EB*/
+                "CErkFIuijB9Clcb/aRpRs0wDqvgBLuUm", /*EC*/
+                "iSBbXA8LfLMYvdDYLyyTQO8v7txTmYJS", /*ED*/
+                "b1bqN9FNnAhi12CfhlR48g1rOqk9BgNl", /*EE*/
+                "x+LLwCbFI07wcmtgBXpLiHv2bqYK2A3z", /*EF*/
+                "4Hby85LGkTVbiLuyWC7C2ynKbXgGDeoV", /*F0*/
+                "lqK3kJ3swSzmKpIg344LNcG2DVglZx6Q", /*F1*/
+                "Id6ZwE5Z4R1RM9JI6B/O0XFm4nZKdF6A", /*F2*/
+                "Ex4HiXqk6Oi5J+cs9rv6vlandD8tPuJa", /*F3*/
+                "3OUI/YzkZouyJc1J59drNbrpKpNCTc/A", /*F4*/
+                "PgdhrcAQbRTGhLkVpD/rB/GlvK+/g6EK", /*F5*/
+                "pEch+HyJPd9KVTuqgtJq40vhta3KhEVV", /*F6*/
+                "tGfshCY0S9jJpvAr7/iji4taLdbKZdkX", /*F7*/
+                "DKu1A/Eqaiizn7U98YuP/UmLvmge0gJS", /*F8*/
+                "fDBMIYDRZdShcIDEVXhnlLcYZ1yzT2Z9", /*F9*/
+                "+N+tC8xOzEzMbzHhVVgKyvSMDR7Y4x4M", /*FA*/
+                "hyFq89tkXpzi8FpMj0VFioHTBIJ0GONM", /*FB*/
+                "pa92Tw1yY/+M/gkfAunXiNhMwG+X6ylV", /*FC*/
+                "YkmEYyKd8IViUOIQT+gLnLVAlAMyur6P", /*FD*/
+                "J6RHxOuI3LpyhcQ+POhMKX3K5EP+3K/V", /*FE*/
+                "TyZ9zH5NddtcVyANgbrSDarYbosjUYau", /*FF*/
+                "RFJqYyG1PCD/M/kG3EibuTnkZbdWIqiL"  /*00*/
+            );
+
+            public static readonly Row<byte> FIN = CreateRow<byte>
+            (
+                "GRIjFgEfCQAMKgURBxMNAhQuCiYrHCAXLQQpGiEGIigPHiUQCy8bDhUsHScIAyQY"
+            );
+        }
+
+        //=======================================================================
+        // PUBLIC METHODS
+        //=======================================================================
+
+        public MHash384()
+        {
+            Reset(); /*initialize*/
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Update(byte value)
+        {
+            if(finished)
+            {
+                throw new InvalidOperationException("Hash computation finished. Must call reset() first!");
+            }
+            Iterate(hash, Tables.XOR[value], Tables.MIX[rnd++], Tables.ADD[value]);
+        }
+
+        public void Update(byte[] data)
+        {
+            if(object.ReferenceEquals(data, null))
+            {
+                throw new ArgumentNullException("Input array must not be null!");
+            }
+            foreach(byte value in data)
+            {
+                Update(value);
+            }
+        }
+
+        public void Update(byte[] data, int len)
+        {
+            if (object.ReferenceEquals(data, null))
+            {
+                throw new ArgumentNullException("Input array must not be null!");
+            }
+            for (int i = 0; i < len; ++i)
+            {
+                Update(data[i]);
+            }
+        }
+
+        public void Update(byte[] data, int offset, int len)
+        {
+            if (object.ReferenceEquals(data, null))
+            {
+                throw new ArgumentNullException("Input array must not be null!");
+            }
+            int limit = checked(offset + len);
+            for(int i = offset; i < limit; ++i)
+            {
+                Update(data[i]);
+            }
+        }
+
+        public byte[] GetDigest()
+        {
+            if(finished)
+            {
+                throw new InvalidOperationException("Hash computation finished. Must call reset() first!");
+            }
+            byte[] digest = new byte[MHASH384_SIZE];
+            Row<ulong> row_xor = Tables.XOR[256];
+            Row<uint>  row_add = Tables.ADD[256];
+            for(int i = 0; i < MHASH384_SIZE; ++i)
+            {
+                Iterate(hash, row_xor, Tables.MIX[rnd++], row_add);
+                digest[i] = GetByte(hash, Tables.FIN[i]);
+            }
+            return digest;
+        }
+
+        public void Update(string str, Encoding enc = null)
+        {
+            if (object.ReferenceEquals(str, null))
+            {
+                throw new ArgumentNullException("Input string must not be null!");
+            }
+            Update((enc ?? Encoding.UTF8).GetBytes(str));
+        }
+
+        public void Reset()
+        {
+            rnd = 0;
+            hash = Tables.INI.ToArray();
+            finished = false;
+        }
+
+        //-----------------------------------------------------------------------
+        // Convenience functions
+        //-----------------------------------------------------------------------
+
+        public static byte[] Compute(byte[] data)
+        {
+            MHash384 hash = new MHash384();
+            hash.Update(data);
+            return hash.GetDigest();
+        }
+
+        public static byte[] Compute(byte[] data, int len)
+        {
+            MHash384 hash = new MHash384();
+            hash.Update(data, len);
+            return hash.GetDigest();
+        }
+
+        public static byte[] Compute(byte[] data, int offset, int len)
+        {
+            MHash384 hash = new MHash384();
+            hash.Update(data, offset, len);
+            return hash.GetDigest();
+        }
+
+        public static byte[] Compute(string str, Encoding enc = null)
+        {
+            MHash384 hash = new MHash384();
+            hash.Update(str, enc);
+            return hash.GetDigest();
+        }
+
+        //=======================================================================
+        // INTERNAL METHODS
+        //=======================================================================
+
+        /* Magic onst*/
+        private const ulong KMUL = 0x9DDFEA08EB382D69;
+
+        /* Hash state */
+        private ulong[] hash;
+        private byte rnd;
+        private bool finished;
+
+        /* Temporary */
+        private readonly ulong[] temp = new ulong[MHASH384_WORDS];
+
+        //-----------------------------------------------------------------------
+        // Initialization
+        //-----------------------------------------------------------------------
+
+        static MHash384()
+        {
+            if (!BitConverter.IsLittleEndian)
+            {
+                throw new SystemException("BigEndian system is not currently supported!");
+            }
+        }
+
+        //-----------------------------------------------------------------------
+        // Utility functions
+        //-----------------------------------------------------------------------
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private void Iterate(ulong[] hash, Row<ulong> xor, Row<byte> mix, Row<uint> add)
+        {
+            for(int i = 0; i < MHASH384_WORDS; ++i)
+            {
+                temp[i] = Mix128to64(hash[i] + add[i], hash[mix[i]]) ^ xor[i];
+            }
+            Array.Copy(temp, 0, hash, 0, MHASH384_WORDS);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static byte GetByte(ulong[] hash, byte index)
+        {
+            return (byte) (hash[index / 8] >> ((index % 8) * 8));
+        }
+
+        private static ulong Mix128to64(ulong u, ulong v)
+        {
+            v = (v ^ u) * KMUL;
+            v ^= (v >> 47);
+            v = (v ^ u) * KMUL;
+            v ^= (v >> 47);
+            return (v * KMUL);
+        }
+
+        //-----------------------------------------------------------------------
+        // Table initialization
+        //-----------------------------------------------------------------------
+
+        private static Table<T> CreateTable<T>(params string[] lines)
+        {
+            Row<T>[] table = new Row<T>[lines.Length];
+            int row = 0;
+            foreach (string line in lines)
+            {
+                table[row++] = CreateRow<T>(line);
+            }
+            return Table<T>.Wrap(table);
+        }
+
+        private static Row<T> CreateRow<T>(string line)
+        {
+            byte[] data = Convert.FromBase64String(line);
+            switch (Type.GetTypeCode(typeof(T)))
+            {
+                case TypeCode.Byte:
+                    return (Row<T>) (object) BuildRow(line, (byte[] src, int off) => src[off], 1);
+                case TypeCode.UInt32:
+                    return (Row<T>) (object) BuildRow(line, (byte[] src, int off) => BitConverter.ToUInt32(src, off), 4);
+                case TypeCode.UInt64:
+                    return (Row<T>) (object) BuildRow(line, (byte[] src, int off) => BitConverter.ToUInt64(src, off), 8);
+                default:
+                    throw new InvalidOperationException("Unsupported type!");
+            }
+        }
+
+        private static Row<T> BuildRow<T>(string line, Func<byte[], int, T> convert, int pitch)
+        {
+            byte[] data = Convert.FromBase64String(line);
+            if (data.Length % pitch != 0)
+            {
+                throw new ArgumentException("Length of input array is not a multiple of the specified pitch!");
+            }
+            T[] row_data = new T[data.Length / pitch];
+            for (int col = 0, offset = 0; offset < data.Length; ++col, offset += pitch)
+            {
+                row_data[col] = convert(data, offset);
+            }
+            return Row<T>.Wrap(row_data);
+        }
+    }
+}
diff --git a/ports/c-sharp/libmhash384/MHash384.csproj b/ports/c-sharp/libmhash384/MHash384.csproj
new file mode 100644 (file)
index 0000000..d0c9207
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4D49C06B-385E-47C4-B206-732B48B2F34E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>com.muldersoft.mhash384</RootNamespace>
+    <AssemblyName>mhash384-2</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>false</NoStdLib>
+    <Prefer32Bit>false</Prefer32Bit>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="MHash384.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/ports/c-sharp/libmhash384/Properties/AssemblyInfo.cs b/ports/c-sharp/libmhash384/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..cf98678
--- /dev/null
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MHash-384")]
+[assembly: AssemblyDescription("Simple fast portable secure hashing library")]
+#if DEBUG
+[assembly: AssemblyConfiguration("Debug")]
+#else
+[assembly: AssemblyConfiguration("Release")]
+#endif
+[assembly: AssemblyCompany("Muldersoft <mulder2@gmx.de>")]
+[assembly: AssemblyProduct("MHash-384")]
+[assembly: AssemblyCopyright("Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>")]
+[assembly: AssemblyTrademark("MuldeRsoft")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("43c251f0-571f-482f-bda2-e3c9ef0f6f66")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("2.0.*")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
diff --git a/ports/c-sharp/test/MHash384Test.cs b/ports/c-sharp/test/MHash384Test.cs
new file mode 100644 (file)
index 0000000..c6704fe
--- /dev/null
@@ -0,0 +1,210 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+using System;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics;
+
+namespace com.muldersoft.mhash384.test
+{
+    [TestClass]
+    public class MHash384Test
+    {
+        private static bool m_success;
+
+        [ClassInitialize()]
+        public static void Initialize(TestContext testContext)
+        {
+            Trace.WriteLine(String.Format("MHash-384 v{0:D}.{1:D2}-{2:D}, Microsoft.NET v{3} [{4:D}-Bit]\n", MHash384.VERSION_MAJOR, MHash384.VERSION_MINOR, MHash384.VERSION_PATCH, System.Environment.Version, System.Environment.Is64BitProcess ? 64 : 32));
+            m_success = true;
+        }
+
+        [ClassCleanup()]
+        public static void Cleanup()
+        {
+            if(m_success)
+            {
+                Trace.WriteLine("\nSelf-test completed successfully :-)");
+            }
+            else
+            {
+                Trace.WriteLine("\nError: Self-test has failed! :-(");
+            }
+        }
+
+        //=======================================================================
+        // TEST VECTORS
+        //=======================================================================
+
+        [TestMethod]
+        public void TestVector_01()
+        {
+            RunTest
+            (
+                1, "",
+                "D629CB37F76156621E09C93B8D1029C5F0F7B778DE5BD9578230673FE7FA4C45A2308AB4E9D99AA0EA194CBF6230C202"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_02()
+        {
+            RunTest
+            (
+                1, "abc",
+                "1D7B1593D7AA4DD7DC8DA6D6BD591D8B507CA514E1C7EC37F43E78DD6B83253C355403F61009582890480C4CD527F405"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_03()
+        {
+            RunTest
+            (
+                1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+                "9B98CE4C3F4EA9018E1ED3034717E3E5D8DA20AB375BAFE372D07780FFDEFDA32BA3C822155E2883E333AFCAAEAFA614"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_04()
+        {
+            RunTest
+            (
+                1, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+                "45416D1FFD44D3940C5AF5B425B5DA07FD8C06BAB7C58CD13389BC284650ED6090A9A1952C29FEB1B2C6AFBF5F996108"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_05()
+        {
+            RunTest
+            (
+                0x186A0, "aaaaaaaaaa",
+                "20774C570AE2E6A49A01DAE948672AE94D465D9167130FE87BF24148649CF121E8A50759507BF97134F0D28CEE91DCA2"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_06()
+        {
+            RunTest
+            (
+                0x1000000, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno",
+                "C18843D4DD9E0479D38A55E8C75E2201F0E93B6EF1F916EBAF3C4074D188945C7B9657F45269A1DAAB4A8FB6F63D0BEE"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_07()
+        {
+            RunTest
+            (
+                1, "The quick brown fox jumps over the lazy dog",
+                "E2901EDB76AA83F2D52FEA9A34EB2BC05EDFA9571C812620245BBEBA95FA2D82CBB5BAD93EB64D4B72B46635D565400B"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_08()
+        {
+            RunTest
+            (
+                1, "The quick brown fox jumps over the lazy cog",
+                "8B81CD9C1DEE8BCC642F8B1EA982CE79D15F50E66939FF34294E63D93AE3C610F9464FEFEF30297409B62231F028ABC0"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_09()
+        {
+            RunTest
+            (
+                1, "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern",
+                "A545E6319F6ACE0CEF62BCAAF5D488858751B96C2A488D5BE6EC63D50006C9D54DAD66168488F03B4A868D3BA610CCF8"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_10()
+        {
+            RunTest
+            (
+                1, "Frank jagt im komplett verwahrlosten Taxi quer durch Bayern",
+                "2BECB89DD55FC9F2F3384DF61D6240DDA54FC275D186A45A883C03AA873DDAF4FAD4744212B92D26054B92852DEA5F1D"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_11()
+        {
+            RunTest
+            (
+                1, "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+                "6283CE91DA8AF5091C7B06E1352DC947B9E3B89614807C04C43DA322321FBADAD3CCCABECB5C1B1B265432A6039121E1"
+            );
+        }
+
+        [TestMethod]
+        public void TestVector_12()
+        {
+            RunTest
+            (
+                1, "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamc0 laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+                "5DCB7C4B27BA841688FB6A860E97A45256917533F63448CF666781EA4B5FAB20E1C746C8821099A915222E0D77624098"
+            );
+        }
+
+        //=======================================================================
+        // HELPER FUNCTIONS
+        //=======================================================================
+
+        private static void RunTest(uint repetitions, string test, string expected)
+        {
+            string digest = GetDigest(repetitions, test);
+            bool matches = digest.Equals(expected, StringComparison.OrdinalIgnoreCase);
+            m_success &= matches;
+            Trace.WriteLine(String.Format("{0} - {1}", digest, matches ? "OK" : "Error!"));
+            Assert.IsTrue(matches);
+        }
+
+        private static string GetDigest(uint repetitions, string test)
+        {
+            MHash384 hash = new MHash384();
+            for(uint i = 0; i < repetitions; ++i)
+            {
+                hash.Update(test);
+            }
+            return ToHexString(hash.GetDigest());
+        }
+
+        private static string ToHexString(byte[] bytes)
+        {
+            StringBuilder sb = new StringBuilder(bytes.Length * 2);
+            foreach (byte b in bytes)
+            {
+                sb.AppendFormat("{0:X2}", b);
+            }
+            return sb.ToString();
+        }
+    }
+}
diff --git a/ports/c-sharp/test/MHash384Test.csproj b/ports/c-sharp/test/MHash384Test.csproj
new file mode 100644 (file)
index 0000000..b8e1a80
--- /dev/null
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>
+    </ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{65520FD4-4567-4A9D-BC00-AC38DC52D8A4}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>com.muldersoft.mhash384.test</RootNamespace>
+    <AssemblyName>mhash384test-2</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetFrameworkProfile />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="MHash384Test.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\libmhash384\MHash384.csproj">
+      <Project>{4d49c06b-385e-47c4-b206-732b48b2f34e}</Project>
+      <Name>MHash384</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/ports/c-sharp/test/MHash384Test.runsettings b/ports/c-sharp/test/MHash384Test.runsettings
new file mode 100644 (file)
index 0000000..363d3f1
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RunSettings>
+       <RunConfiguration>
+               <TargetPlatform>x64</TargetPlatform>
+               <ResultsDirectory>%TMP%\~MHash384.TestResults</ResultsDirectory>
+       </RunConfiguration>
+</RunSettings>
diff --git a/ports/c-sharp/test/Main.cs b/ports/c-sharp/test/Main.cs
new file mode 100644 (file)
index 0000000..240a690
--- /dev/null
@@ -0,0 +1,78 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+
+namespace com.muldersoft.mhash384.test
+{
+    class TestDriver
+    {
+        static void Main(string[] args)
+        {
+            Trace.Listeners.Add(new ConsoleTraceListener());
+            RunAllTests<MHash384Test>();
+        }
+
+        private static void RunAllTests<T>()
+        {
+            T instance = (T) Activator.CreateInstance(typeof(T));
+            foreach (var method in GetMethodsByAttribute<ClassInitializeAttribute>(typeof(T)))
+            {
+                method.Invoke(null, new object[] { null });
+            }
+            foreach (var method in GetMethodsByAttribute<TestMethodAttribute>(typeof(T)))
+            {
+                try
+                {
+                    method.Invoke(instance, null);
+                }
+                catch (TargetInvocationException targetInvocationException)
+                {
+                    if (typeof(AssertFailedException).IsAssignableFrom(targetInvocationException.GetType()))
+                    {
+                        throw targetInvocationException;
+                    }
+                }
+            }
+            foreach (var method in GetMethodsByAttribute<ClassCleanupAttribute>(typeof(T)))
+            {
+                method.Invoke(null, null);
+            }
+        }
+
+        private static IEnumerable<MethodInfo> GetMethodsByAttribute<T>(Type type)
+        {
+            try
+            {
+                return type.GetMethods().Where((method) => 
+                    method.GetCustomAttributes(false).Select((attr) => attr.GetType()).Contains(typeof(T)));
+            }
+            catch
+            {
+                return Enumerable.Empty<MethodInfo>();
+            }
+        }
+    }
+}
diff --git a/ports/c-sharp/test/Properties/AssemblyInfo.cs b/ports/c-sharp/test/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..b059ef2
--- /dev/null
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MHash-384")]
+[assembly: AssemblyDescription("Simple fast portable secure hashing library")]
+#if DEBUG
+[assembly: AssemblyConfiguration("Debug")]
+#else
+[assembly: AssemblyConfiguration("Release")]
+#endif
+[assembly: AssemblyCompany("Muldersoft <mulder2@gmx.de>")]
+[assembly: AssemblyProduct("MHash-384")]
+[assembly: AssemblyCopyright("Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>")]
+[assembly: AssemblyTrademark("MuldeRsoft")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("04fda165-6d17-4644-99bc-d849011fe433")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("2.0.*")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
diff --git a/ports/delphi/libmhash384/mhash384.pas b/ports/delphi/libmhash384/mhash384.pas
new file mode 100644 (file)
index 0000000..ee6a4e1
--- /dev/null
@@ -0,0 +1,1128 @@
+{* ---------------------------------------------------------------------------------------------- *}
+{* MHash-384 - Simple fast portable secure hashing library                                        *}
+{* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            *}
+{*                                                                                                *}
+{* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  *}
+{* and associated documentation files (the "Software"), to deal in the Software without           *}
+{* restriction, including without limitation the rights to use, copy, modify, merge, publish,     *}
+{* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  *}
+{* Software is furnished to do so, subject to the following conditions:                           *}
+{*                                                                                                *}
+{* The above copyright notice and this permission notice shall be included in all copies or       *}
+{* substantial portions of the Software.                                                          *}
+{*                                                                                                *}
+{* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  *}
+{* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     *}
+{* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *}
+{* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *}
+{* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *}
+{* ---------------------------------------------------------------------------------------------- *}
+
+unit MHash384;
+
+{ ================================================================================================ }
+{ INTERFACE                                                                                        }
+{ ================================================================================================ }
+
+interface
+
+uses
+  SysUtils, Math, Classes;
+
+const
+  MHASH384_VERSION_MAJOR: Smallint = 2;
+  MHASH384_VERSION_MINOR: Smallint = 0;
+  MHASH384_VERSION_PATCH: Smallint = 0;
+
+  MHASH384_WORDS = 6;
+  MHASH384_SIZE = (MHASH384_WORDS * 8);
+  
+type
+  TMHash384Digest = array[0..MHASH384_SIZE-1] of Byte;
+  PMHash384Digest = ^TMHash384Digest;
+
+  TMHash384 = Class
+  public
+    constructor Create;
+    procedure Update(const value: Byte); overload;
+    procedure Update(const data: TByteArray); overload;
+    procedure Update(const data: TByteArray; const len: Integer); overload;
+    procedure Update(const data: TByteArray; const offset: Integer; const len: Integer); overload;
+    procedure Update(const data: PChar; const len: LongWord); overload;
+    procedure Update(const str: String); overload;
+    procedure Update(const stream: TStream); overload;
+    function GetDigest: TMHash384Digest;
+    procedure Reset;
+    class function Compute(const data: TByteArray): TMHash384Digest; overload;
+    class function Compute(const data: TByteArray; const len: Integer): TMHash384Digest; overload;
+    class function Compute(const data: TByteArray; const offset: Integer; const len: Integer): TMHash384Digest; overload;
+    class function Compute(const data: PChar; const len: LongWord): TMHash384Digest; overload;
+    class function Compute(const str: String): TMHash384Digest; overload;
+    class function Compute(const stream: TStream): TMHash384Digest; overload;
+  private
+    rnd: Byte;
+    hash: array[0..MHASH384_WORDS-1] of UInt64;
+    finished: Boolean;
+  end;
+
+{ ================================================================================================ }
+{ IMPLEMENTATION                                                                                   }
+{ ================================================================================================ }
+
+implementation
+
+type
+  UI32 = LongWord;
+  UI64 = UInt64;
+  
+  TRowByte = array[0..MHASH384_WORDS-1] of Byte;
+  TRowUI32 = array[0..MHASH384_WORDS-1] of UI32;
+  TRowUI64 = array[0..MHASH384_WORDS-1] of UI64;
+
+  PRowByte = ^TRowByte;
+  PRowUI32 = ^TRowUI32;
+  PRowUI64 = ^TRowUI64;
+
+{ --------------------------------------------------------------------------- }
+{ CONST TABLES                                                                }
+{ --------------------------------------------------------------------------- }
+
+const
+  MHASH384_INI: TRowUI64 =
+  (
+         UI64($243F6A8885A308D3), UI64($13198A2E03707344), UI64($A4093822299F31D0),
+       UI64($082EFA98EC4E6C89), UI64($452821E638D01377), UI64($BE5466CF34E90C6C)
+  );
+
+  MHASH384_XOR: array[0..256] of TRowUI64 =
+  (
+    ( UI64($01DCDF00414B3037), UI64($B1B3AF661B8E96F8), UI64($944D2873DB393121), UI64($73DA9A36662AE755), UI64($1F4F318C4ECB56B1), UI64($F09743D99C2AA5BC) ), { 00 }
+    ( UI64($A81FBBC6CBBFC954), UI64($39DE43648959EDDB), UI64($1A641A0BDA01822F), UI64($B52E607266932658), UI64($2C5B1731AC802084), UI64($C2EF10671FC79DD4) ), { 01 }
+    ( UI64($CF2A8D8E08810046), UI64($8B7E9B2089E268F6), UI64($930461652C5D2DEC), UI64($F096E42223BFC8B9), UI64($8DD338964CFE0970), UI64($269C342F7CEC60BD) ), { 02 }
+    ( UI64($B970A920D2ED0552), UI64($010F894A254DA7E1), UI64($8D5F205F9D1A40D8), UI64($50C33DCCC3FD5F58), UI64($B49F31BDE7D82C57), UI64($7CDE04F62A959033) ), { 03 }
+    ( UI64($49FAB2822B9C84AC), UI64($34B8648CD68CBEF1), UI64($E5121147BB4126DE), UI64($C0B31F54B2FFE00F), UI64($2F193DA38E8CC632), UI64($058C984B429B8AFC) ), { 04 }
+    ( UI64($E07F9DA44D8C9942), UI64($BE2AF9B39ACA65F2), UI64($5D3D8FB1466DC295), UI64($C0051E3EC3F962C7), UI64($F8FDC3CCD4CE2BB6), UI64($9024C0EFC6199937) ), { 05 }
+    ( UI64($A3111377EF01F5EF), UI64($31F59B366C02A3FF), UI64($61B82949760D16DC), UI64($F6B958AF92BD3BDF), UI64($7297AAEFEC69C0B2), UI64($FE8A50AD9E8684CD) ), { 06 }
+    ( UI64($3D3DD0C829EA9AA0), UI64($3E77597EEC96C7A3), UI64($8FD038231E7F1684), UI64($64617B131FB7EDE0), UI64($85C99CE4C5405874), UI64($A58735D41F19C5E3) ), { 07 }
+    ( UI64($8028628ACAF91B9A), UI64($194A640538C97064), UI64($04A15E018A4F1680), UI64($F4BE1B04C2360955), UI64($DFB24D4CEF581A20), UI64($3C59D0A0FD15879D) ), { 08 }
+    ( UI64($88F8E2ECE78AF1BC), UI64($B46B6E22297364C2), UI64($9339F17F926B99F3), UI64($31293489B3B8F07C), UI64($3909CE1649C9BCF1), UI64($0C46103BFA31BCE9) ), { 09 }
+    ( UI64($4D1A0B8CC7EFE2A9), UI64($AFD7878CAD55E871), UI64($C89CFBC858CF4153), UI64($C4739486C74F75D6), UI64($0BF7192C130AC9F2), UI64($0084F2BC5E81BD9A) ), { 0A }
+    ( UI64($4AFBE975014FCACF), UI64($41DEAF8CFACC41E4), UI64($3C1EC23B53ED16E9), UI64($78B06EB30F1C3248), UI64($DD11165D04285C72), UI64($6546D9B5609491E4) ), { 0B }
+    ( UI64($FFD1E2E04DC8D260), UI64($07B186948A74ECCE), UI64($B5120E45121AC531), UI64($BD0BC86330810C85), UI64($DE93AFDDDB487730), UI64($78DEB0DE6EB99196) ), { 0C }
+    ( UI64($79BAA2AC3FDEBA55), UI64($B1B7E3E1C92A567E), UI64($A53F69AB4A5B0794), UI64($F0DA7499954F6DDD), UI64($58117C89E1132248), UI64($D95DF5F794C51A6E) ), { 0D }
+    ( UI64($89BC8A0C65091C33), UI64($B04EEAEE063135C2), UI64($F53267E04AB6E689), UI64($B4C579B7207E8BF2), UI64($3FD31E51343CD2DF), UI64($119E523E2F8197FE) ), { 0E }
+    ( UI64($2E10CB1C6060F32D), UI64($BC92E732A94E6B63), UI64($F3220D831FD04267), UI64($502C5F7414BCE87F), UI64($89E0651DE91D2457), UI64($759E56B04482D915) ), { 0F }
+    ( UI64($43AEE32C6A84E803), UI64($0C5007202C0BD7E3), UI64($B4F464474205D32A), UI64($7D17FC95DE386C06), UI64($E8DFBF64567AA545), UI64($55BD889D5853046F) ), { 10 }
+    ( UI64($687ABE14EAB8DA27), UI64($397B3AB50D72C344), UI64($505EAA6D1FDE618D), UI64($61BE79865DA13F69), UI64($17BBAB29B5E90E2D), UI64($010C921972FA8B2F) ), { 11 }
+    ( UI64($8B7223A4F56FF453), UI64($291B7B5CB98B6FE1), UI64($FD421625786FBF7D), UI64($E33D1020D0E8CDC8), UI64($CA530C708B739E87), UI64($878AF1F304B8A12F) ), { 12 }
+    ( UI64($7ECE1F24E56DD711), UI64($2E0869241B2FA6DF), UI64($84B834DCC459B2FD), UI64($E022EDA6319E7D3B), UI64($59839D8CA03C9928), UI64($644790F491BBC774) ), { 13 }
+    ( UI64($CBDC6F49E6B0DD0D), UI64($44BA2F8D00346732), UI64($86BCC821586AE61C), UI64($C7B7491285CEE55B), UI64($ED3912FFD97F3851), UI64($F4AF0186BEBEBCBF) ), { 14 }
+    ( UI64($CA8A48E54ECCE516), UI64($BEDF1864B7F8F506), UI64($D56A1F60A4B36AA4), UI64($49B25AB5FE0DD9D9), UI64($21377DBB5E49FCE1), UI64($708F64F5D59D99E7) ), { 15 }
+    ( UI64($E9F873A569AFE02C), UI64($DA66BC05CA997390), UI64($8C88174756D35385), UI64($EAAAF16CF4FDA730), UI64($B39F7A55653A3512), UI64($F10AB727BC23E852) ), { 16 }
+    ( UI64($93E96FF8C5BBE2AF), UI64($A47785420253E97C), UI64($704B25D1F77D074C), UI64($C0B2093F1470559C), UI64($8D5BFDD4E364AACF), UI64($550518673F5B1BF7) ), { 17 }
+    ( UI64($8DAC832E5BE81ACB), UI64($588BFB202B7583D8), UI64($A34D8A70DFD1D7E4), UI64($D03B0627B687033E), UI64($E3D0BE7EDBDC75CF), UI64($818EE8C5B09F8BEA) ), { 18 }
+    ( UI64($8E3B02E1489D7D31), UI64($5336752B64E3B532), UI64($E4D4CC795C580A65), UI64($6DAB08F313ED767E), UI64($8E567E88FDBA36BF), UI64($259490F1D8E933D0) ), { 19 }
+    ( UI64($EAB437D0D62CAA62), UI64($C090AD28B982B003), UI64($E255D768D25704EC), UI64($A048511AF6256A43), UI64($E79F078F4D498B5F), UI64($C41735FB75B357FE) ), { 1A }
+    ( UI64($70DA9FC3504FF29D), UI64($B9AB1F388673FF25), UI64($36922F4CD17357BA), UI64($F09C3AB292E7E04A), UI64($90CE0BC3D9BA13EC), UI64($647C4CA63C918DE3) ), { 1B }
+    ( UI64($D834A38DD1ECD688), UI64($A97A0020DE46AB6A), UI64($9CDEC7F6E62EA71F), UI64($288A5A6FD74DC47E), UI64($D44A2E2765CE50F1), UI64($BB9B50B5DB9E4F3C) ), { 1C }
+    ( UI64($C66DA90E41DDF2E6), UI64($5A3FE86F160C5C09), UI64($6F6AF0405108CCBE), UI64($F938382EB627FC7F), UI64($163DD634617F006C), UI64($5184B1FEDC908497) ), { 1D }
+    ( UI64($C95719ED07FCB21C), UI64($5112DF043F6EE7EB), UI64($50F9FD60012334CE), UI64($589FA85104D96579), UI64($B7129E44D71905A7), UI64($3314766E0733528D) ), { 1E }
+    ( UI64($DC6C8014C5457CB8), UI64($D635FDCD286A69B6), UI64($D66F232CE27D01BF), UI64($56AF4AC0F682EC0F), UI64($57DF1D55B64328F5), UI64($651ED4C52A87CACA) ), { 1F }
+    ( UI64($26D9D1CC79EEC502), UI64($69BF340A34B1EBFE), UI64($FAA5AAAC8E397174), UI64($D0A8F9BD426BCF6F), UI64($5B131F464D6D2452), UI64($122DD15660D0D6DA) ), { 20 }
+    ( UI64($6E389AEC5F51A22F), UI64($7EF68F1C54C127FB), UI64($986D4D46E0485C30), UI64($F0A47B39E7CF8A31), UI64($1D398DFDB7F2A78F), UI64($2FC651D1FBB10D2E) ), { 21 }
+    ( UI64($A44E4E8D1B49DCB0), UI64($07A4822049C2F343), UI64($C40AC04A8D6505BA), UI64($D9B91D3F0729B16C), UI64($AAF39951B50F9015), UI64($966EF5D3AD3F9076) ), { 22 }
+    ( UI64($EA78CBAC0EB6D009), UI64($A0FEA6725A23DEAB), UI64($CE729C7444CB94D9), UI64($40A994626627AA0D), UI64($37F738CDE3D018D5), UI64($4C29491C01CDB3C5) ), { 23 }
+    ( UI64($7C9792AEA745C87A), UI64($D1FF5620C5BD8FD4), UI64($9ECA84E3004B56B9), UI64($5AFD3923C228B1D6), UI64($E5DBF79EB3FD283B), UI64($441712E354084B9F) ), { 24 }
+    ( UI64($E35D288BD8E249BC), UI64($91776C1453A366E5), UI64($F5D1E1684E95EFEC), UI64($9108E117D7DDF606), UI64($81B30F9DA2CE7C8C), UI64($6497DBD786818C0D) ), { 25 }
+    ( UI64($C2F891FF45044BE0), UI64($75A1A76D2B87E2EB), UI64($85CE65798AF3C2BF), UI64($213F532B4EFD09DC), UI64($0DAA1DF5A53A6C88), UI64($3028606A50D826B2) ), { 26 }
+    ( UI64($609A62616379F33A), UI64($A339A3BC53E4516D), UI64($D7AD92616A5ADBEC), UI64($D043726D86E924AA), UI64($8555B564F4C29865), UI64($56AA12AB31C1D6B0) ), { 27 }
+    ( UI64($CED9ED85C1C17BFF), UI64($EB522325ACBAFFC2), UI64($04D3D8F4B2D15394), UI64($D271504C04756EEA), UI64($2DDBA4A91AF827F1), UI64($1F67D5C28F8002E4) ), { 28 }
+    ( UI64($8B9C08AD432DC08F), UI64($5A7543E29796BBC7), UI64($34A6DB5B3C1967DE), UI64($016E3BC2A2804EE4), UI64($5B9BCACCE5172F75), UI64($7549598B80ADBDBA) ), { 29 }
+    ( UI64($6F3FB117C5CDD155), UI64($16C3B0A59CD6EEC5), UI64($D9A1A411DE538769), UI64($938C54979F4AC37C), UI64($3737BCC1D55284DB), UI64($6CAD9F8AF9156BB7) ), { 2A }
+    ( UI64($EBBF284F9C75EBDF), UI64($B383EBB406753DE8), UI64($AA86127AEE7C403C), UI64($10BFDD10523DE027), UI64($138BF6C4EB4A8A13), UI64($B1EFF67DDB78B067) ), { 2B }
+    ( UI64($F6D1138D7AA3DA5E), UI64($BAA8098D8FB66371), UI64($DAE76D1B8B6CAAF2), UI64($400F1034368D1EDC), UI64($7C937F5172E8D277), UI64($7D05BBF83CADE6EF) ), { 2C }
+    ( UI64($0E9C2EA6CF34B081), UI64($9036B30D58F60BA0), UI64($DB3A2C5848F08BCA), UI64($C87AD1B94250D564), UI64($7C892E09EEF96166), UI64($26DB85CF571085F3) ), { 2D }
+    ( UI64($251EE3F58718C12A), UI64($F9438D81178A2AE4), UI64($F0929A889039A8A8), UI64($F06B65225EBDCCFD), UI64($2E4D14EDF7BF73C6), UI64($A9369895BC1DFACF) ), { 2E }
+    ( UI64($CAE302B41D6979CB), UI64($BBFA5A58B51EE623), UI64($5113B99DC81AB52F), UI64($6093795BEC17A056), UI64($8F71FB4D2E5E355E), UI64($762F92EDBA34A2F2) ), { 2F }
+    ( UI64($D130015265A4D9FF), UI64($09BEA253D71F26C8), UI64($81B6EAEDC46521E6), UI64($FAE268165682B8A9), UI64($A89C3EC4774AB623), UI64($0D2E45E055219DB2) ), { 30 }
+    ( UI64($2B560284C3A692AB), UI64($37008AD0B379A7B8), UI64($AF11CD2C30F90BFC), UI64($7FE87A250F2762ED), UI64($C3FBD711647242C3), UI64($74ED8264F6B322BD) ), { 31 }
+    ( UI64($28195CC8A7AD3943), UI64($53CBE808464C4FC4), UI64($D58E3D7A765F8726), UI64($D83052F60185AA4F), UI64($EFCB0D85223BB4E7), UI64($5A31305E787FAC28) ), { 32 }
+    ( UI64($725D0EE230F19543), UI64($9091D2C6BDDF34E0), UI64($E3BE49C6C2754601), UI64($61BE300BA4AD566B), UI64($02D79D7551FA7CC1), UI64($6543910F5F1CDA58) ), { 33 }
+    ( UI64($4099ADC44481B43F), UI64($FE1361922FD9EB81), UI64($A989C09E441FCEAC), UI64($449B3A13D3CB9019), UI64($45A9BE396F201134), UI64($DC1AD05A046633FE) ), { 34 }
+    ( UI64($1A563A6D522F3E69), UI64($BE589E079F475A9E), UI64($75A2A9638E4C0038), UI64($DA3B6202577A0362), UI64($211D3F1E0D727AF6), UI64($5E1FFC529AD99233) ), { 35 }
+    ( UI64($47B61E86C6D6D01B), UI64($437D6F83ADADC318), UI64($D5A361028DED738C), UI64($A00D4C630425164B), UI64($1A69AFA5AF4C9DD2), UI64($F99E1C67F951B582) ), { 36 }
+    ( UI64($A66A7740B6BDEA79), UI64($FEF7FF1496AF80A3), UI64($05AFD43EEACD898C), UI64($B00C78ED31AD7134), UI64($0ED31A1AD7846673), UI64($74B96844161499BE) ), { 37 }
+    ( UI64($46FA8D6CCBF6D12E), UI64($31C2FC147F303956), UI64($707F4401DE5F067F), UI64($3AE5FEC7E33594E9), UI64($28E39F8A63531714), UI64($B7B329EA1E9FCAB2) ), { 38 }
+    ( UI64($EFD8F755825C7804), UI64($1F5A93870BD30CD1), UI64($EFBF894671FF8716), UI64($28ED617FF22BDA58), UI64($411289CCAE5CB62E), UI64($95DD42F41801F2F9) ), { 39 }
+    ( UI64($A8525B8645FC59E1), UI64($75E62DC00A5F7F0C), UI64($09C56785210416AC), UI64($50EF76E9B30D7626), UI64($2B3B2CDC19F5D665), UI64($A41297CD11D8F4FF) ), { 3A }
+    ( UI64($EAC99A649EEE5039), UI64($A593C92F143C0065), UI64($B314735203071206), UI64($EA2761A0C764A4EC), UI64($02AA7FD46CAC25B3), UI64($C68CC182A96D03BF) ), { 3B }
+    ( UI64($B2873F024EC83CA8), UI64($97470AB8FD8853EB), UI64($18FE15C159B305BD), UI64($B0AB08F687EAEAFD), UI64($510A3FDE73602E43), UI64($03E1B84DCCF0FCF0) ), { 3C }
+    ( UI64($D85BBBDC8033C0D8), UI64($9223D9C39CA9F34F), UI64($7D3BCB6D5B63C3FD), UI64($1C30F974DA0C0FB5), UI64($8B24BC9EBEFB5143), UI64($C58954925B7B84FC) ), { 3D }
+    ( UI64($6ABD7C2E0844D7A7), UI64($CCF2EA456CDF530D), UI64($E8938CF52B3921B8), UI64($BA023CA2F281657C), UI64($EC635DA675D1EDAE), UI64($B4AA52F22EE1BE6C) ), { 3E }
+    ( UI64($981C3AC677CB5904), UI64($6A92B54C84877B49), UI64($745BA6BB40C55815), UI64($B7AF550D22A371ED), UI64($D5E8BD87C65F5374), UI64($67874A37F0F538F5) ), { 3F }
+    ( UI64($C23BBA2A9DECC021), UI64($4E610E930B0E3450), UI64($1A681AA91477577E), UI64($38A3209714EDC376), UI64($0FD15563EEEB4AB6), UI64($7D57668A01D42178) ), { 40 }
+    ( UI64($6AF88CE145A098B5), UI64($1AEB858CD88B8B46), UI64($E8B733AFB8E2D6E8), UI64($313FAA8C10A7EBFA), UI64($127D375E77557CEA), UI64($96BDA2F70B2F2155) ), { 41 }
+    ( UI64($EC8903978FAFB636), UI64($C7213C425C079763), UI64($760384036AB6D17C), UI64($E0C63A26385F1F49), UI64($299877D6811A6DF5), UI64($876F90FC5304B88D) ), { 42 }
+    ( UI64($A6FABBC2D6E0BA16), UI64($9B70C9640080E6BC), UI64($29B2D5265598B27B), UI64($4A9657C726E4397E), UI64($A801CCC6766678D5), UI64($800EF7CC72619998) ), { 43 }
+    ( UI64($235931A8CF5490BF), UI64($E798F98E0E8F879F), UI64($C6EEE29C38F30CA7), UI64($929A79F2D53E0024), UI64($88F2E12749587A45), UI64($0B85B28F38891965) ), { 44 }
+    ( UI64($165E0303E4A4D827), UI64($67994F42D1E8436A), UI64($E6CC8BCF6E130D1B), UI64($50101711709DDEFC), UI64($373BDEC40CD05328), UI64($40B274A4AA5109F6) ), { 45 }
+    ( UI64($A9F88BA008FDF8C8), UI64($ECC897E3476EE05A), UI64($BCE290AB69D57A74), UI64($FA44DB1811E3115D), UI64($6267AEFD64480C88), UI64($2697D04A2D3AECEB) ), { 46 }
+    ( UI64($C0782AF2ABCD3313), UI64($02BA1290F2F96273), UI64($63C82F1A56ADC2B9), UI64($10F8E8C03EFE51C4), UI64($E3EB348625CCAFFD), UI64($93D607969CB8E7AE) ), { 47 }
+    ( UI64($CC6E179443E58FBC), UI64($D21C93C655A7B8EE), UI64($2B9834A31F2B8BA4), UI64($C83B69516025ECEE), UI64($9176EB7B427AAE94), UI64($8CB65B9E30B7A76E) ), { 48 }
+    ( UI64($C1A33A0AD6EDD989), UI64($18B3C5D95813B5F7), UI64($B024BD263B359A8B), UI64($C8C17C2216A99B50), UI64($71F9A11D58237729), UI64($3AA67C7618284290) ), { 49 }
+    ( UI64($99B7465E09201C7B), UI64($9AF89FA01CA4FA81), UI64($FC2EC63E761AD123), UI64($E2A9A39585B17D14), UI64($08394DE529F94E81), UI64($479448E69794FAA4) ), { 4A }
+    ( UI64($23CA3D1C4CBDCABB), UI64($E3265436CE1A37E4), UI64($1BBF10F69E8A4CC9), UI64($05A66708048F5C4D), UI64($E259DCDD9C5BFEFE), UI64($439E65FAFD936EFD) ), { 4B }
+    ( UI64($A24D73B6978F719C), UI64($3F53F343CCB0BB8E), UI64($BE3C72769EE07C6A), UI64($FACB9E539CF558DD), UI64($67B91D4E30DE986A), UI64($1DB913D11698913A) ), { 4C }
+    ( UI64($98BD4E140DC3C3C6), UI64($142B1592BF3263E8), UI64($CDBEAC59ED095B0E), UI64($900763F0F625896A), UI64($E213550F30324E39), UI64($8A13A4417A803195) ), { 4D }
+    ( UI64($2ACD98ED8C626073), UI64($1CAAA6B4C4CF3238), UI64($04DCB41EB677EB5D), UI64($F88B5844A8105B68), UI64($981D9E951A061A4D), UI64($BC9471894C878EDB) ), { 4E }
+    ( UI64($4959FEAD5D6C2DBD), UI64($6ABD59E28C503049), UI64($06D2C5494CAF8B34), UI64($70E4541304A4293C), UI64($520F3416CAF2F503), UI64($B23D09D92613DB85) ), { 4F }
+    ( UI64($26B5A815C32D1791), UI64($2C99E7555BB033C6), UI64($09CE9D6A0002514F), UI64($D485282B2B8D7997), UI64($9C5B792F4A4A14C6), UI64($851D9D02DC0BB4E7) ), { 50 }
+    ( UI64($62FEB6CACFB060EC), UI64($9D977D69D5C661EA), UI64($BF08EFD806D81556), UI64($25F1EEA460EA5718), UI64($A25346B51F5A9665), UI64($D92F9ADC358CA274) ), { 51 }
+    ( UI64($27E63DFC63E8FFA6), UI64($CDB9CCE2CE99FDA3), UI64($979D5B754974830D), UI64($3298C8407D6693BE), UI64($629D5FADA39B42B7), UI64($2654D31271CD84E1) ), { 52 }
+    ( UI64($AB1FA4DAF66E583C), UI64($EEB6B7A236D24766), UI64($A90738CDFDF5C6B3), UI64($28CBA9E5648E2D4C), UI64($FDE5BF6C0CFE0DA3), UI64($9D00B863D7D78485) ), { 53 }
+    ( UI64($75FBBF094EEA16AA), UI64($48931F027CD729F2), UI64($5D360679009B2E7F), UI64($DDFCD148BD3DE21A), UI64($4DBFF544B094D0E1), UI64($9C0E5C6294352C22) ), { 54 }
+    ( UI64($283A27FF968853D2), UI64($B0960C6CEA0D03F2), UI64($172BBA07A473DB38), UI64($688C87D296E6F4BB), UI64($5CB7E9BC5D68CF0F), UI64($57A5D71B0E47BFB4) ), { 55 }
+    ( UI64($DE0108AAC1E4FF2F), UI64($D346CFABEAC62B99), UI64($B72E203F98B5F608), UI64($81853D8CA54B29BE), UI64($A6AED7C89FAA1680), UI64($D2093B155C39D7ED) ), { 56 }
+    ( UI64($0BAEAC99D4974B84), UI64($C7F258A699C9B4DA), UI64($6F622C5E4ACCF5C1), UI64($58AB397D9781BEAA), UI64($BF811F67E101FFE3), UI64($AFBCC2881C3C0EF3) ), { 57 }
+    ( UI64($26B211FB518D6C3E), UI64($64BADAD51A10784A), UI64($E6BE4E06A587186C), UI64($D471F5C61343CD5C), UI64($8389BB0DD6AAED5D), UI64($C88112678914A17D) ), { 58 }
+    ( UI64($2B2D0BC3BB88D27D), UI64($C5A7D1FAFF517AD2), UI64($96F39056A09F82AD), UI64($FB38A61A6CED4D4E), UI64($9D308E4EA6F9B264), UI64($9097CE294AECC6B3) ), { 59 }
+    ( UI64($8FCA2B950690B1A2), UI64($293EFCBF03D422DF), UI64($8C9125B3E76353AB), UI64($3D402092A1A70173), UI64($9BAB974CAB9BF676), UI64($5EA8FCC55D8C586E) ), { 5A }
+    ( UI64($408C92E8C2E1EC8C), UI64($4AF4C914B71B4350), UI64($5186AEE0CDFB1069), UI64($2385EAFAB9657C67), UI64($F708E4D3C898CA80), UI64($1EC8B9F89884907E) ), { 5B }
+    ( UI64($46E8958B6A2C1878), UI64($2172FD410F78A647), UI64($9D8E9DD83A299004), UI64($390913C3265AD025), UI64($D231F1E23077CBF1), UI64($E7EE3E574E80D7F3) ), { 5C }
+    ( UI64($5A8567A3D85E40B2), UI64($16ECF161133FCF73), UI64($52DA5C6FBA3C0DD7), UI64($56E57983DEB34BFB), UI64($83254FDCB768D153), UI64($9A14F95F35C6B82D) ), { 5D }
+    ( UI64($498A29C6E19D4AE6), UI64($2EF4AAF46027BA11), UI64($BDBA7DAA84F39505), UI64($940B2A04F6DC944D), UI64($4E7ED35610FC0D53), UI64($BADD94C2907E59E1) ), { 5E }
+    ( UI64($14DF0FC43F475F80), UI64($17E2AA8D264BF82F), UI64($92625BDFE58B934D), UI64($8384F415A4ACEA81), UI64($8E9C5EAEC5D8642B), UI64($4D8EF55F1C826687) ), { 5F }
+    ( UI64($4A2335C4F77128D9), UI64($544E1476D29ABA94), UI64($654EC86321785044), UI64($B04AD9B02F80445A), UI64($B0E01B6480C8D020), UI64($596E325E88A3CBBF) ), { 60 }
+    ( UI64($896955157448D062), UI64($0DB08C4C0F236D68), UI64($3BA8FC5B3CD1C4A2), UI64($04F57C53E144535B), UI64($B7D04DCC7BE46840), UI64($4BBE993192334646) ), { 61 }
+    ( UI64($1D7837E6AB02CE27), UI64($3EA35BAED4493EA4), UI64($D1CAFDB5DF94FABE), UI64($98B580BB62170C4F), UI64($C3C57A6CA9421C43), UI64($68D65FC2C1201634) ), { 62 }
+    ( UI64($FAEABABC48717536), UI64($454251E8F62F7315), UI64($B318E8A7FDCDC523), UI64($7C2E832013C91344), UI64($4D9E5DAFD1699052), UI64($12262E8C870537A7) ), { 63 }
+    ( UI64($8A3E5D0BEF8402A2), UI64($A33BC5FAFA019909), UI64($63CBE8ACD00762F5), UI64($EA26A3F181984178), UI64($6EEB78D1BB4AF6BB), UI64($7ECF9671300E845F) ), { 64 }
+    ( UI64($0811B67CCCF5D0FC), UI64($9F8CAB3F3496BD6B), UI64($57CB7D24F1355C2D), UI64($58218594165BDE80), UI64($FAF3368A653A78F8), UI64($C04CD80176267762) ), { 65 }
+    ( UI64($E6417CE75AAA23B0), UI64($34A7BFE3CBA61761), UI64($8C13E396F8C9B6ED), UI64($5C9066464B09ED63), UI64($76CB6A642C5CE283), UI64($498E082A3EB449C6) ), { 66 }
+    ( UI64($6F2ADEA6357B5AA0), UI64($54DA382B15557B69), UI64($302BD81946237AAE), UI64($8F0CBB82111EFEDC), UI64($45DD2DADCE20F2D3), UI64($8A77A5E9E8A2D1D8) ), { 67 }
+    ( UI64($E1EC332735862A28), UI64($92B68B1A7E9C7C44), UI64($F45618DC99E963E3), UI64($7CAC984502DD1A73), UI64($C8650598CD70840D), UI64($9A5DA584A26D4EFD) ), { 68 }
+    ( UI64($16B19B010740C15C), UI64($B4544AC01016439A), UI64($221F749C9E2F99A5), UI64($A63E8A279A65570F), UI64($C7231669ADD072AD), UI64($C5BC35BA740BC801) ), { 69 }
+    ( UI64($6C44E75A4F378694), UI64($D27ACE108A577647), UI64($17C487FAFA7E15D6), UI64($6A3654D5C8E29EDF), UI64($0CE35EEDCC611FFA), UI64($D88A8C03C0095093) ), { 6A }
+    ( UI64($CF106948BC4B1F2C), UI64($91C0DC9990B99712), UI64($193B21E3E109AB32), UI64($3340DE0608DD1666), UI64($8A5BB677BF602828), UI64($402C410B1197B771) ), { 6B }
+    ( UI64($EB080FF49CA5543E), UI64($B4B9429542D6CA27), UI64($5999D45DC1533205), UI64($F7EA9E398A1BEF3E), UI64($BE8817775476DEC6), UI64($17064D7790C84100) ), { 6C }
+    ( UI64($F3328E9150A7F8D6), UI64($52E3E61B04ACFDF8), UI64($51D82010F3CEB015), UI64($59D673336676D5D8), UI64($4CB3BCEF1D91C342), UI64($0C589AB58033BE49) ), { 6D }
+    ( UI64($54B8E70EDCE03855), UI64($7BB590E99687FD57), UI64($6CFF08688D2B1FDD), UI64($FD0F6D068BFE994F), UI64($EB9BCE302489AE44), UI64($66B21F200661E3E4) ), { 6E }
+    ( UI64($2F5E0060189669AD), UI64($473AF1D03C00CAE4), UI64($0278299268D1F3B4), UI64($888714BC3A7EC9D2), UI64($9FF9C7F071EBD2D9), UI64($875A5DC25DFFDB10) ), { 6F }
+    ( UI64($E2A97A3E468399D8), UI64($3BF7EACA32C80DA1), UI64($13DCAC8EB6C2231D), UI64($227EC90E1102EE97), UI64($B2344832F0381434), UI64($8613888303B190EB) ), { 70 }
+    ( UI64($3A3D3B6CE026BFFE), UI64($18D4953B9A68ED59), UI64($24BB7B574AB777A0), UI64($E0CB7DD64983DCB1), UI64($CF768C439869AC97), UI64($8062BC7A900E6033) ), { 71 }
+    ( UI64($39D4C3B78A7A33C7), UI64($43D72EF22AB0B4EB), UI64($54AE8184DDA50394), UI64($0C2A7DA083C38536), UI64($9DBC6F921D4AD822), UI64($2CBB61FE182EAA42) ), { 72 }
+    ( UI64($D8CE9A806C0BD24D), UI64($F69D65A65845727C), UI64($C3FF81CC76F2B048), UI64($76B1FDC3CA67CE58), UI64($CED0970AFBCBE78A), UI64($57502941B726F5F3) ), { 73 }
+    ( UI64($E006AEC17FCEFCF9), UI64($05CAA1629E003591), UI64($B7050CC99F585312), UI64($669260401E159490), UI64($8442D25AA757CC5A), UI64($228655CD4038770C) ), { 74 }
+    ( UI64($93EE8D67D3F1F3A1), UI64($BEA46D48DBF8D7F4), UI64($3C91F02B8646453C), UI64($6C3D7C1F04188A58), UI64($EFA97287F89CEF84), UI64($CB40364E108BFF4B) ), { 75 }
+    ( UI64($C6DCE3730D4FF825), UI64($02AF54F87D972790), UI64($7D69D20F6F4F788F), UI64($90C255C64C166E8F), UI64($A3529FBF4BF9C9A2), UI64($3ECEC41136694F6B) ), { 76 }
+    ( UI64($3DE10A5EC6CA7B3F), UI64($7E196081D085ACAA), UI64($DF5F0DE3705D60F7), UI64($393E7C83DCC57075), UI64($A5F33BC2DCB98F97), UI64($0AEB7F050D1204C0) ), { 77 }
+    ( UI64($6F3B3B3D11A8BC05), UI64($B52269AB2B95B8DC), UI64($12EDE24EB1385F13), UI64($202BBA6B5836B5E1), UI64($EE3636C5925ACC49), UI64($42224CF6EEB509BF) ), { 78 }
+    ( UI64($5F0CC3BBC4BE9A92), UI64($584313FCCC54DD2E), UI64($C11FE90F00394036), UI64($3371667C72FC9723), UI64($9611990B62AC8D9F), UI64($4CFCB9EB3C317FAD) ), { 79 }
+    ( UI64($CA8E520A894A3FBA), UI64($BD9ED1B80098CC40), UI64($BDF24507DFF3757C), UI64($47AEC572E68D35EC), UI64($F3D4523D27B373E4), UI64($1AB11E16973A05AB) ), { 7A }
+    ( UI64($FFC293A6C26B817D), UI64($2C9E9D134959D828), UI64($7FA5216408199BBF), UI64($A6F002DE0DCCD861), UI64($BE8F9DC57F2CF35D), UI64($1352E2DF86A47647) ), { 7B }
+    ( UI64($84B55BE101708E74), UI64($3ADEC53721209F3E), UI64($B18F9A1E68DFADBD), UI64($09A050819774CF2D), UI64($E4AB295D380A8762), UI64($A3605B0C689C239F) ), { 7C }
+    ( UI64($DDC7031FBFDFFE8F), UI64($0B175DE65B832F0A), UI64($31162ABC65719685), UI64($51215E534BBC36B1), UI64($9F2F7D3B5D01AE44), UI64($CF43A2426E83B61B) ), { 7D }
+    ( UI64($7E32DB672B16F04A), UI64($CE6F45DE0E6AB788), UI64($25718548B8E70B41), UI64($D7368BCF39A0FAC4), UI64($956863EC49880C47), UI64($720E335796341674) ), { 7E }
+    ( UI64($06707A8E33D9D6C6), UI64($B684BFE26CD576C6), UI64($44F47E5ECD5FC46C), UI64($AF1B23A856D844B7), UI64($98A627916AC5657E), UI64($040C3964A1127E19) ), { 7F }
+    ( UI64($A5DAEC3134C0A39B), UI64($0CA04160BD5ADB1F), UI64($B50EC5A9F29E1ACB), UI64($BE2FA1126AF7BFAF), UI64($BEFC0AC4C9C5A4B3), UI64($994739C71FB1EB29) ), { 80 }
+    ( UI64($6FEC2D343E83A763), UI64($5BDBA5715757F50C), UI64($D6F6282EE46A11B3), UI64($A8B501F5922A5524), UI64($A782A21006B605CA), UI64($A10BD2E896975C81) ), { 81 }
+    ( UI64($B8AAE0532226D0ED), UI64($891831C0470E84B7), UI64($74C824D648E8FF28), UI64($B5E4E02EAD3906EB), UI64($5ABB086ADA60A713), UI64($A80C57666A9E29F1) ), { 82 }
+    ( UI64($529E3E52B1E7230A), UI64($0C148861C9F08E26), UI64($0CFC8A131BAD803D), UI64($8C09F324902FAA9F), UI64($0231EE4987999848), UI64($3B0688492E2B5457) ), { 83 }
+    ( UI64($EFA6EAC5036814CD), UI64($02773C1F8DAA5DF5), UI64($0E4EEDBD0702DE31), UI64($BA7FD757D0D740EF), UI64($A8805F0C74005F8B), UI64($1448467BFF3E1EF8) ), { 84 }
+    ( UI64($2A07B766016AC70D), UI64($64215C35364219E9), UI64($CD6F7EFE35FCF6F1), UI64($F05CC06084C29267), UI64($AB3BF2F32579A444), UI64($AC75F42D9A25B9C9) ), { 85 }
+    ( UI64($EF3A14B5EDDB8464), UI64($2314E0802D2DD0E9), UI64($14DEAEA9F928762A), UI64($5763EBB480E15A02), UI64($25F7CA14E8CDF5E6), UI64($8E594510DC61E6BC) ), { 86 }
+    ( UI64($E62C38DCFD21000B), UI64($7BB32AE917EE3DA7), UI64($E49F15E24CC9B656), UI64($56E28259DCA361D8), UI64($B43B8008A9285F48), UI64($0DC6B4AF7E4AE61B) ), { 87 }
+    ( UI64($703C64241142DCAE), UI64($732D33342C45063A), UI64($37877EA1624567CB), UI64($2871D534614DD114), UI64($E748092A1D94F5D1), UI64($4524056F0C6D1CB7) ), { 88 }
+    ( UI64($E325B1823A595DF9), UI64($742D0DD5C96F397C), UI64($44361C9540A9F451), UI64($02382F9BF6331FB9), UI64($8ECBAFBBE91A0467), UI64($528EBF3811F904A8) ), { 89 }
+    ( UI64($FD2BC6534631FB0D), UI64($27A5F036FEEB9A6C), UI64($D0F876D7911D0775), UI64($12EFB3A29C6E0B72), UI64($DC4BCA3D5E871DA1), UI64($028FB6E6E608F46F) ), { 8A }
+    ( UI64($EF17ECC8930A7B4A), UI64($9D97B34672FB273D), UI64($C6AE835F35A25D8F), UI64($6C27469530C21F5B), UI64($2FBC16A26150E795), UI64($02AD93AAE0B5C71A) ), { 8B }
+    ( UI64($6D24BE43CF07DD56), UI64($63681D62A38D2A2F), UI64($9872C9B411724AA0), UI64($B882B4857C19690A), UI64($87B1BA8D2804C6F4), UI64($D7B199CC36F40B49) ), { 8C }
+    ( UI64($EEFB8D8573FD9E0F), UI64($933403199B91560A), UI64($FF0DB41665D5248C), UI64($322EE105EA984196), UI64($DB8CE0F83890D89B), UI64($3A32F8983C901F80) ), { 8D }
+    ( UI64($082CDAF93F215BAC), UI64($67C118A1B9274FAC), UI64($AF74501CFB93198A), UI64($53525CABA0E812D3), UI64($C9AF3A005EFE8A6E), UI64($F242DCB60DA7B2FE) ), { 8E }
+    ( UI64($D3887FBFBB7314DF), UI64($DDDCCCF0F720C342), UI64($B2C4331C33C8C415), UI64($1666010767F4785B), UI64($8455B7C1FD5DE487), UI64($A821C5EA181875F2) ), { 8F }
+    ( UI64($7E289831418562F0), UI64($2AD12E3042B185C3), UI64($7C20D0D735A6AE96), UI64($A68BEF98E22CBD41), UI64($A1411D22F8D93243), UI64($D813FB404F3D2F38) ), { 90 }
+    ( UI64($E13FC0A76F664294), UI64($7E21C9D9F7FDDDCB), UI64($161E68B366D6B1F8), UI64($55BF957EB5743874), UI64($B23213EF8364D766), UI64($529BB98AF96643D4) ), { 91 }
+    ( UI64($036D7ADDAADB5C33), UI64($0525835F802D032E), UI64($7DF7D0D8D7A2BEF2), UI64($84927644B27696B7), UI64($215E21E4D1F9B5B9), UI64($77743669C40EB7FD) ), { 92 }
+    ( UI64($A9B3534BE8897784), UI64($5BFD4283541A5090), UI64($97AFFCCD121C9778), UI64($C146C4C9637989C7), UI64($0820E72FCBDA59C7), UI64($5526E2F4A0AE4F4F) ), { 93 }
+    ( UI64($A4739E20FD72BDC2), UI64($6D6EE5A5C1A54CA6), UI64($70A97A6FCB884E5C), UI64($2B6108339E979C48), UI64($93A63730D6BB23A7), UI64($5B1DCEAB00045EE5) ), { 94 }
+    ( UI64($427C14E4F88C8BDB), UI64($1D8630868E039BC2), UI64($33DB40A251502D1B), UI64($E043C9CCB45D2B3D), UI64($292B67B6EE077B2D), UI64($1C3A2FBDE24C742A) ), { 95 }
+    ( UI64($3DED69F37016D86A), UI64($9A947B13AC66D7C3), UI64($822D8645DF4CB39C), UI64($2BA20F98F19E10DA), UI64($6703138D422AC4C4), UI64($8D34D6138FA04A1D) ), { 96 }
+    ( UI64($28E59C8B257D112C), UI64($8747068CC5499FCF), UI64($D6C16EB780F9191A), UI64($B416151633F7AF08), UI64($A230E00D6BA1A1C3), UI64($FD066FB9965B83D2) ), { 97 }
+    ( UI64($70F4BC1B7F8FFC37), UI64($38DC0331E56B0FDC), UI64($A9AB7290AD2B0BBD), UI64($B307973C3D0783C6), UI64($BDC455F6CDCA111F), UI64($23F0E08317B8F0DC) ), { 98 }
+    ( UI64($0AEEC24E9285C50F), UI64($3BCDA47833B61ACE), UI64($839986F959EE0723), UI64($C959034A8D7F5EB9), UI64($D4AD7E05B05C4FB5), UI64($6C37A3D39F7A0EC4) ), { 99 }
+    ( UI64($0227B7230FBF2D07), UI64($28D7D2AD632BED47), UI64($07BD8F8B5012EFD0), UI64($48A0D43AE0403442), UI64($9B8939207F1449A1), UI64($351EAD01B9FDF219) ), { 9A }
+    ( UI64($A7119D2E311CEF25), UI64($1E532CD0C4ED0479), UI64($2272F878D8D30A0B), UI64($769C412CED9C4C42), UI64($262FFBFA65CBDDF5), UI64($DB73D86721EA368E) ), { 9B }
+    ( UI64($4BDBE90B3FBADCB2), UI64($1324EC3A8D6FEA57), UI64($6D9EFBE530850D00), UI64($401A88AFF8A4C8F4), UI64($655CB76B8A2E271C), UI64($35505B6DBDE16F43) ), { 9C }
+    ( UI64($6E15E57E23F57037), UI64($4962737362C1FA26), UI64($C962372D1829B80B), UI64($A1FE6832EA4D6211), UI64($6726E307F96E7763), UI64($04C761081677505B) ), { 9D }
+    ( UI64($42E2FF3A8A6FC164), UI64($FB85B2BC9D28B268), UI64($C559CFF024533A28), UI64($2EC83F3911DAB3CE), UI64($AE0FC74A9D736A27), UI64($DB9CDD048BAB4CCF) ), { 9E }
+    ( UI64($D79C52221D20E765), UI64($499EDD73903CE704), UI64($9B016D987DF48349), UI64($FCFAB44AD12FC5C1), UI64($811293F3B800FDF9), UI64($511DC619CA53CEBE) ), { 9F }
+    ( UI64($A059EE78B826EDDF), UI64($4673AF294D17C85A), UI64($5E527D4E4DF282B5), UI64($DB5B9A2693F95CE3), UI64($6551D304FB54F296), UI64($AB3EB70D65912FCC) ), { A0 }
+    ( UI64($7D0C4F67B6C78135), UI64($390CAEA7DE304D37), UI64($49E19FABC8D494FE), UI64($1A9E1B6437A04516), UI64($886CC4BDAB6AF35A), UI64($0529217344F502FE) ), { A1 }
+    ( UI64($3CEDF34141B52CEE), UI64($8133BA924753573F), UI64($CB32BE22BC66025A), UI64($0C480183DE403CB3), UI64($BF5B84B427DFCF31), UI64($7251428DB0232156) ), { A2 }
+    ( UI64($86FCE831C58E25CB), UI64($5CC43FFE45CBFC75), UI64($33877CC042F199BE), UI64($1212FA7F0CC22E1C), UI64($448EAB4B7D1F9823), UI64($A7B1363A9FA7599E) ), { A3 }
+    ( UI64($2D8C2FEDA0E5106D), UI64($192E366838BBEB3F), UI64($36226AA60ACEA0AF), UI64($E7E1285DC1F3926A), UI64($900371FA1883D9EC), UI64($BAC33B1AF360EB66) ), { A4 }
+    ( UI64($D4A2A11612BDE0E3), UI64($82AB0DA614CB4CB8), UI64($189A4D50AC01F4C6), UI64($E36A5DA1D9F6A647), UI64($E43120D6B16B11B6), UI64($7D395F4236E75378) ), { A5 }
+    ( UI64($C0C155CD47F3877F), UI64($4B03BFE5C334CA71), UI64($77710F1F4B844FF7), UI64($3443BBAB720E8DC5), UI64($F03F8868C5863406), UI64($0FD60511C872EB50) ), { A6 }
+    ( UI64($8C253DAAB5286306), UI64($9AA438F54A6196AC), UI64($181D08C723A22C5E), UI64($633C49C88E3910A1), UI64($C9F54A67992675B0), UI64($1FDD98ACBD38D976) ), { A7 }
+    ( UI64($A10893DA7575A9F7), UI64($8F5F4A025AB2A018), UI64($D80538F0336BFFC0), UI64($0F9751D33889626F), UI64($30383EB925BF911A), UI64($E6149F68CE19CC60) ), { A8 }
+    ( UI64($B9081DBAC6BE0598), UI64($785DD9BC69C71492), UI64($8B035A0CA56E172B), UI64($8946783500724888), UI64($AF1E57C958650569), UI64($E1DE4E944FF22261) ), { A9 }
+    ( UI64($EA5EDC4D2718C0D2), UI64($CB1C5D4DA15A8AE4), UI64($C6272382F8163015), UI64($94A934E5057B54CE), UI64($658E481A3D68D10D), UI64($E8F24929E50A46A0) ), { AA }
+    ( UI64($7DF146281AF482CD), UI64($014B68E726407B06), UI64($6CE564938C70DDBC), UI64($36DAD2DE72A5DAA2), UI64($6D573BF69C0B2980), UI64($684DAB14B4AA0329) ), { AB }
+    ( UI64($9C69DC064E738B5F), UI64($83CC16BD5A1C36F5), UI64($A99B365E6E141B12), UI64($2748FA5AD0FACCE8), UI64($26D073A047D99C49), UI64($B005B182505B0C0C) ), { AC }
+    ( UI64($15B6A2A20ED0FD1C), UI64($9333AF729BD65A25), UI64($22CC333293BD2C1B), UI64($D724D949B15E8BE1), UI64($69D0DB0512B97117), UI64($85ACA8980DD7653C) ), { AD }
+    ( UI64($230EC629D77BB3F2), UI64($43115B991D297CB2), UI64($A2F955792C53C76F), UI64($48A76728EBE25BA7), UI64($7CE662A405384400), UI64($DDC06B7E6BF49D66) ), { AE }
+    ( UI64($20DDB9BD7644410B), UI64($056391B1FA2E8C06), UI64($CA4EDE51CF167C00), UI64($46602B550536F870), UI64($5040672597C21FF4), UI64($0AF8EC6E8AFB844B) ), { AF }
+    ( UI64($0023C5749251B883), UI64($335A4F86D66B7E00), UI64($AE353DED3EFACE8F), UI64($3FC80526D67B35DE), UI64($0D9078FBDA80BC53), UI64($467900DFF3FE4C14) ), { B0 }
+    ( UI64($0F9CB2BE6A448113), UI64($E38D541B6A9A5829), UI64($673953DAF354FC0E), UI64($3C818A277F8569E9), UI64($8D16EA77DB122A3B), UI64($E40A860318B6EA84) ), { B1 }
+    ( UI64($78CE11F42D7D5E50), UI64($84F76DFF199C998D), UI64($999B578E3AE935CB), UI64($D9FD092C1BE63212), UI64($31F33C63ACD316D8), UI64($5AA08030B8D65C0C) ), { B2 }
+    ( UI64($0098DBE19CA84FE9), UI64($E2426617D1142137), UI64($63C3C4166A78E21B), UI64($74B145353E03B0E4), UI64($F43C0824EAE508C4), UI64($58C1E6622528602A) ), { B3 }
+    ( UI64($9E27EBE6D1426A6F), UI64($2A6A600A6B5FA342), UI64($8FF7E2306BA90370), UI64($DF83D91A683EDDDD), UI64($29572442F0225388), UI64($E9CC0F1B6437320A) ), { B4 }
+    ( UI64($054DF380E896064E), UI64($FAB81A4AA3AD88A4), UI64($F87426486CCA156F), UI64($BB1B3C8237472960), UI64($7EC0B87CF73F960A), UI64($5C57D7E6470F7808) ), { B5 }
+    ( UI64($5758E103AC614A1A), UI64($766AEE86F81358DF), UI64($203FBA51DC74396A), UI64($78C93DF969C5721F), UI64($E69E32E230196597), UI64($E287C6CECD8AB95B) ), { B6 }
+    ( UI64($2A06A7C10C0DCC97), UI64($99D5298268A6745F), UI64($F2D818BB774858B3), UI64($D52A820D4F64D886), UI64($2F808EF87A263981), UI64($BB91206E6347C676) ), { B7 }
+    ( UI64($0847C6D71CE0C746), UI64($86FD451B447C1E11), UI64($C20623B0E2856FCC), UI64($3ADDFA2D0398181E), UI64($6736A0A06B336B46), UI64($D1C70AEEB2B1257D) ), { B8 }
+    ( UI64($5633260D141A9776), UI64($D530805F596CA3DB), UI64($8CE33EF69437CE46), UI64($F62D54E97E747088), UI64($DF5C9318489B45EA), UI64($A4AAD29F0BA850CA) ), { B9 }
+    ( UI64($BDBD7B16767F6D9F), UI64($F7968427F1B7B6DD), UI64($58C76599B35276EE), UI64($286F4C7F6CADD791), UI64($8188C0401742117B), UI64($CEC4F1964266D163) ), { BA }
+    ( UI64($97E4E8A6B5135B24), UI64($8A8BD785E5297977), UI64($4545C1A0975BC5BB), UI64($13FAE3BD9F59E37D), UI64($AFD5627C0E91DE2B), UI64($A223AC778474E1A9) ), { BB }
+    ( UI64($DE1BF1EAF86C6B3B), UI64($A246A3ACD50035FE), UI64($6F80179DD96A21CD), UI64($3F8DB7CB17300D03), UI64($497A798B5D94506C), UI64($AD52DCC6F61AE841) ), { BC }
+    ( UI64($F4A4E1D08E1F440B), UI64($5E27633CD56422E0), UI64($1465C14F1DB41420), UI64($9A939043988D37C2), UI64($CBE65CFA245DB368), UI64($6340AEDE28DDA855) ), { BD }
+    ( UI64($1F7AB65A3F892454), UI64($D70AB4167EBEB5A1), UI64($9B2631E824C2028D), UI64($D5D97BDEE31519BC), UI64($EA2DC77449E4058C), UI64($EB204F2D6D2FBAFF) ), { BE }
+    ( UI64($6537E69171A2665D), UI64($3FD2F835435A3F23), UI64($ADD5DD3E622D6C8A), UI64($C522CDD5E5E243F8), UI64($5AEC27F3DBFDA8A2), UI64($477A65ED570E1445) ), { BF }
+    ( UI64($3BA7CB01D32E9D63), UI64($9E335734E7B5416B), UI64($0ED96A84F94539F6), UI64($45CEE2E46DF5A70D), UI64($DE142EE1E9AFEC1C), UI64($78D6121C4FDC72DD) ), { C0 }
+    ( UI64($7BB30AF653390B77), UI64($2D394F2B7F8F7BB6), UI64($0277A3C213AF3489), UI64($7DF6E674DD56D084), UI64($5643CD3073C42451), UI64($FAB15F8BD1A1DC18) ), { C1 }
+    ( UI64($42B453ABF5150D8B), UI64($913F109C1188E18C), UI64($C27BB7631FB43BF9), UI64($EBDDE685EF108419), UI64($76D67C87C56D33EA), UI64($95EC73C0AF40F084) ), { C2 }
+    ( UI64($BCE43D59A1F50BFB), UI64($BA7027CA04D84600), UI64($FB6FDB98A2BE644B), UI64($D5DE777E993DED4A), UI64($FCA39F1EDF710F3A), UI64($A5E5893C858D8841) ), { C3 }
+    ( UI64($C68AC776E6AEACFC), UI64($538067C7866106EB), UI64($D27B4A352F4EFDE3), UI64($847DA2B3BF01E378), UI64($3C79E3C136926D58), UI64($F957BC8726AA1610) ), { C4 }
+    ( UI64($95492C4203C7C612), UI64($0DD60DB1EE8321FC), UI64($E1D9EBA902F62B42), UI64($EA2DBF7D0E37A4F2), UI64($E11FB9098BF5DA48), UI64($DBFE213F818EA338) ), { C5 }
+    ( UI64($17CB21316D4756DD), UI64($B88952498140146A), UI64($648112F580844288), UI64($4947ADC3F7D58F35), UI64($651CCE28E26A5377), UI64($0B3803DAF337F89B) ), { C6 }
+    ( UI64($BEAB16E2DCE6B6E3), UI64($8F39ECC8E39172DF), UI64($607CC9553FF29C0E), UI64($4BFD15154F4F0BA7), UI64($EE6230B6BD408CE4), UI64($35B654110D164E99) ), { C7 }
+    ( UI64($ADDDFF1BD2C11CD4), UI64($2A1A262CBA6E1AA0), UI64($0BF2291D09475A46), UI64($4C93A0ABADF4DE32), UI64($73EE8E1327333E63), UI64($F3AE2031F5D13B28) ), { C8 }
+    ( UI64($246C7CABB2D9A55C), UI64($50E9C7282C1EE0F6), UI64($2FBDA09565A0D3D7), UI64($196552679C04A4EB), UI64($137C66DA29A6DD82), UI64($08A76B6B4BDA56BF) ), { C9 }
+    ( UI64($7CA3C59BE3E28610), UI64($6ADD75CF1F7AE248), UI64($01747450737A6435), UI64($A1F2259CB2B4923B), UI64($E0C8F55E8ECE7210), UI64($D7964398F350B69B) ), { CA }
+    ( UI64($E045864ED1825101), UI64($AC54969193E1A1C5), UI64($23D85A934D0794C7), UI64($B4FA88CB734A4213), UI64($7C5CBFD6BDA3D5F9), UI64($66607FE938748825) ), { CB }
+    ( UI64($BAF36FD2A180D481), UI64($EAC440AC1B9598F7), UI64($9AA24D80FFB7B06C), UI64($79601F517358F163), UI64($D1071831418BB63B), UI64($819609A6AE7D3A03) ), { CC }
+    ( UI64($3E9152D8CDBAE551), UI64($86AD793F203DD016), UI64($BE3AEB778AD4A891), UI64($2810254DD76B6618), UI64($9B5DCDE36636C327), UI64($0A8AAD65868BC58C) ), { CD }
+    ( UI64($6D0672780D93152A), UI64($EEE705247B828091), UI64($9EBDB976F137463F), UI64($A7DE3E73A2D0C1BF), UI64($F871A00BA0046AC7), UI64($484C96A803F23486) ), { CE }
+    ( UI64($0FC7BCDABB06BFFB), UI64($F75C3FFB3D6309B3), UI64($ECA305D103109162), UI64($373F503B204FFF61), UI64($CE332C9F54963FA2), UI64($9A4420A52242CDB4) ), { CF }
+    ( UI64($C71D481179D198C1), UI64($505A2845CEE92569), UI64($F339BFF6DD6755B5), UI64($8BEAD52B8DE89245), UI64($4B686E65920DCA2B), UI64($99593FA43EE68A37) ), { D0 }
+    ( UI64($D90A68D717E61501), UI64($9BB920AEA19161A6), UI64($2F3D6F96D90EB1E4), UI64($DF15ECBA10513D7D), UI64($E6E5D539B4F01831), UI64($C7D17A7528FECE36) ), { D1 }
+    ( UI64($A04FF0BEB4EBFBAF), UI64($E5E90A5B3DDAA3CA), UI64($8453542209F4A145), UI64($80A6FFD72BB5A707), UI64($14E0C4705A1ABF6A), UI64($D699EC1FC18A677D) ), { D2 }
+    ( UI64($7021A124E3181575), UI64($DC7AAE2817AD945F), UI64($8BB5521E7F0D565A), UI64($6671D3792F0805EE), UI64($D3888EA394413A1A), UI64($CE4D7E47B55BF9CC) ), { D3 }
+    ( UI64($22F440263CAADE68), UI64($E77BB287772EAC7B), UI64($29493775962A40E9), UI64($1E06A27FA68CB91B), UI64($DDEF02932ABDB9C7), UI64($79F03B88DC175233) ), { D4 }
+    ( UI64($65F6D517B53E2391), UI64($97DB65A2F00B1C39), UI64($1D77AE9B85AA4855), UI64($19133B9B3E9B0771), UI64($6376D9F11A7DB3D4), UI64($949AD02F5AE16184) ), { D5 }
+    ( UI64($FE4434CDE09D923B), UI64($03B0FCFD713B7052), UI64($2D713290D4A67238), UI64($2B56946FF629EE96), UI64($60A15D01B2B3C428), UI64($0B1D5EAF793933A0) ), { D6 }
+    ( UI64($BC40FCFB0E0D494B), UI64($A31C4648C7B3D1DE), UI64($F1113C219A07EC8D), UI64($2378BEB1A5C2BD1C), UI64($190CC3478070A194), UI64($63DAB6E1CCF56329) ), { D7 }
+    ( UI64($901B6B9E82BABF91), UI64($872A234C45D61001), UI64($6CA46A95C1CC6D6C), UI64($22779315E0F02295), UI64($60A59396346BE6AC), UI64($FB67A503CB488846) ), { D8 }
+    ( UI64($50D440F74C97660B), UI64($E71ECABF64EDFE0C), UI64($80201B895718CE22), UI64($A05D89804D35D306), UI64($8F700402A2B0D086), UI64($326FCB334CA4DFC0) ), { D9 }
+    ( UI64($BCFBD02EA005CDD5), UI64($F0225A4675553115), UI64($08E18B3692A7AF62), UI64($05D34A820C8CED0A), UI64($51A8D7CEC33E80EA), UI64($0AC007503FAE879C) ), { DA }
+    ( UI64($F43EEFB5C83C521A), UI64($E5E9B05FC48841AC), UI64($79C52C38BF85B5F9), UI64($26CD0818AE3BF7A9), UI64($4F385C32CA8F5F74), UI64($F17B22107B954752) ), { DB }
+    ( UI64($1A48FC969198A4B0), UI64($D9A78940BB0C4E1C), UI64($42781D9BE60E7691), UI64($87D1CAF3680F8A30), UI64($D09FF193606AAF29), UI64($4518DABC60048793) ), { DC }
+    ( UI64($F05D48134A56A034), UI64($89A65EEB91DC69B9), UI64($8FC7F43960E63C62), UI64($FA1C6B9FF9415E92), UI64($7E219D4E56347935), UI64($2B6A48D6DE0AEF85) ), { DD }
+    ( UI64($1A7FF9C54B045FFD), UI64($44A0A9562E9468B2), UI64($F11425A22D1EBF92), UI64($208D33120BD28E0E), UI64($F2D74197AF80E162), UI64($CEEDCA73DFE66C93) ), { DE }
+    ( UI64($D57190439D29C9A4), UI64($44C007DC2B5EAF9D), UI64($EF6DDF48A780CEDC), UI64($61B205E4A96024B1), UI64($1885B6CE84C3FE5D), UI64($B8B56986B6E2CE21) ), { DF }
+    ( UI64($F36DACFA34237E99), UI64($BE45EB5253BCFED0), UI64($402C6946B8B21AC0), UI64($2460A6FCE7E9CD67), UI64($F89A6D5B162629FC), UI64($F66CCEA374DB821E) ), { E0 }
+    ( UI64($16E06074DCC31A1D), UI64($F172017AC3FA38C3), UI64($BBC1CE4BB784ED60), UI64($DA89A8BCE82AE671), UI64($A6DACFFB8D26C0BB), UI64($185181AE9609F6D6) ), { E1 }
+    ( UI64($F110DBDD94D17661), UI64($F59FBB4CBA69F393), UI64($463B60FB3F3C5E00), UI64($1C60B896FE8E78AC), UI64($5EB3E26795DE5AB6), UI64($997328D4654D6219) ), { E2 }
+    ( UI64($21069118ABE24B61), UI64($811CB8C48FCEFC6A), UI64($483B032CFB56F902), UI64($FB32E848198CC057), UI64($A620815462A04F70), UI64($900038D1894959E2) ), { E3 }
+    ( UI64($5AD509789BFFECD0), UI64($DDCD5E8325F69CA0), UI64($154D8F1ACD9B8C82), UI64($AC7DF75E94CE3CAF), UI64($6D6554D1B38754BE), UI64($B5DB64AF738486E7) ), { E4 }
+    ( UI64($35A308A1AC9A43BF), UI64($2647805AB3E6E492), UI64($4BB74A616F61588F), UI64($FA4602EE5BDBF54E), UI64($3FDD62470A7174DB), UI64($5795433CA808FAAC) ), { E5 }
+    ( UI64($51A094B8774CA605), UI64($5F07974C74EEF225), UI64($022AFEF7AD81A953), UI64($0967C44BBA336FD6), UI64($8AA327918AECBA3D), UI64($F70B8436573C3F0A) ), { E6 }
+    ( UI64($CF374F83420766C3), UI64($71F31901A13EF07C), UI64($63AD56C7DEF9DC0F), UI64($9E5BB5E859F5A231), UI64($D0BF453BB9893E4C), UI64($A1E14B66C2719760) ), { E7 }
+    ( UI64($B41861CC73FD3E48), UI64($461D79A138B04BE1), UI64($4010D37D37FBA817), UI64($7D9622AA693225A4), UI64($2204454B8126799A), UI64($33A5D487DCCD6EB6) ), { E8 }
+    ( UI64($D291D0317A053320), UI64($E27678F1E50D1F76), UI64($9A3D663A63159FC7), UI64($AD7B4D3F67BAB452), UI64($269CC05E2B33CE1C), UI64($0FB8261CD734BCC3) ), { E9 }
+    ( UI64($F3D0546D3D4A25EE), UI64($B42874AD28C9B7F2), UI64($73EC788B29962D28), UI64($4AE73A48132B8553), UI64($756C99D7A0910B66), UI64($ECA7E2C2712D555C) ), { EA }
+    ( UI64($559FA5BF24911FDD), UI64($A1DDF5DE3770554B), UI64($C7C3FD139366B946), UI64($6E7ECC0C881D2BA4), UI64($14E76D6A27E54B87), UI64($7352D5FBC4FAB878) ), { EB }
+    ( UI64($F19A622BED8DAC0A), UI64($35548E5D7EFC5A2E), UI64($CAC84974B4F057B2), UI64($AB317ED03D0335AE), UI64($710FC138F2C51738), UI64($9C90CC495A403416) ), { EC }
+    ( UI64($9FA7DEB936F10461), UI64($A1529B0B58462F9D), UI64($9F109111C8B9EC65), UI64($23A3EB28444E33EA), UI64($554084CA75118937), UI64($599D58A7C946EAC2) ), { ED }
+    ( UI64($6EC3AABB7856AC4E), UI64($980E6907C1CBCCAF), UI64($1F8557ADC700CBF5), UI64($7DCB1CE0AF48D9F4), UI64($7FB3DADF8199AB8A), UI64($E6B36DB8FADBF312) ), { EE }
+    ( UI64($C00F0D3F7A101660), UI64($605B94B12DB6C697), UI64($79944F7BA2B65F38), UI64($40858ADEDD47E2BC), UI64($1E044BDB0E9FB02B), UI64($86C79D01A3109539) ), { EF }
+    ( UI64($9731893D5B98482A), UI64($FB8DE267F9790326), UI64($8780F407143A505D), UI64($A41CAEFCCCD3A8E3), UI64($A042F0B3D7B7A7FE), UI64($3E3151FEBB19A1AC) ), { F0 }
+    ( UI64($E7EDF679003A6950), UI64($BAFC97D4A8C6AB12), UI64($13C096B49C79559A), UI64($C3052501434B5019), UI64($1280FB23E7ADFB09), UI64($1959905D31BD2FC0) ), { F1 }
+    ( UI64($575C0C46FCFCC65B), UI64($FE625E873F34B419), UI64($1696FDCC7F51B8A3), UI64($C79C56F30E5AE7C0), UI64($14E3461CD27FAD15), UI64($1B7BCCB9CB472859) ), { F2 }
+    ( UI64($3806FE58E5CC8F16), UI64($F8244ED76734C1BF), UI64($4E04940E0F5DDB56), UI64($5BD0AFDDC4158B7B), UI64($A4C6BA949911C5C9), UI64($FF6E2AC155AE9726) ), { F3 }
+    ( UI64($49C7C844B8114144), UI64($B450E41BCA35CB00), UI64($302450EC67BEF97C), UI64($A8662049DB1E0D8B), UI64($DA69C022528EB8FA), UI64($6ABBF16585C1A2F7) ), { F4 }
+    ( UI64($37BB420DF67F044E), UI64($DCC0E9F3E2EF07B3), UI64($4D10088618777841), UI64($0492E5379305DAAE), UI64($3DA4791C37E4128F), UI64($80688445CBA4EA17) ), { F5 }
+    ( UI64($51398A7CE4CF8D9D), UI64($49A5FCD891A69CA5), UI64($3D72A60EC2392DA5), UI64($0E8296B879AB5539), UI64($6BCB00AF2EDC0BDE), UI64($BEB93848E54B3E90) ), { F6 }
+    ( UI64($7AD7C52A18922E19), UI64($29292C57C4F5B8F5), UI64($F0CF1F98A577C10B), UI64($072B9F293BB660CD), UI64($09B8604F5575B6FB), UI64($DECB396A81B9FCDB) ), { F7 }
+    ( UI64($254AD7ADB4C220DE), UI64($6C62E20F95A0070D), UI64($ADEB89F339309BD8), UI64($A2F685CC178B289F), UI64($9343905B5DEE95A5), UI64($E0C30F34A2977C86) ), { F8 }
+    ( UI64($669CD51AF7CFBFAA), UI64($E3E0806F6880271D), UI64($6934C259E098BF90), UI64($5DFEEAF0FBCA7249), UI64($89F74B948B4118B6), UI64($53640AEAFB6807C3) ), { F9 }
+    ( UI64($DD3BACDCC04BE120), UI64($6D4949BD64198E51), UI64($31FDB39666598A74), UI64($BBBC6DE9C0C15A81), UI64($F27F201C61C06279), UI64($2738AFE3E84E5CDD) ), { FA }
+    ( UI64($CDD71FD35A6411DE), UI64($3CC012793E87523F), UI64($B0CFF8720FCA36F3), UI64($93E85FE07300F012), UI64($E894A085263F090B), UI64($2DF60A01DAFA90EC) ), { FB }
+    ( UI64($9DA50DB1EEB4FADD), UI64($E524E49C9974799A), UI64($DE09FFF26A24CBB9), UI64($AF9D71E9F3ACE7CD), UI64($EB62B1A62566EC9D), UI64($06D02AB1217D3553) ), { FC }
+    ( UI64($DD31E6391AE03522), UI64($93ACD1065B35E915), UI64($F4EB56CC03E79218), UI64($0717815C850C97F1), UI64($BF4F6A8AC0540A6F), UI64($FCF8AE5DE9507FF0) ), { FD }
+    ( UI64($AB45B413DC50B207), UI64($40B417369551D8D5), UI64($CA32286A108E7210), UI64($03225E54D8D093AF), UI64($4B6CA5591EA576E9), UI64($4E12AB774DC4E062) ), { FE }
+    ( UI64($D9F4F850DF6CB96C), UI64($8ABAD81B1667335D), UI64($CB4079CFE79C72E5), UI64($E5542F763E316996), UI64($303E4B79B9D397C4), UI64($E46933038B945111) ), { FF }
+    ( UI64($75B15CC53B0D2502), UI64($DA1BCA6BA0524358), UI64($9EDA977556C06B7E), UI64($6C57727ECF0A1325), UI64($DC613D5A78E5C3F8), UI64($CE062D94A3B4945A) )  { ZZ }
+  );
+
+  MHASH384_MIX: array[0..255] of TRowByte =
+  (
+    ( $05, $03, $04, $01, $02, $00 ), { 00 }
+    ( $02, $05, $00, $04, $03, $01 ), { 01 }
+    ( $04, $03, $01, $02, $05, $00 ), { 02 }
+    ( $03, $05, $04, $00, $02, $01 ), { 03 }
+    ( $02, $03, $05, $01, $00, $04 ), { 04 }
+    ( $04, $00, $03, $05, $02, $01 ), { 05 }
+    ( $03, $02, $05, $01, $00, $04 ), { 06 }
+    ( $04, $05, $03, $02, $01, $00 ), { 07 }
+    ( $03, $04, $01, $05, $00, $02 ), { 08 }
+    ( $01, $02, $04, $00, $05, $03 ), { 09 }
+    ( $05, $04, $03, $01, $00, $02 ), { 0A }
+    ( $04, $02, $01, $05, $03, $00 ), { 0B }
+    ( $05, $03, $04, $01, $00, $02 ), { 0C }
+    ( $04, $00, $01, $05, $02, $03 ), { 0D }
+    ( $02, $05, $03, $04, $00, $01 ), { 0E }
+    ( $05, $02, $01, $00, $03, $04 ), { 0F }
+    ( $04, $05, $03, $01, $00, $02 ), { 10 }
+    ( $01, $00, $04, $02, $05, $03 ), { 11 }
+    ( $02, $05, $01, $04, $03, $00 ), { 12 }
+    ( $04, $02, $00, $01, $05, $03 ), { 13 }
+    ( $01, $03, $05, $02, $00, $04 ), { 14 }
+    ( $04, $00, $01, $05, $03, $02 ), { 15 }
+    ( $01, $05, $04, $02, $00, $03 ), { 16 }
+    ( $03, $04, $05, $00, $01, $02 ), { 17 }
+    ( $01, $02, $00, $05, $03, $04 ), { 18 }
+    ( $04, $05, $03, $02, $00, $01 ), { 19 }
+    ( $05, $03, $00, $04, $01, $02 ), { 1A }
+    ( $02, $05, $04, $01, $00, $03 ), { 1B }
+    ( $05, $00, $03, $04, $02, $01 ), { 1C }
+    ( $04, $03, $00, $01, $05, $02 ), { 1D }
+    ( $01, $02, $04, $05, $03, $00 ), { 1E }
+    ( $04, $00, $03, $02, $05, $01 ), { 1F }
+    ( $02, $03, $00, $05, $01, $04 ), { 20 }
+    ( $03, $04, $01, $00, $05, $02 ), { 21 }
+    ( $05, $00, $03, $01, $02, $04 ), { 22 }
+    ( $04, $03, $00, $02, $05, $01 ), { 23 }
+    ( $05, $02, $03, $01, $00, $04 ), { 24 }
+    ( $02, $04, $05, $00, $01, $03 ), { 25 }
+    ( $04, $03, $00, $05, $02, $01 ), { 26 }
+    ( $05, $02, $01, $04, $00, $03 ), { 27 }
+    ( $03, $05, $04, $01, $02, $00 ), { 28 }
+    ( $02, $03, $05, $00, $01, $04 ), { 29 }
+    ( $04, $05, $00, $01, $02, $03 ), { 2A }
+    ( $05, $03, $01, $02, $00, $04 ), { 2B }
+    ( $02, $05, $00, $04, $01, $03 ), { 2C }
+    ( $05, $02, $04, $01, $03, $00 ), { 2D }
+    ( $04, $05, $03, $00, $01, $02 ), { 2E }
+    ( $05, $00, $01, $02, $03, $04 ), { 2F }
+    ( $03, $05, $04, $01, $00, $02 ), { 30 }
+    ( $01, $00, $05, $02, $03, $04 ), { 31 }
+    ( $05, $04, $03, $00, $01, $02 ), { 32 }
+    ( $03, $00, $04, $05, $02, $01 ), { 33 }
+    ( $05, $02, $00, $04, $01, $03 ), { 34 }
+    ( $01, $04, $05, $00, $03, $02 ), { 35 }
+    ( $03, $00, $01, $05, $02, $04 ), { 36 }
+    ( $01, $05, $04, $00, $03, $02 ), { 37 }
+    ( $03, $02, $01, $05, $00, $04 ), { 38 }
+    ( $02, $00, $05, $04, $01, $03 ), { 39 }
+    ( $04, $02, $03, $01, $05, $00 ), { 3A }
+    ( $03, $05, $01, $04, $00, $02 ), { 3B }
+    ( $05, $00, $04, $02, $01, $03 ), { 3C }
+    ( $04, $03, $05, $00, $02, $01 ), { 3D }
+    ( $05, $02, $01, $04, $03, $00 ), { 3E }
+    ( $01, $05, $03, $02, $00, $04 ), { 3F }
+    ( $05, $00, $01, $04, $03, $02 ), { 40 }
+    ( $02, $05, $03, $01, $00, $04 ), { 41 }
+    ( $03, $04, $05, $02, $01, $00 ), { 42 }
+    ( $01, $05, $04, $00, $02, $03 ), { 43 }
+    ( $02, $04, $01, $05, $03, $00 ), { 44 }
+    ( $04, $00, $05, $01, $02, $03 ), { 45 }
+    ( $03, $05, $00, $02, $01, $04 ), { 46 }
+    ( $05, $00, $04, $01, $02, $03 ), { 47 }
+    ( $03, $02, $00, $05, $01, $04 ), { 48 }
+    ( $02, $03, $01, $04, $05, $00 ), { 49 }
+    ( $01, $04, $03, $05, $00, $02 ), { 4A }
+    ( $03, $05, $00, $01, $02, $04 ), { 4B }
+    ( $02, $00, $03, $04, $05, $01 ), { 4C }
+    ( $05, $04, $01, $02, $00, $03 ), { 4D }
+    ( $03, $00, $05, $01, $02, $04 ), { 4E }
+    ( $01, $03, $04, $02, $05, $00 ), { 4F }
+    ( $03, $04, $05, $00, $02, $01 ), { 50 }
+    ( $04, $02, $00, $05, $01, $03 ), { 51 }
+    ( $01, $05, $03, $04, $00, $02 ), { 52 }
+    ( $03, $02, $00, $01, $05, $04 ), { 53 }
+    ( $04, $03, $05, $00, $01, $02 ), { 54 }
+    ( $05, $02, $03, $04, $00, $01 ), { 55 }
+    ( $03, $00, $05, $02, $01, $04 ), { 56 }
+    ( $01, $03, $04, $00, $05, $02 ), { 57 }
+    ( $02, $04, $03, $05, $01, $00 ), { 58 }
+    ( $05, $03, $00, $04, $02, $01 ), { 59 }
+    ( $04, $02, $03, $05, $01, $00 ), { 5A }
+    ( $05, $04, $00, $01, $03, $02 ), { 5B }
+    ( $03, $05, $01, $00, $02, $04 ), { 5C }
+    ( $04, $03, $05, $02, $00, $01 ), { 5D }
+    ( $03, $00, $01, $04, $05, $02 ), { 5E }
+    ( $05, $03, $04, $02, $01, $00 ), { 5F }
+    ( $04, $05, $01, $00, $02, $03 ), { 60 }
+    ( $01, $03, $00, $02, $05, $04 ), { 61 }
+    ( $02, $05, $04, $01, $03, $00 ), { 62 }
+    ( $05, $04, $03, $02, $00, $01 ), { 63 }
+    ( $01, $00, $04, $05, $03, $02 ), { 64 }
+    ( $02, $04, $05, $01, $00, $03 ), { 65 }
+    ( $03, $02, $01, $04, $05, $00 ), { 66 }
+    ( $02, $05, $00, $01, $03, $04 ), { 67 }
+    ( $03, $02, $05, $04, $00, $01 ), { 68 }
+    ( $01, $05, $03, $00, $02, $04 ), { 69 }
+    ( $02, $00, $04, $01, $05, $03 ), { 6A }
+    ( $01, $02, $03, $05, $00, $04 ), { 6B }
+    ( $04, $05, $00, $02, $01, $03 ), { 6C }
+    ( $02, $04, $05, $01, $03, $00 ), { 6D }
+    ( $04, $03, $01, $05, $00, $02 ), { 6E }
+    ( $05, $02, $00, $04, $03, $01 ), { 6F }
+    ( $02, $03, $04, $05, $01, $00 ), { 70 }
+    ( $04, $00, $03, $01, $05, $02 ), { 71 }
+    ( $01, $03, $05, $00, $02, $04 ), { 72 }
+    ( $02, $00, $04, $05, $03, $01 ), { 73 }
+    ( $04, $03, $05, $02, $01, $00 ), { 74 }
+    ( $01, $04, $03, $00, $05, $02 ), { 75 }
+    ( $05, $00, $01, $04, $02, $03 ), { 76 }
+    ( $02, $03, $04, $05, $00, $01 ), { 77 }
+    ( $05, $04, $03, $02, $01, $00 ), { 78 }
+    ( $04, $03, $05, $01, $00, $02 ), { 79 }
+    ( $05, $04, $00, $02, $03, $01 ), { 7A }
+    ( $01, $00, $04, $05, $02, $03 ), { 7B }
+    ( $02, $05, $03, $00, $01, $04 ), { 7C }
+    ( $01, $04, $00, $02, $05, $03 ), { 7D }
+    ( $05, $02, $03, $04, $01, $00 ), { 7E }
+    ( $04, $05, $00, $01, $03, $02 ), { 7F }
+    ( $01, $02, $03, $04, $05, $00 ), { 80 }
+    ( $05, $00, $04, $02, $03, $01 ), { 81 }
+    ( $01, $02, $03, $00, $05, $04 ), { 82 }
+    ( $04, $00, $05, $01, $03, $02 ), { 83 }
+    ( $02, $04, $03, $05, $00, $01 ), { 84 }
+    ( $05, $02, $00, $01, $03, $04 ), { 85 }
+    ( $02, $03, $05, $04, $01, $00 ), { 86 }
+    ( $04, $05, $00, $02, $03, $01 ), { 87 }
+    ( $02, $04, $03, $01, $05, $00 ), { 88 }
+    ( $03, $02, $05, $00, $01, $04 ), { 89 }
+    ( $01, $05, $00, $04, $03, $02 ), { 8A }
+    ( $04, $03, $01, $05, $02, $00 ), { 8B }
+    ( $03, $05, $04, $02, $00, $01 ), { 8C }
+    ( $02, $04, $00, $01, $05, $03 ), { 8D }
+    ( $03, $05, $04, $00, $01, $02 ), { 8E }
+    ( $01, $04, $05, $02, $00, $03 ), { 8F }
+    ( $04, $05, $01, $00, $03, $02 ), { 90 }
+    ( $02, $00, $04, $05, $01, $03 ), { 91 }
+    ( $04, $03, $05, $01, $02, $00 ), { 92 }
+    ( $02, $00, $01, $04, $05, $03 ), { 93 }
+    ( $03, $04, $05, $02, $00, $01 ), { 94 }
+    ( $02, $05, $03, $04, $01, $00 ), { 95 }
+    ( $05, $03, $04, $02, $00, $01 ), { 96 }
+    ( $02, $05, $01, $00, $03, $04 ), { 97 }
+    ( $04, $03, $00, $05, $01, $02 ), { 98 }
+    ( $01, $00, $05, $04, $02, $03 ), { 99 }
+    ( $03, $04, $01, $02, $05, $00 ), { 9A }
+    ( $05, $00, $03, $04, $01, $02 ), { 9B }
+    ( $03, $05, $01, $02, $00, $04 ), { 9C }
+    ( $04, $02, $00, $05, $03, $01 ), { 9D }
+    ( $03, $00, $05, $04, $01, $02 ), { 9E }
+    ( $04, $05, $01, $02, $03, $00 ), { 9F }
+    ( $02, $00, $03, $05, $01, $04 ), { A0 }
+    ( $01, $03, $00, $04, $05, $02 ), { A1 }
+    ( $02, $00, $05, $01, $03, $04 ), { A2 }
+    ( $04, $02, $01, $00, $05, $03 ), { A3 }
+    ( $05, $03, $00, $02, $01, $04 ), { A4 }
+    ( $02, $04, $05, $00, $03, $01 ), { A5 }
+    ( $01, $00, $03, $04, $05, $02 ), { A6 }
+    ( $05, $03, $01, $00, $02, $04 ), { A7 }
+    ( $01, $05, $04, $02, $03, $00 ), { A8 }
+    ( $02, $03, $00, $01, $05, $04 ), { A9 }
+    ( $04, $02, $01, $05, $00, $03 ), { AA }
+    ( $03, $00, $05, $04, $02, $01 ), { AB }
+    ( $05, $04, $01, $00, $03, $02 ), { AC }
+    ( $02, $03, $05, $04, $00, $01 ), { AD }
+    ( $03, $02, $04, $05, $01, $00 ), { AE }
+    ( $02, $00, $05, $04, $03, $01 ), { AF }
+    ( $05, $02, $03, $00, $01, $04 ), { B0 }
+    ( $03, $04, $05, $01, $00, $02 ), { B1 }
+    ( $02, $00, $01, $05, $03, $04 ), { B2 }
+    ( $03, $05, $04, $02, $01, $00 ), { B3 }
+    ( $01, $00, $03, $05, $02, $04 ), { B4 }
+    ( $02, $05, $04, $00, $01, $03 ), { B5 }
+    ( $05, $04, $01, $02, $03, $00 ), { B6 }
+    ( $04, $02, $05, $00, $01, $03 ), { B7 }
+    ( $03, $05, $01, $04, $02, $00 ), { B8 }
+    ( $05, $00, $04, $01, $03, $02 ), { B9 }
+    ( $04, $02, $03, $05, $00, $01 ), { BA }
+    ( $02, $03, $01, $00, $05, $04 ), { BB }
+    ( $01, $05, $03, $04, $02, $00 ), { BC }
+    ( $02, $04, $01, $05, $00, $03 ), { BD }
+    ( $03, $02, $04, $01, $05, $00 ), { BE }
+    ( $05, $04, $01, $00, $02, $03 ), { BF }
+    ( $02, $00, $03, $01, $05, $04 ), { C0 }
+    ( $05, $04, $00, $02, $01, $03 ), { C1 }
+    ( $04, $02, $05, $00, $03, $01 ), { C2 }
+    ( $05, $03, $00, $01, $02, $04 ), { C3 }
+    ( $02, $05, $01, $04, $00, $03 ), { C4 }
+    ( $04, $00, $05, $02, $03, $01 ), { C5 }
+    ( $03, $04, $01, $05, $02, $00 ), { C6 }
+    ( $04, $00, $05, $02, $01, $03 ), { C7 }
+    ( $03, $02, $04, $00, $05, $01 ), { C8 }
+    ( $01, $04, $05, $02, $03, $00 ), { C9 }
+    ( $03, $00, $04, $05, $01, $02 ), { CA }
+    ( $05, $03, $01, $04, $02, $00 ), { CB }
+    ( $03, $04, $00, $01, $05, $02 ), { CC }
+    ( $01, $03, $04, $05, $02, $00 ), { CD }
+    ( $05, $00, $03, $02, $01, $04 ), { CE }
+    ( $01, $02, $04, $05, $00, $03 ), { CF }
+    ( $02, $03, $00, $04, $05, $01 ), { D0 }
+    ( $05, $02, $04, $00, $01, $03 ), { D1 }
+    ( $02, $03, $01, $05, $00, $04 ), { D2 }
+    ( $01, $05, $00, $04, $02, $03 ), { D3 }
+    ( $02, $04, $03, $00, $05, $01 ), { D4 }
+    ( $01, $03, $00, $05, $02, $04 ), { D5 }
+    ( $03, $00, $04, $02, $05, $01 ), { D6 }
+    ( $01, $03, $05, $04, $00, $02 ), { D7 }
+    ( $04, $05, $03, $01, $02, $00 ), { D8 }
+    ( $02, $03, $04, $00, $05, $01 ), { D9 }
+    ( $03, $02, $05, $04, $01, $00 ), { DA }
+    ( $04, $03, $01, $00, $05, $02 ), { DB }
+    ( $01, $02, $05, $04, $03, $00 ), { DC }
+    ( $03, $04, $00, $02, $05, $01 ), { DD }
+    ( $01, $03, $05, $04, $02, $00 ), { DE }
+    ( $02, $04, $01, $00, $05, $03 ), { DF }
+    ( $03, $05, $00, $04, $01, $02 ), { E0 }
+    ( $05, $03, $04, $00, $02, $01 ), { E1 }
+    ( $03, $04, $00, $05, $01, $02 ), { E2 }
+    ( $04, $05, $01, $02, $00, $03 ), { E3 }
+    ( $03, $04, $00, $05, $02, $01 ), { E4 }
+    ( $01, $00, $05, $04, $03, $02 ), { E5 }
+    ( $03, $02, $04, $05, $00, $01 ), { E6 }
+    ( $01, $04, $05, $00, $02, $03 ), { E7 }
+    ( $04, $00, $03, $05, $01, $02 ), { E8 }
+    ( $03, $02, $00, $04, $05, $01 ), { E9 }
+    ( $05, $03, $04, $00, $01, $02 ), { EA }
+    ( $04, $02, $05, $01, $00, $03 ), { EB }
+    ( $01, $05, $00, $02, $03, $04 ), { EC }
+    ( $04, $02, $03, $00, $05, $01 ), { ED }
+    ( $01, $04, $00, $05, $02, $03 ), { EE }
+    ( $05, $03, $01, $04, $00, $02 ), { EF }
+    ( $01, $04, $03, $05, $02, $00 ), { F0 }
+    ( $05, $02, $04, $01, $00, $03 ), { F1 }
+    ( $03, $00, $01, $02, $05, $04 ), { F2 }
+    ( $05, $02, $04, $00, $03, $01 ), { F3 }
+    ( $02, $04, $00, $05, $01, $03 ), { F4 }
+    ( $01, $02, $05, $00, $03, $04 ), { F5 }
+    ( $05, $04, $03, $01, $02, $00 ), { F6 }
+    ( $01, $02, $05, $04, $00, $03 ), { F7 }
+    ( $02, $04, $00, $05, $03, $01 ), { F8 }
+    ( $04, $00, $01, $02, $05, $03 ), { F9 }
+    ( $03, $04, $05, $01, $02, $00 ), { FA }
+    ( $01, $00, $03, $02, $05, $04 ), { FB }
+    ( $03, $05, $00, $04, $02, $01 ), { FC }
+    ( $02, $03, $04, $01, $05, $00 ), { FD }
+    ( $04, $05, $03, $00, $02, $01 ), { FE }
+    ( $01, $04, $00, $05, $03, $02 )  { FF }
+  );
+
+  MHASH384_ADD: array[0..256] of TRowUI32 =
+  (
+    ( $13B2C18C, $AF30E30D, $5F10AD61, $E8F5FFA6, $7952A3AC, $F215E976 ), { 00 }
+    ( $A7C9CBBA, $BF3C579D, $8C2062B3, $55AAFE8D, $F8151801, $281703B4 ), { 01 }
+    ( $EE69CC38, $74AC54A9, $84C8483B, $059B5078, $3F3319EE, $4B248CD1 ), { 02 }
+    ( $EE7E0264, $3D788335, $D4865073, $1B74418F, $C65AF6E0, $A30D5853 ), { 03 }
+    ( $A2C86BBD, $B7A852D3, $5F97613C, $5F75197A, $D78805E8, $153532A9 ), { 04 }
+    ( $F2D5318B, $5C30FD1E, $3877136D, $C46F4EDD, $97A40BBE, $9FCFEE6E ), { 05 }
+    ( $DAB8050C, $651C9456, $7210B2E0, $EAB621CF, $60F2036E, $DBF9CFC0 ), { 06 }
+    ( $D8575E14, $F084AA1C, $9C1E76C0, $336F6CA9, $8771CBFE, $C2132D38 ), { 07 }
+    ( $86A377A0, $BFF921DA, $16AD6B57, $C8880A45, $AEA6CEDD, $F79BA939 ), { 08 }
+    ( $A008749B, $293CFB8A, $7E8A4C92, $5E84F211, $3CCF7485, $8E54C33E ), { 09 }
+    ( $9A78176F, $7872ECAB, $7EE61199, $F739F0CD, $8B2BA20D, $72B339A5 ), { 0A }
+    ( $F9B79F6C, $27F44D63, $D0E5A65B, $06092C7E, $C4EB60E6, $8304D410 ), { 0B }
+    ( $9C9A92DA, $F8E68CD1, $6DA77F4A, $2013EB87, $D5D48685, $D0D7A557 ), { 0C }
+    ( $12608877, $5B6310FD, $41296D3D, $57435D83, $A906DFDC, $3A1A6D72 ), { 0D }
+    ( $5112C7E6, $EBF6D751, $FD3026A5, $08A39D23, $54134FF1, $EC5B2C8A ), { 0E }
+    ( $2F52EEE6, $40A853D3, $358BED81, $C76B62DF, $8E786E4F, $75F63677 ), { 0F }
+    ( $54ABD27E, $B7EE2BB8, $17756DC1, $B6DE3BBB, $A992B540, $66A4E44A ), { 10 }
+    ( $9B8C6F0B, $3CA2CEB1, $BD583C09, $14713651, $AA79A7DE, $28C3D1C5 ), { 11 }
+    ( $ABB4F78B, $D3E194D8, $AA0A85E3, $C9C7B196, $3885710F, $0392E30B ), { 12 }
+    ( $A122EA90, $C71A2436, $223F5C82, $8CB0A4FF, $5B9B57D1, $F16A689D ), { 13 }
+    ( $7AFA3B0D, $75E05D93, $BE7D07A1, $89C88598, $FBDBF0C1, $6C47F63E ), { 14 }
+    ( $D3D2BA3F, $61C4F0CF, $9F4B127D, $EAAFA57A, $08CE931D, $C9EC6985 ), { 15 }
+    ( $B0792CA2, $39D65B2C, $7D2FE4DD, $F4C6E55F, $6F26B34B, $392C16F2 ), { 16 }
+    ( $59EFBF60, $056FAD5A, $206CBB30, $DCAE65BE, $D679DCAE, $DD4EE6DB ), { 17 }
+    ( $3FE0CBE3, $3D16C1AE, $2E10E8AA, $EC4D3C7F, $3EC26B8C, $C1952F33 ), { 18 }
+    ( $D515AA2F, $2400E7A5, $4E71FE3A, $D78DFE09, $B3CD989D, $A031E3EB ), { 19 }
+    ( $684B950C, $1F449B7A, $D5BDEF26, $EB6562AD, $2B28F5F3, $0A3DF9F9 ), { 1A }
+    ( $EC3811B9, $7F53DD87, $0BA9B287, $B3D46AAF, $D30D9034, $8F0AEEF9 ), { 1B }
+    ( $76366768, $81F9D6A1, $3386DB56, $D9B20BBF, $5601E297, $30646236 ), { 1C }
+    ( $7FDA5C84, $953B0881, $AC4ACC72, $35565AEE, $D3540FDB, $072C64DD ), { 1D }
+    ( $5F19ABAA, $C91EE5F5, $F5AFB55E, $2BE896A1, $E1C409D5, $74E9FA0F ), { 1E }
+    ( $D372CD9F, $5B676E7C, $4CFB5AF8, $AF377F22, $C931858C, $5445CE0D ), { 1F }
+    ( $423B2C7F, $58695641, $53F7F865, $DD8FF14B, $3787B012, $769070D6 ), { 20 }
+    ( $DCD0417D, $F914813A, $3841DBBF, $601B29BE, $B4B7B901, $DCC3A649 ), { 21 }
+    ( $3BE29DEB, $EDF9A0D0, $F2DDFA0F, $922F23CC, $C4563BC3, $E4122F72 ), { 22 }
+    ( $E88B4666, $DDCEBA90, $5B7B313D, $BE0FDC0A, $5D4431D9, $6D05CEB5 ), { 23 }
+    ( $6BF2646B, $9E4BEF14, $B17DAA68, $731EB896, $B47996F6, $3C0699E9 ), { 24 }
+    ( $3E88E294, $66F97202, $701DBD04, $91CF6F7E, $BC81A5D4, $D5B632EB ), { 25 }
+    ( $5F0C32D5, $0118B38F, $7C72778B, $45E251C9, $0EE9A676, $E18CED9A ), { 26 }
+    ( $0DEC4615, $BCFACA34, $7A33CF9B, $7FFC4202, $3C036C98, $2FB0117F ), { 27 }
+    ( $4BE81882, $D12BC6B9, $FAAC1942, $C825B793, $3D235059, $0C0DB0B2 ), { 28 }
+    ( $1D4049E2, $2A84B86A, $537FDB7E, $EC81B40E, $7DDA393F, $AFA3D7D0 ), { 29 }
+    ( $036B6D44, $9BDE4C03, $805ECC65, $2FB48667, $894CB979, $8B79B9CF ), { 2A }
+    ( $26A1E724, $C041E47B, $C552045C, $5DF502CC, $86B77E47, $CC37F33D ), { 2B }
+    ( $F8733714, $8049E9F7, $00262BDF, $D6E324DB, $A286C1A4, $F44E998B ), { 2C }
+    ( $2AB8AD83, $71FE5EF6, $4905D6E8, $16DAAD77, $04750CAC, $00EE14E7 ), { 2D }
+    ( $C9E482E1, $54B04F45, $05C6636B, $A3501ED2, $F9FB2A23, $895FBECC ), { 2E }
+    ( $AD3D24C5, $D0017ECC, $DFA881B8, $48DC3C52, $97E69D2D, $EFC5D21C ), { 2F }
+    ( $CC56C844, $875BF026, $8AF0DB7A, $C8AA9F7B, $7977E1D8, $96557C38 ), { 30 }
+    ( $51704FD2, $C451174E, $1DC0C5FC, $3C690432, $EE113D49, $1C2F3BE1 ), { 31 }
+    ( $E67BA4D2, $1CA12AD0, $4C5E09B0, $8CC90A26, $6BB15CEF, $04A20BCF ), { 32 }
+    ( $F3A8861E, $ABA8B64B, $A71D73C1, $B33F5566, $D780C2BB, $35A4F1B3 ), { 33 }
+    ( $3AC6E50E, $058237EE, $28CCD3E2, $65C138E9, $36165F62, $BA461352 ), { 34 }
+    ( $C190A454, $3BB14A4B, $6EAA4F8B, $C454F8AF, $23FB09D9, $CC8B3B7A ), { 35 }
+    ( $9A7B55A8, $B97F3D39, $BD95F71C, $F8765FE4, $60E434BF, $4D43C8E3 ), { 36 }
+    ( $7449A794, $17C054E4, $031E4411, $CB8AD1A1, $49ADAE58, $BBC53D1E ), { 37 }
+    ( $44D4328B, $609D1567, $1D278E05, $5ADD1AA9, $98C8FD64, $56B954FF ), { 38 }
+    ( $22BF5E54, $DAF9D8A6, $6D232343, $488EF3C1, $F0147776, $4185C674 ), { 39 }
+    ( $BEBF70A3, $1EC08D69, $404E9F1B, $445D9117, $3CB72E80, $475685E5 ), { 3A }
+    ( $563E64AC, $71D3014A, $72741CFB, $F22ECB26, $4551C41A, $0023EC43 ), { 3B }
+    ( $E3E9DD2B, $37C31996, $E55E66A0, $D12D1F0D, $342599B5, $C56F482F ), { 3C }
+    ( $F1A9E9E3, $770E2D8D, $4B0BA236, $797D4C71, $5514E96F, $BD938686 ), { 3D }
+    ( $2A55DF59, $CC18982D, $093B8D26, $78F7470A, $4F719A03, $4A437F9E ), { 3E }
+    ( $97AB2269, $AC22A233, $5D3D1D17, $7906351E, $3DC9583A, $7FEB2192 ), { 3F }
+    ( $7911E3A5, $D3BC66BF, $70B96F33, $13C364F7, $6BE4373D, $95EE1CA3 ), { 40 }
+    ( $624B1BB9, $B1D57F69, $23D6BEDA, $14C47359, $53C61BBE, $A2630CBA ), { 41 }
+    ( $8614B657, $30CD13F1, $DCFFBAC2, $091A6966, $D18999EC, $AEA3C354 ), { 42 }
+    ( $CEBB00CB, $44C14586, $97BA2ADE, $58E0E16F, $EFD68B88, $757742C8 ), { 43 }
+    ( $ADD6619B, $C64480CE, $9A15BE92, $7E2C055C, $E0E34FFF, $53B744DD ), { 44 }
+    ( $18598EB8, $B9108E1F, $94B5C815, $79FA3053, $E01C1377, $7967D7F2 ), { 45 }
+    ( $AFFFBD10, $0DEAAEF3, $1C66243F, $DD6601F3, $2012069B, $43045C84 ), { 46 }
+    ( $542CCA4B, $5878A842, $292F30B6, $AABB827D, $D8230B3D, $3262082F ), { 47 }
+    ( $D964DDF0, $4D8351A6, $FC140DD6, $2D6B8672, $0532D394, $CA677441 ), { 48 }
+    ( $9B58B961, $9BF99AF4, $478A9887, $4A77DE7C, $0560B7D4, $B1A31887 ), { 49 }
+    ( $3C3415CC, $AC4B8189, $B06793FA, $C0B9C0F2, $479D1B15, $1FA353D8 ), { 4A }
+    ( $5307D37A, $8E7684EB, $E9392362, $6D06BA38, $C1843AB6, $A7ECDDCE ), { 4B }
+    ( $AB93AC3F, $B8C34E0D, $17479CBE, $39B9FF22, $CB2532B3, $B4169E93 ), { 4C }
+    ( $6C7B4787, $295048F3, $27401801, $592ECAB0, $8D36903A, $CDC7255A ), { 4D }
+    ( $1BE412A4, $726A831D, $EB00B75F, $173BFCCA, $952FAEDB, $43EA817D ), { 4E }
+    ( $FBC40010, $D10BDB17, $AE3D20AE, $20347FD2, $AFF07636, $A586CC6E ), { 4F }
+    ( $03000F48, $2C7332CC, $B0020AAD, $09ECB64D, $DBB82864, $8A9CF7C0 ), { 50 }
+    ( $C0D05E64, $11921D7D, $92F79AD0, $4C1F5EC5, $B38AA2C9, $0511831C ), { 51 }
+    ( $8D190938, $6F3AE8FB, $C8EDF48F, $F26CAB54, $B0E7FAA4, $16C2AA21 ), { 52 }
+    ( $359C9C58, $889140C3, $5E70BCB7, $58ACF356, $C3BDB2FB, $A888D5D5 ), { 53 }
+    ( $84F6B9EF, $5C554168, $4A8DCAB7, $5DEDC340, $44C57BF7, $31BFADDB ), { 54 }
+    ( $C42C7720, $94DAD11B, $29FC745D, $3C1F4639, $E52F6DFC, $97DDAE2E ), { 55 }
+    ( $0C8B14C2, $B0D980FE, $135623B6, $5C72D71F, $5B5B8DCA, $DB4A99C0 ), { 56 }
+    ( $5E7BDF3F, $D2885F09, $CF46F88F, $1EB9EFCD, $3CBB6BE0, $907C7544 ), { 57 }
+    ( $BD9BD888, $A6806C72, $E6C0B60F, $7B5B2DCE, $E7AB0E6C, $E220CDC2 ), { 58 }
+    ( $8C55577B, $A5023515, $C6630DE7, $3D3C780A, $3650EECC, $C14EEBCB ), { 59 }
+    ( $709661B9, $AE770422, $A6CF70C5, $B33FA2FE, $EB3AF10A, $F4228B91 ), { 5A }
+    ( $244EA452, $1580EB30, $DFC147E7, $F96FC12E, $17F51E9B, $E0E70E7D ), { 5B }
+    ( $344FD50E, $8F84DFB7, $8539197A, $2FFA298A, $58E522A5, $6B46761B ), { 5C }
+    ( $00047013, $4663B6F3, $58184E79, $CA5F3449, $9607C508, $27FA414C ), { 5D }
+    ( $EFC168C3, $DC017B33, $7F31A48D, $6B4B3C6E, $3CD05242, $653C3728 ), { 5E }
+    ( $AAC9448A, $25BFB909, $42213EB3, $0B6EE0F7, $70321152, $40B5B6EA ), { 5F }
+    ( $4F2547E3, $84C88B48, $C789D44C, $E8317D46, $FB1E318E, $A3338DD8 ), { 60 }
+    ( $D80FB73E, $8144D28C, $33A441CC, $B7736354, $A91B2A6E, $3C973147 ), { 61 }
+    ( $D0C2FF1D, $F80BAB81, $7E006359, $5A050090, $928374BC, $E636C5E9 ), { 62 }
+    ( $29C96D66, $AEE27C6C, $267CE151, $40747378, $B04CD4D9, $5140C1F3 ), { 63 }
+    ( $156B775E, $9A4D35D0, $84DA5F3B, $1E794E7A, $6C15952D, $BE34D677 ), { 64 }
+    ( $95FBF1EB, $4BCA6744, $72F0776C, $7C11B4CD, $A5674E3C, $A7022DA4 ), { 65 }
+    ( $6C7098F6, $3535A203, $63224F93, $4FE5F6F1, $4FD60AC0, $6284F031 ), { 66 }
+    ( $B5F1757D, $F0A2E1A9, $4046267D, $2365E6CA, $F01C84B7, $A27177F5 ), { 67 }
+    ( $F7A8A55F, $28E4D223, $6933DBB2, $C06E657C, $404C94B7, $CDC9278E ), { 68 }
+    ( $B88FDB49, $DB3C1CB0, $6643719A, $A78A1157, $74895649, $9B35EA26 ), { 69 }
+    ( $E05200A6, $AF8CBC8F, $76366935, $8C653672, $10A3F99B, $382F29AA ), { 6A }
+    ( $29AB3900, $289C44C4, $1563E45F, $A90A65DE, $30A0BFEC, $AB9FDCCE ), { 6B }
+    ( $E1F20AA6, $EC9D69CA, $03256EA4, $D7BFB23B, $9A838907, $2CAD4277 ), { 6C }
+    ( $DD6B37C3, $816E8914, $50F5D946, $392C3B93, $3F2362CD, $5BFEF741 ), { 6D }
+    ( $6D758401, $DACC8B90, $290771BB, $ED79A318, $1A87526F, $2F2E3E76 ), { 6E }
+    ( $3383AD16, $0F4744FA, $8A1C7B37, $8ECC2413, $7732295A, $A3F6A1AF ), { 6F }
+    ( $F1B25367, $233EEB5B, $279D52B0, $9A046CCA, $B0D76507, $885963AB ), { 70 }
+    ( $EC73E1F9, $6FAED772, $EC780F72, $46C50E26, $6221DB5B, $89CA75E6 ), { 71 }
+    ( $DAD89F5D, $59DB2678, $A579C018, $90DA08F5, $BE9E795E, $11E4D988 ), { 72 }
+    ( $2373AF1F, $CCCFD9AD, $365E9E15, $743A1FF1, $13057CED, $6DD11662 ), { 73 }
+    ( $E32ACFAB, $EC659E78, $0CB472F2, $DD02907E, $FFCE3802, $B91F1963 ), { 74 }
+    ( $43CC1C2D, $A4239D99, $776E306B, $F5749A88, $9CED6490, $2D9DF0DC ), { 75 }
+    ( $3D8A32E9, $F3DB557E, $A7D3EEF1, $329C6341, $3A6D3C73, $09D021F8 ), { 76 }
+    ( $74DE7662, $8FB0F13A, $6793D109, $EFE86A86, $9A396326, $EF96D376 ), { 77 }
+    ( $7C921DE2, $C24C55D5, $3544D45B, $5686D9A2, $5DF25635, $EFC7E954 ), { 78 }
+    ( $6C48781D, $EA8C8306, $757AAD29, $40115C87, $A92EC03D, $F36D3EC2 ), { 79 }
+    ( $8A48EC01, $6AC7EEC6, $E0FF1268, $0A5127C7, $0244071E, $AFB6D0ED ), { 7A }
+    ( $99B29D33, $5E8DCDCB, $DA2ED4A8, $D9CCFD7E, $668BE4DA, $081858C3 ), { 7B }
+    ( $DDDC6207, $B52329C3, $341DB972, $4FAB30E8, $FF821F4D, $47B68C9D ), { 7C }
+    ( $D59521A6, $EB85350D, $CCF547C6, $EF50E0A2, $B549AF5A, $FBB0C484 ), { 7D }
+    ( $5217E9F4, $B27C2313, $C82B22AF, $619A46D0, $4E0FF4FA, $1AB7FED5 ), { 7E }
+    ( $913EBFA5, $BE552440, $B81E27A5, $FEF80DA9, $5C100864, $BC3F8EEE ), { 7F }
+    ( $27627613, $DD53D691, $19BAA1BD, $D179E811, $921BFDA0, $3E1AC539 ), { 80 }
+    ( $17CAC507, $6AA98FE0, $FB02E085, $F6D0EEFB, $676799F4, $12359D40 ), { 81 }
+    ( $554D9AEE, $DEA25249, $C4BC501C, $F011B4B2, $58B984DC, $929C6B5A ), { 82 }
+    ( $3217ADC8, $FD9A6DEE, $C3921E15, $ABD659C1, $ABD33969, $93306767 ), { 83 }
+    ( $35328CAF, $F3C4D7A2, $07B0347E, $3DF627E5, $B273C78C, $ADF208CD ), { 84 }
+    ( $2BD7721F, $F5783803, $1BBB9624, $55B4B105, $FFB3F3CF, $4CF2E1B3 ), { 85 }
+    ( $D165DD68, $B1C01D6D, $1D101E62, $3A0A5662, $3C8722D2, $B744FF5A ), { 86 }
+    ( $449B8418, $29C5CEEB, $974403CD, $E49660AB, $82145199, $20CEB67B ), { 87 }
+    ( $7C2BA473, $E7AE8079, $31432DD8, $8787F5A9, $E04228B5, $33392F2F ), { 88 }
+    ( $962716FA, $0A6F1D12, $46B3F858, $62E219C7, $861E2AF1, $5866B232 ), { 89 }
+    ( $57B30251, $62F51A37, $59324168, $F0836E30, $C083BC01, $778BB1AE ), { 8A }
+    ( $71A1C89E, $ECAC3A4C, $3CBBCE64, $D1F58D2F, $6A5C6E06, $61C64195 ), { 8B }
+    ( $7C05A21C, $155BEAD9, $7EDDFF5C, $78BB8C98, $A8E84E11, $C5EEB1F9 ), { 8C }
+    ( $439FFFB3, $F1AD1346, $9C898BB1, $FAB4D098, $30EF7863, $8B7646E8 ), { 8D }
+    ( $07B9817C, $96A9A389, $4698863E, $024356E1, $38AFF21A, $F4117D09 ), { 8E }
+    ( $A70B2873, $488A3145, $43A5C731, $12A49FD3, $BD0000E5, $9B5E9001 ), { 8F }
+    ( $17D6630F, $F3AE0FCC, $36D04FEB, $20B8C4A8, $717582B9, $48538D7C ), { 90 }
+    ( $91B045FE, $3FDCF695, $356D0D5C, $2EB8808E, $FD4E4CE3, $1DC99A76 ), { 91 }
+    ( $44F1E72A, $4530F446, $B25545D6, $5080498D, $B8C6D8B2, $CB32B8F4 ), { 92 }
+    ( $A8062C57, $3F3EDD44, $48EEE98C, $E25EB954, $1712BDDB, $5270DFE1 ), { 93 }
+    ( $12F901C2, $9DE6D999, $C5728969, $062C5DE5, $3C49C5E4, $5B344AAD ), { 94 }
+    ( $7B41A9D4, $0017D3BD, $AC5A46D5, $AFAF2284, $45EFCEA8, $33CEC63F ), { 95 }
+    ( $B3EAA2A4, $15908324, $DCB5FE00, $D0F1E9D7, $51E362BC, $FECBB788 ), { 96 }
+    ( $2FD5E605, $C6FDCADA, $E4DF9EEB, $22A39E17, $94EE60C9, $F2CE4D87 ), { 97 }
+    ( $5E627410, $DD58EAC8, $76FF0DD4, $A51ACFF9, $406E5D9A, $41F6C488 ), { 98 }
+    ( $910860F9, $8C88E2FB, $6F3E3B4A, $B563F5D9, $3F0FE042, $F3BB7251 ), { 99 }
+    ( $C4720898, $174B8899, $D027627E, $C75E54E5, $FE3A0F70, $B83A697C ), { 9A }
+    ( $97B3FDFB, $DE80D5E2, $974DAFD3, $83506833, $51AA7EF0, $2751E9A9 ), { 9B }
+    ( $486AB0AE, $39C74A47, $8BE5059E, $D306D21F, $466C2587, $B0C35B18 ), { 9C }
+    ( $53D44A4C, $4D5C4EDD, $EF47022B, $03F49875, $58EA6784, $1DB8F4A6 ), { 9D }
+    ( $F36D6C63, $283FCE64, $1F277678, $DA4D0B72, $4EEC07D6, $8BED9511 ), { 9E }
+    ( $5125D019, $31DF9C3D, $558F39A8, $2E823985, $360F63D9, $61FEB82F ), { 9F }
+    ( $E47C41B8, $A70EADF2, $EE5A94B4, $9AA96718, $467AF85B, $46A2071D ), { A0 }
+    ( $EE121014, $2EF7A126, $63B12F85, $AA52F030, $8CCF5A69, $2EF4C5D0 ), { A1 }
+    ( $56E30275, $9C3EC92D, $03C0ABA6, $10816DEA, $75ABE59E, $A9060355 ), { A2 }
+    ( $8C319B84, $CDFFB55A, $9602A044, $4183058F, $6C50CAC6, $76A12BBC ), { A3 }
+    ( $1C25A145, $041EF5B5, $07420A60, $30A79DCE, $9AC49851, $BA509884 ), { A4 }
+    ( $C076D4D4, $D5E8731E, $AEF1C167, $52CE4D69, $461243C2, $59124BE8 ), { A5 }
+    ( $D179B2C7, $06EE1498, $86EF65D0, $C447768F, $87F4BF53, $00D002C5 ), { A6 }
+    ( $FBB7BFA7, $83E7FE96, $C08A6777, $05F43892, $B0217F85, $2CC91FC3 ), { A7 }
+    ( $E8032675, $A17040D9, $A98BD110, $7B746D5B, $71AAAD57, $CF70C5C0 ), { A8 }
+    ( $0732A5B6, $08A88647, $63EA848B, $8922AE62, $00377824, $E6B642F0 ), { A9 }
+    ( $941FF159, $0C6FA82A, $55D7B637, $D5A512AE, $47A6A530, $B36D7D46 ), { AA }
+    ( $CA49B481, $F3788B26, $16C0E515, $2DAEF7D9, $6247A75B, $78484BB5 ), { AB }
+    ( $65104E93, $AA602717, $36EECD02, $843F8EE5, $29A1ACCE, $BDC90BD5 ), { AC }
+    ( $0F62269D, $6D370AC7, $1A16E7F8, $463448CB, $B8B864FB, $CC9EAA14 ), { AD }
+    ( $A05ADD64, $D1544F88, $808E890E, $AD4307FE, $DB9DA315, $0A3C9088 ), { AE }
+    ( $DBB49743, $821DC0E2, $E57A2CD8, $E9F06FC7, $363E1070, $295AA9D5 ), { AF }
+    ( $A326B444, $621F4637, $92616801, $FD1F5FBB, $DC6FFEAC, $58B11C80 ), { B0 }
+    ( $212E49C7, $D151D095, $4B36A276, $2AD77D66, $CF1AAC37, $F77B7920 ), { B1 }
+    ( $A2AB4280, $3971A920, $B906F07C, $D913BA8C, $0429D1C6, $070BB87C ), { B2 }
+    ( $34ABFAAD, $8D662459, $9C5D03C9, $B386D713, $AD737CE3, $72F9F913 ), { B3 }
+    ( $2E8D78B7, $A30453D0, $F4C54371, $D18E0B82, $2B2D1995, $0333AC78 ), { B4 }
+    ( $E1E6FE04, $9804A75D, $FB1F11DE, $D220B6D9, $7CB4BC91, $6EF76861 ), { B5 }
+    ( $BE87A55A, $00D797E6, $0F6281D1, $242235BC, $F7A4054F, $EA57BBDB ), { B6 }
+    ( $987D0049, $03C098D8, $C0C966D5, $D68B7202, $0EC76AA0, $CE4A6659 ), { B7 }
+    ( $701714D3, $CC2B4D3A, $CA8E5A83, $1AE4DF4C, $59EDB778, $33C0ACF9 ), { B8 }
+    ( $E90B0122, $E8002693, $152B3944, $22F42540, $C6574494, $46C28CE2 ), { B9 }
+    ( $72B182AC, $A901F7F6, $5CFDD45B, $39A97979, $C1E75D8D, $7B3C5A41 ), { BA }
+    ( $639C71B4, $BE0FCFF8, $526CF104, $54FAE329, $032098BB, $E7B55777 ), { BB }
+    ( $FEAB769B, $296C0749, $A63BF06F, $0C2D627C, $84607425, $A4F94069 ), { BC }
+    ( $F2C938A7, $27D41E44, $7E56AA59, $6DE46E6C, $DBEDFC6D, $04401409 ), { BD }
+    ( $32FC8801, $8516D260, $64D61AFE, $96594532, $1EBACA12, $6F093C6B ), { BE }
+    ( $4DCDBDAC, $4DE66599, $2794AABC, $93FF2F9D, $7E2AA11A, $F0CF874A ), { BF }
+    ( $DE166A6B, $BAC8ED71, $36FE1A68, $C0F096DF, $85B741C5, $96BB9548 ), { C0 }
+    ( $F1DAF2D2, $8BD22114, $E6909F91, $767E60EF, $4CF7FAF2, $BB801A57 ), { C1 }
+    ( $46BAA05B, $20DD6D7A, $4B6774B5, $9D9DDDED, $FDD60142, $5351A50A ), { C2 }
+    ( $1154D2B9, $6243A3C8, $EFBA1A3C, $D880D653, $59CD5256, $4BEF63AC ), { C3 }
+    ( $BB7F0FCA, $8BCF3DEE, $EF7CD3E8, $409A6EA5, $D05B2A11, $CB3F8B7D ), { C4 }
+    ( $5CDF0286, $15AA322B, $82F74519, $19762535, $10AEEA00, $A6C6BB13 ), { C5 }
+    ( $4F8CCF64, $C175F9A2, $458A2088, $334E560B, $3ED94A31, $C36FFEA0 ), { C6 }
+    ( $2A749029, $A780E916, $32183706, $932F528E, $1D50C3E4, $E089FC18 ), { C7 }
+    ( $AA26728F, $C29D086D, $61F88E5C, $2CEFEA8D, $EE88F1DD, $C89BBA0F ), { C8 }
+    ( $A5E2CD57, $629DC4B7, $C7726079, $EEA440B1, $507D7674, $A03EED7F ), { C9 }
+    ( $23B73098, $7BE996C7, $6C8BBDDA, $7D881A37, $12447B37, $112E9D40 ), { CA }
+    ( $C21D0A92, $D09A010A, $CD357AF3, $0526B63F, $D1E2DF26, $4FF48234 ), { CB }
+    ( $950D59CD, $0639DBE1, $9C332783, $FA49C746, $953DC7EB, $8EB136E4 ), { CC }
+    ( $99A8F4FE, $896A1686, $DE1BE583, $20E3A642, $0E65E5D5, $0FACDACC ), { CD }
+    ( $4F8ADD7D, $C27A7DFF, $65438661, $04BE6BB2, $DF80958C, $67369A32 ), { CE }
+    ( $104E92CE, $94E19F20, $6FAA86F3, $9A25E48D, $0482204E, $912C2D1B ), { CF }
+    ( $28AC8824, $81DD3CBF, $D4003B0A, $5FA83632, $5F485E0A, $5F819A8A ), { D0 }
+    ( $E6D0E6AB, $09E97DC8, $5E946DBE, $7DD90573, $F5ECA786, $B0BBD0BC ), { D1 }
+    ( $B8D377F1, $8FA2B637, $2B35180A, $28464162, $C455D035, $7DFA9021 ), { D2 }
+    ( $6AC52907, $2749E4C6, $6AD6A4D0, $3B7174DA, $FE19E3EF, $F9F1F40A ), { D3 }
+    ( $DB100345, $F5D5FFFE, $5AAF4546, $A95A6CC5, $B172E231, $92B8E45F ), { D4 }
+    ( $617D2C5B, $E133BB0C, $95CE7C6F, $E859BBF1, $E12576F7, $74D28A61 ), { D5 }
+    ( $C284CA4E, $CCF3DCDE, $C69CF9DB, $D397A5D3, $02809CDC, $7FBC873F ), { D6 }
+    ( $177158DC, $2B30DC6A, $AF526BD8, $79E783CB, $C8D635C5, $68B89A41 ), { D7 }
+    ( $350FDBE3, $909AA71C, $C199C6F3, $970566A2, $58BF37DA, $62CA0756 ), { D8 }
+    ( $8B629171, $83C60BD9, $55E7DE9D, $0A87FD89, $63165A91, $C4BE5C85 ), { D9 }
+    ( $7B8B02E2, $98B5A8CC, $97BE12B3, $EFC17CC8, $620E1180, $BBE6B9D2 ), { DA }
+    ( $97936B90, $3059A8D7, $99242C99, $5212715B, $3B40E4A2, $47B330FF ), { DB }
+    ( $DEE82F48, $9C5862A5, $46C98152, $DE26C0C1, $A07CDCE2, $BC69F20C ), { DC }
+    ( $AAEA3141, $F840354A, $7EE1A095, $498F6DAC, $EAE8216D, $B65E96A0 ), { DD }
+    ( $12D75D9C, $6AAA1531, $AE20DF76, $FE257981, $434EE77B, $549C7579 ), { DE }
+    ( $1B2FC468, $0940E108, $60DE1A9E, $41D46F89, $CF0DD612, $7AA0386B ), { DF }
+    ( $A56433F6, $789100BA, $50CDB7E9, $3A11AE6C, $8224361A, $1F8B3C14 ), { E0 }
+    ( $FD6D3A1C, $E92DA632, $08B35A14, $6DF921CD, $BE887850, $EE1AD2A4 ), { E1 }
+    ( $772C59F4, $B9570E21, $7448E01C, $A632B61E, $4A0218E4, $48D4936B ), { E2 }
+    ( $001CB7C4, $642511D7, $5E1457A9, $1BD71C53, $F88EBB30, $AAF79F12 ), { E3 }
+    ( $3B29999C, $61F2A87B, $A71C8C84, $0B3FD74B, $991AC230, $1CD5189C ), { E4 }
+    ( $97F0DB05, $4166DBCB, $F9CD085B, $083FF569, $CD95CEBD, $A0A4AC2C ), { E5 }
+    ( $8C28FED9, $0BA76739, $D7C81E03, $28EC9369, $F47EB379, $4E03C624 ), { E6 }
+    ( $88EF27AD, $17971236, $4DE8CC38, $D468926B, $8BE392B3, $56394091 ), { E7 }
+    ( $AD7B6B0C, $E6086D38, $74CC103E, $734FC4AB, $18963383, $F5D7FD09 ), { E8 }
+    ( $36B40975, $7E419219, $D109DB23, $DD569F6F, $CC5DF3F2, $637C2AAC ), { E9 }
+    ( $C354E0FF, $711DABE3, $3808EEEA, $6C206679, $D75040EA, $40FB6C41 ), { EA }
+    ( $DD9AAB46, $41E64E67, $261A425B, $80CB3F7C, $A531A139, $75934DFA ), { EB }
+    ( $14E44A08, $1F8CA28B, $FFC69542, $B3511A69, $F8AA034C, $26E52E01 ), { EC }
+    ( $5C5B2089, $B37C0B0F, $D8D0BD18, $40932C2F, $DCEE2FEF, $52829953 ), { ED }
+    ( $37EA566F, $089C4DD1, $9F60D762, $F2785486, $A93A6B0D, $6503063D ), { EE }
+    ( $C0CBE2C7, $4E23C526, $606B72F0, $884B7A05, $A66EF67B, $F30DD80A ), { EF }
+    ( $F3F276E0, $3591C692, $B2BB885B, $DBC22E58, $786DCA29, $15EA0D06 ), { F0 }
+    ( $90B7A296, $2CC1EC9D, $20922AE6, $350B8EDF, $580DB6C1, $901E6725 ), { F1 }
+    ( $C099DE21, $1DE1594E, $48D23351, $D1CE1FE8, $76E26671, $805E744A ), { F2 }
+    ( $89071E13, $E8E8A47A, $2CE727B9, $BEFABBF6, $3F74A756, $5AE23E2D ), { F3 }
+    ( $FD08E5DC, $8B66E48C, $49CD25B2, $356BD7E7, $932AE9BA, $C0CF4D42 ), { F4 }
+    ( $AD61073E, $146D10C0, $15B984C6, $07EB3FA4, $AFBCA5F1, $0AA183BF ), { F5 }
+    ( $F82147A4, $DF3D897C, $AA3B554A, $E36AD282, $ADB5E14B, $554584CA ), { F6 }
+    ( $84EC67B4, $D84B3426, $2BF0A6C9, $8BA3F8EF, $D62D5A8B, $17D965CA ), { F7 }
+    ( $03B5AB0C, $286A2AF1, $3DB59FB3, $FD8F8BF1, $68BE8B49, $5202D21E ), { F8 }
+    ( $214C307C, $D465D180, $C48070A1, $94677855, $5C6718B7, $7D664FB3 ), { F9 }
+    ( $0BADDFF8, $4CCC4ECC, $E1316FCC, $CA0A5855, $1E0D8CF4, $0C1EE3D8 ), { FA }
+    ( $F36A2187, $9C5E64DB, $4C5AF0E2, $8A45458F, $8204D381, $4CE31874 ), { FB }
+    ( $4F76AFA5, $FF63720D, $1F09FE8C, $88D7E902, $6FC04CD8, $5529EB97 ), { FC }
+    ( $63844962, $85F09D22, $10E25062, $9C0BE84F, $039440B5, $8FBEBA32 ), { FD }
+    ( $C447A427, $BADC88EB, $3EC48572, $294CE83C, $43E4CA7D, $D5AFDCFE ), { FE }
+    ( $CC7D264F, $DB754D7E, $0D20575C, $0DD2BA81, $8B6ED8AA, $AE865123 ), { FF }
+    ( $636A5244, $203CB521, $06F933FF, $B99B48DC, $B765E439, $8BA82256 )  { ZZ }
+  );
+
+  MHASH384_FIN: array[0..MHASH384_SIZE-1] of Byte =
+  (
+    $19, $12, $23, $16, $01, $1F, $09, $00, $0C, $2A, $05, $11, $07, $13, $0D, $02,
+    $14, $2E, $0A, $26, $2B, $1C, $20, $17, $2D, $04, $29, $1A, $21, $06, $22, $28,
+    $0F, $1E, $25, $10, $0B, $2F, $1B, $0E, $15, $2C, $1D, $27, $08, $03, $24, $18
+  );
+
+{ --------------------------------------------------------------------------- }
+{ UTILITY FUNCTIONS                                                           }
+{ --------------------------------------------------------------------------- }
+
+function Mix128To64(const u: UI64; v: UI64): UI64;
+const
+  KMUL: UI64 = UI64($9DDFEA08EB382D69);
+begin
+       v := (v xor u) * KMUL;
+       v := v xor (v shr 47);
+       v := (v xor u) * KMUL;
+       v := v xor (v shr 47);
+       Result := v * KMUL;
+end;
+
+procedure Iterate(const hash: PRowUI64; const p_xor: PRowUI64; const p_mix: PRowByte; const p_add: PRowUI32);
+var
+  i: Integer;
+  temp: TRowUI64;
+begin
+  for i := 0 to MHASH384_WORDS-1 do
+  begin
+    temp[i] := Mix128To64(hash^[i] + p_add^[i], hash^[p_mix^[i]]) xor p_xor^[i];
+  end;
+  Move(temp[0], hash[0], SizeOf(UI64) * MHASH384_WORDS);
+end;
+
+function GetByte(const hash: PRowUI64; const idx: Byte): Byte;
+begin
+  Result := hash^[idx div 8] shr ((idx mod 8) * 8);
+end;
+
+{ --------------------------------------------------------------------------- }
+{ PUBLIC FUNCTIONS                                                            }
+{ --------------------------------------------------------------------------- }
+
+constructor TMHash384.Create;
+begin
+  Reset;
+end;
+
+procedure TMHash384.Update(const value: Byte);
+begin
+  if finished then
+  begin
+    raise EInvalidOp.Create('Hash computation finished. Must call reset() first!');
+  end;
+  Iterate(@hash, @MHASH384_XOR[value], @MHASH384_MIX[rnd], @MHASH384_ADD[value]);
+  rnd := rnd + 1;
+end;
+
+procedure TMHash384.Update(const data: TByteArray);
+var
+  i: Integer;
+begin
+  if finished then
+  begin
+    raise EInvalidOp.Create('Hash computation finished. Must call reset() first!');
+  end;
+  for i := 0 to High(data) do
+  begin
+    Iterate(@hash, @MHASH384_XOR[data[i]], @MHASH384_MIX[rnd], @MHASH384_ADD[data[i]]);
+    rnd := rnd + 1;
+  end;
+end;
+
+procedure TMHash384.Update(const data: TByteArray; const len: Integer);
+var
+  i: Integer;
+begin
+  if finished then
+  begin
+    raise EInvalidOp.Create('Hash computation finished. Must call reset() first!');
+  end;
+  if len < 0 then
+  begin
+    raise EInvalidArgument.Create('Length must not be negative!');
+  end;
+  if len > Length(data) then
+  begin
+    raise EOverflow.Create('Length exceeds the size of TByteArray!');
+  end;
+  for i := 0 to len-1 do
+  begin
+    Iterate(@hash, @MHASH384_XOR[data[i]], @MHASH384_MIX[rnd], @MHASH384_ADD[data[i]]);
+    rnd := rnd + 1;
+  end;
+end;
+
+procedure TMHash384.Update(const data: TByteArray; const offset: Integer; const len: Integer);
+var
+  i, limit: Integer;
+begin
+  if finished then
+  begin
+    raise EInvalidOp.Create('Hash computation finished. Must call reset() first!');
+  end;
+  if (offset < 0) or (len < 0) then
+  begin
+    raise EInvalidArgument.Create('Length or offset must not be negative!');
+  end;
+  limit := offset + len;
+  if (limit > Length(data)) or (limit < 0) then
+  begin
+    raise EOverflow.Create('Length plus offset exceeds the size of TByteArray!');
+  end;
+  for i := offset to limit-1 do
+  begin
+    Iterate(@hash, @MHASH384_XOR[data[i]], @MHASH384_MIX[rnd], @MHASH384_ADD[data[i]]);
+    rnd := rnd + 1;
+  end;
+end;
+
+procedure TMHash384.Update(const data: PChar; const len: LongWord);
+var
+  i: LongWord;
+begin
+  if finished then
+  begin
+    raise EInvalidOp.Create('Hash computation finished. Must call reset() first!');
+  end;
+  if len > 0 then
+  begin
+    for i := 0 to len-1 do
+    begin
+      Iterate(@hash, @MHASH384_XOR[Byte(data[i])], @MHASH384_MIX[rnd], @MHASH384_ADD[Byte(data[i])]);
+      rnd := rnd + 1;
+    end;
+  end;
+end;
+
+procedure TMHash384.Update(const str: String);
+begin
+  Update(PChar(str), Length(str));
+end;
+
+procedure TMHash384.Update(const stream: TStream);
+var
+  len: Integer;
+  buffer: TByteArray;
+begin
+  repeat
+    len := stream.Read(buffer, Length(buffer));
+    if len > 0 then
+    begin
+      Update(buffer, len);
+    end;
+  until len <= 0;
+end;
+
+function TMHash384.GetDigest: TMHash384Digest;
+var
+  i: Integer;
+  p_xor: PRowUI64;
+  p_add: PRowUI32;
+begin
+  if finished then
+  begin
+    raise EInvalidOp.Create('Hash computation finished. Must call reset() first!');
+  end;
+  p_xor := @MHASH384_XOR[256];
+  p_add := @MHASH384_ADD[256];
+  for i := 0 to MHASH384_SIZE-1 do
+  begin
+    Iterate(@hash, p_xor, @MHASH384_MIX[rnd], p_add);
+    rnd := rnd + 1;
+    Result[i] := GetByte(@hash, MHASH384_FIN[i]);
+  end;
+  finished := True;
+end;
+
+procedure TMHash384.Reset;
+begin
+  rnd := 0;
+  Move(MHASH384_INI[0], hash[0], SizeOf(UI64) * MHASH384_WORDS);
+  finished := False;
+end;
+
+{ --------------------------------------------------------------------------- }
+{ CONVENIENCE FUNCTIONS                                                       }
+{ --------------------------------------------------------------------------- }
+
+class function TMHash384.Compute(const data: TByteArray): TMHash384Digest;
+var
+  instance: TMHash384;
+begin
+  instance := TMHash384.Create();
+  instance.Update(data);
+  Result := instance.GetDigest();
+  FreeAndNil(instance);
+end;
+
+class function TMHash384.Compute(const data: TByteArray; const len: Integer): TMHash384Digest;
+var
+  instance: TMHash384;
+begin
+  instance := TMHash384.Create();
+  instance.Update(data, len);
+  Result := instance.GetDigest();
+  instance.Free;
+end;
+
+class function TMHash384.Compute(const data: TByteArray; const offset: Integer; const len: Integer): TMHash384Digest;
+var
+  instance: TMHash384;
+begin
+  instance := TMHash384.Create();
+  instance.Update(data, offset, len);
+  Result := instance.GetDigest();
+  instance.Free;
+end;
+
+class function TMHash384.Compute(const data: PChar; const len: LongWord): TMHash384Digest;
+var
+  instance: TMHash384;
+begin
+  instance := TMHash384.Create();
+  instance.Update(data, len);
+  Result := instance.GetDigest();
+  instance.Free;
+end;
+
+class function TMHash384.Compute(const str: String): TMHash384Digest;
+var
+  instance: TMHash384;
+begin
+  instance := TMHash384.Create();
+  instance.Update(str);
+  Result := instance.GetDigest();
+  instance.Free;
+end;
+
+class function TMHash384.Compute(const stream: TStream): TMHash384Digest;
+var
+  instance: TMHash384;
+begin
+  instance := TMHash384.Create();
+  instance.Update(stream);
+  Result := instance.GetDigest();
+  instance.Free;
+end;
+
+end.
diff --git a/ports/delphi/test/MHash384Test.cfg b/ports/delphi/test/MHash384Test.cfg
new file mode 100644 (file)
index 0000000..e9c1cc1
--- /dev/null
@@ -0,0 +1,38 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-LE"c:\program files (x86)\borland\delphi7\Projects\Bpl"
+-LN"c:\program files (x86)\borland\delphi7\Projects\Bpl"
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST
diff --git a/ports/delphi/test/MHash384Test.dof b/ports/delphi/test/MHash384Test.dof
new file mode 100644 (file)
index 0000000..b1bb997
--- /dev/null
@@ -0,0 +1,136 @@
+[FileVersion]
+Version=7.0
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=0
+K=0
+L=1
+M=0
+N=1
+O=1
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=0
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+NamespacePrefix=
+SymbolDeprecated=1
+SymbolLibrary=1
+SymbolPlatform=1
+UnitLibrary=1
+UnitPlatform=1
+UnitDeprecated=1
+HResultCompat=1
+HidingMember=1
+HiddenVirtual=1
+Garbage=1
+BoundsError=1
+ZeroNilCompat=1
+StringConstTruncated=1
+ForLoopVarVarPar=1
+TypedConstVarPar=1
+AsgToTypedConst=1
+CaseLabelRange=1
+ForVariable=1
+ConstructingAbstract=1
+ComparisonFalse=1
+ComparisonTrue=1
+ComparingSignedUnsigned=1
+CombiningSignedUnsigned=1
+UnsupportedConstruct=1
+FileOpen=1
+FileOpenUnitSrc=1
+BadGlobalSymbol=1
+DuplicateConstructorDestructor=1
+InvalidDirective=1
+PackageNoLink=1
+PackageThreadVar=1
+ImplicitImport=1
+HPPEMITIgnored=1
+NoRetVal=1
+UseBeforeDef=1
+ForLoopVarUndef=1
+UnitNameMismatch=1
+NoCFGFileFound=1
+MessageDirective=1
+ImplicitVariants=1
+UnicodeToLocale=1
+LocaleToUnicode=1
+ImagebaseMultiple=1
+SuspiciousTypecast=1
+PrivatePropAccessor=1
+UnsafeType=0
+UnsafeCode=0
+UnsafeCast=0
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=
+UnitOutputDir=
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=
+Packages=
+Conditionals=
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Language]
+ActiveLang=
+ProjectLang=
+RootDir=
+[Version Info]
+IncludeVerInfo=0
+AutoIncBuild=0
+MajorVer=1
+MinorVer=0
+Release=0
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1031
+CodePage=1252
+[Version Info Keys]
+CompanyName=
+FileDescription=
+FileVersion=1.0.0.0
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=1.0.0.0
+Comments=
diff --git a/ports/delphi/test/MHash384Test.dpr b/ports/delphi/test/MHash384Test.dpr
new file mode 100644 (file)
index 0000000..0010dbd
--- /dev/null
@@ -0,0 +1,144 @@
+{* ---------------------------------------------------------------------------------------------- *}
+{* MHash-384 - Simple fast portable secure hashing library                                        *}
+{* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            *}
+{*                                                                                                *}
+{* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  *}
+{* and associated documentation files (the "Software"), to deal in the Software without           *}
+{* restriction, including without limitation the rights to use, copy, modify, merge, publish,     *}
+{* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  *}
+{* Software is furnished to do so, subject to the following conditions:                           *}
+{*                                                                                                *}
+{* The above copyright notice and this permission notice shall be included in all copies or       *}
+{* substantial portions of the Software.                                                          *}
+{*                                                                                                *}
+{* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  *}
+{* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     *}
+{* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *}
+{* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *}
+{* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *}
+{* ---------------------------------------------------------------------------------------------- *}
+
+program MHash384Test;
+
+{$APPTYPE CONSOLE}
+
+uses
+  SysUtils,
+  StrUtils,
+  MHash384 in '..\libmhash384\MHash384.pas';
+
+{ --------------------------------------------------------------------------- }
+{ TEST DATA                                                                   }
+{ --------------------------------------------------------------------------- }
+
+type
+  TTestVector = record
+    count: LongWord;
+    text: String;
+  end;
+
+const
+  TestVectors: array[0..11] of TTestVector =
+  (
+    ( count: $00000001; text: '' ),
+    ( count: $00000001; text: 'abc' ),
+    ( count: $00000001; text: 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq' ),
+    ( count: $00000001; text: 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu' ),
+    ( count: $000186A0; text: 'aaaaaaaaaa' ),
+    ( count: $01000000; text: 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno' ),
+    ( count: $00000001; text: 'The quick brown fox jumps over the lazy dog' ),
+    ( count: $00000001; text: 'The quick brown fox jumps over the lazy cog' ),
+    ( count: $00000001; text: 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern' ),
+    ( count: $00000001; text: 'Frank jagt im komplett verwahrlosten Taxi quer durch Bayern' ),
+    ( count: $00000001; text: 'Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. ' + 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' + 'Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' ),
+    ( count: $00000001; text: 'Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. ' + 'Ut enim ad minim veniam, quis nostrud exercitation ullamc0 laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' + 'Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' )
+  );
+
+  Expected: array[0..11] of TMHash384Digest =
+  (
+    ( $D6, $29, $CB, $37, $F7, $61, $56, $62, $1E, $09, $C9, $3B, $8D, $10, $29, $C5, $F0, $F7, $B7, $78, $DE, $5B, $D9, $57, $82, $30, $67, $3F, $E7, $FA, $4C, $45, $A2, $30, $8A, $B4, $E9, $D9, $9A, $A0, $EA, $19, $4C, $BF, $62, $30, $C2, $02 ),
+    ( $1D, $7B, $15, $93, $D7, $AA, $4D, $D7, $DC, $8D, $A6, $D6, $BD, $59, $1D, $8B, $50, $7C, $A5, $14, $E1, $C7, $EC, $37, $F4, $3E, $78, $DD, $6B, $83, $25, $3C, $35, $54, $03, $F6, $10, $09, $58, $28, $90, $48, $0C, $4C, $D5, $27, $F4, $05 ),
+    ( $9B, $98, $CE, $4C, $3F, $4E, $A9, $01, $8E, $1E, $D3, $03, $47, $17, $E3, $E5, $D8, $DA, $20, $AB, $37, $5B, $AF, $E3, $72, $D0, $77, $80, $FF, $DE, $FD, $A3, $2B, $A3, $C8, $22, $15, $5E, $28, $83, $E3, $33, $AF, $CA, $AE, $AF, $A6, $14 ),
+    ( $45, $41, $6D, $1F, $FD, $44, $D3, $94, $0C, $5A, $F5, $B4, $25, $B5, $DA, $07, $FD, $8C, $06, $BA, $B7, $C5, $8C, $D1, $33, $89, $BC, $28, $46, $50, $ED, $60, $90, $A9, $A1, $95, $2C, $29, $FE, $B1, $B2, $C6, $AF, $BF, $5F, $99, $61, $08 ),
+    ( $20, $77, $4C, $57, $0A, $E2, $E6, $A4, $9A, $01, $DA, $E9, $48, $67, $2A, $E9, $4D, $46, $5D, $91, $67, $13, $0F, $E8, $7B, $F2, $41, $48, $64, $9C, $F1, $21, $E8, $A5, $07, $59, $50, $7B, $F9, $71, $34, $F0, $D2, $8C, $EE, $91, $DC, $A2 ),
+    ( $C1, $88, $43, $D4, $DD, $9E, $04, $79, $D3, $8A, $55, $E8, $C7, $5E, $22, $01, $F0, $E9, $3B, $6E, $F1, $F9, $16, $EB, $AF, $3C, $40, $74, $D1, $88, $94, $5C, $7B, $96, $57, $F4, $52, $69, $A1, $DA, $AB, $4A, $8F, $B6, $F6, $3D, $0B, $EE ),
+    ( $E2, $90, $1E, $DB, $76, $AA, $83, $F2, $D5, $2F, $EA, $9A, $34, $EB, $2B, $C0, $5E, $DF, $A9, $57, $1C, $81, $26, $20, $24, $5B, $BE, $BA, $95, $FA, $2D, $82, $CB, $B5, $BA, $D9, $3E, $B6, $4D, $4B, $72, $B4, $66, $35, $D5, $65, $40, $0B ),
+    ( $8B, $81, $CD, $9C, $1D, $EE, $8B, $CC, $64, $2F, $8B, $1E, $A9, $82, $CE, $79, $D1, $5F, $50, $E6, $69, $39, $FF, $34, $29, $4E, $63, $D9, $3A, $E3, $C6, $10, $F9, $46, $4F, $EF, $EF, $30, $29, $74, $09, $B6, $22, $31, $F0, $28, $AB, $C0 ),
+    ( $A5, $45, $E6, $31, $9F, $6A, $CE, $0C, $EF, $62, $BC, $AA, $F5, $D4, $88, $85, $87, $51, $B9, $6C, $2A, $48, $8D, $5B, $E6, $EC, $63, $D5, $00, $06, $C9, $D5, $4D, $AD, $66, $16, $84, $88, $F0, $3B, $4A, $86, $8D, $3B, $A6, $10, $CC, $F8 ),
+    ( $2B, $EC, $B8, $9D, $D5, $5F, $C9, $F2, $F3, $38, $4D, $F6, $1D, $62, $40, $DD, $A5, $4F, $C2, $75, $D1, $86, $A4, $5A, $88, $3C, $03, $AA, $87, $3D, $DA, $F4, $FA, $D4, $74, $42, $12, $B9, $2D, $26, $05, $4B, $92, $85, $2D, $EA, $5F, $1D ),
+    ( $62, $83, $CE, $91, $DA, $8A, $F5, $09, $1C, $7B, $06, $E1, $35, $2D, $C9, $47, $B9, $E3, $B8, $96, $14, $80, $7C, $04, $C4, $3D, $A3, $22, $32, $1F, $BA, $DA, $D3, $CC, $CA, $BE, $CB, $5C, $1B, $1B, $26, $54, $32, $A6, $03, $91, $21, $E1 ),
+    ( $5D, $CB, $7C, $4B, $27, $BA, $84, $16, $88, $FB, $6A, $86, $0E, $97, $A4, $52, $56, $91, $75, $33, $F6, $34, $48, $CF, $66, $67, $81, $EA, $4B, $5F, $AB, $20, $E1, $C7, $46, $C8, $82, $10, $99, $A9, $15, $22, $2E, $0D, $77, $62, $40, $98 )
+  );
+
+{ --------------------------------------------------------------------------- }
+{ UTILITY FUNCTIONS                                                           }
+{ --------------------------------------------------------------------------- }
+
+function BytesToHex(input: PMHash384Digest): String;
+const
+  Digits: array[0..15] of char = '0123456789ABCDEF';
+var
+  i: Integer;
+begin
+  Result := '';
+  for i := 0 to High(input^) do
+  begin
+    Result := Result + digits[input^[i] shr 4] + digits[input^[i] and $0F];
+  end;
+end;
+
+function RunTest(const count: LongWord; const text: String; const expected: PMHash384Digest): Boolean;
+var
+  hash: TMHash384;
+  digest: TMHash384Digest;
+  i: LongWord;
+begin
+  if count = 1 then
+  begin
+    digest := TMHash384.Compute(text);
+  end
+  else begin
+    hash := TMHash384.Create();
+    for i := 0 to count-1 do
+    begin
+      hash.Update(text);
+    end;
+    digest := hash.GetDigest();
+    FreeAndNil(hash);
+  end;
+  Result := CompareMem(@digest, expected, MHASH384_SIZE);
+  WriteLn(Format('%s - %s', [BytesToHex(@digest), IfThen(Result, 'OK', 'Error!')]));
+end;
+
+{ --------------------------------------------------------------------------- }
+{ MAIN FUNCTION                                                               }
+{ --------------------------------------------------------------------------- }
+
+var
+  i: Integer;
+  success: Boolean;
+begin
+{$IFNDEF FPC}
+  DecimalSeparator := '.';
+  WriteLn(Format('MHash-384 v%d.%.2d-%d [Delphi Compiler %f]' + sLineBreak, [MHASH384_VERSION_MAJOR, MHASH384_VERSION_MINOR, MHASH384_VERSION_PATCH, CompilerVersion]));
+{$ELSE}
+  {$MACRO ON}
+  WriteLn(Format('MHash-384 v%d.%.2d-%d [Free Pascal Compiler %d.%d.%d]' + sLineBreak, [MHASH384_VERSION_MAJOR, MHASH384_VERSION_MINOR, MHASH384_VERSION_PATCH, FPC_FULLVERSION div 10000, (FPC_FULLVERSION mod 10000) div 100, FPC_FULLVERSION mod 100]));
+{$ENDIF}
+  success := True;
+  for i := 0 to High(TestVectors) do
+  begin
+    if not RunTest(TestVectors[i].count, TestVectors[i].text, @Expected[i]) then
+    begin
+      success := False;
+    end;
+  end;
+  if success then
+  begin
+    WriteLn(sLineBreak + 'Self-test completed successfully :-)');
+  end
+  else begin
+    WriteLn(sLineBreak + 'Error: Self-test has failed! :-(');
+  end;
+end.
+
diff --git a/ports/java/.classpath b/ports/java/.classpath
new file mode 100644 (file)
index 0000000..62eae5b
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="test"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-8.0.232.09-hotspot">
+               <attributes>
+                       <attribute name="module" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/ports/java/.project b/ports/java/.project
new file mode 100644 (file)
index 0000000..ed4de92
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>MHash-384</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/ports/java/build.xml b/ports/java/build.xml
new file mode 100644 (file)
index 0000000..d60eabe
--- /dev/null
@@ -0,0 +1,47 @@
+<project default="jar">
+    <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+        <classpath>
+            <pathelement location="lib/ant-contrib-1.0b3.jar"/>
+        </classpath>
+    </taskdef>
+
+    <condition property="outname" value="${outname}" else="mhash384-2.jar">
+        <isset property="outname"/>
+    </condition>
+    <tstamp>
+        <format property="today" pattern="yyyy-MM-dd HH:mm:ss"/>
+    </tstamp>
+
+    <!-- CLEAN -->
+    <target name="clean">
+        <if>
+            <available file="bin" type="dir"/>
+            <then>
+                <delete verbose="true"><fileset dir="bin" includes="**/*.class"/></delete>
+            </then>
+        </if>
+        <if>
+            <available file="out" type="dir"/>
+            <then>
+                <delete verbose="true"><fileset dir="out" includes="**/*.jar"/></delete>
+            </then>
+        </if>
+    </target>
+
+    <!-- COMPILE -->
+    <target name="compile">
+        <mkdir dir="bin"/>
+        <javac srcdir="src" destdir="bin" target="1.8" source="1.8" includeantruntime="false"/>
+    </target>
+
+    <!-- JAR -->
+    <target name="jar" depends="clean,compile">
+        <mkdir dir="out"/>
+        <jar destfile="out/${outname}" basedir="bin">
+            <fileset file="../../COPYING.txt"/>
+            <manifest>
+                <attribute name="Build-Date" value="${today}"/>
+            </manifest>
+        </jar>
+    </target>
+</project>
diff --git a/ports/java/lib/ant-contrib-1.0b3.jar b/ports/java/lib/ant-contrib-1.0b3.jar
new file mode 100644 (file)
index 0000000..0625376
Binary files /dev/null and b/ports/java/lib/ant-contrib-1.0b3.jar differ
diff --git a/ports/java/src/com/muldersoft/mhash384/MHash384.java b/ports/java/src/com/muldersoft/mhash384/MHash384.java
new file mode 100644 (file)
index 0000000..28c5895
--- /dev/null
@@ -0,0 +1,1080 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+package com.muldersoft.mhash384;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+/**
+ * <p><b>MHash-384</b> - Simple fast portable secure hashing library</p>
+ * <p>Copyright(c) 2016-2019 LoRd_MuldeR &lt;mulder2@gmx.de&gt;</p>
+ *
+ * @author LoRd_MuldeR &lt;mulder2@gmx.de&gt;
+ * @version 2.0
+ */
+public class MHash384 {
+
+       public static final int MHASH384_WORDS = 6;
+       public static final int MHASH384_SIZE = MHASH384_WORDS * Long.BYTES;
+
+       public static final short VERSION_MAJOR = 2;
+       public static final short VERSION_MINOR = 0;
+       public static final short VERSION_PATCH = 0;
+
+       //=======================================================================
+       // CONST TABLES
+       //=======================================================================
+       
+       private static class Tables {
+               static final List<Long> INI = createRow(Long.class,
+                       "0wijhYhqPyREc3ADLooZE9AxnykiOAmkiWxO7Jj6Lgh3E9A45iEoRWwM6TTPZlS+");
+
+               static final List<List<Long>> XOR = createTable(Long.class,
+                       "NzBLQQDf3AH4lo4bZq+zsSExOdtzKE2UVecqZjaa2nOxVstOjDFPH7ylKpzZQ5fw", /*00*/
+                       "VMm/y8a7H6jb7VmJZEPeOS+CAdoLGmQaWCaTZnJgLrWEIICsMRdbLNSdxx9nEO/C", /*01*/
+                       "RgCBCI6NKs/2aOKJIJt+i+wtXSxlYQSTuci/IyLklvBwCf5MljjTjb1g7HwvNJwm", /*02*/
+                       "UgXt0iCpcLnhp00lSokPAdhAGp1fIF+NWF/9w8w9w1BXLNjnvTGftDOQlSr2BN58", /*03*/
+                       "rIScK4Ky+knxvozWjGS4NN4mQbtHERLlD+D/slQfs8AyxoyOoz0ZL/yKm0JLmIwF", /*04*/
+                       "QpmMTaSdf+DyZcqas/kqvpXCbUaxjz1dx2L5wz4eBcC2K87UzMP9+DeZGcbvwCSQ", /*05*/
+                       "7/UB73cTEaP/owJsNpv1MdwWDXZJKbhh3zu9kq9YufaywGns76qXcs2Ehp6tUIr+", /*06*/
+                       "oJrqKcjQPT2jx5bsfll3PoQWfx4jONCP4O23HxN7YWR0WEDF5JzJhePFGR/UNYel", /*07*/
+                       "mhv5yopiKIBkcMk4BWRKGYAWT4oBXqEEVQk2wgQbvvQgGljvTE2y352HFf2g0Fk8", /*08*/
+                       "vPGK5+zi+IjCZHMpIm5rtPOZa5J/8TmTfPC4s4k0KTHxvMlJFs4JOem8Mfo7EEYM", /*09*/
+                       "qeLvx4wLGk1x6FWtjIfXr1NBz1jI+5zI1nVPx4aUc8TyyQoTLBn3C5q9gV688oQA", /*0A*/
+                       "z8pPAXXp+0rkQcz6jK/eQekW7VM7wh48SDIcD7NusHhyXCgEXRYR3eSRlGC12UZl", /*0B*/
+                       "YNLITeDi0f/O7HSKlIaxBzHFGhJFDhK1hQyBMGPIC70wd0jb3a+T3paRuW7esN54", /*0C*/
+                       "VbreP6yiunl+VirJ4eO3sZQHW0qraT+l3W1PlZl02vBIIhPhiXwRWG4axZT39V3Z", /*0D*/
+                       "MxwJZQyKvInCNTEG7upOsInmtkrgZzL18ot+ILd5xbTf0jw0UR7TP/6XgS8+Up4R", /*0E*/
+                       "LfNgYBzLEC5ja06pMueSvGdC0B+DDSLzf+i8FHRfLFBXJB3pHWXgiRXZgkSwVp51", /*0F*/
+                       "A+iEaizjrkPj1wssIAdQDCrTBUJHZPS0Bmw43pX8F31FpXpWZL/f6G8EU1idiL1V", /*10*/
+                       "J9q46hS+emhEw3INtTp7OY1h3h9tql5QaT+hXYZ5vmEtDum1Kau7Fy+L+nIZkgwB", /*11*/
+                       "U/Rv9aQjcovhb4u5XHsbKX2/b3glFkL9yM3o0CAQPeOHnnOLcAxTyi+huATz8YqH", /*12*/
+                       "Eddt5SQfzn7fpi8bJGkILv2yWcTcNLiEO32eMabtIuAomTygjJ2DWXTHu5H0kEdk", /*13*/
+                       "Dd2w5klv3MsyZzQAjS+6RBzmalghyLyGW+XOhRJJt8dROH/Z/xI57b+8vr6GAa/0", /*14*/
+                       "FuXMTuVIisoG9fi3ZBjfvqRqs6RgH2rV2dkN/rVasknh/Eleu303IeeZndX1ZI9w", /*15*/
+                       "LOCvaaVz+OmQc5nKBbxm2oVT01ZHF4iMMKf99GzxquoSNTplVXqfs1LoI7wntwrx", /*16*/
+                       "r+K7xfhv6ZN86VMCQoV3pEwHfffRJUtwnFVwFD8JssDPqmTj1P1bjfcbWz9nGAVV", /*17*/
+                       "yxroWy6DrI3Yg3UrIPuLWOTX0d9wik2jPgOHticGO9DPddzbfr7Q4+qLn7DF6I6B", /*18*/
+                       "MX2dSOECO44yteNkK3U2U2UKWFx5zNTkfnbtE/MIq22/Nrr9iH5WjtAz6djxkJQl", /*19*/
+                       "Yqos1tA3tOoDsIK5KK2QwOwEV9Jo11XiQ2ol9hpRSKBfi0lNjwef5/5Xs3X7NRfE", /*1A*/
+                       "nfJPUMOf2nAl/3OGOB+rubpXc9FML5I2SuDnkrI6nPDsE7rZwwvOkOONkTymTHxk", /*1B*/
+                       "iNbs0Y2jNNhqq0beIAB6qR+nLub2x96cfsRN129aiijxUM5lJy5K1DxPntu1UJu7", /*1C*/
+                       "5vLdQQ6pbcYJXAwWb+g/Wr7MCFFA8Gpvf/wnti44OPlsAH9hNNY9FpeEkNz+sYRR", /*1D*/
+                       "HLL8B+0ZV8nr524/BN8SUc40IwFg/flQeWXZBFGon1inBRnXRJ4St41SMwdudhQz", /*1E*/
+                       "uHxFxRSAbNy2aWoozf011r8BfeIsI2/WD+yC9sBKr1b1KEO2VR3fV8rKhyrF1B5l", /*1F*/
+                       "AsXueczR2Sb+67E0CjS/aXRxOY6sqqX6b89rQr35qNBSJG1NRh8TW9rW0GBW0S0S", /*20*/
+                       "L6JRX+yaOG77J8FUHI/2fjBcSOBGTW2YMYrP5zl7pPCPp/K3/Y05HS4NsfvRUcYv", /*21*/
+                       "sNxJG41OTqRD88JJIIKkB7oFZY1KwArEbLEpBz8dudkVkA+1UZnzqnaQP63T9W6W", /*22*/
+                       "CdC2DqzLeOqr3iNacqb+oNmUy0R0nHLODaonZmKUqUDVGNDjzTj3N8WzzQEcSSlM", /*23*/
+                       "eshFp66Sl3zUj73FIFb/0blWSwDjhMqe1rEowiM5/Vo7KP2znvfb5Z9LCFTjEhdE", /*24*/
+                       "vEni2IsoXePlZqNTFGx3kezvlU5o4dH1Bvbd1xfhCJGMfM6inQ+zgQ2MgYbX25dk", /*25*/
+                       "4EsERf+R+MLr4ocrbaehdb/C84p5Zc6F3An9TitTPyGIbDql9R2qDbIm2FBqYCgw", /*26*/
+                       "OvN5Y2FimmBtUeRTvKM5o+zbWmphkq3XqiTphm1yQ9BlmML0ZLVVhbDWwTGrEqpW", /*27*/
+                       "/3vBwYXt2c7C/7qsJSNS65RT0bL02NME6m51BExQcdLxJ/gaqaTbLeQCgI/C1Wcf", /*28*/
+                       "j8AtQ60InIvHu5aX4kN1Wt5nGTxb26Y05E6AosI7bgF1LxflzMqbW7q9rYCLWUl1", /*29*/
+                       "VdHNxRexP2/F7tacpbDDFmmHU94RpKHZfMNKn5dUjJPbhFLVwbw3N7drFfmKn61s", /*2A*/
+                       "3+t1nE8ov+voPXUGtOuDszxAfO56EoaqJ+A9UhDdvxATikrrxPaLE2eweNt99u+x", /*2B*/
+                       "Xtqjeo0T0fZxY7aPjQmouvKqbIsbbefa3B6NNjQQD0B30uhyUX+TfO/mrTz4uwV9", /*2C*/
+                       "gbA0z6YunA6gC/ZYDbM2kMqL8EhYLDrbZNVQQrnReshmYfnuCS6JfPOFEFfPhdsm", /*2D*/
+                       "KsEYh/XjHiXkKooXgY1D+aioOZCImpLw/cy9XiJla/DGc7/37RRNLs/6HbyVmDap", /*2E*/
+                       "y3lpHbQC48oj5h61WFr6uy+1GsiduRNRVqAX7Ft5k2BeNV4uTftxj/KiNLrtki92", /*2F*/
+                       "/9mkZVIBMNHIJh/XU6K+CeYhZcTt6raBqbiCVhZo4vojtkp3xD6cqLKdIVXgRS4N", /*30*/
+                       "q5Kmw4QCViu4p3mz0IoAN/wL+TAszRGv7WInDyV66H/DQnJkEdf7w70is/Zkgu10", /*31*/
+                       "Qzmtp8hcGSjET0xGCOjLUyaHX3Z6PY7VT6qFAfZSMNjntDsihQ3L7yisf3heMDFa", /*32*/
+                       "Q5XxMOIOXXLgNN+9xtKRkAFGdcLGSb7ja1atpAswvmHBfPpRdZ3XAljaHF8PkUNl", /*33*/
+                       "P7SBRMStmUCB69kvkmET/qzOH0SewImpGZDL0xM6m0Q0ESBvOb6pRf4zZgRa0Brc", /*34*/
+                       "aT4vUm06VhqeWkefB55YvjgATI5jqaJ1YgN6VwJiO9r2enINHj8dITOS2ZpS/B9e", /*35*/
+                       "G9DWxoYetkcYw62tg299Q4xz7Y0CYaPVSxYlBGNMDaDSnUyvpa9pGoK1UflnHJ75", /*36*/
+                       "eeq9tkB3aqajgK+WFP/3/oyJzeo+1K8FNHGtMe14DLBzZoTXGhrTDr6ZFBZEaLl0", /*37*/
+                       "LtH2y2yN+kZWOTB/FPzCMX8GX94BRH9w6ZQ148f+5ToUF1Njip/jKLLKnx7qKbO3", /*38*/
+                       "BHhcglX32O/RDNMLh5NaHxaH/3FGib/vWNor8n9h7SgutlyuzIkSQfnyARj0Qt2V", /*39*/
+                       "4Vn8RYZbUqgMf18KwC3mdawWBCGFZ8UJJnYNs+l271Bl1vUZ3Cw7K//02BHNlxKk", /*3A*/
+                       "OVDunmSayeplADwUL8mTpQYSBwNScxSz7KRkx6BhJ+qzJaxs1H+qAr8DbamCwYzG", /*3B*/
+                       "qDzITgI/h7LrU4j9uApHl70Fs1nBFf4Y/erqh/YIq7BDLmBz3j8KUfD88MxNuOED", /*3C*/
+                       "2MAzgNy7W9hP86mcw9kjkv3DY1ttyzt9tQ8M2nT5MBxDUfu+nrwki/yEe1uSVInF", /*3D*/
+                       "p9dECC58vWoNU99sReryzLghOSv1jJPofGWB8qI8Arqu7dF1pl1j7Gy+4S7yUqq0", /*3E*/
+                       "BFnLd8Y6HJhJe4eETLWSahVYxUC7plt07XGjIg1Vr7d0U1/Gh73o1fU49fA3Sodn", /*3F*/
+                       "IcDsnSq6O8JQNA4Lkw5hTn5XdxSpGmgadsPtFJcgozi2SuvuY1XRD3gh1AGKZld9", /*40*/
+                       "tZigReGM+GpGi4vYjIXrGujW4rivM7fo+uunEIyqPzHqfFV3Xjd9ElUhLwv3or2W", /*41*/
+                       "Nravj5cDiexjlwdcQjwhx3zRtmoDhAN2SR9fOCY6xuD1bRqB1neYKY24BFP8kG+H", /*42*/
+                       "Frrg1sK7+qa85oAAZMlwm3uymFUm1bIpfjnkJsdXlkrVeGZ2xswBqJiZYXLM9w6A", /*43*/
+                       "v5BUz6gxWSOfh48OjvmY56cM8zic4u7GJAA+1fJ5mpJFelhJJ+HyiGUZiTiPsoUL", /*44*/
+                       "J9ik5AMDXhZqQ+jRQk+ZZxsNE27Pi8zm/N6dcBEXEFAoU9AMxN47N/YJUaqkdLJA", /*45*/
+                       "yPj9CKCL+Kla4G5H45fI7HR61WmrkOK8XRHjERjbRPqIDEhk/a5nYuvsOi1K0Jcm", /*46*/
+                       "EzPNq/IqeMBzYvnykBK6ArnCrVYaL8hjxFH+PsDo+BD9r8wlhjTr467nuJyWB9aT", /*47*/
+                       "vI/lQ5QXbszuuKdVxpMc0qSLKx+jNJgr7uwlYFFpO8iUrnpCe+t2kW6ntzCeW7aM", /*48*/
+                       "idnt1go6o8H3tRNY2cWzGIuaNTsmvSSwUJupFiJ8wcgpdyNYHaH5cZBCKBh2fKY6", /*49*/
+                       "exwgCV5Gt5mB+qQcoJ/4miPRGnY+xi78FH2xhZWjqeKBTvkp5U05CKT6lJfmSJRH", /*4A*/
+                       "u8q9TBw9yiPkNxrONlQm48lMip72EL8bTVyPBAhnpgX+/luc3dxZ4v1uk/36ZZ5D", /*4B*/
+                       "nHGPl7ZzTaKOu7DMQ/NTP2p84J52cjy+3Vj1nFOey/pqmN4wTh25ZzqRmBbRE7kd", /*4C*/
+                       "xsPDDRROvZjoYzK/khUrFA5bCe1ZrL7Naokl9vBjB5A5TjIwD1UT4pUxgHpBpBOK", /*4D*/
+                       "c2BijO2YzSo4Ms/EtKaqHF3rd7YetNwEaFsQqERYi/hNGgYalZ4dmNuOh0yJcZS8", /*4E*/
+                       "vS1sXa3+WUlJMFCM4lm9ajSLr0xJxdIGPCmkBBNU5HAD9fLKFjQPUoXbEybZCT2y", /*4F*/
+                       "kRctwxWotSbGM7BbVeeZLE9RAgBqnc4Jl3mNKysohdTGFEpKL3lbnOe0C9wCnR2F", /*50*/
+                       "7GCwz8q2/mLqYcbVaX2XnVYV2AbY7wi/GFfqYKTu8SVllloftUZTonSijDXcmi/Z", /*51*/
+                       "pv/oY/w95iej/ZnO4sy5zQ2DdEl1W52XvpNmfUDImDK3QpujrV+dYuGEzXES01Qm", /*52*/
+                       "PFhu9tqkH6tmR9I2ore27rPG9f3NOAepTC2OZOWpyyijDf4MbL/l/YWE19djuACd", /*53*/
+                       "qhbqTgm/+3XyKdd8Ah+TSH8umwB5BjZdGuI9vUjR/N3h0JSwRPW/TSIsNZRiXA6c", /*54*/
+                       "0lOIlv8nOijyAw3qbAyWsDjbc6QHuisXu/TmltKHjGgPz2hdvOm3XLS/Rw4b16VX", /*55*/
+                       "L//kwaoIAd6ZK8bqq89G0wj2tZg/IC63vilLpYw9hYGAFqqfyNeupu3XOVwVOwnS", /*56*/
+                       "hEuX1JmsrgvatMmZpljyx8H1zEpeLGJvqr6Bl305q1jj/wHhZx+Bv/MOPByIwryv", /*57*/
+                       "PmyNUfsRsiZKeBAa1dq6ZGwYh6UGTr7mXM1DE8b1cdRd7arWDbuJg32hFIlnEoHI", /*58*/
+                       "fdKIu8MLLSvSelH/+tGnxa2Cn6BWkPOWTk3tbBqmOPtksvmmTo4wnbPG7EopzpeQ", /*59*/
+                       "orGQBpUryo/fItQDv/w+KatTY+ezJZGMcwGnoZIgQD129purTJerm25YjF3F/Khe", /*5A*/
+                       "jOzhwuiSjEBQQxu3FMn0SmkQ+83groZRZ3xlufrqhSOAypjI0+QI936QhJj4ucge", /*5B*/
+                       "eBgsaouV6EZHpngPQf1yIQSQKTrYnY6dJdBaJsMTCTnxy3cw4vEx0vPXgE5XPu7n", /*5C*/
+                       "skBe2KNnhVpzzz8TYfHsFtcNPLpvXNpS+0uz3oN55VZT0Wi33E8lgy24xjVf+RSa", /*5D*/
+                       "5kqd4cYpikkRuidg9Kr0LgWV84Sqfbq9TZTc9gQqC5RTDfwQVtN+TuFZfpDClN26", /*5E*/
+                       "gF9HP8QP3xQv+EsmjariF02Ti+XfW2KSgeqspBX0hIMrZNjFrl6cjodmghxf9Y5N", /*5F*/
+                       "2Shx98Q1I0qUuprSdhROVERQeCFjyE5lWkSAL7DZSrAg0MiAZBvgsL/Lo4heMm5Z", /*60*/
+                       "YtBIdBVVaYlobSMPTIywDaLE0Txb/Kg7W1NE4VN89QRAaOR7zE3Qt0ZGM5Ixmb5L", /*61*/
+                       "J84Cq+Y3eB2kPknUrlujPr76lN+1/crRTwwXYruAtZhDHEKpbHrFwzQWIMHCX9Zo", /*62*/
+                       "NnVxSLy66voVcy/26FFCRSPFzf2n6BizRBPJEyCDLnxSkGnRr12eTac3BYeMLiYS", /*63*/
+                       "ogKE7wtdPooJmQH6+sU7o/ViB9Cs6MtjeEGYgfGjJuq79kq70Xjrbl+EDjBxls9+", /*64*/
+                       "/ND1zHy2EQhrvZY0P6uMny1cNfEkfctXgN5bFpSFIVj4eDplijbz+mJ3JnYB2EzA", /*65*/
+                       "sCOqWud8QeZhF6bL47+nNO22yfiW4xOMY+0JS0ZmkFyD4lwsZGrLdsZJtD4qCI5J", /*66*/
+                       "oFp7NabeKm9pe1UVKzjaVK56I0YZ2Csw3P4eEYK7DI/T8iDOrS3dRdjRoujppXeK", /*67*/
+                       "KCqGNScz7OFEfJx+Gou2kuNj6ZncGFb0cxrdAkWYrHwNhHDNmAVlyP1ObaKEpV2a", /*68*/
+                       "XMFABwGbsRaaQxYQwEpUtKWZL56cdB8iD1dlmieKPqatctCtaRYjxwHIC3S6NbzF", /*69*/
+                       "lIY3T1rnRGxHdleKEM560tYVfvr6h8QX357iyNVUNmr6H2HM7V7jDJNQCcADjIrY", /*6A*/
+                       "LB9LvEhpEM8Sl7mQmdzAkTKrCeHjITsZZhbdCAbeQDMoKGC/d7ZbinG3lxELQSxA", /*6B*/
+                       "PlSlnPQPCOsnytZClUK5tAUyU8Fd1JlZPu8bijme6vfG3nZUdxeIvgBByJB3TQYX", /*6C*/
+                       "1vinUJGOMvP4/awEG+bjUhWwzvMQINhR2NV2ZjNz1llCw5Ed77yzTEm+M4C1mlgM", /*6D*/
+                       "VTjg3A7nuFRX/YeW6ZC1e90fK41oCP9sT5n+iwZtD/1ErokkMM6b6+TjYQYgH7Jm", /*6E*/
+                       "rWmWGGAAXi/kygA80PE6R7Tz0WiSKXgC0sl+OrwUh4jZ0utx8Mf5nxDb/13CXVqH", /*6F*/
+                       "2JmDRj56qeKhDcgyyur3Ox0jwraOrNwTl+4CEQ7JfiI0FDjwMkg0suuQsQODiBOG", /*70*/
+                       "/r8m4Gw7PTpZ7WiaO5XUGKB3t0pXe7sksdyDSdZ9y+CXrGmYQ4x2zzNgDpB6vGKA", /*71*/
+                       "xzN6irfD1DnrtLAq8i7XQ5QDpd2Ega5UNoXDg6B9Kgwi2Eodkm+8nUKqLhj+Ybss", /*72*/
+                       "TdILbICazth8ckVYpmWd9kiw8nbMgf/DWM5nysP9sXaK58v7CpfQzvP1JrdBKVBX", /*73*/
+                       "+fzOf8GuBuCRNQCeYqHKBRJTWJ/JDAW3kJQVHkBgkmZazFenWtJChAx3OEDNVYYi", /*74*/
+                       "ofPx02eN7pP01/jbSG2kvjxFRoYr8JE8WIoYBB98PWyE75z4h3Kp70v/ixBONkDL", /*75*/
+                       "JfhPDXPj3MaQJ5d9+FSvAo94T28P0ml9j24WTMZVwpCiyflLv59So2tPaTYRxM4+", /*76*/
+                       "P3vKxl4K4T2qrIXQgWAZfvdgXXDjDV/fdXDF3IN8PjmXj7ncwjvzpcAEEg0Ff+sK", /*77*/
+                       "BbyoET07O2/cuJUrq2kitRNfOLFO4u0S4bU2WGu6KyBJzFqSxTY27r8Jte72TCJC", /*78*/
+                       "kpq+xLvDDF8u3VTM/BNDWDZAOQAP6R/BI5f8cnxmcTOfjaxiC5kRlq1/MTzrufxM", /*79*/
+                       "uj9KiQpSjspAzJgAuNGevXx1898HRfK97DWN5nLFrkfkc7MnPVLU86sFOpcWHrEa", /*7A*/
+                       "fYFrwqaTwv8o2FlJE52eLL+bGQhkIaV/YdjMDd4C8KZd8yx/xZ2Pvkd2pIbf4lIT", /*7B*/
+                       "dI5wAeFbtYQ+nyAhN8XeOr2t32gemo+xLc90l4FQoAlihwo4XSmr5J8jnGgMW2Cj", /*7C*/
+                       "j/7fvx8Dx90KL4Nb5l0XC4WWcWW8KhYxsTa8S1NeIVFErgFdO30vnxu2g25CokPP", /*7D*/
+                       "SvAWK2fbMn6It2oO3kVvzkEL57hIhXElxPqgOc+LNtdHDIhJ7GNolXQWNJZXMw5y", /*7E*/
+                       "xtbZM456cAbGdtVs4r+EtmzEX81efvREt0TYVqgjG69+ZcVqkSemmBl+EqFkOQwE", /*7F*/
+                       "m6PANDHs2qUf21q9YEGgDMsanvKpxQ61r7/3ahKhL76zpMXJxAr8vinrsR/HOUeZ", /*80*/
+                       "Y6eDPjQt7G8M9VdXcaXbW7MRauQuKPbWJFUqkvUBtajKBbYGEKKCp4Fcl5bo0guh", /*81*/
+                       "7dAmIlPgqri3hA5HwDEYiSj/6EjWJMh06wY5rS7g5LUTp2Daagi7WvEpnmpmVwyo", /*82*/
+                       "CiPnsVI+nlImjvDJYYgUDD2ArRsTivwMn6ovkCTzCYxImJmHSe4xAldUKy5JiAY7", /*83*/
+                       "zRRoA8Xqpu/1XaqNHzx3AjHeAge97U4O70DX0FfXf7qLXwB0DF+AqPgePv97RkgU", /*84*/
+                       "DcdqAWa3ByrpGUI2NVwhZPH2/DX+fm/NZ5LChGDAXPBEpHkl8/I7q8m5JZot9HWs", /*85*/
+                       "ZITb7bUUOu/p0C0tgOAUIyp2KPmprt4UAlrhgLTrY1fm9c3oFMr3JbzmYdwQRVmO", /*86*/
+                       "CwAh/dw4LOanPe4X6Sqze1a2yUziFZ/k2GGj3FmC4lZIXyipCIA7tBvmSn6vtMYN", /*87*/
+                       "rtxCESRkPHA6BkUsNDMtc8tnRWKhfoc3FNFNYTTVcSjR9ZQdKglI57ccbQxvBSRF", /*88*/
+                       "+V1ZOoKxJeN8OW/J1Q0tdFH0qUCVHDZEuR8z9psvOAJnBBrpu6/LjqgE+RE4v45S", /*89*/
+                       "DfsxRlPGK/1smuv+NvClJ3UHHZHXdvjQcgtunKKz7xKhHYdePcpL3G/0CObmto8C", /*8A*/
+                       "SnsKk8jsF+89J/tyRrOXnY9dojVfg67GWx/CMJVGJ2yV51Bhoha8LxrHteCqk60C", /*8B*/
+                       "Vt0Hz0O+JG0vKo2jYh1oY6BKchG0yXKYCmkZfIW0grj0xgQojbqxh0kL9DbMmbHX", /*8C*/
+                       "D579c4WN++4KVpGbGQM0k4wk1WUWtA3/lkGY6gXhLjKb2JA4+OCM24AfkDyY+DI6", /*8D*/
+                       "rFshP/naLAisTye5oRjBZ4oZk/scUHSv0xLooKtcUlNuiv5eADqvyf6ypw223ELy", /*8E*/
+                       "3xRzu79/iNNCwyD38Mzc3RXEyDMcM8SyW3j0ZwcBZhaH5F39wbdVhPJ1GBjqxSGo", /*8F*/
+                       "8GKFQTGYKH7DhbFCMC7RKpaupjXX0CB8Qb0s4pjvi6ZDMtn4Ih1BoTgvPU9A+xPY", /*90*/
+                       "lEJmb6fAP+HL3f332ckhfvix1mazaB4WdDh0tX6Vv1Vm12SD7xMystRDZvmKuZtS", /*91*/
+                       "M1zbqt16bQMuAy2AX4MlBfK+otfY0Pd9t5Z2skR2koS5tfnR5CFeIf23DsRpNnR3", /*92*/
+                       "hHeJ6EtTs6mQUBpUg0L9W3iXHBLN/K+Xx4l5Y8nERsHHWdrLL+cgCE9PrqD04iZV", /*93*/
+                       "wr1y/SCec6SmTKXBpeVubVxOiMtveqlwSJyXnjMIYSunI7vWMDemk+VeBACrzh1b", /*94*/
+                       "24uM+OQUfELCmwOOhjCGHRstUFGiQNszPStdtMzJQ+AtewfutmcrKSp0TOK9Lzoc", /*95*/
+                       "atgWcPNp7T3D12asE3uUmpyzTN9Fhi2C2hCe8ZgPoivExCpCjRMDZx1KoI8T1jSN", /*96*/
+                       "LBF9JYuc5SjPn0nFjAZHhxoZ+YC3bsHWCK/3MxYVFrTDoaFrDeAwotKDW5a5bwb9", /*97*/
+                       "N/yPfxu89HDcD2vlMQPcOL0LK62QcqupxoMHPTyXB7MfEcrN9lXEvdzwuBeD4PAj", /*98*/
+                       "D8WFkk7C7grOGrYzeKTNOyMH7ln5hpmDuV5/jUoDWcm1T1ywBX6t1MQOep/Tozds", /*99*/
+                       "By2/DyO3JwJH7StjrdLXKNDvElCLj70HQjRA4DrUoEihSRR/IDmJmxny/bkBrR41", /*9A*/
+                       "Je8cMS6dEad5BO3E0CxTHgsK09h4+HIiQkyc7SxBnHb13ctl+vsvJo426iFn2HPb", /*9B*/
+                       "sty6Pwvp20tX6m+NOuwkEwANhTDl+55t9Mik+K+IGkAcJy6Ka7dcZUNv4b1tW1A1", /*9C*/
+                       "N3D1I37lFW4m+sFic3NiSQu4KRgtN2LJEWJN6jJo/qFjd275B+MmZ1tQdxYIYccE", /*9D*/
+                       "ZMFvijr/4kJosiidvLKF+yg6UyTwz1nFzrPaETk/yC4nanOdSscPrs9Mq4sE3Zzb", /*9E*/
+                       "ZecgHSJSnNcE5zyQc92eSUmD9H2YbQGbwcUv0Uq0+vz5/QC485MSgb7OU8oZxh1R", /*9F*/
+                       "3+0muHjuWaBayBdNKa9zRrWC8k1OfVJe41z5kyaaW9uW8lT7BNNRZcwvkWUNtz6r", /*A0*/
+                       "NYHHtmdPDH03TTDep64MOf6U1Mirn+FJFkWgN2Qbnhpa82qrvcRsiP4C9URzISkF", /*A1*/
+                       "7iy1QUHz7Tw/V1NHkrozgVoCZrwivjLLszxA3oMBSAwxz98ntIRbv1YhI7CNQlFy", /*A2*/
+                       "yyWOxTHo/IZ1/MtF/j/EXL6Z8ULAfIczHC7CDH/6EhIjmB99S6uORJ5Zp586NrGn", /*A3*/
+                       "bRDloO0vjC0/67s4aDYuGa+gzgqmaiI2apLzwV0o4efs2YMY+nEDkGbrYPMaO8O6", /*A4*/
+                       "4+C9EhahotS4TMsUpg2rgsb0AaxQTZoYR6b22aFdauO2EWux1iAx5HhT5zZCXzl9", /*A5*/
+                       "f4fzR81VwcBxyjTD5b8DS/dPhEsfD3F3xY0Ocqu7QzQGNIbFaIg/8FDrcsgRBdYP", /*A6*/
+                       "BmMotao9JYyslmFK9Tikml4soiPHCB0YoRA5jshJPGOwdSaZZ0r1yXbZOL2smN0f", /*A7*/
+                       "96l1ddqTCKEYoLJaAkpfj8D/azPwOAXYb2KJONNRlw8akb8luT44MGDMGc5onxTm", /*A8*/
+                       "mAW+xrodCLmSFMdpvNldeCsXbqUMWgOLiEhyADV4RolpBWVYyVcer2Ei8k+UTt7h", /*A9*/
+                       "0sAYJ03cXurkilqhTV0cyxUwFviCIyfGzlR7BeU0qZQN0Wg9GkiOZaBGCuUpSfLo", /*AA*/
+                       "zYL0GihG8X0Ge0Am52hLAbzdcIyTZOVsotqlct7S2jaAKQuc9jtXbSkDqrQUq01o", /*AB*/
+                       "X4tzTgbcaZz1NhxavRbMgxIbFG5eNpup6Mz60Fr6SCdJnNlHoHPQJgwMW1CCsQWw", /*AC*/
+                       "HP3QDqKithUlWtabcq8zkxssvZMyM8wi4YtesUnZJNcXcbkSBdvQaTxl1w2YqKyF", /*AD*/
+                       "8rN71ynGDiOyfCkdmVsRQ2/HUyx5Vfmip1vi6yhnp0gARDgFpGLmfGad9Gt+a8Dd", /*AE*/
+                       "C0FEdr253SAGjC76sZFjBQB8Fs9R3k7KcPg2BVUrYEb0H8KXJWdAUEuE+4pu7PgK", /*AF*/
+                       "g7hRknTFIwAAfmvWhk9aM4/O+j7tPTWu3jV71iYFyD9TvIDa+3iQDRRM/vPfAHlG", /*B0*/
+                       "E4FEar6ynA8pWJpqG1SN4w78VPPaUzln6WmFfyeKgTw7KhLbd+oWjYTqthgDhgrk", /*B1*/
+                       "UF59LfQRzniNmZwZ/233hMs16TqOV5uZEjLmGywJ/dnYFtOsYzzzMQxc1rgwgKBa", /*B2*/
+                       "6U+onOHbmAA3IRTRF2ZC4hvieGoWxMNj5LADPjVFsXTECOXqJAg89CpgKCVi5sFY", /*B3*/
+                       "b2pC0ebrJ55Co19rCmBqKnADqWsw4veP3d0+aBrZg9+IUyLwQiRXKQoyN2QbD8zp", /*B4*/
+                       "TgaW6IDzTQWkiK2jShq4+m8VymxIJnT4YClHN4I8G7sKlj/3fLjAfgh4D0fm11dc", /*B5*/
+                       "GkphrAPhWFffWBP4hu5qdmo5dNxRuj8gH3LFafk9yXiXZRkw4jKe5lu5is3Oxofi", /*B6*/
+                       "l8wNDMGnBipfdKZoginVmbNYSHe7GNjyhthkTw2CKtWBOSZ6+I6AL3bGR2NuIJG7", /*B7*/
+                       "RsfgHNfGRwgRHnxEG0X9hsxvheKwIwbCHhiYAy363TpGazNroKA2Z30lsbLuCsfR", /*B8*/
+                       "dpcaFA0mM1bbo2xZX4Aw1UbON5T2PuOMiHB0fulULfbqRZtIGJNc38pQqAuf0qqk", /*B9*/
+                       "n21/dhZ7vb3dtrfxJ4SW9+52UrOZZcdYkdetbH9Mbyh7EUIXQMCIgWPRZkKW8cTO", /*BA*/
+                       "JFsTtabo5Jd3eSnlhdeLirvFW5egwUVFfeNZn73j+hMr3pEOfGLVr6nhdIR3rCOi", /*BB*/
+                       "O2ts+OrxG97+NQDVrKNGos0hatmdF4BvAw0wF8u3jT9sUJRdi3l6SUHoGvbG3FKt", /*BC*/
+                       "C0QfjtDhpPTgImTVPGMnXiAUtB1PwWUUwjeNmEOQk5pos10k+lzmy1Wo3SjerkBj", /*BD*/
+                       "VCSJP1q2eh+htb5+FrQK140CwiToMSabvBkV49572dWMBeRJdMct6v+6L20tTyDr", /*BE*/
+                       "XWaicZHmN2UjP1pDNfjSP4psLWI+3dWt+EPi5dXNIsWiqP3b8yfsWkUUDlftZXpH", /*BF*/
+                       "Y50u0wHLpztrQbXnNFcznvY5RfmEatkODaf1beTizkUc7K/p4S4U3t1y3E8cEtZ4", /*C0*/
+                       "dws5U/YKs3u2e49/K085LYk0rxPCo3cChNBW3XTm9n1RJMRzMM1DVhjcodGLX7H6", /*C1*/
+                       "iw0V9atTtEKM4YgRnBA/kfk7tB9jt3vCGYQQ74Xm3evqM23Fh3zWdoTwQK/Ac+yV", /*C2*/
+                       "+wv1oVk95LwARtgEyidwuktkvqKY22/7Su09mX533tU6D3HfHp+j/EGIjYU8ieWl", /*C3*/
+                       "/Kyu5nbHisbrBmGGx2eAU+P9Ti81SnvSeOMBv7OifYRYbZI2weN5PBAWqiaHvFf5", /*C4*/
+                       "EsbHA0IsSZX8IYPusQ3WDUIr9gKp69nh8qQ3Dn2/LepI2vWLCbkf4TijjoE/If7b", /*C5*/
+                       "3VZHbTEhyxdqFECBSVKJuIhChID1EoFkNY/V98OtR0l3U2riKM4cZZv4N/PaAzgL", /*C6*/
+                       "47bm3OIWq77fcpHjyOw5jw6c8j9VyXxgpwtPTxUV/UvkjEC9tjBi7plOFg0RVLY1", /*C7*/
+                       "1BzB0hv/3a2gGm66LCYaKkZaRwkdKfILMt70raugk0xjPjMnE47ucyg70fUxIK7z", /*C8*/
+                       "XKXZsqt8bCT24B4sKMfpUNfToGWVoL0v66QEnGdSZRmC3aYp2mZ8E79W2ktra6cI", /*C9*/
+                       "EIbi45vFo3xI4nofz3XdajVkenNQdHQBO5K0spwl8qEQcs6OXvXI4Ju2UPOYQ5bX", /*CA*/
+                       "AVGC0U6GReDFoeGTkZZUrMeUB02TWtgjE0JKc8uI+rT51aO91r9cfCWIdDjpf2Bm", /*CB*/
+                       "gdSAodJv87r3mJUbrEDE6mywt/+ATaKaY/FYc1EfYHk7totBMRgH0QM6fa6mCZaB", /*CC*/
+                       "UeW6zdhSkT4W0D0gP3mthpGo1Ip36zq+GGZr100lECgnwzZm481dm4zFi4ZlrYoK", /*CD*/
+                       "KhWTDXhyBm2RgIJ7JAXn7j9GN/F2ub2ev8HQonM+3qfHagSgC6Bx+IY08gOolkxI", /*CE*/
+                       "+78Gu9q8xw+zCWM9+z9c92KREAPRBaPsYf9PIDtQPzeiP5ZUnywzzrTNQiKlIESa", /*CF*/
+                       "wZjReRFIHcdpJenORShaULVVZ932vznzRZLojSvV6osryg2SZW5oSzeK5j6kP1mZ", /*D0*/
+                       "ARXmF9doCtmmYZGhriC5m+SxDtmWbz0vfT1RELrsFd8xGPC0OdXl5jbO/ih1etHH", /*D1*/
+                       "r/vrtL7wT6DKo9o9Wwrp5UWh9AkiVFOEB6e1K9f/poBqvxpacMTgFH1nisEf7JnW", /*D2*/
+                       "dRUY4yShIXBflK0XKK563FpWDX8eUrWL7gUIL3nTcWYaOkGUo46I08z5W7VHfk3O", /*D3*/
+                       "aN6qPCZA9CJ7rC53h7J75+lAKpZ1N0kpG7mMpn+iBh7Hub0qkwLv3TNSF9yIO/B5", /*D4*/
+                       "kSM+tRfV9mU5HAvwomXbl1VIqoWbrncdcQebPps7ExnUs30a8dl2Y4Rh4Vov0JqU", /*D5*/
+                       "O5Kd4M00RP5ScDtx/fywAzhyptSQMnEtlu4p9m+UVisoxLOyAV2hYKAzOXmvXh0L", /*D6*/
+                       "S0kNDvv8QLze0bPHSEYco43sB5ohPBHxHL3CpbG+eCOUoXCAR8MMGSlj9czhttpj", /*D7*/
+                       "kb+6gp5rG5ABENZFTCMqh2xtzMGVaqRslSLw4BWTdyKs5ms0lpOlYEaISMsDpWf7", /*D8*/
+                       "C2aXTPdA1FAM/u1kv8oe5yLOGFeJGyCABtM1TYCJXaCG0LCiAgRwj8DfpEwzy28y", /*D9*/
+                       "1c0FoC7Q+7wVMVV1Rloi8GKvp5I2i+EICu2MDIJK0wXqgD7DzteoUZyHrj9QB8AK", /*DA*/
+                       "GlI8yLXvPvSsQYjEX7Dp5fm1hb84LMV5qfc7rhgIzSZ0X4/KMlw4T1JHlXsQInvx", /*DB*/
+                       "sKSYkZb8SBocTgy7QImn2ZF2DuabHXhCMIoPaPPK0Ycpr2pgk/Gf0JOHBGC82hhF", /*DC*/
+                       "NKBWShNIXfC5adyR616miWI85mA59MePkl5B+Z9rHPo1eTRWTp0hfoXvCt7WSGor", /*DD*/
+                       "/V8ES8X5fxqyaJQuVqmgRJK/Hi2iJRTxDo7SCxIzjSBi4YCvl0HX8pNs5t9zyu3O", /*DE*/
+                       "pMkpnUOQcdWdr14r3AfARNzOgKdI323vsSRgqeQFsmFd/sOEzraFGCHO4raGabW4", /*DF*/
+                       "mX4jNPqsbfPQ/rxTUutFvsAasrhGaSxAZ83p5/ymYCT8KSYWW22a+B6C23Sjzmz2", /*E0*/
+                       "HRrD3HRg4BbDOPrDegFy8WDthLdLzsG7ceYq6Lyoidq7wCaN+8/aptb2CZaugVEY", /*E1*/
+                       "YXbRlN3bEPGT82m6TLuf9QBePD/7YDtGrHiO/pa4YBy2Wt6VZ+KzXhliTWXUKHOZ", /*E2*/
+                       "YUviqxiRBiFq/M6PxLgcgQL5VvssAztIV8CMGUjoMvtwT6BiVIEgpuJZSYnROACQ", /*E3*/
+                       "0Oz/m3gJ1VqgnPYlg17N3YKMm80aj00VrzzOlF73fay+VIez0VRlbeeGhHOvZNu1", /*E4*/
+                       "v0OarKEIozWS5OazWoBHJo9YYW9hSrdLTvXbW+4CRvrbdHEKR2LdP6z6CKg8Q5VX", /*E5*/
+                       "BaZMd7iUoFEl8u50TJcHX1Opga33/ioC1m8zukvEZwk9uuyKkSejigo/PFc2hAv3", /*E6*/
+                       "w2YHQoNPN8988D6hARnzcQ/c+d7HVq1jMaL1Wei1W55MPom5O0W/0GCXccJmS+Gh", /*E7*/
+                       "SD79c8xhGLThS7A4oXkdRheo+zd90xBApCUyaaoiln2aeSaBS0UEIrZuzdyH1KUz", /*E8*/
+                       "IDMFejHQkdJ2Hw3l8Xh24sefFWM6Zj2aUrS6Zz9Ne60czjMrXsCcJsO8NNccJrgP", /*E9*/
+                       "7iVKPW1U0PPyt8korXQotCgtlimLeOxzU4UrE0g650pmC5Gg15lsdVxVLXHC4qfs", /*EA*/
+                       "3R+RJL+ln1VLVXA33vXdoUa5ZpMT/cPHpCsdiAzMfm6HS+Unam3nFHi4+sT71VJz", /*EB*/
+                       "CqyN7StimvEuWvx+XY5UNbJX8LR0ScjKrjUDPdB+Mas4F8XyOMEPcRY0QFpJzJCc", /*EC*/
+                       "YQTxNrnep5+dL0ZYC5tSoWXsucgRkRCf6jNORCjroyM3iRF1yoRAVcLqRsmnWJ1Z", /*ED*/
+                       "TqxWeLuqw26vzMvBB2kOmPXLAMetV4Uf9NlIr+Acy32Kq5mB39qzfxLz2/q4bbPm", /*EE*/
+                       "YBYQej8ND8CXxrYtsZRbYDhftqJ7T5R5vOJH3d6KhUArsJ8O20sEHjmVEKMBnceG", /*EF*/
+                       "KkiYWz2JMZcmA3n5Z+KN+11QOhQH9ICH46jTzPyuHKT+p7fXs/BCoKyhGbv+UTE+", /*F0*/
+                       "UGk6AHn27ecSq8ao1Jf8uppVeZy0lsATGVBLQwElBcMJ+63nI/uAEsAvvTFdkFkZ", /*F1*/
+                       "W8b8/EYMXFcZtDQ/h15i/qO4UX/M/ZYWwOdaDvNWnMcVrX/SHEbjFFkoR8u5zHsb", /*F2*/
+                       "Fo/M5Vj+Bji/wTRn104k+FbbXQ8OlAROe4sVxN2v0FvJxRGZlLrGpCaXrlXBKm7/", /*F3*/
+                       "REERuETIx0kAyzXKG+RQtHz5vmfsUCQwiw0e20kgZqj6uI5SIsBp2veiwYVl8btq", /*F4*/
+                       "TgR/9g1CuzezB+/i8+nA3EF4dxiGCBBNrtoFkzflkgSPEuQ3HHmkPRfqpMtFhGiA", /*F5*/
+                       "nY3P5HyKOVGlnKaR2PylSaUtOcIOpnI9OVWrebiWgg7eC9wurwDLa5A+S+VIOLm+", /*F6*/
+                       "GS6SGCrF13r1uPXEVywpKQvBd6WYH8/wzWC2OymfKwf7tnVVT2C4Cdv8uYFqOcve", /*F7*/
+                       "3iDCtK3XSiUNB6CVD+JibNibMDnzieutnyiLF8yF9qKlle5dW5BDk4Z8l6I0D8Pg", /*F8*/
+                       "qr/P9xrVnGYdJ4Bob4Dg45C/mOBZwjRpSXLK+/Dq/l22GEGLlEv3icMHaPvqCmRT", /*F9*/
+                       "IOFLwNysO91RjhlkvUlJbXSKWWaWs/0xgVrBwOltvLt5YsBhHCB/8t1cTujjrzgn", /*FA*/
+                       "3hFkWtMf180/Uoc+eRLAPPM2yg9y+M+wEvAAc+Bf6JMLCT8mhaCU6OyQ+toBCvYt", /*FB*/
+                       "3fq07rENpZ2aeXSZnOQk5bnLJGry/wnezees8+lxna+d7GYlprFi61M1fSGxKtAG", /*FC*/
+                       "IjXgGjnmMd0V6TVbBtGskxiS5wPMVuv08ZcMhVyBFwdvClTAimpPv/B/UOldrvj8", /*FD*/
+                       "B7JQ3BO0RavV2FGVNhe0QBByjhBqKDLKr5PQ2FReIgPpdqUeWaVsS2LgxE13qxJO", /*FE*/
+                       "bLls31D49NldM2cWG9i6iuVynOfPeUDLlmkxPnYvVOXEl9O5eUs+MBFRlIsDM2nk", /*FF*/
+                       "AiUNO8VcsXVYQ1Kga8ob2n5rwFZ1l9qeJRMKz35yV2z4w+V4Wj1h3FqUtKOULQbO"  /*00*/
+               );
+               
+               static final List<List<Byte>> MIX = createTable(Byte.class,
+                       "BQMEAQIA", /*00*/
+                       "AgUABAMB", /*01*/
+                       "BAMBAgUA", /*02*/
+                       "AwUEAAIB", /*03*/
+                       "AgMFAQAE", /*04*/
+                       "BAADBQIB", /*05*/
+                       "AwIFAQAE", /*06*/
+                       "BAUDAgEA", /*07*/
+                       "AwQBBQAC", /*08*/
+                       "AQIEAAUD", /*09*/
+                       "BQQDAQAC", /*0A*/
+                       "BAIBBQMA", /*0B*/
+                       "BQMEAQAC", /*0C*/
+                       "BAABBQID", /*0D*/
+                       "AgUDBAAB", /*0E*/
+                       "BQIBAAME", /*0F*/
+                       "BAUDAQAC", /*10*/
+                       "AQAEAgUD", /*11*/
+                       "AgUBBAMA", /*12*/
+                       "BAIAAQUD", /*13*/
+                       "AQMFAgAE", /*14*/
+                       "BAABBQMC", /*15*/
+                       "AQUEAgAD", /*16*/
+                       "AwQFAAEC", /*17*/
+                       "AQIABQME", /*18*/
+                       "BAUDAgAB", /*19*/
+                       "BQMABAEC", /*1A*/
+                       "AgUEAQAD", /*1B*/
+                       "BQADBAIB", /*1C*/
+                       "BAMAAQUC", /*1D*/
+                       "AQIEBQMA", /*1E*/
+                       "BAADAgUB", /*1F*/
+                       "AgMABQEE", /*20*/
+                       "AwQBAAUC", /*21*/
+                       "BQADAQIE", /*22*/
+                       "BAMAAgUB", /*23*/
+                       "BQIDAQAE", /*24*/
+                       "AgQFAAED", /*25*/
+                       "BAMABQIB", /*26*/
+                       "BQIBBAAD", /*27*/
+                       "AwUEAQIA", /*28*/
+                       "AgMFAAEE", /*29*/
+                       "BAUAAQID", /*2A*/
+                       "BQMBAgAE", /*2B*/
+                       "AgUABAED", /*2C*/
+                       "BQIEAQMA", /*2D*/
+                       "BAUDAAEC", /*2E*/
+                       "BQABAgME", /*2F*/
+                       "AwUEAQAC", /*30*/
+                       "AQAFAgME", /*31*/
+                       "BQQDAAEC", /*32*/
+                       "AwAEBQIB", /*33*/
+                       "BQIABAED", /*34*/
+                       "AQQFAAMC", /*35*/
+                       "AwABBQIE", /*36*/
+                       "AQUEAAMC", /*37*/
+                       "AwIBBQAE", /*38*/
+                       "AgAFBAED", /*39*/
+                       "BAIDAQUA", /*3A*/
+                       "AwUBBAAC", /*3B*/
+                       "BQAEAgED", /*3C*/
+                       "BAMFAAIB", /*3D*/
+                       "BQIBBAMA", /*3E*/
+                       "AQUDAgAE", /*3F*/
+                       "BQABBAMC", /*40*/
+                       "AgUDAQAE", /*41*/
+                       "AwQFAgEA", /*42*/
+                       "AQUEAAID", /*43*/
+                       "AgQBBQMA", /*44*/
+                       "BAAFAQID", /*45*/
+                       "AwUAAgEE", /*46*/
+                       "BQAEAQID", /*47*/
+                       "AwIABQEE", /*48*/
+                       "AgMBBAUA", /*49*/
+                       "AQQDBQAC", /*4A*/
+                       "AwUAAQIE", /*4B*/
+                       "AgADBAUB", /*4C*/
+                       "BQQBAgAD", /*4D*/
+                       "AwAFAQIE", /*4E*/
+                       "AQMEAgUA", /*4F*/
+                       "AwQFAAIB", /*50*/
+                       "BAIABQED", /*51*/
+                       "AQUDBAAC", /*52*/
+                       "AwIAAQUE", /*53*/
+                       "BAMFAAEC", /*54*/
+                       "BQIDBAAB", /*55*/
+                       "AwAFAgEE", /*56*/
+                       "AQMEAAUC", /*57*/
+                       "AgQDBQEA", /*58*/
+                       "BQMABAIB", /*59*/
+                       "BAIDBQEA", /*5A*/
+                       "BQQAAQMC", /*5B*/
+                       "AwUBAAIE", /*5C*/
+                       "BAMFAgAB", /*5D*/
+                       "AwABBAUC", /*5E*/
+                       "BQMEAgEA", /*5F*/
+                       "BAUBAAID", /*60*/
+                       "AQMAAgUE", /*61*/
+                       "AgUEAQMA", /*62*/
+                       "BQQDAgAB", /*63*/
+                       "AQAEBQMC", /*64*/
+                       "AgQFAQAD", /*65*/
+                       "AwIBBAUA", /*66*/
+                       "AgUAAQME", /*67*/
+                       "AwIFBAAB", /*68*/
+                       "AQUDAAIE", /*69*/
+                       "AgAEAQUD", /*6A*/
+                       "AQIDBQAE", /*6B*/
+                       "BAUAAgED", /*6C*/
+                       "AgQFAQMA", /*6D*/
+                       "BAMBBQAC", /*6E*/
+                       "BQIABAMB", /*6F*/
+                       "AgMEBQEA", /*70*/
+                       "BAADAQUC", /*71*/
+                       "AQMFAAIE", /*72*/
+                       "AgAEBQMB", /*73*/
+                       "BAMFAgEA", /*74*/
+                       "AQQDAAUC", /*75*/
+                       "BQABBAID", /*76*/
+                       "AgMEBQAB", /*77*/
+                       "BQQDAgEA", /*78*/
+                       "BAMFAQAC", /*79*/
+                       "BQQAAgMB", /*7A*/
+                       "AQAEBQID", /*7B*/
+                       "AgUDAAEE", /*7C*/
+                       "AQQAAgUD", /*7D*/
+                       "BQIDBAEA", /*7E*/
+                       "BAUAAQMC", /*7F*/
+                       "AQIDBAUA", /*80*/
+                       "BQAEAgMB", /*81*/
+                       "AQIDAAUE", /*82*/
+                       "BAAFAQMC", /*83*/
+                       "AgQDBQAB", /*84*/
+                       "BQIAAQME", /*85*/
+                       "AgMFBAEA", /*86*/
+                       "BAUAAgMB", /*87*/
+                       "AgQDAQUA", /*88*/
+                       "AwIFAAEE", /*89*/
+                       "AQUABAMC", /*8A*/
+                       "BAMBBQIA", /*8B*/
+                       "AwUEAgAB", /*8C*/
+                       "AgQAAQUD", /*8D*/
+                       "AwUEAAEC", /*8E*/
+                       "AQQFAgAD", /*8F*/
+                       "BAUBAAMC", /*90*/
+                       "AgAEBQED", /*91*/
+                       "BAMFAQIA", /*92*/
+                       "AgABBAUD", /*93*/
+                       "AwQFAgAB", /*94*/
+                       "AgUDBAEA", /*95*/
+                       "BQMEAgAB", /*96*/
+                       "AgUBAAME", /*97*/
+                       "BAMABQEC", /*98*/
+                       "AQAFBAID", /*99*/
+                       "AwQBAgUA", /*9A*/
+                       "BQADBAEC", /*9B*/
+                       "AwUBAgAE", /*9C*/
+                       "BAIABQMB", /*9D*/
+                       "AwAFBAEC", /*9E*/
+                       "BAUBAgMA", /*9F*/
+                       "AgADBQEE", /*A0*/
+                       "AQMABAUC", /*A1*/
+                       "AgAFAQME", /*A2*/
+                       "BAIBAAUD", /*A3*/
+                       "BQMAAgEE", /*A4*/
+                       "AgQFAAMB", /*A5*/
+                       "AQADBAUC", /*A6*/
+                       "BQMBAAIE", /*A7*/
+                       "AQUEAgMA", /*A8*/
+                       "AgMAAQUE", /*A9*/
+                       "BAIBBQAD", /*AA*/
+                       "AwAFBAIB", /*AB*/
+                       "BQQBAAMC", /*AC*/
+                       "AgMFBAAB", /*AD*/
+                       "AwIEBQEA", /*AE*/
+                       "AgAFBAMB", /*AF*/
+                       "BQIDAAEE", /*B0*/
+                       "AwQFAQAC", /*B1*/
+                       "AgABBQME", /*B2*/
+                       "AwUEAgEA", /*B3*/
+                       "AQADBQIE", /*B4*/
+                       "AgUEAAED", /*B5*/
+                       "BQQBAgMA", /*B6*/
+                       "BAIFAAED", /*B7*/
+                       "AwUBBAIA", /*B8*/
+                       "BQAEAQMC", /*B9*/
+                       "BAIDBQAB", /*BA*/
+                       "AgMBAAUE", /*BB*/
+                       "AQUDBAIA", /*BC*/
+                       "AgQBBQAD", /*BD*/
+                       "AwIEAQUA", /*BE*/
+                       "BQQBAAID", /*BF*/
+                       "AgADAQUE", /*C0*/
+                       "BQQAAgED", /*C1*/
+                       "BAIFAAMB", /*C2*/
+                       "BQMAAQIE", /*C3*/
+                       "AgUBBAAD", /*C4*/
+                       "BAAFAgMB", /*C5*/
+                       "AwQBBQIA", /*C6*/
+                       "BAAFAgED", /*C7*/
+                       "AwIEAAUB", /*C8*/
+                       "AQQFAgMA", /*C9*/
+                       "AwAEBQEC", /*CA*/
+                       "BQMBBAIA", /*CB*/
+                       "AwQAAQUC", /*CC*/
+                       "AQMEBQIA", /*CD*/
+                       "BQADAgEE", /*CE*/
+                       "AQIEBQAD", /*CF*/
+                       "AgMABAUB", /*D0*/
+                       "BQIEAAED", /*D1*/
+                       "AgMBBQAE", /*D2*/
+                       "AQUABAID", /*D3*/
+                       "AgQDAAUB", /*D4*/
+                       "AQMABQIE", /*D5*/
+                       "AwAEAgUB", /*D6*/
+                       "AQMFBAAC", /*D7*/
+                       "BAUDAQIA", /*D8*/
+                       "AgMEAAUB", /*D9*/
+                       "AwIFBAEA", /*DA*/
+                       "BAMBAAUC", /*DB*/
+                       "AQIFBAMA", /*DC*/
+                       "AwQAAgUB", /*DD*/
+                       "AQMFBAIA", /*DE*/
+                       "AgQBAAUD", /*DF*/
+                       "AwUABAEC", /*E0*/
+                       "BQMEAAIB", /*E1*/
+                       "AwQABQEC", /*E2*/
+                       "BAUBAgAD", /*E3*/
+                       "AwQABQIB", /*E4*/
+                       "AQAFBAMC", /*E5*/
+                       "AwIEBQAB", /*E6*/
+                       "AQQFAAID", /*E7*/
+                       "BAADBQEC", /*E8*/
+                       "AwIABAUB", /*E9*/
+                       "BQMEAAEC", /*EA*/
+                       "BAIFAQAD", /*EB*/
+                       "AQUAAgME", /*EC*/
+                       "BAIDAAUB", /*ED*/
+                       "AQQABQID", /*EE*/
+                       "BQMBBAAC", /*EF*/
+                       "AQQDBQIA", /*F0*/
+                       "BQIEAQAD", /*F1*/
+                       "AwABAgUE", /*F2*/
+                       "BQIEAAMB", /*F3*/
+                       "AgQABQED", /*F4*/
+                       "AQIFAAME", /*F5*/
+                       "BQQDAQIA", /*F6*/
+                       "AQIFBAAD", /*F7*/
+                       "AgQABQMB", /*F8*/
+                       "BAABAgUD", /*F9*/
+                       "AwQFAQIA", /*FA*/
+                       "AQADAgUE", /*FB*/
+                       "AwUABAIB", /*FC*/
+                       "AgMEAQUA", /*FD*/
+                       "BAUDAAIB", /*FE*/
+                       "AQQABQMC"  /*FF*/
+               );
+               
+               static final List<List<Integer>> ADD = createTable(Integer.class,
+                       "jMGyEw3jMK9hrRBfpv/16KyjUnl26RXy", /*00*/
+                       "usvJp51XPL+zYiCMjf6qVQEYFfi0Axco", /*01*/
+                       "OMxp7qlUrHQ7SMiEeFCbBe4ZMz/RjCRL", /*02*/
+                       "ZAJ+7jWDeD1zUIbUj0F0G+D2WsZTWA2j", /*03*/
+                       "vWvIotNSqLc8YZdfehl1X+gFiNepMjUV", /*04*/
+                       "izHV8h79MFxtE3c43U5vxL4LpJdu7s+f", /*05*/
+                       "DAW42laUHGXgshByzyG26m4D8mDAz/nb", /*06*/
+                       "FF5X2ByqhPDAdh6cqWxvM/7LcYc4LRPC", /*07*/
+                       "oHejhtoh+b9Xa60WRQqIyN3Opq45qZv3", /*08*/
+                       "m3QIoIr7PCmSTIp+EfKEXoV0zzw+w1SO", /*09*/
+                       "bxd4mqvscniZEeZ+zfA59w2iK4ulObNy", /*0A*/
+                       "bJ+3+WNN9CdbpuXQfiwJBuZg68QQ1ASD", /*0B*/
+                       "2pKanNGM5vhKf6dth+sTIIWG1NVXpdfQ", /*0C*/
+                       "d4hgEv0QY1s9bSlBg11DV9zfBqlybRo6", /*0D*/
+                       "5scSUVHX9uulJjD9I52jCPFPE1SKLFvs", /*0E*/
+                       "5u5SL9NTqECB7Ys132Jrx09ueI53NvZ1", /*0F*/
+                       "ftKrVLgr7rfBbXUXuzvetkC1kqlK5KRm", /*10*/
+                       "C2+Mm7HOojwJPFi9UTZxFN6nearF0cMo", /*11*/
+                       "i/e0q9iU4dPjhQqqlrHHyQ9xhTgL45ID", /*12*/
+                       "kOoioTYkGseCXD8i/6SwjNFXm1udaGrx", /*13*/
+                       "DTv6epNd4HWhB32+mIXIicHw2/s+9kds", /*14*/
+                       "P7rS08/wxGF9EkufeqWv6h2TzgiFaezJ", /*15*/
+                       "oix5sCxb1jnd5C99X+XG9EuzJm/yFiw5", /*16*/
+                       "YL/vWVqtbwUwu2wgvmWu3K7cedbb5k7d", /*17*/
+                       "48vgP67BFj2q6BAufzxN7Ixrwj4zL5XB", /*18*/
+                       "L6oV1aXnACQ6/nFOCf6N152YzbPr4zGg", /*19*/
+                       "DJVLaHqbRB8m773VrWJl6/P1KCv5+T0K", /*1A*/
+                       "uRE47IfdU3+HsqkLr2rUszSQDdP57gqP", /*1B*/
+                       "aGc2dqHW+YFW24Yzvwuy2ZfiAVY2YmQw", /*1C*/
+                       "hFzaf4EIO5VyzEqs7lpWNdsPVNPdZCwH", /*1D*/
+                       "qqsZX/XlHsleta/1oZboK9UJxOEP+ul0", /*1E*/
+                       "n81y03xuZ1v4WvtMIn83r4yFMckNzkVU", /*1F*/
+                       "fyw7QkFWaVhl+PdTS/GP3RKwhzfWcJB2", /*20*/
+                       "fUHQ3DqBFPm/20E4vikbYAG5t7RJpsPc", /*21*/
+                       "653iO9Cg+e0P+t3yzCMvksM7VsRyLxLk", /*22*/
+                       "ZkaL6JC6zt09MXtbCtwPvtkxRF21zgVt", /*23*/
+                       "a2TyaxTvS55oqn2xlrgec/aWebTpmQY8", /*24*/
+                       "lOKIPgJy+WYEvR1wfm/PkdSlgbzrMrbV", /*25*/
+                       "1TIMX4+zGAGLd3J8yVHiRXam6Q6a7Yzh", /*26*/
+                       "FUbsDTTK+rybzzN6AkL8f5hsAzx/EbAv", /*27*/
+                       "ghjoS7nGK9FCGaz6k7clyFlQIz2ysA0M", /*28*/
+                       "4klAHWq4hCp+239TDrSB7D852n3Q16Ov", /*29*/
+                       "RG1rAwNM3ptlzF6AZ4a0L3m5TInPuXmL", /*2A*/
+                       "JOehJnvkQcBcBFLFzAL1XUd+t4Y98zfM", /*2B*/
+                       "FDdz+PfpSYDfKyYA2yTj1qTBhqKLmU70", /*2C*/
+                       "g624KvZe/nHo1gVJd63aFqwMdQTnFO4A", /*2D*/
+                       "4YLkyUVPsFRrY8YF0h5QoyMq+/nMvl+J", /*2E*/
+                       "xSQ9rcx+AdC4gajfUjzcSC2d5pcc0sXv", /*2F*/
+                       "RMhWzCbwW4d62/CKe5+qyNjhd3k4fFWW", /*30*/
+                       "0k9wUU4XUcT8xcAdMgRpPEk9Ee7hOy8c", /*31*/
+                       "0qR75tAqoRywCV5MJgrJjO9csWvPC6IE", /*32*/
+                       "Hoao80u2qKvBcx2nZlU/s7vCgNez8aQ1", /*33*/
+                       "DuXGOu43ggXi08wo6TjBZWJfFjZSE0a6", /*34*/
+                       "VKSQwUtKsTuLT6pur/hUxNkJ+yN6O4vM", /*35*/
+                       "qFV7mjk9f7kc95W95F92+L805GDjyENN", /*36*/
+                       "lKdJdORUwBcRRB4DodGKy1iurUkePcW7", /*37*/
+                       "izLURGcVnWAFjicdqRrdWmT9yJj/VLlW", /*38*/
+                       "VF6/IqbY+dpDIyNtwfOOSHZ3FPB0xoVB", /*39*/
+                       "o3C/vmmNwB4bn05AF5FdRIAutzzlhVZH", /*3A*/
+                       "rGQ+VkoB03H7HHRyJssu8hrEUUVD7CMA", /*3B*/
+                       "K93p45YZwzegZl7lDR8t0bWZJTQvSG/F", /*3C*/
+                       "4+mp8Y0tDnc2ogtLcUx9eW/pFFWGhpO9", /*3D*/
+                       "Wd9VKi2YGMwmjTsJCkf3eAOacU+ef0NK", /*3E*/
+                       "aSKrlzOiIqwXHT1dHjUGeTpYyT2SIet/", /*3F*/
+                       "peMReb9mvNMzb7lw92TDEz035GujHO6V", /*40*/
+                       "uRtLYml/1bHavtYjWXPEFL4bxlO6DGOi", /*41*/
+                       "V7YUhvETzTDCuv/cZmkaCeyZidFUw6Ou", /*42*/
+                       "ywC7zoZFwUTeKrqXb+HgWIiL1u/IQnd1", /*43*/
+                       "m2HWrc6ARMaSvhWaXAUsfv9P4+DdRLdT", /*44*/
+                       "uI5ZGB+OELkVyLWUUzD6eXcTHODy12d5", /*45*/
+                       "EL3/r/Ou6g0/JGYc8wFm3ZsGEiCEXARD", /*46*/
+                       "S8osVEKoeFi2MC8pfYK7qj0LI9gvCGIy", /*47*/
+                       "8N1k2aZRg03WDRT8coZrLZTTMgVBdGfK", /*48*/
+                       "YblYm/Sa+ZuHmIpHfN53StS3YAWHGKOx", /*49*/
+                       "zBU0PImBS6z6k2ew8sC5wBUbnUfYU6Mf", /*4A*/
+                       "etMHU+uEdo5iIznpOLoGbbY6hMHO3eyn", /*4B*/
+                       "P6yTqw1Ow7i+nEcXIv+5ObMyJcuTnha0", /*4C*/
+                       "h0d7bPNIUCkBGEAnsMouWTqQNo1aJcfN", /*4D*/
+                       "pBLkGx2DanJftwDryvw7F9uuL5V9gepD", /*4E*/
+                       "EADE+xfbC9GuID2u0n80IDZ28K9uzIal", /*4F*/
+                       "SA8AA8wycyytCgKwTbbsCWQouNvA95yK", /*50*/
+                       "ZF7QwH0dkhHQmveSxV4fTMmiirMcgxEF", /*51*/
+                       "OAkZjfvoOm+P9O3IVKts8qT657AhqsIW", /*52*/
+                       "WJycNcNAkYi3vHBeVvOsWPuyvcPV1Yio", /*53*/
+                       "77n2hGhBVVy3yo1KQMPtXfd7xUTbrb8x", /*54*/
+                       "IHcsxBvR2pRddPwpOUYfPPxtL+Uurt2X", /*55*/
+                       "whSLDP6A2bC2I1YTH9dyXMqNW1vAmUrb", /*56*/
+                       "P997XglfiNKP+EbPze+5HuBruzxEdXyQ", /*57*/
+                       "iNibvXJsgKYPtsDmzi1be2wOq+fCzSDi", /*58*/
+                       "e1dVjBU1AqXnDWPGCng8PczuUDbL607B", /*59*/
+                       "uWGWcCIEd67FcM+m/qI/swrxOuuRiyL0", /*5A*/
+                       "UqROJDDrgBXnR8HfLsFv+Zse9Rd9Dufg", /*5B*/
+                       "DtVPNLffhI96GTmFiin6L6Ui5VgbdkZr", /*5C*/
+                       "E3AEAPO2Y0Z5ThhYSTRfygjFB5ZMQfon", /*5D*/
+                       "w2jB7zN7AdyNpDF/bjxLa0JS0DwoNzxl", /*5E*/
+                       "ikTJqgm5vyWzPiFC9+BuC1IRMnDqtrVA", /*5F*/
+                       "40clT0iLyIRM1InHRn0x6I4xHvvYjTOj", /*60*/
+                       "PrcP2IzSRIHMQaQzVGNzt24qG6lHMZc8", /*61*/
+                       "Hf/C0IGrC/hZYwB+kAAFWrx0g5LpxTbm", /*62*/
+                       "Zm3JKWx84q5R4XwmeHN0QNnUTLDzwUBR", /*63*/
+                       "XndrFdA1TZo7X9qEek55Hi2VFWx31jS+", /*64*/
+                       "6/H7lURnyktsd/ByzbQRfDxOZ6WkLQKn", /*65*/
+                       "9phwbAOiNTWTTyJj8fblT8AK1k8x8IRi", /*66*/
+                       "fXXxtanhovB9JkZAyuZlI7eEHPD1d3Gi", /*67*/
+                       "X6Wo9yPS5Ciy2zNpfGVuwLeUTECOJ8nN", /*68*/
+                       "SduPuLAcPNuacUNmVxGKp0lWiXQm6jWb", /*69*/
+                       "pgBS4I+8jK81aTZ2cjZljJv5oxCqKS84", /*6A*/
+                       "ADmrKcREnChf5GMV3mUKqey/oDDO3J+r", /*6B*/
+                       "pgry4cppneykbiUDO7K/1weJg5p3Qq0s", /*6C*/
+                       "wzdr3RSJboFG2fVQkzssOc1iIz9B9/5b", /*6D*/
+                       "AYR1bZCLzNq7cQcpGKN57W9Shxp2Pi4v", /*6E*/
+                       "Fq2DM/pERw83exyKEyTMjlopMnevofaj", /*6F*/
+                       "Z1Oy8VvrPiOwUp0nymwEmgdl17CrY1mI", /*70*/
+                       "+eFz7HLXrm9yD3jsJg7FRlvbIWLmdcqJ", /*71*/
+                       "XZ/Y2ngm21kYwHml9QjakF55nr6I2eQR", /*72*/
+                       "H69zI63Zz8wVnl428R86dO18BRNiFtFt", /*73*/
+                       "q88q43ieZezycrQMfpAC3QI4zv9jGR+5", /*74*/
+                       "LRzMQ5mdI6RrMG53iJp09ZBk7Zzc8J0t", /*75*/
+                       "6TKKPX5V2/Px7tOnQWOcMnM8bTr4IdAJ", /*76*/
+                       "YnbedDrxsI8J0ZNnhmro7yZjOZp205bv", /*77*/
+                       "4h2SfNVVTMJb1EQ1otmGVjVW8l1U6cfv", /*78*/
+                       "HXhIbAaDjOoprXp1h1wRQD3ALqnCPm3z", /*79*/
+                       "AexIisbux2poEv/gxydRCh4HRALt0Lav", /*7A*/
+                       "M52ymcvNjV6o1C7afv3M2drki2bDWBgI", /*7B*/
+                       "B2Lc3cMpI7VyuR006DCrT00fgv+djLZH", /*7C*/
+                       "piGV1Q01hevGR/XMouBQ71qvSbWExLD7", /*7D*/
+                       "9OkXUhMjfLKvIivI0EaaYfr0D07V/rca", /*7E*/
+                       "pb8+kUAkVb6lJx64qQ34/mQIEFzujj+8", /*7F*/
+                       "E3ZiJ5HWU929oboZEeh50aD9G5I5xRo+", /*80*/
+                       "B8XKF+CPqWqF4AL7++7Q9vSZZ2dAnTUS", /*81*/
+                       "7ppNVUlSot4cULzEsrQR8NyEuVhaa5yS", /*82*/
+                       "yK0XMu5tmv0VHpLDwVnWq2k506tnZzCT", /*83*/
+                       "r4wyNaLXxPN+NLAH5Sf2PYzHc7LNCPKt", /*84*/
+                       "H3LXKwM4ePUklrsbBbG0Vc/zs/+z4fJM", /*85*/
+                       "aN1l0W0dwLFiHhAdYlYKOtIihzxa/0S3", /*86*/
+                       "GISbROvOxSnNA0SXq2CW5JlRFIJ7ts4g", /*87*/
+                       "c6QrfHmArufYLUMxqfWHh7UoQuAvLzkz", /*88*/
+                       "+hYnlhIdbwpY+LNGxxniYvEqHoYysmZY", /*89*/
+                       "UQKzVzca9WJoQTJZMG6D8AG8g8CusYt3", /*8A*/
+                       "nsihcUw6rOxkzrs8L4310QZuXGqVQcZh", /*8B*/
+                       "HKIFfNnqWxVc/91+mIy7eBFO6Kj5se7F", /*8C*/
+                       "s/+fQ0YTrfGxi4mcmNC0+mN47zDoRnaL", /*8D*/
+                       "fIG5B4mjqZY+hphG4VZDAhryrzgJfRH0", /*8E*/
+                       "cygLp0Uxikgxx6VD05+kEuUAAL0BkF6b", /*8F*/
+                       "D2PWF8wPrvPrT9A2qMS4ILmCdXF8jVNI", /*90*/
+                       "/kWwkZX23D9cDW01joC4LuNMTv12mskd", /*91*/
+                       "KufxREb0MEXWRVWyjUmAULLYxrj0uDLL", /*92*/
+                       "VywGqETdPj+M6e5IVLle4tu9Ehfh33BS", /*93*/
+                       "wgH5EpnZ5p1piXLF5V0sBuTFSTytSjRb", /*94*/
+                       "1KlBe73TFwDVRlqshCKvr6jO70U/xs4z", /*95*/
+                       "pKLqsySDkBUA/rXc1+nx0Lxi41GIt8v+", /*96*/
+                       "BebVL9rK/cbrnt/kF56jIslg7pSHTc7y", /*97*/
+                       "EHRiXsjqWN3UDf92+c8apZpdbkCIxPZB", /*98*/
+                       "+WAIkfviiIxKOz5v2fVjtULgDz9Rcrvz", /*99*/
+                       "mAhyxJmISxd+YifQ5VRex3APOv58aTq4", /*9A*/
+                       "+/2zl+LVgN7Tr02XM2hQg/B+qlGp6VEn", /*9B*/
+                       "rrBqSEdKxzmeBeWLH9IG04clbEYYW8Ow", /*9C*/
+                       "TErUU91OXE0rAkfvdZj0A4Rn6lim9Lgd", /*9D*/
+                       "Y2xt82TOPyh4dicfcgtN2tYH7E4Rle2L", /*9E*/
+                       "GdAlUT2c3zGoOY9VhTmCLtljDzYvuP5h", /*9F*/
+                       "uEF85PKtDqe0lFruGGepmlv4ekYdB6JG", /*A0*/
+                       "FBAS7iah9y6FL7FjMPBSqmlaz4zQxfQu", /*A1*/
+                       "dQLjVi3JPpymq8AD6m2BEJ7lq3VVAwap", /*A2*/
+                       "hJsxjFq1/81EoAKWjwWDQcbKUGy8K6F2", /*A3*/
+                       "RaElHLX1HgRgCkIHzp2nMFGYxJqEmFC6", /*A4*/
+                       "1NR2wB5z6NVnwfGuaU3OUsJDEkboSxJZ", /*A5*/
+                       "x7J50ZgU7gbQZe+Gj3ZHxFO/9IfFAtAA", /*A6*/
+                       "p7+3+5b+54N3Z4rAkjj0BYV/IbDDH8ks", /*A7*/
+                       "dSYD6NlAcKEQ0YupW210e1etqnHAxXDP", /*A8*/
+                       "tqUyB0eGqAiLhOpjYq4iiSR4NwDwQrbm", /*A9*/
+                       "WfEflCqobww3ttdVrhKl1TClpkdGfW2z", /*AA*/
+                       "gbRJyiaLePMV5cAW2feuLVunR2K1S0h4", /*AB*/
+                       "k04QZRcnYKoCze425Y4/hM6soSnVC8m9", /*AC*/
+                       "nSZiD8cKN2345xYay0g0RvtkuLgUqp7M", /*AD*/
+                       "ZN1aoIhPVNEOiY6A/gdDrRWjnduIkDwK", /*AE*/
+                       "Q5e02+LAHYLYLHrlx2/w6XAQPjbVqVop", /*AF*/
+                       "RLQmozdGH2IBaGGSu18f/az+b9yAHLFY", /*B0*/
+                       "x0kuIZXQUdF2ojZLZn3XKjesGs8geXv3", /*B1*/
+                       "gEKroiCpcTl88Aa5jLoT2cbRKQR8uAsH", /*B2*/
+                       "rfqrNFkkZo3JA12cE9eGs+N8c60T+fly", /*B3*/
+                       "t3iNLtBTBKNxQ8X0gguO0ZUZLSt4rDMD", /*B4*/
+                       "BP7m4V2nBJjeER/72bYg0pG8tHxhaPdu", /*B5*/
+                       "WqWHvuaX1wDRgWIPvDUiJE8FpPfbu1fq", /*B6*/
+                       "SQB9mNiYwAPVZsnAAnKL1qBqxw5ZZkrO", /*B7*/
+                       "0xQXcDpNK8yDWo7KTN/kGni37Vn5rMAz", /*B8*/
+                       "IgEL6ZMmAOhEOSsVQCX0IpREV8bijMJG", /*B9*/
+                       "rIKxcvb3Aalb1P1ceXmpOY1d58FBWjx7", /*BA*/
+                       "tHGcY/jPD74E8WxSKeP6VLuYIAN3V7Xn", /*BB*/
+                       "m3ar/kkHbClv8DumfGItDCV0YIRpQPmk", /*BC*/
+                       "pzjJ8kQe1CdZqlZ+bG7kbW387dsJFEAE", /*BD*/
+                       "AYj8MmDSFoX+GtZkMkVZlhLKuh5rPAlv", /*BE*/
+                       "rL3NTZll5k28qpQnnS//kxqhKn5Kh8/w", /*BF*/
+                       "a2oW3nHtyLpoGv4235bwwMVBt4VIlbuW", /*C0*/
+                       "0vLa8RQh0ouRn5Dm72B+dvL690xXGoC7", /*C1*/
+                       "W6C6Rnpt3SC1dGdL7d2dnUIB1v0KpVFT", /*C2*/
+                       "udJUEcijQ2I8GrrvU9aA2FZSzVmsY+9L", /*C3*/
+                       "yg9/u+49z4vo03zvpW6aQBEqW9B9iz/L", /*C4*/
+                       "hgLfXCsyqhUZRfeCNSV2GQDqrhATu8am", /*C5*/
+                       "ZM+MT6L5dcGIIIpFC1ZOMzFK2T6g/m/D", /*C6*/
+                       "KZB0KhbpgKcGNxgyjlIvk+TDUB0Y/Ing", /*C7*/
+                       "j3Imqm0IncJcjvhhjervLN3xiO4PupvI", /*C8*/
+                       "V83ipbfEnWJ5YHLHsUCk7nR2fVB/7T6g", /*C9*/
+                       "mDC3I8eW6XvavYtsNxqIfTd7RBJAnS4R", /*CA*/
+                       "kgodwgoBmtDzejXNP7YmBSbf4tE0gvRP", /*CB*/
+                       "zVkNleHbOQaDJzOcRsdJ+uvHPZXkNrGO", /*CC*/
+                       "/vSomYYWaomD5RveQqbjINXlZQ7M2qwP", /*CD*/
+                       "fd2KT/99esJhhkNlsmu+BIyVgN8ymjZn", /*CE*/
+                       "zpJOECCf4ZTzhqpvjeQlmk4gggQbLSyR", /*CF*/
+                       "JIisKL883YEKOwDUMjaoXwpeSF+KmoFf", /*D0*/
+                       "q+bQ5sh96Qm+bZRecwXZfYan7PW80Luw", /*D1*/
+                       "8XfTuDe2oo8KGDUrYkFGKDXQVcQhkPp9", /*D2*/
+                       "BynFasbkSSfQpNZq2nRxO+/jGf4K9PH5", /*D3*/
+                       "RQMQ2/7/1fVGRa9axWxaqTHicrFf5LiS", /*D4*/
+                       "Wyx9YQy7M+FvfM6V8btZ6Pd2JeFhitJ0", /*D5*/
+                       "TsqEwt7c88zb+ZzG06WX09ycgAI/h7x/", /*D6*/
+                       "3FhxF2rcMCvYa1Kvy4PnecU11shBmrho", /*D7*/
+                       "49sPNRynmpDzxpnBomYFl9o3v1hWB8pi", /*D8*/
+                       "cZFii9kLxoOd3udVif2HCpFaFmOFXL7E", /*D9*/
+                       "4gKLe8yotZizEr6XyHzB74ARDmLSuea7", /*DA*/
+                       "kGuTl9eoWTCZLCSZW3ESUqLkQDv/MLNH", /*DB*/
+                       "SC/o3qViWJxSgclGwcAm3uLcfKAM8mm8", /*DC*/
+                       "QTHqqko1QPiVoOF+rG2PSW0h6Oqgll62", /*DD*/
+                       "nF3XEjEVqmp23yCugXkl/nvnTkN5dZxU", /*DE*/
+                       "aMQvGwjhQAmeGt5giW/UQRLWDc9rOKB6", /*DF*/
+                       "9jNkpboAkXjpt81QbK4ROho2JIIUPIsf", /*E0*/
+                       "HDpt/TKmLekUWrMIzSH5bVB4iL6k0hru", /*E1*/
+                       "9FksdyEOV7kc4Eh0HrYypuQYAkprk9RI", /*E2*/
+                       "xLccANcRJWSpVxReUxzXGzC7jvgSn/eq", /*E3*/
+                       "nJkpO3uo8mGEjBynS9c/CzDCGpmcGNUc", /*E4*/
+                       "Bdvwl8vbZkFbCM35afU/CL3Olc0srKSg", /*E5*/
+                       "2f4ojDlnpwsDHsjXaZPsKHmzfvQkxgNO", /*E6*/
+                       "rSfviDYSlxc4zOhNa5Jo1LOS44uRQDlW", /*E7*/
+                       "DGt7rThtCOY+EMx0q8RPc4MzlhgJ/df1", /*E8*/
+                       "dQm0NhmSQX4j2wnRb59W3fLzXcysKnxj", /*E9*/
+                       "/+BUw+OrHXHq7gg4eWYgbOpAUNdBbPtA", /*EA*/
+                       "Rqua3WdO5kFbQhomfD/LgDmhMaX6TZN1", /*EB*/
+                       "CErkFIuijB9Clcb/aRpRs0wDqvgBLuUm", /*EC*/
+                       "iSBbXA8LfLMYvdDYLyyTQO8v7txTmYJS", /*ED*/
+                       "b1bqN9FNnAhi12CfhlR48g1rOqk9BgNl", /*EE*/
+                       "x+LLwCbFI07wcmtgBXpLiHv2bqYK2A3z", /*EF*/
+                       "4Hby85LGkTVbiLuyWC7C2ynKbXgGDeoV", /*F0*/
+                       "lqK3kJ3swSzmKpIg344LNcG2DVglZx6Q", /*F1*/
+                       "Id6ZwE5Z4R1RM9JI6B/O0XFm4nZKdF6A", /*F2*/
+                       "Ex4HiXqk6Oi5J+cs9rv6vlandD8tPuJa", /*F3*/
+                       "3OUI/YzkZouyJc1J59drNbrpKpNCTc/A", /*F4*/
+                       "PgdhrcAQbRTGhLkVpD/rB/GlvK+/g6EK", /*F5*/
+                       "pEch+HyJPd9KVTuqgtJq40vhta3KhEVV", /*F6*/
+                       "tGfshCY0S9jJpvAr7/iji4taLdbKZdkX", /*F7*/
+                       "DKu1A/Eqaiizn7U98YuP/UmLvmge0gJS", /*F8*/
+                       "fDBMIYDRZdShcIDEVXhnlLcYZ1yzT2Z9", /*F9*/
+                       "+N+tC8xOzEzMbzHhVVgKyvSMDR7Y4x4M", /*FA*/
+                       "hyFq89tkXpzi8FpMj0VFioHTBIJ0GONM", /*FB*/
+                       "pa92Tw1yY/+M/gkfAunXiNhMwG+X6ylV", /*FC*/
+                       "YkmEYyKd8IViUOIQT+gLnLVAlAMyur6P", /*FD*/
+                       "J6RHxOuI3LpyhcQ+POhMKX3K5EP+3K/V", /*FE*/
+                       "TyZ9zH5NddtcVyANgbrSDarYbosjUYau", /*FF*/
+                       "RFJqYyG1PCD/M/kG3EibuTnkZbdWIqiL"  /*00*/
+               );
+               
+               static final List<Byte> FIN = createRow(Byte.class,
+                       "GRIjFgEfCQAMKgURBxMNAhQuCiYrHCAXLQQpGiEGIigPHiUQCy8bDhUsHScIAyQY");
+       }
+       
+       //=======================================================================
+       // HASH STATE
+       //=======================================================================
+
+       private long[] hash;
+       private byte rnd;
+       private boolean finished;
+
+       //=======================================================================
+       // PUBLIC METHODS
+       //=======================================================================
+
+       public MHash384() {
+               reset(); /*initialize*/
+       }
+       
+       public void update(final byte value) {
+               if(finished) {
+                       throw new IllegalStateException("Hash computation finished. Must call reset() first!");
+               }
+               final List<Long>    xor = Tables.XOR.get(value & 0xFF);
+               final List<Byte>    mix = Tables.MIX.get(rnd++ & 0xFF);
+               final List<Integer> add = Tables.ADD.get(value & 0xFF);
+               iterate(hash, xor, mix, add);
+       }
+       
+       public void update(final byte[] data) {
+               if(data == null) {
+                       throw new NullPointerException("Input array must not be null!");
+               }
+               for(final byte value : data) {
+                       update(value);
+               }
+       }
+       
+       public void update(final byte[] data, final int len) {
+               if(data == null) {
+                       throw new NullPointerException("Input array must not be null!");
+               }
+               if(len < 0) {
+                       throw new IllegalArgumentException("Length must not be negative!");
+               }
+               for(int i = 0; i < len; ++i) {
+                       update(data[i]);
+               }
+       }
+       
+       public void update(final byte[] data, final int offset, final int len) {
+               if(data == null) {
+                       throw new NullPointerException("Input array must not be null!");
+               }
+               if((offset < 0) || (len < 0)) {
+                       throw new IllegalArgumentException("Offset or length must not be negative!");
+               }
+               final int limit = Math.addExact(offset, len);
+               for(int i = offset; i < limit; ++i) {
+                       update(data[i]);
+               }
+       }
+
+       public void update(final ByteBuffer buffer) {
+               if(buffer == null) {
+                       throw new NullPointerException("Input buffer must not be null!");
+               }
+               if(buffer.hasRemaining()) {
+                       final byte[] temp = new byte[Math.min(buffer.remaining(), Short.MAX_VALUE)];
+                       while(buffer.hasRemaining()) {
+                               final int length = Math.min(buffer.remaining(), temp.length);
+                               buffer.get(temp, 0, length);
+                               update(temp, length);
+                       }
+               }
+       }
+       
+       public void update(final InputStream stream) throws IOException {
+               if(stream == null) {
+                       throw new NullPointerException("Input stream array must not be null!");
+               }
+               int length;
+               final byte[] temp = new byte[Math.max(Math.min(stream.available(), Short.MAX_VALUE), 2048)];
+               do {
+                       length = stream.read(temp);
+                       if(length > 0) {
+                               update(temp, length);
+                       }
+               } while(length >= 0);
+       }
+       
+       
+       public void update(final String str, final Charset cs) {
+               if(str == null) {
+                       throw new NullPointerException("Input string must not be null!");
+               }
+               if(cs == null) {
+                       throw new NullPointerException("Character set must not be null!");
+               }
+               update(str.getBytes(cs));
+       }
+       
+       public void update(final String str) {
+               if(str == null) {
+                       throw new NullPointerException("Input string must not be null!");
+               }
+               update(str.getBytes(StandardCharsets.UTF_8));
+       }
+       
+       public byte[] getDigest() {
+               if(finished) {
+                       throw new IllegalStateException("Hash computation finished. Must call reset() first!");
+               }
+               final byte[] digest = new byte[MHASH384_SIZE];
+               final List<Long>    xor = Tables.XOR.get(256);
+               final List<Integer> add = Tables.ADD.get(256);
+               for(int i = 0; i < MHASH384_SIZE; ++i) {
+                       final List<Byte> mix = Tables.MIX.get(rnd++ & 0xFF);
+                       iterate(hash, xor, mix, add);
+                       digest[i] = getByte(hash, Tables.FIN.get(i));
+               }
+               return digest;
+       }
+       
+       public void reset() {
+               rnd = 0;
+               hash = Tables.INI.stream().mapToLong(Long::longValue).toArray();
+               finished = false;
+       }
+
+       //-----------------------------------------------------------------------
+       // Convenience functions
+       //-----------------------------------------------------------------------
+       
+       public static byte[] compute(final byte[] data) {
+               final MHash384 hash = new MHash384();
+               hash.update(data);
+               return hash.getDigest();
+       }
+       
+       public static byte[] compute(final byte[] data, final int len) {
+               final MHash384 hash = new MHash384();
+               hash.update(data,len);
+               return hash.getDigest();
+       }
+       
+       public static byte[] compute(final byte[] data, final int offset, final int len) {
+               final MHash384 hash = new MHash384();
+               hash.update(data, offset, len);
+               return hash.getDigest();
+       }
+       
+       public static byte[] compute(final ByteBuffer buffer) {
+               final MHash384 hash = new MHash384();
+               hash.update(buffer);
+               return hash.getDigest();
+       }
+       
+       public static byte[] compute(final String str) {
+               final MHash384 hash = new MHash384();
+               hash.update(str);
+               return hash.getDigest();
+       }
+
+       public static byte[] compute(final String str, final Charset cs) {
+               final MHash384 hash = new MHash384();
+               hash.update(str, cs);
+               return hash.getDigest();
+       }
+       
+       //=======================================================================
+       // INTERNAL METHODS
+       //=======================================================================
+       
+       private final long[] temp = new long [MHASH384_WORDS];
+
+       private void iterate(final long[] hash, final List<Long> xor, final List<Byte> mix, final List<Integer> add) {
+               for(int i = 0; i < MHASH384_WORDS; ++i) {
+                       temp[i] = mix128to64(addUnsigned(hash[i], add.get(i)), hash[mix.get(i) & 0xFF]) ^ xor.get(i);
+               }
+               System.arraycopy(temp, 0, hash, 0, MHASH384_WORDS);
+       }
+
+       private static byte getByte(long[] hash, final byte index) {
+               final int pos = (index & 0xFF);
+               return (byte) ((hash[pos / 8] >> ((pos % 8) * 8)) & 0xFF);
+       }
+
+       //-----------------------------------------------------------------------
+       // Utility functions
+       //-----------------------------------------------------------------------
+
+       static final long KMUL = 0x9DDFEA08EB382D69L;
+       
+       private static long mix128to64(final long u, long v) {
+               v = (v ^ u) * KMUL;
+               v ^= (v >>> 47);
+               v = (v ^ u) * KMUL;
+               v ^= (v >>> 47);
+               return (v * KMUL);
+       }
+       
+       private static long addUnsigned(final long u, final int v) {
+               return u + (v & 0xFFFFFFFFL);
+       }
+
+       //-----------------------------------------------------------------------
+       // Table initialization
+       //-----------------------------------------------------------------------
+
+       private static <T> List<List<T>> createTable(final Class<T> clazz, final String... data) {
+               final List<List<T>> table = new ArrayList<List<T>>(data.length);
+               for(final String line : data) {
+                       table.add(createRow(clazz, line));
+               }
+               return Collections.unmodifiableList(table);
+       }
+       
+       @SuppressWarnings("unchecked")
+       private static <T> List<T> createRow(final Class<T> clazz, final String line) {
+               final ByteBuffer buffer = ByteBuffer.wrap(Base64.getDecoder().decode(line)).order(ByteOrder.LITTLE_ENDIAN);
+               switch(clazz.getCanonicalName()) {
+               case "java.lang.Byte":
+                       return (List<T>) buildRow(Byte.class, buffer, x->x.get());
+               case "java.lang.Integer":
+                       return (List<T>) buildRow(Integer.class, buffer.asIntBuffer(), x->x.get());
+               case "java.lang.Long":
+                       return (List<T>) buildRow(Long.class, buffer.asLongBuffer(), x->x.get());
+               default:
+                       throw new UnsupportedOperationException("Type not supported!");
+               }
+       }
+
+       private static <T,R extends Buffer> List<T> buildRow(final Class<T> clazz, final R buffer, final Function<R,T> getter) {
+               final List<T> row = new ArrayList<T>(buffer.limit());
+               while(buffer.hasRemaining()) {
+                       row.add(getter.apply(buffer));
+               }
+               return Collections.unmodifiableList(row);
+       }
+}
diff --git a/ports/java/src/com/muldersoft/mhash384/package-info.java b/ports/java/src/com/muldersoft/mhash384/package-info.java
new file mode 100644 (file)
index 0000000..37e4eaf
--- /dev/null
@@ -0,0 +1,8 @@
+/**
+ * <p><b>MHash-384</b> - Simple fast portable secure hashing library</p>
+ * <p>Copyright(c) 2016-2019 LoRd_MuldeR &lt;mulder2@gmx.de&gt;</p>
+ *
+ * @author LoRd_MuldeR &lt;mulder2@gmx.de&gt;
+ * @version 2.0
+ */
+package com.muldersoft.mhash384;
diff --git a/ports/java/test/com/muldersoft/mhash384/test/MHash384Test.java b/ports/java/test/com/muldersoft/mhash384/test/MHash384Test.java
new file mode 100644 (file)
index 0000000..53583c2
--- /dev/null
@@ -0,0 +1,167 @@
+/* ---------------------------------------------------------------------------------------------- */
+/* MHash-384 - Simple fast portable secure hashing library                                        */
+/* Copyright(c) 2016-2019 LoRd_MuldeR <mulder2@gmx.de>                                            */
+/*                                                                                                */
+/* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
+/* and associated documentation files (the "Software"), to deal in the Software without           */
+/* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
+/* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
+/* Software is furnished to do so, subject to the following conditions:                           */
+/*                                                                                                */
+/* The above copyright notice and this permission notice shall be included in all copies or       */
+/* substantial portions of the Software.                                                          */
+/*                                                                                                */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
+/* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
+/* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
+/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
+/* ---------------------------------------------------------------------------------------------- */
+
+package com.muldersoft.mhash384.test;
+
+import com.muldersoft.mhash384.MHash384;
+
+import org.junit.Test;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class MHash384Test {
+
+       private static final AtomicBoolean m_success = new AtomicBoolean();
+
+       @BeforeClass
+       public static void initialize() {
+               final RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
+               System.out.printf("MHash-384 v%d.%02d-%d, Java v%s [%s %s]\n\n", MHash384.VERSION_MAJOR, MHash384.VERSION_MINOR, MHash384.VERSION_PATCH, rt.getSpecVersion(), rt.getVmName(), rt.getVmVersion());
+               m_success.set(true);
+       }
+       
+       @AfterClass
+       public static void finish() {
+               if(m_success.get()) {
+                       System.out.println("\nSelf-test completed successfully :-)");
+               } else {
+                       System.out.println("\nError: Self-test has failed! :-(");
+               }
+       }
+       
+       //=======================================================================
+       // TEST VECTORS
+       //=======================================================================
+
+       @Test
+       public void TestVector_01() {
+               runTest(1, "",
+                       "D629CB37F76156621E09C93B8D1029C5F0F7B778DE5BD9578230673FE7FA4C45A2308AB4E9D99AA0EA194CBF6230C202");
+       }
+
+       @Test
+       public void TestVector_02() {
+               runTest(1, "abc",
+                       "1D7B1593D7AA4DD7DC8DA6D6BD591D8B507CA514E1C7EC37F43E78DD6B83253C355403F61009582890480C4CD527F405");
+       }
+       
+       @Test
+       public void TestVector_03() {
+               runTest(1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+                       "9B98CE4C3F4EA9018E1ED3034717E3E5D8DA20AB375BAFE372D07780FFDEFDA32BA3C822155E2883E333AFCAAEAFA614");
+       }
+
+       @Test
+       public void TestVector_04() {
+               runTest(1, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+                       "45416D1FFD44D3940C5AF5B425B5DA07FD8C06BAB7C58CD13389BC284650ED6090A9A1952C29FEB1B2C6AFBF5F996108");
+       }
+       
+       @Test
+       public void TestVector_05() {
+               runTest(0x186A0, "aaaaaaaaaa",
+                       "20774C570AE2E6A49A01DAE948672AE94D465D9167130FE87BF24148649CF121E8A50759507BF97134F0D28CEE91DCA2");
+       }
+
+       @Test
+       public void TestVector_06() {
+               runTest(0x1000000, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno",
+                       "C18843D4DD9E0479D38A55E8C75E2201F0E93B6EF1F916EBAF3C4074D188945C7B9657F45269A1DAAB4A8FB6F63D0BEE");
+       }
+       
+
+       @Test
+       public void TestVector_07() {
+               runTest(1, "The quick brown fox jumps over the lazy dog",
+                       "E2901EDB76AA83F2D52FEA9A34EB2BC05EDFA9571C812620245BBEBA95FA2D82CBB5BAD93EB64D4B72B46635D565400B");
+       }
+       
+
+       @Test
+       public void TestVector_08() {
+               runTest(1, "The quick brown fox jumps over the lazy cog",
+                       "8B81CD9C1DEE8BCC642F8B1EA982CE79D15F50E66939FF34294E63D93AE3C610F9464FEFEF30297409B62231F028ABC0");
+       }
+       
+
+       @Test
+       public void TestVector_09() {
+               runTest(1, "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern",
+                       "A545E6319F6ACE0CEF62BCAAF5D488858751B96C2A488D5BE6EC63D50006C9D54DAD66168488F03B4A868D3BA610CCF8");
+       }
+       
+       @Test
+       public void TestVector_10() {
+               runTest(1, "Frank jagt im komplett verwahrlosten Taxi quer durch Bayern",
+                       "2BECB89DD55FC9F2F3384DF61D6240DDA54FC275D186A45A883C03AA873DDAF4FAD4744212B92D26054B92852DEA5F1D");
+       }
+       
+       @Test
+       public void TestVector_11() {
+               runTest(1, "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+                       "6283CE91DA8AF5091C7B06E1352DC947B9E3B89614807C04C43DA322321FBADAD3CCCABECB5C1B1B265432A6039121E1");
+       }
+
+       @Test
+       public void TestVector_12() {
+               runTest(1, "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamc0 laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+                       "5DCB7C4B27BA841688FB6A860E97A45256917533F63448CF666781EA4B5FAB20E1C746C8821099A915222E0D77624098");
+       }
+
+       //=======================================================================
+       // HELPER FUNCTIONS
+       //=======================================================================
+
+       private static final String HEX_CHARS = "0123456789ABCDEF";
+
+       private static void runTest(final int repetitions, final String test, final String expected) {
+               final String digest = getDigest(repetitions, test);
+               final boolean matches = digest.equalsIgnoreCase(expected);
+               System.out.printf("%s - %s\n", digest, matches ? "OK" : "Error!");
+               if(!matches) {
+                       m_success.compareAndSet(true, false);
+               }
+               assertTrue(matches);
+       }
+
+       private static String getDigest(final int repetitions, final String test) {
+               final MHash384 hash = new MHash384();
+               for(int i = 0; i < repetitions; ++i) {
+                       hash.update(test);
+               }
+               return bytesToHex(hash.getDigest());
+       }
+       
+       private static String bytesToHex(byte[] bytes) {
+               final char[] hexChars = new char[bytes.length * 2];
+               final char[] hexArray = HEX_CHARS.toCharArray();
+               for ( int j = 0; j < bytes.length; j++ ) {
+                       final int v = bytes[j] & 0xFF;
+                       hexChars[j * 2] = hexArray[v >>> 4];
+                       hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+               }
+               return new String(hexChars);
+       }
+}
diff --git a/testdata/testdata.xz b/testdata/testdata.xz
new file mode 100644 (file)
index 0000000..cd9122b
Binary files /dev/null and b/testdata/testdata.xz differ