From 7d3602807891e54673867524821a2fa4a9709cc3 Mon Sep 17 00:00:00 2001
From: Yann Collet <yann.collet.73@gmail.com>
Date: Fri, 12 Feb 2016 00:07:30 +0100
Subject: [PATCH] Integrate dictBuilder into libzstd

---
 dictBuilder/Makefile                     |    7 +-
 dictBuilder/dibcli.c                     |    8 +-
 dictBuilder/dibio.c                      |  281 ++++
 dictBuilder/dibio.h                      |   64 +
 dictBuilder/dictBuilder.h                |   94 --
 dictBuilder/dictionary                   |  Bin 0 -> 112640 bytes
 dictBuilder/divsufsort.c                 |  404 -----
 dictBuilder/divsufsort.h                 |  180 --
 dictBuilder/divsufsort_private.h         |  212 ---
 dictBuilder/lfs.h                        |   56 -
 dictBuilder/sssort.c                     |  844 ----------
 dictBuilder/trsort.c                     |  615 -------
 dictBuilder/utils.c                      |  381 -----
 lib/Makefile                             |    6 +-
 {dictBuilder => lib}/dictBuilder.c       |  354 ++--
 lib/dictBuilder.h                        |   67 +
 lib/dictBuilder_static.h                 |  104 ++
 lib/divsufsort.c                         | 1905 ++++++++++++++++++++++
 dictBuilder/config.h => lib/divsufsort.h |   72 +-
 lib/mem.h                                |   11 +-
 lib/zstd.h                               |    2 +-
 lib/zstd_compress.c                      |   78 +-
 lib/zstd_internal.h                      |   65 +-
 lib/zstd_static.h                        |    7 +-
 24 files changed, 2661 insertions(+), 3156 deletions(-)
 create mode 100644 dictBuilder/dibio.c
 create mode 100644 dictBuilder/dibio.h
 delete mode 100644 dictBuilder/dictBuilder.h
 create mode 100644 dictBuilder/dictionary
 delete mode 100644 dictBuilder/divsufsort.c
 delete mode 100644 dictBuilder/divsufsort.h
 delete mode 100644 dictBuilder/divsufsort_private.h
 delete mode 100644 dictBuilder/lfs.h
 delete mode 100644 dictBuilder/sssort.c
 delete mode 100644 dictBuilder/trsort.c
 delete mode 100644 dictBuilder/utils.c
 rename {dictBuilder => lib}/dictBuilder.c (72%)
 create mode 100644 lib/dictBuilder.h
 create mode 100644 lib/dictBuilder_static.h
 create mode 100644 lib/divsufsort.c
 rename dictBuilder/config.h => lib/divsufsort.h (52%)

diff --git a/dictBuilder/Makefile b/dictBuilder/Makefile
index e5a4f1aa7..949995253 100644
--- a/dictBuilder/Makefile
+++ b/dictBuilder/Makefile
@@ -1,6 +1,6 @@
 # ##########################################################################
 # Dict Builder - Makefile
-# Copyright (C) Yann Collet 2015
+# Copyright (C) Yann Collet 2016
 #
 # GPL v2 License
 #
@@ -19,8 +19,7 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #
 # You can contact the author at :
-#  - ZSTD source repository : http://code.google.com/p/zstd/
-#  - Public forum : https://groups.google.com/forum/#!forum/lz4c
+#  - ZSTD homepage : http://www.zstd.net/
 # ##########################################################################
 
 CPPFLAGS= -I../lib
@@ -47,7 +46,7 @@ default: dictBuilder
 
 all: dictBuilder
 
-dictBuilder: dictBuilder.c dibcli.c divsufsort.c sssort.c trsort.c $(ZSTDDIR)/huff0.c $(ZSTDDIR)/fse.c $(ZSTDDIR)/zstd_decompress.c
+dictBuilder: dibio.c dibcli.c $(ZSTDDIR)/dictBuilder.c $(ZSTDDIR)/huff0.c $(ZSTDDIR)/fse.c $(ZSTDDIR)/zstd_decompress.c $(ZSTDDIR)/zstd_compress.c $(ZSTDDIR)/divsufsort.c
 	$(CC)      $(FLAGS) $^ -o $@$(EXT)
 
 clean:
diff --git a/dictBuilder/dibcli.c b/dictBuilder/dibcli.c
index 8566c6245..a8009ae63 100644
--- a/dictBuilder/dibcli.c
+++ b/dictBuilder/dibcli.c
@@ -37,8 +37,8 @@
 #include <stdlib.h>   /* exit, calloc, free */
 #include <string.h>   /* strcmp, strlen */
 #include <stdio.h>    /* fprintf, getchar */
-
-#include "dictBuilder.h"
+#include "dibio.h"
+#include "zstd.h"     /* version numbers */
 
 
 /*-************************************
@@ -48,7 +48,7 @@
 #ifndef PROGRAM_VERSION
 #  define QUOTE(str) #str
 #  define EXP_Q(str) QUOTE(str)
-#  define PROGRAM_VERSION "v" EXP_Q(DiB_VERSION_MAJOR) "." EXP_Q(DiB_VERSION_MINOR) "." EXP_Q(DiB_VERSION_RELEASE)
+#  define PROGRAM_VERSION "v" EXP_Q(ZSTD_VERSION_MAJOR) "." EXP_Q(ZSTD_VERSION_MINOR) "." EXP_Q(ZSTD_VERSION_RELEASE)
 #endif
 #define AUTHOR "Yann Collet"
 #define WELCOME_MESSAGE "*** %s %s %i-bits, by %s ***\n", PROGRAM_DESCRIPTION, PROGRAM_VERSION, (int)(sizeof(void*)*8), AUTHOR
@@ -248,7 +248,7 @@ int main(int argCount, const char** argv)
 
     /* building ... */
     {
-        DiB_params_t param;
+        ZDICT_params_t param;
         param.selectivityLevel = selectionLevel;
         param.compressionLevel = cLevel;
         DiB_setNotificationLevel(g_displayLevel);
diff --git a/dictBuilder/dibio.c b/dictBuilder/dibio.c
new file mode 100644
index 000000000..679b6504c
--- /dev/null
+++ b/dictBuilder/dibio.c
@@ -0,0 +1,281 @@
+/*
+    dibio - I/O API for dictionary builder
+    Copyright (C) Yann Collet 2016
+
+    GPL v2 License
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+    You can contact the author at :
+    - zstd homepage : http://www.zstd.net/
+*/
+
+/*-**************************************
+*  Compiler Options
+****************************************/
+/* Disable some Visual warning messages */
+#ifdef _MSC_VER
+#  define _CRT_SECURE_NO_WARNINGS                /* fopen */
+#  pragma warning(disable : 4127)                /* disable: C4127: conditional expression is constant */
+#endif
+
+/* Unix Large Files support (>4GB) */
+#define _FILE_OFFSET_BITS 64
+#if (defined(__sun__) && (!defined(__LP64__)))   /* Sun Solaris 32-bits requires specific definitions */
+#  define _LARGEFILE_SOURCE
+#elif ! defined(__LP64__)                        /* No point defining Large file for 64 bit */
+#  define _LARGEFILE64_SOURCE
+#endif
+
+
+/*-*************************************
+*  Includes
+***************************************/
+#include <stdlib.h>         /* malloc, free */
+#include <string.h>         /* memset */
+#include <stdio.h>          /* fprintf, fopen, ftello64 */
+#include <sys/types.h>      /* stat64 */
+#include <sys/stat.h>       /* stat64 */
+#include <time.h>           /* clock */
+
+#include "mem.h"            /* read */
+#include "error_private.h"
+#include "dictBuilder_static.h"
+
+/*-*************************************
+*  Compiler specifics
+***************************************/
+#if !defined(S_ISREG)
+#  define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
+#endif
+
+
+/*-*************************************
+*  Constants
+***************************************/
+#define KB *(1 <<10)
+#define MB *(1 <<20)
+#define GB *(1U<<30)
+
+#define DICTLISTSIZE 10000
+#define MEMMULT 11
+static const size_t maxMemory = (sizeof(size_t) == 4) ? (2 GB - 64 MB) : ((size_t)(512 MB) << sizeof(size_t));
+
+#define NOISELENGTH 32
+#define PRIME1   2654435761U
+#define PRIME2   2246822519U
+
+#define MINRATIO 4
+static const U32 g_compressionLevel_default = 5;
+static const U32 g_selectivity_default = 9;
+static const size_t g_provision_entropySize = 200;
+static const size_t g_min_fast_dictContent = 192;
+
+
+/*-*************************************
+*  Console display
+***************************************/
+#define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
+#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
+static unsigned g_displayLevel = 0;   /* 0 : no display;   1: errors;   2: default;  4: full information */
+void DiB_setNotificationLevel(unsigned l) { g_displayLevel=l; ZDICT_setNotificationLevel(l); }
+
+void DiB_printHex(U32 dlevel, const void* ptr, size_t length)
+{
+    const BYTE* const b = (const BYTE*)ptr;
+    size_t u;
+    for (u=0; u<length; u++) {
+        BYTE c = b[u];
+        if (c<32 || c>126) c = '.';   /* non-printable char */
+        DISPLAYLEVEL(dlevel, "%c", c);
+    }
+}
+
+
+/*-*************************************
+*  Exceptions
+***************************************/
+#ifndef DEBUG
+#  define DEBUG 0
+#endif
+#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__);
+#define EXM_THROW(error, ...)                                             \
+{                                                                         \
+    DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \
+    DISPLAYLEVEL(1, "Error %i : ", error);                                \
+    DISPLAYLEVEL(1, __VA_ARGS__);                                         \
+    DISPLAYLEVEL(1, "\n");                                                \
+    exit(error);                                                          \
+}
+
+
+/* ********************************************************
+*  Helper functions
+**********************************************************/
+unsigned DiB_isError(size_t errorCode) { return ERR_isError(errorCode); }
+
+const char* DiB_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
+
+
+/* ********************************************************
+*  File related operations
+**********************************************************/
+static unsigned long long DiB_getFileSize(const char* infilename)
+{
+    int r;
+#if defined(_MSC_VER)
+    struct _stat64 statbuf;
+    r = _stat64(infilename, &statbuf);
+#else
+    struct stat statbuf;
+    r = stat(infilename, &statbuf);
+#endif
+    if (r || !S_ISREG(statbuf.st_mode)) return 0;   /* No good... */
+    return (unsigned long long)statbuf.st_size;
+}
+
+
+static unsigned long long DiB_getTotalFileSize(const char** fileNamesTable, unsigned nbFiles)
+{
+    unsigned long long total = 0;
+    unsigned n;
+    for (n=0; n<nbFiles; n++)
+        total += DiB_getFileSize(fileNamesTable[n]);
+    return total;
+}
+
+
+static void DiB_loadFiles(void* buffer, size_t bufferSize,
+                          size_t* fileSizes,
+                          const char** fileNamesTable, unsigned nbFiles)
+{
+    char* buff = (char*)buffer;
+    size_t pos = 0;
+    unsigned n;
+
+    for (n=0; n<nbFiles; n++) {
+        size_t readSize;
+        unsigned long long fileSize = DiB_getFileSize(fileNamesTable[n]);
+        FILE* f = fopen(fileNamesTable[n], "rb");
+        if (f==NULL) EXM_THROW(10, "impossible to open file %s", fileNamesTable[n]);
+        DISPLAYLEVEL(2, "Loading %s...       \r", fileNamesTable[n]);
+        if (fileSize > bufferSize-pos) fileSize = 0;  /* stop there, not enough memory to load all files */
+        readSize = fread(buff+pos, 1, (size_t)fileSize, f);
+        if (readSize != (size_t)fileSize) EXM_THROW(11, "could not read %s", fileNamesTable[n]);
+        pos += readSize;
+        fileSizes[n] = (size_t)fileSize;
+        fclose(f);
+    }
+}
+
+
+/*-********************************************************
+*  Dictionary training functions
+**********************************************************/
+static size_t DiB_findMaxMem(unsigned long long requiredMem)
+{
+    size_t step = 8 MB;
+    void* testmem = NULL;
+
+    requiredMem = (((requiredMem >> 23) + 1) << 23);
+    requiredMem += 2 * step;
+    if (requiredMem > maxMemory) requiredMem = maxMemory;
+
+    while (!testmem) {
+        requiredMem -= step;
+        testmem = malloc((size_t)requiredMem);
+    }
+
+    free(testmem);
+    return (size_t)(requiredMem - step);
+}
+
+
+static void DiB_fillNoise(void* buffer, size_t length)
+{
+    unsigned acc = PRIME1;
+    size_t p=0;;
+
+    for (p=0; p<length; p++) {
+        acc *= PRIME2;
+        ((unsigned char*)buffer)[p] = (unsigned char)(acc >> 21);
+    }
+}
+
+
+static void DiB_saveDict(const char* dictFileName,
+                         const void* buff, size_t buffSize)
+{
+    FILE* f;
+    size_t n;
+
+    f = fopen(dictFileName, "wb");
+    if (f==NULL) EXM_THROW(3, "cannot open %s ", dictFileName);
+
+    n = fwrite(buff, 1, buffSize, f);
+    if (n!=buffSize) EXM_THROW(4, "%s : write error", dictFileName)
+
+    n = (size_t)fclose(f);
+    if (n!=0) EXM_THROW(5, "%s : flush error", dictFileName)
+}
+
+
+int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
+                       const char** fileNamesTable, unsigned nbFiles,
+                       ZDICT_params_t params)
+{
+    void* srcBuffer;
+    size_t benchedSize;
+    size_t* fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t));
+    unsigned long long totalSizeToLoad = DiB_getTotalFileSize(fileNamesTable, nbFiles);
+    void* dictBuffer = malloc(maxDictSize);
+    size_t dictSize;
+    int result = 0;
+
+    /* init */
+    benchedSize = DiB_findMaxMem(totalSizeToLoad * MEMMULT) / MEMMULT;
+    if ((unsigned long long)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad;
+    if (benchedSize < totalSizeToLoad)
+        DISPLAYLEVEL(1, "Not enough memory; training on %u MB only...\n", (unsigned)(benchedSize >> 20));
+
+    /* Memory allocation & restrictions */
+    srcBuffer = malloc(benchedSize+NOISELENGTH);     /* + noise */
+    if ((!fileSizes) || (!srcBuffer) || (!dictBuffer)) EXM_THROW(12, "not enough memory for DiB_trainFiles");  /* should not happen */
+
+    /* Load input buffer */
+    DiB_loadFiles(srcBuffer, benchedSize, fileSizes, fileNamesTable, nbFiles);
+    DiB_fillNoise((char*)srcBuffer + benchedSize, NOISELENGTH);   /* guard band, for end of buffer condition */
+
+    /* call buffer version */
+    dictSize = ZDICT_trainFromBuffer_unsafe(dictBuffer, maxDictSize,
+                        srcBuffer, fileSizes, nbFiles,
+                        params);
+    if (ZDICT_isError(dictSize)) {
+        DISPLAYLEVEL(1, "dictionary training failed : %s", ZDICT_getErrorName(dictSize));   /* should not happen */
+        result = 1;
+        goto _cleanup;
+    }
+
+    /* save dict */
+    DISPLAYLEVEL(2, "Save dictionary of size %u into file %s \n", (U32)dictSize, dictFileName);
+    DiB_saveDict(dictFileName, dictBuffer, dictSize);
+
+    /* clean up */
+_cleanup:
+    free(srcBuffer);
+    free(dictBuffer);
+    free(fileSizes);
+    return result;
+}
diff --git a/dictBuilder/dibio.h b/dictBuilder/dibio.h
new file mode 100644
index 000000000..c9aee1fcd
--- /dev/null
+++ b/dictBuilder/dibio.h
@@ -0,0 +1,64 @@
+/*
+    dibio.h - I/O API for dictionary builder
+    Copyright (C) Yann Collet 2016
+
+    GPL v2 License
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+    You can contact the author at :
+    - zstd source repository : https://github.com/Cyan4973/zstd
+    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
+*/
+
+/* This library is designed for a single-threaded console application.
+*  It exit() and printf() into stderr when it encounters an error condition. */
+
+#ifndef DIBIO_H_003
+#define DIBIO_H_003
+
+
+/*-*************************************
+*  Dependencies
+***************************************/
+#include "dictBuilder_static.h"   /* ZDICT_params_t */
+
+
+/*-*************************************
+*  Public functions
+***************************************/
+/*! DiB_trainFromFiles() :
+    Train a dictionary from a set of files provided by `fileNamesTable`.
+    Resulting dictionary is written into file `dictFileName`.
+    `parameters` is optional and can be provided with values set to 0, meaning "default".
+    @return : 0 == ok. Any other : error.
+*/
+int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
+                       const char** fileNamesTable, unsigned nbFiles,
+                       ZDICT_params_t parameters);
+
+
+/*-*************************************
+*  Helper functions
+***************************************/
+/*! DiB_setNotificationLevel
+    Set amount of notification to be displayed on the console.
+    default initial value : 0 = no console notification.
+    Note : not thread-safe (use a global constant)
+*/
+void DiB_setNotificationLevel(unsigned l);
+
+
+#endif
diff --git a/dictBuilder/dictBuilder.h b/dictBuilder/dictBuilder.h
deleted file mode 100644
index a022583eb..000000000
--- a/dictBuilder/dictBuilder.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-    dictBuilder.h
-    Copyright (C) Yann Collet 2016
-
-    GPL v2 License
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-    You can contact the author at :
-    - zstd source repository : https://github.com/Cyan4973/zstd
-    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
-*/
-
-/* This library is designed for a single-threaded console application.
-*  It exit() and printf() into stderr when it encounters an error condition. */
-
-#ifndef DICTBUILDER_H_001
-#define DICTBUILDER_H_001
-
-/*-*************************************
-*  Version
-***************************************/
-#define DiB_VERSION_MAJOR    0    /* for breaking interface changes  */
-#define DiB_VERSION_MINOR    0    /* for new (non-breaking) interface capabilities */
-#define DiB_VERSION_RELEASE  1    /* for tweaks, bug-fixes, or development */
-#define DiB_VERSION_NUMBER  (DiB_VERSION_MAJOR *100*100 + DiB_VERSION_MINOR *100 + DiB_VERSION_RELEASE)
-unsigned DiB_versionNumber (void);
-
-
-/*-*************************************
-*  Public type
-***************************************/
-typedef struct {
-    unsigned selectivityLevel;   /* 0 means default; larger => bigger selection => larger dictionary */
-    unsigned compressionLevel;   /* 0 means default; target a specific zstd compression level */
-} DiB_params_t;
-
-
-/*-*************************************
-*  Public functions
-***************************************/
-/*! DiB_trainFromBuffer
-    Train a dictionary from a memory buffer @samplesBuffer
-    where @nbSamples samples have been stored concatenated.
-    Each sample size is provided into an orderly table @sampleSizes.
-    Resulting dictionary will be saved into @dictBuffer.
-    @parameters is optional and can be provided with 0 values to mean "default".
-    @result : size of dictionary stored into @dictBuffer (<= @dictBufferSize)
-              or an error code, which can be tested by DiB_isError().
-    note : DiB_trainFromBuffer() will send notifications into stderr if instructed to, using DiB_setNotificationLevel()
-*/
-size_t DiB_trainFromBuffer(void* dictBuffer, size_t dictBufferSize,
-                           const void* samplesBuffer, const size_t* sampleSizes, unsigned nbSamples,
-                           DiB_params_t parameters);
-
-
-/*! DiB_trainFromFiles
-    Train a dictionary from a set of files provided by @fileNamesTable
-    Resulting dictionary is written into file @dictFileName.
-    @parameters is optional and can be provided with 0 values.
-    @result : 0 == ok. Any other : error.
-*/
-int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
-                       const char** fileNamesTable, unsigned nbFiles,
-                       DiB_params_t parameters);
-
-
-/*-*************************************
-*  Helper functions
-***************************************/
-unsigned DiB_isError(size_t errorCode);
-const char* DiB_getErrorName(size_t errorCode);
-
-/*! DiB_setNotificationLevel
-    Set amount of notification to be displayed on the console.
-    default initial value : 0 = no console notification.
-    Note : not thread-safe (use a global constant)
-*/
-void DiB_setNotificationLevel(unsigned l);
-
-
-#endif
diff --git a/dictBuilder/dictionary b/dictBuilder/dictionary
new file mode 100644
index 0000000000000000000000000000000000000000..d6bf575c61f3b366de2c0aadadb0b484deaf377d
GIT binary patch
literal 112640
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
Xnn*h->!a-xKTVJ2qh8TvnyCK^?B0R|

literal 0
HcmV?d00001

