// Building-Blocks_DUMPER rev.2-

/*
C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>dir osho.txt
 Volume in drive C is H320_Vol2
 Volume Serial Number is A094-FAE2

 Directory of C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1

10/04/2010  06:32 AM                18 osho.txt
               1 File(s)             18 bytes
               0 Dir(s)   1,159,110,656 bytes free

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type osho.txt
bxr bxr boban dodo
C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>cl /Ox Building-Blocks_DUMPER.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

Building-Blocks_DUMPER.c
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:Building-Blocks_DUMPER.exe
Building-Blocks_DUMPER.obj

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>Building-Blocks_DUMPER.exe
Building-Blocks_DUMPER rev.1, written by Kaze.
Sorting 16 Pointers to Building-Blocks 3 chars in size ...
Allocated memory for pointers-to-words in MB: 1
Writing Sorted Building-Blocks to BB003.txt ...
3|18-3+1|13|3
Sorting 15 Pointers to Building-Blocks 4 chars in size ...
Allocated memory for pointers-to-words in MB: 1
Writing Sorted Building-Blocks to BB004.txt ...
4|18-4+1|13|2
Sorting 14 Pointers to Building-Blocks 5 chars in size ...
Allocated memory for pointers-to-words in MB: 1
Writing Sorted Building-Blocks to BB005.txt ...
5|18-5+1|13|1

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type BB003.txt
 bo
 bx
 do
an
ban
bob
bxr
dod
n d
oba
odo
r b
xr

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type BB004.txt
 bob
 bxr
 dod
an d
ban
boba
bxr
dodo
n do
oban
r bo
r bx
xr b

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type BB005.txt
 boba
 bxr
 dodo
an do
ban d
boban
bxr b
n dod
oban
r bob
r bxr
xr bo
xr bx

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>
*/

/*
C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type osho.txt
bxr bxr boban dodo
C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>dir osho.txt
18 osho.txt

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>cl /Ox Building-Blocks_DUMPER.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

Building-Blocks_DUMPER.c
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:Building-Blocks_DUMPER.exe
Building-Blocks_DUMPER.obj

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>Building-Blocks_DUMPER.exe
Building-Blocks_DUMPER rev.1, written by Kaze.
Sorting 16 Pointers to Building-Blocks 3 chars in size ...
Allocated memory for pointers-to-words in MB: 1
Writing Sorted Building-Blocks to BB003.txt ...

In %c:
C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type BB003.txt
 bo
 bx
 do
an
ban
bob
bxr
bxr
dod
n d
oba
odo
r b
r b
xr
xr

In HEX:
C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type BB003.txt
20626f
206278
20646f
616e20
62616e
626f62
627872
627872
646f64
6e2064
6f6261
6f646f
722062
722062
787220
787220

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>Building-Blocks_DUMPER.exe
Building-Blocks_DUMPER rev.1, written by Kaze.
Sorting 16 Pointers to Building-Blocks 3 chars in size ...
Allocated memory for pointers-to-words in MB: 1
Writing Sorted Building-Blocks to BB003.txt ...
3|18-3+1|13|3

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type BB003.txt
 bo
 bx
 do
an
ban
bob
bxr
dod
n d
oba
odo
r b
xr

C:\WorkTemp\LEPREC~1\VISUAL~1\LEA56D~1>type osho.txt
*/

/*

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>Compile_Intel.bat

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>icl /Ox /TcBuilding-Blocks_DUMPER.c /FaB
uilding-Blocks_DUMPER /w /FAcs
Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.4.196 Build 20110427
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.
30 DAY EVALUATION LICENSE

icl: NOTE: The evaluation period for this product ends on 25-aug-2011 UTC.
Building-Blocks_DUMPER.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:Building-Blocks_DUMPER.exe
Building-Blocks_DUMPER.obj

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>Building-Blocks_DUMPER.exe
Building-Blocks_DUMPER rev.1+, written by Kaze.
Note1: This is the precursor of Simplicius Simplicissimus - a superfast-low-performance TEXT decompressor.
Note2: The niftiness lies in readiness for multi-threading and mostly in boosting the search by having the BBs.
       The decompressor would upload (at burst speed) the BB data and then read-and-decode one-by-one the
       triads (BB pool/array indexes), that is a simple copying. The pool houses up to 256*256*256 BBs/elements.
Note3: Compiler used: Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.4.196 Build 20110427.
Note4: Compile line: icl /Ox /TcBuilding-Blocks_DUMPER.c /FaBuilding-Blocks_DUMPER /w /FAcs
Note5: Maximum size of input text file is arbitrary - 384MB, in fact 384MB+4*384MB must be less than 19??MB.
Note6: The file format is given by typing the compressed file e.g. D:\>type OSHO.TXT.SS.
       The header is 270 bytes long followed by BBs and triads/indexes and the eventual remainder/literals.
Note7: My benchmark text file OSHO.TXT 206,908,949 bytes where OSHO.TXT.SS 116,871,584 bytes:
       Decompressing OSHO.TXT.SS to RAM without Dumping to DRIVE time: 2736 clocks, an awful result, grmbl.
       Obviously the fastest cache size is crucial, for OSHO.TXT 12MB BB pool vs 1MB L1 cache disbalance is the
       cause for this badly inferior performance comparing with LZ cache-friendly variants.
Note8: For more fast decompressing idea(s) you may contact me at sanmayce@sanmayce.com freely.

Usage: Building-Blocks_DUMPER textfilename
Example1: Building-Blocks_DUMPER The_Little_Match_Girl.txt
Example2: Building-Blocks_DUMPER The_Little_Match_Girl.txt.SS
Note: When the extension is not .SS then compression is commenced otherwise decompression.

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>Building-Blocks_DUMPER.exe OSHO.TXT
Building-Blocks_DUMPER rev.1+, written by Kaze.
Note1: This is the precursor of Simplicius Simplicissimus - a superfast-low-performance TEXT decompressor.
Note2: The niftiness lies in readiness for multi-threading and mostly in boosting the search by having the BBs.
       The decompressor would upload (at burst speed) the BB data and then read-and-decode one-by-one the
       triads (BB pool/array indexes), that is a simple copying. The pool houses up to 256*256*256 BBs/elements.
Note3: Compiler used: Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.4.196 Build 20110427.
Note4: Compile line: icl /Ox /TcBuilding-Blocks_DUMPER.c /FaBuilding-Blocks_DUMPER /w /FAcs
Note5: Maximum size of input text file is arbitrary - 384MB, in fact 384MB+4*384MB must be less than 19??MB.
Note6: The file format is given by typing the compressed file e.g. D:\>type OSHO.TXT.SS.
       The header is 270 bytes long followed by BBs and triads/indexes and the eventual remainder/literals.
Note7: My benchmark text file OSHO.TXT 206,908,949 bytes where OSHO.TXT.SS 116,871,584 bytes:
       Decompressing OSHO.TXT.SS to RAM without Dumping to DRIVE time: 2736 clocks, an awful result, grmbl.
       Obviously the fastest cache size is crucial, for OSHO.TXT 12MB BB pool vs 1MB L1 cache disbalance is the
       cause for this badly inferior performance comparing with LZ cache-friendly variants.
Note8: For more fast decompressing idea(s) you may contact me at sanmayce@sanmayce.com freely.

Allocating 384MB ... OK

Examining BB orders 3 to 16 whether they are codeable within 3bytes i.e. 16,777,216 ...
Size of incoming file or Strnglen: 206908949

Sorting 206908947 Pointers to Building-Blocks 3 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB003.txt ...
Patternlen:3|206908949-3+1|linecounterRL:46486|206862461
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): -139458

Sorting 206908946 Pointers to Building-Blocks 4 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB004.txt ...
Patternlen:4|206908949-4+1|linecounterRL:248019|206660927
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 50735161

Sorting 206908945 Pointers to Building-Blocks 5 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB005.txt ...
Patternlen:5|206908949-5+1|linecounterRL:855682|206053263
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 78485168

Sorting 206908944 Pointers to Building-Blocks 6 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB006.txt ...
Patternlen:6|206908949-6+1|linecounterRL:2236138|204672806
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 90037644

Sorting 206908943 Pointers to Building-Blocks 7 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB007.txt ...
Patternlen:7|206908949-7+1|linecounterRL:4803152|202105791
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 84611620

Sorting 206908942 Pointers to Building-Blocks 8 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB008.txt ...
Patternlen:8|206908949-8+1|linecounterRL:8956496|197952446
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 57666122

Sorting 206908941 Pointers to Building-Blocks 9 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB009.txt ...
Patternlen:9|206908949-9+1|linecounterRL:15006172|191902769
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 2883750

Sorting 206908940 Pointers to Building-Blocks 10 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB010.txt ...
Patternlen:10|206908949-10+1|linecounterRL:22992127|183916813
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): -85085012

Maximum compression (or minimum expansion) for order: 6

Creating OSHO.TXT.SS ...

Building-Blocks_DUMPER .SS dumping time: 42720 clocks
Building-Blocks_DUMPER total time: 1869829 clocks

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>dir
 Volume in drive D is S640_Vol5
 Volume Serial Number is F85D-148B

 Directory of D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel

08/22/2011  01:08 AM    <DIR>          .
08/22/2011  01:08 AM    <DIR>          ..
08/22/2011  12:41 AM           139,458 BB003.txt
08/22/2011  12:45 AM           992,076 BB004.txt
08/22/2011  12:49 AM         4,278,410 BB005.txt
08/22/2011  12:52 AM        13,416,828 BB006.txt
08/22/2011  12:56 AM        33,622,064 BB007.txt
08/22/2011  01:00 AM        71,651,968 BB008.txt
08/22/2011  01:04 AM       135,055,548 BB009.txt
08/22/2011  01:08 AM       229,921,270 BB010.txt
08/22/2011  12:33 AM            72,814 Building-Blocks_DUMPER.c
08/22/2011  12:38 AM           917,642 Building-Blocks_DUMPER.cod
08/22/2011  12:38 AM           103,424 Building-Blocks_DUMPER.exe
08/22/2011  12:38 AM            34,431 Building-Blocks_DUMPER.obj
08/22/2011  12:34 AM                72 Compile_Intel.bat
08/21/2011  08:57 AM       206,908,949 OSHO.TXT
08/22/2011  01:09 AM       116,871,584 OSHO.TXT.SS
              15 File(s)    813,986,538 bytes
               2 Dir(s)  128,145,555,456 bytes free

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>type OSHO.TXT.SS
[Simplicius_Simplicissimus_revision_1]
The file format after the ASCII code 026:
1 byte for BB_Order,
4bytes for Original_Size,
4bytes for BB length,
BB itself,
3*(Original_Size/BB_Order) bytes of indexes followed by the (Original_Size%BB_Order) bytes of literals.
D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>Building-Blocks_DUMPER.exe OSHO.TXT.SS
Building-Blocks_DUMPER rev.1+, written by Kaze.
Note1: This is the precursor of Simplicius Simplicissimus - a superfast-low-performance TEXT decompressor.
Note2: The niftiness lies in readiness for multi-threading and mostly in boosting the search by having the BBs.
       The decompressor would upload (at burst speed) the BB data and then read-and-decode one-by-one the
       triads (BB pool/array indexes), that is a simple copying. The pool houses up to 256*256*256 BBs/elements.
Note3: Compiler used: Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.4.196 Build 20110427.
Note4: Compile line: icl /Ox /TcBuilding-Blocks_DUMPER.c /FaBuilding-Blocks_DUMPER /w /FAcs
Note5: Maximum size of input text file is arbitrary - 384MB, in fact 384MB+4*384MB must be less than 19??MB.
Note6: The file format is given by typing the compressed file e.g. D:\>type OSHO.TXT.SS.
       The header is 270 bytes long followed by BBs and triads/indexes and the eventual remainder/literals.
Note7: My benchmark text file OSHO.TXT 206,908,949 bytes where OSHO.TXT.SS 116,871,584 bytes:
       Decompressing OSHO.TXT.SS to RAM without Dumping to DRIVE time: 2736 clocks, an awful result, grmbl.
       Obviously the fastest cache size is crucial, for OSHO.TXT 12MB BB pool vs 1MB L1 cache disbalance is the
       cause for this badly inferior performance comparing with LZ cache-friendly variants.
Note8: For more fast decompressing idea(s) you may contact me at sanmayce@sanmayce.com freely.

Allocating 384MB ... OK

Simplicius Simplicissimus is decompressing OSHO.TXT ...
Allocating 256MB for BBs pool + 384MB for RAM-to-RAM decompression ... OK
BBs order: 6
Original file size: 206908949
BBs pool size: 13416828

Decompression to RAM without Dumping to DRIVE time: 2876 clocks
Decompression to RAM without Dumping to DRIVE performance: 70257 KB/s
Total time: 6595 clocks

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>Building-Blocks_DUMPER.exe OSHO.TXT.SS
Building-Blocks_DUMPER rev.1+, written by Kaze.
Note1: This is the precursor of Simplicius Simplicissimus - a superfast-low-performance TEXT decompressor.
Note2: The niftiness lies in readiness for multi-threading and mostly in boosting the search by having the BBs.
       The decompressor would upload (at burst speed) the BB data and then read-and-decode one-by-one the
       triads (BB pool/array indexes), that is a simple copying. The pool houses up to 256*256*256 BBs/elements.
Note3: Compiler used: Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.4.196 Build 20110427.
Note4: Compile line: icl /Ox /TcBuilding-Blocks_DUMPER.c /FaBuilding-Blocks_DUMPER /w /FAcs
Note5: Maximum size of input text file is arbitrary - 384MB, in fact 384MB+4*384MB must be less than 19??MB.
Note6: The file format is given by typing the compressed file e.g. D:\>type OSHO.TXT.SS.
       The header is 270 bytes long followed by BBs and triads/indexes and the eventual remainder/literals.
Note7: My benchmark text file OSHO.TXT 206,908,949 bytes where OSHO.TXT.SS 116,871,584 bytes:
       Decompressing OSHO.TXT.SS to RAM without Dumping to DRIVE time: 2736 clocks, an awful result, grmbl.
       Obviously the fastest cache size is crucial, for OSHO.TXT 12MB BB pool vs 1MB L1 cache disbalance is the
       cause for this badly inferior performance comparing with LZ cache-friendly variants.
Note8: For more fast decompressing idea(s) you may contact me at sanmayce@sanmayce.com freely.

Allocating 384MB ... OK

Simplicius Simplicissimus is decompressing OSHO.TXT ...
Allocating 256MB for BBs pool + 384MB for RAM-to-RAM decompression ... OK
BBs order: 6
Original file size: 206908949
BBs pool size: 13416828

Decompression to RAM without Dumping to DRIVE time: 2767 clocks
Decompression to RAM without Dumping to DRIVE performance: 73024 KB/s
Total time: 5251 clocks

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>Building-Blocks_DUMPER.exe OSHO.TXT.SS
Building-Blocks_DUMPER rev.1+, written by Kaze.
Note1: This is the precursor of Simplicius Simplicissimus - a superfast-low-performance TEXT decompressor.
Note2: The niftiness lies in readiness for multi-threading and mostly in boosting the search by having the BBs.
       The decompressor would upload (at burst speed) the BB data and then read-and-decode one-by-one the
       triads (BB pool/array indexes), that is a simple copying. The pool houses up to 256*256*256 BBs/elements.
Note3: Compiler used: Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.4.196 Build 20110427.
Note4: Compile line: icl /Ox /TcBuilding-Blocks_DUMPER.c /FaBuilding-Blocks_DUMPER /w /FAcs
Note5: Maximum size of input text file is arbitrary - 384MB, in fact 384MB+4*384MB must be less than 19??MB.
Note6: The file format is given by typing the compressed file e.g. D:\>type OSHO.TXT.SS.
       The header is 270 bytes long followed by BBs and triads/indexes and the eventual remainder/literals.
Note7: My benchmark text file OSHO.TXT 206,908,949 bytes where OSHO.TXT.SS 116,871,584 bytes:
       Decompressing OSHO.TXT.SS to RAM without Dumping to DRIVE time: 2736 clocks, an awful result, grmbl.
       Obviously the fastest cache size is crucial, for OSHO.TXT 12MB BB pool vs 1MB L1 cache disbalance is the
       cause for this badly inferior performance comparing with LZ cache-friendly variants.
Note8: For more fast decompressing idea(s) you may contact me at sanmayce@sanmayce.com freely.

Allocating 384MB ... OK

Simplicius Simplicissimus is decompressing OSHO.TXT ...
Allocating 256MB for BBs pool + 384MB for RAM-to-RAM decompression ... OK
BBs order: 6
Original file size: 206908949
BBs pool size: 13416828

Decompression to RAM without Dumping to DRIVE time: 2861 clocks
Decompression to RAM without Dumping to DRIVE performance: 70625 KB/s
Total time: 5517 clocks

D:\_KAZE_new-stuff\Building-Blocks_DUMPER_r1+_Simplicius_Simplicissimus\Intel>
*/

