From c54c68c73d519939417290aa0da6b28f68a27621 Mon Sep 17 00:00:00 2001 From: caius72 Date: Sat, 22 Aug 2026 22:38:34 +0200 Subject: [PATCH] Add lbzip2 2.6.5 lbzip2 is a bzip2-compatible compressor whose command-line tool splits the work over threads. lzbench benchmarks buffer-to-buffer calls and does its own threading, so the wrapper drives lbzip2's low-level encoder and decoder sequentially, block by block, the way compress.c and expand.c do around their scheduler. Only the codec sources are vendored (crctab.c, decode.c, divbwt.c, encode.c, parse.c), unmodified; the tool's threading and I/O machinery is not built. Two -D renames keep the link clear of zstd's divbwt() and of any other xmalloc(), and a small arpa/inet.h shim covers MinGW, which lacks that header. The output is bzip2: bzip2 -t accepts it, and on silesia.tar the compressed size is within 0.005% of bzip2's at -9. --- Makefile | 17 +- README.md | 1 + bench/codecs.h | 9 + bench/lzbench.h | 1 + bench/symmetric_codecs.cpp | 18 + bwt/lbzip2/COPYING | 674 ++++++++++++++ bwt/lbzip2/README.md | 22 + bwt/lbzip2/arpa/inet.h | 26 + bwt/lbzip2/common.h | 144 +++ bwt/lbzip2/crctab.c | 410 +++++++++ bwt/lbzip2/decode.c | 1209 ++++++++++++++++++++++++ bwt/lbzip2/decode.h | 79 ++ bwt/lbzip2/divbwt.c | 1726 +++++++++++++++++++++++++++++++++++ bwt/lbzip2/encode.c | 1403 ++++++++++++++++++++++++++++ bwt/lbzip2/encode.h | 38 + bwt/lbzip2/lbzip2_lzbench.c | 181 ++++ bwt/lbzip2/lbzip2_lzbench.h | 24 + bwt/lbzip2/main.h | 91 ++ bwt/lbzip2/parse.c | 342 +++++++ bwt/lbzip2/scantab.h | 512 +++++++++++ 20 files changed, 6926 insertions(+), 1 deletion(-) create mode 100644 bwt/lbzip2/COPYING create mode 100644 bwt/lbzip2/README.md create mode 100644 bwt/lbzip2/arpa/inet.h create mode 100644 bwt/lbzip2/common.h create mode 100644 bwt/lbzip2/crctab.c create mode 100644 bwt/lbzip2/decode.c create mode 100644 bwt/lbzip2/decode.h create mode 100644 bwt/lbzip2/divbwt.c create mode 100644 bwt/lbzip2/encode.c create mode 100644 bwt/lbzip2/encode.h create mode 100644 bwt/lbzip2/lbzip2_lzbench.c create mode 100644 bwt/lbzip2/lbzip2_lzbench.h create mode 100644 bwt/lbzip2/main.h create mode 100644 bwt/lbzip2/parse.c create mode 100644 bwt/lbzip2/scantab.h diff --git a/Makefile b/Makefile index 00716902..b98f990d 100644 --- a/Makefile +++ b/Makefile @@ -974,6 +974,14 @@ else endif +ifeq "$(DONT_BUILD_LBZIP2)" "1" + DEFINES += -DBENCH_REMOVE_LBZIP2 +else + LBZIP2_FILES += bwt/lbzip2/crctab.o bwt/lbzip2/decode.o bwt/lbzip2/divbwt.o + LBZIP2_FILES += bwt/lbzip2/encode.o bwt/lbzip2/parse.o bwt/lbzip2/lbzip2_lzbench.o +endif + + ifeq "$(DONT_BUILD_BZIP3)" "1" DEFINES += -DBENCH_REMOVE_BZIP3 else @@ -1140,7 +1148,7 @@ endif # ifeq "$(ENABLE_CUDA)" MKDIR = mkdir -p -lzbench: $(BUGGY_C_FILES) $(BUGGY_CC_FILES) $(BUGGY_CXX_FILES) $(ACEAPEX_FILES) $(BSC_C_FILES) $(BSC_CXX_FILES) $(BSC_CUDA_FILES) $(ACEAPEX_CUDA_FILES) $(GPUCOMPACT_FILES) $(BZIP2_FILES) $(BZIP3_FILES) $(CSC_FILES) $(KANZI_FILES) $(FASTLZMA2_OBJ) $(ZSTD_FILES) $(LZSSE_FILES) $(LZFSE_FILES) $(XZ_FILES) $(LIBLZG_FILES) $(BRIEFLZ_FILES) $(LZF_FILES) $(BROTLI_FILES) $(LZMA_FILES) $(ZLING_FILES) $(QUICKLZ_FILES) $(OPENZL_C_FILES) $(OPENZL_S_FILES) $(SNAPPY_FILES) $(ZLIB_FILES) $(ZLIB_NG_FILES) $(LZHAM_FILES) $(LZO_FILES) $(UCL_FILES) $(LZ4_FILES) $(LIZARD_FILES) $(LIBDEFLATE_FILES) $(ZXC_FILES) $(MISA77_FILES) $(MISC_FILES) $(NVCOMP_FILES) $(PPMD_FILES) $(BENCH_FILES) $(SKIM_FILE) +lzbench: $(BUGGY_C_FILES) $(BUGGY_CC_FILES) $(BUGGY_CXX_FILES) $(ACEAPEX_FILES) $(BSC_C_FILES) $(BSC_CXX_FILES) $(BSC_CUDA_FILES) $(ACEAPEX_CUDA_FILES) $(GPUCOMPACT_FILES) $(BZIP2_FILES) $(BZIP3_FILES) $(LBZIP2_FILES) $(CSC_FILES) $(KANZI_FILES) $(FASTLZMA2_OBJ) $(ZSTD_FILES) $(LZSSE_FILES) $(LZFSE_FILES) $(XZ_FILES) $(LIBLZG_FILES) $(BRIEFLZ_FILES) $(LZF_FILES) $(BROTLI_FILES) $(LZMA_FILES) $(ZLING_FILES) $(QUICKLZ_FILES) $(OPENZL_C_FILES) $(OPENZL_S_FILES) $(SNAPPY_FILES) $(ZLIB_FILES) $(ZLIB_NG_FILES) $(LZHAM_FILES) $(LZO_FILES) $(UCL_FILES) $(LZ4_FILES) $(LIZARD_FILES) $(LIBDEFLATE_FILES) $(ZXC_FILES) $(MISA77_FILES) $(MISC_FILES) $(NVCOMP_FILES) $(PPMD_FILES) $(BENCH_FILES) $(SKIM_FILE) $(CXX) $^ -o $@ $(LDFLAGS) $(LDFLAGS_LIBDL) @echo Linked GCC_VERSION=$(GCC_VERSION) CLANG_VERSION=$(CLANG_VERSION) COMPILER=$(COMPILER) @@ -1190,6 +1198,13 @@ $(BUGGY_CXX_FILES): %.o : %.cpp @$(MKDIR) $(dir $@) $(CXX) $(CFLAGS_O2) $< -c -o $@ +# -Ibwt/lbzip2 also picks up the shim there, which MinGW needs. +# zstd's dictBuilder exports a divbwt() too, and xmalloc() is a name anything +# might take, so rename both rather than patch the vendored source. +$(LBZIP2_FILES): %.o : %.c + @$(MKDIR) $(dir $@) + $(CC) $(CFLAGS) -Ibwt/lbzip2 -Ddivbwt=lbzip2_divbwt -Dxmalloc=lbzip2_xmalloc $< -c -o $@ + $(BZIP3_FILES): %.o : %.c @$(MKDIR) $(dir $@) $(CC) $(CFLAGS) -DVERSION=\"1.5.3\" -Ibwt/bzip3/include $< -c -o $@ diff --git a/README.md b/README.md index 70a9a6b8..d0a5989f 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Notes column says otherwise. | [glza 0.12](https://encode.su/threads/2427-GLZA) | 2026-03-23 | | | [gpucompact 1.0](https://github.com/UDPSendToFailed/gpucompact) | 2026-07-27 | CUDA only | | [kanzi 2.5.3](https://github.com/flanglet/kanzi-cpp) | 2026-04-22 | | +| [lbzip2 2.6.5](https://github.com/caius72/lbzip2) | 2026-08-18 | bzip2 format; benchmarked single-threaded | | [libdeflate v1.25](https://github.com/ebiggers/libdeflate) | 2025-11-01 | | | [lizard v2.1](https://github.com/inikep/lizard) | 2025-01-26 | | | [lz4/lz4hc v1.10.0](https://github.com/lz4/lz4) | 2024-07-21 | | diff --git a/bench/codecs.h b/bench/codecs.h index d7dbfd26..e7492555 100644 --- a/bench/codecs.h +++ b/bench/codecs.h @@ -79,6 +79,15 @@ int64_t lzbench_memcpy(char *inbuf, size_t insize, char *outbuf, size_t outsize, #endif // BENCH_REMOVE_BZIP2 +#ifndef BENCH_REMOVE_LBZIP2 + int64_t lzbench_lbzip2_compress(char *inbuf, size_t insize, char *outbuf, size_t outsize, codec_options_t *codec_options); + int64_t lzbench_lbzip2_decompress(char *inbuf, size_t insize, char *outbuf, size_t outsize, codec_options_t *codec_options); +#else + #define lzbench_lbzip2_compress NULL + #define lzbench_lbzip2_decompress NULL +#endif // BENCH_REMOVE_LBZIP2 + + #ifndef BENCH_REMOVE_BZIP3 int64_t lzbench_bzip3_compress(char *inbuf, size_t insize, char *outbuf, size_t outsize, codec_options_t *codec_options); int64_t lzbench_bzip3_decompress(char *inbuf, size_t insize, char *outbuf, size_t outsize, codec_options_t *codec_options); diff --git a/bench/lzbench.h b/bench/lzbench.h index 492781e6..d077e9c8 100644 --- a/bench/lzbench.h +++ b/bench/lzbench.h @@ -204,6 +204,7 @@ static const compressor_desc_t comp_desc[] = { "gpucompact", "gpucompact 1.0", 1, 5, 0, NO_THREADING, lzbench_gpucompact_compress, lzbench_gpucompact_decompress, lzbench_gpucompact_init, lzbench_gpucompact_deinit }, #endif { "kanzi", "kanzi 2.5.3", 1, 9, 0, FULL_THREADING, lzbench_kanzi_compress, lzbench_kanzi_decompress, NULL, NULL }, + { "lbzip2", "lbzip2 2.6.5", 1, 9, 0, BENCH_POOL_MT, lzbench_lbzip2_compress, lzbench_lbzip2_decompress, NULL, NULL }, { "libdeflate", "libdeflate 1.25", 1, 12, 0, BENCH_POOL_MT, lzbench_libdeflate_compress, lzbench_libdeflate_decompress, NULL, NULL }, { "lizard", "lizard 2.1", 10, 49, 0, BENCH_POOL_MT, lzbench_lizard_compress, lzbench_lizard_decompress, NULL, NULL }, { "lz4", "lz4 1.10.0", 0, 0, 0, BENCH_POOL_MT, lzbench_lz4_compress, lzbench_lz4_decompress, NULL, NULL }, diff --git a/bench/symmetric_codecs.cpp b/bench/symmetric_codecs.cpp index 92387aa0..0f6de366 100644 --- a/bench/symmetric_codecs.cpp +++ b/bench/symmetric_codecs.cpp @@ -153,6 +153,24 @@ int64_t lzbench_bzip2_decompress(char *inbuf, size_t insize, char *outbuf, size_ #endif // BENCH_REMOVE_BZIP2 +#ifndef BENCH_REMOVE_LBZIP2 +#include "bwt/lbzip2/lbzip2_lzbench.h" + +int64_t lzbench_lbzip2_compress(char *inbuf, size_t insize, char *outbuf, size_t outsize, codec_options_t *codec_options) +{ + size_t res = lbzip2_buf_compress(inbuf, insize, outbuf, outsize, codec_options->level); + return res ? (int64_t)res : -1; +} + +int64_t lzbench_lbzip2_decompress(char *inbuf, size_t insize, char *outbuf, size_t outsize, codec_options_t *codec_options) +{ + size_t res = lbzip2_buf_decompress(inbuf, insize, outbuf, outsize); + return res ? (int64_t)res : -1; +} + +#endif // BENCH_REMOVE_LBZIP2 + + #ifndef BENCH_REMOVE_BZIP3 #include "bwt/bzip3/include/libbz3.h" diff --git a/bwt/lbzip2/COPYING b/bwt/lbzip2/COPYING new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/bwt/lbzip2/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/bwt/lbzip2/README.md b/bwt/lbzip2/README.md new file mode 100644 index 00000000..ea577b58 --- /dev/null +++ b/bwt/lbzip2/README.md @@ -0,0 +1,22 @@ +# lbzip2 in lzbench + +Vendored from https://github.com/caius72/lbzip2 at v2.6.5 (commit 26461f6), +which is a maintained fork of https://github.com/kjn/lbzip2. GPL-3.0-or-later; +see COPYING. + +`crctab.c`, `decode.c`, `divbwt.c`, `encode.c`, `parse.c` and the headers are +upstream's `src/` files, unmodified. They are the low-level codec; the rest of +upstream (`main.c`, `process.c`, `compress.c`, `expand.c`, ...) is the +multi-threaded command-line tool and is not used here. + +`lbzip2_lzbench.c` is the lzbench-side wrapper: it drives that codec +sequentially, block by block, the way the tool does around its scheduler, and +supplies the one function (`xmalloc`) that `decode.c` expects from the tool. + +`arpa/inet.h` is a shim for MinGW, which lacks that header; three of the +vendored sources include it for `ntohl`/`htonl` alone. It is reachable only +through `-Ibwt/lbzip2`. + +To update: copy those files from a newer lbzip2 `src/`, and check that +`collect`/`encode`/`transmit` and `parse`/`retrieve`/`decode`/`emit` still +have the signatures the wrapper uses. diff --git a/bwt/lbzip2/arpa/inet.h b/bwt/lbzip2/arpa/inet.h new file mode 100644 index 00000000..733e38b0 --- /dev/null +++ b/bwt/lbzip2/arpa/inet.h @@ -0,0 +1,26 @@ +/* + Shim for the three lbzip2 sources that include , which MinGW + does not have. They use nothing from it but ntohl() and htonl(), so this + provides those and lets the vendored sources stay byte-for-byte upstream. + Only reachable through -Ibwt/lbzip2, i.e. only for those sources. +*/ +#ifndef LBZIP2_LZBENCH_ARPA_INET_H +#define LBZIP2_LZBENCH_ARPA_INET_H + +#include + +/* Some libcs define these from headers lbzip2 already includes; leave those + alone. */ +#ifndef ntohl +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define ntohl(x) ((uint32_t)(x)) +#else +#define ntohl(x) __builtin_bswap32((uint32_t)(x)) +#endif +#endif + +#ifndef htonl +#define htonl(x) ntohl(x) +#endif + +#endif diff --git a/bwt/lbzip2/common.h b/bwt/lbzip2/common.h new file mode 100644 index 00000000..e879656d --- /dev/null +++ b/bwt/lbzip2/common.h @@ -0,0 +1,144 @@ +/*- + common.h -- common declarations + + Copyright (C) 2012, 2014 Mikolaj Izdebski + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +#include /* assert() */ +#include /* errno */ +#include /* uint32_t */ +#include /* bool */ +#include /* size_t */ +#include /* abort() */ + + +/* Tracing, useful in debugging, but not officially supported. */ +#ifdef ENABLE_TRACING +#define Trace(x) info x +#else +#define Trace(x) +#endif + + +/* + Minimal and maximal alphabet size used in prefix coding. We always have 2 + RLE symbols, from 0 to 255 MTF values and 1 EOF symbol. +*/ +#define MIN_ALPHA_SIZE (2+0+1) +#define MAX_ALPHA_SIZE (2+255+1) + +#define MIN_TREES 2 +#define MAX_TREES 6 +#define GROUP_SIZE 50 +#define MIN_CODE_LENGTH 1 /* implied by MIN_ALPHA_SIZE > 1u */ +#define MAX_CODE_LENGTH 20 +#define MAX_BLOCK_SIZE 900000 +#define MAX_GROUPS ((MAX_BLOCK_SIZE + GROUP_SIZE - 1) / GROUP_SIZE) +#define MAX_SELECTORS 32767 + +enum error { + OK, /* no error */ + MORE, + FINISH, + + ERR_MAGIC, /* bad stream header magic */ + ERR_HEADER, /* bad block header magic */ + ERR_BITMAP, /* empty source alphabet */ + ERR_TREES, /* bad number of trees */ + ERR_GROUPS, /* no coding groups */ + ERR_SELECTOR, /* invalid selector */ + ERR_DELTA, /* invalid delta code */ + ERR_PREFIX, /* invalid prefix code */ + ERR_INCOMPLT, /* incomplete prefix code */ + ERR_EMPTY, /* empty block */ + ERR_UNTERM, /* unterminated block */ + ERR_RUNLEN, /* missing run length */ + ERR_BLKCRC, /* block CRC mismatch */ + ERR_STRMCRC, /* stream CRC mismatch */ + ERR_OVERFLOW, /* block overflow */ + ERR_BWTIDX, /* primary index too large */ + ERR_EOF, /* unexpected end of file */ +}; + + +/* Minimum and maximum. It's important to keep the same condition in both + macros because then some compilers on some architectures (like gcc on x86) + will generate better code. */ +#define min(x,y) ((x) < (y) ? (x) : (y)) +#define max(x,y) ((x) < (y) ? (y) : (x)) + + +/* Check GCC version. This not only works for GNU C, but also Clang and + possibly others. If a particular compiler defines __GNUC__ but it's not GCC + compatible then it's that compilers problem. */ +#define GNUC_VERSION (10000 * (__GNUC__ + 0) + 100 * (__GNUC_MINOR__ + 0) + \ + (__GNUC_PATCHLEVEL__ + 0)) + + +/* Explicit static branch prediction to help compiler generating faster + code. */ +#if GNUC_VERSION >= 30004 +# define likely(x) __builtin_expect((x), 1) +# define unlikely(x) __builtin_expect((x), 0) +#else +# define likely(x) (x) +# define unlikely(x) (x) +#endif + + +#if GNUC_VERSION >= 20300 +# define format_printf(fmt, args) __attribute__((format(printf, (fmt), (args)))) +#else +# define format_printf(fmt, args) +#endif + + +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L +/* Some C libraries define _Noreturn themselves when the compiler is not in + C11 mode -- MSYS2 makes it __dead2 in . Theirs means the same + thing as ours, and redefining it differently warns once per translation + unit, so leave any existing definition alone. */ +# ifndef _Noreturn +# if GNUC_VERSION >= 20500 +# define _Noreturn __attribute__((noreturn)) +# else +# define _Noreturn +# endif +# endif +#endif + + +#if GNUC_VERSION >= 70000 +# define FALLTHROUGH __attribute__((fallthrough)); +#else +# define FALLTHROUGH +#endif + + +/* CRC-32/BZIP2 -- polynomial 0x04C11DB7, most significant bit first, which is + the checksum bzip2 stores for each block. In crctab.c. */ +extern uint32_t crc_table[256]; +uint32_t crc32_bzip2(uint32_t crc, const uint8_t *buf, size_t len); + + +#if ENABLE_COVERAGE + 0 +void __gcov_flush(void); +#define gcov_flush() __gcov_flush() +#else +#define gcov_flush() +#endif diff --git a/bwt/lbzip2/crctab.c b/bwt/lbzip2/crctab.c new file mode 100644 index 00000000..9ec8f757 --- /dev/null +++ b/bwt/lbzip2/crctab.c @@ -0,0 +1,410 @@ +/* The 256-entry crc_table below was generated automatically by + make-crctab.pl; for comments refer to the generator script. The wider + slices and crc32_bzip2() after it were derived from that table by the + recurrence documented there. */ + +#include "common.h" + +uint32_t crc_table[256] = { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, + 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, + 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, + 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, + 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, + 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, + 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, + 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, + 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, + 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, + 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, + 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, + 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, + 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, + 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, + 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, + 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, + 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, + 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, + 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, + 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9, + 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, + 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, + 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, + 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, + 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, + 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, + 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, + 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, + 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, + 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, + 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, + 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4, +}; + + +/* Slices for the eight-bytes-at-a-time CRC in crc32_bzip2(). crc_more[k][i] + is the checksum of byte i followed by k+2 zero bytes -- that is, the same + recurrence as crc_table above, carried k+1 steps further: + + crc_more[0][i] = (crc_table[i] << 8) ^ crc_table[crc_table[i] >> 24] + crc_more[k][i] = (crc_more[k-1][i] << 8) ^ crc_table[crc_more[k-1][i] >> 24] + + Together with crc_table they let one round consume eight input bytes. */ +static const uint32_t crc_more[7][256] = { + { + 0x00000000, 0xD219C1DC, 0xA0F29E0F, 0x72EB5FD3, 0x452421A9, 0x973DE075, + 0xE5D6BFA6, 0x37CF7E7A, 0x8A484352, 0x5851828E, 0x2ABADD5D, 0xF8A31C81, + 0xCF6C62FB, 0x1D75A327, 0x6F9EFCF4, 0xBD873D28, 0x10519B13, 0xC2485ACF, + 0xB0A3051C, 0x62BAC4C0, 0x5575BABA, 0x876C7B66, 0xF58724B5, 0x279EE569, + 0x9A19D841, 0x4800199D, 0x3AEB464E, 0xE8F28792, 0xDF3DF9E8, 0x0D243834, + 0x7FCF67E7, 0xADD6A63B, 0x20A33626, 0xF2BAF7FA, 0x8051A829, 0x524869F5, + 0x6587178F, 0xB79ED653, 0xC5758980, 0x176C485C, 0xAAEB7574, 0x78F2B4A8, + 0x0A19EB7B, 0xD8002AA7, 0xEFCF54DD, 0x3DD69501, 0x4F3DCAD2, 0x9D240B0E, + 0x30F2AD35, 0xE2EB6CE9, 0x9000333A, 0x4219F2E6, 0x75D68C9C, 0xA7CF4D40, + 0xD5241293, 0x073DD34F, 0xBABAEE67, 0x68A32FBB, 0x1A487068, 0xC851B1B4, + 0xFF9ECFCE, 0x2D870E12, 0x5F6C51C1, 0x8D75901D, 0x41466C4C, 0x935FAD90, + 0xE1B4F243, 0x33AD339F, 0x04624DE5, 0xD67B8C39, 0xA490D3EA, 0x76891236, + 0xCB0E2F1E, 0x1917EEC2, 0x6BFCB111, 0xB9E570CD, 0x8E2A0EB7, 0x5C33CF6B, + 0x2ED890B8, 0xFCC15164, 0x5117F75F, 0x830E3683, 0xF1E56950, 0x23FCA88C, + 0x1433D6F6, 0xC62A172A, 0xB4C148F9, 0x66D88925, 0xDB5FB40D, 0x094675D1, + 0x7BAD2A02, 0xA9B4EBDE, 0x9E7B95A4, 0x4C625478, 0x3E890BAB, 0xEC90CA77, + 0x61E55A6A, 0xB3FC9BB6, 0xC117C465, 0x130E05B9, 0x24C17BC3, 0xF6D8BA1F, + 0x8433E5CC, 0x562A2410, 0xEBAD1938, 0x39B4D8E4, 0x4B5F8737, 0x994646EB, + 0xAE893891, 0x7C90F94D, 0x0E7BA69E, 0xDC626742, 0x71B4C179, 0xA3AD00A5, + 0xD1465F76, 0x035F9EAA, 0x3490E0D0, 0xE689210C, 0x94627EDF, 0x467BBF03, + 0xFBFC822B, 0x29E543F7, 0x5B0E1C24, 0x8917DDF8, 0xBED8A382, 0x6CC1625E, + 0x1E2A3D8D, 0xCC33FC51, 0x828CD898, 0x50951944, 0x227E4697, 0xF067874B, + 0xC7A8F931, 0x15B138ED, 0x675A673E, 0xB543A6E2, 0x08C49BCA, 0xDADD5A16, + 0xA83605C5, 0x7A2FC419, 0x4DE0BA63, 0x9FF97BBF, 0xED12246C, 0x3F0BE5B0, + 0x92DD438B, 0x40C48257, 0x322FDD84, 0xE0361C58, 0xD7F96222, 0x05E0A3FE, + 0x770BFC2D, 0xA5123DF1, 0x189500D9, 0xCA8CC105, 0xB8679ED6, 0x6A7E5F0A, + 0x5DB12170, 0x8FA8E0AC, 0xFD43BF7F, 0x2F5A7EA3, 0xA22FEEBE, 0x70362F62, + 0x02DD70B1, 0xD0C4B16D, 0xE70BCF17, 0x35120ECB, 0x47F95118, 0x95E090C4, + 0x2867ADEC, 0xFA7E6C30, 0x889533E3, 0x5A8CF23F, 0x6D438C45, 0xBF5A4D99, + 0xCDB1124A, 0x1FA8D396, 0xB27E75AD, 0x6067B471, 0x128CEBA2, 0xC0952A7E, + 0xF75A5404, 0x254395D8, 0x57A8CA0B, 0x85B10BD7, 0x383636FF, 0xEA2FF723, + 0x98C4A8F0, 0x4ADD692C, 0x7D121756, 0xAF0BD68A, 0xDDE08959, 0x0FF94885, + 0xC3CAB4D4, 0x11D37508, 0x63382ADB, 0xB121EB07, 0x86EE957D, 0x54F754A1, + 0x261C0B72, 0xF405CAAE, 0x4982F786, 0x9B9B365A, 0xE9706989, 0x3B69A855, + 0x0CA6D62F, 0xDEBF17F3, 0xAC544820, 0x7E4D89FC, 0xD39B2FC7, 0x0182EE1B, + 0x7369B1C8, 0xA1707014, 0x96BF0E6E, 0x44A6CFB2, 0x364D9061, 0xE45451BD, + 0x59D36C95, 0x8BCAAD49, 0xF921F29A, 0x2B383346, 0x1CF74D3C, 0xCEEE8CE0, + 0xBC05D333, 0x6E1C12EF, 0xE36982F2, 0x3170432E, 0x439B1CFD, 0x9182DD21, + 0xA64DA35B, 0x74546287, 0x06BF3D54, 0xD4A6FC88, 0x6921C1A0, 0xBB38007C, + 0xC9D35FAF, 0x1BCA9E73, 0x2C05E009, 0xFE1C21D5, 0x8CF77E06, 0x5EEEBFDA, + 0xF33819E1, 0x2121D83D, 0x53CA87EE, 0x81D34632, 0xB61C3848, 0x6405F994, + 0x16EEA647, 0xC4F7679B, 0x79705AB3, 0xAB699B6F, 0xD982C4BC, 0x0B9B0560, + 0x3C547B1A, 0xEE4DBAC6, 0x9CA6E515, 0x4EBF24C9, + }, + { + 0x00000000, 0x01D8AC87, 0x03B1590E, 0x0269F589, 0x0762B21C, 0x06BA1E9B, + 0x04D3EB12, 0x050B4795, 0x0EC56438, 0x0F1DC8BF, 0x0D743D36, 0x0CAC91B1, + 0x09A7D624, 0x087F7AA3, 0x0A168F2A, 0x0BCE23AD, 0x1D8AC870, 0x1C5264F7, + 0x1E3B917E, 0x1FE33DF9, 0x1AE87A6C, 0x1B30D6EB, 0x19592362, 0x18818FE5, + 0x134FAC48, 0x129700CF, 0x10FEF546, 0x112659C1, 0x142D1E54, 0x15F5B2D3, + 0x179C475A, 0x1644EBDD, 0x3B1590E0, 0x3ACD3C67, 0x38A4C9EE, 0x397C6569, + 0x3C7722FC, 0x3DAF8E7B, 0x3FC67BF2, 0x3E1ED775, 0x35D0F4D8, 0x3408585F, + 0x3661ADD6, 0x37B90151, 0x32B246C4, 0x336AEA43, 0x31031FCA, 0x30DBB34D, + 0x269F5890, 0x2747F417, 0x252E019E, 0x24F6AD19, 0x21FDEA8C, 0x2025460B, + 0x224CB382, 0x23941F05, 0x285A3CA8, 0x2982902F, 0x2BEB65A6, 0x2A33C921, + 0x2F388EB4, 0x2EE02233, 0x2C89D7BA, 0x2D517B3D, 0x762B21C0, 0x77F38D47, + 0x759A78CE, 0x7442D449, 0x714993DC, 0x70913F5B, 0x72F8CAD2, 0x73206655, + 0x78EE45F8, 0x7936E97F, 0x7B5F1CF6, 0x7A87B071, 0x7F8CF7E4, 0x7E545B63, + 0x7C3DAEEA, 0x7DE5026D, 0x6BA1E9B0, 0x6A794537, 0x6810B0BE, 0x69C81C39, + 0x6CC35BAC, 0x6D1BF72B, 0x6F7202A2, 0x6EAAAE25, 0x65648D88, 0x64BC210F, + 0x66D5D486, 0x670D7801, 0x62063F94, 0x63DE9313, 0x61B7669A, 0x606FCA1D, + 0x4D3EB120, 0x4CE61DA7, 0x4E8FE82E, 0x4F5744A9, 0x4A5C033C, 0x4B84AFBB, + 0x49ED5A32, 0x4835F6B5, 0x43FBD518, 0x4223799F, 0x404A8C16, 0x41922091, + 0x44996704, 0x4541CB83, 0x47283E0A, 0x46F0928D, 0x50B47950, 0x516CD5D7, + 0x5305205E, 0x52DD8CD9, 0x57D6CB4C, 0x560E67CB, 0x54679242, 0x55BF3EC5, + 0x5E711D68, 0x5FA9B1EF, 0x5DC04466, 0x5C18E8E1, 0x5913AF74, 0x58CB03F3, + 0x5AA2F67A, 0x5B7A5AFD, 0xEC564380, 0xED8EEF07, 0xEFE71A8E, 0xEE3FB609, + 0xEB34F19C, 0xEAEC5D1B, 0xE885A892, 0xE95D0415, 0xE29327B8, 0xE34B8B3F, + 0xE1227EB6, 0xE0FAD231, 0xE5F195A4, 0xE4293923, 0xE640CCAA, 0xE798602D, + 0xF1DC8BF0, 0xF0042777, 0xF26DD2FE, 0xF3B57E79, 0xF6BE39EC, 0xF766956B, + 0xF50F60E2, 0xF4D7CC65, 0xFF19EFC8, 0xFEC1434F, 0xFCA8B6C6, 0xFD701A41, + 0xF87B5DD4, 0xF9A3F153, 0xFBCA04DA, 0xFA12A85D, 0xD743D360, 0xD69B7FE7, + 0xD4F28A6E, 0xD52A26E9, 0xD021617C, 0xD1F9CDFB, 0xD3903872, 0xD24894F5, + 0xD986B758, 0xD85E1BDF, 0xDA37EE56, 0xDBEF42D1, 0xDEE40544, 0xDF3CA9C3, + 0xDD555C4A, 0xDC8DF0CD, 0xCAC91B10, 0xCB11B797, 0xC978421E, 0xC8A0EE99, + 0xCDABA90C, 0xCC73058B, 0xCE1AF002, 0xCFC25C85, 0xC40C7F28, 0xC5D4D3AF, + 0xC7BD2626, 0xC6658AA1, 0xC36ECD34, 0xC2B661B3, 0xC0DF943A, 0xC10738BD, + 0x9A7D6240, 0x9BA5CEC7, 0x99CC3B4E, 0x981497C9, 0x9D1FD05C, 0x9CC77CDB, + 0x9EAE8952, 0x9F7625D5, 0x94B80678, 0x9560AAFF, 0x97095F76, 0x96D1F3F1, + 0x93DAB464, 0x920218E3, 0x906BED6A, 0x91B341ED, 0x87F7AA30, 0x862F06B7, + 0x8446F33E, 0x859E5FB9, 0x8095182C, 0x814DB4AB, 0x83244122, 0x82FCEDA5, + 0x8932CE08, 0x88EA628F, 0x8A839706, 0x8B5B3B81, 0x8E507C14, 0x8F88D093, + 0x8DE1251A, 0x8C39899D, 0xA168F2A0, 0xA0B05E27, 0xA2D9ABAE, 0xA3010729, + 0xA60A40BC, 0xA7D2EC3B, 0xA5BB19B2, 0xA463B535, 0xAFAD9698, 0xAE753A1F, + 0xAC1CCF96, 0xADC46311, 0xA8CF2484, 0xA9178803, 0xAB7E7D8A, 0xAAA6D10D, + 0xBCE23AD0, 0xBD3A9657, 0xBF5363DE, 0xBE8BCF59, 0xBB8088CC, 0xBA58244B, + 0xB831D1C2, 0xB9E97D45, 0xB2275EE8, 0xB3FFF26F, 0xB19607E6, 0xB04EAB61, + 0xB545ECF4, 0xB49D4073, 0xB6F4B5FA, 0xB72C197D, + }, + { + 0x00000000, 0xDC6D9AB7, 0xBC1A28D9, 0x6077B26E, 0x7CF54C05, 0xA098D6B2, + 0xC0EF64DC, 0x1C82FE6B, 0xF9EA980A, 0x258702BD, 0x45F0B0D3, 0x999D2A64, + 0x851FD40F, 0x59724EB8, 0x3905FCD6, 0xE5686661, 0xF7142DA3, 0x2B79B714, + 0x4B0E057A, 0x97639FCD, 0x8BE161A6, 0x578CFB11, 0x37FB497F, 0xEB96D3C8, + 0x0EFEB5A9, 0xD2932F1E, 0xB2E49D70, 0x6E8907C7, 0x720BF9AC, 0xAE66631B, + 0xCE11D175, 0x127C4BC2, 0xEAE946F1, 0x3684DC46, 0x56F36E28, 0x8A9EF49F, + 0x961C0AF4, 0x4A719043, 0x2A06222D, 0xF66BB89A, 0x1303DEFB, 0xCF6E444C, + 0xAF19F622, 0x73746C95, 0x6FF692FE, 0xB39B0849, 0xD3ECBA27, 0x0F812090, + 0x1DFD6B52, 0xC190F1E5, 0xA1E7438B, 0x7D8AD93C, 0x61082757, 0xBD65BDE0, + 0xDD120F8E, 0x017F9539, 0xE417F358, 0x387A69EF, 0x580DDB81, 0x84604136, + 0x98E2BF5D, 0x448F25EA, 0x24F89784, 0xF8950D33, 0xD1139055, 0x0D7E0AE2, + 0x6D09B88C, 0xB164223B, 0xADE6DC50, 0x718B46E7, 0x11FCF489, 0xCD916E3E, + 0x28F9085F, 0xF49492E8, 0x94E32086, 0x488EBA31, 0x540C445A, 0x8861DEED, + 0xE8166C83, 0x347BF634, 0x2607BDF6, 0xFA6A2741, 0x9A1D952F, 0x46700F98, + 0x5AF2F1F3, 0x869F6B44, 0xE6E8D92A, 0x3A85439D, 0xDFED25FC, 0x0380BF4B, + 0x63F70D25, 0xBF9A9792, 0xA31869F9, 0x7F75F34E, 0x1F024120, 0xC36FDB97, + 0x3BFAD6A4, 0xE7974C13, 0x87E0FE7D, 0x5B8D64CA, 0x470F9AA1, 0x9B620016, + 0xFB15B278, 0x277828CF, 0xC2104EAE, 0x1E7DD419, 0x7E0A6677, 0xA267FCC0, + 0xBEE502AB, 0x6288981C, 0x02FF2A72, 0xDE92B0C5, 0xCCEEFB07, 0x108361B0, + 0x70F4D3DE, 0xAC994969, 0xB01BB702, 0x6C762DB5, 0x0C019FDB, 0xD06C056C, + 0x3504630D, 0xE969F9BA, 0x891E4BD4, 0x5573D163, 0x49F12F08, 0x959CB5BF, + 0xF5EB07D1, 0x29869D66, 0xA6E63D1D, 0x7A8BA7AA, 0x1AFC15C4, 0xC6918F73, + 0xDA137118, 0x067EEBAF, 0x660959C1, 0xBA64C376, 0x5F0CA517, 0x83613FA0, + 0xE3168DCE, 0x3F7B1779, 0x23F9E912, 0xFF9473A5, 0x9FE3C1CB, 0x438E5B7C, + 0x51F210BE, 0x8D9F8A09, 0xEDE83867, 0x3185A2D0, 0x2D075CBB, 0xF16AC60C, + 0x911D7462, 0x4D70EED5, 0xA81888B4, 0x74751203, 0x1402A06D, 0xC86F3ADA, + 0xD4EDC4B1, 0x08805E06, 0x68F7EC68, 0xB49A76DF, 0x4C0F7BEC, 0x9062E15B, + 0xF0155335, 0x2C78C982, 0x30FA37E9, 0xEC97AD5E, 0x8CE01F30, 0x508D8587, + 0xB5E5E3E6, 0x69887951, 0x09FFCB3F, 0xD5925188, 0xC910AFE3, 0x157D3554, + 0x750A873A, 0xA9671D8D, 0xBB1B564F, 0x6776CCF8, 0x07017E96, 0xDB6CE421, + 0xC7EE1A4A, 0x1B8380FD, 0x7BF43293, 0xA799A824, 0x42F1CE45, 0x9E9C54F2, + 0xFEEBE69C, 0x22867C2B, 0x3E048240, 0xE26918F7, 0x821EAA99, 0x5E73302E, + 0x77F5AD48, 0xAB9837FF, 0xCBEF8591, 0x17821F26, 0x0B00E14D, 0xD76D7BFA, + 0xB71AC994, 0x6B775323, 0x8E1F3542, 0x5272AFF5, 0x32051D9B, 0xEE68872C, + 0xF2EA7947, 0x2E87E3F0, 0x4EF0519E, 0x929DCB29, 0x80E180EB, 0x5C8C1A5C, + 0x3CFBA832, 0xE0963285, 0xFC14CCEE, 0x20795659, 0x400EE437, 0x9C637E80, + 0x790B18E1, 0xA5668256, 0xC5113038, 0x197CAA8F, 0x05FE54E4, 0xD993CE53, + 0xB9E47C3D, 0x6589E68A, 0x9D1CEBB9, 0x4171710E, 0x2106C360, 0xFD6B59D7, + 0xE1E9A7BC, 0x3D843D0B, 0x5DF38F65, 0x819E15D2, 0x64F673B3, 0xB89BE904, + 0xD8EC5B6A, 0x0481C1DD, 0x18033FB6, 0xC46EA501, 0xA419176F, 0x78748DD8, + 0x6A08C61A, 0xB6655CAD, 0xD612EEC3, 0x0A7F7474, 0x16FD8A1F, 0xCA9010A8, + 0xAAE7A2C6, 0x768A3871, 0x93E25E10, 0x4F8FC4A7, 0x2FF876C9, 0xF395EC7E, + 0xEF171215, 0x337A88A2, 0x530D3ACC, 0x8F60A07B, + }, + { + 0x00000000, 0x490D678D, 0x921ACF1A, 0xDB17A897, 0x20F48383, 0x69F9E40E, + 0xB2EE4C99, 0xFBE32B14, 0x41E90706, 0x08E4608B, 0xD3F3C81C, 0x9AFEAF91, + 0x611D8485, 0x2810E308, 0xF3074B9F, 0xBA0A2C12, 0x83D20E0C, 0xCADF6981, + 0x11C8C116, 0x58C5A69B, 0xA3268D8F, 0xEA2BEA02, 0x313C4295, 0x78312518, + 0xC23B090A, 0x8B366E87, 0x5021C610, 0x192CA19D, 0xE2CF8A89, 0xABC2ED04, + 0x70D54593, 0x39D8221E, 0x036501AF, 0x4A686622, 0x917FCEB5, 0xD872A938, + 0x2391822C, 0x6A9CE5A1, 0xB18B4D36, 0xF8862ABB, 0x428C06A9, 0x0B816124, + 0xD096C9B3, 0x999BAE3E, 0x6278852A, 0x2B75E2A7, 0xF0624A30, 0xB96F2DBD, + 0x80B70FA3, 0xC9BA682E, 0x12ADC0B9, 0x5BA0A734, 0xA0438C20, 0xE94EEBAD, + 0x3259433A, 0x7B5424B7, 0xC15E08A5, 0x88536F28, 0x5344C7BF, 0x1A49A032, + 0xE1AA8B26, 0xA8A7ECAB, 0x73B0443C, 0x3ABD23B1, 0x06CA035E, 0x4FC764D3, + 0x94D0CC44, 0xDDDDABC9, 0x263E80DD, 0x6F33E750, 0xB4244FC7, 0xFD29284A, + 0x47230458, 0x0E2E63D5, 0xD539CB42, 0x9C34ACCF, 0x67D787DB, 0x2EDAE056, + 0xF5CD48C1, 0xBCC02F4C, 0x85180D52, 0xCC156ADF, 0x1702C248, 0x5E0FA5C5, + 0xA5EC8ED1, 0xECE1E95C, 0x37F641CB, 0x7EFB2646, 0xC4F10A54, 0x8DFC6DD9, + 0x56EBC54E, 0x1FE6A2C3, 0xE40589D7, 0xAD08EE5A, 0x761F46CD, 0x3F122140, + 0x05AF02F1, 0x4CA2657C, 0x97B5CDEB, 0xDEB8AA66, 0x255B8172, 0x6C56E6FF, + 0xB7414E68, 0xFE4C29E5, 0x444605F7, 0x0D4B627A, 0xD65CCAED, 0x9F51AD60, + 0x64B28674, 0x2DBFE1F9, 0xF6A8496E, 0xBFA52EE3, 0x867D0CFD, 0xCF706B70, + 0x1467C3E7, 0x5D6AA46A, 0xA6898F7E, 0xEF84E8F3, 0x34934064, 0x7D9E27E9, + 0xC7940BFB, 0x8E996C76, 0x558EC4E1, 0x1C83A36C, 0xE7608878, 0xAE6DEFF5, + 0x757A4762, 0x3C7720EF, 0x0D9406BC, 0x44996131, 0x9F8EC9A6, 0xD683AE2B, + 0x2D60853F, 0x646DE2B2, 0xBF7A4A25, 0xF6772DA8, 0x4C7D01BA, 0x05706637, + 0xDE67CEA0, 0x976AA92D, 0x6C898239, 0x2584E5B4, 0xFE934D23, 0xB79E2AAE, + 0x8E4608B0, 0xC74B6F3D, 0x1C5CC7AA, 0x5551A027, 0xAEB28B33, 0xE7BFECBE, + 0x3CA84429, 0x75A523A4, 0xCFAF0FB6, 0x86A2683B, 0x5DB5C0AC, 0x14B8A721, + 0xEF5B8C35, 0xA656EBB8, 0x7D41432F, 0x344C24A2, 0x0EF10713, 0x47FC609E, + 0x9CEBC809, 0xD5E6AF84, 0x2E058490, 0x6708E31D, 0xBC1F4B8A, 0xF5122C07, + 0x4F180015, 0x06156798, 0xDD02CF0F, 0x940FA882, 0x6FEC8396, 0x26E1E41B, + 0xFDF64C8C, 0xB4FB2B01, 0x8D23091F, 0xC42E6E92, 0x1F39C605, 0x5634A188, + 0xADD78A9C, 0xE4DAED11, 0x3FCD4586, 0x76C0220B, 0xCCCA0E19, 0x85C76994, + 0x5ED0C103, 0x17DDA68E, 0xEC3E8D9A, 0xA533EA17, 0x7E244280, 0x3729250D, + 0x0B5E05E2, 0x4253626F, 0x9944CAF8, 0xD049AD75, 0x2BAA8661, 0x62A7E1EC, + 0xB9B0497B, 0xF0BD2EF6, 0x4AB702E4, 0x03BA6569, 0xD8ADCDFE, 0x91A0AA73, + 0x6A438167, 0x234EE6EA, 0xF8594E7D, 0xB15429F0, 0x888C0BEE, 0xC1816C63, + 0x1A96C4F4, 0x539BA379, 0xA878886D, 0xE175EFE0, 0x3A624777, 0x736F20FA, + 0xC9650CE8, 0x80686B65, 0x5B7FC3F2, 0x1272A47F, 0xE9918F6B, 0xA09CE8E6, + 0x7B8B4071, 0x328627FC, 0x083B044D, 0x413663C0, 0x9A21CB57, 0xD32CACDA, + 0x28CF87CE, 0x61C2E043, 0xBAD548D4, 0xF3D82F59, 0x49D2034B, 0x00DF64C6, + 0xDBC8CC51, 0x92C5ABDC, 0x692680C8, 0x202BE745, 0xFB3C4FD2, 0xB231285F, + 0x8BE90A41, 0xC2E46DCC, 0x19F3C55B, 0x50FEA2D6, 0xAB1D89C2, 0xE210EE4F, + 0x390746D8, 0x700A2155, 0xCA000D47, 0x830D6ACA, 0x581AC25D, 0x1117A5D0, + 0xEAF48EC4, 0xA3F9E949, 0x78EE41DE, 0x31E32653, + }, + { + 0x00000000, 0x1B280D78, 0x36501AF0, 0x2D781788, 0x6CA035E0, 0x77883898, + 0x5AF02F10, 0x41D82268, 0xD9406BC0, 0xC26866B8, 0xEF107130, 0xF4387C48, + 0xB5E05E20, 0xAEC85358, 0x83B044D0, 0x989849A8, 0xB641CA37, 0xAD69C74F, + 0x8011D0C7, 0x9B39DDBF, 0xDAE1FFD7, 0xC1C9F2AF, 0xECB1E527, 0xF799E85F, + 0x6F01A1F7, 0x7429AC8F, 0x5951BB07, 0x4279B67F, 0x03A19417, 0x1889996F, + 0x35F18EE7, 0x2ED9839F, 0x684289D9, 0x736A84A1, 0x5E129329, 0x453A9E51, + 0x04E2BC39, 0x1FCAB141, 0x32B2A6C9, 0x299AABB1, 0xB102E219, 0xAA2AEF61, + 0x8752F8E9, 0x9C7AF591, 0xDDA2D7F9, 0xC68ADA81, 0xEBF2CD09, 0xF0DAC071, + 0xDE0343EE, 0xC52B4E96, 0xE853591E, 0xF37B5466, 0xB2A3760E, 0xA98B7B76, + 0x84F36CFE, 0x9FDB6186, 0x0743282E, 0x1C6B2556, 0x311332DE, 0x2A3B3FA6, + 0x6BE31DCE, 0x70CB10B6, 0x5DB3073E, 0x469B0A46, 0xD08513B2, 0xCBAD1ECA, + 0xE6D50942, 0xFDFD043A, 0xBC252652, 0xA70D2B2A, 0x8A753CA2, 0x915D31DA, + 0x09C57872, 0x12ED750A, 0x3F956282, 0x24BD6FFA, 0x65654D92, 0x7E4D40EA, + 0x53355762, 0x481D5A1A, 0x66C4D985, 0x7DECD4FD, 0x5094C375, 0x4BBCCE0D, + 0x0A64EC65, 0x114CE11D, 0x3C34F695, 0x271CFBED, 0xBF84B245, 0xA4ACBF3D, + 0x89D4A8B5, 0x92FCA5CD, 0xD32487A5, 0xC80C8ADD, 0xE5749D55, 0xFE5C902D, + 0xB8C79A6B, 0xA3EF9713, 0x8E97809B, 0x95BF8DE3, 0xD467AF8B, 0xCF4FA2F3, + 0xE237B57B, 0xF91FB803, 0x6187F1AB, 0x7AAFFCD3, 0x57D7EB5B, 0x4CFFE623, + 0x0D27C44B, 0x160FC933, 0x3B77DEBB, 0x205FD3C3, 0x0E86505C, 0x15AE5D24, + 0x38D64AAC, 0x23FE47D4, 0x622665BC, 0x790E68C4, 0x54767F4C, 0x4F5E7234, + 0xD7C63B9C, 0xCCEE36E4, 0xE196216C, 0xFABE2C14, 0xBB660E7C, 0xA04E0304, + 0x8D36148C, 0x961E19F4, 0xA5CB3AD3, 0xBEE337AB, 0x939B2023, 0x88B32D5B, + 0xC96B0F33, 0xD243024B, 0xFF3B15C3, 0xE41318BB, 0x7C8B5113, 0x67A35C6B, + 0x4ADB4BE3, 0x51F3469B, 0x102B64F3, 0x0B03698B, 0x267B7E03, 0x3D53737B, + 0x138AF0E4, 0x08A2FD9C, 0x25DAEA14, 0x3EF2E76C, 0x7F2AC504, 0x6402C87C, + 0x497ADFF4, 0x5252D28C, 0xCACA9B24, 0xD1E2965C, 0xFC9A81D4, 0xE7B28CAC, + 0xA66AAEC4, 0xBD42A3BC, 0x903AB434, 0x8B12B94C, 0xCD89B30A, 0xD6A1BE72, + 0xFBD9A9FA, 0xE0F1A482, 0xA12986EA, 0xBA018B92, 0x97799C1A, 0x8C519162, + 0x14C9D8CA, 0x0FE1D5B2, 0x2299C23A, 0x39B1CF42, 0x7869ED2A, 0x6341E052, + 0x4E39F7DA, 0x5511FAA2, 0x7BC8793D, 0x60E07445, 0x4D9863CD, 0x56B06EB5, + 0x17684CDD, 0x0C4041A5, 0x2138562D, 0x3A105B55, 0xA28812FD, 0xB9A01F85, + 0x94D8080D, 0x8FF00575, 0xCE28271D, 0xD5002A65, 0xF8783DED, 0xE3503095, + 0x754E2961, 0x6E662419, 0x431E3391, 0x58363EE9, 0x19EE1C81, 0x02C611F9, + 0x2FBE0671, 0x34960B09, 0xAC0E42A1, 0xB7264FD9, 0x9A5E5851, 0x81765529, + 0xC0AE7741, 0xDB867A39, 0xF6FE6DB1, 0xEDD660C9, 0xC30FE356, 0xD827EE2E, + 0xF55FF9A6, 0xEE77F4DE, 0xAFAFD6B6, 0xB487DBCE, 0x99FFCC46, 0x82D7C13E, + 0x1A4F8896, 0x016785EE, 0x2C1F9266, 0x37379F1E, 0x76EFBD76, 0x6DC7B00E, + 0x40BFA786, 0x5B97AAFE, 0x1D0CA0B8, 0x0624ADC0, 0x2B5CBA48, 0x3074B730, + 0x71AC9558, 0x6A849820, 0x47FC8FA8, 0x5CD482D0, 0xC44CCB78, 0xDF64C600, + 0xF21CD188, 0xE934DCF0, 0xA8ECFE98, 0xB3C4F3E0, 0x9EBCE468, 0x8594E910, + 0xAB4D6A8F, 0xB06567F7, 0x9D1D707F, 0x86357D07, 0xC7ED5F6F, 0xDCC55217, + 0xF1BD459F, 0xEA9548E7, 0x720D014F, 0x69250C37, 0x445D1BBF, 0x5F7516C7, + 0x1EAD34AF, 0x058539D7, 0x28FD2E5F, 0x33D52327, + }, + { + 0x00000000, 0x4F576811, 0x9EAED022, 0xD1F9B833, 0x399CBDF3, 0x76CBD5E2, + 0xA7326DD1, 0xE86505C0, 0x73397BE6, 0x3C6E13F7, 0xED97ABC4, 0xA2C0C3D5, + 0x4AA5C615, 0x05F2AE04, 0xD40B1637, 0x9B5C7E26, 0xE672F7CC, 0xA9259FDD, + 0x78DC27EE, 0x378B4FFF, 0xDFEE4A3F, 0x90B9222E, 0x41409A1D, 0x0E17F20C, + 0x954B8C2A, 0xDA1CE43B, 0x0BE55C08, 0x44B23419, 0xACD731D9, 0xE38059C8, + 0x3279E1FB, 0x7D2E89EA, 0xC824F22F, 0x87739A3E, 0x568A220D, 0x19DD4A1C, + 0xF1B84FDC, 0xBEEF27CD, 0x6F169FFE, 0x2041F7EF, 0xBB1D89C9, 0xF44AE1D8, + 0x25B359EB, 0x6AE431FA, 0x8281343A, 0xCDD65C2B, 0x1C2FE418, 0x53788C09, + 0x2E5605E3, 0x61016DF2, 0xB0F8D5C1, 0xFFAFBDD0, 0x17CAB810, 0x589DD001, + 0x89646832, 0xC6330023, 0x5D6F7E05, 0x12381614, 0xC3C1AE27, 0x8C96C636, + 0x64F3C3F6, 0x2BA4ABE7, 0xFA5D13D4, 0xB50A7BC5, 0x9488F9E9, 0xDBDF91F8, + 0x0A2629CB, 0x457141DA, 0xAD14441A, 0xE2432C0B, 0x33BA9438, 0x7CEDFC29, + 0xE7B1820F, 0xA8E6EA1E, 0x791F522D, 0x36483A3C, 0xDE2D3FFC, 0x917A57ED, + 0x4083EFDE, 0x0FD487CF, 0x72FA0E25, 0x3DAD6634, 0xEC54DE07, 0xA303B616, + 0x4B66B3D6, 0x0431DBC7, 0xD5C863F4, 0x9A9F0BE5, 0x01C375C3, 0x4E941DD2, + 0x9F6DA5E1, 0xD03ACDF0, 0x385FC830, 0x7708A021, 0xA6F11812, 0xE9A67003, + 0x5CAC0BC6, 0x13FB63D7, 0xC202DBE4, 0x8D55B3F5, 0x6530B635, 0x2A67DE24, + 0xFB9E6617, 0xB4C90E06, 0x2F957020, 0x60C21831, 0xB13BA002, 0xFE6CC813, + 0x1609CDD3, 0x595EA5C2, 0x88A71DF1, 0xC7F075E0, 0xBADEFC0A, 0xF589941B, + 0x24702C28, 0x6B274439, 0x834241F9, 0xCC1529E8, 0x1DEC91DB, 0x52BBF9CA, + 0xC9E787EC, 0x86B0EFFD, 0x574957CE, 0x181E3FDF, 0xF07B3A1F, 0xBF2C520E, + 0x6ED5EA3D, 0x2182822C, 0x2DD0EE65, 0x62878674, 0xB37E3E47, 0xFC295656, + 0x144C5396, 0x5B1B3B87, 0x8AE283B4, 0xC5B5EBA5, 0x5EE99583, 0x11BEFD92, + 0xC04745A1, 0x8F102DB0, 0x67752870, 0x28224061, 0xF9DBF852, 0xB68C9043, + 0xCBA219A9, 0x84F571B8, 0x550CC98B, 0x1A5BA19A, 0xF23EA45A, 0xBD69CC4B, + 0x6C907478, 0x23C71C69, 0xB89B624F, 0xF7CC0A5E, 0x2635B26D, 0x6962DA7C, + 0x8107DFBC, 0xCE50B7AD, 0x1FA90F9E, 0x50FE678F, 0xE5F41C4A, 0xAAA3745B, + 0x7B5ACC68, 0x340DA479, 0xDC68A1B9, 0x933FC9A8, 0x42C6719B, 0x0D91198A, + 0x96CD67AC, 0xD99A0FBD, 0x0863B78E, 0x4734DF9F, 0xAF51DA5F, 0xE006B24E, + 0x31FF0A7D, 0x7EA8626C, 0x0386EB86, 0x4CD18397, 0x9D283BA4, 0xD27F53B5, + 0x3A1A5675, 0x754D3E64, 0xA4B48657, 0xEBE3EE46, 0x70BF9060, 0x3FE8F871, + 0xEE114042, 0xA1462853, 0x49232D93, 0x06744582, 0xD78DFDB1, 0x98DA95A0, + 0xB958178C, 0xF60F7F9D, 0x27F6C7AE, 0x68A1AFBF, 0x80C4AA7F, 0xCF93C26E, + 0x1E6A7A5D, 0x513D124C, 0xCA616C6A, 0x8536047B, 0x54CFBC48, 0x1B98D459, + 0xF3FDD199, 0xBCAAB988, 0x6D5301BB, 0x220469AA, 0x5F2AE040, 0x107D8851, + 0xC1843062, 0x8ED35873, 0x66B65DB3, 0x29E135A2, 0xF8188D91, 0xB74FE580, + 0x2C139BA6, 0x6344F3B7, 0xB2BD4B84, 0xFDEA2395, 0x158F2655, 0x5AD84E44, + 0x8B21F677, 0xC4769E66, 0x717CE5A3, 0x3E2B8DB2, 0xEFD23581, 0xA0855D90, + 0x48E05850, 0x07B73041, 0xD64E8872, 0x9919E063, 0x02459E45, 0x4D12F654, + 0x9CEB4E67, 0xD3BC2676, 0x3BD923B6, 0x748E4BA7, 0xA577F394, 0xEA209B85, + 0x970E126F, 0xD8597A7E, 0x09A0C24D, 0x46F7AA5C, 0xAE92AF9C, 0xE1C5C78D, + 0x303C7FBE, 0x7F6B17AF, 0xE4376989, 0xAB600198, 0x7A99B9AB, 0x35CED1BA, + 0xDDABD47A, 0x92FCBC6B, 0x43050458, 0x0C526C49, + }, + { + 0x00000000, 0x5BA1DCCA, 0xB743B994, 0xECE2655E, 0x6A466E9F, 0x31E7B255, + 0xDD05D70B, 0x86A40BC1, 0xD48CDD3E, 0x8F2D01F4, 0x63CF64AA, 0x386EB860, + 0xBECAB3A1, 0xE56B6F6B, 0x09890A35, 0x5228D6FF, 0xADD8A7CB, 0xF6797B01, + 0x1A9B1E5F, 0x413AC295, 0xC79EC954, 0x9C3F159E, 0x70DD70C0, 0x2B7CAC0A, + 0x79547AF5, 0x22F5A63F, 0xCE17C361, 0x95B61FAB, 0x1312146A, 0x48B3C8A0, + 0xA451ADFE, 0xFFF07134, 0x5F705221, 0x04D18EEB, 0xE833EBB5, 0xB392377F, + 0x35363CBE, 0x6E97E074, 0x8275852A, 0xD9D459E0, 0x8BFC8F1F, 0xD05D53D5, + 0x3CBF368B, 0x671EEA41, 0xE1BAE180, 0xBA1B3D4A, 0x56F95814, 0x0D5884DE, + 0xF2A8F5EA, 0xA9092920, 0x45EB4C7E, 0x1E4A90B4, 0x98EE9B75, 0xC34F47BF, + 0x2FAD22E1, 0x740CFE2B, 0x262428D4, 0x7D85F41E, 0x91679140, 0xCAC64D8A, + 0x4C62464B, 0x17C39A81, 0xFB21FFDF, 0xA0802315, 0xBEE0A442, 0xE5417888, + 0x09A31DD6, 0x5202C11C, 0xD4A6CADD, 0x8F071617, 0x63E57349, 0x3844AF83, + 0x6A6C797C, 0x31CDA5B6, 0xDD2FC0E8, 0x868E1C22, 0x002A17E3, 0x5B8BCB29, + 0xB769AE77, 0xECC872BD, 0x13380389, 0x4899DF43, 0xA47BBA1D, 0xFFDA66D7, + 0x797E6D16, 0x22DFB1DC, 0xCE3DD482, 0x959C0848, 0xC7B4DEB7, 0x9C15027D, + 0x70F76723, 0x2B56BBE9, 0xADF2B028, 0xF6536CE2, 0x1AB109BC, 0x4110D576, + 0xE190F663, 0xBA312AA9, 0x56D34FF7, 0x0D72933D, 0x8BD698FC, 0xD0774436, + 0x3C952168, 0x6734FDA2, 0x351C2B5D, 0x6EBDF797, 0x825F92C9, 0xD9FE4E03, + 0x5F5A45C2, 0x04FB9908, 0xE819FC56, 0xB3B8209C, 0x4C4851A8, 0x17E98D62, + 0xFB0BE83C, 0xA0AA34F6, 0x260E3F37, 0x7DAFE3FD, 0x914D86A3, 0xCAEC5A69, + 0x98C48C96, 0xC365505C, 0x2F873502, 0x7426E9C8, 0xF282E209, 0xA9233EC3, + 0x45C15B9D, 0x1E608757, 0x79005533, 0x22A189F9, 0xCE43ECA7, 0x95E2306D, + 0x13463BAC, 0x48E7E766, 0xA4058238, 0xFFA45EF2, 0xAD8C880D, 0xF62D54C7, + 0x1ACF3199, 0x416EED53, 0xC7CAE692, 0x9C6B3A58, 0x70895F06, 0x2B2883CC, + 0xD4D8F2F8, 0x8F792E32, 0x639B4B6C, 0x383A97A6, 0xBE9E9C67, 0xE53F40AD, + 0x09DD25F3, 0x527CF939, 0x00542FC6, 0x5BF5F30C, 0xB7179652, 0xECB64A98, + 0x6A124159, 0x31B39D93, 0xDD51F8CD, 0x86F02407, 0x26700712, 0x7DD1DBD8, + 0x9133BE86, 0xCA92624C, 0x4C36698D, 0x1797B547, 0xFB75D019, 0xA0D40CD3, + 0xF2FCDA2C, 0xA95D06E6, 0x45BF63B8, 0x1E1EBF72, 0x98BAB4B3, 0xC31B6879, + 0x2FF90D27, 0x7458D1ED, 0x8BA8A0D9, 0xD0097C13, 0x3CEB194D, 0x674AC587, + 0xE1EECE46, 0xBA4F128C, 0x56AD77D2, 0x0D0CAB18, 0x5F247DE7, 0x0485A12D, + 0xE867C473, 0xB3C618B9, 0x35621378, 0x6EC3CFB2, 0x8221AAEC, 0xD9807626, + 0xC7E0F171, 0x9C412DBB, 0x70A348E5, 0x2B02942F, 0xADA69FEE, 0xF6074324, + 0x1AE5267A, 0x4144FAB0, 0x136C2C4F, 0x48CDF085, 0xA42F95DB, 0xFF8E4911, + 0x792A42D0, 0x228B9E1A, 0xCE69FB44, 0x95C8278E, 0x6A3856BA, 0x31998A70, + 0xDD7BEF2E, 0x86DA33E4, 0x007E3825, 0x5BDFE4EF, 0xB73D81B1, 0xEC9C5D7B, + 0xBEB48B84, 0xE515574E, 0x09F73210, 0x5256EEDA, 0xD4F2E51B, 0x8F5339D1, + 0x63B15C8F, 0x38108045, 0x9890A350, 0xC3317F9A, 0x2FD31AC4, 0x7472C60E, + 0xF2D6CDCF, 0xA9771105, 0x4595745B, 0x1E34A891, 0x4C1C7E6E, 0x17BDA2A4, + 0xFB5FC7FA, 0xA0FE1B30, 0x265A10F1, 0x7DFBCC3B, 0x9119A965, 0xCAB875AF, + 0x3548049B, 0x6EE9D851, 0x820BBD0F, 0xD9AA61C5, 0x5F0E6A04, 0x04AFB6CE, + 0xE84DD390, 0xB3EC0F5A, 0xE1C4D9A5, 0xBA65056F, 0x56876031, 0x0D26BCFB, + 0x8B82B73A, 0xD0236BF0, 0x3CC10EAE, 0x6760D264, + }, +}; + + +/* CRC-32/BZIP2 of BUF, continuing from CRC. Same polynomial and bit order as + the byte-at-a-time loop this replaces, eight bytes to the round: the state + is folded into the first four bytes, then all eight are looked up at once + and combined. Trailing bytes fall back to the one-byte step. */ +uint32_t +crc32_bzip2(uint32_t crc, const uint8_t *buf, size_t len) +{ + while (len >= 8) { + uint32_t head = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) + | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3]; + uint32_t tail = ((uint32_t)buf[4] << 24) | ((uint32_t)buf[5] << 16) + | ((uint32_t)buf[6] << 8) | (uint32_t)buf[7]; + + crc ^= head; + + crc = crc_more[6][ crc >> 24] ^ crc_more[5][(crc >> 16) & 0xFF] + ^ crc_more[4][(crc >> 8) & 0xFF] ^ crc_more[3][ crc & 0xFF] + ^ crc_more[2][ tail >> 24] ^ crc_more[1][(tail >> 16) & 0xFF] + ^ crc_more[0][(tail >> 8) & 0xFF] ^ crc_table [ tail & 0xFF]; + + buf += 8; + len -= 8; + } + + while (len-- > 0) + crc = (crc << 8) ^ crc_table[(crc >> 24) ^ *buf++]; + + return crc; +} diff --git a/bwt/lbzip2/decode.c b/bwt/lbzip2/decode.c new file mode 100644 index 00000000..21614e4d --- /dev/null +++ b/bwt/lbzip2/decode.c @@ -0,0 +1,1209 @@ +/*- + decode.c -- low-level decompressor + + Copyright (C) 2011, 2012, 2013, 2014 Mikolaj Izdebski + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +#include "common.h" +#include /* ntohl() */ +#include /* memcpy() */ +#if defined(__aarch64__) && defined(__ARM_NEON) +# include /* vqtbl1q_u8() */ +# define MTF_NEON 1 +#elif defined(__SSSE3__) +# include /* _mm_shuffle_epi8() */ +# define MTF_SSSE3 1 +#endif + +#include "decode.h" +#include "main.h" + + +/* Prefix code decoding is performed using a multilevel table lookup. + The fastest way to decode is to simply build a lookup table whose size + is determined by the longest code. However, the time it takes to build + this table can also be a factor if the data being decoded is not very + long. The most common codes are necessarily the shortest codes, so those + codes dominate the decoding time, and hence the speed. The idea is you + can have a shorter table that decodes the shorter, more probable codes, + and then point to subsidiary tables for the longer codes. The time it + costs to decode the longer codes is then traded against the time it takes + to make longer tables. + + This result of this trade are in the constant HUFF_START_WIDTH below. + HUFF_START_WIDTH is the number of bits the first level table can decode + in one step. Subsequent tables always decode one bit at time. The current + value of HUFF_START_WIDTH was determined with a series of benchmarks. + The optimum value may differ though from machine to machine, and possibly + even between compilers. Your mileage may vary. +*/ +#define HUFF_START_WIDTH 10 + + +/* Notes on prefix code decoding: + + 1) Width of a tree node is defined as 2^-d, where d is depth of + that node. A prefix tree is said to be complete iff all leaf + widths sum to 1. If this sum is less (greater) than 1, we say + the tree is incomplete (oversubscribed). See also: Kraft's + inequality. + + In this implementation, malformed trees (oversubscribed or + incomplete) aren't rejected directly at creation (that's the + moment when both bad cases are detected). Instead, invalid + trees cause decode error only when they are actually used to + decode a group. + + This is nonconforming behavior -- the original bzip2, which + serves as a reference implementation, accepts malformed trees as + long as nonexistent codes don't appear in compressed stream. + Neither bzip2 nor any alternative implementation I know produces + such trees, so this behavior seems sane. + + 2) When held in variables, codes are usually in left-justified + form, meaning that they occupy consecutive most significant + bits of the variable they are stored in, while less significant + bits of variable are padded with zeroes. + + Such form allows for easy lexicographical comparison of codes + using unsigned arithmetic comparison operators, without the + need for normalization. + */ + + +/* Structure used for quick decoding of prefix codes. */ +struct tree { + uint16_t start[1 << HUFF_START_WIDTH]; + uint64_t base[MAX_CODE_LENGTH + 2]; /* 2 sentinels (first and last pos) */ + unsigned count[MAX_CODE_LENGTH + 1]; /* 1 sentinel (first pos) */ + uint16_t perm[MAX_ALPHA_SIZE]; +}; +/* start[] - decoding start point. `k = start[c] & 0x1F' is code + length. If k <= HUFF_START_WIDTH then `s = start[c] >> 5' is the + immediate symbol value. If k > HUFF_START_WIDTH then s is + undefined, but code starting with c is guaranteed to be at least k + bits long. + + base[] - base codes. For k in 1..20, base[k] is either the first + code of length k or it is equal to base[k+1] if there are no codes + of length k. The other 2 elements are sentinels: base[0] is always + zero, base[21] is plus infinity (represented as UINT64_MAX). + + count[] - cumulative code length counts. For k in 1..20, count[k] + is the number of symbols which codes are shorter than k bits; + count[0] is a sentinel (always zero). + + perm[] - sorting permutation. The rules of canonical prefix coding + require that the source alphabet is sorted stably by ascending code + length (the order of symbols of the same code length is preserved). + The perm table holds the sorting permutation. +*/ + + +#define ROW_WIDTH 16u +#define SLIDE_LENGTH 8192u +#define NUM_ROWS (256u / ROW_WIDTH) +#define CMAP_BASE (SLIDE_LENGTH - 256) + +struct retriever_internal_state { + unsigned state; /* current state of retriever FSA */ + uint8_t selector[MAX_SELECTORS]; /* coding tree selectors */ + unsigned num_trees; /* number of prefix trees used */ + unsigned num_selectors; /* number of tree selectors present */ + unsigned alpha_size; /* number of distinct prefix codes */ + uint8_t code_len[MAX_ALPHA_SIZE]; + unsigned mtf[MAX_TREES]; /* current state of inverse MTF FSA */ + struct tree tree[MAX_TREES]; /* coding trees */ + + uint16_t big; /* big descriptor of the bitmap */ + uint16_t small; /* small descriptor of the bitmap */ + unsigned j; /* general purpose index */ + unsigned t; /* current tree number */ + unsigned g; /* current group number */ + + uint8_t *imtf_row[NUM_ROWS]; + uint8_t imtf_slide[SLIDE_LENGTH]; + unsigned runChar; + unsigned run; + unsigned shift; +}; + + +/* FSM states from which retriever can be started or resumed. */ +enum { + S_INIT, + S_BWT_IDX, + S_BITMAP_BIG, + S_BITMAP_SMALL, + S_SELECTOR_MTF, + S_DELTA_TAG, + S_PREFIX, +}; + + +/* Internal symbol values differ from that used in bzip2! + 257 - RUN-A + 258 - RUN-B + 1-255 - MTFV + 0 - EOB +*/ +#define RUN_A (256+1) +#define RUN_B (256+2) +#define EOB 0 +#define RUN(s) ((s) - 256) +#define IS_RUN(s) ((s) >= 256) +#define IS_EOB(s) ((s) == EOB) + + +/* Given a list of code lengths, make a set of tables to decode that + set of codes. Return value is passed in mtf array of the decoder + state. On success value from zero to five is passed (the tables + are built only in this case), but also error codes ERR_INCOMPLT or + ERR_PREFIX may be returned, which means that given code set is + incomplete or (respectively) the code is invalid (an oversubscribed + set of lengths). + + Because the alphabet size is always less or equal to 258 (2 RUN + symbols, at most 255 MFV values and 1 EOB symbol) the average code + length is strictly less than 9. Hence the probability of decoding + code longer than 10 bits is quite small (usually < 0.2). + + lbzip2 utilises this fact by implementing a hybrid algorithm for + prefix decoding. For codes of length <= 10 lbzip2 maintains a LUT + (look-up table) that maps codes directly to corresponding symbol + values. Codes longer than 10 bits are not mapped by the LUT are + decoded using cannonical prefix decoding algorithm. + + The above value of 10 bits was determined using a series of + benchmarks. It's not hardcoded but instead it is defined as a + constant HUFF_START_WIDTH (see the comment above). If on some + system a different value works better, it can be adjusted freely. +*/ +static void +make_tree(struct retriever_internal_state *rs) +{ + unsigned n; /* alphabet size */ + const uint8_t *L; /* code lengths */ + uint32_t *C; /* code length count; C[0] is a sentinel */ + uint64_t *B; /* left-justified base */ + uint16_t *P; /* symbols sorted by code length */ + uint16_t *S; /* lookup table */ + + unsigned k; /* current code length */ + unsigned s; /* current symbol */ + unsigned cum; + unsigned code; + uint64_t sofar; + uint64_t next; + uint64_t inc; + uint64_t v; + + /* Initialize constants. */ + n = rs->alpha_size; + L = rs->code_len; + C = rs->tree[rs->t].count; + B = rs->tree[rs->t].base; + P = rs->tree[rs->t].perm; + S = rs->tree[rs->t].start; + + /* Count symbol lengths. */ + for (k = 0; k <= MAX_CODE_LENGTH; k++) + C[k] = 0; + for (s = 0; s < n; s++) { + k = L[s]; + C[k]++; + } + /* Make sure there are no zero-length codes. */ + assert(C[0] == 0); + + /* Check if Kraft's inequality is satisfied. */ + sofar = 0; + for (k = MIN_CODE_LENGTH; k <= MAX_CODE_LENGTH; k++) + sofar += (uint64_t)C[k] << (MAX_CODE_LENGTH - k); + if (sofar != (1 << MAX_CODE_LENGTH)) { + rs->mtf[rs->t] = + sofar < (1 << MAX_CODE_LENGTH) ? ERR_INCOMPLT : ERR_PREFIX; + return; + } + + /* Create left-justified base table. */ + sofar = 0; + for (k = MIN_CODE_LENGTH; k <= MAX_CODE_LENGTH; k++) { + next = sofar + ((uint64_t)C[k] << (64 - k)); + assert(next == 0 || next >= sofar); + B[k] = sofar; + sofar = next; + } + /* Ensure that "sofar" has overflowed to zero. */ + assert(sofar == 0); + + /* The last few entries of lj-base may have overflowed to zero, so replace + all trailing zeros with the greatest possible 64-bit value (which is + greater than the greatest possible left-justified base). + */ + assert(k == MAX_CODE_LENGTH + 1); + do { + assert(k > MIN_CODE_LENGTH); + assert(k > MAX_CODE_LENGTH || B[k] == 0); + B[k--] = -1; + } + while (C[k] == 0); + + /* Transform counts into indices (cumulative counts). */ + cum = 0; + for (k = MIN_CODE_LENGTH; k <= MAX_CODE_LENGTH; k++) { + uint32_t t1 = C[k]; + C[k] = cum; + cum += t1; + } + assert(cum == n); + + /* Perform counting sort. */ + P[C[L[0]]++] = RUN_A; + P[C[L[1]]++] = RUN_B; + for (s = 2; s < n - 1; s++) + P[C[L[s]]++] = s - 1; + P[C[L[n - 1]]++] = EOB; + + /* Create first, complete start entries. */ + code = 0; + inc = 1 << (HUFF_START_WIDTH - 1); + for (k = 1; k <= HUFF_START_WIDTH; k++) { + for (s = C[k - 1]; s < C[k]; s++) { + uint16_t x = (P[s] << 5) | k; + v = code; + code += inc; + while (v < code) + S[v++] = x; + } + inc >>= 1; + } + + /* Fill remaining, incomplete start entries. */ + assert(k == HUFF_START_WIDTH + 1); + sofar = (uint64_t)code << (64 - HUFF_START_WIDTH); + while (code < (1 << HUFF_START_WIDTH)) { + while (sofar >= B[k + 1]) + k++; + S[code] = k; + code++; + sofar += (uint64_t)1 << (64 - HUFF_START_WIDTH); + } + assert(sofar == 0); + + /* Restore cumulative counts as they were destroyed by the sorting + phase. The sentinel wasn't touched, so no need to restore it. */ + for (k = MAX_CODE_LENGTH; k > 0; k--) { + C[k] = C[k - 1]; + } + assert(C[0] == 0); + + /* Valid tables were created successfully. */ + rs->mtf[rs->t] = rs->t; +} + + +/* The following is a lookup table for determining the position + of the first zero bit (starting at the most significant bit) + in a 6-bit integer. + + 0xxxxx... -> 1 + 10xxxx... -> 2 + 110xxx... -> 3 + 1110xx... -> 4 + 11110x... -> 5 + 111110... -> 6 + 111111... -> no zeros (marked as 7) +*/ +static const uint8_t table[64] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, +}; + +/* Pattern L[] R[] + 0xxxxx 1 0 + 100xxx 3 +1 + 10100x 5 +2 + 101010 6 +3 + 101011 6 +1 + 10110x 5 0 + 101110 6 +1 + 101111 6 -1 + 110xxx 3 -1 + 11100x 5 0 + 111010 6 +1 + 111011 6 -1 + 11110x 5 -2 + 111110 6 -1 + 111111 6 -3 + + The actual R[] entries are biased (3 is added). +*/ +static const uint8_t L[64] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 6, 6, 5, 5, 6, 6, + 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 6, 6, 5, 5, 6, 6, +}; + +static const uint8_t R[64] = { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 4, 3, 3, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 2, 1, 1, 2, 0, +}; + + +#define DECLARE unsigned w; uint64_t v; const uint32_t *next, *limit, \ + *tt_limit; uint32_t *tt +#define SAVE() (bs->buff = v, bs->live = w, bs->data = next, \ + ds->block_size = tt - ds->tt) +#define RESTORE() (v = bs->buff, w = bs->live, next = bs->data, \ + limit = bs->limit, tt = ds->tt + ds->block_size, \ + tt_limit = ds->tt + MAX_BLOCK_SIZE) + +/* Make sure that bit buffer v holds at least 32 bits, but no more + than 63. + + If there buffer contains from 0 to 31 bits then an attempt to + append next 32 bits is made. If there is not enough input + available then current state is saved (including FSM state, which + is saved as s) and the function returns. + + Note that it would be wrong to put more than 63 bits (i.e. 64 bits) + in v as a potential value of UINT64_MAX could be misrepresented as + plus infinity. +*/ +#define NEED(s) \ + { \ + if (w < 32u) { \ + if (unlikely(next == limit)) { \ + SAVE(); \ + if (bs->eof) \ + return ERR_EOF; \ + rs->state = (s); \ + return MORE; \ + case (s): \ + if (unlikely(bs->data == bs->limit)) { \ + assert(bs->eof); \ + return ERR_EOF; \ + } \ + RESTORE(); \ + assert (w < 32u); \ + } \ + v |= (uint64_t)ntohl(*next) << (64u - (w += 32u)); \ + next++; \ + } \ + } + +/* Same as NEED(), but assumes that there is at least one 32-bit word + of input available. */ +#define NEED_FAST() \ + { \ + if (w < 32u) { \ + v |= (uint64_t)ntohl (*next) << (64u - (w += 32u)); \ + next++; \ + } \ + } + +/* Return k most significant bits of bit buffer v. */ +#define PEEK(k) (v >> (64u - (k))) + +/* Remove k most significant bits of bit buffer v. */ +#define DUMP(k) (v <<= (k), w -= (k), (void)0) + +/* Remove and return k most significant bits of bit buffer v. */ +#define TAKE(x,k) ((x) = PEEK(k), DUMP(k)) + + +/* Implementation of Sliding Lists algorithm for doing Inverse + Move-To-Front (IMTF) transformation in O(n) space and amortized + O(sqrt(n)) time. The naive IMTF algorithm does the same in both + O(n) space and time. + + IMTF could be done in O(log(n)) time using algorithms based on + (quite) complex data structures such as self-balancing binary + search trees, but these algorithms have quite big constant factor + which makes them impractical for MTF of 256 items. +*/ +#if defined(MTF_NEON) || defined(MTF_SSSE3) +/* Moving row nn to the front and shifting everything above it up by one is a + single byte shuffle: byte i of the result is byte mtf_shuffle[nn][i] of the + row. */ +static const uint8_t mtf_shuffle[16][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 3, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 5, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 6, 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 7, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 8, 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15 }, + { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15 }, + { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15 }, + { 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15 }, + { 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15 }, + { 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 }, + { 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15 }, + { 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, +}; + +static void +shuffle_row(uint8_t *pp, unsigned nn) +{ +#ifdef MTF_NEON + vst1q_u8(pp, vqtbl1q_u8(vld1q_u8(pp), vld1q_u8(mtf_shuffle[nn]))); +#else + _mm_storeu_si128((__m128i *)pp, + _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)pp), + _mm_loadu_si128((const __m128i *) + mtf_shuffle[nn]))); +#endif +} +#endif + + +static uint8_t +mtf_one(uint8_t **imtf_row, uint8_t *imtf_slide, uint8_t c) +{ + uint8_t *pp; + + /* We expect the index to be small, so we have a special case for that. */ + if (likely(c < ROW_WIDTH)) { + unsigned nn = c; + + pp = imtf_row[0]; + c = pp[nn]; + + /* Forgive me the ugliness of this code, but mtf_one() is executed + frequently and needs to be fast. + */ +#if ROW_WIDTH != 16 +# error "mtf_one() shifts a row of exactly sixteen bytes" +#endif +#if defined(MTF_NEON) || defined(MTF_SSSE3) + { + shuffle_row(pp, nn); + return c; + } +#endif + switch (nn) { + default: + abort(); +#define R(n) FALLTHROUGH case n: pp[n] = pp[n-1] + R(15); R(14); R(13); R(12); R(11); R(10); R(9); + R(8); R(7); R(6); R(5); R(4); R(3); R(2); R(1); +#undef R + } + } + else { /* A general case for indices >= ROW_WIDTH. */ + + /* If the sliding list already reached the bottom of memory pool + allocated for it, we need to rebuild it. */ + if (unlikely(imtf_row[0] == imtf_slide)) { + uint8_t *kk = imtf_slide + SLIDE_LENGTH; + uint8_t **rr = imtf_row + NUM_ROWS; + + while (rr > imtf_row) { + uint8_t *bg = *--rr; + uint8_t *bb = bg + ROW_WIDTH; + + assert(bg >= imtf_slide && bb <= imtf_slide + SLIDE_LENGTH); + + while (bb > bg) + *--kk = *--bb; + *rr = kk; + } + } + + { + uint8_t **lno = imtf_row + c / ROW_WIDTH; + uint8_t *bb = *lno; + + pp = bb + c % ROW_WIDTH; + c = *pp; + + while (pp > bb) { + uint8_t *tt = pp--; + + *tt = *pp; + } + + while (lno > imtf_row) { + uint8_t **lno1 = lno; + + pp = --(*--lno); + **lno1 = pp[ROW_WIDTH]; + } + } + } + + *pp = c; + return c; +} + + +int +retrieve(struct decoder_state *restrict ds, struct bitstream *bs) +{ + struct retriever_internal_state *restrict rs = ds->internal_state; + + DECLARE; + RESTORE(); + + switch (rs->state) { + case S_INIT: + NEED(S_BWT_IDX); + TAKE(ds->rand, 1u); + TAKE(ds->bwt_idx, 24u); + + /* Retrieve bitmap. */ + NEED(S_BITMAP_BIG); + TAKE(rs->big, 16u); + rs->small = 0; + rs->alpha_size = 0u; + rs->j = 0; + do { + if (rs->big & 0x8000) { + TAKE(rs->small, 16u); + NEED(S_BITMAP_SMALL); + } + do { + rs->imtf_slide[CMAP_BASE + rs->alpha_size] = rs->j++; + rs->alpha_size += rs->small >> 15; + rs->small <<= 1; + } + while (rs->j & 0xF); + rs->big <<= 1; + } + while (rs->j < 256u); + + if (rs->alpha_size == 0) + return ERR_BITMAP; + rs->alpha_size += 2u; /* -1 MTFV, +2 RUN, +1 EOB */ + + TAKE(rs->num_trees, 3u); + if (rs->num_trees < MIN_TREES || rs->num_trees > MAX_TREES) + return ERR_TREES; + + TAKE(rs->num_selectors, 15u); + if (rs->num_selectors == 0) + return ERR_GROUPS; + + /* Retrieve selector MTF values. */ + for (rs->j = 0; rs->j < rs->num_selectors; rs->j++) { + unsigned k = table[PEEK(6u)]; + + if (unlikely(k > rs->num_trees)) + return ERR_SELECTOR; + rs->selector[rs->j] = k - 1u; + DUMP(k); + NEED(S_SELECTOR_MTF); + } + + /* Retrieve decoding tables. */ + for (rs->t = 0; rs->t < rs->num_trees; rs->t++) { + rs->j = 0u; + TAKE(rs->code_len[0u], 5); + + while (rs->j < rs->alpha_size) { + unsigned k = PEEK(6u); + + rs->code_len[rs->j] += R[k]; + if (unlikely(rs->code_len[rs->j] < 3 + MIN_CODE_LENGTH || + rs->code_len[rs->j] > 3 + MAX_CODE_LENGTH)) + return ERR_DELTA; + rs->code_len[rs->j] -= 3; + k = L[k]; + if (k != 6u) { + rs->j++; + if (rs->j < rs->alpha_size) + rs->code_len[rs->j] = rs->code_len[rs->j - 1u]; + } + DUMP(k); + NEED(S_DELTA_TAG); + } + + make_tree(rs); + } + + /* Initialize IMTF decoding structure. */ + { + unsigned i; + + for (i = 0; i < NUM_ROWS; i++) + rs->imtf_row[i] = rs->imtf_slide + CMAP_BASE + i * ROW_WIDTH; + } + + rs->runChar = rs->imtf_row[0][0]; + rs->run = 0; + rs->shift = 0; + + /* Initialize IBWT frequency table. */ + memset(ds->ftab, 0, sizeof(ds->ftab)); + + /* Retrieve block MTF values. + + Block MTF values (MTFV) are prefix-encoded with varying trees. + MTFVs are divided into max. 18000 groups, each group contains 50 MTFVs + (except the last one, which can contain from 1 to 50 MTFVs). + + Each group has assigned a prefix-free codebook. As there are up to 6 + codebooks, the group's codebook number (called selector) is a value + from 0 to 5. A selector of 6 or 7 means oversubscribed or incomplete + codebook. If such selector is encountered, decoding is aborted. + */ + + /* Bound selectors at 18001. */ + if (rs->num_selectors > 18001) + rs->num_selectors = 18001; + + for (rs->g = 0; rs->g < rs->num_selectors; rs->g++) { + unsigned s, x, k, i; + + /* Select the tree coding this group. */ + i = rs->selector[rs->g]; + rs->t = rs->mtf[i]; + if (unlikely(rs->t >= MAX_TREES)) + return rs->t; + + /* Update IMTF table. */ + for (; i > 0; i--) + rs->mtf[i] = rs->mtf[i - 1]; + rs->mtf[0] = rs->t; + + /* In one coding group we can have at most 50 codes, 20 bits + each, so the largest possible group size is 1000 bits. If + there are at least 1000 bits of input available then we can + safely assume that the whole group can be decoded without + asking for more input. + + There are two code paths. The first one is executed when + there is at least 1024 bits of input available (i.e. 32 + words, 32 bits each). In this case we can apply several + optimizations, most notably we are allowed to keep state in + local variables and we can use NEED_FAST() - faster version + of NEED(). The second code path is executed when there is + not enough input to for fast decoding. + */ + if (likely((limit - next) >= 32)) { + struct tree *T = &rs->tree[rs->t]; + unsigned j; + unsigned run = rs->run; + unsigned runChar = rs->runChar; + unsigned shift = rs->shift; + + for (j = 0; j < GROUP_SIZE; j++) { + NEED_FAST(); + x = T->start[PEEK(HUFF_START_WIDTH)]; + k = x & 0x1F; + + if (likely(k <= HUFF_START_WIDTH)) { + s = x >> 5; + } + else { + while (v >= T->base[k + 1]) + k++; + s = T->perm[T->count[k] + ((v - T->base[k]) >> (64 - k))]; + } + + DUMP(k); + + if (unlikely(IS_EOB(s))) { + rs->run = run; + rs->runChar = runChar; + goto eob; + } + + if (likely(IS_RUN(s) && run <= MAX_BLOCK_SIZE)) { + run += RUN(s) << shift++; + continue; + } + + if (unlikely(run > (size_t)(tt_limit - tt))) { + return ERR_OVERFLOW; + } + + ds->ftab[runChar] += run; + while (run-- > 0) { + *tt++ = runChar; + } + + runChar = mtf_one(rs->imtf_row, rs->imtf_slide, s); + shift = 0; + run = 1; + } + + rs->run = run; + rs->runChar = runChar; + rs->shift = shift; + } + else { + /* There are up to GROUP_SIZE codes in any group. */ + for (rs->j = 0; rs->j < GROUP_SIZE; rs->j++) { + struct tree *T; + + NEED(S_PREFIX); + T = &rs->tree[rs->t]; + x = T->start[PEEK(HUFF_START_WIDTH)]; + k = x & 0x1F; + + if (likely(k <= HUFF_START_WIDTH)) { + /* Use look-up table in average case. */ + s = x >> 5; + } + else { + /* Code length exceeds HUFF_START_WIDTH, use canonical + prefix decoding algorithm instead of look-up table. */ + while (v >= T->base[k + 1]) + k++; + s = T->perm[T->count[k] + ((v - T->base[k]) >> (64 - k))]; + } + + DUMP(k); + + if (unlikely(IS_EOB(s))) { + eob: + if (unlikely(rs->run > (size_t)(tt_limit - tt))) + return ERR_OVERFLOW; + + ds->ftab[rs->runChar] += rs->run; + while (rs->run--) { + *tt++ = rs->runChar; + } + + SAVE(); + + /* Sanity-check the BWT primary index. */ + if (ds->block_size == 0) + return ERR_EMPTY; + if (ds->bwt_idx >= ds->block_size) + return ERR_BWTIDX; + + free(ds->internal_state); + ds->internal_state = NULL; + return OK; + } + + /* If we decoded a RLE symbol, increase run length and keep + going. However, we need to stop accepting RLE symbols if + the run gets too long. Note that rejecting further RLE + symbols after the run has reached the length of 900k bytes + is perfectly correct because runs longer than 900k bytes + will cause block overflow anyways and hence stop decoding + with an error. */ + if (likely(IS_RUN(s) && rs->run <= MAX_BLOCK_SIZE)) { + rs->run += RUN(s) << rs->shift++; + continue; + } + + /* At this point we most likely have a run of one or more + bytes. Zero-length run is possible only at the beginning, + once per block, so any optimization involving zero-length + runs are pointless. */ + if (unlikely(rs->run > (size_t)(tt_limit - tt))) { + return ERR_OVERFLOW; + } + + /* Dump the run. */ + ds->ftab[rs->runChar] += rs->run; + while (rs->run-- > 0) { + *tt++ = rs->runChar; + } + + rs->runChar = mtf_one(rs->imtf_row, rs->imtf_slide, s); + rs->shift = 0; + rs->run = 1; + } + } + } + + return ERR_UNTERM; + + default: + abort(); + } +} + + +/*== IBWT / IMTF ==*/ + +/* Block size threshold above which block randomization has any effect. + Randomizing blocks of size <= RAND_THRESH is a no-op. +*/ +#define RAND_THRESH 617u + +/* A table filled with arbitrary numbers, in range 50-999, used for + derandomizing randomized blocks. These numbers are strictly related + to the bzip2 file format and they are not subject to change. +*/ +static const uint16_t rand_table[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863, + 491, 741, 242, 949, 214, 733, 859, 335, 708, 621, 574, +73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, +51, 878, 465, 811, 169, 869, + 675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, +59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727, + 476, 693, 425, 174, 647, +73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 641, 801, 220, 162, 819, + 984, 589, 513, 495, 799, 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, +98, 553, 163, 354, 666, + 933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, +68, 770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383, + 461, 404, 758, 839, 887, 715, +67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, +79, 804, +96, 409, 713, 940, 652, 934, 970, 447, 318, + 353, 859, 672, 112, 785, 645, 863, 803, 350, 139, +93, 354, +99, 820, 908, + 609, 772, 154, 274, 580, 184, +79, 626, 630, 742, 653, 282, 762, 623, 680, + +81, 927, 626, 789, 125, 411, 521, 938, 300, 821, +78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, +78, 352, 126, 857, 956, 358, 619, 580, + 124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, +52, 600, 747, 642, 182, 862, +81, 344, 805, 988, 739, 511, + 655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, +51, 686, 754, 806, 760, 493, + 403, 415, 394, 687, 700, 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879, 194, 572, 640, + 724, 926, +56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, +59, +87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631, + 212, 174, 643, 304, 329, 343, +97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, +73, 263, 980, 736, 876, 478, 430, 305, 170, 514, 364, 692, 829, + +82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, +82, 896, 831, 547, 261, 524, + 462, 293, 465, 502, +56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, +61, 688, 793, 644, 986, + 403, 106, 366, 905, 644, 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713, 857, + 265, 203, +50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638, +}; + + +void +decode(struct decoder_state *ds) +{ + uint32_t i, j, k; + uint32_t cum; + uint8_t uc; + + uint32_t *tt = ds->tt; + + /* Transform counts into indices (cumulative counts). */ + cum = 0; + for (i = 0; i < 256; i++) + ds->ftab[i] = (cum += ds->ftab[i]) - ds->ftab[i]; + assert(cum == ds->block_size); + + + /* Construct the IBWT singly-linked cyclic list. Traversing that list + starting at primary index produces the source string. + + Each list node consists of a pointer to the next node and a character + of the source string. Those 2 values are packed into a single 32bit + integer. The character is kept in bits 0-7 and the pointer in stored + in bits 8-27. Bits 28-31 are unused (always clear). + + Note: Iff the source string consists of a string repeated k times + (eg. ABABAB - the string AB is repeated k=3 times) then this algorithm + will construct k independent (not connected), isomorphic lists. + */ + for (i = 0u; i < ds->block_size; i++) { + uc = tt[i]; + tt[ds->ftab[uc]] += (i << 8); + ds->ftab[uc]++; + } + assert(ds->ftab[255] == ds->block_size); + + /* Derandomize the block if necessary. + + The derandomization algorithm is implemented inefficiently, but the + assumption is that randomized blocks are unlikely to be encountered. + Most of bzip2 implementations try to avoid randomizing blocks because + it usually leads to decreased compression ratio. + */ + if (unlikely(ds->rand)) { + /* Compute IBWT in-situ. A slower algorithm based on binary search is used + to avoid extra memory allocation. */ + j = ds->bwt_idx; + for (i = 0; i < ds->block_size; i++) { + k = 0; + if (j >= ds->ftab[k + 127]) k += 128; + if (j >= ds->ftab[k + 63]) k += 64; + if (j >= ds->ftab[k + 31]) k += 32; + if (j >= ds->ftab[k + 15]) k += 16; + if (j >= ds->ftab[k + 7]) k += 8; + if (j >= ds->ftab[k + 3]) k += 4; + if (j >= ds->ftab[k + 1]) k += 2; + if (j >= ds->ftab[k + 0]) k += 1; + tt[i] = (tt[i] & ~0xFF) + k; + j = tt[j] >> 8; + } + + /* Derandomize the block. */ + i = 0, j = RAND_THRESH; + while (j < ds->block_size) { + tt[j] ^= 1; + i = (i + 1) & 0x1FF; + j += rand_table[i]; + } + + /* Reform a linked list. */ + for (i = 0; i < ds->block_size; i++) + tt[i] = ((i + 1) << 8) + (tt[i] & 0xFF); + } + + ds->rle_state = 0; + ds->rle_crc = -1; + ds->rle_index = ds->rand ? 0 : ds->tt[ds->bwt_idx]; + ds->rle_avail = ds->block_size; + ds->rle_prev = 0; + ds->rle_char = 0; +} + + +#define M1 0xFFFFFFFFu + + +/* Emit decoded block into buffer buf of size *buf_sz. Buffer size is + updated to reflect the remaining space left in the buffer. + + Returns OK if the block was completely emitted, MORE if more output + space is needed to fully emit the block or ERR_RUNLEN if data error + was detected (missing run length). +*/ +int +emit(struct decoder_state *ds, void *buf, size_t *buf_sz) +{ + uint32_t p; /* IBWT linked list pointer */ + uint32_t a; /* available input bytes */ + uint32_t s; /* CRC checksum */ + uint8_t c; /* current character */ + uint8_t d; /* next character */ + const uint32_t *t; /* IBWT linked list base address */ + uint8_t *b; /* next free byte in output buffer */ + uint32_t m; /* number of free output bytes available */ + + assert(ds); + assert(buf); + assert(buf_sz && *buf_sz > 0); + + t = ds->tt; + b = buf; + m = *buf_sz; + + s = ds->rle_crc; + p = ds->rle_index; + a = ds->rle_avail; + c = ds->rle_char; + d = ds->rle_prev; + + + /*=== UNRLE FINITE STATE AUTOMATON ===*/ + /* There are 6 states, numbered from 0 to 5. */ + + /* Excuse me, but the following is a write-only code. It wasn't written + for readability or maintainability, but rather for high efficiency. */ + switch (ds->rle_state) { + default: + abort(); + case 1: + if (unlikely(!m--)) + break; + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (c != d) + break; + if (unlikely(!a--)) + break; + c = p = t[p >> 8]; + /* fall-through */ + case 2: + if (unlikely(!m--)) { + ds->rle_state = 2; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (c != d) + break; + if (unlikely(!a--)) + break; + c = p = t[p >> 8]; + /* fall-through */ + case 3: + if (unlikely(!m--)) { + ds->rle_state = 3; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (c != d) + break; + if (unlikely(!a--)) + return ERR_RUNLEN; + c = p = t[p >> 8]; + /* fall-through */ + case 4: + if (unlikely(m < c)) { + c -= m; + while (m--) + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = d)]; + ds->rle_state = 4; + break; + } + m -= c; + while (c--) + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = d)]; + /* fall-through */ + case 0: + if (unlikely(!a--)) + break; + c = p = t[p >> 8]; + /* fall-through */ + case 5: + if (unlikely(!m--)) { + ds->rle_state = 5; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + } + + if (likely(a != M1 && m != M1)) { + for (;;) { + if (unlikely(!a--)) + break; + d = c; + c = p = t[p >> 8]; + if (unlikely(!m--)) { + ds->rle_state = 1; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (likely(c != d)) { + if (unlikely(!a--)) + break; + d = c; + c = p = t[p >> 8]; + if (unlikely(!m--)) { + ds->rle_state = 1; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (likely(c != d)) { + if (unlikely(!a--)) + break; + d = c; + c = p = t[p >> 8]; + if (unlikely(!m--)) { + ds->rle_state = 1; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (likely(c != d)) { + if (unlikely(!a--)) + break; + d = c; + c = p = t[p >> 8]; + if (unlikely(!m--)) { + ds->rle_state = 1; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (c != d) + continue; + } + } + } + if (unlikely(!a--)) + break; + c = p = t[p >> 8]; + if (unlikely(!m--)) { + ds->rle_state = 2; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (c != d) + continue; + if (unlikely(!a--)) + break; + c = p = t[p >> 8]; + if (unlikely(!m--)) { + ds->rle_state = 3; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + if (c != d) + continue; + if (unlikely(!a--)) + return ERR_RUNLEN; + if (m < (c = p = t[p >> 8])) { + c -= m; + while (m--) + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = d)]; + ds->rle_state = 4; + break; + } + m -= c; + while (c--) + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = d)]; + if (unlikely(!a--)) + break; + c = p = t[p >> 8]; + if (unlikely(!m--)) { + ds->rle_state = 5; + break; + } + s = (s << 8) ^ crc_table[(s >> 24) ^ (*b++ = c)]; + } + } + + /* Exactly one of `a' and `m' is equal to M1. */ + assert((a == M1) != (m == M1)); + + ds->rle_avail = a; + if (m == M1) { + assert(a != M1); + ds->rle_index = p; + ds->rle_char = c; + ds->rle_prev = d; + ds->rle_crc = s; + *buf_sz = 0; + return MORE; + } + + assert(a == M1); + ds->crc = s ^ M1; + *buf_sz = m; + return OK; +} + + +void +decoder_init(struct decoder_state *ds) +{ + ds->internal_state = XMALLOC(struct retriever_internal_state); + ds->internal_state->state = S_INIT; + + ds->tt = XNMALLOC(MAX_BLOCK_SIZE, uint32_t); + ds->block_size = 0; +} + + +void +decoder_free(struct decoder_state *ds) +{ + free(ds->tt); + free(ds->internal_state); +} diff --git a/bwt/lbzip2/decode.h b/bwt/lbzip2/decode.h new file mode 100644 index 00000000..72e9d04a --- /dev/null +++ b/bwt/lbzip2/decode.h @@ -0,0 +1,79 @@ +/*- + decode.h -- low-level decompressor header + + Copyright (C) 2012, 2014 Mikolaj Izdebski + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +struct header { + int bs100k; + uint32_t crc; +}; + + +struct parser_state { + int state; + int bs100k; + uint32_t stored_crc; + uint32_t computed_crc; + int stream_mode; +}; + + +struct in_blk; + +struct bitstream { + unsigned live; + uint64_t buff; + struct in_blk *block; + const uint32_t *data; + const uint32_t *limit; + bool eof; +}; + + +struct decoder_state { + struct retriever_internal_state *internal_state; + + bool rand; /* block randomized */ + unsigned bwt_idx; /* BWT primary index */ + unsigned block_size; /* compressed block size */ + uint32_t crc; /* expected block CRC */ + uint32_t ftab[256]; /* frequency table used in counting sort */ + uint32_t *tt; + + int rle_state; /* FSA state */ + uint32_t rle_crc; /* CRC checksum */ + uint32_t rle_index; /* IBWT linked list pointer */ + uint32_t rle_avail; /* available input bytes */ + uint8_t rle_char; /* current character */ + uint8_t rle_prev; /* prevoius character */ +}; + + +struct source; + +void parser_init(struct parser_state *ps, int bs100k, int stream_mode); +int parse(struct parser_state *ps, struct header *hd, struct bitstream *bs, + unsigned *garbage); +int scan(struct bitstream *bs, unsigned skip); + +void decoder_init(struct decoder_state *ds); +void decoder_free(struct decoder_state *ds); +int retrieve(struct decoder_state *ds, struct bitstream *bs); +void decode(struct decoder_state *ds); +int emit(struct decoder_state *ds, void *buf, size_t *buf_sz); diff --git a/bwt/lbzip2/divbwt.c b/bwt/lbzip2/divbwt.c new file mode 100644 index 00000000..bbc4b2d8 --- /dev/null +++ b/bwt/lbzip2/divbwt.c @@ -0,0 +1,1726 @@ +/*- + divbwt.c -- Burrows-Wheeler transformation + + Copyright (C) 2012, 2014 Mikolaj Izdebski + Copyright (c) 2012 Yuta Mori + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +#include "common.h" + +#include "encode.h" + +#include /* memset() */ + + +/*- Settings -*/ +#define SS_INSERTIONSORT_THRESHOLD 8 +#define SS_BLOCKSIZE 1024 +#define ALPHABET_SIZE 256 + + +/*- Datatypes -*/ +typedef uint8_t sauchar_t; +typedef int32_t saidx_t; +typedef int_fast32_t saint_t; + + +/*- Constants -*/ +#define INLINE +/* for sssort.c */ +#if defined(SS_INSERTIONSORT_THRESHOLD) +# if SS_INSERTIONSORT_THRESHOLD < 1 +# undef SS_INSERTIONSORT_THRESHOLD +# define SS_INSERTIONSORT_THRESHOLD (1) +# endif +#else +# define SS_INSERTIONSORT_THRESHOLD (8) +#endif +#if defined(SS_BLOCKSIZE) +# if SS_BLOCKSIZE < 0 +# undef SS_BLOCKSIZE +# define SS_BLOCKSIZE (0) +# elif 32768 <= SS_BLOCKSIZE +# undef SS_BLOCKSIZE +# define SS_BLOCKSIZE (32767) +# endif +#else +# define SS_BLOCKSIZE (1024) +#endif +/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */ +#if SS_BLOCKSIZE == 0 +# if defined(BUILD_DIVSUFSORT64) +# define SS_MISORT_STACKSIZE (96) +# else +# define SS_MISORT_STACKSIZE (64) +# endif +#elif SS_BLOCKSIZE <= 4096 +# define SS_MISORT_STACKSIZE (16) +#else +# define SS_MISORT_STACKSIZE (24) +#endif +#if defined(BUILD_DIVSUFSORT64) +# define SS_SMERGE_STACKSIZE (64) +#else +# define SS_SMERGE_STACKSIZE (32) +#endif +/* for trsort.c */ +#define TR_INSERTIONSORT_THRESHOLD (8) +#if defined(BUILD_DIVSUFSORT64) +# define TR_STACKSIZE (96) +#else +# define TR_STACKSIZE (64) +#endif + +/*- Macros -*/ +#ifndef SWAP +# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0) +#endif /* SWAP */ +#ifndef MIN +# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +#endif /* MIN */ +#define STACK_PUSH(_a, _b, _c, _d)\ + do {\ + assert(ssize < STACK_SIZE);\ + stack[ssize].a = (_a), stack[ssize].b = (_b),\ + stack[ssize].c = (_c), stack[ssize++].d = (_d);\ + } while(0) +#define STACK_PUSH5(_a, _b, _c, _d, _e)\ + do {\ + assert(ssize < STACK_SIZE);\ + stack[ssize].a = (_a), stack[ssize].b = (_b),\ + stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\ + } while(0) +#define STACK_POP(_a, _b, _c, _d)\ + do {\ + assert(0 <= ssize);\ + if(ssize == 0) { return; }\ + (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ + (_c) = stack[ssize].c, (_d) = stack[ssize].d;\ + } while(0) +#define STACK_POP5(_a, _b, _c, _d, _e)\ + do {\ + assert(0 <= ssize);\ + if(ssize == 0) { return; }\ + (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ + (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\ + } while(0) +/* for divsufsort.c */ +#define BUCKET_A(_c0) bucket[(_c0) + ALPHABET_SIZE * ALPHABET_SIZE] +#if ALPHABET_SIZE == 256 +#define BUCKET_B(_c0, _c1) (bucket[((_c1) << 8) | (_c0)]) +#define BUCKET_BSTAR(_c0, _c1) (bucket[((_c0) << 8) | (_c1)]) +#else +#define BUCKET_B(_c0, _c1) (bucket[(_c1) * ALPHABET_SIZE + (_c0)]) +#define BUCKET_BSTAR(_c0, _c1) (bucket[(_c0) * ALPHABET_SIZE + (_c1)]) +#endif +/* for trsort.c */ +#define TR_GETC(_p) (((_p) < (ISAn - ISAd)) ? ISAd[(_p)] : ISA[(ISAd - ISA + (_p)) % (ISAn - ISA)]) +/* for sssort.c and trsort.c */ +static const saint_t lg_table[256]= { + -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +static +saidx_t +getidx(saidx_t *pa) { + saidx_t a = *pa; + return (0 <= a) ? a : ~a; +} + +/*---- sssort ----*/ + +/*- Private Functions -*/ + +#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) + +static INLINE +saint_t +ss_ilg(saidx_t n) { + return (n & 0xff00) ? + 8 + lg_table[(n >> 8) & 0xff] : + 0 + lg_table[(n >> 0) & 0xff]; +} + +#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ + +#if SS_BLOCKSIZE != 0 + +static const saint_t sqq_table[256] = { + 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, + 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, + 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, +110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, +128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, +143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, +156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, +169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180, +181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, +192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, +202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, +212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, +221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, +230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, +239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, +247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255 +}; + +static INLINE +saidx_t +ss_isqrt(saidx_t x) { + saidx_t y, e; + + assert(x <= 0x00ffffff); + if(x < 0x100) { return sqq_table[x] >> 4; } + + if(x < 0x10000) { + e = 8 + lg_table[(x >> 8) & 0xff]; + y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1; + } else { + e = 16 + lg_table[(x >> 16) & 0xff]; + y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7); + y = (y + 1 + x / y) >> 1; + } + return (x < (y * y)) ? y - 1 : y; +} + +#endif /* SS_BLOCKSIZE != 0 */ + + +/*---------------------------------------------------------------------------*/ + +/* Compares two suffixes. */ +static INLINE +saint_t +ss_compare(const sauchar_t *T, + const saidx_t *p1, const saidx_t *p2, + saidx_t depth) { + const sauchar_t *U1, *U2, *U1n, *U2n; + + for(U1 = T + depth + *p1, + U2 = T + depth + *p2, + U1n = T + *(p1 + 1) + 2, + U2n = T + *(p2 + 1) + 2; + (U1 < U1n) && (U2 < U2n) && (*U1 == *U2); + ++U1, ++U2) { + } + + return U1 < U1n ? + (U2 < U2n ? *U1 - *U2 : 1) : + (U2 < U2n ? -1 : 0); +} + +static INLINE +saint_t +ss_compare_last(const sauchar_t *T, const saidx_t *PA, + const saidx_t *p1, const saidx_t *p2, + saidx_t depth, saidx_t size) { + const sauchar_t *U1, *U2, *U1n, *U2n; + + for(U1 = T + depth + *p1, + U2 = T + depth + *p2, + U1n = T + size, + U2n = T + *(p2 + 1) + 2; + (U1 < U1n) && (U2 < U2n) && (*U1 == *U2); + ++U1, ++U2) { + } + + if(U1 < U1n) { return (U2 < U2n) ? *U1 - *U2 : 1; } + else if(U2 == U2n) { return 1; } + + for(U1 = T + (U1 - T) % size, U1n = T + PA[0] + 2; + (U1 < U1n) && (U2 < U2n) && (*U1 == *U2); + ++U1, ++U2) { + } + + return U1 < U1n ? + (U2 < U2n ? *U1 - *U2 : 1) : + (U2 < U2n ? -1 : 0); + +} + + +/*---------------------------------------------------------------------------*/ + +#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) + +/* Insertionsort for small size groups */ +static +void +ss_insertionsort(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *last, saidx_t depth) { + saidx_t *i, *j; + saidx_t t; + saint_t r; + + for(i = last - 2; first <= i; --i) { + for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) { + do { *(j - 1) = *j; } while((++j < last) && (*j < 0)); + if(last <= j) { break; } + } + if(r == 0) { *j = ~*j; } + *(j - 1) = t; + } +} + +#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */ + + +/*---------------------------------------------------------------------------*/ + +#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) + +static INLINE +void +ss_fixdown(const sauchar_t *Td, const saidx_t *PA, + saidx_t *SA, saidx_t i, saidx_t size) { + saidx_t j, k; + saidx_t v; + saint_t c, d, e; + + for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { + d = Td[PA[SA[k = j++]]]; + if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; } + if(d <= c) { break; } + } + SA[i] = v; +} + +/* Simple top-down heapsort. */ +static +void +ss_heapsort(const sauchar_t *Td, const saidx_t *PA, saidx_t *SA, saidx_t size) { + saidx_t i, m; + saidx_t t; + + m = size; + if((size % 2) == 0) { + m--; + if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); } + } + + for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); } + if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); } + for(i = m - 1; 0 < i; --i) { + t = SA[0], SA[0] = SA[i]; + ss_fixdown(Td, PA, SA, 0, i); + SA[i] = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Returns the median of three elements. */ +static INLINE +saidx_t * +ss_median3(const sauchar_t *Td, const saidx_t *PA, + saidx_t *v1, saidx_t *v2, saidx_t *v3) { + saidx_t *t; + if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); } + if(Td[PA[*v2]] > Td[PA[*v3]]) { + if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; } + else { return v3; } + } + return v2; +} + +/* Returns the median of five elements. */ +static INLINE +saidx_t * +ss_median5(const sauchar_t *Td, const saidx_t *PA, + saidx_t *v1, saidx_t *v2, saidx_t *v3, saidx_t *v4, saidx_t *v5) { + saidx_t *t; + if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); } + if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); } + if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); } + if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); } + if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); } + if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; } + return v3; +} + +/* Returns the pivot element. */ +static INLINE +saidx_t * +ss_pivot(const sauchar_t *Td, const saidx_t *PA, saidx_t *first, saidx_t *last) { + saidx_t *middle; + saidx_t t; + + t = last - first; + middle = first + t / 2; + + if(t <= 512) { + if(t <= 32) { + return ss_median3(Td, PA, first, middle, last - 1); + } else { + t >>= 2; + return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1); + } + } + t >>= 3; + first = ss_median3(Td, PA, first, first + t, first + (t << 1)); + middle = ss_median3(Td, PA, middle - t, middle, middle + t); + last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1); + return ss_median3(Td, PA, first, middle, last); +} + + +/*---------------------------------------------------------------------------*/ + +/* Binary partition for substrings. */ +static INLINE +saidx_t * +ss_partition(const saidx_t *PA, + saidx_t *first, saidx_t *last, saidx_t depth) { + saidx_t *a, *b; + saidx_t t; + for(a = first - 1, b = last;;) { + for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; } + for(; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) { } + if(b <= a) { break; } + t = ~*b; + *b = *a; + *a = t; + } + if(first < a) { *first = ~*first; } + return a; +} + +/* Multikey introsort for medium size groups. */ +static +void +ss_mintrosort(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *last, + saidx_t depth) { +#define STACK_SIZE SS_MISORT_STACKSIZE + struct { saidx_t *a, *b, c; saint_t d; } stack[STACK_SIZE]; + const sauchar_t *Td; + saidx_t *a, *b, *c, *d, *e, *f; + saidx_t s, t; + saint_t ssize; + saint_t limit; + saint_t v, x = 0; + + for(ssize = 0, limit = ss_ilg(last - first);;) { + + if((last - first) <= SS_INSERTIONSORT_THRESHOLD) { +#if 1 < SS_INSERTIONSORT_THRESHOLD + if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); } +#endif + STACK_POP(first, last, depth, limit); + continue; + } + + Td = T + depth; + if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); } + if(limit < 0) { + for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) { + if((x = Td[PA[*a]]) != v) { + if(1 < (a - first)) { break; } + v = x; + first = a; + } + } + if(Td[PA[*first] - 1] < v) { + first = ss_partition(PA, first, a, depth); + } + if((a - first) <= (last - a)) { + if(1 < (a - first)) { + STACK_PUSH(a, last, depth, -1); + last = a, depth += 1, limit = ss_ilg(a - first); + } else { + first = a, limit = -1; + } + } else { + if(1 < (last - a)) { + STACK_PUSH(first, a, depth + 1, ss_ilg(a - first)); + first = a, limit = -1; + } else { + last = a, depth += 1, limit = ss_ilg(a - first); + } + } + continue; + } + + /* choose pivot */ + a = ss_pivot(Td, PA, first, last); + v = Td[PA[*a]]; + SWAP(*first, *a); + + /* partition */ + for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { } + if(((a = b) < last) && (x < v)) { + for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + } + for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { } + if((b < (d = c)) && (x > v)) { + for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + for(; b < c;) { + SWAP(*b, *c); + for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + + if(a <= d) { + c = b - 1; + + if((s = a - first) > (t = b - a)) { s = t; } + for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + if((s = d - c) > (t = last - d - 1)) { s = t; } + for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + + a = first + (b - a), c = last - (d - c); + b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth); + + if((a - first) <= (last - c)) { + if((last - c) <= (c - b)) { + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + STACK_PUSH(c, last, depth, limit); + last = a; + } else if((a - first) <= (c - b)) { + STACK_PUSH(c, last, depth, limit); + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + last = a; + } else { + STACK_PUSH(c, last, depth, limit); + STACK_PUSH(first, a, depth, limit); + first = b, last = c, depth += 1, limit = ss_ilg(c - b); + } + } else { + if((a - first) <= (c - b)) { + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + STACK_PUSH(first, a, depth, limit); + first = c; + } else if((last - c) <= (c - b)) { + STACK_PUSH(first, a, depth, limit); + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + first = c; + } else { + STACK_PUSH(first, a, depth, limit); + STACK_PUSH(c, last, depth, limit); + first = b, last = c, depth += 1, limit = ss_ilg(c - b); + } + } + } else { + limit += 1; + if(Td[PA[*first] - 1] < v) { + first = ss_partition(PA, first, last, depth); + limit = ss_ilg(last - first); + } + depth += 1; + } + } +#undef STACK_SIZE +} + +#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ + + +/*---------------------------------------------------------------------------*/ + +#if SS_BLOCKSIZE != 0 + +static INLINE +void +ss_blockswap(saidx_t *a, saidx_t *b, saidx_t n) { + saidx_t t; + for(; 0 < n; --n, ++a, ++b) { + t = *a, *a = *b, *b = t; + } +} + +static INLINE +void +ss_rotate(saidx_t *first, saidx_t *middle, saidx_t *last) { + saidx_t *a, *b, t; + saidx_t l, r; + l = middle - first, r = last - middle; + for(; (0 < l) && (0 < r);) { + if(l == r) { ss_blockswap(first, middle, l); break; } + if(l < r) { + a = last - 1, b = middle - 1; + t = *a; + do { + *a-- = *b, *b-- = *a; + if(b < first) { + *a = t; + last = a; + if((r -= l + 1) <= l) { break; } + a -= 1, b = middle - 1; + t = *a; + } + } while(1); + } else { + a = first, b = middle; + t = *a; + do { + *a++ = *b, *b++ = *a; + if(last <= b) { + *a = t; + first = a + 1; + if((l -= r + 1) <= r) { break; } + a += 1, b = middle; + t = *a; + } + } while(1); + } + } +} + + +/*---------------------------------------------------------------------------*/ + +static +void +ss_inplacemerge(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *middle, saidx_t *last, + saidx_t depth) { + const saidx_t *p; + saidx_t *a, *b; + saidx_t len, half; + saint_t q, r; + saint_t x; + + for(;;) { + if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); } + else { x = 0; p = PA + *(last - 1); } + for(a = first, len = middle - first, half = len >> 1, r = -1; + 0 < len; + len = half, half >>= 1) { + b = a + half; + q = ss_compare(T, PA + getidx(b), p, depth); + if(q < 0) { + a = b + 1; + half -= (len & 1) ^ 1; + } else { + r = q; + } + } + if(a < middle) { + if(r == 0) { *a = ~*a; } + ss_rotate(a, middle, last); + last -= middle - a; + middle = a; + if(first == middle) { break; } + } + --last; + if(x != 0) { while(*--last < 0) { } } + if(middle == last) { break; } + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Merge-forward with internal buffer. */ +static +void +ss_mergeforward(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *middle, saidx_t *last, + saidx_t *buf, saidx_t depth) { + saidx_t *a, *b, *c, *bufend; + saidx_t t; + saint_t r; + + bufend = buf + (middle - first) - 1; + ss_blockswap(buf, first, middle - first); + + for(t = *(a = first), b = buf, c = middle;;) { + r = ss_compare(T, PA + *b, PA + *c, depth); + if(r < 0) { + do { + *a++ = *b; + if(bufend <= b) { *bufend = t; return; } + *b++ = *a; + } while(*b < 0); + } else if(r > 0) { + do { + *a++ = *c, *c++ = *a; + if(last <= c) { + while(b < bufend) { *a++ = *b, *b++ = *a; } + *a = *b, *b = t; + return; + } + } while(*c < 0); + } else { + *c = ~*c; + do { + *a++ = *b; + if(bufend <= b) { *bufend = t; return; } + *b++ = *a; + } while(*b < 0); + + do { + *a++ = *c, *c++ = *a; + if(last <= c) { + while(b < bufend) { *a++ = *b, *b++ = *a; } + *a = *b, *b = t; + return; + } + } while(*c < 0); + } + } +} + +/* Merge-backward with internal buffer. */ +static +void +ss_mergebackward(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *middle, saidx_t *last, + saidx_t *buf, saidx_t depth) { + const saidx_t *p1, *p2; + saidx_t *a, *b, *c, *bufend; + saidx_t t; + saint_t r; + saint_t x; + + bufend = buf + (last - middle) - 1; + ss_blockswap(buf, middle, last - middle); + + x = 0; + if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; } + else { p1 = PA + *bufend; } + if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; } + else { p2 = PA + *(middle - 1); } + for(t = *(a = last - 1), b = bufend, c = middle - 1;;) { + r = ss_compare(T, p1, p2, depth); + if(0 < r) { + if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } + *a-- = *b; + if(b <= buf) { *buf = t; break; } + *b-- = *a; + if(*b < 0) { p1 = PA + ~*b; x |= 1; } + else { p1 = PA + *b; } + } else if(r < 0) { + if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } + *a-- = *c, *c-- = *a; + if(c < first) { + while(buf < b) { *a-- = *b, *b-- = *a; } + *a = *b, *b = t; + break; + } + if(*c < 0) { p2 = PA + ~*c; x |= 2; } + else { p2 = PA + *c; } + } else { + if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } + *a-- = ~*b; + if(b <= buf) { *buf = t; break; } + *b-- = *a; + if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } + *a-- = *c, *c-- = *a; + if(c < first) { + while(buf < b) { *a-- = *b, *b-- = *a; } + *a = *b, *b = t; + break; + } + if(*b < 0) { p1 = PA + ~*b; x |= 1; } + else { p1 = PA + *b; } + if(*c < 0) { p2 = PA + ~*c; x |= 2; } + else { p2 = PA + *c; } + } + } +} + +static +void +merge_check(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *last, + saint_t check, saidx_t depth) { + if((check & 1) || + ((check & 2) && (ss_compare(T, PA + getidx(first - 1), PA + *first, depth) == 0))) { + *first = ~*first; + } + if((check & 4) && ((ss_compare(T, PA + getidx(last - 1), PA + *last, depth) == 0))) { + *last = ~*last; + } +} + +/* D&C based merge. */ +static +void +ss_swapmerge(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *middle, saidx_t *last, + saidx_t *buf, saidx_t bufsize, saidx_t depth) { +#define STACK_SIZE SS_SMERGE_STACKSIZE + struct { saidx_t *a, *b, *c; saint_t d; } stack[STACK_SIZE]; + saidx_t *l, *r, *lm, *rm; + saidx_t m, len, half; + saint_t ssize; + saint_t check, next; + + for(check = 0, ssize = 0;;) { + if((last - middle) <= bufsize) { + if((first < middle) && (middle < last)) { + ss_mergebackward(T, PA, first, middle, last, buf, depth); + } + merge_check(T, PA, first, last, check, depth); + STACK_POP(first, middle, last, check); + continue; + } + + if((middle - first) <= bufsize) { + if(first < middle) { + ss_mergeforward(T, PA, first, middle, last, buf, depth); + } + merge_check(T, PA, first, last, check, depth); + STACK_POP(first, middle, last, check); + continue; + } + + for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1; + 0 < len; + len = half, half >>= 1) { + if(ss_compare(T, PA + getidx(middle + m + half), + PA + getidx(middle - m - half - 1), depth) < 0) { + m += half + 1; + half -= (len & 1) ^ 1; + } + } + + if(0 < m) { + lm = middle - m, rm = middle + m; + ss_blockswap(lm, middle, m); + l = r = middle, next = 0; + if(rm < last) { + if(*rm < 0) { + *rm = ~*rm; + if(first < lm) { for(; *--l < 0;) { } next |= 4; } + next |= 1; + } else if(first < lm) { + for(; *r < 0; ++r) { } + next |= 2; + } + } + + if((l - first) <= (last - r)) { + STACK_PUSH(r, rm, last, (next & 3) | (check & 4)); + middle = lm, last = l, check = (check & 3) | (next & 4); + } else { + if((next & 2) && (r == middle)) { next ^= 6; } + STACK_PUSH(first, lm, l, (check & 3) | (next & 4)); + first = r, middle = rm, check = (next & 3) | (check & 4); + } + } else { + if(ss_compare(T, PA + getidx(middle - 1), PA + *middle, depth) == 0) { + *middle = ~*middle; + } + merge_check(T, PA, first, last, check, depth); + STACK_POP(first, middle, last, check); + } + } +#undef STACK_SIZE +} + +#endif /* SS_BLOCKSIZE != 0 */ + + +/*---------------------------------------------------------------------------*/ + +/*- Function -*/ + +/* Substring sort */ +static +void +sssort(const sauchar_t *T, const saidx_t *PA, + saidx_t *first, saidx_t *last, + saidx_t *buf, saidx_t bufsize, + saidx_t depth, saidx_t n, saint_t lastsuffix) { + saidx_t *a; +#if SS_BLOCKSIZE != 0 + saidx_t *b, *middle, *curbuf; + saidx_t j, k, curbufsize, limit; +#endif + saidx_t i; + + if(lastsuffix != 0) { ++first; } + +#if SS_BLOCKSIZE == 0 + ss_mintrosort(T, PA, first, last, depth); +#else + if((bufsize < SS_BLOCKSIZE) && + (bufsize < (last - first)) && + (bufsize < (limit = ss_isqrt(last - first)))) { + if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; } + buf = middle = last - limit, bufsize = limit; + } else { + middle = last, limit = 0; + } + for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) { +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth); +#endif + curbufsize = last - (a + SS_BLOCKSIZE); + curbuf = a + SS_BLOCKSIZE; + if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; } + for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) { + ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth); + } + } +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, a, middle, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, a, middle, depth); +#endif + for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) { + if(i & 1) { + ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth); + a -= k; + } + } + if(limit != 0) { +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, middle, last, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, middle, last, depth); +#endif + ss_inplacemerge(T, PA, first, middle, last, depth); + } +#endif + + if(lastsuffix != 0) { + /* Insert last type B* suffix. */ + saint_t r; + for(a = first, i = *(first - 1), r = 1; + (a < last) && ((*a < 0) || (0 < (r = ss_compare_last(T, PA, PA + i, PA + *a, depth, n)))); + ++a) { + *(a - 1) = *a; + } + if(r == 0) { *a = ~*a; } + *(a - 1) = i; + } +} + + +/*---- trsort ----*/ + +/*- Private Functions -*/ + +static INLINE +saint_t +tr_ilg(saidx_t n) { + return (n & 0x00ffff00) ? + ((n & 0x00ff0000) ? + 16 + lg_table[(n >> 16) & 0xff] : + 8 + lg_table[(n >> 8) & 0xff]) : + 0 + lg_table[(n >> 0) & 0xff]; +} + + +/*---------------------------------------------------------------------------*/ + +/* Simple insertionsort for small size groups. */ +static +void +tr_insertionsort(const saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *first, saidx_t *last) { + saidx_t *a, *b; + saidx_t t, r; + + for(a = first + 1; a < last; ++a) { + for(t = *a, b = a - 1; 0 > (r = TR_GETC(t) - TR_GETC(*b));) { + do { *(b + 1) = *b; } while((first <= --b) && (*b < 0)); + if(b < first) { break; } + } + if(r == 0) { *b = ~*b; } + *(b + 1) = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +void +tr_fixdown(const saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *SA, saidx_t i, saidx_t size) { + saidx_t j, k; + saidx_t v; + saidx_t c, d, e; + + for(v = SA[i], c = TR_GETC(v); (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { + k = j++; + d = TR_GETC(SA[k]); + if(d < (e = TR_GETC(SA[j]))) { k = j; d = e; } + if(d <= c) { break; } + } + SA[i] = v; +} + +/* Simple top-down heapsort. */ +static +void +tr_heapsort(const saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *SA, saidx_t size) { + saidx_t i, m; + saidx_t t; + + m = size; + if((size % 2) == 0) { + m--; + if(TR_GETC(SA[m / 2]) < TR_GETC(SA[m])) { SWAP(SA[m], SA[m / 2]); } + } + + for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISA, ISAd, ISAn, SA, i, m); } + if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISA, ISAd, ISAn, SA, 0, m); } + for(i = m - 1; 0 < i; --i) { + t = SA[0], SA[0] = SA[i]; + tr_fixdown(ISA, ISAd, ISAn, SA, 0, i); + SA[i] = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Returns the median of three elements. */ +static INLINE +saidx_t * +tr_median3(const saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *v1, saidx_t *v2, saidx_t *v3) { + saidx_t *t; + if(TR_GETC(*v1) > TR_GETC(*v2)) { SWAP(v1, v2); } + if(TR_GETC(*v2) > TR_GETC(*v3)) { + if(TR_GETC(*v1) > TR_GETC(*v3)) { return v1; } + else { return v3; } + } + return v2; +} + +/* Returns the median of five elements. */ +static INLINE +saidx_t * +tr_median5(const saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *v1, saidx_t *v2, saidx_t *v3, saidx_t *v4, saidx_t *v5) { + saidx_t *t; + if(TR_GETC(*v2) > TR_GETC(*v3)) { SWAP(v2, v3); } + if(TR_GETC(*v4) > TR_GETC(*v5)) { SWAP(v4, v5); } + if(TR_GETC(*v2) > TR_GETC(*v4)) { SWAP(v2, v4); SWAP(v3, v5); } + if(TR_GETC(*v1) > TR_GETC(*v3)) { SWAP(v1, v3); } + if(TR_GETC(*v1) > TR_GETC(*v4)) { SWAP(v1, v4); SWAP(v3, v5); } + if(TR_GETC(*v3) > TR_GETC(*v4)) { return v4; } + return v3; +} + +/* Returns the pivot element. */ +static INLINE +saidx_t * +tr_pivot(const saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *first, saidx_t *last) { + saidx_t *middle; + saidx_t t; + + t = last - first; + middle = first + t / 2; + + if(t <= 512) { + if(t <= 32) { + return tr_median3(ISA, ISAd, ISAn, first, middle, last - 1); + } else { + t >>= 2; + return tr_median5(ISA, ISAd, ISAn, first, first + t, middle, last - 1 - t, last - 1); + } + } + t >>= 3; + first = tr_median3(ISA, ISAd, ISAn, first, first + t, first + (t << 1)); + middle = tr_median3(ISA, ISAd, ISAn, middle - t, middle, middle + t); + last = tr_median3(ISA, ISAd, ISAn, last - 1 - (t << 1), last - 1 - t, last - 1); + return tr_median3(ISA, ISAd, ISAn, first, middle, last); +} + + +/*---------------------------------------------------------------------------*/ + +typedef struct _trbudget_t trbudget_t; +struct _trbudget_t { + saidx_t chance; + saidx_t remain; + saidx_t incval; + saidx_t count; +}; + +static INLINE +void +trbudget_init(trbudget_t *budget, saidx_t chance, saidx_t incval) { + budget->chance = chance; + budget->remain = budget->incval = incval; +} + +static INLINE +saint_t +trbudget_check(trbudget_t *budget, saidx_t size) { + if(size <= budget->remain) { budget->remain -= size; return 1; } + if(budget->chance == 0) { budget->count += size; return 0; } + budget->remain += budget->incval - size; + budget->chance -= 1; + return 1; +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +void +tr_partition(const saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *first, saidx_t *middle, saidx_t *last, + saidx_t **pa, saidx_t **pb, saidx_t v) { + saidx_t *a, *b, *c, *d, *e, *f; + saidx_t t, s; + saidx_t x = 0; + + for(b = middle - 1; (++b < last) && ((x = TR_GETC(*b)) == v);) { } + if(((a = b) < last) && (x < v)) { + for(; (++b < last) && ((x = TR_GETC(*b)) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + } + for(c = last; (b < --c) && ((x = TR_GETC(*c)) == v);) { } + if((b < (d = c)) && (x > v)) { + for(; (b < --c) && ((x = TR_GETC(*c)) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + for(; b < c;) { + SWAP(*b, *c); + for(; (++b < c) && ((x = TR_GETC(*b)) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + for(; (b < --c) && ((x = TR_GETC(*c)) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + + if(a <= d) { + c = b - 1; + if((s = a - first) > (t = b - a)) { s = t; } + for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + if((s = d - c) > (t = last - d - 1)) { s = t; } + for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + first += (b - a), last -= (d - c); + } + *pa = first, *pb = last; +} + +static +void +tr_copy(saidx_t *ISA, const saidx_t *ISAn, const saidx_t *SA, + saidx_t *first, saidx_t *a, saidx_t *b, saidx_t *last, + saidx_t depth) { + /* sort suffixes of middle partition + by using sorted order of suffixes of left and right partition. */ + saidx_t *c, *d, *e; + saidx_t s, v; + + v = b - SA - 1; + for(c = first, d = a - 1; c <= d; ++c) { + if((s = *c - depth) < 0) { s += ISAn - ISA; } + if(ISA[s] == v) { + *++d = s; + ISA[s] = d - SA; + } + } + for(c = last - 1, e = d + 1, d = b; e < d; --c) { + if((s = *c - depth) < 0) { s += ISAn - ISA; } + if(ISA[s] == v) { + *--d = s; + ISA[s] = d - SA; + } + } +} + +static +void +tr_partialcopy(saidx_t *ISA, const saidx_t *ISAn, const saidx_t *SA, + saidx_t *first, saidx_t *a, saidx_t *b, saidx_t *last, + saidx_t depth) { + saidx_t *c, *d, *e; + saidx_t s, v, t; + saidx_t rank, lastrank, newrank = -1; + + v = b - SA - 1; + lastrank = -1; + for(c = first, d = a - 1; c <= d; ++c) { + t = *c; + if((s = t - depth) < 0) { s += ISAn - ISA; } + if(ISA[s] == v) { + *++d = s; + rank = ISA[t]; + if(lastrank != rank) { lastrank = rank; newrank = d - SA; } + ISA[s] = newrank; + } + } + + lastrank = -1; + for(e = d; first <= e; --e) { + rank = ISA[*e]; + if(lastrank != rank) { lastrank = rank; newrank = e - SA; } + if(newrank != rank) { ISA[*e] = newrank; } + } + + lastrank = -1; + for(c = last - 1, e = d + 1, d = b; e < d; --c) { + t = *c; + if((s = t - depth) < 0) { s += ISAn - ISA; } + if(ISA[s] == v) { + *--d = s; + rank = ISA[t]; + if(lastrank != rank) { lastrank = rank; newrank = d - SA; } + ISA[s] = newrank; + } + } +} + +static +void +tr_introsort(saidx_t *ISA, const saidx_t *ISAd, const saidx_t *ISAn, + saidx_t *SA, saidx_t *first, saidx_t *last, + trbudget_t *budget) { +#define STACK_SIZE TR_STACKSIZE + struct { const saidx_t *a; saidx_t *b, *c; saint_t d, e; }stack[STACK_SIZE]; + saidx_t *a, *b, *c; + saidx_t t; + saidx_t v, x = 0; + saidx_t incr = ISAd - ISA; + saint_t limit, next; + saint_t ssize, trlink = -1; + + for(ssize = 0, limit = tr_ilg(last - first);;) { + assert((ISAd < ISAn) || (limit == -3)); + + if(limit < 0) { + if(limit == -1) { + /* tandem repeat partition */ + tr_partition(ISA, ISAd - incr, ISAn, first, first, last, &a, &b, last - SA - 1); + + /* update ranks */ + if(a < last) { + for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } + } + if(b < last) { + for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } + } + + /* push */ + if(1 < (b - a)) { + STACK_PUSH5(NULL, a, b, 0, 0); + STACK_PUSH5(ISAd - incr, first, last, -2, trlink); + trlink = ssize - 2; + } + if((a - first) <= (last - b)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink); + last = a, limit = tr_ilg(a - first); + } else if(1 < (last - b)) { + first = b, limit = tr_ilg(last - b); + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } else { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink); + first = b, limit = tr_ilg(last - b); + } else if(1 < (a - first)) { + last = a, limit = tr_ilg(a - first); + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } else if(limit == -2) { + /* tandem repeat copy */ + a = stack[--ssize].b, b = stack[ssize].c; + if(stack[ssize].d == 0) { + tr_copy(ISA, ISAn, SA, first, a, b, last, ISAd - ISA); + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + tr_partialcopy(ISA, ISAn, SA, first, a, b, last, ISAd - ISA); + } + STACK_POP5(ISAd, first, last, limit, trlink); + } else { + /* sorted partition */ + if(0 <= *first) { + a = first; + do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a)); + first = a; + } + if(first < last) { + a = first; do { *a = ~*a; } while(*++a < 0); + next = (incr < (ISAn - ISAd)) ? ((ISA[*a] != TR_GETC(*a)) ? tr_ilg(a - first + 1) : -1) : -3; + if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } } + + /* push */ + if(trbudget_check(budget, a - first)) { + if((a - first) <= (last - a)) { + STACK_PUSH5(ISAd, a, last, -3, trlink); + ISAd += incr, last = a, limit = next; + } else { + if(1 < (last - a)) { + STACK_PUSH5(ISAd + incr, first, a, next, trlink); + first = a, limit = -3; + } else { + ISAd += incr, last = a, limit = next; + } + } + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + if(1 < (last - a)) { + first = a, limit = -3; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + continue; + } + + if((last - first) <= TR_INSERTIONSORT_THRESHOLD) { + tr_insertionsort(ISA, ISAd, ISAn, first, last); + limit = -3; + continue; + } + + if(limit-- == 0) { + tr_heapsort(ISA, ISAd, ISAn, first, last - first); + for(a = last - 1; first < a; a = b) { + for(x = TR_GETC(*a), b = a - 1; (first <= b) && (TR_GETC(*b) == x); --b) { *b = ~*b; } + } + limit = -3; + continue; + } + + /* choose pivot */ + a = tr_pivot(ISA, ISAd, ISAn, first, last); + SWAP(*first, *a); + v = TR_GETC(*first); + + /* partition */ + tr_partition(ISA, ISAd, ISAn, first, first + 1, last, &a, &b, v); + if((last - first) != (b - a)) { + next = (incr < (ISAn - ISAd)) ? ((ISA[*a] != v) ? tr_ilg(b - a) : -1) : -3; + + /* update ranks */ + for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } + if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } } + + /* push */ + if((1 < (b - a)) && (trbudget_check(budget, b - a))) { + if((a - first) <= (last - b)) { + if((last - b) <= (b - a)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + STACK_PUSH5(ISAd, b, last, limit, trlink); + last = a; + } else if(1 < (last - b)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + first = b; + } else { + ISAd += incr, first = a, last = b, limit = next; + } + } else if((a - first) <= (b - a)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, limit, trlink); + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + last = a; + } else { + STACK_PUSH5(ISAd, b, last, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + STACK_PUSH5(ISAd, b, last, limit, trlink); + STACK_PUSH5(ISAd, first, a, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + if((a - first) <= (b - a)) { + if(1 < (last - b)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + STACK_PUSH5(ISAd, first, a, limit, trlink); + first = b; + } else if(1 < (a - first)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + last = a; + } else { + ISAd += incr, first = a, last = b, limit = next; + } + } else if((last - b) <= (b - a)) { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, limit, trlink); + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + first = b; + } else { + STACK_PUSH5(ISAd, first, a, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + STACK_PUSH5(ISAd, first, a, limit, trlink); + STACK_PUSH5(ISAd, b, last, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } + } else { + if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; } + if((a - first) <= (last - b)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, limit, trlink); + last = a; + } else if(1 < (last - b)) { + first = b; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } else { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, limit, trlink); + first = b; + } else if(1 < (a - first)) { + last = a; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } + } else { + if(trbudget_check(budget, last - first)) { + limit = (incr < (ISAn - ISAd)) ? ((ISA[*first] != TR_GETC(*first)) ? (limit + 1) : -1) : -3; + ISAd += incr; + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } +#undef STACK_SIZE +} + + +/*---------------------------------------------------------------------------*/ + +/*- Function -*/ + +/* Tandem repeat sort */ +static +void +trsort(saidx_t *ISA, saidx_t *SA, saidx_t n, saidx_t depth) { + saidx_t *ISAd; + saidx_t *first, *last, *a; + trbudget_t budget; + saidx_t t, skip, unsorted; + + if (-n >= *SA) { return; } + trbudget_init(&budget, tr_ilg(n) * 2 / 3, n); + for(ISAd = ISA + depth;; ISAd += ISAd - ISA) { + assert(n > ISAd - ISA); + first = SA; + skip = 0; + unsorted = 0; + do { + if((t = *first) < 0) { first -= t; skip += t; } + else { + if(skip != 0) { *(first + skip) = skip; skip = 0; } + last = SA + ISA[t] + 1; + if(1 < (last - first)) { + budget.count = 0; + tr_introsort(ISA, ISAd, ISA + n, SA, first, last, &budget); + if(budget.count != 0) { unsorted += budget.count; } + else { skip = first - last; } + } else if((last - first) == 1) { + skip = -1; + } + first = last; + } + } while(first < (SA + n)); + if(skip != 0) { *(first + skip) = skip; } + if(unsorted == 0 || -n >= *SA) { break; } + if(n <= (ISAd - ISA) * 2) { + do { + if((t = *first) < 0) { first -= t; } + else { + last = SA + ISA[t] + 1; + for(a = first; a < last; ++a) { ISA[*a] = a - SA; } + first = last; + } + } while(first < (SA + n)); + break; + } + } +} + + +/*---- divsufsort ----*/ + +/*- Private Functions -*/ + +/* Sorts suffixes of type B*. */ +static +saidx_t +sort_typeBstar(const sauchar_t *T, saidx_t *SA, + saidx_t *bucket, saidx_t n) { + saidx_t *PAb, *ISAb, *buf; + saidx_t i, j, k, t, m, bufsize; + saint_t c0, c1; + int flag; + + /* Initialize bucket arrays. */ + memset(bucket, 0, (ALPHABET_SIZE + 1) * ALPHABET_SIZE * sizeof(saidx_t)); + + /* Count the number of occurrences of the first one or two characters of each + type A, B and B* suffix. Moreover, store the beginning position of all + type B* suffixes into the array SA. */ + for(i = 1, flag = 1; i < n; ++i) { + if(T[i - 1] != T[i]) { + if(T[i - 1] > T[i]) { flag = 0; } + break; + } + } + i = n - 1, m = n, c0 = T[n - 1], c1 = T[0]; + if((c0 < c1) || ((c0 == c1) && (flag != 0))) { + if(flag == 0) { ++BUCKET_BSTAR(c0, c1); SA[--m] = i; } + else { ++BUCKET_B(c0, c1); } + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { ++BUCKET_B(c0, c1); } + } + for(; 0 <= i;) { + /* type A suffix. */ + do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1)); + if(0 <= i) { + /* type B* suffix. */ + ++BUCKET_BSTAR(c0, c1); + SA[--m] = i; + /* type B suffix. */ + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { + ++BUCKET_B(c0, c1); + } + } + } + m = n - m; + assert(m <= n/2); + if(m == 0) { return 0; } +/* +note: + A type B* suffix is lexicographically smaller than a type B suffix that + begins with the same first two characters. +*/ + + /* Calculate the index of start/end point of each bucket. */ + for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) { + t = i + BUCKET_A(c0); + BUCKET_A(c0) = i + j; /* start point */ + i = t + BUCKET_B(c0, c0); + for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) { + j += BUCKET_BSTAR(c0, c1); + BUCKET_BSTAR(c0, c1) = j; /* end point */ + i += BUCKET_B(c0, c1); + } + } + + /* Sort the type B* suffixes by their first two characters. */ + PAb = SA + n - m; ISAb = SA + m; + for(i = m - 2; 0 <= i; --i) { + t = PAb[i], c0 = T[t], c1 = T[t + 1]; + SA[--BUCKET_BSTAR(c0, c1)] = i; + } + t = PAb[m - 1], c0 = T[t], c1 = T[t + 1]; + SA[--BUCKET_BSTAR(c0, c1)] = m - 1; + + /* Sort the type B* substrings using sssort. */ + buf = SA + m, bufsize = n - (2 * m); + for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) { + for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) { + i = BUCKET_BSTAR(c0, c1); + if(1 < (j - i)) { + sssort(T, PAb, SA + i, SA + j, + buf, bufsize, 2, n, *(SA + i) == (m - 1)); + } + } + } + + /* Compute ranks of type B* substrings. */ + for(i = m - 1; 0 <= i; --i) { + if(0 <= SA[i]) { + j = i; + do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i])); + SA[i + 1] = i - j; + if(i <= 0) { break; } + } + j = i; + do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0); + ISAb[SA[i]] = j; + } + + /* Construct the inverse suffix array of type B* suffixes using trsort. */ + trsort(ISAb, SA, m, 1); + + /* Set the sorted order of type B* suffixes. */ + i = n - 1, j = m, c0 = T[n - 1], c1 = T[0]; + if((c0 < c1) || ((c0 == c1) && (flag != 0))) { + t = i; + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { } + if(flag == 0) { SA[ISAb[--j]] = ((1 < (t - i))) ? t : ~t; } + } + for(; 0 <= i;) { + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { } + if(0 <= i) { + t = i; + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { } + SA[ISAb[--j]] = ((1 < (t - i))) ? t : ~t; + } + } + if(SA[ISAb[0]] == ~((saidx_t)0)) { + /* check last type */ + if(T[n - 1] <= T[0]) { /* is type B? */ + SA[ISAb[0]] = 0; + } + } + +#ifdef DEBUG + for(i = m; i < n; ++i) { + SA[i] = ~n; + } +#endif + + /* Calculate the index of start/end point of each bucket. */ + BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */ + for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) { + i = BUCKET_A(c0 + 1) - 1; + for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) { + t = i - BUCKET_B(c0, c1); + BUCKET_B(c0, c1) = i; /* end point */ + + /* Move all type B* suffixes to the correct position. */ + for(i = t, j = BUCKET_BSTAR(c0, c1); + j <= k; + --i, --k) { SA[i] = SA[k]; } + } + BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */ + BUCKET_B(c0, c0) = i; /* end point */ + } + + return m; +} + +static +saidx_t +construct_BWT(const sauchar_t *T, saidx_t *SA, + saidx_t *bucket, saidx_t n) { + saidx_t *i, *j, *k; + saidx_t s, t, orig = -10; + saint_t c0, c1, c2; + + /* Construct the sorted order of type B suffixes by using + the sorted order of type B* suffixes. */ + for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { + /* Scan the suffix array from right to left. */ + for(i = SA + BUCKET_BSTAR(c1, c1 + 1), + j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; + i <= j; + --j) { + if(0 <= (s = *j)) { + assert(s < n); + assert(T[s] == c1); + assert(T[s] <= T[((s + 1) < n) ? (s + 1) : (0)]); + if(s != 0) { t = s - 1; } + else { t = n - 1; orig = j - SA; } + assert(T[t] <= T[s]); + c0 = T[t]; + *j = ~((saidx_t)c0); + if(c0 != c2) { + if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } + k = SA + BUCKET_B(c2 = c0, c1); + } + assert(k < j); + *k-- = (((t != 0) ? T[t - 1] : T[n - 1]) > c2) ? ~t : t; + } else { + *j = ~s; + assert(~s < n); + } + } + } + + /* Construct the BWTed string by using + the sorted order of type B suffixes. */ + k = SA + BUCKET_A(c2 = 0); + /* Scan the suffix array from left to right. */ + for(i = SA, j = SA + n; i < j; ++i) { + if(0 <= (s = *i)) { + if(s != 0) { t = s - 1; } + else { t = n - 1; orig = i - SA; } + assert(T[t] >= T[s]); + c0 = T[t]; + *i = c0; + if(c0 != c2) { + BUCKET_A(c2) = k - SA; + k = SA + BUCKET_A(c2 = c0); + } + if(t != 0) { c1 = T[t - 1]; } + else { c1 = T[n - 1]; orig = k - SA; } + assert(i <= k); + *k++ = (c1 < c2) ? ~((saidx_t)c1) : t; + } else { + *i = ~s; + } + } + + assert(orig != -10); + assert((0 <= orig) && (orig < n)); + return orig; +} + + +/*---------------------------------------------------------------------------*/ + +/*- Function -*/ + +saidx_t +divbwt(sauchar_t *T, saidx_t *SA, saidx_t *bucket, saidx_t n) { + saidx_t m, pidx, i; + + /* Check arguments. */ + assert(n > 0); + if(n == 1) { SA[0] = T[0]; return 0; } + + T[n] = T[0]; + + /* Burrows-Wheeler Transform. */ + m = sort_typeBstar(T, SA, bucket, n); + if(0 < m) { + pidx = construct_BWT(T, SA, bucket, n); + } else { + pidx = 0; + for(i = 0; i < n; ++i) { SA[i] = T[0]; } + } + + return pidx; +} diff --git a/bwt/lbzip2/encode.c b/bwt/lbzip2/encode.c new file mode 100644 index 00000000..13fb4405 --- /dev/null +++ b/bwt/lbzip2/encode.c @@ -0,0 +1,1403 @@ +/*- + encode.c -- low-level compressor + + Copyright (C) 2011, 2012, 2013, 2014 Mikolaj Izdebski + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +#include "common.h" +#include "encode.h" + +#include /* htonl() */ +#include /* memset() */ + +/* The forward move-to-front transform searches a list of symbols and then + shifts everything below the hit up by one slot. Both halves run sixteen + bytes at a time. This direction needs no shuffle, only a compare and a + byte shift, so plain SSE2 will do where decode.c wants SSSE3. */ +#if defined(__aarch64__) && defined(__ARM_NEON) +# include /* vceqq_u8(), vextq_u8() */ +# define MTF_NEON 1 +#elif defined(__SSE2__) +# include /* _mm_cmpeq_epi8(), _mm_slli_si128() */ +# define MTF_SSE2 1 +#endif + + +/* + PREFIX CODING (also called Huffman coding) + + bzip2 file format uses cannonical, prefix-free codes in the last stage of + coding process. bzip2 predescor -- bzip -- used arithmenic coding instead. + Any cannonical, prefix-free codes can be used in bzip2 file. One could use + Shannon or Shannon-Fano codes, but they are usually suboptimal. + + In bzip2 file format the maximal code length is limited to 20, meaning that + no code longer than 20 bits can exist. For generating such liength-limited + prefix code bzip2 uses an algorithm based on the original Huffman algorithm, + but it has several disadvantages. It may require several iterations to + converge and the generated codes can be suboptimal in some cases. + + One of the best known algorithms for generating optimal length-limited prefix + code is Package-Merge algorithm. Unfortunatelly it is significantly slower + and uses more memory than simple algorithms like Huffman algorithm. + + lbzip2 implements a hybrid algorithm. First a lightweight in-place algorithm + based on Huffman algorithm is used to create optimal prefix codes. Then the + maximal code length is computed and if it found to exceed the maximal allowed + length (wich is 20), then these results are discarded and the Package-Merge + algorithm is used to solve the problem from scratch. +*/ + + +/* Maximal code length that can possibly be generated using simple Huffman + algorighm is limited by maximal block size. Generated codes should never be + longer than 30 bits because Fib(30+1) > MAX_BLOCK_SIZE+1. (Huffman codes + are closely connected with the Fibonacci numbers.) */ +#define MAX_HUFF_CODE_LENGTH 30 + + +struct encoder_state { + bool cmap[256]; + int rle_state; + unsigned rle_character; + + uint32_t block_crc; + + uint32_t bwt_idx; + uint32_t out_expect_len; + uint32_t nmtf; + uint32_t nblock; + uint32_t alpha_size; + + uint32_t max_block_size; + uint32_t cluster_factor; + + union { + struct { + uint8_t selector[18000 + 1 + 1]; + uint8_t selectorMTF[18000 + 1 + 7]; + uint32_t num_selectors; + uint32_t num_trees; + unsigned tree_pad; + /* There is a sentinel symbol added at the end of each alphabet, + hence the +1s below. */ + uint8_t length[MAX_TREES][MAX_ALPHA_SIZE + 1]; + uint32_t code[MAX_TREES][MAX_ALPHA_SIZE + 1]; + uint32_t frequency[MAX_TREES][MAX_ALPHA_SIZE + 1]; + /* Three more sets of counters, so that neighbouring symbols in a group + never increment the same address. Folded into frequency before the + maximization step. Free: the union is sized by bucket[]. */ + uint32_t frequency2[MAX_TREES][MAX_ALPHA_SIZE + 1]; + uint32_t frequency3[MAX_TREES][MAX_ALPHA_SIZE + 1]; + uint32_t frequency4[MAX_TREES][MAX_ALPHA_SIZE + 1]; + unsigned tmap_old2new[MAX_TREES]; + unsigned tmap_new2old[MAX_TREES]; + } s; + + int32_t bucket[65536 + 256]; + } u; + + int32_t SA[]; +}; + +#define MAX_RUN_LENGTH (4+255) + + +size_t +encoder_alloc_size(unsigned long max_block_size) +{ + return (sizeof(struct encoder_state) + + (max_block_size + GROUP_SIZE) * sizeof(uint32_t) + + max_block_size + 1); +} + + +void +encoder_init(struct encoder_state *s, unsigned long max_block_size, + unsigned cluster_factor) +{ + assert(s != 0); + assert(max_block_size > 0 && max_block_size <= MAX_BLOCK_SIZE); + assert(cluster_factor > 0 && cluster_factor <= 65535); + + s->max_block_size = max_block_size; + s->cluster_factor = cluster_factor; + + memset(s->cmap, 0, 256u * sizeof(bool)); + s->rle_state = 0; + s->block_crc = -1; + s->nblock = 0; +} + + +int +collect(struct encoder_state *s, const uint8_t *inbuf, size_t *buf_sz) +{ + /* Cache some often used member variables for faster access. */ + size_t avail = *buf_sz; + const uint8_t *p = inbuf; + const uint8_t *pLim = p + avail; + uint8_t *block = (void *)(s->SA + s->max_block_size + GROUP_SIZE); + uint8_t *q = block + s->nblock; + uint8_t *qMax = block + s->max_block_size - 1; + unsigned ch, last; + uint32_t run; + + /* State can't be equal to MAX_RUN_LENGTH because the run would have + already been dumped by the previous function call. */ + assert(s->rle_state >= 0 && s->rle_state < MAX_RUN_LENGTH); + + /* Finish any existing runs before starting a new one. */ + if (unlikely(s->rle_state != 0)) { + ch = s->rle_character; + goto finish_run; + } + +state0: + /*=== STATE 0 ===*/ + if (unlikely(q > qMax)) { + s->rle_state = -1; + goto done; + } + if (unlikely(p == pLim)) { + s->rle_state = 0; + goto done; + } + ch = *p++; + +#define S1 \ + s->cmap[ch] = true; \ + *q++ = ch; \ + if (unlikely(q > qMax)) { \ + s->rle_state = -1; \ + goto done; \ + } \ + if (unlikely(p == pLim)) { \ + s->rle_state = 1; \ + s->rle_character = ch; \ + goto done; \ + } \ + last = ch; \ + ch = *p++; \ + if (unlikely(ch == last)) \ + goto state2 + +state1: + /*=== STATE 1 ===*/ + S1; + S1; + S1; + S1; + goto state1; + +state2: + /*=== STATE 2 ===*/ + *q++ = ch; + if (unlikely(q > qMax)) { + s->rle_state = -1; + goto done; + } + if (unlikely(p == pLim)) { + s->rle_state = 2; + s->rle_character = ch; + goto done; + } + ch = *p++; + if (ch != last) + goto state1; + + /*=== STATE 3 ===*/ + *q++ = ch; + if (unlikely(q >= qMax && (q > qMax || (p < pLim && *p == last)))) { + s->rle_state = -1; + goto done; + } + if (unlikely(p == pLim)) { + s->rle_state = 3; + s->rle_character = ch; + goto done; + } + ch = *p++; + if (ch != last) + goto state1; + + /*=== STATE 4+ ===*/ + assert(q < qMax); + *q++ = ch; + + /* While the run is shorter than MAX_RUN_LENGTH characters, + keep trying to append more characters to it. */ + for (run = 4; run < MAX_RUN_LENGTH; run++) { + /* Check for end of input buffer. */ + if (unlikely(p == pLim)) { + s->rle_state = run; + s->rle_character = ch; + goto done; + } + + /* Fetch the next character. */ + ch = *p++; + + /* If the character does not match, terminate + the current run and start a fresh one. */ + if (ch != last) { + *q++ = run - 4; + s->cmap[run - 4] = true; + if (likely(q <= qMax)) + goto state1; + + /* There is no space left to begin a new run. + Unget the last character and finish. */ + p--; + s->rle_state = -1; + goto done; + } + } + + /* The run has reached maximal length, + so it must be ended prematurely. */ + *q++ = MAX_RUN_LENGTH - 4; + s->cmap[MAX_RUN_LENGTH - 4] = true; + goto state0; + +finish_run: + /* There is an unfinished run from the previous call, try to finish it. */ + if (q >= qMax && (q > qMax || (s->rle_state == 3 && p < pLim && *p == ch))) { + s->rle_state = -1; + goto done; + } + + /* We have run out of input bytes before finishing the run. */ + if (p == pLim) + goto done; + + /* If the run is at least 4 characters long, treat it specifically. */ + if (s->rle_state >= 4) { + assert(q <= qMax); + + while (p < pLim) { + /* Lookahead the next character. Terminate current run + if lookahead character doesn't match. */ + if (*p != ch) { + *q++ = s->rle_state - 4; + s->cmap[s->rle_state - 4] = true; + goto state0; + } + + /* Lookahead character turned out to be continuation of the run. + Consume it and increase run length. */ + p++; + s->rle_state++; + + /* If the run has reached length of MAX_RUN_LENGTH, + we have to terminate it prematurely (i.e. now). */ + if (s->rle_state == MAX_RUN_LENGTH) { + *q++ = MAX_RUN_LENGTH - 4; + s->cmap[MAX_RUN_LENGTH - 4] = true; + goto state0; + } + } + + /* We have ran out of input bytes before finishing the run. */ + goto done; + } + + /* Lookahead the next character. Terminate current run + if lookahead character does not match. */ + if (*p != ch) + goto state0; + + /* Append the character to the run. */ + p++; + s->rle_state++; + *q++ = ch; + + /* We haven't finished the run yet, so keep going. */ + goto finish_run; + +done: + s->nblock = q - block; + s->block_crc = crc32_bzip2(s->block_crc, inbuf, (size_t)(p - inbuf)); + *buf_sz -= p - inbuf; + return s->rle_state < 0; +} + + +/* return ninuse */ +static unsigned +make_map_e(uint8_t *cmap, const bool *inuse) +{ + unsigned i, j; + + j = 0; + + for (i = 0; i < 256; i++) { + int k = inuse[i]; + + cmap[i] = j; + j += k; + } + + return j; +} + + +#if defined(MTF_NEON) || defined(MTF_SSE2) + +/* Lane numbers, for turning a hit position into a blend mask. */ +static const uint8_t mtf_lane[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +/* Index of C in ORDER. The caller guarantees C is there: ORDER holds every + symbol except the one at the front of the list, and C is never that one. + ORDER is 256 bytes so the last vector load stays in bounds; a stray match + in the pad byte cannot win, because the real one sits at a lower index. */ +static unsigned +mtf_search(const uint8_t *order, uint8_t c) +{ + unsigned j; + + for (j = 0; j < 256u; j += 16u) { +#ifdef MTF_NEON + uint8x16_t eq = vceqq_u8(vld1q_u8(order + j), vdupq_n_u8(c)); + /* Halve each lane's width to get four mask bits per byte in one word. */ + uint64_t m = vget_lane_u64(vreinterpret_u64_u8( + vshrn_n_u16(vreinterpretq_u16_u8(eq), 4)), 0); + + if (m != 0) + return j + (unsigned)(__builtin_ctzll(m) >> 2); +#else + unsigned m = (unsigned)_mm_movemask_epi8( + _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i *)(order + j)), + _mm_set1_epi8((char)c))); + + if (m != 0) + return j + (unsigned)__builtin_ctz(m); +#endif + } + + assert(0); /* unreachable: C is always in ORDER */ + return 0; +} + +/* Move ORDER[0..J-1] up one slot and drop U in at the front, overwriting the + symbol at ORDER[J]. Chunks run downwards so each one reads its incoming + byte before the chunk below it is touched. */ +static void +mtf_slide(uint8_t *order, unsigned j, uint8_t u) +{ + unsigned b = j & ~15u; + uint8_t carry = (b == 0u) ? u : order[b - 1u]; + +#ifdef MTF_NEON + uint8x16_t v = vld1q_u8(order + b); + /* Lanes at or below the hit take the shifted vector, the rest stand. */ + uint8x16_t keep = vcgtq_u8(vld1q_u8(mtf_lane), vdupq_n_u8((uint8_t)(j & 15u))); + + vst1q_u8(order + b, vbslq_u8(keep, v, vextq_u8(vdupq_n_u8(carry), v, 15))); + + while (b != 0u) { + b -= 16u; + carry = (b == 0u) ? u : order[b - 1u]; + v = vld1q_u8(order + b); + vst1q_u8(order + b, vextq_u8(vdupq_n_u8(carry), v, 15)); + } +#else + __m128i v = _mm_loadu_si128((const __m128i *)(order + b)); + __m128i keep = _mm_cmpgt_epi8(_mm_loadu_si128((const __m128i *)mtf_lane), + _mm_set1_epi8((char)(j & 15u))); + __m128i sh = _mm_or_si128(_mm_slli_si128(v, 1), _mm_cvtsi32_si128(carry)); + + _mm_storeu_si128((__m128i *)(order + b), + _mm_or_si128(_mm_and_si128(keep, v), + _mm_andnot_si128(keep, sh))); + + while (b != 0u) { + b -= 16u; + carry = (b == 0u) ? u : order[b - 1u]; + v = _mm_loadu_si128((const __m128i *)(order + b)); + _mm_storeu_si128((__m128i *)(order + b), + _mm_or_si128(_mm_slli_si128(v, 1), + _mm_cvtsi32_si128(carry))); + } +#endif +} + +#endif + + +/*---------------------------------------------------*/ +/* returns nmtf */ +static uint32_t +do_mtf(int32_t *bwt, uint32_t *mtffreq, uint8_t *cmap, int32_t nblock, + int32_t EOB) +{ + uint8_t order[256]; /* 255 symbols, padded for vector access */ + int32_t i; + int32_t k; + int32_t t; + uint8_t c; + uint8_t u; + uint16_t *mtfv = (void *)bwt; + const uint16_t *mtfv0 = mtfv; + + for (i = 0; i <= EOB; i++) + mtffreq[i] = 0; + + k = 0; + u = 0; + for (i = 0; i < 255; i++) + order[i] = i + 1; + order[255] = 0; /* pad; never the first hit of a search */ + +#define RUN() \ + if (unlikely(k)) \ + do { \ + mtffreq[*mtfv++ = --k & 1]++; \ + k >>= 1; \ + } while (k) \ + +#if defined(MTF_NEON) || defined(MTF_SSE2) +#define MTF() \ + { \ + unsigned j = mtf_search(order, c); \ + \ + mtf_slide(order, j, u); \ + u = c; \ + t = (int32_t)j + 2; \ + *mtfv++ = t; \ + mtffreq[t]++; \ + } +#else +#define MTF() \ + { \ + uint8_t *p = order; \ + t = *p; \ + *p = u; \ + for (;;) \ + { \ + if (c == t) { u = t; break; } \ + u = *++p; \ + *p = t; \ + if (c == u) break; \ + t = *++p; \ + *p = u; \ + } \ + t = p - order + 2; \ + *mtfv++ = t; \ + mtffreq[t]++; \ + } +#endif + + for (i = 0; i < nblock; i++) { + if ((c = cmap[*bwt++]) == u) { + k++; + continue; + } + RUN(); + MTF(); + } + + RUN(); + + *mtfv++ = EOB; + mtffreq[EOB]++; + + return mtfv - mtfv0; + +#undef RUN +#undef MTF +} + +size_t +encode(struct encoder_state *s, uint32_t *crc) +{ + uint32_t cost; + uint32_t pk; + uint32_t i; + const uint8_t *sp; /* selector pointer */ + uint8_t *smp; /* selector MTFV pointer */ + uint8_t c; /* value before MTF */ + uint8_t j; /* value after MTF */ + uint32_t p; /* MTF state */ + uint32_t EOB; + uint8_t cmap[256]; + uint8_t *block = (void *)(s->SA + s->max_block_size + GROUP_SIZE); + + /* Finalize initial RLE. */ + if (s->rle_state >= 4) { + assert(s->nblock < s->max_block_size); + block[s->nblock++] = s->rle_state - 4; + s->cmap[s->rle_state - 4] = true; + } + assert(s->nblock > 0); + + EOB = make_map_e(cmap, s->cmap) + 1; + assert(EOB >= 2); + assert(EOB < 258); + + /* Sort block. */ + assert(s->nblock > 0); + + s->bwt_idx = divbwt(block, s->SA, s->u.bucket, s->nblock); + s->nmtf = do_mtf(s->SA, s->u.s.code[0], cmap, s->nblock, EOB); + + cost = 48 /* header */ + + 32 /* crc */ + + 1 /* rand bit */ + + 24 /* bwt index */ + + 00 /* {cmap} */ + + 3 /* nGroups */ + + 15 /* nSelectors */ + + 00 /* {sel} */ + + 00 /* {tree} */ + + 00; /* {mtfv} */ + + cost += generate_prefix_code(s); + + sp = s->u.s.selector; + smp = s->u.s.selectorMTF; + + /* A trick that allows to do MTF without branching, using arithmetical + and logical operations only. The whole MTF state packed into one + 32-bit integer. + */ + + /* Set up initial MTF state. */ + p = 0x543210; + + assert(*sp < MAX_TREES); + assert(s->u.s.tmap_old2new[*sp] == 0); + + while ((c = *sp) != MAX_TREES) { + uint32_t v, z, l, h; + + c = s->u.s.tmap_old2new[c]; + assert(c < s->u.s.num_trees); + assert((size_t)(sp - s->u.s.selector) < s->u.s.num_selectors); + + v = p ^ (0x111111 * c); + z = (v + 0xEEEEEF) & 0x888888; + l = z ^ (z - 1); + h = ~l; + p = (p | l) & ((p << 4) | h | c); +#if GNUC_VERSION >= 30406 + j = (__builtin_ctz(h) >> 2) - 1; +#else + h &= -h; + j = !!(h & 0x01010100); + h |= h >> 4; + j |= h >> 11; + j |= h >> 18; + j &= 7; +#endif + sp++; + *smp++ = j; + cost += j + 1; + } + + /* Compute number of padding bit to add to make block size multiply + of 8 bits. */ + j = cost & 0x7; + j = (8 - j) & 0x7; + Trace(("Block padding: %d bits", j)); + cost += j; + s->u.s.tree_pad = j >> 1; /* dummy delta code (0, 2, 4 or 6 bits) */ + j &= 1; + s->u.s.num_selectors += j; /* dummy selector MTF (0 or 1 bit of padding) */ + while (j--) + *smp++ = 0; + assert(cost % 8 == 0); + + /* Calculate the cost of transmitting character map. */ + for (i = 0; i < 16; i++) { + pk = 0; + for (j = 0; j < 16; j++) + pk |= s->cmap[16 * i + j]; + cost += pk << 4; + } + cost += 16; /* Big bucket costs 16 bits on its own. */ + + /* Convert cost from bits to bytes. */ + assert(cost % 8 == 0); + cost >>= 3; + + s->out_expect_len = cost; + + *crc = s->block_crc; + + return cost; +} + + +/* Sort source alphabet by descending fequency. + + Use plain simple insertion sort because (1) the alphabet is small enough and + (2) we expect symbols to be already nearly sorted on common data. +*/ +static void +sort_alphabet(uint64_t *first, uint64_t *last) +{ + uint64_t t, *a, *b, *b1; + + for (a = first + 1; a < last; ++a) { + t = *(b1 = a); + for (b = b1 - 1; *b < t; --b) { + *b1 = *b; + if ((b1 = b) == first) + break; + } + *b1 = t; + } +} + + +/* Build a prefix-free tree. Because the source alphabet is already sorted, + we need not to maintain a priority queue -- two normal FIFO queues + (one for leaves and one for internal nodes) will suffice. + */ +static void +build_tree(uint32_t *restrict tree, uint64_t *restrict weight, int32_t as) +{ + unsigned r; /* index of the next tree in the queue */ + unsigned s; /* index of the next singleton leaf */ + unsigned t; /**/ + uint64_t w1, w2; + + r = as; + s = as; /* Start with the last singleton tree. */ + + for (t = as-1; t > 0; t--) { + if (s < 1 || (r > t+2 && weight[r-2] < weight[s-1])) { + /* Select two internal nodes. */ + tree[r-1] = t; + tree[r-2] = t; + w1 = weight[r-1]; + w2 = weight[r-2]; + r -= 2; + } + else if (r < t+2 || (s > 1 && weight[s-2] <= weight[r-1])) { + /* Select two singleton leaf nodes. */ + w1 = weight[s-1]; + w2 = weight[s-2]; + s -= 2; + } + else { + /* Select one internal node and one singleton leaf node. */ + tree[r-1] = t; + w1 = weight[r-1]; + w2 = weight[s-1]; + s--; + r--; + } + + weight[t] = (weight[t] & 0xFFFF) + ((w1 + w2) & ~(uint64_t)0xFF00FFFF) + + max(w1 & 0xFF000000, w2 & 0xFF000000) + 0x01000000; + } + assert(r == 2); + assert(s == 0); + assert(t == 0); +} + + +/* Compute counts from given Huffman tree. The tree itself is clobbered. */ +static void +compute_depths(uint32_t *restrict count, uint32_t *restrict tree, uint32_t as) +{ + uint32_t avail; /* total number of nodes at current level */ + uint32_t used; /* number of internal nodes */ + uint32_t node; /* current tree node */ + uint32_t depth; /* current node depth */ + + tree[1] = 0; /* The root always has depth of 0. */ + count[0] = 0; /* There are no zero-length codes in bzip2. */ + node = 2; /* The root is done, advance to the next node (index 2). */ + depth = 1; /* The root was the last node at depth 0, go deeper. */ + avail = 2; /* At depth of 1 there are always exactly 2 nodes. */ + + /* Repeat while we have more nodes. */ + while (depth <= MAX_HUFF_CODE_LENGTH) { + used = 0; /* So far we haven't seen any internal nodes at this level. */ + + while (node < as && tree[tree[node]] + 1 == depth) { + assert(avail > used); + used++; + tree[node++] = depth; /* Overwrite parent pointer with node depth. */ + } + + count[depth] = avail - used; + depth++; + avail = used << 1; + } + + assert(avail == 0); +} + + +#define weight_add(w1,w2) ((((w1) + (w2)) & ~(uint64_t)0xFFFFFFFF) + \ + max((w1) & 0xFF000000, \ + (w2) & 0xFF000000) + 0x01000000) + +/* The following is an implementation of the Package-Merge algorithm for + finding an optimal length-limited prefix-free codeset. +*/ + +static void +package_merge(uint16_t tree[MAX_CODE_LENGTH + 1][MAX_CODE_LENGTH + 1], + uint32_t *restrict count, const uint64_t *restrict leaf_weight, + uint_fast32_t as) +{ + uint64_t pkg_weight[MAX_CODE_LENGTH + 1]; + uint64_t prev_weight[MAX_CODE_LENGTH + 1]; + uint64_t curr_weight[MAX_CODE_LENGTH + 1]; + uint_fast32_t width; + uint_fast32_t next_depth; + uint_fast32_t depth; + + pkg_weight[0] = -1; + + for (depth = 1; depth <= MAX_CODE_LENGTH; depth++) { + tree[depth][0] = 2; + pkg_weight[depth] = weight_add(leaf_weight[as], leaf_weight[as - 1]); + prev_weight[depth] = leaf_weight[as - 1]; + curr_weight[depth] = leaf_weight[as - 2]; + } + + for (width = 2; width < as; width++) { + count[0] = MAX_CODE_LENGTH; + depth = MAX_CODE_LENGTH; + next_depth = 1; + for (;;) { + if (pkg_weight[depth - 1] <= curr_weight[depth]) { + if (likely(depth != 1)) { + memcpy(&tree[depth][1], &tree[depth - 1][0], + MAX_CODE_LENGTH * sizeof(uint16_t)); + pkg_weight[depth] = weight_add(prev_weight[depth], + pkg_weight[depth - 1]); + prev_weight[depth] = pkg_weight[depth - 1]; + depth--; + count[next_depth++] = depth; + continue; + } + } + else { + tree[depth][0]++; + pkg_weight[depth] = weight_add(prev_weight[depth], curr_weight[depth]); + prev_weight[depth] = curr_weight[depth]; + curr_weight[depth] = leaf_weight[as - tree[depth][0]]; + } + if (unlikely(next_depth == 0)) + break; + next_depth--; + depth = count[next_depth]; + } + } +} + + +static void +make_code_lengths(uint8_t length[], uint32_t frequency[], uint32_t as) +{ + uint32_t i; + uint32_t k; + uint32_t d; + uint32_t c; + uint64_t weight[MAX_ALPHA_SIZE]; + uint32_t V[MAX_ALPHA_SIZE]; + uint32_t count[MAX_HUFF_CODE_LENGTH + 2]; + + assert(as >= MIN_ALPHA_SIZE); + assert(as <= MAX_ALPHA_SIZE); + + /* Label weights with sequence numbers. + Labelling has two main purposes: firstly it allows to sort pairs of weight + and sequence number more easily; secondly: the package-merge algorithm + requires weights to be strictly monotonous and putting unique values in + lower bits assures that. */ + for (i = 0; i < as; i++) { + /* + FFFFFFFF00000000 - symbol frequency + 00000000FF000000 - node depth + 0000000000FF0000 - initially one + 000000000000FFFF - symbol + */ + weight[i] = (((uint64_t)max(frequency[i], 1u) << 32) | + 0x10000 | (MAX_ALPHA_SIZE - i)); + } + + /* Sort weights and sequence numbers together. */ + sort_alphabet(weight, weight + as); + + build_tree(V, weight, as); + compute_depths(count, V, as); + + /* Generate code lengths. */ + i = 0; + c = 0; + for (d = 0; d <= MAX_HUFF_CODE_LENGTH; d++) { + k = count[d]; + + c = (c + k) << 1; + + while (k != 0) { + assert(i < as); + length[MAX_ALPHA_SIZE - (weight[i] & 0xFFFF)] = d; + i++; + k--; + } + } + assert(c == (1UL << (MAX_HUFF_CODE_LENGTH + 1))); + assert(i == as); +} + + +/* Create initial mapping of symbols to trees. + + The goal is to divide all as symbols [0,as) into nt equivalence classes (EC) + [0,nt) such that standard deviation of symbol frequencies in classes is + minimal. We use a kind of a heuristic to achieve that. There might exist a + better way to achieve that, but this one seems to be good (and fast) enough. + + If the symbol v belongs to the equivalence class t then set + s->u.s.length[t][v] to zero. Otherwise set it to 1. +*/ +static void +generate_initial_trees(struct encoder_state *s, unsigned nm, unsigned nt) +{ + unsigned a, b; /* range [a,b) of symbols forming current EC */ + unsigned freq; /* symbol frequency */ + unsigned cum; /* cumulative frequency */ + unsigned as; /* effective alphabet size (alphabet size minus number + of symbols with frequency equal to zero) */ + unsigned t; /* current tree */ + + /* Equivalence classes are initially empty. */ + memset(s->u.s.length, 1, sizeof(s->u.s.length)); + + /* Determine effective alphabet size. */ + as = 0; + for (a = 0, cum = 0; cum < nm; a++) { + freq = s->u.s.code[0][a]; + cum += freq; + as += min(freq, 1); + } + assert(cum == nm); + + /* Bound number of EC by number of symbols. Each EC is non-empty, so number + of symbol EC must be <= number of symbols. */ + nt = min(nt, as); + + /* For each equivalence class: */ + a = 0; + for (t = 0; nt > 0; t++, nt--) { + assert(nm > 0); + assert(as >= nt); + + /* Find a range of symbols which total count is roughly proportional to one + nt-th of all values. */ + freq = s->u.s.code[0][a]; + cum = freq; + as -= min(freq, 1); + b = a+1; + while (as > nt-1 && cum * nt < nm) { + freq = s->u.s.code[0][b]; + cum += freq; + as -= min(freq, 1); + b++; + } + if (cum > freq && (2*cum - freq) * nt > 2*nm) { + cum -= freq; + as += min(freq, 1); + b--; + } + assert(a < b); + assert(cum > 0); + assert(cum <= nm); + assert(as >= nt-1); + Trace(("Tree %u: EC=[%3u,%3u), |EC|=%3u, cum=%6u", t, a, b, b-a, cum)); + + /* Now [a,b) is our range -- assign it to equivalence class t. */ + memset(&s->u.s.length[t][a], 0, b - a); + a = b; + nm -= cum; + } + assert(as == 0); + assert(nm == 0); +} + +/* Find the tree which takes the least number of bits to encode current group. + Return number from 0 to nt-1 identifying the selected tree. +*/ +static int +find_best_tree(const uint16_t *gs, unsigned nt, const uint64_t *len_pack) +{ + unsigned c, bc; /* code length, best code length */ + unsigned t, bt; /* tree, best tree */ + uint64_t cp; /* cost packed */ + unsigned i; + + /* Compute how many bits it takes to encode current group by each of trees. + Utilize vector operations for best performance. Let's hope the compiler + unrolls the loop for us. + */ + cp = 0; + for (i = 0; i < GROUP_SIZE; i++) + cp += len_pack[gs[i]]; + + /* At the beginning assume the first tree is the best. */ + bc = cp & 0x3ff; + bt = 0; + + /* Iterate over other trees (starting from second one) to see + which one is the best to encode current group. */ + for (t = 1; t < nt; t++) { + cp >>= 10; + c = cp & 0x3ff; + if (c < bc) + bc = c, bt = t; + } + + /* Return our favorite. */ + return bt; +} + + +/* Assign prefix-free codes. Return cost of transmitting the tree and + all symbols it codes. */ +static uint32_t +assign_codes(uint32_t *code, uint8_t *length, + const uint32_t *frequency, uint32_t as) +{ + uint32_t leaf; + uint32_t avail; + uint32_t height; + uint32_t next_code; + uint32_t symbol; + uint64_t leaf_weight[MAX_ALPHA_SIZE + 1]; + uint32_t count[MAX_HUFF_CODE_LENGTH + 2]; + uint32_t base_code[MAX_CODE_LENGTH + 1]; + uint16_t tree[MAX_CODE_LENGTH + 1][MAX_CODE_LENGTH + 1]; + uint32_t best_cost; + uint32_t best_height; + uint32_t depth; + uint32_t cost; + + for (leaf = 0; leaf < as; leaf++) + leaf_weight[leaf + 1] = (((uint64_t)frequency[leaf] << 32) | + 0x10000 | (MAX_ALPHA_SIZE - leaf)); + + sort_alphabet(leaf_weight + 1, leaf_weight + as + 1); + leaf_weight[0] = -1; + + memset(tree, 0, sizeof(tree)); + package_merge(tree, count, leaf_weight, as); + + best_cost = -1; + best_height = MAX_CODE_LENGTH; + + for (height = 2; height <= MAX_CODE_LENGTH; height++) { + if ((1UL << height) < as) + continue; + if (tree[height][height - 1] == 0) { + Trace((" (for heights >%u costs is the same as for height=%u)", + height - 1, height - 1)); + break; + } + + cost = 0; + leaf = 0; + for (depth = 1; depth <= height; depth++) { + for (avail = tree[height][depth - 1] - tree[height][depth]; + avail > 0; avail--) { + assert(leaf < as); + symbol = MAX_ALPHA_SIZE - (leaf_weight[leaf + 1] & 0xFFFF); + length[symbol] = depth; + cost += (unsigned)(leaf_weight[leaf + 1] >> 32) * depth; + leaf++; + } + } + + for (symbol = 1; symbol < as; symbol++) + cost += 2 * max((int)length[symbol - 1] - (int)length[symbol], + (int)length[symbol] - (int)length[symbol - 1]); + cost += 5 + as; + + Trace((" for height=%2u transmission cost is %7u", height, cost)); + if (cost < best_cost) { + best_cost = cost; + best_height = height; + } + } + Trace((" best tree height is %u", best_height)); + + /* Generate code lengths and base codes. */ + leaf = 0; + next_code = 0; + for (depth = 1; depth <= best_height; depth++) { + avail = tree[best_height][depth - 1] - tree[best_height][depth]; + base_code[depth] = next_code; + next_code = (next_code + avail) << 1; + + while (avail > 0) { + assert(leaf < as); + symbol = MAX_ALPHA_SIZE - (leaf_weight[leaf + 1] & 0xFFFF); + length[symbol] = depth; + leaf++; + avail--; + } + } + assert(next_code == (1UL << (best_height + 1))); + assert(leaf == as); + + /* Assign prefix-free codes. */ + for (symbol = 0; symbol < as; symbol++) + code[symbol] = base_code[length[symbol]]++; + +#ifdef ENABLE_TRACING + Trace((" Prefix code dump:")); + for (symbol = 0; symbol < as; symbol++) { + static char buffer[MAX_HUFF_CODE_LENGTH+2]; + char *p = buffer; + unsigned len = length[symbol]; + + while (len-- > 0) + *p++ = (code[symbol] & (1UL << len)) ? '1' : '0'; + *p = 0; + + Trace((" symbol %3u has code %s", symbol, buffer)); + } +#endif + + return best_cost; +} + + +/* The main function generating prefix code for the whole block. + + Input: MTF values + Output: trees and selectors + + What this function does: + 1) decides how many trees to generate + 2) divides groups into equivalence classes (using Expectation-Maximization + algorithm, which is a heuristic usually giving suboptimal results) + 3) generates an optimal prefix tree for each class (with a hubrid algorithm + consisting of Huffman algorithm and Package-Merge algorithm) + 4) generates selectors + 5) sorts trees by their first occurence in selector sequence + 6) computes and returns cost (in bits) of transmitting trees and codes +*/ +unsigned +generate_prefix_code(struct encoder_state *s) +{ + uint32_t as; + uint32_t nt; + uint32_t iter, i; + uint32_t cost; + + uint16_t *mtfv = (void *)s->SA; + uint32_t nm = s->nmtf; + + as = mtfv[nm - 1] + 1; /* the last mtfv is EOB */ + s->u.s.num_selectors = (nm + GROUP_SIZE - 1) / GROUP_SIZE; + + /* Decide how many prefix-free trees to use for current block. The best + for compression ratio would be to always use the maximal number of trees. + However, the space it takes to transmit these trees can also be a factor, + especially if the data being encoded is not very long. If we use less + trees for smaller block then the space needed to transmit additional + trees is traded against the space saved by using more trees. + */ + assert(nm >= 2); + nt = (nm > 2400 ? 6 : + nm > 1200 ? 5 : + nm > 600 ? 4 : + nm > 300 ? 3 : + nm > 150 ? 2 : 1); + + /* Complete the last group with dummy symbols. */ + for (i = nm; i < s->u.s.num_selectors * GROUP_SIZE; i++) + mtfv[i] = as; + + /* Grow up an initial forest. */ + generate_initial_trees(s, nm, nt); + + /* Perform a few iterations of the Expectation-Maximization algorithm to + improve trees. + */ + iter = s->cluster_factor; + while (iter-- > 0) { + uint64_t len_pack[MAX_ALPHA_SIZE + 1]; + uint16_t *gs; + uint32_t v, t; + uint8_t *sp; + + /* Pack code lengths of all trees into 64-bit integers in order to take + advantage of 64-bit vector arithmetic. Each group holds at most + 50 codes, each code is at most 20 bit long, so each group is coded + by at most 1000 bits. We can store that in 10 bits. */ + for (v = 0; v < as; v++) + len_pack[v] = (((uint64_t)s->u.s.length[0][v] ) + + ((uint64_t)s->u.s.length[1][v] << 10) + + ((uint64_t)s->u.s.length[2][v] << 20) + + ((uint64_t)s->u.s.length[3][v] << 30) + + ((uint64_t)s->u.s.length[4][v] << 40) + + ((uint64_t)s->u.s.length[5][v] << 50)); + len_pack[as] = 0; + + sp = s->u.s.selector; + + /* (E): Expectation step -- estimate likehood. */ + memset(s->u.s.frequency, 0, nt * sizeof(*s->u.s.frequency)); + memset(s->u.s.frequency2, 0, nt * sizeof(*s->u.s.frequency2)); + memset(s->u.s.frequency3, 0, nt * sizeof(*s->u.s.frequency3)); + memset(s->u.s.frequency4, 0, nt * sizeof(*s->u.s.frequency4)); + for (gs = mtfv; gs < mtfv + nm; gs += GROUP_SIZE) { + /* Check out which prefix-free tree is the best to encode current + group. Then increment symbol frequencies for the chosen tree + and remember the choice in the selector array. + + The counters rotate through four arrays. Runs of one symbol are + everywhere in MTF output, and incrementing one address twice running + costs the store-to-load forward each time; sending neighbours to + separate arrays lets the chains overlap. Fifty is not a multiple of + four, so the last two symbols fall back to the first array. */ + t = find_best_tree(gs, nt, len_pack); + assert(t < nt); + *sp++ = t; + for (i = 0; i + 4 <= GROUP_SIZE; i += 4) { + s->u.s.frequency[t][gs[i]]++; + s->u.s.frequency2[t][gs[i + 1]]++; + s->u.s.frequency3[t][gs[i + 2]]++; + s->u.s.frequency4[t][gs[i + 3]]++; + } + for (; i < GROUP_SIZE; i++) + s->u.s.frequency[t][gs[i]]++; + } + + assert((size_t)(sp - s->u.s.selector) == s->u.s.num_selectors); + *sp = MAX_TREES; /* sentinel */ + + for (t = 0; t < nt; t++) + for (i = 0; i <= as; i++) + s->u.s.frequency[t][i] += s->u.s.frequency2[t][i] + + s->u.s.frequency3[t][i] + + s->u.s.frequency4[t][i]; + + /* (M): Maximization step -- maximize expectations. */ + for (t = 0; t < nt; t++) + make_code_lengths(s->u.s.length[t], s->u.s.frequency[t], as); + } + + cost = 0; + + /* Reorder trees. This also removes unused trees. */ + { + /* Only lowest nt bits are used, from 0 to nt-1. If i-th bit is set then + i-th tree exists but hasn't been seen yet. */ + unsigned not_seen = (1 << nt) - 1; + unsigned t, v; + uint8_t *sp = s->u.s.selector; + + nt = 0; + while (not_seen > 0 && (t = *sp++) < MAX_TREES) { + if (not_seen & (1 << t)) { + not_seen -= 1 << t; + s->u.s.tmap_old2new[t] = nt; + s->u.s.tmap_new2old[nt] = t; + nt++; + + /* Create lookup tables for this tree. These tables are used by the + transmiter to quickly send codes for MTF values. */ + cost += assign_codes(s->u.s.code[t], s->u.s.length[t], + s->u.s.frequency[t], as); + s->u.s.code[t][as] = 0; + s->u.s.length[t][as] = 0; + } + } + + /* If there is only one prefix tree in current block, we need to create + a second dummy tree. This increases the cost of transmitting the block, + but unfortunately bzip2 doesn't allow blocks with a single tree. */ + assert(nt >= 1); + if (nt == 1) { + unsigned cl0; + nt = 2; + t = s->u.s.tmap_new2old[0] ^ 1; + s->u.s.tmap_old2new[t] = 1; + s->u.s.tmap_new2old[1] = t; + cl0 = (((0xffffaa50 >> ((as < 0x20 ? as : (as >> 4)) & 0x1e)) & 0x3) + + (as < 0x20 ? 1 : 5)); /* cl0 = floor(log2(as)) */ + for (v = 0; v < (2 << cl0) - as; v++) + s->u.s.length[t][v] = cl0; + if (v < as) + cost += 2; + for (; v < as; v++) + s->u.s.length[t][v] = cl0 + 1; + cost += as + 5; + } + } + + s->u.s.num_trees = nt; + return cost; +} + + +#define PUTBIT(n,v) \ + b = (b << (n)) | (v); \ + k += (n); +#define DUMP() \ + k -= 32; \ + *p++ = htonl((uint32_t)(b >> k)); +#define SEND(n,v) \ + PUTBIT((n), (v)); \ + if (k >= 32) { \ + DUMP(); \ + } + +void * +transmit(struct encoder_state *s, void *buf) +{ + uint64_t b; + unsigned k; + uint8_t *sp; + unsigned t; + unsigned v; + uint16_t *mtfv; + uint32_t *p; + unsigned ns; + unsigned as; + uint32_t gr; + + + /* Initialize bit buffer. */ + b = 0; + k = 0; + p = buf; + + mtfv = (void *)s->SA; + as = mtfv[s->nmtf - 1] + 1; + ns = (s->nmtf + GROUP_SIZE - 1) / GROUP_SIZE; + + /* If no external buffer was provided then use an internal buffer. */ + if (!buf) { + buf = &mtfv[ns * GROUP_SIZE]; + assert((char *)buf + (s->out_expect_len + 3) / 4 * 4 <= + (char *)s + encoder_alloc_size(s->max_block_size)); + p = buf; + } + + /* Transmit block metadata. */ + PUTBIT(24, 0x314159); + PUTBIT(24, 0x265359); + DUMP(); + PUTBIT(32, s->block_crc ^ 0xFFFFFFFF); + DUMP(); + PUTBIT(1, 0); /* non-rand */ + PUTBIT(24, s->bwt_idx); /* bwt primary index */ + DUMP(); + assert(k == 9); + + /* Transmit character map. */ + { + unsigned pack[16]; + unsigned pk; + unsigned i; + unsigned j; + unsigned big = 0; + + for (i = 0; i < 16; i++) { + pk = 0; + for (j = 0; j < 16; j++) + pk = (pk << 1) + s->cmap[16 * i + j]; + pack[i] = pk; + big = (big << 1) + !!pk; + } + + PUTBIT(16, big); + for (i = 0; i < 16; i++) + if (pack[i]) { + SEND(16, pack[i]); + } + } + + /* Transmit selectors. */ + assert(s->u.s.num_trees >= MIN_TREES && s->u.s.num_trees <= MAX_TREES); + PUTBIT(3, s->u.s.num_trees); + assert(k == 12 || k == 28); + t = s->u.s.num_selectors; + SEND(15, t); + sp = s->u.s.selectorMTF; + while (t--) { + v = 1 + *sp++; + SEND(v, (1 << v) - 2); + } + + /* Transmit prefix trees. */ + for (t = 0; t < s->u.s.num_trees; t++) { + int32_t a, c; + uint8_t *len = s->u.s.length[s->u.s.tmap_new2old[t]]; + + a = len[0]; + if (t == 0) { + if (a < 4) + a += s->u.s.tree_pad; + else + a -= s->u.s.tree_pad; + } + SEND(5, a); + for (v = 0; v < as; v++) { + c = len[v]; + while (a < c) { + SEND(2, 2); + a++; + } + while (a > c) { + SEND(2, 3); + a--; + } + SEND(1, 0); + } + } + + /* Transmit prefix codes. */ + for (gr = 0; gr < ns; gr++) { + unsigned i; /* symbol index in group */ + const uint32_t *L; /* symbol-to-code lookup table */ + const uint8_t *B; /* code lengths */ + unsigned mv; /* symbol (MTF value) */ + + t = s->u.s.selector[gr]; + L = s->u.s.code[t]; + B = s->u.s.length[t]; + + for (i = 0; i < GROUP_SIZE; i++) { + mv = *mtfv++; + SEND(B[mv], L[mv]); + } + } + + /* Flush */ + assert(k % 8 == 0); + assert(k / 8 == s->out_expect_len % 4); + assert(p == (uint32_t *)buf + s->out_expect_len / 4); + SEND(31, 0); + + return buf; +} diff --git a/bwt/lbzip2/encode.h b/bwt/lbzip2/encode.h new file mode 100644 index 00000000..04eec2a4 --- /dev/null +++ b/bwt/lbzip2/encode.h @@ -0,0 +1,38 @@ +/*- + encode.h -- low-level compressor header + + Copyright (C) 2012 Mikolaj Izdebski + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +#define CLUSTER_FACTOR 8u +#define HEADER_SIZE 4u +#define TRAILER_SIZE 10u + + +struct encoder_state; + +size_t encoder_alloc_size(unsigned long mbs); +void encoder_init(struct encoder_state *e, unsigned long mbs, unsigned cf); +int collect(struct encoder_state *e, const uint8_t *buf, size_t *buf_sz); +size_t encode(struct encoder_state *e, uint32_t *crc); +void *transmit(struct encoder_state *e, void *buf); +unsigned generate_prefix_code(struct encoder_state *s); + +int32_t divbwt(uint8_t *T, int32_t *SA, int32_t *bucket, int32_t n); + +#define combine_crc(cc,c) (((cc) << 1) ^ ((cc) >> 31) ^ (c) ^ -1) diff --git a/bwt/lbzip2/lbzip2_lzbench.c b/bwt/lbzip2/lbzip2_lzbench.c new file mode 100644 index 00000000..d3353fda --- /dev/null +++ b/bwt/lbzip2/lbzip2_lzbench.c @@ -0,0 +1,181 @@ +/* + lbzip2_lzbench.c -- buffer-to-buffer wrapper around lbzip2's codec + + lbzip2 is a bzip2-compatible compressor whose command-line tool splits the + work over threads. lzbench benchmarks buffer-to-buffer calls and does its + own threading, so this drives the same low-level encoder and decoder + sequentially, one 100k-900k block at a time, exactly as compress.c and + expand.c do around their scheduler. The bytes produced are the same. + + This file is part of lzbench and, like lbzip2, is distributed under the GNU + General Public License, version 3 or later. +*/ + +#include +#include + +#include "common.h" +#include "decode.h" +#include "encode.h" +#include "lbzip2_lzbench.h" + +/* decode.c allocates through main.c's xmalloc(), which is the only thing it + needs from the command-line tool. */ +void * +xmalloc(size_t size) +{ + void *ptr = malloc(size); + + if (ptr == NULL) + abort(); + + return ptr; +} + + +size_t +lbzip2_buf_compress(const void *inbuf, size_t insize, void *outbuf, + size_t outsize, int level) +{ + const uint8_t *in = inbuf; + uint8_t *out = outbuf; + struct encoder_state *enc; + size_t left = insize; + size_t pos = HEADER_SIZE; + uint32_t combined_crc = 0; + + if (level < 1 || level > 9 || outsize < HEADER_SIZE + TRAILER_SIZE) + return 0; + + out[0] = 0x42; + out[1] = 0x5A; + out[2] = 0x68; + out[3] = 0x30 + level; + + enc = malloc(encoder_alloc_size(level * 100000u)); + if (enc == NULL) + return 0; + + while (left > 0) { + uint32_t crc; + size_t size; + const void *block; + + encoder_init(enc, level * 100000u, CLUSTER_FACTOR); + + /* One call fills the block, or exhausts the input trying. */ + (void)collect(enc, in + (insize - left), &left); + + size = encode(enc, &crc); + block = transmit(enc, NULL); + combined_crc = combine_crc(combined_crc, crc); + + /* Every block is padded to a whole number of bytes by the encoder, so + blocks concatenate without any bit shifting. */ + if (pos + size + TRAILER_SIZE > outsize) { + free(enc); + return 0; + } + memcpy(out + pos, block, size); + pos += size; + } + + free(enc); + + out[pos++] = 0x17; + out[pos++] = 0x72; + out[pos++] = 0x45; + out[pos++] = 0x38; + out[pos++] = 0x50; + out[pos++] = 0x90; + out[pos++] = combined_crc >> 24; + out[pos++] = (combined_crc >> 16) & 0xFF; + out[pos++] = (combined_crc >> 8) & 0xFF; + out[pos++] = combined_crc & 0xFF; + + return pos; +} + + +size_t +lbzip2_buf_decompress(const void *inbuf, size_t insize, void *outbuf, + size_t outsize) +{ + const uint8_t *in = inbuf; + struct parser_state ps; + struct bitstream bs; + struct header hd; + uint32_t *words; + size_t nwords; + size_t produced = 0; + unsigned garbage; + int rv; + + /* The stream header is what tells the parser the block size; the tool + reads it before starting the expansion, and so do we. */ + if (insize < HEADER_SIZE + TRAILER_SIZE || in[0] != 0x42 || in[1] != 0x5A || + in[2] != 0x68 || in[3] < 0x31 || in[3] > 0x39) + return 0; + + /* The decoder reads the stream as 32-bit words, so copy the rest of the + input into an aligned buffer zero-padded to a word boundary. Compressed + input is small next to the work of decoding it. */ + nwords = (insize - HEADER_SIZE + 3) / 4; + words = calloc(nwords, sizeof(uint32_t)); + if (words == NULL) + return 0; + memcpy(words, in + HEADER_SIZE, insize - HEADER_SIZE); + + bs.live = 0; + bs.buff = 0; + bs.block = NULL; + bs.data = words; + bs.limit = words + nwords; + bs.eof = true; + + parser_init(&ps, in[3] - 0x30, 0); + + for (;;) { + struct decoder_state ds; + + rv = parse(&ps, &hd, &bs, &garbage); + if (rv == FINISH) + break; + if (rv != OK) + goto err; + + decoder_init(&ds); + + rv = retrieve(&ds, &bs); + if (rv == OK) { + decode(&ds); + + do { + size_t avail = outsize - produced; + + if (avail == 0) { + rv = ERR_OVERFLOW; + break; + } + rv = emit(&ds, (char *)outbuf + produced, &avail); + produced = outsize - avail; + } + while (rv == MORE); + } + + if (rv == OK && ds.crc != hd.crc) + rv = ERR_BLKCRC; + + decoder_free(&ds); + + if (rv != OK) + goto err; + } + + free(words); + return produced; + +err: + free(words); + return 0; +} diff --git a/bwt/lbzip2/lbzip2_lzbench.h b/bwt/lbzip2/lbzip2_lzbench.h new file mode 100644 index 00000000..22a3d9fc --- /dev/null +++ b/bwt/lbzip2/lbzip2_lzbench.h @@ -0,0 +1,24 @@ +/* + Buffer-to-buffer entry points for lbzip2, for lzbench. See + lbzip2_lzbench.c. Both return 0 on error, otherwise the number of bytes + written to outbuf. +*/ +#ifndef LBZIP2_LZBENCH_H +#define LBZIP2_LZBENCH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +size_t lbzip2_buf_compress(const void *inbuf, size_t insize, void *outbuf, + size_t outsize, int level); +size_t lbzip2_buf_decompress(const void *inbuf, size_t insize, void *outbuf, + size_t outsize); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bwt/lbzip2/main.h b/bwt/lbzip2/main.h new file mode 100644 index 00000000..131161dc --- /dev/null +++ b/bwt/lbzip2/main.h @@ -0,0 +1,91 @@ +/*- + main.h -- main module header + + Copyright (C) 2011, 2012 Mikolaj Izdebski + Copyright (C) 2008, 2009, 2010 Laszlo Ersek + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +#include /* CHAR_BIT */ + +#if 8 != CHAR_BIT +#error "Environments where 8 != CHAR_BIT are not supported." +#endif + + +/* + The file specifier. + + The pointers "sep" and "fmt" point to character arrays that either don't + need to be released, or need to be released through different aliases. + These are prepared solely for logging. This is why the pointed to chars + are qualified as const. +*/ +struct filespec { + int fd; /* the file descriptor; -1 if none */ + const char *sep; /* name separator; either "" or "\"" */ + const char *fmt; /* either file name or a special name */ + uintmax_t total; /* total number of bytes transferred */ + uintmax_t size; /* file size or 0 if unknown */ +}; + + +extern unsigned num_worker; /* -n */ +extern size_t max_mem; /* -m */ +extern bool decompress; /* -d */ +extern unsigned bs100k; /* -1..-9 */ +extern bool force; /* -f */ +extern bool keep; /* -k */ +extern bool verbose; /* -v */ +extern bool small; /* -s */ +extern bool ultra; /* -u */ +extern struct filespec ispec; +extern struct filespec ospec; + + +void *xmalloc(size_t); +#define XMALLOC(type) ((type *)xmalloc(sizeof(type))) +#define XNMALLOC(n, type) ((type *)xmalloc((n) * sizeof(type))) + +void info(const char *fmt, ...) + format_printf(1, 2); +void infof(const struct filespec *f, const char *fmt, ...) + format_printf(2, 3); +void infox(int x, const char *fmt, ...) + format_printf(2, 3); +void infofx(const struct filespec *f, int x, const char *fmt, ...) + format_printf(3, 4); +void warn(const char *fmt, ...) + format_printf(1, 2); +void warnf(const struct filespec *f, const char *fmt, ...) + format_printf(2, 3); +void warnx(int x, const char *fmt, ...) + format_printf(2, 3); +void warnfx(const struct filespec *f, int x, const char *fmt, ...) + format_printf(3, 4); +_Noreturn void fail(const char *fmt, ...) + format_printf(1, 2); +_Noreturn void failf(const struct filespec *f, const char *fmt, ...) + format_printf(2, 3); +_Noreturn void failx(int x, const char *fmt, ...) + format_printf(2, 3); +_Noreturn void failfx(const struct filespec *f, int x, const char *fmt, ...) + format_printf(3, 4); +void display(const char *fmt, ...) + format_printf(1, 2); + +void work(void); diff --git a/bwt/lbzip2/parse.c b/bwt/lbzip2/parse.c new file mode 100644 index 00000000..f2b6f32b --- /dev/null +++ b/bwt/lbzip2/parse.c @@ -0,0 +1,342 @@ +/*- + parse.c -- find block boundaries + + Copyright (C) 2011, 2012, 2013, 2014 Mikolaj Izdebski + + This file is part of lbzip2. + + lbzip2 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + lbzip2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with lbzip2. If not, see . +*/ + +/* + This file contains implementations of two different algorithms for finding + boundaries of compressed block -- deterministic "parsing" and probabilistic + "scanning". Both are based on deterministic finite state automatons. + + Parsing is a deterministic algorithm used to find location of next block, + given location of the end of previous block. It processes and validates + block and stream metadata. Its main disadvantage is that it has to be ran + sequentially only -- all preceding blocks must be fully decoded before + attempting to find the location of any block. + + Scanning is another way of finding locations where compressed blocks are + likely to begin. It can be ran in parallel by multiple threads to discover + locations which with high probability start compressed blocks. + + The two ways of finding block boundaries can be nicely combined together. + First scanning can be used to determine likely candidates for blocks, which + can be later confirmed or rejected after parsing block headers. + + The probability of finding false positives when scanning for block headers is + usually very small (below 1e-14). However it is possible to create + compressed files which would cause large number of false positives, so lbzip2 + had to be designed to behave correctly even in cases with high ratios of + false positives. There is also some small probability of not discovering + existing block header in the scanning phase. This can happen if block magic + pattern, which is used to identify block headers, crosses boundaries of two + I/O blocks. Such headers will not be recognized by scanner threads. The + probability of missing magic pattern is low -- the magic is only 6 bytes long + and I/O blocks are 1 MiB each. This is not a big problem as deterministic + parser will will eventually find all missed blocks, but it is possible to + construct a compressed file in a way which will prevent scanner from finding + some blocks. Both above cases of specially hand-crafted compressed files may + affect decompression performance, but they should not affect correctness. + + lbzip2 was constructed in the way that worst-case decompression time using + more than one thread is the same as decompression using one thread, minus the + time spent for thread synchronization, which is usually low. (Simply + speaking, a n-thread decompressor can be thought of as a single sequential + decompressor with n-1 helper workers, which try to predict what will need to + be done in future and prepare that work in advance so that when sequential + decompressor reaches that point it will be able to simply take the work done + by helper worker. The predictions are usually close to be perfect, which + means that the sequential worker can take advantage of them, which results in + performance gains. But if some evil force tries to mislead helper workers, + the worst that can happen is complete waste of resources used by the n-1 + helper threads -- the deterministic sequential decompressor will still be + able to complete the decompression job, without any help from other workers.) +*/ + + +#include "common.h" /* OK */ + +#include /* htonl() */ + +#include "decode.h" /* bits_need() */ + +#include "scantab.h" + + +#define bits_need(bs,n) \ + ((n) <= (bs)->live \ + ? \ + OK \ + : \ + unlikely ((bs)->data == (bs)->limit) \ + ? \ + (bs)->eof \ + ? \ + FINISH \ + : \ + MORE \ + : \ + ((bs)->buff |= (uint64_t) ntohl \ + (*(bs)->data) << (32u - (bs)->live), \ + (bs)->data++, \ + (bs)->live += 32u, \ + OK)) + +#define bits_peek(bs,n) ((bs)->buff >> (64u - (n))) + +#define bits_dump(bs,n) \ + ((bs)->buff <<= (n), \ + (bs)->live -= (n), \ + (void) 0) + +#define bits_align(bs) \ + (bits_dump (bs, (bs)->live % 8u), \ + (void) 0) + +#define bits_consume(bs) \ + (bits_dump (bs, (bs)->live), \ + (bs)->data = (bs)->limit, \ + (void) 0) + + +enum { + STREAM_MAGIC_1, STREAM_MAGIC_2, BLOCK_MAGIC_1, BLOCK_MAGIC_2, BLOCK_MAGIC_3, + BLOCK_CRC_1, BLOCK_CRC_2, EOS_2, EOS_3, EOS_CRC_1, EOS_CRC_2, +}; + + +void +parser_init(struct parser_state *ps, int bs100k, int stream_mode) +{ + ps->state = BLOCK_MAGIC_1; + ps->bs100k = bs100k; + ps->computed_crc = 0u; + ps->stream_mode = stream_mode; +} + + +/* Parse stream headers until a compressed block or end of stream is reached. + + Possible return codes: + OK - a compressed block was found + FINISH - end of stream was reached + MORE - more input is need, parsing was suspended + ERR_HEADER - invalid stream header + ERR_STRMCRC - stream CRC does not match + ERR_EOF - unterminated stream (EOF reached before end of stream) + + garbage is set only when returning FINISH. It is number of garbage bits + consumed after end of stream was reached. +*/ +int +parse(struct parser_state *restrict ps, struct header *restrict hd, + struct bitstream *bs, unsigned *garbage) +{ + assert(ps->state != ACCEPT); + + while (OK == bits_need(bs, 16)) { + unsigned word = bits_peek(bs, 16); + + bits_dump(bs, 16); + + switch (ps->state) { + case STREAM_MAGIC_1: + assert(!ps->stream_mode); + if (0x425Au != word) { + hd->bs100k = -1; + hd->crc = 0; + ps->state = ACCEPT; + *garbage = 16; + return FINISH; + } + ps->state = STREAM_MAGIC_2; + continue; + + case STREAM_MAGIC_2: + assert(!ps->stream_mode); + if (0x6839u < word || 0x6831 > word) { + hd->bs100k = -1; + hd->crc = 0; + ps->state = ACCEPT; + *garbage = 32; + return FINISH; + } + ps->bs100k = word & 15u; + ps->state = BLOCK_MAGIC_1; + continue; + + case BLOCK_MAGIC_1: + if (0x1772u == word) { + ps->state = EOS_2; + continue; + } + if (0x3141u != word) + return ERR_HEADER; + ps->state = BLOCK_MAGIC_2; + continue; + + case BLOCK_MAGIC_2: + if (0x5926u != word) + return ERR_HEADER; + ps->state = BLOCK_MAGIC_3; + continue; + + case BLOCK_MAGIC_3: + if (0x5359u != word) + return ERR_HEADER; + ps->state = BLOCK_CRC_1; + continue; + + case BLOCK_CRC_1: + ps->stored_crc = word; + ps->state = BLOCK_CRC_2; + continue; + + case BLOCK_CRC_2: + hd->crc = (ps->stored_crc << 16) | word; + hd->bs100k = ps->bs100k; + ps->computed_crc = + (ps->computed_crc << 1) ^ (ps->computed_crc >> 31) ^ hd->crc; + ps->state = BLOCK_MAGIC_1; + return OK; + + case EOS_2: + if (0x4538u != word) + return ERR_HEADER; + ps->state = EOS_3; + continue; + + case EOS_3: + if (0x5090u != word) + return ERR_HEADER; + ps->state = EOS_CRC_1; + continue; + + case EOS_CRC_1: + ps->stored_crc = word; + ps->state = EOS_CRC_2; + continue; + + case EOS_CRC_2: + ps->stored_crc = (ps->stored_crc << 16) | word; + if (ps->stored_crc != ps->computed_crc) + return ERR_STRMCRC; + if (ps->stream_mode) { + ps->state = ACCEPT; + *garbage = 0; + return FINISH; + } + ps->computed_crc = 0u; + bits_align(bs); + ps->state = STREAM_MAGIC_1; + continue; + + default: + break; + } + + assert(0); + } + + if (FINISH != bits_need(bs, 16)) + return MORE; + + if (ps->state == STREAM_MAGIC_1) { + ps->state = ACCEPT; + *garbage = 0; + return FINISH; + } + if (ps->state == STREAM_MAGIC_2) { + ps->state = ACCEPT; + *garbage = 16; + return FINISH; + } + + return ERR_EOF; +} + + +/* Scan for magic bit sequence which presence indicates probable start of + compressed block. + + Possible return codes: + OK - the magic sequence was found + MORE - block header magic was not found +*/ +int +scan(struct bitstream *bs, unsigned skip) +{ + unsigned state = 0; + const uint32_t *data, *limit; + + if (skip > bs->live) { + skip -= bs->live; + bits_dump(bs, bs->live); + skip = (skip + 31u) / 32u; + if ((size_t)(bs->limit - bs->data) < skip) + bs->data = bs->limit; + else + bs->data += skip; + } + +again: + assert(state < ACCEPT); + while (bs->live > 0) { + unsigned bit = bits_peek(bs, 1); + + bits_dump(bs, 1); + state = mini_dfa[state][bit]; + + if (state == ACCEPT) { + if (bits_need(bs, 32) == OK) { + bits_dump(bs, 32); + return OK; + } + else { + bits_consume(bs); + return MORE; + } + } + } + + data = bs->data; + limit = bs->limit; + + while (data < limit) { + unsigned bt_state = state; + uint32_t word = *data; + + word = ntohl(word); + state = big_dfa[state][word >> 24]; + state = big_dfa[state][(uint8_t)(word >> 16)]; + state = big_dfa[state][(uint8_t)(word >> 8)]; + state = big_dfa[state][(uint8_t)word]; + + if (unlikely(state == ACCEPT)) { + state = bt_state; + bs->data = data; + (void)bits_need(bs, 1u); + goto again; + } + + data++; + } + + bs->data = data; + return MORE; +} diff --git a/bwt/lbzip2/scantab.h b/bwt/lbzip2/scantab.h new file mode 100644 index 00000000..aa724c0d --- /dev/null +++ b/bwt/lbzip2/scantab.h @@ -0,0 +1,512 @@ +/* This file was generated automatically by make-scantab.pl. + For comments refer to the generator script -- make-scantab.pl. */ + +static const unsigned char ACCEPT = 48; + +static const unsigned char mini_dfa[48][2] = { + {1, 0,}, {2, 0,}, {2, 3,}, {1, 4,}, {5, 0,}, {6, 0,}, {7, 3,}, {2, 8,}, {9, + 4,}, {2, 10,}, {11, 0,}, {12, 0,}, {13, 3,}, {14, 3,}, {15, 3,}, {2, 16,}, + {17, 4,}, {2, 18,}, {19, 0,}, {2, 20,}, {1, 21,}, {22, 0,}, {23, 0,}, {2, + 24,}, {25, 4,}, {26, 0,}, {2, 27,}, {28, 4,}, {29, 0,}, {2, 30,}, {1, 31,}, + {32, 0,}, {33, 0,}, {7, 34,}, {35, 4,}, {2, 36,}, {37, 0,}, {38, 0,}, {2, + 39,}, {1, 40,}, {41, 0,}, {6, 42,}, {43, 0,}, {2, 44,}, {1, 45,}, {46, 0,}, + {47, 0,}, {2, 48,}, +}; + +static const unsigned char big_dfa[49][256] = { + {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 11, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 12, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 13, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 14, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 10, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 15, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 10, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 16, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 11, 0, 6, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 17, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 18, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 19, 0, 6, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, + 20, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, 2, + 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 21, 2, 0, 1, + 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, 2, 3, + 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 22, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, 2, 3, 1, + 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 23, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 24, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 11, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 25, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, + {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 26, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, + 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 27, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 28, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 29, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 30, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 6, 0, 1, 0, 2, 3, 1, 31, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 32, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 11, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 33, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 34, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 10, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 35, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 11, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 9, 4, 2, 36, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 10, 5, 0, 2, 3, 37, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 11, 0, 6, 0, 1, 0, 2, 3, + 1, 4, 38, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, + 1, 4, 12, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 39, 1, + 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, + 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 13, 3, 1, 0, 2, + 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 40, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 6, 0, 1, 0, 14, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 41, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, + 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 6, 42, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 11, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, + 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 43, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, + 1, 4, 2, 44, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, + {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, + 0, 2, 3, 1, 45, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, + 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, + 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 10, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 46, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 11, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 47, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 12, 0, 1, 0, 7, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 48, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, + 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 13, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, + 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, + 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 48, 48, 2, 0, 1, 0, + 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 48, 48, 48, 48, 2, 3, 1, + 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, + 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, + 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 48, 48, 48, 48, 48, 48, 48, 48, 2, 3, 1, + 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, + 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 6, 0, 1, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0,}, {2, 3, 1, + 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 7, 3, 1, 0, 2, + 0, 1, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, + 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, + 2, 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, + 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, + 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, + 2, 0, 1, 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, + 0, 1, 0, 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, + 0, 2, 8, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, + 0,}, {2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, + 7, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 8, + 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 5, 0, 2, 3, 1, 0, + 6, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 9, 4, 2, 0, + 5, 0, 2, 3, 1, 0, 2, 0, 1, 0, 2, 3, 1, 4, 2, 0, 1, 0, 2, 3, 1, 0, 2, 0, 1, 0, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,}, {48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48,}, +};