diff --git a/dictBuilder/divsufsort.c b/dictBuilder/divsufsort.c
deleted file mode 100644
index 312813597..000000000
--- a/dictBuilder/divsufsort.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * divsufsort.c for libdivsufsort
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * 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.
- */
-
-/*- Compiler specifics -*/
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wshorten-64-to-32"
-#endif
-
-/*- Dependencies -*/
-#include "divsufsort_private.h"
-#ifdef _OPENMP
-# include <omp.h>
-#endif
-
-
-/*- Private Functions -*/
-
-/* Sorts suffixes of type B*. */
-static
-saidx_t
-sort_typeBstar(const sauchar_t *T, saidx_t *SA,
-               saidx_t *bucket_A, saidx_t *bucket_B,
-               saidx_t n) {
-  saidx_t *PAb, *ISAb, *buf;
-#ifdef _OPENMP
-  saidx_t *curbuf;
-  saidx_t l;
-#endif
-  saidx_t i, j, k, t, m, bufsize;
-  saint_t c0, c1;
-#ifdef _OPENMP
-  saint_t d0, d1;
-  int tmp;
-#endif
-
-  /* Initialize bucket arrays. */
-  for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; }
-  for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; }
-
-  /* Count the number of occurrences of the first one or two characters of each
-     type A, B and B* suffix. Moreover, store the beginning position of all
-     type B* suffixes into the array SA. */
-  for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) {
-    /* type A suffix. */
-    do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1));
-    if(0 <= i) {
-      /* type B* suffix. */
-      ++BUCKET_BSTAR(c0, c1);
-      SA[--m] = i;
-      /* type B suffix. */
-      for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) {
-        ++BUCKET_B(c0, c1);
-      }
-    }
-  }
-  m = n - m;
-/*
-note:
-  A type B* suffix is lexicographically smaller than a type B suffix that
-  begins with the same first two characters.
-*/
-
-  /* Calculate the index of start/end point of each bucket. */
-  for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) {
-    t = i + BUCKET_A(c0);
-    BUCKET_A(c0) = i + j; /* start point */
-    i = t + BUCKET_B(c0, c0);
-    for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) {
-      j += BUCKET_BSTAR(c0, c1);
-      BUCKET_BSTAR(c0, c1) = j; /* end point */
-      i += BUCKET_B(c0, c1);
-    }
-  }
-
-  if(0 < m) {
-    /* Sort the type B* suffixes by their first two characters. */
-    PAb = SA + n - m; ISAb = SA + m;
-    for(i = m - 2; 0 <= i; --i) {
-      t = PAb[i], c0 = T[t], c1 = T[t + 1];
-      SA[--BUCKET_BSTAR(c0, c1)] = i;
-    }
-    t = PAb[m - 1], c0 = T[t], c1 = T[t + 1];
-    SA[--BUCKET_BSTAR(c0, c1)] = m - 1;
-
-    /* Sort the type B* substrings using sssort. */
-#ifdef _OPENMP
-    tmp = omp_get_max_threads();
-    buf = SA + m, bufsize = (n - (2 * m)) / tmp;
-    c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m;
-#pragma omp parallel default(shared) private(curbuf, k, l, d0, d1, tmp)
-    {
-      tmp = omp_get_thread_num();
-      curbuf = buf + tmp * bufsize;
-      k = 0;
-      for(;;) {
-        #pragma omp critical(sssort_lock)
-        {
-          if(0 < (l = j)) {
-            d0 = c0, d1 = c1;
-            do {
-              k = BUCKET_BSTAR(d0, d1);
-              if(--d1 <= d0) {
-                d1 = ALPHABET_SIZE - 1;
-                if(--d0 < 0) { break; }
-              }
-            } while(((l - k) <= 1) && (0 < (l = k)));
-            c0 = d0, c1 = d1, j = k;
-          }
-        }
-        if(l == 0) { break; }
-        sssort(T, PAb, SA + k, SA + l,
-               curbuf, bufsize, 2, n, *(SA + k) == (m - 1));
-      }
-    }
-#else
-    buf = SA + m, bufsize = n - (2 * m);
-    for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
-      for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
-        i = BUCKET_BSTAR(c0, c1);
-        if(1 < (j - i)) {
-          sssort(T, PAb, SA + i, SA + j,
-                 buf, bufsize, 2, n, *(SA + i) == (m - 1));
-        }
-      }
-    }
-#endif
-
-    /* Compute ranks of type B* substrings. */
-    for(i = m - 1; 0 <= i; --i) {
-      if(0 <= SA[i]) {
-        j = i;
-        do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i]));
-        SA[i + 1] = i - j;
-        if(i <= 0) { break; }
-      }
-      j = i;
-      do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0);
-      ISAb[SA[i]] = j;
-    }
-
-    /* Construct the inverse suffix array of type B* suffixes using trsort. */
-    trsort(ISAb, SA, m, 1);
-
-    /* Set the sorted order of tyoe B* suffixes. */
-    for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {
-      for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }
-      if(0 <= i) {
-        t = i;
-        for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { }
-        SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t;
-      }
-    }
-
-    /* Calculate the index of start/end point of each bucket. */
-    BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */
-    for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) {
-      i = BUCKET_A(c0 + 1) - 1;
-      for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) {
-        t = i - BUCKET_B(c0, c1);
-        BUCKET_B(c0, c1) = i; /* end point */
-
-        /* Move all type B* suffixes to the correct position. */
-        for(i = t, j = BUCKET_BSTAR(c0, c1);
-            j <= k;
-            --i, --k) { SA[i] = SA[k]; }
-      }
-      BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */
-      BUCKET_B(c0, c0) = i; /* end point */
-    }
-  }
-
-  return m;
-}
-
-/* Constructs the suffix array by using the sorted order of type B* suffixes. */
-static
-void
-construct_SA(const sauchar_t *T, saidx_t *SA,
-             saidx_t *bucket_A, saidx_t *bucket_B,
-             saidx_t n, saidx_t m) {
-  saidx_t *i, *j, *k;
-  saidx_t s;
-  saint_t c0, c1, c2;
-
-  if(0 < m) {
-    /* Construct the sorted order of type B suffixes by using
-       the sorted order of type B* suffixes. */
-    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
-      /* Scan the suffix array from right to left. */
-      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
-          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
-          i <= j;
-          --j) {
-        if(0 < (s = *j)) {
-          assert(T[s] == c1);
-          assert(((s + 1) < n) && (T[s] <= T[s + 1]));
-          assert(T[s - 1] <= T[s]);
-          *j = ~s;
-          c0 = T[--s];
-          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
-          if(c0 != c2) {
-            if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
-            k = SA + BUCKET_B(c2 = c0, c1);
-          }
-          assert(k < j);
-          *k-- = s;
-        } else {
-          assert(((s == 0) && (T[s] == c1)) || (s < 0));
-          *j = ~s;
-        }
-      }
-    }
-  }
-
-  /* Construct the suffix array by using
-     the sorted order of type B suffixes. */
-  k = SA + BUCKET_A(c2 = T[n - 1]);
-  *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1);
-  /* Scan the suffix array from left to right. */
-  for(i = SA, j = SA + n; i < j; ++i) {
-    if(0 < (s = *i)) {
-      assert(T[s - 1] >= T[s]);
-      c0 = T[--s];
-      if((s == 0) || (T[s - 1] < c0)) { s = ~s; }
-      if(c0 != c2) {
-        BUCKET_A(c2) = k - SA;
-        k = SA + BUCKET_A(c2 = c0);
-      }
-      assert(i < k);
-      *k++ = s;
-    } else {
-      assert(s < 0);
-      *i = ~s;
-    }
-  }
-}
-
-/* Constructs the burrows-wheeler transformed string directly
-   by using the sorted order of type B* suffixes. */
-static
-saidx_t
-construct_BWT(const sauchar_t *T, saidx_t *SA,
-              saidx_t *bucket_A, saidx_t *bucket_B,
-              saidx_t n, saidx_t m) {
-  saidx_t *i, *j, *k, *orig;
-  saidx_t s;
-  saint_t c0, c1, c2;
-
-  if(0 < m) {
-    /* Construct the sorted order of type B suffixes by using
-       the sorted order of type B* suffixes. */
-    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
-      /* Scan the suffix array from right to left. */
-      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
-          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
-          i <= j;
-          --j) {
-        if(0 < (s = *j)) {
-          assert(T[s] == c1);
-          assert(((s + 1) < n) && (T[s] <= T[s + 1]));
-          assert(T[s - 1] <= T[s]);
-          c0 = T[--s];
-          *j = ~((saidx_t)c0);
-          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
-          if(c0 != c2) {
-            if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
-            k = SA + BUCKET_B(c2 = c0, c1);
-          }
-          assert(k < j);
-          *k-- = s;
-        } else if(s != 0) {
-          *j = ~s;
-#ifndef NDEBUG
-        } else {
-          assert(T[s] == c1);
-#endif
-        }
-      }
-    }
-  }
-
-  /* Construct the BWTed string by using
-     the sorted order of type B suffixes. */
-  k = SA + BUCKET_A(c2 = T[n - 1]);
-  *k++ = (T[n - 2] < c2) ? ~((saidx_t)T[n - 2]) : (n - 1);
-  /* Scan the suffix array from left to right. */
-  for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
-    if(0 < (s = *i)) {
-      assert(T[s - 1] >= T[s]);
-      c0 = T[--s];
-      *i = c0;
-      if((0 < s) && (T[s - 1] < c0)) { s = ~((saidx_t)T[s - 1]); }
-      if(c0 != c2) {
-        BUCKET_A(c2) = k - SA;
-        k = SA + BUCKET_A(c2 = c0);
-      }
-      assert(i < k);
-      *k++ = s;
-    } else if(s != 0) {
-      *i = ~s;
-    } else {
-      orig = i;
-    }
-  }
-
-  return orig - SA;
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/*- Function -*/
-
-saint_t
-divsufsort(const sauchar_t *T, saidx_t *SA, saidx_t n) {
-  saidx_t *bucket_A, *bucket_B;
-  saidx_t m;
-  saint_t err = 0;
-
-  /* Check arguments. */
-  if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }
-  else if(n == 0) { return 0; }
-  else if(n == 1) { SA[0] = 0; return 0; }
-  else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; }
-
-  bucket_A = (saidx_t *)malloc(BUCKET_A_SIZE * sizeof(saidx_t));
-  bucket_B = (saidx_t *)malloc(BUCKET_B_SIZE * sizeof(saidx_t));
-
-  /* Suffixsort. */
-  if((bucket_A != NULL) && (bucket_B != NULL)) {
-    m = sort_typeBstar(T, SA, bucket_A, bucket_B, n);
-    construct_SA(T, SA, bucket_A, bucket_B, n, m);
-  } else {
-    err = -2;
-  }
-
-  free(bucket_B);
-  free(bucket_A);
-
-  return err;
-}
-
-saidx_t
-divbwt(const sauchar_t *T, sauchar_t *U, saidx_t *A, saidx_t n) {
-  saidx_t *B;
-  saidx_t *bucket_A, *bucket_B;
-  saidx_t m, pidx, i;
-
-  /* Check arguments. */
-  if((T == NULL) || (U == NULL) || (n < 0)) { return -1; }
-  else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
-
-  if((B = A) == NULL) { B = (saidx_t *)malloc((size_t)(n + 1) * sizeof(saidx_t)); }
-  bucket_A = (saidx_t *)malloc(BUCKET_A_SIZE * sizeof(saidx_t));
-  bucket_B = (saidx_t *)malloc(BUCKET_B_SIZE * sizeof(saidx_t));
-
-  /* Burrows-Wheeler Transform. */
-  if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) {
-    m = sort_typeBstar(T, B, bucket_A, bucket_B, n);
-    pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m);
-
-    /* Copy to output string. */
-    U[0] = T[n - 1];
-    for(i = 0; i < pidx; ++i) { U[i + 1] = (sauchar_t)B[i]; }
-    for(i += 1; i < n; ++i) { U[i] = (sauchar_t)B[i]; }
-    pidx += 1;
-  } else {
-    pidx = -2;
-  }
-
-  free(bucket_B);
-  free(bucket_A);
-  if(A == NULL) { free(B); }
-
-  return pidx;
-}
-
-const char *
-divsufsort_version(void) {
-  return PROJECT_VERSION_FULL;
-}
diff --git a/dictBuilder/divsufsort.h b/dictBuilder/divsufsort.h
deleted file mode 100644
index 6d3e64870..000000000
--- a/dictBuilder/divsufsort.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * divsufsort.h for libdivsufsort
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * 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 _DIVSUFSORT_H
-#define _DIVSUFSORT_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#include <inttypes.h>
-
-#ifndef DIVSUFSORT_API
-# ifdef DIVSUFSORT_BUILD_DLL
-#  define DIVSUFSORT_API 
-# else
-#  define DIVSUFSORT_API 
-# endif
-#endif
-
-/*- Datatypes -*/
-#ifndef SAUCHAR_T
-#define SAUCHAR_T
-typedef uint8_t sauchar_t;
-#endif /* SAUCHAR_T */
-#ifndef SAINT_T
-#define SAINT_T
-typedef int32_t saint_t;
-#endif /* SAINT_T */
-#ifndef SAIDX_T
-#define SAIDX_T
-typedef int32_t saidx_t;
-#endif /* SAIDX_T */
-#ifndef PRIdSAINT_T
-#define PRIdSAINT_T PRId32
-#endif /* PRIdSAINT_T */
-#ifndef PRIdSAIDX_T
-#define PRIdSAIDX_T PRId32
-#endif /* PRIdSAIDX_T */
-
-
-/*- Prototypes -*/
-
-/**
- * Constructs the suffix array of a given string.
- * @param T[0..n-1] The input string.
- * @param SA[0..n-1] The output array of suffixes.
- * @param n The length of the given string.
- * @return 0 if no error occurred, -1 or -2 otherwise.
- */
-DIVSUFSORT_API
-saint_t
-divsufsort(const sauchar_t *T, saidx_t *SA, saidx_t n);
-
-/**
- * Constructs the burrows-wheeler transformed string of a given string.
- * @param T[0..n-1] The input string.
- * @param U[0..n-1] The output string. (can be T)
- * @param A[0..n-1] The temporary array. (can be NULL)
- * @param n The length of the given string.
- * @return The primary index if no error occurred, -1 or -2 otherwise.
- */
-DIVSUFSORT_API
-saidx_t
-divbwt(const sauchar_t *T, sauchar_t *U, saidx_t *A, saidx_t n);
-
-/**
- * Returns the version of the divsufsort library.
- * @return The version number string.
- */
-DIVSUFSORT_API
-const char *
-divsufsort_version(void);
-
-
-/**
- * Constructs the burrows-wheeler transformed string of a given string and suffix array.
- * @param T[0..n-1] The input string.
- * @param U[0..n-1] The output string. (can be T)
- * @param SA[0..n-1] The suffix array. (can be NULL)
- * @param n The length of the given string.
- * @param idx The output primary index.
- * @return 0 if no error occurred, -1 or -2 otherwise.
- */
-DIVSUFSORT_API
-saint_t
-bw_transform(const sauchar_t *T, sauchar_t *U,
-             saidx_t *SA /* can NULL */,
-             saidx_t n, saidx_t *idx);
-
-/**
- * Inverse BW-transforms a given BWTed string.
- * @param T[0..n-1] The input string.
- * @param U[0..n-1] The output string. (can be T)
- * @param A[0..n-1] The temporary array. (can be NULL)
- * @param n The length of the given string.
- * @param idx The primary index.
- * @return 0 if no error occurred, -1 or -2 otherwise.
- */
-DIVSUFSORT_API
-saint_t
-inverse_bw_transform(const sauchar_t *T, sauchar_t *U,
-                     saidx_t *A /* can NULL */,
-                     saidx_t n, saidx_t idx);
-
-/**
- * Checks the correctness of a given suffix array.
- * @param T[0..n-1] The input string.
- * @param SA[0..n-1] The input suffix array.
- * @param n The length of the given string.
- * @param verbose The verbose mode.
- * @return 0 if no error occurred.
- */
-DIVSUFSORT_API
-saint_t
-sufcheck(const sauchar_t *T, const saidx_t *SA, saidx_t n, saint_t verbose);
-
-/**
- * Search for the pattern P in the string T.
- * @param T[0..Tsize-1] The input string.
- * @param Tsize The length of the given string.
- * @param P[0..Psize-1] The input pattern string.
- * @param Psize The length of the given pattern string.
- * @param SA[0..SAsize-1] The input suffix array.
- * @param SAsize The length of the given suffix array.
- * @param idx The output index.
- * @return The count of matches if no error occurred, -1 otherwise.
- */
-DIVSUFSORT_API
-saidx_t
-sa_search(const sauchar_t *T, saidx_t Tsize,
-          const sauchar_t *P, saidx_t Psize,
-          const saidx_t *SA, saidx_t SAsize,
-          saidx_t *left);
-
-/**
- * Search for the character c in the string T.
- * @param T[0..Tsize-1] The input string.
- * @param Tsize The length of the given string.
- * @param SA[0..SAsize-1] The input suffix array.
- * @param SAsize The length of the given suffix array.
- * @param c The input character.
- * @param idx The output index.
- * @return The count of matches if no error occurred, -1 otherwise.
- */
-DIVSUFSORT_API
-saidx_t
-sa_simplesearch(const sauchar_t *T, saidx_t Tsize,
-                const saidx_t *SA, saidx_t SAsize,
-                saint_t c, saidx_t *left);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-#endif /* _DIVSUFSORT_H */
diff --git a/dictBuilder/divsufsort_private.h b/dictBuilder/divsufsort_private.h
deleted file mode 100644
index 0a18f6d28..000000000
--- a/dictBuilder/divsufsort_private.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * divsufsort_private.h for libdivsufsort
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * 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 _DIVSUFSORT_PRIVATE_H
-#define _DIVSUFSORT_PRIVATE_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* *************************
-*  Includes
-***************************/
-#include <assert.h>
-#include <stdlib.h>   /* unconditional */
-#include <stdio.h>
-#include "config.h"   /* unconditional */
-
-
-#if HAVE_STRING_H
-# include <string.h>
-#endif
-#if HAVE_MEMORY_H
-# include <memory.h>
-#endif
-#if HAVE_STDDEF_H
-# include <stddef.h>
-#endif
-#if HAVE_STRINGS_H
-# ifdef _WIN32
-#  include <string.h>
-# else
-#  include <strings.h>
-# endif
-#endif
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-#  include <stdint.h>
-# endif
-#endif
-#if defined(BUILD_DIVSUFSORT64)
-# include "divsufsort64.h"
-# ifndef SAIDX_T
-#  define SAIDX_T
-#  define saidx_t saidx64_t
-# endif /* SAIDX_T */
-# ifndef PRIdSAIDX_T
-#  define PRIdSAIDX_T PRIdSAIDX64_T
-# endif /* PRIdSAIDX_T */
-# define divsufsort divsufsort64
-# define divbwt divbwt64
-# define divsufsort_version divsufsort64_version
-# define bw_transform bw_transform64
-# define inverse_bw_transform inverse_bw_transform64
-# define sufcheck sufcheck64
-# define sa_search sa_search64
-# define sa_simplesearch sa_simplesearch64
-# define sssort sssort64
-# define trsort trsort64
-#else
-# include "divsufsort.h"
-#endif
-
-
-/*- Constants -*/
-#if !defined(UINT8_MAX)
-# define UINT8_MAX (255)
-#endif /* UINT8_MAX */
-#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1)
-# undef ALPHABET_SIZE
-#endif
-#if !defined(ALPHABET_SIZE)
-# define ALPHABET_SIZE (UINT8_MAX + 1)
-#endif
-/* for divsufsort.c */
-#define BUCKET_A_SIZE (ALPHABET_SIZE)
-#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)
-/* for sssort.c */
-#if defined(SS_INSERTIONSORT_THRESHOLD)
-# if SS_INSERTIONSORT_THRESHOLD < 1
-#  undef SS_INSERTIONSORT_THRESHOLD
-#  define SS_INSERTIONSORT_THRESHOLD (1)
-# endif
-#else
-# define SS_INSERTIONSORT_THRESHOLD (8)
-#endif
-#if defined(SS_BLOCKSIZE)
-# if SS_BLOCKSIZE < 0
-#  undef SS_BLOCKSIZE
-#  define SS_BLOCKSIZE (0)
-# elif 32768 <= SS_BLOCKSIZE
-#  undef SS_BLOCKSIZE
-#  define SS_BLOCKSIZE (32767)
-# endif
-#else
-# define SS_BLOCKSIZE (1024)
-#endif
-/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */
-#if SS_BLOCKSIZE == 0
-# if defined(BUILD_DIVSUFSORT64)
-#  define SS_MISORT_STACKSIZE (96)
-# else
-#  define SS_MISORT_STACKSIZE (64)
-# endif
-#elif SS_BLOCKSIZE <= 4096
-# define SS_MISORT_STACKSIZE (16)
-#else
-# define SS_MISORT_STACKSIZE (24)
-#endif
-#if defined(BUILD_DIVSUFSORT64)
-# define SS_SMERGE_STACKSIZE (64)
-#else
-# define SS_SMERGE_STACKSIZE (32)
-#endif
-/* for trsort.c */
-#define TR_INSERTIONSORT_THRESHOLD (8)
-#if defined(BUILD_DIVSUFSORT64)
-# define TR_STACKSIZE (96)
-#else
-# define TR_STACKSIZE (64)
-#endif
-
-
-/*- Macros -*/
-#ifndef SWAP
-# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0)
-#endif /* SWAP */
-#ifndef MIN
-# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
-#endif /* MIN */
-#ifndef MAX
-# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
-#endif /* MAX */
-#define STACK_PUSH(_a, _b, _c, _d)\
-  do {\
-    assert(ssize < STACK_SIZE);\
-    stack[ssize].a = (_a), stack[ssize].b = (_b),\
-    stack[ssize].c = (_c), stack[ssize++].d = (_d);\
-  } while(0)
-#define STACK_PUSH5(_a, _b, _c, _d, _e)\
-  do {\
-    assert(ssize < STACK_SIZE);\
-    stack[ssize].a = (_a), stack[ssize].b = (_b),\
-    stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\
-  } while(0)
-#define STACK_POP(_a, _b, _c, _d)\
-  do {\
-    assert(0 <= ssize);\
-    if(ssize == 0) { return; }\
-    (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
-    (_c) = stack[ssize].c, (_d) = stack[ssize].d;\
-  } while(0)
-#define STACK_POP5(_a, _b, _c, _d, _e)\
-  do {\
-    assert(0 <= ssize);\
-    if(ssize == 0) { return; }\
-    (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
-    (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\
-  } while(0)
-/* for divsufsort.c */
-#define BUCKET_A(_c0) bucket_A[(_c0)]
-#if ALPHABET_SIZE == 256
-#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])
-#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])
-#else
-#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])
-#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])
-#endif
-
-
-/*- Private Prototypes -*/
-/* sssort.c */
-void
-sssort(const sauchar_t *Td, const saidx_t *PA,
-       saidx_t *first, saidx_t *last,
-       saidx_t *buf, saidx_t bufsize,
-       saidx_t depth, saidx_t n, saint_t lastsuffix);
-/* trsort.c */
-void
-trsort(saidx_t *ISA, saidx_t *SA, saidx_t n, saidx_t depth);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-#endif /* _DIVSUFSORT_PRIVATE_H */
diff --git a/dictBuilder/lfs.h b/dictBuilder/lfs.h
deleted file mode 100644
index 7ef88f0b4..000000000
--- a/dictBuilder/lfs.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * lfs.h for libdivsufsort
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * 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 _LFS_H
-#define _LFS_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#ifndef __STRICT_ANSI__
-# define LFS_OFF_T off_t
-# define LFS_FOPEN fopen
-# define LFS_FTELL ftello
-# define LFS_FSEEK fseeko
-# define LFS_PRId  PRIdMAX
-#else
-# define LFS_OFF_T long
-# define LFS_FOPEN fopen
-# define LFS_FTELL ftell
-# define LFS_FSEEK fseek
-# define LFS_PRId "ld"
-#endif
-#ifndef PRIdOFF_T
-# define PRIdOFF_T LFS_PRId
-#endif
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-#endif /* _LFS_H */
diff --git a/dictBuilder/sssort.c b/dictBuilder/sssort.c
deleted file mode 100644
index 07cb5bd1b..000000000
--- a/dictBuilder/sssort.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- * sssort.c for libdivsufsort
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * 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.
- */
-
-/*- Compiler specifics -*/
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wshorten-64-to-32"
-#endif
-
-#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-/* inline is defined */
-#elif defined(_MSC_VER)
-#  define inline __inline
-#else
-#  define inline /* disable inline */
-#endif
-
-#ifdef _MSC_VER    /* Visual Studio */
-#  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
-#  define FORCE_INLINE static __forceinline
-#else
-#  if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
-#    ifdef __GNUC__
-#      define FORCE_INLINE static inline __attribute__((always_inline))
-#    else
-#      define FORCE_INLINE static inline
-#    endif
-#  else
-#    define FORCE_INLINE static
-#  endif /* __STDC_VERSION__ */
-#endif
-
-/*- Dependencies -*/
-#include "divsufsort_private.h"
-
-
-/*- Private Functions -*/
-
-static const saint_t lg_table[256]= {
- -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-};
-
-#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
-
-static INLINE
-saint_t
-ss_ilg(saidx_t n) {
-#if SS_BLOCKSIZE == 0
-# if defined(BUILD_DIVSUFSORT64)
-  return (n >> 32) ?
-          ((n >> 48) ?
-            ((n >> 56) ?
-              56 + lg_table[(n >> 56) & 0xff] :
-              48 + lg_table[(n >> 48) & 0xff]) :
-            ((n >> 40) ?
-              40 + lg_table[(n >> 40) & 0xff] :
-              32 + lg_table[(n >> 32) & 0xff])) :
-          ((n & 0xffff0000) ?
-            ((n & 0xff000000) ?
-              24 + lg_table[(n >> 24) & 0xff] :
-              16 + lg_table[(n >> 16) & 0xff]) :
-            ((n & 0x0000ff00) ?
-               8 + lg_table[(n >>  8) & 0xff] :
-               0 + lg_table[(n >>  0) & 0xff]));
-# else
-  return (n & 0xffff0000) ?
-          ((n & 0xff000000) ?
-            24 + lg_table[(n >> 24) & 0xff] :
-            16 + lg_table[(n >> 16) & 0xff]) :
-          ((n & 0x0000ff00) ?
-             8 + lg_table[(n >>  8) & 0xff] :
-             0 + lg_table[(n >>  0) & 0xff]);
-# endif
-#elif SS_BLOCKSIZE < 256
-  return lg_table[n];
-#else
-  return (n & 0xff00) ?
-          8 + lg_table[(n >> 8) & 0xff] :
-          0 + lg_table[(n >> 0) & 0xff];
-#endif
-}
-
-#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
-
-#if SS_BLOCKSIZE != 0
-
-static const saint_t sqq_table[256] = {
-  0,  16,  22,  27,  32,  35,  39,  42,  45,  48,  50,  53,  55,  57,  59,  61,
- 64,  65,  67,  69,  71,  73,  75,  76,  78,  80,  81,  83,  84,  86,  87,  89,
- 90,  91,  93,  94,  96,  97,  98,  99, 101, 102, 103, 104, 106, 107, 108, 109,
-110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
-128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
-143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155,
-156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
-169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180,
-181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191,
-192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201,
-202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
-212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221,
-221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230,
-230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
-239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
-247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
-};
-
-static INLINE
-saidx_t
-ss_isqrt(saidx_t x) {
-  saidx_t y, e;
-
-  if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; }
-  e = (x & 0xffff0000) ?
-        ((x & 0xff000000) ?
-          24 + lg_table[(x >> 24) & 0xff] :
-          16 + lg_table[(x >> 16) & 0xff]) :
-        ((x & 0x0000ff00) ?
-           8 + lg_table[(x >>  8) & 0xff] :
-           0 + lg_table[(x >>  0) & 0xff]);
-
-  if(e >= 16) {
-    y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7);
-    if(e >= 24) { y = (y + 1 + x / y) >> 1; }
-    y = (y + 1 + x / y) >> 1;
-  } else if(e >= 8) {
-    y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1;
-  } else {
-    return sqq_table[x] >> 4;
-  }
-
-  return (x < (y * y)) ? y - 1 : y;
-}
-
-#endif /* SS_BLOCKSIZE != 0 */
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Compares two suffixes. */
-static INLINE
-saint_t
-ss_compare(const sauchar_t *T,
-           const saidx_t *p1, const saidx_t *p2,
-           saidx_t depth) {
-  const sauchar_t *U1, *U2, *U1n, *U2n;
-
-  for(U1 = T + depth + *p1,
-      U2 = T + depth + *p2,
-      U1n = T + *(p1 + 1) + 2,
-      U2n = T + *(p2 + 1) + 2;
-      (U1 < U1n) && (U2 < U2n) && (*U1 == *U2);
-      ++U1, ++U2) {
-  }
-
-  return U1 < U1n ?
-        (U2 < U2n ? *U1 - *U2 : 1) :
-        (U2 < U2n ? -1 : 0);
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1)
-
-/* Insertionsort for small size groups */
-static
-void
-ss_insertionsort(const sauchar_t *T, const saidx_t *PA,
-                 saidx_t *first, saidx_t *last, saidx_t depth) {
-  saidx_t *i, *j;
-  saidx_t t;
-  saint_t r;
-
-  for(i = last - 2; first <= i; --i) {
-    for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) {
-      do { *(j - 1) = *j; } while((++j < last) && (*j < 0));
-      if(last <= j) { break; }
-    }
-    if(r == 0) { *j = ~*j; }
-    *(j - 1) = t;
-  }
-}
-
-#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */
-
-
-/*---------------------------------------------------------------------------*/
-
-#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
-
-static INLINE
-void
-ss_fixdown(const sauchar_t *Td, const saidx_t *PA,
-           saidx_t *SA, saidx_t i, saidx_t size) {
-  saidx_t j, k;
-  saidx_t v;
-  saint_t c, d, e;
-
-  for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
-    d = Td[PA[SA[k = j++]]];
-    if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; }
-    if(d <= c) { break; }
-  }
-  SA[i] = v;
-}
-
-/* Simple top-down heapsort. */
-static
-void
-ss_heapsort(const sauchar_t *Td, const saidx_t *PA, saidx_t *SA, saidx_t size) {
-  saidx_t i, m;
-  saidx_t t;
-
-  m = size;
-  if((size % 2) == 0) {
-    m--;
-    if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); }
-  }
-
-  for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); }
-  if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); }
-  for(i = m - 1; 0 < i; --i) {
-    t = SA[0], SA[0] = SA[i];
-    ss_fixdown(Td, PA, SA, 0, i);
-    SA[i] = t;
-  }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Returns the median of three elements. */
-static INLINE
-saidx_t *
-ss_median3(const sauchar_t *Td, const saidx_t *PA,
-           saidx_t *v1, saidx_t *v2, saidx_t *v3) {
-  saidx_t *t;
-  if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); }
-  if(Td[PA[*v2]] > Td[PA[*v3]]) {
-    if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; }
-    else { return v3; }
-  }
-  return v2;
-}
-
-/* Returns the median of five elements. */
-static INLINE
-saidx_t *
-ss_median5(const sauchar_t *Td, const saidx_t *PA,
-           saidx_t *v1, saidx_t *v2, saidx_t *v3, saidx_t *v4, saidx_t *v5) {
-  saidx_t *t;
-  if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); }
-  if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); }
-  if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); }
-  if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); }
-  if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); }
-  if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; }
-  return v3;
-}
-
-/* Returns the pivot element. */
-static INLINE
-saidx_t *
-ss_pivot(const sauchar_t *Td, const saidx_t *PA, saidx_t *first, saidx_t *last) {
-  saidx_t *middle;
-  saidx_t t;
-
-  t = last - first;
-  middle = first + t / 2;
-
-  if(t <= 512) {
-    if(t <= 32) {
-      return ss_median3(Td, PA, first, middle, last - 1);
-    } else {
-      t >>= 2;
-      return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1);
-    }
-  }
-  t >>= 3;
-  first  = ss_median3(Td, PA, first, first + t, first + (t << 1));
-  middle = ss_median3(Td, PA, middle - t, middle, middle + t);
-  last   = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1);
-  return ss_median3(Td, PA, first, middle, last);
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Binary partition for substrings. */
-static INLINE
-saidx_t *
-ss_partition(const saidx_t *PA,
-                    saidx_t *first, saidx_t *last, saidx_t depth) {
-  saidx_t *a, *b;
-  saidx_t t;
-  for(a = first - 1, b = last;;) {
-    for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; }
-    for(; (a < --b) && ((PA[*b] + depth) <  (PA[*b + 1] + 1));) { }
-    if(b <= a) { break; }
-    t = ~*b;
-    *b = *a;
-    *a = t;
-  }
-  if(first < a) { *first = ~*first; }
-  return a;
-}
-
-/* Multikey introsort for medium size groups. */
-static
-void
-ss_mintrosort(const sauchar_t *T, const saidx_t *PA,
-              saidx_t *first, saidx_t *last,
-              saidx_t depth) {
-#define STACK_SIZE SS_MISORT_STACKSIZE
-  struct { saidx_t *a, *b, c; saint_t d; } stack[STACK_SIZE];
-  const sauchar_t *Td;
-  saidx_t *a, *b, *c, *d, *e, *f;
-  saidx_t s, t;
-  saint_t ssize;
-  saint_t limit;
-  saint_t v, x = 0;
-
-  for(ssize = 0, limit = ss_ilg(last - first);;) {
-
-    if((last - first) <= SS_INSERTIONSORT_THRESHOLD) {
-#if 1 < SS_INSERTIONSORT_THRESHOLD
-      if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); }
-#endif
-      STACK_POP(first, last, depth, limit);
-      continue;
-    }
-
-    Td = T + depth;
-    if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); }
-    if(limit < 0) {
-      for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) {
-        if((x = Td[PA[*a]]) != v) {
-          if(1 < (a - first)) { break; }
-          v = x;
-          first = a;
-        }
-      }
-      if(Td[PA[*first] - 1] < v) {
-        first = ss_partition(PA, first, a, depth);
-      }
-      if((a - first) <= (last - a)) {
-        if(1 < (a - first)) {
-          STACK_PUSH(a, last, depth, -1);
-          last = a, depth += 1, limit = ss_ilg(a - first);
-        } else {
-          first = a, limit = -1;
-        }
-      } else {
-        if(1 < (last - a)) {
-          STACK_PUSH(first, a, depth + 1, ss_ilg(a - first));
-          first = a, limit = -1;
-        } else {
-          last = a, depth += 1, limit = ss_ilg(a - first);
-        }
-      }
-      continue;
-    }
-
-    /* choose pivot */
-    a = ss_pivot(Td, PA, first, last);
-    v = Td[PA[*a]];
-    SWAP(*first, *a);
-
-    /* partition */
-    for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { }
-    if(((a = b) < last) && (x < v)) {
-      for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) {
-        if(x == v) { SWAP(*b, *a); ++a; }
-      }
-    }
-    for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { }
-    if((b < (d = c)) && (x > v)) {
-      for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
-        if(x == v) { SWAP(*c, *d); --d; }
-      }
-    }
-    for(; b < c;) {
-      SWAP(*b, *c);
-      for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) {
-        if(x == v) { SWAP(*b, *a); ++a; }
-      }
-      for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
-        if(x == v) { SWAP(*c, *d); --d; }
-      }
-    }
-
-    if(a <= d) {
-      c = b - 1;
-
-      if((s = a - first) > (t = b - a)) { s = t; }
-      for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
-      if((s = d - c) > (t = last - d - 1)) { s = t; }
-      for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
-
-      a = first + (b - a), c = last - (d - c);
-      b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth);
-
-      if((a - first) <= (last - c)) {
-        if((last - c) <= (c - b)) {
-          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
-          STACK_PUSH(c, last, depth, limit);
-          last = a;
-        } else if((a - first) <= (c - b)) {
-          STACK_PUSH(c, last, depth, limit);
-          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
-          last = a;
-        } else {
-          STACK_PUSH(c, last, depth, limit);
-          STACK_PUSH(first, a, depth, limit);
-          first = b, last = c, depth += 1, limit = ss_ilg(c - b);
-        }
-      } else {
-        if((a - first) <= (c - b)) {
-          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
-          STACK_PUSH(first, a, depth, limit);
-          first = c;
-        } else if((last - c) <= (c - b)) {
-          STACK_PUSH(first, a, depth, limit);
-          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
-          first = c;
-        } else {
-          STACK_PUSH(first, a, depth, limit);
-          STACK_PUSH(c, last, depth, limit);
-          first = b, last = c, depth += 1, limit = ss_ilg(c - b);
-        }
-      }
-    } else {
-      limit += 1;
-      if(Td[PA[*first] - 1] < v) {
-        first = ss_partition(PA, first, last, depth);
-        limit = ss_ilg(last - first);
-      }
-      depth += 1;
-    }
-  }
-#undef STACK_SIZE
-}
-
-#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
-
-
-/*---------------------------------------------------------------------------*/
-
-#if SS_BLOCKSIZE != 0
-
-static INLINE
-void
-ss_blockswap(saidx_t *a, saidx_t *b, saidx_t n) {
-  saidx_t t;
-  for(; 0 < n; --n, ++a, ++b) {
-    t = *a, *a = *b, *b = t;
-  }
-}
-
-static INLINE
-void
-ss_rotate(saidx_t *first, saidx_t *middle, saidx_t *last) {
-  saidx_t *a, *b, t;
-  saidx_t l, r;
-  l = middle - first, r = last - middle;
-  for(; (0 < l) && (0 < r);) {
-    if(l == r) { ss_blockswap(first, middle, l); break; }
-    if(l < r) {
-      a = last - 1, b = middle - 1;
-      t = *a;
-      do {
-        *a-- = *b, *b-- = *a;
-        if(b < first) {
-          *a = t;
-          last = a;
-          if((r -= l + 1) <= l) { break; }
-          a -= 1, b = middle - 1;
-          t = *a;
-        }
-      } while(1);
-    } else {
-      a = first, b = middle;
-      t = *a;
-      do {
-        *a++ = *b, *b++ = *a;
-        if(last <= b) {
-          *a = t;
-          first = a + 1;
-          if((l -= r + 1) <= r) { break; }
-          a += 1, b = middle;
-          t = *a;
-        }
-      } while(1);
-    }
-  }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-static
-void
-ss_inplacemerge(const sauchar_t *T, const saidx_t *PA,
-                saidx_t *first, saidx_t *middle, saidx_t *last,
-                saidx_t depth) {
-  const saidx_t *p;
-  saidx_t *a, *b;
-  saidx_t len, half;
-  saint_t q, r;
-  saint_t x;
-
-  for(;;) {
-    if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); }
-    else                { x = 0; p = PA +  *(last - 1); }
-    for(a = first, len = middle - first, half = len >> 1, r = -1;
-        0 < len;
-        len = half, half >>= 1) {
-      b = a + half;
-      q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth);
-      if(q < 0) {
-        a = b + 1;
-        half -= (len & 1) ^ 1;
-      } else {
-        r = q;
-      }
-    }
-    if(a < middle) {
-      if(r == 0) { *a = ~*a; }
-      ss_rotate(a, middle, last);
-      last -= middle - a;
-      middle = a;
-      if(first == middle) { break; }
-    }
-    --last;
-    if(x != 0) { while(*--last < 0) { } }
-    if(middle == last) { break; }
-  }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Merge-forward with internal buffer. */
-static
-void
-ss_mergeforward(const sauchar_t *T, const saidx_t *PA,
-                saidx_t *first, saidx_t *middle, saidx_t *last,
-                saidx_t *buf, saidx_t depth) {
-  saidx_t *a, *b, *c, *bufend;
-  saidx_t t;
-  saint_t r;
-
-  bufend = buf + (middle - first) - 1;
-  ss_blockswap(buf, first, middle - first);
-
-  for(t = *(a = first), b = buf, c = middle;;) {
-    r = ss_compare(T, PA + *b, PA + *c, depth);
-    if(r < 0) {
-      do {
-        *a++ = *b;
-        if(bufend <= b) { *bufend = t; return; }
-        *b++ = *a;
-      } while(*b < 0);
-    } else if(r > 0) {
-      do {
-        *a++ = *c, *c++ = *a;
-        if(last <= c) {
-          while(b < bufend) { *a++ = *b, *b++ = *a; }
-          *a = *b, *b = t;
-          return;
-        }
-      } while(*c < 0);
-    } else {
-      *c = ~*c;
-      do {
-        *a++ = *b;
-        if(bufend <= b) { *bufend = t; return; }
-        *b++ = *a;
-      } while(*b < 0);
-
-      do {
-        *a++ = *c, *c++ = *a;
-        if(last <= c) {
-          while(b < bufend) { *a++ = *b, *b++ = *a; }
-          *a = *b, *b = t;
-          return;
-        }
-      } while(*c < 0);
-    }
-  }
-}
-
-/* Merge-backward with internal buffer. */
-static
-void
-ss_mergebackward(const sauchar_t *T, const saidx_t *PA,
-                 saidx_t *first, saidx_t *middle, saidx_t *last,
-                 saidx_t *buf, saidx_t depth) {
-  const saidx_t *p1, *p2;
-  saidx_t *a, *b, *c, *bufend;
-  saidx_t t;
-  saint_t r;
-  saint_t x;
-
-  bufend = buf + (last - middle) - 1;
-  ss_blockswap(buf, middle, last - middle);
-
-  x = 0;
-  if(*bufend < 0)       { p1 = PA + ~*bufend; x |= 1; }
-  else                  { p1 = PA +  *bufend; }
-  if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; }
-  else                  { p2 = PA +  *(middle - 1); }
-  for(t = *(a = last - 1), b = bufend, c = middle - 1;;) {
-    r = ss_compare(T, p1, p2, depth);
-    if(0 < r) {
-      if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
-      *a-- = *b;
-      if(b <= buf) { *buf = t; break; }
-      *b-- = *a;
-      if(*b < 0) { p1 = PA + ~*b; x |= 1; }
-      else       { p1 = PA +  *b; }
-    } else if(r < 0) {
-      if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
-      *a-- = *c, *c-- = *a;
-      if(c < first) {
-        while(buf < b) { *a-- = *b, *b-- = *a; }
-        *a = *b, *b = t;
-        break;
-      }
-      if(*c < 0) { p2 = PA + ~*c; x |= 2; }
-      else       { p2 = PA +  *c; }
-    } else {
-      if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
-      *a-- = ~*b;
-      if(b <= buf) { *buf = t; break; }
-      *b-- = *a;
-      if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
-      *a-- = *c, *c-- = *a;
-      if(c < first) {
-        while(buf < b) { *a-- = *b, *b-- = *a; }
-        *a = *b, *b = t;
-        break;
-      }
-      if(*b < 0) { p1 = PA + ~*b; x |= 1; }
-      else       { p1 = PA +  *b; }
-      if(*c < 0) { p2 = PA + ~*c; x |= 2; }
-      else       { p2 = PA +  *c; }
-    }
-  }
-}
-
-/* D&C based merge. */
-static
-void
-ss_swapmerge(const sauchar_t *T, const saidx_t *PA,
-             saidx_t *first, saidx_t *middle, saidx_t *last,
-             saidx_t *buf, saidx_t bufsize, saidx_t depth) {
-#define STACK_SIZE SS_SMERGE_STACKSIZE
-#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a)))
-#define MERGE_CHECK(a, b, c)\
-  do {\
-    if(((c) & 1) ||\
-       (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\
-      *(a) = ~*(a);\
-    }\
-    if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\
-      *(b) = ~*(b);\
-    }\
-  } while(0)
-  struct { saidx_t *a, *b, *c; saint_t d; } stack[STACK_SIZE];
-  saidx_t *l, *r, *lm, *rm;
-  saidx_t m, len, half;
-  saint_t ssize;
-  saint_t check, next;
-
-  for(check = 0, ssize = 0;;) {
-    if((last - middle) <= bufsize) {
-      if((first < middle) && (middle < last)) {
-        ss_mergebackward(T, PA, first, middle, last, buf, depth);
-      }
-      MERGE_CHECK(first, last, check);
-      STACK_POP(first, middle, last, check);
-      continue;
-    }
-
-    if((middle - first) <= bufsize) {
-      if(first < middle) {
-        ss_mergeforward(T, PA, first, middle, last, buf, depth);
-      }
-      MERGE_CHECK(first, last, check);
-      STACK_POP(first, middle, last, check);
-      continue;
-    }
-
-    for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1;
-        0 < len;
-        len = half, half >>= 1) {
-      if(ss_compare(T, PA + GETIDX(*(middle + m + half)),
-                       PA + GETIDX(*(middle - m - half - 1)), depth) < 0) {
-        m += half + 1;
-        half -= (len & 1) ^ 1;
-      }
-    }
-
-    if(0 < m) {
-      lm = middle - m, rm = middle + m;
-      ss_blockswap(lm, middle, m);
-      l = r = middle, next = 0;
-      if(rm < last) {
-        if(*rm < 0) {
-          *rm = ~*rm;
-          if(first < lm) { for(; *--l < 0;) { } next |= 4; }
-          next |= 1;
-        } else if(first < lm) {
-          for(; *r < 0; ++r) { }
-          next |= 2;
-        }
-      }
-
-      if((l - first) <= (last - r)) {
-        STACK_PUSH(r, rm, last, (next & 3) | (check & 4));
-        middle = lm, last = l, check = (check & 3) | (next & 4);
-      } else {
-        if((next & 2) && (r == middle)) { next ^= 6; }
-        STACK_PUSH(first, lm, l, (check & 3) | (next & 4));
-        first = r, middle = rm, check = (next & 3) | (check & 4);
-      }
-    } else {
-      if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) {
-        *middle = ~*middle;
-      }
-      MERGE_CHECK(first, last, check);
-      STACK_POP(first, middle, last, check);
-    }
-  }
-#undef STACK_SIZE
-}
-
-#endif /* SS_BLOCKSIZE != 0 */
-
-
-/*---------------------------------------------------------------------------*/
-
-/*- Function -*/
-
-/* Substring sort */
-void
-sssort(const sauchar_t *T, const saidx_t *PA,
-       saidx_t *first, saidx_t *last,
-       saidx_t *buf, saidx_t bufsize,
-       saidx_t depth, saidx_t n, saint_t lastsuffix) {
-  saidx_t *a;
-#if SS_BLOCKSIZE != 0
-  saidx_t *b, *middle, *curbuf;
-  saidx_t j, k, curbufsize, limit;
-#endif
-  saidx_t i;
-
-  if(lastsuffix != 0) { ++first; }
-
-#if SS_BLOCKSIZE == 0
-  ss_mintrosort(T, PA, first, last, depth);
-#else
-  if((bufsize < SS_BLOCKSIZE) &&
-      (bufsize < (last - first)) &&
-      (bufsize < (limit = ss_isqrt(last - first)))) {
-    if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; }
-    buf = middle = last - limit, bufsize = limit;
-  } else {
-    middle = last, limit = 0;
-  }
-  for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) {
-#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
-    ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth);
-#elif 1 < SS_BLOCKSIZE
-    ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth);
-#endif
-    curbufsize = last - (a + SS_BLOCKSIZE);
-    curbuf = a + SS_BLOCKSIZE;
-    if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; }
-    for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) {
-      ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth);
-    }
-  }
-#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
-  ss_mintrosort(T, PA, a, middle, depth);
-#elif 1 < SS_BLOCKSIZE
-  ss_insertionsort(T, PA, a, middle, depth);
-#endif
-  for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) {
-    if(i & 1) {
-      ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth);
-      a -= k;
-    }
-  }
-  if(limit != 0) {
-#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
-    ss_mintrosort(T, PA, middle, last, depth);
-#elif 1 < SS_BLOCKSIZE
-    ss_insertionsort(T, PA, middle, last, depth);
-#endif
-    ss_inplacemerge(T, PA, first, middle, last, depth);
-  }
-#endif
-
-  if(lastsuffix != 0) {
-    /* Insert last type B* suffix. */
-    saidx_t PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2;
-    for(a = first, i = *(first - 1);
-        (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth)));
-        ++a) {
-      *(a - 1) = *a;
-    }
-    *(a - 1) = i;
-  }
-}
diff --git a/dictBuilder/trsort.c b/dictBuilder/trsort.c
deleted file mode 100644
index 9e21e68ec..000000000
--- a/dictBuilder/trsort.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * trsort.c for libdivsufsort
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * 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.
- */
-
-/*- Compiler specifics -*/
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wshorten-64-to-32"
-#endif
-
-#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
-/* inline is defined */
-#elif defined(_MSC_VER)
-#  define inline __inline
-#else
-#  define inline /* disable inline */
-#endif
-
-#ifdef _MSC_VER    /* Visual Studio */
-#  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
-#  define FORCE_INLINE static __forceinline
-#else
-#  if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
-#    ifdef __GNUC__
-#      define FORCE_INLINE static inline __attribute__((always_inline))
-#    else
-#      define FORCE_INLINE static inline
-#    endif
-#  else
-#    define FORCE_INLINE static
-#  endif /* __STDC_VERSION__ */
-#endif
-
-/*- Dependencies -*/
-#include "divsufsort_private.h"
-
-
-/*- Private Functions -*/
-
-static const saint_t lg_table[256]= {
- -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-};
-
-static INLINE
-saint_t
-tr_ilg(saidx_t n) {
-#if defined(BUILD_DIVSUFSORT64)
-  return (n >> 32) ?
-          ((n >> 48) ?
-            ((n >> 56) ?
-              56 + lg_table[(n >> 56) & 0xff] :
-              48 + lg_table[(n >> 48) & 0xff]) :
-            ((n >> 40) ?
-              40 + lg_table[(n >> 40) & 0xff] :
-              32 + lg_table[(n >> 32) & 0xff])) :
-          ((n & 0xffff0000) ?
-            ((n & 0xff000000) ?
-              24 + lg_table[(n >> 24) & 0xff] :
-              16 + lg_table[(n >> 16) & 0xff]) :
-            ((n & 0x0000ff00) ?
-               8 + lg_table[(n >>  8) & 0xff] :
-               0 + lg_table[(n >>  0) & 0xff]));
-#else
-  return (n & 0xffff0000) ?
-          ((n & 0xff000000) ?
-            24 + lg_table[(n >> 24) & 0xff] :
-            16 + lg_table[(n >> 16) & 0xff]) :
-          ((n & 0x0000ff00) ?
-             8 + lg_table[(n >>  8) & 0xff] :
-             0 + lg_table[(n >>  0) & 0xff]);
-#endif
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Simple insertionsort for small size groups. */
-static
-void
-tr_insertionsort(const saidx_t *ISAd, saidx_t *first, saidx_t *last) {
-  saidx_t *a, *b;
-  saidx_t t, r;
-
-  for(a = first + 1; a < last; ++a) {
-    for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) {
-      do { *(b + 1) = *b; } while((first <= --b) && (*b < 0));
-      if(b < first) { break; }
-    }
-    if(r == 0) { *b = ~*b; }
-    *(b + 1) = t;
-  }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-static INLINE
-void
-tr_fixdown(const saidx_t *ISAd, saidx_t *SA, saidx_t i, saidx_t size) {
-  saidx_t j, k;
-  saidx_t v;
-  saidx_t c, d, e;
-
-  for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
-    d = ISAd[SA[k = j++]];
-    if(d < (e = ISAd[SA[j]])) { k = j; d = e; }
-    if(d <= c) { break; }
-  }
-  SA[i] = v;
-}
-
-/* Simple top-down heapsort. */
-static
-void
-tr_heapsort(const saidx_t *ISAd, saidx_t *SA, saidx_t size) {
-  saidx_t i, m;
-  saidx_t t;
-
-  m = size;
-  if((size % 2) == 0) {
-    m--;
-    if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); }
-  }
-
-  for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); }
-  if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); }
-  for(i = m - 1; 0 < i; --i) {
-    t = SA[0], SA[0] = SA[i];
-    tr_fixdown(ISAd, SA, 0, i);
-    SA[i] = t;
-  }
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-/* Returns the median of three elements. */
-static INLINE
-saidx_t *
-tr_median3(const saidx_t *ISAd, saidx_t *v1, saidx_t *v2, saidx_t *v3) {
-  saidx_t *t;
-  if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); }
-  if(ISAd[*v2] > ISAd[*v3]) {
-    if(ISAd[*v1] > ISAd[*v3]) { return v1; }
-    else { return v3; }
-  }
-  return v2;
-}
-
-/* Returns the median of five elements. */
-static INLINE
-saidx_t *
-tr_median5(const saidx_t *ISAd,
-           saidx_t *v1, saidx_t *v2, saidx_t *v3, saidx_t *v4, saidx_t *v5) {
-  saidx_t *t;
-  if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); }
-  if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); }
-  if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); }
-  if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); }
-  if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); }
-  if(ISAd[*v3] > ISAd[*v4]) { return v4; }
-  return v3;
-}
-
-/* Returns the pivot element. */
-static INLINE
-saidx_t *
-tr_pivot(const saidx_t *ISAd, saidx_t *first, saidx_t *last) {
-  saidx_t *middle;
-  saidx_t t;
-
-  t = last - first;
-  middle = first + t / 2;
-
-  if(t <= 512) {
-    if(t <= 32) {
-      return tr_median3(ISAd, first, middle, last - 1);
-    } else {
-      t >>= 2;
-      return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1);
-    }
-  }
-  t >>= 3;
-  first  = tr_median3(ISAd, first, first + t, first + (t << 1));
-  middle = tr_median3(ISAd, middle - t, middle, middle + t);
-  last   = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1);
-  return tr_median3(ISAd, first, middle, last);
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-typedef struct _trbudget_t trbudget_t;
-struct _trbudget_t {
-  saidx_t chance;
-  saidx_t remain;
-  saidx_t incval;
-  saidx_t count;
-};
-
-static INLINE
-void
-trbudget_init(trbudget_t *budget, saidx_t chance, saidx_t incval) {
-  budget->chance = chance;
-  budget->remain = budget->incval = incval;
-}
-
-static INLINE
-saint_t
-trbudget_check(trbudget_t *budget, saidx_t size) {
-  if(size <= budget->remain) { budget->remain -= size; return 1; }
-  if(budget->chance == 0) { budget->count += size; return 0; }
-  budget->remain += budget->incval - size;
-  budget->chance -= 1;
-  return 1;
-}
-
-
-/*---------------------------------------------------------------------------*/
-
-static INLINE
-void
-tr_partition(const saidx_t *ISAd,
-             saidx_t *first, saidx_t *middle, saidx_t *last,
-             saidx_t **pa, saidx_t **pb, saidx_t v) {
-  saidx_t *a, *b, *c, *d, *e, *f;
-  saidx_t t, s;
-  saidx_t x = 0;
-
-  for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { }
-  if(((a = b) < last) && (x < v)) {
-    for(; (++b < last) && ((x = ISAd[*b]) <= v);) {
-      if(x == v) { SWAP(*b, *a); ++a; }
-    }
-  }
-  for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { }
-  if((b < (d = c)) && (x > v)) {
-    for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
-      if(x == v) { SWAP(*c, *d); --d; }
-    }
-  }
-  for(; b < c;) {
-    SWAP(*b, *c);
-    for(; (++b < c) && ((x = ISAd[*b]) <= v);) {
-      if(x == v) { SWAP(*b, *a); ++a; }
-    }
-    for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
-      if(x == v) { SWAP(*c, *d); --d; }
-    }
-  }
-
-  if(a <= d) {
-    c = b - 1;
-    if((s = a - first) > (t = b - a)) { s = t; }
-    for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
-    if((s = d - c) > (t = last - d - 1)) { s = t; }
-    for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
-    first += (b - a), last -= (d - c);
-  }
-  *pa = first, *pb = last;
-}
-
-static
-void
-tr_copy(saidx_t *ISA, const saidx_t *SA,
-        saidx_t *first, saidx_t *a, saidx_t *b, saidx_t *last,
-        saidx_t depth) {
-  /* sort suffixes of middle partition
-     by using sorted order of suffixes of left and right partition. */
-  saidx_t *c, *d, *e;
-  saidx_t s, v;
-
-  v = b - SA - 1;
-  for(c = first, d = a - 1; c <= d; ++c) {
-    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
-      *++d = s;
-      ISA[s] = d - SA;
-    }
-  }
-  for(c = last - 1, e = d + 1, d = b; e < d; --c) {
-    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
-      *--d = s;
-      ISA[s] = d - SA;
-    }
-  }
-}
-
-static
-void
-tr_partialcopy(saidx_t *ISA, const saidx_t *SA,
-               saidx_t *first, saidx_t *a, saidx_t *b, saidx_t *last,
-               saidx_t depth) {
-  saidx_t *c, *d, *e;
-  saidx_t s, v;
-  saidx_t rank, lastrank, newrank = -1;
-
-  v = b - SA - 1;
-  lastrank = -1;
-  for(c = first, d = a - 1; c <= d; ++c) {
-    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
-      *++d = s;
-      rank = ISA[s + depth];
-      if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
-      ISA[s] = newrank;
-    }
-  }
-
-  lastrank = -1;
-  for(e = d; first <= e; --e) {
-    rank = ISA[*e];
-    if(lastrank != rank) { lastrank = rank; newrank = e - SA; }
-    if(newrank != rank) { ISA[*e] = newrank; }
-  }
-
-  lastrank = -1;
-  for(c = last - 1, e = d + 1, d = b; e < d; --c) {
-    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
-      *--d = s;
-      rank = ISA[s + depth];
-      if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
-      ISA[s] = newrank;
-    }
-  }
-}
-
-static
-void
-tr_introsort(saidx_t *ISA, const saidx_t *ISAd,
-             saidx_t *SA, saidx_t *first, saidx_t *last,
-             trbudget_t *budget) {
-#define STACK_SIZE TR_STACKSIZE
-  struct { const saidx_t *a; saidx_t *b, *c; saint_t d, e; }stack[STACK_SIZE];
-  saidx_t *a, *b, *c;
-  saidx_t t;
-  saidx_t v, x = 0;
-  saidx_t incr = ISAd - ISA;
-  saint_t limit, next;
-  saint_t ssize, trlink = -1;
-
-  for(ssize = 0, limit = tr_ilg(last - first);;) {
-
-    if(limit < 0) {
-      if(limit == -1) {
-        /* tandem repeat partition */
-        tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1);
-
-        /* update ranks */
-        if(a < last) {
-          for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
-        }
-        if(b < last) {
-          for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; }
-        }
-
-        /* push */
-        if(1 < (b - a)) {
-          STACK_PUSH5(NULL, a, b, 0, 0);
-          STACK_PUSH5(ISAd - incr, first, last, -2, trlink);
-          trlink = ssize - 2;
-        }
-        if((a - first) <= (last - b)) {
-          if(1 < (a - first)) {
-            STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink);
-            last = a, limit = tr_ilg(a - first);
-          } else if(1 < (last - b)) {
-            first = b, limit = tr_ilg(last - b);
-          } else {
-            STACK_POP5(ISAd, first, last, limit, trlink);
-          }
-        } else {
-          if(1 < (last - b)) {
-            STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink);
-            first = b, limit = tr_ilg(last - b);
-          } else if(1 < (a - first)) {
-            last = a, limit = tr_ilg(a - first);
-          } else {
-            STACK_POP5(ISAd, first, last, limit, trlink);
-          }
-        }
-      } else if(limit == -2) {
-        /* tandem repeat copy */
-        a = stack[--ssize].b, b = stack[ssize].c;
-        if(stack[ssize].d == 0) {
-          tr_copy(ISA, SA, first, a, b, last, ISAd - ISA);
-        } else {
-          if(0 <= trlink) { stack[trlink].d = -1; }
-          tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA);
-        }
-        STACK_POP5(ISAd, first, last, limit, trlink);
-      } else {
-        /* sorted partition */
-        if(0 <= *first) {
-          a = first;
-          do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a));
-          first = a;
-        }
-        if(first < last) {
-          a = first; do { *a = ~*a; } while(*++a < 0);
-          next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1;
-          if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } }
-
-          /* push */
-          if(trbudget_check(budget, a - first)) {
-            if((a - first) <= (last - a)) {
-              STACK_PUSH5(ISAd, a, last, -3, trlink);
-              ISAd += incr, last = a, limit = next;
-            } else {
-              if(1 < (last - a)) {
-                STACK_PUSH5(ISAd + incr, first, a, next, trlink);
-                first = a, limit = -3;
-              } else {
-                ISAd += incr, last = a, limit = next;
-              }
-            }
-          } else {
-            if(0 <= trlink) { stack[trlink].d = -1; }
-            if(1 < (last - a)) {
-              first = a, limit = -3;
-            } else {
-              STACK_POP5(ISAd, first, last, limit, trlink);
-            }
-          }
-        } else {
-          STACK_POP5(ISAd, first, last, limit, trlink);
-        }
-      }
-      continue;
-    }
-
-    if((last - first) <= TR_INSERTIONSORT_THRESHOLD) {
-      tr_insertionsort(ISAd, first, last);
-      limit = -3;
-      continue;
-    }
-
-    if(limit-- == 0) {
-      tr_heapsort(ISAd, first, last - first);
-      for(a = last - 1; first < a; a = b) {
-        for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; }
-      }
-      limit = -3;
-      continue;
-    }
-
-    /* choose pivot */
-    a = tr_pivot(ISAd, first, last);
-    SWAP(*first, *a);
-    v = ISAd[*first];
-
-    /* partition */
-    tr_partition(ISAd, first, first + 1, last, &a, &b, v);
-    if((last - first) != (b - a)) {
-      next = (ISA[*a] != v) ? tr_ilg(b - a) : -1;
-
-      /* update ranks */
-      for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
-      if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } }
-
-      /* push */
-      if((1 < (b - a)) && (trbudget_check(budget, b - a))) {
-        if((a - first) <= (last - b)) {
-          if((last - b) <= (b - a)) {
-            if(1 < (a - first)) {
-              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
-              STACK_PUSH5(ISAd, b, last, limit, trlink);
-              last = a;
-            } else if(1 < (last - b)) {
-              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
-              first = b;
-            } else {
-              ISAd += incr, first = a, last = b, limit = next;
-            }
-          } else if((a - first) <= (b - a)) {
-            if(1 < (a - first)) {
-              STACK_PUSH5(ISAd, b, last, limit, trlink);
-              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
-              last = a;
-            } else {
-              STACK_PUSH5(ISAd, b, last, limit, trlink);
-              ISAd += incr, first = a, last = b, limit = next;
-            }
-          } else {
-            STACK_PUSH5(ISAd, b, last, limit, trlink);
-            STACK_PUSH5(ISAd, first, a, limit, trlink);
-            ISAd += incr, first = a, last = b, limit = next;
-          }
-        } else {
-          if((a - first) <= (b - a)) {
-            if(1 < (last - b)) {
-              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
-              STACK_PUSH5(ISAd, first, a, limit, trlink);
-              first = b;
-            } else if(1 < (a - first)) {
-              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
-              last = a;
-            } else {
-              ISAd += incr, first = a, last = b, limit = next;
-            }
-          } else if((last - b) <= (b - a)) {
-            if(1 < (last - b)) {
-              STACK_PUSH5(ISAd, first, a, limit, trlink);
-              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
-              first = b;
-            } else {
-              STACK_PUSH5(ISAd, first, a, limit, trlink);
-              ISAd += incr, first = a, last = b, limit = next;
-            }
-          } else {
-            STACK_PUSH5(ISAd, first, a, limit, trlink);
-            STACK_PUSH5(ISAd, b, last, limit, trlink);
-            ISAd += incr, first = a, last = b, limit = next;
-          }
-        }
-      } else {
-        if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; }
-        if((a - first) <= (last - b)) {
-          if(1 < (a - first)) {
-            STACK_PUSH5(ISAd, b, last, limit, trlink);
-            last = a;
-          } else if(1 < (last - b)) {
-            first = b;
-          } else {
-            STACK_POP5(ISAd, first, last, limit, trlink);
-          }
-        } else {
-          if(1 < (last - b)) {
-            STACK_PUSH5(ISAd, first, a, limit, trlink);
-            first = b;
-          } else if(1 < (a - first)) {
-            last = a;
-          } else {
-            STACK_POP5(ISAd, first, last, limit, trlink);
-          }
-        }
-      }
-    } else {
-      if(trbudget_check(budget, last - first)) {
-        limit = tr_ilg(last - first), ISAd += incr;
-      } else {
-        if(0 <= trlink) { stack[trlink].d = -1; }
-        STACK_POP5(ISAd, first, last, limit, trlink);
-      }
-    }
-  }
-#undef STACK_SIZE
-}
-
-
-
-/*---------------------------------------------------------------------------*/
-
-/*- Function -*/
-
-/* Tandem repeat sort */
-void
-trsort(saidx_t *ISA, saidx_t *SA, saidx_t n, saidx_t depth) {
-  saidx_t *ISAd;
-  saidx_t *first, *last;
-  trbudget_t budget;
-  saidx_t t, skip, unsorted;
-
-  trbudget_init(&budget, tr_ilg(n) * 2 / 3, n);
-/*  trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */
-  for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) {
-    first = SA;
-    skip = 0;
-    unsorted = 0;
-    do {
-      if((t = *first) < 0) { first -= t; skip += t; }
-      else {
-        if(skip != 0) { *(first + skip) = skip; skip = 0; }
-        last = SA + ISA[t] + 1;
-        if(1 < (last - first)) {
-          budget.count = 0;
-          tr_introsort(ISA, ISAd, SA, first, last, &budget);
-          if(budget.count != 0) { unsorted += budget.count; }
-          else { skip = first - last; }
-        } else if((last - first) == 1) {
-          skip = -1;
-        }
-        first = last;
-      }
-    } while(first < (SA + n));
-    if(skip != 0) { *(first + skip) = skip; }
-    if(unsorted == 0) { break; }
-  }
-}
diff --git a/dictBuilder/utils.c b/dictBuilder/utils.c
deleted file mode 100644
index 90fb23efa..000000000
--- a/dictBuilder/utils.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * utils.c for libdivsufsort
- * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
- *
- * 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 "divsufsort_private.h"
-
-
-/*- Private Function -*/
-
-/* Binary search for inverse bwt. */
-static
-saidx_t
-binarysearch_lower(const saidx_t *A, saidx_t size, saidx_t value) {
-  saidx_t half, i;
-  for(i = 0, half = size >> 1;
-      0 < size;
-      size = half, half >>= 1) {
-    if(A[i + half] < value) {
-      i += half + 1;
-      half -= (size & 1) ^ 1;
-    }
-  }
-  return i;
-}
-
-
-/*- Functions -*/
-
-/* Burrows-Wheeler transform. */
-saint_t
-bw_transform(const sauchar_t *T, sauchar_t *U, saidx_t *SA,
-             saidx_t n, saidx_t *idx) {
-  saidx_t *A, i, j, p, t;
-  saint_t c;
-
-  /* Check arguments. */
-  if((T == NULL) || (U == NULL) || (n < 0) || (idx == NULL)) { return -1; }
-  if(n <= 1) {
-    if(n == 1) { U[0] = T[0]; }
-    *idx = n;
-    return 0;
-  }
-
-  if((A = SA) == NULL) {
-    i = divbwt(T, U, NULL, n);
-    if(0 <= i) { *idx = i; i = 0; }
-    return (saint_t)i;
-  }
-
-  /* BW transform. */
-  if(T == U) {
-    t = n;
-    for(i = 0, j = 0; i < n; ++i) {
-      p = t - 1;
-      t = A[i];
-      if(0 <= p) {
-        c = T[j];
-        U[j] = (j <= p) ? T[p] : (sauchar_t)A[p];
-        A[j] = c;
-        j++;
-      } else {
-        *idx = i;
-      }
-    }
-    p = t - 1;
-    if(0 <= p) {
-      c = T[j];
-      U[j] = (j <= p) ? T[p] : (sauchar_t)A[p];
-      A[j] = c;
-    } else {
-      *idx = i;
-    }
-  } else {
-    U[0] = T[n - 1];
-    for(i = 0; A[i] != 0; ++i) { U[i + 1] = T[A[i] - 1]; }
-    *idx = i + 1;
-    for(++i; i < n; ++i) { U[i] = T[A[i] - 1]; }
-  }
-
-  if(SA == NULL) {
-    /* Deallocate memory. */
-    free(A);
-  }
-
-  return 0;
-}
-
-/* Inverse Burrows-Wheeler transform. */
-saint_t
-inverse_bw_transform(const sauchar_t *T, sauchar_t *U, saidx_t *A,
-                     saidx_t n, saidx_t idx) {
-  saidx_t C[ALPHABET_SIZE];
-  sauchar_t D[ALPHABET_SIZE];
-  saidx_t *B;
-  saidx_t i, p;
-  saint_t c, d;
-
-  /* Check arguments. */
-  if((T == NULL) || (U == NULL) || (n < 0) || (idx < 0) ||
-     (n < idx) || ((0 < n) && (idx == 0))) {
-    return -1;
-  }
-  if(n <= 1) { return 0; }
-
-  if((B = A) == NULL) {
-    /* Allocate n*sizeof(saidx_t) bytes of memory. */
-    if((B = (saidx_t *)malloc((size_t)n * sizeof(saidx_t))) == NULL) { return -2; }
-  }
-
-  /* Inverse BW transform. */
-  for(c = 0; c < ALPHABET_SIZE; ++c) { C[c] = 0; }
-  for(i = 0; i < n; ++i) { ++C[T[i]]; }
-  for(c = 0, d = 0, i = 0; c < ALPHABET_SIZE; ++c) {
-    p = C[c];
-    if(0 < p) {
-      C[c] = i;
-      D[d++] = (sauchar_t)c;
-      i += p;
-    }
-  }
-  for(i = 0; i < idx; ++i) { B[C[T[i]]++] = i; }
-  for( ; i < n; ++i)       { B[C[T[i]]++] = i + 1; }
-  for(c = 0; c < d; ++c) { C[c] = C[D[c]]; }
-  for(i = 0, p = idx; i < n; ++i) {
-    U[i] = D[binarysearch_lower(C, d, p)];
-    p = B[p - 1];
-  }
-
-  if(A == NULL) {
-    /* Deallocate memory. */
-    free(B);
-  }
-
-  return 0;
-}
-
-/* Checks the suffix array SA of the string T. */
-saint_t
-sufcheck(const sauchar_t *T, const saidx_t *SA,
-         saidx_t n, saint_t verbose) {
-  saidx_t C[ALPHABET_SIZE];
-  saidx_t i, p, q, t;
-  saint_t c;
-
-  if(verbose) { fprintf(stderr, "sufcheck: "); }
-
-  /* Check arguments. */
-  if((T == NULL) || (SA == NULL) || (n < 0)) {
-    if(verbose) { fprintf(stderr, "Invalid arguments.\n"); }
-    return -1;
-  }
-  if(n == 0) {
-    if(verbose) { fprintf(stderr, "Done.\n"); }
-    return 0;
-  }
-
-  /* check range: [0..n-1] */
-  for(i = 0; i < n; ++i) {
-    if((SA[i] < 0) || (n <= SA[i])) {
-      if(verbose) {
-        fprintf(stderr, "Out of the range [0,%" PRIdSAIDX_T "].\n"
-                        "  SA[%" PRIdSAIDX_T "]=%" PRIdSAIDX_T "\n",
-                        n - 1, i, SA[i]);
-      }
-      return -2;
-    }
-  }
-
-  /* check first characters. */
-  for(i = 1; i < n; ++i) {
-    if(T[SA[i - 1]] > T[SA[i]]) {
-      if(verbose) {
-        fprintf(stderr, "Suffixes in wrong order.\n"
-                        "  T[SA[%" PRIdSAIDX_T "]=%" PRIdSAIDX_T "]=%d"
-                        " > T[SA[%" PRIdSAIDX_T "]=%" PRIdSAIDX_T "]=%d\n",
-                        i - 1, SA[i - 1], T[SA[i - 1]], i, SA[i], T[SA[i]]);
-      }
-      return -3;
-    }
-  }
-
-  /* check suffixes. */
-  for(i = 0; i < ALPHABET_SIZE; ++i) { C[i] = 0; }
-  for(i = 0; i < n; ++i) { ++C[T[i]]; }
-  for(i = 0, p = 0; i < ALPHABET_SIZE; ++i) {
-    t = C[i];
-    C[i] = p;
-    p += t;
-  }
-
-  q = C[T[n - 1]];
-  C[T[n - 1]] += 1;
-  for(i = 0; i < n; ++i) {
-    p = SA[i];
-    if(0 < p) {
-      c = T[--p];
-      t = C[c];
-    } else {
-      c = T[p = n - 1];
-      t = q;
-    }
-    if((t < 0) || (p != SA[t])) {
-      if(verbose) {
-        fprintf(stderr, "Suffix in wrong position.\n"
-                        "  SA[%" PRIdSAIDX_T "]=%" PRIdSAIDX_T " or\n"
-                        "  SA[%" PRIdSAIDX_T "]=%" PRIdSAIDX_T "\n",
-                        t, (0 <= t) ? SA[t] : -1, i, SA[i]);
-      }
-      return -4;
-    }
-    if(t != q) {
-      ++C[c];
-      if((n <= C[c]) || (T[SA[C[c]]] != c)) { C[c] = -1; }
-    }
-  }
-
-  if(1 <= verbose) { fprintf(stderr, "Done.\n"); }
-  return 0;
-}
-
-
-static
-int
-_compare(const sauchar_t *T, saidx_t Tsize,
-         const sauchar_t *P, saidx_t Psize,
-         saidx_t suf, saidx_t *match) {
-  saidx_t i, j;
-  saint_t r;
-  for(i = suf + *match, j = *match, r = 0;
-      (i < Tsize) && (j < Psize) && ((r = T[i] - P[j]) == 0); ++i, ++j) { }
-  *match = j;
-  return (r == 0) ? -(j != Psize) : r;
-}
-
-/* Search for the pattern P in the string T. */
-saidx_t
-sa_search(const sauchar_t *T, saidx_t Tsize,
-          const sauchar_t *P, saidx_t Psize,
-          const saidx_t *SA, saidx_t SAsize,
-          saidx_t *idx) {
-  saidx_t size, lsize, rsize, half;
-  saidx_t match, lmatch, rmatch;
-  saidx_t llmatch, lrmatch, rlmatch, rrmatch;
-  saidx_t i, j, k;
-  saint_t r;
-
-  if(idx != NULL) { *idx = -1; }
-  if((T == NULL) || (P == NULL) || (SA == NULL) ||
-     (Tsize < 0) || (Psize < 0) || (SAsize < 0)) { return -1; }
-  if((Tsize == 0) || (SAsize == 0)) { return 0; }
-  if(Psize == 0) { if(idx != NULL) { *idx = 0; } return SAsize; }
-
-  for(i = j = k = 0, lmatch = rmatch = 0, size = SAsize, half = size >> 1;
-      0 < size;
-      size = half, half >>= 1) {
-    match = MIN(lmatch, rmatch);
-    r = _compare(T, Tsize, P, Psize, SA[i + half], &match);
-    if(r < 0) {
-      i += half + 1;
-      half -= (size & 1) ^ 1;
-      lmatch = match;
-    } else if(r > 0) {
-      rmatch = match;
-    } else {
-      lsize = half, j = i, rsize = size - half - 1, k = i + half + 1;
-
-      /* left part */
-      for(llmatch = lmatch, lrmatch = match, half = lsize >> 1;
-          0 < lsize;
-          lsize = half, half >>= 1) {
-        lmatch = MIN(llmatch, lrmatch);
-        r = _compare(T, Tsize, P, Psize, SA[j + half], &lmatch);
-        if(r < 0) {
-          j += half + 1;
-          half -= (lsize & 1) ^ 1;
-          llmatch = lmatch;
-        } else {
-          lrmatch = lmatch;
-        }
-      }
-
-      /* right part */
-      for(rlmatch = match, rrmatch = rmatch, half = rsize >> 1;
-          0 < rsize;
-          rsize = half, half >>= 1) {
-        rmatch = MIN(rlmatch, rrmatch);
-        r = _compare(T, Tsize, P, Psize, SA[k + half], &rmatch);
-        if(r <= 0) {
-          k += half + 1;
-          half -= (rsize & 1) ^ 1;
-          rlmatch = rmatch;
-        } else {
-          rrmatch = rmatch;
-        }
-      }
-
-      break;
-    }
-  }
-
-  if(idx != NULL) { *idx = (0 < (k - j)) ? j : i; }
-  return k - j;
-}
-
-/* Search for the character c in the string T. */
-saidx_t
-sa_simplesearch(const sauchar_t *T, saidx_t Tsize,
-                const saidx_t *SA, saidx_t SAsize,
-                saint_t c, saidx_t *idx) {
-  saidx_t size, lsize, rsize, half;
-  saidx_t i, j, k, p;
-  saint_t r;
-
-  if(idx != NULL) { *idx = -1; }
-  if((T == NULL) || (SA == NULL) || (Tsize < 0) || (SAsize < 0)) { return -1; }
-  if((Tsize == 0) || (SAsize == 0)) { return 0; }
-
-  for(i = j = k = 0, size = SAsize, half = size >> 1;
-      0 < size;
-      size = half, half >>= 1) {
-    p = SA[i + half];
-    r = (p < Tsize) ? T[p] - c : -1;
-    if(r < 0) {
-      i += half + 1;
-      half -= (size & 1) ^ 1;
-    } else if(r == 0) {
-      lsize = half, j = i, rsize = size - half - 1, k = i + half + 1;
-
-      /* left part */
-      for(half = lsize >> 1;
-          0 < lsize;
-          lsize = half, half >>= 1) {
-        p = SA[j + half];
-        r = (p < Tsize) ? T[p] - c : -1;
-        if(r < 0) {
-          j += half + 1;
-          half -= (lsize & 1) ^ 1;
-        }
-      }
-
-      /* right part */
-      for(half = rsize >> 1;
-          0 < rsize;
-          rsize = half, half >>= 1) {
-        p = SA[k + half];
-        r = (p < Tsize) ? T[p] - c : -1;
-        if(r <= 0) {
-          k += half + 1;
-          half -= (rsize & 1) ^ 1;
-        }
-      }
-
-      break;
-    }
-  }
-
-  if(idx != NULL) { *idx = (0 < (k - j)) ? j : i; }
-  return k - j;
-}
diff --git a/lib/Makefile b/lib/Makefile
index e0ca0c626..5ce8c18b7 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,6 +1,6 @@
 # ################################################################
 # ZSTD library - Makefile