#define DumboDUMP
#define QuickS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#ifndef NULL
#define NULL ((void*)0)
#endif

typedef unsigned char char_t;
typedef char_t *string;

int Patternlen;      

clock_t clocks1, clocks2;
clock_t clocks3, clocks4;
double TotalRoughSearchTime = 0;
double TotalRoughSearchTime2 = 0;

// SINHA fragment[

#define swapKAZE(a, b) { t = *(a); *(a) = *(b); *(b) = t; }

static void InsertSortKAZE(string *a, int n, int d) //void inssort(unsigned char **a, int n, int d)
{   string *pi, *pj, s, t;                          //unsigned char **pi, **pj, *s, *t;
    for (pi = a + 1; --n > 0; pi++)
        for (pj = pi; pj > a; pj--) {
            /* Inline strcmp: break if *(pj-1) <= *pj */
            for (s=*(pj-1)+d, t=*pj+d; *s==*t && *s!=0; s++, t++)
                ;
            if (*s <= *t)
                break;
            swapKAZE(pj, pj-1);
    }
}

//int cmpit(unsigned char **h1, unsigned char **h2)
//{
//    return( scmp(*h1, *h2) );
//}

int scmp( unsigned char *s1, unsigned char *s2 )
{
    while( *s1 != '\0' && *s1 == *s2 )
    {
        s1++;
        s2++;
    }
    return( *s1-*s2 );
}

static void simplesort(string a[], int n, int b)
{
   int i, j;
   string tmp;

   for (i = 1; i < n; i++)
      for (j = i; j > 0 && scmp(a[j-1]+b, a[j]+b) > 0; j--)
         { tmp = a[j]; a[j] = a[j-1]; a[j-1] = tmp; }
}

int memcmpKAZE (
        const void * buf1,
        const void * buf2,
        size_t count
        )
{
        if (!count)
                return(0);

        while ( --count && *(char *)buf1 == *(char *)buf2 ) {
                buf1 = (char *)buf1 + 1;
                buf2 = (char *)buf2 + 1;
        }

        return( *((unsigned char *)buf1) - *((unsigned char *)buf2) );
}

void * memcpyKAZE (
        void * dst,
        const void * src,
        size_t count
        )
{
        void * ret = dst;

        /*
         * copy from lower addresses to higher addresses
         */
        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }
        return(ret);
}

static void simplesortFIXEDLength(string a[], int n, int b, int FIXEDLength)
{
   int i, j;
   string tmp;

   for (i = 1; i < n; i++)
      for (j = i; j > 0 && memcmpKAZE(a[j-1]+b, a[j]+b,FIXEDLength) > 0; j--)
         { tmp = a[j]; a[j] = a[j-1]; a[j-1] = tmp; }
}


// SINHA fragment]

// mkqsort.c BEGIN **********************************************************
/*
   Multikey quicksort, a radix sort algorithm for arrays of character
   strings by Bentley and Sedgewick.

   J. Bentley and R. Sedgewick. Fast algorithms for sorting and
   searching strings. In Proceedings of 8th Annual ACM-SIAM Symposium
   on Discrete Algorithms, 1997.

   http://www.CS.Princeton.EDU/~rs/strings/index.html

   The code presented in this file has been tested with care but is
   not guaranteed for any purpose. The writer does not offer any
   warranties nor does he accept any liabilities with respect to
   the code.

   Ranjan Sinha, 1 jan 2003.

   School of Computer Science and Information Technology,
   RMIT University, Melbourne, Australia
   rsinha@cs.rmit.edu.au

*/

//#include "sortstring.h"

/* MULTIKEY QUICKSORT */

#ifndef min
#define min(a, b) ((a)<=(b) ? (a) : (b))
#endif


/* ssort2 -- Faster Version of Multikey Quicksort */

void vecswap2(unsigned char **a, unsigned char **b, int n)
{   while (n-- > 0) {
        unsigned char *t = *a;
        *a++ = *b;
        *b++ = t;
    }
}

#define swap2(a, b) { t = *(a); *(a) = *(b); *(b) = t; }
#define ptr2char(i) (*(*(i) + depth))

unsigned char **med3func(unsigned char **a, unsigned char **b, unsigned char **c, int depth)
{   int va, vb, vc;
    if ((va=ptr2char(a)) == (vb=ptr2char(b)))
        return a;
    if ((vc=ptr2char(c)) == va || vc == vb)
        return c;       
    return va < vb ?
          (vb < vc ? b : (va < vc ? c : a ) )
        : (vb > vc ? b : (va < vc ? a : c ) );
}
#define med3(a, b, c) med3func(a, b, c, depth)

void inssort(unsigned char **a, int n, int d)
{   unsigned char **pi, **pj, *s, *t;
    for (pi = a + 1; --n > 0; pi++)
        for (pj = pi; pj > a; pj--) {
            /* Inline strcmp: break if *(pj-1) <= *pj */
            for (s=*(pj-1)+d, t=*pj+d; *s==*t && *s!=0; s++, t++)
                ;
            if (*s <= *t)
                break;
            swap2(pj, pj-1);
    }
}

void mkqsort(unsigned char **a, int n, int depth)
{   int d, r, partval;
    unsigned char **pa, **pb, **pc, **pd, **pl, **pm, **pn, *t;
											//printf("depth:%d\n",depth); // Silent exit when millions of equal 7bytes chunks: shitty recusrive approach !!!!!!!!!!
/*
The next dpeths are for file hs_ref_GRCh37.p5_chrX.fa:
...
depth:8
depth:9
depth:9
depth:10
depth:10
depth:11
depth:10
depth:9
depth:10
depth:10
depth:11
depth:11
depth:12
depth:10
depth:10
depth:11
depth:10
depth:9
depth:10
depth:10
depth:10
depth:11
depth:10
depth:11
depth:11
depth:11
depth:11
depth:12
depth:12
depth:12
depth:12
depth:13
depth:13
depth:14
depth:14
depth:15
depth:15
depth:16
depth:16
depth:17
depth:1
depth:1
depth:2
depth:3
depth:4
depth:5
depth:6
depth:7
depth:8
depth:9
depth:10
depth:11
depth:12
depth:13
depth:14
depth:15
depth:16
depth:17
depth:18
depth:19
depth:20
depth:21
depth:22
depth:23
depth:24
depth:25
depth:26
depth:27
depth:28
depth:29
depth:30
depth:31
depth:32
depth:33
depth:34
depth:35
depth:36
depth:37
depth:38
depth:39
depth:40
...
depth:903
depth:904
depth:905
depth:906
depth:907
depth:907
...
depth:2572
depth:2573
depth:2574
depth:2575
...
depth:3380
depth:3381
depth:3382
depth:3383
depth:3470
depth:3471
depth:3472
depth:3473
...
depth:21310
depth:21311
depth:21312
...
depth:21416
depth:21417
depth:21418

and self-exit at this depth! That is the program terminates itself as if no error occurred!
*/

    if (n < 20) {
        //inssort(a, n, depth);
          simplesortFIXEDLength(a, n, depth, Patternlen);
        return;
    }
    pl = a;
    pm = a + (n/2);
    pn = a + (n-1);
    if (n > 30) { /* On big arrays, pseudomedian of 9 */
        d = (n/8);
        pl = med3(pl, pl+d, pl+2*d);
        pm = med3(pm-d, pm, pm+d);
        pn = med3(pn-2*d, pn-d, pn);
    }
    pm = med3(pl, pm, pn);
    swap2(a, pm);
    partval = ptr2char(a);
    pa = pb = a + 1;
    pc = pd = a + n-1;
    for (;;) {
        while (pb <= pc && (r = ptr2char(pb)-partval) <= 0) {
            if (r == 0) { swap2(pa, pb); pa++; }
            pb++;
        }
        while (pb <= pc && (r = ptr2char(pc)-partval) >= 0) {
            if (r == 0) { swap2(pc, pd); pd--; }
            pc--;
       }
        if (pb > pc) break;
        swap2(pb, pc);
        pb++;
        pc--;
    }
    pn = a + n;
    r = min(pa-a, pb-pa);    vecswap2(a,  pb-r, r);
    r = min(pd-pc, pn-pd-1); vecswap2(pb, pn-r, r);
    if ((r = pb-pa) > 1)
        mkqsort(a, r, depth);
    if (ptr2char(a + r) != 0)
        mkqsort(a + r, pa-a + pn-pd-1, depth+1);
    if ((r = pd-pc) > 1)
        mkqsort(a + n-r, r, depth);
}

void mkqsort_main(unsigned char **a, int n) { mkqsort(a, n, 0); }
// mkqsort.c END ************************************************************

// Why Sinha uses int instead of long??!!
static int readlines(char *file_name, string **lines)
{
   int nlines = 0;
   size_t size;
   FILE *in_file;
   string basep, cur, next;
   string *ASbackup;

   if (!(in_file = fopen(file_name, "rb"))) {
      printf( "Leprechaun: Can't open file %s \n", file_name ); 
      exit(-1);
   }
   fseek(in_file, 0, SEEK_END);
   size = ftell(in_file);
   fseek(in_file, 0, SEEK_SET);
   if (!(basep = (string) malloc(size*sizeof(char_t)))) return -1;
   printf( "Allocated memory for words in MB: %lu\n", ((size*sizeof(char_t))>>20)+1 );
   if (fread(basep, 1, size, in_file) < size) {
      printf( "Leprechaun: Can't read file %s \n", file_name ); 
      exit(-1);
   }
   fclose(in_file);

// GET nlines:
   cur = basep;
   while (cur < basep + size) {
      next = cur;
      while ((next < basep + size) && (*next != '\n')) {next++;}
      *--next = '\0';          // This is ala DOS i.e. Windows
                               // 1310 not 10(\n=10)
      cur = next + 2;
      nlines++;
   }

// printf("%lu\n",(unsigned long)*lines); -> backup = *lines = 0
ASbackup = (string *)malloc( nlines*sizeof(string) ); // sizeof(string) is 4
if( ASbackup == NULL )
{ puts( "Leprechaun: Needed memory allocation denied!\n" ); return( 1 ); }
printf( "Allocated memory for pointers-to-words in MB: %lu\n", ((nlines*sizeof(string))>>20)+1 );
*lines = ASbackup;
//printf("%lu\n",(unsigned long)*lines); -> backup = *lines = ASbackup = 6946888

// Upload nlines times:
   nlines = 0;
   cur = basep;
   while (cur < basep + size) {
      next = cur;
      while ((next < basep + size) && (*next != '\n')) {next++;}
      *--next = '\0';          // This is ala DOS i.e. Windows
                               // 1310 not 10(\n=10)
      ASbackup[nlines] = cur;
      cur = next + 2;
      nlines++;
   }
   return nlines;
}

void x64toaKAZE (      /* stdcall is faster and smaller... Might as well use it for the helper. */
        unsigned long long val,
        char *buf,
        unsigned radix,
        int is_neg
        )
{
        char *p;                /* pointer to traverse string */
        char *firstdig;         /* pointer to first digit */
        char temp;              /* temp char */
        unsigned digval;        /* value of digit */

        p = buf;

        if ( is_neg )
        {
            *p++ = '-';         /* negative, so output '-' and negate */
            val = (unsigned long long)(-(long long)val);
        }

        firstdig = p;           /* save pointer to first digit */

        do {
            digval = (unsigned) (val % radix);
            val /= radix;       /* get next digit */

            /* convert to ascii and store */
            if (digval > 9)
                *p++ = (char) (digval - 10 + 'a');  /* a letter */
            else
                *p++ = (char) (digval + '0');       /* a digit */
        } while (val > 0);

        /* We now have the digit of the number in the buffer, but in reverse
           order.  Thus we reverse them now. */

        *p-- = '\0';            /* terminate string; p points to last digit */

        do {
            temp = *p;
            *p = *firstdig;
            *firstdig = temp;   /* swap *p and *firstdig */
            --p;
            ++firstdig;         /* advance to next two digits */
        } while (firstdig < p); /* repeat until halfway */
}

