From fb25e53b4f9a719f556b8d540f049237f64616c6 Mon Sep 17 00:00:00 2001 From: Moinak Ghosh Date: Sat, 30 Nov 2013 22:13:33 +0530 Subject: [PATCH] Add forked and optimized copy of LGPL version of Libbsc. Strip out Sort Transform from Libbsc copy. Reduce Libbsc memory use. Avoid redundant adler32 of data block in Libbsc. --- Makefile.in | 18 +- bsc/AUTHORS | 13 + bsc/CHANGES | 64 + bsc/COPYING | 674 +++++++++ bsc/COPYING.LIB | 165 ++ bsc/README | 145 ++ bsc/VERSION | 1 + bsc/bsc.cpp | 884 +++++++++++ bsc/libbsc/adler32/adler32.cpp | 85 ++ bsc/libbsc/adler32/adler32.h | 59 + bsc/libbsc/bwt/bwt.cpp | 404 +++++ bsc/libbsc/bwt/bwt.h | 73 + bsc/libbsc/bwt/divsufsort/divsufsort.c | 1907 ++++++++++++++++++++++++ bsc/libbsc/bwt/divsufsort/divsufsort.h | 67 + bsc/libbsc/coder/coder.cpp | 346 +++++ bsc/libbsc/coder/coder.h | 78 + bsc/libbsc/coder/common/predictor.h | 205 +++ bsc/libbsc/coder/common/rangecoder.h | 215 +++ bsc/libbsc/coder/common/tables.h | 1899 +++++++++++++++++++++++ bsc/libbsc/coder/qlfc/qlfc.cpp | 1363 +++++++++++++++++ bsc/libbsc/coder/qlfc/qlfc.h | 93 ++ bsc/libbsc/coder/qlfc/qlfc_model.cpp | 84 ++ bsc/libbsc/coder/qlfc/qlfc_model.h | 252 ++++ bsc/libbsc/filters.h | 111 ++ bsc/libbsc/filters/detectors.cpp | 587 ++++++++ bsc/libbsc/filters/preprocessing.cpp | 182 +++ bsc/libbsc/filters/tables.h | 756 ++++++++++ bsc/libbsc/libbsc.h | 165 ++ bsc/libbsc/libbsc/libbsc.cpp | 632 ++++++++ bsc/libbsc/lzp/lzp.cpp | 426 ++++++ bsc/libbsc/lzp/lzp.h | 74 + bsc/libbsc/platform/platform.cpp | 135 ++ bsc/libbsc/platform/platform.h | 108 ++ bsc/makefile | 111 ++ config | 21 +- libbsc_compress.c | 17 +- pcompress.h | 2 +- 37 files changed, 12401 insertions(+), 20 deletions(-) create mode 100644 bsc/AUTHORS create mode 100644 bsc/CHANGES create mode 100644 bsc/COPYING create mode 100644 bsc/COPYING.LIB create mode 100644 bsc/README create mode 100644 bsc/VERSION create mode 100644 bsc/bsc.cpp create mode 100644 bsc/libbsc/adler32/adler32.cpp create mode 100644 bsc/libbsc/adler32/adler32.h create mode 100644 bsc/libbsc/bwt/bwt.cpp create mode 100644 bsc/libbsc/bwt/bwt.h create mode 100644 bsc/libbsc/bwt/divsufsort/divsufsort.c create mode 100644 bsc/libbsc/bwt/divsufsort/divsufsort.h create mode 100644 bsc/libbsc/coder/coder.cpp create mode 100644 bsc/libbsc/coder/coder.h create mode 100644 bsc/libbsc/coder/common/predictor.h create mode 100644 bsc/libbsc/coder/common/rangecoder.h create mode 100644 bsc/libbsc/coder/common/tables.h create mode 100644 bsc/libbsc/coder/qlfc/qlfc.cpp create mode 100644 bsc/libbsc/coder/qlfc/qlfc.h create mode 100644 bsc/libbsc/coder/qlfc/qlfc_model.cpp create mode 100644 bsc/libbsc/coder/qlfc/qlfc_model.h create mode 100644 bsc/libbsc/filters.h create mode 100644 bsc/libbsc/filters/detectors.cpp create mode 100644 bsc/libbsc/filters/preprocessing.cpp create mode 100644 bsc/libbsc/filters/tables.h create mode 100644 bsc/libbsc/libbsc.h create mode 100644 bsc/libbsc/libbsc/libbsc.cpp create mode 100644 bsc/libbsc/lzp/lzp.cpp create mode 100644 bsc/libbsc/lzp/lzp.h create mode 100644 bsc/libbsc/platform/platform.cpp create mode 100644 bsc/libbsc/platform/platform.h create mode 100644 bsc/makefile diff --git a/Makefile.in b/Makefile.in index ac10df2..59e17c8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -323,10 +323,7 @@ $(KECCAK_OBJS): $(KECCAK_SRCS) $(KECCAK_HDRS) $(KECCAK_OBJS_ASM): $(KECCAK_SRCS_ASM) $(KECCAK_HDRS) $(COMPILE) $(KECCAK_FLAGS) $(@:.o=.s) -o $@ -$(LIBBSCLIB): - (cd $(LIBBSCDIR); make) - -$(LIBBSCWRAPOBJ): $(LIBBSCWRAP) $(LIBBSCLIB) +$(LIBBSCWRAPOBJ): $(LIBBSCWRAP) $(COMPILE) $(GEN_OPT) $(VEC_FLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@ $(TRANSP_OBJS): $(TRANSP_SRCS) $(TRANSP_HDRS) @@ -367,14 +364,18 @@ $(MAINOBJS): $(MAINSRCS) $(MAINHDRS) $(PROGOBJS): $(PROGSRCS) $(PROGHDRS) $(COMPILE) $(GEN_OPT) $(LOOP_OPTFLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@ -$(LIB): $(OBJS) +$(LIBBSCLIB): + (cd $(LIBBSCDIR); make) + +$(LIB): $(OBJS) $(LIBBSCLIB) $(LINK.LIB) -Wl,-soname,$(LIB).$(LIBVER) -o $(LIB).$(LIBVER) $(OBJS) $(LDLIBS) ln -sf $(LIB).$(LIBVER) $(LIB) -$(PROG): $(LIB) $(PROGOBJS) - $(LINK.PROG) -o $@ $(PROGOBJS) $(LDLIBS) -L. -l$(LINKLIB) +./buildtmp/$(PROG): mkdir -p buildtmp - cp $@ buildtmp + $(LINK.PROG) -o $@ $(PROGOBJS) $(LDLIBS) -L. -l$(LINKLIB) + +$(PROG): $(LIB) $(PROGOBJS) ./buildtmp/$(PROG) cat utils/pcompress.sh | sed "s##`pwd`#" > pcompress chmod +x pcompress @@ -389,6 +390,7 @@ clean: distclean: clean $(RM) Makefile + (cd $(LIBBSCDIR); make clean) install: $(PROG) @mkdir -p $(DESTDIR)$(PREFIX)/bin diff --git a/bsc/AUTHORS b/bsc/AUTHORS new file mode 100644 index 0000000..b69c408 --- /dev/null +++ b/bsc/AUTHORS @@ -0,0 +1,13 @@ +-- Authors of bsc and libbsc + + Ilya Grebnov + +-- This program is based on (at least) the work of + + Yuta Mori, Charles Bloom, Julian Seward, Mike Burrows, Matt Mahoney, + David Wheeler, Sebastian Deorowicz, Florin Ghido, Peter Fenwick, + Michael Schindler, Bulat Ziganshin, Eugene Shelwien, Yann Collet, + Dmitry Shkarin, Mark Adler, Przemyslaw Skibinski, Duane Merrill. + + + diff --git a/bsc/CHANGES b/bsc/CHANGES new file mode 100644 index 0000000..48875f1 --- /dev/null +++ b/bsc/CHANGES @@ -0,0 +1,64 @@ +Changes in 3.1.0 (July 8, 2012) +- Added Kepler GPU support with CUDA Toolkit 4.2 + +Changes in 3.0.0 (August 26, 2011) +- NVIDIA GPU acceleration of forward ST algorithms +- Added Sort Transform of order 7 & 8 (GPU only) + +Changes in 2.8.0 (August 8, 2011) +- Added parallel version of LZP algorithm +- Large RAM pages (2 MB) support for Windows +- Improved performance of ST and BWT algorithms + +Changes in 2.7.0 (June 5, 2011) +- Improved performance of LZP algorithm + +Changes in 2.6.1 (May 4, 2011) +- Fixed bug in segmentation algorithm + +Changes in 2.6.0 (April 30, 2011) +- Added Sort Transform of order 6 + +Changes in 2.5.0 (March 20, 2011) +- Some minor performance improvments +- CRC32 replaced with Adler32 + +Changes in 2.4.5 (January 3, 2011) +- Improved performance of reverse BWT and ST algorithms + +Changes in 2.4.0 (October 18, 2010) +- Improved performance of reverse BWT and ST algorithms + +Changes in 2.3.0 (August 9, 2010) +- Improved performance of QLFC algorithm + +Changes in 2.2.5 (July 5, 2010) +- Added parallel version of segmentation algorithm + +Changes in 2.2.0 (June 15, 2010) +- Added parallel version of reverse BWT transform +- Added parallel version of forward ST transform + +Changes in 2.1.5 (June 1, 2010) +- Improved multi-core systems support +- Improved segmentation algorithm + +Changes in 2.1.0 (May 17, 2010) +- Added GNU C++ compiler support +- Added makefile + +Changes in 2.0.0 (May 3, 2010) +- Released source code under LGPL license +- Added multi-core systems support +- Added fast "-f" compression mode +- Added Sort Transform of order 3 + +Changes in 1.0.3 (April 11, 2010) +- Fixed bug in block-sorting algorithm +- Added support for large files(>2Gb long) + +Changes in 1.0.1 (April 8, 2010) +- Decreased memory usage from 6 to 5 times per block size + +Changes in 1.0.0 (April 7, 2010) +- First public version for community technology preview diff --git a/bsc/COPYING b/bsc/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/bsc/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/bsc/COPYING.LIB b/bsc/COPYING.LIB new file mode 100644 index 0000000..fc8a5de --- /dev/null +++ b/bsc/COPYING.LIB @@ -0,0 +1,165 @@ + GNU LESSER 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. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser 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 +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/bsc/README b/bsc/README new file mode 100644 index 0000000..2eef0ec --- /dev/null +++ b/bsc/README @@ -0,0 +1,145 @@ +Introduction: +------------- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +bsc is a high performance file compressor based on lossless, +block-sorting data compression algorithms. + +libbsc is a library based on bsc, it uses the same algorithms +as bsc and enables you to compress memory blocks. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +See the bsc and libbsc web site: + http://libbsc.com/ for more information. + +Software License: +----------------- + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + + +Memory usage: +------------- + +bsc compresses large files in blocks. Multiple blocks can be processed in +parallel on multiple-core CPU. At decompression time, the block size used +for compression is read from the header of the compressed file. The block +size and number of blocks processed in parallel affects both the compression +ratio achieved, and the amount of memory needed for compression and decompression. +Compression and decompression requirements are the same and in bytes, can +be estimated as 16Mb + 5 x block size x number of blocks processed in parallel. + +GPU memory usage for NVIDIA CUDA technology is different from CPU memory usage +and can be estimated as 20 x block size. + + +NVIDIA GPU acceleration: +------------------------ + +1. libbsc uses NVIDIA CUDA technology, resulting in a performance boost on computers +with NVIDIA GPU of compute capability 1.1 or higher. Lists of supported GPUs +can be found on the NVIDIA website http://developer.nvidia.com/cuda-gpus. +You also need to install latest graphics drivers that support CUDA. + +2. Individual kernels are limited to a 2-second runtime by Windows. Kernels that run for +longer than 2 seconds will trigger the Timeout Detection and Recovery (TDR) mechanism. +Detailed information on disabling the Windows TDR is available at: +http://msdn.microsoft.com/en-us/windows/hardware/gg487368.aspx#E2 + + +Sort Transform: +--------------- + +Sort Transform is patented by Michael Schindler under US patent 6,199,064. +However for research purposes this algorithm is included in this software. +So if you are of the type who should worry about this (making money) worry away. +The author shall have no liability with respect to the infringement of +copyrights, trade secrets or any patents by this software. In no event will +the author be liable for any lost revenue or profits or other special, +indirect and consequential damages. + +Sort Transform is disabled by default and can be enabled by defining the +preprocessor macro LIBBSC_SORT_TRANSFORM_SUPPORT at compile time. + + +Back 40 Computing: +------------------ + +The Back 40 Computing project is a collection of fast, efficient GPU +primitives. This project implements a very fast, efficient radix sorting +method for CUDA-capable devices. libbsc uses the Back 40 Computing +primitives for constructing Sort Transform for CUDA-capable devices. + +The Back 40 Computing copyright is as follows: + +Copyright 2010-2011 Duane Merrill + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +See also the Back 40 Computing web site: + http://code.google.com/p/back40computing/ for more information. + + +libdivsufsort: +-------------- + +The libdivsufsort project provides a fast, lightweight, and robust +C API library to construct the suffix array and the Burrows-Wheeler +transformed string for any input string of a constant-size alphabet. +libbsc uses libdivsufsort for constructing Burrows-Wheeler transform. + +The libdivsufsort copyright is as follows: + +Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +See also the libdivsufsort web site: + http://libdivsufsort.googlecode.com/ for more information. diff --git a/bsc/VERSION b/bsc/VERSION new file mode 100644 index 0000000..a0cd9f0 --- /dev/null +++ b/bsc/VERSION @@ -0,0 +1 @@ +3.1.0 \ No newline at end of file diff --git a/bsc/bsc.cpp b/bsc/bsc.cpp new file mode 100644 index 0000000..665553e --- /dev/null +++ b/bsc/bsc.cpp @@ -0,0 +1,884 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Block Sorting Compressor */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +/*-- + +Sort Transform is patented by Michael Schindler under US patent 6,199,064. +However for research purposes this algorithm is included in this software. +So if you are of the type who should worry about this (making money) worry away. +The author shall have no liability with respect to the infringement of +copyrights, trade secrets or any patents by this software. In no event will +the author be liable for any lost revenue or profits or other special, +indirect and consequential damages. + +Sort Transform is disabled by default and can be enabled by defining the +preprocessor macro LIBBSC_SORT_TRANSFORM_SUPPORT at compile time. + +--*/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include +#include + +#include "libbsc/libbsc.h" +#include "libbsc/filters.h" +#include "libbsc/platform/platform.h" + +#pragma pack(push, 1) + +#define LIBBSC_CONTEXTS_AUTODETECT 3 + +unsigned char bscFileSign[4] = {'b', 's', 'c', 0x31}; + +typedef struct BSC_BLOCK_HEADER +{ + long long blockOffset; + signed char recordSize; + signed char sortingContexts; +} BSC_BLOCK_HEADER; + +#pragma pack(pop) + +int paramBlockSize = 25 * 1024 * 1024; +int paramBlockSorter = LIBBSC_BLOCKSORTER_BWT; +int paramCoder = LIBBSC_CODER_QLFC_STATIC; +int paramSortingContexts = LIBBSC_CONTEXTS_FOLLOWING; + +int paramEnableParallelProcessing = 1; +int paramEnableMultiThreading = 1; +int paramEnableFastMode = 1; +int paramEnableLargePages = 0; +int paramEnableCUDA = 0; +int paramEnableSegmentation = 0; +int paramEnableReordering = 0; +int paramEnableLZP = 1; +int paramLZPHashSize = 16; +int paramLZPMinLen = 128; + +int paramFeatures() +{ + int features = + (paramEnableFastMode ? LIBBSC_FEATURE_FASTMODE : LIBBSC_FEATURE_NONE) | + (paramEnableMultiThreading ? LIBBSC_FEATURE_MULTITHREADING : LIBBSC_FEATURE_NONE) | + (paramEnableLargePages ? LIBBSC_FEATURE_LARGEPAGES : LIBBSC_FEATURE_NONE) | + (paramEnableCUDA ? LIBBSC_FEATURE_CUDA : LIBBSC_FEATURE_NONE) + ; + + return features; +} + +#if defined(__GNUC__) && (defined(_GLIBCXX_USE_LFS) || defined(__MINGW32__)) + #define BSC_FSEEK fseeko64 + #define BSC_FTELL ftello64 + #define BSC_FILEOFFSET off64_t +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define BSC_FSEEK _fseeki64 + #define BSC_FTELL _ftelli64 + #define BSC_FILEOFFSET __int64 +#else + #define BSC_FSEEK fseek + #define BSC_FTELL ftell + #define BSC_FILEOFFSET long +#endif + +#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) || defined(_MSC_VER) + #include + double BSC_CLOCK() { return 0.001 * GetTickCount(); } +#elif defined (__unix) || defined (__linux__) || defined (__QNX__) || defined (_AIX) || defined (__NetBSD__) || defined(macintosh) || defined (_MAC) + #include + double BSC_CLOCK() { timeval tv; gettimeofday(&tv, 0); return tv.tv_sec + tv.tv_usec * 0.000001; } +#else + double BSC_CLOCK() { return (double)clock() / CLOCKS_PER_SEC; } +#endif + +int segmentedBlock[256]; + +void Compression(char * argv[]) +{ + if (!paramEnableLZP) + { + paramLZPHashSize = 0; + paramLZPMinLen = 0; + } + + FILE * fInput = fopen(argv[2], "rb"); + if (fInput == NULL) + { + fprintf(stderr, "Can't open input file: %s!\n", argv[2]); + exit(1); + } + + FILE * fOutput = fopen(argv[3], "wb"); + if (fOutput == NULL) + { + fprintf(stderr, "Can't create output file: %s!\n", argv[3]); + exit(1); + } + + if (BSC_FSEEK(fInput, 0, SEEK_END)) + { + fprintf(stderr, "IO error on file: %s!\n", argv[2]); + exit(1); + } + + BSC_FILEOFFSET fileSize = BSC_FTELL(fInput); + if (fileSize < 0) + { + fprintf(stderr, "IO error on file: %s!\n", argv[2]); + exit(1); + } + + if (BSC_FSEEK(fInput, 0, SEEK_SET)) + { + fprintf(stderr, "IO error on file: %s!\n", argv[2]); + exit(1); + } + + if (paramBlockSize > fileSize) + { + paramBlockSize = (int)fileSize; + } + + if (fwrite(bscFileSign, sizeof(bscFileSign), 1, fOutput) != 1) + { + fprintf(stderr, "IO error on file: %s!\n", argv[3]); + exit(1); + } + + int nBlocks = paramBlockSize > 0 ? (int)((fileSize + paramBlockSize - 1) / paramBlockSize) : 0; + if (fwrite(&nBlocks, sizeof(nBlocks), 1, fOutput) != 1) + { + fprintf(stderr, "IO error on file: %s!\n", argv[3]); + exit(1); + } + + double startTime = BSC_CLOCK(); + +#ifdef LIBBSC_OPENMP + + int numThreads = 1; + if (paramEnableParallelProcessing) + { + numThreads = omp_get_max_threads(); + if (numThreads <= nBlocks) paramEnableMultiThreading = 0; + if (numThreads >= nBlocks) numThreads = nBlocks; + } + +#endif + + int segmentationStart = 0, segmentationEnd = 0; + +#ifdef LIBBSC_OPENMP + #pragma omp parallel num_threads(numThreads) if(numThreads > 1) +#endif + { + unsigned char * buffer = (unsigned char *)bsc_malloc(paramBlockSize + LIBBSC_HEADER_SIZE); + if (buffer == NULL) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + + fprintf(stderr, "Not enough memory! Please check README file for more information.\n"); + exit(2); + } + } + + while (true) + { + BSC_FILEOFFSET blockOffset = 0; + int dataSize = 0; + +#ifdef LIBBSC_OPENMP + #pragma omp critical(input) +#endif + { + if ((feof(fInput) == 0) && (BSC_FTELL(fInput) != fileSize)) + { +#ifdef LIBBSC_OPENMP + #pragma omp master +#endif + { + double progress = (100.0 * (double)BSC_FTELL(fInput)) / fileSize; + fprintf(stdout, "\rCompressing %.55s(%02d%%)", argv[2], (int)progress); + fflush(stdout); + } + + blockOffset = BSC_FTELL(fInput); + + int currentBlockSize = paramBlockSize; + if (paramEnableSegmentation) + { + if (segmentationEnd - segmentationStart > 1) currentBlockSize = segmentedBlock[segmentationStart]; + } + + dataSize = (int)fread(buffer, 1, currentBlockSize, fInput); + if (dataSize <= 0) + { + fprintf(stderr, "\nIO error on file: %s!\n", argv[2]); + exit(1); + } + + if (paramEnableSegmentation) + { + bool bSegmentation = false; + + if (segmentationStart == segmentationEnd) bSegmentation = true; + if ((segmentationEnd - segmentationStart == 1) && (dataSize != segmentedBlock[segmentationStart])) bSegmentation = true; + + if (bSegmentation) + { + segmentationStart = 0; segmentationEnd = bsc_detect_segments(buffer, dataSize, segmentedBlock, 256, paramFeatures()); + if (segmentationEnd <= LIBBSC_NO_ERROR) + { + switch (segmentationEnd) + { + case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; + default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); + } + exit(2); + } + } + + int newDataSize = segmentedBlock[segmentationStart++]; + if (dataSize != newDataSize) + { + BSC_FILEOFFSET pos = BSC_FTELL(fInput) - dataSize + newDataSize; + BSC_FSEEK(fInput, pos, SEEK_SET); + dataSize = newDataSize; + } + } + } + } + + if (dataSize == 0) break; + + signed char recordSize = 1; + if (paramEnableReordering) + { + recordSize = bsc_detect_recordsize(buffer, dataSize, paramFeatures()); + if (recordSize < LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + switch (recordSize) + { + case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; + default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); + } + exit(2); + } + } + if (recordSize > 1) + { + int result = bsc_reorder_forward(buffer, dataSize, recordSize, paramFeatures()); + if (result != LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + switch (result) + { + case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; + default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); + } + exit(2); + } + } + } + } + + signed char sortingContexts = paramSortingContexts; + if (paramSortingContexts == LIBBSC_CONTEXTS_AUTODETECT) + { + sortingContexts = bsc_detect_contextsorder(buffer, dataSize, paramFeatures()); + if (sortingContexts < LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + switch (sortingContexts) + { + case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory!\n"); break; + default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); + } + exit(2); + } + } + } + if (sortingContexts == LIBBSC_CONTEXTS_PRECEDING) + { + int result = bsc_reverse_block(buffer, dataSize, paramFeatures()); + if (result != LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + fprintf(stderr, "\nInternal program error, please contact the author!\n"); + exit(2); + } + } + } + + int blockSize = bsc_compress(buffer, buffer, dataSize, paramLZPHashSize, paramLZPMinLen, paramBlockSorter, paramCoder, paramFeatures()); + if (blockSize == LIBBSC_NOT_COMPRESSIBLE) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(input) +#endif + { + sortingContexts = LIBBSC_CONTEXTS_FOLLOWING; recordSize = 1; + + BSC_FILEOFFSET pos = BSC_FTELL(fInput); + { + BSC_FSEEK(fInput, blockOffset, SEEK_SET); + if (dataSize != (int)fread(buffer, 1, dataSize, fInput)) + { + fprintf(stderr, "\nInternal program error, please contact the author!\n"); + exit(2); + } + } + BSC_FSEEK(fInput, pos, SEEK_SET); + } + + blockSize = bsc_store(buffer, buffer, dataSize, paramFeatures()); + } + if (blockSize < LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + switch (blockSize) + { + case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; + case LIBBSC_NOT_SUPPORTED : fprintf(stderr, "\nSpecified compression method is not supported on this platform!\n"); break; + case LIBBSC_GPU_ERROR : fprintf(stderr, "\nGeneral GPU failure! Please check README file for more information.\n"); break; + case LIBBSC_GPU_NOT_SUPPORTED : fprintf(stderr, "\nYour GPU is not supported! Please check README file for more information.\n"); break; + case LIBBSC_GPU_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough GPU memory! Please check README file for more information.\n"); break; + + default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); + } + exit(2); + } + } + +#ifdef LIBBSC_OPENMP + #pragma omp critical(output) +#endif + { + BSC_BLOCK_HEADER header = {blockOffset, recordSize, sortingContexts}; + + if (fwrite(&header, sizeof(BSC_BLOCK_HEADER), 1, fOutput) != 1) + { + fprintf(stderr, "\nIO error on file: %s!\n", argv[3]); + exit(1); + } + + if ((int)fwrite(buffer, 1, blockSize, fOutput) != blockSize) + { + fprintf(stderr, "\nIO error on file: %s!\n", argv[3]); + exit(1); + } + } + + } + + bsc_free(buffer); + } + + fprintf(stdout, "\r%.55s compressed %.0f into %.0f in %.3f seconds.\n", argv[2], (double)fileSize, (double)BSC_FTELL(fOutput), BSC_CLOCK() - startTime); + + fclose(fInput); fclose(fOutput); +} + +void Decompression(char * argv[]) +{ + FILE * fInput = fopen(argv[2], "rb"); + if (fInput == NULL) + { + fprintf(stderr, "Can't open input file: %s!\n", argv[2]); + exit(1); + } + + FILE * fOutput = fopen(argv[3], "wb"); + if (fOutput == NULL) + { + fprintf(stderr, "Can't create output file: %s!\n", argv[3]); + exit(1); + } + + if (BSC_FSEEK(fInput, 0, SEEK_END)) + { + fprintf(stderr, "IO error on file: %s!\n", argv[2]); + exit(1); + } + + BSC_FILEOFFSET fileSize = BSC_FTELL(fInput); + if (fileSize < 0) + { + fprintf(stderr, "IO error on file: %s!\n", argv[2]); + exit(1); + } + + if (BSC_FSEEK(fInput, 0, SEEK_SET)) + { + fprintf(stderr, "IO error on file: %s!\n", argv[2]); + exit(1); + } + + unsigned char inputFileSign[sizeof(bscFileSign)]; + + if (fread(inputFileSign, sizeof(bscFileSign), 1, fInput) != 1) + { + fprintf(stderr, "This is not bsc archive!\n"); + exit(1); + } + + if (memcmp(inputFileSign, bscFileSign, sizeof(bscFileSign)) != 0) + { + fprintf(stderr, "This is not bsc archive or invalid compression method!\n"); + exit(2); + } + + int nBlocks = 0; + if (fread(&nBlocks, sizeof(nBlocks), 1, fInput) != 1) + { + fprintf(stderr, "This is not bsc archive!\n"); + exit(1); + } + + double startTime = BSC_CLOCK(); + +#ifdef LIBBSC_OPENMP + + int numThreads = 1; + if (paramEnableParallelProcessing) + { + numThreads = omp_get_max_threads(); + if (numThreads <= nBlocks) paramEnableMultiThreading = 0; + if (numThreads >= nBlocks) numThreads = nBlocks; + } + + #pragma omp parallel num_threads(numThreads) if(numThreads > 1) +#endif + { + int bufferSize = -1; unsigned char * buffer = NULL; + + while (true) + { + BSC_FILEOFFSET blockOffset = 0; + + signed char sortingContexts = 0; + signed char recordSize = 0; + int blockSize = 0; + int dataSize = 0; + +#ifdef LIBBSC_OPENMP + #pragma omp critical(input) +#endif + { + if ((feof(fInput) == 0) && (BSC_FTELL(fInput) != fileSize)) + { +#ifdef LIBBSC_OPENMP + #pragma omp master +#endif + { + double progress = (100.0 * (double)BSC_FTELL(fInput)) / fileSize; + fprintf(stdout, "\rDecompressing %.55s(%02d%%)", argv[2], (int)progress); + fflush(stdout); + } + + BSC_BLOCK_HEADER header = {0, 0, 0}; + if (fread(&header, sizeof(BSC_BLOCK_HEADER), 1, fInput) != 1) + { + fprintf(stderr, "\nUnexpected end of file: %s!\n", argv[2]); + exit(1); + } + + recordSize = header.recordSize; + if (recordSize < 1) + { + fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); + exit(2); + } + + sortingContexts = header.sortingContexts; + if ((sortingContexts != LIBBSC_CONTEXTS_FOLLOWING) && (sortingContexts != LIBBSC_CONTEXTS_PRECEDING)) + { + fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); + exit(2); + } + + blockOffset = (BSC_FILEOFFSET)header.blockOffset; + + unsigned char bscBlockHeader[LIBBSC_HEADER_SIZE]; + + if (fread(bscBlockHeader, LIBBSC_HEADER_SIZE, 1, fInput) != 1) + { + fprintf(stderr, "\nUnexpected end of file: %s!\n", argv[2]); + exit(1); + } + + if (bsc_block_info(bscBlockHeader, LIBBSC_HEADER_SIZE, &blockSize, &dataSize, paramFeatures()) != LIBBSC_NO_ERROR) + { + fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); + exit(2); + } + + if ((blockSize > bufferSize) || (dataSize > bufferSize)) + { + if (blockSize > bufferSize) bufferSize = blockSize; + if (dataSize > bufferSize) bufferSize = dataSize; + + if (buffer != NULL) bsc_free(buffer); buffer = (unsigned char *)bsc_malloc(bufferSize); + } + + if (buffer == NULL) + { + fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); + exit(2); + } + + memcpy(buffer, bscBlockHeader, LIBBSC_HEADER_SIZE); + + if (fread(buffer + LIBBSC_HEADER_SIZE, blockSize - LIBBSC_HEADER_SIZE, 1, fInput) != 1) + { + fprintf(stderr, "\nUnexpected end of file: %s!\n", argv[2]); + exit(1); + } + } + } + + if (dataSize == 0) break; + + int result = bsc_decompress(buffer, blockSize, buffer, dataSize, paramFeatures()); + if (result < LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + switch (result) + { + case LIBBSC_DATA_CORRUPT : fprintf(stderr, "\nThe compressed data is corrupted!\n"); break; + case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; + case LIBBSC_GPU_ERROR : fprintf(stderr, "\nGeneral GPU failure! Please check README file for more information.\n"); break; + case LIBBSC_GPU_NOT_SUPPORTED : fprintf(stderr, "\nYour GPU is not supported! Please check README file for more information.\n"); break; + case LIBBSC_GPU_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough GPU memory! Please check README file for more information.\n"); break; + + default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); + } + exit(2); + } + } + + if (sortingContexts == LIBBSC_CONTEXTS_PRECEDING) + { + result = bsc_reverse_block(buffer, dataSize, paramFeatures()); + if (result != LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + fprintf(stderr, "\nInternal program error, please contact the author!\n"); + exit(2); + } + } + } + + if (recordSize > 1) + { + result = bsc_reorder_reverse(buffer, dataSize, recordSize, paramFeatures()); + if (result != LIBBSC_NO_ERROR) + { +#ifdef LIBBSC_OPENMP + #pragma omp critical(print) +#endif + { + switch (result) + { + case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; + default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); + } + exit(2); + } + } + } + +#ifdef LIBBSC_OPENMP + #pragma omp critical(output) +#endif + { + if (BSC_FSEEK(fOutput, blockOffset, SEEK_SET)) + { + fprintf(stderr, "\nIO error on file: %s!\n", argv[3]); + exit(1); + } + + if ((int)fwrite(buffer, 1, dataSize, fOutput) != dataSize) + { + fprintf(stderr, "\nIO error on file: %s!\n", argv[3]); + exit(1); + } + } + } + + if (buffer != NULL) bsc_free(buffer); + } + + if (BSC_FSEEK(fOutput, 0, SEEK_END)) + { + fprintf(stderr, "IO error on file: %s!\n", argv[3]); + exit(1); + } + + fprintf(stdout, "\r%.55s decompressed %.0f into %.0f in %.3f seconds.\n", argv[2], (double)fileSize, (double)BSC_FTELL(fOutput), BSC_CLOCK() - startTime); + + fclose(fInput); fclose(fOutput); +} + +void ShowUsage(void) +{ + fprintf(stdout, "Usage: bsc inputfile outputfile \n\n"); + + fprintf(stdout, "Block sorting options:\n"); + fprintf(stdout, " -b Block size in megabytes, default: -b25\n"); + fprintf(stdout, " minimum: -b1, maximum: -b1024\n"); + fprintf(stdout, " -m Block sorting algorithm, default: -m0\n"); + fprintf(stdout, " -m0 Burrows Wheeler Transform (default)\n"); +#ifdef LIBBSC_SORT_TRANSFORM_SUPPORT + fprintf(stdout, " -m3..8 Sort Transform of order n\n"); +#endif + fprintf(stdout, " -c Contexts for sorting, default: -cf\n"); + fprintf(stdout, " -cf Following contexts (default)\n"); + fprintf(stdout, " -cp Preceding contexts\n"); + fprintf(stdout, " -ca Autodetect (experimental)\n"); + fprintf(stdout, " -e Entropy encoding algorithm, default: -e1\n"); + fprintf(stdout, " -e1 Static Quantized Local Frequency Coding (default)\n"); + fprintf(stdout, " -e2 Adaptive Quantized Local Frequency Coding (best compression)\n"); + + fprintf(stdout, "\nPreprocessing options:\n"); + fprintf(stdout, " -p Disable all preprocessing techniques\n"); + fprintf(stdout, " -s Enable segmentation (adaptive block size), default: disable\n"); + fprintf(stdout, " -r Enable structured data reordering, default: disable\n"); + fprintf(stdout, " -l Enable Lempel-Ziv preprocessing, default: enable\n"); + fprintf(stdout, " -H LZP dictionary size in bits, default: -H16\n"); + fprintf(stdout, " minimum: -H10, maximum: -H28\n"); + fprintf(stdout, " -M LZP minimum match length, default: -M128\n"); + fprintf(stdout, " minimum: -M4, maximum: -M255\n"); + + fprintf(stdout, "\nPlatform specific options:\n"); +#ifdef LIBBSC_CUDA_SUPPORT + fprintf(stdout, " -G Enable Sort Transform acceleration on NVIDIA GPU, default: disable\n"); +#endif +#ifdef _WIN32 + fprintf(stdout, " -P Enable large 2MB RAM pages, default: disable\n"); +#endif +#ifdef LIBBSC_OPENMP + fprintf(stdout, " -t Disable parallel blocks processing, default: enable\n"); + fprintf(stdout, " -T Disable multi-core systems support, default: enable\n"); +#endif + + fprintf(stdout,"\nOptions may be combined into one, like -b128p -m5e1\n"); + exit(0); +} + +void ProcessSwitch(char * s) +{ + if (*s == 0) + { + ShowUsage(); + } + + for (; *s != 0; ) + { + switch (*s++) + { + case 'b': + { + char * strNum = s; while ((*s >= '0') && (*s <= '9')) s++; + paramBlockSize = atoi(strNum) * 1024 * 1024; + if ((paramBlockSize < 1024 * 1024) || (paramBlockSize > 1024 * 1024 * 1024)) ShowUsage(); + break; + } + + case 'm': + { + char * strNum = s; while ((*s >= '0') && (*s <= '9')) s++; + switch (atoi(strNum)) + { + case 0 : paramBlockSorter = LIBBSC_BLOCKSORTER_BWT; break; + +#ifdef LIBBSC_SORT_TRANSFORM_SUPPORT + case 3 : paramBlockSorter = LIBBSC_BLOCKSORTER_ST3; break; + case 4 : paramBlockSorter = LIBBSC_BLOCKSORTER_ST4; break; + case 5 : paramBlockSorter = LIBBSC_BLOCKSORTER_ST5; break; + case 6 : paramBlockSorter = LIBBSC_BLOCKSORTER_ST6; break; + case 7 : paramBlockSorter = LIBBSC_BLOCKSORTER_ST7; paramEnableCUDA = 1; break; + case 8 : paramBlockSorter = LIBBSC_BLOCKSORTER_ST8; paramEnableCUDA = 1; break; +#endif + + default : ShowUsage(); + } + break; + } + + case 'c': + { + switch (*s++) + { + case 'f' : paramSortingContexts = LIBBSC_CONTEXTS_FOLLOWING; break; + case 'p' : paramSortingContexts = LIBBSC_CONTEXTS_PRECEDING; break; + case 'a' : paramSortingContexts = LIBBSC_CONTEXTS_AUTODETECT; break; + default : ShowUsage(); + } + break; + } + + case 'e': + { + switch (*s++) + { + case '1' : paramCoder = LIBBSC_CODER_QLFC_STATIC; break; + case '2' : paramCoder = LIBBSC_CODER_QLFC_ADAPTIVE; break; + default : ShowUsage(); + } + break; + } + + case 'H': + { + char * strNum = s; while ((*s >= '0') && (*s <= '9')) s++; + paramLZPHashSize = atoi(strNum); + if ((paramLZPHashSize < 10) || (paramLZPHashSize > 28)) ShowUsage(); + break; + } + + case 'M': + { + char * strNum = s; while ((*s >= '0') && (*s <= '9')) s++; + paramLZPMinLen = atoi(strNum); + if ((paramLZPMinLen < 4) || (paramLZPMinLen > 255)) ShowUsage(); + break; + } + + case 'l': paramEnableLZP = 1; break; + case 's': paramEnableSegmentation = 1; break; + case 'r': paramEnableReordering = 1; break; + + case 'p': paramEnableLZP = paramEnableSegmentation = paramEnableReordering = 0; break; + +#ifdef LIBBSC_OPENMP + case 't': paramEnableParallelProcessing = 0; break; + case 'T': paramEnableParallelProcessing = paramEnableMultiThreading = 0; break; +#endif + +#ifdef LIBBSC_CUDA_SUPPORT + case 'G': paramEnableCUDA = 1; break; +#endif + +#ifdef _WIN32 + case 'P': paramEnableLargePages = 1; break; +#endif + + default : ShowUsage(); + } + } +} + +void ProcessCommandline(int argc, char * argv[]) +{ + if (argc < 4 || strlen(argv[1]) != 1) + { + ShowUsage(); + } + + for (int i = 4; i < argc; ++i) + { + if (argv[i][0] == '-') + { + ProcessSwitch(&argv[i][1]); + } + else + { + ShowUsage(); + } + } +} + +int main(int argc, char * argv[]) +{ + fprintf(stdout, "This is bsc, Block Sorting Compressor. Version 3.1.0. 8 July 2012.\n"); + fprintf(stdout, "Copyright (c) 2009-2012 Ilya Grebnov .\n\n"); + +#if defined(_OPENMP) && defined(__INTEL_COMPILER) + + kmp_set_warnings_off(); + +#endif + + ProcessCommandline(argc, argv); + + if (bsc_init(paramFeatures()) != LIBBSC_NO_ERROR) + { + fprintf(stderr, "\nInternal program error, please contact the author!\n"); + exit(2); + } + + switch (*argv[1]) + { + case 'e' : case 'E' : Compression(argv); break; + case 'd' : case 'D' : Decompression(argv); break; + default : ShowUsage(); + } + + return 0; +} + +/*-----------------------------------------------------------*/ +/* End bsc.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/adler32/adler32.cpp b/bsc/libbsc/adler32/adler32.cpp new file mode 100644 index 0000000..1cac326 --- /dev/null +++ b/bsc/libbsc/adler32/adler32.cpp @@ -0,0 +1,85 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Adler-32 checksum functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include +#include + +#include "adler32.h" + +#include "../platform/platform.h" +#include "../libbsc.h" + +#define BASE 65521UL +#define NMAX 5552 + +#define DO1(buf, i) { sum1 += (buf)[i]; sum2 += sum1; } +#define DO2(buf, i) DO1(buf, i); DO1(buf, i + 1); +#define DO4(buf, i) DO2(buf, i); DO2(buf, i + 2); +#define DO8(buf, i) DO4(buf, i); DO4(buf, i + 4); +#define DO16(buf) DO8(buf, 0); DO8(buf, 8); +#define MOD(a) a %= BASE + +unsigned int bsc_adler32(const unsigned char * T, int n, int features) +{ + unsigned int sum1 = 1; + unsigned int sum2 = 0; + + while (n >= NMAX) + { + for (int i = 0; i < NMAX / 16; ++i) + { + DO16(T); T += 16; + } + MOD(sum1); MOD(sum2); n -= NMAX; + } + + while (n >= 16) + { + DO16(T); T += 16; n -= 16; + } + + while (n > 0) + { + DO1(T, 0); T += 1; n -= 1; + } + + MOD(sum1); MOD(sum2); + + return sum1 | (sum2 << 16); +} + +/*-----------------------------------------------------------*/ +/* End adler32.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/adler32/adler32.h b/bsc/libbsc/adler32/adler32.h new file mode 100644 index 0000000..ee21400 --- /dev/null +++ b/bsc/libbsc/adler32/adler32.h @@ -0,0 +1,59 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to Adler-32 checksum functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_ADLER32_H +#define _LIBBSC_ADLER32_H + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Calculates Adler-32 checksum for input memory block. + * @param T - the input memory block of n bytes. + * @param n - the length of the input memory block. + * @param features - the set of additional features. + * @return the value of cyclic redundancy check. + */ + unsigned int bsc_adler32(const unsigned char * T, int n, int features); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-----------------------------------------------------------*/ +/* End adler32.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/bwt/bwt.cpp b/bsc/libbsc/bwt/bwt.cpp new file mode 100644 index 0000000..28e4dea --- /dev/null +++ b/bsc/libbsc/bwt/bwt.cpp @@ -0,0 +1,404 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Burrows Wheeler Transform */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include + +#include "bwt.h" + +#include "../platform/platform.h" +#include "../libbsc.h" + +#include "divsufsort/divsufsort.h" + +int bsc_bwt_encode(unsigned char * T, int n, unsigned char * num_indexes, int * indexes, int features) +{ + int index = divbwt(T, T, NULL, n, num_indexes, indexes, features & LIBBSC_FEATURE_MULTITHREADING); + switch (index) + { + case -1 : return LIBBSC_BAD_PARAMETER; + case -2 : return LIBBSC_NOT_ENOUGH_MEMORY; + } + return index; +} + +static int bsc_unbwt_mergedTL_serial(unsigned char * RESTRICT T, unsigned int * RESTRICT P, int n, int index) +{ + unsigned int bucket[ALPHABET_SIZE]; + + memset(bucket, 0, ALPHABET_SIZE * sizeof(unsigned int)); + + for (int i = 0; i < index; ++i) + { + unsigned char c = T[i]; + P[i] = ((bucket[c]++) << 8) | c; + } + for (int i = index; i < n; ++i) + { + unsigned char c = T[i]; + P[i + 1] = ((bucket[c]++) << 8) | c; + } + + for (int sum = 1, i = 0; i < ALPHABET_SIZE; ++i) + { + int tmp = sum; sum += bucket[i]; bucket[i] = tmp; + } + + for (int p = 0, i = n - 1; i >= 0; --i) + { + unsigned int u = P[p]; + unsigned char c = u & 0xff; + T[i] = c; p = (u >> 8) + bucket[c]; + } + + return LIBBSC_NO_ERROR; +} + +#define BWT_NUM_FASTBITS (17) + +static int bsc_unbwt_biPSI_serial(unsigned char * RESTRICT T, unsigned int * RESTRICT P, int n, int index) +{ + if (int * RESTRICT bucket = (int *)bsc_zero_malloc(ALPHABET_SIZE * ALPHABET_SIZE * sizeof(int))) + { + if (unsigned short * RESTRICT fastbits = (unsigned short *)bsc_malloc((1 + (1 << BWT_NUM_FASTBITS)) * sizeof(unsigned short))) + { + int count[ALPHABET_SIZE]; memset(count, 0, ALPHABET_SIZE * sizeof(int)); + + int shift = 0; while ((n >> shift) > (1 << BWT_NUM_FASTBITS)) shift++; + + for (int i = 0; i < n; ++i) count[T[i]]++; + + for (int sum = 1, c = 0; c < ALPHABET_SIZE; ++c) + { + int tmp = sum; sum += count[c]; count[c] = tmp; + if (count[c] != sum) + { + int * RESTRICT bucket_p = &bucket[c << 8]; + + int hi = index; if (sum < hi) hi = sum; + for (int i = count[c]; i < hi; ++i) bucket_p[T[i]]++; + + int lo = index + 1; if (count[c] > lo) lo = count[c]; + for (int i = lo; i < sum; ++i) bucket_p[T[i - 1]]++; + } + } + + int lastc = T[0]; + for (int v = 0, sum = 1, c = 0; c < ALPHABET_SIZE; ++c) + { + if (c == lastc) sum++; + + int * RESTRICT bucket_p = &bucket[c]; + for (int d = 0; d < ALPHABET_SIZE; ++d) + { + int tmp = sum; sum += bucket_p[d << 8]; bucket_p[d << 8] = tmp; + if (bucket_p[d << 8] != sum) + { + for (; v <= ((sum - 1) >> shift); ++v) fastbits[v] = (c << 8) | d; + } + } + } + + for (int i = 0; i < index; ++i) + { + unsigned char c = T[i]; + int p = count[c]++; + + if (p < index) P[bucket[(c << 8) | T[p ]]++] = i; else + if (p > index) P[bucket[(c << 8) | T[p - 1]]++] = i; + } + + for (int i = index; i < n; ++i) + { + unsigned char c = T[i]; + int p = count[c]++; + + if (p < index) P[bucket[(c << 8) | T[p ]]++] = i + 1; else + if (p > index) P[bucket[(c << 8) | T[p - 1]]++] = i + 1; + } + + for (int c = 0; c < ALPHABET_SIZE; ++c) + { + for (int d = 0; d < c; ++d) + { + int tmp = bucket[(d << 8) | c]; bucket[(d << 8) | c] = bucket[(c << 8) | d]; bucket[(c << 8) | d] = tmp; + } + } + + for (int p = index, i = 1; i < n; i += 2) + { + int c = fastbits[p >> shift]; while (bucket[c] <= p) c++; + T[i - 1] = (unsigned char)(c >> 8); T[i] = (unsigned char)(c & 0xff); + p = P[p]; + } + + T[n - 1] = (unsigned char)lastc; + + bsc_free(fastbits); bsc_free(bucket); + return LIBBSC_NO_ERROR; + } + bsc_free(bucket); + }; + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +static int bsc_unbwt_reconstruct_serial(unsigned char * T, unsigned int * P, int n, int index) +{ + if (n < 3 * 1024 * 1024) return bsc_unbwt_mergedTL_serial(T, P, n, index); + return bsc_unbwt_biPSI_serial(T, P, n, index); +} + +#ifdef LIBBSC_OPENMP + +static int bsc_unbwt_mergedTL_parallel(unsigned char * RESTRICT T, unsigned int * RESTRICT P, int n, int index, int * RESTRICT indexes) +{ + unsigned int bucket[ALPHABET_SIZE]; + + memset(bucket, 0, ALPHABET_SIZE * sizeof(unsigned int)); + + for (int i = 0; i < index; ++i) + { + unsigned char c = T[i]; + P[i] = ((bucket[c]++) << 8) | c; + } + for (int i = index; i < n; ++i) + { + unsigned char c = T[i]; + P[i + 1] = ((bucket[c]++) << 8) | c; + } + + for (int sum = 1, i = 0; i < ALPHABET_SIZE; ++i) + { + int tmp = sum; sum += bucket[i]; bucket[i] = tmp; + } + + int mod = n / 8; + { + mod |= mod >> 1; mod |= mod >> 2; + mod |= mod >> 4; mod |= mod >> 8; + mod |= mod >> 16; mod >>= 1; mod++; + } + + int nBlocks = 1 + (n - 1) / mod; + + #pragma omp parallel for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int p = (blockId < nBlocks - 1) ? indexes[blockId] + 1 : 0; + int blockStart = (blockId < nBlocks - 1) ? mod * blockId + mod - 1 : n - 1; + int blockEnd = mod * blockId; + + for (int i = blockStart; i >= blockEnd; --i) + { + unsigned int u = P[p]; + unsigned char c = u & 0xff; + T[i] = c; p = (u >> 8) + bucket[c]; + } + } + + return LIBBSC_NO_ERROR; +} + +static int bsc_unbwt_biPSI_parallel(unsigned char * RESTRICT T, unsigned int * RESTRICT P, int n, int index, int * RESTRICT indexes) +{ + if (int * RESTRICT bucket = (int *)bsc_zero_malloc(ALPHABET_SIZE * ALPHABET_SIZE * sizeof(int))) + { + if (unsigned short * RESTRICT fastbits = (unsigned short *)bsc_malloc((1 + (1 << BWT_NUM_FASTBITS)) * sizeof(unsigned short))) + { + int count[ALPHABET_SIZE]; memset(count, 0, ALPHABET_SIZE * sizeof(int)); + + int shift = 0; while ((n >> shift) > (1 << BWT_NUM_FASTBITS)) shift++; + + #pragma omp parallel + { + unsigned int count_local[ALPHABET_SIZE]; + + memset(count_local, 0, ALPHABET_SIZE * sizeof(unsigned int)); + + #pragma omp for schedule(static) nowait + for (int i = 0; i < n; ++i) count_local[T[i]]++; + + #pragma omp critical + for (int c = 0; c < ALPHABET_SIZE; ++c) count[c] += count_local[c]; + } + + for (int sum = 1, c = 0; c < ALPHABET_SIZE; ++c) + { + int tmp = sum; sum += count[c]; count[c] = tmp; + } + + #pragma omp parallel for schedule(static, 1) + for (int c = 0; c < ALPHABET_SIZE; ++c) + { + int start = count[c], end = (c + 1 < ALPHABET_SIZE) ? count[c + 1] : n + 1; + if (start != end) + { + int * RESTRICT bucket_p = &bucket[c << 8]; + + int hi = index; if (end < hi) hi = end; + for (int i = start; i < hi; ++i) bucket_p[T[i]]++; + + int lo = index + 1; if (start > lo) lo = start; + for (int i = lo; i < end; ++i) bucket_p[T[i - 1]]++; + } + } + + int lastc = T[0]; + for (int v = 0, sum = 1, c = 0; c < ALPHABET_SIZE; ++c) + { + if (c == lastc) sum++; + + int * RESTRICT bucket_p = &bucket[c]; + for (int d = 0; d < ALPHABET_SIZE; ++d) + { + int tmp = sum; sum += bucket_p[d << 8]; bucket_p[d << 8] = tmp; + if (bucket_p[d << 8] != sum) + { + for (; v <= ((sum - 1) >> shift); ++v) fastbits[v] = (c << 8) | d; + } + } + } + + for (int i = 0; i < index; ++i) + { + unsigned char c = T[i]; + int p = count[c]++; + + if (p < index) P[bucket[(c << 8) | T[p ]]++] = i; else + if (p > index) P[bucket[(c << 8) | T[p - 1]]++] = i; + } + + for (int i = index; i < n; ++i) + { + unsigned char c = T[i]; + int p = count[c]++; + + if (p < index) P[bucket[(c << 8) | T[p ]]++] = i + 1; else + if (p > index) P[bucket[(c << 8) | T[p - 1]]++] = i + 1; + } + + for (int c = 0; c < ALPHABET_SIZE; ++c) + { + for (int d = 0; d < c; ++d) + { + int tmp = bucket[(d << 8) | c]; bucket[(d << 8) | c] = bucket[(c << 8) | d]; bucket[(c << 8) | d] = tmp; + } + } + + int mod = n / 8; + { + mod |= mod >> 1; mod |= mod >> 2; + mod |= mod >> 4; mod |= mod >> 8; + mod |= mod >> 16; mod >>= 1; mod++; + } + + int nBlocks = 1 + (n - 1) / mod; + + #pragma omp parallel for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int p = (blockId > 0 ) ? indexes[blockId - 1] + 1 : index; + int blockEnd = (blockId < nBlocks - 1) ? mod * blockId + mod : n; + int blockStart = mod * blockId; + + if (blockEnd != n) blockEnd++; else T[n - 1] = (unsigned char)lastc; + + for (int i = blockStart + 1; i < blockEnd; i += 2) + { + int c = fastbits[p >> shift]; while (bucket[c] <= p) c++; + T[i - 1] = (unsigned char)(c >> 8); T[i] = (unsigned char)(c & 0xff); + p = P[p]; + } + } + + bsc_free(fastbits); bsc_free(bucket); + return LIBBSC_NO_ERROR; + } + bsc_free(bucket); + }; + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +static int bsc_unbwt_reconstruct_parallel(unsigned char * T, unsigned int * P, int n, int index, int * indexes) +{ + if (n < 3 * 1024 * 1024) return bsc_unbwt_mergedTL_parallel(T, P, n, index, indexes); + return bsc_unbwt_biPSI_parallel(T, P, n, index, indexes); +} + +#endif + +int bsc_bwt_decode(unsigned char * T, int n, int index, unsigned char num_indexes, int * indexes, int features) +{ + if ((T == NULL) || (n < 0) || (index <= 0) || (index > n)) + { + return LIBBSC_BAD_PARAMETER; + } + if (n <= 1) + { + return LIBBSC_NO_ERROR; + } + if (unsigned int * P = (unsigned int *)bsc_malloc((n + 1) * sizeof(unsigned int))) + { + int result = LIBBSC_NO_ERROR; + +#ifdef LIBBSC_OPENMP + + int mod = n / 8; + { + mod |= mod >> 1; mod |= mod >> 2; + mod |= mod >> 4; mod |= mod >> 8; + mod |= mod >> 16; mod >>= 1; + } + + if ((features & LIBBSC_FEATURE_MULTITHREADING) && (n >= 64 * 1024) && (num_indexes == (unsigned char)((n - 1) / (mod + 1))) && (indexes != NULL)) + { + result = bsc_unbwt_reconstruct_parallel(T, P, n, index, indexes); + } + else + +#endif + + { + result = bsc_unbwt_reconstruct_serial(T, P, n, index); + } + + bsc_free(P); + return result; + }; + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +/*-----------------------------------------------------------*/ +/* End bwt.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/bwt/bwt.h b/bsc/libbsc/bwt/bwt.h new file mode 100644 index 0000000..7161bba --- /dev/null +++ b/bsc/libbsc/bwt/bwt.h @@ -0,0 +1,73 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to Burrows Wheeler Transform */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_BWT_H +#define _LIBBSC_BWT_H + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Constructs the burrows wheeler transformed string of a given string. + * @param T - the input/output string of n chars. + * @param n - the length of the given string. + * @param num_indexes - the length of secondary indexes array, can be NULL. + * @param indexes - the secondary indexes array, can be NULL. + * @param features - the set of additional features. + * @return the primary index if no error occurred, error code otherwise. + */ + int bsc_bwt_encode(unsigned char * T, int n, unsigned char * num_indexes, int * indexes, int features); + + /** + * Reconstructs the original string from burrows wheeler transformed string. + * @param T - the input/output string of n chars. + * @param n - the length of the given string. + * @param index - the primary index. + * @param num_indexes - the length of secondary indexes array, can be 0. + * @param indexes - the secondary indexes array, can be NULL. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_bwt_decode(unsigned char * T, int n, int index, unsigned char num_indexes, int * indexes, int features); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-----------------------------------------------------------*/ +/* End bwt.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/bwt/divsufsort/divsufsort.c b/bsc/libbsc/bwt/divsufsort/divsufsort.c new file mode 100644 index 0000000..2277de7 --- /dev/null +++ b/bsc/libbsc/bwt/divsufsort/divsufsort.c @@ -0,0 +1,1907 @@ +/* + * divsufsort.c for libdivsufsort-lite + * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#if defined(_MSC_VER) + #pragma warning(disable : 4244) +#endif + +#include +#include +#include + +#include "divsufsort.h" + +#include "../../platform/platform.h" +#include "../../libbsc.h" + +/*- Constants -*/ +#if defined(INLINE) +# undef INLINE +#endif +#if !defined(INLINE) +# define INLINE __inline +#endif +#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1) +# undef ALPHABET_SIZE +#endif +#if !defined(ALPHABET_SIZE) +# define ALPHABET_SIZE (256) +#endif +#define BUCKET_A_SIZE (ALPHABET_SIZE) +#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE) +#if defined(SS_INSERTIONSORT_THRESHOLD) +# if SS_INSERTIONSORT_THRESHOLD < 1 +# undef SS_INSERTIONSORT_THRESHOLD +# define SS_INSERTIONSORT_THRESHOLD (1) +# endif +#else +# define SS_INSERTIONSORT_THRESHOLD (8) +#endif +#if defined(SS_BLOCKSIZE) +# if SS_BLOCKSIZE < 0 +# undef SS_BLOCKSIZE +# define SS_BLOCKSIZE (0) +# elif 32768 <= SS_BLOCKSIZE +# undef SS_BLOCKSIZE +# define SS_BLOCKSIZE (32767) +# endif +#else +# define SS_BLOCKSIZE (1024) +#endif +/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */ +#if SS_BLOCKSIZE == 0 +# define SS_MISORT_STACKSIZE (96) +#elif SS_BLOCKSIZE <= 4096 +# define SS_MISORT_STACKSIZE (16) +#else +# define SS_MISORT_STACKSIZE (24) +#endif +#define SS_SMERGE_STACKSIZE (32) +#define TR_INSERTIONSORT_THRESHOLD (8) +#define TR_STACKSIZE (64) + + +/*- Macros -*/ +#ifndef SWAP +# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0) +#endif /* SWAP */ +#ifndef MIN +# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +#endif /* MIN */ +#ifndef MAX +# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) +#endif /* MAX */ +#define STACK_PUSH(_a, _b, _c, _d)\ + do {\ + assert(ssize < STACK_SIZE);\ + stack[ssize].a = (_a), stack[ssize].b = (_b),\ + stack[ssize].c = (_c), stack[ssize++].d = (_d);\ + } while(0) +#define STACK_PUSH5(_a, _b, _c, _d, _e)\ + do {\ + assert(ssize < STACK_SIZE);\ + stack[ssize].a = (_a), stack[ssize].b = (_b),\ + stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\ + } while(0) +#define STACK_POP(_a, _b, _c, _d)\ + do {\ + assert(0 <= ssize);\ + if(ssize == 0) { return; }\ + (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ + (_c) = stack[ssize].c, (_d) = stack[ssize].d;\ + } while(0) +#define STACK_POP5(_a, _b, _c, _d, _e)\ + do {\ + assert(0 <= ssize);\ + if(ssize == 0) { return; }\ + (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ + (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\ + } while(0) +#define BUCKET_A(_c0) bucket_A[(_c0)] +#if ALPHABET_SIZE == 256 +#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)]) +#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)]) +#else +#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)]) +#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)]) +#endif + + +/*- Private Functions -*/ + +static const int lg_table[256]= { + -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) + +static INLINE +int +ss_ilg(int n) { +#if SS_BLOCKSIZE == 0 + return (n & 0xffff0000) ? + ((n & 0xff000000) ? + 24 + lg_table[(n >> 24) & 0xff] : + 16 + lg_table[(n >> 16) & 0xff]) : + ((n & 0x0000ff00) ? + 8 + lg_table[(n >> 8) & 0xff] : + 0 + lg_table[(n >> 0) & 0xff]); +#elif SS_BLOCKSIZE < 256 + return lg_table[n]; +#else + return (n & 0xff00) ? + 8 + lg_table[(n >> 8) & 0xff] : + 0 + lg_table[(n >> 0) & 0xff]; +#endif +} + +#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ + +#if SS_BLOCKSIZE != 0 + +static const int sqq_table[256] = { + 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, + 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, + 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, +110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, +128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, +143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, +156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, +169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180, +181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, +192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, +202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, +212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, +221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, +230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, +239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, +247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255 +}; + +static INLINE +int +ss_isqrt(int x) { + int y, e; + + if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; } + e = (x & 0xffff0000) ? + ((x & 0xff000000) ? + 24 + lg_table[(x >> 24) & 0xff] : + 16 + lg_table[(x >> 16) & 0xff]) : + ((x & 0x0000ff00) ? + 8 + lg_table[(x >> 8) & 0xff] : + 0 + lg_table[(x >> 0) & 0xff]); + + if(e >= 16) { + y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7); + if(e >= 24) { y = (y + 1 + x / y) >> 1; } + y = (y + 1 + x / y) >> 1; + } else if(e >= 8) { + y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1; + } else { + return sqq_table[x] >> 4; + } + + return (x < (y * y)) ? y - 1 : y; +} + +#endif /* SS_BLOCKSIZE != 0 */ + + +/*---------------------------------------------------------------------------*/ + +/* Compares two suffixes. */ +static INLINE +int +ss_compare(const unsigned char *T, + const int *p1, const int *p2, + int depth) { + const unsigned char *U1, *U2, *U1n, *U2n; + + for(U1 = T + depth + *p1, + U2 = T + depth + *p2, + U1n = T + *(p1 + 1) + 2, + U2n = T + *(p2 + 1) + 2; + (U1 < U1n) && (U2 < U2n) && (*U1 == *U2); + ++U1, ++U2) { + } + + return U1 < U1n ? + (U2 < U2n ? *U1 - *U2 : 1) : + (U2 < U2n ? -1 : 0); +} + + +/*---------------------------------------------------------------------------*/ + +#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) + +/* Insertionsort for small size groups */ +static +void +ss_insertionsort(const unsigned char *T, const int *PA, + int *first, int *last, int depth) { + int *i, *j; + int t; + int r; + + for(i = last - 2; first <= i; --i) { + for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) { + do { *(j - 1) = *j; } while((++j < last) && (*j < 0)); + if(last <= j) { break; } + } + if(r == 0) { *j = ~*j; } + *(j - 1) = t; + } +} + +#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */ + + +/*---------------------------------------------------------------------------*/ + +#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) + +static INLINE +void +ss_fixdown(const unsigned char *Td, const int *PA, + int *SA, int i, int size) { + int j, k; + int v; + int c, d, e; + + for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { + d = Td[PA[SA[k = j++]]]; + if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; } + if(d <= c) { break; } + } + SA[i] = v; +} + +/* Simple top-down heapsort. */ +static +void +ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) { + int i, m; + int t; + + m = size; + if((size % 2) == 0) { + m--; + if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); } + } + + for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); } + if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); } + for(i = m - 1; 0 < i; --i) { + t = SA[0], SA[0] = SA[i]; + ss_fixdown(Td, PA, SA, 0, i); + SA[i] = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Returns the median of three elements. */ +static INLINE +int * +ss_median3(const unsigned char *Td, const int *PA, + int *v1, int *v2, int *v3) { + int *t; + if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); } + if(Td[PA[*v2]] > Td[PA[*v3]]) { + if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; } + else { return v3; } + } + return v2; +} + +/* Returns the median of five elements. */ +static INLINE +int * +ss_median5(const unsigned char *Td, const int *PA, + int *v1, int *v2, int *v3, int *v4, int *v5) { + int *t; + if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); } + if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); } + if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); } + if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); } + if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); } + if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; } + return v3; +} + +/* Returns the pivot element. */ +static INLINE +int * +ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) { + int *middle; + int t; + + t = last - first; + middle = first + t / 2; + + if(t <= 512) { + if(t <= 32) { + return ss_median3(Td, PA, first, middle, last - 1); + } else { + t >>= 2; + return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1); + } + } + t >>= 3; + first = ss_median3(Td, PA, first, first + t, first + (t << 1)); + middle = ss_median3(Td, PA, middle - t, middle, middle + t); + last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1); + return ss_median3(Td, PA, first, middle, last); +} + + +/*---------------------------------------------------------------------------*/ + +/* Binary partition for substrings. */ +static INLINE +int * +ss_partition(const int *PA, + int *first, int *last, int depth) { + int *a, *b; + int t; + for(a = first - 1, b = last;;) { + for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; } + for(; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) { } + if(b <= a) { break; } + t = ~*b; + *b = *a; + *a = t; + } + if(first < a) { *first = ~*first; } + return a; +} + +/* Multikey introsort for medium size groups. */ +static +void +ss_mintrosort(const unsigned char *T, const int *PA, + int *first, int *last, + int depth) { +#define STACK_SIZE SS_MISORT_STACKSIZE + struct { int *a, *b, c; int d; } stack[STACK_SIZE]; + const unsigned char *Td; + int *a, *b, *c, *d, *e, *f; + int s, t; + int ssize; + int limit; + int v, x = 0; + + for(ssize = 0, limit = ss_ilg(last - first);;) { + + if((last - first) <= SS_INSERTIONSORT_THRESHOLD) { +#if 1 < SS_INSERTIONSORT_THRESHOLD + if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); } +#endif + STACK_POP(first, last, depth, limit); + continue; + } + + Td = T + depth; + if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); } + if(limit < 0) { + for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) { + if((x = Td[PA[*a]]) != v) { + if(1 < (a - first)) { break; } + v = x; + first = a; + } + } + if(Td[PA[*first] - 1] < v) { + first = ss_partition(PA, first, a, depth); + } + if((a - first) <= (last - a)) { + if(1 < (a - first)) { + STACK_PUSH(a, last, depth, -1); + last = a, depth += 1, limit = ss_ilg(a - first); + } else { + first = a, limit = -1; + } + } else { + if(1 < (last - a)) { + STACK_PUSH(first, a, depth + 1, ss_ilg(a - first)); + first = a, limit = -1; + } else { + last = a, depth += 1, limit = ss_ilg(a - first); + } + } + continue; + } + + /* choose pivot */ + a = ss_pivot(Td, PA, first, last); + v = Td[PA[*a]]; + SWAP(*first, *a); + + /* partition */ + for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { } + if(((a = b) < last) && (x < v)) { + for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + } + for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { } + if((b < (d = c)) && (x > v)) { + for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + for(; b < c;) { + SWAP(*b, *c); + for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + + if(a <= d) { + c = b - 1; + + if((s = a - first) > (t = b - a)) { s = t; } + for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + if((s = d - c) > (t = last - d - 1)) { s = t; } + for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + + a = first + (b - a), c = last - (d - c); + b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth); + + if((a - first) <= (last - c)) { + if((last - c) <= (c - b)) { + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + STACK_PUSH(c, last, depth, limit); + last = a; + } else if((a - first) <= (c - b)) { + STACK_PUSH(c, last, depth, limit); + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + last = a; + } else { + STACK_PUSH(c, last, depth, limit); + STACK_PUSH(first, a, depth, limit); + first = b, last = c, depth += 1, limit = ss_ilg(c - b); + } + } else { + if((a - first) <= (c - b)) { + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + STACK_PUSH(first, a, depth, limit); + first = c; + } else if((last - c) <= (c - b)) { + STACK_PUSH(first, a, depth, limit); + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + first = c; + } else { + STACK_PUSH(first, a, depth, limit); + STACK_PUSH(c, last, depth, limit); + first = b, last = c, depth += 1, limit = ss_ilg(c - b); + } + } + } else { + limit += 1; + if(Td[PA[*first] - 1] < v) { + first = ss_partition(PA, first, last, depth); + limit = ss_ilg(last - first); + } + depth += 1; + } + } +#undef STACK_SIZE +} + +#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ + + +/*---------------------------------------------------------------------------*/ + +#if SS_BLOCKSIZE != 0 + +static INLINE +void +ss_blockswap(int *a, int *b, int n) { + int t; + for(; 0 < n; --n, ++a, ++b) { + t = *a, *a = *b, *b = t; + } +} + +static INLINE +void +ss_rotate(int *first, int *middle, int *last) { + int *a, *b, t; + int l, r; + l = middle - first, r = last - middle; + for(; (0 < l) && (0 < r);) { + if(l == r) { ss_blockswap(first, middle, l); break; } + if(l < r) { + a = last - 1, b = middle - 1; + t = *a; + do { + *a-- = *b, *b-- = *a; + if(b < first) { + *a = t; + last = a; + if((r -= l + 1) <= l) { break; } + a -= 1, b = middle - 1; + t = *a; + } + } while(1); + } else { + a = first, b = middle; + t = *a; + do { + *a++ = *b, *b++ = *a; + if(last <= b) { + *a = t; + first = a + 1; + if((l -= r + 1) <= r) { break; } + a += 1, b = middle; + t = *a; + } + } while(1); + } + } +} + + +/*---------------------------------------------------------------------------*/ + +static +void +ss_inplacemerge(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int depth) { + const int *p; + int *a, *b; + int len, half; + int q, r; + int x; + + for(;;) { + if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); } + else { x = 0; p = PA + *(last - 1); } + for(a = first, len = middle - first, half = len >> 1, r = -1; + 0 < len; + len = half, half >>= 1) { + b = a + half; + q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth); + if(q < 0) { + a = b + 1; + half -= (len & 1) ^ 1; + } else { + r = q; + } + } + if(a < middle) { + if(r == 0) { *a = ~*a; } + ss_rotate(a, middle, last); + last -= middle - a; + middle = a; + if(first == middle) { break; } + } + --last; + if(x != 0) { while(*--last < 0) { } } + if(middle == last) { break; } + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Merge-forward with internal buffer. */ +static +void +ss_mergeforward(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int *buf, int depth) { + int *a, *b, *c, *bufend; + int t; + int r; + + bufend = buf + (middle - first) - 1; + ss_blockswap(buf, first, middle - first); + + for(t = *(a = first), b = buf, c = middle;;) { + r = ss_compare(T, PA + *b, PA + *c, depth); + if(r < 0) { + do { + *a++ = *b; + if(bufend <= b) { *bufend = t; return; } + *b++ = *a; + } while(*b < 0); + } else if(r > 0) { + do { + *a++ = *c, *c++ = *a; + if(last <= c) { + while(b < bufend) { *a++ = *b, *b++ = *a; } + *a = *b, *b = t; + return; + } + } while(*c < 0); + } else { + *c = ~*c; + do { + *a++ = *b; + if(bufend <= b) { *bufend = t; return; } + *b++ = *a; + } while(*b < 0); + + do { + *a++ = *c, *c++ = *a; + if(last <= c) { + while(b < bufend) { *a++ = *b, *b++ = *a; } + *a = *b, *b = t; + return; + } + } while(*c < 0); + } + } +} + +/* Merge-backward with internal buffer. */ +static +void +ss_mergebackward(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int *buf, int depth) { + const int *p1, *p2; + int *a, *b, *c, *bufend; + int t; + int r; + int x; + + bufend = buf + (last - middle) - 1; + ss_blockswap(buf, middle, last - middle); + + x = 0; + if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; } + else { p1 = PA + *bufend; } + if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; } + else { p2 = PA + *(middle - 1); } + for(t = *(a = last - 1), b = bufend, c = middle - 1;;) { + r = ss_compare(T, p1, p2, depth); + if(0 < r) { + if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } + *a-- = *b; + if(b <= buf) { *buf = t; break; } + *b-- = *a; + if(*b < 0) { p1 = PA + ~*b; x |= 1; } + else { p1 = PA + *b; } + } else if(r < 0) { + if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } + *a-- = *c, *c-- = *a; + if(c < first) { + while(buf < b) { *a-- = *b, *b-- = *a; } + *a = *b, *b = t; + break; + } + if(*c < 0) { p2 = PA + ~*c; x |= 2; } + else { p2 = PA + *c; } + } else { + if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } + *a-- = ~*b; + if(b <= buf) { *buf = t; break; } + *b-- = *a; + if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } + *a-- = *c, *c-- = *a; + if(c < first) { + while(buf < b) { *a-- = *b, *b-- = *a; } + *a = *b, *b = t; + break; + } + if(*b < 0) { p1 = PA + ~*b; x |= 1; } + else { p1 = PA + *b; } + if(*c < 0) { p2 = PA + ~*c; x |= 2; } + else { p2 = PA + *c; } + } + } +} + +/* D&C based merge. */ +static +void +ss_swapmerge(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int *buf, int bufsize, int depth) { +#define STACK_SIZE SS_SMERGE_STACKSIZE +#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a))) +#define MERGE_CHECK(a, b, c)\ + do {\ + if(((c) & 1) ||\ + (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\ + *(a) = ~*(a);\ + }\ + if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\ + *(b) = ~*(b);\ + }\ + } while(0) + struct { int *a, *b, *c; int d; } stack[STACK_SIZE]; + int *l, *r, *lm, *rm; + int m, len, half; + int ssize; + int check, next; + + for(check = 0, ssize = 0;;) { + if((last - middle) <= bufsize) { + if((first < middle) && (middle < last)) { + ss_mergebackward(T, PA, first, middle, last, buf, depth); + } + MERGE_CHECK(first, last, check); + STACK_POP(first, middle, last, check); + continue; + } + + if((middle - first) <= bufsize) { + if(first < middle) { + ss_mergeforward(T, PA, first, middle, last, buf, depth); + } + MERGE_CHECK(first, last, check); + STACK_POP(first, middle, last, check); + continue; + } + + for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1; + 0 < len; + len = half, half >>= 1) { + if(ss_compare(T, PA + GETIDX(*(middle + m + half)), + PA + GETIDX(*(middle - m - half - 1)), depth) < 0) { + m += half + 1; + half -= (len & 1) ^ 1; + } + } + + if(0 < m) { + lm = middle - m, rm = middle + m; + ss_blockswap(lm, middle, m); + l = r = middle, next = 0; + if(rm < last) { + if(*rm < 0) { + *rm = ~*rm; + if(first < lm) { for(; *--l < 0;) { } next |= 4; } + next |= 1; + } else if(first < lm) { + for(; *r < 0; ++r) { } + next |= 2; + } + } + + if((l - first) <= (last - r)) { + STACK_PUSH(r, rm, last, (next & 3) | (check & 4)); + middle = lm, last = l, check = (check & 3) | (next & 4); + } else { + if((next & 2) && (r == middle)) { next ^= 6; } + STACK_PUSH(first, lm, l, (check & 3) | (next & 4)); + first = r, middle = rm, check = (next & 3) | (check & 4); + } + } else { + if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) { + *middle = ~*middle; + } + MERGE_CHECK(first, last, check); + STACK_POP(first, middle, last, check); + } + } +#undef STACK_SIZE +} + +#endif /* SS_BLOCKSIZE != 0 */ + + +/*---------------------------------------------------------------------------*/ + +/* Substring sort */ +static +void +sssort(const unsigned char *T, const int *PA, + int *first, int *last, + int *buf, int bufsize, + int depth, int n, int lastsuffix) { + int *a; +#if SS_BLOCKSIZE != 0 + int *b, *middle, *curbuf; + int j, k, curbufsize, limit; +#endif + int i; + + if(lastsuffix != 0) { ++first; } + +#if SS_BLOCKSIZE == 0 + ss_mintrosort(T, PA, first, last, depth); +#else + if((bufsize < SS_BLOCKSIZE) && + (bufsize < (last - first)) && + (bufsize < (limit = ss_isqrt(last - first)))) { + if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; } + buf = middle = last - limit, bufsize = limit; + } else { + middle = last, limit = 0; + } + for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) { +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth); +#endif + curbufsize = last - (a + SS_BLOCKSIZE); + curbuf = a + SS_BLOCKSIZE; + if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; } + for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) { + ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth); + } + } +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, a, middle, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, a, middle, depth); +#endif + for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) { + if(i & 1) { + ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth); + a -= k; + } + } + if(limit != 0) { +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, middle, last, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, middle, last, depth); +#endif + ss_inplacemerge(T, PA, first, middle, last, depth); + } +#endif + + if(lastsuffix != 0) { + /* Insert last type B* suffix. */ + int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2; + for(a = first, i = *(first - 1); + (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth))); + ++a) { + *(a - 1) = *a; + } + *(a - 1) = i; + } +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +int +tr_ilg(int n) { + return (n & 0xffff0000) ? + ((n & 0xff000000) ? + 24 + lg_table[(n >> 24) & 0xff] : + 16 + lg_table[(n >> 16) & 0xff]) : + ((n & 0x0000ff00) ? + 8 + lg_table[(n >> 8) & 0xff] : + 0 + lg_table[(n >> 0) & 0xff]); +} + + +/*---------------------------------------------------------------------------*/ + +/* Simple insertionsort for small size groups. */ +static +void +tr_insertionsort(const int *ISAd, int *first, int *last) { + int *a, *b; + int t, r; + + for(a = first + 1; a < last; ++a) { + for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) { + do { *(b + 1) = *b; } while((first <= --b) && (*b < 0)); + if(b < first) { break; } + } + if(r == 0) { *b = ~*b; } + *(b + 1) = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +void +tr_fixdown(const int *ISAd, int *SA, int i, int size) { + int j, k; + int v; + int c, d, e; + + for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { + d = ISAd[SA[k = j++]]; + if(d < (e = ISAd[SA[j]])) { k = j; d = e; } + if(d <= c) { break; } + } + SA[i] = v; +} + +/* Simple top-down heapsort. */ +static +void +tr_heapsort(const int *ISAd, int *SA, int size) { + int i, m; + int t; + + m = size; + if((size % 2) == 0) { + m--; + if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); } + } + + for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); } + if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); } + for(i = m - 1; 0 < i; --i) { + t = SA[0], SA[0] = SA[i]; + tr_fixdown(ISAd, SA, 0, i); + SA[i] = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Returns the median of three elements. */ +static INLINE +int * +tr_median3(const int *ISAd, int *v1, int *v2, int *v3) { + int *t; + if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); } + if(ISAd[*v2] > ISAd[*v3]) { + if(ISAd[*v1] > ISAd[*v3]) { return v1; } + else { return v3; } + } + return v2; +} + +/* Returns the median of five elements. */ +static INLINE +int * +tr_median5(const int *ISAd, + int *v1, int *v2, int *v3, int *v4, int *v5) { + int *t; + if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); } + if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); } + if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); } + if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); } + if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); } + if(ISAd[*v3] > ISAd[*v4]) { return v4; } + return v3; +} + +/* Returns the pivot element. */ +static INLINE +int * +tr_pivot(const int *ISAd, int *first, int *last) { + int *middle; + int t; + + t = last - first; + middle = first + t / 2; + + if(t <= 512) { + if(t <= 32) { + return tr_median3(ISAd, first, middle, last - 1); + } else { + t >>= 2; + return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1); + } + } + t >>= 3; + first = tr_median3(ISAd, first, first + t, first + (t << 1)); + middle = tr_median3(ISAd, middle - t, middle, middle + t); + last = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1); + return tr_median3(ISAd, first, middle, last); +} + + +/*---------------------------------------------------------------------------*/ + +typedef struct _trbudget_t trbudget_t; +struct _trbudget_t { + int chance; + int remain; + int incval; + int count; +}; + +static INLINE +void +trbudget_init(trbudget_t *budget, int chance, int incval) { + budget->chance = chance; + budget->remain = budget->incval = incval; +} + +static INLINE +int +trbudget_check(trbudget_t *budget, int size) { + if(size <= budget->remain) { budget->remain -= size; return 1; } + if(budget->chance == 0) { budget->count += size; return 0; } + budget->remain += budget->incval - size; + budget->chance -= 1; + return 1; +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +void +tr_partition(const int *ISAd, + int *first, int *middle, int *last, + int **pa, int **pb, int v) { + int *a, *b, *c, *d, *e, *f; + int t, s; + int x = 0; + + for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { } + if(((a = b) < last) && (x < v)) { + for(; (++b < last) && ((x = ISAd[*b]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + } + for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { } + if((b < (d = c)) && (x > v)) { + for(; (b < --c) && ((x = ISAd[*c]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + for(; b < c;) { + SWAP(*b, *c); + for(; (++b < c) && ((x = ISAd[*b]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + for(; (b < --c) && ((x = ISAd[*c]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + + if(a <= d) { + c = b - 1; + if((s = a - first) > (t = b - a)) { s = t; } + for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + if((s = d - c) > (t = last - d - 1)) { s = t; } + for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + first += (b - a), last -= (d - c); + } + *pa = first, *pb = last; +} + +static +void +tr_copy(int *ISA, const int *SA, + int *first, int *a, int *b, int *last, + int depth) { + /* sort suffixes of middle partition + by using sorted order of suffixes of left and right partition. */ + int *c, *d, *e; + int s, v; + + v = b - SA - 1; + for(c = first, d = a - 1; c <= d; ++c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *++d = s; + ISA[s] = d - SA; + } + } + for(c = last - 1, e = d + 1, d = b; e < d; --c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *--d = s; + ISA[s] = d - SA; + } + } +} + +static +void +tr_partialcopy(int *ISA, const int *SA, + int *first, int *a, int *b, int *last, + int depth) { + int *c, *d, *e; + int s, v; + int rank, lastrank, newrank = -1; + + v = b - SA - 1; + lastrank = -1; + for(c = first, d = a - 1; c <= d; ++c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *++d = s; + rank = ISA[s + depth]; + if(lastrank != rank) { lastrank = rank; newrank = d - SA; } + ISA[s] = newrank; + } + } + + lastrank = -1; + for(e = d; first <= e; --e) { + rank = ISA[*e]; + if(lastrank != rank) { lastrank = rank; newrank = e - SA; } + if(newrank != rank) { ISA[*e] = newrank; } + } + + lastrank = -1; + for(c = last - 1, e = d + 1, d = b; e < d; --c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *--d = s; + rank = ISA[s + depth]; + if(lastrank != rank) { lastrank = rank; newrank = d - SA; } + ISA[s] = newrank; + } + } +} + +static +void +tr_introsort(int *ISA, const int *ISAd, + int *SA, int *first, int *last, + trbudget_t *budget) { +#define STACK_SIZE TR_STACKSIZE + struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE]; + int *a, *b, *c; + int t; + int v, x = 0; + int incr = ISAd - ISA; + int limit, next; + int ssize, trlink = -1; + + for(ssize = 0, limit = tr_ilg(last - first);;) { + + if(limit < 0) { + if(limit == -1) { + /* tandem repeat partition */ + tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1); + + /* update ranks */ + if(a < last) { + for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } + } + if(b < last) { + for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } + } + + /* push */ + if(1 < (b - a)) { + STACK_PUSH5(NULL, a, b, 0, 0); + STACK_PUSH5(ISAd - incr, first, last, -2, trlink); + trlink = ssize - 2; + } + if((a - first) <= (last - b)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink); + last = a, limit = tr_ilg(a - first); + } else if(1 < (last - b)) { + first = b, limit = tr_ilg(last - b); + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } else { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink); + first = b, limit = tr_ilg(last - b); + } else if(1 < (a - first)) { + last = a, limit = tr_ilg(a - first); + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } else if(limit == -2) { + /* tandem repeat copy */ + a = stack[--ssize].b, b = stack[ssize].c; + if(stack[ssize].d == 0) { + tr_copy(ISA, SA, first, a, b, last, ISAd - ISA); + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA); + } + STACK_POP5(ISAd, first, last, limit, trlink); + } else { + /* sorted partition */ + if(0 <= *first) { + a = first; + do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a)); + first = a; + } + if(first < last) { + a = first; do { *a = ~*a; } while(*++a < 0); + next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1; + if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } } + + /* push */ + if(trbudget_check(budget, a - first)) { + if((a - first) <= (last - a)) { + STACK_PUSH5(ISAd, a, last, -3, trlink); + ISAd += incr, last = a, limit = next; + } else { + if(1 < (last - a)) { + STACK_PUSH5(ISAd + incr, first, a, next, trlink); + first = a, limit = -3; + } else { + ISAd += incr, last = a, limit = next; + } + } + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + if(1 < (last - a)) { + first = a, limit = -3; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + continue; + } + + if((last - first) <= TR_INSERTIONSORT_THRESHOLD) { + tr_insertionsort(ISAd, first, last); + limit = -3; + continue; + } + + if(limit-- == 0) { + tr_heapsort(ISAd, first, last - first); + for(a = last - 1; first < a; a = b) { + for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; } + } + limit = -3; + continue; + } + + /* choose pivot */ + a = tr_pivot(ISAd, first, last); + SWAP(*first, *a); + v = ISAd[*first]; + + /* partition */ + tr_partition(ISAd, first, first + 1, last, &a, &b, v); + if((last - first) != (b - a)) { + next = (ISA[*a] != v) ? tr_ilg(b - a) : -1; + + /* update ranks */ + for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } + if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } } + + /* push */ + if((1 < (b - a)) && (trbudget_check(budget, b - a))) { + if((a - first) <= (last - b)) { + if((last - b) <= (b - a)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + STACK_PUSH5(ISAd, b, last, limit, trlink); + last = a; + } else if(1 < (last - b)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + first = b; + } else { + ISAd += incr, first = a, last = b, limit = next; + } + } else if((a - first) <= (b - a)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, limit, trlink); + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + last = a; + } else { + STACK_PUSH5(ISAd, b, last, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + STACK_PUSH5(ISAd, b, last, limit, trlink); + STACK_PUSH5(ISAd, first, a, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + if((a - first) <= (b - a)) { + if(1 < (last - b)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + STACK_PUSH5(ISAd, first, a, limit, trlink); + first = b; + } else if(1 < (a - first)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + last = a; + } else { + ISAd += incr, first = a, last = b, limit = next; + } + } else if((last - b) <= (b - a)) { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, limit, trlink); + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + first = b; + } else { + STACK_PUSH5(ISAd, first, a, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + STACK_PUSH5(ISAd, first, a, limit, trlink); + STACK_PUSH5(ISAd, b, last, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } + } else { + if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; } + if((a - first) <= (last - b)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, limit, trlink); + last = a; + } else if(1 < (last - b)) { + first = b; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } else { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, limit, trlink); + first = b; + } else if(1 < (a - first)) { + last = a; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } + } else { + if(trbudget_check(budget, last - first)) { + limit = tr_ilg(last - first), ISAd += incr; + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } +#undef STACK_SIZE +} + + + +/*---------------------------------------------------------------------------*/ + +/* Tandem repeat sort */ +static +void +trsort(int *ISA, int *SA, int n, int depth) { + int *ISAd; + int *first, *last; + trbudget_t budget; + int t, skip, unsorted; + + trbudget_init(&budget, tr_ilg(n) * 2 / 3, n); +/* trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */ + for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) { + first = SA; + skip = 0; + unsorted = 0; + do { + if((t = *first) < 0) { first -= t; skip += t; } + else { + if(skip != 0) { *(first + skip) = skip; skip = 0; } + last = SA + ISA[t] + 1; + if(1 < (last - first)) { + budget.count = 0; + tr_introsort(ISA, ISAd, SA, first, last, &budget); + if(budget.count != 0) { unsorted += budget.count; } + else { skip = first - last; } + } else if((last - first) == 1) { + skip = -1; + } + first = last; + } + } while(first < (SA + n)); + if(skip != 0) { *(first + skip) = skip; } + if(unsorted == 0) { break; } + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Sorts suffixes of type B*. */ +static +int +sort_typeBstar(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int openMP) { + int *PAb, *ISAb, *buf; +#ifdef LIBBSC_OPENMP + int *curbuf; + int l; +#endif + int i, j, k, t, m, bufsize; + int c0, c1; +#ifdef LIBBSC_OPENMP + int d0, d1; +#endif + + /* Initialize bucket arrays. */ + for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; } + for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; } + + /* Count the number of occurrences of the first one or two characters of each + type A, B and B* suffix. Moreover, store the beginning position of all + type B* suffixes into the array SA. */ + for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) { + /* type A suffix. */ + do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1)); + if(0 <= i) { + /* type B* suffix. */ + ++BUCKET_BSTAR(c0, c1); + SA[--m] = i; + /* type B suffix. */ + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { + ++BUCKET_B(c0, c1); + } + } + } + m = n - m; +/* +note: + A type B* suffix is lexicographically smaller than a type B suffix that + begins with the same first two characters. +*/ + + /* Calculate the index of start/end point of each bucket. */ + for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) { + t = i + BUCKET_A(c0); + BUCKET_A(c0) = i + j; /* start point */ + i = t + BUCKET_B(c0, c0); + for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) { + j += BUCKET_BSTAR(c0, c1); + BUCKET_BSTAR(c0, c1) = j; /* end point */ + i += BUCKET_B(c0, c1); + } + } + + if(0 < m) { + /* Sort the type B* suffixes by their first two characters. */ + PAb = SA + n - m; ISAb = SA + m; + for(i = m - 2; 0 <= i; --i) { + t = PAb[i], c0 = T[t], c1 = T[t + 1]; + SA[--BUCKET_BSTAR(c0, c1)] = i; + } + t = PAb[m - 1], c0 = T[t], c1 = T[t + 1]; + SA[--BUCKET_BSTAR(c0, c1)] = m - 1; + + /* Sort the type B* substrings using sssort. */ +#ifdef LIBBSC_OPENMP + if (openMP) + { + buf = SA + m; + c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m; +#pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1) + { + bufsize = (n - (2 * m)) / omp_get_num_threads(); + curbuf = buf + omp_get_thread_num() * bufsize; + k = 0; + for(;;) { + #pragma omp critical(sssort_lock) + { + if(0 < (l = j)) { + d0 = c0, d1 = c1; + do { + k = BUCKET_BSTAR(d0, d1); + if(--d1 <= d0) { + d1 = ALPHABET_SIZE - 1; + if(--d0 < 0) { break; } + } + } while(((l - k) <= 1) && (0 < (l = k))); + c0 = d0, c1 = d1, j = k; + } + } + if(l == 0) { break; } + sssort(T, PAb, SA + k, SA + l, + curbuf, bufsize, 2, n, *(SA + k) == (m - 1)); + } + } + } + else + { + buf = SA + m, bufsize = n - (2 * m); + for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) { + for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) { + i = BUCKET_BSTAR(c0, c1); + if(1 < (j - i)) { + sssort(T, PAb, SA + i, SA + j, + buf, bufsize, 2, n, *(SA + i) == (m - 1)); + } + } + } + } +#else + buf = SA + m, bufsize = n - (2 * m); + for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) { + for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) { + i = BUCKET_BSTAR(c0, c1); + if(1 < (j - i)) { + sssort(T, PAb, SA + i, SA + j, + buf, bufsize, 2, n, *(SA + i) == (m - 1)); + } + } + } +#endif + + /* Compute ranks of type B* substrings. */ + for(i = m - 1; 0 <= i; --i) { + if(0 <= SA[i]) { + j = i; + do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i])); + SA[i + 1] = i - j; + if(i <= 0) { break; } + } + j = i; + do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0); + ISAb[SA[i]] = j; + } + + /* Construct the inverse suffix array of type B* suffixes using trsort. */ + trsort(ISAb, SA, m, 1); + + /* Set the sorted order of tyoe B* suffixes. */ + for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) { + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { } + if(0 <= i) { + t = i; + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { } + SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t; + } + } + + /* Calculate the index of start/end point of each bucket. */ + BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */ + for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) { + i = BUCKET_A(c0 + 1) - 1; + for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) { + t = i - BUCKET_B(c0, c1); + BUCKET_B(c0, c1) = i; /* end point */ + + /* Move all type B* suffixes to the correct position. */ + for(i = t, j = BUCKET_BSTAR(c0, c1); + j <= k; + --i, --k) { SA[i] = SA[k]; } + } + BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */ + BUCKET_B(c0, c0) = i; /* end point */ + } + } + + return m; +} + +/* Constructs the suffix array by using the sorted order of type B* suffixes. */ +static +void +construct_SA(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int m) { + int *i, *j, *k; + int s; + int c0, c1, c2; + + if(0 < m) { + /* Construct the sorted order of type B suffixes by using + the sorted order of type B* suffixes. */ + for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { + /* Scan the suffix array from right to left. */ + for(i = SA + BUCKET_BSTAR(c1, c1 + 1), + j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; + i <= j; + --j) { + if(0 < (s = *j)) { + assert(T[s] == c1); + assert(((s + 1) < n) && (T[s] <= T[s + 1])); + assert(T[s - 1] <= T[s]); + *j = ~s; + c0 = T[--s]; + if((0 < s) && (T[s - 1] > c0)) { s = ~s; } + if(c0 != c2) { + if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } + k = SA + BUCKET_B(c2 = c0, c1); + } + assert(k < j); + *k-- = s; + } else { + assert(((s == 0) && (T[s] == c1)) || (s < 0)); + *j = ~s; + } + } + } + } + + /* Construct the suffix array by using + the sorted order of type B suffixes. */ + k = SA + BUCKET_A(c2 = T[n - 1]); + *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1); + /* Scan the suffix array from left to right. */ + for(i = SA, j = SA + n; i < j; ++i) { + if(0 < (s = *i)) { + assert(T[s - 1] >= T[s]); + c0 = T[--s]; + if((s == 0) || (T[s - 1] < c0)) { s = ~s; } + if(c0 != c2) { + BUCKET_A(c2) = k - SA; + k = SA + BUCKET_A(c2 = c0); + } + assert(i < k); + *k++ = s; + } else { + assert(s < 0); + *i = ~s; + } + } +} + +/* Constructs the burrows-wheeler transformed string directly + by using the sorted order of type B* suffixes. */ +static +int +construct_BWT(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int m) { + int *i, *j, *k, *orig; + int s; + int c0, c1, c2; + + if(0 < m) { + /* Construct the sorted order of type B suffixes by using + the sorted order of type B* suffixes. */ + for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { + /* Scan the suffix array from right to left. */ + for(i = SA + BUCKET_BSTAR(c1, c1 + 1), + j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; + i <= j; + --j) { + if(0 < (s = *j)) { + assert(T[s] == c1); + assert(((s + 1) < n) && (T[s] <= T[s + 1])); + assert(T[s - 1] <= T[s]); + c0 = T[--s]; + *j = ~((int)c0); + if((0 < s) && (T[s - 1] > c0)) { s = ~s; } + if(c0 != c2) { + if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } + k = SA + BUCKET_B(c2 = c0, c1); + } + assert(k < j); + *k-- = s; + } else if(s != 0) { + *j = ~s; +#ifndef NDEBUG + } else { + assert(T[s] == c1); +#endif + } + } + } + } + + /* Construct the BWTed string by using + the sorted order of type B suffixes. */ + k = SA + BUCKET_A(c2 = T[n - 1]); + *k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1); + /* Scan the suffix array from left to right. */ + for(i = SA, j = SA + n, orig = SA; i < j; ++i) { + if(0 < (s = *i)) { + assert(T[s - 1] >= T[s]); + c0 = T[--s]; + *i = c0; + if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); } + if(c0 != c2) { + BUCKET_A(c2) = k - SA; + k = SA + BUCKET_A(c2 = c0); + } + assert(i < k); + *k++ = s; + } else if(s != 0) { + *i = ~s; + } else { + orig = i; + } + } + + return orig - SA; +} + +/* Constructs the burrows-wheeler transformed string directly + by using the sorted order of type B* suffixes. */ +static +int +construct_BWT_indexes(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int m, + unsigned char * num_indexes, int * indexes) { + int *i, *j, *k, *orig; + int s; + int c0, c1, c2; + + int mod = n / 8; + { + mod |= mod >> 1; mod |= mod >> 2; + mod |= mod >> 4; mod |= mod >> 8; + mod |= mod >> 16; mod >>= 1; + + *num_indexes = (unsigned char)((n - 1) / (mod + 1)); + } + + if(0 < m) { + /* Construct the sorted order of type B suffixes by using + the sorted order of type B* suffixes. */ + for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { + /* Scan the suffix array from right to left. */ + for(i = SA + BUCKET_BSTAR(c1, c1 + 1), + j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; + i <= j; + --j) { + if(0 < (s = *j)) { + assert(T[s] == c1); + assert(((s + 1) < n) && (T[s] <= T[s + 1])); + assert(T[s - 1] <= T[s]); + + if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = j - SA; + + c0 = T[--s]; + *j = ~((int)c0); + if((0 < s) && (T[s - 1] > c0)) { s = ~s; } + if(c0 != c2) { + if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } + k = SA + BUCKET_B(c2 = c0, c1); + } + assert(k < j); + *k-- = s; + } else if(s != 0) { + *j = ~s; +#ifndef NDEBUG + } else { + assert(T[s] == c1); +#endif + } + } + } + } + + /* Construct the BWTed string by using + the sorted order of type B suffixes. */ + k = SA + BUCKET_A(c2 = T[n - 1]); + if (T[n - 2] < c2) { + if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = k - SA; + *k++ = ~((int)T[n - 2]); + } + else { + *k++ = n - 1; + } + + /* Scan the suffix array from left to right. */ + for(i = SA, j = SA + n, orig = SA; i < j; ++i) { + if(0 < (s = *i)) { + assert(T[s - 1] >= T[s]); + + if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = i - SA; + + c0 = T[--s]; + *i = c0; + if(c0 != c2) { + BUCKET_A(c2) = k - SA; + k = SA + BUCKET_A(c2 = c0); + } + assert(i < k); + if((0 < s) && (T[s - 1] < c0)) { + if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = k - SA; + *k++ = ~((int)T[s - 1]); + } else + *k++ = s; + } else if(s != 0) { + *i = ~s; + } else { + orig = i; + } + } + + return orig - SA; +} + + +/*---------------------------------------------------------------------------*/ + +/*- Function -*/ + +int +divsufsort(const unsigned char *T, int *SA, int n, int openMP) { + int *bucket_A, *bucket_B; + int m; + int err = 0; + + /* Check arguments. */ + if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; } + else if(n == 0) { return 0; } + else if(n == 1) { SA[0] = 0; return 0; } + else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; } + + bucket_A = (int *)bsc_malloc(BUCKET_A_SIZE * sizeof(int)); + bucket_B = (int *)bsc_malloc(BUCKET_B_SIZE * sizeof(int)); + + /* Suffixsort. */ + if((bucket_A != NULL) && (bucket_B != NULL)) { + m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP); + construct_SA(T, SA, bucket_A, bucket_B, n, m); + } else { + err = -2; + } + + bsc_free(bucket_B); + bsc_free(bucket_A); + + return err; +} + +int +divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP) { + int *B; + int *bucket_A, *bucket_B; + int m, pidx, i; + + /* Check arguments. */ + if((T == NULL) || (U == NULL) || (n < 0)) { return -1; } + else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; } + + if((B = A) == NULL) { B = (int *)bsc_malloc((size_t)(n + 1) * sizeof(int)); } + bucket_A = (int *)bsc_malloc(BUCKET_A_SIZE * sizeof(int)); + bucket_B = (int *)bsc_malloc(BUCKET_B_SIZE * sizeof(int)); + + /* Burrows-Wheeler Transform. */ + if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) { + m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP); + + if (num_indexes == NULL || indexes == NULL) { + pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m); + } else { + pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes); + } + + /* Copy to output string. */ + U[0] = T[n - 1]; + for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)B[i]; } + for(i += 1; i < n; ++i) { U[i] = (unsigned char)B[i]; } + pidx += 1; + } else { + pidx = -2; + } + + bsc_free(bucket_B); + bsc_free(bucket_A); + if(A == NULL) { bsc_free(B); } + + return pidx; +} diff --git a/bsc/libbsc/bwt/divsufsort/divsufsort.h b/bsc/libbsc/bwt/divsufsort/divsufsort.h new file mode 100644 index 0000000..dac0936 --- /dev/null +++ b/bsc/libbsc/bwt/divsufsort/divsufsort.h @@ -0,0 +1,67 @@ +/* + * divsufsort.h for libdivsufsort-lite + * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DIVSUFSORT_H +#define _DIVSUFSORT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/*- Prototypes -*/ + +/** + * Constructs the suffix array of a given string. + * @param T[0..n-1] The input string. + * @param SA[0..n-1] The output array of suffixes. + * @param n The length of the given string. + * @param openMP enables OpenMP optimization. + * @return 0 if no error occurred, -1 or -2 otherwise. + */ +int +divsufsort(const unsigned char *T, int *SA, int n, int openMP); + +/** + * Constructs the burrows-wheeler transformed string of a given string. + * @param T[0..n-1] The input string. + * @param U[0..n-1] The output string. (can be T) + * @param A[0..n-1] The temporary array. (can be NULL) + * @param n The length of the given string. + * @param num_indexes The length of secondary indexes array. (can be NULL) + * @param indexes The secondary indexes array. (can be NULL) + * @param openMP enables OpenMP optimization. + * @return The primary index if no error occurred, -1 or -2 otherwise. + */ +int +divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* _DIVSUFSORT_H */ diff --git a/bsc/libbsc/coder/coder.cpp b/bsc/libbsc/coder/coder.cpp new file mode 100644 index 0000000..11e4c9d --- /dev/null +++ b/bsc/libbsc/coder/coder.cpp @@ -0,0 +1,346 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Second stage encoding functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include + +#include "coder.h" + +#include "../libbsc.h" +#include "../platform/platform.h" + +#include "qlfc/qlfc.h" + +int bsc_coder_init(int features) +{ + int result = LIBBSC_NO_ERROR; + + if (result == LIBBSC_NO_ERROR) result = bsc_qlfc_init(features); + + return result; +} + +static INLINE int bsc_coder_num_blocks(int n) +{ + if (n < 256 * 1024) return 1; + if (n < 4 * 1024 * 1024) return 2; + if (n < 16 * 1024 * 1024) return 4; + + return 8; +} + +int bsc_coder_encode_block(const unsigned char * input, unsigned char * output, int inputSize, int outputSize, int coder) +{ + if (coder == LIBBSC_CODER_QLFC_STATIC) return bsc_qlfc_static_encode_block (input, output, inputSize, outputSize); + if (coder == LIBBSC_CODER_QLFC_ADAPTIVE) return bsc_qlfc_adaptive_encode_block(input, output, inputSize, outputSize); + + return LIBBSC_BAD_PARAMETER; +} + +void bsc_coder_split_blocks(const unsigned char * input, int n, int nBlocks, int * blockStart, int * blockSize) +{ + int rankSize = 0; + for (int i = 1; i < n; i += 32) + { + if (input[i] != input[i - 1]) rankSize++; + } + + if (rankSize > nBlocks) + { + int blockRankSize = rankSize / nBlocks; + + blockStart[0] = 0; rankSize = 0; + for (int id = 0, i = 1; i < n; i += 32) + { + if (input[i] != input[i - 1]) + { + rankSize++; + if (rankSize == blockRankSize) + { + rankSize = 0; + + blockSize[id] = i - blockStart[id]; + id++; blockStart[id] = i; + + if (id == nBlocks - 1) break; + } + } + } + blockSize[nBlocks - 1] = n - blockStart[nBlocks - 1]; + } + else + { + for (int p = 0; p < nBlocks; ++p) + { + blockStart[p] = (n / nBlocks) * p; + blockSize[p] = (p != nBlocks - 1) ? n / nBlocks : n - (n / nBlocks) * (nBlocks - 1); + } + } +} + +int bsc_coder_compress_serial(const unsigned char * input, unsigned char * output, int n, int coder) +{ + if (bsc_coder_num_blocks(n) == 1) + { + int result = bsc_coder_encode_block(input, output + 1, n, n - 1, coder); + if (result >= LIBBSC_NO_ERROR) result = (output[0] = 1, result + 1); + + return result; + } + + int compressedStart[ALPHABET_SIZE]; + int compressedSize[ALPHABET_SIZE]; + + int nBlocks = bsc_coder_num_blocks(n); + int outputPtr = 1 + 8 * nBlocks; + + bsc_coder_split_blocks(input, n, nBlocks, compressedStart, compressedSize); + + output[0] = nBlocks; + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int inputStart = compressedStart[blockId]; + int inputSize = compressedSize[blockId]; + int outputSize = inputSize; if (outputSize > n - outputPtr) outputSize = n - outputPtr; + + int result = bsc_coder_encode_block(input + inputStart, output + outputPtr, inputSize, outputSize, coder); + if (result < LIBBSC_NO_ERROR) + { + if (outputPtr + inputSize >= n) return LIBBSC_NOT_COMPRESSIBLE; + result = inputSize; memcpy(output + outputPtr, input + inputStart, inputSize); + } + + *(int *)(output + 1 + 8 * blockId + 0) = inputSize; + *(int *)(output + 1 + 8 * blockId + 4) = result; + + outputPtr += result; + } + + return outputPtr; +} + +#ifdef LIBBSC_OPENMP + +int bsc_coder_compress_parallel(const unsigned char * input, unsigned char * output, int n, int coder) +{ + if (unsigned char * buffer = (unsigned char *)bsc_malloc(n * sizeof(unsigned char))) + { + int compressionResult[ALPHABET_SIZE]; + int compressedStart[ALPHABET_SIZE]; + int compressedSize[ALPHABET_SIZE]; + + int nBlocks = bsc_coder_num_blocks(n); + int result = LIBBSC_NO_ERROR; + + int numThreads = omp_get_max_threads(); + if (numThreads > nBlocks) numThreads = nBlocks; + + output[0] = nBlocks; + #pragma omp parallel num_threads(numThreads) if(numThreads > 1) + { + if (omp_get_num_threads() == 1) + { + result = bsc_coder_compress_serial(input, output, n, coder); + } + else + { + #pragma omp single + { + bsc_coder_split_blocks(input, n, nBlocks, compressedStart, compressedSize); + } + + #pragma omp for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int blockStart = compressedStart[blockId]; + int blockSize = compressedSize[blockId]; + + compressionResult[blockId] = bsc_coder_encode_block(input + blockStart, buffer + blockStart, blockSize, blockSize, coder); + if (compressionResult[blockId] < LIBBSC_NO_ERROR) compressionResult[blockId] = blockSize; + + *(int *)(output + 1 + 8 * blockId + 0) = blockSize; + *(int *)(output + 1 + 8 * blockId + 4) = compressionResult[blockId]; + } + + #pragma omp single + { + result = 1 + 8 * nBlocks; + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + result += compressionResult[blockId]; + } + + if (result >= n) result = LIBBSC_NOT_COMPRESSIBLE; + } + + if (result >= LIBBSC_NO_ERROR) + { + #pragma omp for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int blockStart = compressedStart[blockId]; + int blockSize = compressedSize[blockId]; + + int outputPtr = 1 + 8 * nBlocks; + for (int p = 0; p < blockId; ++p) outputPtr += compressionResult[p]; + + if (compressionResult[blockId] != blockSize) + { + memcpy(output + outputPtr, buffer + blockStart, compressionResult[blockId]); + } + else + { + memcpy(output + outputPtr, input + blockStart, compressionResult[blockId]); + } + } + } + } + } + + bsc_free(buffer); + + return result; + } + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +#endif + +int bsc_coder_compress(const unsigned char * input, unsigned char * output, int n, int coder, int features) +{ + if ((coder != LIBBSC_CODER_QLFC_STATIC) && (coder != LIBBSC_CODER_QLFC_ADAPTIVE)) + { + return LIBBSC_BAD_PARAMETER; + } + +#ifdef LIBBSC_OPENMP + + if ((bsc_coder_num_blocks(n) != 1) && (features & LIBBSC_FEATURE_MULTITHREADING)) + { + return bsc_coder_compress_parallel(input, output, n, coder); + } + +#endif + + return bsc_coder_compress_serial(input, output, n, coder); +} + + +int bsc_coder_decode_block(const unsigned char * input, unsigned char * output, int coder) +{ + if (coder == LIBBSC_CODER_QLFC_STATIC) return bsc_qlfc_static_decode_block (input, output); + if (coder == LIBBSC_CODER_QLFC_ADAPTIVE) return bsc_qlfc_adaptive_decode_block(input, output); + + return LIBBSC_BAD_PARAMETER; +} + +int bsc_coder_decompress(const unsigned char * input, unsigned char * output, int coder, int features) +{ + if ((coder != LIBBSC_CODER_QLFC_STATIC) && (coder != LIBBSC_CODER_QLFC_ADAPTIVE)) + { + return LIBBSC_BAD_PARAMETER; + } + + int nBlocks = input[0]; + if (nBlocks == 1) + { + return bsc_coder_decode_block(input + 1, output, coder); + } + + int decompressionResult[ALPHABET_SIZE]; + +#ifdef LIBBSC_OPENMP + + if (features & LIBBSC_FEATURE_MULTITHREADING) + { + #pragma omp parallel for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int inputPtr = 0; for (int p = 0; p < blockId; ++p) inputPtr += *(int *)(input + 1 + 8 * p + 4); + int outputPtr = 0; for (int p = 0; p < blockId; ++p) outputPtr += *(int *)(input + 1 + 8 * p + 0); + + inputPtr += 1 + 8 * nBlocks; + + int inputSize = *(int *)(input + 1 + 8 * blockId + 4); + int outputSize = *(int *)(input + 1 + 8 * blockId + 0); + + if (inputSize != outputSize) + { + decompressionResult[blockId] = bsc_coder_decode_block(input + inputPtr, output + outputPtr, coder); + } + else + { + decompressionResult[blockId] = inputSize; memcpy(output + outputPtr, input + inputPtr, inputSize); + } + } + } + else + +#endif + + { + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int inputPtr = 0; for (int p = 0; p < blockId; ++p) inputPtr += *(int *)(input + 1 + 8 * p + 4); + int outputPtr = 0; for (int p = 0; p < blockId; ++p) outputPtr += *(int *)(input + 1 + 8 * p + 0); + + inputPtr += 1 + 8 * nBlocks; + + int inputSize = *(int *)(input + 1 + 8 * blockId + 4); + int outputSize = *(int *)(input + 1 + 8 * blockId + 0); + + if (inputSize != outputSize) + { + decompressionResult[blockId] = bsc_coder_decode_block(input + inputPtr, output + outputPtr, coder); + } + else + { + decompressionResult[blockId] = inputSize; memcpy(output + outputPtr, input + inputPtr, inputSize); + } + } + } + + int dataSize = 0, result = LIBBSC_NO_ERROR; + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + if (decompressionResult[blockId] < LIBBSC_NO_ERROR) result = decompressionResult[blockId]; + dataSize += decompressionResult[blockId]; + } + + return (result == LIBBSC_NO_ERROR) ? dataSize : result; +} + +/*-----------------------------------------------------------*/ +/* End coder.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/coder.h b/bsc/libbsc/coder/coder.h new file mode 100644 index 0000000..dd8eaf4 --- /dev/null +++ b/bsc/libbsc/coder/coder.h @@ -0,0 +1,78 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to second stage encoding functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_CODER_H +#define _LIBBSC_CODER_H + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * You should call this function before you call any of the other functions in coder. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_coder_init(int features); + + /** + * Compress a memory block using Quantized Local Frequency Coding. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n bytes. + * @param n - the length of the input memory block. + * @param coder - the entropy coding algorithm. + * @param features - the set of additional features. + * @return the length of compressed memory block if no error occurred, error code otherwise. + */ + int bsc_coder_compress(const unsigned char * input, unsigned char * output, int n, int coder, int features); + + /** + * Decompress a memory block using Quantized Local Frequency Coding. + * @param input - the input memory block. + * @param output - the output memory block. + * @param coder - the entropy coding algorithm. + * @param features - the set of additional features. + * @return the length of decompressed memory block if no error occurred, error code otherwise. + */ + int bsc_coder_decompress(const unsigned char * input, unsigned char * output, int coder, int features); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-----------------------------------------------------------*/ +/* End coder.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/common/predictor.h b/bsc/libbsc/coder/common/predictor.h new file mode 100644 index 0000000..275bdb4 --- /dev/null +++ b/bsc/libbsc/coder/common/predictor.h @@ -0,0 +1,205 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Probability counter and logistic mixer */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_CODER_PREDICTOR_H +#define _LIBBSC_CODER_PREDICTOR_H + +#include "../../platform/platform.h" + +#include "tables.h" + +struct ProbabilityCounter +{ + +public: + + static INLINE void UpdateBit0(short & probability, const int threshold, const int adaptationRate) + { + probability = probability + (((4096 - threshold - probability) * adaptationRate) >> 12); + }; + + static INLINE void UpdateBit1(short & probability, const int threshold, const int adaptationRate) + { + probability = probability - (((probability - threshold) * adaptationRate) >> 12); + }; + +}; + +struct ProbabilityMixer +{ + +private: + + short stretchedProbability0; + short stretchedProbability1; + short stretchedProbability2; + int mixedProbability; + int index; + + short probabilityMap[17]; + + int weight0; + int weight1; + int weight2; + +public: + + INLINE void Init() + { + weight0 = weight1 = 2048 << 5; weight2 = 0; + for (int p = 0; p < 17; ++p) + { + probabilityMap[p] = bsc_squash((p - 8) * 256); + } + } + + INLINE int Mixup(const int probability0, const int probability1, const int probability2) + { + stretchedProbability0 = bsc_stretch(probability0); + stretchedProbability1 = bsc_stretch(probability1); + stretchedProbability2 = bsc_stretch(probability2); + + short stretchedProbability = (stretchedProbability0 * weight0 + stretchedProbability1 * weight1 + stretchedProbability2 * weight2) >> 17; + + if (stretchedProbability < -2047) stretchedProbability = -2047; + if (stretchedProbability > 2047) stretchedProbability = 2047; + + index = (stretchedProbability + 2048) >> 8; + const int weight = stretchedProbability & 255; + const int probability = bsc_squash(stretchedProbability); + const int mappedProbability = probabilityMap[index] + (((probabilityMap[index + 1] - probabilityMap[index]) * weight) >> 8); + + return mixedProbability = (3 * probability + mappedProbability) >> 2; + }; + + INLINE int MixupAndUpdateBit0(const int probability0, const int probability1, const int probability2, + const int learningRate0, const int learningRate1, const int learningRate2, + const int threshold, const int adaptationRate + ) + { + const short stretchedProbability0 = bsc_stretch(probability0); + const short stretchedProbability1 = bsc_stretch(probability1); + const short stretchedProbability2 = bsc_stretch(probability2); + + short stretchedProbability = (stretchedProbability0 * weight0 + stretchedProbability1 * weight1 + stretchedProbability2 * weight2) >> 17; + + if (stretchedProbability < -2047) stretchedProbability = -2047; + if (stretchedProbability > 2047) stretchedProbability = 2047; + + const int weight = stretchedProbability & 255; + const int index = (stretchedProbability + 2048) >> 8; + const int probability = bsc_squash(stretchedProbability); + const int mappedProbability = probabilityMap[index] + (((probabilityMap[index + 1] - probabilityMap[index]) * weight) >> 8); + const int mixedProbability = (3 * probability + mappedProbability) >> 2; + + ProbabilityCounter::UpdateBit0(probabilityMap[index], threshold, adaptationRate); + ProbabilityCounter::UpdateBit0(probabilityMap[index + 1], threshold, adaptationRate); + + const int eps = mixedProbability - 4095; + + weight0 -= (learningRate0 * eps * stretchedProbability0) >> 16; + weight1 -= (learningRate1 * eps * stretchedProbability1) >> 16; + weight2 -= (learningRate2 * eps * stretchedProbability2) >> 16; + + return mixedProbability; + }; + + INLINE int MixupAndUpdateBit1(const int probability0, const int probability1, const int probability2, + const int learningRate0, const int learningRate1, const int learningRate2, + const int threshold, const int adaptationRate + ) + { + const short stretchedProbability0 = bsc_stretch(probability0); + const short stretchedProbability1 = bsc_stretch(probability1); + const short stretchedProbability2 = bsc_stretch(probability2); + + short stretchedProbability = (stretchedProbability0 * weight0 + stretchedProbability1 * weight1 + stretchedProbability2 * weight2) >> 17; + + if (stretchedProbability < -2047) stretchedProbability = -2047; + if (stretchedProbability > 2047) stretchedProbability = 2047; + + const int weight = stretchedProbability & 255; + const int index = (stretchedProbability + 2048) >> 8; + const int probability = bsc_squash(stretchedProbability); + const int mappedProbability = probabilityMap[index] + (((probabilityMap[index + 1] - probabilityMap[index]) * weight) >> 8); + const int mixedProbability = (3 * probability + mappedProbability) >> 2; + + ProbabilityCounter::UpdateBit1(probabilityMap[index], threshold, adaptationRate); + ProbabilityCounter::UpdateBit1(probabilityMap[index + 1], threshold, adaptationRate); + + const int eps = mixedProbability - 1; + + weight0 -= (learningRate0 * eps * stretchedProbability0) >> 16; + weight1 -= (learningRate1 * eps * stretchedProbability1) >> 16; + weight2 -= (learningRate2 * eps * stretchedProbability2) >> 16; + + return mixedProbability; + }; + + INLINE void UpdateBit0(const int learningRate0, const int learningRate1, const int learningRate2, + const int threshold, const int adaptationRate + ) + { + ProbabilityCounter::UpdateBit0(probabilityMap[index], threshold, adaptationRate); + ProbabilityCounter::UpdateBit0(probabilityMap[index + 1], threshold, adaptationRate); + + const int eps = mixedProbability - 4095; + + weight0 -= (learningRate0 * eps * stretchedProbability0) >> 16; + weight1 -= (learningRate1 * eps * stretchedProbability1) >> 16; + weight2 -= (learningRate2 * eps * stretchedProbability2) >> 16; + }; + + INLINE void UpdateBit1(const int learningRate0, const int learningRate1, const int learningRate2, + const int threshold, const int adaptationRate + ) + { + ProbabilityCounter::UpdateBit1(probabilityMap[index], threshold, adaptationRate); + ProbabilityCounter::UpdateBit1(probabilityMap[index + 1], threshold, adaptationRate); + + const int eps = mixedProbability - 1; + + weight0 -= (learningRate0 * eps * stretchedProbability0) >> 16; + weight1 -= (learningRate1 * eps * stretchedProbability1) >> 16; + weight2 -= (learningRate2 * eps * stretchedProbability2) >> 16; + }; + +}; + + +#endif + +/*-----------------------------------------------------------*/ +/* End predictor.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/common/rangecoder.h b/bsc/libbsc/coder/common/rangecoder.h new file mode 100644 index 0000000..97a26f3 --- /dev/null +++ b/bsc/libbsc/coder/common/rangecoder.h @@ -0,0 +1,215 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Range coder */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_CODER_RANGECODER_H +#define _LIBBSC_CODER_RANGECODER_H + +#include "../../platform/platform.h" + +class RangeCoder +{ + +private: + + union ari + { + struct u + { + unsigned int low32; + unsigned int carry; + } u; + unsigned long long low; + } ari; + + unsigned int ari_code; + unsigned int ari_ffnum; + unsigned int ari_cache; + unsigned int ari_range; + + const unsigned short * RESTRICT ari_input; + unsigned short * RESTRICT ari_output; + unsigned short * RESTRICT ari_outputEOB; + unsigned short * RESTRICT ari_outputStart; + + INLINE void OutputShort(unsigned short s) + { + *ari_output++ = s; + }; + + INLINE unsigned short InputShort() + { + return *ari_input++; + }; + + INLINE void ShiftLow() + { + if (ari.u.low32 < 0xffff0000U || ari.u.carry) + { + OutputShort(ari_cache + ari.u.carry); + if (ari_ffnum) + { + unsigned short s = ari.u.carry - 1; + do { OutputShort(s); } while (--ari_ffnum); + } + ari_cache = ari.u.low32 >> 16; ari.u.carry = 0; + } else ari_ffnum++; + ari.u.low32 <<= 16; + } + +public: + + INLINE bool CheckEOB() + { + return ari_output >= ari_outputEOB; + } + + INLINE void InitEncoder(unsigned char * output, int outputSize) + { + ari_outputStart = (unsigned short *)output; + ari_output = (unsigned short *)output; + ari_outputEOB = (unsigned short *)(output + outputSize - 16); + ari.low = 0; + ari_ffnum = 0; + ari_cache = 0; + ari_range = 0xffffffff; + }; + + INLINE int FinishEncoder() + { + ShiftLow(); ShiftLow(); ShiftLow(); + return (int)(ari_output - ari_outputStart) * sizeof(ari_output[0]); + } + + INLINE void EncodeBit0(int probability) + { + ari_range = (ari_range >> 12) * probability; + if (ari_range < 0x10000) + { + ari_range <<= 16; ShiftLow(); + } + } + + INLINE void EncodeBit1(int probability) + { + unsigned int range = (ari_range >> 12) * probability; + ari.low += range; ari_range -= range; + if (ari_range < 0x10000) + { + ari_range <<= 16; ShiftLow(); + } + } + + INLINE void EncodeBit(unsigned int bit) + { + if (bit) EncodeBit1(2048); else EncodeBit0(2048); + }; + + INLINE void EncodeByte(unsigned int byte) + { + for (int bit = 7; bit >= 0; --bit) + { + EncodeBit(byte & (1 << bit)); + } + }; + + INLINE void EncodeWord(unsigned int word) + { + for (int bit = 31; bit >= 0; --bit) + { + EncodeBit(word & (1 << bit)); + } + }; + + INLINE void InitDecoder(const unsigned char * input) + { + ari_input = (unsigned short *)input; + ari_code = 0; + ari_range = 0xffffffff; + ari_code = (ari_code << 16) | InputShort(); + ari_code = (ari_code << 16) | InputShort(); + ari_code = (ari_code << 16) | InputShort(); + }; + + INLINE int DecodeBit(int probability) + { + unsigned int range = (ari_range >> 12) * probability; + if (ari_code >= range) + { + ari_code -= range; ari_range -= range; + if (ari_range < 0x10000) + { + ari_range <<= 16; ari_code = (ari_code << 16) | InputShort(); + } + return 1; + } + ari_range = range; + if (ari_range < 0x10000) + { + ari_range <<= 16; ari_code = (ari_code << 16) | InputShort(); + } + return 0; + } + + INLINE unsigned int DecodeBit() + { + return DecodeBit(2048); + } + + INLINE unsigned int DecodeByte() + { + unsigned int byte = 0; + for (int bit = 7; bit >= 0; --bit) + { + byte += byte + DecodeBit(); + } + return byte; + } + + INLINE unsigned int DecodeWord() + { + unsigned int word = 0; + for (int bit = 31; bit >= 0; --bit) + { + word += word + DecodeBit(); + } + return word; + } + +}; + +#endif + +/*-----------------------------------------------------------*/ +/* End rangecoder.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/common/tables.h b/bsc/libbsc/coder/common/tables.h new file mode 100644 index 0000000..3dd2f23 --- /dev/null +++ b/bsc/libbsc/coder/common/tables.h @@ -0,0 +1,1899 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Static tables of constant values */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_CODER_TABLES_H +#define _LIBBSC_CODER_TABLES_H + +#include "../../platform/platform.h" + +static const int bsc_log2_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 const short bsc_stretch_table[4097] = +{ + -2047,-2047,-1952,-1848,-1774,-1717,-1670,-1631,-1597,-1566,-1539,-1515,-1492,-1472,-1453,-1435, + -1419,-1403,-1388,-1374,-1361,-1349,-1337,-1325,-1314,-1304,-1294,-1284,-1275,-1266,-1257,-1248, + -1240,-1232,-1224,-1217,-1210,-1203,-1196,-1189,-1182,-1176,-1170,-1164,-1158,-1152,-1146,-1141, + -1135,-1130,-1125,-1120,-1115,-1110,-1105,-1100,-1095,-1091,-1086,-1082,-1077,-1073,-1069,-1065, + -1061,-1057,-1053,-1049,-1045,-1041,-1037,-1034,-1030,-1026,-1023,-1019,-1016,-1012,-1009,-1006, + -1002, -999, -996, -993, -990, -987, -984, -981, -978, -975, -972, -969, -966, -963, -960, -958, + -955, -952, -949, -947, -944, -941, -939, -936, -934, -931, -929, -926, -924, -921, -919, -917, + -914, -912, -910, -907, -905, -903, -901, -898, -896, -894, -892, -890, -887, -885, -883, -881, + -879, -877, -875, -873, -871, -869, -867, -865, -863, -861, -859, -857, -855, -853, -852, -850, + -848, -846, -844, -842, -841, -839, -837, -835, -834, -832, -830, -828, -827, -825, -823, -822, + -820, -818, -817, -815, -813, -812, -810, -808, -807, -805, -804, -802, -801, -799, -798, -796, + -794, -793, -791, -790, -788, -787, -785, -784, -783, -781, -780, -778, -777, -775, -774, -773, + -771, -770, -768, -767, -766, -764, -763, -762, -760, -759, -757, -756, -755, -754, -752, -751, + -750, -748, -747, -746, -744, -743, -742, -741, -739, -738, -737, -736, -734, -733, -732, -731, + -730, -728, -727, -726, -725, -724, -722, -721, -720, -719, -718, -717, -715, -714, -713, -712, + -711, -710, -709, -707, -706, -705, -704, -703, -702, -701, -700, -699, -698, -696, -695, -694, + -693, -692, -691, -690, -689, -688, -687, -686, -685, -684, -683, -682, -681, -680, -679, -678, + -677, -676, -675, -674, -673, -672, -671, -670, -669, -668, -667, -666, -665, -664, -663, -662, + -661, -660, -659, -658, -657, -656, -655, -654, -653, -652, -652, -651, -650, -649, -648, -647, + -646, -645, -644, -643, -642, -642, -641, -640, -639, -638, -637, -636, -635, -634, -634, -633, + -632, -631, -630, -629, -628, -628, -627, -626, -625, -624, -623, -622, -622, -621, -620, -619, + -618, -617, -617, -616, -615, -614, -613, -613, -612, -611, -610, -609, -608, -608, -607, -606, + -605, -604, -604, -603, -602, -601, -601, -600, -599, -598, -597, -597, -596, -595, -594, -594, + -593, -592, -591, -590, -590, -589, -588, -587, -587, -586, -585, -584, -584, -583, -582, -582, + -581, -580, -579, -579, -578, -577, -576, -576, -575, -574, -574, -573, -572, -571, -571, -570, + -569, -569, -568, -567, -566, -566, -565, -564, -564, -563, -562, -562, -561, -560, -559, -559, + -558, -557, -557, -556, -555, -555, -554, -553, -553, -552, -551, -551, -550, -549, -549, -548, + -547, -547, -546, -545, -545, -544, -543, -543, -542, -541, -541, -540, -539, -539, -538, -538, + -537, -536, -536, -535, -534, -534, -533, -532, -532, -531, -531, -530, -529, -529, -528, -527, + -527, -526, -526, -525, -524, -524, -523, -522, -522, -521, -521, -520, -519, -519, -518, -518, + -517, -516, -516, -515, -515, -514, -513, -513, -512, -512, -511, -510, -510, -509, -509, -508, + -507, -507, -506, -506, -505, -504, -504, -503, -503, -502, -502, -501, -500, -500, -499, -499, + -498, -498, -497, -496, -496, -495, -495, -494, -494, -493, -492, -492, -491, -491, -490, -490, + -489, -489, -488, -487, -487, -486, -486, -485, -485, -484, -484, -483, -483, -482, -481, -481, + -480, -480, -479, -479, -478, -478, -477, -477, -476, -475, -475, -474, -474, -473, -473, -472, + -472, -471, -471, -470, -470, -469, -469, -468, -468, -467, -467, -466, -465, -465, -464, -464, + -463, -463, -462, -462, -461, -461, -460, -460, -459, -459, -458, -458, -457, -457, -456, -456, + -455, -455, -454, -454, -453, -453, -452, -452, -451, -451, -450, -450, -449, -449, -448, -448, + -447, -447, -446, -446, -445, -445, -444, -444, -443, -443, -442, -442, -441, -441, -440, -440, + -439, -439, -438, -438, -437, -437, -436, -436, -436, -435, -435, -434, -434, -433, -433, -432, + -432, -431, -431, -430, -430, -429, -429, -428, -428, -427, -427, -427, -426, -426, -425, -425, + -424, -424, -423, -423, -422, -422, -421, -421, -421, -420, -420, -419, -419, -418, -418, -417, + -417, -416, -416, -415, -415, -415, -414, -414, -413, -413, -412, -412, -411, -411, -411, -410, + -410, -409, -409, -408, -408, -407, -407, -407, -406, -406, -405, -405, -404, -404, -403, -403, + -403, -402, -402, -401, -401, -400, -400, -399, -399, -399, -398, -398, -397, -397, -396, -396, + -396, -395, -395, -394, -394, -393, -393, -393, -392, -392, -391, -391, -390, -390, -390, -389, + -389, -388, -388, -387, -387, -387, -386, -386, -385, -385, -385, -384, -384, -383, -383, -382, + -382, -382, -381, -381, -380, -380, -380, -379, -379, -378, -378, -377, -377, -377, -376, -376, + -375, -375, -375, -374, -374, -373, -373, -373, -372, -372, -371, -371, -370, -370, -370, -369, + -369, -368, -368, -368, -367, -367, -366, -366, -366, -365, -365, -364, -364, -364, -363, -363, + -362, -362, -362, -361, -361, -360, -360, -360, -359, -359, -359, -358, -358, -357, -357, -357, + -356, -356, -355, -355, -355, -354, -354, -353, -353, -353, -352, -352, -351, -351, -351, -350, + -350, -350, -349, -349, -348, -348, -348, -347, -347, -346, -346, -346, -345, -345, -345, -344, + -344, -343, -343, -343, -342, -342, -342, -341, -341, -340, -340, -340, -339, -339, -338, -338, + -338, -337, -337, -337, -336, -336, -335, -335, -335, -334, -334, -334, -333, -333, -333, -332, + -332, -331, -331, -331, -330, -330, -330, -329, -329, -328, -328, -328, -327, -327, -327, -326, + -326, -326, -325, -325, -324, -324, -324, -323, -323, -323, -322, -322, -322, -321, -321, -320, + -320, -320, -319, -319, -319, -318, -318, -318, -317, -317, -316, -316, -316, -315, -315, -315, + -314, -314, -314, -313, -313, -313, -312, -312, -311, -311, -311, -310, -310, -310, -309, -309, + -309, -308, -308, -308, -307, -307, -307, -306, -306, -305, -305, -305, -304, -304, -304, -303, + -303, -303, -302, -302, -302, -301, -301, -301, -300, -300, -300, -299, -299, -299, -298, -298, + -298, -297, -297, -296, -296, -296, -295, -295, -295, -294, -294, -294, -293, -293, -293, -292, + -292, -292, -291, -291, -291, -290, -290, -290, -289, -289, -289, -288, -288, -288, -287, -287, + -287, -286, -286, -286, -285, -285, -285, -284, -284, -284, -283, -283, -283, -282, -282, -282, + -281, -281, -281, -280, -280, -280, -279, -279, -279, -278, -278, -278, -277, -277, -277, -276, + -276, -276, -275, -275, -275, -274, -274, -274, -273, -273, -273, -272, -272, -272, -271, -271, + -271, -270, -270, -270, -269, -269, -269, -268, -268, -268, -267, -267, -267, -266, -266, -266, + -265, -265, -265, -265, -264, -264, -264, -263, -263, -263, -262, -262, -262, -261, -261, -261, + -260, -260, -260, -259, -259, -259, -258, -258, -258, -257, -257, -257, -257, -256, -256, -256, + -255, -255, -255, -254, -254, -254, -253, -253, -253, -252, -252, -252, -251, -251, -251, -250, + -250, -250, -250, -249, -249, -249, -248, -248, -248, -247, -247, -247, -246, -246, -246, -245, + -245, -245, -245, -244, -244, -244, -243, -243, -243, -242, -242, -242, -241, -241, -241, -241, + -240, -240, -240, -239, -239, -239, -238, -238, -238, -237, -237, -237, -236, -236, -236, -236, + -235, -235, -235, -234, -234, -234, -233, -233, -233, -233, -232, -232, -232, -231, -231, -231, + -230, -230, -230, -229, -229, -229, -229, -228, -228, -228, -227, -227, -227, -226, -226, -226, + -226, -225, -225, -225, -224, -224, -224, -223, -223, -223, -223, -222, -222, -222, -221, -221, + -221, -220, -220, -220, -220, -219, -219, -219, -218, -218, -218, -217, -217, -217, -217, -216, + -216, -216, -215, -215, -215, -214, -214, -214, -214, -213, -213, -213, -212, -212, -212, -212, + -211, -211, -211, -210, -210, -210, -209, -209, -209, -209, -208, -208, -208, -207, -207, -207, + -207, -206, -206, -206, -205, -205, -205, -204, -204, -204, -204, -203, -203, -203, -202, -202, + -202, -202, -201, -201, -201, -200, -200, -200, -200, -199, -199, -199, -198, -198, -198, -197, + -197, -197, -197, -196, -196, -196, -195, -195, -195, -195, -194, -194, -194, -193, -193, -193, + -193, -192, -192, -192, -191, -191, -191, -191, -190, -190, -190, -189, -189, -189, -189, -188, + -188, -188, -187, -187, -187, -187, -186, -186, -186, -185, -185, -185, -185, -184, -184, -184, + -183, -183, -183, -183, -182, -182, -182, -181, -181, -181, -181, -180, -180, -180, -180, -179, + -179, -179, -178, -178, -178, -178, -177, -177, -177, -176, -176, -176, -176, -175, -175, -175, + -174, -174, -174, -174, -173, -173, -173, -172, -172, -172, -172, -171, -171, -171, -171, -170, + -170, -170, -169, -169, -169, -169, -168, -168, -168, -167, -167, -167, -167, -166, -166, -166, + -166, -165, -165, -165, -164, -164, -164, -164, -163, -163, -163, -162, -162, -162, -162, -161, + -161, -161, -161, -160, -160, -160, -159, -159, -159, -159, -158, -158, -158, -158, -157, -157, + -157, -156, -156, -156, -156, -155, -155, -155, -155, -154, -154, -154, -153, -153, -153, -153, + -152, -152, -152, -152, -151, -151, -151, -150, -150, -150, -150, -149, -149, -149, -149, -148, + -148, -148, -147, -147, -147, -147, -146, -146, -146, -146, -145, -145, -145, -144, -144, -144, + -144, -143, -143, -143, -143, -142, -142, -142, -141, -141, -141, -141, -140, -140, -140, -140, + -139, -139, -139, -139, -138, -138, -138, -137, -137, -137, -137, -136, -136, -136, -136, -135, + -135, -135, -135, -134, -134, -134, -133, -133, -133, -133, -132, -132, -132, -132, -131, -131, + -131, -131, -130, -130, -130, -129, -129, -129, -129, -128, -128, -128, -128, -127, -127, -127, + -127, -126, -126, -126, -125, -125, -125, -125, -124, -124, -124, -124, -123, -123, -123, -123, + -122, -122, -122, -121, -121, -121, -121, -120, -120, -120, -120, -119, -119, -119, -119, -118, + -118, -118, -118, -117, -117, -117, -116, -116, -116, -116, -115, -115, -115, -115, -114, -114, + -114, -114, -113, -113, -113, -113, -112, -112, -112, -111, -111, -111, -111, -110, -110, -110, + -110, -109, -109, -109, -109, -108, -108, -108, -108, -107, -107, -107, -107, -106, -106, -106, + -105, -105, -105, -105, -104, -104, -104, -104, -103, -103, -103, -103, -102, -102, -102, -102, + -101, -101, -101, -101, -100, -100, -100, -99, -99, -99, -99, -98, -98, -98, -98, -97, + -97, -97, -97, -96, -96, -96, -96, -95, -95, -95, -95, -94, -94, -94, -94, -93, + -93, -93, -92, -92, -92, -92, -91, -91, -91, -91, -90, -90, -90, -90, -89, -89, + -89, -89, -88, -88, -88, -88, -87, -87, -87, -87, -86, -86, -86, -86, -85, -85, + -85, -85, -84, -84, -84, -83, -83, -83, -83, -82, -82, -82, -82, -81, -81, -81, + -81, -80, -80, -80, -80, -79, -79, -79, -79, -78, -78, -78, -78, -77, -77, -77, + -77, -76, -76, -76, -76, -75, -75, -75, -75, -74, -74, -74, -74, -73, -73, -73, + -72, -72, -72, -72, -71, -71, -71, -71, -70, -70, -70, -70, -69, -69, -69, -69, + -68, -68, -68, -68, -67, -67, -67, -67, -66, -66, -66, -66, -65, -65, -65, -65, + -64, -64, -64, -64, -63, -63, -63, -63, -62, -62, -62, -62, -61, -61, -61, -61, + -60, -60, -60, -60, -59, -59, -59, -59, -58, -58, -58, -57, -57, -57, -57, -56, + -56, -56, -56, -55, -55, -55, -55, -54, -54, -54, -54, -53, -53, -53, -53, -52, + -52, -52, -52, -51, -51, -51, -51, -50, -50, -50, -50, -49, -49, -49, -49, -48, + -48, -48, -48, -47, -47, -47, -47, -46, -46, -46, -46, -45, -45, -45, -45, -44, + -44, -44, -44, -43, -43, -43, -43, -42, -42, -42, -42, -41, -41, -41, -41, -40, + -40, -40, -40, -39, -39, -39, -39, -38, -38, -38, -38, -37, -37, -37, -37, -36, + -36, -36, -36, -35, -35, -35, -35, -34, -34, -34, -34, -33, -33, -33, -33, -32, + -32, -32, -32, -31, -31, -31, -31, -30, -30, -30, -30, -29, -29, -29, -29, -28, + -28, -28, -28, -27, -27, -27, -27, -26, -26, -26, -26, -25, -25, -25, -25, -24, + -24, -24, -24, -23, -23, -23, -23, -22, -22, -22, -22, -21, -21, -21, -21, -20, + -20, -20, -20, -19, -19, -19, -19, -18, -18, -18, -18, -17, -17, -17, -17, -16, + -16, -16, -16, -15, -15, -15, -15, -14, -14, -14, -14, -13, -13, -13, -13, -12, + -12, -12, -12, -11, -11, -11, -11, -10, -10, -10, -10, -9, -9, -9, -9, -8, + -8, -8, -8, -7, -7, -7, -7, -6, -6, -6, -6, -5, -5, -5, -5, -4, + -4, -4, -4, -3, -3, -3, -3, -2, -2, -2, -2, -1, -1, -1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, + 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, + 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, + 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, + 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, + 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, + 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, + 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, + 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, + 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, + 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, + 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, + 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, + 56, 56, 57, 57, 57, 57, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, + 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, 64, 64, 64, + 64, 65, 65, 65, 65, 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, + 68, 69, 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, + 72, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76, + 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, 80, 80, 80, 80, + 81, 81, 81, 81, 82, 82, 82, 82, 83, 83, 83, 83, 84, 84, 84, 85, + 85, 85, 85, 86, 86, 86, 86, 87, 87, 87, 87, 88, 88, 88, 88, 89, + 89, 89, 89, 90, 90, 90, 90, 91, 91, 91, 91, 92, 92, 92, 92, 93, + 93, 93, 94, 94, 94, 94, 95, 95, 95, 95, 96, 96, 96, 96, 97, 97, + 97, 97, 98, 98, 98, 98, 99, 99, 99, 99, 100, 100, 100, 101, 101, 101, + 101, 102, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 104, 105, 105, 105, + 105, 106, 106, 106, 107, 107, 107, 107, 108, 108, 108, 108, 109, 109, 109, 109, + 110, 110, 110, 110, 111, 111, 111, 111, 112, 112, 112, 113, 113, 113, 113, 114, + 114, 114, 114, 115, 115, 115, 115, 116, 116, 116, 116, 117, 117, 117, 118, 118, + 118, 118, 119, 119, 119, 119, 120, 120, 120, 120, 121, 121, 121, 121, 122, 122, + 122, 123, 123, 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 126, 126, 126, + 127, 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 131, + 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 135, 135, + 135, 135, 136, 136, 136, 136, 137, 137, 137, 137, 138, 138, 138, 139, 139, 139, + 139, 140, 140, 140, 140, 141, 141, 141, 141, 142, 142, 142, 143, 143, 143, 143, + 144, 144, 144, 144, 145, 145, 145, 146, 146, 146, 146, 147, 147, 147, 147, 148, + 148, 148, 149, 149, 149, 149, 150, 150, 150, 150, 151, 151, 151, 152, 152, 152, + 152, 153, 153, 153, 153, 154, 154, 154, 155, 155, 155, 155, 156, 156, 156, 156, + 157, 157, 157, 158, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 161, 161, + 161, 161, 162, 162, 162, 162, 163, 163, 163, 164, 164, 164, 164, 165, 165, 165, + 166, 166, 166, 166, 167, 167, 167, 167, 168, 168, 168, 169, 169, 169, 169, 170, + 170, 170, 171, 171, 171, 171, 172, 172, 172, 172, 173, 173, 173, 174, 174, 174, + 174, 175, 175, 175, 176, 176, 176, 176, 177, 177, 177, 178, 178, 178, 178, 179, + 179, 179, 180, 180, 180, 180, 181, 181, 181, 181, 182, 182, 182, 183, 183, 183, + 183, 184, 184, 184, 185, 185, 185, 185, 186, 186, 186, 187, 187, 187, 187, 188, + 188, 188, 189, 189, 189, 189, 190, 190, 190, 191, 191, 191, 191, 192, 192, 192, + 193, 193, 193, 193, 194, 194, 194, 195, 195, 195, 195, 196, 196, 196, 197, 197, + 197, 197, 198, 198, 198, 199, 199, 199, 200, 200, 200, 200, 201, 201, 201, 202, + 202, 202, 202, 203, 203, 203, 204, 204, 204, 204, 205, 205, 205, 206, 206, 206, + 207, 207, 207, 207, 208, 208, 208, 209, 209, 209, 209, 210, 210, 210, 211, 211, + 211, 212, 212, 212, 212, 213, 213, 213, 214, 214, 214, 214, 215, 215, 215, 216, + 216, 216, 217, 217, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 220, 220, + 221, 221, 221, 222, 222, 222, 223, 223, 223, 223, 224, 224, 224, 225, 225, 225, + 226, 226, 226, 226, 227, 227, 227, 228, 228, 228, 229, 229, 229, 229, 230, 230, + 230, 231, 231, 231, 232, 232, 232, 233, 233, 233, 233, 234, 234, 234, 235, 235, + 235, 236, 236, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 239, 240, 240, + 240, 241, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, + 245, 245, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, + 250, 250, 251, 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255, 255, + 255, 256, 256, 256, 257, 257, 257, 257, 258, 258, 258, 259, 259, 259, 260, 260, + 260, 261, 261, 261, 262, 262, 262, 263, 263, 263, 264, 264, 264, 265, 265, 265, + 265, 266, 266, 266, 267, 267, 267, 268, 268, 268, 269, 269, 269, 270, 270, 270, + 271, 271, 271, 272, 272, 272, 273, 273, 273, 274, 274, 274, 275, 275, 275, 276, + 276, 276, 277, 277, 277, 278, 278, 278, 279, 279, 279, 280, 280, 280, 281, 281, + 281, 282, 282, 282, 283, 283, 283, 284, 284, 284, 285, 285, 285, 286, 286, 286, + 287, 287, 287, 288, 288, 288, 289, 289, 289, 290, 290, 290, 291, 291, 291, 292, + 292, 292, 293, 293, 293, 294, 294, 294, 295, 295, 295, 296, 296, 296, 297, 297, + 298, 298, 298, 299, 299, 299, 300, 300, 300, 301, 301, 301, 302, 302, 302, 303, + 303, 303, 304, 304, 304, 305, 305, 305, 306, 306, 307, 307, 307, 308, 308, 308, + 309, 309, 309, 310, 310, 310, 311, 311, 311, 312, 312, 313, 313, 313, 314, 314, + 314, 315, 315, 315, 316, 316, 316, 317, 317, 318, 318, 318, 319, 319, 319, 320, + 320, 320, 321, 321, 322, 322, 322, 323, 323, 323, 324, 324, 324, 325, 325, 326, + 326, 326, 327, 327, 327, 328, 328, 328, 329, 329, 330, 330, 330, 331, 331, 331, + 332, 332, 333, 333, 333, 334, 334, 334, 335, 335, 335, 336, 336, 337, 337, 337, + 338, 338, 338, 339, 339, 340, 340, 340, 341, 341, 342, 342, 342, 343, 343, 343, + 344, 344, 345, 345, 345, 346, 346, 346, 347, 347, 348, 348, 348, 349, 349, 350, + 350, 350, 351, 351, 351, 352, 352, 353, 353, 353, 354, 354, 355, 355, 355, 356, + 356, 357, 357, 357, 358, 358, 359, 359, 359, 360, 360, 360, 361, 361, 362, 362, + 362, 363, 363, 364, 364, 364, 365, 365, 366, 366, 366, 367, 367, 368, 368, 368, + 369, 369, 370, 370, 370, 371, 371, 372, 372, 373, 373, 373, 374, 374, 375, 375, + 375, 376, 376, 377, 377, 377, 378, 378, 379, 379, 380, 380, 380, 381, 381, 382, + 382, 382, 383, 383, 384, 384, 385, 385, 385, 386, 386, 387, 387, 387, 388, 388, + 389, 389, 390, 390, 390, 391, 391, 392, 392, 393, 393, 393, 394, 394, 395, 395, + 396, 396, 396, 397, 397, 398, 398, 399, 399, 399, 400, 400, 401, 401, 402, 402, + 403, 403, 403, 404, 404, 405, 405, 406, 406, 407, 407, 407, 408, 408, 409, 409, + 410, 410, 411, 411, 411, 412, 412, 413, 413, 414, 414, 415, 415, 415, 416, 416, + 417, 417, 418, 418, 419, 419, 420, 420, 421, 421, 421, 422, 422, 423, 423, 424, + 424, 425, 425, 426, 426, 427, 427, 427, 428, 428, 429, 429, 430, 430, 431, 431, + 432, 432, 433, 433, 434, 434, 435, 435, 436, 436, 436, 437, 437, 438, 438, 439, + 439, 440, 440, 441, 441, 442, 442, 443, 443, 444, 444, 445, 445, 446, 446, 447, + 447, 448, 448, 449, 449, 450, 450, 451, 451, 452, 452, 453, 453, 454, 454, 455, + 455, 456, 456, 457, 457, 458, 458, 459, 459, 460, 460, 461, 461, 462, 462, 463, + 463, 464, 464, 465, 465, 466, 467, 467, 468, 468, 469, 469, 470, 470, 471, 471, + 472, 472, 473, 473, 474, 474, 475, 475, 476, 477, 477, 478, 478, 479, 479, 480, + 480, 481, 481, 482, 483, 483, 484, 484, 485, 485, 486, 486, 487, 487, 488, 489, + 489, 490, 490, 491, 491, 492, 492, 493, 494, 494, 495, 495, 496, 496, 497, 498, + 498, 499, 499, 500, 500, 501, 502, 502, 503, 503, 504, 504, 505, 506, 506, 507, + 507, 508, 509, 509, 510, 510, 511, 512, 512, 513, 513, 514, 515, 515, 516, 516, + 517, 518, 518, 519, 519, 520, 521, 521, 522, 522, 523, 524, 524, 525, 526, 526, + 527, 527, 528, 529, 529, 530, 531, 531, 532, 532, 533, 534, 534, 535, 536, 536, + 537, 538, 538, 539, 539, 540, 541, 541, 542, 543, 543, 544, 545, 545, 546, 547, + 547, 548, 549, 549, 550, 551, 551, 552, 553, 553, 554, 555, 555, 556, 557, 557, + 558, 559, 559, 560, 561, 562, 562, 563, 564, 564, 565, 566, 566, 567, 568, 569, + 569, 570, 571, 571, 572, 573, 574, 574, 575, 576, 576, 577, 578, 579, 579, 580, + 581, 582, 582, 583, 584, 584, 585, 586, 587, 587, 588, 589, 590, 590, 591, 592, + 593, 594, 594, 595, 596, 597, 597, 598, 599, 600, 601, 601, 602, 603, 604, 604, + 605, 606, 607, 608, 608, 609, 610, 611, 612, 613, 613, 614, 615, 616, 617, 617, + 618, 619, 620, 621, 622, 622, 623, 624, 625, 626, 627, 628, 628, 629, 630, 631, + 632, 633, 634, 634, 635, 636, 637, 638, 639, 640, 641, 642, 642, 643, 644, 645, + 646, 647, 648, 649, 650, 651, 652, 652, 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, + 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, + 693, 694, 695, 696, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 709, 710, + 711, 712, 713, 714, 715, 717, 718, 719, 720, 721, 722, 724, 725, 726, 727, 728, + 730, 731, 732, 733, 734, 736, 737, 738, 739, 741, 742, 743, 744, 746, 747, 748, + 750, 751, 752, 754, 755, 756, 757, 759, 760, 762, 763, 764, 766, 767, 768, 770, + 771, 773, 774, 775, 777, 778, 780, 781, 783, 784, 785, 787, 788, 790, 791, 793, + 794, 796, 798, 799, 801, 802, 804, 805, 807, 808, 810, 812, 813, 815, 817, 818, + 820, 822, 823, 825, 827, 828, 830, 832, 834, 835, 837, 839, 841, 842, 844, 846, + 848, 850, 852, 853, 855, 857, 859, 861, 863, 865, 867, 869, 871, 873, 875, 877, + 879, 881, 883, 885, 887, 890, 892, 894, 896, 898, 901, 903, 905, 907, 910, 912, + 914, 917, 919, 921, 924, 926, 929, 931, 934, 936, 939, 941, 944, 947, 949, 952, + 955, 958, 960, 963, 966, 969, 972, 975, 978, 981, 984, 987, 990, 993, 996, 999, + 1002, 1006, 1009, 1012, 1016, 1019, 1023, 1026, 1030, 1034, 1037, 1041, 1045, 1049, 1053, 1057, + 1061, 1065, 1069, 1073, 1077, 1082, 1086, 1091, 1095, 1100, 1105, 1110, 1115, 1120, 1125, 1130, + 1135, 1141, 1146, 1152, 1158, 1164, 1170, 1176, 1182, 1189, 1196, 1203, 1210, 1217, 1224, 1232, + 1240, 1248, 1257, 1266, 1275, 1284, 1294, 1304, 1314, 1325, 1337, 1349, 1361, 1374, 1388, 1403, + 1419, 1435, 1453, 1472, 1492, 1515, 1539, 1566, 1597, 1631, 1670, 1717, 1774, 1848, 1952, 2047, + 2047 +}; + +static const short bsc_squash_table[4097] = +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 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, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 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, 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, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 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, 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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, + 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 35, + 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, + 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, + 39, 39, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, + 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, + 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, + 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, + 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 54, + 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, + 57, 57, 58, 58, 58, 58, 59, 59, 59, 59, 59, 60, 60, 60, 60, 61, + 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, 64, 64, 64, 64, 65, + 65, 65, 65, 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 69, + 69, 69, 69, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 72, 73, 73, + 73, 74, 74, 74, 74, 75, 75, 75, 76, 76, 76, 76, 77, 77, 77, 78, + 78, 78, 79, 79, 79, 79, 80, 80, 80, 81, 81, 81, 82, 82, 82, 83, + 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 88, 88, + 88, 89, 89, 89, 90, 90, 90, 91, 91, 91, 92, 92, 92, 93, 93, 93, + 94, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 99, 99, 99, + 100, 100, 100, 101, 101, 102, 102, 102, 103, 103, 104, 104, 104, 105, 105, 106, + 106, 106, 107, 107, 108, 108, 108, 109, 109, 110, 110, 111, 111, 111, 112, 112, + 113, 113, 114, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 118, 119, 119, + 120, 120, 121, 121, 122, 122, 123, 123, 123, 124, 124, 125, 125, 126, 126, 127, + 127, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 135, + 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 142, 142, 143, 143, + 144, 144, 145, 145, 146, 146, 147, 148, 148, 149, 149, 150, 150, 151, 152, 152, + 153, 153, 154, 154, 155, 156, 156, 157, 157, 158, 159, 159, 160, 160, 161, 162, + 162, 163, 163, 164, 165, 165, 166, 166, 167, 168, 168, 169, 170, 170, 171, 172, + 172, 173, 174, 174, 175, 175, 176, 177, 177, 178, 179, 179, 180, 181, 181, 182, + 183, 184, 184, 185, 186, 186, 187, 188, 188, 189, 190, 191, 191, 192, 193, 193, + 194, 195, 196, 196, 197, 198, 199, 199, 200, 201, 201, 202, 203, 204, 205, 205, + 206, 207, 208, 208, 209, 210, 211, 211, 212, 213, 214, 215, 215, 216, 217, 218, + 219, 219, 220, 221, 222, 223, 224, 224, 225, 226, 227, 228, 229, 229, 230, 231, + 232, 233, 234, 235, 235, 236, 237, 238, 239, 240, 241, 242, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 310, + 311, 312, 313, 314, 315, 316, 317, 319, 320, 321, 322, 323, 324, 326, 327, 328, + 329, 330, 331, 333, 334, 335, 336, 337, 339, 340, 341, 342, 344, 345, 346, 347, + 348, 350, 351, 352, 353, 355, 356, 357, 359, 360, 361, 362, 364, 365, 366, 368, + 369, 370, 371, 373, 374, 375, 377, 378, 379, 381, 382, 384, 385, 386, 388, 389, + 390, 392, 393, 395, 396, 397, 399, 400, 402, 403, 404, 406, 407, 409, 410, 412, + 413, 414, 416, 417, 419, 420, 422, 423, 425, 426, 428, 429, 431, 432, 434, 435, + 437, 438, 440, 441, 443, 444, 446, 448, 449, 451, 452, 454, 455, 457, 459, 460, + 462, 463, 465, 467, 468, 470, 471, 473, 475, 476, 478, 480, 481, 483, 485, 486, + 488, 490, 491, 493, 495, 496, 498, 500, 501, 503, 505, 507, 508, 510, 512, 514, + 515, 517, 519, 521, 522, 524, 526, 528, 530, 531, 533, 535, 537, 539, 541, 542, + 544, 546, 548, 550, 552, 553, 555, 557, 559, 561, 563, 565, 567, 569, 571, 572, + 574, 576, 578, 580, 582, 584, 586, 588, 590, 592, 594, 596, 598, 600, 602, 604, + 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, 626, 628, 631, 633, 635, 637, + 639, 641, 643, 645, 647, 650, 652, 654, 656, 658, 660, 663, 665, 667, 669, 671, + 673, 676, 678, 680, 682, 685, 687, 689, 691, 694, 696, 698, 700, 703, 705, 707, + 709, 712, 714, 716, 719, 721, 723, 726, 728, 730, 733, 735, 737, 740, 742, 745, + 747, 749, 752, 754, 757, 759, 761, 764, 766, 769, 771, 774, 776, 778, 781, 783, + 786, 788, 791, 793, 796, 798, 801, 803, 806, 809, 811, 814, 816, 819, 821, 824, + 826, 829, 832, 834, 837, 839, 842, 845, 847, 850, 853, 855, 858, 860, 863, 866, + 868, 871, 874, 877, 879, 882, 885, 887, 890, 893, 896, 898, 901, 904, 907, 909, + 912, 915, 918, 920, 923, 926, 929, 932, 934, 937, 940, 943, 946, 949, 951, 954, + 957, 960, 963, 966, 969, 972, 975, 977, 980, 983, 986, 989, 992, 995, 998, 1001, + 1004, 1007, 1010, 1013, 1016, 1019, 1022, 1025, 1028, 1031, 1034, 1037, 1040, 1043, 1046, 1049, + 1052, 1055, 1058, 1061, 1064, 1067, 1070, 1073, 1077, 1080, 1083, 1086, 1089, 1092, 1095, 1098, + 1102, 1105, 1108, 1111, 1114, 1117, 1120, 1124, 1127, 1130, 1133, 1136, 1140, 1143, 1146, 1149, + 1153, 1156, 1159, 1162, 1165, 1169, 1172, 1175, 1179, 1182, 1185, 1188, 1192, 1195, 1198, 1202, + 1205, 1208, 1212, 1215, 1218, 1222, 1225, 1228, 1232, 1235, 1238, 1242, 1245, 1249, 1252, 1255, + 1259, 1262, 1266, 1269, 1272, 1276, 1279, 1283, 1286, 1290, 1293, 1296, 1300, 1303, 1307, 1310, + 1314, 1317, 1321, 1324, 1328, 1331, 1335, 1338, 1342, 1345, 1349, 1352, 1356, 1360, 1363, 1367, + 1370, 1374, 1377, 1381, 1384, 1388, 1392, 1395, 1399, 1402, 1406, 1410, 1413, 1417, 1420, 1424, + 1428, 1431, 1435, 1439, 1442, 1446, 1450, 1453, 1457, 1461, 1464, 1468, 1472, 1475, 1479, 1483, + 1486, 1490, 1494, 1497, 1501, 1505, 1509, 1512, 1516, 1520, 1524, 1527, 1531, 1535, 1539, 1542, + 1546, 1550, 1554, 1557, 1561, 1565, 1569, 1572, 1576, 1580, 1584, 1588, 1591, 1595, 1599, 1603, + 1607, 1610, 1614, 1618, 1622, 1626, 1630, 1633, 1637, 1641, 1645, 1649, 1653, 1656, 1660, 1664, + 1668, 1672, 1676, 1680, 1683, 1687, 1691, 1695, 1699, 1703, 1707, 1711, 1715, 1718, 1722, 1726, + 1730, 1734, 1738, 1742, 1746, 1750, 1754, 1758, 1761, 1765, 1769, 1773, 1777, 1781, 1785, 1789, + 1793, 1797, 1801, 1805, 1809, 1813, 1817, 1820, 1824, 1828, 1832, 1836, 1840, 1844, 1848, 1852, + 1856, 1860, 1864, 1868, 1872, 1876, 1880, 1884, 1888, 1892, 1896, 1900, 1904, 1908, 1912, 1916, + 1920, 1924, 1928, 1932, 1936, 1940, 1944, 1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, + 1984, 1988, 1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2044, + 2048, 2052, 2056, 2059, 2063, 2067, 2071, 2075, 2079, 2083, 2087, 2091, 2095, 2099, 2103, 2107, + 2111, 2115, 2119, 2123, 2127, 2131, 2135, 2139, 2143, 2147, 2151, 2155, 2159, 2163, 2167, 2171, + 2175, 2179, 2183, 2187, 2191, 2195, 2199, 2203, 2207, 2211, 2215, 2219, 2223, 2227, 2231, 2235, + 2239, 2243, 2247, 2251, 2255, 2259, 2263, 2267, 2271, 2275, 2279, 2282, 2286, 2290, 2294, 2298, + 2302, 2306, 2310, 2314, 2318, 2322, 2326, 2330, 2334, 2338, 2341, 2345, 2349, 2353, 2357, 2361, + 2365, 2369, 2373, 2377, 2381, 2384, 2388, 2392, 2396, 2400, 2404, 2408, 2412, 2416, 2419, 2423, + 2427, 2431, 2435, 2439, 2443, 2446, 2450, 2454, 2458, 2462, 2466, 2469, 2473, 2477, 2481, 2485, + 2489, 2492, 2496, 2500, 2504, 2508, 2511, 2515, 2519, 2523, 2527, 2530, 2534, 2538, 2542, 2545, + 2549, 2553, 2557, 2560, 2564, 2568, 2572, 2575, 2579, 2583, 2587, 2590, 2594, 2598, 2602, 2605, + 2609, 2613, 2616, 2620, 2624, 2627, 2631, 2635, 2638, 2642, 2646, 2649, 2653, 2657, 2660, 2664, + 2668, 2671, 2675, 2679, 2682, 2686, 2689, 2693, 2697, 2700, 2704, 2707, 2711, 2715, 2718, 2722, + 2725, 2729, 2732, 2736, 2739, 2743, 2747, 2750, 2754, 2757, 2761, 2764, 2768, 2771, 2775, 2778, + 2782, 2785, 2789, 2792, 2796, 2799, 2803, 2806, 2809, 2813, 2816, 2820, 2823, 2827, 2830, 2833, + 2837, 2840, 2844, 2847, 2850, 2854, 2857, 2861, 2864, 2867, 2871, 2874, 2877, 2881, 2884, 2887, + 2891, 2894, 2897, 2901, 2904, 2907, 2911, 2914, 2917, 2920, 2924, 2927, 2930, 2934, 2937, 2940, + 2943, 2946, 2950, 2953, 2956, 2959, 2963, 2966, 2969, 2972, 2975, 2979, 2982, 2985, 2988, 2991, + 2994, 2997, 3001, 3004, 3007, 3010, 3013, 3016, 3019, 3022, 3026, 3029, 3032, 3035, 3038, 3041, + 3044, 3047, 3050, 3053, 3056, 3059, 3062, 3065, 3068, 3071, 3074, 3077, 3080, 3083, 3086, 3089, + 3092, 3095, 3098, 3101, 3104, 3107, 3110, 3113, 3116, 3118, 3121, 3124, 3127, 3130, 3133, 3136, + 3139, 3142, 3144, 3147, 3150, 3153, 3156, 3159, 3161, 3164, 3167, 3170, 3173, 3175, 3178, 3181, + 3184, 3186, 3189, 3192, 3195, 3197, 3200, 3203, 3206, 3208, 3211, 3214, 3216, 3219, 3222, 3225, + 3227, 3230, 3233, 3235, 3238, 3240, 3243, 3246, 3248, 3251, 3254, 3256, 3259, 3261, 3264, 3267, + 3269, 3272, 3274, 3277, 3279, 3282, 3284, 3287, 3290, 3292, 3295, 3297, 3300, 3302, 3305, 3307, + 3310, 3312, 3315, 3317, 3319, 3322, 3324, 3327, 3329, 3332, 3334, 3336, 3339, 3341, 3344, 3346, + 3348, 3351, 3353, 3356, 3358, 3360, 3363, 3365, 3367, 3370, 3372, 3374, 3377, 3379, 3381, 3384, + 3386, 3388, 3390, 3393, 3395, 3397, 3399, 3402, 3404, 3406, 3408, 3411, 3413, 3415, 3417, 3420, + 3422, 3424, 3426, 3428, 3430, 3433, 3435, 3437, 3439, 3441, 3443, 3446, 3448, 3450, 3452, 3454, + 3456, 3458, 3460, 3462, 3465, 3467, 3469, 3471, 3473, 3475, 3477, 3479, 3481, 3483, 3485, 3487, + 3489, 3491, 3493, 3495, 3497, 3499, 3501, 3503, 3505, 3507, 3509, 3511, 3513, 3515, 3517, 3519, + 3521, 3523, 3525, 3526, 3528, 3530, 3532, 3534, 3536, 3538, 3540, 3542, 3544, 3545, 3547, 3549, + 3551, 3553, 3555, 3556, 3558, 3560, 3562, 3564, 3566, 3567, 3569, 3571, 3573, 3575, 3576, 3578, + 3580, 3582, 3583, 3585, 3587, 3589, 3590, 3592, 3594, 3596, 3597, 3599, 3601, 3602, 3604, 3606, + 3607, 3609, 3611, 3612, 3614, 3616, 3617, 3619, 3621, 3622, 3624, 3626, 3627, 3629, 3630, 3632, + 3634, 3635, 3637, 3638, 3640, 3642, 3643, 3645, 3646, 3648, 3649, 3651, 3653, 3654, 3656, 3657, + 3659, 3660, 3662, 3663, 3665, 3666, 3668, 3669, 3671, 3672, 3674, 3675, 3677, 3678, 3680, 3681, + 3683, 3684, 3685, 3687, 3688, 3690, 3691, 3693, 3694, 3695, 3697, 3698, 3700, 3701, 3702, 3704, + 3705, 3707, 3708, 3709, 3711, 3712, 3713, 3715, 3716, 3718, 3719, 3720, 3722, 3723, 3724, 3726, + 3727, 3728, 3729, 3731, 3732, 3733, 3735, 3736, 3737, 3738, 3740, 3741, 3742, 3744, 3745, 3746, + 3747, 3749, 3750, 3751, 3752, 3753, 3755, 3756, 3757, 3758, 3760, 3761, 3762, 3763, 3764, 3766, + 3767, 3768, 3769, 3770, 3771, 3773, 3774, 3775, 3776, 3777, 3778, 3780, 3781, 3782, 3783, 3784, + 3785, 3786, 3787, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3800, 3801, 3802, + 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, + 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, + 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3843, 3844, 3845, 3846, 3847, 3848, 3849, + 3850, 3851, 3852, 3853, 3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3860, 3861, 3862, 3863, + 3864, 3865, 3866, 3866, 3867, 3868, 3869, 3870, 3871, 3871, 3872, 3873, 3874, 3875, 3876, 3876, + 3877, 3878, 3879, 3880, 3880, 3881, 3882, 3883, 3884, 3884, 3885, 3886, 3887, 3887, 3888, 3889, + 3890, 3890, 3891, 3892, 3893, 3894, 3894, 3895, 3896, 3896, 3897, 3898, 3899, 3899, 3900, 3901, + 3902, 3902, 3903, 3904, 3904, 3905, 3906, 3907, 3907, 3908, 3909, 3909, 3910, 3911, 3911, 3912, + 3913, 3914, 3914, 3915, 3916, 3916, 3917, 3918, 3918, 3919, 3920, 3920, 3921, 3921, 3922, 3923, + 3923, 3924, 3925, 3925, 3926, 3927, 3927, 3928, 3929, 3929, 3930, 3930, 3931, 3932, 3932, 3933, + 3933, 3934, 3935, 3935, 3936, 3936, 3937, 3938, 3938, 3939, 3939, 3940, 3941, 3941, 3942, 3942, + 3943, 3943, 3944, 3945, 3945, 3946, 3946, 3947, 3947, 3948, 3949, 3949, 3950, 3950, 3951, 3951, + 3952, 3952, 3953, 3953, 3954, 3955, 3955, 3956, 3956, 3957, 3957, 3958, 3958, 3959, 3959, 3960, + 3960, 3961, 3961, 3962, 3962, 3963, 3963, 3964, 3964, 3965, 3965, 3966, 3966, 3967, 3967, 3968, + 3968, 3969, 3969, 3970, 3970, 3971, 3971, 3972, 3972, 3972, 3973, 3973, 3974, 3974, 3975, 3975, + 3976, 3976, 3977, 3977, 3977, 3978, 3978, 3979, 3979, 3980, 3980, 3981, 3981, 3981, 3982, 3982, + 3983, 3983, 3984, 3984, 3984, 3985, 3985, 3986, 3986, 3987, 3987, 3987, 3988, 3988, 3989, 3989, + 3989, 3990, 3990, 3991, 3991, 3991, 3992, 3992, 3993, 3993, 3993, 3994, 3994, 3995, 3995, 3995, + 3996, 3996, 3996, 3997, 3997, 3998, 3998, 3998, 3999, 3999, 3999, 4000, 4000, 4000, 4001, 4001, + 4002, 4002, 4002, 4003, 4003, 4003, 4004, 4004, 4004, 4005, 4005, 4005, 4006, 4006, 4006, 4007, + 4007, 4007, 4008, 4008, 4008, 4009, 4009, 4009, 4010, 4010, 4010, 4011, 4011, 4011, 4012, 4012, + 4012, 4013, 4013, 4013, 4014, 4014, 4014, 4015, 4015, 4015, 4016, 4016, 4016, 4016, 4017, 4017, + 4017, 4018, 4018, 4018, 4019, 4019, 4019, 4019, 4020, 4020, 4020, 4021, 4021, 4021, 4021, 4022, + 4022, 4022, 4023, 4023, 4023, 4023, 4024, 4024, 4024, 4024, 4025, 4025, 4025, 4026, 4026, 4026, + 4026, 4027, 4027, 4027, 4027, 4028, 4028, 4028, 4028, 4029, 4029, 4029, 4029, 4030, 4030, 4030, + 4030, 4031, 4031, 4031, 4031, 4032, 4032, 4032, 4032, 4033, 4033, 4033, 4033, 4034, 4034, 4034, + 4034, 4035, 4035, 4035, 4035, 4036, 4036, 4036, 4036, 4036, 4037, 4037, 4037, 4037, 4038, 4038, + 4038, 4038, 4038, 4039, 4039, 4039, 4039, 4040, 4040, 4040, 4040, 4040, 4041, 4041, 4041, 4041, + 4041, 4042, 4042, 4042, 4042, 4042, 4043, 4043, 4043, 4043, 4043, 4044, 4044, 4044, 4044, 4044, + 4045, 4045, 4045, 4045, 4045, 4046, 4046, 4046, 4046, 4046, 4047, 4047, 4047, 4047, 4047, 4048, + 4048, 4048, 4048, 4048, 4048, 4049, 4049, 4049, 4049, 4049, 4050, 4050, 4050, 4050, 4050, 4050, + 4051, 4051, 4051, 4051, 4051, 4051, 4052, 4052, 4052, 4052, 4052, 4052, 4053, 4053, 4053, 4053, + 4053, 4053, 4054, 4054, 4054, 4054, 4054, 4054, 4055, 4055, 4055, 4055, 4055, 4055, 4056, 4056, + 4056, 4056, 4056, 4056, 4056, 4057, 4057, 4057, 4057, 4057, 4057, 4057, 4058, 4058, 4058, 4058, + 4058, 4058, 4058, 4059, 4059, 4059, 4059, 4059, 4059, 4059, 4060, 4060, 4060, 4060, 4060, 4060, + 4060, 4061, 4061, 4061, 4061, 4061, 4061, 4061, 4062, 4062, 4062, 4062, 4062, 4062, 4062, 4062, + 4063, 4063, 4063, 4063, 4063, 4063, 4063, 4063, 4064, 4064, 4064, 4064, 4064, 4064, 4064, 4064, + 4065, 4065, 4065, 4065, 4065, 4065, 4065, 4065, 4065, 4066, 4066, 4066, 4066, 4066, 4066, 4066, + 4066, 4066, 4067, 4067, 4067, 4067, 4067, 4067, 4067, 4067, 4067, 4068, 4068, 4068, 4068, 4068, + 4068, 4068, 4068, 4068, 4069, 4069, 4069, 4069, 4069, 4069, 4069, 4069, 4069, 4069, 4070, 4070, + 4070, 4070, 4070, 4070, 4070, 4070, 4070, 4070, 4071, 4071, 4071, 4071, 4071, 4071, 4071, 4071, + 4071, 4071, 4072, 4072, 4072, 4072, 4072, 4072, 4072, 4072, 4072, 4072, 4072, 4073, 4073, 4073, + 4073, 4073, 4073, 4073, 4073, 4073, 4073, 4073, 4073, 4074, 4074, 4074, 4074, 4074, 4074, 4074, + 4074, 4074, 4074, 4074, 4074, 4075, 4075, 4075, 4075, 4075, 4075, 4075, 4075, 4075, 4075, 4075, + 4075, 4076, 4076, 4076, 4076, 4076, 4076, 4076, 4076, 4076, 4076, 4076, 4076, 4076, 4077, 4077, + 4077, 4077, 4077, 4077, 4077, 4077, 4077, 4077, 4077, 4077, 4077, 4077, 4078, 4078, 4078, 4078, + 4078, 4078, 4078, 4078, 4078, 4078, 4078, 4078, 4078, 4078, 4078, 4079, 4079, 4079, 4079, 4079, + 4079, 4079, 4079, 4079, 4079, 4079, 4079, 4079, 4079, 4079, 4079, 4080, 4080, 4080, 4080, 4080, + 4080, 4080, 4080, 4080, 4080, 4080, 4080, 4080, 4080, 4080, 4080, 4081, 4081, 4081, 4081, 4081, + 4081, 4081, 4081, 4081, 4081, 4081, 4081, 4081, 4081, 4081, 4081, 4081, 4081, 4082, 4082, 4082, + 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, 4082, + 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, 4083, + 4083, 4083, 4083, 4083, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, + 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4085, 4085, 4085, 4085, 4085, + 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, + 4085, 4085, 4085, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, + 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4087, 4087, + 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, + 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4087, 4088, 4088, 4088, + 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, + 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4088, 4089, + 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, + 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, 4089, + 4089, 4089, 4089, 4089, 4089, 4089, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, + 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, + 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, 4090, + 4090, 4090, 4090, 4090, 4090, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, + 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, + 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, + 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4091, 4092, 4092, + 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, + 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, + 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, + 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, + 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4092, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, + 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, + 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, + 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, + 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, + 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, + 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, 4093, + 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, + 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, + 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, + 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, + 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, + 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4094, 4095, + 4095 +}; + +static const unsigned char model_rank_state_table[32768] = +{ + 224, 0, 0, 0, 0, 0, 0, 0, 205, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 6, 176, 18, 11, 35, 46, 124, 159, 6, 75, 207, 180, 229, 24, 0, 234, 6, 176, 124, 231, 53, 209, 0, 110, 62, 176, 243, 53, 41, 38, + 0, 140, 6, 176, 241, 109, 42, 65, 120, 234, 6, 44, 92, 156, 183, 20, 0, 234, 206, 75, 18, 165, 253, 190, 0, 62, 62, 176, 99, 99, 198, 20, + 0, 54, 62, 176, 109, 42, 111, 244, 0, 74, 62, 176, 219, 170, 42, 0, 0, 21, 62, 241, 138, 5, 167, 12, 0, 107, 110, 176, 5, 218, 111, 183, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 234, 74, 254, 161, 180, 0, 0, 0, 16, 228, 176, 127, 232, 197, 166, 0, 141, 21, 197, 5, 212, 182, 0, 0, 246, 21, 3, 211, 92, 35, 150, + 0, 185, 52, 176, 1, 235, 10, 253, 0, 191, 54, 197, 3, 216, 219, 46, 0, 45, 47, 197, 73, 35, 0, 50, 0, 230, 6, 5, 243, 42, 76, 60, + 0, 82, 47, 115, 204, 31, 126, 164, 0, 172, 2, 176, 161, 4, 23, 0, 0, 57, 74, 30, 222, 0, 53, 0, 0, 62, 62, 176, 5, 128, 109, 190, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 26, 89, 192, 99, 62, 187, 0, 47, 74, 176, 194, 156, 216, 218, 0, 234, 62, 207, 153, 166, 167, 180, 23, 62, 62, 176, 122, 170, 231, 120, + 0, 172, 74, 151, 241, 109, 99, 23, 0, 139, 110, 237, 203, 92, 251, 14, 0, 172, 74, 3, 75, 11, 5, 0, 0, 39, 62, 89, 251, 23, 92, 163, + 17, 238, 123, 56, 161, 92, 165, 165, 0, 6, 110, 127, 122, 23, 170, 50, 0, 54, 54, 177, 122, 194, 11, 120, 35, 110, 110, 176, 5, 42, 167, 163, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 71, 189, 18, 138, 12, 233, 0, 22, 214, 75, 153, 28, 0, 0, 0, 159, 2, 44, 99, 181, 243, 68, 0, 238, 30, 202, 128, 132, 46, 221, + 0, 141, 119, 91, 115, 124, 65, 159, 0, 16, 135, 94, 74, 17, 0, 0, 0, 191, 106, 110, 166, 0, 116, 108, 0, 136, 22, 75, 119, 208, 244, 0, + 0, 47, 6, 176, 156, 180, 231, 112, 78, 103, 6, 254, 194, 18, 153, 0, 0, 58, 206, 3, 217, 188, 0, 229, 0, 6, 74, 241, 18, 157, 204, 252, + 238, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 145, 74, 62, 241, 255, 107, 0, 0, 159, 110, 49, 176, 86, 92, 49, 0, 22, 223, 240, 194, 178, 56, 168, 108, 54, 74, 176, 194, 28, 28, 180, + 0, 140, 74, 241, 3, 157, 221, 120, 0, 10, 2, 127, 106, 165, 239, 0, 0, 8, 117, 91, 18, 96, 112, 46, 0, 74, 62, 69, 174, 218, 224, 73, + 0, 238, 110, 176, 232, 144, 28, 46, 0, 110, 62, 32, 199, 194, 221, 254, 0, 52, 2, 176, 5, 35, 42, 50, 12, 110, 62, 176, 138, 53, 60, 24, + 238, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 185, 234, 40, 161, 198, 220, 203, 0, 16, 234, 49, 237, 197, 239, 19, 0, 87, 57, 85, 126, 195, 62, 0, 0, 96, 235, 148, 210, 219, 0, 0, + 0, 185, 6, 75, 219, 232, 250, 218, 0, 141, 6, 49, 129, 243, 195, 0, 0, 58, 2, 219, 195, 233, 0, 0, 231, 201, 85, 79, 73, 206, 0, 253, + 0, 19, 110, 3, 219, 42, 20, 0, 0, 54, 74, 31, 122, 198, 32, 253, 0, 58, 6, 169, 176, 94, 53, 0, 0, 172, 62, 176, 5, 109, 231, 168, + 64, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 34, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, + 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, + 0, 103, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 175, 0, 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 62, 176, 216, 42, 100, 221, 0, 8, 74, 176, 18, 86, 12, 244, 0, 6, 6, 217, 156, 128, 149, 231, 0, 238, 110, 176, 109, 218, 231, 111, + 0, 54, 74, 176, 192, 144, 232, 20, 0, 57, 74, 62, 31, 42, 0, 0, 0, 141, 22, 192, 208, 42, 0, 20, 0, 107, 62, 176, 99, 18, 126, 128, + 180, 74, 62, 176, 5, 128, 144, 17, 12, 47, 74, 176, 219, 170, 168, 20, 179, 74, 62, 13, 5, 166, 187, 167, 0, 110, 110, 176, 5, 144, 126, 120, + 1, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 82, 94, 204, 141, 0, 0, 0, 0, 237, 174, 240, 180, 203, 0, 0, 0, 134, 110, 204, 92, 0, 0, 0, 0, 62, 176, 161, 42, 76, 198, + 76, 0, 172, 91, 13, 189, 34, 0, 0, 0, 9, 100, 25, 243, 244, 0, 0, 0, 2, 142, 151, 45, 196, 91, 179, 0, 62, 110, 5, 53, 172, 11, + 0, 0, 54, 90, 216, 109, 176, 168, 0, 0, 71, 75, 153, 251, 50, 209, 0, 0, 110, 56, 5, 229, 20, 28, 247, 0, 110, 176, 219, 12, 229, 163, + 1, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 107, 56, 18, 166, 72, 0, 72, 0, 172, 217, 5, 180, 208, 18, 0, 0, 47, 30, 42, 161, 50, 0, 199, 0, 62, 176, 99, 42, 76, 231, + 0, 0, 172, 107, 138, 128, 6, 183, 0, 0, 6, 91, 241, 198, 219, 170, 30, 0, 6, 240, 56, 11, 126, 170, 58, 0, 62, 176, 18, 211, 42, 65, + 53, 0, 233, 56, 161, 166, 35, 17, 0, 0, 110, 176, 99, 92, 28, 50, 0, 0, 62, 62, 99, 72, 76, 46, 221, 0, 110, 241, 5, 218, 17, 17, + 63, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 6, 176, 5, 11, 168, 111, 0, 159, 6, 75, 207, 195, 231, 163, 68, 234, 6, 176, 241, 92, 111, 126, 203, 74, 62, 176, 5, 11, 38, 0, + 0, 234, 6, 176, 99, 194, 231, 209, 0, 234, 206, 176, 99, 198, 190, 244, 0, 234, 206, 176, 49, 194, 53, 231, 0, 110, 62, 176, 5, 42, 168, 112, + 0, 110, 62, 176, 5, 42, 198, 28, 0, 47, 62, 176, 5, 109, 165, 137, 0, 6, 62, 176, 153, 72, 187, 231, 0, 110, 110, 176, 5, 42, 168, 24, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 3, 176, 23, 50, 0, 0, 140, 6, 3, 194, 170, 161, 211, 0, 140, 6, 179, 122, 11, 42, 253, 0, 145, 6, 176, 156, 144, 76, 65, + 0, 234, 6, 40, 72, 23, 53, 30, 0, 234, 6, 69, 219, 5, 7, 211, 85, 141, 22, 30, 219, 203, 81, 86, 0, 47, 6, 176, 207, 5, 231, 108, + 0, 54, 110, 69, 153, 166, 218, 138, 0, 159, 6, 176, 207, 168, 231, 6, 0, 110, 62, 91, 127, 2, 168, 46, 0, 62, 62, 176, 156, 166, 229, 120, + 51, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 246, 110, 89, 56, 109, 109, 203, 0, 246, 110, 176, 219, 144, 218, 111, 0, 54, 62, 176, 5, 42, 157, 221, 20, 54, 62, 176, 5, 218, 168, 190, + 0, 172, 62, 176, 204, 218, 24, 5, 0, 172, 62, 75, 31, 48, 229, 170, 0, 74, 6, 69, 176, 12, 231, 24, 0, 110, 62, 176, 156, 53, 120, 0, + 0, 19, 110, 56, 192, 166, 166, 168, 0, 62, 110, 176, 138, 218, 111, 112, 0, 6, 110, 176, 161, 203, 168, 157, 18, 110, 110, 176, 5, 218, 167, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 103, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 254, 71, 48, 0, 152, 0, 136, 228, 69, 148, 28, 56, 0, 0, 162, 2, 10, 146, 0, 0, 219, 0, 57, 21, 94, 85, 245, 0, 0, + 0, 45, 6, 197, 197, 72, 111, 0, 0, 242, 71, 4, 147, 112, 0, 30, 0, 58, 129, 197, 164, 0, 0, 0, 0, 234, 21, 240, 198, 74, 189, 48, + 0, 222, 62, 75, 180, 23, 203, 18, 0, 172, 62, 40, 122, 156, 120, 28, 0, 6, 62, 31, 32, 0, 0, 53, 0, 62, 139, 49, 86, 42, 108, 218, + 181, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 254, 139, 5, 5, 253, 18, 0, 74, 62, 235, 138, 111, 17, 17, 0, 101, 21, 219, 192, 5, 211, 190, 0, 107, 62, 176, 156, 72, 195, 168, + 252, 118, 6, 176, 11, 28, 60, 241, 0, 16, 62, 3, 232, 232, 0, 253, 0, 242, 206, 44, 115, 3, 153, 181, 0, 123, 6, 30, 31, 232, 55, 50, + 23, 172, 110, 176, 5, 109, 111, 38, 0, 172, 62, 176, 99, 144, 167, 50, 0, 139, 6, 176, 122, 231, 108, 8, 0, 62, 176, 176, 5, 128, 168, 209, + 51, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 4, 5, 2, 31, 0, 0, 140, 52, 204, 73, 136, 38, 0, 0, 87, 206, 179, 128, 23, 105, 192, 0, 228, 6, 241, 18, 72, 53, 0, + 0, 140, 6, 40, 237, 177, 209, 0, 0, 141, 6, 219, 130, 203, 194, 0, 0, 141, 54, 147, 243, 179, 190, 168, 0, 74, 62, 240, 18, 69, 231, 20, + 0, 140, 74, 3, 156, 17, 35, 172, 0, 246, 2, 134, 122, 142, 115, 73, 0, 234, 74, 3, 243, 204, 44, 0, 0, 123, 62, 176, 243, 124, 35, 28, + 181, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 181, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 181, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 6, 176, 18, 249, 86, 38, 0, 47, 74, 176, 219, 195, 211, 108, 0, 74, 74, 30, 91, 251, 108, 108, 0, 21, 62, 176, 99, 53, 126, 221, + 0, 123, 62, 89, 124, 240, 221, 194, 0, 6, 62, 176, 12, 11, 176, 37, 0, 6, 215, 75, 99, 194, 46, 244, 0, 47, 110, 75, 5, 35, 65, 17, + 0, 123, 110, 176, 5, 53, 111, 112, 0, 254, 110, 176, 31, 109, 126, 28, 0, 74, 62, 176, 5, 20, 76, 190, 0, 110, 62, 176, 5, 11, 111, 17, + 51, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 54, 89, 166, 145, 45, 0, 0, 0, 6, 75, 132, 20, 212, 0, 0, 0, 6, 30, 195, 195, 211, 0, 0, 0, 62, 176, 99, 72, 187, 20, + 0, 0, 62, 100, 109, 47, 0, 251, 0, 0, 62, 10, 243, 170, 136, 0, 0, 0, 62, 18, 242, 237, 73, 0, 0, 0, 62, 176, 195, 144, 170, 144, + 0, 0, 74, 89, 166, 3, 209, 1, 0, 0, 110, 85, 161, 166, 221, 221, 0, 0, 21, 91, 211, 180, 203, 237, 0, 0, 110, 176, 5, 218, 168, 221, + 1, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 62, 89, 5, 166, 38, 183, 0, 0, 62, 91, 219, 23, 208, 116, 0, 0, 110, 176, 18, 128, 99, 231, 0, 0, 110, 176, 5, 11, 187, 17, + 0, 0, 74, 176, 216, 23, 178, 253, 0, 0, 74, 30, 208, 180, 5, 65, 0, 0, 206, 176, 127, 176, 126, 251, 13, 0, 62, 176, 5, 198, 167, 112, + 211, 0, 110, 56, 161, 166, 35, 168, 100, 0, 62, 176, 18, 11, 168, 168, 0, 0, 110, 176, 122, 42, 72, 24, 214, 0, 110, 176, 5, 218, 167, 50, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 28, 159, 6, 176, 31, 11, 35, 253, 0, 159, 6, 75, 5, 109, 229, 111, 0, 234, 6, 30, 249, 195, 112, 126, 221, 110, 62, 176, 208, 198, 157, 108, + 0, 140, 6, 176, 99, 195, 35, 112, 0, 234, 6, 176, 156, 53, 112, 46, 0, 234, 6, 75, 18, 42, 20, 253, 0, 74, 62, 176, 219, 53, 24, 20, + 238, 54, 62, 176, 5, 109, 28, 190, 74, 74, 62, 176, 5, 42, 120, 0, 12, 110, 62, 176, 18, 198, 163, 231, 98, 110, 110, 176, 5, 218, 183, 50, + 150, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 133, 89, 161, 214, 198, 20, 0, 57, 21, 44, 192, 177, 187, 231, 0, 141, 6, 91, 208, 33, 20, 99, 0, 54, 6, 30, 23, 53, 218, 112, + 196, 67, 6, 13, 18, 99, 111, 20, 0, 58, 52, 44, 53, 148, 0, 128, 0, 234, 110, 44, 3, 194, 100, 21, 0, 47, 6, 75, 138, 92, 253, 211, + 0, 172, 74, 127, 56, 31, 1, 0, 0, 96, 62, 207, 11, 229, 160, 0, 0, 134, 110, 75, 176, 180, 62, 20, 211, 107, 62, 176, 122, 210, 203, 74, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 62, 89, 251, 229, 229, 107, 0, 6, 6, 91, 92, 216, 219, 142, 0, 57, 56, 176, 99, 53, 0, 203, 73, 107, 62, 176, 122, 180, 168, 73, + 0, 172, 233, 176, 161, 56, 157, 126, 0, 110, 110, 5, 99, 132, 18, 88, 0, 134, 62, 75, 73, 0, 180, 116, 0, 2, 74, 176, 5, 28, 17, 157, + 0, 54, 110, 62, 204, 109, 166, 111, 0, 62, 62, 176, 249, 180, 35, 244, 0, 6, 62, 176, 161, 72, 72, 84, 0, 222, 62, 176, 156, 218, 17, 17, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 62, 75, 99, 56, 28, 221, 0, 45, 215, 100, 211, 147, 144, 104, 0, 45, 22, 217, 211, 219, 140, 143, 0, 26, 62, 100, 174, 72, 220, 120, + 0, 140, 74, 179, 251, 11, 128, 65, 0, 141, 6, 75, 208, 92, 209, 211, 0, 214, 74, 176, 73, 38, 35, 24, 0, 123, 2, 176, 122, 72, 22, 60, + 0, 246, 74, 176, 138, 210, 35, 209, 0, 47, 6, 75, 5, 42, 20, 60, 0, 74, 6, 176, 177, 221, 38, 227, 0, 110, 62, 176, 5, 180, 17, 244, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 74, 176, 99, 198, 157, 221, 0, 47, 6, 30, 122, 92, 23, 25, 0, 230, 62, 4, 5, 170, 127, 50, 0, 254, 62, 30, 208, 198, 218, 120, + 187, 238, 62, 75, 99, 12, 35, 253, 0, 71, 6, 69, 207, 216, 23, 24, 0, 234, 22, 200, 124, 12, 216, 60, 50, 110, 62, 200, 5, 42, 163, 253, + 0, 238, 62, 176, 5, 198, 35, 108, 0, 54, 62, 176, 5, 180, 229, 0, 0, 74, 62, 176, 156, 218, 168, 111, 0, 62, 110, 176, 5, 218, 167, 108, + 238, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 74, 176, 99, 198, 109, 65, 0, 141, 6, 30, 170, 216, 11, 163, 0, 234, 6, 176, 219, 69, 0, 46, 0, 52, 62, 62, 170, 166, 216, 190, + 0, 140, 6, 176, 31, 124, 28, 116, 0, 141, 6, 75, 5, 218, 120, 174, 0, 140, 6, 75, 124, 22, 35, 0, 0, 54, 6, 30, 5, 195, 53, 233, + 46, 246, 74, 176, 5, 195, 35, 221, 0, 47, 6, 176, 5, 12, 50, 137, 0, 110, 62, 176, 208, 128, 120, 0, 237, 110, 62, 3, 122, 42, 198, 168, + 82, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 67, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 103, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 246, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 62, 176, 31, 166, 229, 35, 0, 47, 62, 75, 18, 11, 53, 50, 0, 74, 6, 176, 124, 99, 28, 72, 0, 110, 62, 176, 5, 92, 168, 46, + 0, 54, 62, 176, 99, 11, 187, 253, 0, 47, 62, 176, 31, 53, 76, 120, 0, 54, 6, 176, 99, 161, 20, 111, 0, 110, 62, 176, 156, 128, 128, 0, + 212, 110, 110, 176, 5, 42, 168, 0, 187, 74, 62, 176, 5, 11, 231, 65, 0, 110, 62, 176, 5, 11, 76, 190, 167, 110, 110, 176, 5, 144, 167, 190, + 238, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 123, 62, 122, 79, 124, 0, 0, 0, 47, 3, 86, 139, 34, 0, 0, 0, 8, 197, 4, 185, 191, 16, 0, 0, 6, 30, 251, 187, 128, 153, + 0, 0, 110, 123, 232, 18, 6, 2, 0, 0, 6, 89, 153, 198, 65, 196, 0, 0, 6, 235, 40, 220, 97, 0, 0, 0, 6, 115, 211, 42, 241, 167, + 0, 0, 110, 56, 31, 109, 111, 229, 0, 0, 6, 176, 208, 218, 203, 168, 0, 0, 62, 75, 243, 195, 183, 108, 0, 0, 62, 176, 5, 218, 38, 112, + 238, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 62, 56, 161, 166, 35, 48, 0, 0, 6, 89, 90, 42, 110, 176, 0, 0, 110, 241, 249, 5, 168, 128, 0, 0, 110, 176, 5, 42, 53, 0, + 0, 0, 110, 176, 99, 170, 198, 30, 0, 0, 6, 179, 241, 180, 16, 110, 0, 0, 62, 127, 156, 219, 164, 72, 0, 0, 110, 176, 5, 194, 231, 35, + 0, 0, 110, 56, 192, 166, 229, 46, 0, 0, 110, 176, 99, 11, 231, 209, 133, 0, 110, 176, 99, 92, 168, 209, 244, 0, 110, 176, 5, 218, 167, 60, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 25, 159, 6, 176, 207, 42, 231, 221, 0, 159, 6, 176, 207, 203, 28, 46, 0, 140, 6, 176, 5, 92, 111, 0, 0, 110, 62, 176, 5, 170, 167, 244, + 0, 140, 6, 176, 18, 180, 20, 126, 223, 234, 6, 176, 18, 12, 231, 209, 0, 234, 6, 176, 153, 194, 253, 244, 0, 74, 62, 176, 156, 128, 35, 20, + 101, 110, 62, 176, 5, 42, 111, 209, 140, 110, 62, 176, 5, 249, 11, 35, 75, 74, 62, 176, 208, 198, 187, 0, 168, 110, 62, 176, 5, 218, 112, 190, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 62, 179, 5, 198, 166, 167, 0, 140, 74, 75, 207, 38, 203, 16, 0, 141, 6, 91, 164, 126, 50, 120, 0, 47, 6, 176, 99, 198, 137, 0, + 0, 234, 6, 176, 192, 166, 180, 187, 0, 234, 6, 217, 75, 243, 244, 109, 0, 140, 6, 75, 3, 124, 56, 111, 0, 47, 74, 176, 5, 42, 23, 120, + 0, 62, 62, 176, 18, 53, 108, 163, 0, 119, 6, 176, 153, 210, 120, 190, 0, 110, 6, 100, 30, 5, 50, 20, 0, 110, 110, 176, 5, 144, 168, 221, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 74, 176, 5, 166, 161, 166, 0, 47, 62, 176, 138, 195, 168, 190, 0, 123, 110, 176, 5, 198, 11, 221, 0, 123, 62, 176, 5, 42, 168, 244, + 0, 110, 62, 176, 86, 124, 20, 137, 0, 62, 62, 176, 219, 170, 38, 3, 0, 52, 110, 91, 99, 128, 142, 153, 144, 6, 62, 176, 5, 218, 165, 0, + 0, 107, 110, 176, 99, 92, 28, 167, 0, 74, 110, 176, 243, 42, 126, 209, 0, 74, 62, 176, 99, 195, 218, 116, 0, 110, 110, 176, 5, 218, 120, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, + 0, 150, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 105, 140, 6, 176, 73, 92, 35, 35, 0, 234, 6, 142, 251, 220, 46, 225, 0, 140, 6, 4, 32, 210, 136, 163, 0, 47, 6, 30, 5, 42, 72, 153, + 0, 141, 6, 176, 18, 177, 35, 190, 0, 141, 6, 174, 92, 72, 253, 221, 0, 234, 6, 30, 243, 137, 50, 0, 0, 54, 62, 176, 124, 72, 229, 180, + 0, 47, 74, 176, 5, 198, 53, 221, 0, 47, 6, 176, 5, 11, 35, 46, 0, 52, 62, 176, 216, 12, 120, 72, 0, 110, 62, 176, 122, 92, 41, 28, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 74, 176, 122, 30, 35, 65, 0, 47, 6, 176, 208, 23, 46, 60, 0, 74, 6, 30, 122, 76, 195, 35, 0, 107, 62, 176, 99, 42, 35, 24, + 0, 123, 62, 176, 156, 12, 209, 245, 0, 74, 62, 100, 99, 5, 231, 224, 0, 234, 62, 75, 208, 128, 28, 24, 0, 47, 62, 176, 5, 194, 35, 168, + 0, 54, 110, 176, 5, 42, 35, 108, 0, 110, 62, 176, 5, 128, 168, 209, 0, 54, 62, 176, 156, 218, 76, 244, 0, 110, 110, 176, 5, 218, 120, 244, + 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 46, 140, 6, 75, 18, 180, 165, 163, 0, 234, 6, 176, 31, 122, 168, 0, 0, 234, 6, 179, 208, 170, 208, 163, 0, 74, 62, 75, 161, 187, 229, 0, + 0, 140, 6, 75, 75, 194, 12, 221, 0, 141, 6, 75, 156, 249, 167, 166, 0, 141, 6, 3, 199, 3, 42, 72, 0, 6, 62, 30, 122, 109, 118, 38, + 0, 47, 74, 176, 5, 109, 35, 112, 0, 47, 6, 176, 156, 42, 157, 0, 0, 140, 62, 176, 5, 42, 28, 12, 0, 110, 62, 176, 5, 11, 35, 46, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 62, 176, 99, 11, 229, 229, 0, 47, 6, 75, 207, 42, 109, 89, 0, 246, 62, 176, 122, 203, 161, 0, 0, 110, 62, 176, 5, 195, 229, 23, + 0, 54, 62, 176, 176, 11, 165, 111, 0, 6, 74, 176, 207, 12, 38, 108, 0, 74, 62, 30, 5, 192, 20, 221, 0, 47, 62, 176, 99, 42, 76, 183, + 231, 110, 110, 176, 5, 42, 35, 209, 22, 47, 62, 176, 5, 11, 229, 24, 157, 110, 62, 176, 5, 42, 20, 209, 133, 110, 110, 176, 5, 218, 28, 190, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 62, 89, 249, 109, 172, 16, 0, 0, 74, 142, 96, 211, 165, 109, 0, 0, 6, 3, 127, 11, 126, 111, 0, 0, 110, 176, 5, 198, 35, 20, + 0, 0, 110, 176, 153, 23, 166, 1, 0, 0, 6, 56, 75, 99, 108, 183, 0, 0, 6, 176, 207, 203, 116, 0, 0, 0, 110, 176, 5, 180, 167, 108, + 0, 0, 110, 176, 161, 42, 120, 229, 0, 0, 6, 176, 207, 11, 229, 112, 0, 0, 110, 176, 5, 194, 20, 120, 13, 0, 110, 176, 5, 218, 168, 190, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 110, 56, 176, 194, 42, 187, 0, 0, 74, 176, 99, 216, 231, 53, 0, 0, 110, 176, 5, 232, 195, 46, 65, 0, 110, 176, 5, 218, 231, 108, + 0, 0, 110, 176, 5, 11, 170, 120, 0, 0, 110, 75, 207, 31, 53, 220, 0, 0, 62, 30, 5, 42, 166, 126, 232, 0, 110, 176, 5, 218, 168, 112, + 194, 0, 110, 176, 192, 42, 35, 46, 80, 0, 110, 176, 18, 42, 229, 116, 19, 0, 62, 176, 5, 42, 38, 60, 120, 0, 110, 176, 5, 218, 120, 190, + 63, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 170, 159, 6, 176, 99, 11, 229, 112, 0, 159, 6, 176, 207, 195, 111, 116, 0, 234, 6, 176, 99, 42, 42, 112, 0, 54, 62, 176, 243, 5, 20, 168, + 0, 140, 62, 176, 99, 198, 157, 203, 0, 234, 6, 75, 5, 11, 76, 112, 0, 234, 62, 176, 99, 218, 46, 112, 0, 62, 62, 176, 219, 42, 20, 168, + 237, 238, 62, 176, 18, 42, 42, 183, 0, 54, 62, 176, 99, 168, 120, 60, 0, 62, 62, 176, 156, 42, 11, 244, 0, 110, 62, 176, 156, 128, 231, 65, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 110, 235, 192, 161, 35, 65, 0, 140, 74, 176, 5, 53, 42, 120, 0, 140, 62, 4, 75, 138, 167, 76, 108, 62, 62, 176, 5, 72, 203, 244, + 0, 140, 74, 89, 204, 11, 187, 0, 0, 16, 8, 44, 208, 36, 125, 28, 0, 234, 6, 30, 5, 199, 28, 24, 36, 74, 62, 176, 99, 218, 229, 219, + 0, 172, 107, 89, 161, 128, 56, 244, 0, 123, 62, 176, 18, 128, 168, 157, 0, 62, 62, 69, 156, 12, 168, 126, 0, 233, 62, 69, 5, 218, 221, 46, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 170, 47, 110, 176, 192, 109, 165, 111, 90, 47, 74, 176, 5, 42, 35, 65, 0, 47, 6, 176, 86, 11, 218, 231, 163, 110, 62, 176, 5, 23, 168, 65, + 0, 54, 110, 176, 192, 161, 165, 35, 0, 47, 62, 176, 99, 198, 72, 111, 0, 62, 6, 30, 5, 11, 38, 190, 0, 74, 62, 176, 243, 218, 17, 163, + 0, 238, 110, 56, 192, 166, 165, 183, 240, 47, 110, 176, 31, 180, 165, 46, 0, 54, 110, 176, 156, 72, 180, 65, 163, 110, 110, 176, 5, 218, 38, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 224, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 4, 243, 144, 229, 187, 0, 141, 6, 100, 174, 180, 190, 119, 0, 16, 2, 164, 99, 231, 0, 0, 0, 6, 62, 30, 216, 164, 0, 244, + 0, 140, 21, 176, 32, 28, 168, 231, 0, 234, 22, 176, 197, 100, 229, 241, 0, 6, 22, 179, 5, 18, 31, 0, 0, 74, 110, 241, 73, 0, 116, 0, + 0, 172, 110, 176, 219, 218, 92, 231, 0, 47, 110, 30, 156, 180, 253, 244, 0, 2, 110, 49, 11, 50, 170, 174, 0, 172, 62, 176, 5, 194, 128, 108, + 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 246, 110, 200, 192, 128, 72, 116, 0, 47, 74, 30, 5, 144, 168, 46, 0, 2, 62, 40, 219, 144, 221, 24, 0, 110, 62, 176, 86, 232, 168, 163, + 0, 246, 110, 176, 122, 170, 218, 20, 0, 47, 134, 176, 5, 218, 192, 218, 0, 10, 22, 176, 5, 231, 38, 60, 0, 62, 110, 241, 5, 42, 167, 48, + 65, 238, 62, 176, 5, 42, 168, 0, 0, 6, 62, 75, 5, 92, 229, 24, 0, 74, 62, 176, 5, 72, 42, 209, 0, 110, 62, 176, 5, 12, 167, 65, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 47, 81, 243, 128, 161, 28, 0, 246, 6, 179, 69, 129, 168, 126, 0, 234, 22, 179, 240, 0, 0, 0, 0, 62, 107, 3, 73, 99, 181, 24, + 0, 47, 74, 22, 122, 124, 99, 235, 0, 140, 62, 3, 113, 2, 0, 0, 0, 45, 57, 30, 167, 220, 38, 65, 0, 45, 254, 215, 148, 0, 76, 0, + 0, 19, 62, 176, 18, 23, 46, 1, 0, 74, 22, 176, 5, 111, 190, 46, 0, 62, 62, 75, 179, 0, 60, 20, 0, 110, 176, 176, 99, 23, 209, 157, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 141, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 246, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 181, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 74, 127, 176, 203, 12, 163, 0, 119, 74, 32, 153, 170, 65, 128, 0, 131, 62, 79, 211, 42, 35, 0, 0, 123, 74, 176, 5, 251, 209, 24, + 0, 54, 228, 115, 5, 109, 249, 41, 0, 21, 6, 91, 198, 49, 0, 209, 249, 62, 6, 75, 127, 170, 0, 38, 0, 54, 62, 89, 86, 18, 231, 120, + 0, 238, 110, 176, 5, 166, 229, 157, 0, 6, 62, 30, 208, 195, 53, 24, 0, 21, 56, 176, 156, 144, 128, 244, 0, 110, 62, 176, 5, 42, 111, 65, + 181, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 107, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 71, 107, 219, 151, 48, 203, 0, 0, 8, 164, 208, 96, 38, 128, 0, 0, 189, 220, 21, 144, 8, 0, 0, 0, 110, 40, 5, 72, 157, 231, + 0, 0, 62, 179, 248, 192, 65, 203, 0, 0, 134, 176, 192, 195, 0, 0, 0, 0, 62, 254, 198, 0, 157, 0, 0, 0, 62, 176, 180, 138, 116, 61, + 0, 0, 74, 107, 122, 109, 76, 228, 0, 0, 74, 127, 219, 198, 11, 0, 0, 0, 74, 75, 241, 23, 73, 38, 0, 0, 62, 176, 5, 144, 157, 17, + 181, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 56, 31, 166, 166, 76, 0, 0, 74, 176, 249, 237, 218, 231, 0, 0, 110, 176, 176, 5, 38, 32, 11, 0, 62, 176, 5, 11, 157, 65, + 0, 0, 54, 56, 161, 109, 229, 35, 0, 0, 110, 62, 208, 42, 65, 25, 0, 0, 6, 75, 177, 31, 20, 111, 0, 0, 110, 176, 5, 144, 170, 209, + 0, 0, 233, 56, 192, 166, 165, 17, 0, 0, 110, 176, 31, 195, 112, 65, 0, 0, 110, 176, 99, 170, 11, 183, 77, 0, 110, 176, 5, 218, 167, 190, + 63, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 12, 159, 6, 75, 5, 11, 35, 116, 43, 159, 6, 176, 207, 11, 229, 221, 0, 140, 6, 176, 5, 42, 35, 137, 0, 54, 62, 176, 5, 42, 35, 221, + 0, 234, 6, 176, 5, 12, 157, 38, 0, 234, 6, 176, 5, 11, 120, 50, 0, 234, 6, 176, 5, 92, 231, 50, 126, 47, 62, 176, 5, 42, 38, 253, + 0, 54, 62, 176, 5, 198, 28, 0, 0, 110, 62, 176, 5, 218, 231, 108, 0, 74, 62, 176, 5, 12, 157, 46, 64, 110, 62, 176, 5, 218, 120, 190, + 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 107, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 63, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 53, 111, 187, 0, 140, 6, 176, 219, 170, 35, 50, 0, 140, 6, 176, 207, 11, 165, 111, 199, 246, 74, 176, 5, 218, 35, 209, + 0, 234, 62, 176, 99, 170, 11, 107, 0, 234, 6, 176, 5, 42, 168, 20, 0, 141, 6, 176, 5, 11, 20, 111, 231, 47, 6, 176, 5, 218, 35, 112, + 0, 74, 62, 176, 161, 166, 165, 111, 0, 74, 62, 176, 5, 198, 231, 111, 0, 74, 62, 176, 243, 92, 35, 11, 0, 110, 62, 176, 5, 218, 167, 50, + 63, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 166, 47, 74, 176, 5, 92, 165, 28, 98, 246, 74, 176, 5, 42, 35, 112, 232, 172, 74, 176, 99, 198, 187, 46, 221, 172, 62, 176, 5, 42, 168, 209, + 216, 74, 62, 176, 99, 42, 35, 46, 0, 74, 62, 176, 5, 198, 35, 112, 111, 47, 6, 176, 5, 198, 38, 28, 38, 74, 62, 176, 5, 42, 168, 253, + 42, 172, 110, 176, 161, 42, 165, 28, 180, 110, 110, 176, 5, 42, 35, 28, 0, 110, 62, 176, 5, 11, 157, 112, 244, 110, 110, 176, 5, 218, 167, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 99, 195, 126, 112, 0, 141, 6, 176, 5, 3, 112, 108, 0, 234, 6, 75, 156, 128, 38, 206, 0, 123, 62, 75, 31, 157, 0, 0, + 0, 140, 6, 176, 243, 249, 126, 161, 0, 234, 6, 174, 156, 42, 112, 76, 0, 234, 6, 75, 49, 72, 60, 203, 0, 62, 6, 91, 153, 204, 50, 243, + 0, 172, 62, 176, 99, 53, 0, 120, 0, 123, 6, 176, 5, 11, 12, 231, 186, 52, 62, 176, 211, 5, 214, 60, 0, 62, 62, 176, 5, 166, 198, 203, + 224, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 210, 47, 74, 176, 99, 194, 76, 111, 0, 159, 62, 176, 99, 198, 168, 0, 0, 54, 6, 75, 5, 211, 28, 190, 0, 110, 62, 176, 5, 218, 229, 221, + 0, 54, 62, 176, 5, 53, 0, 0, 0, 246, 62, 176, 156, 120, 221, 204, 0, 22, 6, 176, 208, 5, 50, 221, 0, 74, 110, 176, 219, 72, 198, 126, + 0, 123, 110, 176, 5, 42, 28, 209, 0, 123, 62, 176, 5, 128, 167, 0, 0, 110, 110, 176, 5, 11, 76, 65, 0, 110, 62, 176, 5, 218, 167, 163, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 234, 6, 176, 5, 116, 76, 46, 0, 140, 6, 69, 161, 176, 255, 1, 0, 234, 6, 30, 176, 238, 89, 24, 0, 47, 74, 176, 243, 35, 221, 206, + 0, 141, 6, 117, 219, 155, 0, 249, 0, 140, 6, 217, 177, 17, 194, 38, 0, 234, 6, 179, 122, 109, 72, 50, 0, 47, 62, 75, 18, 243, 35, 179, + 0, 74, 62, 176, 5, 42, 120, 111, 0, 54, 6, 75, 99, 157, 166, 128, 0, 110, 6, 176, 11, 170, 38, 195, 0, 107, 110, 176, 5, 180, 168, 35, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 246, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 67, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 62, 75, 122, 12, 157, 209, 0, 47, 6, 176, 99, 211, 28, 190, 0, 140, 62, 176, 56, 72, 53, 229, 153, 123, 62, 176, 5, 92, 38, 46, + 0, 62, 62, 176, 208, 5, 112, 213, 0, 6, 6, 91, 122, 203, 92, 28, 0, 214, 6, 176, 86, 53, 209, 42, 0, 74, 62, 176, 156, 11, 229, 163, + 0, 54, 62, 176, 5, 170, 38, 209, 0, 74, 62, 176, 5, 198, 229, 190, 0, 62, 62, 176, 5, 218, 28, 120, 2, 107, 62, 176, 5, 218, 120, 190, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 181, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 110, 74, 251, 126, 168, 0, 0, 0, 74, 69, 249, 248, 221, 30, 0, 0, 62, 176, 18, 42, 11, 77, 23, 0, 62, 30, 5, 72, 109, 46, + 0, 0, 6, 176, 217, 35, 198, 53, 0, 0, 6, 94, 208, 198, 231, 32, 0, 0, 6, 100, 210, 120, 127, 195, 0, 0, 62, 176, 5, 198, 38, 209, + 0, 0, 110, 176, 99, 128, 11, 163, 0, 0, 110, 179, 18, 192, 229, 168, 0, 0, 74, 176, 208, 11, 72, 76, 0, 0, 110, 176, 5, 218, 38, 244, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 62, 99, 42, 92, 183, 0, 0, 110, 176, 99, 218, 38, 168, 0, 0, 74, 176, 5, 5, 12, 111, 0, 0, 110, 176, 5, 218, 168, 65, + 0, 0, 110, 176, 161, 11, 38, 163, 0, 0, 74, 176, 31, 198, 203, 111, 0, 0, 74, 176, 219, 218, 11, 231, 0, 0, 62, 176, 5, 42, 167, 41, + 190, 0, 110, 176, 192, 166, 165, 28, 0, 0, 110, 176, 5, 42, 35, 0, 0, 0, 110, 176, 5, 11, 229, 137, 190, 0, 110, 176, 5, 218, 120, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 6, 176, 5, 218, 35, 221, 215, 159, 6, 75, 219, 11, 231, 60, 0, 234, 6, 176, 207, 198, 168, 244, 0, 54, 62, 176, 5, 42, 35, 108, + 0, 140, 6, 176, 99, 11, 111, 65, 157, 234, 6, 176, 124, 53, 76, 41, 0, 234, 6, 176, 73, 23, 120, 60, 0, 74, 62, 176, 5, 23, 60, 244, + 0, 110, 62, 176, 99, 218, 38, 112, 0, 74, 62, 176, 5, 218, 168, 65, 0, 110, 62, 176, 156, 42, 157, 183, 0, 110, 62, 176, 5, 72, 167, 65, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 74, 75, 122, 161, 72, 210, 0, 141, 6, 176, 99, 166, 86, 209, 0, 140, 6, 75, 122, 195, 210, 174, 0, 172, 74, 176, 99, 128, 168, 209, + 0, 234, 6, 176, 204, 72, 11, 76, 0, 140, 6, 176, 124, 40, 111, 2, 0, 140, 6, 75, 122, 53, 5, 75, 0, 47, 62, 176, 156, 243, 138, 50, + 0, 54, 74, 176, 161, 161, 157, 168, 0, 6, 62, 176, 211, 109, 54, 98, 0, 110, 62, 176, 86, 192, 30, 20, 0, 62, 62, 176, 5, 128, 109, 168, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 74, 176, 161, 170, 111, 111, 0, 159, 6, 176, 5, 11, 60, 167, 0, 54, 62, 176, 5, 144, 167, 0, 0, 110, 62, 176, 5, 218, 168, 50, + 0, 54, 110, 176, 5, 42, 35, 209, 0, 6, 62, 176, 5, 128, 76, 28, 0, 234, 6, 176, 241, 12, 12, 76, 0, 74, 62, 176, 5, 218, 167, 0, + 138, 238, 110, 176, 161, 42, 35, 17, 0, 74, 62, 176, 99, 42, 42, 76, 0, 110, 62, 176, 5, 198, 23, 24, 81, 110, 110, 176, 5, 218, 167, 112, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 125, 140, 6, 176, 124, 11, 168, 0, 0, 141, 6, 75, 99, 128, 187, 221, 0, 234, 6, 176, 5, 195, 231, 35, 0, 107, 62, 44, 5, 23, 180, 126, + 0, 140, 6, 75, 207, 12, 111, 0, 0, 141, 6, 75, 5, 195, 170, 38, 0, 234, 6, 176, 124, 170, 218, 76, 0, 54, 62, 176, 18, 41, 46, 53, + 24, 246, 74, 176, 5, 11, 168, 253, 0, 47, 6, 176, 5, 12, 35, 108, 0, 230, 62, 176, 5, 42, 38, 46, 0, 110, 62, 176, 5, 218, 168, 209, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 246, 74, 176, 5, 42, 38, 0, 0, 47, 6, 176, 5, 42, 38, 112, 129, 6, 62, 176, 99, 92, 42, 65, 0, 110, 62, 176, 5, 218, 76, 137, + 111, 54, 74, 176, 5, 195, 168, 112, 0, 47, 62, 176, 5, 12, 218, 41, 0, 6, 62, 176, 5, 42, 168, 209, 0, 62, 62, 176, 5, 42, 46, 0, + 231, 238, 110, 176, 5, 42, 168, 209, 0, 47, 62, 176, 5, 42, 168, 190, 168, 74, 62, 176, 5, 218, 168, 190, 0, 62, 62, 176, 5, 218, 167, 190, + 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 219, 109, 111, 111, 0, 234, 6, 4, 5, 180, 218, 163, 0, 234, 6, 75, 216, 76, 112, 168, 0, 47, 62, 176, 251, 99, 80, 34, + 0, 140, 6, 176, 99, 195, 20, 126, 0, 141, 6, 75, 153, 11, 219, 0, 0, 140, 6, 179, 156, 249, 112, 46, 0, 246, 6, 179, 30, 203, 65, 0, + 0, 47, 74, 176, 5, 128, 229, 46, 0, 47, 6, 176, 99, 198, 126, 167, 0, 74, 6, 176, 5, 12, 163, 190, 0, 110, 62, 176, 5, 92, 165, 253, + 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 246, 74, 176, 18, 166, 35, 24, 0, 159, 6, 176, 99, 72, 20, 116, 0, 6, 62, 176, 99, 42, 35, 231, 0, 107, 62, 176, 5, 198, 168, 253, + 0, 172, 62, 176, 99, 210, 168, 24, 0, 6, 6, 176, 5, 53, 187, 120, 0, 6, 2, 217, 153, 232, 231, 137, 0, 6, 62, 176, 99, 42, 167, 163, + 73, 110, 110, 176, 5, 42, 35, 112, 0, 47, 62, 176, 5, 194, 168, 0, 0, 74, 62, 176, 5, 42, 120, 50, 0, 62, 110, 176, 5, 218, 120, 209, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 176, 161, 38, 166, 0, 0, 0, 6, 176, 31, 24, 120, 123, 0, 0, 107, 241, 243, 17, 11, 231, 0, 0, 62, 176, 122, 180, 168, 35, + 0, 0, 74, 176, 192, 11, 65, 17, 0, 0, 6, 179, 31, 62, 20, 255, 0, 0, 62, 89, 3, 198, 85, 0, 0, 0, 62, 176, 5, 203, 92, 253, + 0, 0, 110, 176, 5, 42, 35, 167, 0, 0, 74, 176, 5, 53, 180, 28, 0, 0, 62, 176, 156, 42, 28, 244, 0, 0, 110, 176, 5, 42, 35, 65, + 238, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 110, 176, 31, 166, 170, 35, 0, 0, 6, 176, 192, 92, 165, 35, 0, 0, 62, 176, 5, 198, 198, 0, 0, 0, 110, 176, 5, 170, 38, 46, + 0, 0, 110, 176, 161, 42, 35, 229, 0, 0, 74, 176, 138, 128, 35, 157, 0, 0, 62, 176, 5, 218, 126, 163, 231, 0, 110, 176, 5, 12, 229, 244, + 155, 0, 110, 176, 161, 166, 35, 46, 60, 0, 110, 176, 5, 42, 187, 0, 0, 0, 110, 176, 5, 198, 38, 112, 229, 0, 110, 176, 5, 218, 167, 190, + 63, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 4, 159, 6, 176, 5, 11, 229, 112, 253, 159, 6, 176, 5, 195, 35, 65, 38, 140, 6, 176, 5, 198, 229, 112, 42, 54, 62, 176, 5, 42, 35, 112, + 122, 140, 6, 176, 5, 11, 229, 126, 0, 234, 6, 176, 5, 42, 20, 0, 1, 234, 6, 176, 5, 11, 35, 137, 0, 74, 62, 176, 5, 218, 231, 112, + 236, 110, 62, 176, 99, 42, 231, 65, 0, 110, 62, 176, 5, 42, 35, 60, 0, 110, 62, 176, 5, 12, 229, 0, 126, 110, 62, 176, 5, 218, 168, 190, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, + 190, 141, 6, 176, 99, 195, 38, 60, 0, 140, 6, 176, 5, 11, 203, 17, 0, 140, 6, 176, 5, 195, 46, 111, 0, 47, 74, 176, 5, 42, 35, 253, + 0, 234, 6, 176, 122, 42, 72, 253, 0, 234, 6, 176, 5, 128, 168, 111, 0, 141, 6, 176, 5, 12, 0, 198, 91, 47, 6, 176, 5, 42, 231, 24, + 2, 74, 62, 176, 5, 203, 126, 187, 0, 74, 62, 176, 5, 42, 187, 120, 0, 110, 62, 176, 5, 11, 218, 187, 218, 110, 62, 176, 5, 218, 168, 190, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 241, 47, 62, 176, 5, 42, 165, 65, 42, 172, 74, 176, 5, 42, 229, 60, 20, 54, 74, 176, 5, 42, 35, 221, 187, 172, 62, 176, 5, 218, 168, 209, + 0, 54, 62, 176, 5, 42, 35, 187, 0, 6, 6, 176, 5, 194, 231, 190, 209, 47, 6, 176, 5, 12, 168, 209, 253, 47, 62, 176, 5, 218, 168, 190, + 0, 110, 110, 176, 5, 42, 35, 28, 180, 110, 62, 176, 5, 198, 231, 112, 0, 110, 62, 176, 5, 218, 229, 112, 20, 110, 62, 176, 5, 218, 120, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 99, 12, 28, 60, 0, 141, 6, 176, 99, 198, 42, 111, 0, 234, 6, 176, 5, 124, 92, 24, 0, 54, 62, 176, 5, 198, 42, 209, + 0, 140, 6, 176, 5, 11, 111, 111, 0, 141, 6, 176, 5, 203, 76, 28, 0, 234, 6, 176, 219, 218, 23, 28, 0, 54, 62, 176, 5, 198, 120, 180, + 0, 172, 74, 176, 5, 42, 231, 65, 43, 47, 6, 176, 5, 12, 168, 0, 0, 54, 62, 176, 5, 11, 229, 28, 0, 110, 62, 176, 5, 42, 120, 209, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 94, 172, 74, 176, 5, 42, 35, 209, 148, 47, 6, 176, 5, 198, 231, 46, 0, 54, 6, 176, 5, 42, 157, 65, 227, 110, 110, 176, 5, 218, 168, 112, + 0, 172, 74, 176, 5, 12, 168, 253, 0, 47, 6, 176, 5, 198, 168, 209, 154, 6, 62, 176, 5, 198, 35, 190, 0, 110, 62, 176, 5, 218, 28, 0, + 167, 172, 110, 176, 5, 42, 168, 209, 93, 47, 62, 176, 5, 218, 168, 209, 120, 74, 62, 176, 5, 218, 120, 24, 0, 110, 62, 176, 5, 218, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 18, 53, 20, 221, 0, 140, 6, 176, 5, 203, 232, 0, 0, 234, 6, 176, 208, 195, 46, 253, 0, 47, 62, 176, 5, 23, 46, 163, + 0, 140, 6, 176, 5, 195, 231, 111, 0, 141, 6, 176, 5, 198, 20, 111, 0, 140, 6, 176, 5, 72, 195, 112, 198, 172, 62, 176, 5, 42, 92, 111, + 0, 47, 62, 176, 5, 42, 229, 60, 0, 47, 74, 176, 5, 11, 35, 108, 0, 54, 62, 176, 5, 11, 187, 137, 42, 110, 110, 176, 5, 42, 167, 24, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 74, 176, 5, 92, 35, 112, 0, 47, 74, 176, 5, 194, 229, 157, 0, 110, 62, 176, 5, 72, 109, 231, 0, 110, 62, 176, 5, 218, 168, 46, + 0, 54, 62, 176, 99, 11, 229, 187, 0, 74, 62, 176, 5, 11, 221, 46, 0, 74, 62, 176, 99, 42, 72, 28, 0, 110, 62, 176, 5, 42, 38, 231, + 0, 123, 110, 176, 5, 42, 168, 112, 0, 74, 62, 176, 5, 218, 38, 112, 0, 110, 62, 176, 5, 11, 120, 163, 166, 110, 110, 176, 5, 218, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 176, 161, 72, 229, 157, 0, 0, 74, 176, 219, 170, 161, 187, 0, 0, 74, 176, 5, 166, 192, 7, 0, 0, 110, 176, 5, 218, 168, 35, + 0, 0, 74, 176, 99, 198, 42, 76, 0, 0, 74, 176, 99, 194, 243, 231, 0, 0, 6, 176, 219, 203, 28, 126, 112, 0, 110, 176, 5, 12, 168, 112, + 0, 0, 110, 176, 5, 42, 231, 111, 0, 0, 110, 176, 5, 42, 35, 46, 0, 0, 110, 176, 5, 92, 229, 60, 168, 0, 110, 176, 5, 42, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 110, 176, 5, 92, 38, 111, 0, 0, 74, 176, 5, 42, 229, 111, 0, 0, 110, 176, 5, 218, 120, 46, 12, 0, 110, 176, 5, 218, 168, 209, + 0, 0, 110, 176, 99, 42, 38, 38, 0, 0, 110, 176, 5, 218, 229, 111, 0, 0, 74, 176, 5, 11, 229, 46, 44, 0, 110, 176, 5, 218, 168, 209, + 120, 0, 110, 176, 5, 42, 168, 60, 231, 0, 110, 176, 5, 42, 168, 112, 112, 0, 110, 176, 5, 218, 168, 0, 28, 0, 110, 176, 5, 218, 120, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 207, 159, 6, 176, 5, 11, 35, 65, 0, 159, 6, 176, 31, 11, 28, 253, 0, 234, 22, 75, 5, 23, 194, 76, 0, 62, 62, 176, 216, 11, 244, 120, + 128, 140, 6, 176, 99, 180, 35, 35, 0, 234, 62, 176, 5, 203, 231, 24, 0, 234, 6, 75, 122, 99, 244, 190, 0, 74, 62, 30, 5, 42, 92, 0, + 28, 54, 62, 176, 5, 92, 35, 46, 0, 47, 62, 75, 5, 218, 120, 187, 0, 62, 62, 176, 5, 166, 120, 108, 0, 110, 110, 176, 5, 218, 35, 190, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 107, 222, 207, 224, 168, 0, 0, 159, 21, 89, 18, 180, 224, 203, 0, 141, 21, 30, 66, 122, 73, 229, 0, 172, 6, 176, 241, 23, 165, 17, + 0, 58, 10, 176, 18, 92, 230, 0, 0, 58, 6, 174, 1, 213, 167, 0, 0, 234, 2, 237, 5, 11, 165, 0, 0, 26, 9, 91, 177, 42, 157, 53, + 0, 123, 54, 254, 56, 72, 170, 23, 0, 134, 6, 62, 11, 128, 195, 218, 0, 9, 21, 91, 251, 187, 76, 70, 0, 123, 254, 30, 99, 92, 23, 108, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 246, 62, 79, 5, 207, 198, 16, 0, 159, 74, 89, 18, 128, 124, 124, 0, 123, 62, 241, 170, 98, 62, 223, 0, 172, 74, 176, 5, 12, 112, 50, + 0, 47, 56, 233, 127, 180, 174, 111, 0, 215, 21, 4, 122, 92, 253, 0, 0, 133, 62, 44, 251, 219, 19, 0, 0, 107, 110, 176, 5, 203, 203, 0, + 0, 238, 62, 56, 192, 166, 35, 46, 0, 110, 62, 241, 122, 166, 128, 209, 0, 74, 62, 30, 5, 198, 76, 38, 0, 62, 110, 176, 5, 23, 35, 163, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 234, 6, 94, 177, 80, 202, 0, 0, 82, 6, 56, 32, 86, 0, 0, 0, 140, 134, 32, 232, 173, 0, 0, 0, 119, 74, 49, 219, 0, 0, 0, + 0, 234, 110, 142, 176, 124, 118, 190, 0, 234, 10, 164, 71, 153, 0, 0, 0, 140, 117, 174, 210, 83, 194, 70, 0, 62, 134, 30, 148, 107, 0, 88, + 0, 123, 123, 69, 18, 42, 110, 220, 0, 145, 74, 179, 75, 209, 72, 0, 0, 71, 223, 49, 5, 208, 0, 0, 0, 62, 110, 30, 218, 198, 38, 168, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 110, 89, 170, 166, 86, 5, 0, 123, 6, 200, 243, 207, 32, 41, 0, 235, 110, 142, 5, 124, 3, 0, 0, 74, 62, 75, 156, 128, 218, 0, + 0, 118, 62, 30, 56, 153, 23, 151, 0, 62, 6, 100, 138, 218, 0, 0, 0, 21, 6, 240, 176, 32, 120, 198, 0, 6, 3, 176, 194, 99, 187, 126, + 35, 238, 110, 176, 18, 11, 231, 46, 126, 74, 62, 176, 122, 203, 244, 221, 0, 10, 74, 75, 251, 72, 76, 17, 0, 62, 62, 176, 5, 42, 120, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 30, 18, 180, 35, 229, 0, 141, 6, 176, 207, 72, 38, 187, 0, 162, 2, 176, 73, 30, 114, 179, 0, 139, 110, 200, 31, 210, 46, 12, + 240, 140, 6, 91, 207, 128, 229, 76, 0, 141, 6, 179, 210, 85, 23, 209, 0, 214, 6, 30, 217, 218, 153, 209, 0, 123, 139, 177, 217, 28, 24, 0, + 0, 246, 74, 176, 18, 11, 28, 24, 0, 47, 62, 176, 99, 218, 99, 0, 0, 6, 62, 176, 3, 86, 167, 60, 0, 110, 74, 241, 56, 180, 168, 163, + 213, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, + 0, 213, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 181, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 0, 141, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 107, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, + 216, 246, 74, 75, 5, 11, 111, 112, 0, 47, 6, 176, 5, 166, 76, 35, 0, 6, 6, 176, 5, 180, 35, 187, 0, 74, 62, 176, 5, 194, 198, 50, + 8, 54, 62, 176, 161, 42, 195, 0, 76, 6, 6, 176, 122, 11, 203, 28, 0, 6, 6, 179, 243, 180, 38, 24, 42, 74, 62, 176, 204, 203, 111, 65, + 50, 54, 74, 176, 99, 42, 168, 209, 117, 74, 62, 176, 5, 92, 229, 65, 221, 74, 62, 176, 5, 42, 157, 0, 0, 110, 110, 176, 5, 128, 120, 41, + 181, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 26, 110, 204, 216, 233, 180, 0, 0, 10, 6, 31, 153, 11, 228, 0, 0, 62, 9, 156, 18, 64, 96, 0, 0, 110, 176, 200, 198, 145, 221, + 0, 0, 6, 222, 169, 156, 170, 0, 0, 0, 2, 237, 75, 218, 53, 190, 0, 0, 6, 91, 30, 198, 10, 229, 0, 0, 62, 30, 156, 72, 203, 46, + 0, 0, 19, 176, 18, 165, 194, 42, 0, 0, 74, 30, 99, 62, 35, 218, 0, 0, 6, 217, 23, 218, 12, 190, 144, 0, 62, 176, 5, 144, 168, 221, + 1, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 62, 89, 192, 161, 166, 111, 0, 0, 74, 176, 216, 180, 198, 112, 121, 0, 62, 13, 31, 23, 11, 112, 21, 0, 62, 176, 243, 218, 231, 60, + 0, 0, 107, 13, 192, 166, 109, 187, 0, 0, 6, 74, 56, 75, 195, 144, 0, 0, 6, 176, 208, 99, 23, 231, 0, 0, 62, 176, 122, 23, 111, 163, + 236, 0, 233, 56, 161, 166, 165, 111, 0, 0, 62, 176, 5, 109, 35, 168, 0, 0, 110, 176, 18, 180, 38, 24, 0, 0, 110, 176, 5, 218, 168, 17, + 224, 0, 0, 0, 0, 0, 0, 0, 205, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 6, 176, 207, 195, 229, 253, 0, 159, 6, 176, 5, 198, 28, 221, 0, 140, 6, 176, 5, 195, 187, 157, 0, 110, 62, 176, 5, 11, 28, 46, + 0, 140, 6, 176, 99, 53, 244, 187, 0, 234, 6, 176, 207, 126, 203, 120, 0, 234, 6, 176, 99, 12, 99, 209, 0, 62, 62, 176, 5, 86, 157, 50, + 0, 54, 62, 176, 5, 42, 11, 24, 0, 74, 62, 176, 99, 5, 38, 221, 0, 74, 62, 30, 5, 72, 28, 35, 229, 110, 62, 176, 5, 128, 46, 65, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 6, 176, 18, 161, 248, 65, 0, 140, 62, 217, 5, 203, 235, 65, 0, 141, 6, 75, 243, 92, 195, 28, 0, 47, 62, 176, 5, 11, 35, 253, + 0, 140, 6, 3, 138, 170, 253, 31, 0, 234, 6, 179, 122, 53, 0, 27, 0, 141, 6, 75, 219, 11, 35, 18, 66, 159, 62, 176, 5, 12, 24, 209, + 0, 123, 54, 176, 204, 210, 162, 12, 0, 62, 6, 69, 3, 92, 59, 46, 0, 54, 62, 91, 86, 42, 253, 182, 0, 74, 62, 176, 5, 72, 23, 108, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 6, 176, 5, 92, 168, 231, 0, 47, 74, 176, 5, 156, 126, 41, 221, 74, 62, 176, 232, 5, 204, 11, 0, 74, 62, 176, 5, 42, 157, 190, + 0, 74, 62, 176, 156, 11, 92, 157, 0, 246, 6, 75, 251, 92, 248, 94, 0, 6, 110, 176, 138, 166, 35, 46, 0, 74, 62, 176, 5, 42, 35, 209, + 0, 62, 62, 176, 161, 92, 187, 190, 0, 62, 62, 176, 5, 11, 35, 108, 0, 110, 62, 176, 5, 42, 28, 116, 190, 62, 62, 176, 5, 218, 76, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 45, 6, 100, 5, 11, 20, 60, 0, 141, 74, 197, 207, 76, 46, 167, 0, 140, 6, 91, 249, 153, 218, 27, 0, 6, 62, 237, 208, 122, 221, 79, + 0, 141, 74, 176, 241, 198, 120, 218, 0, 140, 6, 94, 166, 161, 157, 253, 0, 234, 6, 176, 3, 243, 26, 92, 0, 6, 74, 30, 208, 120, 226, 166, + 0, 123, 62, 75, 156, 218, 229, 50, 0, 74, 62, 176, 208, 42, 86, 229, 0, 6, 62, 179, 156, 218, 253, 221, 0, 54, 62, 176, 5, 72, 112, 221, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 14, 47, 74, 176, 99, 180, 50, 163, 0, 47, 62, 75, 207, 156, 187, 251, 0, 6, 110, 176, 124, 5, 180, 53, 0, 123, 62, 176, 5, 195, 167, 157, + 0, 140, 62, 75, 5, 53, 195, 180, 0, 62, 62, 75, 18, 12, 111, 190, 0, 234, 2, 176, 219, 120, 17, 209, 0, 74, 62, 176, 5, 12, 168, 190, + 0, 172, 62, 176, 5, 128, 168, 38, 0, 54, 110, 176, 99, 203, 157, 17, 0, 110, 62, 176, 31, 170, 167, 167, 243, 110, 62, 176, 5, 128, 167, 65, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 75, 18, 92, 23, 194, 0, 159, 6, 100, 156, 243, 229, 228, 0, 234, 6, 44, 243, 180, 0, 97, 0, 107, 62, 176, 5, 166, 109, 18, + 0, 140, 6, 75, 243, 128, 60, 221, 0, 234, 6, 237, 5, 170, 100, 2, 0, 140, 6, 176, 194, 12, 49, 229, 0, 74, 6, 49, 211, 3, 243, 12, + 0, 54, 62, 176, 5, 198, 38, 35, 0, 47, 62, 30, 5, 194, 204, 203, 0, 74, 62, 3, 30, 38, 231, 218, 0, 74, 62, 176, 99, 195, 231, 166, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 74, 176, 99, 23, 35, 17, 209, 47, 6, 75, 5, 11, 23, 60, 0, 47, 6, 176, 207, 156, 38, 166, 193, 110, 62, 176, 5, 109, 231, 28, + 0, 54, 74, 176, 99, 218, 38, 46, 0, 140, 6, 176, 156, 42, 229, 60, 132, 6, 62, 75, 5, 92, 23, 76, 0, 110, 62, 176, 5, 42, 229, 120, + 102, 110, 62, 176, 5, 42, 35, 0, 214, 110, 62, 176, 5, 218, 168, 209, 0, 62, 62, 176, 5, 92, 231, 221, 69, 62, 62, 176, 5, 218, 167, 65, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 30, 124, 42, 23, 244, 0, 0, 74, 91, 161, 12, 229, 112, 0, 0, 6, 75, 5, 219, 46, 12, 38, 0, 110, 176, 5, 128, 76, 17, + 0, 0, 62, 176, 243, 208, 5, 253, 0, 0, 6, 75, 5, 72, 209, 253, 0, 0, 6, 75, 5, 76, 229, 0, 0, 0, 62, 176, 5, 170, 231, 163, + 0, 0, 110, 176, 99, 11, 35, 167, 0, 0, 110, 176, 5, 92, 180, 157, 0, 0, 110, 176, 5, 198, 203, 165, 229, 0, 62, 176, 5, 128, 20, 60, + 181, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 143, 0, 74, 176, 99, 170, 166, 221, 214, 0, 74, 176, 99, 170, 111, 231, 0, 0, 74, 176, 99, 92, 195, 203, 171, 0, 110, 176, 5, 42, 187, 24, + 0, 0, 62, 176, 161, 109, 20, 187, 0, 0, 74, 176, 5, 194, 74, 76, 0, 0, 62, 176, 30, 35, 231, 111, 46, 0, 62, 176, 5, 42, 76, 0, + 20, 0, 110, 176, 192, 166, 35, 46, 0, 0, 110, 176, 5, 92, 38, 111, 0, 0, 110, 176, 5, 12, 126, 46, 229, 0, 110, 176, 5, 218, 120, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 187, 159, 6, 75, 207, 11, 35, 221, 24, 159, 6, 75, 207, 195, 35, 209, 144, 234, 6, 176, 99, 23, 180, 60, 0, 110, 62, 176, 5, 42, 168, 209, + 112, 140, 6, 176, 5, 11, 35, 221, 86, 234, 6, 176, 5, 195, 28, 0, 69, 234, 6, 176, 5, 203, 76, 46, 0, 74, 62, 176, 156, 128, 35, 209, + 168, 54, 62, 176, 5, 42, 35, 209, 92, 47, 62, 176, 5, 42, 35, 65, 0, 74, 62, 176, 5, 11, 231, 190, 187, 110, 62, 176, 5, 218, 167, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 100, 122, 92, 165, 112, 0, 234, 6, 69, 127, 16, 165, 194, 0, 234, 6, 254, 243, 38, 74, 20, 0, 47, 62, 176, 5, 53, 180, 11, + 0, 140, 62, 176, 99, 180, 251, 21, 0, 140, 62, 176, 91, 109, 111, 244, 0, 234, 6, 100, 31, 99, 12, 109, 0, 74, 62, 30, 243, 203, 46, 112, + 0, 238, 110, 176, 99, 99, 12, 28, 0, 47, 6, 176, 5, 195, 128, 76, 0, 47, 62, 179, 166, 12, 41, 108, 0, 74, 62, 176, 5, 198, 20, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 62, 3, 18, 42, 126, 108, 0, 47, 74, 176, 99, 170, 111, 28, 0, 110, 74, 176, 5, 128, 76, 244, 0, 74, 62, 176, 99, 128, 161, 187, + 0, 74, 110, 176, 31, 192, 198, 187, 0, 214, 6, 30, 31, 144, 174, 0, 0, 134, 62, 217, 249, 180, 42, 72, 0, 74, 62, 176, 156, 194, 249, 229, + 0, 172, 110, 176, 192, 166, 35, 221, 0, 123, 62, 176, 243, 92, 76, 24, 0, 74, 62, 3, 99, 72, 168, 209, 0, 110, 62, 176, 5, 218, 157, 221, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 30, 177, 176, 180, 126, 169, 140, 6, 179, 124, 120, 99, 229, 0, 234, 6, 30, 13, 112, 34, 187, 0, 47, 74, 176, 243, 128, 0, 21, + 0, 140, 6, 176, 176, 11, 35, 35, 0, 141, 6, 179, 129, 23, 218, 3, 0, 140, 6, 174, 4, 192, 91, 60, 0, 6, 9, 30, 99, 23, 0, 157, + 0, 47, 74, 176, 156, 203, 38, 111, 0, 47, 6, 176, 99, 194, 229, 108, 0, 54, 6, 30, 5, 72, 72, 20, 0, 47, 62, 176, 243, 12, 218, 190, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 74, 176, 31, 109, 167, 24, 0, 47, 62, 91, 5, 211, 99, 50, 0, 107, 62, 176, 156, 161, 218, 29, 0, 74, 62, 176, 156, 12, 20, 20, + 0, 54, 110, 176, 73, 180, 144, 28, 0, 47, 6, 197, 207, 35, 244, 76, 0, 123, 6, 176, 122, 5, 60, 218, 0, 6, 62, 75, 99, 23, 168, 209, + 0, 172, 62, 176, 5, 42, 35, 209, 0, 47, 62, 75, 5, 198, 76, 209, 95, 74, 62, 176, 5, 198, 42, 120, 229, 110, 110, 176, 5, 42, 231, 50, + 238, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 251, 140, 6, 176, 5, 11, 229, 111, 42, 141, 6, 176, 5, 11, 168, 65, 0, 234, 6, 217, 219, 210, 20, 11, 0, 74, 62, 176, 18, 5, 76, 108, + 194, 140, 6, 176, 5, 11, 35, 111, 0, 141, 6, 176, 219, 180, 229, 231, 209, 234, 6, 217, 249, 194, 109, 209, 0, 74, 62, 176, 99, 92, 144, 183, + 163, 246, 74, 176, 5, 42, 35, 209, 0, 47, 6, 176, 5, 42, 231, 112, 0, 74, 62, 176, 5, 12, 126, 112, 0, 110, 62, 176, 5, 12, 20, 65, + 82, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 137, 246, 74, 176, 5, 42, 35, 221, 189, 47, 6, 176, 5, 11, 35, 65, 24, 74, 6, 176, 5, 42, 38, 60, 0, 110, 62, 176, 5, 42, 120, 0, + 244, 54, 74, 176, 5, 42, 35, 46, 0, 47, 6, 176, 5, 42, 38, 24, 0, 6, 62, 176, 5, 42, 42, 163, 0, 74, 62, 176, 5, 218, 35, 209, + 190, 238, 62, 176, 5, 42, 168, 209, 168, 47, 62, 176, 5, 42, 168, 209, 180, 62, 62, 176, 5, 42, 168, 50, 198, 110, 62, 176, 5, 218, 167, 50, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 176, 56, 203, 229, 38, 0, 0, 62, 176, 219, 42, 28, 7, 0, 0, 62, 179, 251, 42, 120, 163, 0, 0, 62, 176, 156, 53, 157, 38, + 0, 0, 74, 176, 18, 69, 46, 170, 0, 0, 74, 44, 5, 53, 11, 120, 0, 0, 6, 176, 156, 195, 120, 120, 195, 0, 74, 176, 156, 5, 218, 183, + 0, 0, 110, 176, 161, 42, 167, 209, 112, 0, 62, 176, 99, 42, 187, 187, 0, 0, 6, 176, 99, 198, 35, 24, 183, 0, 110, 176, 5, 218, 168, 190, + 238, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 176, 192, 42, 35, 165, 0, 0, 110, 176, 5, 180, 229, 157, 0, 0, 62, 75, 156, 12, 120, 112, 0, 0, 110, 176, 5, 92, 187, 112, + 0, 0, 74, 176, 192, 198, 111, 126, 0, 0, 62, 30, 208, 180, 157, 218, 0, 0, 6, 176, 99, 92, 187, 41, 0, 0, 110, 176, 5, 11, 231, 221, + 0, 0, 110, 176, 161, 166, 165, 183, 244, 0, 110, 176, 5, 42, 157, 0, 0, 0, 62, 176, 99, 42, 165, 0, 167, 0, 110, 176, 5, 218, 120, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 126, 159, 6, 176, 207, 195, 35, 221, 72, 159, 6, 176, 219, 11, 35, 0, 0, 234, 6, 176, 5, 12, 231, 112, 82, 110, 62, 176, 5, 218, 76, 111, + 0, 140, 6, 176, 5, 11, 231, 65, 244, 234, 6, 176, 5, 198, 168, 209, 183, 234, 6, 176, 5, 198, 157, 50, 0, 74, 62, 176, 99, 218, 76, 244, + 143, 54, 62, 176, 5, 42, 168, 50, 0, 74, 62, 176, 5, 42, 231, 65, 218, 74, 62, 176, 5, 218, 28, 209, 190, 110, 62, 176, 5, 218, 120, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 208, 23, 120, 111, 0, 140, 6, 176, 31, 42, 38, 190, 0, 141, 6, 176, 5, 12, 35, 111, 0, 47, 6, 176, 5, 218, 168, 24, + 0, 140, 6, 176, 99, 11, 251, 53, 0, 140, 6, 176, 156, 12, 38, 221, 0, 140, 6, 176, 99, 12, 35, 65, 0, 47, 62, 176, 5, 218, 111, 65, + 0, 47, 62, 176, 5, 42, 168, 209, 0, 47, 62, 176, 5, 194, 229, 0, 0, 54, 62, 176, 99, 218, 187, 28, 0, 110, 62, 176, 5, 218, 168, 112, + 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 62, 176, 5, 218, 229, 183, 0, 47, 62, 176, 5, 195, 229, 41, 0, 74, 74, 176, 156, 11, 157, 46, 0, 110, 62, 176, 5, 42, 20, 65, + 207, 110, 62, 176, 5, 11, 229, 116, 1, 6, 62, 176, 5, 42, 229, 41, 0, 47, 62, 176, 99, 42, 229, 65, 168, 110, 62, 176, 5, 198, 76, 253, + 244, 123, 62, 176, 5, 42, 168, 46, 0, 110, 62, 176, 5, 42, 229, 168, 0, 110, 62, 176, 5, 12, 231, 0, 11, 110, 62, 176, 5, 218, 120, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 156, 198, 198, 137, 0, 234, 6, 176, 208, 92, 5, 28, 0, 140, 6, 75, 5, 166, 168, 183, 0, 47, 62, 176, 5, 195, 166, 65, + 0, 140, 6, 176, 99, 128, 28, 108, 0, 140, 6, 176, 208, 128, 111, 221, 0, 140, 6, 100, 5, 232, 126, 209, 0, 54, 62, 176, 5, 42, 231, 120, + 0, 47, 74, 176, 5, 42, 229, 112, 0, 47, 6, 176, 5, 218, 229, 244, 166, 54, 62, 176, 5, 218, 35, 221, 254, 110, 62, 176, 5, 218, 120, 244, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 62, 176, 99, 11, 231, 46, 0, 47, 62, 176, 5, 195, 168, 157, 110, 74, 62, 176, 5, 12, 157, 157, 0, 74, 110, 176, 5, 218, 38, 167, + 7, 54, 62, 176, 5, 218, 120, 28, 0, 74, 62, 176, 156, 92, 111, 0, 0, 74, 62, 176, 5, 218, 231, 60, 0, 74, 62, 176, 5, 198, 168, 137, + 0, 110, 62, 176, 5, 198, 35, 65, 37, 110, 62, 176, 5, 42, 187, 24, 0, 74, 62, 176, 5, 218, 120, 60, 0, 110, 62, 176, 5, 218, 120, 253, + 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 195, 229, 112, 0, 141, 6, 176, 5, 11, 229, 116, 0, 234, 6, 176, 86, 195, 120, 112, 0, 74, 62, 176, 5, 218, 198, 168, + 38, 140, 6, 176, 5, 42, 35, 137, 0, 141, 6, 176, 207, 72, 231, 244, 0, 234, 6, 176, 5, 42, 229, 187, 0, 110, 62, 176, 5, 198, 198, 28, + 0, 246, 74, 176, 5, 42, 168, 221, 0, 47, 6, 176, 5, 42, 168, 209, 0, 74, 62, 176, 5, 42, 167, 209, 0, 110, 62, 176, 5, 198, 76, 112, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 126, 246, 74, 176, 5, 42, 229, 221, 0, 47, 6, 176, 5, 11, 231, 112, 0, 54, 62, 176, 99, 42, 28, 46, 0, 110, 62, 176, 5, 218, 168, 112, + 0, 54, 74, 176, 5, 42, 35, 112, 0, 47, 6, 176, 5, 42, 35, 60, 3, 6, 6, 176, 5, 218, 231, 41, 0, 110, 62, 176, 5, 42, 168, 0, + 209, 172, 62, 176, 5, 42, 168, 209, 194, 47, 62, 176, 5, 218, 168, 244, 207, 74, 62, 176, 5, 42, 168, 209, 92, 110, 62, 176, 5, 218, 168, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 176, 5, 194, 167, 209, 0, 0, 6, 176, 5, 109, 231, 111, 0, 0, 74, 176, 124, 92, 72, 65, 0, 0, 74, 176, 5, 42, 28, 209, + 0, 0, 74, 176, 5, 42, 28, 24, 0, 0, 74, 176, 219, 194, 35, 35, 0, 0, 74, 176, 5, 12, 120, 209, 86, 0, 74, 176, 5, 42, 231, 60, + 0, 0, 110, 176, 5, 42, 167, 46, 0, 0, 110, 176, 5, 11, 168, 253, 65, 0, 110, 176, 5, 42, 231, 116, 20, 0, 110, 176, 5, 218, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 110, 176, 5, 92, 166, 183, 0, 0, 110, 176, 5, 42, 229, 111, 0, 0, 110, 176, 5, 11, 38, 112, 23, 0, 110, 176, 5, 218, 168, 209, + 0, 0, 110, 176, 5, 42, 38, 46, 0, 0, 110, 176, 5, 11, 229, 111, 0, 0, 110, 176, 5, 11, 126, 116, 28, 0, 110, 176, 5, 218, 168, 112, + 48, 0, 110, 176, 5, 42, 165, 112, 0, 0, 110, 176, 5, 42, 229, 0, 229, 0, 110, 176, 5, 42, 38, 65, 120, 0, 110, 176, 5, 218, 120, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 179, 159, 6, 176, 5, 11, 229, 137, 0, 159, 6, 176, 207, 195, 187, 229, 166, 234, 6, 176, 156, 218, 46, 221, 0, 74, 62, 176, 99, 170, 35, 60, + 128, 140, 62, 75, 99, 180, 38, 244, 0, 234, 6, 176, 124, 218, 53, 229, 84, 234, 6, 176, 99, 218, 50, 0, 0, 74, 62, 176, 156, 86, 168, 0, + 201, 54, 74, 176, 99, 42, 168, 112, 0, 74, 62, 176, 5, 42, 229, 65, 0, 74, 62, 176, 5, 180, 28, 190, 8, 110, 62, 176, 5, 218, 187, 190, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 74, 176, 232, 12, 78, 156, 0, 141, 6, 30, 219, 192, 92, 190, 0, 141, 6, 49, 99, 92, 203, 165, 0, 47, 62, 30, 5, 218, 231, 76, + 0, 140, 74, 40, 232, 198, 76, 15, 0, 141, 6, 75, 207, 203, 23, 190, 0, 234, 6, 49, 138, 23, 215, 0, 0, 54, 62, 40, 192, 72, 92, 76, + 0, 54, 110, 176, 161, 11, 94, 60, 0, 47, 74, 237, 208, 12, 177, 151, 0, 123, 6, 32, 21, 12, 50, 166, 0, 110, 62, 176, 5, 92, 76, 244, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 74, 176, 192, 166, 76, 163, 0, 47, 62, 176, 99, 12, 111, 190, 0, 74, 74, 176, 99, 166, 218, 0, 4, 54, 62, 176, 5, 42, 28, 209, + 198, 54, 62, 89, 192, 166, 46, 35, 0, 6, 62, 176, 207, 166, 165, 157, 0, 234, 6, 75, 156, 144, 12, 24, 0, 110, 62, 176, 5, 194, 28, 163, + 108, 110, 110, 89, 161, 166, 35, 111, 0, 74, 62, 176, 99, 92, 229, 163, 21, 6, 62, 176, 156, 53, 38, 65, 167, 110, 62, 176, 5, 218, 167, 253, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 0, 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 75, 99, 92, 11, 46, 0, 141, 6, 197, 5, 72, 187, 168, 0, 140, 6, 164, 232, 65, 190, 102, 0, 172, 74, 176, 153, 120, 244, 243, + 0, 141, 6, 30, 153, 161, 166, 221, 0, 140, 6, 30, 85, 180, 109, 76, 0, 140, 22, 75, 18, 166, 22, 0, 0, 74, 62, 3, 156, 219, 73, 157, + 0, 47, 62, 176, 99, 92, 167, 249, 0, 123, 62, 176, 243, 92, 11, 5, 0, 242, 22, 49, 100, 144, 168, 168, 144, 6, 62, 176, 5, 72, 120, 17, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 74, 176, 5, 128, 203, 190, 0, 47, 6, 176, 207, 194, 229, 221, 0, 234, 62, 176, 18, 11, 187, 108, 0, 74, 62, 176, 156, 144, 38, 190, + 0, 54, 62, 3, 99, 198, 229, 50, 0, 6, 6, 30, 153, 11, 92, 65, 0, 234, 2, 176, 5, 203, 229, 46, 0, 110, 62, 176, 243, 198, 111, 120, + 0, 172, 62, 176, 5, 42, 231, 17, 0, 47, 62, 176, 5, 170, 187, 0, 0, 74, 62, 176, 156, 23, 76, 0, 0, 110, 62, 176, 5, 218, 120, 60, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 75, 249, 195, 60, 60, 0, 141, 6, 75, 211, 92, 166, 249, 0, 234, 6, 237, 32, 12, 209, 111, 0, 47, 74, 176, 243, 161, 5, 142, + 0, 140, 6, 3, 207, 53, 194, 126, 0, 141, 6, 176, 124, 207, 204, 137, 0, 234, 6, 179, 241, 194, 184, 65, 18, 6, 62, 176, 49, 60, 28, 12, + 0, 246, 74, 176, 99, 11, 35, 60, 0, 47, 62, 176, 31, 195, 231, 112, 0, 21, 62, 75, 31, 122, 195, 89, 0, 123, 62, 176, 5, 218, 111, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 54, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 181, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 224, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 74, 176, 99, 23, 35, 60, 0, 47, 6, 75, 5, 12, 231, 0, 104, 74, 62, 176, 153, 11, 76, 111, 0, 74, 62, 176, 99, 194, 53, 120, + 0, 140, 74, 176, 99, 53, 195, 209, 0, 47, 6, 176, 5, 170, 229, 209, 0, 6, 6, 176, 156, 53, 157, 50, 0, 74, 62, 176, 5, 53, 170, 209, + 163, 172, 62, 176, 99, 42, 35, 112, 0, 74, 62, 176, 5, 218, 38, 0, 0, 110, 62, 176, 5, 42, 28, 24, 0, 110, 62, 176, 5, 218, 120, 190, + 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 200, 124, 195, 28, 229, 0, 0, 6, 176, 219, 60, 229, 0, 0, 0, 74, 75, 208, 56, 24, 255, 0, 0, 62, 176, 99, 109, 28, 0, + 0, 0, 74, 30, 5, 218, 120, 165, 0, 0, 74, 75, 153, 111, 207, 253, 0, 0, 6, 179, 243, 109, 22, 38, 0, 0, 62, 176, 5, 218, 167, 12, + 0, 0, 74, 176, 161, 109, 111, 50, 0, 0, 74, 75, 156, 92, 187, 170, 140, 0, 110, 91, 122, 194, 180, 35, 65, 0, 62, 176, 5, 23, 168, 0, + 181, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 24, 0, 74, 176, 192, 92, 165, 60, 0, 0, 74, 176, 219, 195, 229, 111, 0, 0, 74, 176, 99, 53, 180, 24, 49, 0, 110, 176, 5, 42, 35, 112, + 0, 0, 62, 176, 99, 166, 111, 28, 0, 0, 62, 176, 5, 166, 180, 65, 0, 0, 6, 176, 5, 53, 229, 253, 2, 0, 110, 176, 5, 218, 168, 60, + 35, 0, 110, 176, 192, 166, 165, 183, 118, 0, 62, 176, 5, 42, 165, 46, 215, 0, 62, 176, 5, 42, 168, 116, 12, 0, 110, 176, 5, 218, 120, 190, + 63, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 6, 176, 207, 195, 229, 60, 11, 159, 6, 75, 207, 11, 229, 112, 0, 140, 6, 176, 5, 218, 111, 60, 0, 54, 62, 176, 5, 42, 168, 221, + 0, 140, 6, 176, 99, 92, 53, 190, 0, 234, 6, 176, 5, 11, 35, 28, 0, 234, 6, 176, 5, 92, 203, 126, 23, 74, 62, 176, 5, 42, 76, 190, + 0, 54, 62, 176, 99, 198, 35, 111, 0, 74, 62, 176, 5, 180, 38, 112, 0, 110, 62, 176, 5, 218, 231, 112, 221, 110, 62, 176, 5, 218, 120, 190, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 42, 46, 126, 50, 140, 6, 176, 5, 11, 42, 46, 0, 140, 6, 176, 5, 12, 229, 229, 253, 172, 110, 176, 5, 42, 35, 209, + 0, 234, 6, 176, 122, 211, 35, 210, 0, 140, 6, 176, 208, 42, 165, 112, 0, 141, 6, 176, 219, 198, 20, 253, 0, 47, 6, 176, 5, 42, 35, 209, + 0, 110, 110, 176, 5, 42, 35, 229, 0, 110, 110, 176, 5, 218, 229, 28, 0, 110, 110, 176, 5, 92, 92, 190, 0, 110, 110, 176, 5, 218, 168, 46, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 120, 47, 110, 176, 5, 42, 35, 221, 237, 172, 110, 176, 5, 11, 35, 60, 0, 172, 110, 176, 5, 42, 229, 221, 190, 172, 110, 176, 5, 218, 168, 209, + 0, 54, 110, 176, 5, 198, 168, 28, 0, 110, 62, 176, 5, 42, 187, 209, 0, 47, 6, 176, 5, 42, 229, 46, 137, 47, 62, 176, 5, 218, 120, 209, + 38, 110, 110, 176, 5, 42, 165, 112, 0, 110, 110, 176, 5, 92, 229, 221, 16, 110, 110, 176, 5, 42, 38, 60, 65, 110, 110, 176, 5, 218, 120, 190, + 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 159, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 11, 168, 231, 0, 140, 6, 176, 5, 12, 231, 38, 0, 140, 6, 176, 5, 12, 203, 157, 0, 47, 110, 176, 5, 42, 28, 112, + 0, 140, 6, 176, 5, 195, 12, 231, 0, 234, 6, 176, 176, 218, 111, 41, 0, 140, 6, 176, 5, 92, 229, 128, 0, 110, 110, 176, 5, 218, 126, 221, + 0, 172, 110, 176, 5, 5, 126, 221, 0, 172, 110, 176, 5, 72, 218, 221, 0, 123, 62, 176, 243, 11, 195, 0, 0, 110, 62, 176, 5, 218, 168, 112, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 209, 47, 6, 176, 5, 42, 111, 120, 0, 159, 6, 176, 5, 42, 229, 209, 0, 54, 110, 176, 5, 198, 38, 0, 10, 54, 110, 176, 5, 218, 168, 209, + 0, 54, 110, 176, 5, 42, 35, 253, 0, 54, 6, 176, 5, 12, 35, 41, 0, 110, 6, 176, 5, 218, 35, 46, 0, 110, 110, 176, 5, 42, 20, 244, + 0, 110, 110, 176, 5, 218, 167, 209, 0, 110, 110, 176, 5, 198, 35, 190, 0, 110, 110, 176, 5, 218, 120, 209, 198, 110, 110, 176, 5, 218, 168, 163, + 51, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 28, 140, 6, 176, 5, 11, 168, 198, 0, 140, 6, 176, 208, 198, 229, 187, 0, 140, 6, 176, 211, 12, 229, 229, 0, 47, 62, 176, 5, 12, 38, 65, + 0, 140, 6, 176, 219, 176, 194, 221, 0, 234, 6, 176, 5, 156, 76, 65, 0, 234, 6, 176, 122, 72, 229, 65, 0, 47, 62, 176, 5, 11, 28, 65, + 190, 172, 110, 176, 5, 195, 42, 209, 0, 47, 110, 176, 99, 218, 38, 60, 0, 74, 62, 176, 5, 11, 209, 0, 0, 110, 62, 176, 5, 42, 231, 76, + 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 212, 47, 6, 176, 5, 11, 157, 46, 209, 47, 6, 176, 5, 42, 229, 60, 0, 140, 6, 176, 5, 12, 76, 46, 0, 54, 110, 176, 5, 42, 168, 209, + 0, 54, 110, 176, 99, 42, 168, 0, 0, 110, 6, 176, 5, 42, 229, 0, 0, 234, 6, 176, 5, 12, 38, 46, 0, 110, 110, 176, 5, 218, 187, 46, + 0, 172, 110, 176, 5, 42, 28, 244, 0, 110, 110, 176, 5, 42, 231, 50, 0, 110, 62, 176, 5, 11, 38, 244, 245, 110, 110, 176, 5, 218, 120, 190, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 110, 176, 5, 11, 187, 53, 0, 0, 110, 176, 5, 195, 53, 126, 0, 0, 110, 176, 5, 11, 168, 253, 8, 0, 110, 176, 5, 42, 168, 46, + 46, 0, 110, 176, 99, 53, 42, 108, 0, 0, 110, 176, 99, 218, 168, 168, 0, 0, 6, 176, 5, 42, 180, 46, 0, 0, 110, 176, 5, 42, 231, 60, + 0, 0, 110, 176, 5, 42, 187, 0, 0, 0, 110, 176, 5, 12, 229, 111, 0, 0, 110, 176, 5, 42, 231, 229, 224, 0, 110, 176, 5, 218, 168, 190, + 51, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, + 203, 0, 110, 176, 99, 42, 231, 183, 208, 0, 110, 176, 5, 42, 229, 111, 192, 0, 110, 176, 5, 11, 229, 221, 76, 0, 110, 176, 5, 42, 168, 209, + 0, 0, 110, 176, 5, 198, 35, 60, 0, 0, 110, 176, 5, 11, 229, 112, 213, 0, 110, 176, 5, 12, 38, 46, 168, 0, 110, 176, 5, 218, 120, 190, + 168, 0, 110, 176, 5, 42, 35, 183, 28, 0, 110, 176, 5, 42, 157, 112, 75, 0, 110, 176, 5, 42, 229, 137, 20, 0, 110, 176, 5, 218, 120, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 35, 159, 6, 176, 5, 11, 35, 221, 25, 159, 6, 176, 5, 11, 35, 65, 0, 234, 6, 176, 5, 42, 28, 244, 0, 110, 62, 176, 5, 42, 28, 0, + 112, 140, 6, 176, 5, 42, 35, 46, 209, 234, 6, 176, 5, 11, 231, 112, 0, 234, 6, 176, 5, 198, 229, 46, 0, 110, 62, 176, 5, 42, 231, 24, + 163, 172, 62, 176, 5, 42, 168, 209, 198, 47, 62, 176, 5, 42, 168, 137, 0, 110, 62, 176, 5, 42, 165, 253, 0, 110, 110, 176, 5, 218, 168, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 173, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 198, 168, 168, 0, 140, 6, 176, 18, 194, 28, 168, 0, 140, 6, 176, 207, 12, 231, 35, 120, 47, 6, 176, 5, 218, 120, 190, + 0, 140, 6, 176, 161, 198, 76, 112, 0, 140, 6, 176, 5, 138, 116, 35, 0, 234, 6, 176, 5, 194, 126, 50, 0, 47, 62, 176, 5, 12, 229, 38, + 0, 172, 110, 176, 5, 11, 35, 76, 0, 47, 62, 176, 5, 42, 157, 163, 0, 110, 6, 176, 5, 218, 157, 35, 144, 110, 110, 176, 5, 218, 167, 17, + 173, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 110, 176, 99, 42, 35, 209, 0, 47, 6, 176, 5, 42, 35, 60, 0, 54, 62, 176, 5, 194, 229, 65, 0, 110, 110, 176, 5, 218, 28, 209, + 0, 54, 110, 176, 5, 11, 35, 35, 144, 6, 6, 176, 5, 42, 168, 17, 0, 110, 110, 176, 5, 12, 167, 209, 194, 110, 110, 176, 5, 218, 168, 244, + 158, 172, 110, 176, 5, 42, 35, 209, 126, 110, 62, 176, 5, 42, 231, 65, 0, 110, 62, 176, 5, 42, 231, 65, 194, 110, 110, 176, 5, 218, 120, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 42, 168, 41, 0, 141, 6, 176, 5, 12, 126, 28, 0, 234, 6, 176, 243, 198, 46, 108, 0, 110, 62, 176, 5, 42, 35, 163, + 31, 140, 6, 176, 5, 11, 35, 108, 0, 141, 6, 176, 99, 198, 187, 76, 0, 234, 6, 217, 5, 12, 199, 65, 0, 110, 62, 176, 5, 42, 209, 116, + 112, 172, 110, 176, 5, 42, 35, 108, 35, 47, 6, 176, 5, 42, 167, 0, 0, 54, 6, 176, 5, 218, 168, 112, 0, 110, 110, 176, 5, 218, 168, 209, + 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 110, 176, 5, 42, 35, 0, 112, 47, 6, 176, 5, 42, 168, 60, 0, 54, 62, 176, 5, 42, 231, 253, 16, 110, 62, 176, 5, 218, 35, 221, + 0, 172, 110, 176, 5, 42, 229, 0, 0, 47, 6, 176, 99, 218, 38, 112, 0, 6, 6, 176, 5, 42, 42, 221, 0, 110, 110, 176, 5, 218, 28, 65, + 120, 172, 110, 176, 5, 42, 168, 209, 46, 47, 62, 176, 5, 42, 168, 209, 104, 110, 62, 176, 5, 218, 168, 190, 190, 110, 110, 176, 5, 218, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 46, 140, 6, 176, 5, 42, 126, 65, 0, 141, 6, 176, 5, 195, 157, 65, 0, 234, 6, 176, 5, 42, 23, 60, 0, 110, 62, 176, 5, 218, 20, 76, + 42, 140, 6, 176, 5, 42, 11, 116, 163, 141, 6, 176, 5, 12, 111, 53, 121, 234, 6, 176, 5, 31, 126, 244, 0, 74, 62, 176, 5, 42, 35, 168, + 244, 172, 110, 176, 5, 42, 168, 65, 157, 47, 6, 176, 5, 218, 231, 209, 0, 54, 6, 176, 5, 42, 231, 46, 0, 110, 110, 176, 5, 218, 168, 65, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 238, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 74, 176, 5, 42, 168, 65, 65, 47, 6, 176, 5, 42, 35, 209, 0, 110, 6, 176, 5, 198, 231, 50, 0, 110, 62, 176, 5, 218, 120, 209, + 126, 172, 110, 176, 5, 42, 168, 209, 0, 47, 6, 176, 5, 198, 120, 112, 0, 6, 6, 176, 5, 42, 168, 0, 196, 110, 62, 176, 5, 218, 28, 60, + 20, 172, 110, 176, 5, 42, 168, 209, 112, 47, 62, 176, 5, 218, 168, 209, 108, 110, 62, 176, 5, 218, 168, 209, 144, 110, 110, 176, 5, 218, 167, 24, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 110, 176, 5, 12, 35, 112, 0, 0, 6, 176, 5, 11, 12, 65, 0, 0, 6, 176, 5, 11, 111, 28, 0, 0, 110, 176, 5, 42, 38, 137, + 0, 0, 110, 176, 5, 11, 111, 111, 0, 0, 110, 176, 5, 12, 218, 38, 0, 0, 110, 176, 5, 11, 187, 111, 213, 0, 110, 176, 5, 42, 111, 60, + 120, 0, 110, 176, 5, 42, 35, 0, 0, 0, 110, 176, 5, 42, 168, 209, 0, 0, 110, 176, 5, 218, 35, 65, 43, 0, 110, 176, 5, 218, 168, 60, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 128, 0, 110, 176, 99, 42, 35, 168, 0, 0, 110, 176, 5, 42, 229, 28, 0, 0, 110, 176, 5, 42, 168, 112, 25, 0, 110, 176, 5, 218, 168, 46, + 0, 0, 110, 176, 5, 42, 35, 183, 209, 0, 110, 176, 5, 42, 35, 221, 194, 0, 110, 176, 5, 11, 168, 46, 77, 0, 110, 176, 5, 218, 168, 190, + 168, 0, 110, 176, 5, 42, 35, 209, 38, 0, 110, 176, 5, 42, 168, 209, 157, 0, 110, 176, 5, 218, 168, 24, 220, 0, 110, 176, 5, 218, 120, 190, + 224, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 120, 159, 6, 176, 5, 11, 35, 221, 91, 159, 6, 176, 5, 11, 229, 111, 0, 140, 6, 176, 5, 42, 231, 112, 11, 172, 110, 176, 5, 218, 168, 112, + 108, 140, 6, 176, 5, 11, 229, 60, 0, 140, 6, 176, 5, 42, 231, 221, 231, 140, 6, 176, 5, 42, 35, 65, 197, 110, 62, 176, 5, 42, 168, 209, + 200, 172, 110, 176, 5, 42, 168, 112, 24, 47, 62, 176, 5, 42, 168, 112, 109, 110, 62, 176, 5, 218, 167, 137, 209, 110, 110, 176, 5, 218, 120, 190, + 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, + 210, 140, 6, 176, 5, 42, 229, 221, 0, 140, 6, 176, 5, 11, 229, 111, 0, 140, 6, 176, 5, 12, 126, 126, 0, 172, 110, 176, 5, 42, 231, 112, + 0, 140, 6, 176, 5, 42, 28, 60, 0, 140, 6, 176, 5, 42, 35, 60, 0, 140, 6, 176, 5, 11, 229, 111, 0, 47, 110, 176, 5, 42, 168, 112, + 38, 172, 110, 176, 5, 42, 35, 221, 112, 172, 110, 176, 5, 42, 168, 0, 251, 123, 110, 176, 5, 42, 168, 221, 190, 110, 110, 176, 5, 218, 168, 60, + 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 110, 176, 5, 42, 231, 112, 137, 172, 110, 176, 5, 12, 229, 46, 0, 172, 110, 176, 5, 12, 229, 46, 28, 172, 110, 176, 5, 218, 168, 190, + 187, 172, 110, 176, 5, 42, 35, 112, 0, 54, 110, 176, 5, 218, 168, 0, 0, 47, 110, 176, 5, 12, 35, 116, 218, 110, 110, 176, 5, 218, 120, 209, + 78, 110, 110, 176, 5, 218, 168, 0, 12, 110, 110, 176, 5, 218, 168, 112, 216, 110, 110, 176, 5, 218, 168, 190, 111, 110, 110, 176, 5, 218, 120, 190, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 82, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 42, 126, 60, 0, 140, 6, 176, 5, 11, 231, 126, 0, 140, 6, 176, 5, 42, 111, 126, 0, 172, 110, 176, 5, 218, 229, 0, + 0, 140, 6, 176, 5, 11, 126, 111, 0, 140, 6, 176, 5, 12, 229, 111, 0, 140, 6, 176, 5, 11, 126, 126, 0, 123, 110, 176, 5, 12, 168, 221, + 0, 172, 110, 176, 5, 42, 231, 112, 72, 47, 110, 176, 5, 42, 229, 46, 0, 54, 110, 176, 5, 42, 229, 112, 76, 110, 110, 176, 5, 218, 120, 112, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 122, 172, 74, 176, 5, 42, 229, 209, 168, 172, 110, 176, 5, 42, 229, 112, 126, 172, 110, 176, 5, 42, 229, 112, 112, 123, 110, 176, 5, 218, 168, 112, + 20, 172, 110, 176, 5, 42, 35, 112, 53, 172, 110, 176, 5, 218, 229, 209, 106, 54, 110, 176, 5, 12, 229, 108, 108, 110, 110, 176, 5, 218, 120, 209, + 35, 172, 110, 176, 5, 218, 168, 190, 229, 123, 110, 176, 5, 218, 168, 190, 190, 54, 110, 176, 5, 218, 120, 190, 209, 110, 110, 176, 5, 218, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 140, 6, 176, 5, 42, 229, 221, 0, 140, 6, 176, 5, 218, 229, 221, 0, 140, 6, 176, 5, 12, 168, 65, 56, 123, 110, 176, 5, 218, 168, 190, + 143, 140, 6, 176, 5, 42, 231, 221, 0, 140, 6, 176, 5, 42, 229, 168, 0, 140, 6, 176, 5, 218, 35, 46, 0, 123, 110, 176, 5, 218, 168, 221, + 244, 172, 110, 176, 5, 42, 231, 112, 0, 47, 110, 176, 5, 42, 231, 112, 62, 54, 110, 176, 5, 42, 168, 112, 194, 110, 110, 176, 5, 218, 168, 112, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 3, 172, 110, 176, 5, 42, 231, 112, 157, 47, 110, 176, 5, 42, 229, 112, 190, 54, 62, 176, 5, 42, 231, 112, 168, 110, 110, 176, 5, 218, 168, 112, + 42, 172, 110, 176, 5, 42, 35, 60, 28, 47, 110, 176, 5, 12, 229, 108, 106, 54, 62, 176, 5, 42, 229, 46, 0, 110, 110, 176, 5, 218, 168, 209, + 209, 172, 110, 176, 5, 218, 168, 209, 163, 47, 110, 176, 5, 218, 168, 190, 253, 54, 110, 176, 5, 218, 168, 190, 76, 110, 110, 176, 5, 218, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, + 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, + 42, 0, 110, 176, 5, 42, 229, 111, 0, 0, 110, 176, 5, 12, 229, 126, 107, 0, 110, 176, 5, 42, 229, 126, 231, 0, 110, 176, 5, 218, 168, 112, + 0, 0, 110, 176, 5, 42, 229, 35, 187, 0, 110, 176, 5, 12, 229, 116, 0, 0, 110, 176, 5, 12, 126, 116, 221, 0, 110, 176, 5, 42, 231, 112, + 218, 0, 110, 176, 5, 218, 168, 112, 3, 0, 110, 176, 5, 42, 168, 190, 190, 0, 110, 176, 5, 218, 231, 112, 167, 0, 110, 176, 5, 218, 120, 190, + 172, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, + 169, 0, 110, 176, 5, 42, 229, 111, 120, 0, 110, 176, 5, 42, 229, 111, 16, 0, 110, 176, 5, 42, 229, 112, 168, 0, 110, 176, 5, 218, 120, 190, + 18, 0, 110, 176, 5, 42, 168, 112, 157, 0, 110, 176, 5, 42, 229, 111, 231, 0, 110, 176, 5, 12, 229, 116, 190, 0, 110, 176, 5, 218, 120, 190, + 28, 0, 110, 176, 5, 218, 168, 190, 187, 0, 110, 176, 5, 218, 168, 190, 190, 0, 110, 176, 5, 218, 120, 190, 190, 0, 110, 176, 5, 218, 120, 190, +}; + +static const unsigned char model_run_state_table[8192] = +{ + 80, 168, 115, 59, 51, 58, 99, 250, 80, 80, 225, 59, 63, 99, 250, 250, 233, 80, 225, 23, 51, 63, 207, 99, 233, 80, 225, 23, 23, 249, 207, 1, + 20, 80, 225, 23, 23, 98, 104, 58, 20, 80, 225, 23, 23, 160, 108, 167, 20, 80, 65, 23, 23, 160, 207, 148, 80, 80, 65, 112, 160, 160, 207, 4, + 114, 114, 219, 247, 223, 222, 108, 108, 61, 128, 216, 202, 59, 100, 108, 12, 61, 128, 245, 25, 13, 103, 226, 132, 61, 20, 245, 251, 247, 231, 84, 104, + 61, 20, 245, 159, 239, 89, 251, 84, 61, 20, 20, 251, 72, 250, 103, 135, 34, 20, 20, 232, 100, 104, 251, 58, 34, 61, 20, 237, 103, 72, 125, 104, + 114, 145, 219, 247, 123, 63, 58, 4, 128, 245, 142, 247, 103, 58, 58, 250, 20, 190, 142, 13, 103, 100, 104, 218, 61, 190, 245, 146, 239, 119, 226, 108, + 61, 20, 237, 25, 226, 160, 224, 183, 61, 20, 245, 14, 199, 4, 108, 108, 34, 20, 20, 251, 72, 82, 1, 108, 34, 20, 20, 125, 125, 47, 226, 104, + 128, 151, 219, 247, 119, 63, 12, 108, 85, 156, 219, 219, 231, 100, 58, 108, 94, 137, 151, 219, 7, 100, 89, 108, 94, 128, 190, 25, 72, 231, 63, 104, + 61, 73, 151, 219, 14, 89, 224, 192, 50, 61, 151, 56, 6, 232, 104, 183, 50, 61, 151, 237, 72, 227, 104, 104, 153, 61, 20, 237, 232, 72, 104, 108, + 114, 145, 115, 155, 100, 226, 108, 108, 128, 245, 219, 231, 231, 47, 89, 4, 61, 245, 142, 74, 231, 104, 104, 255, 61, 20, 245, 142, 231, 82, 177, 192, + 61, 20, 245, 146, 47, 14, 140, 222, 61, 20, 20, 146, 89, 125, 207, 250, 61, 20, 20, 146, 100, 104, 207, 207, 34, 20, 20, 125, 125, 160, 226, 108, + 128, 114, 219, 183, 164, 100, 226, 250, 252, 128, 184, 25, 103, 47, 89, 104, 94, 128, 190, 25, 14, 47, 125, 104, 94, 85, 190, 26, 14, 47, 104, 72, + 50, 85, 20, 147, 14, 18, 14, 192, 50, 61, 144, 33, 26, 45, 14, 125, 50, 61, 144, 26, 14, 100, 252, 192, 153, 61, 20, 26, 18, 72, 192, 192, + 114, 151, 219, 247, 199, 98, 158, 250, 85, 190, 151, 6, 231, 89, 168, 89, 94, 128, 190, 142, 103, 89, 89, 104, 94, 128, 190, 25, 14, 14, 125, 104, + 94, 20, 190, 25, 14, 232, 232, 47, 50, 61, 190, 159, 14, 72, 25, 101, 50, 61, 20, 159, 232, 89, 125, 108, 153, 61, 20, 26, 125, 103, 192, 104, + 128, 151, 219, 247, 247, 63, 63, 108, 85, 156, 151, 219, 231, 100, 47, 108, 94, 137, 151, 219, 14, 14, 89, 89, 94, 85, 151, 33, 14, 89, 89, 232, + 50, 85, 190, 33, 14, 14, 89, 104, 50, 85, 190, 130, 14, 14, 135, 192, 50, 85, 73, 33, 14, 14, 104, 104, 153, 61, 20, 26, 232, 89, 192, 192, + 145, 219, 247, 155, 172, 110, 58, 162, 20, 245, 142, 59, 82, 99, 103, 58, 20, 245, 142, 25, 103, 89, 231, 207, 20, 245, 142, 142, 231, 160, 214, 108, + 20, 20, 142, 146, 125, 14, 167, 192, 20, 20, 142, 13, 103, 160, 207, 162, 20, 20, 20, 82, 125, 160, 207, 4, 34, 20, 20, 125, 160, 160, 226, 108, + 114, 151, 219, 247, 247, 63, 58, 250, 85, 156, 151, 219, 231, 227, 58, 108, 94, 128, 151, 219, 231, 47, 58, 192, 50, 128, 245, 244, 89, 47, 14, 108, + 50, 128, 190, 56, 103, 14, 14, 155, 61, 69, 190, 6, 103, 104, 135, 84, 61, 61, 20, 26, 14, 231, 104, 154, 153, 61, 20, 237, 232, 14, 89, 104, + 114, 219, 219, 247, 119, 79, 12, 4, 128, 151, 219, 219, 231, 51, 58, 4, 61, 190, 151, 219, 231, 100, 160, 84, 61, 128, 245, 25, 103, 232, 18, 80, + 61, 20, 245, 25, 103, 219, 99, 104, 61, 61, 245, 130, 146, 232, 89, 108, 61, 61, 190, 25, 89, 192, 104, 250, 34, 20, 20, 237, 232, 125, 226, 104, + 128, 151, 219, 247, 119, 79, 22, 4, 85, 151, 219, 247, 247, 63, 63, 226, 94, 137, 151, 219, 231, 100, 89, 226, 94, 137, 151, 219, 231, 47, 89, 89, + 50, 85, 151, 219, 103, 47, 58, 58, 50, 85, 151, 56, 232, 89, 89, 226, 50, 85, 151, 145, 14, 232, 47, 104, 153, 61, 20, 237, 232, 89, 11, 104, + 114, 145, 219, 155, 65, 47, 226, 158, 128, 114, 219, 13, 89, 125, 108, 179, 128, 20, 245, 251, 103, 89, 89, 14, 61, 20, 245, 142, 231, 231, 99, 20, + 61, 20, 245, 251, 14, 18, 58, 192, 61, 20, 20, 245, 45, 58, 4, 1, 61, 20, 20, 80, 231, 160, 207, 108, 34, 20, 20, 125, 125, 125, 99, 104, + 128, 151, 219, 13, 100, 100, 103, 108, 85, 128, 151, 237, 147, 103, 127, 192, 94, 128, 190, 33, 14, 47, 89, 227, 94, 85, 190, 33, 135, 135, 14, 16, + 50, 85, 190, 144, 14, 232, 201, 103, 50, 85, 73, 26, 14, 45, 103, 115, 50, 61, 20, 20, 14, 45, 89, 11, 153, 61, 20, 26, 135, 135, 201, 192, + 156, 151, 219, 13, 247, 100, 98, 162, 85, 156, 151, 142, 231, 103, 159, 104, 94, 128, 190, 56, 14, 72, 47, 226, 94, 128, 190, 33, 14, 47, 125, 104, + 50, 128, 190, 26, 14, 14, 33, 72, 50, 61, 190, 26, 14, 18, 100, 249, 50, 61, 190, 26, 45, 103, 33, 72, 153, 61, 20, 26, 135, 125, 192, 192, + 156, 151, 219, 219, 100, 100, 226, 108, 85, 137, 151, 219, 14, 232, 89, 104, 85, 137, 151, 33, 14, 14, 89, 72, 60, 85, 190, 33, 14, 14, 45, 72, + 49, 85, 73, 33, 14, 14, 125, 192, 49, 85, 73, 33, 14, 14, 14, 192, 49, 85, 73, 33, 14, 14, 45, 192, 153, 55, 32, 154, 135, 135, 192, 192, + 27, 8, 142, 44, 103, 51, 63, 4, 186, 20, 216, 6, 3, 103, 58, 58, 34, 144, 216, 8, 123, 255, 58, 181, 61, 190, 142, 6, 23, 226, 72, 4, + 88, 20, 56, 159, 51, 115, 67, 4, 28, 8, 80, 44, 25, 33, 12, 131, 34, 20, 42, 216, 93, 41, 25, 63, 34, 80, 20, 125, 72, 255, 231, 250, + 193, 213, 219, 219, 247, 127, 59, 162, 252, 213, 216, 124, 146, 237, 242, 125, 50, 190, 190, 179, 14, 251, 238, 6, 50, 85, 245, 245, 42, 159, 144, 113, + 50, 228, 245, 6, 59, 11, 108, 168, 61, 161, 20, 42, 134, 138, 225, 181, 94, 20, 26, 184, 55, 213, 238, 244, 34, 61, 20, 80, 159, 82, 104, 108, + 27, 97, 216, 6, 103, 102, 226, 104, 105, 97, 190, 130, 159, 82, 0, 41, 50, 69, 190, 147, 146, 14, 231, 219, 50, 20, 245, 237, 237, 75, 126, 100, + 50, 15, 252, 21, 146, 61, 250, 192, 50, 36, 73, 190, 175, 11, 251, 0, 88, 61, 233, 5, 232, 127, 0, 71, 34, 61, 20, 26, 18, 45, 44, 41, + 128, 151, 219, 247, 247, 51, 58, 226, 85, 97, 151, 219, 247, 247, 231, 155, 94, 97, 9, 184, 146, 104, 6, 99, 50, 37, 190, 25, 89, 63, 108, 147, + 50, 190, 190, 184, 159, 250, 144, 170, 88, 69, 97, 189, 135, 104, 33, 135, 153, 194, 35, 80, 103, 40, 125, 25, 153, 61, 190, 237, 25, 103, 250, 104, + 27, 128, 142, 146, 146, 80, 145, 226, 252, 228, 190, 80, 103, 232, 15, 147, 94, 61, 8, 6, 7, 44, 162, 139, 50, 61, 144, 179, 25, 191, 96, 12, + 61, 105, 235, 18, 146, 135, 111, 99, 50, 61, 20, 61, 183, 155, 231, 180, 88, 61, 197, 45, 240, 250, 219, 64, 34, 61, 20, 26, 89, 103, 125, 197, + 128, 151, 151, 219, 168, 47, 58, 158, 85, 128, 245, 151, 134, 232, 184, 192, 94, 128, 8, 235, 107, 47, 145, 72, 50, 194, 20, 20, 173, 26, 155, 144, + 50, 61, 36, 14, 82, 125, 237, 99, 50, 105, 20, 27, 14, 137, 167, 235, 50, 61, 175, 186, 190, 28, 108, 127, 153, 61, 54, 26, 129, 89, 26, 108, + 252, 97, 216, 25, 7, 11, 159, 226, 94, 252, 190, 245, 235, 135, 251, 18, 50, 252, 190, 8, 33, 125, 144, 226, 88, 94, 144, 42, 202, 13, 45, 253, + 88, 94, 97, 27, 14, 93, 153, 192, 88, 61, 61, 9, 103, 228, 250, 244, 88, 61, 144, 20, 14, 232, 18, 138, 153, 61, 61, 154, 26, 215, 18, 192, + 128, 156, 219, 219, 247, 100, 63, 108, 252, 97, 151, 151, 239, 103, 103, 231, 94, 85, 190, 244, 159, 141, 233, 18, 50, 85, 156, 8, 45, 14, 72, 133, + 50, 94, 190, 33, 14, 135, 159, 80, 50, 94, 73, 37, 20, 14, 155, 157, 153, 94, 37, 245, 26, 192, 153, 68, 153, 61, 32, 26, 129, 232, 18, 192, + 27, 235, 56, 56, 59, 249, 45, 226, 61, 190, 33, 25, 159, 47, 104, 231, 186, 54, 20, 26, 151, 80, 249, 146, 61, 61, 235, 6, 192, 72, 82, 4, + 34, 128, 73, 18, 192, 93, 232, 0, 50, 2, 237, 20, 230, 250, 52, 161, 19, 20, 20, 109, 231, 190, 49, 102, 34, 215, 20, 26, 244, 54, 183, 125, + 128, 151, 219, 247, 247, 249, 158, 108, 85, 137, 151, 121, 219, 232, 59, 80, 94, 190, 190, 142, 239, 232, 6, 76, 94, 73, 189, 26, 237, 247, 156, 90, + 50, 61, 149, 144, 5, 178, 49, 68, 36, 242, 221, 176, 159, 251, 10, 6, 50, 73, 26, 144, 190, 82, 0, 229, 34, 61, 20, 20, 103, 125, 47, 116, + 194, 213, 151, 219, 231, 231, 51, 104, 94, 161, 213, 151, 7, 146, 7, 249, 50, 35, 190, 245, 25, 18, 251, 165, 50, 69, 190, 245, 237, 146, 72, 120, + 50, 36, 73, 147, 25, 190, 34, 72, 153, 50, 73, 215, 89, 25, 120, 71, 153, 87, 144, 14, 189, 55, 36, 167, 153, 61, 20, 20, 129, 147, 57, 115, + 128, 151, 219, 247, 119, 119, 12, 250, 85, 156, 219, 219, 247, 63, 63, 249, 94, 137, 151, 219, 13, 100, 47, 72, 50, 137, 151, 70, 14, 89, 103, 247, + 49, 85, 190, 25, 125, 247, 192, 138, 50, 69, 190, 130, 14, 255, 227, 100, 49, 85, 190, 233, 14, 18, 89, 247, 153, 61, 20, 26, 129, 72, 14, 192, + 27, 9, 130, 146, 145, 125, 125, 226, 186, 27, 8, 33, 56, 145, 14, 104, 94, 61, 245, 33, 80, 199, 91, 192, 50, 186, 144, 103, 232, 194, 247, 194, + 50, 61, 54, 235, 152, 132, 244, 228, 61, 61, 144, 190, 180, 21, 196, 188, 50, 61, 144, 125, 51, 74, 0, 114, 153, 61, 20, 26, 72, 232, 154, 214, + 156, 151, 219, 219, 159, 100, 7, 7, 85, 137, 151, 8, 56, 245, 159, 183, 94, 85, 190, 245, 142, 9, 22, 13, 50, 85, 190, 21, 244, 114, 201, 45, + 50, 94, 190, 33, 72, 165, 104, 24, 50, 61, 20, 19, 80, 92, 9, 90, 50, 94, 32, 235, 197, 113, 234, 192, 153, 61, 61, 26, 129, 135, 18, 47, + 252, 156, 151, 237, 29, 103, 103, 104, 94, 128, 190, 237, 14, 135, 72, 223, 94, 252, 190, 26, 14, 26, 26, 104, 50, 94, 69, 20, 33, 47, 135, 72, + 50, 94, 73, 54, 14, 135, 114, 249, 88, 50, 20, 2, 245, 197, 188, 58, 88, 61, 61, 186, 135, 153, 136, 185, 153, 61, 61, 197, 135, 135, 201, 192, + 156, 151, 219, 219, 232, 232, 220, 108, 85, 137, 151, 21, 232, 232, 89, 232, 60, 137, 151, 33, 14, 232, 232, 135, 60, 85, 73, 33, 14, 232, 18, 104, + 49, 85, 73, 27, 14, 14, 33, 192, 49, 94, 73, 73, 135, 135, 135, 249, 49, 60, 73, 154, 33, 45, 125, 15, 153, 55, 32, 154, 135, 135, 135, 192, + 0, 111, 247, 119, 79, 62, 167, 90, 0, 130, 247, 59, 51, 62, 181, 101, 0, 117, 142, 247, 113, 160, 224, 1, 0, 130, 6, 59, 63, 148, 99, 181, + 0, 205, 74, 146, 59, 118, 104, 84, 0, 121, 65, 119, 146, 140, 168, 1, 0, 190, 44, 30, 62, 222, 101, 121, 0, 74, 65, 132, 112, 22, 181, 101, + 0, 219, 247, 119, 79, 22, 238, 90, 0, 151, 219, 247, 119, 62, 22, 214, 0, 151, 219, 247, 222, 63, 99, 1, 0, 5, 219, 247, 132, 99, 108, 181, + 0, 33, 219, 119, 148, 62, 207, 108, 0, 151, 219, 132, 100, 140, 226, 181, 0, 18, 44, 132, 63, 160, 226, 104, 0, 151, 182, 123, 224, 12, 238, 101, + 244, 247, 247, 79, 224, 0, 0, 0, 128, 219, 247, 199, 0, 0, 0, 0, 128, 48, 147, 148, 0, 0, 0, 0, 170, 48, 142, 124, 0, 0, 0, 0, + 128, 77, 159, 53, 0, 0, 0, 0, 186, 184, 183, 0, 0, 0, 0, 0, 32, 142, 83, 207, 0, 0, 0, 0, 20, 20, 247, 56, 0, 0, 0, 0, + 151, 247, 247, 162, 0, 0, 0, 0, 156, 219, 247, 255, 84, 0, 0, 0, 156, 151, 219, 224, 46, 0, 0, 0, 128, 151, 219, 115, 105, 0, 0, 0, + 128, 151, 219, 51, 0, 0, 0, 0, 85, 151, 219, 192, 0, 0, 0, 0, 128, 151, 111, 0, 0, 0, 0, 0, 61, 145, 219, 13, 0, 0, 0, 0, + 0, 219, 247, 119, 79, 62, 22, 214, 0, 5, 219, 247, 51, 148, 63, 250, 0, 137, 219, 239, 51, 58, 160, 63, 0, 216, 219, 247, 100, 158, 162, 181, + 0, 244, 179, 3, 51, 58, 62, 22, 0, 137, 219, 6, 119, 99, 62, 250, 0, 151, 130, 204, 100, 158, 158, 42, 0, 213, 202, 140, 132, 99, 4, 250, + 0, 219, 247, 119, 79, 22, 238, 90, 0, 219, 247, 247, 119, 79, 22, 214, 0, 151, 219, 247, 119, 79, 207, 4, 0, 151, 219, 247, 119, 12, 207, 4, + 0, 151, 219, 247, 113, 12, 12, 214, 0, 151, 219, 247, 53, 12, 207, 4, 0, 151, 234, 123, 79, 79, 4, 214, 0, 151, 247, 30, 222, 12, 4, 214, + 151, 247, 247, 62, 130, 0, 0, 0, 128, 151, 219, 53, 146, 0, 0, 0, 85, 151, 219, 224, 162, 0, 0, 0, 85, 151, 219, 253, 0, 0, 0, 0, + 94, 245, 41, 132, 0, 0, 0, 0, 94, 114, 142, 126, 0, 0, 0, 0, 61, 114, 219, 84, 0, 0, 0, 0, 61, 114, 219, 51, 0, 0, 0, 0, + 151, 247, 247, 22, 101, 0, 0, 0, 156, 219, 247, 158, 119, 0, 0, 0, 156, 219, 219, 224, 0, 0, 0, 0, 156, 151, 219, 255, 208, 0, 0, 0, + 85, 151, 219, 255, 160, 0, 0, 0, 85, 151, 219, 191, 0, 0, 0, 0, 85, 151, 219, 12, 0, 0, 0, 0, 85, 151, 247, 89, 0, 0, 0, 0, + 0, 219, 247, 119, 53, 22, 12, 181, 0, 219, 219, 247, 51, 118, 250, 4, 0, 5, 202, 155, 58, 231, 12, 99, 0, 77, 179, 6, 249, 115, 148, 18, + 0, 184, 42, 131, 127, 108, 4, 108, 0, 77, 145, 179, 63, 63, 4, 112, 0, 187, 74, 6, 89, 199, 99, 207, 0, 190, 145, 183, 249, 162, 113, 250, + 0, 219, 247, 119, 79, 22, 238, 90, 0, 151, 219, 247, 119, 98, 12, 250, 0, 151, 219, 247, 119, 224, 162, 1, 0, 151, 219, 247, 119, 226, 108, 108, + 0, 151, 219, 39, 119, 255, 62, 181, 0, 128, 134, 155, 155, 58, 181, 58, 0, 9, 111, 247, 113, 181, 108, 250, 0, 151, 219, 31, 95, 162, 108, 84, + 151, 219, 247, 32, 0, 0, 0, 0, 128, 151, 219, 45, 158, 0, 0, 0, 128, 114, 109, 79, 0, 0, 0, 0, 54, 114, 247, 0, 0, 0, 0, 0, + 194, 245, 8, 146, 0, 0, 0, 0, 194, 20, 219, 139, 0, 0, 0, 0, 194, 56, 72, 0, 0, 0, 0, 0, 61, 20, 151, 114, 0, 0, 0, 0, + 151, 219, 247, 255, 161, 0, 0, 0, 156, 151, 219, 30, 0, 0, 0, 0, 128, 156, 219, 196, 211, 0, 0, 0, 85, 156, 219, 226, 0, 0, 0, 0, + 85, 156, 219, 121, 0, 0, 0, 0, 85, 190, 151, 116, 0, 0, 0, 0, 85, 128, 190, 66, 0, 0, 0, 0, 94, 128, 151, 89, 142, 0, 0, 0, + 0, 219, 247, 247, 79, 118, 22, 4, 0, 151, 219, 247, 119, 63, 63, 250, 0, 151, 219, 219, 199, 249, 160, 226, 0, 151, 184, 239, 223, 222, 224, 207, + 0, 190, 130, 7, 231, 58, 63, 1, 0, 20, 219, 115, 100, 118, 162, 214, 0, 73, 244, 74, 59, 58, 192, 90, 0, 117, 145, 146, 140, 58, 162, 1, + 0, 219, 247, 119, 79, 22, 238, 90, 0, 151, 219, 247, 119, 79, 12, 250, 0, 151, 219, 247, 119, 12, 162, 181, 0, 151, 219, 247, 51, 79, 162, 84, + 0, 151, 219, 247, 113, 148, 12, 84, 0, 151, 219, 247, 222, 12, 4, 250, 0, 151, 219, 183, 119, 62, 99, 1, 0, 151, 219, 31, 222, 12, 250, 84, + 151, 219, 247, 255, 0, 0, 0, 0, 156, 151, 219, 191, 0, 0, 0, 0, 128, 156, 151, 53, 0, 0, 0, 0, 85, 190, 219, 160, 0, 0, 0, 0, + 85, 128, 5, 49, 0, 0, 0, 0, 85, 137, 245, 169, 0, 0, 0, 0, 94, 128, 190, 0, 0, 0, 0, 0, 61, 128, 219, 133, 0, 0, 0, 0, + 151, 219, 247, 58, 255, 0, 0, 0, 156, 151, 219, 220, 30, 0, 0, 0, 156, 151, 219, 219, 0, 0, 0, 0, 156, 151, 219, 155, 48, 0, 0, 0, + 85, 156, 219, 89, 90, 0, 0, 0, 85, 156, 219, 108, 0, 0, 0, 0, 85, 156, 151, 222, 0, 0, 0, 0, 60, 156, 219, 192, 0, 0, 0, 0, + 0, 200, 179, 82, 51, 63, 99, 250, 0, 117, 142, 239, 103, 223, 103, 250, 0, 97, 111, 13, 227, 47, 142, 4, 0, 116, 72, 59, 129, 199, 223, 181, + 0, 56, 212, 213, 44, 207, 126, 0, 0, 10, 184, 126, 107, 30, 51, 214, 0, 152, 20, 66, 232, 110, 230, 181, 0, 117, 146, 146, 227, 53, 99, 4, + 0, 219, 247, 119, 119, 62, 12, 214, 0, 151, 219, 247, 140, 119, 99, 108, 0, 187, 151, 247, 51, 63, 181, 199, 0, 212, 109, 219, 59, 158, 214, 207, + 0, 8, 52, 40, 118, 140, 238, 238, 0, 208, 219, 132, 100, 167, 133, 224, 0, 41, 211, 142, 25, 127, 100, 7, 0, 145, 96, 159, 110, 99, 51, 101, + 128, 244, 13, 59, 0, 0, 0, 0, 252, 75, 219, 232, 164, 0, 0, 0, 252, 245, 9, 57, 0, 0, 0, 0, 194, 128, 44, 220, 0, 0, 0, 0, + 87, 212, 125, 0, 0, 0, 0, 0, 85, 36, 20, 0, 0, 0, 0, 0, 50, 20, 228, 0, 0, 0, 0, 0, 186, 128, 80, 51, 0, 0, 0, 0, + 156, 219, 247, 220, 118, 0, 0, 0, 97, 151, 219, 168, 0, 0, 0, 0, 35, 190, 151, 100, 0, 0, 0, 0, 242, 170, 176, 202, 0, 0, 0, 0, + 94, 170, 151, 45, 0, 0, 0, 0, 85, 144, 52, 0, 0, 0, 0, 0, 85, 170, 145, 0, 113, 0, 0, 0, 34, 20, 244, 72, 0, 0, 0, 0, + 0, 213, 219, 82, 172, 249, 63, 250, 0, 97, 121, 202, 82, 51, 249, 58, 0, 97, 9, 145, 146, 159, 93, 192, 0, 97, 184, 6, 89, 20, 65, 0, + 0, 144, 130, 72, 82, 13, 45, 103, 0, 213, 26, 216, 231, 250, 58, 250, 0, 150, 20, 147, 89, 152, 13, 181, 0, 48, 9, 146, 103, 58, 104, 104, + 0, 219, 247, 119, 79, 62, 167, 214, 0, 151, 219, 247, 119, 79, 12, 250, 0, 43, 219, 247, 119, 53, 63, 1, 0, 151, 219, 183, 223, 63, 162, 238, + 0, 120, 219, 39, 172, 108, 158, 181, 0, 144, 229, 31, 123, 98, 249, 4, 0, 114, 109, 82, 58, 58, 160, 224, 0, 240, 219, 59, 51, 98, 99, 101, + 252, 216, 219, 219, 2, 0, 0, 0, 252, 190, 151, 156, 0, 0, 0, 0, 94, 128, 121, 13, 167, 0, 0, 0, 94, 54, 176, 86, 0, 0, 0, 0, + 88, 27, 8, 0, 0, 0, 0, 0, 87, 128, 134, 92, 0, 0, 0, 0, 153, 161, 117, 0, 0, 0, 0, 0, 50, 194, 245, 40, 0, 0, 0, 0, + 156, 219, 247, 62, 1, 89, 0, 0, 97, 219, 219, 249, 0, 0, 0, 0, 85, 151, 219, 230, 0, 0, 0, 0, 252, 189, 219, 70, 0, 0, 0, 0, + 252, 156, 77, 89, 0, 0, 0, 0, 94, 149, 120, 12, 0, 0, 0, 0, 55, 156, 124, 189, 0, 0, 0, 0, 94, 240, 219, 199, 0, 0, 0, 0, + 0, 70, 111, 82, 51, 51, 58, 250, 0, 9, 25, 239, 7, 82, 99, 14, 0, 9, 38, 7, 244, 28, 98, 58, 0, 235, 245, 121, 123, 181, 65, 1, + 0, 28, 245, 176, 146, 205, 186, 1, 0, 85, 237, 120, 192, 176, 175, 7, 0, 205, 20, 2, 100, 51, 42, 75, 0, 156, 145, 18, 98, 59, 59, 192, + 0, 219, 247, 119, 79, 12, 4, 214, 0, 151, 219, 247, 199, 222, 99, 162, 0, 151, 219, 168, 119, 47, 214, 167, 0, 156, 120, 247, 100, 119, 62, 101, + 0, 187, 200, 100, 63, 7, 143, 115, 0, 149, 151, 247, 58, 227, 46, 148, 0, 64, 5, 219, 137, 160, 214, 0, 0, 187, 219, 247, 158, 98, 4, 250, + 128, 213, 219, 104, 0, 0, 0, 0, 194, 9, 109, 195, 63, 0, 0, 0, 85, 190, 244, 0, 0, 0, 0, 0, 94, 97, 184, 40, 0, 0, 0, 0, + 94, 27, 94, 0, 0, 0, 0, 0, 19, 85, 151, 0, 0, 0, 0, 0, 50, 61, 237, 0, 0, 0, 0, 0, 105, 28, 145, 144, 0, 0, 0, 0, + 151, 219, 219, 119, 190, 0, 0, 0, 156, 151, 219, 160, 0, 0, 0, 0, 85, 137, 219, 51, 0, 0, 0, 0, 85, 156, 190, 0, 0, 0, 0, 0, + 85, 156, 97, 0, 0, 0, 0, 0, 94, 156, 159, 0, 0, 0, 0, 0, 94, 20, 96, 243, 0, 0, 0, 0, 60, 20, 219, 154, 0, 0, 0, 0, + 0, 151, 219, 239, 172, 249, 108, 250, 0, 189, 184, 202, 146, 123, 158, 108, 0, 97, 213, 74, 6, 115, 232, 108, 0, 97, 213, 25, 202, 47, 224, 118, + 0, 73, 235, 25, 146, 148, 58, 104, 0, 128, 20, 147, 51, 126, 46, 162, 0, 128, 243, 74, 176, 58, 250, 46, 0, 128, 245, 146, 59, 223, 250, 101, + 0, 219, 247, 247, 119, 62, 4, 214, 0, 151, 219, 247, 247, 222, 12, 1, 0, 151, 219, 247, 100, 98, 58, 4, 0, 151, 151, 247, 199, 224, 162, 181, + 0, 156, 219, 247, 155, 123, 181, 84, 0, 156, 219, 247, 199, 98, 158, 255, 0, 137, 151, 109, 172, 51, 43, 223, 0, 156, 219, 168, 222, 12, 250, 84, + 97, 213, 151, 108, 160, 0, 0, 0, 85, 97, 151, 189, 0, 0, 0, 0, 252, 97, 190, 43, 0, 0, 0, 0, 94, 97, 245, 76, 0, 0, 0, 0, + 94, 186, 201, 0, 0, 0, 0, 0, 94, 85, 170, 216, 0, 0, 0, 0, 50, 61, 184, 171, 0, 0, 0, 0, 50, 128, 147, 104, 0, 0, 0, 0, + 151, 219, 219, 100, 18, 0, 0, 0, 156, 151, 219, 247, 0, 0, 0, 0, 85, 156, 151, 114, 0, 0, 0, 0, 85, 156, 151, 64, 0, 0, 0, 0, + 85, 156, 151, 197, 0, 0, 0, 0, 85, 156, 151, 90, 0, 0, 0, 0, 60, 156, 151, 100, 0, 0, 0, 0, 60, 156, 151, 108, 22, 0, 0, 0, + 80, 145, 115, 100, 79, 222, 99, 101, 186, 8, 142, 159, 172, 58, 1, 108, 61, 20, 21, 59, 158, 47, 104, 108, 54, 144, 251, 59, 227, 103, 226, 214, + 34, 212, 20, 103, 113, 63, 250, 181, 20, 9, 142, 223, 72, 162, 84, 199, 20, 20, 184, 125, 112, 98, 111, 214, 34, 20, 142, 146, 125, 47, 158, 250, + 114, 114, 219, 44, 51, 99, 63, 4, 94, 128, 245, 70, 51, 47, 110, 201, 50, 61, 190, 74, 124, 199, 125, 8, 50, 27, 245, 235, 232, 121, 162, 226, + 50, 34, 20, 232, 124, 130, 19, 181, 61, 15, 130, 26, 231, 22, 120, 0, 61, 61, 144, 18, 54, 144, 166, 214, 34, 20, 20, 251, 89, 100, 232, 226, + 114, 145, 219, 247, 16, 98, 158, 84, 94, 190, 38, 145, 231, 103, 160, 104, 61, 20, 190, 25, 14, 103, 226, 104, 61, 161, 8, 74, 231, 51, 249, 160, + 61, 212, 184, 145, 7, 226, 123, 125, 50, 61, 235, 44, 168, 110, 215, 4, 34, 20, 20, 237, 24, 102, 125, 103, 34, 20, 20, 125, 103, 100, 104, 84, + 128, 151, 219, 247, 119, 158, 99, 63, 94, 161, 38, 234, 7, 103, 31, 72, 94, 128, 190, 25, 179, 126, 192, 89, 50, 242, 190, 25, 211, 192, 181, 72, + 50, 85, 190, 75, 72, 25, 118, 63, 50, 61, 73, 3, 18, 18, 166, 16, 50, 194, 245, 6, 89, 197, 203, 108, 153, 61, 20, 26, 72, 125, 66, 104, + 128, 145, 145, 247, 123, 148, 108, 207, 94, 144, 245, 42, 159, 103, 226, 158, 61, 20, 147, 159, 59, 146, 192, 72, 61, 61, 26, 216, 14, 109, 247, 249, + 61, 69, 120, 18, 219, 2, 7, 250, 61, 61, 190, 245, 175, 238, 207, 250, 61, 215, 25, 56, 125, 89, 238, 207, 34, 20, 20, 125, 7, 125, 100, 84, + 128, 114, 145, 247, 100, 249, 95, 84, 94, 128, 190, 25, 103, 25, 104, 250, 50, 252, 190, 33, 26, 103, 47, 47, 50, 61, 245, 237, 103, 125, 182, 192, + 88, 61, 245, 147, 172, 89, 198, 58, 50, 61, 190, 20, 103, 18, 7, 27, 153, 61, 20, 237, 144, 172, 135, 101, 153, 61, 20, 237, 18, 103, 103, 104, + 128, 151, 219, 247, 247, 63, 226, 4, 94, 128, 151, 142, 59, 232, 58, 108, 94, 144, 190, 6, 103, 249, 26, 155, 50, 94, 245, 134, 14, 82, 167, 250, + 50, 54, 20, 251, 42, 129, 63, 199, 50, 61, 190, 147, 125, 6, 125, 250, 50, 61, 117, 235, 115, 121, 192, 84, 153, 61, 20, 125, 100, 251, 108, 72, + 128, 151, 219, 247, 247, 119, 12, 4, 94, 156, 151, 219, 13, 103, 125, 108, 50, 69, 151, 25, 72, 232, 103, 12, 50, 85, 190, 21, 14, 89, 26, 160, + 50, 85, 190, 33, 14, 14, 14, 104, 50, 94, 73, 33, 14, 47, 18, 104, 153, 61, 190, 26, 14, 47, 129, 181, 153, 61, 20, 237, 14, 89, 89, 84, + 114, 145, 13, 126, 58, 99, 158, 162, 186, 190, 145, 42, 47, 18, 249, 108, 94, 144, 142, 237, 231, 226, 249, 203, 50, 20, 147, 237, 103, 226, 176, 207, + 61, 20, 20, 18, 18, 146, 186, 90, 61, 20, 20, 7, 76, 126, 232, 1, 34, 20, 216, 125, 83, 18, 179, 108, 34, 20, 20, 125, 80, 20, 181, 192, + 128, 244, 219, 65, 249, 251, 51, 47, 94, 128, 190, 33, 44, 192, 47, 72, 94, 252, 190, 184, 237, 16, 200, 80, 50, 61, 27, 26, 166, 192, 226, 119, + 50, 61, 128, 18, 100, 192, 153, 90, 50, 186, 20, 215, 125, 195, 0, 244, 50, 61, 20, 143, 24, 191, 79, 104, 153, 61, 20, 20, 129, 125, 232, 67, + 114, 145, 145, 155, 249, 98, 108, 84, 94, 128, 245, 237, 103, 103, 103, 59, 94, 128, 190, 159, 14, 227, 255, 192, 50, 61, 190, 26, 14, 89, 99, 162, + 50, 61, 20, 8, 72, 47, 45, 4, 50, 61, 20, 201, 14, 125, 89, 84, 50, 61, 190, 18, 237, 113, 1, 250, 153, 61, 20, 18, 18, 103, 47, 84, + 128, 151, 219, 247, 100, 58, 108, 226, 94, 128, 190, 237, 72, 7, 227, 104, 94, 85, 190, 33, 14, 72, 135, 89, 50, 94, 128, 33, 26, 18, 125, 103, + 50, 94, 144, 26, 45, 72, 192, 104, 50, 94, 73, 147, 159, 72, 26, 84, 153, 61, 20, 28, 26, 14, 192, 235, 153, 61, 20, 26, 18, 89, 103, 104, + 128, 151, 219, 247, 247, 226, 226, 84, 186, 243, 8, 25, 232, 7, 63, 72, 94, 27, 190, 45, 7, 251, 249, 231, 50, 73, 20, 3, 14, 242, 110, 193, + 50, 105, 190, 34, 14, 72, 250, 18, 50, 61, 8, 142, 249, 108, 104, 47, 50, 50, 154, 251, 95, 29, 0, 250, 34, 61, 20, 26, 125, 20, 224, 108, + 128, 156, 151, 44, 136, 103, 160, 108, 94, 128, 190, 245, 29, 47, 250, 108, 94, 85, 190, 33, 14, 231, 151, 205, 50, 94, 190, 26, 18, 89, 135, 89, + 50, 94, 190, 144, 26, 125, 191, 231, 50, 61, 144, 26, 18, 89, 14, 248, 153, 50, 190, 190, 72, 104, 9, 238, 153, 61, 20, 26, 18, 45, 192, 226, + 128, 151, 219, 247, 247, 226, 108, 4, 94, 128, 245, 48, 103, 47, 135, 47, 94, 85, 190, 147, 103, 103, 192, 192, 50, 85, 190, 26, 26, 14, 223, 108, + 50, 61, 20, 33, 14, 192, 7, 192, 50, 94, 20, 20, 14, 51, 23, 108, 50, 61, 73, 20, 47, 14, 181, 45, 153, 61, 20, 26, 18, 14, 125, 192, + 156, 151, 219, 247, 100, 100, 58, 250, 85, 137, 151, 21, 232, 232, 89, 104, 60, 137, 190, 21, 14, 232, 135, 104, 49, 85, 190, 33, 14, 14, 232, 135, + 49, 85, 73, 33, 14, 18, 89, 192, 49, 94, 73, 33, 18, 14, 192, 192, 49, 60, 73, 33, 14, 18, 232, 104, 153, 55, 32, 154, 135, 135, 135, 192, + 186, 144, 216, 159, 59, 58, 103, 250, 94, 54, 9, 146, 103, 255, 99, 99, 19, 85, 144, 146, 202, 13, 181, 47, 50, 161, 42, 115, 59, 63, 70, 83, + 88, 69, 25, 112, 231, 94, 219, 123, 2, 144, 3, 129, 58, 100, 177, 255, 61, 54, 25, 202, 160, 157, 0, 1, 34, 20, 20, 59, 160, 72, 47, 108, + 186, 8, 216, 239, 239, 7, 119, 155, 50, 27, 216, 245, 25, 82, 85, 109, 88, 61, 190, 147, 155, 242, 22, 192, 50, 150, 20, 5, 216, 144, 4, 143, + 88, 94, 144, 237, 103, 36, 209, 17, 163, 88, 36, 29, 232, 231, 148, 10, 163, 55, 28, 164, 15, 72, 74, 25, 34, 228, 235, 237, 129, 245, 101, 97, + 252, 97, 213, 237, 7, 103, 58, 104, 88, 252, 190, 56, 26, 146, 104, 108, 88, 94, 54, 33, 26, 14, 192, 104, 88, 94, 54, 54, 33, 45, 115, 202, + 88, 186, 27, 54, 14, 46, 18, 231, 88, 50, 20, 57, 18, 29, 100, 58, 10, 61, 20, 137, 120, 216, 104, 154, 163, 61, 54, 26, 26, 25, 104, 192, + 186, 97, 213, 121, 7, 102, 47, 250, 94, 85, 156, 25, 14, 72, 108, 104, 50, 105, 190, 235, 26, 245, 6, 101, 88, 19, 144, 130, 237, 192, 135, 67, + 50, 105, 61, 117, 117, 81, 195, 39, 88, 61, 144, 26, 241, 40, 166, 0, 88, 55, 34, 228, 146, 31, 75, 26, 153, 50, 54, 193, 103, 201, 146, 226, + 228, 235, 216, 6, 82, 103, 135, 104, 19, 186, 144, 25, 111, 235, 147, 103, 50, 50, 190, 251, 20, 47, 132, 232, 88, 242, 194, 235, 103, 154, 250, 0, + 50, 69, 67, 103, 162, 126, 191, 45, 50, 2, 147, 25, 44, 237, 159, 0, 153, 105, 184, 191, 144, 237, 227, 67, 163, 61, 190, 26, 47, 71, 104, 0, + 128, 216, 134, 239, 82, 47, 249, 47, 94, 35, 190, 144, 144, 237, 41, 232, 94, 94, 20, 144, 237, 103, 31, 240, 88, 105, 144, 235, 159, 22, 51, 224, + 50, 61, 235, 237, 103, 103, 159, 67, 49, 2, 20, 144, 237, 237, 141, 178, 153, 19, 144, 144, 103, 103, 159, 7, 153, 61, 144, 144, 103, 103, 51, 18, + 186, 97, 216, 124, 72, 7, 7, 226, 50, 252, 9, 38, 202, 72, 192, 58, 88, 94, 161, 56, 26, 115, 80, 146, 88, 36, 73, 54, 45, 197, 250, 255, + 88, 61, 190, 20, 251, 103, 147, 181, 153, 87, 73, 114, 180, 182, 45, 110, 153, 61, 54, 251, 251, 120, 126, 138, 153, 61, 27, 26, 147, 68, 135, 26, + 85, 156, 219, 219, 247, 51, 108, 108, 94, 165, 151, 219, 159, 102, 89, 226, 49, 85, 156, 245, 14, 146, 45, 14, 50, 105, 190, 21, 232, 72, 89, 212, + 153, 61, 243, 33, 237, 245, 82, 59, 88, 61, 69, 156, 18, 83, 102, 64, 153, 50, 190, 8, 18, 251, 242, 0, 153, 61, 20, 26, 18, 72, 142, 197, + 186, 144, 245, 56, 89, 125, 56, 127, 19, 186, 8, 8, 89, 132, 232, 158, 50, 186, 212, 147, 231, 237, 247, 104, 50, 61, 190, 45, 14, 79, 15, 20, + 50, 88, 194, 129, 34, 27, 202, 62, 88, 61, 190, 50, 128, 151, 73, 162, 88, 105, 215, 26, 26, 87, 143, 92, 163, 61, 215, 20, 197, 124, 14, 192, + 252, 128, 184, 121, 146, 232, 185, 63, 94, 94, 161, 233, 17, 227, 246, 34, 88, 94, 221, 28, 232, 22, 37, 215, 88, 69, 20, 75, 109, 192, 211, 193, + 50, 61, 190, 28, 134, 233, 151, 224, 50, 94, 61, 232, 119, 138, 0, 0, 88, 50, 194, 194, 252, 92, 10, 0, 153, 61, 20, 144, 25, 252, 197, 86, + 252, 252, 190, 56, 29, 103, 159, 104, 88, 252, 54, 54, 26, 129, 201, 192, 88, 94, 54, 26, 14, 196, 103, 192, 88, 50, 54, 54, 18, 45, 26, 192, + 88, 50, 54, 54, 26, 135, 197, 104, 88, 50, 61, 197, 54, 14, 166, 192, 10, 50, 61, 197, 192, 18, 88, 10, 10, 88, 61, 197, 135, 135, 192, 192, + 252, 128, 213, 237, 103, 7, 72, 192, 94, 85, 190, 235, 14, 89, 147, 8, 88, 94, 69, 54, 33, 72, 103, 108, 88, 94, 85, 54, 135, 135, 114, 85, + 88, 50, 69, 144, 135, 175, 147, 163, 88, 50, 61, 61, 26, 42, 155, 192, 153, 88, 94, 36, 56, 243, 158, 156, 10, 153, 61, 61, 210, 251, 135, 192, + 186, 240, 245, 235, 25, 154, 133, 78, 19, 186, 144, 20, 33, 103, 44, 192, 50, 252, 20, 80, 125, 134, 209, 30, 50, 50, 73, 26, 25, 125, 222, 125, + 50, 87, 194, 235, 50, 132, 151, 108, 153, 105, 212, 50, 201, 81, 0, 249, 153, 34, 69, 103, 61, 106, 0, 0, 153, 61, 186, 26, 20, 20, 7, 17, + 128, 156, 151, 202, 82, 104, 155, 145, 94, 85, 190, 216, 159, 144, 253, 108, 94, 94, 190, 147, 56, 146, 100, 103, 50, 94, 144, 212, 18, 177, 174, 200, + 50, 105, 144, 20, 100, 235, 122, 174, 88, 50, 144, 87, 216, 89, 159, 251, 153, 50, 144, 194, 20, 8, 181, 243, 153, 61, 61, 144, 144, 237, 18, 104, + 252, 97, 9, 237, 14, 72, 146, 104, 94, 252, 190, 54, 26, 45, 47, 104, 88, 94, 54, 26, 135, 26, 82, 192, 88, 94, 61, 154, 14, 72, 103, 103, + 88, 50, 61, 2, 26, 147, 88, 45, 88, 50, 61, 20, 14, 2, 254, 70, 153, 50, 50, 87, 125, 237, 137, 19, 10, 88, 61, 197, 26, 135, 26, 192, + 85, 156, 151, 219, 72, 72, 232, 108, 94, 242, 170, 21, 14, 18, 25, 103, 94, 85, 190, 33, 14, 45, 192, 104, 49, 94, 73, 33, 14, 232, 21, 47, + 49, 94, 69, 212, 14, 89, 14, 34, 49, 50, 194, 105, 135, 97, 45, 80, 153, 55, 61, 36, 33, 173, 21, 92, 153, 50, 61, 154, 135, 135, 135, 192, + 0, 44, 247, 119, 79, 22, 238, 250, 0, 216, 179, 59, 51, 12, 99, 250, 0, 184, 179, 59, 51, 148, 99, 250, 0, 97, 179, 100, 118, 181, 4, 162, + 0, 78, 191, 132, 62, 132, 238, 250, 0, 187, 179, 249, 53, 108, 214, 249, 0, 143, 7, 155, 224, 59, 207, 79, 0, 225, 65, 113, 99, 167, 214, 101, + 0, 219, 247, 119, 79, 22, 167, 214, 0, 151, 219, 247, 119, 148, 22, 214, 0, 77, 219, 247, 79, 12, 4, 4, 0, 151, 247, 126, 113, 148, 4, 118, + 0, 253, 168, 30, 79, 178, 101, 12, 0, 151, 191, 131, 222, 250, 70, 1, 0, 5, 131, 119, 62, 255, 111, 1, 0, 38, 247, 119, 224, 167, 181, 84, + 151, 247, 247, 98, 101, 0, 0, 0, 97, 216, 41, 118, 0, 0, 0, 0, 97, 38, 142, 98, 64, 0, 0, 0, 177, 244, 179, 224, 0, 0, 0, 0, + 128, 244, 179, 104, 0, 0, 0, 0, 61, 244, 65, 0, 0, 0, 0, 0, 34, 219, 223, 0, 0, 0, 0, 0, 20, 7, 82, 250, 0, 0, 0, 0, + 151, 247, 247, 22, 0, 0, 0, 0, 156, 219, 219, 160, 0, 0, 0, 0, 97, 151, 219, 12, 0, 0, 0, 0, 85, 219, 202, 12, 0, 0, 0, 0, + 27, 109, 115, 148, 0, 0, 0, 0, 15, 151, 82, 227, 4, 0, 0, 0, 128, 244, 191, 0, 0, 0, 0, 0, 20, 145, 247, 158, 160, 0, 0, 0, + 0, 219, 247, 119, 79, 62, 22, 101, 0, 120, 219, 247, 119, 51, 62, 250, 0, 151, 219, 247, 119, 98, 12, 226, 0, 244, 44, 68, 51, 108, 101, 162, + 0, 48, 247, 59, 231, 255, 231, 207, 0, 235, 179, 129, 119, 118, 207, 101, 0, 75, 247, 30, 222, 99, 238, 207, 0, 5, 182, 119, 79, 99, 207, 4, + 0, 219, 247, 119, 79, 22, 238, 90, 0, 151, 247, 119, 79, 62, 167, 214, 0, 151, 247, 119, 79, 62, 238, 101, 0, 151, 247, 119, 178, 22, 207, 1, + 0, 187, 247, 119, 79, 22, 4, 214, 0, 139, 191, 119, 79, 167, 4, 90, 0, 219, 191, 119, 79, 62, 238, 214, 0, 120, 247, 119, 118, 167, 4, 214, + 151, 247, 247, 4, 191, 0, 0, 0, 170, 219, 219, 226, 0, 0, 0, 0, 128, 121, 219, 189, 0, 0, 0, 0, 252, 6, 13, 84, 0, 0, 0, 0, + 97, 245, 225, 62, 28, 0, 0, 0, 128, 151, 168, 250, 0, 0, 0, 0, 252, 56, 225, 62, 0, 0, 0, 0, 15, 145, 202, 214, 0, 0, 0, 0, + 151, 247, 247, 238, 226, 0, 0, 0, 156, 219, 247, 162, 249, 0, 0, 0, 156, 219, 247, 226, 0, 0, 0, 0, 156, 219, 247, 22, 0, 0, 0, 0, + 128, 219, 247, 53, 0, 0, 0, 0, 85, 219, 247, 118, 0, 0, 0, 0, 85, 219, 247, 226, 0, 0, 0, 0, 128, 219, 191, 162, 0, 0, 0, 0, + 0, 219, 247, 247, 110, 79, 108, 101, 0, 213, 216, 239, 51, 63, 162, 108, 0, 97, 216, 239, 51, 63, 22, 192, 0, 243, 77, 25, 249, 58, 42, 101, + 0, 97, 6, 179, 63, 181, 158, 250, 0, 177, 184, 124, 158, 162, 101, 167, 0, 33, 109, 82, 100, 238, 214, 45, 0, 244, 142, 59, 51, 226, 101, 4, + 0, 219, 247, 119, 79, 22, 4, 1, 0, 213, 219, 247, 119, 58, 4, 250, 0, 213, 219, 247, 63, 255, 108, 12, 0, 128, 78, 182, 164, 224, 100, 104, + 0, 156, 219, 172, 16, 162, 108, 98, 0, 245, 219, 247, 119, 99, 4, 90, 0, 151, 121, 222, 16, 222, 98, 62, 0, 245, 219, 59, 53, 58, 181, 1, + 244, 219, 247, 47, 0, 0, 0, 0, 252, 97, 219, 120, 0, 0, 0, 0, 252, 128, 121, 230, 0, 0, 0, 0, 252, 97, 8, 193, 0, 0, 0, 0, + 252, 128, 124, 203, 0, 0, 0, 0, 252, 128, 3, 9, 0, 0, 0, 0, 94, 33, 103, 110, 0, 0, 0, 0, 61, 20, 41, 110, 0, 0, 0, 0, + 151, 219, 247, 226, 0, 0, 0, 0, 97, 213, 219, 33, 0, 0, 0, 0, 85, 156, 151, 61, 0, 0, 0, 0, 85, 156, 145, 55, 0, 0, 0, 0, + 252, 128, 219, 189, 0, 0, 0, 0, 94, 156, 142, 108, 0, 0, 0, 0, 252, 190, 219, 0, 0, 0, 0, 0, 61, 190, 52, 153, 125, 0, 0, 0, + 0, 219, 247, 247, 119, 22, 207, 1, 0, 151, 219, 219, 199, 119, 148, 250, 0, 213, 151, 229, 231, 239, 103, 51, 0, 151, 109, 202, 225, 23, 160, 111, + 0, 149, 142, 239, 59, 4, 33, 108, 0, 190, 142, 219, 23, 99, 34, 0, 0, 213, 219, 59, 13, 58, 70, 127, 0, 151, 145, 82, 158, 79, 53, 214, + 0, 219, 247, 119, 79, 62, 238, 90, 0, 219, 219, 247, 119, 79, 207, 4, 0, 151, 219, 247, 119, 58, 162, 250, 0, 151, 219, 247, 113, 160, 250, 250, + 0, 151, 219, 247, 110, 12, 1, 214, 0, 151, 219, 126, 58, 62, 214, 22, 0, 151, 219, 191, 255, 167, 63, 84, 0, 151, 219, 126, 222, 89, 90, 84, + 151, 219, 247, 68, 0, 0, 0, 0, 97, 213, 219, 102, 0, 0, 0, 0, 85, 213, 219, 109, 0, 0, 0, 0, 85, 128, 142, 226, 0, 0, 0, 0, + 252, 128, 159, 42, 0, 0, 0, 0, 252, 128, 134, 240, 0, 0, 0, 0, 61, 128, 142, 0, 0, 0, 0, 0, 61, 190, 120, 10, 0, 0, 0, 0, + 151, 219, 247, 224, 45, 0, 0, 0, 156, 151, 219, 227, 131, 0, 0, 0, 156, 151, 219, 111, 0, 0, 0, 0, 85, 156, 219, 218, 0, 0, 0, 0, + 85, 156, 219, 168, 0, 0, 0, 0, 85, 156, 219, 15, 0, 0, 0, 0, 85, 156, 219, 117, 0, 0, 0, 0, 85, 156, 219, 217, 0, 0, 0, 0, + 0, 213, 179, 59, 51, 63, 99, 250, 0, 213, 179, 59, 51, 51, 108, 1, 0, 97, 78, 202, 123, 63, 58, 84, 0, 5, 179, 202, 59, 58, 110, 250, + 0, 37, 134, 74, 112, 101, 101, 1, 0, 147, 145, 6, 103, 118, 82, 250, 0, 186, 179, 255, 4, 98, 158, 103, 0, 166, 74, 204, 51, 63, 4, 101, + 0, 121, 191, 191, 119, 62, 167, 214, 0, 176, 219, 191, 132, 79, 207, 108, 0, 221, 239, 239, 123, 224, 99, 162, 0, 221, 78, 239, 123, 167, 133, 255, + 0, 54, 13, 168, 119, 158, 225, 159, 0, 121, 142, 239, 227, 100, 213, 58, 0, 36, 48, 191, 178, 53, 172, 118, 0, 77, 109, 40, 224, 222, 249, 250, + 97, 216, 216, 227, 192, 0, 0, 0, 252, 97, 216, 212, 197, 0, 0, 0, 94, 150, 216, 135, 106, 0, 0, 0, 50, 144, 233, 162, 0, 0, 0, 0, + 87, 54, 9, 118, 0, 0, 0, 0, 88, 54, 114, 234, 0, 0, 0, 0, 49, 37, 225, 99, 0, 0, 0, 0, 88, 243, 235, 158, 0, 0, 0, 0, + 97, 121, 219, 127, 61, 92, 0, 0, 97, 213, 219, 72, 203, 0, 0, 0, 252, 213, 234, 52, 0, 0, 0, 0, 94, 240, 211, 236, 0, 0, 0, 0, + 252, 114, 75, 58, 0, 0, 0, 0, 15, 137, 145, 0, 0, 0, 0, 0, 252, 170, 24, 0, 0, 0, 0, 0, 64, 245, 185, 200, 0, 0, 0, 0, + 0, 121, 219, 191, 51, 63, 99, 250, 0, 5, 121, 219, 172, 249, 158, 108, 0, 156, 216, 179, 172, 103, 7, 250, 0, 97, 142, 145, 103, 123, 27, 227, + 0, 221, 130, 121, 40, 123, 59, 104, 0, 143, 245, 82, 222, 23, 100, 163, 0, 241, 202, 74, 159, 19, 122, 67, 0, 176, 121, 82, 103, 249, 250, 108, + 0, 169, 191, 119, 79, 62, 167, 214, 0, 219, 247, 247, 119, 62, 12, 214, 0, 5, 219, 247, 119, 63, 12, 1, 0, 213, 219, 119, 119, 148, 99, 1, + 0, 187, 191, 119, 140, 224, 4, 238, 0, 38, 219, 199, 63, 238, 1, 4, 0, 24, 239, 40, 22, 178, 58, 84, 0, 169, 191, 119, 178, 22, 181, 214, + 97, 121, 219, 249, 250, 0, 0, 0, 97, 213, 216, 47, 0, 0, 0, 0, 64, 9, 107, 45, 0, 0, 0, 0, 85, 213, 70, 196, 0, 0, 0, 0, + 252, 97, 134, 124, 0, 0, 0, 0, 60, 213, 120, 88, 0, 0, 0, 0, 64, 37, 77, 108, 0, 0, 0, 0, 252, 245, 213, 241, 0, 0, 0, 0, + 133, 191, 191, 62, 214, 0, 0, 0, 156, 219, 219, 172, 118, 0, 0, 0, 128, 151, 219, 255, 226, 0, 0, 0, 85, 151, 219, 107, 0, 0, 0, 0, + 85, 151, 234, 214, 0, 0, 0, 0, 194, 134, 219, 64, 0, 0, 0, 0, 252, 56, 168, 175, 0, 0, 0, 0, 186, 145, 168, 146, 227, 0, 0, 0, + 0, 97, 216, 6, 102, 227, 226, 108, 0, 97, 213, 25, 13, 227, 104, 192, 0, 252, 221, 237, 146, 199, 219, 108, 0, 252, 213, 80, 202, 30, 41, 84, + 0, 165, 235, 142, 126, 232, 187, 0, 0, 97, 48, 42, 31, 166, 184, 192, 0, 97, 193, 8, 132, 51, 181, 181, 0, 27, 245, 159, 103, 47, 99, 1, + 0, 107, 219, 191, 119, 12, 12, 101, 0, 213, 78, 219, 199, 224, 162, 250, 0, 213, 107, 44, 249, 232, 63, 250, 0, 213, 107, 13, 72, 118, 53, 167, + 0, 97, 70, 168, 16, 132, 101, 229, 0, 213, 142, 232, 222, 100, 198, 245, 0, 184, 244, 168, 47, 108, 0, 0, 0, 213, 145, 191, 199, 58, 249, 108, + 252, 97, 216, 45, 114, 8, 0, 0, 252, 252, 190, 166, 0, 0, 0, 0, 252, 252, 144, 113, 0, 0, 0, 0, 88, 252, 54, 166, 0, 0, 0, 0, + 88, 94, 190, 238, 0, 0, 0, 0, 88, 61, 245, 174, 10, 0, 0, 0, 88, 252, 54, 198, 0, 0, 0, 0, 88, 252, 54, 86, 202, 0, 0, 0, + 97, 213, 219, 39, 46, 0, 0, 0, 252, 97, 151, 17, 0, 0, 0, 0, 252, 97, 213, 52, 0, 0, 0, 0, 252, 97, 213, 60, 0, 0, 0, 0, + 94, 97, 156, 206, 0, 0, 0, 0, 94, 37, 142, 0, 0, 0, 0, 0, 94, 128, 133, 0, 0, 0, 0, 0, 94, 97, 190, 243, 0, 0, 0, 0, + 0, 213, 121, 219, 51, 63, 226, 108, 0, 97, 213, 121, 239, 231, 108, 104, 0, 97, 213, 25, 146, 47, 59, 25, 0, 128, 9, 139, 204, 232, 58, 177, + 0, 128, 216, 237, 103, 235, 145, 221, 0, 212, 245, 202, 45, 242, 108, 0, 0, 150, 33, 251, 153, 132, 0, 0, 0, 144, 216, 168, 65, 58, 82, 18, + 0, 219, 191, 191, 119, 62, 167, 214, 0, 151, 219, 247, 119, 63, 99, 4, 0, 151, 219, 247, 119, 227, 226, 226, 0, 156, 219, 39, 183, 58, 178, 148, + 0, 43, 151, 219, 98, 148, 140, 14, 0, 190, 219, 155, 112, 110, 22, 146, 0, 190, 78, 31, 100, 249, 6, 77, 0, 151, 219, 191, 223, 148, 4, 108, + 97, 213, 219, 13, 126, 0, 0, 0, 252, 97, 213, 171, 143, 0, 0, 0, 252, 252, 190, 49, 0, 0, 0, 0, 252, 85, 73, 74, 0, 0, 0, 0, + 94, 252, 9, 0, 0, 0, 0, 0, 94, 35, 159, 0, 0, 0, 0, 0, 94, 194, 70, 0, 0, 0, 0, 0, 94, 194, 184, 111, 0, 0, 0, 0, + 43, 219, 219, 127, 99, 0, 0, 0, 97, 151, 219, 195, 0, 0, 0, 0, 85, 156, 219, 182, 0, 0, 0, 0, 85, 156, 219, 146, 0, 0, 0, 0, + 85, 170, 219, 171, 0, 0, 0, 0, 94, 170, 219, 1, 0, 0, 0, 0, 94, 170, 219, 140, 0, 0, 0, 0, 94, 170, 219, 248, 0, 0, 0, 0, +}; + +static INLINE int bsc_log2_256(const int n) +{ + return bsc_log2_table[n]; +} + +static INLINE int bsc_log2(const int n) +{ + if (n < 0x100) return 0 + bsc_log2_table[n >> 0]; + if (n < 0x10000) return 8 + bsc_log2_table[n >> 8]; + if (n < 0x1000000) return 16 + bsc_log2_table[n >> 16]; + return 24 + bsc_log2_table[n >> 24]; +} + +static INLINE int bsc_stretch(const int p) +{ + return bsc_stretch_table[p]; +} + +static INLINE int bsc_squash(const int s) +{ + return bsc_squash_table[2048 + s]; +} + +static INLINE int model_rank_state(const int contextRank4, const int contextRun, const int rankSizeHistory) +{ + return model_rank_state_table[(contextRun << 11) | (contextRank4 << 3) | (rankSizeHistory)]; +} + +static INLINE int model_run_state(const int contextRank0, const int contextRun, const int rank, const int runSizeHistory) +{ + return model_run_state_table[(contextRank0 << 10) | (contextRun << 6) | ((rank < 7 ? rank : 7) << 3) | (runSizeHistory < 7 ? runSizeHistory : 7)]; +} + +#endif + +/*-----------------------------------------------------------*/ +/* End tables.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/qlfc/qlfc.cpp b/bsc/libbsc/coder/qlfc/qlfc.cpp new file mode 100644 index 0000000..3294399 --- /dev/null +++ b/bsc/libbsc/coder/qlfc/qlfc.cpp @@ -0,0 +1,1363 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Quantized Local Frequency Coding functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include + +#include "qlfc.h" + +#include "../../libbsc.h" +#include "../../platform/platform.h" + +#include "../common/rangecoder.h" +#include "../common/tables.h" +#include "../common/predictor.h" + +#include "qlfc_model.h" + +int bsc_qlfc_init(int features) +{ + return bsc_qlfc_init_static_model(); +} + +unsigned char * bsc_qlfc_transform(const unsigned char * RESTRICT input, unsigned char * RESTRICT buffer, int n, unsigned char * RESTRICT MTFTable) +{ + unsigned char Flag[ALPHABET_SIZE]; + + for (int i = 0; i < ALPHABET_SIZE; ++i) Flag[i] = 0; + for (int i = 0; i < ALPHABET_SIZE; ++i) MTFTable[i] = i; + + if (input[n - 1] == 0) + { + MTFTable[0] = 1; MTFTable[1] = 0; + } + + int index = n, nSymbols = 0; + for (int i = n - 1; i >= 0;) + { + unsigned char currentChar = input[i--]; + for (; (i >= 0) && (input[i] == currentChar); --i) ; + + unsigned char previousChar = MTFTable[0], rank = 1; MTFTable[0] = currentChar; + while (true) + { + unsigned char temporaryChar0 = MTFTable[rank + 0]; MTFTable[rank + 0] = previousChar; + if (temporaryChar0 == currentChar) { rank += 0; break; } + + unsigned char temporaryChar1 = MTFTable[rank + 1]; MTFTable[rank + 1] = temporaryChar0; + if (temporaryChar1 == currentChar) { rank += 1; break; } + + unsigned char temporaryChar2 = MTFTable[rank + 2]; MTFTable[rank + 2] = temporaryChar1; + if (temporaryChar2 == currentChar) { rank += 2; break; } + + unsigned char temporaryChar3 = MTFTable[rank + 3]; MTFTable[rank + 3] = temporaryChar2; + if (temporaryChar3 == currentChar) { rank += 3; break; } + + rank += 4; previousChar = temporaryChar3; + } + + if (Flag[currentChar] == 0) + { + Flag[currentChar] = 1; + rank = nSymbols++; + } + + buffer[--index] = rank; + } + + buffer[n - 1] = 1; + + for (int rank = 1; rank < ALPHABET_SIZE; ++rank) + { + if (Flag[MTFTable[rank]] == 0) + { + MTFTable[rank] = MTFTable[rank - 1]; + break; + } + } + + return buffer + index; +} + +int bsc_qlfc_adaptive_encode(const unsigned char * input, unsigned char * output, unsigned char * buffer, int inputSize, int outputSize, QlfcStatisticalModel * model) +{ + unsigned char MTFTable[ALPHABET_SIZE]; + + bsc_qlfc_init_model(model); + + int contextRank0 = 0; + int contextRank4 = 0; + int contextRun = 0; + int maxRank = 7; + int avgRank = 0; + + unsigned char rankHistory[ALPHABET_SIZE], runHistory[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) + { + rankHistory[i] = runHistory[i] = 0; + } + + unsigned char * rankArray = bsc_qlfc_transform(input, buffer, inputSize, MTFTable); + + RangeCoder coder; + + coder.InitEncoder(output, outputSize); + coder.EncodeWord((unsigned int)inputSize); + + unsigned char usedChar[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) usedChar[i] = 0; + + int prevChar = -1; + for (int rank = 0; rank < ALPHABET_SIZE; ++rank) + { + int currentChar = MTFTable[rank]; + + for (int bit = 7; bit >= 0; --bit) + { + bool bit0 = false, bit1 = false; + + for (int c = 0; c < ALPHABET_SIZE; ++c) + { + if (c == prevChar || usedChar[c] == 0) + { + if ((currentChar >> (bit + 1)) == (c >> (bit + 1))) + { + if (c & (1 << bit)) bit1 = true; else bit0 = true; + if (bit0 && bit1) break; + } + } + } + + if (bit0 && bit1) + { + coder.EncodeBit(currentChar & (1 << bit)); + } + } + + if (currentChar == prevChar) + { + maxRank = bsc_log2_256(rank - 1); + break; + } + + prevChar = currentChar; usedChar[currentChar] = 1; + } + + for (const unsigned char * inputEnd = input + inputSize; input < inputEnd;) + { + if (coder.CheckEOB()) + { + return LIBBSC_NOT_COMPRESSIBLE; + } + + int currentChar = *input, runSize; + { + const unsigned char * inputStart = input++; + while (true) + { + if (input <= inputEnd - 4) + { + if (input[0] != currentChar) { input += 0; break; } + if (input[1] != currentChar) { input += 1; break; } + if (input[2] != currentChar) { input += 2; break; } + if (input[3] != currentChar) { input += 3; break; } + + input += 4; + } + else + { + while ((input < inputEnd) && (*input == currentChar)) ++input; + break; + } + } + + runSize = (int)(input - inputStart); + } + + int rank = *rankArray++; + int history = rankHistory[currentChar]; + int state = model_rank_state(contextRank4, contextRun, history); + + short * RESTRICT statePredictor = & model->Rank.StateModel[state]; + short * RESTRICT charPredictor = & model->Rank.CharModel[currentChar]; + short * RESTRICT staticPredictor = & model->Rank.StaticModel; + ProbabilityMixer * RESTRICT mixer = & model->mixerOfRank[currentChar]; + + if (avgRank < 32) + { + if (rank == 1) + { + rankHistory[currentChar] = 0; + + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit0(*statePredictor, M_RANK_TS_TH0, M_RANK_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RANK_TC_TH0, M_RANK_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RANK_TP_TH0, M_RANK_TP_AR0); + + coder.EncodeBit0(mixer->MixupAndUpdateBit0(probability0, probability1, probability2, M_RANK_TM_LR0, M_RANK_TM_LR1, M_RANK_TM_LR2, M_RANK_TM_TH0, M_RANK_TM_AR0)); + } + else + { + { + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit1(*statePredictor, M_RANK_TS_TH1, M_RANK_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, M_RANK_TC_TH1, M_RANK_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RANK_TP_TH1, M_RANK_TP_AR1); + + coder.EncodeBit1(mixer->MixupAndUpdateBit1(probability0, probability1, probability2, M_RANK_TM_LR0, M_RANK_TM_LR1, M_RANK_TM_LR2, M_RANK_TM_TH1, M_RANK_TM_AR1)); + } + + int bitRankSize = bsc_log2_256(rank); rankHistory[currentChar] = bitRankSize; + + statePredictor = & model->Rank.Exponent.StateModel[state][0]; + charPredictor = & model->Rank.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Exponent.StaticModel[0]; + mixer = & model->mixerOfRankExponent[history < 1 ? 1 : history][1]; + + for (int bit = 1; bit < bitRankSize; ++bit, ++statePredictor, ++charPredictor, ++staticPredictor) + { + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit1(*statePredictor, M_RANK_ES_TH1, M_RANK_ES_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, M_RANK_EC_TH1, M_RANK_EC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RANK_EP_TH1, M_RANK_EP_AR1); + + coder.EncodeBit1(mixer->MixupAndUpdateBit1(probability0, probability1, probability2, M_RANK_EM_LR0, M_RANK_EM_LR1, M_RANK_EM_LR2, M_RANK_EM_TH1, M_RANK_EM_AR1)); + + mixer = & model->mixerOfRankExponent[history <= bit ? bit + 1 : history][bit + 1]; + } + if (bitRankSize < maxRank) + { + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit0(*statePredictor, M_RANK_ES_TH0, M_RANK_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RANK_EC_TH0, M_RANK_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RANK_EP_TH0, M_RANK_EP_AR0); + + coder.EncodeBit0(mixer->MixupAndUpdateBit0(probability0, probability1, probability2, M_RANK_EM_LR0, M_RANK_EM_LR1, M_RANK_EM_LR2, M_RANK_EM_TH0, M_RANK_EM_AR0)); + } + + statePredictor = & model->Rank.Mantissa[bitRankSize].StateModel[state][0]; + charPredictor = & model->Rank.Mantissa[bitRankSize].CharModel[currentChar][0]; + staticPredictor = & model->Rank.Mantissa[bitRankSize].StaticModel[0]; + mixer = & model->mixerOfRankMantissa[bitRankSize]; + + for (int context = 1, bit = bitRankSize - 1; bit >= 0; --bit) + { + if (rank & (1 << bit)) + { + int probability0 = charPredictor[context], probability1 = statePredictor[context], probability2 = staticPredictor[context]; + + ProbabilityCounter::UpdateBit1(statePredictor[context], M_RANK_MS_TH1, M_RANK_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], M_RANK_MC_TH1, M_RANK_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], M_RANK_MP_TH1, M_RANK_MP_AR1); + + coder.EncodeBit1(mixer->MixupAndUpdateBit1(probability0, probability1, probability2, M_RANK_MM_LR0, M_RANK_MM_LR1, M_RANK_MM_LR2, M_RANK_MM_TH1, M_RANK_MM_AR1)); + + context += context + 1; + } + else + { + int probability0 = charPredictor[context], probability1 = statePredictor[context], probability2 = staticPredictor[context]; + + ProbabilityCounter::UpdateBit0(statePredictor[context], M_RANK_MS_TH0, M_RANK_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], M_RANK_MC_TH0, M_RANK_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], M_RANK_MP_TH0, M_RANK_MP_AR0); + + coder.EncodeBit0(mixer->MixupAndUpdateBit0(probability0, probability1, probability2, M_RANK_MM_LR0, M_RANK_MM_LR1, M_RANK_MM_LR2, M_RANK_MM_TH0, M_RANK_MM_AR0)); + + context += context; + } + } + } + } + else + { + rankHistory[currentChar] = bsc_log2_256(rank); + + statePredictor = & model->Rank.Escape.StateModel[state][0]; + charPredictor = & model->Rank.Escape.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Escape.StaticModel[0]; + + for (int context = 1, bit = maxRank; bit >= 0; --bit) + { + mixer = & model->mixerOfRankEscape[context]; + + if (rank & (1 << bit)) + { + int probability0 = charPredictor[context], probability1 = statePredictor[context], probability2 = staticPredictor[context]; + + ProbabilityCounter::UpdateBit1(statePredictor[context], M_RANK_PS_TH1, M_RANK_PS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], M_RANK_PC_TH1, M_RANK_PC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], M_RANK_PP_TH1, M_RANK_PP_AR1); + + coder.EncodeBit1(mixer->MixupAndUpdateBit1(probability0, probability1, probability2, M_RANK_PM_LR0, M_RANK_PM_LR1, M_RANK_PM_LR2, M_RANK_PM_TH1, M_RANK_PM_AR1)); + + context += context + 1; + } + else + { + int probability0 = charPredictor[context], probability1 = statePredictor[context], probability2 = staticPredictor[context]; + + ProbabilityCounter::UpdateBit0(statePredictor[context], M_RANK_PS_TH0, M_RANK_PS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], M_RANK_PC_TH0, M_RANK_PC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], M_RANK_PP_TH0, M_RANK_PP_AR0); + + coder.EncodeBit0(mixer->MixupAndUpdateBit0(probability0, probability1, probability2, M_RANK_PM_LR0, M_RANK_PM_LR1, M_RANK_PM_LR2, M_RANK_PM_TH0, M_RANK_PM_AR0)); + + context += context; + } + } + } + + avgRank = (avgRank * 124 + rank * 4) >> 7; + rank = rank - 1; + history = runHistory[currentChar]; + state = model_run_state(contextRank0, contextRun, rank, history); + statePredictor = & model->Run.StateModel[state]; + charPredictor = & model->Run.CharModel[currentChar]; + staticPredictor = & model->Run.StaticModel; + mixer = & model->mixerOfRun[currentChar]; + + if (runSize == 1) + { + runHistory[currentChar] = (runHistory[currentChar] + 2) >> 2; + + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit0(*statePredictor, M_RUN_TS_TH0, M_RUN_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RUN_TC_TH0, M_RUN_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RUN_TP_TH0, M_RUN_TP_AR0); + + coder.EncodeBit0(mixer->MixupAndUpdateBit0(probability0, probability1, probability2, M_RUN_TM_LR0, M_RUN_TM_LR1, M_RUN_TM_LR2, M_RUN_TM_TH0, M_RUN_TM_AR0)); + } + else + { + { + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit1(*statePredictor, M_RUN_TS_TH1, M_RUN_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, M_RUN_TC_TH1, M_RUN_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RUN_TP_TH1, M_RUN_TP_AR1); + + coder.EncodeBit1(mixer->MixupAndUpdateBit1(probability0, probability1, probability2, M_RUN_TM_LR0, M_RUN_TM_LR1, M_RUN_TM_LR2, M_RUN_TM_TH1, M_RUN_TM_AR1)); + } + + int bitRunSize = bsc_log2(runSize); runHistory[currentChar] = (runHistory[currentChar] + 3 * bitRunSize + 3) >> 2; + + statePredictor = & model->Run.Exponent.StateModel[state][0]; + charPredictor = & model->Run.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Run.Exponent.StaticModel[0]; + mixer = & model->mixerOfRunExponent[history < 1 ? 1 : history][1]; + + for (int bit = 1; bit < bitRunSize; ++bit, ++statePredictor, ++charPredictor, ++staticPredictor) + { + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit1(*statePredictor, M_RUN_ES_TH1, M_RUN_ES_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, M_RUN_EC_TH1, M_RUN_EC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RUN_EP_TH1, M_RUN_EP_AR1); + + coder.EncodeBit1(mixer->MixupAndUpdateBit1(probability0, probability1, probability2, M_RUN_EM_LR0, M_RUN_EM_LR1, M_RUN_EM_LR2, M_RUN_EM_TH1, M_RUN_EM_AR1)); + + mixer = & model->mixerOfRunExponent[history <= bit ? bit + 1 : history][bit + 1]; + } + { + int probability0 = *charPredictor, probability1 = *statePredictor, probability2 = *staticPredictor; + + ProbabilityCounter::UpdateBit0(*statePredictor, M_RUN_ES_TH0, M_RUN_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RUN_EC_TH0, M_RUN_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RUN_EP_TH0, M_RUN_EP_AR0); + + coder.EncodeBit0(mixer->MixupAndUpdateBit0(probability0, probability1, probability2, M_RUN_EM_LR0, M_RUN_EM_LR1, M_RUN_EM_LR2, M_RUN_EM_TH0, M_RUN_EM_AR0)); + } + + statePredictor = & model->Run.Mantissa[bitRunSize].StateModel[state][0]; + charPredictor = & model->Run.Mantissa[bitRunSize].CharModel[currentChar][0]; + staticPredictor = & model->Run.Mantissa[bitRunSize].StaticModel[0]; + mixer = & model->mixerOfRunMantissa[bitRunSize]; + + for (int context = 1, bit = bitRunSize - 1; bit >= 0; --bit) + { + if (runSize & (1 << bit)) + { + int probability0 = charPredictor[context], probability1 = statePredictor[context], probability2 = staticPredictor[context]; + + ProbabilityCounter::UpdateBit1(statePredictor[context], M_RUN_MS_TH1, M_RUN_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], M_RUN_MC_TH1, M_RUN_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], M_RUN_MP_TH1, M_RUN_MP_AR1); + + coder.EncodeBit1(mixer->MixupAndUpdateBit1(probability0, probability1, probability2, M_RUN_MM_LR0, M_RUN_MM_LR1, M_RUN_MM_LR2, M_RUN_MM_TH1, M_RUN_MM_AR1)); + + if (bitRunSize <= 5) context += context + 1; else context++; + } + else + { + int probability0 = charPredictor[context], probability1 = statePredictor[context], probability2 = staticPredictor[context]; + + ProbabilityCounter::UpdateBit0(statePredictor[context], M_RUN_MS_TH0, M_RUN_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], M_RUN_MC_TH0, M_RUN_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], M_RUN_MP_TH0, M_RUN_MP_AR0); + + coder.EncodeBit0(mixer->MixupAndUpdateBit0(probability0, probability1, probability2, M_RUN_MM_LR0, M_RUN_MM_LR1, M_RUN_MM_LR2, M_RUN_MM_TH0, M_RUN_MM_AR0)); + + if (bitRunSize <= 5) context += context + 0; else context++; + } + } + } + + contextRank0 = ((contextRank0 << 1) | (rank == 0 ? 1 : 0)) & 0x7; + contextRank4 = ((contextRank4 << 2) | (rank < 3 ? rank : 3)) & 0xff; + contextRun = ((contextRun << 1) | (runSize < 3 ? 1 : 0)) & 0xf; + } + + return coder.FinishEncoder(); +} + +int bsc_qlfc_static_encode(const unsigned char * input, unsigned char * output, unsigned char * buffer, int inputSize, int outputSize, QlfcStatisticalModel * model) +{ + unsigned char MTFTable[ALPHABET_SIZE]; + + bsc_qlfc_init_model(model); + + int contextRank0 = 0; + int contextRank4 = 0; + int contextRun = 0; + int maxRank = 7; + int avgRank = 0; + + unsigned char rankHistory[ALPHABET_SIZE], runHistory[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) + { + rankHistory[i] = runHistory[i] = 0; + } + + unsigned char * rankArray = bsc_qlfc_transform(input, buffer, inputSize, MTFTable); + + RangeCoder coder; + + coder.InitEncoder(output, outputSize); + coder.EncodeWord((unsigned int)inputSize); + + unsigned char usedChar[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) usedChar[i] = 0; + + int prevChar = -1; + for (int rank = 0; rank < ALPHABET_SIZE; ++rank) + { + int currentChar = MTFTable[rank]; + + for (int bit = 7; bit >= 0; --bit) + { + bool bit0 = false, bit1 = false; + + for (int c = 0; c < ALPHABET_SIZE; ++c) + { + if (c == prevChar || usedChar[c] == 0) + { + if ((currentChar >> (bit + 1)) == (c >> (bit + 1))) + { + if (c & (1 << bit)) bit1 = true; else bit0 = true; + if (bit0 && bit1) break; + } + } + } + + if (bit0 && bit1) + { + coder.EncodeBit(currentChar & (1 << bit)); + } + } + + if (currentChar == prevChar) + { + maxRank = bsc_log2_256(rank - 1); + break; + } + + prevChar = currentChar; usedChar[currentChar] = 1; + } + + for (const unsigned char * inputEnd = input + inputSize; input < inputEnd;) + { + if (coder.CheckEOB()) + { + return LIBBSC_NOT_COMPRESSIBLE; + } + + int currentChar = *input, runSize; + { + const unsigned char * inputStart = input++; + while (true) + { + if (input <= inputEnd - 4) + { + if (input[0] != currentChar) { input += 0; break; } + if (input[1] != currentChar) { input += 1; break; } + if (input[2] != currentChar) { input += 2; break; } + if (input[3] != currentChar) { input += 3; break; } + + input += 4; + } + else + { + while ((input < inputEnd) && (*input == currentChar)) ++input; + break; + } + } + + runSize = (int)(input - inputStart); + } + + int rank = *rankArray++; + int history = rankHistory[currentChar]; + int state = model_rank_state(contextRank4, contextRun, history); + + short * RESTRICT statePredictor = & model->Rank.StateModel[state]; + short * RESTRICT charPredictor = & model->Rank.CharModel[currentChar]; + short * RESTRICT staticPredictor = & model->Rank.StaticModel; + + if (avgRank < 32) + { + if (rank == 1) + { + rankHistory[currentChar] = 0; + + int probability = ((*charPredictor) * F_RANK_TM_LR0 + (*statePredictor) * F_RANK_TM_LR1 + (*staticPredictor) * F_RANK_TM_LR2) >> 5; + + ProbabilityCounter::UpdateBit0(*statePredictor, F_RANK_TS_TH0, F_RANK_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RANK_TC_TH0, F_RANK_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RANK_TP_TH0, F_RANK_TP_AR0); + + coder.EncodeBit0(probability); + } + else + { + { + int probability = ((*charPredictor) * F_RANK_TM_LR0 + (*statePredictor) * F_RANK_TM_LR1 + (*staticPredictor) * F_RANK_TM_LR2) >> 5; + + ProbabilityCounter::UpdateBit1(*statePredictor, F_RANK_TS_TH1, F_RANK_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, F_RANK_TC_TH1, F_RANK_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RANK_TP_TH1, F_RANK_TP_AR1); + + coder.EncodeBit1(probability); + } + + int bitRankSize = bsc_log2_256(rank); rankHistory[currentChar] = bitRankSize; + + statePredictor = & model->Rank.Exponent.StateModel[state][0]; + charPredictor = & model->Rank.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Exponent.StaticModel[0]; + + for (int bit = 1; bit < bitRankSize; ++bit, ++statePredictor, ++charPredictor, ++staticPredictor) + { + int probability = ((*charPredictor) * F_RANK_EM_LR0 + (*statePredictor) * F_RANK_EM_LR1 + (*staticPredictor) * F_RANK_EM_LR2) >> 5; + + ProbabilityCounter::UpdateBit1(*statePredictor, F_RANK_ES_TH1, F_RANK_ES_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, F_RANK_EC_TH1, F_RANK_EC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RANK_EP_TH1, F_RANK_EP_AR1); + + coder.EncodeBit1(probability); + } + if (bitRankSize < maxRank) + { + int probability = ((*charPredictor) * F_RANK_EM_LR0 + (*statePredictor) * F_RANK_EM_LR1 + (*staticPredictor) * F_RANK_EM_LR2) >> 5; + + ProbabilityCounter::UpdateBit0(*statePredictor, F_RANK_ES_TH0, F_RANK_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RANK_EC_TH0, F_RANK_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RANK_EP_TH0, F_RANK_EP_AR0); + + coder.EncodeBit0(probability); + } + + statePredictor = & model->Rank.Mantissa[bitRankSize].StateModel[state][0]; + charPredictor = & model->Rank.Mantissa[bitRankSize].CharModel[currentChar][0]; + staticPredictor = & model->Rank.Mantissa[bitRankSize].StaticModel[0]; + + for (int context = 1, bit = bitRankSize - 1; bit >= 0; --bit) + { + int probability = (charPredictor[context] * F_RANK_MM_LR0 + statePredictor[context] * F_RANK_MM_LR1 + staticPredictor[context] * F_RANK_MM_LR2) >> 5; + + if (rank & (1 << bit)) + { + ProbabilityCounter::UpdateBit1(statePredictor[context], F_RANK_MS_TH1, F_RANK_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], F_RANK_MC_TH1, F_RANK_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], F_RANK_MP_TH1, F_RANK_MP_AR1); + + coder.EncodeBit1(probability); context += context + 1; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[context], F_RANK_MS_TH0, F_RANK_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], F_RANK_MC_TH0, F_RANK_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], F_RANK_MP_TH0, F_RANK_MP_AR0); + + coder.EncodeBit0(probability); context += context; + } + } + } + } + else + { + rankHistory[currentChar] = bsc_log2_256(rank); + + statePredictor = & model->Rank.Escape.StateModel[state][0]; + charPredictor = & model->Rank.Escape.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Escape.StaticModel[0]; + + for (int context = 1, bit = maxRank; bit >= 0; --bit) + { + int probability = (charPredictor[context] * F_RANK_PM_LR0 + statePredictor[context] * F_RANK_PM_LR1 + staticPredictor[context] * F_RANK_PM_LR2) >> 5; + + if (rank & (1 << bit)) + { + ProbabilityCounter::UpdateBit1(statePredictor[context], F_RANK_PS_TH1, F_RANK_PS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], F_RANK_PC_TH1, F_RANK_PC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], F_RANK_PP_TH1, F_RANK_PP_AR1); + + coder.EncodeBit1(probability); context += context + 1; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[context], F_RANK_PS_TH0, F_RANK_PS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], F_RANK_PC_TH0, F_RANK_PC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], F_RANK_PP_TH0, F_RANK_PP_AR0); + + coder.EncodeBit0(probability); context += context; + } + } + } + + avgRank = (avgRank * 124 + rank * 4) >> 7; + rank = rank - 1; + history = runHistory[currentChar]; + state = model_run_state(contextRank0, contextRun, rank, history); + statePredictor = & model->Run.StateModel[state]; + charPredictor = & model->Run.CharModel[currentChar]; + staticPredictor = & model->Run.StaticModel; + + if (runSize == 1) + { + runHistory[currentChar] = (runHistory[currentChar] + 2) >> 2; + + int probability = ((*charPredictor) * F_RUN_TM_LR0 + (*statePredictor) * F_RUN_TM_LR1 + (*staticPredictor) * F_RUN_TM_LR2) >> 5; + + ProbabilityCounter::UpdateBit0(*statePredictor, F_RUN_TS_TH0, F_RUN_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RUN_TC_TH0, F_RUN_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RUN_TP_TH0, F_RUN_TP_AR0); + + coder.EncodeBit0(probability); + } + else + { + { + int probability = ((*charPredictor) * F_RUN_TM_LR0 + (*statePredictor) * F_RUN_TM_LR1 + (*staticPredictor) * F_RUN_TM_LR2) >> 5; + + ProbabilityCounter::UpdateBit1(*statePredictor, F_RUN_TS_TH1, F_RUN_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, F_RUN_TC_TH1, F_RUN_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RUN_TP_TH1, F_RUN_TP_AR1); + + coder.EncodeBit1(probability); + } + + int bitRunSize = bsc_log2(runSize); runHistory[currentChar] = (runHistory[currentChar] + 3 * bitRunSize + 3) >> 2; + + statePredictor = & model->Run.Exponent.StateModel[state][0]; + charPredictor = & model->Run.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Run.Exponent.StaticModel[0]; + + for (int bit = 1; bit < bitRunSize; ++bit, ++statePredictor, ++charPredictor, ++staticPredictor) + { + int probability = ((*charPredictor) * F_RUN_EM_LR0 + (*statePredictor) * F_RUN_EM_LR1 + (*staticPredictor) * F_RUN_EM_LR2) >> 5; + + ProbabilityCounter::UpdateBit1(*statePredictor, F_RUN_ES_TH1, F_RUN_ES_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, F_RUN_EC_TH1, F_RUN_EC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RUN_EP_TH1, F_RUN_EP_AR1); + + coder.EncodeBit1(probability); + } + { + int probability = ((*charPredictor) * F_RUN_EM_LR0 + (*statePredictor) * F_RUN_EM_LR1 + (*staticPredictor) * F_RUN_EM_LR2) >> 5; + + ProbabilityCounter::UpdateBit0(*statePredictor, F_RUN_ES_TH0, F_RUN_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RUN_EC_TH0, F_RUN_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RUN_EP_TH0, F_RUN_EP_AR0); + + coder.EncodeBit0(probability); + } + + statePredictor = & model->Run.Mantissa[bitRunSize].StateModel[state][0]; + charPredictor = & model->Run.Mantissa[bitRunSize].CharModel[currentChar][0]; + staticPredictor = & model->Run.Mantissa[bitRunSize].StaticModel[0]; + + for (int context = 1, bit = bitRunSize - 1; bit >= 0; --bit) + { + int probability = (charPredictor[context] * F_RUN_MM_LR0 + statePredictor[context] * F_RUN_MM_LR1 + staticPredictor[context] * F_RUN_MM_LR2) >> 5; + if (runSize & (1 << bit)) + { + ProbabilityCounter::UpdateBit1(statePredictor[context], F_RUN_MS_TH1, F_RUN_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], F_RUN_MC_TH1, F_RUN_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], F_RUN_MP_TH1, F_RUN_MP_AR1); + + coder.EncodeBit1(probability); if (bitRunSize <= 5) context += context + 1; else context++; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[context], F_RUN_MS_TH0, F_RUN_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], F_RUN_MC_TH0, F_RUN_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], F_RUN_MP_TH0, F_RUN_MP_AR0); + + coder.EncodeBit0(probability); if (bitRunSize <= 5) context += context + 0; else context++; + } + } + } + + contextRank0 = ((contextRank0 << 1) | (rank == 0 ? 1 : 0)) & 0x7; + contextRank4 = ((contextRank4 << 2) | (rank < 3 ? rank : 3)) & 0xff; + contextRun = ((contextRun << 1) | (runSize < 3 ? 1 : 0)) & 0xf; + } + + return coder.FinishEncoder(); +} + +int bsc_qlfc_adaptive_decode(const unsigned char * input, unsigned char * output, QlfcStatisticalModel * model) +{ + RangeCoder coder; + + unsigned char MTFTable[ALPHABET_SIZE]; + + bsc_qlfc_init_model(model); + + int contextRank0 = 0; + int contextRank4 = 0; + int contextRun = 0; + int maxRank = 7; + int avgRank = 0; + + unsigned char rankHistory[ALPHABET_SIZE], runHistory[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) + { + rankHistory[i] = runHistory[i] = 0; + } + + coder.InitDecoder(input); + int n = (int)coder.DecodeWord(); + + unsigned char usedChar[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) usedChar[i] = 0; + + int prevChar = -1; + for (int rank = 0; rank < ALPHABET_SIZE; ++rank) + { + int currentChar = 0; + + for (int bit = 7; bit >= 0; --bit) + { + bool bit0 = false, bit1 = false; + + for (int c = 0; c < ALPHABET_SIZE; ++c) + { + if (c == prevChar || usedChar[c] == 0) + { + if (currentChar == (c >> (bit + 1))) + { + if (c & (1 << bit)) bit1 = true; else bit0 = true; + if (bit0 && bit1) break; + } + } + } + + if (bit0 && bit1) + { + currentChar += currentChar + coder.DecodeBit(); + } + else + { + if (bit0) currentChar += currentChar + 0; + if (bit1) currentChar += currentChar + 1; + } + } + + MTFTable[rank] = currentChar; + + if (currentChar == prevChar) + { + maxRank = bsc_log2_256(rank - 1); + break; + } + + prevChar = currentChar; usedChar[currentChar] = 1; + } + + for (int i = 0; i < n;) + { + int currentChar = MTFTable[0]; + int history = rankHistory[currentChar]; + int state = model_rank_state(contextRank4, contextRun, history); + + short * RESTRICT statePredictor = & model->Rank.StateModel[state]; + short * RESTRICT charPredictor = & model->Rank.CharModel[currentChar]; + short * RESTRICT staticPredictor = & model->Rank.StaticModel; + ProbabilityMixer * RESTRICT mixer = & model->mixerOfRank[currentChar]; + + int rank = 1; + if (avgRank < 32) + { + if (coder.DecodeBit(mixer->Mixup(*charPredictor, *statePredictor, *staticPredictor))) + { + ProbabilityCounter::UpdateBit1(*statePredictor, M_RANK_TS_TH1, M_RANK_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, M_RANK_TC_TH1, M_RANK_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RANK_TP_TH1, M_RANK_TP_AR1); + mixer->UpdateBit1(M_RANK_TM_LR0, M_RANK_TM_LR1, M_RANK_TM_LR2, M_RANK_TM_TH1, M_RANK_TM_AR1); + + statePredictor = & model->Rank.Exponent.StateModel[state][0]; + charPredictor = & model->Rank.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Exponent.StaticModel[0]; + mixer = & model->mixerOfRankExponent[history < 1 ? 1 : history][1]; + + int bitRankSize = 1; + while (true) + { + if (bitRankSize == maxRank) break; + if (coder.DecodeBit(mixer->Mixup(*charPredictor, *statePredictor, *staticPredictor))) + { + ProbabilityCounter::UpdateBit1(*statePredictor, M_RANK_ES_TH1, M_RANK_ES_AR1); statePredictor++; + ProbabilityCounter::UpdateBit1(*charPredictor, M_RANK_EC_TH1, M_RANK_EC_AR1); charPredictor++; + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RANK_EP_TH1, M_RANK_EP_AR1); staticPredictor++; + mixer->UpdateBit1(M_RANK_EM_LR0, M_RANK_EM_LR1, M_RANK_EM_LR2, M_RANK_EM_TH1, M_RANK_EM_AR1); + bitRankSize++; + mixer = & model->mixerOfRankExponent[history < bitRankSize ? bitRankSize : history][bitRankSize]; + } + else + { + ProbabilityCounter::UpdateBit0(*statePredictor, M_RANK_ES_TH0, M_RANK_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RANK_EC_TH0, M_RANK_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RANK_EP_TH0, M_RANK_EP_AR0); + mixer->UpdateBit0(M_RANK_EM_LR0, M_RANK_EM_LR1, M_RANK_EM_LR2, M_RANK_EM_TH0, M_RANK_EM_AR0); + break; + } + } + + rankHistory[currentChar] = bitRankSize; + + statePredictor = & model->Rank.Mantissa[bitRankSize].StateModel[state][0]; + charPredictor = & model->Rank.Mantissa[bitRankSize].CharModel[currentChar][0]; + staticPredictor = & model->Rank.Mantissa[bitRankSize].StaticModel[0]; + mixer = & model->mixerOfRankMantissa[bitRankSize]; + + for (int bit = bitRankSize - 1; bit >= 0; --bit) + { + if (coder.DecodeBit(mixer->Mixup(charPredictor[rank], statePredictor[rank], staticPredictor[rank]))) + { + ProbabilityCounter::UpdateBit1(statePredictor[rank], M_RANK_MS_TH1, M_RANK_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[rank], M_RANK_MC_TH1, M_RANK_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[rank], M_RANK_MP_TH1, M_RANK_MP_AR1); + mixer->UpdateBit1(M_RANK_MM_LR0, M_RANK_MM_LR1, M_RANK_MM_LR2, M_RANK_MM_TH1, M_RANK_MM_AR1); + rank += rank + 1; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[rank], M_RANK_MS_TH0, M_RANK_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[rank], M_RANK_MC_TH0, M_RANK_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[rank], M_RANK_MP_TH0, M_RANK_MP_AR0); + mixer->UpdateBit0(M_RANK_MM_LR0, M_RANK_MM_LR1, M_RANK_MM_LR2, M_RANK_MM_TH0, M_RANK_MM_AR0); + rank += rank; + } + } + } + else + { + rankHistory[currentChar] = 0; + ProbabilityCounter::UpdateBit0(*statePredictor, M_RANK_TS_TH0, M_RANK_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RANK_TC_TH0, M_RANK_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RANK_TP_TH0, M_RANK_TP_AR0); + mixer->UpdateBit0(M_RANK_TM_LR0, M_RANK_TM_LR1, M_RANK_TM_LR2, M_RANK_TM_TH0, M_RANK_TM_AR0); + } + } + else + { + statePredictor = & model->Rank.Escape.StateModel[state][0]; + charPredictor = & model->Rank.Escape.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Escape.StaticModel[0]; + + rank = 0; + for (int context = 1, bit = maxRank; bit >= 0; --bit) + { + mixer = & model->mixerOfRankEscape[context]; + + if (coder.DecodeBit(mixer->Mixup(charPredictor[context], statePredictor[context], staticPredictor[context]))) + { + ProbabilityCounter::UpdateBit1(statePredictor[context], M_RANK_PS_TH1, M_RANK_PS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], M_RANK_PC_TH1, M_RANK_PC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], M_RANK_PP_TH1, M_RANK_PP_AR1); + mixer->UpdateBit1(M_RANK_PM_LR0, M_RANK_PM_LR1, M_RANK_PM_LR2, M_RANK_PM_TH1, M_RANK_PM_AR1); + context += context + 1; rank += rank + 1; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[context], M_RANK_PS_TH0, M_RANK_PS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], M_RANK_PC_TH0, M_RANK_PC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], M_RANK_PP_TH0, M_RANK_PP_AR0); + mixer->UpdateBit0(M_RANK_PM_LR0, M_RANK_PM_LR1, M_RANK_PM_LR2, M_RANK_PM_TH0, M_RANK_PM_AR0); + context += context; rank += rank; + } + } + + rankHistory[currentChar] = bsc_log2_256(rank); + } + + { + for (int r = 0; r < rank; ++r) + { + MTFTable[r] = MTFTable[r + 1]; + } + MTFTable[rank] = currentChar; + } + + avgRank = (avgRank * 124 + rank * 4) >> 7; + rank = rank - 1; + history = runHistory[currentChar]; + state = model_run_state(contextRank0, contextRun, rank, history); + statePredictor = & model->Run.StateModel[state]; + charPredictor = & model->Run.CharModel[currentChar]; + staticPredictor = & model->Run.StaticModel; + mixer = & model->mixerOfRun[currentChar]; + + int runSize = 1; + if (coder.DecodeBit(mixer->Mixup(*charPredictor, *statePredictor, *staticPredictor))) + { + ProbabilityCounter::UpdateBit1(*statePredictor, M_RUN_TS_TH1, M_RUN_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, M_RUN_TC_TH1, M_RUN_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RUN_TP_TH1, M_RUN_TP_AR1); + mixer->UpdateBit1(M_RUN_TM_LR0, M_RUN_TM_LR1, M_RUN_TM_LR2, M_RUN_TM_TH1, M_RUN_TM_AR1); + + statePredictor = & model->Run.Exponent.StateModel[state][0]; + charPredictor = & model->Run.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Run.Exponent.StaticModel[0]; + mixer = & model->mixerOfRunExponent[history < 1 ? 1 : history][1]; + + int bitRunSize = 1; + while (true) + { + if (coder.DecodeBit(mixer->Mixup(*charPredictor, *statePredictor, *staticPredictor))) + { + ProbabilityCounter::UpdateBit1(*statePredictor, M_RUN_ES_TH1, M_RUN_ES_AR1); statePredictor++; + ProbabilityCounter::UpdateBit1(*charPredictor, M_RUN_EC_TH1, M_RUN_EC_AR1); charPredictor++; + ProbabilityCounter::UpdateBit1(*staticPredictor, M_RUN_EP_TH1, M_RUN_EP_AR1); staticPredictor++; + mixer->UpdateBit1(M_RUN_EM_LR0, M_RUN_EM_LR1, M_RUN_EM_LR2, M_RUN_EM_TH1, M_RUN_EM_AR1); + bitRunSize++; mixer = & model->mixerOfRunExponent[history < bitRunSize ? bitRunSize : history][bitRunSize]; + } + else + { + ProbabilityCounter::UpdateBit0(*statePredictor, M_RUN_ES_TH0, M_RUN_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RUN_EC_TH0, M_RUN_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RUN_EP_TH0, M_RUN_EP_AR0); + mixer->UpdateBit0(M_RUN_EM_LR0, M_RUN_EM_LR1, M_RUN_EM_LR2, M_RUN_EM_TH0, M_RUN_EM_AR0); + break; + } + } + + runHistory[currentChar] = (runHistory[currentChar] + 3 * bitRunSize + 3) >> 2; + + statePredictor = & model->Run.Mantissa[bitRunSize].StateModel[state][0]; + charPredictor = & model->Run.Mantissa[bitRunSize].CharModel[currentChar][0]; + staticPredictor = & model->Run.Mantissa[bitRunSize].StaticModel[0]; + mixer = & model->mixerOfRunMantissa[bitRunSize]; + + for (int context = 1, bit = bitRunSize - 1; bit >= 0; --bit) + { + if (coder.DecodeBit(mixer->Mixup(charPredictor[context], statePredictor[context], staticPredictor[context]))) + { + ProbabilityCounter::UpdateBit1(statePredictor[context], M_RUN_MS_TH1, M_RUN_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], M_RUN_MC_TH1, M_RUN_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], M_RUN_MP_TH1, M_RUN_MP_AR1); + mixer->UpdateBit1(M_RUN_MM_LR0, M_RUN_MM_LR1, M_RUN_MM_LR2, M_RUN_MM_TH1, M_RUN_MM_AR1); + runSize += runSize + 1; if (bitRunSize <= 5) context += context + 1; else context++; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[context], M_RUN_MS_TH0, M_RUN_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], M_RUN_MC_TH0, M_RUN_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], M_RUN_MP_TH0, M_RUN_MP_AR0); + mixer->UpdateBit0(M_RUN_MM_LR0, M_RUN_MM_LR1, M_RUN_MM_LR2, M_RUN_MM_TH0, M_RUN_MM_AR0); + runSize += runSize; if (bitRunSize <= 5) context += context; else context++; + } + } + + } + else + { + runHistory[currentChar] = (runHistory[currentChar] + 2) >> 2; + ProbabilityCounter::UpdateBit0(*statePredictor, M_RUN_TS_TH0, M_RUN_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, M_RUN_TC_TH0, M_RUN_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, M_RUN_TP_TH0, M_RUN_TP_AR0); + mixer->UpdateBit0(M_RUN_TM_LR0, M_RUN_TM_LR1, M_RUN_TM_LR2, M_RUN_TM_TH0, M_RUN_TM_AR0); + } + + contextRank0 = ((contextRank0 << 1) | (rank == 0 ? 1 : 0)) & 0x7; + contextRank4 = ((contextRank4 << 2) | (rank < 3 ? rank : 3)) & 0xff; + contextRun = ((contextRun << 1) | (runSize < 3 ? 1 : 0)) & 0xf; + + for (; runSize > 0; --runSize) output[i++] = currentChar; + } + + return n; +} + +int bsc_qlfc_static_decode(const unsigned char * input, unsigned char * output, QlfcStatisticalModel * model) +{ + RangeCoder coder; + + unsigned char MTFTable[ALPHABET_SIZE]; + + bsc_qlfc_init_model(model); + + int contextRank0 = 0; + int contextRank4 = 0; + int contextRun = 0; + int maxRank = 7; + int avgRank = 0; + + unsigned char rankHistory[ALPHABET_SIZE], runHistory[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) + { + rankHistory[i] = runHistory[i] = 0; + } + + coder.InitDecoder(input); + int n = (int)coder.DecodeWord(); + + unsigned char usedChar[ALPHABET_SIZE]; + for (int i = 0; i < ALPHABET_SIZE; ++i) usedChar[i] = 0; + + int prevChar = -1; + for (int rank = 0; rank < ALPHABET_SIZE; ++rank) + { + int currentChar = 0; + + for (int bit = 7; bit >= 0; --bit) + { + bool bit0 = false, bit1 = false; + + for (int c = 0; c < ALPHABET_SIZE; ++c) + { + if (c == prevChar || usedChar[c] == 0) + { + if (currentChar == (c >> (bit + 1))) + { + if (c & (1 << bit)) bit1 = true; else bit0 = true; + if (bit0 && bit1) break; + } + } + } + + if (bit0 && bit1) + { + currentChar += currentChar + coder.DecodeBit(); + } + else + { + if (bit0) currentChar += currentChar + 0; + if (bit1) currentChar += currentChar + 1; + } + } + + MTFTable[rank] = currentChar; + + if (currentChar == prevChar) + { + maxRank = bsc_log2_256(rank - 1); + break; + } + + prevChar = currentChar; usedChar[currentChar] = 1; + } + + for (int i = 0; i < n;) + { + int currentChar = MTFTable[0]; + int history = rankHistory[currentChar]; + int state = model_rank_state(contextRank4, contextRun, history); + + short * RESTRICT statePredictor = & model->Rank.StateModel[state]; + short * RESTRICT charPredictor = & model->Rank.CharModel[currentChar]; + short * RESTRICT staticPredictor = & model->Rank.StaticModel; + + int rank = 1; + if (avgRank < 32) + { + if (coder.DecodeBit((*charPredictor * F_RANK_TM_LR0 + *statePredictor * F_RANK_TM_LR1 + *staticPredictor * F_RANK_TM_LR2) >> 5)) + { + ProbabilityCounter::UpdateBit1(*statePredictor, F_RANK_TS_TH1, F_RANK_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, F_RANK_TC_TH1, F_RANK_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RANK_TP_TH1, F_RANK_TP_AR1); + + statePredictor = & model->Rank.Exponent.StateModel[state][0]; + charPredictor = & model->Rank.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Exponent.StaticModel[0]; + + int bitRankSize = 1; + while (true) + { + if (bitRankSize == maxRank) break; + if (coder.DecodeBit((*charPredictor * F_RANK_EM_LR0 + *statePredictor * F_RANK_EM_LR1 + *staticPredictor * F_RANK_EM_LR2) >> 5)) + { + ProbabilityCounter::UpdateBit1(*statePredictor, F_RANK_ES_TH1, F_RANK_ES_AR1); statePredictor++; + ProbabilityCounter::UpdateBit1(*charPredictor, F_RANK_EC_TH1, F_RANK_EC_AR1); charPredictor++; + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RANK_EP_TH1, F_RANK_EP_AR1); staticPredictor++; + bitRankSize++; + } + else + { + ProbabilityCounter::UpdateBit0(*statePredictor, F_RANK_ES_TH0, F_RANK_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RANK_EC_TH0, F_RANK_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RANK_EP_TH0, F_RANK_EP_AR0); + break; + } + } + + rankHistory[currentChar] = bitRankSize; + + statePredictor = & model->Rank.Mantissa[bitRankSize].StateModel[state][0]; + charPredictor = & model->Rank.Mantissa[bitRankSize].CharModel[currentChar][0]; + staticPredictor = & model->Rank.Mantissa[bitRankSize].StaticModel[0]; + + for (int bit = bitRankSize - 1; bit >= 0; --bit) + { + if (coder.DecodeBit((charPredictor[rank] * F_RANK_MM_LR0 + statePredictor[rank] * F_RANK_MM_LR1 + staticPredictor[rank] * F_RANK_MM_LR2) >> 5)) + { + ProbabilityCounter::UpdateBit1(statePredictor[rank], F_RANK_MS_TH1, F_RANK_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[rank], F_RANK_MC_TH1, F_RANK_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[rank], F_RANK_MP_TH1, F_RANK_MP_AR1); + rank += rank + 1; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[rank], F_RANK_MS_TH0, F_RANK_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[rank], F_RANK_MC_TH0, F_RANK_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[rank], F_RANK_MP_TH0, F_RANK_MP_AR0); + rank += rank; + } + } + } + else + { + rankHistory[currentChar] = 0; + ProbabilityCounter::UpdateBit0(*statePredictor, F_RANK_TS_TH0, F_RANK_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RANK_TC_TH0, F_RANK_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RANK_TP_TH0, F_RANK_TP_AR0); + } + } + else + { + statePredictor = & model->Rank.Escape.StateModel[state][0]; + charPredictor = & model->Rank.Escape.CharModel[currentChar][0]; + staticPredictor = & model->Rank.Escape.StaticModel[0]; + + rank = 0; + for (int context = 1, bit = maxRank; bit >= 0; --bit) + { + if (coder.DecodeBit((charPredictor[context] * F_RANK_PM_LR0 + statePredictor[context] * F_RANK_PM_LR1 + staticPredictor[context] * F_RANK_PM_LR2) >> 5)) + { + ProbabilityCounter::UpdateBit1(statePredictor[context], F_RANK_PS_TH1, F_RANK_PS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], F_RANK_PC_TH1, F_RANK_PC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], F_RANK_PP_TH1, F_RANK_PP_AR1); + context += context + 1; rank += rank + 1; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[context], F_RANK_PS_TH0, F_RANK_PS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], F_RANK_PC_TH0, F_RANK_PC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], F_RANK_PP_TH0, F_RANK_PP_AR0); + context += context; rank += rank; + } + } + + rankHistory[currentChar] = bsc_log2_256(rank); + } + + { + for (int r = 0; r < rank; ++r) + { + MTFTable[r] = MTFTable[r + 1]; + } + MTFTable[rank] = currentChar; + } + + avgRank = (avgRank * 124 + rank * 4) >> 7; + rank = rank - 1; + history = runHistory[currentChar]; + state = model_run_state(contextRank0, contextRun, rank, history); + statePredictor = & model->Run.StateModel[state]; + charPredictor = & model->Run.CharModel[currentChar]; + staticPredictor = & model->Run.StaticModel; + + int runSize = 1; + if (coder.DecodeBit((*charPredictor * F_RUN_TM_LR0 + *statePredictor * F_RUN_TM_LR1 + *staticPredictor * F_RUN_TM_LR2) >> 5)) + { + ProbabilityCounter::UpdateBit1(*statePredictor, F_RUN_TS_TH1, F_RUN_TS_AR1); + ProbabilityCounter::UpdateBit1(*charPredictor, F_RUN_TC_TH1, F_RUN_TC_AR1); + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RUN_TP_TH1, F_RUN_TP_AR1); + + statePredictor = & model->Run.Exponent.StateModel[state][0]; + charPredictor = & model->Run.Exponent.CharModel[currentChar][0]; + staticPredictor = & model->Run.Exponent.StaticModel[0]; + + int bitRunSize = 1; + while (true) + { + if (coder.DecodeBit((*charPredictor * F_RUN_EM_LR0 + *statePredictor * F_RUN_EM_LR1 + *staticPredictor * F_RUN_EM_LR2) >> 5)) + { + ProbabilityCounter::UpdateBit1(*statePredictor, F_RUN_ES_TH1, F_RUN_ES_AR1); statePredictor++; + ProbabilityCounter::UpdateBit1(*charPredictor, F_RUN_EC_TH1, F_RUN_EC_AR1); charPredictor++; + ProbabilityCounter::UpdateBit1(*staticPredictor, F_RUN_EP_TH1, F_RUN_EP_AR1); staticPredictor++; + bitRunSize++; + } + else + { + ProbabilityCounter::UpdateBit0(*statePredictor, F_RUN_ES_TH0, F_RUN_ES_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RUN_EC_TH0, F_RUN_EC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RUN_EP_TH0, F_RUN_EP_AR0); + break; + } + } + + runHistory[currentChar] = (runHistory[currentChar] + 3 * bitRunSize + 3) >> 2; + + statePredictor = & model->Run.Mantissa[bitRunSize].StateModel[state][0]; + charPredictor = & model->Run.Mantissa[bitRunSize].CharModel[currentChar][0]; + staticPredictor = & model->Run.Mantissa[bitRunSize].StaticModel[0]; + + for (int context = 1, bit = bitRunSize - 1; bit >= 0; --bit) + { + if (coder.DecodeBit((charPredictor[context] * F_RUN_MM_LR0 + statePredictor[context] * F_RUN_MM_LR1 + staticPredictor[context] * F_RUN_MM_LR2) >> 5)) + { + ProbabilityCounter::UpdateBit1(statePredictor[context], F_RUN_MS_TH1, F_RUN_MS_AR1); + ProbabilityCounter::UpdateBit1(charPredictor[context], F_RUN_MC_TH1, F_RUN_MC_AR1); + ProbabilityCounter::UpdateBit1(staticPredictor[context], F_RUN_MP_TH1, F_RUN_MP_AR1); + runSize += runSize + 1; if (bitRunSize <= 5) context += context + 1; else context++; + } + else + { + ProbabilityCounter::UpdateBit0(statePredictor[context], F_RUN_MS_TH0, F_RUN_MS_AR0); + ProbabilityCounter::UpdateBit0(charPredictor[context], F_RUN_MC_TH0, F_RUN_MC_AR0); + ProbabilityCounter::UpdateBit0(staticPredictor[context], F_RUN_MP_TH0, F_RUN_MP_AR0); + runSize += runSize; if (bitRunSize <= 5) context += context; else context++; + } + } + + } + else + { + runHistory[currentChar] = (runHistory[currentChar] + 2) >> 2; + ProbabilityCounter::UpdateBit0(*statePredictor, F_RUN_TS_TH0, F_RUN_TS_AR0); + ProbabilityCounter::UpdateBit0(*charPredictor, F_RUN_TC_TH0, F_RUN_TC_AR0); + ProbabilityCounter::UpdateBit0(*staticPredictor, F_RUN_TP_TH0, F_RUN_TP_AR0); + } + + contextRank0 = ((contextRank0 << 1) | (rank == 0 ? 1 : 0)) & 0x7; + contextRank4 = ((contextRank4 << 2) | (rank < 3 ? rank : 3)) & 0xff; + contextRun = ((contextRun << 1) | (runSize < 3 ? 1 : 0)) & 0xf; + + for (; runSize > 0; --runSize) output[i++] = currentChar; + } + + return n; +} + +int bsc_qlfc_static_encode_block(const unsigned char * input, unsigned char * output, int inputSize, int outputSize) +{ + if (QlfcStatisticalModel * model = (QlfcStatisticalModel *)bsc_malloc(sizeof(QlfcStatisticalModel))) + { + if (unsigned char * buffer = (unsigned char *)bsc_malloc(inputSize * sizeof(unsigned char))) + { + int result = bsc_qlfc_static_encode(input, output, buffer, inputSize, outputSize, model); + + bsc_free(buffer); bsc_free(model); + + return result; + }; + bsc_free(model); + }; + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_qlfc_adaptive_encode_block(const unsigned char * input, unsigned char * output, int inputSize, int outputSize) +{ + if (QlfcStatisticalModel * model = (QlfcStatisticalModel *)bsc_malloc(sizeof(QlfcStatisticalModel))) + { + if (unsigned char * buffer = (unsigned char *)bsc_malloc(inputSize * sizeof(unsigned char))) + { + int result = bsc_qlfc_adaptive_encode(input, output, buffer, inputSize, outputSize, model); + + bsc_free(buffer); bsc_free(model); + + return result; + }; + bsc_free(model); + }; + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_qlfc_static_decode_block(const unsigned char * input, unsigned char * output) +{ + if (QlfcStatisticalModel * model = (QlfcStatisticalModel *)bsc_malloc(sizeof(QlfcStatisticalModel))) + { + int result = bsc_qlfc_static_decode(input, output, model); + + bsc_free(model); + + return result; + }; + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_qlfc_adaptive_decode_block(const unsigned char * input, unsigned char * output) +{ + if (QlfcStatisticalModel * model = (QlfcStatisticalModel *)bsc_malloc(sizeof(QlfcStatisticalModel))) + { + int result = bsc_qlfc_adaptive_decode(input, output, model); + + bsc_free(model); + + return result; + }; + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +/*-----------------------------------------------------------*/ +/* End qlfc.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/qlfc/qlfc.h b/bsc/libbsc/coder/qlfc/qlfc.h new file mode 100644 index 0000000..8b01ec2 --- /dev/null +++ b/bsc/libbsc/coder/qlfc/qlfc.h @@ -0,0 +1,93 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to Quantized Local Frequency Coding functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_QLFC_H +#define _LIBBSC_QLFC_H + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * You should call this function before you call any of the other functions in qlfc. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_qlfc_init(int features); + + /** + * Compress a memory block using Quantized Local Frequency Coding algorithm. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n bytes. + * @param inputSize - the length of the input memory block. + * @param outputSize - the length of the output memory block. + * @return the length of compressed memory block if no error occurred, error code otherwise. + */ + int bsc_qlfc_static_encode_block(const unsigned char * input, unsigned char * output, int inputSize, int outputSize); + + /** + * Decompress a memory block using Quantized Local Frequency Coding algorithm. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n bytes. + * @param inputSize - the length of the input memory block. + * @param outputSize - the length of the output memory block. + * @return the length of decompressed memory block if no error occurred, error code otherwise. + */ + int bsc_qlfc_adaptive_encode_block(const unsigned char * input, unsigned char * output, int inputSize, int outputSize); + + /** + * Compress a memory block using Quantized Local Frequency Coding algorithm. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n bytes. + * @return the length of compressed memory block if no error occurred, error code otherwise. + */ + int bsc_qlfc_static_decode_block(const unsigned char * input, unsigned char * output); + + /** + * Decompress a memory block using Quantized Local Frequency Coding algorithm. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n bytes. + * @return the length of decompressed memory block if no error occurred, error code otherwise. + */ + int bsc_qlfc_adaptive_decode_block(const unsigned char * input, unsigned char * output); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-----------------------------------------------------------*/ +/* End qlfc.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/qlfc/qlfc_model.cpp b/bsc/libbsc/coder/qlfc/qlfc_model.cpp new file mode 100644 index 0000000..11fe666 --- /dev/null +++ b/bsc/libbsc/coder/qlfc/qlfc_model.cpp @@ -0,0 +1,84 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Statistical data compression model for QLFC */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include + +#include "qlfc_model.h" + +#include "../../libbsc.h" +#include "../../platform/platform.h" + +QlfcStatisticalModel g_QlfcStatisticalModel; + +void bsc_qlfc_memset_2048(void * dst, int size) +{ + for (int i = 0; i < size / 2; ++i) ((short *)dst)[i] = 2048; +} + +int bsc_qlfc_init_static_model() +{ + for (int mixer = 0; mixer < ALPHABET_SIZE; ++mixer) + { + g_QlfcStatisticalModel.mixerOfRank[mixer].Init(); + g_QlfcStatisticalModel.mixerOfRankEscape[mixer].Init(); + g_QlfcStatisticalModel.mixerOfRun[mixer].Init(); + } + for (int bit = 0; bit < 8; ++bit) + { + g_QlfcStatisticalModel.mixerOfRankMantissa[bit].Init(); + for (int context = 0; context < 8; ++context) + g_QlfcStatisticalModel.mixerOfRankExponent[context][bit].Init(); + } + for (int bit = 0; bit < 32; ++bit) + { + g_QlfcStatisticalModel.mixerOfRunMantissa[bit].Init(); + for (int context = 0; context < 32; ++context) + g_QlfcStatisticalModel.mixerOfRunExponent[context][bit].Init(); + } + + bsc_qlfc_memset_2048(&g_QlfcStatisticalModel.Rank, sizeof(g_QlfcStatisticalModel.Rank)); + bsc_qlfc_memset_2048(&g_QlfcStatisticalModel.Run, sizeof(g_QlfcStatisticalModel.Run)); + + return LIBBSC_NO_ERROR; +} + +void bsc_qlfc_init_model(QlfcStatisticalModel * model) +{ + memcpy(model, &g_QlfcStatisticalModel, sizeof(QlfcStatisticalModel)); +} + +/*-----------------------------------------------------------*/ +/* End qlfc_model.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/coder/qlfc/qlfc_model.h b/bsc/libbsc/coder/qlfc/qlfc_model.h new file mode 100644 index 0000000..65a6c11 --- /dev/null +++ b/bsc/libbsc/coder/qlfc/qlfc_model.h @@ -0,0 +1,252 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Statistical data compression model for QLFC */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_QLFC_MODEL_H +#define _LIBBSC_QLFC_MODEL_H + +#include "../common/predictor.h" + +const int M_RANK_TS_TH0 = 1; const int M_RANK_TS_AR0 = 57; +const int M_RANK_TS_TH1 = -111; const int M_RANK_TS_AR1 = 31; +const int M_RANK_TC_TH0 = 291; const int M_RANK_TC_AR0 = 250; +const int M_RANK_TC_TH1 = 154; const int M_RANK_TC_AR1 = 528; +const int M_RANK_TP_TH0 = 375; const int M_RANK_TP_AR0 = 163; +const int M_RANK_TP_TH1 = 313; const int M_RANK_TP_AR1 = 639; +const int M_RANK_TM_TH0 = -41; const int M_RANK_TM_AR0 = 96; +const int M_RANK_TM_TH1 = 53; const int M_RANK_TM_AR1 = 49; +const int M_RANK_TM_LR0 = 20; const int M_RANK_TM_LR1 = 47; +const int M_RANK_TM_LR2 = 27; + +const int M_RANK_ES_TH0 = -137; const int M_RANK_ES_AR0 = 17; +const int M_RANK_ES_TH1 = 482; const int M_RANK_ES_AR1 = 40; +const int M_RANK_EC_TH0 = 61; const int M_RANK_EC_AR0 = 192; +const int M_RANK_EC_TH1 = 200; const int M_RANK_EC_AR1 = 133; +const int M_RANK_EP_TH0 = 54; const int M_RANK_EP_AR0 = 1342; +const int M_RANK_EP_TH1 = 578; const int M_RANK_EP_AR1 = 1067; +const int M_RANK_EM_TH0 = -11; const int M_RANK_EM_AR0 = 318; +const int M_RANK_EM_TH1 = 144; const int M_RANK_EM_AR1 = 848; +const int M_RANK_EM_LR0 = 49; const int M_RANK_EM_LR1 = 41; +const int M_RANK_EM_LR2 = 40; + +const int M_RANK_MS_TH0 = -145; const int M_RANK_MS_AR0 = 18; +const int M_RANK_MS_TH1 = 114; const int M_RANK_MS_AR1 = 24; +const int M_RANK_MC_TH0 = -43; const int M_RANK_MC_AR0 = 69; +const int M_RANK_MC_TH1 = -36; const int M_RANK_MC_AR1 = 78; +const int M_RANK_MP_TH0 = -2; const int M_RANK_MP_AR0 = 1119; +const int M_RANK_MP_TH1 = 11; const int M_RANK_MP_AR1 = 1181; +const int M_RANK_MM_TH0 = -203; const int M_RANK_MM_AR0 = 20; +const int M_RANK_MM_TH1 = -271; const int M_RANK_MM_AR1 = 15; +const int M_RANK_MM_LR0 = 263; const int M_RANK_MM_LR1 = 175; +const int M_RANK_MM_LR2 = 17; + +const int M_RANK_PS_TH0 = -99; const int M_RANK_PS_AR0 = 32; +const int M_RANK_PS_TH1 = 318; const int M_RANK_PS_AR1 = 42; +const int M_RANK_PC_TH0 = 17; const int M_RANK_PC_AR0 = 101; +const int M_RANK_PC_TH1 = 1116; const int M_RANK_PC_AR1 = 246; +const int M_RANK_PP_TH0 = 22; const int M_RANK_PP_AR0 = 964; +const int M_RANK_PP_TH1 = -2; const int M_RANK_PP_AR1 = 1110; +const int M_RANK_PM_TH0 = -194; const int M_RANK_PM_AR0 = 21; +const int M_RANK_PM_TH1 = -129; const int M_RANK_PM_AR1 = 20; +const int M_RANK_PM_LR0 = 480; const int M_RANK_PM_LR1 = 202; +const int M_RANK_PM_LR2 = 17; + +const int M_RUN_TS_TH0 = -93; const int M_RUN_TS_AR0 = 34; +const int M_RUN_TS_TH1 = -4; const int M_RUN_TS_AR1 = 51; +const int M_RUN_TC_TH0 = 139; const int M_RUN_TC_AR0 = 423; +const int M_RUN_TC_TH1 = 244; const int M_RUN_TC_AR1 = 162; +const int M_RUN_TP_TH0 = 275; const int M_RUN_TP_AR0 = 450; +const int M_RUN_TP_TH1 = -6; const int M_RUN_TP_AR1 = 579; +const int M_RUN_TM_TH0 = -68; const int M_RUN_TM_AR0 = 25; +const int M_RUN_TM_TH1 = 1; const int M_RUN_TM_AR1 = 64; +const int M_RUN_TM_LR0 = 15; const int M_RUN_TM_LR1 = 50; +const int M_RUN_TM_LR2 = 78; + +const int M_RUN_ES_TH0 = -116; const int M_RUN_ES_AR0 = 31; +const int M_RUN_ES_TH1 = 43; const int M_RUN_ES_AR1 = 45; +const int M_RUN_EC_TH0 = 165; const int M_RUN_EC_AR0 = 222; +const int M_RUN_EC_TH1 = 30; const int M_RUN_EC_AR1 = 324; +const int M_RUN_EP_TH0 = 315; const int M_RUN_EP_AR0 = 857; +const int M_RUN_EP_TH1 = 109; const int M_RUN_EP_AR1 = 867; +const int M_RUN_EM_TH0 = -14; const int M_RUN_EM_AR0 = 215; +const int M_RUN_EM_TH1 = 61; const int M_RUN_EM_AR1 = 73; +const int M_RUN_EM_LR0 = 35; const int M_RUN_EM_LR1 = 37; +const int M_RUN_EM_LR2 = 42; + +const int M_RUN_MS_TH0 = -176; const int M_RUN_MS_AR0 = 14; +const int M_RUN_MS_TH1 = -141; const int M_RUN_MS_AR1 = 21; +const int M_RUN_MC_TH0 = 84; const int M_RUN_MC_AR0 = 172; +const int M_RUN_MC_TH1 = 37; const int M_RUN_MC_AR1 = 263; +const int M_RUN_MP_TH0 = 2; const int M_RUN_MP_AR0 = 15; +const int M_RUN_MP_TH1 = -197; const int M_RUN_MP_AR1 = 20; +const int M_RUN_MM_TH0 = -27; const int M_RUN_MM_AR0 = 142; +const int M_RUN_MM_TH1 = -146; const int M_RUN_MM_AR1 = 27; +const int M_RUN_MM_LR0 = 51; const int M_RUN_MM_LR1 = 44; +const int M_RUN_MM_LR2 = 80; + +const int F_RANK_TS_TH0 = -116; const int F_RANK_TS_AR0 = 33; +const int F_RANK_TS_TH1 = -78; const int F_RANK_TS_AR1 = 34; +const int F_RANK_TC_TH0 = -2; const int F_RANK_TC_AR0 = 282; +const int F_RANK_TC_TH1 = 12; const int F_RANK_TC_AR1 = 274; +const int F_RANK_TP_TH0 = 4; const int F_RANK_TP_AR0 = 697; +const int F_RANK_TP_TH1 = 55; const int F_RANK_TP_AR1 = 1185; +const int F_RANK_TM_LR0 = 17; const int F_RANK_TM_LR1 = 14; +const int F_RANK_TM_LR2 = 1; + +const int F_RANK_ES_TH0 = -177; const int F_RANK_ES_AR0 = 23; +const int F_RANK_ES_TH1 = -370; const int F_RANK_ES_AR1 = 11; +const int F_RANK_EC_TH0 = -14; const int F_RANK_EC_AR0 = 271; +const int F_RANK_EC_TH1 = 3; const int F_RANK_EC_AR1 = 308; +const int F_RANK_EP_TH0 = -3; const int F_RANK_EP_AR0 = 788; +const int F_RANK_EP_TH1 = 135; const int F_RANK_EP_AR1 = 1364; +const int F_RANK_EM_LR0 = 22; const int F_RANK_EM_LR1 = 6; +const int F_RANK_EM_LR2 = 4; + +const int F_RANK_MS_TH0 = -254; const int F_RANK_MS_AR0 = 16; +const int F_RANK_MS_TH1 = -177; const int F_RANK_MS_AR1 = 20; +const int F_RANK_MC_TH0 = -55; const int F_RANK_MC_AR0 = 73; +const int F_RANK_MC_TH1 = -54; const int F_RANK_MC_AR1 = 74; +const int F_RANK_MP_TH0 = -6; const int F_RANK_MP_AR0 = 575; +const int F_RANK_MP_TH1 = 1670; const int F_RANK_MP_AR1 = 1173; +const int F_RANK_MM_LR0 = 15; const int F_RANK_MM_LR1 = 10; +const int F_RANK_MM_LR2 = 7; + +const int F_RANK_PS_TH0 = -126; const int F_RANK_PS_AR0 = 32; +const int F_RANK_PS_TH1 = -126; const int F_RANK_PS_AR1 = 32; +const int F_RANK_PC_TH0 = -33; const int F_RANK_PC_AR0 = 120; +const int F_RANK_PC_TH1 = -25; const int F_RANK_PC_AR1 = 157; +const int F_RANK_PP_TH0 = -6; const int F_RANK_PP_AR0 = 585; +const int F_RANK_PP_TH1 = 150; const int F_RANK_PP_AR1 = 275; +const int F_RANK_PM_LR0 = 16; const int F_RANK_PM_LR1 = 11; +const int F_RANK_PM_LR2 = 5; + +const int F_RUN_TS_TH0 = -68; const int F_RUN_TS_AR0 = 38; +const int F_RUN_TS_TH1 = -112; const int F_RUN_TS_AR1 = 36; +const int F_RUN_TC_TH0 = -4; const int F_RUN_TC_AR0 = 221; +const int F_RUN_TC_TH1 = -13; const int F_RUN_TC_AR1 = 231; +const int F_RUN_TP_TH0 = 0; const int F_RUN_TP_AR0 = 0; +const int F_RUN_TP_TH1 = 0; const int F_RUN_TP_AR1 = 0; +const int F_RUN_TM_LR0 = 14; const int F_RUN_TM_LR1 = 18; +const int F_RUN_TM_LR2 = 0; + +const int F_RUN_ES_TH0 = -90; const int F_RUN_ES_AR0 = 45; +const int F_RUN_ES_TH1 = -92; const int F_RUN_ES_AR1 = 44; +const int F_RUN_EC_TH0 = -3; const int F_RUN_EC_AR0 = 325; +const int F_RUN_EC_TH1 = -11; const int F_RUN_EC_AR1 = 341; +const int F_RUN_EP_TH0 = 24; const int F_RUN_EP_AR0 = 887; +const int F_RUN_EP_TH1 = -4; const int F_RUN_EP_AR1 = 765; +const int F_RUN_EM_LR0 = 14; const int F_RUN_EM_LR1 = 15; +const int F_RUN_EM_LR2 = 3; + +const int F_RUN_MS_TH0 = -275; const int F_RUN_MS_AR0 = 14; +const int F_RUN_MS_TH1 = -185; const int F_RUN_MS_AR1 = 22; +const int F_RUN_MC_TH0 = -18; const int F_RUN_MC_AR0 = 191; +const int F_RUN_MC_TH1 = -15; const int F_RUN_MC_AR1 = 241; +const int F_RUN_MP_TH0 = -73; const int F_RUN_MP_AR0 = 54; +const int F_RUN_MP_TH1 = -214; const int F_RUN_MP_AR1 = 19; +const int F_RUN_MM_LR0 = 7; const int F_RUN_MM_LR1 = 15; +const int F_RUN_MM_LR2 = 10; + +struct QlfcStatisticalModel +{ + +public: + + ProbabilityMixer mixerOfRank[ALPHABET_SIZE]; + ProbabilityMixer mixerOfRankExponent[8][8]; + ProbabilityMixer mixerOfRankMantissa[8]; + ProbabilityMixer mixerOfRankEscape[ALPHABET_SIZE]; + ProbabilityMixer mixerOfRun[ALPHABET_SIZE]; + ProbabilityMixer mixerOfRunExponent[32][32]; + ProbabilityMixer mixerOfRunMantissa[32]; + + struct Rank + { + short StaticModel; + short StateModel[ALPHABET_SIZE]; + short CharModel[ALPHABET_SIZE]; + + struct Exponent + { + short StaticModel[8]; + short StateModel[ALPHABET_SIZE][8]; + short CharModel[ALPHABET_SIZE][8]; + } Exponent; + + struct Mantissa + { + short StaticModel[ALPHABET_SIZE]; + short StateModel[ALPHABET_SIZE][ALPHABET_SIZE]; + short CharModel[ALPHABET_SIZE][ALPHABET_SIZE]; + } Mantissa[8]; + + struct Escape + { + short StaticModel[ALPHABET_SIZE]; + short StateModel[ALPHABET_SIZE][ALPHABET_SIZE]; + short CharModel[ALPHABET_SIZE][ALPHABET_SIZE]; + } Escape; + + } Rank; + + struct Run + { + short StaticModel; + short StateModel[ALPHABET_SIZE]; + short CharModel[ALPHABET_SIZE]; + + struct Exponent + { + short StaticModel[32]; + short StateModel[ALPHABET_SIZE][32]; + short CharModel[ALPHABET_SIZE][32]; + } Exponent; + + struct Mantissa + { + short StaticModel[32]; + short StateModel[ALPHABET_SIZE][32]; + short CharModel[ALPHABET_SIZE][32]; + } Mantissa[32]; + + } Run; +}; + +int bsc_qlfc_init_static_model(); +void bsc_qlfc_init_model(QlfcStatisticalModel * model); + +#endif + +/*-----------------------------------------------------------*/ +/* End qlfc_model.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/filters.h b/bsc/libbsc/filters.h new file mode 100644 index 0000000..766a9df --- /dev/null +++ b/bsc/libbsc/filters.h @@ -0,0 +1,111 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to data preprocessing filters */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_FILTERS_H +#define _LIBBSC_FILTERS_H + +#define LIBBSC_CONTEXTS_FOLLOWING 1 +#define LIBBSC_CONTEXTS_PRECEDING 2 + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Autodetects segments for better compression of heterogeneous files. + * @param input - the input memory block of n bytes. + * @param n - the length of the input memory block. + * @param segments - the output array of segments of k elements size. + * @param k - the size of the output segments array. + * @param features - the set of additional features. + * @return The number of segments if no error occurred, error code otherwise. + */ + int bsc_detect_segments(const unsigned char * input, int n, int * segments, int k, int features); + + /** + * Autodetects order of contexts for better compression of binary files. + * @param input - the input memory block of n bytes. + * @param n - the length of the input memory block. + * @param features - the set of additional features. + * @return The detected contexts order if no error occurred, error code otherwise. + */ + int bsc_detect_contextsorder(const unsigned char * input, int n, int features); + + /** + * Reverses memory block to change order of contexts. + * @param T - the input/output memory block of n bytes. + * @param n - the length of the memory block. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_reverse_block(unsigned char * T, int n, int features); + + /** + * Autodetects record size for better compression of multimedia files. + * @param input - the input memory block of n bytes. + * @param n - the length of the input memory block. + * @param features - the set of additional features. + * @return The size of record if no error occurred, error code otherwise. + */ + int bsc_detect_recordsize(const unsigned char * input, int n, int features); + + /** + * Reorders memory block for specific size of record (Forward transform). + * @param T - the input/output memory block of n bytes. + * @param n - the length of the memory block. + * @param recordSize - the size of record. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_reorder_forward(unsigned char * T, int n, int recordSize, int features); + + /** + * Reorders memory block for specific size of record (Reverse transform). + * @param T - the input/output memory block of n bytes. + * @param n - the length of the memory block. + * @param recordSize - the size of record. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_reorder_reverse(unsigned char * T, int n, int recordSize, int features); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------*/ +/* End filters.h */ +/*-------------------------------------------------*/ diff --git a/bsc/libbsc/filters/detectors.cpp b/bsc/libbsc/filters/detectors.cpp new file mode 100644 index 0000000..289a083 --- /dev/null +++ b/bsc/libbsc/filters/detectors.cpp @@ -0,0 +1,587 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Detectors of blocksize, recordsize and contexts reorder. */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include + +#include "../filters.h" + +#include "../platform/platform.h" +#include "../libbsc.h" + +#include "tables.h" + +#define DETECTORS_MAX_RECORD_SIZE 4 +#define DETECTORS_NUM_BLOCKS 48 +#define DETECTORS_BLOCK_SIZE 24576 + +struct BscSegmentationModel +{ + struct + { + int left, right; + } contextsCount[ALPHABET_SIZE]; + struct + { + struct + { + int left, right; + } Frequencies[ALPHABET_SIZE]; + } contexts[ALPHABET_SIZE]; +}; + +struct BscReorderingModel +{ + struct + { + int frequencies[ALPHABET_SIZE]; + } contexts[DETECTORS_MAX_RECORD_SIZE][ALPHABET_SIZE]; +}; + +int bsc_detect_segments_serial(BscSegmentationModel * RESTRICT model, const unsigned char * RESTRICT input, int n) +{ + memset(model, 0, sizeof(BscSegmentationModel)); + + for (int context = 0, i = 0; i < n; ++i) + { + unsigned char symbol = input[i]; + model->contexts[context].Frequencies[symbol].right++; + context = (unsigned char)((context << 5) ^ symbol); + } + + long long entropy = 0; + for (int context = 0; context < ALPHABET_SIZE; ++context) + { + int count = 0; + for (int symbol = 0; symbol < ALPHABET_SIZE; ++symbol) + { + int frequency = model->contexts[context].Frequencies[symbol].right; + count += frequency; entropy -= bsc_entropy(frequency); + } + model->contextsCount[context].right = count; entropy += bsc_entropy(count); + } + + int blockSize = n; + + long long localEntropy = entropy, bestEntropy = entropy - (entropy >> 5) - (65536LL * 12 * 1024); + for (int context = 0, i = 0; i < n; ++i) + { + if (localEntropy < bestEntropy) + { + bestEntropy = localEntropy; + blockSize = i; + } + + unsigned char symbol = input[i]; + + localEntropy += bsc_delta(--model->contexts[context].Frequencies[symbol].right); + localEntropy -= bsc_delta(model->contexts[context].Frequencies[symbol].left++); + localEntropy -= bsc_delta(--model->contextsCount[context].right); + localEntropy += bsc_delta(model->contextsCount[context].left++); + + context = (unsigned char)((context << 5) ^ symbol); + } + + return blockSize; +} + +#ifdef LIBBSC_OPENMP + +int bsc_detect_segments_parallel(BscSegmentationModel * RESTRICT model0, BscSegmentationModel * RESTRICT model1, const unsigned char * RESTRICT input, int n) +{ + int globalBlockSize = n; long long globalEntropy, globalBestEntropy; + + #pragma omp parallel num_threads(2) + { + int nThreads = omp_get_num_threads(); + int threadId = omp_get_thread_num(); + + if (nThreads == 1) + { + globalBlockSize = bsc_detect_segments_serial(model0, input, n); + } + else + { + int median = n / 2; + + { + if (threadId == 0) + { + memset(model0, 0, sizeof(BscSegmentationModel)); + + int context = 0; + for (int i = 0; i < median; ++i) + { + unsigned char symbol = input[i]; + model0->contexts[context].Frequencies[symbol].right++; + context = (unsigned char)((context << 5) ^ symbol); + } + } + else + { + memset(model1, 0, sizeof(BscSegmentationModel)); + + int context = (unsigned char)((input[median - 2] << 5) ^ input[median - 1]); + for (int i = median; i < n; ++i) + { + unsigned char symbol = input[i]; + model1->contexts[context].Frequencies[symbol].left++; + context = (unsigned char)((context << 5) ^ symbol); + } + } + + #pragma omp barrier + } + + { + #pragma omp single + { + long long entropy = 0; + for (int context = 0; context < ALPHABET_SIZE; ++context) + { + int count = 0; + for (int symbol = 0; symbol < ALPHABET_SIZE; ++symbol) + { + int frequency = model0->contexts[context].Frequencies[symbol].right + model1->contexts[context].Frequencies[symbol].left; + model0->contexts[context].Frequencies[symbol].right = model1->contexts[context].Frequencies[symbol].left = frequency; + + count += frequency; entropy -= bsc_entropy(frequency); + } + model0->contextsCount[context].right = model1->contextsCount[context].left = count; entropy += bsc_entropy(count); + } + + globalEntropy = entropy; globalBestEntropy = entropy - (entropy >> 5) - (65536LL * 12 * 1024); + } + } + + { + int localBlockSize = n; long long localBestEntropy = globalEntropy - (globalEntropy >> 5) - (65536LL * 12 * 1024); + + if (threadId == 0) + { + long long localEntropy = globalEntropy; + for (int context = 0, i = 0; i < median; ++i) + { + if (localEntropy < localBestEntropy) + { + localBestEntropy = localEntropy; + localBlockSize = i; + } + + unsigned char symbol = input[i]; + + localEntropy += bsc_delta(--model0->contexts[context].Frequencies[symbol].right); + localEntropy -= bsc_delta(model0->contexts[context].Frequencies[symbol].left++); + localEntropy -= bsc_delta(--model0->contextsCount[context].right); + localEntropy += bsc_delta(model0->contextsCount[context].left++); + + context = (unsigned char)((context << 5) ^ symbol); + } + } + else + { + long long localEntropy = globalEntropy; + for (int i = n - 1; i >= median; --i) + { + unsigned char symbol = input[i]; + int context = (unsigned char)((input[i - 2] << 5) ^ input[i - 1]); + + localEntropy -= bsc_delta(model1->contexts[context].Frequencies[symbol].right++); + localEntropy += bsc_delta(--model1->contexts[context].Frequencies[symbol].left); + localEntropy += bsc_delta(model1->contextsCount[context].right++); + localEntropy -= bsc_delta(--model1->contextsCount[context].left); + + if (localEntropy <= localBestEntropy) + { + localBestEntropy = localEntropy; + localBlockSize = i; + } + } + } + + if (globalBestEntropy > localBestEntropy) + { + #pragma omp critical + { + if (globalBestEntropy > localBestEntropy) + { + globalBlockSize = localBlockSize; globalBestEntropy = localBestEntropy; + } + } + } + } + } + } + + return globalBlockSize; +} + + +#endif + +int bsc_detect_segments_recursive(BscSegmentationModel * model0, BscSegmentationModel * model1, const unsigned char * input, int n, int * segments, int k, int features) +{ + if (n < DETECTORS_BLOCK_SIZE || k == 1) + { + segments[0] = n; + return 1; + } + + int blockSize = n; + +#ifdef LIBBSC_OPENMP + + if (features & LIBBSC_FEATURE_MULTITHREADING) + { + blockSize = bsc_detect_segments_parallel(model0, model1, input, n); + } + else + +#endif + + { + blockSize = bsc_detect_segments_serial(model0, input, n); + } + + if (blockSize == n) + { + segments[0] = n; + return 1; + } + + int leftResult = bsc_detect_segments_recursive(model0, model1, input, blockSize, segments, k - 1, features); + if (leftResult < LIBBSC_NO_ERROR) return leftResult; + + int rightResult = bsc_detect_segments_recursive(model0, model1, input + blockSize, n - blockSize, segments + leftResult, k - leftResult, features); + if (rightResult < LIBBSC_NO_ERROR) return rightResult; + + return leftResult + rightResult; +} + +int bsc_detect_segments(const unsigned char * input, int n, int * segments, int k, int features) +{ + if (n < DETECTORS_BLOCK_SIZE || k == 1) + { + segments[0] = n; + return 1; + } + + if (BscSegmentationModel * model0 = (BscSegmentationModel *)bsc_malloc(sizeof(BscSegmentationModel))) + { + if (BscSegmentationModel * model1 = (BscSegmentationModel *)bsc_malloc(sizeof(BscSegmentationModel))) + { + int result = bsc_detect_segments_recursive(model0, model1, input, n, segments, k, features); + + bsc_free(model1); bsc_free(model0); + + return result; + } + bsc_free(model0); + }; + + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +static long long bsc_estimate_contextsorder(const unsigned char * input, int n) +{ + int frequencies[ALPHABET_SIZE][3]; + + memset(frequencies, 0, sizeof(frequencies)); + + unsigned char MTF0 = 0; + unsigned char MTF1 = 1; + unsigned char MTFC = 0; + + for (int i = 0; i < n; ++i) + { + unsigned char C = input[i]; + if (C == MTF0) + { + frequencies[MTFC][0]++; MTFC = MTFC << 2; + } + else + { + if (C == MTF1) + { + frequencies[MTFC][1]++; MTFC = (MTFC << 2) | 1; + } + else + { + frequencies[MTFC][2]++; MTFC = (MTFC << 2) | 2; + } + MTF1 = MTF0; MTF0 = C; + } + } + + long long entropy = 0; + for (int context = 0; context < ALPHABET_SIZE; ++context) + { + int count = 0; + for (int rank = 0; rank < 3; ++rank) + { + count += frequencies[context][rank]; + entropy -= bsc_entropy(frequencies[context][rank]); + } + entropy += bsc_entropy(count); + } + + return entropy; +} + +int bsc_detect_contextsorder(const unsigned char * RESTRICT input, int n, int features) +{ + int sortingContexts = LIBBSC_NOT_ENOUGH_MEMORY; + + if ((n > DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE) && (features & LIBBSC_FEATURE_FASTMODE)) + { + if (unsigned char * buffer = (unsigned char *)bsc_malloc(DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE * sizeof(unsigned char))) + { + int blockStride = (((n - DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE) / DETECTORS_NUM_BLOCKS) / 48) * 48; + + for (int block = 0; block < DETECTORS_NUM_BLOCKS; ++block) + { + memcpy(buffer + block * DETECTORS_BLOCK_SIZE, input + block * (DETECTORS_BLOCK_SIZE + blockStride), DETECTORS_BLOCK_SIZE); + } + + sortingContexts = bsc_detect_contextsorder(buffer, DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE, features); + + bsc_free(buffer); + } + + return sortingContexts; + } + + if (unsigned char * RESTRICT buffer = (unsigned char *)bsc_malloc(n * sizeof(unsigned char))) + { + if (int * RESTRICT bucket0 = (int *)bsc_zero_malloc(ALPHABET_SIZE * ALPHABET_SIZE * sizeof(int))) + { + if (int * RESTRICT bucket1 = (int *)bsc_zero_malloc(ALPHABET_SIZE * ALPHABET_SIZE * sizeof(int))) + { + unsigned char C0 = input[n - 1]; + for (int i = 0; i < n; ++i) + { + unsigned char C1 = input[i]; + bucket0[(C0 << 8) | C1]++; + bucket1[(C1 << 8) | C0]++; + C0 = C1; + } + + for (int sum = 0, i = 0; i < ALPHABET_SIZE * ALPHABET_SIZE; ++i) + { + int tmp = sum; sum += bucket0[i]; bucket0[i] = tmp; + } + + unsigned char F0 = input[n - 2]; + unsigned char F1 = input[n - 1]; + for (int i = 0; i < n; ++i) + { + unsigned char F2 = input[i]; + buffer[bucket0[(F1 << 8) | F2]++] = F0; + F0 = F1; F1 = F2; + } + + long long following = bsc_estimate_contextsorder(buffer, n); + + for (int sum = 0, i = 0; i < ALPHABET_SIZE * ALPHABET_SIZE; ++i) + { + int tmp = sum; sum += bucket1[i]; bucket1[i] = tmp; + } + + unsigned char P0 = input[1]; + unsigned char P1 = input[0]; + for (int i = n - 1; i >= 0; --i) + { + unsigned char P2 = input[i]; + buffer[bucket1[(P1 << 8) | P2]++] = P0; + P0 = P1; P1 = P2; + } + + long long preceding = bsc_estimate_contextsorder(buffer, n); + + sortingContexts = (preceding < following) ? LIBBSC_CONTEXTS_PRECEDING : LIBBSC_CONTEXTS_FOLLOWING; + + bsc_free(bucket1); + } + bsc_free(bucket0); + }; + bsc_free(buffer); + } + + return sortingContexts; +} + +long long bsc_estimate_reordering(BscReorderingModel * model, int recordSize) +{ + long long entropy = 0; + for (int record = 0; record < recordSize; ++record) + { + for (int context = 0; context < ALPHABET_SIZE; ++context) + { + int count = 0; + for (int symbol = 0; symbol < ALPHABET_SIZE; ++symbol) + { + int frequency = model->contexts[record][context].frequencies[symbol]; + count += frequency; entropy -= bsc_entropy(frequency); + } + entropy += (65536LL * 8 * (count < 256 ? count : 256)) + bsc_entropy(count); + } + } + return entropy; +} + +int bsc_detect_recordsize(const unsigned char * RESTRICT input, int n, int features) +{ + int result = LIBBSC_NOT_ENOUGH_MEMORY; + + if ((n > DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE) && (features & LIBBSC_FEATURE_FASTMODE)) + { + if (unsigned char * buffer = (unsigned char *)bsc_malloc(DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE * sizeof(unsigned char))) + { + int blockStride = (((n - DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE) / DETECTORS_NUM_BLOCKS) / 48) * 48; + + for (int block = 0; block < DETECTORS_NUM_BLOCKS; ++block) + { + memcpy(buffer + block * DETECTORS_BLOCK_SIZE, input + block * (DETECTORS_BLOCK_SIZE + blockStride), DETECTORS_BLOCK_SIZE); + } + + result = bsc_detect_recordsize(buffer, DETECTORS_NUM_BLOCKS * DETECTORS_BLOCK_SIZE, features); + + bsc_free(buffer); + } + + return result; + } + + if (BscReorderingModel * RESTRICT model = (BscReorderingModel *)bsc_malloc(sizeof(BscReorderingModel))) + { + long long Entropy[DETECTORS_MAX_RECORD_SIZE]; + + if ((n % 48) != 0) n = n - (n % 48); + + for (int recordSize = 1; recordSize <= DETECTORS_MAX_RECORD_SIZE; ++recordSize) + { + memset(model, 0, sizeof(BscReorderingModel)); + + if (recordSize == 1) + { + int ctx0 = 0; + for (int i = 0; i < n; i += 8) + { + unsigned char c0 = input[i + 0]; model->contexts[0][ctx0].frequencies[c0]++; ctx0 = c0; + unsigned char c1 = input[i + 1]; model->contexts[0][ctx0].frequencies[c1]++; ctx0 = c1; + unsigned char c2 = input[i + 2]; model->contexts[0][ctx0].frequencies[c2]++; ctx0 = c2; + unsigned char c3 = input[i + 3]; model->contexts[0][ctx0].frequencies[c3]++; ctx0 = c3; + unsigned char c4 = input[i + 4]; model->contexts[0][ctx0].frequencies[c4]++; ctx0 = c4; + unsigned char c5 = input[i + 5]; model->contexts[0][ctx0].frequencies[c5]++; ctx0 = c5; + unsigned char c6 = input[i + 6]; model->contexts[0][ctx0].frequencies[c6]++; ctx0 = c6; + unsigned char c7 = input[i + 7]; model->contexts[0][ctx0].frequencies[c7]++; ctx0 = c7; + } + } + + if (recordSize == 2) + { + int ctx0 = 0, ctx1 = 0; + for (int i = 0; i < n; i += 8) + { + unsigned char c0 = input[i + 0]; model->contexts[0][ctx0].frequencies[c0]++; ctx0 = c0; + unsigned char c1 = input[i + 1]; model->contexts[1][ctx1].frequencies[c1]++; ctx1 = c1; + unsigned char c2 = input[i + 2]; model->contexts[0][ctx0].frequencies[c2]++; ctx0 = c2; + unsigned char c3 = input[i + 3]; model->contexts[1][ctx1].frequencies[c3]++; ctx1 = c3; + unsigned char c4 = input[i + 4]; model->contexts[0][ctx0].frequencies[c4]++; ctx0 = c4; + unsigned char c5 = input[i + 5]; model->contexts[1][ctx1].frequencies[c5]++; ctx1 = c5; + unsigned char c6 = input[i + 6]; model->contexts[0][ctx0].frequencies[c6]++; ctx0 = c6; + unsigned char c7 = input[i + 7]; model->contexts[1][ctx1].frequencies[c7]++; ctx1 = c7; + } + } + + if (recordSize == 3) + { + int ctx0 = 0, ctx1 = 0, ctx2 = 0; + for (int i = 0; i < n; i += 6) + { + unsigned char c0 = input[i + 0]; model->contexts[0][ctx0].frequencies[c0]++; ctx0 = c0; + unsigned char c1 = input[i + 1]; model->contexts[1][ctx1].frequencies[c1]++; ctx1 = c1; + unsigned char c2 = input[i + 2]; model->contexts[2][ctx2].frequencies[c2]++; ctx2 = c2; + unsigned char c3 = input[i + 3]; model->contexts[0][ctx0].frequencies[c3]++; ctx0 = c3; + unsigned char c4 = input[i + 4]; model->contexts[1][ctx1].frequencies[c4]++; ctx1 = c4; + unsigned char c5 = input[i + 5]; model->contexts[2][ctx2].frequencies[c5]++; ctx2 = c5; + } + } + + if (recordSize == 4) + { + int ctx0 = 0, ctx1 = 0, ctx2 = 0, ctx3 = 0; + for (int i = 0; i < n; i += 8) + { + unsigned char c0 = input[i + 0]; model->contexts[0][ctx0].frequencies[c0]++; ctx0 = c0; + unsigned char c1 = input[i + 1]; model->contexts[1][ctx1].frequencies[c1]++; ctx1 = c1; + unsigned char c2 = input[i + 2]; model->contexts[2][ctx2].frequencies[c2]++; ctx2 = c2; + unsigned char c3 = input[i + 3]; model->contexts[3][ctx3].frequencies[c3]++; ctx3 = c3; + unsigned char c4 = input[i + 4]; model->contexts[0][ctx0].frequencies[c4]++; ctx0 = c4; + unsigned char c5 = input[i + 5]; model->contexts[1][ctx1].frequencies[c5]++; ctx1 = c5; + unsigned char c6 = input[i + 6]; model->contexts[2][ctx2].frequencies[c6]++; ctx2 = c6; + unsigned char c7 = input[i + 7]; model->contexts[3][ctx3].frequencies[c7]++; ctx3 = c7; + } + } + + if (recordSize > 4) + { + int Context[DETECTORS_MAX_RECORD_SIZE] = { 0 }; + for (int record = 0, i = 0; i < n; ++i) + { + model->contexts[record][Context[record]].frequencies[input[i]]++; + Context[record] = input[i]; record++; if (record == recordSize) record = 0; + } + } + + Entropy[recordSize - 1] = bsc_estimate_reordering(model, recordSize); + } + + long long bestSize = Entropy[0] - (Entropy[0] >> 4) - (65536LL * 8 * 1024); + + result = 1; + for (int recordSize = 1; recordSize <= DETECTORS_MAX_RECORD_SIZE; ++recordSize) + { + if (bestSize > Entropy[recordSize - 1]) { bestSize = Entropy[recordSize - 1]; result = recordSize; } + } + + bsc_free(model); + }; + + return result; +} + +/*-------------------------------------------------*/ +/* End detectors.cpp */ +/*-------------------------------------------------*/ diff --git a/bsc/libbsc/filters/preprocessing.cpp b/bsc/libbsc/filters/preprocessing.cpp new file mode 100644 index 0000000..9989fde --- /dev/null +++ b/bsc/libbsc/filters/preprocessing.cpp @@ -0,0 +1,182 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Data preprocessing functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include + +#include "../filters.h" + +#include "../platform/platform.h" +#include "../libbsc.h" + +int bsc_reverse_block(unsigned char * T, int n, int features) +{ + +#ifdef LIBBSC_OPENMP + + if (features & LIBBSC_FEATURE_MULTITHREADING) + { + #pragma omp parallel for + for (int i = 0; i < n / 2; ++i) + { + unsigned char tmp = T[i]; T[i] = T[n - 1 - i]; T[n - 1 - i] = tmp; + } + } + else + +#endif + + { + for (int i = 0, j = n - 1; i < j; ++i, --j) + { + unsigned char tmp = T[i]; T[i] = T[j]; T[j] = tmp; + } + } + + return LIBBSC_NO_ERROR; +} + +int bsc_reorder_forward(unsigned char * T, int n, int recordSize, int features) +{ + if (recordSize <= 0) return LIBBSC_BAD_PARAMETER; + if (recordSize == 1) return LIBBSC_NO_ERROR; + + if (unsigned char * buffer = (unsigned char *)bsc_malloc(n)) + { + memcpy(buffer, T, n); + + unsigned char * RESTRICT S = buffer; + unsigned char * RESTRICT D = T; + + int chunk = (n / recordSize); + +#ifdef LIBBSC_OPENMP + + if (features & LIBBSC_FEATURE_MULTITHREADING) + { + switch (recordSize) + { + case 2: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { D[i] = S[2 * i]; D[chunk + i] = S[2 * i + 1]; } break; + case 3: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { D[i] = S[3 * i]; D[chunk + i] = S[3 * i + 1]; D[chunk * 2 + i] = S[3 * i + 2]; } break; + case 4: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { D[i] = S[4 * i]; D[chunk + i] = S[4 * i + 1]; D[chunk * 2 + i] = S[4 * i + 2]; D[chunk * 3 + i] = S[4 * i + 3]; } break; + default: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { for (int j = 0; j < recordSize; ++j) D[j * chunk + i] = S[recordSize * i + j]; } + } + } + else + +#endif + + { + switch (recordSize) + { + case 2: for (int i = 0; i < chunk; ++i) { D[0] = S[0]; D[chunk] = S[1]; D++; S += 2; } break; + case 3: for (int i = 0; i < chunk; ++i) { D[0] = S[0]; D[chunk] = S[1]; D[chunk * 2] = S[2]; D++; S += 3; } break; + case 4: for (int i = 0; i < chunk; ++i) { D[0] = S[0]; D[chunk] = S[1]; D[chunk * 2] = S[2]; D[chunk * 3] = S[3]; D++; S += 4; } break; + default: + for (int i = 0; i < chunk; ++i) { for (int j = 0; j < recordSize; ++j) D[j * chunk] = S[j]; D++; S += recordSize; } + } + } + + bsc_free(buffer); return LIBBSC_NO_ERROR; + } + + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_reorder_reverse(unsigned char * T, int n, int recordSize, int features) +{ + if (recordSize <= 0) return LIBBSC_BAD_PARAMETER; + if (recordSize == 1) return LIBBSC_NO_ERROR; + + if (unsigned char * buffer = (unsigned char *)bsc_malloc(n)) + { + memcpy(buffer, T, n); + + unsigned char * RESTRICT S = buffer; + unsigned char * RESTRICT D = T; + + int chunk = (n / recordSize); + +#ifdef LIBBSC_OPENMP + + if (features & LIBBSC_FEATURE_MULTITHREADING) + { + switch (recordSize) + { + case 2: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { D[2 * i] = S[i]; D[2 * i + 1] = S[chunk + i]; } break; + case 3: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { D[3 * i] = S[i]; D[3 * i + 1] = S[chunk + i]; D[3 * i + 2] = S[chunk * 2 + i]; } break; + case 4: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { D[4 * i] = S[i]; D[4 * i + 1] = S[chunk + i]; D[4 * i + 2] = S[chunk * 2 + i]; D[4 * i + 3] = S[chunk * 3 + i]; } break; + default: + #pragma omp parallel for + for (int i = 0; i < chunk; ++i) { for (int j = 0; j < recordSize; ++j) D[recordSize * i + j] = S[j * chunk + i]; } + } + } + else + +#endif + + { + switch (recordSize) + { + case 2: for (int i = 0; i < chunk; ++i) { D[0] = S[0]; D[1] = S[chunk]; D += 2; S++; } break; + case 3: for (int i = 0; i < chunk; ++i) { D[0] = S[0]; D[1] = S[chunk]; D[2] = S[chunk * 2]; D += 3; S++; } break; + case 4: for (int i = 0; i < chunk; ++i) { D[0] = S[0]; D[1] = S[chunk]; D[2] = S[chunk * 2]; D[3] = S[chunk * 3]; D += 4; S++; } break; + default: + for (int i = 0; i < chunk; ++i) { for (int j = 0; j < recordSize; ++j) D[j] = S[j * chunk]; D += recordSize; S++; } + } + } + + bsc_free(buffer); return LIBBSC_NO_ERROR; + } + + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +/*-------------------------------------------------*/ +/* End preprocessing.cpp */ +/*-------------------------------------------------*/ diff --git a/bsc/libbsc/filters/tables.h b/bsc/libbsc/filters/tables.h new file mode 100644 index 0000000..c4bc2bb --- /dev/null +++ b/bsc/libbsc/filters/tables.h @@ -0,0 +1,756 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Static tables of constant values */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_FILTERS_TABLES_H +#define _LIBBSC_FILTERS_TABLES_H + +#include "../platform/platform.h" + +static const unsigned int bsc_code_table[4096] = +{ + 0, 0, 65536, 103872, 131072, 152169, 169408, 183982, 196608, 207744, 217705, 226717, + 234944, 242512, 249518, 256041, 262144, 267875, 273280, 278392, 283241, 287854, 292253, 296456, + 300480, 304339, 308048, 311616, 315054, 318372, 321577, 324678, 327680, 330589, 333411, 336152, + 338816, 341406, 343928, 346384, 348777, 351112, 353390, 355615, 357789, 359914, 361992, 364025, + 366016, 367965, 369875, 371748, 373584, 375384, 377152, 378887, 380590, 382264, 383908, 385524, + 387113, 388676, 390214, 391727, 393216, 394681, 396125, 397547, 398947, 400328, 401688, 403029, + 404352, 405656, 406942, 408211, 409464, 410700, 411920, 413124, 414313, 415488, 416648, 417794, + 418926, 420045, 421151, 422244, 423325, 424393, 425450, 426494, 427528, 428550, 429561, 430562, + 431552, 432531, 433501, 434461, 435411, 436352, 437284, 438206, 439120, 440024, 440920, 441808, + 442688, 443559, 444423, 445278, 446126, 446967, 447800, 448626, 449444, 450256, 451060, 451858, + 452649, 453434, 454212, 454984, 455750, 456509, 457263, 458010, 458752, 459487, 460217, 460942, + 461661, 462374, 463083, 463786, 464483, 465176, 465864, 466546, 467224, 467897, 468565, 469229, + 469888, 470542, 471192, 471837, 472478, 473115, 473747, 474376, 475000, 475620, 476236, 476848, + 477456, 478060, 478660, 479257, 479849, 480438, 481024, 481606, 482184, 482759, 483330, 483898, + 484462, 485024, 485581, 486136, 486687, 487235, 487780, 488322, 488861, 489396, 489929, 490459, + 490986, 491509, 492030, 492548, 493064, 493576, 494086, 494593, 495097, 495599, 496098, 496594, + 497088, 497579, 498067, 498553, 499037, 499518, 499997, 500473, 500947, 501419, 501888, 502355, + 502820, 503282, 503742, 504200, 504656, 505109, 505560, 506009, 506456, 506901, 507344, 507785, + 508224, 508661, 509095, 509528, 509959, 510387, 510814, 511239, 511662, 512083, 512503, 512920, + 513336, 513750, 514162, 514572, 514980, 515387, 515792, 516195, 516596, 516996, 517394, 517791, + 518185, 518579, 518970, 519360, 519748, 520135, 520520, 520904, 521286, 521666, 522045, 522423, + 522799, 523173, 523546, 523917, 524288, 524656, 525023, 525389, 525753, 526116, 526478, 526838, + 527197, 527554, 527910, 528265, 528619, 528971, 529322, 529671, 530019, 530366, 530712, 531057, + 531400, 531742, 532082, 532422, 532760, 533097, 533433, 533768, 534101, 534434, 534765, 535095, + 535424, 535751, 536078, 536403, 536728, 537051, 537373, 537694, 538014, 538333, 538651, 538968, + 539283, 539598, 539912, 540224, 540536, 540846, 541156, 541464, 541772, 542078, 542384, 542688, + 542992, 543294, 543596, 543896, 544196, 544495, 544793, 545089, 545385, 545680, 545974, 546268, + 546560, 546851, 547142, 547431, 547720, 548008, 548295, 548581, 548866, 549150, 549434, 549717, + 549998, 550279, 550560, 550839, 551117, 551395, 551672, 551948, 552223, 552498, 552771, 553044, + 553316, 553588, 553858, 554128, 554397, 554665, 554932, 555199, 555465, 555730, 555995, 556259, + 556522, 556784, 557045, 557306, 557566, 557826, 558084, 558342, 558600, 558856, 559112, 559367, + 559622, 559876, 560129, 560381, 560633, 560884, 561135, 561384, 561634, 561882, 562130, 562377, + 562624, 562870, 563115, 563359, 563603, 563847, 564089, 564332, 564573, 564814, 565054, 565294, + 565533, 565771, 566009, 566247, 566483, 566719, 566955, 567190, 567424, 567658, 567891, 568124, + 568356, 568587, 568818, 569048, 569278, 569507, 569736, 569964, 570192, 570419, 570645, 570871, + 571096, 571321, 571545, 571769, 571992, 572215, 572437, 572659, 572880, 573101, 573321, 573541, + 573760, 573978, 574197, 574414, 574631, 574848, 575064, 575280, 575495, 575709, 575923, 576137, + 576350, 576563, 576775, 576987, 577198, 577409, 577619, 577829, 578039, 578248, 578456, 578664, + 578872, 579079, 579286, 579492, 579698, 579903, 580108, 580312, 580516, 580720, 580923, 581125, + 581328, 581530, 581731, 581932, 582132, 582332, 582532, 582731, 582930, 583129, 583327, 583524, + 583721, 583918, 584115, 584311, 584506, 584701, 584896, 585090, 585284, 585478, 585671, 585864, + 586056, 586248, 586440, 586631, 586822, 587012, 587202, 587392, 587581, 587770, 587959, 588147, + 588335, 588522, 588709, 588896, 589082, 589268, 589453, 589639, 589824, 590008, 590192, 590376, + 590559, 590742, 590925, 591107, 591289, 591471, 591652, 591833, 592014, 592194, 592374, 592554, + 592733, 592912, 593090, 593269, 593446, 593624, 593801, 593978, 594155, 594331, 594507, 594682, + 594858, 595033, 595207, 595382, 595555, 595729, 595902, 596075, 596248, 596421, 596593, 596764, + 596936, 597107, 597278, 597448, 597618, 597788, 597958, 598127, 598296, 598465, 598633, 598801, + 598969, 599137, 599304, 599471, 599637, 599804, 599970, 600135, 600301, 600466, 600631, 600795, + 600960, 601124, 601287, 601451, 601614, 601777, 601939, 602102, 602264, 602426, 602587, 602748, + 602909, 603070, 603230, 603390, 603550, 603710, 603869, 604028, 604187, 604345, 604504, 604662, + 604819, 604977, 605134, 605291, 605448, 605604, 605760, 605916, 606072, 606227, 606382, 606537, + 606692, 606846, 607000, 607154, 607308, 607461, 607614, 607767, 607920, 608072, 608224, 608376, + 608528, 608679, 608830, 608981, 609132, 609282, 609432, 609582, 609732, 609882, 610031, 610180, + 610329, 610477, 610625, 610774, 610921, 611069, 611216, 611364, 611510, 611657, 611804, 611950, + 612096, 612242, 612387, 612533, 612678, 612823, 612967, 613112, 613256, 613400, 613544, 613687, + 613831, 613974, 614117, 614260, 614402, 614544, 614686, 614828, 614970, 615111, 615253, 615394, + 615534, 615675, 615815, 615956, 616096, 616235, 616375, 616514, 616653, 616792, 616931, 617070, + 617208, 617346, 617484, 617622, 617759, 617897, 618034, 618171, 618307, 618444, 618580, 618716, + 618852, 618988, 619124, 619259, 619394, 619529, 619664, 619798, 619933, 620067, 620201, 620335, + 620468, 620602, 620735, 620868, 621001, 621134, 621266, 621399, 621531, 621663, 621795, 621926, + 622058, 622189, 622320, 622451, 622581, 622712, 622842, 622972, 623102, 623232, 623362, 623491, + 623620, 623749, 623878, 624007, 624136, 624264, 624392, 624520, 624648, 624776, 624903, 625031, + 625158, 625285, 625412, 625538, 625665, 625791, 625917, 626043, 626169, 626295, 626420, 626545, + 626671, 626796, 626920, 627045, 627170, 627294, 627418, 627542, 627666, 627790, 627913, 628036, + 628160, 628283, 628406, 628528, 628651, 628773, 628895, 629017, 629139, 629261, 629383, 629504, + 629625, 629747, 629868, 629988, 630109, 630230, 630350, 630470, 630590, 630710, 630830, 630950, + 631069, 631188, 631307, 631426, 631545, 631664, 631783, 631901, 632019, 632137, 632255, 632373, + 632491, 632608, 632726, 632843, 632960, 633077, 633194, 633310, 633427, 633543, 633660, 633776, + 633892, 634007, 634123, 634239, 634354, 634469, 634584, 634699, 634814, 634929, 635043, 635158, + 635272, 635386, 635500, 635614, 635728, 635841, 635955, 636068, 636181, 636294, 636407, 636520, + 636632, 636745, 636857, 636969, 637081, 637193, 637305, 637417, 637528, 637640, 637751, 637862, + 637973, 638084, 638195, 638306, 638416, 638527, 638637, 638747, 638857, 638967, 639077, 639186, + 639296, 639405, 639514, 639624, 639733, 639841, 639950, 640059, 640167, 640276, 640384, 640492, + 640600, 640708, 640816, 640923, 641031, 641138, 641245, 641352, 641459, 641566, 641673, 641780, + 641886, 641993, 642099, 642205, 642311, 642417, 642523, 642629, 642734, 642840, 642945, 643050, + 643155, 643260, 643365, 643470, 643575, 643679, 643784, 643888, 643992, 644096, 644200, 644304, + 644408, 644511, 644615, 644718, 644822, 644925, 645028, 645131, 645234, 645336, 645439, 645541, + 645644, 645746, 645848, 645950, 646052, 646154, 646256, 646357, 646459, 646560, 646661, 646763, + 646864, 646965, 647066, 647166, 647267, 647367, 647468, 647568, 647668, 647768, 647868, 647968, + 648068, 648168, 648267, 648367, 648466, 648566, 648665, 648764, 648863, 648962, 649060, 649159, + 649257, 649356, 649454, 649552, 649651, 649749, 649847, 649944, 650042, 650140, 650237, 650335, + 650432, 650529, 650626, 650723, 650820, 650917, 651014, 651110, 651207, 651303, 651400, 651496, + 651592, 651688, 651784, 651880, 651976, 652071, 652167, 652262, 652358, 652453, 652548, 652643, + 652738, 652833, 652928, 653023, 653117, 653212, 653306, 653400, 653495, 653589, 653683, 653777, + 653871, 653964, 654058, 654151, 654245, 654338, 654432, 654525, 654618, 654711, 654804, 654897, + 654989, 655082, 655175, 655267, 655360, 655452, 655544, 655636, 655728, 655820, 655912, 656004, + 656095, 656187, 656278, 656370, 656461, 656552, 656643, 656734, 656825, 656916, 657007, 657098, + 657188, 657279, 657369, 657460, 657550, 657640, 657730, 657820, 657910, 658000, 658090, 658179, + 658269, 658358, 658448, 658537, 658626, 658716, 658805, 658894, 658982, 659071, 659160, 659249, + 659337, 659426, 659514, 659602, 659691, 659779, 659867, 659955, 660043, 660131, 660218, 660306, + 660394, 660481, 660569, 660656, 660743, 660830, 660918, 661005, 661091, 661178, 661265, 661352, + 661438, 661525, 661611, 661698, 661784, 661870, 661957, 662043, 662129, 662214, 662300, 662386, + 662472, 662557, 662643, 662728, 662814, 662899, 662984, 663069, 663154, 663239, 663324, 663409, + 663494, 663579, 663663, 663748, 663832, 663917, 664001, 664085, 664169, 664253, 664337, 664421, + 664505, 664589, 664673, 664756, 664840, 664923, 665007, 665090, 665173, 665257, 665340, 665423, + 665506, 665589, 665671, 665754, 665837, 665919, 666002, 666084, 666167, 666249, 666331, 666414, + 666496, 666578, 666660, 666742, 666823, 666905, 666987, 667068, 667150, 667231, 667313, 667394, + 667475, 667557, 667638, 667719, 667800, 667881, 667962, 668042, 668123, 668204, 668284, 668365, + 668445, 668526, 668606, 668686, 668766, 668846, 668926, 669006, 669086, 669166, 669246, 669325, + 669405, 669485, 669564, 669644, 669723, 669802, 669881, 669961, 670040, 670119, 670198, 670277, + 670355, 670434, 670513, 670591, 670670, 670748, 670827, 670905, 670984, 671062, 671140, 671218, + 671296, 671374, 671452, 671530, 671608, 671685, 671763, 671841, 671918, 671996, 672073, 672150, + 672228, 672305, 672382, 672459, 672536, 672613, 672690, 672767, 672844, 672920, 672997, 673074, + 673150, 673227, 673303, 673379, 673456, 673532, 673608, 673684, 673760, 673836, 673912, 673988, + 674064, 674139, 674215, 674291, 674366, 674442, 674517, 674592, 674668, 674743, 674818, 674893, + 674968, 675043, 675118, 675193, 675268, 675343, 675418, 675492, 675567, 675641, 675716, 675790, + 675865, 675939, 676013, 676087, 676161, 676236, 676310, 676383, 676457, 676531, 676605, 676679, + 676752, 676826, 676900, 676973, 677046, 677120, 677193, 677266, 677340, 677413, 677486, 677559, + 677632, 677705, 677778, 677851, 677923, 677996, 678069, 678141, 678214, 678286, 678359, 678431, + 678503, 678576, 678648, 678720, 678792, 678864, 678936, 679008, 679080, 679152, 679223, 679295, + 679367, 679438, 679510, 679581, 679653, 679724, 679796, 679867, 679938, 680009, 680080, 680151, + 680222, 680293, 680364, 680435, 680506, 680577, 680647, 680718, 680789, 680859, 680930, 681000, + 681070, 681141, 681211, 681281, 681351, 681422, 681492, 681562, 681632, 681701, 681771, 681841, + 681911, 681981, 682050, 682120, 682189, 682259, 682328, 682398, 682467, 682536, 682606, 682675, + 682744, 682813, 682882, 682951, 683020, 683089, 683158, 683226, 683295, 683364, 683433, 683501, + 683570, 683638, 683707, 683775, 683843, 683912, 683980, 684048, 684116, 684184, 684252, 684320, + 684388, 684456, 684524, 684592, 684660, 684727, 684795, 684863, 684930, 684998, 685065, 685132, + 685200, 685267, 685334, 685402, 685469, 685536, 685603, 685670, 685737, 685804, 685871, 685938, + 686004, 686071, 686138, 686205, 686271, 686338, 686404, 686471, 686537, 686604, 686670, 686736, + 686802, 686869, 686935, 687001, 687067, 687133, 687199, 687265, 687331, 687396, 687462, 687528, + 687594, 687659, 687725, 687790, 687856, 687921, 687987, 688052, 688117, 688183, 688248, 688313, + 688378, 688443, 688508, 688573, 688638, 688703, 688768, 688833, 688898, 688962, 689027, 689092, + 689156, 689221, 689285, 689350, 689414, 689479, 689543, 689607, 689672, 689736, 689800, 689864, + 689928, 689992, 690056, 690120, 690184, 690248, 690312, 690376, 690439, 690503, 690567, 690630, + 690694, 690757, 690821, 690884, 690948, 691011, 691074, 691138, 691201, 691264, 691327, 691390, + 691453, 691516, 691579, 691642, 691705, 691768, 691831, 691893, 691956, 692019, 692081, 692144, + 692207, 692269, 692332, 692394, 692456, 692519, 692581, 692643, 692706, 692768, 692830, 692892, + 692954, 693016, 693078, 693140, 693202, 693264, 693326, 693387, 693449, 693511, 693572, 693634, + 693696, 693757, 693819, 693880, 693942, 694003, 694064, 694126, 694187, 694248, 694309, 694370, + 694431, 694492, 694553, 694614, 694675, 694736, 694797, 694858, 694919, 694980, 695040, 695101, + 695161, 695222, 695283, 695343, 695404, 695464, 695524, 695585, 695645, 695705, 695766, 695826, + 695886, 695946, 696006, 696066, 696126, 696186, 696246, 696306, 696366, 696426, 696486, 696545, + 696605, 696665, 696724, 696784, 696843, 696903, 696962, 697022, 697081, 697141, 697200, 697259, + 697319, 697378, 697437, 697496, 697555, 697614, 697673, 697732, 697791, 697850, 697909, 697968, + 698027, 698086, 698144, 698203, 698262, 698320, 698379, 698438, 698496, 698555, 698613, 698671, + 698730, 698788, 698846, 698905, 698963, 699021, 699079, 699137, 699196, 699254, 699312, 699370, + 699428, 699485, 699543, 699601, 699659, 699717, 699775, 699832, 699890, 699948, 700005, 700063, + 700120, 700178, 700235, 700293, 700350, 700407, 700465, 700522, 700579, 700636, 700694, 700751, + 700808, 700865, 700922, 700979, 701036, 701093, 701150, 701207, 701264, 701320, 701377, 701434, + 701491, 701547, 701604, 701660, 701717, 701774, 701830, 701886, 701943, 701999, 702056, 702112, + 702168, 702225, 702281, 702337, 702393, 702449, 702505, 702561, 702617, 702673, 702729, 702785, + 702841, 702897, 702953, 703009, 703064, 703120, 703176, 703232, 703287, 703343, 703398, 703454, + 703509, 703565, 703620, 703676, 703731, 703786, 703842, 703897, 703952, 704007, 704063, 704118, + 704173, 704228, 704283, 704338, 704393, 704448, 704503, 704558, 704613, 704668, 704722, 704777, + 704832, 704887, 704941, 704996, 705050, 705105, 705160, 705214, 705269, 705323, 705377, 705432, + 705486, 705540, 705595, 705649, 705703, 705757, 705812, 705866, 705920, 705974, 706028, 706082, + 706136, 706190, 706244, 706298, 706352, 706405, 706459, 706513, 706567, 706620, 706674, 706728, + 706781, 706835, 706888, 706942, 706995, 707049, 707102, 707156, 707209, 707262, 707316, 707369, + 707422, 707476, 707529, 707582, 707635, 707688, 707741, 707794, 707847, 707900, 707953, 708006, + 708059, 708112, 708165, 708218, 708270, 708323, 708376, 708428, 708481, 708534, 708586, 708639, + 708691, 708744, 708796, 708849, 708901, 708954, 709006, 709058, 709111, 709163, 709215, 709268, + 709320, 709372, 709424, 709476, 709528, 709580, 709632, 709684, 709736, 709788, 709840, 709892, + 709944, 709996, 710047, 710099, 710151, 710203, 710254, 710306, 710358, 710409, 710461, 710512, + 710564, 710615, 710667, 710718, 710770, 710821, 710872, 710924, 710975, 711026, 711077, 711129, + 711180, 711231, 711282, 711333, 711384, 711435, 711486, 711537, 711588, 711639, 711690, 711741, + 711792, 711843, 711893, 711944, 711995, 712046, 712096, 712147, 712197, 712248, 712299, 712349, + 712400, 712450, 712501, 712551, 712602, 712652, 712702, 712753, 712803, 712853, 712903, 712954, + 713004, 713054, 713104, 713154, 713204, 713254, 713304, 713355, 713404, 713454, 713504, 713554, + 713604, 713654, 713704, 713754, 713803, 713853, 713903, 713953, 714002, 714052, 714102, 714151, + 714201, 714250, 714300, 714349, 714399, 714448, 714498, 714547, 714596, 714646, 714695, 714744, + 714793, 714843, 714892, 714941, 714990, 715039, 715088, 715138, 715187, 715236, 715285, 715334, + 715383, 715431, 715480, 715529, 715578, 715627, 715676, 715725, 715773, 715822, 715871, 715919, + 715968, 716017, 716065, 716114, 716162, 716211, 716259, 716308, 716356, 716405, 716453, 716502, + 716550, 716598, 716646, 716695, 716743, 716791, 716839, 716888, 716936, 716984, 717032, 717080, + 717128, 717176, 717224, 717272, 717320, 717368, 717416, 717464, 717512, 717560, 717607, 717655, + 717703, 717751, 717798, 717846, 717894, 717941, 717989, 718037, 718084, 718132, 718179, 718227, + 718274, 718322, 718369, 718416, 718464, 718511, 718559, 718606, 718653, 718700, 718748, 718795, + 718842, 718889, 718936, 718983, 719031, 719078, 719125, 719172, 719219, 719266, 719313, 719360, + 719407, 719453, 719500, 719547, 719594, 719641, 719687, 719734, 719781, 719828, 719874, 719921, + 719968, 720014, 720061, 720107, 720154, 720200, 720247, 720293, 720340, 720386, 720433, 720479, + 720525, 720572, 720618, 720664, 720711, 720757, 720803, 720849, 720896, 720942, 720988, 721034, + 721080, 721126, 721172, 721218, 721264, 721310, 721356, 721402, 721448, 721494, 721540, 721585, + 721631, 721677, 721723, 721769, 721814, 721860, 721906, 721951, 721997, 722043, 722088, 722134, + 722179, 722225, 722270, 722316, 722361, 722407, 722452, 722498, 722543, 722588, 722634, 722679, + 722724, 722770, 722815, 722860, 722905, 722950, 722996, 723041, 723086, 723131, 723176, 723221, + 723266, 723311, 723356, 723401, 723446, 723491, 723536, 723581, 723626, 723671, 723715, 723760, + 723805, 723850, 723894, 723939, 723984, 724028, 724073, 724118, 724162, 724207, 724252, 724296, + 724341, 724385, 724430, 724474, 724518, 724563, 724607, 724652, 724696, 724740, 724785, 724829, + 724873, 724918, 724962, 725006, 725050, 725094, 725138, 725183, 725227, 725271, 725315, 725359, + 725403, 725447, 725491, 725535, 725579, 725623, 725667, 725711, 725754, 725798, 725842, 725886, + 725930, 725973, 726017, 726061, 726105, 726148, 726192, 726236, 726279, 726323, 726366, 726410, + 726454, 726497, 726541, 726584, 726627, 726671, 726714, 726758, 726801, 726844, 726888, 726931, + 726974, 727018, 727061, 727104, 727147, 727191, 727234, 727277, 727320, 727363, 727406, 727449, + 727493, 727536, 727579, 727622, 727665, 727708, 727750, 727793, 727836, 727879, 727922, 727965, + 728008, 728051, 728093, 728136, 728179, 728222, 728264, 728307, 728350, 728392, 728435, 728478, + 728520, 728563, 728605, 728648, 728690, 728733, 728775, 728818, 728860, 728903, 728945, 728988, + 729030, 729072, 729115, 729157, 729199, 729241, 729284, 729326, 729368, 729410, 729453, 729495, + 729537, 729579, 729621, 729663, 729705, 729747, 729789, 729831, 729873, 729915, 729957, 729999, + 730041, 730083, 730125, 730167, 730209, 730250, 730292, 730334, 730376, 730418, 730459, 730501, + 730543, 730584, 730626, 730668, 730709, 730751, 730793, 730834, 730876, 730917, 730959, 731000, + 731042, 731083, 731125, 731166, 731207, 731249, 731290, 731331, 731373, 731414, 731455, 731497, + 731538, 731579, 731620, 731662, 731703, 731744, 731785, 731826, 731867, 731909, 731950, 731991, + 732032, 732073, 732114, 732155, 732196, 732237, 732278, 732319, 732359, 732400, 732441, 732482, + 732523, 732564, 732604, 732645, 732686, 732727, 732767, 732808, 732849, 732890, 732930, 732971, + 733011, 733052, 733093, 733133, 733174, 733214, 733255, 733295, 733336, 733376, 733417, 733457, + 733498, 733538, 733578, 733619, 733659, 733699, 733740, 733780, 733820, 733861, 733901, 733941, + 733981, 734021, 734062, 734102, 734142, 734182, 734222, 734262, 734302, 734342, 734382, 734422, + 734462, 734502, 734542, 734582, 734622, 734662, 734702, 734742, 734782, 734822, 734861, 734901, + 734941, 734981, 735021, 735060, 735100, 735140, 735180, 735219, 735259, 735299, 735338, 735378, + 735417, 735457, 735497, 735536, 735576, 735615, 735655, 735694, 735734, 735773, 735813, 735852, + 735891, 735931, 735970, 736009, 736049, 736088, 736127, 736167, 736206, 736245, 736284, 736324, + 736363, 736402, 736441, 736480, 736520, 736559, 736598, 736637, 736676, 736715, 736754, 736793, + 736832, 736871, 736910, 736949, 736988, 737027, 737066, 737105, 737144, 737183, 737221, 737260, + 737299, 737338, 737377, 737415, 737454, 737493, 737532, 737570, 737609, 737648, 737686, 737725, + 737764, 737802, 737841, 737879, 737918, 737957, 737995, 738034, 738072, 738111, 738149, 738188, + 738226, 738264, 738303, 738341, 738380, 738418, 738456, 738495, 738533, 738571, 738610, 738648, + 738686, 738724, 738763, 738801, 738839, 738877, 738915, 738953, 738992, 739030, 739068, 739106, + 739144, 739182, 739220, 739258, 739296, 739334, 739372, 739410, 739448, 739486, 739524, 739562, + 739600, 739637, 739675, 739713, 739751, 739789, 739827, 739864, 739902, 739940, 739978, 740015, + 740053, 740091, 740128, 740166, 740204, 740241, 740279, 740317, 740354, 740392, 740429, 740467, + 740504, 740542, 740579, 740617, 740654, 740692, 740729, 740767, 740804, 740841, 740879, 740916, + 740954, 740991, 741028, 741066, 741103, 741140, 741177, 741215, 741252, 741289, 741326, 741363, + 741401, 741438, 741475, 741512, 741549, 741586, 741623, 741660, 741697, 741734, 741772, 741809, + 741846, 741883, 741919, 741956, 741993, 742030, 742067, 742104, 742141, 742178, 742215, 742252, + 742288, 742325, 742362, 742399, 742436, 742472, 742509, 742546, 742582, 742619, 742656, 742693, + 742729, 742766, 742802, 742839, 742876, 742912, 742949, 742985, 743022, 743058, 743095, 743131, + 743168, 743204, 743241, 743277, 743314, 743350, 743387, 743423, 743459, 743496, 743532, 743568, + 743605, 743641, 743677, 743713, 743750, 743786, 743822, 743858, 743895, 743931, 743967, 744003, + 744039, 744075, 744112, 744148, 744184, 744220, 744256, 744292, 744328, 744364, 744400, 744436, + 744472, 744508, 744544, 744580, 744616, 744652, 744688, 744724, 744759, 744795, 744831, 744867, + 744903, 744939, 744974, 745010, 745046, 745082, 745117, 745153, 745189, 745225, 745260, 745296, + 745332, 745367, 745403, 745438, 745474, 745510, 745545, 745581, 745616, 745652, 745687, 745723, + 745758, 745794, 745829, 745865, 745900, 745936, 745971, 746007, 746042, 746077, 746113, 746148, + 746183, 746219, 746254, 746289, 746325, 746360, 746395, 746430, 746466, 746501, 746536, 746571, + 746606, 746642, 746677, 746712, 746747, 746782, 746817, 746852, 746887, 746922, 746958, 746993, + 747028, 747063, 747098, 747133, 747168, 747202, 747237, 747272, 747307, 747342, 747377, 747412, + 747447, 747482, 747517, 747551, 747586, 747621, 747656, 747691, 747725, 747760, 747795, 747830, + 747864, 747899, 747934, 747968, 748003, 748038, 748072, 748107, 748142, 748176, 748211, 748245, + 748280, 748314, 748349, 748383, 748418, 748453, 748487, 748521, 748556, 748590, 748625, 748659, + 748694, 748728, 748762, 748797, 748831, 748866, 748900, 748934, 748969, 749003, 749037, 749071, + 749106, 749140, 749174, 749208, 749243, 749277, 749311, 749345, 749379, 749413, 749448, 749482, + 749516, 749550, 749584, 749618, 749652, 749686, 749720, 749754, 749788, 749822, 749856, 749890, + 749924, 749958, 749992, 750026, 750060, 750094, 750128, 750162, 750196, 750229, 750263, 750297, + 750331, 750365, 750399, 750432, 750466, 750500, 750534, 750567, 750601, 750635, 750668, 750702, + 750736, 750769, 750803, 750837, 750870, 750904, 750938, 750971, 751005, 751038, 751072, 751105, + 751139, 751173, 751206, 751240, 751273, 751307, 751340, 751373, 751407, 751440, 751474, 751507, + 751540, 751574, 751607, 751641, 751674, 751707, 751741, 751774, 751807, 751840, 751874, 751907, + 751940, 751974, 752007, 752040, 752073, 752106, 752140, 752173, 752206, 752239, 752272, 752305, + 752338, 752371, 752405, 752438, 752471, 752504, 752537, 752570, 752603, 752636, 752669, 752702, + 752735, 752768, 752801, 752834, 752867, 752899, 752932, 752965, 752998, 753031, 753064, 753097, + 753130, 753162, 753195, 753228, 753261, 753294, 753326, 753359, 753392, 753425, 753457, 753490, + 753523, 753555, 753588, 753621, 753653, 753686, 753719, 753751, 753784, 753816, 753849, 753882, + 753914, 753947, 753979, 754012, 754044, 754077, 754109, 754142, 754174, 754207, 754239, 754272, + 754304, 754337, 754369, 754401, 754434, 754466, 754498, 754531, 754563, 754595, 754628, 754660, + 754692, 754725, 754757, 754789, 754821, 754854, 754886, 754918, 754950, 754983, 755015, 755047, + 755079, 755111, 755143, 755176, 755208, 755240, 755272, 755304, 755336, 755368, 755400, 755432, + 755464, 755496, 755528, 755560, 755592, 755624, 755656, 755688, 755720, 755752, 755784, 755816, + 755848, 755880, 755912, 755943, 755975, 756007, 756039, 756071, 756103, 756134, 756166, 756198, + 756230, 756262, 756293, 756325, 756357, 756389, 756420, 756452, 756484, 756515, 756547, 756579, + 756610, 756642, 756674, 756705, 756737, 756768, 756800, 756832, 756863, 756895, 756926, 756958, + 756989, 757021, 757052, 757084, 757115, 757147, 757178, 757210, 757241, 757272, 757304, 757335, + 757367, 757398, 757429, 757461, 757492, 757524, 757555, 757586, 757617, 757649, 757680, 757711, + 757743, 757774, 757805, 757836, 757868, 757899, 757930, 757961, 757992, 758024, 758055, 758086, + 758117, 758148, 758179, 758210, 758242, 758273, 758304, 758335, 758366, 758397, 758428, 758459, + 758490, 758521, 758552, 758583, 758614, 758645, 758676, 758707, 758738, 758769, 758800, 758831, + 758862, 758892, 758923, 758954, 758985, 759016, 759047, 759078, 759108, 759139, 759170, 759201, + 759232, 759262, 759293, 759324, 759355, 759385, 759416, 759447, 759478, 759508, 759539, 759570, + 759600, 759631, 759662, 759692, 759723, 759753, 759784, 759815, 759845, 759876, 759906, 759937, + 759967, 759998, 760028, 760059, 760089, 760120, 760150, 760181, 760211, 760242, 760272, 760303, + 760333, 760364, 760394, 760424, 760455, 760485, 760516, 760546, 760576, 760607, 760637, 760667, + 760697, 760728, 760758, 760788, 760819, 760849, 760879, 760909, 760940, 760970, 761000, 761030, + 761060, 761091, 761121, 761151, 761181, 761211, 761241, 761272, 761302, 761332, 761362, 761392, + 761422, 761452, 761482, 761512, 761542, 761572, 761602, 761632, 761662, 761692, 761722, 761752, + 761782, 761812, 761842, 761872, 761902, 761932, 761962, 761992, 762022, 762051, 762081, 762111, + 762141, 762171, 762201, 762231, 762260, 762290, 762320, 762350, 762379, 762409, 762439, 762469, + 762498, 762528, 762558, 762588, 762617, 762647, 762677, 762706, 762736, 762766, 762795, 762825, + 762855, 762884, 762914, 762943, 762973, 763003, 763032, 763062, 763091, 763121, 763150, 763180, + 763209, 763239, 763268, 763298, 763327, 763357, 763386, 763416, 763445, 763475, 763504, 763533, + 763563, 763592, 763622, 763651, 763680, 763710, 763739, 763768, 763798, 763827, 763856, 763886, + 763915, 763944, 763974, 764003, 764032, 764061, 764091, 764120, 764149, 764178, 764207, 764237, + 764266, 764295, 764324, 764353, 764382, 764412, 764441, 764470, 764499, 764528, 764557, 764586, + 764615, 764644, 764673, 764703, 764732, 764761, 764790, 764819, 764848, 764877, 764906, 764935, + 764964, 764993, 765021, 765050, 765079, 765108, 765137, 765166, 765195, 765224, 765253, 765282, + 765311, 765339, 765368, 765397, 765426, 765455, 765484, 765512, 765541, 765570, 765599, 765627, + 765656, 765685, 765714, 765742, 765771, 765800, 765829, 765857, 765886, 765915, 765943, 765972, + 766001, 766029, 766058, 766087, 766115, 766144, 766172, 766201, 766230, 766258, 766287, 766315, + 766344, 766372, 766401, 766429, 766458, 766486, 766515, 766543, 766572, 766600, 766629, 766657, + 766686, 766714, 766743, 766771, 766800, 766828, 766856, 766885, 766913, 766941, 766970, 766998, + 767027, 767055, 767083, 767112, 767140, 767168, 767196, 767225, 767253, 767281, 767310, 767338, + 767366, 767394, 767422, 767451, 767479, 767507, 767535, 767563, 767592, 767620, 767648, 767676, + 767704, 767732, 767761, 767789, 767817, 767845, 767873, 767901, 767929, 767957, 767985, 768013, + 768041, 768069, 768097, 768125, 768153, 768181, 768209, 768237, 768265, 768293, 768321, 768349, + 768377, 768405, 768433, 768461, 768489, 768517, 768545, 768573, 768600, 768628, 768656, 768684, + 768712, 768740, 768768, 768795, 768823, 768851, 768879, 768907, 768934, 768962, 768990, 769018, + 769045, 769073, 769101, 769129, 769156, 769184, 769212, 769239, 769267, 769295, 769322, 769350, + 769378, 769405, 769433, 769461, 769488, 769516, 769543, 769571, 769599, 769626, 769654, 769681, + 769709, 769736, 769764, 769792, 769819, 769847, 769874, 769902, 769929, 769957, 769984, 770011, + 770039, 770066, 770094, 770121, 770149, 770176, 770204, 770231, 770258, 770286, 770313, 770340, + 770368, 770395, 770423, 770450, 770477, 770504, 770532, 770559, 770586, 770614, 770641, 770668, + 770696, 770723, 770750, 770777, 770805, 770832, 770859, 770886, 770913, 770941, 770968, 770995, + 771022, 771049, 771076, 771104, 771131, 771158, 771185, 771212, 771239, 771266, 771293, 771321, + 771348, 771375, 771402, 771429, 771456, 771483, 771510, 771537, 771564, 771591, 771618, 771645, + 771672, 771699, 771726, 771753, 771780, 771807, 771834, 771861, 771888, 771914, 771941, 771968, + 771995, 772022, 772049, 772076, 772103, 772130, 772156, 772183, 772210, 772237, 772264, 772291, + 772317, 772344, 772371, 772398, 772424, 772451, 772478, 772505, 772531, 772558, 772585, 772612, + 772638, 772665, 772692, 772718, 772745, 772772, 772798, 772825, 772852, 772878, 772905, 772932, + 772958, 772985, 773012, 773038, 773065, 773091, 773118, 773144, 773171, 773198, 773224, 773251, + 773277, 773304, 773330, 773357, 773383, 773410, 773436, 773463, 773489, 773516, 773542, 773569, + 773595, 773621, 773648, 773674, 773701, 773727, 773754, 773780, 773806, 773833, 773859, 773885, + 773912, 773938, 773964, 773991, 774017, 774043, 774070, 774096, 774122, 774149, 774175, 774201, + 774227, 774254, 774280, 774306, 774332, 774359, 774385, 774411, 774437, 774464, 774490, 774516, + 774542, 774568, 774594, 774621, 774647, 774673, 774699, 774725, 774751, 774777, 774804, 774830, + 774856, 774882, 774908, 774934, 774960, 774986, 775012, 775038, 775064, 775090, 775116, 775142, + 775168, 775194, 775220, 775246, 775272, 775298, 775324, 775350, 775376, 775402, 775428, 775454, + 775480, 775506, 775532, 775558, 775583, 775609, 775635, 775661, 775687, 775713, 775739, 775764, + 775790, 775816, 775842, 775868, 775894, 775919, 775945, 775971, 775997, 776022, 776048, 776074, + 776100, 776126, 776151, 776177, 776203, 776228, 776254, 776280, 776306, 776331, 776357, 776383, + 776408, 776434, 776460, 776485, 776511, 776536, 776562, 776588, 776613, 776639, 776665, 776690, + 776716, 776741, 776767, 776792, 776818, 776844, 776869, 776895, 776920, 776946, 776971, 776997, + 777022, 777048, 777073, 777099, 777124, 777150, 777175, 777201, 777226, 777251, 777277, 777302, + 777328, 777353, 777379, 777404, 777429, 777455, 777480, 777505, 777531, 777556, 777582, 777607, + 777632, 777658, 777683, 777708, 777733, 777759, 777784, 777809, 777835, 777860, 777885, 777910, + 777936, 777961, 777986, 778011, 778037, 778062, 778087, 778112, 778138, 778163, 778188, 778213, + 778238, 778263, 778289, 778314, 778339, 778364, 778389, 778414, 778439, 778465, 778490, 778515, + 778540, 778565, 778590, 778615, 778640, 778665, 778690, 778715, 778740, 778765, 778790, 778815, + 778840, 778866, 778891, 778916, 778940, 778965, 778990, 779015, 779040, 779065, 779090, 779115, + 779140, 779165, 779190, 779215, 779240, 779265, 779290, 779315, 779339, 779364, 779389, 779414, + 779439, 779464, 779489, 779513, 779538, 779563, 779588, 779613, 779638, 779662, 779687, 779712, + 779737, 779761, 779786, 779811, 779836, 779861, 779885, 779910, 779935, 779959, 779984, 780009, + 780034, 780058, 780083, 780108, 780132, 780157, 780182, 780206, 780231, 780256, 780280, 780305, + 780329, 780354, 780379, 780403, 780428, 780453, 780477, 780502, 780526, 780551, 780575, 780600, + 780624, 780649, 780674, 780698, 780723, 780747, 780772, 780796, 780821, 780845, 780870, 780894, + 780919, 780943, 780967, 780992, 781016, 781041, 781065, 781090, 781114, 781139, 781163, 781187, + 781212, 781236, 781261, 781285, 781309, 781334, 781358, 781382, 781407, 781431, 781455, 781480, + 781504, 781528, 781553, 781577, 781601, 781626, 781650, 781674, 781698, 781723, 781747, 781771, + 781795, 781820, 781844, 781868, 781892, 781917, 781941, 781965, 781989, 782013, 782038, 782062, + 782086, 782110, 782134, 782158, 782182, 782207, 782231, 782255, 782279, 782303, 782327, 782351, + 782375, 782400, 782424, 782448, 782472, 782496, 782520, 782544, 782568, 782592, 782616, 782640, + 782664, 782688, 782712, 782736, 782760, 782784, 782808, 782832, 782856, 782880, 782904, 782928, + 782952, 782976, 783000, 783024, 783048, 783072, 783096, 783119, 783143, 783167, 783191, 783215, + 783239, 783263, 783287, 783310, 783334, 783358, 783382, 783406, 783430, 783454, 783477, 783501, + 783525, 783549, 783573, 783596, 783620, 783644, 783668, 783691, 783715, 783739, 783763, 783786, + 783810, 783834, 783858, 783881, 783905, 783929, 783952, 783976, 784000, 784024, 784047, 784071, + 784095, 784118, 784142, 784165, 784189, 784213, 784236, 784260, 784284, 784307, 784331, 784354, + 784378, 784402, 784425, 784449, 784472, 784496, 784519, 784543, 784567, 784590, 784614, 784637, + 784661, 784684, 784708, 784731, 784755, 784778, 784802, 784825, 784849, 784872, 784896, 784919, + 784943, 784966, 784989, 785013, 785036, 785060, 785083, 785107, 785130, 785153, 785177, 785200, + 785223, 785247, 785270, 785294, 785317, 785340, 785364, 785387, 785410, 785434, 785457, 785480, + 785504, 785527, 785550, 785574, 785597, 785620, 785643, 785667, 785690, 785713, 785736, 785760, + 785783, 785806, 785829, 785853, 785876, 785899, 785922, 785946, 785969, 785992, 786015, 786038, + 786061, 786085, 786108, 786131, 786154, 786177, 786200, 786224, 786247, 786270, 786293, 786316, + 786339, 786362, 786385, 786408 +}; + +static const unsigned int bsc_delta_table[4096] = +{ + 0, 131072, 180544, 212672, 236557, 255603, 271426, 284990, 296832, 307354, 316837, 325441, + 333328, 340596, 347363, 353689, 359571, 365165, 370408, 375372, 380114, 384632, 388922, 393032, + 396955, 400773, 404384, 407880, 411276, 414522, 417708, 420742, 423677, 426537, 429346, 432056, + 434646, 437242, 439712, 442104, 444512, 446788, 449065, 451271, 453414, 455502, 457543, 459593, + 461517, 463465, 465398, 467220, 468984, 470856, 472577, 474255, 476008, 477616, 479252, 480864, + 482456, 484032, 485533, 487023, 488441, 489985, 491399, 492747, 494236, 495528, 496899, 498285, + 499544, 500820, 502117, 503439, 504636, 505860, 507036, 508244, 509488, 510608, 511766, 512882, + 514041, 515161, 516242, 517372, 518377, 519523, 520454, 521622, 522574, 523584, 524656, 525602, + 526515, 527591, 528541, 529461, 530452, 531416, 532250, 533262, 534040, 535000, 535936, 536848, + 537627, 538599, 539328, 540254, 541159, 541929, 542790, 543514, 544448, 545128, 546022, 546778, + 547634, 548350, 549168, 549968, 550625, 551513, 552132, 552986, 553567, 554387, 555192, 555850, + 556490, 557380, 557988, 558578, 559424, 560120, 560662, 561466, 562117, 562753, 563517, 564125, + 564718, 565442, 566007, 566705, 567391, 567915, 568726, 569224, 569860, 570484, 571096, 571696, + 572284, 572860, 573583, 573977, 574678, 575370, 575890, 576398, 577059, 577545, 578186, 578650, + 579440, 579714, 580486, 580908, 581491, 582065, 582630, 583186, 583556, 584270, 584799, 585319, + 585649, 586331, 586824, 587492, 587784, 588436, 588895, 589345, 589975, 590409, 590834, 591442, + 591851, 592251, 592837, 593417, 593794, 594360, 594721, 595273, 595819, 596157, 596689, 597215, + 597530, 598042, 598548, 599048, 599333, 599819, 600299, 600773, 601241, 601703, 602159, 602609, + 603053, 603273, 603922, 604348, 604547, 605181, 605589, 605991, 606387, 607003, 607162, 607768, + 608142, 608510, 608872, 609228, 609811, 610157, 610497, 610831, 611396, 611720, 612277, 612351, + 613139, 613201, 613740, 614032, 614563, 614845, 615368, 615640, 615906, 616416, 616923, 617175, + 617421, 617915, 618151, 618893, 618864, 619342, 619817, 620029, 620496, 620960, 621158, 621614, + 621802, 622250, 622695, 623137, 623307, 623741, 623901, 624327, 624750, 625170, 625587, 625725, + 626134, 626262, 626942, 627062, 627457, 627849, 628238, 628340, 629006, 629100, 629475, 629847, + 629927, 630581, 630653, 631303, 631367, 631719, 632068, 632414, 632757, 633097, 633434, 633468, + 634098, 634426, 634448, 635072, 635086, 635706, 635712, 636328, 636326, 636938, 636928, 637536, + 637518, 638122, 638096, 638696, 638979, 639259, 639217, 639809, 640080, 640348, 640936, 640876, + 641135, 641717, 641645, 642223, 642472, 642718, 642961, 643201, 643438, 644006, 644239, 644133, + 644695, 645257, 645141, 645359, 645915, 646129, 646340, 646548, 647098, 646956, 647502, 647700, + 648244, 648088, 648628, 648816, 649001, 649183, 649717, 649895, 650070, 650600, 650771, 650939, + 651104, 651266, 651788, 651946, 652466, 652254, 652770, 653286, 653064, 653576, 653717, 654227, + 654364, 654498, 654629, 655133, 655260, 655762, 655506, 656384, 656122, 656618, 656731, 657225, + 657334, 657440, 657543, 658031, 658519, 658227, 659102, 658804, 659286, 659374, 659854, 659938, + 660019, 660495, 660971, 660647, 661119, 661591, 661660, 661726, 662194, 662256, 662722, 662780, + 662835, 663297, 663348, 663808, 663855, 664313, 664356, 664812, 664851, 664887, 665339, 665371, + 665821, 665849, 666297, 666321, 666767, 666787, 667231, 667247, 667689, 667701, 668141, 668149, + 668154, 669024, 668592, 669026, 669460, 669456, 669888, 669880, 669869, 670297, 670725, 670709, + 671135, 671115, 671539, 671515, 671937, 671909, 672329, 672749, 672716, 672680, 673096, 673512, + 673471, 673885, 673840, 674252, 674203, 674613, 674560, 674968, 675376, 675318, 675257, 676129, + 676066, 676000, 676402, 676332, 676732, 677132, 677057, 677455, 677853, 677773, 677690, 678084, + 678478, 678872, 678783, 678691, 679081, 679471, 679374, 679762, 680150, 680048, 680434, 680328, + 680712, 681096, 680985, 681367, 681252, 681632, 682012, 681892, 682270, 682648, 682523, 682899, + 682770, 683144, 683518, 683384, 683756, 683618, 684499, 684359, 684216, 684584, 684952, 684804, + 685170, 685536, 685383, 685747, 686111, 685953, 686315, 686677, 686514, 686874, 687234, 687066, + 687424, 687252, 688139, 687433, 688320, 688142, 688496, 688850, 688667, 689019, 688832, 689722, + 689533, 689341, 690232, 689494, 690385, 690187, 690533, 690879, 691225, 691021, 690814, 691708, + 691499, 691841, 691628, 691968, 692308, 692648, 692429, 692767, 693105, 692881, 693217, 693553, + 693889, 693659, 693993, 693759, 694660, 694424, 694185, 695087, 694846, 695176, 694931, 695835, + 695588, 695338, 696243, 695991, 696317, 696061, 696968, 696710, 697034, 696772, 697094, 697416, + 697738, 697470, 697790, 698110, 698430, 698156, 698474, 698792, 698513, 699427, 699146, 698862, + 699777, 699491, 699805, 700119, 699828, 700140, 700452, 700764, 700467, 700777, 701087, 701397, + 701094, 701402, 701710, 702018, 701709, 702015, 702321, 702627, 702312, 702616, 702920, 703224, + 702903, 703205, 703507, 703809, 703482, 703782, 704082, 704382, 704682, 704348, 704646, 704944, + 704605, 704901, 705836, 704854, 705789, 705443, 706380, 705388, 706325, 706619, 706266, 706558, + 706850, 706492, 707433, 707073, 707363, 706999, 707942, 707576, 707864, 708152, 707781, 708727, + 708354, 708640, 708926, 708548, 708832, 709116, 709400, 709684, 709299, 710251, 709864, 709474, + 710427, 710035, 710990, 710596, 710199, 711155, 710756, 711034, 711312, 711590, 711868, 711462, + 711738, 712014, 712290, 711878, 712841, 712427, 712701, 712283, 713248, 712828, 713100, 713372, + 713644, 713916, 713489, 713759, 714029, 714299, 713866, 714838, 714403, 714671, 714939, 714499, + 715474, 715032, 715298, 715564, 715830, 715382, 716361, 715911, 716175, 716439, 715984, 716966, + 716509, 716771, 717033, 716571, 717556, 717092, 717352, 717612, 717872, 718132, 717661, 717919, + 718177, 718435, 718693, 718951, 718472, 718728, 718984, 719240, 719496, 719010, 720007, 719519, + 719773, 720027, 719534, 720534, 720039, 720291, 720543, 720795, 721047, 720545, 720795, 721801, + 721296, 720788, 721795, 722045, 721534, 721782, 722030, 722278, 722526, 722008, 722254, 723268, + 722747, 722993, 722468, 723484, 722957, 723201, 723445, 723689, 723933, 724177, 723642, 723884, + 724907, 724369, 723828, 724852, 725094, 724550, 724790, 725030, 725270, 725510, 725750, 725198, + 725436, 725674, 725912, 726150, 726388, 726626, 726065, 726301, 726537, 726773, 727009, 727245, + 726676, 727716, 727145, 727379, 727613, 727847, 727270, 728314, 727735, 728781, 728200, 728432, + 727847, 728895, 729127, 728539, 728769, 728999, 729229, 729459, 729689, 729093, 730148, 729550, + 729778, 730006, 730234, 730462, 729857, 730917, 730310, 730536, 730762, 730988, 731214, 730600, + 731665, 731049, 731273, 731497, 731721, 731945, 732169, 731545, 732616, 731990, 732212, 732434, + 732656, 732878, 733100, 732466, 733543, 732907, 733127, 733347, 733567, 733787, 733144, 734226, + 733581, 733799, 734884, 734236, 733585, 734671, 734889, 734235, 735324, 734668, 734884, 735100, + 735316, 735532, 734869, 735963, 735298, 735512, 735726, 735940, 736154, 736368, 736582, 735908, + 737009, 736333, 736545, 736757, 736969, 737181, 737393, 736709, 737816, 737130, 737340, 737550, + 737760, 737970, 738180, 738390, 737695, 738809, 738112, 738320, 738528, 738736, 738944, 739152, + 738447, 739567, 738860, 739982, 739273, 739479, 739685, 739891, 739176, 740302, 739585, 740713, + 739994, 740198, 740402, 740606, 740810, 741014, 740287, 741421, 740692, 740894, 742031, 741299, + 741501, 741703, 740966, 742106, 741367, 742509, 741768, 741968, 742168, 742368, 742568, 742768, + 742968, 742218, 743367, 742615, 743766, 743012, 743210, 743408, 743606, 742846, 744001, 743239, + 744396, 743632, 743828, 744988, 744221, 744417, 743646, 744808, 745004, 744230, 745395, 744619, + 744813, 745007, 745201, 745395, 745589, 745783, 744998, 746170, 745383, 746557, 745768, 745960, + 746152, 746344, 746536, 746728, 745931, 747111, 746312, 747494, 746693, 746883, 747073, 747263, + 747453, 747643, 747833, 747023, 748212, 747400, 747588, 748780, 747965, 748153, 748341, 748529, + 747708, 748904, 748081, 749279, 748454, 749654, 748827, 749013, 749199, 749385, 749571, 748737, + 749942, 750128, 749291, 750499, 749660, 749844, 750028, 750212, 750396, 750580, 750764, 749916, + 751131, 750281, 751498, 750646, 750828, 751010, 751192, 751374, 751556, 751738, 751920, 751058, + 752283, 751419, 752646, 751780, 751960, 752140, 752320, 752500, 752680, 752860, 751985, 753219, + 752342, 753578, 752699, 752877, 754116, 753234, 753412, 752526, 753767, 753945, 754123, 753233, + 754478, 753586, 753762, 755010, 754115, 754291, 754467, 754643, 754819, 753917, 755170, 755346, + 754441, 755697, 754790, 754964, 755138, 756398, 755487, 754573, 755834, 756008, 756182, 755264, + 756529, 755609, 756876, 755954, 756126, 757396, 756471, 756643, 755714, 756986, 757158, 757330, + 756397, 757673, 756738, 758016, 757079, 757249, 757419, 757589, 757759, 757929, 758099, 758269, + 758439, 757491, 758778, 757828, 759117, 758165, 758333, 758501, 758669, 758837, 759005, 759173, + 759341, 759509, 758546, 759844, 758879, 760179, 759212, 759378, 760681, 759711, 759877, 760043, + 760209, 759233, 760540, 760706, 759727, 761037, 760056, 761368, 760385, 760549, 761864, 760878, + 761042, 761206, 761370, 760378, 761697, 761861, 760866, 762188, 761191, 762515, 761516, 761678, + 763005, 762003, 762165, 762327, 762489, 762651, 761642, 762974, 763136, 762124, 763459, 762445, + 763782, 762766, 762926, 763086, 763246, 763406, 763566, 763726, 763886, 764046, 763019, 764365, + 764525, 763495, 764844, 763812, 763970, 764128, 765481, 764445, 764603, 764761, 764919, 763877, + 765234, 765392, 764347, 765707, 764660, 766022, 764973, 766337, 765286, 765442, 765598, 765754, + 765910, 766066, 766222, 766378, 765317, 766689, 766845, 765781, 767156, 766090, 766244, 767622, + 766553, 766707, 766861, 767015, 767169, 767323, 767477, 767631, 766552, 767938, 768092, 767010, + 768399, 767315, 767467, 768859, 767772, 767924, 768076, 768228, 768380, 768532, 768684, 768836, + 767739, 769139, 769291, 768191, 769594, 768492, 768642, 770048, 768943, 769093, 769243, 769393, + 769543, 769693, 769843, 769993, 770143, 770293, 769176, 770592, 769473, 770891, 769770, 771190, + 770067, 770215, 770363, 770511, 771936, 770808, 769677, 771103, 771251, 771399, 771547, 770411, + 771842, 771990, 770851, 770997, 772432, 771290, 771436, 772874, 771729, 771875, 772021, 772167, + 772313, 772459, 772605, 771451, 772896, 773042, 771885, 773333, 772174, 773624, 772463, 772607, + 774060, 772896, 773040, 773184, 773328, 773472, 773616, 773760, 773904, 772730, 774191, 774335, + 773158, 774622, 773443, 774909, 773728, 775196, 774013, 774155, 774297, 774439, 774581, 774723, + 774865, 775007, 775149, 775291, 775433, 774237, 775716, 775858, 774659, 776141, 774940, 775080, + 776565, 775361, 775501, 775641, 777130, 775922, 776062, 776202, 774989, 776481, 776621, 776761, + 776901, 775683, 777180, 775960, 777459, 776237, 777738, 776514, 776652, 778156, 776929, 777067, + 777205, 777343, 777481, 777619, 777757, 777895, 776658, 778170, 778308, 778446, 777205, 778721, + 777478, 778996, 777751, 777887, 779408, 778160, 778296, 778432, 778568, 778704, 778840, 778976, + 779112, 779248, 779384, 779520, 778259, 779791, 779927, 778663, 780198, 778932, 779066, 780604, + 779335, 779469, 781010, 779738, 779872, 780006, 780140, 780274, 780408, 780542, 780676, 779394, + 780943, 781077, 781211, 779925, 781478, 780190, 781745, 780455, 782012, 780720, 780852, 780984, + 782545, 781249, 781381, 781513, 781645, 781777, 781909, 782041, 780736, 782304, 782436, 782568, + 781259, 782831, 781520, 783094, 781781, 783357, 782042, 782172, 783751, 782433, 782563, 782693, + 782823, 782953, 783083, 783213, 783343, 783473, 783603, 783733, 782402, 783992, 784122, 782788, + 784381, 783045, 784640, 783302, 784899, 783559, 783687, 785287, 783944, 784072, 784200, 784328, + 784456, 784584, 784712, 784840, 784968, 785096, 785224, 783868, 785479, 785607, 784248, 785862, + 784501, 786117, 784754, 786372, 785007, 785133, 786754, 785386, 785512, 785638, 785764, 785890, + 786016, 786142, 786268, 786394, 786520, 786646, 785265, 786897, 787023, 785639, 787274, 787400, + 786013, 787651, 786262, 786386, 788027, 786635, 786759, 788403, 787008, 787132, 787256, 787380, + 787504, 787628, 787752, 787876, 788000, 788124, 786717, 788371, 788495, 787085, 788742, 788866, + 787453, 789113, 787698, 789360, 787943, 788065, 789730, 788310, 788432, 788554, 788676, 788798, + 788920, 789042, 789164, 789286, 789408, 789530, 789652, 789774, 789896, 788460, 790139, 788701, + 790382, 790504, 789063, 790747, 789304, 789424, 791111, 789665, 789785, 791475, 790026, 790146, + 790266, 790386, 790506, 790626, 790746, 790866, 790986, 791106, 791226, 791346, 789883, 791585, + 791705, 790239, 791944, 790476, 792183, 790713, 792422, 790950, 792661, 791187, 791305, 793019, + 791542, 791660, 791778, 791896, 792014, 792132, 792250, 792368, 792486, 792604, 792722, 792840, + 792958, 791466, 793193, 793311, 791816, 793546, 793664, 792166, 793899, 792399, 792515, 794251, + 792748, 792864, 794603, 793097, 793213, 793329, 793445, 795189, 793678, 793794, 793910, 794026, + 792509, 794257, 794373, 794489, 794605, 794721, 793198, 794952, 795068, 793542, 795299, 793771, + 795530, 794000, 795761, 794229, 794343, 796107, 794572, 794686, 794800, 796568, 795029, 795143, + 795257, 795371, 795485, 795599, 795713, 795827, 795941, 796055, 794504, 796282, 796396, 796510, + 794955, 796737, 795180, 796964, 797078, 795518, 795630, 797418, 795855, 797645, 796080, 796192, + 797985, 796417, 796529, 796641, 796753, 796865, 796977, 797089, 797201, 797313, 797425, 797537, + 797649, 797761, 797873, 796289, 798096, 798208, 798320, 796732, 798543, 796953, 798766, 797174, + 798989, 797395, 799212, 797616, 797726, 799546, 797947, 798057, 798167, 799991, 798388, 798498, + 798608, 798718, 798828, 798938, 799048, 799158, 799268, 799378, 799488, 797872, 799707, 799817, + 799927, 798307, 800146, 798524, 800365, 800475, 798850, 800694, 799067, 799175, 801022, 799392, + 799500, 801350, 799717, 799825, 799933, 801787, 800150, 800258, 800366, 800474, 800582, 800690, + 800798, 800906, 801014, 801122, 799473, 801337, 801445, 801553, 799900, 801768, 801876, 800220, + 802091, 800433, 802306, 800646, 802521, 800859, 802736, 801072, 801178, 803058, 801391, 801497, + 803380, 801710, 801816, 801922, 802028, 802134, 802240, 802346, 802452, 802558, 802664, 802770, + 802876, 802982, 803088, 801402, 803299, 803405, 801716, 803616, 803722, 802030, 803933, 802239, + 804144, 802448, 804355, 802657, 804566, 802866, 802970, 804882, 803179, 803283, 805198, 803492, + 803596, 803700, 803804, 803908, 804012, 804116, 804220, 804324, 804428, 804532, 804636, 804740, + 804844, 803122, 805051, 805155, 805259, 803533, 805466, 805570, 803841, 805777, 804046, 805984, + 804251, 806191, 804456, 806398, 804661, 804763, 806708, 804968, 805070, 805172, 807121, 805377, + 805479, 805581, 805683, 805785, 805887, 805989, 806091, 806193, 806295, 806397, 806499, 806601, + 806703, 804943, 806906, 807008, 807110, 805346, 807313, 805547, 807516, 807618, 805849, 807821, + 806050, 808024, 806251, 808227, 806452, 806552, 808531, 806753, 806853, 806953, 808936, 807154, + 807254, 807354, 807454, 807554, 807654, 807754, 809745, 806063, 808054, 808154, 808254, 808354, + 808454, 808554, 808654, 806854, 808853, 808953, 809053, 807249, 809252, 809352, 807545, 809551, + 807742, 809750, 807939, 809949, 808136, 810148, 808333, 808431, 810446, 808628, 808726, 808824, + 810843, 809021, 809119, 809217, 809315, 809413, 811438, 809610, 809708, 809806, 809904, 810002, + 808167, 810197, 810295, 810393, 810491, 810589, 810687, 808845, 810882, 810980, 809135, 811175, + 811273, 809425, 811468, 809618, 811663, 809811, 811858, 810004, 812053, 810197, 812248, 810390, + 810486, 810582, 812637, 810775, 810871, 810967, 813026, 811160, 811256, 811352, 811448, 811544, + 811640, 811736, 811832, 811928, 812024, 812120, 812216, 812312, 812408, 810526, 812599, 812695, + 812791, 810905, 812982, 813078, 811189, 813269, 813365, 811473, 813556, 811662, 813747, 811851, + 813938, 812040, 812134, 814224, 812323, 814415, 812512, 812606, 812700, 814796, 812889, 812983, + 813077, 813171, 813265, 815367, 813454, 813548, 813642, 813736, 813830, 813924, 814018, 814112, + 812189, 814299, 814393, 814487, 814581, 812653, 814768, 814862, 814956, 813024, 815143, 815237, + 813302, 815424, 813487, 815611, 813672, 815798, 813857, 815985, 814042, 816172, 814227, 814319, + 816452, 814504, 814596, 816732, 814781, 814873, 814965, 817105, 815150, 815242, 815334, 815426, + 815518, 815610, 815702, 815794, 815886, 815978, 816070, 816162, 816254, 816346, 814375, 816529, + 816621, 816713, 816805, 814829, 816988, 817080, 815101, 817263, 817355, 815373, 817538, 815554, + 817721, 815735, 817904, 815916, 818087, 816097, 818270, 816278, 816368, 818544, 816549, 816639, + 818818, 816820, 816910, 817000, 817090, 819274, 817271, 817361, 817451, 817541, 817631, 817721, + 817811, 817901, 817991, 818081, 818171, 818261, 818351, 818441, 818531, 816511, 818710, 818800, + 818890, 816866, 819069, 819159, 817132, 819338, 819428, 817398, 819607, 819697, 817664, 819876, + 817841, 820055, 818018, 818106, 820323, 818283, 820502, 818460, 818548, 820770, 818725, 818813, + 821038, 818990, 819078, 819166, 819254, 819342, 821573, 819519, 819607, 819695, 819783, 819871, + 819959, 820047, 820135, 820223, 820311, 820399, 820487, 818419, 820662, 820750, 820838, 820926, + 818853, 821101, 821189, 821277, 819200, 821452, 821540, 819460, 821715, 819633, 821890, 821978, + 819893, 822153, 820066, 820152, 822415, 820325, 822590, 820498, 820584, 822852, 820757, 820843, + 823114, 821016, 821102, 821188, 823463, 821361, 821447, 821533, 821619, 821705, 821791, 824073, + 821964, 822050, 822136, 822222, 822308, 820192, 822479, 822565, 822651, 822737, 822823, 822909, + 822995, 820871, 823166, 823252, 823338, 821210, 823509, 823595, 821464, 823766, 823852, 821718, + 824023, 821887, 824194, 822056, 824365, 822225, 824536, 822394, 824707, 822563, 824878, 822732, + 822816, 825134, 822985, 823069, 823153, 825475, 823322, 823406, 823490, 825816, 823659, 823743, + 823827, 823911, 823995, 824079, 824163, 824247, 824331, 824415, 824499, 824583, 824667, 824751, + 824835, 824919, 825003, 825087, 822910, 825254, 825338, 825422, 825506, 823324, 825673, 825757, + 823572, 825924, 826008, 823820, 826175, 826259, 824068, 826426, 824233, 826593, 824398, 826760, + 824563, 826927, 824728, 824810, 827177, 824975, 825057, 827427, 825222, 825304, 827677, 825469, + 825551, 825633, 828010, 825798, 825880, 825962, 826044, 826126, 828509, 826291, 826373, 826455, + 826537, 826619, 826701, 826783, 826865, 826947, 827029, 824799, 827192, 827274, 827356, 827438, + 827520, 825284, 827683, 827765, 827847, 825607, 828010, 828092, 828174, 825930, 828337, 826091, + 828500, 828582, 826333, 828745, 826494, 828908, 826655, 829071, 826816, 829234, 826977, 829397, + 827138, 827218, 829641, 827379, 827459, 829885, 827620, 827700, 830129, 827861, 827941, 828021, + 828101, 830535, 828262, 828342, 828422, 828502, 828582, 828662, 828742, 828822, 828902, 828982, + 829062, 829142, 829222, 829302, 829382, 829462, 829542, 829622, 829702, 827408, 829861, 829941, + 830021, 830101, 827802, 830260, 830340, 830420, 828117, 830579, 830659, 828353, 830818, 828510, + 830977, 831057, 828746, 831216, 828903, 831375, 829060, 831534, 829217, 831693, 829374, 829452, + 831931, 829609, 829687, 832169, 829844, 829922, 832407, 830079, 830157, 830235, 832724, 830392, + 830470, 830548, 830626, 833120, 830783, 830861, 830939, 831017, 831095, 831173, 831251, 831329, + 831407, 831485, 831563, 831641, 831719, 831797, 831875, 831953, 832031, 829675, 832186, 832264, + 832342, 832420, 830059, 832575, 832653, 832731, 830366, 832886, 832964, 830596, 833119, 833197, + 830826, 833352, 830979, 833507, 833585, 831209, 833740, 831362, 833895, 831515, 834050, 831668, + 831744, 834282, 831897, 834437, 832050, 832126, 834669, 832279, 832355, 834901, 832508, 832584, + 832660, 835210, 832813, 832889, 832965, 833041, 833117, 835673, 833270, 833346, 833422, 833498, + 833574, 833650, 833726, 833802, 833878, 833954, 834030, 834106, 834182, 834258, 834334, 834410, + 831989, 834561, 834637, 834713, 834789, 834865, 832438, 835016, 835092, 835168, 832737, 835319, + 835395, 832961, 835546, 835622, 833185, 835773, 835849, 833409, 836000, 833558, 836151, 833707, + 836302, 833856, 836453, 834005, 836604, 834154, 836755, 834303, 834377, 836981, 834526, 837132, + 834675, 834749, 837358, 834898, 834972, 835046, 837659, 835195, 835269, 835343, 835417, 838035, + 835566, 835640, 835714, 835788, 835862, 835936, 836010, 836084, 836158, 838786, 836307, 836381, + 836455, 833971, 836602, 836676, 836750, 836824, 836898, 836972, 837046, 837120, 837194, 834700, + 837341, 837415, 837489, 837563, 835064, 837710, 837784, 835282, 837931, 838005, 838079, 835573, + 838226, 835718, 838373, 838447, 835936, 838594, 836081, 838741, 836226, 838888, 836371, 839035, + 836516, 839182, 836661, 839329, 836806, 839476, 836951, 837023, 839696, 837168, 837240, 839916, + 837385, 837457, 837529, 840209, 837674, 837746, 837818, 840502, 837963, 838035, 838107, 838179, + 838251, 840941, 838396, 838468, 838540, 838612, 838684, 838756, 838828, 838900, 838972, 839044, + 839116, 839188, 839260, 839332, 839404, 839476, 839548, 836984, 839691, 839763, 839835, 839907, + 839979, 837409, 840122, 840194, 840266, 837692, 840409, 840481, 840553, 837975, 840696, 840768, + 838187, 840911, 838328, 841054, 841126, 838540, 841269, 838681, 841412, 838822, 841555, 838963, + 841698, 839104, 841841, 839245, 841984, 839386, 842127, 839527, 839597, 842341, 839738, 839808, + 842555, 839949, 840019, 842769, 840160, 840230, 840300, 843054, 840441, 840511, 840581, 840651, + 843410, 840792, 840862, 840932, 841002, 841072, 841142, 841212, 841282, 844050, 841423, 841493, + 841563, 841633, 841703, 841773, 839138, 841912, 841982, 842052, 842122, 842192, 842262, 842332, + 842402, 842472, 839827, 842611, 842681, 842751, 842821, 840171, 842960, 843030, 843100, 840446, + 843239, 843309, 840652, 843448, 843518, 840858, 843657, 843727, 841064, 843866, 841201, 844005, + 841338, 844144, 841475, 844283, 844353, 841681, 841749, 844561, 841886, 844700, 842023, 844839, + 842160, 842228, 845047, 842365, 845186, 842502, 842570, 845394, 842707, 842775, 842843, 845671, + 842980, 843048, 843116, 845948, 843253, 843321, 843389, 843457, 843525, 846363, 843662, 843730, + 843798, 843866, 843934, 844002, 844070, 844138, 844206, 844274, 844342, 844410, 844478, 844546, + 844614, 844682, 844750, 844818, 844886, 844954, 845022, 845090, 842365, 845225, 845293, 845361, + 845429, 845497, 842766, 845632, 845700, 845768, 843033, 845903, 845971, 843233, 846106, 846174, + 843433, 846309, 846377, 843633, 846512, 846580, 843833, 846715, 843966, 846850, 844099, 846985, + 847053, 844299, 847188, 844432, 847323, 844565, 844631, 847525, 844764, 847660, 844897, 844963, + 847862, 845096, 847997, 845229, 845295, 848199, 845428, 845494, 845560, 848468, 845693, 845759, + 848670, 845892, 845958, 846024, 846090, 849006, 846223, 846289, 846355, 846421, 846487, 846553, + 846619, 849543, 846752, 846818, 846884, 846950, 847016, 847082, 847148, 847214, 847280, 847346, + 847412, 847478, 847544, 847610, 844803, 847741, 847807, 847873, 847939, 848005, 848071, 848137, + 845322, 848268, 848334, 848400, 848466, 845646, 848597, 848663, 848729, 845905, 848860, 848926, + 846099, 849057, 849123, 846293, 849254, 849320, 846487, 849451, 846616, 849582, 849648, 846810, + 849779, 846939, 849910, 847068, 850041, 847197, 850172, 847326, 850303, 847455, 850434, 847584, + 850565, 847713, 847777, 850761, 847906, 847970, 850957, 848099, 848163, 851153, 848292, 848356, + 851349, 848485, 848549, 848613, 851610, 848742, 848806, 848870, 851871, 848999, 849063, 849127, + 849191, 849255, 852262, 849384, 849448, 849512, 849576, 849640, 849704, 849768, 849832, 849896, + 849960, 850024, 850088, 850152, 850216, 850280, 850344, 850408, 850472, 850536, 850600, 850664, + 850728, 850792, 847889, 850919, 850983, 851047, 851111, 851175, 848266, 851302, 851366, 851430, + 851494, 848580, 851621, 851685, 851749, 848831, 851876, 851940, 849019, 852067, 852131, 849207, + 852258, 852322, 849395, 852449, 849520, 852576, 852640, 849708, 852767, 849833, 852894, 849958, + 853021, 850083, 853148, 850208, 853275, 850333, 853402, 850458, 850520, 853592, 850645, 853719, + 850770, 850832, 853909, 850957, 854036, 851082, 851144, 851206, 854289, 851331, 851393, 854479, + 851518, 851580, 851642, 854732, 851767, 851829, 851891, 851953, 855048, 852078, 852140, 852202, + 852264, 852326, 852388, 855490, 852513, 852575, 852637, 852699, 852761, 852823, 852885, 852947, + 853009, 853071, 853133, 853195, 853257, 853319, 853381, 853443, 853505, 853567, 853629, 853691, + 850692, 853814, 853876, 853938, 854000, 854062, 854124, 851118, 854247, 854309, 854371, 854433, + 851422, 854556, 854618, 854680, 851665, 854803, 854865, 854927, 851908, 855050, 855112, 852090, + 855235, 855297, 852272, 855420, 852393, 855543, 855605, 852575, 855728, 852696, 855851, 852817, + 855974, 852938, 856097, 853059, 856220, 853180, 856343, 853301, 856466, 853422, 856589, 853543, + 856712, 853664, 853724, 856896, 853845, 857019, 853966, 854026, 857203, 854147, 854207, 854267, + 857448, 854388, 854448, 857632, 854569, 854629, 854689, 857877, 854810, 854870, 854930, 854990, + 858183, 855111, 855171, 855231, 855291, 855351, 858550, 855472, 855532, 855592, 855652, 855712, + 855772, 855832, 855892, 855952, 856012, 856072, 856132, 856192, 856252, 856312, 856372, 856432, + 856492, 856552, 856612, 856672, 856732, 856792, 856852, 856912, 853807, 857031, 857091, 857151, + 857211, 857271, 857331, 854219, 857450, 857510, 857570, 854454, 857689, 857749, 857809, 854689, + 857928, 857988, 858048, 854924, 858167, 858227, 855100, 858346, 858406, 855276, 858525, 858585, + 855452, 858704, 855569, 858823, 858883, 855745, 859002, 855862, 859121, 855979, 859240, 856096, + 859359, 856213, 859478, 856330, 859597, 856447, 859716, 856564, 859835, 856681, 856739, 860013, + 856856, 860132, 856973, 857031, 860310, 857148, 857206, 860488, 857323, 857381, 860666, 857498, + 857556, 860844, 857673, 857731, 857789, 861081, 857906, 857964, 858022, 858080, 861377, 858197, + 858255, 858313, 858371, 858429, 861732, 858546, 858604, 858662, 858720, 858778, 858836, 858894, + 858952, 859010, 862323, 859127, 859185, 859243, 859301, 859359, 859417, 859475, 859533, 859591, + 859649, 856441, 859764, 859822, 859880, 859938, 859996, 860054, 860112, 860170, 860228, 860286, + 857067, 860401, 860459, 860517, 860575, 860633, 857408, 860748, 860806, 860864, 857635, 860979, + 861037, 861095, 857862, 861210, 861268, 861326, 858089, 861441, 861499, 858259, 861614, 861672, + 858429, 861787, 861845, 858599, 861960, 858712, 862075, 862133, 858882, 862248, 858995, 862363, + 859108, 862478, 859221, 862593, 859334, 862708, 859447, 862823, 859560, 862938, 859673, 863053, + 859786, 863168, 859899, 863283, 860012, 860068, 863455, 860181, 860237, 863627, 860350, 863742, + 860463, 860519, 863914, 860632, 860688, 860744, 864143, 860857, 860913, 864315, 861026, 861082, + 861138, 861194, 864601, 861307, 861363, 861419, 861475, 864887, 861588, 861644, 861700, 861756, + 861812, 865230, 861925, 861981, 862037, 862093, 862149, 862205, 862261, 862317, 862373, 862429, + 862485, 862541, 862597, 862653, 862709, 862765, 862821, 862877, 862933, 862989, 863045, 863101, + 863157, 863213, 863269, 863325, 863381, 863437, 863493, 860157, 863604, 863660, 863716, 863772, + 863828, 863884, 860541, 863995, 864051, 864107, 864163, 860815, 864274, 864330, 864386, 861034, + 864497, 864553, 864609, 861253, 864720, 864776, 861417, 864887, 864943, 861581, 865054, 865110, + 861745, 865221, 865277, 861909, 865388, 862018, 865499, 865555, 862182, 865666, 862291, 865777, + 862400, 865888, 865944, 862564, 866055, 862673, 866166, 862782, 866277, 862891, 862945, 866443, + 863054, 866554, 863163, 866665, 863272, 866776, 863381, 863435, 866942, 863544, 863598, 867108, + 863707, 867219, 863816, 863870, 863924, 867440, 864033, 864087, 867606, 864196, 864250, 867772, + 864359, 864413, 864467, 867993, 864576, 864630, 864684, 864738, 868269, 864847, 864901, 864955, + 865009, 865063, 868600, 865172, 865226, 865280, 865334, 865388, 865442, 865496, 869041, 865605, + 865659, 865713, 865767, 865821, 865875, 865929, 865983, 866037, 866091, 866145, 866199, 866253, + 866307, 866361, 866415, 866469, 866523, 866577, 866631, 866685, 863226, 866792, 866846, 866900, + 866954, 867008, 867062, 867116, 867170, 863702, 867277, 867331, 867385, 867439, 867493, 864019, + 867600, 867654, 867708, 864230, 867815, 867869, 867923, 864441, 868030, 868084, 868138, 864652, + 868245, 868299, 864810, 868406, 868460, 864968, 868567, 868621, 865126, 868728, 868782, 865284, + 868889, 868943, 865442, 869050, 865547, 869157, 865652, 869264, 869318, 865810, 869425, 865915, + 869532, 866020, 869639, 866125, 869746, 866230, 869853, 866335, 869960, 866440, 870067, 866545, + 866597, 870227, 866702, 870334, 866807, 870441, 866912, 866964, 870601, 867069, 867121, 870761, + 867226, 867278, 870921, 867383, 867435, 871081, 867540, 867592, 871241, 867697, 867749, 867801, + 871454, 867906, 867958, 868010, 871667, 868115, 868167, 868219, 871880, 868324, 868376, 868428, + 868480, 868532, 872199, 868637, 868689, 868741, 868793, 868845, 868897, 872571, 869002, 869054, + 869106, 869158, 869210, 869262, 869314, 869366, 869418, 869470, 869522, 869574, 869626, 869678, + 869730, 869782, 869834, 869886, 869938, 869990, 870042, 870094, 870146, 870198, 870250, 870302, + 870354, 870406, 870458, 866858, 870561, 870613, 870665, 870717, 870769, 870821, 867214, 870924, + 870976, 871028, 871080, 871132, 867519, 871235, 871287, 871339, 867722, 871442, 871494, 871546, + 871598, 867976, 871701, 871753, 868128, 871856, 871908, 871960, 868331, 872063, 872115, 868483, + 872218, 872270, 868635, 872373, 868736, 872476, 872528, 868888, 872631, 872683, 869040, 872786, + 869141, 872889, 869242, 872992, 873044, 869394, 873147, 869495, 873250, 869596, 873353, 869697, + 873456, 869798, 873559, 869899, 873662, 870000, 873765, 870101, 870151, 873919, 870252, 874022, + 870353, 874125, 870454, 870504, 874279, 870605, 870655, 874433, 870756, 874536, 870857, 870907, + 874690, 871008, 871058, 871108, 874895, 871209, 871259, 875049, 871360, 871410, 871460, 875254, + 871561, 871611, 871661, 875459, 871762, 871812, 871862, 875664, 871963, 872013, 872063, 872113, + 872163, 875971, 872264, 872314, 872364, 872414, 872464, 872514, 876329, 872615, 872665, 872715, + 872765, 872815, 872865, 872915, 872965, 873015, 873065, 873115, 873165, 873215, 873265, 873315, + 877146, 873416, 873466, 869732, 873565, 873615, 873665, 873715, 873765, 873815, 873865, 873915, + 873965, 874015, 874065, 874115, 874165, 874215, 874265, 870515, 874364, 874414, 874464, 874514, + 874564, 874614, 870857, 874713, 874763, 874813, 874863, 874913, 871150, 875012, 875062, 875112, + 871345, 875211, 875261, 875311, 875361, 871589, 875460, 875510, 871735, 875609, 875659, 875709, + 871930, 875808, 875858, 872076, 875957, 876007, 872222, 876106, 876156, 872368, 876255, 872465, + 876354, 876404, 872611, 876503, 876553, 872757, 876652, 872854, 876751, 872951, 876850, 873048, + 876949, 876999, 873194, 877098, 873291, 877197, 873388, 877296, 873485, 877395, 873582, 877494, + 873679, 873727, 877642, 873824, 877741, 873921, 877840, 874018, 877939, 874115, 874163, 878087, + 874260, 878186, 874357, 874405, 878334, 874502, 874550, 878482, 874647, 874695, 878630, 874792, + 874840, 878778, 874937, 874985, 878926, 875082, 875130, 875178, 879123, 875275, 875323, 875371, + 879320, 875468, 875516, 875564, 879517, 875661, 875709, 875757, 875805, 879763, 875902, 875950, + 875998, 876046, 876094, 876142, 880107, 876239, 876287, 876335, 876383, 876431, 876479, 876527, + 880500, 876624, 876672, 876720, 876768, 876816, 876864, 876912, 876960, 877008, 877056, 877104, + 877152, 877200, 877248, 877296, 877344, 877392, 877440, 877488, 877536, 877584, 877632, 877680, + 877728, 877776, 877824, 877872, 877920, 877968, 874061, 878063, 878111, 878159, 878207, 878255, + 878303, 878351, 874436, 878446, 878494, 878542, 878590, 878638, 878686, 874764, 878781, 878829, + 878877, 878925, 874998, 879020, 879068, 879116, 875185, 879211, 879259, 879307, 875372, 879402, + 879450, 879498, 875559, 879593, 879641, 875699, 879736, 879784, 879832, 875886, 879927, 879975, + 876026, 880070, 876119, 880165, 880213, 876259, 880308, 880356, 876399, 880451, 876492, 880546, + 880594, 876632, 880689, 876725, 880784, 876818, 880879, 880927, 876958, 881022, 877051, 881117, + 877144, 881212, 877237, 881307, 877330, 881402, 877423, 881497, 877516, 881592, 877609, 881687, + 877702, 877748, 881829, 877841, 881924, 877934, 882019, 878027, 878073, 882161, 878166, 878212, + 882303, 878305, 882398, 878398, 878444, 882540, 878537, 878583, 882682, 878676, 878722, 882824, + 878815, 878861, 882966, 878954, 879000, 879046, 883155, 879139, 879185, 879231, 883344, 879324, + 879370, 879416, 883533, 879509, 879555, 879601, 883722, 879694, 879740, 879786, 879832, 879878, + 884005, 879971, 880017, 880063, 880109, 880155, 884288, 880248, 880294, 880340, 880386, 880432, + 880478, 880524, 880570, 884712 +}; + +static INLINE long long bsc_entropy(int n) +{ + if (n < 0x1000) return (long long) n * bsc_code_table[n]; + if (n < 0x100000) return (long long) n * (8 * 65536 + bsc_code_table[n >> 8]); + if (n < 0x10000000) return (long long) n * (16 * 65536 + bsc_code_table[n >> 16]); + return (long long) n * (20 * 65536 + bsc_code_table[n >> 20]); +} + +static INLINE long long bsc_delta(int n) +{ + if (n < 0x1000) return (long long) bsc_delta_table[n]; + if ((n & 0xff) != 0xff) + { + if (n < 0x100000) return (long long)(bsc_code_table[n >> 8] + 8 * 65536); + if (n < 0x10000000) return (long long)(bsc_code_table[n >> 16] + 16 * 65536); + return (long long)(bsc_code_table[n >> 20] + 20 * 65536); + } + return bsc_entropy(n + 1) - bsc_entropy(n); +} + +#endif + +/*-----------------------------------------------------------*/ +/* End tables.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/libbsc.h b/bsc/libbsc/libbsc.h new file mode 100644 index 0000000..7261455 --- /dev/null +++ b/bsc/libbsc/libbsc.h @@ -0,0 +1,165 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to compression/decompression functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +/*-- + +Sort Transform is patented by Michael Schindler under US patent 6,199,064. +However for research purposes this algorithm is included in this software. +So if you are of the type who should worry about this (making money) worry away. +The author shall have no liability with respect to the infringement of +copyrights, trade secrets or any patents by this software. In no event will +the author be liable for any lost revenue or profits or other special, +indirect and consequential damages. + +Sort Transform is disabled by default and can be enabled by defining the +preprocessor macro LIBBSC_SORT_TRANSFORM_SUPPORT at compile time. + +--*/ + +#ifndef _LIBBSC_LIBBSC_H +#define _LIBBSC_LIBBSC_H + +#define LIBBSC_NO_ERROR 0 +#define LIBBSC_BAD_PARAMETER -1 +#define LIBBSC_NOT_ENOUGH_MEMORY -2 +#define LIBBSC_NOT_COMPRESSIBLE -3 +#define LIBBSC_NOT_SUPPORTED -4 +#define LIBBSC_UNEXPECTED_EOB -5 +#define LIBBSC_DATA_CORRUPT -6 + +#define LIBBSC_GPU_ERROR -7 +#define LIBBSC_GPU_NOT_SUPPORTED -8 +#define LIBBSC_GPU_NOT_ENOUGH_MEMORY -9 +#define LIBBSC_SKIP_DATA -10 + +#define LIBBSC_BLOCKSORTER_NONE 0 +#define LIBBSC_BLOCKSORTER_BWT 1 + +#ifdef LIBBSC_SORT_TRANSFORM_SUPPORT + + #define LIBBSC_BLOCKSORTER_ST3 3 + #define LIBBSC_BLOCKSORTER_ST4 4 + #define LIBBSC_BLOCKSORTER_ST5 5 + #define LIBBSC_BLOCKSORTER_ST6 6 + #define LIBBSC_BLOCKSORTER_ST7 7 + #define LIBBSC_BLOCKSORTER_ST8 8 + +#endif + +#define LIBBSC_CODER_NONE 0 +#define LIBBSC_CODER_QLFC_STATIC 1 +#define LIBBSC_CODER_QLFC_ADAPTIVE 2 + +#define LIBBSC_FEATURE_NONE 0 +#define LIBBSC_FEATURE_FASTMODE 1 +#define LIBBSC_FEATURE_MULTITHREADING 2 +#define LIBBSC_FEATURE_LARGEPAGES 4 +#define LIBBSC_FEATURE_CUDA 8 + +#define LIBBSC_DEFAULT_LZPHASHSIZE 16 +#define LIBBSC_DEFAULT_LZPMINLEN 128 +#define LIBBSC_DEFAULT_BLOCKSORTER LIBBSC_BLOCKSORTER_BWT +#define LIBBSC_DEFAULT_CODER LIBBSC_CODER_QLFC_STATIC +#define LIBBSC_DEFAULT_FEATURES LIBBSC_FEATURE_FASTMODE | LIBBSC_FEATURE_MULTITHREADING + +#define LIBBSC_HEADER_SIZE 28 + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * You should call this function before you call any of the other functions in libbsc. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_init(int features); + + /** + * Compress a memory block. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n + LIBBSC_HEADER_SIZE bytes. + * @param n - the length of the input memory block. + * @param lzpHashSize[0, 10..28] - the hash table size if LZP enabled, 0 otherwise. + * @param lzpMinLen[0, 4..255] - the minimum match length if LZP enabled, 0 otherwise. + * @param blockSorter[ST3..ST8, BWT] - the block sorting algorithm. + * @param coder[MTF or QLFC] - the entropy coding algorithm. + * @param features - the set of additional features. + * @return the length of compressed memory block if no error occurred, error code otherwise. + */ + int bsc_compress(unsigned char * input, unsigned char * output, int n, int lzpHashSize, int lzpMinLen, int blockSorter, int coder, int features); + + /** + * Store a memory block. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n + LIBBSC_HEADER_SIZE bytes. + * @param n - the length of the input memory block. + * @param features - the set of additional features. + * @return the length of stored memory block if no error occurred, error code otherwise. + */ + int bsc_store(const unsigned char * input, unsigned char * output, int n, int features); + + /** + * Determinate the sizes of input and output memory blocks for bsc_decompress function. + * @param blockHeader - the header of input(compressed) memory block of headerSize bytes. + * @param headerSize - the length of header, should be at least LIBBSC_HEADER_SIZE bytes. + * @param pBlockSize[out] - the length of the input memory block for bsc_decompress function. + * @param pDataSize[out] - the length of the output memory block for bsc_decompress function. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_block_info(unsigned char * blockHeader, int headerSize, int * pBlockSize, int * pDataSize, int features); + + /** + * Decompress a memory block. + * Note : You should call bsc_block_info function to determinate the sizes of input and output memory blocks. + * @param input - the input memory block of inputSize bytes. + * @param inputSize - the length of the input memory block. + * @param output - the output memory block of outputSize bytes. + * @param outputSize - the length of the output memory block. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_decompress(unsigned char * input, int inputSize, unsigned char * output, int outputSize, int features); + int bsc_decompress_old(const unsigned char * input, int inputSize, unsigned char * output, int outputSize, int features); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------*/ +/* End libbsc.h */ +/*-------------------------------------------------*/ diff --git a/bsc/libbsc/libbsc/libbsc.cpp b/bsc/libbsc/libbsc/libbsc.cpp new file mode 100644 index 0000000..6866aa7 --- /dev/null +++ b/bsc/libbsc/libbsc/libbsc.cpp @@ -0,0 +1,632 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Compression/decompression functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include +#include +#include + +#include "../platform/platform.h" +#include "../libbsc.h" + +#include "../adler32/adler32.h" +#include "../bwt/bwt.h" +#include "../lzp/lzp.h" +#include "../coder/coder.h" + +int bsc_init(int features) +{ + int result = LIBBSC_NO_ERROR; + + if (result == LIBBSC_NO_ERROR) result = bsc_platform_init(features); + if (result == LIBBSC_NO_ERROR) result = bsc_coder_init(features); + + return result; +} + +int bsc_store(const unsigned char * input, unsigned char * output, int n, int features) +{ + unsigned int adler32_data = bsc_adler32(input, n, features); + + memmove(output + LIBBSC_HEADER_SIZE, input, n); + *(int *)(output + 0) = n + LIBBSC_HEADER_SIZE; + *(int *)(output + 4) = n; + *(int *)(output + 8) = 0; + *(int *)(output + 12) = 0; + *(int *)(output + 16) = adler32_data; + *(int *)(output + 20) = adler32_data; + *(int *)(output + 24) = bsc_adler32(output, 24, features); + return n + LIBBSC_HEADER_SIZE; +} + +int bsc_compress_inplace(unsigned char * data, int n, int lzpHashSize, int lzpMinLen, int blockSorter, int coder, int features) +{ + int indexes[256]; + unsigned char num_indexes; + + int mode = 0; + + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : mode = LIBBSC_BLOCKSORTER_BWT; break; + + default : return LIBBSC_BAD_PARAMETER; + } + + switch (coder) + { + case LIBBSC_CODER_QLFC_STATIC: mode += (LIBBSC_CODER_QLFC_STATIC << 5); break; + case LIBBSC_CODER_QLFC_ADAPTIVE: mode += (LIBBSC_CODER_QLFC_ADAPTIVE << 5); break; + + default : return LIBBSC_BAD_PARAMETER; + } + + if (lzpMinLen != 0 || lzpHashSize != 0) + { + if (lzpMinLen < 4 || lzpMinLen > 255) return LIBBSC_BAD_PARAMETER; + if (lzpHashSize < 10 || lzpHashSize > 28) return LIBBSC_BAD_PARAMETER; + mode += (lzpMinLen << 8); + mode += (lzpHashSize << 16); + } + if (n < 0 || n > 1073741824) return LIBBSC_BAD_PARAMETER; + if (n <= LIBBSC_HEADER_SIZE) + { + return bsc_store(data, data, n, features); + } + + unsigned int adler32_data = bsc_adler32(data, n, features); + + int lzSize = n; + if (mode != (mode & 0xff)) + { + unsigned char * buffer = (unsigned char *)bsc_malloc(n); + if (buffer == NULL) return LIBBSC_NOT_ENOUGH_MEMORY; + + lzSize = bsc_lzp_compress(data, buffer, n, lzpHashSize, lzpMinLen, features); + if (lzSize < LIBBSC_NO_ERROR) + { + lzSize = n; mode &= 0xff; + } + else + { + memcpy(data, buffer, lzSize); + } + + bsc_free(buffer); + } + + if (lzSize <= LIBBSC_HEADER_SIZE) + { + blockSorter = LIBBSC_BLOCKSORTER_BWT; + mode = (mode & 0xffffffe0) | LIBBSC_BLOCKSORTER_BWT; + } + + int index = LIBBSC_BAD_PARAMETER; num_indexes = 0; + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : index = bsc_bwt_encode(data, lzSize, &num_indexes, indexes, features); break; + + default : return LIBBSC_BAD_PARAMETER; + } + + if (n < 64 * 1024) num_indexes = 0; + + if (index < LIBBSC_NO_ERROR) + { + return index; + } + + if (unsigned char * buffer = (unsigned char *)bsc_malloc(lzSize + 4096)) + { + int result = bsc_coder_compress(data, buffer, lzSize, coder, features); + if (result >= LIBBSC_NO_ERROR) memcpy(data + LIBBSC_HEADER_SIZE, buffer, result); + bsc_free(buffer); + if ((result < LIBBSC_NO_ERROR) || (result + 1 + 4 * num_indexes >= n)) + { + return LIBBSC_NOT_COMPRESSIBLE; + } + { + if (num_indexes > 0) + { + memcpy(data + LIBBSC_HEADER_SIZE + result, indexes, 4 * num_indexes); + } + data[LIBBSC_HEADER_SIZE + result + 4 * num_indexes] = num_indexes; + result += 1 + 4 * num_indexes; + } + *(int *)(data + 0) = result + LIBBSC_HEADER_SIZE; + *(int *)(data + 4) = n; + *(int *)(data + 8) = mode; + *(int *)(data + 12) = index; + *(int *)(data + 16) = adler32_data; + *(int *)(data + 20) = bsc_adler32(data + LIBBSC_HEADER_SIZE, result, features); + *(int *)(data + 24) = bsc_adler32(data, 24, features); + return result + LIBBSC_HEADER_SIZE; + } + + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_compress(unsigned char * input, unsigned char * output, int n, int lzpHashSize, int lzpMinLen, int blockSorter, int coder, int features) +{ + if (input == output) + { + return bsc_compress_inplace(output, n, lzpHashSize, lzpMinLen, blockSorter, coder, features); + } + + int indexes[256]; + unsigned char num_indexes; + + int mode = 0; + + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : mode = LIBBSC_BLOCKSORTER_BWT; break; + + default : return LIBBSC_BAD_PARAMETER; + } + + switch (coder) + { + case LIBBSC_CODER_QLFC_STATIC: mode += (LIBBSC_CODER_QLFC_STATIC << 5); break; + case LIBBSC_CODER_QLFC_ADAPTIVE: mode += (LIBBSC_CODER_QLFC_ADAPTIVE << 5); break; + + default : return LIBBSC_BAD_PARAMETER; + } + + if (lzpMinLen != 0 || lzpHashSize != 0) + { + if (lzpMinLen < 4 || lzpMinLen > 255) return LIBBSC_BAD_PARAMETER; + if (lzpHashSize < 10 || lzpHashSize > 28) return LIBBSC_BAD_PARAMETER; + mode += (lzpMinLen << 8); + mode += (lzpHashSize << 16); + } + if (n < 0 || n > 1073741824) return LIBBSC_BAD_PARAMETER; + if (n <= LIBBSC_HEADER_SIZE) + { + return (LIBBSC_SKIP_DATA); + } + int lzSize = 0; + if (mode != (mode & 0xff)) + { + lzSize = bsc_lzp_compress(input, output, n, lzpHashSize, lzpMinLen, features); + if (lzSize < LIBBSC_NO_ERROR || n - lzSize <= LIBBSC_HEADER_SIZE) + { + mode &= 0xff; + } + } + if (mode == (mode & 0xff)) + { + lzSize = n; memcpy(output, input, n); + } + + if (lzSize <= LIBBSC_HEADER_SIZE) + { + blockSorter = LIBBSC_BLOCKSORTER_BWT; + mode = (mode & 0xffffffe0) | LIBBSC_BLOCKSORTER_BWT; + } + + int index = LIBBSC_BAD_PARAMETER; num_indexes = 0; + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : index = bsc_bwt_encode(output, lzSize, &num_indexes, indexes, features); break; + + default : return LIBBSC_BAD_PARAMETER; + } + + if (n < 64 * 1024) num_indexes = 0; + + if (index < LIBBSC_NO_ERROR) + { + return index; + } + + int coded = 1; + int result = bsc_coder_compress(output, input, lzSize, coder, features); + if ((result < LIBBSC_NO_ERROR) || (result + 1 + 4 * num_indexes >= n)) { + coded = 0; + result = lzSize; + /* + * Original input has been destroyed so we have to decode BWT. + */ + bsc_bwt_decode(output, lzSize, index, num_indexes, indexes, features); + coded = 0; + if (mode == (mode & 0xff)) { + /* + * No coding, no LZP. No compression whatsoever. + */ + memcpy(input, output, n); + return (LIBBSC_SKIP_DATA); + } + /* + * At least LZP is successful. + */ + memmove(output + LIBBSC_HEADER_SIZE, output, result); + } else { + memcpy(output + LIBBSC_HEADER_SIZE, input, result); + } + if (coded > 0) { + if (num_indexes > 0) + { + memcpy(output + LIBBSC_HEADER_SIZE + result, indexes, 4 * num_indexes); + } + output[LIBBSC_HEADER_SIZE + result + 4 * num_indexes] = num_indexes; + result += 1 + 4 * num_indexes; + } + *(int *)(output + 0) = result + LIBBSC_HEADER_SIZE; + *(int *)(output + 4) = n; + *(int *)(output + 8) = mode; + *(int *)(output + 12) = index; + *(int *)(output + 16) = features; + *(int *)(output + 20) = coded; + *(int *)(output + 24) = bsc_adler32(output, 24, features); + return result + LIBBSC_HEADER_SIZE; + + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_block_info(unsigned char * blockHeader, int headerSize, int * pBlockSize, int * pDataSize, int features) +{ + if (headerSize < LIBBSC_HEADER_SIZE) + { + return LIBBSC_UNEXPECTED_EOB; + } + + if (*(unsigned int *)(blockHeader + 24) != bsc_adler32(blockHeader, 24, features)) + { + return LIBBSC_DATA_CORRUPT; + } + + int blockSize = *(int *)(blockHeader + 0); + int dataSize = *(int *)(blockHeader + 4); + int mode = *(int *)(blockHeader + 8); + int index = *(int *)(blockHeader + 12); + + int lzpHashSize = (mode >> 16) & 0xff; + int lzpMinLen = (mode >> 8) & 0xff; + int coder = (mode >> 5) & 0x7; + int blockSorter = (mode >> 0) & 0x1f; + + int test_mode = 0; + + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : test_mode = LIBBSC_BLOCKSORTER_BWT; break; + + default : if (blockSorter > 0) return LIBBSC_DATA_CORRUPT; + } + + switch (coder) + { + case LIBBSC_CODER_QLFC_STATIC: test_mode += (LIBBSC_CODER_QLFC_STATIC << 5); break; + case LIBBSC_CODER_QLFC_ADAPTIVE: test_mode += (LIBBSC_CODER_QLFC_ADAPTIVE << 5); break; + + default : return LIBBSC_BAD_PARAMETER; + } + + if (lzpMinLen != 0 || lzpHashSize != 0) + { + if (lzpMinLen < 4 || lzpMinLen > 255) return LIBBSC_DATA_CORRUPT; + if (lzpHashSize < 10 || lzpHashSize > 28) return LIBBSC_DATA_CORRUPT; + test_mode += (lzpMinLen << 8); + test_mode += (lzpHashSize << 16); + } + + if (test_mode != mode) + { + return LIBBSC_DATA_CORRUPT; + } + + if (blockSize < LIBBSC_HEADER_SIZE || blockSize > LIBBSC_HEADER_SIZE + dataSize) + { + return LIBBSC_DATA_CORRUPT; + } + + if (index < 0 || index > dataSize) + { + return LIBBSC_DATA_CORRUPT; + } + + if (pBlockSize != NULL) *pBlockSize = blockSize; + if (pDataSize != NULL) *pDataSize = dataSize; + + return LIBBSC_NO_ERROR; +} + +int bsc_decompress_inplace(unsigned char * data, int inputSize, int outputSize, int features) +{ + int indexes[256]; + unsigned char num_indexes; + + int blockSize = 0, dataSize = 0; + + int info = bsc_block_info(data, inputSize, &blockSize, &dataSize, features); + if (info != LIBBSC_NO_ERROR) + { + return info; + } + + if (inputSize < blockSize || outputSize < dataSize) + { + return LIBBSC_UNEXPECTED_EOB; + } + + if (*(unsigned int *)(data + 20) != bsc_adler32(data + LIBBSC_HEADER_SIZE, blockSize - LIBBSC_HEADER_SIZE, features)) + { + return LIBBSC_DATA_CORRUPT; + } + + int mode = *(int *)(data + 8); + if (mode == 0) + { + memmove(data, data + LIBBSC_HEADER_SIZE, dataSize); + return LIBBSC_NO_ERROR; + } + + int index = *(int *)(data + 12); + unsigned int adler32_data = *(int *)(data + 16); + + num_indexes = data[blockSize - 1]; + if (num_indexes > 0) + { + memcpy(indexes, data + blockSize - 1 - 4 * num_indexes, 4 * num_indexes); + } + + int lzpHashSize = (mode >> 16) & 0xff; + int lzpMinLen = (mode >> 8) & 0xff; + int coder = (mode >> 5) & 0x7; + int blockSorter = (mode >> 0) & 0x1f; + + int lzSize = LIBBSC_NO_ERROR; + { + unsigned char * buffer = (unsigned char *)bsc_malloc(blockSize); + if (buffer == NULL) return LIBBSC_NOT_ENOUGH_MEMORY; + + memcpy(buffer, data, blockSize); + + lzSize = bsc_coder_decompress(buffer + LIBBSC_HEADER_SIZE, data, coder, features); + + bsc_free(buffer); + } + if (lzSize < LIBBSC_NO_ERROR) + { + return lzSize; + } + + int result; + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : result = bsc_bwt_decode(data, lzSize, index, num_indexes, indexes, features); break; + + default : return LIBBSC_DATA_CORRUPT; + } + if (result < LIBBSC_NO_ERROR) + { + return result; + } + + if (mode != (mode & 0xff)) + { + if (unsigned char * buffer = (unsigned char *)bsc_malloc(lzSize)) + { + memcpy(buffer, data, lzSize); + result = bsc_lzp_decompress(buffer, data, lzSize, lzpHashSize, lzpMinLen, features); + bsc_free(buffer); + if (result < LIBBSC_NO_ERROR) + { + return result; + } + return result == dataSize ? (adler32_data == bsc_adler32(data, dataSize, features) ? LIBBSC_NO_ERROR : LIBBSC_DATA_CORRUPT) : LIBBSC_DATA_CORRUPT; + } + return LIBBSC_NOT_ENOUGH_MEMORY; + } + + return lzSize == dataSize ? (adler32_data == bsc_adler32(data, dataSize, features) ? LIBBSC_NO_ERROR : LIBBSC_DATA_CORRUPT) : LIBBSC_DATA_CORRUPT; +} + +int bsc_decompress(unsigned char * input, int inputSize, unsigned char * output, int outputSize, int features) +{ + int indexes[256]; + unsigned char num_indexes; + + if (input == output) + { + return bsc_decompress_inplace(output, inputSize, outputSize, features); + } + + int blockSize = 0, dataSize = 0; + + int info = bsc_block_info(input, inputSize, &blockSize, &dataSize, features); + if (info != LIBBSC_NO_ERROR) + { + return info; + } + + if (inputSize < blockSize || outputSize < dataSize) + { + return LIBBSC_UNEXPECTED_EOB; + } + + int coded = *(int *)(input + 20); + int mode = *(int *)(input + 8); + if (mode == 0) + { + memcpy(output, input + LIBBSC_HEADER_SIZE, dataSize); + return LIBBSC_NO_ERROR; + } + + int index = *(int *)(input + 12); + int features_stored = *(int *)(input + 16); + if (features_stored != features) return LIBBSC_DATA_CORRUPT; + + num_indexes = input[blockSize - 1]; + if (num_indexes > 0) + { + memcpy(indexes, input + blockSize - 1 - 4 * num_indexes, 4 * num_indexes); + } + + int lzpHashSize = (mode >> 16) & 0xff; + int lzpMinLen = (mode >> 8) & 0xff; + int coder = (mode >> 5) & 0x7; + int blockSorter = (mode >> 0) & 0x1f; + int result, lzSize; + + if (coded) { + lzSize = bsc_coder_decompress(input + LIBBSC_HEADER_SIZE, output, coder, features); + if (lzSize < LIBBSC_NO_ERROR) + { + return lzSize; + } + + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : result = bsc_bwt_decode(output, lzSize, index, num_indexes, indexes, features); break; + + default : return LIBBSC_DATA_CORRUPT; + } + if (result < LIBBSC_NO_ERROR) + { + return result; + } + } else { + memcpy(output, input + LIBBSC_HEADER_SIZE, blockSize - LIBBSC_HEADER_SIZE); + lzSize = blockSize - LIBBSC_HEADER_SIZE; + } + + result = lzSize; + if (mode != (mode & 0xff)) + { + memcpy(input, output, lzSize); + result = bsc_lzp_decompress(input, output, lzSize, lzpHashSize, lzpMinLen, features); + if (result < LIBBSC_NO_ERROR) + { + return result; + } + return result == dataSize ? LIBBSC_NO_ERROR : LIBBSC_DATA_CORRUPT; + } + + return result == dataSize ? LIBBSC_NO_ERROR : LIBBSC_DATA_CORRUPT; +} + +/* + * Compatibility to decompress older archive versions. + */ +int bsc_decompress_old(const unsigned char * input, int inputSize, unsigned char * output, int outputSize, int features) +{ + int indexes[256]; + unsigned char num_indexes; + + if (input == output) + { + return bsc_decompress_inplace(output, inputSize, outputSize, features); + } + + int blockSize = 0, dataSize = 0; + + int info = bsc_block_info((unsigned char *)input, inputSize, &blockSize, &dataSize, features); + if (info != LIBBSC_NO_ERROR) + { + return info; + } + + if (inputSize < blockSize || outputSize < dataSize) + { + return LIBBSC_UNEXPECTED_EOB; + } + + if (*(unsigned int *)(input + 20) != bsc_adler32(input + LIBBSC_HEADER_SIZE, blockSize - LIBBSC_HEADER_SIZE, features)) + { + return LIBBSC_DATA_CORRUPT; + } + + int mode = *(int *)(input + 8); + if (mode == 0) + { + memcpy(output, input + LIBBSC_HEADER_SIZE, dataSize); + return LIBBSC_NO_ERROR; + } + + int index = *(int *)(input + 12); + unsigned int adler32_data = *(int *)(input + 16); + + num_indexes = input[blockSize - 1]; + if (num_indexes > 0) + { + memcpy(indexes, input + blockSize - 1 - 4 * num_indexes, 4 * num_indexes); + } + + int lzpHashSize = (mode >> 16) & 0xff; + int lzpMinLen = (mode >> 8) & 0xff; + int coder = (mode >> 5) & 0x7; + int blockSorter = (mode >> 0) & 0x1f; + + int lzSize = bsc_coder_decompress(input + LIBBSC_HEADER_SIZE, output, coder, features); + if (lzSize < LIBBSC_NO_ERROR) + { + return lzSize; + } + + int result; + switch (blockSorter) + { + case LIBBSC_BLOCKSORTER_BWT : result = bsc_bwt_decode(output, lzSize, index, num_indexes, indexes, features); break; + + default : return LIBBSC_DATA_CORRUPT; + } + if (result < LIBBSC_NO_ERROR) + { + return result; + } + + if (mode != (mode & 0xff)) + { + if (unsigned char * buffer = (unsigned char *)bsc_malloc(lzSize)) + { + memcpy(buffer, output, lzSize); + result = bsc_lzp_decompress(buffer, output, lzSize, lzpHashSize, lzpMinLen, features); + bsc_free(buffer); + if (result < LIBBSC_NO_ERROR) + { + return result; + } + return result == dataSize ? (adler32_data == bsc_adler32(output, dataSize, features) ? LIBBSC_NO_ERROR : LIBBSC_DATA_CORRUPT) : LIBBSC_DATA_CORRUPT; + } + return LIBBSC_NOT_ENOUGH_MEMORY; + } + + return lzSize == dataSize ? (adler32_data == bsc_adler32(output, dataSize, features) ? LIBBSC_NO_ERROR : LIBBSC_DATA_CORRUPT) : LIBBSC_DATA_CORRUPT; +} + +/*-------------------------------------------------*/ +/* End libbsc.cpp */ +/*-------------------------------------------------*/ diff --git a/bsc/libbsc/lzp/lzp.cpp b/bsc/libbsc/lzp/lzp.cpp new file mode 100644 index 0000000..7fa5c5d --- /dev/null +++ b/bsc/libbsc/lzp/lzp.cpp @@ -0,0 +1,426 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Lempel Ziv Prediction */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include +#include + +#include "lzp.h" + +#include "../platform/platform.h" +#include "../libbsc.h" + +#define LIBBSC_LZP_MATCH_FLAG 0xf2 + +static INLINE int bsc_lzp_num_blocks(int n) +{ + if (n < 256 * 1024) return 1; + if (n < 4 * 1024 * 1024) return 2; + if (n < 16 * 1024 * 1024) return 4; + + return 8; +} + +int bsc_lzp_encode_block(const unsigned char * input, const unsigned char * inputEnd, unsigned char * output, unsigned char * outputEnd, int hashSize, int minLen) +{ + if (inputEnd - input < 16) + { + return LIBBSC_NOT_COMPRESSIBLE; + } + + if (int * lookup = (int *)bsc_zero_malloc((int)(1 << hashSize) * sizeof(int))) + { + unsigned int mask = (int)(1 << hashSize) - 1; + const unsigned char * inputStart = input; + const unsigned char * outputStart = output; + const unsigned char * outputEOB = outputEnd - 4; + + unsigned int context = 0; + for (int i = 0; i < 4; ++i) + { + context = (context << 8) | (*output++ = *input++); + } + + const unsigned char * heuristic = input; + const unsigned char * inputMinLenEnd = inputEnd - minLen - 8; + while ((input < inputMinLenEnd) && (output < outputEOB)) + { + unsigned int index = ((context >> 15) ^ context ^ (context >> 3)) & mask; + int value = lookup[index]; lookup[index] = (int)(input - inputStart); + if (value > 0) + { + const unsigned char * reference = inputStart + value; + if ((*(unsigned int *)(input + minLen - 4) == *(unsigned int *)(reference + minLen - 4)) && (*(unsigned int *)(input) == *(unsigned int *)(reference))) + { + if ((heuristic > input) && (*(unsigned int *)heuristic != *(unsigned int *)(reference + (heuristic - input)))) + { + goto LIBBSC_LZP_MATCH_NOT_FOUND; + } + + int len = 4; + for (; input + len < inputMinLenEnd; len += 4) + { + if (*(unsigned int *)(input + len) != *(unsigned int *)(reference + len)) break; + } + if (len < minLen) + { + if (heuristic < input + len) heuristic = input + len; + goto LIBBSC_LZP_MATCH_NOT_FOUND; + } + + if (input[len] == reference[len]) len++; + if (input[len] == reference[len]) len++; + if (input[len] == reference[len]) len++; + + input += len; context = input[-1] | (input[-2] << 8) | (input[-3] << 16) | (input[-4] << 24); + + *output++ = LIBBSC_LZP_MATCH_FLAG; + + len -= minLen; while (len >= 254) { len -= 254; *output++ = 254; if (output >= outputEOB) break; } + + *output++ = (unsigned char)(len); + } + else + { + +LIBBSC_LZP_MATCH_NOT_FOUND: + + unsigned char next = *output++ = *input++; context = (context << 8) | next; + if (next == LIBBSC_LZP_MATCH_FLAG) *output++ = 255; + } + } + else + { + context = (context << 8) | (*output++ = *input++); + } + } + + while ((input < inputEnd) && (output < outputEOB)) + { + unsigned int index = ((context >> 15) ^ context ^ (context >> 3)) & mask; + int value = lookup[index]; lookup[index] = (int)(input - inputStart); + if (value > 0) + { + unsigned char next = *output++ = *input++; context = (context << 8) | next; + if (next == LIBBSC_LZP_MATCH_FLAG) *output++ = 255; + } + else + { + context = (context << 8) | (*output++ = *input++); + } + } + + bsc_free(lookup); + + return (output >= outputEOB) ? LIBBSC_NOT_COMPRESSIBLE : (int)(output - outputStart); + } + + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_lzp_decode_block(const unsigned char * input, const unsigned char * inputEnd, unsigned char * output, int hashSize, int minLen) +{ + if (inputEnd - input < 4) + { + return LIBBSC_UNEXPECTED_EOB; + } + + if (int * lookup = (int *)bsc_zero_malloc((int)(1 << hashSize) * sizeof(int))) + { + unsigned int mask = (int)(1 << hashSize) - 1; + const unsigned char * outputStart = output; + + unsigned int context = 0; + for (int i = 0; i < 4; ++i) + { + context = (context << 8) | (*output++ = *input++); + } + + while (input < inputEnd) + { + unsigned int index = ((context >> 15) ^ context ^ (context >> 3)) & mask; + int value = lookup[index]; lookup[index] = (int)(output - outputStart); + if (*input == LIBBSC_LZP_MATCH_FLAG && value > 0) + { + input++; + if (*input != 255) + { + int len = minLen; while (true) { len += *input; if (*input++ != 254) break; } + + const unsigned char * reference = outputStart + value; + unsigned char * outputEnd = output + len; + + if (output - reference < 4) + { + int offset[4] = {0, 3, 2, 3}; + + *output++ = *reference++; + *output++ = *reference++; + *output++ = *reference++; + *output++ = *reference++; + + reference -= offset[output - reference]; + } + + while (output < outputEnd) { *(unsigned int *)output = *(unsigned int*)reference; output += 4; reference += 4; } + + output = outputEnd; context = output[-1] | (output[-2] << 8) | (output[-3] << 16) | (output[-4] << 24); + } + else + { + input++; context = (context << 8) | (*output++ = LIBBSC_LZP_MATCH_FLAG); + } + } + else + { + context = (context << 8) | (*output++ = *input++); + } + } + + bsc_free(lookup); + + return (int)(output - outputStart); + } + + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +int bsc_lzp_compress_serial(const unsigned char * input, unsigned char * output, int n, int hashSize, int minLen) +{ + if (bsc_lzp_num_blocks(n) == 1) + { + int result = bsc_lzp_encode_block(input, input + n, output + 1, output + n - 1, hashSize, minLen); + if (result >= LIBBSC_NO_ERROR) result = (output[0] = 1, result + 1); + + return result; + } + + int nBlocks = bsc_lzp_num_blocks(n); + int chunkSize = n / nBlocks; + int outputPtr = 1 + 8 * nBlocks; + + output[0] = nBlocks; + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int inputStart = blockId * chunkSize; + int inputSize = blockId != nBlocks - 1 ? chunkSize : n - inputStart; + int outputSize = inputSize; if (outputSize > n - outputPtr) outputSize = n - outputPtr; + + int result = bsc_lzp_encode_block(input + inputStart, input + inputStart + inputSize, output + outputPtr, output + outputPtr + outputSize, hashSize, minLen); + if (result < LIBBSC_NO_ERROR) + { + if (outputPtr + inputSize >= n) return LIBBSC_NOT_COMPRESSIBLE; + result = inputSize; memcpy(output + outputPtr, input + inputStart, inputSize); + } + + *(int *)(output + 1 + 8 * blockId + 0) = inputSize; + *(int *)(output + 1 + 8 * blockId + 4) = result; + + outputPtr += result; + } + + return outputPtr; +} + +#ifdef LIBBSC_OPENMP + +int bsc_lzp_compress_parallel(const unsigned char * input, unsigned char * output, int n, int hashSize, int minLen) +{ + if (unsigned char * buffer = (unsigned char *)bsc_malloc(n * sizeof(unsigned char))) + { + int compressionResult[ALPHABET_SIZE]; + + int nBlocks = bsc_lzp_num_blocks(n); + int result = LIBBSC_NO_ERROR; + int chunkSize = n / nBlocks; + + int numThreads = omp_get_max_threads(); + if (numThreads > nBlocks) numThreads = nBlocks; + + output[0] = nBlocks; + #pragma omp parallel num_threads(numThreads) if(numThreads > 1) + { + if (omp_get_num_threads() == 1) + { + result = bsc_lzp_compress_serial(input, output, n, hashSize, minLen); + } + else + { + #pragma omp for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int blockStart = blockId * chunkSize; + int blockSize = blockId != nBlocks - 1 ? chunkSize : n - blockStart; + + compressionResult[blockId] = bsc_lzp_encode_block(input + blockStart, input + blockStart + blockSize, buffer + blockStart, buffer + blockStart + blockSize, hashSize, minLen); + if (compressionResult[blockId] < LIBBSC_NO_ERROR) compressionResult[blockId] = blockSize; + + *(int *)(output + 1 + 8 * blockId + 0) = blockSize; + *(int *)(output + 1 + 8 * blockId + 4) = compressionResult[blockId]; + } + + #pragma omp single + { + result = 1 + 8 * nBlocks; + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + result += compressionResult[blockId]; + } + + if (result >= n) result = LIBBSC_NOT_COMPRESSIBLE; + } + + if (result >= LIBBSC_NO_ERROR) + { + #pragma omp for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int blockStart = blockId * chunkSize; + int blockSize = blockId != nBlocks - 1 ? chunkSize : n - blockStart; + + int outputPtr = 1 + 8 * nBlocks; + for (int p = 0; p < blockId; ++p) outputPtr += compressionResult[p]; + + if (compressionResult[blockId] != blockSize) + { + memcpy(output + outputPtr, buffer + blockStart, compressionResult[blockId]); + } + else + { + memcpy(output + outputPtr, input + blockStart, compressionResult[blockId]); + } + } + } + } + } + + bsc_free(buffer); + + return result; + } + return LIBBSC_NOT_ENOUGH_MEMORY; +} + +#endif + +int bsc_lzp_compress(const unsigned char * input, unsigned char * output, int n, int hashSize, int minLen, int features) +{ + +#ifdef LIBBSC_OPENMP + + if ((bsc_lzp_num_blocks(n) != 1) && (features & LIBBSC_FEATURE_MULTITHREADING)) + { + return bsc_lzp_compress_parallel(input, output, n, hashSize, minLen); + } + +#endif + + return bsc_lzp_compress_serial(input, output, n, hashSize, minLen); +} + +int bsc_lzp_decompress(const unsigned char * input, unsigned char * output, int n, int hashSize, int minLen, int features) +{ + int nBlocks = input[0]; + + if (nBlocks == 1) + { + return bsc_lzp_decode_block(input + 1, input + n, output, hashSize, minLen); + } + + int decompressionResult[ALPHABET_SIZE]; + +#ifdef LIBBSC_OPENMP + + if (features & LIBBSC_FEATURE_MULTITHREADING) + { + #pragma omp parallel for schedule(dynamic) + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int inputPtr = 0; for (int p = 0; p < blockId; ++p) inputPtr += *(int *)(input + 1 + 8 * p + 4); + int outputPtr = 0; for (int p = 0; p < blockId; ++p) outputPtr += *(int *)(input + 1 + 8 * p + 0); + + inputPtr += 1 + 8 * nBlocks; + + int inputSize = *(int *)(input + 1 + 8 * blockId + 4); + int outputSize = *(int *)(input + 1 + 8 * blockId + 0); + + if (inputSize != outputSize) + { + decompressionResult[blockId] = bsc_lzp_decode_block(input + inputPtr, input + inputPtr + inputSize, output + outputPtr, hashSize, minLen); + } + else + { + decompressionResult[blockId] = inputSize; memcpy(output + outputPtr, input + inputPtr, inputSize); + } + } + } + else + +#endif + + { + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + int inputPtr = 0; for (int p = 0; p < blockId; ++p) inputPtr += *(int *)(input + 1 + 8 * p + 4); + int outputPtr = 0; for (int p = 0; p < blockId; ++p) outputPtr += *(int *)(input + 1 + 8 * p + 0); + + inputPtr += 1 + 8 * nBlocks; + + int inputSize = *(int *)(input + 1 + 8 * blockId + 4); + int outputSize = *(int *)(input + 1 + 8 * blockId + 0); + + if (inputSize != outputSize) + { + decompressionResult[blockId] = bsc_lzp_decode_block(input + inputPtr, input + inputPtr + inputSize, output + outputPtr, hashSize, minLen); + } + else + { + decompressionResult[blockId] = inputSize; memcpy(output + outputPtr, input + inputPtr, inputSize); + } + } + } + + int dataSize = 0, result = LIBBSC_NO_ERROR; + for (int blockId = 0; blockId < nBlocks; ++blockId) + { + if (decompressionResult[blockId] < LIBBSC_NO_ERROR) result = decompressionResult[blockId]; + dataSize += decompressionResult[blockId]; + } + + return (result == LIBBSC_NO_ERROR) ? dataSize : result; +} + +/*-----------------------------------------------------------*/ +/* End lzp.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/lzp/lzp.h b/bsc/libbsc/lzp/lzp.h new file mode 100644 index 0000000..a249732 --- /dev/null +++ b/bsc/libbsc/lzp/lzp.h @@ -0,0 +1,74 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to Lempel Ziv Prediction functions */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_LZP_H +#define _LIBBSC_LZP_H + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Preprocess a memory block by LZP algorithm. + * @param input - the input memory block of n bytes. + * @param output - the output memory block of n bytes. + * @param n - the length of the input/output memory blocks. + * @param hashSize - the hash table size. + * @param minLen - the minimum match length. + * @param features - the set of additional features. + * @return The length of preprocessed memory block if no error occurred, error code otherwise. + */ + int bsc_lzp_compress(const unsigned char * input, unsigned char * output, int n, int hashSize, int minLen, int features); + + /** + * Reconstructs the original memory block after LZP algorithm. + * @param input - the input memory block of n bytes. + * @param output - the output memory block. + * @param n - the length of the input memory block. + * @param hashSize - the hash table size. + * @param minLen - the minimum match length. + * @param features - the set of additional features. + * @return The length of original memory block if no error occurred, error code otherwise. + */ + int bsc_lzp_decompress(const unsigned char * input, unsigned char * output, int n, int hashSize, int minLen, int features); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-----------------------------------------------------------*/ +/* End lzp.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/platform/platform.cpp b/bsc/libbsc/platform/platform.cpp new file mode 100644 index 0000000..7ee8f37 --- /dev/null +++ b/bsc/libbsc/platform/platform.cpp @@ -0,0 +1,135 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Platform specific functions and constants */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#include +#include +#include + +#include "platform.h" + +#include "../libbsc.h" + +#if defined(_WIN32) + #include + SIZE_T g_LargePageSize = 0; +#endif + +int bsc_platform_init(int features) +{ + +#if defined(_WIN32) + + if (features & LIBBSC_FEATURE_LARGEPAGES) + { + HANDLE hToken = 0; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + LUID luid; + if (LookupPrivilegeValue(NULL, TEXT("SeLockMemoryPrivilege"), &luid)) + { + TOKEN_PRIVILEGES tp; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), 0, 0); + } + + CloseHandle(hToken); + } + + { + if (HMODULE hKernel = GetModuleHandle(TEXT("kernel32.dll"))) + { + typedef SIZE_T (WINAPI * GetLargePageMinimumProcT)(); + + GetLargePageMinimumProcT largePageMinimumProc = (GetLargePageMinimumProcT)GetProcAddress(hKernel, "GetLargePageMinimum"); + if (largePageMinimumProc != NULL) + { + SIZE_T largePageSize = largePageMinimumProc(); + + if ((largePageSize & (largePageSize - 1)) != 0) largePageSize = 0; + + g_LargePageSize = largePageSize; + } + } + } + } + +#endif + + return LIBBSC_NO_ERROR; +} + +void * bsc_malloc(size_t size) +{ +#if defined(_WIN32) + if ((g_LargePageSize != 0) && (size >= 256 * 1024)) + { + void * address = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (address != NULL) return address; + } + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +#else + return malloc(size); +#endif +} + +void * bsc_zero_malloc(size_t size) +{ +#if defined(_WIN32) + if ((g_LargePageSize != 0) && (size >= 256 * 1024)) + { + void * address = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (address != NULL) return address; + } + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +#else + return calloc(1, size); +#endif +} + +void bsc_free(void * address) +{ +#if defined(_WIN32) + VirtualFree(address, 0, MEM_RELEASE); +#else + free(address); +#endif +} + +/*-----------------------------------------------------------*/ +/* End platform.cpp */ +/*-----------------------------------------------------------*/ diff --git a/bsc/libbsc/platform/platform.h b/bsc/libbsc/platform/platform.h new file mode 100644 index 0000000..c39508d --- /dev/null +++ b/bsc/libbsc/platform/platform.h @@ -0,0 +1,108 @@ +/*-----------------------------------------------------------*/ +/* Block Sorting, Lossless Data Compression Library. */ +/* Interface to platform specific functions and constants */ +/*-----------------------------------------------------------*/ + +/*-- + +This file is a part of bsc and/or libbsc, a program and a library for +lossless, block-sorting data compression. + +Copyright (c) 2009-2012 Ilya Grebnov + +See file AUTHORS for a full list of contributors. + +The bsc and libbsc is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The bsc and libbsc 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the bsc and libbsc. If not, see http://www.gnu.org/licenses/. + +Please see the files COPYING and COPYING.LIB for full copyright information. + +See also the bsc and libbsc web site: + http://libbsc.com/ for more information. + +--*/ + +#ifndef _LIBBSC_PLATFORM_H +#define _LIBBSC_PLATFORM_H + +#if defined(_OPENMP) && defined(LIBBSC_OPENMP_SUPPORT) + #include + #define LIBBSC_OPENMP +#endif + +#if defined(__GNUC__) + #define INLINE __inline__ +#elif defined(_MSC_VER) + #define INLINE __forceinline +#elif defined(__IBMC__) + #define INLINE _Inline +#elif defined(__cplusplus) + #define INLINE inline +#else + #define INLINE /* */ +#endif + +#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) + #define RESTRICT __restrict__ +#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600) + #define RESTRICT __restrict +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define RESTRICT __restrict +#elif defined(__CUDACC__) && (CUDA_VERSION >= 3000) + #define RESTRICT __restrict__ +#else + #define RESTRICT /* */ +#endif + +#define ALPHABET_SIZE (256) + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * You should call this function before you call any of the other platform specific functions. + * @param features - the set of additional features. + * @return LIBBSC_NO_ERROR if no error occurred, error code otherwise. + */ + int bsc_platform_init(int features); + + /** + * Allocates memory blocks. + * @param size - bytes to allocate. + * @return a pointer to allocated space or NULL if there is insufficient memory available. + */ + void * bsc_malloc(size_t size); + + /** + * Allocates memory blocks and initializes all its bits to zero. + * @param size - bytes to allocate. + * @return a pointer to allocated space or NULL if there is insufficient memory available. + */ + void * bsc_zero_malloc(size_t size); + + /** + * Deallocates or frees a memory block. + * @param address - previously allocated memory block to be freed. + */ + void bsc_free(void * address); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-----------------------------------------------------------*/ +/* End platform.h */ +/*-----------------------------------------------------------*/ diff --git a/bsc/makefile b/bsc/makefile new file mode 100644 index 0000000..43c2cab --- /dev/null +++ b/bsc/makefile @@ -0,0 +1,111 @@ +SHELL = /bin/sh + +CC = g++ +AR = ar +RANLIB = ranlib + +CFLAGS = -g -Wall -fPIC + +# Sort Transform is patented by Michael Schindler under US patent 6,199,064. +# However for research purposes this algorithm is included in this software. +# So if you are of the type who should worry about this (making money) worry away. +# The author shall have no liability with respect to the infringement of +# copyrights, trade secrets or any patents by this software. In no event will +# the author be liable for any lost revenue or profits or other special, +# indirect and consequential damages. + +# Sort Transform is disabled by default and can be enabled by defining the +# preprocessor macro LIBBSC_SORT_TRANSFORM_SUPPORT at compile time. + +#CFLAGS += -DLIBBSC_SORT_TRANSFORM_SUPPORT + +# Comment out CFLAGS line below for compatability mode for 32bit file sizes +# (less than 2GB) and systems that have compilers that treat int as 64bit +# natively (ie: modern AIX) +CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + +# Comment out CFLAGS line below to disable optimizations +CFLAGS += -O3 -fomit-frame-pointer -fstrict-aliasing + +# Comment out CFLAGS line below to disable OpenMP optimizations +CFLAGS += -fopenmp -DLIBBSC_OPENMP_SUPPORT + +# Comment out CFLAGS line below to enable debug output +CFLAGS += -DNDEBUG + +# Where you want bsc installed when you do 'make install' +PREFIX = /usr + +OBJS = \ + adler32.o \ + divsufsort.o \ + bwt.o \ + coder.o \ + qlfc.o \ + qlfc_model.o \ + detectors.o \ + preprocessing.o \ + libbsc.o \ + lzp.o \ + platform.o \ + +all: libbsc.a bsc + +bsc: libbsc.a bsc.cpp + $(CC) $(CFLAGS) bsc.cpp -o bsc -L. -lbsc + +libbsc.a: $(OBJS) + rm -f libbsc.a + $(AR) cq libbsc.a $(OBJS) + @if ( test -f $(RANLIB) -o -f /usr/bin/ranlib -o \ + -f /bin/ranlib -o -f /usr/ccs/bin/ranlib ) ; then \ + echo $(RANLIB) libbsc.a ; \ + $(RANLIB) libbsc.a ; \ + fi + +install: libbsc.a bsc + if ( test ! -d $(PREFIX)/bin ) ; then mkdir -p $(PREFIX)/bin ; fi + if ( test ! -d $(PREFIX)/lib ) ; then mkdir -p $(PREFIX)/lib ; fi + if ( test ! -d $(PREFIX)/include ) ; then mkdir -p $(PREFIX)/include ; fi + cp -f bsc $(PREFIX)/bin/bsc + chmod a+x $(PREFIX)/bin/bsc + cp -f libbsc/libbsc.h $(PREFIX)/include + chmod a+r $(PREFIX)/include/libbsc.h + cp -f libbsc.a $(PREFIX)/lib + chmod a+r $(PREFIX)/lib/libbsc.a + +clean: + rm -f *.o libbsc.a bsc + +adler32.o: libbsc/adler32/adler32.cpp + $(CC) $(CFLAGS) -c libbsc/adler32/adler32.cpp + +divsufsort.o: libbsc/bwt/divsufsort/divsufsort.c + $(CC) $(CFLAGS) -c libbsc/bwt/divsufsort/divsufsort.c + +bwt.o: libbsc/bwt/bwt.cpp + $(CC) $(CFLAGS) -c libbsc/bwt/bwt.cpp + +coder.o: libbsc/coder/coder.cpp + $(CC) $(CFLAGS) -c libbsc/coder/coder.cpp + +qlfc.o: libbsc/coder/qlfc/qlfc.cpp + $(CC) $(CFLAGS) -c libbsc/coder/qlfc/qlfc.cpp + +qlfc_model.o: libbsc/coder/qlfc/qlfc_model.cpp + $(CC) $(CFLAGS) -c libbsc/coder/qlfc/qlfc_model.cpp + +detectors.o: libbsc/filters/detectors.cpp + $(CC) $(CFLAGS) -c libbsc/filters/detectors.cpp + +preprocessing.o: libbsc/filters/preprocessing.cpp + $(CC) $(CFLAGS) -c libbsc/filters/preprocessing.cpp + +libbsc.o: libbsc/libbsc/libbsc.cpp + $(CC) $(CFLAGS) -c libbsc/libbsc/libbsc.cpp + +lzp.o: libbsc/lzp/lzp.cpp + $(CC) $(CFLAGS) -c libbsc/lzp/lzp.cpp + +platform.o: libbsc/platform/platform.cpp + $(CC) $(CFLAGS) -c libbsc/platform/platform.cpp diff --git a/config b/config index 5b9beb1..ba91eb8 100755 --- a/config +++ b/config @@ -31,9 +31,9 @@ ${prog} [] --enable-debug Enable debug mode compilation (default: disabled). --disable-allocator Disable use of internal memory allocator mechanism (default: enabled). --enable-debug-stats Enable printing of some verbose debug info (default: disabled). ---with-libbsc= - Enable support for libbsc (See: libbsc.com). Full path to the libbsc - source tree must be provided. It links the library statically. +--with-libbsc= (Default: Internal copy) + Full path to external libbsc source tree can be provided. It links the + library statically. --with-openssl= (Default: System) This defaults to the system's OpenSSL library. You can use this option if you want to use an alternate OpenSSL installation. @@ -60,12 +60,12 @@ debug=0 allocator=1 debug_stats=0 prefix=/usr -libbsc_dir= -libbsc_lib= -libbsclflags= -libbscwrapobj= -libbscgenopt= -libbsccppflags= +libbsc_dir=./bsc +libbsc_lib=${libbsc_dir}/libbsc.a +libbsclflags='\$\(LIBBSCLFLAGS\)' +libbscwrapobj='\$\(LIBBSCWRAPOBJ\)' +libbscgenopt='\$\(LIBBSCGEN_OPT\)' +libbsccppflags='\$\(LIBBSCCPPFLAGS\)' openssl_prefix= openssl_libdir= openssl_incdir= @@ -162,7 +162,8 @@ do libbscgenopt='\$\(LIBBSCGEN_OPT\)' libbsccppflags='\$\(LIBBSCCPPFLAGS\)' else - echo "Libbsc not found in ${path}, not enabling libbsc support.\n" + echo "Libbsc not found in ${path}.\n" + exit 1 fi ;; --with-openssl=*) diff --git a/libbsc_compress.c b/libbsc_compress.c index 0eeb104..21fed2f 100644 --- a/libbsc_compress.c +++ b/libbsc_compress.c @@ -40,6 +40,7 @@ struct libbsc_params { int lzpMinLen; int bscCoder; int features; + int oldversion; }; static void @@ -68,6 +69,13 @@ libbsc_stats(int show) { } +int +libbsc_buf_extra(uint64_t buflen) +{ + return (4096); +} + + /* * BSC uses OpenMP where it does not control thread count * deterministically. We only use multithread capability in BSC @@ -124,6 +132,10 @@ libbsc_init(void **data, int *level, int nthreads, uint64_t chunksize, bscdat->lzpMinLen = 200; bscdat->bscCoder = LIBBSC_CODER_QLFC_ADAPTIVE; } + + if (file_version < 9) { + bscdat->oldversion = 1; + } *data = bscdat; rv = bsc_init(bscdat->features); if (rv != LIBBSC_NO_ERROR) { @@ -176,7 +188,10 @@ libbsc_decompress(void *src, uint64_t srclen, void *dst, uint64_t *dstlen, int rv; struct libbsc_params *bscdat = (struct libbsc_params *)data; - rv = bsc_decompress(src, srclen, dst, *dstlen, bscdat->features); + if (bscdat->oldversion) + rv = bsc_decompress_old(src, srclen, dst, *dstlen, bscdat->features); + else + rv = bsc_decompress(src, srclen, dst, *dstlen, bscdat->features); if (rv != LIBBSC_NO_ERROR) { libbsc_err(rv); return (-1); diff --git a/pcompress.h b/pcompress.h index 38172c1..d35566f 100644 --- a/pcompress.h +++ b/pcompress.h @@ -40,7 +40,7 @@ extern "C" { #define CHUNK_FLAG_SZ 1 #define ALGO_SZ 8 #define MIN_CHUNK 2048 -#define VERSION 8 +#define VERSION 9 #define FLAG_DEDUP 1 #define FLAG_DEDUP_FIXED 2 #define FLAG_SINGLE_CHUNK 4