-# Copyright (C) Yann Collet 2015
+# Copyright (C) Yann Collet 2015-2016
 # All rights reserved.
 # 
 # BSD license
@@ -28,7 +28,6 @@
 # 
 # You can contact the author at :
 #  - ZSTD homepage : http://www.zstd.net
-#  - ZSTD source repository : https://github.com/Cyan4973/zstd
 # ################################################################
 
 # Version numbers
@@ -52,7 +51,7 @@ FLAGS   = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(MOREFLAGS)
 LIBDIR ?= $(PREFIX)/lib
 INCLUDEDIR=$(PREFIX)/include
 
-ZSTD_FILES := zstd_compress.c zstd_decompress.c fse.c huff0.c
+ZSTD_FILES := zstd_compress.c zstd_decompress.c fse.c huff0.c dictBuilder.c divsufsort.c
 ZSTD_LEGACY:= legacy/zstd_v01.c legacy/zstd_v02.c legacy/zstd_v03.c legacy/zstd_v04.c
 
 ifeq ($(ZSTD_LEGACY_SUPPORT), 0)
@@ -119,6 +118,7 @@ install: libzstd libzstd.pc
 	@cp -a libzstd.pc $(DESTDIR)$(LIBDIR)/pkgconfig/
 	@install -m 644 libzstd.a $(DESTDIR)$(LIBDIR)/libzstd.a
 	@install -m 644 zstd.h $(DESTDIR)$(INCLUDEDIR)/zstd.h