/* Actual functions just call conversion helper with neg flag set correctly,
   and return pointer to buffer. */

char * _i64toaKAZE (
        long long val,
        char *buf,
        int radix
        )
{
        x64toaKAZE((unsigned long long)val, buf, radix, (radix == 10 && val < 0));
        return buf;
}

char * _ui64toaKAZE (
        unsigned long long val,
        char *buf,
        int radix
        )
{
        x64toaKAZE(val, buf, radix, 0);
        return buf;
}

char * _ui64toaKAZEzerocomma (
        unsigned long long val,
        char *buf,
        int radix
        )
{
                        char *p;
                        char temp;
                        int txpman;
                        int pxnman;
        x64toaKAZE(val, buf, radix, 0);
                        p = buf;
                        do {
                        } while (*++p != '\0');
                        p--; // p points to last digit
                             // buf points to first digit
                        buf[26] = 0;
                        txpman = 1;
                        pxnman = 0;
                        do
                        { if (buf <= p)
                          { temp = *p;
                            buf[26-txpman] = temp; pxnman++;
                            p--;
                            if (pxnman % 3 == 0)
                            { txpman++;
                              buf[26-txpman] = (char) (',');
                            }
                          }
                          else
                          { buf[26-txpman] = (char) ('0'); pxnman++;
                            if (pxnman % 3 == 0)
                            { txpman++;
                              buf[26-txpman] = (char) (',');
                            }
                          }
                          txpman++;
                        } while (txpman <= 26);
        return buf;
}

char * _ui64toaKAZEcomma (
        unsigned long long val,
        char *buf,
        int radix
        )
{
                        char *p;
                        char temp;
                        int txpman;
                        int pxnman;
        x64toaKAZE(val, buf, radix, 0);
                        p = buf;
                        do {
                        } while (*++p != '\0');
                        p--; // p points to last digit
                             // buf points to first digit
                        buf[26] = 0;
                        txpman = 1;
                        pxnman = 0;
                        while (buf <= p)
                        { temp = *p;
                          buf[26-txpman] = temp; pxnman++;
                          p--;
                          if (pxnman % 3 == 0 && buf <= p)
                          { txpman++;
                            buf[26-txpman] = (char) (',');
                          }
                          txpman++;
                        } 
        return buf+26-(txpman-1);
}



int compVS2003 (
        const void * buf1,
        const void * buf2
        )
{
        unsigned long * buf1Nested = buf1;
        unsigned long * buf2Nested = buf2;
        void * buf1Fetched;
        void * buf2Fetched;
 
        buf1Fetched = *buf1Nested;
        buf2Fetched = *buf2Nested;

        return( memcmpKAZE ( buf1Fetched, buf2Fetched, Patternlen ) );

}



// QsortVS2003 [ =============================================================



/***
*swap(a, b, width) - swap two elements
*
*Purpose:
*       swaps the two array elements of size width
*
*Entry:
*       char *a, *b = pointer to two elements to swap
*       size_t width = width in bytes of each array element
*
*Exit:
*       returns void
*
*Exceptions:
*
*******************************************************************************/

static void swapVS2003 (
    char *a,
    char *b,
    size_t width
    )
{
    char tmp;

    if ( a != b )
        /* Do the swap one character at a time to avoid potential alignment
           problems. */
        while ( width-- ) {
            tmp = *a;
            *a++ = *b;
            *b++ = tmp;
        }
}




/***
*shortsort(hi, lo, width, comp) - insertion sort for sorting short arrays
*
*Purpose:
*       sorts the sub-array of elements between lo and hi (inclusive)
*       side effects:  sorts in place
*       assumes that lo < hi
*
*Entry:
*       char *lo = pointer to low element to sort
*       char *hi = pointer to high element to sort
*       size_t width = width in bytes of each array element
*       int (*comp)() = pointer to function returning analog of strcmp for
*               strings, but supplied by user for comparing the array elements.
*               it accepts 2 pointers to elements and returns neg if 1<2, 0 if
*               1=2, pos if 1>2.
*
*Exit:
*       returns void
*
*Exceptions:
*
*******************************************************************************/

static void shortsortVS2003 (
    char *lo,
    char *hi,
    size_t width,
    int (*compVS2003)(const void *, const void *)
    )
{
    char *p, *max;

    /* Note: in assertions below, i and j are alway inside original bound of
       array to sort. */

    while (hi > lo) {
        /* A[i] <= A[j] for i <= j, j > hi */
        max = lo;
        for (p = lo+width; p <= hi; p += width) {
            /* A[i] <= A[max] for lo <= i < p */
            if (compVS2003(p, max) > 0) {
                max = p;
            }
            /* A[i] <= A[max] for lo <= i <= p */
        }

        /* A[i] <= A[max] for lo <= i <= hi */

        swapVS2003(max, hi, width);

        /* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j, j >= hi */

        hi -= width;

        /* A[i] <= A[j] for i <= j, j > hi, loop top condition established */
    }
    /* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j] for i < j,
       so array is sorted */
}




/* this parameter defines the cutoff between using quick sort and
   insertion sort for arrays; arrays with lengths shorter or equal to the
   below value use insertion sort */

#define CUTOFF 8            /* testing shows that this is good value */

/***
*qsort(base, num, wid, comp) - quicksort function for sorting arrays
*
*Purpose:
*       quicksort the array of elements
*       side effects:  sorts in place
*       maximum array size is number of elements times size of elements,
*       but is limited by the virtual address space of the processor
*
*Entry:
*       char *base = pointer to base of array
*       size_t num  = number of elements in the array
*       size_t width = width in bytes of each array element
*       int (*comp)() = pointer to function returning analog of strcmp for
*               strings, but supplied by user for comparing the array elements.
*               it accepts 2 pointers to elements and returns neg if 1<2, 0 if
*               1=2, pos if 1>2.
*
*Exit:
*       returns void
*
*Exceptions:
*
*******************************************************************************/

/* sort the array between lo and hi (inclusive) */

#define STKSIZ (8*sizeof(void*) - 2)

void qsortVS2003 (
    void *base,
    size_t num,
    size_t width,
    int (*compVS2003)(const void *, const void *)
    )
{
    /* Note: the number of stack entries required is no more than
       1 + log2(num), so 30 is sufficient for any array */
    char *lo, *hi;              /* ends of sub-array currently sorting */
    char *mid;                  /* points to middle of subarray */
    char *loguy, *higuy;        /* traveling pointers for partition step */
    size_t size;                /* size of the sub-array */
    char *lostk[STKSIZ], *histk[STKSIZ];
    int stkptr;                 /* stack for saving sub-array to be processed */

    if (num < 2 || width == 0)
        return;                 /* nothing to do */

    stkptr = 0;                 /* initialize stack */

    lo = base;
    hi = (char *)base + width * (num-1);        /* initialize limits */

    /* this entry point is for pseudo-recursion calling: setting
       lo and hi and jumping to here is like recursion, but stkptr is
       preserved, locals aren't, so we preserve stuff on the stack */
recurse:

    size = (hi - lo) / width + 1;        /* number of el's to sort */

    /* below a certain size, it is faster to use a O(n^2) sorting method */
    if (size <= CUTOFF) {
        shortsortVS2003(lo, hi, width, compVS2003);
    }
    else {
        /* First we pick a partitioning element.  The efficiency of the
           algorithm demands that we find one that is approximately the median
           of the values, but also that we select one fast.  We choose the
           median of the first, middle, and last elements, to avoid bad
           performance in the face of already sorted data, or data that is made
           up of multiple sorted runs appended together.  Testing shows that a
           median-of-three algorithm provides better performance than simply
           picking the middle element for the latter case. */

        mid = lo + (size / 2) * width;      /* find middle element */

        /* Sort the first, middle, last elements into order */
        if (compVS2003(lo, mid) > 0) {
            swapVS2003(lo, mid, width);
        }
        if (compVS2003(lo, hi) > 0) {
            swapVS2003(lo, hi, width);
        }
        if (compVS2003(mid, hi) > 0) {
            swapVS2003(mid, hi, width);
        }

        /* We now wish to partition the array into three pieces, one consisting
           of elements <= partition element, one of elements equal to the
           partition element, and one of elements > than it.  This is done
           below; comments indicate conditions established at every step. */

        loguy = lo;
        higuy = hi;

        /* Note that higuy decreases and loguy increases on every iteration,
           so loop must terminate. */
        for (;;) {
            /* lo <= loguy < hi, lo < higuy <= hi,
               A[i] <= A[mid] for lo <= i <= loguy,
               A[i] > A[mid] for higuy <= i < hi,
               A[hi] >= A[mid] */

            /* The doubled loop is to avoid calling comp(mid,mid), since some
               existing comparison funcs don't work when passed the same
               value for both pointers. */

            if (mid > loguy) {
                do  {
                    loguy += width;
                } while (loguy < mid && compVS2003(loguy, mid) <= 0);
            }
            if (mid <= loguy) {
                do  {
                    loguy += width;
                } while (loguy <= hi && compVS2003(loguy, mid) <= 0);
            }

            /* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy,
               either loguy > hi or A[loguy] > A[mid] */

            do  {
                higuy -= width;
            } while (higuy > mid && compVS2003(higuy, mid) > 0);

            /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
               either higuy == lo or A[higuy] <= A[mid] */

            if (higuy < loguy)
                break;

            /* if loguy > hi or higuy == lo, then we would have exited, so
               A[loguy] > A[mid], A[higuy] <= A[mid],
               loguy <= hi, higuy > lo */

            swapVS2003(loguy, higuy, width);

            /* If the partition element was moved, follow it.  Only need
               to check for mid == higuy, since before the swap,
               A[loguy] > A[mid] implies loguy != mid. */

            if (mid == higuy)
                mid = loguy;

            /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top
               of loop is re-established */
        }

        /*     A[i] <= A[mid] for lo <= i < loguy,
               A[i] > A[mid] for higuy < i < hi,
               A[hi] >= A[mid]
               higuy < loguy
           implying:
               higuy == loguy-1
               or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */

        /* Find adjacent elements equal to the partition element.  The
           doubled loop is to avoid calling comp(mid,mid), since some
           existing comparison funcs don't work when passed the same value
           for both pointers. */

        higuy += width;
        if (mid < higuy) {
            do  {
                higuy -= width;
            } while (higuy > mid && compVS2003(higuy, mid) == 0);
        }
        if (mid >= higuy) {
            do  {
                higuy -= width;
            } while (higuy > lo && compVS2003(higuy, mid) == 0);
        }

        /* OK, now we have the following:
              higuy < loguy
              lo <= higuy <= hi
              A[i]  <= A[mid] for lo <= i <= higuy
              A[i]  == A[mid] for higuy < i < loguy
              A[i]  >  A[mid] for loguy <= i < hi
              A[hi] >= A[mid] */

        /* We've finished the partition, now we want to sort the subarrays
           [lo, higuy] and [loguy, hi].
           We do the smaller one first to minimize stack usage.
           We only sort arrays of length 2 or more.*/

        if ( higuy - lo >= hi - loguy ) {
            if (lo < higuy) {
                lostk[stkptr] = lo;
                histk[stkptr] = higuy;
                ++stkptr;
            }                           /* save big recursion for later */

            if (loguy < hi) {
                lo = loguy;
                goto recurse;           /* do small recursion */
            }
        }
        else {
            if (loguy < hi) {
                lostk[stkptr] = loguy;
                histk[stkptr] = hi;
                ++stkptr;               /* save big recursion for later */
            }

            if (lo < higuy) {
                hi = higuy;
                goto recurse;           /* do small recursion */
            }
        }
    }

    /* We have sorted the array, except for any pending sorts on the stack.
       Check if there are any, and do them. */

    --stkptr;
    if (stkptr >= 0) {
        lo = lostk[stkptr];
        hi = histk[stkptr];
        goto recurse;           /* pop subarray from stack */
    }
    else
        return;                 /* all subarrays done */
}



// QsortVS2003 ] =============================================================





















long Railgunhits=0;

#define ASIZE 256

// ### Boyer-Moore-Horspool algorithm [
long HORSPOOL(y, x, n, m)
    char *y, *x;
    long n;
    int m;
   {
    long i;
    int a, j, bm_bc[ASIZE];
    unsigned char ch, lastch;
   
    /* Preprocessing */
    for (a=0; a < ASIZE; a++) bm_bc[a]=m;
    for (j=0; j < m-1; j++) bm_bc[x[j]]=m-j-1;
   
    /* Searching */
    lastch=x[m-1];
    i=0;
    while (i <= n-m) {
       ch=y[i+m-1];
       if (ch ==lastch)
          //if (memcmp(&y[i],x,m-1) == 0) OUTPUT(i);
          if (memcmp(&y[i],x,m-1) == 0) return(i);
       i+=bm_bc[ch];
    }
    return(-1);
   }
long Boyer_Moore_Horspool_Kaze(y, x, n, m)
    char *y, *x;
    long n;
    int m;
   {
    long i;
    int a, j, bm_bc[ASIZE];
    unsigned char ch;
    //unsigned char ch, lastch;
    //unsigned char firstch;
   
    /* Preprocessing */
    for (a=0; a < ASIZE; a++) bm_bc[a]=m;
    for (j=0; j < m-1; j++) bm_bc[x[j]]=m-j-1;
   
    /* Searching */
    //lastch=x[m-1];
    //firstch=x[0];
    i=0;
    while (i <= n-m) {
       ch=y[i+m-1];
       //if (ch ==lastch)
          //if (memcmp(&y[i],x,m-1) == 0) OUTPUT(i);
// Below line gives: 315KB/clock
          //if (ch ==lastch && y[i] == firstch && memcmp(&y[i],x,m-1) == 0) return(i);  // Kaze: The idea(to prevent execution of slower 'memcmp') is borrowed from Karp-Rabin i.e. to perform a slower check only when the target "looks like".
// Below line gives: 328KB/clock
          if (ch ==x[m-1] && y[i] == x[0] && memcmp(&y[i],x,m-1) == 0) return(i);  // Kaze: The idea(to prevent execution of slower 'memcmp') is borrowed from Karp-Rabin i.e. to perform a slower check only when the target "looks like".
       i+=bm_bc[ch];
    }
    return(-1);
   }