+	@install -m 644 zstd.h $(DESTDIR)$(INCLUDEDIR)/zstd_buffered.h
 	@echo zstd static and shared library installed
 
 uninstall:
diff --git a/dictBuilder/dictBuilder.c b/lib/dictBuilder.c
similarity index 72%
rename from dictBuilder/dictBuilder.c
rename to lib/dictBuilder.c
index d8b2bdb30..ede3b3d2a 100644
--- a/dictBuilder/dictBuilder.c
+++ b/lib/dictBuilder.c
@@ -1,28 +1,37 @@
 /*
-    dictBuilder - dictionary builder for LZ algorithms
+    dictBuilder - dictionary builder for zstd
     Copyright (C) Yann Collet 2016
 
-    GPL v2 License
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
     You can contact the author at :
-    - zstd source repository : https://github.com/Cyan4973/zstd
+       - Zstd source repository : https://www.zstd.net
 */
 
-/* **************************************
+/*-**************************************
 *  Compiler Options
 ****************************************/
 /* Disable some Visual warning messages */
@@ -41,7 +50,7 @@
 
 
 /*-*************************************
-*  Includes
+*  Dependencies
 ***************************************/
 #include <stdlib.h>        /* malloc, free */
 #include <string.h>        /* memset */
@@ -53,9 +62,10 @@
 #include "mem.h"           /* read */
 #include "error_private.h"
 #include "divsufsort.h"
-#include "dictBuilder.h"
-#include "zstd_compress.c"
+#include "dictBuilder_static.h"
+#include "fse.h"
 #include "huff0_static.h"
+#include "zstd_internal.h"
 
 
 /*-*************************************
@@ -94,16 +104,16 @@ static const size_t g_min_fast_dictContent = 192;
 #define DISPLAY(...)         fprintf(stderr, __VA_ARGS__)
 #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
 static unsigned g_displayLevel = 0;   /* 0 : no display;   1: errors;   2: default;  4: full information */
-void DiB_setNotificationLevel(unsigned l) { g_displayLevel=l; }
+void ZDICT_setNotificationLevel(unsigned l) { g_displayLevel=l; }
 
 #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
-            if (DiB_GetMilliSpan(g_time) > refreshRate)  \
+            if (ZDICT_GetMilliSpan(g_time) > refreshRate)  \
             { g_time = clock(); DISPLAY(__VA_ARGS__); \
             if (g_displayLevel>=4) fflush(stdout); } }
 static const unsigned refreshRate = 300;
 static clock_t g_time = 0;
 
-void DiB_printHex(U32 dlevel, const void* ptr, size_t length)
+void ZDICT_printHex(U32 dlevel, const void* ptr, size_t length)
 {
     const BYTE* const b = (const BYTE*)ptr;
     size_t u;
@@ -133,81 +143,25 @@ void DiB_printHex(U32 dlevel, const void* ptr, size_t length)
 }
 
 
-/* ********************************************************
+/*-********************************************************
 *  Helper functions
 **********************************************************/
-unsigned DiB_versionNumber (void) { return DiB_VERSION_NUMBER; }
-
-static unsigned DiB_GetMilliSpan(clock_t nPrevious)
+static unsigned ZDICT_GetMilliSpan(clock_t nPrevious)
 {
     clock_t nCurrent = clock();
     unsigned nSpan = (unsigned)(((nCurrent - nPrevious) * 1000) / CLOCKS_PER_SEC);
     return nSpan;
 }
 
-unsigned DiB_isError(size_t errorCode) { return ERR_isError(errorCode); }
+unsigned ZDICT_isError(size_t errorCode) { return ERR_isError(errorCode); }
 
-const char* DiB_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
-
-
-/* ********************************************************
-*  File related operations
-**********************************************************/
-static unsigned long long DiB_getFileSize(const char* infilename)
-{
-    int r;
-#if defined(_MSC_VER)
-    struct _stat64 statbuf;
-    r = _stat64(infilename, &statbuf);
-#else
-    struct stat statbuf;
-    r = stat(infilename, &statbuf);
-#endif
-    if (r || !S_ISREG(statbuf.st_mode)) return 0;   /* No good... */
-    return (unsigned long long)statbuf.st_size;
-}
-
-
-static unsigned long long DiB_getTotalFileSize(const char** fileNamesTable, unsigned nbFiles)
-{
-    unsigned long long total = 0;
-    unsigned n;
-    for (n=0; n<nbFiles; n++)
-        total += DiB_getFileSize(fileNamesTable[n]);
-    return total;
-}
-
-
-static void DiB_loadFiles(void* buffer, size_t bufferSize,
-                          size_t* fileSizes,
-                          const char** fileNamesTable, unsigned nbFiles)
-{
-    char* buff = (char*)buffer;
-    size_t pos = 0;
-    unsigned n;
-
-    for (n=0; n<nbFiles; n++) {
-        size_t readSize;
-        unsigned long long fileSize = DiB_getFileSize(fileNamesTable[n]);
-        FILE* f = fopen(fileNamesTable[n], "rb");
-        if (f==NULL) EXM_THROW(10, "impossible to open file %s", fileNamesTable[n]);
-        DISPLAYLEVEL(2, "Loading %s...       \r", fileNamesTable[n]);
-        if (fileSize > bufferSize-pos) fileSize = 0;  /* stop there, not enough memory to load all files */
-        readSize = fread(buff+pos, 1, (size_t)fileSize, f);
-        if (readSize != (size_t)fileSize) EXM_THROW(11, "could not read %s", fileNamesTable[n]);
-        pos += readSize;
-        fileSizes[n] = (size_t)fileSize;
-        fclose(f);
-    }
-}
+const char* ZDICT_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }
 
 
 /*-********************************************************
 *  Dictionary training functions
 **********************************************************/