// ### Boyer-Moore-Horspool algorithm ]


// ### Brute force 'Dummy' algorithm [
   long Brute_Force_Dummy(char *y, char *x, long n, int m) {
    long i, j;
  
    /* Searching */
    for (i=0; i <= n-m; i++) {
       j=0;
       while (j < m && y[i+j] == x[j]) j++;
       if (j >= m) return(i);
    }
    return(-1);
   }
// ### Brute force 'Dummy' algorithm ]


// ### Karp-Rabin algorithm [
   #define REHASH(a, b, h) ((((h) - (a)*d) << 1) + (b))
   long Karp_Rabin(char *y, char *x, long n, int m) {
   int d, hx, hy, i, j;

   /* Preprocessing */
   /* computes d = 2^(m-1) with
      the left-shift operator */
   for (d = i = 1; i < m; ++i)
      d = (d<<1);

   for (hy = hx = i = 0; i < m; ++i) {
      hx = ((hx<<1) + x[i]);
      hy = ((hy<<1) + y[i]);
   }

   /* Searching */
   j = 0;
   while (j <= n-m) {
      if (hx == hy && memcmp(x, y + j, m) == 0) return(j);
      hy = REHASH(y[j], y[j + m], hy);
      ++j;
   }
    return(-1);
   }
// ### Karp-Rabin algorithm ]


// ### Karp-Rabin-Kaze algorithm [
char * KarpRabinKaze (char * pbTarget,
     char * pbPattern,
     unsigned long cbTarget,
     unsigned long cbPattern)
{
    unsigned int    i;
    char *  pbTargetMax = pbTarget + cbTarget;
    char *  pbPatternMax = pbPattern + cbPattern;
    unsigned long  ulBaseToPowerMod = 1;
    register unsigned long  ulHashPattern = 0;
    unsigned long  ulHashTarget = 0;
long hits = 0;
//unsigned long count;
    //char *  buf1;
    //char *  buf2;

    if (cbPattern > cbTarget)
        return(NULL);

    // Compute the power of the left most character in base ulBase
    //for (i = 1; i < cbPattern; i++) ulBaseToPowerMod = (ulBase * ulBaseToPowerMod);

    // Calculate the hash function for the src (and the first dst)
    while (pbPattern < pbPatternMax)
    {
        // Below lines give 366KB/clock for 'underdog':
        //ulHashPattern = (ulHashPattern*ulBase + *pbPattern);
        //ulHashTarget = (ulHashTarget*ulBase + *pbTarget);
        pbPattern++;
        pbTarget++;
    }
        // Below lines give 436KB/clock for 'underdog' + requirement pattern to be 4 chars min.:
        //ulHashPattern = ( (*(long *)(pbPattern-cbPattern)) & 0xffffff00 ) + *(pbPattern-1);
        //ulHashTarget = ( (*(long *)(pbTarget-cbPattern)) & 0xffffff00 ) + *(pbTarget-1);
        // Below lines give 482KB/clock for 'underdog' + requirement pattern to be 2 chars min.:
        //ulHashPattern = ( (*(unsigned short *)(pbPattern-cbPattern)) | *(pbPattern-1) );
        //ulHashTarget = ( (*(unsigned short *)(pbTarget-cbPattern)) | *(pbTarget-1) );
        // Below lines give 482KB/clock for 'underdog' + requirement pattern to be 2 chars min.:
        //ulHashPattern = ( (*(unsigned short *)(pbPattern-cbPattern)) & 0xff00 ) + *(pbPattern-1);
        //ulHashTarget = ( (*(unsigned short *)(pbTarget-cbPattern)) & 0xff00 ) + *(pbTarget-1);
        // Below lines give 605KB/clock for 'underdog' + requirement pattern to be 2 chars min.:
        //ulHashPattern = ( (*(unsigned short *)(pbPattern-cbPattern))<<8 ) + *(pbPattern-1);
        //ulHashTarget = ( (*(unsigned short *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1);
        // Below lines give 668KB/clock for 'underdog':
        ulHashPattern = ( (*(char *)(pbPattern-cbPattern))<<8 ) + *(pbPattern-1);
        ulHashTarget = ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1);

    // Dynamically produce hash values for the string as we go
    for ( ;; )
    {
        if ( (ulHashPattern == ulHashTarget) && !memcmp(pbPattern-cbPattern, pbTarget-cbPattern, (unsigned int)cbPattern) )
       // if ( ulHashPattern == ulHashTarget ) {
       // 
       //  count = cbPattern;
       //  buf1 = pbPattern-cbPattern;
       //  buf2 = pbTarget-cbPattern;
       //  while ( --count && *(char *)buf1 == *(char *)buf2 ) {
       //          buf1 = (char *)buf1 + 1;
       //          buf2 = (char *)buf2 + 1;
       //  }
       //                 
       //  if ( *((unsigned char *)buf1) - *((unsigned char *)buf2) == 0) hits++;
       //  }
            return((pbTarget-cbPattern));
            //hits++;
                                                             
        if (pbTarget == pbTargetMax)
            return(NULL);

        // Below line gives 482KB/clock for 'underdog' + requirement pattern to be 2 chars min.:
        //ulHashTarget = ( (*(unsigned short *)(pbTarget+1-cbPattern)) | *pbTarget );
        // Below line gives 436KB/clock for 'underdog' + requirement pattern to be 4 chars min.:
        //ulHashTarget = ( (*(long *)(pbTarget+1-cbPattern)) & 0xffffff00 ) + *pbTarget;
//; Line 696
//        movsx   esi, BYTE PTR [ebx]
//        mov     ecx, DWORD PTR [edx+1]
//        and     ecx, -256                               ; ffffff00H
//        add     ecx, esi
        // Below line gives 482KB/clock for 'underdog' + requirement pattern to be 2 chars min.:
        //ulHashTarget = ( (*(unsigned short *)(pbTarget+1-cbPattern)) & 0xff00 ) + *pbTarget;
//; Line 691
//        movsx   esi, BYTE PTR [ebx]
//        xor     ecx, ecx
//        mov     cx, WORD PTR [edx+1]
//        and     ecx, 65280                              ; 0000ff00H
//        add     ecx, esi
        // Below line gives 605KB/clock for 'underdog' + requirement pattern to be 2 chars min.:
        //ulHashTarget = ( (*(unsigned short *)(pbTarget+1-cbPattern))<<8 ) + *pbTarget;
        // Below line gives 668KB/clock for 'underdog':
        ulHashTarget = ( (*(char *)(pbTarget+1-cbPattern))<<8 ) + *pbTarget;
//; Line 718
//        movsx   ecx, BYTE PTR [eax+1]
//        movsx   edx, BYTE PTR [ebp]
//        shl     ecx, 8
//        add     ecx, edx
        // Below line gives 366KB/clock for 'underdog':
        //ulHashTarget = (ulHashTarget - *(pbTarget-cbPattern)*ulBaseToPowerMod)*ulBase + *pbTarget;
        pbTarget++;
    }
}
// ### Karp-Rabin-Kaze algorithm ]


// ### Mix(2in1) of Karp-Rabin & Boyer-Moore-Horspool algorithm [
// Caution: For better speed the case 'if (cbPattern==1)' was removed, so Pattern must be longer than 1 char.
char * Railgun (char * pbTarget,
     char * pbPattern,
     unsigned long cbTarget,
     unsigned long cbPattern)
{
    char *  pbTargetMax = pbTarget + cbTarget;
    register unsigned long  ulHashPattern;
    unsigned long  ulHashTarget;
    unsigned long  count;
    unsigned long  countSTATIC, countRemainder;

    long i; //BMH needed
    int a, j, bm_bc[ASIZE]; //BMH needed
    unsigned char ch; //BMH needed
//    unsigned char lastch, firstch; //BMH needed

    if (cbPattern > cbTarget)
        return(NULL);

        countSTATIC = cbPattern-2;

// Doesn't work when cbPattern = 1
if (cbTarget<961) // This value is arbitrary(don't know how exactly), it ensures(at least must) better performance than 'Boyer_Moore_Horspool'.
{
        pbTarget = pbTarget+cbPattern;
        ulHashPattern = ( (*(char *)(pbPattern))<<8 ) + *(pbPattern+(cbPattern-1));

    for ( ;; )
    {
        // The line below gives for 'cbPattern'>=1:
        // Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/543
        // Karp_Rabin_Kaze_4_OCTETS performance: 372KB/clock
/*
        if ( (ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1)) && !memcmp(pbPattern, pbTarget-cbPattern, (unsigned int)cbPattern) )
            return((long)(pbTarget-cbPattern));
*/

        // The fragment below gives for 'cbPattern'>=2:
        // Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/546
        // Karp_Rabin_Kaze_4_OCTETS performance: 370KB/clock

        if ( ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1) ) {
         count = countSTATIC;
         while ( count && *(char *)(pbPattern+1+(countSTATIC-count)) == *(char *)(pbTarget-cbPattern+1+(countSTATIC-count)) ) {
               count--;
         }
         if ( count == 0) return((pbTarget-cbPattern));
        }

        // The fragment below gives for 'cbPattern'>=2:
	// Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/554
	// Karp_Rabin_Kaze_4_OCTETS performance: 364KB/clock
/*
        if ( ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1) ) {
         count = countSTATIC>>2;
         countRemainder = countSTATIC % 4;

         while ( count && *(unsigned long *)(pbPattern+1+((count-1)<<2)) == *(unsigned long *)(pbTarget-cbPattern+1+((count-1)<<2)) ) {
               count--;
         }
	 //if (count == 0) {  // Disastrous degradation only from this line(317KB/clock when 1+2x4+2+1 bytes pattern: 'skillessness'; 312KB/clock when 1+1x4+2+1 bytes pattern: 'underdog'), otherwise 368KB/clock.
         while ( countRemainder && *(char *)(pbPattern+1+(countSTATIC-countRemainder)) == *(char *)(pbTarget-cbPattern+1+(countSTATIC-countRemainder)) ) {
               countRemainder--;
         }
         //if ( countRemainder == 0) return((long)(pbTarget-cbPattern));
         if ( count+countRemainder == 0) return((long)(pbTarget-cbPattern));
         //}
        }
*/

        pbTarget++;
        if (pbTarget > pbTargetMax)
            return(NULL);
    }
}
else
{
    /* Preprocessing */
    for (a=0; a < ASIZE; a++) bm_bc[a]=cbPattern;
    for (j=0; j < cbPattern-1; j++) bm_bc[pbPattern[j]]=cbPattern-j-1;

    /* Searching */
    //lastch=pbPattern[cbPattern-1];
    //firstch=pbPattern[0];
    i=0;
    while (i <= cbTarget-cbPattern) {
       ch=pbTarget[i+cbPattern-1];
       //if (ch ==lastch)
          //if (memcmp(&pbTarget[i],pbPattern,cbPattern-1) == 0) OUTPUT(i);
          //if (ch == lastch && pbTarget[i] == firstch && memcmp(&pbTarget[i],pbPattern,cbPattern-1) == 0) return(i);  // Kaze: The idea(to prevent execution of slower 'memcmp') is borrowed from Karp-Rabin i.e. to perform a slower check only when the target "looks like".
          if (ch == pbPattern[cbPattern-1] && pbTarget[i] == pbPattern[0])
             {
         count = countSTATIC;
         while ( count && *(char *)(pbPattern+1+(countSTATIC-count)) == *(char *)(&pbTarget[i]+1+(countSTATIC-count)) ) {
               count--;
         }
         if ( count == 0) return(pbTarget+i);
	     }
       i+=bm_bc[ch];
    }
    return(NULL);
}
}
// ### Mix(2in1) of Karp-Rabin & Boyer-Moore-Horspool algorithm ]