-static size_t DiB_read_ARCH(const void* p) { size_t r; memcpy(&r, p, sizeof(r)); return r; }
-
-static unsigned DiB_NbCommonBytes (register size_t val)
+static unsigned ZDICT_NbCommonBytes (register size_t val)
 {
     if (MEM_isLittleEndian()) {
         if (MEM_64bits()) {
@@ -266,17 +220,17 @@ static unsigned DiB_NbCommonBytes (register size_t val)
 }
 
 
-/*! DiB_count() :
+/*! ZDICT_count() :
     Count the nb of common bytes between 2 pointers.
     Note : this function presumes end of buffer followed by noisy guard band.
 */
-static size_t DiB_count(const void* pIn, const void* pMatch)
+static size_t ZDICT_count(const void* pIn, const void* pMatch)
 {
     const char* const pStart = (const char*)pIn;
     for (;;) {
-        size_t diff = DiB_read_ARCH(pMatch) ^ DiB_read_ARCH(pIn);
+        size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
         if (!diff) { pIn = (const char*)pIn+sizeof(size_t); pMatch = (const char*)pMatch+sizeof(size_t); continue; }
-        pIn = (const char*)pIn+DiB_NbCommonBytes(diff);
+        pIn = (const char*)pIn+ZDICT_NbCommonBytes(diff);
         return (size_t)((const char*)pIn - pStart);
     }
 }
@@ -288,7 +242,7 @@ typedef struct {
     U32 savings;
 } dictItem;
 
-void DiB_initDictItem(dictItem* d)
+static void ZDICT_initDictItem(dictItem* d)
 {
     d->pos = 1;
     d->length = 0;
@@ -298,9 +252,9 @@ void DiB_initDictItem(dictItem* d)
 
 #define LLIMIT 64          /* heuristic determined experimentally */
 #define MINMATCHLENGTH 7   /* heuristic determined experimentally */
-static dictItem DiB_analyzePos(
+static dictItem ZDICT_analyzePos(
                        BYTE* doneMarks,
-                       const saidx_t* suffix, U32 start,
+                       const int* suffix, U32 start,
                        const void* buffer, U32 minRatio)
 {
     U32 lengthList[LLIMIT] = {0};
@@ -334,12 +288,12 @@ static dictItem DiB_analyzePos(
     /* look forward */
     do {
         end++;
-        length = DiB_count(b + pos, b + suffix[end]);
+        length = ZDICT_count(b + pos, b + suffix[end]);
     } while (length >=MINMATCHLENGTH);
 
     /* look backward */
     do {
-        length = DiB_count(b + pos, b + *(suffix+start-1));
+        length = ZDICT_count(b + pos, b + *(suffix+start-1));
         if (length >=MINMATCHLENGTH) start--;
     } while(length >= MINMATCHLENGTH);
 
@@ -400,14 +354,14 @@ static dictItem DiB_analyzePos(
         /* look forward */
         do {
             end++;
-            length = DiB_count(b + pos, b + suffix[end]);
+            length = ZDICT_count(b + pos, b + suffix[end]);
             if (length >= LLIMIT) length = LLIMIT-1;
             lengthList[length]++;
         } while (length >=MINMATCHLENGTH);
 
         /* look backward */
         do {
-            length = DiB_count(b + pos, b + suffix[start-1]);
+            length = ZDICT_count(b + pos, b + suffix[start-1]);
             if (length >= LLIMIT) length = LLIMIT-1;
             lengthList[length]++;
             if (length >=MINMATCHLENGTH) start--;
@@ -453,7 +407,7 @@ static dictItem DiB_analyzePos(
                 if (testedPos == pos)
                     length = solution.length;
                 else {
-                    length = DiB_count(b+pos, b+testedPos);
+                    length = ZDICT_count(b+pos, b+testedPos);
                     if (length > solution.length) length = solution.length;
                 }
                 pEnd = (U32)(testedPos + length);
@@ -465,11 +419,11 @@ static dictItem DiB_analyzePos(
 }
 
 
-/*! DiB_checkMerge
+/*! ZDICT_checkMerge
     check if dictItem can be merged, do it if possible
     @return : id of destination elt, 0 if not merged
 */
-static U32 DiB_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
+static U32 ZDICT_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
 {
     const U32 tableSize = table->pos;
     const U32 max = elt.pos + (elt.length-1);
@@ -513,7 +467,7 @@ static U32 DiB_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
 }
 
 
-static void DiB_removeDictItem(dictItem* table, U32 id)
+static void ZDICT_removeDictItem(dictItem* table, U32 id)
 {
     /* convention : first element is nb of elts */
     U32 max = table->pos;
@@ -525,15 +479,15 @@ static void DiB_removeDictItem(dictItem* table, U32 id)
 }
 
 
-static void DiB_insertDictItem(dictItem* table, U32 maxSize, dictItem elt)
+static void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt)
 {
     /* merge if possible */
-    U32 mergeId = DiB_checkMerge(table, elt, 0);
+    U32 mergeId = ZDICT_checkMerge(table, elt, 0);
     if (mergeId) {
         U32 newMerge = 1;
         while (newMerge) {
-            newMerge = DiB_checkMerge(table, table[mergeId], mergeId);
-            if (newMerge) DiB_removeDictItem(table, mergeId);
+            newMerge = ZDICT_checkMerge(table, table[mergeId], mergeId);
+            if (newMerge) ZDICT_removeDictItem(table, mergeId);
             mergeId = newMerge;
         }
         return;
@@ -555,7 +509,7 @@ static void DiB_insertDictItem(dictItem* table, U32 maxSize, dictItem elt)
 }
 
 
-static U32 DiB_dictSize(const dictItem* dictList)
+static U32 ZDICT_dictSize(const dictItem* dictList)
 {
     U32 u, dictSize = 0;
     for (u=1; u<dictList[0].pos; u++)
@@ -564,32 +518,32 @@ static U32 DiB_dictSize(const dictItem* dictList)
 }
 
 
-static void DiB_trainBuffer(dictItem* dictList, U32 dictListSize,
+static void ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
                             const void* const buffer, const size_t bufferSize,   /* buffer must end with noisy guard band */
                             const size_t* fileSizes, unsigned nbFiles,
                             U32 shiftRatio, unsigned maxDictSize)
 {
-    saidx_t* const suffix0 = (saidx_t*)malloc((bufferSize+2)*sizeof(*suffix0));
-    saidx_t* const suffix = suffix0+1;
+    int* const suffix0 = (int*)malloc((bufferSize+2)*sizeof(*suffix0));
+    int* const suffix = suffix0+1;
     U32* reverseSuffix = (U32*)malloc((bufferSize)*sizeof(*reverseSuffix));
     BYTE* doneMarks = (BYTE*)malloc((bufferSize+16)*sizeof(*doneMarks));   /* +16 for overflow security */
     U32* filePos = (U32*)malloc(nbFiles * sizeof(*filePos));
     U32 minRatio = nbFiles >> shiftRatio;
-    saint_t errorCode;
+    int divSuftSortResult;
 
     /* init */
     DISPLAYLEVEL(2, "\r%70s\r", "");   /* clean display line */
     if (!suffix0 || !reverseSuffix || !doneMarks || !filePos)
-        EXM_THROW(1, "not enough memory for DiB_trainBuffer");
+        EXM_THROW(1, "not enough memory for ZDICT_trainBuffer");
     if (minRatio < MINRATIO) minRatio = MINRATIO;
     memset(doneMarks, 0, bufferSize+16);
 
     /* sort */
     DISPLAYLEVEL(2, "sorting %u files of total size %u MB ...\n", nbFiles, (U32)(bufferSize>>20));
-    errorCode = divsufsort((const sauchar_t*)buffer, suffix, (saidx_t)bufferSize);
-    if (errorCode != 0) EXM_THROW(2, "sort failed");
-    suffix[bufferSize] = (saidx_t)bufferSize;   /* leads into noise */
-    suffix0[0] = (saidx_t)bufferSize;           /* leads into noise */
+    divSuftSortResult = divsufsort((const unsigned char*)buffer, suffix, (int)bufferSize, 0);
+    if (divSuftSortResult != 0) EXM_THROW(2, "sort failed");
+    suffix[bufferSize] = (int)bufferSize;   /* leads into noise */
+    suffix0[0] = (int)bufferSize;           /* leads into noise */
     {
         /* build reverse suffix sort */
         size_t pos;
@@ -608,9 +562,9 @@ static void DiB_trainBuffer(dictItem* dictList, U32 dictListSize,
         U32 cursor; for (cursor=0; cursor < bufferSize; ) {
             dictItem solution;
             if (doneMarks[cursor]) { cursor++; continue; }
-            solution = DiB_analyzePos(doneMarks, suffix, reverseSuffix[cursor], buffer, minRatio);
+            solution = ZDICT_analyzePos(doneMarks, suffix, reverseSuffix[cursor], buffer, minRatio);
             if (solution.length==0) { cursor++; continue; }
-            DiB_insertDictItem(dictList, dictListSize, solution);
+            ZDICT_insertDictItem(dictList, dictListSize, solution);
             cursor += solution.length;
             DISPLAYUPDATE(2, "\r%4.2f %% \r", (double)cursor / bufferSize * 100);
     }   }
@@ -633,26 +587,7 @@ static void DiB_trainBuffer(dictItem* dictList, U32 dictListSize,
 }
 
 
-static size_t DiB_findMaxMem(unsigned long long requiredMem)
-{
-    size_t step = 8 MB;
-    void* testmem = NULL;
-
-    requiredMem = (((requiredMem >> 23) + 1) << 23);
-    requiredMem += 2 * step;
-    if (requiredMem > maxMemory) requiredMem = maxMemory;
-
-    while (!testmem) {
-        requiredMem -= step;
-        testmem = malloc((size_t)requiredMem);
-    }
-
-    free(testmem);
-    return (size_t)(requiredMem - step);
-}
-
-
-static void DiB_fillNoise(void* buffer, size_t length)
+static void ZDICT_fillNoise(void* buffer, size_t length)
 {
     unsigned acc = PRIME1;
     size_t p=0;;
@@ -672,34 +607,36 @@ typedef struct
 } EStats_ress_t;
 
 
-static void DiB_countEStats(EStats_ress_t esr,
+static void ZDICT_countEStats(EStats_ress_t esr,
                             U32* countLit, U32* offsetcodeCount, U32* matchlengthCount, U32* litlengthCount,
                             const void* src, size_t srcSize)
 {
     const BYTE* bytePtr;
     const U32* u32Ptr;
+    seqStore_t seqStore;
 
     if (srcSize > BLOCKSIZE) srcSize = BLOCKSIZE;   /* protection vs large samples */
     ZSTD_copyCCtx(esr.zc, esr.ref);
     ZSTD_compressBlock(esr.zc, esr.workPlace, BLOCKSIZE, src, srcSize);
+    seqStore = ZSTD_copySeqStore(esr.zc);
 
     /* count stats */
-    for(bytePtr = esr.zc->seqStore.litStart; bytePtr < esr.zc->seqStore.lit; bytePtr++)
+    for(bytePtr = seqStore.litStart; bytePtr < seqStore.lit; bytePtr++)
         countLit[*bytePtr]++;
-    for(u32Ptr = esr.zc->seqStore.offsetStart; u32Ptr < esr.zc->seqStore.offset; u32Ptr++) {
+    for(u32Ptr = seqStore.offsetStart; u32Ptr < seqStore.offset; u32Ptr++) {
         BYTE offcode = (BYTE)ZSTD_highbit(*u32Ptr) + 1;
         if (*u32Ptr==0) offcode=0;
         offsetcodeCount[offcode]++;
     }
-    for(bytePtr = esr.zc->seqStore.matchLengthStart; bytePtr < esr.zc->seqStore.matchLength; bytePtr++)
+    for(bytePtr = seqStore.matchLengthStart; bytePtr < seqStore.matchLength; bytePtr++)
         matchlengthCount[*bytePtr]++;
-    for(bytePtr = esr.zc->seqStore.litLengthStart; bytePtr < esr.zc->seqStore.litLength; bytePtr++)
+    for(bytePtr = seqStore.litLengthStart; bytePtr < seqStore.litLength; bytePtr++)
         litlengthCount[*bytePtr]++;
 }
 
 
-#define OFFCODE_MAX 18
-static size_t DiB_analyzeEntropy(void*  dstBuffer, size_t maxDstSize,
+#define OFFCODE_MAX 18  /* only applicable to first block */
+static size_t ZDICT_analyzeEntropy(void*  dstBuffer, size_t maxDstSize,
                                  unsigned compressionLevel,
                            const void*  srcBuffer, const size_t* fileSizes, unsigned nbFiles,
                            const void* dictBuffer, size_t  dictBufferSize)
@@ -734,7 +671,7 @@ static size_t DiB_analyzeEntropy(void*  dstBuffer, size_t maxDstSize,
 
     /* collect stats on all files */
     for (u=0; u<nbFiles; u++) {
-        DiB_countEStats(esr,
+        ZDICT_countEStats(esr,
                         countLit, offcodeCount, matchLengthCount, litlengthCount,
            (const char*)srcBuffer + pos, fileSizes[u]);
         pos += fileSizes[u];
@@ -794,33 +731,16 @@ static size_t DiB_analyzeEntropy(void*  dstBuffer, size_t maxDstSize,
 }
 
 
-static void DiB_saveDict(const char* dictFileName,
-                         const void* buff, size_t buffSize)
-{
-    FILE* f;
-    size_t n;
-
-    f = fopen(dictFileName, "wb");
-    if (f==NULL) EXM_THROW(3, "cannot open %s ", dictFileName);
-
-    n = fwrite(buff, 1, buffSize, f);
-    if (n!=buffSize) EXM_THROW(4, "%s : write error", dictFileName)
-
-    n = (size_t)fclose(f);
-    if (n!=0) EXM_THROW(5, "%s : flush error", dictFileName)
-}
-
-
 #define DIB_FASTSEGMENTSIZE 64
-/*! DiB_fastSampling (based on an idea by Giuseppe Ottaviano)
-    Fill @dictBuffer with stripes of size DIB_FASTSEGMENTSIZE from @samplesBuffer
-    up to @dictSize.
-    Filling starts from the end of @dictBuffer, down to maximum possible.
-    if @dictSize is not a multiply of DIB_FASTSEGMENTSIZE, some bytes at beginning of @dictBuffer won't be used.
-    @return : amount of data written into @dictBuffer
-              or an error Code (if @dictSize or @samplesSize too small)
+/*! ZDICT_fastSampling (based on an idea by Giuseppe Ottaviano)
+    Fill `dictBuffer` with stripes of size DIB_FASTSEGMENTSIZE from `samplesBuffer`
+    up to `dictSize`.
+    Filling starts from the end of `dictBuffer`, down to maximum possible.
+    if `dictSize` is not a multiply of DIB_FASTSEGMENTSIZE, some bytes at beginning of `dictBuffer` won't be used.
+    @return : amount of data written into `dictBuffer`
+              or an error code
 */
-static size_t DiB_fastSampling(void* dictBuffer, size_t dictSize,
+static size_t ZDICT_fastSampling(void* dictBuffer, size_t dictSize,
                          const void* samplesBuffer, size_t samplesSize)
 {
     char* dstPtr = (char*)dictBuffer + dictSize;
@@ -851,10 +771,10 @@ static size_t DiB_fastSampling(void* dictBuffer, size_t dictSize,
 }
 
 
-static size_t DiB_trainFromBuffer_internal(
+size_t ZDICT_trainFromBuffer_unsafe(
                             void* dictBuffer, size_t maxDictSize,
                             const void* samplesBuffer, const size_t* sampleSizes, unsigned nbSamples,
-                            DiB_params_t params)
+                            ZDICT_params_t params)
 {
     const U32 dictListSize = MAX( MAX(DICTLISTSIZE, nbSamples), (U32)(maxDictSize/16));
     dictItem* dictList = (dictItem*)malloc(dictListSize * sizeof(*dictList));
@@ -869,14 +789,14 @@ static size_t DiB_trainFromBuffer_internal(
 
     /* init */
     { unsigned u; for (u=0, sBuffSize=0; u<nbSamples; u++) sBuffSize += sampleSizes[u]; }
-    if (!dictList) { DISPLAYLEVEL(1, "not enough memory for DiB_trainFromBuffer"); return ERROR(memory_allocation); }
-    DiB_initDictItem(dictList);
+    if (!dictList) return ERROR(memory_allocation);
+    ZDICT_initDictItem(dictList);
     if (selectivity==0) selectivity = g_selectivity_default;
     if (compressionLevel==0) compressionLevel = g_compressionLevel_default;
 
-    /* select stripes */
-    if (selectivity>1) {
-        DiB_trainBuffer(dictList, dictListSize,
+    /* build dictionary */
+    if (selectivity>1) {  /* selectivity == 1 => fast mode */
+        ZDICT_trainBuffer(dictList, dictListSize,
                         samplesBuffer, sBuffSize,
                         sampleSizes, nbSamples,
                         selectivity, (U32)targetDictSize);
@@ -885,7 +805,7 @@ static size_t DiB_trainFromBuffer_internal(
         if (g_displayLevel>= 3) {
             const U32 nb = 25;
             U32 u;
-            U32 dictContentSize = DiB_dictSize(dictList);
+            U32 dictContentSize = ZDICT_dictSize(dictList);
             DISPLAYLEVEL(3, "\n %u segments found, of total size %u \n", dictList[0].pos, dictContentSize);
             DISPLAYLEVEL(3, "list %u best segments \n", nb);
             for (u=1; u<=nb; u++) {
@@ -894,13 +814,13 @@ static size_t DiB_trainFromBuffer_internal(
                 U32 d = MIN(40, l);
                 DISPLAYLEVEL(3, "%3u:%3u bytes at pos %8u, savings %7u bytes |",
                              u, l, p, dictList[u].savings);
-                DiB_printHex(3, (const char*)samplesBuffer+p, d);
+                ZDICT_printHex(3, (const char*)samplesBuffer+p, d);
                 DISPLAYLEVEL(3, "| \n");
     }   }   }
 
     /* create dictionary */
     {
-        U32 dictContentSize = DiB_dictSize(dictList);
+        U32 dictContentSize = ZDICT_dictSize(dictList);
         size_t hSize;
         BYTE* ptr;
         U32 u;
@@ -918,7 +838,7 @@ static size_t DiB_trainFromBuffer_internal(
         if (selectivity==1) {  /* note could also be used to complete a dictionary, but not necessarily better */
             DISPLAYLEVEL(3, "\r%70s\r", "");   /* clean display line */
             DISPLAYLEVEL(3, "Adding %u KB with fast sampling \n", (U32)(targetDictSize>>10));
-            dictContentSize = (U32)DiB_fastSampling((char*)dictBuffer + g_provision_entropySize,
+            dictContentSize = (U32)ZDICT_fastSampling((char*)dictBuffer + g_provision_entropySize,
                                                targetDictSize, samplesBuffer, sBuffSize);
         }
 
@@ -929,7 +849,7 @@ static size_t DiB_trainFromBuffer_internal(
         /* entropic tables */
         DISPLAYLEVEL(2, "\r%70s\r", "");   /* clean display line */
         DISPLAYLEVEL(2, "statistics ... \n");
-        hSize += DiB_analyzeEntropy((char*)dictBuffer+4, maxDictSize-4,
+        hSize += ZDICT_analyzeEntropy((char*)dictBuffer+4, maxDictSize-4,
                                     compressionLevel,
                                     samplesBuffer, sampleSizes, nbSamples,
                                     (char*)dictBuffer + maxDictSize - dictContentSize, dictContentSize);
@@ -945,76 +865,38 @@ static size_t DiB_trainFromBuffer_internal(
 }
 
 
-/* issue : samplesBuffer need to be followed by a noisy guard band.
-*  work around : duplicate the buffer, and add the noise ? */
-size_t DiB_trainFromBuffer(void* dictBuffer, size_t maxDictSize,
-                           const void* samplesBuffer, const size_t* sampleSizes, unsigned nbSamples,
-                           DiB_params_t params)
+size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity,
+                           const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
+                           ZDICT_params_t params)
 {
     size_t sBuffSize;
     void* newBuff;
     size_t result;
 
-    { unsigned u; for (u=0, sBuffSize=0; u<nbSamples; u++) sBuffSize += sampleSizes[u]; }
+    { unsigned u; for (u=0, sBuffSize=0; u<nbSamples; u++) sBuffSize += samplesSizes[u]; }
     newBuff = malloc(sBuffSize + NOISELENGTH);
     if (!newBuff) return ERROR(memory_allocation);
 
     memcpy(newBuff, samplesBuffer, sBuffSize);
-    DiB_fillNoise((char*)newBuff + sBuffSize, NOISELENGTH);   /* guard band, for end of buffer condition */
+    ZDICT_fillNoise((char*)newBuff + sBuffSize, NOISELENGTH);   /* guard band, for end of buffer condition */
 
-    result = DiB_trainFromBuffer_internal(dictBuffer, maxDictSize,
-                                        newBuff, sampleSizes, nbSamples,
+    result = ZDICT_trainFromBuffer_unsafe(dictBuffer, dictBufferCapacity,
+                                        newBuff, samplesSizes, nbSamples,
                                         params);
     free(newBuff);
     return result;
 }
 
 
-int DiB_trainFromFiles(const char* dictFileName, unsigned maxDictSize,
-                       const char** fileNamesTable, unsigned nbFiles,
-                       DiB_params_t params)
+/* issue : samplesBuffer need to be followed by a noisy guard band.
+*  work around : duplicate the buffer, and add the noise ? */
+size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
+                             const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples)
 {
-    void* srcBuffer;
-    size_t benchedSize;
-    size_t* fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t));
-    unsigned long long totalSizeToLoad = DiB_getTotalFileSize(fileNamesTable, nbFiles);
-    void* dictBuffer = malloc(maxDictSize);
-    size_t dictSize;
-    int result = 0;
-
-    /* init */
-    benchedSize = DiB_findMaxMem(totalSizeToLoad * MEMMULT) / MEMMULT;
-    if ((unsigned long long)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad;
-    if (benchedSize < totalSizeToLoad)
-        DISPLAYLEVEL(1, "Not enough memory; training on %u MB only...\n", (unsigned)(benchedSize >> 20));
-
-    /* Memory allocation & restrictions */
-    srcBuffer = malloc(benchedSize+NOISELENGTH);     /* + noise */
-    if ((!fileSizes) || (!srcBuffer) || (!dictBuffer)) EXM_THROW(12, "not enough memory for DiB_trainFiles");  /* should not happen */
-
-    /* Load input buffer */
-    DiB_loadFiles(srcBuffer, benchedSize, fileSizes, fileNamesTable, nbFiles);
-    DiB_fillNoise((char*)srcBuffer + benchedSize, NOISELENGTH);   /* guard band, for end of buffer condition */
-
-    /* call buffer version */
-    dictSize = DiB_trainFromBuffer_internal(dictBuffer, maxDictSize,
-                        srcBuffer, fileSizes, nbFiles,
-                        params);
-    if (DiB_isError(dictSize))
-    {
-        DISPLAYLEVEL(1, "dictionary training failed : %s", DiB_getErrorName(dictSize));  /* should not happen */
-        result = 1;
-        goto _cleanup;
-    }
-
-    /* save dict */
-    DISPLAYLEVEL(2, "Save dictionary of size %u into file %s \n", (U32)dictSize, dictFileName);
-    DiB_saveDict(dictFileName, dictBuffer, dictSize);
-
-    /* clean up */
-_cleanup:
-    free(srcBuffer);
-    free(dictBuffer);
-    free(fileSizes);
-    return result;
+    ZDICT_params_t params;
+    memset(&params, 0, sizeof(params));
+    return ZDICT_trainFromBuffer_advanced(dictBuffer, dictBufferCapacity,
+                                          samplesBuffer, samplesSizes, nbSamples,
+                                          params);
 }
+
diff --git a/lib/dictBuilder.h b/lib/dictBuilder.h
new file mode 100644
index 000000000..2ca190ce3
--- /dev/null
+++ b/lib/dictBuilder.h
@@ -0,0 +1,67 @@
+/*
+    dictBuilder header file
+    Copyright (C) Yann Collet 2016
+
+    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    You can contact the author at :
+       - Zstd source repository : https://www.zstd.net
+*/
+
+#ifndef DICTBUILDER_H_001
+#define DICTBUILDER_H_001
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*-*************************************
+*  Public functions
+***************************************/
+/*! ZDICT_trainFromBuffer() :
+    Train a dictionary from a memory buffer `samplesBuffer`,
+    where `nbSamples` samples have been stored concatenated.
+    Each sample size is provided into an orderly table `samplesSizes`.
+    Resulting dictionary will be saved into `dictBuffer`.
+    @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
+              or an error code, which can be tested by ZDICT_isError().
+*/
+size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
+                             const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples);
+
+
+/*-*************************************
+*  Helper functions
+***************************************/
+unsigned ZDICT_isError(size_t errorCode);
+const char* ZDICT_getErrorName(size_t errorCode);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/lib/dictBuilder_static.h b/lib/dictBuilder_static.h
new file mode 100644
index 000000000..0bddb30df
--- /dev/null
+++ b/lib/dictBuilder_static.h
@@ -0,0 +1,104 @@
+/*
+    dictBuilder header file
+    for static linking only
+    Copyright (C) Yann Collet 2016
+
+    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    You can contact the author at :
+       - Zstd source repository : https://www.zstd.net
+*/
+
+/* This library is EXPERIMENTAL, below API is not yet stable */
+
+#ifndef DICTBUILDER_STATIC_H_002
+#define DICTBUILDER_STATIC_H_002
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*-*************************************
+*  Dependencies
+***************************************/
+#include "dictBuilder.h"
+
+
+/*-*************************************
+*  Public type
+***************************************/
+typedef struct {
+    unsigned selectivityLevel;   /* 0 means default; larger => bigger selection => larger dictionary */
+    unsigned compressionLevel;   /* 0 means default; target a specific zstd compression level */
+} ZDICT_params_t;
+
+
+/*-*************************************
+*  Public functions
+***************************************/
+/*! ZDICT_trainFromBuffer_advanced() :
+    Same as ZDICT_trainFromBuffer() with control over more parameters.
+    `parameters` is optional and can be provided with values set to 0 to mean "default".
+    @return : size of dictionary stored into `dictBuffer` (<= `dictBufferSize`)
+              or an error code, which can be tested by DiB_isError().
+    note : ZDICT_trainFromBuffer_advanced() will send notifications into stderr if instructed to, using ZDICT_setNotificationLevel()
+*/
+size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity,
+                             const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
+                             ZDICT_params_t parameters);
+
+
+/*-*************************************
+*  Helper functions
+***************************************/
+/*! ZDICT_setNotificationLevel() :
+    Set amount of notification to be displayed on the console.
+    default : 0 = no console notification.
+    1 = errors; 2 = notifications; 3 = details; 4 = debug;
+    Note : not thread-safe (uses a global constant)
+*/
+void ZDICT_setNotificationLevel(unsigned l);
+
+
+/*-*************************************
+*  Private functions
+***************************************/
+/*! ZDICT_trainFromBuffer_unsafe() :
+    Same as ZDICT_trainFromBuffer_advanced(), but does not control `samplesBuffer`.
+    note : `samplesBuffer` must be followed by noisy guard band to avoid out-of-buffer reads.
+    @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`)
+              or an error code.
+*/
+size_t ZDICT_trainFromBuffer_unsafe(void* dictBuffer, size_t dictBufferCapacity,
+                              const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
+                              ZDICT_params_t parameters);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif  /* DICTBUILDER_STATIC_H_002 */
diff --git a/lib/divsufsort.c b/lib/divsufsort.c
new file mode 100644
index 000000000..ca790574a
--- /dev/null
+++ b/lib/divsufsort.c
@@ -0,0 +1,1905 @@
+/*
+ * divsufsort.c for libdivsufsort-lite
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * 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.
+ */
+
+#if defined(_MSC_VER)
+  #pragma warning(disable : 4244)
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "divsufsort.h"
+
+/*- Constants -*/
+#if defined(INLINE)
+# undef INLINE
+#endif
+#if !defined(INLINE)
+# define INLINE __inline
+#endif
+#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1)
+# undef ALPHABET_SIZE
+#endif
+#if !defined(ALPHABET_SIZE)
+# define ALPHABET_SIZE (256)
+#endif
+#define BUCKET_A_SIZE (ALPHABET_SIZE)
+#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)
+#if defined(SS_INSERTIONSORT_THRESHOLD)
+# if SS_INSERTIONSORT_THRESHOLD < 1
+#  undef SS_INSERTIONSORT_THRESHOLD
+#  define SS_INSERTIONSORT_THRESHOLD (1)
+# endif
+#else
+# define SS_INSERTIONSORT_THRESHOLD (8)
+#endif
+#if defined(SS_BLOCKSIZE)
+# if SS_BLOCKSIZE < 0
+#  undef SS_BLOCKSIZE
+#  define SS_BLOCKSIZE (0)
+# elif 32768 <= SS_BLOCKSIZE
+#  undef SS_BLOCKSIZE
+#  define SS_BLOCKSIZE (32767)
+# endif
+#else
+# define SS_BLOCKSIZE (1024)
+#endif
+/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */
+#if SS_BLOCKSIZE == 0
+# define SS_MISORT_STACKSIZE (96)
+#elif SS_BLOCKSIZE <= 4096
+# define SS_MISORT_STACKSIZE (16)
+#else
+# define SS_MISORT_STACKSIZE (24)
+#endif
+#define SS_SMERGE_STACKSIZE (32)
+#define TR_INSERTIONSORT_THRESHOLD (8)
+#define TR_STACKSIZE (64)
+
+
+/*- Macros -*/
+#ifndef SWAP
+# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0)
+#endif /* SWAP */
+#ifndef MIN
+# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
+#endif /* MIN */
+#ifndef MAX
+# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
+#endif /* MAX */
+#define STACK_PUSH(_a, _b, _c, _d)\
+  do {\
+    assert(ssize < STACK_SIZE);\
+    stack[ssize].a = (_a), stack[ssize].b = (_b),\
+    stack[ssize].c = (_c), stack[ssize++].d = (_d);\
+  } while(0)
+#define STACK_PUSH5(_a, _b, _c, _d, _e)\
+  do {\
+    assert(ssize < STACK_SIZE);\
+    stack[ssize].a = (_a), stack[ssize].b = (_b),\
+    stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\
+  } while(0)
+#define STACK_POP(_a, _b, _c, _d)\
+  do {\
+    assert(0 <= ssize);\
+    if(ssize == 0) { return; }\
+    (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
+    (_c) = stack[ssize].c, (_d) = stack[ssize].d;\
+  } while(0)
+#define STACK_POP5(_a, _b, _c, _d, _e)\
+  do {\
+    assert(0 <= ssize);\
+    if(ssize == 0) { return; }\
+    (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
+    (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\
+  } while(0)
+#define BUCKET_A(_c0) bucket_A[(_c0)]
+#if ALPHABET_SIZE == 256
+#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])
+#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])
+#else
+#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])
+#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])
+#endif
+
+
+/*- Private Functions -*/
+
+static const int lg_table[256]= {
+ -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
+
+static INLINE
+int
+ss_ilg(int n) {
+#if SS_BLOCKSIZE == 0
+  return (n & 0xffff0000) ?
+          ((n & 0xff000000) ?
+            24 + lg_table[(n >> 24) & 0xff] :
+            16 + lg_table[(n >> 16) & 0xff]) :
+          ((n & 0x0000ff00) ?
+             8 + lg_table[(n >>  8) & 0xff] :
+             0 + lg_table[(n >>  0) & 0xff]);
+#elif SS_BLOCKSIZE < 256
+  return lg_table[n];
+#else
+  return (n & 0xff00) ?
+          8 + lg_table[(n >> 8) & 0xff] :
+          0 + lg_table[(n >> 0) & 0xff];
+#endif
+}
+
+#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
+
+#if SS_BLOCKSIZE != 0
+
+static const int sqq_table[256] = {
+  0,  16,  22,  27,  32,  35,  39,  42,  45,  48,  50,  53,  55,  57,  59,  61,
+ 64,  65,  67,  69,  71,  73,  75,  76,  78,  80,  81,  83,  84,  86,  87,  89,
+ 90,  91,  93,  94,  96,  97,  98,  99, 101, 102, 103, 104, 106, 107, 108, 109,
+110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155,
+156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
+169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180,
+181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191,
+192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201,
+202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
+212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221,
+221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230,
+230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
+239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
+247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
+};
+
+static INLINE
+int
+ss_isqrt(int x) {
+  int y, e;
+
+  if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; }
+  e = (x & 0xffff0000) ?
+        ((x & 0xff000000) ?
+          24 + lg_table[(x >> 24) & 0xff] :
+          16 + lg_table[(x >> 16) & 0xff]) :
+        ((x & 0x0000ff00) ?
+           8 + lg_table[(x >>  8) & 0xff] :
+           0 + lg_table[(x >>  0) & 0xff]);
+
+  if(e >= 16) {
+    y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7);
+    if(e >= 24) { y = (y + 1 + x / y) >> 1; }
+    y = (y + 1 + x / y) >> 1;
+  } else if(e >= 8) {
+    y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1;
+  } else {
+    return sqq_table[x] >> 4;
+  }
+
+  return (x < (y * y)) ? y - 1 : y;
+}
+
+#endif /* SS_BLOCKSIZE != 0 */
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Compares two suffixes. */
+static INLINE
+int
+ss_compare(const unsigned char *T,
+           const int *p1, const int *p2,
+           int depth) {
+  const unsigned char *U1, *U2, *U1n, *U2n;
+
+  for(U1 = T + depth + *p1,
+      U2 = T + depth + *p2,
+      U1n = T + *(p1 + 1) + 2,
+      U2n = T + *(p2 + 1) + 2;
+      (U1 < U1n) && (U2 < U2n) && (*U1 == *U2);
+      ++U1, ++U2) {
+  }
+
+  return U1 < U1n ?
+        (U2 < U2n ? *U1 - *U2 : 1) :
+        (U2 < U2n ? -1 : 0);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1)
+
+/* Insertionsort for small size groups */
+static
+void
+ss_insertionsort(const unsigned char *T, const int *PA,
+                 int *first, int *last, int depth) {
+  int *i, *j;
+  int t;
+  int r;
+
+  for(i = last - 2; first <= i; --i) {
+    for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) {
+      do { *(j - 1) = *j; } while((++j < last) && (*j < 0));
+      if(last <= j) { break; }
+    }
+    if(r == 0) { *j = ~*j; }
+    *(j - 1) = t;
+  }
+}
+
+#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */
+
+
+/*---------------------------------------------------------------------------*/
+
+#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
+
+static INLINE
+void
+ss_fixdown(const unsigned char *Td, const int *PA,
+           int *SA, int i, int size) {
+  int j, k;
+  int v;
+  int c, d, e;
+
+  for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
+    d = Td[PA[SA[k = j++]]];
+    if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; }
+    if(d <= c) { break; }
+  }
+  SA[i] = v;
+}
+
+/* Simple top-down heapsort. */
+static
+void
+ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) {
+  int i, m;
+  int t;
+
+  m = size;
+  if((size % 2) == 0) {
+    m--;
+    if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); }
+  }
+
+  for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); }
+  if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); }
+  for(i = m - 1; 0 < i; --i) {
+    t = SA[0], SA[0] = SA[i];
+    ss_fixdown(Td, PA, SA, 0, i);
+    SA[i] = t;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Returns the median of three elements. */
+static INLINE
+int *
+ss_median3(const unsigned char *Td, const int *PA,
+           int *v1, int *v2, int *v3) {
+  int *t;
+  if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); }
+  if(Td[PA[*v2]] > Td[PA[*v3]]) {
+    if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; }
+    else { return v3; }
+  }
+  return v2;
+}
+
+/* Returns the median of five elements. */
+static INLINE
+int *
+ss_median5(const unsigned char *Td, const int *PA,
+           int *v1, int *v2, int *v3, int *v4, int *v5) {
+  int *t;
+  if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); }
+  if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); }
+  if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); }
+  if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); }
+  if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); }
+  if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; }
+  return v3;
+}
+
+/* Returns the pivot element. */
+static INLINE
+int *
+ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) {
+  int *middle;
+  int t;
+
+  t = last - first;
+  middle = first + t / 2;
+
+  if(t <= 512) {
+    if(t <= 32) {
+      return ss_median3(Td, PA, first, middle, last - 1);
+    } else {
+      t >>= 2;
+      return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1);
+    }
+  }
+  t >>= 3;
+  first  = ss_median3(Td, PA, first, first + t, first + (t << 1));
+  middle = ss_median3(Td, PA, middle - t, middle, middle + t);
+  last   = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1);
+  return ss_median3(Td, PA, first, middle, last);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Binary partition for substrings. */
+static INLINE
+int *
+ss_partition(const int *PA,
+                    int *first, int *last, int depth) {
+  int *a, *b;
+  int t;
+  for(a = first - 1, b = last;;) {
+    for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; }
+    for(; (a < --b) && ((PA[*b] + depth) <  (PA[*b + 1] + 1));) { }
+    if(b <= a) { break; }
+    t = ~*b;
+    *b = *a;
+    *a = t;
+  }
+  if(first < a) { *first = ~*first; }
+  return a;
+}
+
+/* Multikey introsort for medium size groups. */
+static
+void
+ss_mintrosort(const unsigned char *T, const int *PA,
+              int *first, int *last,
+              int depth) {
+#define STACK_SIZE SS_MISORT_STACKSIZE
+  struct { int *a, *b, c; int d; } stack[STACK_SIZE];
+  const unsigned char *Td;
+  int *a, *b, *c, *d, *e, *f;
+  int s, t;
+  int ssize;
+  int limit;
+  int v, x = 0;
+
+  for(ssize = 0, limit = ss_ilg(last - first);;) {
+
+    if((last - first) <= SS_INSERTIONSORT_THRESHOLD) {
+#if 1 < SS_INSERTIONSORT_THRESHOLD
+      if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); }
+#endif
+      STACK_POP(first, last, depth, limit);
+      continue;
+    }
+
+    Td = T + depth;
+    if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); }
+    if(limit < 0) {
+      for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) {
+        if((x = Td[PA[*a]]) != v) {
+          if(1 < (a - first)) { break; }
+          v = x;
+          first = a;
+        }
+      }
+      if(Td[PA[*first] - 1] < v) {
+        first = ss_partition(PA, first, a, depth);
+      }
+      if((a - first) <= (last - a)) {
+        if(1 < (a - first)) {
+          STACK_PUSH(a, last, depth, -1);
+          last = a, depth += 1, limit = ss_ilg(a - first);
+        } else {
+          first = a, limit = -1;
+        }
+      } else {
+        if(1 < (last - a)) {
+          STACK_PUSH(first, a, depth + 1, ss_ilg(a - first));
+          first = a, limit = -1;
+        } else {
+          last = a, depth += 1, limit = ss_ilg(a - first);
+        }
+      }
+      continue;
+    }
+
+    /* choose pivot */
+    a = ss_pivot(Td, PA, first, last);
+    v = Td[PA[*a]];
+    SWAP(*first, *a);
+
+    /* partition */
+    for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { }
+    if(((a = b) < last) && (x < v)) {
+      for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) {
+        if(x == v) { SWAP(*b, *a); ++a; }
+      }
+    }
+    for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { }
+    if((b < (d = c)) && (x > v)) {
+      for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
+        if(x == v) { SWAP(*c, *d); --d; }
+      }
+    }
+    for(; b < c;) {
+      SWAP(*b, *c);
+      for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) {
+        if(x == v) { SWAP(*b, *a); ++a; }
+      }
+      for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
+        if(x == v) { SWAP(*c, *d); --d; }
+      }
+    }
+
+    if(a <= d) {
+      c = b - 1;
+
+      if((s = a - first) > (t = b - a)) { s = t; }
+      for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
+      if((s = d - c) > (t = last - d - 1)) { s = t; }
+      for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
+
+      a = first + (b - a), c = last - (d - c);
+      b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth);
+
+      if((a - first) <= (last - c)) {
+        if((last - c) <= (c - b)) {
+          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
+          STACK_PUSH(c, last, depth, limit);
+          last = a;
+        } else if((a - first) <= (c - b)) {
+          STACK_PUSH(c, last, depth, limit);
+          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
+          last = a;
+        } else {
+          STACK_PUSH(c, last, depth, limit);
+          STACK_PUSH(first, a, depth, limit);
+          first = b, last = c, depth += 1, limit = ss_ilg(c - b);
+        }
+      } else {
+        if((a - first) <= (c - b)) {
+          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
+          STACK_PUSH(first, a, depth, limit);
+          first = c;
+        } else if((last - c) <= (c - b)) {
+          STACK_PUSH(first, a, depth, limit);
+          STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
+          first = c;
+        } else {
+          STACK_PUSH(first, a, depth, limit);
+          STACK_PUSH(c, last, depth, limit);
+          first = b, last = c, depth += 1, limit = ss_ilg(c - b);
+        }
+      }
+    } else {
+      limit += 1;
+      if(Td[PA[*first] - 1] < v) {
+        first = ss_partition(PA, first, last, depth);
+        limit = ss_ilg(last - first);
+      }
+      depth += 1;
+    }
+  }
+#undef STACK_SIZE
+}
+
+#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
+
+
+/*---------------------------------------------------------------------------*/
+
+#if SS_BLOCKSIZE != 0
+
+static INLINE
+void
+ss_blockswap(int *a, int *b, int n) {
+  int t;
+  for(; 0 < n; --n, ++a, ++b) {
+    t = *a, *a = *b, *b = t;
+  }
+}
+
+static INLINE
+void
+ss_rotate(int *first, int *middle, int *last) {
+  int *a, *b, t;
+  int l, r;
+  l = middle - first, r = last - middle;
+  for(; (0 < l) && (0 < r);) {
+    if(l == r) { ss_blockswap(first, middle, l); break; }
+    if(l < r) {
+      a = last - 1, b = middle - 1;
+      t = *a;
+      do {
+        *a-- = *b, *b-- = *a;
+        if(b < first) {
+          *a = t;
+          last = a;
+          if((r -= l + 1) <= l) { break; }
+          a -= 1, b = middle - 1;
+          t = *a;
+        }
+      } while(1);
+    } else {
+      a = first, b = middle;
+      t = *a;
+      do {
+        *a++ = *b, *b++ = *a;
+        if(last <= b) {
+          *a = t;
+          first = a + 1;
+          if((l -= r + 1) <= r) { break; }
+          a += 1, b = middle;
+          t = *a;
+        }
+      } while(1);
+    }
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static
+void
+ss_inplacemerge(const unsigned char *T, const int *PA,
+                int *first, int *middle, int *last,
+                int depth) {
+  const int *p;
+  int *a, *b;
+  int len, half;
+  int q, r;
+  int x;
+
+  for(;;) {
+    if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); }
+    else                { x = 0; p = PA +  *(last - 1); }
+    for(a = first, len = middle - first, half = len >> 1, r = -1;
+        0 < len;
+        len = half, half >>= 1) {
+      b = a + half;
+      q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth);
+      if(q < 0) {
+        a = b + 1;
+        half -= (len & 1) ^ 1;
+      } else {
+        r = q;
+      }
+    }
+    if(a < middle) {
+      if(r == 0) { *a = ~*a; }
+      ss_rotate(a, middle, last);
+      last -= middle - a;
+      middle = a;
+      if(first == middle) { break; }
+    }
+    --last;
+    if(x != 0) { while(*--last < 0) { } }
+    if(middle == last) { break; }
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Merge-forward with internal buffer. */
+static
+void
+ss_mergeforward(const unsigned char *T, const int *PA,
+                int *first, int *middle, int *last,
+                int *buf, int depth) {
+  int *a, *b, *c, *bufend;
+  int t;
+  int r;
+
+  bufend = buf + (middle - first) - 1;
+  ss_blockswap(buf, first, middle - first);
+
+  for(t = *(a = first), b = buf, c = middle;;) {
+    r = ss_compare(T, PA + *b, PA + *c, depth);
+    if(r < 0) {
+      do {
+        *a++ = *b;
+        if(bufend <= b) { *bufend = t; return; }
+        *b++ = *a;
+      } while(*b < 0);
+    } else if(r > 0) {
+      do {
+        *a++ = *c, *c++ = *a;
+        if(last <= c) {
+          while(b < bufend) { *a++ = *b, *b++ = *a; }
+          *a = *b, *b = t;
+          return;
+        }
+      } while(*c < 0);
+    } else {
+      *c = ~*c;
+      do {
+        *a++ = *b;
+        if(bufend <= b) { *bufend = t; return; }
+        *b++ = *a;
+      } while(*b < 0);
+
+      do {
+        *a++ = *c, *c++ = *a;
+        if(last <= c) {
+          while(b < bufend) { *a++ = *b, *b++ = *a; }
+          *a = *b, *b = t;
+          return;
+        }
+      } while(*c < 0);
+    }
+  }
+}
+
+/* Merge-backward with internal buffer. */
+static
+void
+ss_mergebackward(const unsigned char *T, const int *PA,
+                 int *first, int *middle, int *last,
+                 int *buf, int depth) {
+  const int *p1, *p2;
+  int *a, *b, *c, *bufend;
+  int t;
+  int r;
+  int x;
+
+  bufend = buf + (last - middle) - 1;
+  ss_blockswap(buf, middle, last - middle);
+
+  x = 0;
+  if(*bufend < 0)       { p1 = PA + ~*bufend; x |= 1; }
+  else                  { p1 = PA +  *bufend; }
+  if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; }
+  else                  { p2 = PA +  *(middle - 1); }
+  for(t = *(a = last - 1), b = bufend, c = middle - 1;;) {
+    r = ss_compare(T, p1, p2, depth);
+    if(0 < r) {
+      if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
+      *a-- = *b;
+      if(b <= buf) { *buf = t; break; }
+      *b-- = *a;
+      if(*b < 0) { p1 = PA + ~*b; x |= 1; }
+      else       { p1 = PA +  *b; }
+    } else if(r < 0) {
+      if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
+      *a-- = *c, *c-- = *a;
+      if(c < first) {
+        while(buf < b) { *a-- = *b, *b-- = *a; }
+        *a = *b, *b = t;
+        break;
+      }
+      if(*c < 0) { p2 = PA + ~*c; x |= 2; }
+      else       { p2 = PA +  *c; }
+    } else {
+      if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
+      *a-- = ~*b;
+      if(b <= buf) { *buf = t; break; }
+      *b-- = *a;
+      if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
+      *a-- = *c, *c-- = *a;
+      if(c < first) {
+        while(buf < b) { *a-- = *b, *b-- = *a; }
+        *a = *b, *b = t;
+        break;
+      }
+      if(*b < 0) { p1 = PA + ~*b; x |= 1; }
+      else       { p1 = PA +  *b; }
+      if(*c < 0) { p2 = PA + ~*c; x |= 2; }
+      else       { p2 = PA +  *c; }
+    }
+  }
+}
+
+/* D&C based merge. */
+static
+void
+ss_swapmerge(const unsigned char *T, const int *PA,
+             int *first, int *middle, int *last,
+             int *buf, int bufsize, int depth) {
+#define STACK_SIZE SS_SMERGE_STACKSIZE
+#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a)))
+#define MERGE_CHECK(a, b, c)\
+  do {\
+    if(((c) & 1) ||\
+       (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\
+      *(a) = ~*(a);\
+    }\
+    if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\
+      *(b) = ~*(b);\
+    }\
+  } while(0)
+  struct { int *a, *b, *c; int d; } stack[STACK_SIZE];
+  int *l, *r, *lm, *rm;
+  int m, len, half;
+  int ssize;
+  int check, next;
+
+  for(check = 0, ssize = 0;;) {
+    if((last - middle) <= bufsize) {
+      if((first < middle) && (middle < last)) {
+        ss_mergebackward(T, PA, first, middle, last, buf, depth);
+      }
+      MERGE_CHECK(first, last, check);
+      STACK_POP(first, middle, last, check);
+      continue;
+    }
+
+    if((middle - first) <= bufsize) {
+      if(first < middle) {
+        ss_mergeforward(T, PA, first, middle, last, buf, depth);
+      }
+      MERGE_CHECK(first, last, check);
+      STACK_POP(first, middle, last, check);
+      continue;
+    }
+
+    for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1;
+        0 < len;
+        len = half, half >>= 1) {
+      if(ss_compare(T, PA + GETIDX(*(middle + m + half)),
+                       PA + GETIDX(*(middle - m - half - 1)), depth) < 0) {
+        m += half + 1;
+        half -= (len & 1) ^ 1;
+      }
+    }
+
+    if(0 < m) {
+      lm = middle - m, rm = middle + m;
+      ss_blockswap(lm, middle, m);
+      l = r = middle, next = 0;
+      if(rm < last) {
+        if(*rm < 0) {
+          *rm = ~*rm;
+          if(first < lm) { for(; *--l < 0;) { } next |= 4; }
+          next |= 1;
+        } else if(first < lm) {
+          for(; *r < 0; ++r) { }
+          next |= 2;
+        }
+      }
+
+      if((l - first) <= (last - r)) {
+        STACK_PUSH(r, rm, last, (next & 3) | (check & 4));
+        middle = lm, last = l, check = (check & 3) | (next & 4);
+      } else {
+        if((next & 2) && (r == middle)) { next ^= 6; }
+        STACK_PUSH(first, lm, l, (check & 3) | (next & 4));
+        first = r, middle = rm, check = (next & 3) | (check & 4);
+      }
+    } else {
+      if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) {
+        *middle = ~*middle;
+      }
+      MERGE_CHECK(first, last, check);
+      STACK_POP(first, middle, last, check);
+    }
+  }
+#undef STACK_SIZE
+}
+
+#endif /* SS_BLOCKSIZE != 0 */
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Substring sort */
+static
+void
+sssort(const unsigned char *T, const int *PA,
+       int *first, int *last,
+       int *buf, int bufsize,
+       int depth, int n, int lastsuffix) {
+  int *a;
+#if SS_BLOCKSIZE != 0
+  int *b, *middle, *curbuf;
+  int j, k, curbufsize, limit;
+#endif
+  int i;
+
+  if(lastsuffix != 0) { ++first; }
+
+#if SS_BLOCKSIZE == 0
+  ss_mintrosort(T, PA, first, last, depth);
+#else
+  if((bufsize < SS_BLOCKSIZE) &&
+      (bufsize < (last - first)) &&
+      (bufsize < (limit = ss_isqrt(last - first)))) {
+    if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; }
+    buf = middle = last - limit, bufsize = limit;
+  } else {
+    middle = last, limit = 0;
+  }
+  for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) {
+#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
+    ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth);
+#elif 1 < SS_BLOCKSIZE
+    ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth);
+#endif
+    curbufsize = last - (a + SS_BLOCKSIZE);
+    curbuf = a + SS_BLOCKSIZE;
+    if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; }
+    for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) {
+      ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth);
+    }
+  }
+#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
+  ss_mintrosort(T, PA, a, middle, depth);
+#elif 1 < SS_BLOCKSIZE
+  ss_insertionsort(T, PA, a, middle, depth);
+#endif
+  for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) {
+    if(i & 1) {
+      ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth);
+      a -= k;
+    }
+  }
+  if(limit != 0) {
+#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
+    ss_mintrosort(T, PA, middle, last, depth);
+#elif 1 < SS_BLOCKSIZE
+    ss_insertionsort(T, PA, middle, last, depth);
+#endif
+    ss_inplacemerge(T, PA, first, middle, last, depth);
+  }
+#endif
+
+  if(lastsuffix != 0) {
+    /* Insert last type B* suffix. */
+    int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2;
+    for(a = first, i = *(first - 1);
+        (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth)));
+        ++a) {
+      *(a - 1) = *a;
+    }
+    *(a - 1) = i;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static INLINE
+int
+tr_ilg(int n) {
+  return (n & 0xffff0000) ?
+          ((n & 0xff000000) ?
+            24 + lg_table[(n >> 24) & 0xff] :
+            16 + lg_table[(n >> 16) & 0xff]) :
+          ((n & 0x0000ff00) ?
+             8 + lg_table[(n >>  8) & 0xff] :
+             0 + lg_table[(n >>  0) & 0xff]);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Simple insertionsort for small size groups. */
+static
+void
+tr_insertionsort(const int *ISAd, int *first, int *last) {
+  int *a, *b;
+  int t, r;
+
+  for(a = first + 1; a < last; ++a) {
+    for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) {
+      do { *(b + 1) = *b; } while((first <= --b) && (*b < 0));
+      if(b < first) { break; }
+    }
+    if(r == 0) { *b = ~*b; }
+    *(b + 1) = t;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static INLINE
+void
+tr_fixdown(const int *ISAd, int *SA, int i, int size) {
+  int j, k;
+  int v;
+  int c, d, e;
+
+  for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
+    d = ISAd[SA[k = j++]];
+    if(d < (e = ISAd[SA[j]])) { k = j; d = e; }
+    if(d <= c) { break; }
+  }
+  SA[i] = v;
+}
+
+/* Simple top-down heapsort. */
+static
+void
+tr_heapsort(const int *ISAd, int *SA, int size) {
+  int i, m;
+  int t;
+
+  m = size;
+  if((size % 2) == 0) {
+    m--;
+    if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); }
+  }
+
+  for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); }
+  if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); }
+  for(i = m - 1; 0 < i; --i) {
+    t = SA[0], SA[0] = SA[i];
+    tr_fixdown(ISAd, SA, 0, i);
+    SA[i] = t;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Returns the median of three elements. */
+static INLINE
+int *
+tr_median3(const int *ISAd, int *v1, int *v2, int *v3) {
+  int *t;
+  if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); }
+  if(ISAd[*v2] > ISAd[*v3]) {
+    if(ISAd[*v1] > ISAd[*v3]) { return v1; }
+    else { return v3; }
+  }
+  return v2;
+}
+
+/* Returns the median of five elements. */
+static INLINE
+int *
+tr_median5(const int *ISAd,
+           int *v1, int *v2, int *v3, int *v4, int *v5) {
+  int *t;
+  if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); }
+  if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); }
+  if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); }
+  if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); }
+  if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); }
+  if(ISAd[*v3] > ISAd[*v4]) { return v4; }
+  return v3;
+}
+
+/* Returns the pivot element. */
+static INLINE
+int *
+tr_pivot(const int *ISAd, int *first, int *last) {
+  int *middle;
+  int t;
+
+  t = last - first;
+  middle = first + t / 2;
+
+  if(t <= 512) {
+    if(t <= 32) {
+      return tr_median3(ISAd, first, middle, last - 1);
+    } else {
+      t >>= 2;
+      return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1);
+    }
+  }
+  t >>= 3;
+  first  = tr_median3(ISAd, first, first + t, first + (t << 1));
+  middle = tr_median3(ISAd, middle - t, middle, middle + t);
+  last   = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1);
+  return tr_median3(ISAd, first, middle, last);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct _trbudget_t trbudget_t;
+struct _trbudget_t {
+  int chance;
+  int remain;
+  int incval;
+  int count;
+};
+
+static INLINE
+void
+trbudget_init(trbudget_t *budget, int chance, int incval) {
+  budget->chance = chance;
+  budget->remain = budget->incval = incval;
+}
+
+static INLINE
+int
+trbudget_check(trbudget_t *budget, int size) {
+  if(size <= budget->remain) { budget->remain -= size; return 1; }
+  if(budget->chance == 0) { budget->count += size; return 0; }
+  budget->remain += budget->incval - size;
+  budget->chance -= 1;
+  return 1;
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+static INLINE
+void
+tr_partition(const int *ISAd,
+             int *first, int *middle, int *last,
+             int **pa, int **pb, int v) {
+  int *a, *b, *c, *d, *e, *f;
+  int t, s;
+  int x = 0;
+
+  for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { }
+  if(((a = b) < last) && (x < v)) {
+    for(; (++b < last) && ((x = ISAd[*b]) <= v);) {
+      if(x == v) { SWAP(*b, *a); ++a; }
+    }
+  }
+  for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { }
+  if((b < (d = c)) && (x > v)) {
+    for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
+      if(x == v) { SWAP(*c, *d); --d; }
+    }
+  }
+  for(; b < c;) {
+    SWAP(*b, *c);
+    for(; (++b < c) && ((x = ISAd[*b]) <= v);) {
+      if(x == v) { SWAP(*b, *a); ++a; }
+    }
+    for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
+      if(x == v) { SWAP(*c, *d); --d; }
+    }
+  }
+
+  if(a <= d) {
+    c = b - 1;
+    if((s = a - first) > (t = b - a)) { s = t; }
+    for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
+    if((s = d - c) > (t = last - d - 1)) { s = t; }
+    for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
+    first += (b - a), last -= (d - c);
+  }
+  *pa = first, *pb = last;
+}
+
+static
+void
+tr_copy(int *ISA, const int *SA,
+        int *first, int *a, int *b, int *last,
+        int depth) {
+  /* sort suffixes of middle partition
+     by using sorted order of suffixes of left and right partition. */
+  int *c, *d, *e;
+  int s, v;
+
+  v = b - SA - 1;
+  for(c = first, d = a - 1; c <= d; ++c) {
+    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
+      *++d = s;
+      ISA[s] = d - SA;
+    }
+  }
+  for(c = last - 1, e = d + 1, d = b; e < d; --c) {
+    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
+      *--d = s;
+      ISA[s] = d - SA;
+    }
+  }
+}
+
+static
+void
+tr_partialcopy(int *ISA, const int *SA,
+               int *first, int *a, int *b, int *last,
+               int depth) {
+  int *c, *d, *e;
+  int s, v;
+  int rank, lastrank, newrank = -1;
+
+  v = b - SA - 1;
+  lastrank = -1;
+  for(c = first, d = a - 1; c <= d; ++c) {
+    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
+      *++d = s;
+      rank = ISA[s + depth];
+      if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
+      ISA[s] = newrank;
+    }
+  }
+
+  lastrank = -1;
+  for(e = d; first <= e; --e) {
+    rank = ISA[*e];
+    if(lastrank != rank) { lastrank = rank; newrank = e - SA; }
+    if(newrank != rank) { ISA[*e] = newrank; }
+  }
+
+  lastrank = -1;
+  for(c = last - 1, e = d + 1, d = b; e < d; --c) {
+    if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
+      *--d = s;
+      rank = ISA[s + depth];
+      if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
+      ISA[s] = newrank;
+    }
+  }
+}
+
+static
+void
+tr_introsort(int *ISA, const int *ISAd,
+             int *SA, int *first, int *last,
+             trbudget_t *budget) {
+#define STACK_SIZE TR_STACKSIZE
+  struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE];
+  int *a, *b, *c;
+  int t;
+  int v, x = 0;
+  int incr = ISAd - ISA;
+  int limit, next;
+  int ssize, trlink = -1;
+
+  for(ssize = 0, limit = tr_ilg(last - first);;) {
+
+    if(limit < 0) {
+      if(limit == -1) {
+        /* tandem repeat partition */
+        tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1);
+
+        /* update ranks */
+        if(a < last) {
+          for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
+        }
+        if(b < last) {
+          for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; }
+        }
+
+        /* push */
+        if(1 < (b - a)) {
+          STACK_PUSH5(NULL, a, b, 0, 0);
+          STACK_PUSH5(ISAd - incr, first, last, -2, trlink);
+          trlink = ssize - 2;
+        }
+        if((a - first) <= (last - b)) {
+          if(1 < (a - first)) {
+            STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink);
+            last = a, limit = tr_ilg(a - first);
+          } else if(1 < (last - b)) {
+            first = b, limit = tr_ilg(last - b);
+          } else {
+            STACK_POP5(ISAd, first, last, limit, trlink);
+          }
+        } else {
+          if(1 < (last - b)) {
+            STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink);
+            first = b, limit = tr_ilg(last - b);
+          } else if(1 < (a - first)) {
+            last = a, limit = tr_ilg(a - first);
+          } else {
+            STACK_POP5(ISAd, first, last, limit, trlink);
+          }
+        }
+      } else if(limit == -2) {
+        /* tandem repeat copy */
+        a = stack[--ssize].b, b = stack[ssize].c;
+        if(stack[ssize].d == 0) {
+          tr_copy(ISA, SA, first, a, b, last, ISAd - ISA);
+        } else {
+          if(0 <= trlink) { stack[trlink].d = -1; }
+          tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA);
+        }
+        STACK_POP5(ISAd, first, last, limit, trlink);
+      } else {
+        /* sorted partition */
+        if(0 <= *first) {
+          a = first;
+          do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a));
+          first = a;
+        }
+        if(first < last) {
+          a = first; do { *a = ~*a; } while(*++a < 0);
+          next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1;
+          if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } }
+
+          /* push */
+          if(trbudget_check(budget, a - first)) {
+            if((a - first) <= (last - a)) {
+              STACK_PUSH5(ISAd, a, last, -3, trlink);
+              ISAd += incr, last = a, limit = next;
+            } else {
+              if(1 < (last - a)) {
+                STACK_PUSH5(ISAd + incr, first, a, next, trlink);
+                first = a, limit = -3;
+              } else {
+                ISAd += incr, last = a, limit = next;
+              }
+            }
+          } else {
+            if(0 <= trlink) { stack[trlink].d = -1; }
+            if(1 < (last - a)) {
+              first = a, limit = -3;
+            } else {
+              STACK_POP5(ISAd, first, last, limit, trlink);
+            }
+          }
+        } else {
+          STACK_POP5(ISAd, first, last, limit, trlink);
+        }
+      }
+      continue;
+    }
+
+    if((last - first) <= TR_INSERTIONSORT_THRESHOLD) {
+      tr_insertionsort(ISAd, first, last);
+      limit = -3;
+      continue;
+    }
+
+    if(limit-- == 0) {
+      tr_heapsort(ISAd, first, last - first);
+      for(a = last - 1; first < a; a = b) {
+        for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; }
+      }
+      limit = -3;
+      continue;
+    }
+
+    /* choose pivot */
+    a = tr_pivot(ISAd, first, last);
+    SWAP(*first, *a);
+    v = ISAd[*first];
+
+    /* partition */
+    tr_partition(ISAd, first, first + 1, last, &a, &b, v);
+    if((last - first) != (b - a)) {
+      next = (ISA[*a] != v) ? tr_ilg(b - a) : -1;
+
+      /* update ranks */
+      for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
+      if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } }
+
+      /* push */
+      if((1 < (b - a)) && (trbudget_check(budget, b - a))) {
+        if((a - first) <= (last - b)) {
+          if((last - b) <= (b - a)) {
+            if(1 < (a - first)) {
+              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
+              STACK_PUSH5(ISAd, b, last, limit, trlink);
+              last = a;
+            } else if(1 < (last - b)) {
+              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
+              first = b;
+            } else {
+              ISAd += incr, first = a, last = b, limit = next;
+            }
+          } else if((a - first) <= (b - a)) {
+            if(1 < (a - first)) {
+              STACK_PUSH5(ISAd, b, last, limit, trlink);
+              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
+              last = a;
+            } else {
+              STACK_PUSH5(ISAd, b, last, limit, trlink);
+              ISAd += incr, first = a, last = b, limit = next;
+            }
+          } else {
+            STACK_PUSH5(ISAd, b, last, limit, trlink);
+            STACK_PUSH5(ISAd, first, a, limit, trlink);
+            ISAd += incr, first = a, last = b, limit = next;
+          }
+        } else {
+          if((a - first) <= (b - a)) {
+            if(1 < (last - b)) {
+              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
+              STACK_PUSH5(ISAd, first, a, limit, trlink);
+              first = b;
+            } else if(1 < (a - first)) {
+              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
+              last = a;
+            } else {
+              ISAd += incr, first = a, last = b, limit = next;
+            }
+          } else if((last - b) <= (b - a)) {
+            if(1 < (last - b)) {
+              STACK_PUSH5(ISAd, first, a, limit, trlink);
+              STACK_PUSH5(ISAd + incr, a, b, next, trlink);
+              first = b;
+            } else {
+              STACK_PUSH5(ISAd, first, a, limit, trlink);
+              ISAd += incr, first = a, last = b, limit = next;
+            }
+          } else {
+            STACK_PUSH5(ISAd, first, a, limit, trlink);
+            STACK_PUSH5(ISAd, b, last, limit, trlink);
+            ISAd += incr, first = a, last = b, limit = next;
+          }
+        }
+      } else {
+        if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; }
+        if((a - first) <= (last - b)) {
+          if(1 < (a - first)) {
+            STACK_PUSH5(ISAd, b, last, limit, trlink);
+            last = a;
+          } else if(1 < (last - b)) {
+            first = b;
+          } else {
+            STACK_POP5(ISAd, first, last, limit, trlink);
+          }
+        } else {
+          if(1 < (last - b)) {
+            STACK_PUSH5(ISAd, first, a, limit, trlink);
+            first = b;
+          } else if(1 < (a - first)) {
+            last = a;
+          } else {
+            STACK_POP5(ISAd, first, last, limit, trlink);
+          }
+        }
+      }
+    } else {
+      if(trbudget_check(budget, last - first)) {
+        limit = tr_ilg(last - first), ISAd += incr;
+      } else {
+        if(0 <= trlink) { stack[trlink].d = -1; }
+        STACK_POP5(ISAd, first, last, limit, trlink);
+      }
+    }
+  }
+#undef STACK_SIZE
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Tandem repeat sort */
+static
+void
+trsort(int *ISA, int *SA, int n, int depth) {
+  int *ISAd;
+  int *first, *last;
+  trbudget_t budget;
+  int t, skip, unsorted;
+
+  trbudget_init(&budget, tr_ilg(n) * 2 / 3, n);
+/*  trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */
+  for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) {
+    first = SA;
+    skip = 0;
+    unsorted = 0;
+    do {
+      if((t = *first) < 0) { first -= t; skip += t; }
+      else {
+        if(skip != 0) { *(first + skip) = skip; skip = 0; }
+        last = SA + ISA[t] + 1;
+        if(1 < (last - first)) {
+          budget.count = 0;
+          tr_introsort(ISA, ISAd, SA, first, last, &budget);
+          if(budget.count != 0) { unsorted += budget.count; }
+          else { skip = first - last; }
+        } else if((last - first) == 1) {
+          skip = -1;
+        }
+        first = last;
+      }
+    } while(first < (SA + n));
+    if(skip != 0) { *(first + skip) = skip; }
+    if(unsorted == 0) { break; }
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Sorts suffixes of type B*. */
+static
+int
+sort_typeBstar(const unsigned char *T, int *SA,
+               int *bucket_A, int *bucket_B,
+               int n, int openMP) {
+  int *PAb, *ISAb, *buf;
+#ifdef LIBBSC_OPENMP
+  int *curbuf;
+  int l;
+#endif
+  int i, j, k, t, m, bufsize;
+  int c0, c1;
+#ifdef LIBBSC_OPENMP
+  int d0, d1;
+#endif
+  (void)openMP;
+
+  /* Initialize bucket arrays. */
+  for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; }
+  for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; }
+
+  /* Count the number of occurrences of the first one or two characters of each
+     type A, B and B* suffix. Moreover, store the beginning position of all
+     type B* suffixes into the array SA. */
+  for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) {
+    /* type A suffix. */
+    do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1));
+    if(0 <= i) {
+      /* type B* suffix. */
+      ++BUCKET_BSTAR(c0, c1);
+      SA[--m] = i;
+      /* type B suffix. */
+      for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) {
+        ++BUCKET_B(c0, c1);
+      }
+    }
+  }
+  m = n - m;
+/*
+note:
+  A type B* suffix is lexicographically smaller than a type B suffix that
+  begins with the same first two characters.
+*/
+
+  /* Calculate the index of start/end point of each bucket. */
+  for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) {
+    t = i + BUCKET_A(c0);
+    BUCKET_A(c0) = i + j; /* start point */
+    i = t + BUCKET_B(c0, c0);
+    for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) {
+      j += BUCKET_BSTAR(c0, c1);
+      BUCKET_BSTAR(c0, c1) = j; /* end point */
+      i += BUCKET_B(c0, c1);
+    }
+  }
+
+  if(0 < m) {
+    /* Sort the type B* suffixes by their first two characters. */
+    PAb = SA + n - m; ISAb = SA + m;
+    for(i = m - 2; 0 <= i; --i) {
+      t = PAb[i], c0 = T[t], c1 = T[t + 1];
+      SA[--BUCKET_BSTAR(c0, c1)] = i;
+    }
+    t = PAb[m - 1], c0 = T[t], c1 = T[t + 1];
+    SA[--BUCKET_BSTAR(c0, c1)] = m - 1;
+
+    /* Sort the type B* substrings using sssort. */
+#ifdef LIBBSC_OPENMP
+    if (openMP)
+    {
+        buf = SA + m;
+        c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m;
+#pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1)
+        {
+          bufsize = (n - (2 * m)) / omp_get_num_threads();
+          curbuf = buf + omp_get_thread_num() * bufsize;
+          k = 0;
+          for(;;) {
+            #pragma omp critical(sssort_lock)
+            {
+              if(0 < (l = j)) {
+                d0 = c0, d1 = c1;
+                do {
+                  k = BUCKET_BSTAR(d0, d1);
+                  if(--d1 <= d0) {
+                    d1 = ALPHABET_SIZE - 1;
+                    if(--d0 < 0) { break; }
+                  }
+                } while(((l - k) <= 1) && (0 < (l = k)));
+                c0 = d0, c1 = d1, j = k;
+              }
+            }
+            if(l == 0) { break; }
+            sssort(T, PAb, SA + k, SA + l,
+                   curbuf, bufsize, 2, n, *(SA + k) == (m - 1));
+          }
+        }
+    }
+    else
+    {
+        buf = SA + m, bufsize = n - (2 * m);
+        for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
+          for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
+            i = BUCKET_BSTAR(c0, c1);
+            if(1 < (j - i)) {
+              sssort(T, PAb, SA + i, SA + j,
+                     buf, bufsize, 2, n, *(SA + i) == (m - 1));
+            }
+          }
+        }
+    }
+#else
+    buf = SA + m, bufsize = n - (2 * m);
+    for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
+      for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
+        i = BUCKET_BSTAR(c0, c1);
+        if(1 < (j - i)) {
+          sssort(T, PAb, SA + i, SA + j,
+                 buf, bufsize, 2, n, *(SA + i) == (m - 1));
+        }
+      }
+    }
+#endif
+
+    /* Compute ranks of type B* substrings. */
+    for(i = m - 1; 0 <= i; --i) {
+      if(0 <= SA[i]) {
+        j = i;
+        do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i]));
+        SA[i + 1] = i - j;
+        if(i <= 0) { break; }
+      }
+      j = i;
+      do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0);
+      ISAb[SA[i]] = j;
+    }
+
+    /* Construct the inverse suffix array of type B* suffixes using trsort. */
+    trsort(ISAb, SA, m, 1);
+
+    /* Set the sorted order of tyoe B* suffixes. */
+    for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {
+      for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }
+      if(0 <= i) {
+        t = i;
+        for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { }
+        SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t;
+      }
+    }
+
+    /* Calculate the index of start/end point of each bucket. */
+    BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */
+    for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) {
+      i = BUCKET_A(c0 + 1) - 1;
+      for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) {
+        t = i - BUCKET_B(c0, c1);
+        BUCKET_B(c0, c1) = i; /* end point */
+
+        /* Move all type B* suffixes to the correct position. */
+        for(i = t, j = BUCKET_BSTAR(c0, c1);
+            j <= k;
+            --i, --k) { SA[i] = SA[k]; }
+      }
+      BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */
+      BUCKET_B(c0, c0) = i; /* end point */
+    }
+  }
+
+  return m;
+}
+
+/* Constructs the suffix array by using the sorted order of type B* suffixes. */
+static
+void
+construct_SA(const unsigned char *T, int *SA,
+             int *bucket_A, int *bucket_B,
+             int n, int m) {
+  int *i, *j, *k;
+  int s;
+  int c0, c1, c2;
+
+  if(0 < m) {
+    /* Construct the sorted order of type B suffixes by using
+       the sorted order of type B* suffixes. */
+    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
+      /* Scan the suffix array from right to left. */
+      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
+          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
+          i <= j;
+          --j) {
+        if(0 < (s = *j)) {
+          assert(T[s] == c1);
+          assert(((s + 1) < n) && (T[s] <= T[s + 1]));
+          assert(T[s - 1] <= T[s]);
+          *j = ~s;
+          c0 = T[--s];
+          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
+          if(c0 != c2) {
+            if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
+            k = SA + BUCKET_B(c2 = c0, c1);
+          }
+          assert(k < j);
+          *k-- = s;
+        } else {
+          assert(((s == 0) && (T[s] == c1)) || (s < 0));
+          *j = ~s;
+        }
+      }
+    }
+  }
+
+  /* Construct the suffix array by using
+     the sorted order of type B suffixes. */
+  k = SA + BUCKET_A(c2 = T[n - 1]);
+  *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1);
+  /* Scan the suffix array from left to right. */
+  for(i = SA, j = SA + n; i < j; ++i) {
+    if(0 < (s = *i)) {
+      assert(T[s - 1] >= T[s]);
+      c0 = T[--s];
+      if((s == 0) || (T[s - 1] < c0)) { s = ~s; }
+      if(c0 != c2) {
+        BUCKET_A(c2) = k - SA;
+        k = SA + BUCKET_A(c2 = c0);
+      }
+      assert(i < k);
+      *k++ = s;
+    } else {
+      assert(s < 0);
+      *i = ~s;
+    }
+  }
+}
+
+/* Constructs the burrows-wheeler transformed string directly
+   by using the sorted order of type B* suffixes. */
+static
+int
+construct_BWT(const unsigned char *T, int *SA,
+              int *bucket_A, int *bucket_B,
+              int n, int m) {
+  int *i, *j, *k, *orig;
+  int s;
+  int c0, c1, c2;
+
+  if(0 < m) {
+    /* Construct the sorted order of type B suffixes by using
+       the sorted order of type B* suffixes. */
+    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
+      /* Scan the suffix array from right to left. */
+      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
+          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
+          i <= j;
+          --j) {
+        if(0 < (s = *j)) {
+          assert(T[s] == c1);
+          assert(((s + 1) < n) && (T[s] <= T[s + 1]));
+          assert(T[s - 1] <= T[s]);
+          c0 = T[--s];
+          *j = ~((int)c0);
+          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
+          if(c0 != c2) {
+            if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
+            k = SA + BUCKET_B(c2 = c0, c1);
+          }
+          assert(k < j);
+          *k-- = s;
+        } else if(s != 0) {
+          *j = ~s;
+#ifndef NDEBUG
+        } else {
+          assert(T[s] == c1);
+#endif
+        }
+      }
+    }
+  }
+
+  /* Construct the BWTed string by using
+     the sorted order of type B suffixes. */
+  k = SA + BUCKET_A(c2 = T[n - 1]);
+  *k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1);
+  /* Scan the suffix array from left to right. */
+  for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
+    if(0 < (s = *i)) {
+      assert(T[s - 1] >= T[s]);
+      c0 = T[--s];
+      *i = c0;
+      if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); }
+      if(c0 != c2) {
+        BUCKET_A(c2) = k - SA;
+        k = SA + BUCKET_A(c2 = c0);
+      }
+      assert(i < k);
+      *k++ = s;
+    } else if(s != 0) {
+      *i = ~s;
+    } else {
+      orig = i;
+    }
+  }
+
+  return orig - SA;
+}
+
+/* Constructs the burrows-wheeler transformed string directly
+   by using the sorted order of type B* suffixes. */
+static
+int
+construct_BWT_indexes(const unsigned char *T, int *SA,
+                      int *bucket_A, int *bucket_B,
+                      int n, int m,
+                      unsigned char * num_indexes, int * indexes) {
+  int *i, *j, *k, *orig;
+  int s;
+  int c0, c1, c2;
+
+  int mod = n / 8;
+  {
+      mod |= mod >> 1;  mod |= mod >> 2;
+      mod |= mod >> 4;  mod |= mod >> 8;
+      mod |= mod >> 16; mod >>= 1;
+
+      *num_indexes = (unsigned char)((n - 1) / (mod + 1));
+  }
+
+  if(0 < m) {
+    /* Construct the sorted order of type B suffixes by using
+       the sorted order of type B* suffixes. */
+    for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
+      /* Scan the suffix array from right to left. */
+      for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
+          j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
+          i <= j;
+          --j) {
+        if(0 < (s = *j)) {
+          assert(T[s] == c1);
+          assert(((s + 1) < n) && (T[s] <= T[s + 1]));
+          assert(T[s - 1] <= T[s]);
+
+          if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = j - SA;
+
+          c0 = T[--s];
+          *j = ~((int)c0);
+          if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
+          if(c0 != c2) {
+            if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
+            k = SA + BUCKET_B(c2 = c0, c1);
+          }
+          assert(k < j);
+          *k-- = s;
+        } else if(s != 0) {
+          *j = ~s;
+#ifndef NDEBUG
+        } else {
+          assert(T[s] == c1);
+#endif
+        }
+      }
+    }
+  }
+
+  /* Construct the BWTed string by using
+     the sorted order of type B suffixes. */
+  k = SA + BUCKET_A(c2 = T[n - 1]);
+  if (T[n - 2] < c2) {
+    if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = k - SA;
+    *k++ = ~((int)T[n - 2]);
+  }
+  else {
+    *k++ = n - 1;
+  }
+
+  /* Scan the suffix array from left to right. */
+  for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
+    if(0 < (s = *i)) {
+      assert(T[s - 1] >= T[s]);
+
+      if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = i - SA;
+
+      c0 = T[--s];
+      *i = c0;
+      if(c0 != c2) {
+        BUCKET_A(c2) = k - SA;
+        k = SA + BUCKET_A(c2 = c0);
+      }
+      assert(i < k);
+      if((0 < s) && (T[s - 1] < c0)) {
+          if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = k - SA;
+          *k++ = ~((int)T[s - 1]);
+      } else
+        *k++ = s;
+    } else if(s != 0) {
+      *i = ~s;
+    } else {
+      orig = i;
+    }
+  }
+
+  return orig - SA;
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/*- Function -*/
+
+int
+divsufsort(const unsigned char *T, int *SA, int n, int openMP) {
+  int *bucket_A, *bucket_B;
+  int m;
+  int err = 0;
+
+  /* Check arguments. */
+  if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }
+  else if(n == 0) { return 0; }
+  else if(n == 1) { SA[0] = 0; return 0; }
+  else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; }
+
+  bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));
+  bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));
+
+  /* Suffixsort. */
+  if((bucket_A != NULL) && (bucket_B != NULL)) {
+    m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP);
+    construct_SA(T, SA, bucket_A, bucket_B, n, m);
+  } else {
+    err = -2;
+  }
+
+  free(bucket_B);
+  free(bucket_A);
+
+  return err;
+}
+
+int
+divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP) {
+  int *B;
+  int *bucket_A, *bucket_B;
+  int m, pidx, i;
+
+  /* Check arguments. */
+  if((T == NULL) || (U == NULL) || (n < 0)) { return -1; }
+  else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
+
+  if((B = A) == NULL) { B = (int *)malloc((size_t)(n + 1) * sizeof(int)); }
+  bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));
+  bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));
+
+  /* Burrows-Wheeler Transform. */
+  if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) {
+    m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP);
+
+    if (num_indexes == NULL || indexes == NULL) {
+        pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m);
+    } else {
+        pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes);
+    }
+
+    /* Copy to output string. */
+    U[0] = T[n - 1];
+    for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)B[i]; }
+    for(i += 1; i < n; ++i) { U[i] = (unsigned char)B[i]; }
+    pidx += 1;
+  } else {
+    pidx = -2;
+  }
+
+  free(bucket_B);
+  free(bucket_A);
+  if(A == NULL) { free(B); }
+
+  return pidx;
+}
diff --git a/dictBuilder/config.h b/lib/divsufsort.h
similarity index 52%
rename from dictBuilder/config.h
rename to lib/divsufsort.h
index c2925d335..dac093669 100644
--- a/dictBuilder/config.h
+++ b/lib/divsufsort.h
@@ -1,5 +1,5 @@
 /*
- * config.h for libdivsufsort
+ * divsufsort.h for libdivsufsort-lite
  * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person
@@ -24,60 +24,44 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef _CONFIG_H
-#define _CONFIG_H 1
+#ifndef _DIVSUFSORT_H
+#define _DIVSUFSORT_H 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-/** Define to the version of this package. **/
-#define PROJECT_VERSION_FULL "2.0.1"
 
-/** Define to 1 if you have the header files. **/
-#define HAVE_INTTYPES_H 1
-#define HAVE_STDDEF_H 1
-#define HAVE_STDINT_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-#define HAVE_STRINGS_H 1
-#define HAVE_MEMORY_H 1
-#define HAVE_SYS_TYPES_H 1
+/*- Prototypes -*/
 
-/** for WinIO **/
-/* #undef HAVE_IO_H */
-/* #undef HAVE_FCNTL_H */
-/* #undef HAVE__SETMODE */
-/* #undef HAVE_SETMODE */
-/* #undef HAVE__FILENO */
-/* #undef HAVE_FOPEN_S */
-/* #undef HAVE__O_BINARY */
-/*
-#ifndef HAVE__SETMODE
-# if HAVE_SETMODE
-#  define _setmode setmode
-#  define HAVE__SETMODE 1
-# endif
-# if HAVE__SETMODE && !HAVE__O_BINARY
-#  define _O_BINARY 0
-#  define HAVE__O_BINARY 1
-# endif
-#endif
-*/
-
-/** for inline **/
-#ifndef INLINE
-# define INLINE inline
-#endif
+/**
+ * Constructs the suffix array of a given string.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array of suffixes.
+ * @param n The length of the given string.
+ * @param openMP enables OpenMP optimization.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+int
+divsufsort(const unsigned char *T, int *SA, int n, int openMP);
 
-/** for VC++ warning **/
-#ifdef _MSC_VER
-#pragma warning(disable: 4127)
-#endif
+/**
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @param num_indexes The length of secondary indexes array. (can be NULL)
+ * @param indexes The secondary indexes array. (can be NULL)
+ * @param openMP enables OpenMP optimization.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+int
+divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP);
 
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
 
-#endif /* _CONFIG_H */
+#endif /* _DIVSUFSORT_H */
diff --git a/lib/mem.h b/lib/mem.h
index a6606e51d..0e357e530 100644
--- a/lib/mem.h
+++ b/lib/mem.h
@@ -119,11 +119,12 @@ MEM_STATIC unsigned MEM_isLittleEndian(void)
 
 #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
 