// ### Railgun_totalhits [
char * Railgun_totalhits (char * pbTarget,
     char * pbPattern,
     unsigned long cbTarget,
     unsigned long cbPattern)
{
    char *  pbTargetMax = pbTarget + cbTarget;
    register unsigned long  ulHashPattern;
    unsigned long  ulHashTarget;
    unsigned long  count;
    unsigned long  countSTATIC, countRemainder;

    long i; //BMH needed
    int a, j, bm_bc[ASIZE]; //BMH needed
    unsigned char ch; //BMH needed
//    unsigned char lastch, firstch; //BMH needed

    if (cbPattern > cbTarget)
        return(NULL);

        countSTATIC = cbPattern-2;

// Doesn't work when cbPattern = 1
if (cbTarget<961) // This value is arbitrary(don't know how exactly), it ensures(at least must) better performance than 'Boyer_Moore_Horspool'.
{
        pbTarget = pbTarget+cbPattern;
        ulHashPattern = ( (*(char *)(pbPattern))<<8 ) + *(pbPattern+(cbPattern-1));

    for ( ;; )
    {
        // The line below gives for 'cbPattern'>=1:
        // Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/543
        // Karp_Rabin_Kaze_4_OCTETS performance: 372KB/clock
/*
        if ( (ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1)) && !memcmp(pbPattern, pbTarget-cbPattern, (unsigned int)cbPattern) )
            return((long)(pbTarget-cbPattern));
*/

        // The fragment below gives for 'cbPattern'>=2:
        // Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/546
        // Karp_Rabin_Kaze_4_OCTETS performance: 370KB/clock

        if ( ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1) ) {
         count = countSTATIC;
         while ( count && *(char *)(pbPattern+1+(countSTATIC-count)) == *(char *)(pbTarget-cbPattern+1+(countSTATIC-count)) ) {
               count--;
         }
         if ( count == 0) Railgunhits++; //return((pbTarget-cbPattern));
        }

        // The fragment below gives for 'cbPattern'>=2:
	// Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/554
	// Karp_Rabin_Kaze_4_OCTETS performance: 364KB/clock
/*
        if ( ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1) ) {
         count = countSTATIC>>2;
         countRemainder = countSTATIC % 4;

         while ( count && *(unsigned long *)(pbPattern+1+((count-1)<<2)) == *(unsigned long *)(pbTarget-cbPattern+1+((count-1)<<2)) ) {
               count--;
         }
	 //if (count == 0) {  // Disastrous degradation only from this line(317KB/clock when 1+2x4+2+1 bytes pattern: 'skillessness'; 312KB/clock when 1+1x4+2+1 bytes pattern: 'underdog'), otherwise 368KB/clock.
         while ( countRemainder && *(char *)(pbPattern+1+(countSTATIC-countRemainder)) == *(char *)(pbTarget-cbPattern+1+(countSTATIC-countRemainder)) ) {
               countRemainder--;
         }
         //if ( countRemainder == 0) return((long)(pbTarget-cbPattern));
         if ( count+countRemainder == 0) return((long)(pbTarget-cbPattern));
         //}
        }
*/

        pbTarget++;
        if (pbTarget > pbTargetMax)
            return(NULL);
    }
}
else
{
    /* Preprocessing */
    for (a=0; a < ASIZE; a++) bm_bc[a]=cbPattern;
    for (j=0; j < cbPattern-1; j++) bm_bc[pbPattern[j]]=cbPattern-j-1;

    /* Searching */
    //lastch=pbPattern[cbPattern-1];
    //firstch=pbPattern[0];
    i=0;
    while (i <= cbTarget-cbPattern) {
       ch=pbTarget[i+cbPattern-1];
       //if (ch ==lastch)
          //if (memcmp(&pbTarget[i],pbPattern,cbPattern-1) == 0) OUTPUT(i);
          //if (ch == lastch && pbTarget[i] == firstch && memcmp(&pbTarget[i],pbPattern,cbPattern-1) == 0) return(i);  // Kaze: The idea(to prevent execution of slower 'memcmp') is borrowed from Karp-Rabin i.e. to perform a slower check only when the target "looks like".
          if (ch == pbPattern[cbPattern-1] && pbTarget[i] == pbPattern[0])
             {
         count = countSTATIC;
         while ( count && *(char *)(pbPattern+1+(countSTATIC-count)) == *(char *)(&pbTarget[i]+1+(countSTATIC-count)) ) {
               count--;
         }
         if ( count == 0) Railgunhits++; //return(pbTarget+i);
	     }
       i+=bm_bc[ch];
    }
    return(NULL);
}
}
// ### Railgun_totalhits ]


// ### Karp-Rabin-Kaze_BOOSTED algorithm [
char * KarpRabinKaze_BOOSTED (char * pbTarget,
     char * pbPattern,
     unsigned long cbTarget,
     unsigned long cbPattern)
{
    char *  pbTargetMax = pbTarget + cbTarget;
    register unsigned long  ulHashPattern;
    unsigned long  ulHashTarget;

    if (cbPattern > cbTarget)
        return(NULL);

        pbTarget = pbTarget+cbPattern;
        ulHashPattern = ( (*(char *)(pbPattern))<<8 ) + *(pbPattern+(cbPattern-1));

    for ( ;; )
    {
        // Kaze: The idea(FAILED) here is to add an additional(second) layer in order to prevent execution of slower hash calculation(i.e. first layer) which(hash) prevents execution of even slower 'memcmp'.
        // The line below gives: 314KB/clock
        //if ( *pbPattern == *(char *)(pbTarget-cbPattern) && (ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1)) && !memcmp(pbPattern, pbTarget-cbPattern, (unsigned int)cbPattern) )
        // The line below gives: 370KB/clock
        if ( (ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1)) && !memcmp(pbPattern, pbTarget-cbPattern, (unsigned int)cbPattern) )
            return((pbTarget-cbPattern));

        pbTarget++;
        if (pbTarget > pbTargetMax)
            return(NULL);
    }
}
// ### Karp-Rabin-Kaze_BOOSTED algorithm ]

char * strstr_Microsoft (
        const char * str1,
        const char * str2
        )
{
        char *cp = (char *) str1;
        char *s1, *s2;

        if ( !*str2 )
            return((char *)str1);

        while (*cp)
        {
                s1 = cp;
                s2 = (char *) str2;

                while ( *s1 && *s2 && !(*s1-*s2) )
                        s1++, s2++;

                if (!*s2)
                        return(cp);

                cp++;
        }
        return(NULL);
}

char *
strstr_GNU_C_Library (phaystack, pneedle)
     const char *phaystack;
     const char *pneedle;
{
  const unsigned char *haystack, *needle;
  char b;
  const unsigned char *rneedle;

  haystack = (const unsigned char *) phaystack;

  if ((b = *(needle = (const unsigned char *) pneedle)))
    {
      char c;
      haystack--;		/* possible ANSI violation */

      {
	char a;
	do
	  if (!(a = *++haystack))
	    goto ret0;
	while (a != b);
      }

      if (!(c = *++needle))
	goto foundneedle;
      ++needle;
      goto jin;

      for (;;)
	{
	  {
	    char a;
	    if (0)
	    jin:{
		if ((a = *++haystack) == c)
		  goto crest;
	      }
	    else
	      a = *++haystack;
	    do
	      {
		for (; a != b; a = *++haystack)
		  {
		    if (!a)
		      goto ret0;
		    if ((a = *++haystack) == b)
		      break;
		    if (!a)
		      goto ret0;
		  }
	      }
	    while ((a = *++haystack) != c);
	  }
	crest:
	  {
	    char a;
	    {
	      const unsigned char *rhaystack;
	      if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle)))
		do
		  {
		    if (!a)
		      goto foundneedle;
		    if (*++rhaystack != (a = *++needle))
		      break;
		    if (!a)
		      goto foundneedle;
		  }
		while (*++rhaystack == (a = *++needle));
	      needle = rneedle;	/* took the register-poor aproach */
	    }
	    if (!a)
	      break;
	  }
	}
    }
foundneedle:
  return (char *) haystack;
ret0:
  return 0;
}


// ### Mix(2in1) of Karp-Rabin & Boyer-Moore-Horspool algorithm [
// Caution: For better speed the case 'if (cbPattern==1)' was removed, so Pattern must be longer than 1 char.
char * Railgun_Quadruplet (char * pbTarget,
     char * pbPattern,
     unsigned long cbTarget,
     unsigned long cbPattern)
{
    char * pbTargetMax = pbTarget + cbTarget;
    register unsigned long  ulHashPattern;
    unsigned long ulHashTarget;
    unsigned long count;
    unsigned long countSTATIC;
//  unsigned long countRemainder;

/*
    const unsigned char SINGLET = *(char *)(pbPattern);
    const unsigned long Quadruplet2nd = SINGLET<<8;
    const unsigned long Quadruplet3rd = SINGLET<<16;
    const unsigned long Quadruplet4th = SINGLET<<24;
*/
    unsigned char SINGLET;
    unsigned long Quadruplet2nd;
    unsigned long Quadruplet3rd;
    unsigned long Quadruplet4th;

    unsigned long  AdvanceHopperGrass;

    long i; //BMH needed
    int a, j, bm_bc[ASIZE]; //BMH needed
    unsigned char ch; //BMH needed
//    unsigned char lastch, firstch; //BMH needed

    if (cbPattern > cbTarget)
        return(NULL);

// Doesn't work when cbPattern = 1
// The next IF-fragment works very well with cbPattern>1, OBVIOUSLY IT MUST BE UNROLLED(but crippled with less functionality) SINCE either cbPattern=2 or cbPattern=3!
if ( cbPattern<4) { // This IF makes me unhappy: it slows down from 390KB/clock to 367KB/clock for 'fast' pattern. This fragment(for 2..3 pattern lengths) is needed because I need a function different than strchr but sticking to strstr i.e. lengths above 1 are to be handled.
        pbTarget = pbTarget+cbPattern;
        ulHashPattern = ( (*(char *)(pbPattern))<<8 ) + *(pbPattern+(cbPattern-1));
        countSTATIC = cbPattern-2;

    for ( ;; )
    {
        // The line below gives for 'cbPattern'>=1:
        // Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/543
        // Karp_Rabin_Kaze_4_OCTETS performance: 372KB/clock
/*
        if ( (ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1)) && !memcmp(pbPattern, pbTarget-cbPattern, (unsigned int)cbPattern) )
            return((long)(pbTarget-cbPattern));
*/

        // The fragment below gives for 'cbPattern'>=2:
        // Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/546
        // Karp_Rabin_Kaze_4_OCTETS performance: 370KB/clock

        if ( ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1) ) {
         count = countSTATIC;
         while ( count && *(char *)(pbPattern+1+(countSTATIC-count)) == *(char *)(pbTarget-cbPattern+1+(countSTATIC-count)) ) {
               count--;
         }
         if ( count == 0) return((pbTarget-cbPattern));
        }

        // The fragment below gives for 'cbPattern'>=2:
	// Karp_Rabin_Kaze_4_OCTETS_hits/Karp_Rabin_Kaze_4_OCTETS_clocks: 4/554
	// Karp_Rabin_Kaze_4_OCTETS performance: 364KB/clock
/*
        if ( ulHashPattern == ( (*(char *)(pbTarget-cbPattern))<<8 ) + *(pbTarget-1) ) {
         count = countSTATIC>>2;
         countRemainder = countSTATIC % 4;

         while ( count && *(unsigned long *)(pbPattern+1+((count-1)<<2)) == *(unsigned long *)(pbTarget-cbPattern+1+((count-1)<<2)) ) {
               count--;
         }
	 //if (count == 0) {  // Disastrous degradation only from this line(317KB/clock when 1+2x4+2+1 bytes pattern: 'skillessness'; 312KB/clock when 1+1x4+2+1 bytes pattern: 'underdog'), otherwise 368KB/clock.
         while ( countRemainder && *(char *)(pbPattern+1+(countSTATIC-countRemainder)) == *(char *)(pbTarget-cbPattern+1+(countSTATIC-countRemainder)) ) {
               countRemainder--;
         }
         //if ( countRemainder == 0) return((long)(pbTarget-cbPattern));
         if ( count+countRemainder == 0) return((long)(pbTarget-cbPattern));
         //}
        }
*/

        pbTarget++;
        if (pbTarget > pbTargetMax)
            return(NULL);
    }
} else { //if ( cbPattern<4)
if (cbTarget<961) // This value is arbitrary(don't know how exactly), it ensures(at least must) better performance than 'Boyer_Moore_Horspool'.
{
        pbTarget = pbTarget+cbPattern;
        ulHashPattern = *(unsigned long *)(pbPattern);
        countSTATIC = cbPattern-1;

    //SINGLET = *(char *)(pbPattern);
    SINGLET = ulHashPattern & 0xFF;
    Quadruplet2nd = SINGLET<<8;
    Quadruplet3rd = SINGLET<<16;
    Quadruplet4th = SINGLET<<24;

    for ( ;; )
    {
	AdvanceHopperGrass = 0;
	ulHashTarget = *(unsigned long *)(pbTarget-cbPattern);

        if ( ulHashPattern == ulHashTarget ) { // Three unnecessary comparisons here, but 'AdvanceHopperGrass' must be calculated - it has a higher priority.
         count = countSTATIC;
         while ( count && *(char *)(pbPattern+1+(countSTATIC-count)) == *(char *)(pbTarget-cbPattern+1+(countSTATIC-count)) ) {
	       if ( countSTATIC==AdvanceHopperGrass+count && SINGLET != *(char *)(pbTarget-cbPattern+1+(countSTATIC-count)) ) AdvanceHopperGrass++;
               count--;
         }
         if ( count == 0) return((pbTarget-cbPattern));
        } else { // The goal here: to avoid memory accesses by stressing the registers.
    if ( Quadruplet2nd != (ulHashTarget & 0x0000FF00) ) {
         AdvanceHopperGrass++;
         if ( Quadruplet3rd != (ulHashTarget & 0x00FF0000) ) {
              AdvanceHopperGrass++;
              if ( Quadruplet4th != (ulHashTarget & 0xFF000000) ) AdvanceHopperGrass++;;
         }
    }
	}

	AdvanceHopperGrass++;

	pbTarget = pbTarget + AdvanceHopperGrass;
        if (pbTarget > pbTargetMax)
            return(NULL);
    }
} else { //if (cbTarget<961)
        countSTATIC = cbPattern-2;
    /* Preprocessing */
    for (a=0; a < ASIZE; a++) bm_bc[a]=cbPattern;
    for (j=0; j < cbPattern-1; j++) bm_bc[pbPattern[j]]=cbPattern-j-1;

    /* Searching */
    //lastch=pbPattern[cbPattern-1];
    //firstch=pbPattern[0];
    i=0;
    while (i <= cbTarget-cbPattern) {
       ch=pbTarget[i+cbPattern-1];
       //if (ch ==lastch)
          //if (memcmp(&pbTarget[i],pbPattern,cbPattern-1) == 0) OUTPUT(i);
          //if (ch == lastch && pbTarget[i] == firstch && memcmp(&pbTarget[i],pbPattern,cbPattern-1) == 0) return(i);  // Kaze: The idea(to prevent execution of slower 'memcmp') is borrowed from Karp-Rabin i.e. to perform a slower check only when the target "looks like".
          if (ch == pbPattern[cbPattern-1] && pbTarget[i] == pbPattern[0])
             {
         count = countSTATIC;
         while ( count && *(char *)(pbPattern+1+(countSTATIC-count)) == *(char *)(&pbTarget[i]+1+(countSTATIC-count)) ) {
               count--;
         }
         if ( count == 0) return(pbTarget+i);
	     }
       i+=bm_bc[ch];
    }
    return(NULL);
} //if (cbTarget<961)
} //if ( cbPattern<4)
}
// ### Mix(2in1) of Karp-Rabin & Boyer-Moore-Horspool algorithm ]

void strip_ext(unsigned char *str)
{
   int i;
   for(i = strlen(str)-1; str[i] != '.' && i >= 0; i--)
      ;
   if(i > 0)
      str[i] = '\0';
}

int main( int argc, char *argv[] )

  {
FILE *fp_inLINE;
FILE *fp_outLINE;
int Bozan;
long ThunderwithL, ThunderwithR;
char *Strng;
char *BB;
long Strnglen;
long StrnglenTRAVERSED;
char Pattern[20+2000]; // skillessness=12 human consciousness=19 I should have known=19
// In the East, enlightenment is described as a state of ultimate=62
//int Patternlen;      // Make it global in sake of QSORT
long LinesEncountered=0;
long BruteForceDummyhits=0;
long KarpRabinKazehits=0;
long KarpRabinKaze_BOOSTEDhits=0;
long Karp_Rabin_Kaze_4_OCTETShits=0;
long KarpRabinhits=0;
long HORSPOOLhits=0;
long HORSPOOL_Kazehits=0;
long strstrMicrosofthits=0;
long strstrGNUCLibraryhits=0;

   unsigned char *bufEXTENSION;

//int i, j;
int i,j;
register int iREGISTER;
register int jREGISTER;

char *DumboBox[8][2] = { "an\0", "to\0",
                         "TDK\0", "the\0",
                         "fast\0", "easy\0",
                         "grmbl\0", "email\0",
                         "pasting\0", "amazing\0",
                         "underdog\0", "superdog\0",
                         "participants\0", "skillessness\0",
                         "I should have known\0", "human consciousness\0"
};

long FoundIn;
char *FoundInPTR,*FoundInPTRNEW;
char llTOaDigits[27]; // 9,223,372,036,854,775,807: 1(sign or carry)+19(digits)+1('\0')+6(,)
char BuildingBlocksBox[10] = "BB---.txt\0";

   int nlines = 0;
   string basep, cur, next;
   string *ASbackup;

   unsigned long nlines1, linecounterNotRL, linecounterRL, jPrevLine, jFirst;

signed long GainMax=0x80000000; //-2147483648
int GainOrder=0; register int GainOrderREGISTER;
signed int NataliaKills;
int YabbaYabba = 0;
long LeftPointBS, RightPointBS, PivotPointBS;
char SSheader[270];

printf("Simplicius_Simplicissimus_Septupleton rev.2-, written by Kaze.\n");
printf("Note1: This is the precursor of Simplicius Simplicissimus - a superfast-low-performance TEXT decompressor.\n");
printf("Note2: The niftiness lies in readiness for multi-threading and mostly in boosting the search by having the BBs.\n");
printf("       The decompressor would upload (at burst speed) the BB data and then read-and-decode one-by-one the\n");
printf("       triads (BB pool/array indexes), that is a simple copying. The pool houses up to 256*256*256 BBs/elements.\n");
printf("Note3: Compiler used: Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.4.196 Build 20110427.\n");
printf("Note4: Compile line: icl /Ox /TcBuilding-Blocks_DUMPER.c /FaBuilding-Blocks_DUMPER /w /FAcs\n");
printf("Note5: Maximum size of input text file is arbitrary - 384MB, in fact 384MB+4*384MB must be less than 19??MB.\n");
printf("Note6: The file format is given by typing the compressed file e.g. D:\\>type OSHO.TXT.SS.\n");
printf("       The header is 270 bytes long followed by BBs and triads/indexes and the eventual remainder/literals.\n");
printf("Note7: My benchmark text file OSHO.TXT 206,908,949 bytes where OSHO.TXT.SS 116,871,584 bytes for order 6:\n");
printf("       Decompressing OSHO.TXT.SS to RAM without Dumping to DRIVE time: 1704 clocks or 118579 KB/s, an awful result.\n");
printf("       For order 4 enforced: 156,174,067 OSHO.TXT.SS is being decompressed at 192804 KB/s.\n");
printf("       For order 7 enforced: 122,297,608 OSHO.TXT.SS is being decompressed at 85618 KB/s.\n");
printf("       For order 8 enforced: 149,243,106 OSHO.TXT.SS is being decompressed at 115396 KB/s.\n");
printf("       Obviously the fastest cache size is crucial, for OSHO.TXT 12MB BB pool vs 1MB L2 cache disbalance is the\n");
printf("       cause for this badly inferior performance compared to LZ L1 (32KB) cache-friendly variants.\n");
printf("       The test machine is Toshiba Satellite with Intel Merom 2166MHz, with rough 'memcpy' performance: 1646 MB/s.\n");
printf("Note8: Compile line: cl /Ox /TcBuilding-Blocks_DUMPER.c /FaBuilding-Blocks_DUMPER /w /FAcs\n");
printf("Note9: Major (but still inferior) decompressing tweak since r.1+++, this time Microsoft v16 excels:\n");
printf("       For order 7 enforced: 122,297,608 OSHO.TXT.SS is being decompressed at 170083 KB/s.\n");
printf("NoteA: Simplicius_Simplicissimus stands up for his name, the decompressing fragment is 13 instructions small:\n");
printf("       $LL74@main:\n");
printf("       a1 00 00 00 00   mov     eax, DWORD PTR _Patternlen\n");
printf("       03 c2            add     eax, edx\n");
printf("       8b 04 30         mov     eax, DWORD PTR [eax+esi]\n");
printf("       25 ff ff ff 00   and     eax, 16777215\n");
printf("       0f af c7         imul    eax, edi\n");
printf("       8b 1c 30         mov     ebx, DWORD PTR [eax+esi]\n");
printf("       89 19            mov     DWORD PTR [ecx], ebx\n");
printf("       8b 44 30 04      mov     eax, DWORD PTR [eax+esi+4]\n");
printf("       89 41 04         mov     DWORD PTR [ecx+4], eax\n");
printf("       83 c2 03         add     edx, 3\n");
printf("       03 cf            add     ecx, edi\n");
printf("       ff 4c 24 1c      dec     DWORD PTR tv977[esp+376]\n");
printf("       75 d7            jne     SHORT $LL74@main\n");
printf("NoteB: For more fast decompressing idea(s) you may contact me at sanmayce@sanmayce.com freely.\n");
printf("NoteC: Got it? The B note has two meanings: 1] for faster 2] for additional/other fast.\n");
printf("NoteD: Got it? The C note has two meanings: 1] for quicker/tighter 2] for additional/other quick/tight.\n");
printf("NoteE: Since r.2- a new Quicksort function is in use due to the bugginess of the old.\n");
printf("NoteF: A stupid bug (one triad was missing) was crushed also.\n");


Pattern[0]=0x00;

if( argc != 2 )
{ printf( "\nUsage: Building-Blocks_DUMPER textfilename\n" );
  printf( "Example1: Building-Blocks_DUMPER The_Little_Match_Girl.txt\n" );
  printf( "Example2: Building-Blocks_DUMPER The_Little_Match_Girl.txt.SS\n" );
  printf( "Note: When the extension is not .SS then compression is commenced otherwise decompression.\n" );
  return( 1 ); }

if( ( fp_inLINE = fopen( argv[1], "rb" ) ) == NULL )
{ printf( "Building-Blocks_DUMPER: Can't open file %s \n", argv[1] ); return( 1 ); }

printf( "\nAllocating 384MB ... " );
Strng = (char *)malloc( 384*1024*1024 +1); // +1 because one byte is read beyond pool!
if( Strng == NULL )
{ puts( "Building-Blocks_DUMPER: Needed memory allocation denied!\n" ); return( 1 ); }
printf( "OK\n" );

clocks3 = clock();

// DECOMPRESSOR [
if(toupper(argv[1][strlen(argv[1])-1]) == 'S' && toupper(argv[1][strlen(argv[1])-2]) == 'S' && argv[1][strlen(argv[1])-3] == '.') {
	bufEXTENSION = (unsigned char *) malloc(sizeof (unsigned char) * (strlen(argv[1])+1)); //when checking for .SS
	strcpy(bufEXTENSION, argv[1]);
	strip_ext(bufEXTENSION);
printf ("\nSimplicius Simplicissimus is decompressing %s ...\n",bufEXTENSION);
if( ( fp_outLINE = fopen( bufEXTENSION, "wb" ) ) == NULL )
{ printf( "Building-Blocks_DUMPER: Can't open file %s \n", bufEXTENSION ); return( 1 ); }

printf( "Allocating 256MB for BBs pool + 384MB for RAM-to-RAM decompression ... " ); // 16order*16,777,216BBs + (384MB/3order)*3bytes
BB = (char *)malloc( 256*1024*1024 + 384*1024*1024 +1); // +1 because one byte is read beyond pool!
if( BB == NULL )
{ puts( "Building-Blocks_DUMPER: Needed memory allocation denied!\n" ); return( 1 ); }
printf( "OK\n" );

// Uploading BB file to BB pool: 

fread(SSheader, 1, 270, fp_inLINE);
fread((unsigned char *)&GainOrder+0, 1, 1, fp_inLINE);
fread((unsigned char *)&Strnglen+0, 1, 4, fp_inLINE);
fread((unsigned char *)&Patternlen+0, 1, 4, fp_inLINE);
fread(BB, 1, Patternlen, fp_inLINE);

printf ("BBs order: %lu\nOriginal file size: %lu\nBBs pool size: %lu\n",GainOrder,Strnglen,Patternlen);

/*
// Not buffered input, slow slow slow - SHOULD BE quickened! No need of 384MB RAM-to-RAM block! [
      for( j = 0; j < Strnglen / GainOrder; j++ )
   {
ThunderwithL=0; // Zeroing the highest byte i.e. the fourth
fread((unsigned char *)&ThunderwithL+0, 1, 3, fp_inLINE);
fwrite((unsigned char *)BB+GainOrder*ThunderwithL, 1, GainOrder, fp_outLINE);
   }
ThunderwithL=Strnglen % GainOrder;
while (ThunderwithL) {
fread((unsigned char *)&ThunderwithR+0, 1, 1, fp_inLINE);
fwrite((unsigned char *)&ThunderwithR+0, 1, 1, fp_outLINE);
ThunderwithL--;
}
// Not buffered input, slow slow slow - SHOULD BE quickened! No need of 384MB RAM-to-RAM block! ]
*/

// Buffered input, just for OSHO.TXT because for max order 16 and max BBs 16,777,216 the BB pool cannot house the triads for bigger files! [
fread((unsigned char *)BB+Patternlen, 1, 3*(Strnglen / GainOrder), fp_inLINE);


goto SubUGLYSLOW;
// UGLY SLOW !!! [
iREGISTER=Strnglen / GainOrder;
GainOrderREGISTER=GainOrder;

if (Strnglen % GainOrderREGISTER)
fread((unsigned char *)BB+Patternlen+3*(Strnglen / GainOrderREGISTER), 1, Strnglen % GainOrderREGISTER, fp_inLINE);
      for( jREGISTER = 0; jREGISTER < iREGISTER; jREGISTER++ )
   {
//ThunderwithL=0; // Zeroing the highest byte i.e. the fourth
//memcpy (&ThunderwithL, BB+Patternlen+jREGISTER*3, 3);
memcpy (Strng+GainOrderREGISTER*jREGISTER, BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ), GainOrderREGISTER);
   }
if (Strnglen % GainOrderREGISTER)
memcpy (Strng+GainOrderREGISTER*(Strnglen / GainOrderREGISTER), BB+Patternlen+3*(Strnglen / GainOrderREGISTER), Strnglen % GainOrderREGISTER);

// UGLY SLOW !!! ]

// Microsoft compiler 16 gives:
/*
; 1740 :       for( jREGISTER = 0; jREGISTER < iREGISTER; jREGISTER++ )

  016f1	85 db		 test	 ebx, ebx
  016f3	7e 4e		 jle	 SHORT $LN69@main
  016f5	8b 44 24 2c	 mov	 eax, DWORD PTR _Strng$[esp+376]
  016f9	8b 4c 24 1c	 mov	 ecx, DWORD PTR tv1216[esp+376]
  016fd	33 db		 xor	 ebx, ebx
  016ff	89 44 24 14	 mov	 DWORD PTR tv1897[esp+376], eax
  01703	89 4c 24 24	 mov	 DWORD PTR tv1057[esp+376], ecx
  01707	eb 07 8d a4 24
	00 00 00 00	 npad	 9
$LL71@main:

; 1741 :    {
; 1742 : //ThunderwithL=0; // Zeroing the highest byte i.e. the fourth
; 1743 : //memcpy (&ThunderwithL, BB+Patternlen+jREGISTER*3, 3);
; 1744 : memcpy (Strng+GainOrderREGISTER*jREGISTER, BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ), GainOrderREGISTER);

  01710	8b 15 00 00 00
	00		 mov	 edx, DWORD PTR _Patternlen
  01716	8d 04 13	 lea	 eax, DWORD PTR [ebx+edx]
  01719	8b 0c 30	 mov	 ecx, DWORD PTR [eax+esi]
  0171c	8b 54 24 14	 mov	 edx, DWORD PTR tv1897[esp+376]
  01720	81 e1 ff ff ff
	00		 and	 ecx, 16777215		; 00ffffffH
  01726	0f af cf	 imul	 ecx, edi
  01729	57		 push	 edi
  0172a	03 ce		 add	 ecx, esi
  0172c	51		 push	 ecx
  0172d	52		 push	 edx
  0172e	e8 00 00 00 00	 call	 _memcpy
  01733	01 7c 24 20	 add	 DWORD PTR tv1897[esp+388], edi
  01737	83 c4 0c	 add	 esp, 12			; 0000000cH
  0173a	83 c3 03	 add	 ebx, 3
  0173d	ff 4c 24 24	 dec	 DWORD PTR tv1057[esp+376]
  01741	75 cd		 jne	 SHORT $LL71@main
$LN69@main:

; 1745 :    }
*/

SubUGLYSLOW:
goto SubSubUGLYSLOW;
// SUB UGLY SLOW !!! [
iREGISTER=Strnglen / GainOrder;
GainOrderREGISTER=GainOrder;

if (Strnglen % GainOrderREGISTER)
fread((unsigned char *)BB+Patternlen+3*(Strnglen / GainOrderREGISTER), 1, Strnglen % GainOrderREGISTER, fp_inLINE);
      for( jREGISTER = 0; jREGISTER < iREGISTER; jREGISTER++ ) // Unroll by 4 triads in next r.1++++, that is, read into 3 32bit registers 4 triads i.e. 12bytes and >> << &.
   {
//ThunderwithL=0; // Zeroing the highest byte i.e. the fourth
//memcpy (&ThunderwithL, BB+Patternlen+jREGISTER*3, 3);
//memcpy (Strng+GainOrderREGISTER*jREGISTER, BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ), GainOrderREGISTER);

// r.1+++ [
//Dumbo64REGISTER = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
//*(long long *)(Strng+GainOrderREGISTER*jREGISTER)=Dumbo64REGISTER;
*(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
// r.1+++ ]
   }
if (Strnglen % GainOrderREGISTER)
memcpy (Strng+GainOrderREGISTER*(Strnglen / GainOrderREGISTER), BB+Patternlen+3*(Strnglen / GainOrderREGISTER), Strnglen % GainOrderREGISTER);

// SUB UGLY SLOW !!! ]

// Microsoft compiler 16 gives:
/*
; 1811 :       for( jREGISTER = 0; jREGISTER < iREGISTER; jREGISTER++ ) // Unroll by 4 triads in next r.1++++, that is, read into 3 32bit registers 4 triads i.e. 12bytes and >> << &.

  0173d	85 db		 test	 ebx, ebx
  0173f	7e 38		 jle	 SHORT $LN72@main
  01741	8b 4c 24 18	 mov	 ecx, DWORD PTR _Strng$[esp+376]
  01745	33 d2		 xor	 edx, edx
  01747	89 5c 24 1c	 mov	 DWORD PTR tv977[esp+376], ebx
  0174b	eb 03 8d 49 00	 npad	 5
$LL74@main:

; 1812 :    {
; 1813 : //ThunderwithL=0; // Zeroing the highest byte i.e. the fourth
; 1814 : //memcpy (&ThunderwithL, BB+Patternlen+jREGISTER*3, 3);
; 1815 : //memcpy (Strng+GainOrderREGISTER*jREGISTER, BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ), GainOrderREGISTER);
; 1816 : 
; 1817 : // r.1+++ [
; 1818 : //Dumbo64REGISTER = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
; 1819 : //*(long long *)(Strng+GainOrderREGISTER*jREGISTER)=Dumbo64REGISTER;
; 1820 : *(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));

  01750	a1 00 00 00 00	 mov	 eax, DWORD PTR _Patternlen
  01755	03 c2		 add	 eax, edx
  01757	8b 04 30	 mov	 eax, DWORD PTR [eax+esi]
  0175a	25 ff ff ff 00	 and	 eax, 16777215		; 00ffffffH
  0175f	0f af c7	 imul	 eax, edi
  01762	8b 1c 30	 mov	 ebx, DWORD PTR [eax+esi]
  01765	89 19		 mov	 DWORD PTR [ecx], ebx
  01767	8b 44 30 04	 mov	 eax, DWORD PTR [eax+esi+4]
  0176b	89 41 04	 mov	 DWORD PTR [ecx+4], eax
  0176e	83 c2 03	 add	 edx, 3
  01771	03 cf		 add	 ecx, edi
  01773	ff 4c 24 1c	 dec	 DWORD PTR tv977[esp+376]
  01777	75 d7		 jne	 SHORT $LL74@main
$LN72@main:

; 1821 : // r.1+++ ]
; 1822 :    }
*/

SubSubUGLYSLOW: //// Notice that 42<64, but the threefold unrolling boosts (despite of exceeding 64) from 16300KB/s to 17000KB/s.
// SUB SUB UGLY SLOW !!! [
iREGISTER=Strnglen / GainOrder; //iREGISTER=iREGISTER-(iREGISTER%3); Fixed BUG here, how stupid!
GainOrderREGISTER=GainOrder;

if (Strnglen % GainOrderREGISTER)
fread((unsigned char *)BB+Patternlen+3*(Strnglen / GainOrderREGISTER), 1, Strnglen % GainOrderREGISTER, fp_inLINE);
      for( jREGISTER = 0; jREGISTER < iREGISTER; jREGISTER++ )
   {
//ThunderwithL=0; // Zeroing the highest byte i.e. the fourth
//memcpy (&ThunderwithL, BB+Patternlen+jREGISTER*3, 3);
//memcpy (Strng+GainOrderREGISTER*jREGISTER, BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ), GainOrderREGISTER);

// r.1++++ [
//Dumbo64REGISTER = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
//*(long long *)(Strng+GainOrderREGISTER*jREGISTER)=Dumbo64REGISTER;
*(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
jREGISTER++;
*(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
jREGISTER++;
*(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
// r.1++++ ]
   }
if ((Strnglen / GainOrder)%3==1) 
{
jREGISTER++;
*(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
}
if ((Strnglen / GainOrder)%3==2) 
{
jREGISTER++;
*(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
jREGISTER++;
*(long long *)(Strng+GainOrderREGISTER*jREGISTER) = *(long long *)(BB+GainOrderREGISTER*( 0x00FFFFFF & *(unsigned long *)(BB+Patternlen+jREGISTER*3) ));
}

if (Strnglen % GainOrderREGISTER)
memcpy (Strng+GainOrderREGISTER*(Strnglen / GainOrderREGISTER), BB+Patternlen+3*(Strnglen / GainOrderREGISTER), Strnglen % GainOrderREGISTER);

// SUB SUB UGLY SLOW !!! ]


clocks1 = clock();
TotalRoughSearchTime2 = clocks1 - clocks3; TotalRoughSearchTime2++;
printf( "\nDecompression to RAM without Dumping to DRIVE time: %lu clocks\n", (long)(TotalRoughSearchTime2));
printf( "Decompression to RAM without Dumping to DRIVE performance: %lu KB/s or %lu MB/s\n", (long)((Strnglen/TotalRoughSearchTime2)*1000)>>10, ((long)((Strnglen/TotalRoughSearchTime2)*1000)>>10)>>10);
fwrite(Strng, 1, Strnglen, fp_outLINE);
// Buffered input, just for OSHO.TXT because for max order 16 and max BBs 16,777,216 the BB pool cannot house the triads for bigger files! ]

clocks2 = clock();
TotalRoughSearchTime = clocks2 - clocks3; TotalRoughSearchTime++;
printf( "Total time: %lu clocks\n", (long)(TotalRoughSearchTime));

printf ("\nBenchmarking 'memcpy' by copying 197MB (OSHO.TXT size) ten times ...\n");
	clocks3 = clock();
	for (i=0; i<10; i++)
	memcpy (Strng, BB, 197*1024*1024);
	clocks2 = clock();
	clocks2 = clock();
TotalRoughSearchTime = clocks2 - clocks3; TotalRoughSearchTime++;
printf( "Simplicius says for 'memcpy' performance: %lu MB/s\n", 1970000/(long)(TotalRoughSearchTime));
printf( "Simplicius says for Decompression Ratio: %lu%%\n", (((long)((Strnglen/TotalRoughSearchTime2)*1000)>>10)*100)/((1970000/(long)(TotalRoughSearchTime))*1024) );

fclose (fp_inLINE);
fclose (fp_outLINE);
free (BB);
free (Strng);
return -1;
}
// DECOMPRESSOR ]

   fseek(fp_inLINE, 0, SEEK_END);
   Strnglen = ftell(fp_inLINE);
   fseek(fp_inLINE, 0, SEEK_SET);
if (Strnglen>384*1024*1024)
{ printf( "Building-Blocks_DUMPER: File cannot be loaded, it exceeds 384MB limit.\n" ); return( 1 ); }
   fread(Strng, 1, Strnglen, fp_inLINE);
   fclose(fp_inLINE);

//printf("Input Pattern(up to 19 chars): "); gets(Pattern); // char * __cdecl gets(char *);
//printf( "%s\n", _ui64toaKAZEzerocomma (7, llTOaDigits, 16)+(26-2));
//printf( "%s\n", _ui64toaKAZEzerocomma (Pattern[0], llTOaDigits, 16) +(26-2));
//printf( "%s\n", _ui64toaKAZEzerocomma (Pattern[1], llTOaDigits, 16) +(26-2));
//printf( "%s\n", _ui64toaKAZEzerocomma (Pattern[2], llTOaDigits, 16) +(26-2));
//exit(0);
//Patternlen = strlen(&Pattern[0]);

// Replacing CR with NULL i.e. 13->0
//	for (ThunderwithL=0; ThunderwithL<Strnglen; ThunderwithL++)
//		if (Strng[ThunderwithL] == 13) Strng[ThunderwithL] = 0;
//ThunderwithL=0;ThunderwithR=0;
//printf( "Doing Search for Pattern(%dbytes) into String(%dbytes) line-by-line ...\n", Patternlen, Strnglen);

//Patternlen=3; // 3..31
//printf( "\nExamining BB orders 3 to 16 whether they are codeable within 3bytes i.e. 16,777,216 ...\n");
printf( "\nEnforcing BB order 7 ...\n");
printf("Size of incoming file or Strnglen: %d\n",Strnglen);
//for( Patternlen = 3; Patternlen <=16; Patternlen++ )
for( Patternlen = 7; Patternlen <=7; Patternlen++ )
{ // MAIN CYCLE [

memcpy(&BuildingBlocksBox[2],_ui64toaKAZEzerocomma (Patternlen, llTOaDigits, 10) +(26-3),3);

printf( "\nSorting %lu Pointers to Building-Blocks %lu chars in size ...\n", Strnglen-Patternlen+1, Patternlen);

nlines = Strnglen-Patternlen+1;
ASbackup = (string *)malloc( nlines*sizeof(string) ); // sizeof(string) is 4
if( ASbackup == NULL )
{ puts( "Building-Blocks_DUMPER: Needed memory allocation denied!\n" ); return( 1 ); }
printf( "Allocated memory for pointers-to-words in MB: %lu\n", ((nlines*sizeof(string))>>20)+1 );


// ASSIGNING POINTERS ... [
   cur = Strng;
      for( j = 0; j < nlines; j++ )
   {
      ASbackup[j] = cur;
//printf("%d %d %d\n",*(ASbackup[j]+0),*(ASbackup[j]+1),*(ASbackup[j]+2));
      cur = cur + 1;
   }
// ASSIGNING POINTERS ... ]


// SORTING POINTERS ... [
#if defined(QuickS)
//void mkqsort_main(unsigned char **a, int n) { mkqsort(a, n, 0); }
//mkqsort_main(ASbackup, nlines); // Buggy!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
qsortVS2003(ASbackup, nlines,4, compVS2003);

#else
//simplesortFIXEDLength(string a[], int n, int b, int FIXEDLength)
simplesortFIXEDLength(ASbackup, nlines, 0, Patternlen);
#endif
// SORTING POINTERS ... ]


// WRITING SORTED ... [
      if( ( fp_inLINE = fopen( &BuildingBlocksBox[0], "wb+" ) ) == NULL )
      { printf( "Building-Blocks_DUMPER: Can't create file %s\n", &BuildingBlocksBox[0] ); return( 1 ); }
printf( "Writing Sorted Building-Blocks to %s ...\n", &BuildingBlocksBox[0]);
goto SORTED_witout_DUPLICATES;

      for( j = 0; j < nlines; j++ )
      { //Slot = KuxHash3plus(ASbackup[j]);
        //fprintf(fp_out, "Hashcode: %s - ", _ui64toaKAZEzerocomma(Slot, llTOaDigits, 10)+(26-5));
        //fprintf(fp_inLINE, "%s\n", ASbackup[j]);
	    for ( i=0;i<Patternlen; i++)
	    fprintf(fp_inLINE, "%c", *(ASbackup[j]+i));
	    //fprintf(fp_inLINE, "%s", _ui64toaKAZEzerocomma (*(ASbackup[j]+i), llTOaDigits, 16) +(26-2));
	    fprintf(fp_inLINE, "\n");
//        fwrite(CRdLFa, 2, 1, fp_out );
//if (strlen(backup[j]) >=3) {
//        fprintf(fp_out2, "%s", backup[j]);
//        fwrite(CRdLFa, 2, 1, fp_out2 );
//}
      }
// WRITING SORTED ... ]
SORTED_witout_DUPLICATES:

// REMOVING DUPLICATES ... [
      linecounterNotRL = nlines;
      nlines1 = linecounterNotRL;
      linecounterRL = 0;

      jFirst = 0;
                                      if (linecounterNotRL == 1) {
                                          //fprintf(fp_inLINE, "%s\n", ASbackup[jFirst]);
#if defined(DumboDUMP)
					    for ( i=0;i<Patternlen; i++)
					    fprintf(fp_inLINE, "%c", *(ASbackup[jFirst]+i));
					    //fprintf(fp_inLINE, "\n");
#endif
                                          linecounterRL++;
                                      }
      jPrevLine = jFirst;
                linecounterNotRL--;
      for( j = jFirst + 1; j < nlines1; j++ )
      {
                if (linecounterNotRL != 0) {
                linecounterNotRL--;


                //if ( strcmpKAZE(ASbackup[jPrevLine], ASbackup[j]) != 0 ) {
                if ( memcmpKAZE(ASbackup[jPrevLine], ASbackup[j], Patternlen) != 0 ) {
                     //fprintf(fp_inLINE, "%s\n", ASbackup[jPrevLine]);
#if defined(DumboDUMP)
					    for ( i=0;i<Patternlen; i++)
					    fprintf(fp_inLINE, "%c", *(ASbackup[jPrevLine]+i));
					    //fprintf(fp_inLINE, "\n");
#endif
                     linecounterRL++;
                }

                if (linecounterNotRL == 0) {
                                          //fprintf(fp_inLINE, "%s\n", ASbackup[j]);
#if defined(DumboDUMP)
					    for ( i=0;i<Patternlen; i++)
					    fprintf(fp_inLINE, "%c", *(ASbackup[j]+i));
					    //fprintf(fp_inLINE, "\n");
#endif
                                          linecounterRL++;
                }
                jPrevLine = j;
                }
      }
// REMOVING DUPLICATES ... ]

printf("Patternlen:%d|%d-%d+1|linecounterRL:%d|%d\n",Patternlen,Strnglen,Patternlen,linecounterRL,Strnglen-Patternlen+1-linecounterRL);
if (linecounterRL>256*256*256) { //3 bytes encode 2^24=256*256*256 B-Blocks.
	printf( "\nBuilding-Blocks_DUMPER: Overflow! BBs exceed the 16,777,216 limit.\n");
	free(ASbackup);
	free (Strng);
	return -1;
}
printf("Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%%Patternlen)): %d\n",Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)));

if ( (signed long)(Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)))>GainMax) {GainMax=(signed long)(Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen))); GainOrder=Patternlen;}

free(ASbackup);
fclose(fp_inLINE);
} // MAIN CYCLE ]
//clocks2 = clock(); TotalRoughSearchTime = clocks2 - clocks1; TotalRoughSearchTime++;
//printf( "Railgun_hits/Railgun_clocks: %lu/%lu\n", Railgunhits>>4, (long)(TotalRoughSearchTime)>>4);
//printf( "\nBuilding-Blocks_DUMPER total time: %lu clocks\n", (long)(TotalRoughSearchTime));
printf( "\nMaximum compression (or minimum expansion) for order: %lu\n", GainOrder);