-/* violates C standard on structure alignment.
+/* violates C standard, by lying on structure alignment.
 Only use if no other choice to achieve best performance on target platform */
 MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
 MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
 MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
+MEM_STATIC U64 MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
 
 MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
 MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
@@ -133,11 +134,12 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
 
 /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
 /* currently only defined for gcc and icc */
-typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
+typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
 
 MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
 MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
 MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
+MEM_STATIC U64 MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }
 
 MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
 MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
@@ -163,6 +165,11 @@ MEM_STATIC U64 MEM_read64(const void* memPtr)
     U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
 }
 
+MEM_STATIC size_t MEM_readST(const void* memPtr)
+{
+    size_t val; memcpy(&val, memPtr, sizeof(val)); return val;
+}
+
 MEM_STATIC void MEM_write16(void* memPtr, U16 value)
 {
     memcpy(memPtr, &value, sizeof(value));
diff --git a/lib/zstd.h b/lib/zstd.h
index ce56c6351..53ed69739 100644
--- a/lib/zstd.h
+++ b/lib/zstd.h
@@ -61,7 +61,7 @@ extern "C" {
 ***************************************/
 #define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */
 #define ZSTD_VERSION_MINOR    5    /* for new (non-breaking) interface capabilities */
-#define ZSTD_VERSION_RELEASE  0    /* for tweaks, bug-fixes, or development */
+#define ZSTD_VERSION_RELEASE  1    /* for tweaks, bug-fixes, or development */
 #define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
 ZSTDLIB_API unsigned ZSTD_versionNumber (void);
 
diff --git a/lib/zstd_compress.c b/lib/zstd_compress.c
index 39e996c2d..83337b901 100644
--- a/lib/zstd_compress.c
+++ b/lib/zstd_compress.c
@@ -48,7 +48,7 @@
 #endif
 
 
-/* *************************************
+/*-*************************************
 *  Dependencies
 ***************************************/
 #include <stdlib.h>   /* malloc */
@@ -59,46 +59,21 @@
 #include "zstd_internal.h"
 
 
-/* *************************************
+/*-*************************************
 *  Constants
 ***************************************/
 static const U32 g_searchStrength = 8;
 
 
-/* *************************************
+/*-*************************************
 *  Helper functions
 ***************************************/
 size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; }
 
 
-/* *************************************
+/*-*************************************
 *  Sequence storage
 ***************************************/
-typedef struct {
-    void* buffer;
-    U32*  offsetStart;
-    U32*  offset;
-    BYTE* offCodeStart;
-    BYTE* offCode;
-    BYTE* litStart;
-    BYTE* lit;
-    BYTE* litLengthStart;
-    BYTE* litLength;
-    BYTE* matchLengthStart;
-    BYTE* matchLength;
-    BYTE* dumpsStart;
-    BYTE* dumps;
-    /* opt */
-    U32* matchLengthFreq;
-    U32* litLengthFreq;
-    U32* litFreq;
-    U32* offCodeFreq;
-    U32  matchLengthSum;
-    U32  litLengthSum;
-    U32  litSum;
-    U32  offCodeSum;
-} seqStore_t;
-
 static void ZSTD_resetFreqs(seqStore_t* ssPtr)
 {
     unsigned u;
@@ -129,7 +104,7 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
 }
 
 
-/* *************************************
+/*-*************************************
 *  Context memory management
 ***************************************/
 struct ZSTD_CCtx_s
@@ -159,7 +134,6 @@ struct ZSTD_CCtx_s
     FSE_CTable litlengthCTable   [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
 };
 
-
 ZSTD_CCtx* ZSTD_createCCtx(void)
 {
     return (ZSTD_CCtx*) calloc(1, sizeof(ZSTD_CCtx));
@@ -172,14 +146,19 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
     return 0;   /* reserved as a potential error code in the future */
 }
 
+seqStore_t ZSTD_copySeqStore(const ZSTD_CCtx* ctx)
+{
+    return ctx->seqStore;
+}
+
 
 static unsigned ZSTD_highbit(U32 val);
 
 #define CLAMP(val,min,max) { if (val<min) val=min; else if (val>max) val=max; }
 
-/** ZSTD_validateParams()
-    correct params value to remain within authorized range
-    optimize for srcSize if srcSize > 0 */
+/** ZSTD_validateParams() :
+    correct params value to remain within authorized range,
+    optimize for `srcSize` if srcSize > 0 */
 void ZSTD_validateParams(ZSTD_parameters* params)
 {
     const U32 btPlus = (params->strategy == ZSTD_btlazy2) || (params->strategy == ZSTD_opt_bt);
@@ -800,33 +779,9 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const B
 }
 
 
-/* *************************************
+/*-*************************************
 *  Match length counter
 ***************************************/
-static size_t ZSTD_read_ARCH(const void* p) { size_t r; memcpy(&r, p, sizeof(r)); return r; }
-
-static unsigned ZSTD_highbit(U32 val)
-{
-#   if defined(_MSC_VER)   /* Visual */
-    unsigned long r=0;
-    _BitScanReverse(&r, val);
-    return (unsigned)r;
-#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* GCC Intrinsic */
-    return 31 - __builtin_clz(val);
-#   else   /* Software version */
-    static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
-    U32 v = val;
-    int r;
-    v |= v >> 1;
-    v |= v >> 2;
-    v |= v >> 4;
-    v |= v >> 8;
-    v |= v >> 16;
-    r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
-    return r;
-#   endif
-}
-
 static unsigned ZSTD_NbCommonBytes (register size_t val)
 {
     if (MEM_isLittleEndian()) {
@@ -891,12 +846,11 @@ static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLim
     const BYTE* const pStart = pIn;
 
     while ((pIn<pInLimit-(sizeof(size_t)-1))) {
-        size_t diff = ZSTD_read_ARCH(pMatch) ^ ZSTD_read_ARCH(pIn);
+        size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
         if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
         pIn += ZSTD_NbCommonBytes(diff);
         return (size_t)(pIn - pStart);
     }
-
     if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
     if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
     if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
@@ -904,7 +858,7 @@ static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLim
 }
 
 /** ZSTD_count_2segments() :
-*   can count match length with ip & match in potentially 2 different segments.
+*   can count match length with `ip` & `match` in 2 different segments.
 *   convention : on reaching mEnd, match count continue starting from iStart
 */
 static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
diff --git a/lib/zstd_internal.h b/lib/zstd_internal.h
index ca291bd53..318fd55f6 100644
--- a/lib/zstd_internal.h
+++ b/lib/zstd_internal.h
@@ -32,11 +32,7 @@
 #ifndef ZSTD_CCOMMON_H_MODULE
 #define ZSTD_CCOMMON_H_MODULE
 
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/* *************************************
+/*-*************************************
 *  Dependencies
 ***************************************/
 #include "mem.h"
@@ -44,14 +40,14 @@ extern "C" {
 #include "zstd_static.h"
 
 
-/* *************************************
+/*-*************************************
 *  Common macros
 ***************************************/
 #define MIN(a,b) ((a)<(b) ? (a) : (b))
 #define MAX(a,b) ((a)>(b) ? (a) : (b))
 
 
-/* *************************************
+/*-*************************************
 *  Common constants
 ***************************************/
 #define ZSTD_MAGICNUMBER 0xFD2FB525   /* v0.5 */
@@ -130,9 +126,58 @@ MEM_STATIC void ZSTD_wildcopy(void* dst, const void* src, size_t length)
     while (op < oend);
 }
 
-
-#if defined (__cplusplus)
+MEM_STATIC unsigned ZSTD_highbit(U32 val)
+{
+#   if defined(_MSC_VER)   /* Visual */
+    unsigned long r=0;
+    _BitScanReverse(&r, val);
+    return (unsigned)r;
+#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* GCC Intrinsic */
+    return 31 - __builtin_clz(val);
+#   else   /* Software version */
+    static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
+    U32 v = val;
+    int r;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
+    return r;
+#   endif
 }
-#endif
+
+
+/*-*******************************************
+*  Private interfaces
+*********************************************/
+typedef struct {
+    void* buffer;
+    U32*  offsetStart;
+    U32*  offset;
+    BYTE* offCodeStart;
+    BYTE* offCode;
+    BYTE* litStart;
+    BYTE* lit;
+    BYTE* litLengthStart;
+    BYTE* litLength;
+    BYTE* matchLengthStart;
+    BYTE* matchLength;
+    BYTE* dumpsStart;
+    BYTE* dumps;
+    /* opt */
+    U32* matchLengthFreq;
+    U32* litLengthFreq;
+    U32* litFreq;
+    U32* offCodeFreq;
+    U32  matchLengthSum;
+    U32  litLengthSum;
+    U32  litSum;
+    U32  offCodeSum;
+} seqStore_t;
+
+seqStore_t ZSTD_copySeqStore(const ZSTD_CCtx* ctx);
+
 
 #endif   /* ZSTD_CCOMMON_H_MODULE */
diff --git a/lib/zstd_static.h b/lib/zstd_static.h
index f31e63a28..f695ccc06 100644
--- a/lib/zstd_static.h
+++ b/lib/zstd_static.h
@@ -205,7 +205,7 @@ ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t ds
 *  Block functions
 ****************************************/
 /*! Block functions produce and decode raw zstd blocks, without frame metadata.
-    User will have to save and regenerate necessary information to regenerate data, such as block sizes.
+    User will have to take in charge required information to regenerate data, such as block sizes.
 
     A few rules to respect :
     - Uncompressed block size must be <= 128 KB
@@ -222,18 +222,17 @@ ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t ds
       + ZSTD_decompressBlock() doesn't accept uncompressed data as input !!
 */
 
-
 size_t ZSTD_compressBlock  (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
 size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
 
 
-/* *************************************
+/*-*************************************
 *  Error management
 ***************************************/
 #include "error_public.h"
 /*! ZSTD_getErrorCode() :
     convert a `size_t` function result into a `ZSTD_error_code` enum type,
-    which can be used to compare directly with enum list within "error_public.h" */
+    which can be used to compare directly with enum list published into "error_public.h" */
 ZSTD_ErrorCode ZSTD_getError(size_t code);
 
 
-- 
GitLab