clocks3 = clock();
// [ SS file creating:

bufEXTENSION = (unsigned char *) malloc(sizeof (unsigned char) * (strlen(argv[1])+1+3)); //when creating .SS

if(bufEXTENSION == NULL)
{ printf( "Building-Blocks_DUMPER: Can't allocate memory.\n"); return( 1 ); }

strcpy(bufEXTENSION, argv[1]);
strcat(bufEXTENSION, ".SS");

printf( "\nCreating %s ...\n", bufEXTENSION);
if( ( fp_outLINE = fopen( bufEXTENSION, "wb" ) ) == NULL )
{ printf( "Building-Blocks_DUMPER: Can't open file %s \n", bufEXTENSION ); return( 1 ); }

fprintf (fp_outLINE, "[Simplicius_Simplicissimus_revision_1]\n"); // 0x1A = 026 ASCIICODE TEXT EOF
fprintf (fp_outLINE, "The file format after the ASCII code 026: \n1 byte for BB_Order, \n4bytes for Original_Size, \n4bytes for BB length, \nBB itself, \n3*(Original_Size/BB_Order) bytes of indexes followed by the (Original_Size%%BB_Order) bytes of literals.%c",0x1A); // 0x1A = 026 ASCIICODE TEXT EOF

// Uploading BB file to BB pool: 
memcpy(&BuildingBlocksBox[2],_ui64toaKAZEzerocomma (GainOrder, llTOaDigits, 10) +(26-3),3);
if( ( fp_inLINE = fopen( &BuildingBlocksBox[0], "rb" ) ) == NULL )
{ printf( "Building-Blocks_DUMPER: Can't upload file %s\n", &BuildingBlocksBox[0] ); return( 1 ); }

   fseek(fp_inLINE, 0, SEEK_END);
   Patternlen = ftell(fp_inLINE);
   fseek(fp_inLINE, 0, SEEK_SET);

BB = (char *)malloc( 768*1024*1024 );
if( BB == NULL )
{ puts( "Building-Blocks_DUMPER: Needed memory allocation denied!\n" ); return( 1 ); }

if (Patternlen>768*1024*1024)
{ printf( "Building-Blocks_DUMPER: File cannot be loaded, it exceeds 768MB limit.\n" ); return( 1 ); }

fread(BB, 1, Patternlen, fp_inLINE);
fclose(fp_inLINE);

putc(*((unsigned char *)&GainOrder+0), fp_outLINE);

putc(*((unsigned char *)&Strnglen+0), fp_outLINE);
putc(*((unsigned char *)&Strnglen+1), fp_outLINE);
putc(*((unsigned char *)&Strnglen+2), fp_outLINE);
putc(*((unsigned char *)&Strnglen+3), fp_outLINE);

putc(*((unsigned char *)&Patternlen+0), fp_outLINE);
putc(*((unsigned char *)&Patternlen+1), fp_outLINE);
putc(*((unsigned char *)&Patternlen+2), fp_outLINE);
putc(*((unsigned char *)&Patternlen+3), fp_outLINE);

fwrite(BB, 1, Patternlen, fp_outLINE);

// Must dump triads and the eventual remainder/literals.
// 'BB' pool with length 'Patternlen' has 'Patternlen/GainOrder' BBs.
// 'Strng' pool with length 'Strnglen' must be traversed with step 'GainOrder' assigning indexes/triads to BBs ...

// [ Triads dumping

// Maximum slow search:
//Creating googlebooks-eng-us-all-4gram-20090715-graffith_K_distinct.txt.SS ...
//Building-Blocks_DUMPER .SS dumping time: 1558673 clocks
//Building-Blocks_DUMPER total time: 1685829 clocks
goto NextNextInLine;
for (ThunderwithR=0; ThunderwithR<Strnglen/GainOrder; ThunderwithR++)
for (ThunderwithL=0; ThunderwithL<Patternlen/GainOrder; ThunderwithL++)
{
        if (memcmp(&BB[ThunderwithL*GainOrder+0],&Strng[ThunderwithR*GainOrder+0],GainOrder) == 0) {
	putc(*((unsigned char *)&ThunderwithL+0), fp_outLINE);
	putc(*((unsigned char *)&ThunderwithL+1), fp_outLINE);
	putc(*((unsigned char *)&ThunderwithL+2), fp_outLINE);
	// Notice that only 3 lower Little-Endian bytes are dumped!
	break;
	}
}
goto LAstLine;
NextInLine:
// Brute-force slow search: Railgun_Quadruplet
//Creating googlebooks-eng-us-all-4gram-20090715-graffith_K_distinct.txt.SS ...
//Building-Blocks_DUMPER .SS dumping time: 573392 clocks
//Building-Blocks_DUMPER total time: 700579 clocks
for (ThunderwithR=0; ThunderwithR<Strnglen/GainOrder; ThunderwithR++)
{
        FoundInPTR=BB;
	while ( FoundInPTRNEW = Railgun_Quadruplet(FoundInPTR,&Strng[ThunderwithR*GainOrder+0],Patternlen,GainOrder) ) {
	        if ( (FoundInPTRNEW-BB) % GainOrder == 0 ) {
		ThunderwithL = (unsigned long)(FoundInPTRNEW-BB) / GainOrder;
		putc(*((unsigned char *)&ThunderwithL+0), fp_outLINE);
		putc(*((unsigned char *)&ThunderwithL+1), fp_outLINE);
		putc(*((unsigned char *)&ThunderwithL+2), fp_outLINE);
		// Notice that only 3 lower Little-Endian bytes are dumped!
		break;
		}
		FoundInPTR = FoundInPTRNEW+1;
	}
}
goto LAstLine;
NextNextInLine:
// Binary-Search:
//Creating googlebooks-eng-us-all-4gram-20090715-graffith_K_distinct.txt.SS ...
//Building-Blocks_DUMPER .SS dumping time: 1923 clocks
//Building-Blocks_DUMPER total time: 132563 clocks
for (ThunderwithR=0; ThunderwithR<Strnglen/GainOrder; ThunderwithR++)
{
	YabbaYabba = 0;
        LeftPointBS = 0;
        RightPointBS = Patternlen/GainOrder - 1;
        PivotPointBS = 0;
	do {
			if (RightPointBS - LeftPointBS <= 1) {
				NataliaKills = memcmp(&Strng[ThunderwithR*GainOrder+0],&BB[LeftPointBS*GainOrder+0],GainOrder);
			        if ( NataliaKills == 0) { YabbaYabba = 1; PivotPointBS = LeftPointBS; break; }
				NataliaKills = memcmp(&Strng[ThunderwithR*GainOrder+0],&BB[RightPointBS*GainOrder+0],GainOrder);
	        		if ( NataliaKills == 0) { YabbaYabba = 1; PivotPointBS = RightPointBS; break; }
				break; }
	        PivotPointBS = (LeftPointBS + RightPointBS) >> 1;
		NataliaKills = memcmp(&Strng[ThunderwithR*GainOrder+0],&BB[PivotPointBS*GainOrder+0],GainOrder);
	        if ( NataliaKills == 0) { YabbaYabba = 1; break; }
		else if ( NataliaKills < 0) { RightPointBS = PivotPointBS; }
		else { LeftPointBS = PivotPointBS; }
	} while (1 == 1);
	        if ( YabbaYabba != 0 ) {
		ThunderwithL = PivotPointBS;
		putc(*((unsigned char *)&ThunderwithL+0), fp_outLINE);
		putc(*((unsigned char *)&ThunderwithL+1), fp_outLINE);
		putc(*((unsigned char *)&ThunderwithL+2), fp_outLINE);
		// Notice that only 3 lower Little-Endian bytes are dumped!
		}
}

/* Binary search from 'LOGerINFINITY_COUNTRY_CITY.php':
			$WRDpresent = 0;
            $LeftPoint = 0;
            $RightPoint = $linecntrC - 1;
			$q = 0;
	do {
			if ($RightPoint - $LeftPoint <= 1) {
				$SplitIsSTRINGlefta = (float) $array77a[$LeftPoint];
				$SplitIsSTRINGleftb = (float) $array77b[$LeftPoint];
				$SplitIsSTRINGrighta = (float) $array77a[$RightPoint];
				$SplitIsSTRINGrightb = (float) $array77b[$RightPoint];
				if ($long >= $SplitIsSTRINGlefta && $long <= $SplitIsSTRINGleftb) { $WRDpresent = 1; $q = $LeftPoint; break; }
				if ($long >= $SplitIsSTRINGrighta && $long <= $SplitIsSTRINGrightb) { $WRDpresent = 1; $q = $RightPoint; break; } 	
				break; }
	        $q = ($LeftPoint + $RightPoint) >> 1;
			$SplitIsSTRINGa = (float) $array77a[$q];
			$SplitIsSTRINGb = (float) $array77b[$q];
		   	if (($long >= $SplitIsSTRINGa) && ($long <= $SplitIsSTRINGb)) { $WRDpresent = 1; break; }
			if ($long > $SplitIsSTRINGb) { $LeftPoint = $q; }
			if ($long < $SplitIsSTRINGa) { $RightPoint = $q; }
	} while (1 == 1);
*/
LAstLine:

// ] Triads dumping

// [ Literals dumping
ThunderwithL=Strnglen % GainOrder;
while (ThunderwithL) {
putc(*( (unsigned char *)Strng+Strnglen-ThunderwithL ), fp_outLINE);
ThunderwithL--;
}
// ] Literals dumping

// ] SS file creating:

clocks2 = clock();

TotalRoughSearchTime = clocks2 - clocks3; TotalRoughSearchTime++;
printf( "\nBuilding-Blocks_DUMPER .SS dumping time: %lu clocks\n", (long)(TotalRoughSearchTime));

TotalRoughSearchTime = clocks2 - clocks1; TotalRoughSearchTime++;
printf( "Building-Blocks_DUMPER total time: %lu clocks\n", (long)(TotalRoughSearchTime));


/*
printf( "Searching for Pattern(%dbytes) into String(%dbytes) at each position ...\n", Patternlen, Strnglen);
      if( ( fp_inLINE = fopen( &BuildingBlocksBox[0], "wb+" ) ) == NULL )
      { printf( "Building-Blocks_DUMPER: Can't create file %s\n", &BuildingBlocksBox[0] ); return( 1 ); }
printf( "Writing Building-Blocks with corresponding hits(overlapped) to %s ...\n", &BuildingBlocksBox[0]);

Railgunhits=0;
clocks3 = clock();
    for ( i=0;i<=Strnglen-Patternlen; i++)
    {
//	printf( "Searching for ");
//	    for ( j=0;j<Patternlen; j++)
//	    printf( "%s", _ui64toaKAZEzerocomma (Strng[0+i+j], llTOaDigits, 16) +(26-2));
//	printf( " ...\n");
	printf( "Remain: %lu            \r", Strnglen-Patternlen - i + 1);
	FoundInPTR = Railgun_totalhits(&Strng[0], &Strng[0+i], Strnglen, Patternlen);
	    for ( j=0;j<Patternlen; j++)
	    fprintf(fp_inLINE, "%s", _ui64toaKAZEzerocomma (Strng[0+i+j], llTOaDigits, 16) +(26-2));
	    fprintf(fp_inLINE, " %d\n", Railgunhits);
	Railgunhits=0;
    }
clocks2 = clock(); TotalRoughSearchTime = clocks2 - clocks1; TotalRoughSearchTime++;
//printf( "Railgun_hits/Railgun_clocks: %lu/%lu\n", Railgunhits>>4, (long)(TotalRoughSearchTime)>>4);
printf( "\nBuilding-Blocks_DUMPER total time for creating %s: %lu clocks\n", &BuildingBlocksBox[0], (long)(TotalRoughSearchTime));
*/


free(BB);
free(bufEXTENSION);
free(Strng);
return(0);
  }

/*
Order 4:
206,908,949 OSHO.TXT
156,174,067 OSHO.TXT.SS
Sorting 206908946 Pointers to Building-Blocks 4 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB004.txt ...
Patternlen:4|206908949-4+1|linecounterRL:248019|206660927
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 50735161
BBs pool size: 992076
Decompression to RAM without Dumping to DRIVE time: 1564 clocks
Decompression to RAM without Dumping to DRIVE performance: 129194 KB/s

Order 7:
206,908,949 OSHO.TXT
122,297,608 OSHO.TXT.SS
Sorting 206908943 Pointers to Building-Blocks 7 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB007.txt ...
Patternlen:7|206908949-7+1|linecounterRL:4803152|202105791
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 84611620
BBs pool size: 33622064
Decompression to RAM without Dumping to DRIVE time: 3282 clocks
Decompression to RAM without Dumping to DRIVE performance: 61565 KB/s

Order 8:
206,908,949 OSHO.TXT
149,243,106 OSHO.TXT.SS
Sorting 206908942 Pointers to Building-Blocks 8 chars in size ...
Allocated memory for pointers-to-words in MB: 790
Writing Sorted Building-Blocks to BB008.txt ...
Patternlen:8|206908949-8+1|linecounterRL:8956496|197952446
Gain(reduced-size) or Strnglen-(Patternlen*linecounterRL+3*(Strnglen/Patternlen)+(Strnglen%Patternlen)): 57666122
BBs pool size: 71651968
Decompression to RAM without Dumping to DRIVE time: 3001 clocks
Decompression to RAM without Dumping to DRIVE performance: 67330 KB/s
*/