dvisvgm-3.5/000077500000000000000000000000001501401750600130375ustar00rootroot00000000000000dvisvgm-3.5/.appveyor.yml000066400000000000000000000016701501401750600155110ustar00rootroot00000000000000version: 3.5-{build} configuration: Release image: Visual Studio 2022 platform: - x64 - Win32 branches: except: - tmp install: - set FREETYPE_VER=2.13.2 - set ZLIB_VER=1.3.1 - set TTFA_VER=1.8.4 - set TTFA_REV=1 - cd vc - cd freetype - appveyor DownloadFile http://download.savannah.gnu.org/releases/freetype/freetype-%FREETYPE_VER%.tar.gz - tar xzf freetype-%FREETYPE_VER%.tar.gz --strip-components=1 - del freetype-%FREETYPE_VER%.tar.gz - cd ..\zlib - appveyor DownloadFile http://zlib.net/zlib-%ZLIB_VER%.tar.gz - tar xzf zlib-%ZLIB_VER%.tar.gz --strip-components=1 - del zlib-%ZLIB_VER%.tar.gz - cd .. - appveyor DownloadFile https://github.com/mgieseki/ttfautohint-dll/releases/download/r%TTFA_VER%-%TTFA_REV%/ttfautohint-%TTFA_VER%-dll64.zip - unzip -o -d ttfautohint ttfautohint-%TTFA_VER%-dll64.zip - del ttfautohint-%TTFA_VER%-dll64.zip build: project: vc\dvisvgm.sln verbosity: minimal dvisvgm-3.5/.gitattributes000066400000000000000000000000771501401750600157360ustar00rootroot00000000000000doc/dvisvgm.* linguist-documentation libs/** linguist-vendored dvisvgm-3.5/.github/000077500000000000000000000000001501401750600143775ustar00rootroot00000000000000dvisvgm-3.5/.github/FUNDING.yml000066400000000000000000000011361501401750600162150ustar00rootroot00000000000000# These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: mgieseking issuehunt: mgieseki otechie: # Replace with a single Otechie username custom: https://www.paypal.me/mgieseking dvisvgm-3.5/.github/workflows/000077500000000000000000000000001501401750600164345ustar00rootroot00000000000000dvisvgm-3.5/.github/workflows/c-cpp.yml000066400000000000000000000015041501401750600201610ustar00rootroot00000000000000name: C/C++ CI on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: update packages run: sudo apt-get update - name: install dependencies run: > sudo apt-get install -qq autotools-dev autoconf-archive pkg-config libkpathsea-dev libfreetype6-dev libgs-dev libz-dev texlive-base python-is-python3 python3-lxml asciidoc xmlto xsltproc - name: autogen run: autoreconf -fi - name: configure run: ./configure --enable-bundled-libs - name: make clean run: make clean - name: make run: make -j - name: update timestamps run: make -C src -t - name: make check run: make -j check dvisvgm-3.5/.gitignore000066400000000000000000000014371501401750600150340ustar00rootroot00000000000000.* *.a *.la *.o *.lo *.Po *.pyc *.obj *.dvi *.gch *.gcda *.gcno *.lib *.log *.lpro *.ncb *.tex *.svg *.svgz *.aux *.orig *.toc *.tar.* *.tgz *.trs *.zip *.swp *.exe *.tlog *.pdb *.png *.pdf *.tmp *.lastbuildstate *.opensdf *.vcxproj.user *.patch build callgrind.* cmdline.* Makefile Makefile.in autom4te.* dvisvgm aclocal.* aminclude_static.am ar-lib compile libtool ltmain.sh missing cov-int lcov /config.* doc/buildman doc/dvisvgm.txt doc/dvisvgm*.xml doc/dvisvgm.html doc/dvisvgm.sty doc/update-revdate doc/dvisvgm.1 m4/libtool.m4 m4/lt*.m4 doxy backup/* Win32 x64 Debug Release vc/miktex-com/dlldata.c vc/*.s* vc/_* vc/Upgrade* configure configure~ depcomp install-sh src/samples src/psdefs.psc src/CommandLine.* test-driver tests/hashcheck* tests/*Test svg2vml nbproject stamp-h1 a.out test*.* dvisvgm-3.5/.hgignore000066400000000000000000000012161501401750600146420ustar00rootroot00000000000000syntax: glob *.a *.la *.o *.lo *.Po *.pyc *.obj *.dvi *.gch *.gcda *.gcno *.lib *.log *.lpro *.ncb *.tex *.svg *.svgz *.aux *.orig *.toc *.tar.* *.zip *.swp *.exe *.vcxproj.user .deps .dirstamp callgrind.* cmdline.* Makefile Makefile.in autom4te.* dvisvgm aclocal.* missing ./config.* doc/buildman doc/dvisvgm.txt doc/dvisvgm*.xml doc/dvisvgm.html doc/dvisvgm.1 doc/*.pdf m4/libtool.m4 m4/lt*.m4 doxy Debug Release Win32 x64 vc/freetype vc/miktex-2.9.4106-sdk vc/zlib* vc/*.s* vc/_* vc/Upgrade* ar-lib compile configure depcomp install-sh libtool ltmain.sh src/CommandLine.* test-driver tests/hashcheck* tests/*Test nbproject stamp-h1 a.out test*.* lcov dvisvgm-3.5/.hgtags000066400000000000000000000116031501401750600143160ustar00rootroot00000000000000007272ee0386359b9c998547ebacc381376291c2 0.8.5 079655f37ce7da3f6ca0433cf078ca45ec8880f7 0.8.2 1547e7cc2e9a6851c5617a482bf9b26c3408a133 0.8.1 26aa98dd52d09084de1b4203951b974f304081d0 tag/0.5 2d72bfbc31c12712790da77e0e323452154b30ba 0.7.1 368840ae8d987127915ece21f1df4b4d023645ab tag/0.6.1 68b8445b92425fade666ed1b0d6f7bd95c7c3021 0.8.3 8f02c8b9ad443c15475966f4ba418eb663de179d 0.7.3 af5eafa9fa5598e72148dfb1dc3bf263aa8ad1d9 tag/0.4.3 b6c9ed22d8b6db2ea44a61a475500dca0f4bd642 0.7 bc5d6cc99190fc9f1114c2be5efced4a72a7d3b0 tag/0.6 beb39e4ced401d9639504fb2d4c856f35d27e866 0.7.2 d5e6d02b885711e4c031e3cf97e9a1a1f008b45b 0.8.4 deee1d1e70596a8dfaeca86af62f7aac5e6d0214 0.8 fba0d098cc2c883ef5b994ca709e3fbb342478a1 0.8.6 3cd4ce811a3e3b9f9575a53074e747c61a9bf032 0.8.7 2788648c3666fd71d932b18904c3431f7ca9af0c 0.8.8 d5d11a1bb09b466d2d21884b0702bd80f94a8799 0.9 b5d55065c3680768d46ba9184da2ac413d5020d9 0.9.1 63d124d4078c82792e098a57f95d582ac66bd352 1.0 59a269642b92b8bcee2b17a90fa2fe9c062242f5 1.0.1 ba93593ce4f10b62918494b41cf38e4b74c4dc27 1.0.2 26eee1e226b053f61e120afd6876d9b5c5116688 1.0.3 e36afc713701e7ffe0c5972f582f417203183909 1.0.4 1b95a05a87cc2b874b12b3efa314ce58272034f9 1.0.5 87bf127529fd4cc234770c15c56605b7312b683c 1.0.6 f602f9eefdf4d8208e31bfa84baad6f1ec71ad39 1.0.7 eb1de1a9428689185c07b60a0741aec5785126b2 1.0.8 748a4f97334ecda880dd147ef09aaf56b252118f 1.0.9 e4c2ef5f3da9188c07531a27694e43b8c8df7e1f 1.0.10 d76eda7ac1097c2cdbcf5716db8d0e16635a9b2c 1.0.11 f556f8f879ce4999bf1c504525b2650cf1d67254 1.0.12 f541b32413acf23e4a40fcd91f79e3e5bad22982 1.1 68af772f11f285d17ecab6c154c5422fc9d2ac25 1.2 99d1378bf460b7a712f832c2caaa7fc9be930a5d 1.2.1 4d3d07090101ff31f8e92f7fd3c408ecb7c664c3 1.2.2 f6e77b31f30017696f752d66d375e2950689997a 1.3 56fa47468373b5b13c6888121d025e3e2feacfc4 1.4 c7ff1c440c0071a08f2ed381c3a2a39c14609950 1.5 56b5e13eff7271468681775d40647ad3f31e6952 1.5.1 2226c4552e35e07dde5beb633ba1ddfb6c76c49c 1.5.2 90f671880e1f4350c263fb8ceced7e18738737c6 1.5.3 4b9ef65836dff66a205715ac2eba6b678be9a898 1.6 9788762a6d48f50bd43bd817b1061c088fe5d909 1.7 0f6847618ddf50c1691420d41ec8cad0ad9d0bfa 1.8 245acbe637955d3db2d7f87576786f73f1bb5fbf 1.8.1 c60faecaa0342c190b8625630db834c093ec8b86 1.9 bb2e162874e396bfaecfd7e3aaa00c5290433bd6 1.9.1 ba18e67cd90ec91ac8265beceb48a25458dea9dc 1.9.2 2b35d8d8bbf6c0cc993bcf5b141c3c8abdd071fa 1.10 ead09fc11b624fe780b3d0348c3198d29d813e7b 1.11 888bf5fc9883c8d5d39c84949d89d6ec50c47b1e 1.12 d6b13792a3c7fa952e36f68a22ea493685f9c857 1.13 2abcbfa661de604cfa5afcc6459999fed8023391 1.14 1c6aa4251d0431fa7101a79fd6c003d53c98976d 1.14.1 53055b88986475119bda1873f6e31dccd4b0a160 1.14.2 0c259d1a07784d35ad6279612a9bbf067d72bd22 1.15 73df4b875c845fa8e02d77b9320eb3f8fe41a190 1.15.1 6834fb8216fc6e74e32534abcef3bfbd3edf636e 1.16 5fffe81bc6e8bc4eb35d3cc10cd41849ce2b7d9c 2.0 20114bbb8bba37e7cd5130ffe2f51a743fda01a8 2.0.1 eae219c563812b52eecf9a57980bc02c6330e989 2.0.2 54288566617dfc1f90aadba5e14378a982cb8271 2.0.3 1c7ed2d32f46c085f8e0468b52cab41bb50c8e08 2.0.4 1da4fd0617689cc7ed19c40cf4237abab058f8d9 2.1 d978a34405b46feb40092df85587447201794fa8 2.1.1 e5a718c0aa1f7b05fb41efe760bf5d3fa803ebba 2.1.2 c8040a3f043721b391832657f80ff6f24bf0f3b0 2.1.3 f1c4868724df5bc149141bc4d29693c615832cbe 2.2 efc93eb6f273d2319abe43d2697b728c74f08fb8 2.2.1 6809cbe8660297da790e8eb8e75a03395a652cc1 2.2.2 c28420bda49cdfb6e82baba0b8f0d3a7182c2951 2.2.3 37e0f00330bc2bee4d34d4fdca15c95b60351370 2.3 1d2712fac13449af395485f29195f4c32e8fab1f 2.3.1 3c0d4340b274049ef07cff2ee485b546b00770f5 2.3.2 ea6d93f24e7daadd66aa0640925fda66168eed57 2.3.3 9f2eae987cfadc0ab171ba64ef8c2112288dff1e 2.3.4 3375c3d61e04b87ef15023cb960d03f4fc77f159 2.3.5 9eb5e915f9de2d21617be870b6998d65b171c5c5 2.4 9e2c0373bf8fcea0e2e5a69b2a12089b155b2b3d 2.4.1 1703e2e1dfac70803a4c0a998bb33984cc8bd744 2.4.2 256c3ccc90a98fdeba16511ddf4265cd9c04f846 2.5 d5c82632b1344df8bc62aed87a200c343ac8e963 2.6 842536fac2a1367083292e795ce40eee4b352de2 2.6.1 65101435cce8f64cff5ba8d46b5665fa222572ec 2.6.2 46035783cc8b06adae6d1572ab6f94af0ae33ed9 2.6.3 d72572c4aee96d78b36758acd94989e982a1e4f9 2.7 5bd80f3e3e8606a2b3323b2eb51e1ccf60cf71ce 2.7.1 3a5cd42abe5446b973f484e88e611f6817ef22bf 2.7.2 e0cbaa3a4167c49ab77c0e60d43442eab52bab33 2.7.3 62a92294cd7bdf4f47da45a1eecb1a3046ef848a 2.7.4 d625be6fb616009175620c9a2611e556337dcaf5 2.8 29a29be78f08e79fdcc19ffbaa63e2f0e7b96ae0 2.8.1 3f83d14d4cf92e397d3c8f03f89f974552bd68bf 2.8.2 5384d32c28b6de1bd2b5dd4be1c85f4c98e5dfc5 2.9 b467e3de2ae2ee5a083f44cc1b016ce22e52e336 2.9.1 eeaf1a69d766b12cc417acc7b8a723311417e362 2.10 585e39596d7473b92af9814128cdc2dd0a7615f3 2.10.1 ea2da8135fbbefed47cb954382c90e851cd28189 2.11 552dd227ac4ef6fb804e31a71e72a1d5a76a0738 2.11.1 5f8747eb3401a449452799616eed5a9092491204 2.12 ec088a6f6a8b0e80a36861cacd72ba223c981d85 2.13 e13a4ae3e7666f242807538c5a7bd5b52ec496de 2.13.1 3865430cd3814ba14b4d08774fe92ed406578940 2.13.2 e03dfaf4a1a3e356214ff054d7b3df0a7cdd3a7a 2.13.3 8d4370717d6fd883a58cf31055701d8d1b2383aa 2.13.4 1999f62a36ae4688fdd2e5acc648a3efe0bcd95f 2.14 dvisvgm-3.5/AUTHORS000066400000000000000000000007701501401750600141130ustar00rootroot00000000000000Martin Gieseking author of dvisvgm Yann Collet libs/xxHash/xxhash.* https://github.com/Cyan4973/xxHash Google Inc. libs/brotli/* libs/woff2/* https://github.com/google/brotli https://github.com/google/woff2 Angus Johnson libs/clipper/clipper.* https://sourceforge.net/projects/polyclipping/ Michael Park libs/variant/include/mpark/* https://github.com/mpark/variant Alexander Peslyak libs/md5/* Peter Selinger libs/potrace/* https://potrace.sourceforge.net dvisvgm-3.5/COPYING000066400000000000000000001045131501401750600140760ustar00rootroot00000000000000 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 . dvisvgm-3.5/INSTALL000066400000000000000000000220241501401750600140700ustar00rootroot00000000000000Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the `--target=TYPE' option to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc will cause the specified gcc to be used as the C compiler (unless it is overridden in the site shell script). `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. dvisvgm-3.5/Makefile.am000066400000000000000000000014631501401750600150770ustar00rootroot00000000000000## This file is part of dvisvgm ## Copyright (C) 2005-2025 Martin Gieseking ## ## Process this file with automake. include $(top_srcdir)/aminclude_static.am AUTOMAKE_OPTIONS = foreign EXTRA_DIST = COPYING SUBDIRS = libs src if !TEXLIVE_BUILD SUBDIRS += tests doc endif ACLOCAL_AMFLAGS = -I m4 if USE_BUNDLED_LIBS AM_DISTCHECK_CONFIGURE_FLAGS = --enable-bundled-libs endif if CODE_COVERAGE_ENABLED lcov_dir=$(top_builddir)/lcov lcov_file=$(lcov_dir)/lcov.info lcov-report: @mkdir -p $(lcov_dir) lcov --capture --directory . --no-external -o $(lcov_file) genhtml --title "dvisvgm" --num-spaces 2 --legend -o $(lcov_dir) $(lcov_file) lcov-clean: @rm -rf $(lcov_dir) @find . -name "*.gcda" -exec rm {} \; lcov --zerocounters --directory . coverage: lcov-clean check lcov-report endif dvisvgm-3.5/NEWS000066400000000000000000001356721501401750600135540ustar00rootroot00000000000000dvisvgm-3.5 (2025-05-23) - fonts are now embedded in deterministic order (GH issue #288) - different glyphs are now always assigned to different Unicode code points to prevent collisions (GH issue #287) - fixed font-related segmentation faults caused by malformed DVI files (GH issue #289) - fixed a regression that led to incorrect results produced by the SVG optimizer - DVI error messages now also mention the byte position where the error occurred in the DVI file - simplified the evaluation of PostScript operators - many code refactorings and improvements dvisvgm-3.4.4 (2025-03-06) - extended computation of Unicode points by looking for known glyph names - added some common glyph names not yet covered by the AGL table - added warning shown if unsupported PDF specials have been ignored - some additions to the manual page - several code improvements dvisvgm-3.4.3 (2025-01-04) - fixed index error in PS operator "colorimage" (GH issue #279) - updated bundled xxHash library to version 0.8.3 - minor changes to the manual page dvisvgm-3.4.2 (2024-11-14) - fixed evaluation of Unicode data when converting PDF files (GH issue #276) - fixed horizontal character positioning in the PDF handler (GH issue #276) - fixed drawing of single-colored tensor product patches - use static creation and modification dates in TTF/WOFF fonts generated by dvisvgm in order to prevent varying SVG output for unchanged input files (GH issue #120) - small improvements of the manual page dvisvgm-3.4.1 (2024-09-16) - show number of page being processed when converting PDF files - added missing #include required as of GCC 15 (GH issue #273) dvisvgm-3.4 (2024-07-24) - option --embed-bitmaps is now also applied to images included with special dvisvgm:img - added macro {?cmyk(c,m,y,k)} to allow for directly specifying CMYK colors in literal SVG fragments - extended dvips color specials to distinguish between fill and stroke colors - added color special "color set" to replace the current color without pushing a new value onto the color stack - added macros {?fillcolor} and {?strokecolor} to retrieve the current fill and stroke color, respectively. Former macro {?color} equals {?fillcolor} and is still available too - replaced millimeter units with big point (bp) units in the message showing the extent of generated SVG file - fixed the detection of MIME types depending of file name suffixes - several small code improvements dvisvgm-3.3 (2024-04-10) - added file dvisvgm.map to the default font map files being looked up - added evaluation of #include and #includefirst present in font map files - changed conversion of CMYK colors to RGB so that the resulting colors are now similar to those created by Ghostscript and several PDF viewers - fixed invalid bounding boxes assigned when converting multiple DVI pages (GH issue #268) - fixed computation of internal Coons tensor points - updated bundled Google Test to version 1.12.1 dvisvgm-3.2.2 (2024-03-07) - fixed the extraction of bitmaps from PS/EPS files that no longer worked since Ghostscript 10.02.1 due to the removal of GS-specific operators (GH issue #264) - minor automake updates required for TeX Live builds dvisvgm-3.2.1 (2024-02-29) - delayed loading of Ghostscript library to speed up the conversion of DVI files without PS specials (GH issue #262) - some improvements required for TeX Live builds (patches by Karl Berry, GH issues #259, #260) - added more details to some DVI warning messages - added some further information to the manual page dvisvgm-3.2 (2024-01-11) - PDF handler: fixed a rounding issue that could lead to slightly bigger text extents (GH issue #256) - added macros {?pageno}, {?svgfile}, and {?svgpath} to the dvisvgm special commands - added separate verbosity flag 8 for user messages printed by special dvisvgm:message - added command-line option --message to allow for printing user messages after writing an SVG file (GH issue #258) - applied upstream patch regarding undefined type punning to the bundled woff2 library - few improvements of the manual page dvisvgm-3.1.2 (2023-10-12) - improved evaluation of graphic extents created by the 'preview' package (GH issue #246) - fixed computation of character boxes when using --exact-bbox (GH issue #248) - fixed memory error in optimizer module (GH issue #250) - updated bundled brotli library to version 1.1.0 dvisvgm-3.1.1 (2023-08-29) - added evaluation of optional dash prefixes to command-line option --optimize to exclude selected optimizer modules - fixed invalid removal of clipping paths referenced in 'defs' section - fixed automatic calls of optimizer module 'remove-clippaths' - suppress Ghostscript warning about deprecated option -dNEWPDF (GH issue #245) - updated bundled xxHash library to version 0.8.2 - few fixes in the manual page dvisvgm-3.1 (2023-07-06) - added command-line option --currentcolor to replace a given color with CSS variable 'currentColor' (GH issue #214) - added special dvisvgm:currentcolor to replace the currently active color with CSS variable 'currentColor' (GH issue #214) - added special 'dvisvgm:message' to print given texts to the console - added support for Omega Font Metric (OFM) files - added fallback mechanism for missing characters in OFM-based virtual fonts proposed by Takuji Tanaka (GH issue #241) - fixed handling of whitespace in PDF file paths (GH issue #233) - fixed vertical placement of "vertical fonts" in horizontal mode (GH issue #235) - fixed parsing of floating point numbers occurred with libc++ (GH issue #240) - fixed potential segmentation faults triggered by missing font files (GH issue #241) - fixed GLIBCXX assertion error in new PDF handler (GH issue #242) - improved handling of font subset prefixes in new, mutool-based PDF handler (GH issue #242) - several minor code improvements dvisvgm-3.0.4 (2023-03-10) - fixed issue that could prevent reading the output of subprocesses (GH issue #232) - removed optional dependency on libcrypto (OpenSSL) because the MD5 functions have been deprecated (always using the bundled MD5 function now) - added TeX Live conditionals to the build system (patch by Karl Berry) - small code and manual page improvements dvisvgm-3.0.3 (2023-02-21) - fixed resetting of character contexts (GH issue #227) - added missing #includes required for GCC 13 dvisvgm-3.0.2 (2023-01-30) - fixed computation of font sizes in new PDF handler (GH issue #220) - fixed viewBox coordinates determined by new PDF handler (GH issue #223) - improved detection of font names used in PDF files (GH issue #224) - minor code improvements dvisvgm-3.0.1 (2023-01-10) - added support for the 64-bit GS library in TeX Live (patch sent by Akira Kakuto) - MacTeX: explicitly lookup libgs in /usr/local/lib (GH issue #197) - fixed character spacing when processing XDV glyph arrays (GH issue #198) - fixed invalid removal of non-redundant clipPath elements (GH issue #203) - fixed computation of the graphics extents printed to the console when using the preview package (GH issue #209) - several improvements of the autotool scripts (thanks to Sam James) - improved processing of fonts when using the new PDF handler dvisvgm-3.0 (2022-10-16) - added a new PDF handler based on mutool to keep the PDF functionality available which can no longer be realized with Ghostscript 10.1.0 due to the replacement of its PostScript-based PDF interpreter - replaced the bundled minimal Fontforge library (ff-woff) with a dedicated, newly implemented library for embedding TTF/WOFF data into the SVG files - added option --embed-bitmaps to embed bitmaps into the generated SVG files instead of referencing the external files - extended option --tmpdir to optionally suppress the creation of uniquely named subfolders - added filters :even and :odd to option --page to limit the given page ranges to even and odd page numbers respectively - fixed the call of ttfautohint to prevent potential memory errors dvisvgm-2.14 (2022-08-12) - added processing of SVG path elements inserted by "raw" specials in order to treat them similar to generated ones - added support for native font references lacking a file name suffix - improved lookup of native fonts - improved the removal of redundant SVG group elements - fixed conversion of empty glyphs to TTF/WOFF - updated bundled WOFF2 library dvisvgm-2.13.4 (2022-04-20) - fixed the size of bounding boxes applied when converting multiple pages (GH issue #182) - try to enable old PDF interpreter when using Ghostscript >= 9.56.0 (dvisvgm does not work with Ghostscript's new PDF interpreter) dvisvgm-2.13.3 (2022-02-27) - added SVG optimizer module 'reassign-clippaths' that searches for duplicate clipPath elements, removes them, and updates the clip-path references - replaced method to clip embedded EPS/PDF graphics that usually results in faster rendering of the affected SVG sections - fixed a regression regarding transformations of embedded EPS/PDF graphics dvisvgm-2.13.2 (2022-02-23) - improved clipping of embedded EPS/PDF graphics (GH issue #176) dvisvgm-2.13.1 (2022-01-26) - added evaluation of expression {?(...)} to special dvisvgm:rawdef - fixed regression regarding positioning of PDF graphics (GH issue #174) - fixed some build issues dvisvgm-2.13 (2022-01-20) - allow for conversion of multiple EPS files given on the command-line - added variables n and N to option --output representing the current file number and total number of files given on the command-line, respectively - fixed selection of hash algorithm - improved computation of glyph height and depth - extended several paragraphs of the manual page with more detailed information - SVG optimizer: simplify transform attributes also when collapsing groups - updated bundled xxHash library to version 0.8.1 - updated bundled gtest to version 1.11 dvisvgm-2.12 (2021-08-16) - added transparency support of SVG elements created outside the PS handler (GH issue #148) - fixed spacing issue caused by unexpected newline characters in SVG output - fixed PS error occurred when defining (yet unsupported) PS shading patterns - fixed issue in color handling of PS tiling patterns (GH issue #158) - fixed displaced graphics occurred if PDF MediaBox is not located at the origin - fixed handling of root directories of file paths - improved handling of drive letters (Windows only) - several code refactorings and improvements dvisvgm-2.11.1 (2021-01-21) - fixed possible ambiguity of GID to charcode mappings (GH issue #147) - refactored representation of token objects in calculator class - few minor code and test improvements dvisvgm-2.11 (2020-11-28) - added fallback mechanism for JFM-based virtual fonts proposed by Takuji Tanaka (GH issue #144) - improved detection of proper CMap files for current encoding - fixed processing of Unicode surrogates present in CMap files - fixed handling of pdf:mapline and pdf:mapfile specials dvisvgm-2.10.1 (2020-09-22) - added support for new Ghostscript transparency operators .setfillconstantalpha and .setstrokeconstantalpha - added support for new Ghostscript versioning scheme introduced with GS 9.53.0 - added few additional information to the manual page - updated bundled brotli library to version 1.0.9 dvisvgm-2.10 (2020-08-12) - added evaluation of LuaTeX native font definitions - added computation of of italic correction for fake slanted glyphs - dvisvgm now creates dedicated temporary folders for each call of the program to prevent file collisions between different processes - added evaluation of internal GS operators '.fillstroke' and '.eofillstroke' introduced with GS 9.52 to implement PDF operators 'B' and 'B*' (GH issue #139) - fixed and improved optimization of nested group elements - fixed optimization of 'scale' transformation - fixed optimization of 'transform' attributes applied to images clipping paths - fixed processing of PS operator 'eoclip' - fixed processing of clipping path intersections with different fill rule properties - fixed processing of {?(...)} expressions (GH issue #136) - fixed error message about unmatched closing tags in XML parser - updated bundled FreeType library to version 2.10.2 - updated bundled xxHash library to version 0.8 dvisvgm-2.9.1 (2020-03-21) - added macro {?(expr)} to enable the evaluation of math expressions in raw SVG fragments (GH #130) - multiplication operator "*" preceding an opening parentheses can now be omitted in math expressions - fixed the evaluation of transformation command "scale(c)" which is now correctly treated as "scale(c, c)" (GH #131) - minor layout optimizations of the PDF manual page dvisvgm-2.9 (2020-03-13) - added processing of PS operators 'image' and 'colorimage' to embed bitmaps present in PS/PDF data into the generated SVG - added command-line option --bitmap-format to set the format used to embed bitmaps present in EPS/PDF files - added fallback method to retrieve the resolution of GF files if stdout of the Metafont subprocess can't be read through a pipe (GH #129) - fixed broken conversion of PS tiling patterns - fixed the functionality of PS operators 'xshow', 'yshow', and 'xyshow' for multibyte characters - fixed a PS error triggered by unsupported shading types < 4 - prevent negative 'height' and 'width' attributes created by optimizer module 'simplify-transform' - fixed potential segfault caused by deep recursion in huge SVG trees - look for Ghostscript library name 'libgs.dylib.N' additionally to 'libgs.N.dylib' (Mac only) - ensure that 'make install' installs the bundled manual page if it can't be rebuilt due to missing build tools - updated bundled xxHash library to version 0.7.3 dvisvgm-2.8.2 (2019-12-07) - if available, call 'mf-nowin' instead of 'mf' to process Metafont files (GH #121) - fixed handling of null device in PS operator 'restore' (GH #122) - fixed PS error triggered by backslashes in file paths (GH #123) - fixed build issue related to GCC on Solaris 11 - some code cleanup dvisvgm-2.8.1 (2019-11-14) - added SVG optimizer module 'simplify-text' - added support for PS operator 'nulldevice' - copy absolute paths from special 'psfile' unchanged to the SVG file - some code refactorings dvisvgm-2.8 (2019-10-25) - added support for JPEG, PNG, PDF, and SVG files to special 'psfile' - added support for Ghostscript 9.50 - added support for elliptical arc segments in graphics paths - added support for CMap operator 'begincidchar' (patch by Akira Kakuto) - added support for experimental 128-bit XXH3 hashes - extended optimizer module 'simplify-transform' to incorporate translation and scaling components into positional and size attributes - replaced CRC32 checksums used in cache files with XXH32 hashes - updated potrace to version 1.16 - updated xxHash to version 0.7.2 - updated gtest to 1.10 - lots of code refactorings dvisvgm-2.7.4 (2019-07-28) - fixed memory issue occurred when calling Metafont - fixed rounding issue in color conversion (GH #116) - changed location of cache files from ~/.dvisvgm/cache to $XDG_CACHE_HOME/dvisvgm which usually expands to ~/.cache/dvisvgm (GH #112) - some minor refactorings dvisvgm-2.7.3 (2019-07-12) - fixed randomly missing glyph paths referenced by 'use' elements (GH #110) - minor update of the man page - some code refactorings dvisvgm-2.7.2 (2019-06-07) - adapted PostScript handler to incompatible changes introduced with Ghostscript 9.27 (removal of GS_PDF_ProcSet and pdfdict) dvisvgm-2.7.1 (2019-05-20) - fixed a bug in PS operator 'setmatrix' (GH #106) - fixed build issue reported on MacPorts (https://trac.macports.org/ticket/58347) - added source files required to access the MIKTeX session object (required due to deprecation of the MiKTeX SDK) dvisvgm-2.7 (2019-04-13) - added option --optimize to perform several optimizations on the generated SVG files (current optimizer modules: collapse-groups, group-attributes, remove-clippath, simplify-transform) (GH #97) - dvisvgm's "raw" specials are now parsed and converted to proper XML nodes - several improvements to SVG graphics path descriptions: * omit redundant spaces and leading zeros * omit line commands representing zero-length lines * improved detection of reflected control points in Bézier curve sequences - added evaluation of PS operators xshow, yshow, and xyshow - added evaluation of psfile/pdffile attribute 'clip' to clip the drawing region to the bounding box of the image being processed (GH #104) - added specials 'dvisvgm:bbox lock' and 'dvisvgm:bbox unlock' to disable and enable updating the bounding box of the current page (GH #105) - added optional modifier 'transform' to dvisvgm:bbox specials to allow for applying the current transformation to the bounding box - added macro '{?matrix}' to dvisvgm's 'raw' specials that expands to the current transformation matrix - renamed option --exact to --exact-bbox (backward compatible change) - updated the bundled xxHash library to version 0.7.0 - lots of code refactorings dvisvgm-2.6.3 (2019-03-09) - create short RGB hex values for color attributes if possible - fixed rejection of paper formats, like A4, by option --bbox - fixed incomplete adaption of vertical orientation when processing EPS/PDF files - fixed handling of backslashes in EPS/PDF file paths (Windows only) - updated bundled Google Test library to version 1.8.1 - some code refactorings and improvements of the build system dvisvgm-2.6.2 (2019-01-23) - fixed scaling of line properties in PS operator 'grestore' - fixed handling of PS operators 'charpath' and 'show' which may call each other internally - improved processing of PS operator 'clippath' - prevent visible side-effects of PS operator 'stringwidth' - updated bundled brotli library to version 1.0.7 - some modifications of the build system to simplify maintenance in TeX Live dvisvgm-2.6.1 (2018-10-12) - added configuration option --disable-manpage to prevent generating the manual page (GH issue #93) - if configuration option --disable-bundled-libs is given and some of the required system libraries are missing, the corresponding bundled library is used as a fallback (GH issue #94) - updated bundled brotli library to version 1.0.6 - fixed build issue occurred with GCC 4.8 dvisvgm-2.6 (2018-09-08) - added option --page-hashes that allows for skipping the conversion of a page if its content hasn't changed - relaxed plausibility check of total page count stated in the postamble (this value overflows if the DVI file contains more than 65535 pages) - added validity checks for bop (begin of page) offsets present in the bop and post commands - some refactorings and minor improvements dvisvgm-2.5 (2018-08-08) - added multi-page support (option --page) to PDF mode (option --pdf) - added evaluation of transformation options in PDF mode - added support for all length units to option --transform - TeX Live Win32: look for Ghostscript DLL in the TL folders as well (thanks to Akira Kakuto for sending the patch) - potrace has been added again to the bundled third-party libraries - instead of linking the bundled libraries brotli, potrace, woff2, and xxhash, the configure script now looks for the corresponding system libraries by default - added option --enable-bundled-libs to the configure script to build and statically link the bundled libraries - some refactorings dvisvgm-2.4.2 (2018-07-18) - fixed height and depth values computed when using the preview package - removed additional borders from the bounding boxes of hyperlinked areas - prevent warnings if special "psfile" is called with argument "/dev/null" (e.g. option "psfixbb" of the preview package adds such specials) - "make install" no longer fails if the manpage can't be built dvisvgm-2.4.1 (2018-07-07) - fixed handling of delay parameter of option --progress - updated brotli library to version 1.0.5 - updated woff2 library to version 1.0.2 - updated URLs in manual page - several minor code refactorings dvisvgm-2.4 (2018-05-03) - added special 'pdffile' similar to 'psfile' to embed PDF graphics - added option --pdf to convert single-page PDF documents to SVG - reassigned short option -P from --progress to --pdf - added option --stdin to receive input from stdin - option --stdout can now be combined with option --zip - added processing of GS operators '.setshapealpha' and '.setblendmode' - fixed outer transformations applied to psfile specials - fixed computation of bounding boxes triggered by psfile specials - several code refactorings dvisvgm-2.3.5 (2018-03-23) - added evaluation of PS operator 'setpagedevice' in psfile specials - fixed evaluation of dvips color names - fixed warning printed when using Ghostscript 9.23 dvisvgm-2.3.4 (2018-03-14) - fixed error message printed when adding a single '-' on the command-line - added missing data file that lead to failing tests (GH bug #87) - updated brotli library to version 1.0.3 - some code refactorings dvisvgm-2.3.3 (2018-02-20) - fixed wrong behavior when requiring both default mapfiles and pdf:mapline or pdf:mapfile specials - fixed an exception thrown in case of unavailable fonts dvisvgm-2.3.2 (2018-02-08) - prevent the creation of redundant tspan elements - added support for new JFM format (patch by Hironobu Yamashita) - fixed build error occurred if GS development files were missing - fixed a potential memory issue regarding option --cache dvisvgm-2.3.1 (2018-01-12) - fixed the width of characters slanted by a mapfile entry (GH bug #82) - if ttfautohint fails for a font, dvisvgm now uses the unhinted font and prints a corresponding warning message - some code cleanup dvisvgm-2.3 (2017-12-28) - added experimental support for ttfautohint - updated xxHash to version 0.6.4 - added configuration option to set location of libkpathsea (GH bug #71) - some improvements of the build system dvisvgm-2.2.3 (2017-12-12) - updated the bundled brotli library to version 1.0.2 - fixed a potential memory issue - some code and test improvements dvisvgm-2.2.2 (2017-11-17) - fixed memory issue regarding font maps (GH bug #79) - avoid scientific notation of floating point numbers - minor code improvements dvisvgm-2.2.1 (2017-11-13) - fixed portability issue when building the manpage (GH bug #72) - fixed incomplete computation of PS line width (GH bug #77) - further code refactorings dvisvgm-2.2 (2017-10-19) - added evaluation of pdf:pagesize specials - added evaluation of PDF hyperlink specials - try to load Ghostscript dylib on Mac systems (patch by Toby Fleming, GH bug #66) - improved TPIC special handler, added evaluation of 'tx' special - length values in dvisvgm specials now accept unit specifiers - added pdftex.map to default mapfiles - fixed potential infinite loop after starting subprocesses (GH bug #68) - files included with psfile are now also searched in the texmf tree if not present in the current working directory (GH bug #69) - fixed transformation issue in computation of psfile position (GH bug #70) - updated bundled brotli, woff2, and xxhash libraries - several code refactorings and improvements dvisvgm-2.1.3 (2017-02-20) - fixed build failures of libfontforge on Solaris 10 - increased code portablity dvisvgm-2.1.2 (2017-02-12) - bundled the googletest sources to simplify building and executing the tests - fixed a couple of issues related to LLVM's libc++ (thanks to Mojca Miklavec and Rasmus Larsen for their help to isolate the problems) - fixed some potential memory leaks - removed 'restrict' keyword from xxHash sources to avoid C++ compilation errors (https://github.com/Cyan4973/xxHash/issues/88) dvisvgm-2.1.1 (2017-02-07) - don't rerun Metafont for missing fonts - fixed build failure on OS X (GH bug #65) - several minor code improvements and test enhancements dvisvgm-2.1 (2017-01-19) - added option --tmpdir to explicitly set temp folder - temporary files are no longer created in the current working directory by default but in the system's temp folder (GH bug #63) - added warning/error messages if temporary files could not be written - fixed collision of Unicode points in AGL table (GH bug #64) - retain letter case of filenames even if not significant (Windows only) - code refactorings and cleanup dvisvgm-2.0.4 (2016-11-16) - bundled reduced FontForge library (ff-woff) with the sources - minor fixes in manpage and --help texts - few code improvements dvisvgm-2.0.3 (2016-09-27) - fixed a regression in the character positioning of virtual fonts - fixed positioning of rules dvisvgm-2.0.2 (2016-09-19) - fixed computation of the character depths of native fonts - fixed a regression in the computation of DVI positions (GH bug #61) dvisvgm-2.0.1 (2016-09-03) - added optional argument parameter "autohint" to option --font-format in order to create autohinted TTF, WOFF, or WOFF2 fonts dvisvgm-2.0 (2016-08-29) - added option --font-format to select the data format of embedded fonts (currently supported formats: SVG, TTF, WOFF, WOFF2) - switched the code base from C++03 to C++11 - reimplemented the command-line parser and the CommandLine class generator - major refactorings of several parts of the code dvisvgm-1.16 (2016-07-04) - added support for XDV version 7 introduced by XeTeX 0.99995 - added optional processing of papersize specials - added support for length units cc, dd, and sp - fixed unit conversion in computation of bounding boxes - fixed propagation of resolution value to the glyph vectorizer - fixed transformation of background rectangle - prevent processing of corrupted GF files - major refactorings of the DVI reader and the SVG backend dvisvgm-1.15.1 (2016-04-19) - added explicit encoding attribute to the XML declaration again (GH bug #54) - added support for AGL character names of the form 'uFOO' and 'uniFOO' - fixed parsing of transformation parameters given on the command-line - minor code and test improvements dvisvgm-1.15 (2016-02-27) - added option --comments to add additional information to the SVG file - fixed a clipping bug in the PostScript handler - some code improvements and refactorings - moved test data files to a separate folder dvisvgm-1.14.2 (2016-01-20) - fixed handling of background color specials (now they affect all succeeding pages until the next change) - fixed a potential memory issue caused by accessing an invalid iterator - updated xxHash to version 0.5.0 - added xxHash to the output of --version=1 - minor additions to the manpage - added test case to validate the hash values used in Unicode.cpp dvisvgm-1.14.1 (2016-01-05) - fixed an issue in the PostScript handler that could lead to invalid SVG files if multiple DVI pages were converted - added checks for invalid GF files to prevent undefined behavior dvisvgm-1.14 (2015-12-28) - added evaluation of PSTricks specials 'pst:' and 'PST:' - the bounding box data created by the preview package is now adapted to create a tight box by default - added option --bbox=preview to apply the unmodified bounding box data created by the preview package - improved lookup of files located in the current working directory - fixed a memory issue related to graphics paths - improved extraction of kapathsea version number - minor code and test improvements dvisvgm-1.13 (2015-12-08) - added evaluation of PS operators 'ashow', 'awidthshow', and 'widthshow' (GH bug #49) - improved conversion of fonts referenced by PS code to graphics paths - redundant 'moveto' commands are now removed from paths - fixed issue concerning evaluation of PS operator 'setcolor' - fixed output of PS error messages - updated bundled xxHash library to revision 42 - minor code refactorings and cleanup dvisvgm-1.12 (2015-11-18) - added option --colornames to replace RGB values by SVG color names - fixed resolving of character codes for fonts without supported chracater maps - fixed a memory issue that could occur when calling Metafont dvisvgm-1.11 (2015-09-21) - improved mapping of unknown characters to Unicode - improved handling of text elements in conjunction with \specials (patch by Till Tantau) - fixed an issue that could lead to (invalid) U+0000 codepoints - prevent creating invalid XML by quoting xlink:title attributes properly - documentation: updated links to new website address dvisvgm-1.10 (2015-07-15) - added support for the new XDV format 6 created by XeTeX 0.99992 - improved mapping of PostScript character names to Unicode points dvisvgm-1.9.2 (2015-04-08) - avoid retracing of fonts if option --no-fonts and --trace-all=y are given - skip tracer messages if no glyphs have been traced - extended the build system to generate code coverage reports - improved some tests of the test suite - some general code refactorings and improvements dvisvgm-1.9.1 (2015-02-28) - extended --output pattern syntax by arithmetic expressions and width specifiers - improved formatting of manpage - fixed Clang build issue (patch by Peter Breitenlohner) - fixed a build issue occurred with old MinGW compilers - code cleanup and refactorings dvisvgm-1.9 (2014-12-29) - added partial implementation of PostScript operator 'shfill' to create color gradient fills (supported shading types: free-form triangular, lattice-form triangular, Coons, and tensor-product patch meshes) - added options --grad-segments, --grad-overlap, and --grad-simplify to control the approximation of color gradients - added option --no-merge to create separate text elements for each character (patch by Khaled Hosny) - added a simple progress counter to the EPS to SVG converter - added opt2cpp.py as a free replacement for my non-free opt2cpp.xsl script (thanks to Khaled Hosny for the implementation and for providing it for free) - added lookup of Ghostscript library in the Windows registry - fixed validity check of DVI files - fixed interaction of color specials and PostScript color operators - several code refactorings and improvements dvisvgm-1.8.1 (2014-08-29) - unreferenced clipPath elements are now removed from the SVG files - fixed side-effects caused by unexpected bop/eop operators in PS specials (LP bug #1350688) - few improvements to configure.ac (patches by Khaled Hosny) - removed redundant code dvisvgm-1.8 (2014-07-29) - added option --clipjoin which tells dvisvgm to compute intersections of clipping paths itself and not to delegate this task to the SVG renderer - added option --relative to create relative rather than absolute path commands - added evaluation of PS operator 'clippath' which copies the current clipping path into the graphics path - fixed PS operator 'show' to prevent the creation of unintended path overlays - fixed memory leak in class FontEngine (patch by Khaled Hosny) - fixed unintended throwing of a DVIException when dvisvgm is called with option --list-specials - Cygwin builds of dvisvgm now look for the proper filename of the Ghostscript DLL dvisvgm-1.7 (2014-06-18) - all DVI files are pre-processed now to allow the implementation of advanced features that rely on data not available on the pages being converted - added support for internal hyperref links across pages - added \special command dvisvgm:rawdef to insert raw SVG fragments to the section - added the new \special commands dvisvgm:rawset, dvisvgm:endrawset, and dvisvgm:rawput to assign and access a sequence of SVG fragments via an identifier (LP feature request #1215878) - removed redundant elements from SVG files - fixed support of external fonts containing characters not mapped by the embedded unicode tables (LP bug #1276689) - fixed incorrect extent values shown in conjunction with the preview package - many refactorings and code improvements dvisvgm-1.6 (2014-04-22) - added option --zoom to "visually" scale the generated SVG graphics while preserving the original size and position values of the graphic objects - extended argument syntax of option --linkmark to allow to select the box/line color - changed default link marker from 'line' to 'box' - changed link markers to be only split on line breaks while extended in all other cases - if libgs is not directly linked to the binary, dvisvgm now looks for libgs.so.X instead of libgs.so (supported GS ABIs: X = 7, 8, 9) - removed time stamp and machine triplet from generated SVG files - some code improvements and refactorings dvisvgm-1.5.3 (2014-04-11) - improved positioning of PostScript graphics - fixed positioning of DVI rules/rectangles - switched internal computations from TeX points (pt) to PostScript points (bp) dvisvgm-1.5.2 (2014-01-10) - fixed handling of global font colors and color specials - several code improvements dvisvgm-1.5.1 (2013-10-29) - fixed processing of bounding box data created by the preview package - fixed processing of font definitions across DVI pages - fixed compilation issues occurred if processing of PS specials is disabled - don't print the logical page number if it's equal to the physical one - some minor code improvements dvisvgm-1.5 (2013-09-02) - added support for DVI format 3 as created by pTeX in vertical/tate mode - added support for DVI format 5 (XDV) as created by XeTeX - replaced numeric entity references by corresponding UTF-8 characters in generated SVG files - added px unit to font-size attributes as used in the stylesheet section to ensure correct computation of font sizes (LP bug #1215857) - various code refactorings dvisvgm-1.4 (2013-08-02) - added basic support for CMap files and CID-based fonts - added character mapping from CIDs to char codes based on the encoding tables of a non-CID font - added support for OTF fonts - added evaluation of bounding box data generated by the preview package - extended option --linkmark to mark hyperlinked areas with an arbitrary background color - PS handler: improved evaluation of PS header specials - PS handler: improved evaluation of operator 'show' - removed DOCTYPE declaration from generated SVG files - removed encoding attribute from xml declaration (replaces ISO-8859-1 with UTF-8) - various code improvements and refactorings dvisvgm-1.3 (2013-05-13) - added support for hyperref specials - added command-line option --linkmarker to select the way how to mark hyperlinked areas - dvisvgm builds for MiKTeX now try to access the Ghostscript DLL provided by MiKTeX so that it's no longer necessary to install Ghostscript separately - improved the handling of TFM files to avoid failures in case of malformed files - added evaluation of Japanese Font Metric (JFM) files - the bundled potrace library has been removed from the source tarball as it's easy to build the latest releases from the original sources available at http://potrace.sourceforge.net - several code refactorings dvisvgm-1.2.2 (2013-04-26) - fixed a bug that prevented the lookup of fontmap files - avoid throwing an exception but print a warning message if MiKTeX is not available - print a warning message if PostScript specials are found but ignored - added information about "dvisvgm -E" to the --help text and to the manpage - various code refactorings and cleanups dvisvgm-1.2.1 (2013-04-09) - updated bundled potrace library to version 1.11 - avoid building bundled potracelib if system library is present (patch by Alexis Ballier) - allow background color specials to create white background rectangles - code refactorings and cleanup dvisvgm-1.2 (2013-03-01) - PostScript handler: added support of tiling patterns - PostScript handler: added support for EPS files with binary headers/footers - added option --eps to directly convert EPS files to SVG - added option --precision to select the number of decimal places used in the generated SVG files - added an optional argument to --help to choose a display variant - fixed the text alignment of the --help output - improved handling of PostScript operator "show" - choose the correct output location if the input file argument contains path specifiers (Windows only) dvisvgm-1.1 (2013-01-22) - added evaluation of pdf:mapline and pdf:mapfile specials - added evaluation of subfont file definitions (.sfd files) - added support for TTC (TrueType collection) fonts - added evaluation of font style parameters given in a font map definition - renamed option --map-file to --fontmap - the new option --fontmap allows multiple mapfile arguments and optional mode specifiers - if a PostScript error occurs, dvisvgm prints an error message together with the PS operand stack, as generated by Ghostscript - if font checksums don't match, dvisvgm prints a warning now - avoid throwing exceptions if referenced encoding files are not available - added support for 64bit Windows builds - removed compilation error when using a C++11 compiler (patch by Peter Breitenlohner) - some code refactorings and improvements dvisvgm-1.0.12 (2012-09-27) - print a message if the processing of PostScript specials is disabled - the resulting SVG is now scaled to bp ("big point" units) properly - added the evaluation of PS operators rectclip, rectfill, and rectstroke - ignore dvips operator bop if present in a PS special - fixed processing of special strings that contain newline characters dvisvgm-1.0.11 (2012-03-09) - added Ghostscript to library list printed by --version=yes - fixed a bug in the number parser that could lead to displaced objects (SF bug #3471097) - corrected the computation of bounding boxes of DVI rules (lp bug #948713) - improved code compatibility to make dvisvgm compile with clang++ (patch by Vladimir Lomov) - fixed formatting issues in the manual page - updated information about bug reporting (tracker moved to Launchpad) dvisvgm-1.0.10 (2011-12-18) - introduced environment variable DVISVGM_COLORS to allow user-defined message colors - fixed linking issue concerning libfreetype - fixed potential clashes of character IDs dvisvgm-1.0.9 (2011-10-13) - fixed segfault occurred in TeX Live Win32 caused by mf.exe being unavailable (thanks to Akira Kakuto for tracking down the issue) - updated bundled potrace library to version 1.10 - some minor code improvements dvisvgm-1.0.8 (2011-05-31) - PS handler: added evaluation of PS operators save, restore, and grestoreall - PS handler: fixed potential segfault caused by invisible zero-length paths - fixed computation of current drawing position influenced by PS and DVI actions - don't stop Metafont conversions on errors any longer in order to convert buggy MF fonts properly dvisvgm-1.0.7 (2011-05-06) - improved overall handling of PS specials - fixed broken PS special subset 'ps::' - fixed scaling of PS line properties (width, dash distance, etc.) - fixed semantics of TPIC special 'ip' (doesn't draw polygon outlines any longer) dvisvgm-1.0.6 (2011-04-21) - fixed segfault occurred if a (malformed) DVI file calls set_char/put_char without preceding font definition - added CTRL-C handler - MiKTeX support updated to version 2.9 - some code refactorings dvisvgm-1.0.5 (2011-03-01) - added optional integer argument to option -n to disable generation of elements - added missing unit to width/height attributes of svg root element (SF bug #3185773) - added integrity check to font cache files - updated bundled potrace library to version 1.9 - fixed a couple of minor issues dvisvgm-1.0.4 (2010-12-18) - added missing line width/dash pattern scaling to PS handler - fixed scaling issue in PS positioning - fixed compilation issue related to FreeType 2.4.0 dvisvgm-1.0.3 (2010-08-06) - applied some more portability patches for TeX Live - fixed a potential memory issue - fixed a transformation issue regarding special 'psfile' (SF bug #3037372) dvisvgm-1.0.2 (2010-06-22) - applied latest TeX Live portability patches sent by Peter Breitenlohner and Karl Berry - fixed a potrace name clash occurred on Mac OS X Tiger - fixed putchar() name clash occurred on Solaris - fixed a couple of conversion warnings - updated the test suite dvisvgm-1.0.1 (2010-06-11) - fixed a memory issue in the PS handler that could lead to a segfault (SF bug #3013392) - fixed a recursion issue in the PS handler - suppress ANSI color code when terminating dvisvgm-1.0 (2010-06-08) - conversion of multiple pages (must be enabled explicitly, see option --pages) - added transparency support to the PS handler - improved conversion results of the PS handler - added support for computation of local bounding boxes - optional colorization of dvisvgm messages (option --color) - improved progress indicator (option --progress) - a couple of improvements of the build system dvisvgm-0.9.1 (2010-04-23) - CSS style definitions omit unnecessary fonts now - SVG validity was broken when using font elements - fixed two memory issues that could lead to segfaults dvisvgm-0.9 (2010-03-25) - added option --exact and corresponding algorithms to compute the exact bounding boxes of characters - added option --keep that prevents deleting temporary font files - extended option --trace-all by an optional boolean argument controlling the re-tracing of glyphs - fixed bug in evaluation of embedded PS headers - several code refactorings dvisvgm-0.8.8 (2010-02-02) - added option --libgs and evaluation of environment variable LIBGS to overwrite the expected file name of the GS shared library (only available if dvisvgm isn't linked against libgs and GS support isn't completely disabled) - option --bbox can now be used to enlarge the minimal bounding box by a given amount - fixed bug in evaluation of option --page - applied patches sent by Peter Breitenlohner to prepare the integration of dvisvgm into TeX Live - some code refactorings dvisvgm-0.8.7 (2009-11-09) - fixed a bounding box issue concerning italic corrections - PS handler: zero-length paths are now drawn as dots - PS handler: fixed a path positioning issue - PS handler: colors set by color specials are now considered properly - added macro {?nl} to be used with special dvisvgm:raw dvisvgm-0.8.6 (2009-10-13) - renamed command-line option --bbox-format to --bbox - option --bbox can now be used to set an arbitrary bounding box - added the two special variants "dvisvgm:bbox abs" and "dvisvgm:bbox fix" - PS clipping path sequences and intersections are now handled correctly - fixed a PS bounding box bug - fixed a couple of PS positioning issues reported by John Bowman - fixed a bit shift overflow in the font tracer occurred on 64-bit systems dvisvgm-0.8.5 (2009-10-01) - added an optional depth parameter to special dvisvgm:raw - updated the man page - added LGPL license text needed for the gzstream wrapper classes dvisvgm-0.8.4 (2009-09-17) - improved the command-line parser to be more POSIX-compliant - added a simple progress indicator for time-consuming special operations - option --cache prints more information about the cached fonts - fixed a clipping bug in the PostScript handler (thanks to John Bowman for also providing a patch for this issue) - fixed a bug in computation of the PS bounding box - fixed a memory bug in the GF tracer module dvisvgm-0.8.3 (2009-08-28) - added basic evaluation of the PostScript "show" operator (handles PSTricks Type 3 fonts properly now) - improved checks for Ghostscript and potrace library in configure script - external Ghostscript and potrace development files are used if available - PostScript header/prologue files are now loaded regardless of converted page - replaced command-line option variant --cache=? by --cache dvisvgm-0.8.2 (2009-08-24) - changed license of dvisvgm to GPL version 3 or later - replaced getopt-based command-line parser by own implementation in order to simplify future internationalizations - fixed memory bug in fontmap reader dvisvgm-0.8.1 (2009-08-02) - added evaluation of more psfile parameters - fixed computation of bounding box in psfile special - fixed compilation errors and a conversion bug occurred on x64 systems dvisvgm-0.8 (2009-07-27) - experimental evaluation of PostScript specials has been added (requires a recent version of the Ghostscript shared library libgs.so or gsdll32.dll) - several code improvements and refactorings - fixed compilation bug occurred when using GCC 4.4.x dvisvgm-0.7.3 (2009-04-24) - fixed bug in font map reader that could cause a segmentation fault - fixed bug in creation of shorthand path drawing commands - fixed bug in TPIC special handler dvisvgm-0.7.2 (2009-04-02) - font caching has been added (speeds up embedding of bitmap fonts) - added option --trace-all that enables tracing of all glyphs of all bitmap fonts used in the current DVI file. Even glyphs that are currently not needed are considered. This avoids multiple calls of Metafont for the same fonts. In combination with the new caching functionality this can drastically increase the speed of successive dvisvgm calls. - if option --no-fonts is used, all glyph sizes are now computed correctly - use shorthand path commands in SVG fonts if possible dvisvgm-0.7.1 (2009-03-09) - evaluation of a subset of emTeX specials has been added - specials for embedding of raw SVG snippets have been added - evaluation of TPIC specials has been added - added background color support - added option -n, --no-fonts that replaces fonts by paths (enables applications w/o SVG font support to render dvisvgm's output properly) - moved defs to top of SVG file to make Firefox's SVG renderer happy - fixed bug in color handler dvisvgm-0.7 (2009-02-16) - basic support for evaluation of specials has been added - evaluation of color specials has been added - renamed command-line option -S to --no-specials and inverted previous behavior - selected special sets can be disabled by optional arguments to --no-specials (currently only color specials) - added option --no-style (see manpage for further details) - added optional '+' flag to option --map-file (see manpage for further details) - fixed \magnificaton bug (dvi magnification factor is now applied properly) - fixed buggy call of maketfm/makemf in Windows/MiKTeX version - fixed buggy evaluation of command-line argument -m/--map-file - several internal code improvements dvisvgm-0.6.1 (2009-01-29) - added support for dvips map files - removed dependency on dvipdfm's map file (now ps2pk.map, psfonts.map or dvipdfm.map is used by default) - fixed compilation bug #2535497 - some internal refactorings dvisvgm-0.6 (2009-01-23) - added support for varying font encodings - updated MiKTeX support using its COM interface - fixed incomplete handling of nested virtual fonts - fixed a font handling bug that could cause segmentation faults - fixed bug in matrix transformation code - updated bundled potrace library to version 1.8 dvisvgm-0.5 (2007-03-26) - redesigned and improved font handling - added support for virtual fonts - evaluation of dvipdfm's map file to find font files with differing names (e.g. cork-lmr10 => lmr10) - automatic invocation of mktexmf etc. in case of missing font files (tfm, mf) - command-line option -m has been renamed to -M - added command-line options -m/--map-file and -n/--no-mktexmf - memory bug in StreamCounter class has been fixed - added sources of Peter Selinger's potrace library (part of potrace, https://potrace.sourceforge.net) to simplify the build process dvisvgm-0.4.3 (2007-01-03) - problem with changed freetype API (freetype version >= 2.2.1) has been fixed - updated MiKTeX support to version 2.5 - minor code improvements - some unit tests based on CxxTest (http://cxxtest.sourceforge.net) have been added dvisvgm-0.4.2 (2005-09-22) - added SVG transformation options - some bugfixes in command line frontend and TFM handling - code refactorings to improve modularity and extensibility dvisvgm-0.4.1 (2005-09-02) - added option -b to specify the bounding box - added a manual page dvisvgm-0.4 (2005-08-24) - Added a glyph tracing module that vectorizes Metafont's bitmap output if no corresponding Type 1 font file is available. dvisvgm-0.3 (2005-08-10) - Initial public release with basic conversion functionality. dvisvgm-3.5/README000066400000000000000000000125601501401750600137230ustar00rootroot00000000000000dvisvgm -- A DVI to SVG converter DESCRIPTION dvisvgm is a utility for TeX/LaTeX users. It converts DVI, EPS, and PDF files to the XML-based scalable vector graphics format SVG. DEPENDENCIES dvisvgm relies on the following free libraries: * Clipper (https://www.angusj.com/delphi/clipper/documentation/Docs/Overview/_Body.htm) To compute the intersections of two curved paths, dvisvgm flattens the paths to polygons, intersects them using Clipper, and reconstructs the curves afterwards. * FreeType 2 (https://freetype.org) This library is used to extract the glyph outlines from vector fonts (PFB, OTF, TTF). * Ghostscript (https://www.ghostscript.com) The PostScript special handler requires the Ghostscript shared library libgs.so.N (Linux) or gsdll32.dll/gsdll64.dll (Windows) to be installed. If the configure script finds the corresponding Ghostscript development files on the system, it directly links against libgs.so.N, where N is the library's ABI version. Otherwise, the library is looked up during runtime, and the PostScript support is enabled only if the shared library can be found. Due to incompatible changes of the Ghostscript API, dvisvgm requires Ghostscript 8.31 or later. * kpathsea (https://tug.org/kpathsea) This library is part of the Web2C package and is usually installed in conjunction with a TeX distribution. kpathsea provides functions for searching files in the large texmf tree. Please ensure that you use the kpathsea version coming with or matching your TeX system. * potracelib (https://potrace.sourceforge.net) Peter Selinger's bitmap tracing library is utilized to vectorize Metafont's bitmap output. A recent version is also part of the dvisvgm sources. * ttfautohint (https://www.freetype.org/ttfautohint) dvisvgm can optionally be built with ttfautohint support to allow for autohinting the generated TrueType, WOFF, and WOFF2 fonts. Since this is still an experimental feature, ttfautohint support is disabled by default. The development files required for Windows can be found at https://github.com/mgieseki/ttfautohint-dll. * woff2 and brotli (https://github.com/google/woff2) These Google libraries are bundled with the dvisvgm sources. They are used to create WOFF2 from TrueType fonts. * xxHash (https://github.com/Cyan4973/xxHash) The xxHash library provides a fast hash algorithm. dvisvgm uses it to create unique integer values from PostScript character names in order to store them in a compact way together with their Unicode points. A recent version of xxHash is bundled with the dvisvgm sources. * zlib (https://www.zlib.net) This library is required to create compressed SVGZ files. BUILDING DVISVGM FROM SOURCE dvisvgm is written in C++11 (ISO C++ standard 2011) and requires an appropriate compiler, like GCC 4.9, Clang 3.3, or any later version. The configure script checks for the availability of C++11 support and adds the proper compiler options if necessary. Quick installation info: * ensure that the development packages of all libraries, listed above, are installed * type "autoreconf -fi" if "configure" is not present in the dvisvgm root folder * either type "./configure" if you don't want to use the bundled libraries brotli, potrace, woff2, and xxHash but link against the corresponding system libraries, or type "./configure --enable-bundled-libs" in order to build and statically link the bundled libraries. * type "make" * type "make install" as root (or "sudo make install") For generic configuration instructions see the file INSTALL. The configure script should recognize all necessary parameters. If a library is installed but not detected, specify its location as commandline parameter of configure, e.g. ./configure --with-freetype=/usr/local/freetype (all available options can be displayed with ./configure --help) The tracer module calls Metafont in case of lacking TFM or PFB files via a system call. Please ensure that Metafont is installed and reachable through the system's search path. If you don't like compiling the sources yourself, you can download pre-compiled executables for Windows and MiKTeX from the project website instead (see below). USAGE Information about the command-line interface and the available options can be found in the manual page. ADDITIONAL INFORMATION This package is available from CTAN (dviware/dvisvgm) and can be downloaded from the project website as well: https://dvisvgm.de Here you can find the sources, pre-compiled binaries and further additional information about the converter and related topics. If you've found a bug, please let me know. You can either send me an email or preferably use the bug tracker at GitHub (https://github.com/mgieseki/dvisvgm). COPYRIGHT Copyright (C) 2005-2025 Martin Gieseking 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. See file COPYING for details. dvisvgm-3.5/README.md000066400000000000000000000231321501401750600143170ustar00rootroot00000000000000_dvisvgm_ – A fast DVI to SVG converter ============================================= [![C/C++ CI](https://github.com/mgieseki/dvisvgm/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/mgieseki/dvisvgm/actions/workflows/c-cpp.yml) [![Build Status](https://ci.appveyor.com/api/projects/status/0rbkw88js1on4g2u/branch/master?svg=true)](https://ci.appveyor.com/project/mgieseki/dvisvgm/branch/master) [![Copr Status](https://copr.fedorainfracloud.org/coprs/mgieseki/dvisvgm/package/dvisvgm/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/mgieseki/dvisvgm/package/dvisvgm) [![Code Status](https://scan.coverity.com/projects/1099/badge.svg)](https://scan.coverity.com/projects/1099) [![License](https://img.shields.io/:license-GPL%20v3+-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) [![Releases](https://img.shields.io/github/release/mgieseki/dvisvgm.svg)](https://github.com/mgieseki/dvisvgm/releases) Description ----------- _dvisvgm_ is a utility for TeX/LaTeX users. It converts [DVI](https://en.wikipedia.org/wiki/Device_independent_file_format), [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript), and [PDF](https://en.wikipedia.org/wiki/PDF) files to the XML-based scalable vector graphics format [SVG](https://www.w3.org/TR/SVG). The latest releases support standard DVI files (version 2) as well as DVI output created by [pTeX](https://ctan.org/pkg/ptex) in vertical mode (version 3), and [XeTeX](https://xetex.sourceforge.net) (versions 5 to 7, also known as XDV). To get an impression of the conversion results, have a look at the [examples](https://dvisvgm.de/Examples) created with _dvisvgm_. Short overview of the main features: * Complete font support including [virtual fonts](https://texfaq.org/FAQ-virtualfonts), evaluation of [font encodings](https://texfaq.org/FAQ-whatenc), CMap files, sub-font definitions and font maps. * Glyph outlines of all required fonts are embedded into the generated SVG files. * The font data can be embedded in SVG, TrueType, WOFF, or WOFF2 format. * Glyph outlines of fonts that are not available in a vector format are generated on-the-fly by vectorizing [METAFONT](https://en.wikipedia.org/wiki/Metafont)'s bitmap output. * _dvisvgm_ allows to replace [font elements](https://www.w3.org/TR/SVG/fonts.html) by [paths](https://www.w3.org/TR/SVG/paths.html) so that applications without SVG font support are enabled to render dvisvgm's output properly. * Computes tight bounding boxes for the generated graphics, but supports common paper formats and arbitrary user-defined sizes as well. * Option `--eps` allows to convert [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files to SVG. * Option `--pdf` allows to convert [PDF](https://en.wikipedia.org/wiki/PDF) documents to SVG. * [Intersections of clipping paths](https://dvisvgm.de/Clipping) can be computed directly instead of delegating this task to the SVG renderer which increases the compatibility of the generated SVG files. * Approximates PostScript [color gradient fills](https://dvisvgm.de/Gradients) not directly supported by SVG 1.1. * The generated SVG structure and data can be improved with the built-in [SVG optimizer](https://dvisvgm.de/Manpage/#opt-optimize). * Optionally creates compressed [SVGZ](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics#Compression) files. * Provides options for applying page transformations, like translation, rotation, scaling, and skewing. * Evaluates several [specials](https://texfaq.org/FAQ-specials) including color, emTeX, tpic, hyperref/HyperTeX, papersize, PDF hyperlink and mapfile, as well as PostScript specials. * The converter was successfully tested on various Linux ([TeX Live](https://www.tug.org/texlive)) and Windows ([MiKTeX](https://www.miktex.org), TeX Live) systems. * _dvisvgm_ has been added to [TeX Live](https://www.tug.org/texlive), [MiKTeX](https://www.miktex.org), and [MacPorts](https://www.macports.org). It is therefore available for a wide range of operating systems. Usage ----- For detailed information about the command-line interface and all available options of _dvisvgm_, see the [manual page](https://dvisvgm.de/Manpage). Dependencies ------------ _dvisvgm_ relies on the following free libraries: * [Clipper](https://www.angusj.com/delphi/clipper/documentation/Docs/Overview/_Body.htm) To compute the intersection of two curved paths, _dvisvgm_ flattens the paths to polygons, intersects them using a slightly modified version of Clipper, and reconstructs the curves afterwards. A slightly modified version of Clipper is bundled with the sources. * [FreeType 2](https://freetype.org) This library is used to extract the glyph outlines from vector fonts (PFB, OTF, TTF). * [Ghostscript](https://www.ghostscript.com) The PostScript special handler requires the Ghostscript shared library `libgs.so.N` (Linux) or `gsdll32.dll`/`gsdll64.dll` (Windows) to be installed. If the configure script finds the corresponding Ghostscript development files on the system, it directly links against `libgs.so.N`, where _N_ is the library's ABI version. Otherwise, the library is looked up during runtime, and the PostScript support is enabled only if the shared library can be found. Due to incompatible changes of the Ghostscript API, _dvisvgm_ requires Ghostscript 8.31 or later. * [Kpathsea](https://tug.org/kpathsea) This library is part of the Web2C package and is usually installed in conjunction with a TeX distribution. Kpathsea provides functions for searching files in the large `texmf` tree. Please ensure that you use the kpathsea version coming with or matching your TeX system. * [potracelib](https://potrace.sourceforge.net) Peter Selinger's bitmap tracing library is utilized to vectorize Metafont's bitmap output. It's also bundled with the _dvisvgm_ sources. * [ttfautohint](https://www.freetype.org/ttfautohint) _dvisvgm_ can optionally be built with ttfautohint support to allow for autohinting the generated TrueType, WOFF, and WOFF2 fonts. Since this is still an experimental feature, ttfautohint support is disabled by default. To enable it, run `configure` with option `--with-ttfautohint`. * [woff2](https://github.com/google/woff2) and [brotli](https://github.com/google/brotli) These Google libraries are bundled with the _dvisvgm_ sources. They are used to create WOFF2 files from TrueType fonts. * [xxHash](https://github.com/Cyan4973/xxHash) The xxHash library provides a fast hash algorithm. _dvisvgm_ uses it to create unique integer values from PostScript character names in order to store them in a compact way together with their Unicode points. A recent version of xxHash is bundled with the _dvisvgm_ sources. * [zlib](https://www.zlib.net) This library is required to create compressed [SVGZ](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics#Compression) files. Building dvisvgm from source ---------------------------- _dvisvgm_ is written in C++11 ([ISO C++ standard 2011](https://www.iso.org/standard/83626.html)) and requires an appropriate compiler, like [GCC](https://gcc.gnu.org) 4.9, [Clang](https://clang.llvm.org) 3.3, or any later version. The configure script checks for the availability of C++11 support and adds the proper compiler options if necessary. Quick installation info: * ensure that the development packages of all libraries, listed above, are installed * type `autoreconf -fi` if `configure` is not present in the _dvisvgm_ root folder * either type `./configure` if you don't want to use the bundled libraries _brotli_, _potrace_, _woff2_, and _xxHash_ but link against the corresponding system libraries, * or type `./configure --enable-bundled-libs` in order to build and statically link the bundled libraries. * type `make` * type `make install` as root (or `sudo make install`) For generic configuration instructions see the file INSTALL. The configure script should recognize all necessary parameters. If a library is installed but not detected, specify its location as command-line parameter of configure, e.g. `./configure --with-freetype=/usr/local/freetype` (all available options can be displayed with `./configure --help`) The tracer module calls Metafont in case of lacking TFM or PFB files via a system call. Please ensure that Metafont is installed and reachable through the system's search path. If you don't like compiling the sources yourself, you can download pre-compiled binaries for Windows and MiKTeX from the [project website](https://dvisvgm.de) instead. Additional Information ---------------------- This package is available from [CTAN](https://ctan.org/pkg/dvisvgm), and can be downloaded from the [project website](https://dvisvgm.de) as well. There you find the sources, [pre-compiled binaries](https://dvisvgm.de/Downloads), the [manual page](https://dvisvgm.de/Manpage), [FAQs](https://dvisvgm.de/FAQ) and further information about the converter and related topics. If you've found a bug, please let me know. You can either send me an email or preferably use the [bug tracker at GitHub](https://github.com/mgieseki/dvisvgm/issues). Copyright --------- Copyright © 2005–2025 [Martin Gieseking](mailto:martin.gieseking@uos.de) 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](https://www.gnu.org/licenses/gpl-3.0.en.html) for more details. dvisvgm-3.5/configure.ac000066400000000000000000000203101501401750600153210ustar00rootroot00000000000000# This file is part of dvisvgm # Copyright (C) 2005-2025 Martin Gieseking # # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([dvisvgm],[3.5],[martin.gieseking@uos.de]) DATE="May 2025" AC_CONFIG_SRCDIR(src) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_HOST AM_INIT_AUTOMAKE([subdir-objects dist-xz]) AM_CONDITIONAL([TEXLIVE_BUILD], [test "x$enable_texlive_build" = xyes]) AH_TEMPLATE([HOST_SYSTEM], [The machine triplet of the host system]) AC_DEFINE_UNQUOTED([HOST_SYSTEM], ["$host"]) # Checks for programs. AC_PROG_CC AC_PROG_CXX AX_CXX_COMPILE_STDCXX([11]) AM_PROG_AR LT_INIT AC_LANG(C) AX_CHECK_COMPILE_FLAG([-Wmismatched-tags -Wno-mismatched-tags], [CXXFLAGS="$CXXFLAGS -Wno-mismatched-tags"]) AC_CHECK_HEADERS([sys/time.h sys/timeb.h xlocale.h]) AC_HEADER_TIOCGWINSZ CPPFLAGS_SAVE="$CPPFLAGS" CFLAGS_SAVE="$CFLAGS" LDFLAGS_SAVE="$LDFLAGS" # Check availability and usability of the kpathsea library AC_ARG_VAR(KPSE_CFLAGS, [C/C++ compiler flags for the kpathsea library]) AC_ARG_VAR(KPSE_LIBS, [linker flags for the kpathsea library]) AC_ARG_VAR(KPSE_LIBS, []) AC_ARG_WITH([kpathsea], [AS_HELP_STRING([--with-kpathsea=prefix], [set location of kpathsea library])], [with_kpathsea="$withval"], [with_kpathsea=yes]) AS_IF([test "x$with_kpathsea" != "xyes"], [KPSE_CFLAGS="-I$with_kpathsea/include" KPSE_LIBS="-L$with_kpathsea/lib"] [CPPFLAGS="$CPPFLAGS $KPSE_CFLAGS" CFLAGS="$CFLAGS $KPSE_CFLAGS" LDFLAGS="$LDFLAGS $KPSE_LIBS"]) AC_CHECK_HEADER([kpathsea/kpathsea.h],, [AC_MSG_ERROR([please install the kpathsea development package])]) AC_CHECK_LIB([kpathsea], [kpse_find_file],, [AC_MSG_ERROR([libkpathsea not found, please install the corresponding package first])]) AC_MSG_CHECKING([kpathsea version]) AC_RUN_IFELSE([AC_LANG_SOURCE([#include #include #include int main() { FILE *f; f = fopen("kpseversion", "w"); if(!f) exit(1); fprintf(f, "%s\n", KPSEVERSION); fclose(f); exit(0); }])], [kpseversion=`cat kpseversion|sed 's/kpathsea version //'`], [kpseversion=], [kpseversion=unknown]) AC_MSG_RESULT("$kpseversion") rm -f kpseversion AS_IF([test -z "$kpseversion"], [AC_MSG_ERROR([Could not compile a simple kpathsea program -- check your installation])]) AC_SUBST(KPSE_CFLAGS) AC_SUBST(KPSE_LIBS) # Check how to link Ghostscript have_libgs=yes AC_CHECK_HEADER([ghostscript/iapi.h], [AC_CHECK_LIB(gs, gsapi_revision,, [have_libgs=no])], [have_libgs=no]) AS_IF([test "x$have_libgs" = "xno"], # Ghostscript not found, check for dlopen [AC_CHECK_LIB(dl, dlopen,, [AC_DEFINE(DISABLE_GS, 1, [Set to 1 if PostScript support should be disabled])] [AC_MSG_WARN(PostScript support disabled)])]) # Check for pkg-config PKG_PROG_PKG_CONFIG # Check for libraries. PKG_CHECK_MODULES([FREETYPE], [freetype2]) AC_ARG_ENABLE([woff], [AS_HELP_STRING([--disable-woff], [Disable WOFF support @<:@default=no@:>@])], [], [enable_woff=yes]) AM_CONDITIONAL([ENABLE_WOFF], [test "x$enable_woff" = "xyes"]) AC_ARG_WITH([ttfautohint], [AS_HELP_STRING([--with-ttfautohint@<:@=prefix@:>@], [enable ttfautohint support (disabled by default)])], [with_ttfautohint="$withval"], [with_ttfautohint=no]) # Add option to enable linking of bundled libraries (brotli, potrace, woff2, xxhash). AC_ARG_ENABLE([bundled-libs], [AS_HELP_STRING([--enable-bundled-libs], [use bundled libraries instead of the system ones @<:@default=no@:>@])]) AM_CONDITIONAL([USE_BUNDLED_LIBS], [test "x$enable_bundled_libs" = "xyes"]) # If option --enable-bundled-libs is not given, look for system libraries of brotli, potrace, woff2, and xxhash. AS_IF([test "x$enable_bundled_libs" != "xyes"], [AC_CHECK_HEADER(potracelib.h, [AC_SEARCH_LIBS(potrace_trace, [potrace], [have_potrace=yes])])] [AC_CHECK_HEADER([xxhash.h], [AC_SEARCH_LIBS(XXH32, [xxhash], [have_xxhash=yes])])] [AS_IF([test "x$enable_woff" = "xyes"], [PKG_CHECK_MODULES(BROTLI, [libbrotlienc], [have_brotli=yes])] [PKG_CHECK_MODULES(WOFF2, [libwoff2enc], [have_woff2=yes])])]) AM_CONDITIONAL(HAVE_POTRACE, [test "x$have_potrace" = "xyes"]) AM_CONDITIONAL(HAVE_BROTLI, [test "x$have_brotli" = "xyes"]) AM_CONDITIONAL(HAVE_WOFF2, [test "x$have_woff2" = "xyes"]) AM_CONDITIONAL(HAVE_XXHASH, [test "x$have_xxhash" = "xyes"]) # Dummy required for TL build sections in automake files AM_CONDITIONAL(WIN32, false) AS_IF([test "x$enable_woff" != "xyes"], [AC_DEFINE([DISABLE_WOFF], 1, [Define if WOFF support is disabled])], [AS_IF([test "x$with_ttfautohint" != "xno"], [AS_IF([test "x$with_ttfautohint" = "xyes"], # --with-ttfautohint without path => check via pkg-config [PKG_CHECK_MODULES([TTFAUTOHINT], [ttfautohint],, [AC_MSG_ERROR([can't locate ttfautohint, use "--with-ttfautohint=path" to specify its location])])], # --with-ttfautohint=/path/ttfautohint given [TTFAUTOHINT_CFLAGS="-I$with_ttfautohint/include"] [TTFAUTOHINT_LIBS="-L$with_ttfautohint/lib"])] [CPPFLAGS="$CPPFLAGS $TTFAUTOHINT_CFLAGS" CFLAGS="$CFLAGS $TTFAUTOHINT_CFLAGS" LDFLAGS="$LDFLAGS $TTFAUTOHINT_LIBS"] [AC_CHECK_HEADERS([ttfautohint.h],, [AC_MSG_WARN([ttfautohint.h not found])])] [AC_CHECK_LIB([ttfautohint], [TTF_autohint],, [AC_MSG_WARN([no working ttfautohint library found])] [AC_CHECK_LIB(dl, dlopen, [AC_MSG_NOTICE([enabled dynamic loading of ttfautohint])], [AC_MSG_WARN([disabled ttfautohint support])])])] [AC_SUBST(TTFAUTOHINT_CFLAGS) AC_SUBST(TTFAUTOHINT_LIBS)])]) AC_CHECK_LIB(z, gzopen) # Check for header files. AC_HEADER_DIRENT AC_CHECK_HEADERS_ONCE([libintl.h stdlib.h string.h strings.h unistd.h]) # Check for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL AC_TYPE_SIZE_T AC_STRUCT_TM # Check for library functions. AC_FUNC_STAT AC_CHECK_FUNCS_ONCE([ftime gettimeofday sigaction umask uselocale]) AX_GCC_BUILTIN(__builtin_clz) # add options for selection of "optional" library locations # currently these libraries are mandatory; the --with-foo options # are used to specify the locations explicitly AC_ARG_WITH(zlib, [AS_HELP_STRING([--with-zlib=DIR], [set location of the zlib library])], [AS_IF([test "x$withval" != "xno"], [AS_IF([test "x$withval" != "xyes"], [ZLIB_DIR=$withval])] [AS_IF([test -n "$ZLIB_DIR"], [ZLIB_CFLAGS="-I$ZLIB_DIR -I$ZLIB_DIR/include"] [ZLIB_LIBS="-L$ZLIB_DIR/lib" -lz])])]) AC_SUBST([ZLIB_CFLAGS]) AC_SUBST([ZLIB_LIBS]) # Check if the kpathsea headers are C++ safe AC_MSG_CHECKING([if the kpathsea headers are C++ safe]) AC_LANG_PUSH([C++]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[printf("%s\n", concat("one", "two"))]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_DEFINE([KPSE_CXX_UNSAFE], 1, [Define to 1 if the kpathsea headers are not C++ safe.])]) AC_LANG_POP([C++]) CPPFLAGS="$CPPFLAGS_SAVE" CFLAGS="$CFLAGS_SAVE" LDFLAGS="$LDFLAGS_SAVE" AC_ARG_ENABLE([manpage], [AS_HELP_STRING([--disable-manpage], [disable generation of manual page @<:@default=no@:>@])]) AS_IF([test "x$enable_manpage" != "xno"],[ enable_manpage="no" # Check for utilities required to build the manpage AC_CHECK_PROG(ASCIIDOC, asciidoc, yes) AS_IF([test "x$ASCIIDOC" = "xyes"], [ AC_CHECK_PROG(XMLTO, xmlto, yes) AS_IF([test "x$XMLTO" = "xyes"], [ AC_CHECK_PROG(XSLTPROC, xsltproc, yes) AS_IF([test "x$XSLTPROC" = "xyes"],[enable_manpage="yes"])])])]) AS_IF([test "x$enable_manpage" != "xyes"], AC_MSG_NOTICE([generation of manual page has been disabled])) AM_CONDITIONAL([BUILD_MANPAGE], [test "x$enable_manpage" = "xyes"]) AX_CODE_COVERAGE AS_IF([ test "$enable_code_coverage" = "yes" ], [ # disable optimization changequote({,}) CFLAGS=`echo $CFLAGS | sed 's/-O[1-9s]//g'` CXXFLAGS=`echo $CXXFLAGS | sed 's/-O[1-9s]//g'` changequote([,]) ]) AC_SUBST([dvisvgm_srcdir], ['$(top_srcdir)']) AC_SUBST(DATE) AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_LDFLAGS) AC_CONFIG_FILES([ Makefile libs/Makefile libs/boost/Makefile libs/brotli/Makefile libs/clipper/Makefile libs/md5/Makefile libs/potrace/Makefile libs/variant/Makefile libs/woff2/Makefile libs/xxHash/Makefile src/Makefile src/version.hpp src/fonts/Makefile src/optimizer/Makefile src/ttf/Makefile tests/Makefile tests/data/Makefile doc/Makefile]) AC_OUTPUT dvisvgm-3.5/doc/000077500000000000000000000000001501401750600136045ustar00rootroot00000000000000dvisvgm-3.5/doc/Makefile.am000066400000000000000000000071541501401750600156470ustar00rootroot00000000000000## This file is part of dvisvgm ## Copyright (C) 2005-2025 Martin Gieseking ## ## Process this file with automake. # Don't try to install the manpage file if it can't be built due to missing utilities. # However, the distribution tarball should always contain a recent manpage. We ensure # this by adding a dist-hook rule below. man_MANS = dvisvgm.1 EXTRA_DIST = $(man_MANS) \ conf-dblatex-man.xsl \ conf-dblatex-pdf.xsl \ dvisvgm.txt.in \ generate-dvisvgm-sty.xsl \ tweak-dblatex-pdf.xsl \ tweak-dblatex-tex.py \ tweak-db-refentry.xsl if BUILD_MANPAGE CONF_DBLATEX_MAN = $(dvisvgm_srcdir)/doc/conf-dblatex-man.xsl CONF_DBLATEX_PDF = $(dvisvgm_srcdir)/doc/conf-dblatex-pdf.xsl TWEAK_DBLATEX_PDF = $(dvisvgm_srcdir)/doc/tweak-dblatex-pdf.xsl TWEAK_DBLATEX_TEX = $(dvisvgm_srcdir)/doc/tweak-dblatex-tex.py TWEAK_DB_ARTICLE = $(dvisvgm_srcdir)/doc/tweak-db-article.xsl TWEAK_DB_REFENTRY = $(dvisvgm_srcdir)/doc/tweak-db-refentry.xsl GEN_DBLATEX_STY = $(dvisvgm_srcdir)/doc/generate-dvisvgm-sty.xsl DB_VARS = man.endnotes.list.enabled=0 man.endnotes.are.numbered=0 man.authors.section.enabled=0 dvisvgm.1: dvisvgm-man.xml $(CONF_DBLATEX_MAN) xmlto -m $(CONF_DBLATEX_MAN) $(addprefix --stringparam , $(DB_VARS)) man $< dvisvgm.pdf: dvisvgm-man.xml dvisvgm.sty $(CONF_DBLATEX_PDF) $(TWEAK_DBLATEX_PDF) $(TWEAK_DBLATEX_TEX) mv $< $<.tmp xsltproc -o $< $(TWEAK_DBLATEX_PDF) $<.tmp dblatex -bxetex --texstyle=./dvisvgm.sty -p $(CONF_DBLATEX_PDF) -r plugin:$(basename $(TWEAK_DBLATEX_TEX)) $< mv $<.tmp $< mv $(basename $<).pdf $@ dvi-pdf: dvisvgm.dvi dvipdfm $< rm -f $< dvisvgm.dvi: dvisvgm.1 groff -Tdvi -mandoc ./$< >$@ dvisvgm.html: dvisvgm-man.xml db2html.xsl xsltproc -o $@ db2html.xsl $< dvisvgm.md: dvisvgm-man.xml db2md.xsl xsltproc -o $@ db2md.xsl $< dvisvgm.epub: dvisvgm-article.xml a2x -darticle -fepub -L --icons --icons-dir=. $< mv $(basename $<).epub $@ .SECONDARY: dvisvgm-article.xml dvisvgm-man.xml dvisvgm.sty dvisvgm-man.xml: dvisvgm.txt $(TWEAK_DB_REFENTRY) asciidoc -a icons -a 'iconsdir=.' -a badges -a 'revnumber=@VERSION@' --unsafe -bdocbook -dmanpage -o $@.tmp $< xsltproc -o $@ $(TWEAK_DB_REFENTRY) $@.tmp rm $@.tmp dvisvgm-article.xml: dvisvgm.txt $(TWEAK_DB_ARTICLE) asciidoc -a icons -a 'iconsdir=.' -a badges -a 'revnumber=@VERSION@' --unsafe -bdocbook -darticle -o $@.tmp $< xsltproc -o $@ $(TWEAK_DB_ARTICLE) $@.tmp rm $@.tmp sed -i "s/{VERSION}/@VERSION@/" $@ dvisvgm.sty: dvisvgm-man.xml $(GEN_DBLATEX_STY) xsltproc -o dvisvgm.sty $(GEN_DBLATEX_STY) $< .NOTPARALLEL: dvisvgm.txt: dvisvgm.txt.in ../configure.ac sed -e 's/@VERSION[@]/@VERSION@/g' -e 's/@PACKAGE_BUGREPORT[@]/@PACKAGE_BUGREPORT@/g' $< >$@ if [ $< -nt ../configure.ac ]; \ then touch -r $< $@; \ else touch -r ../configure.ac $@; \ fi epub: dvisvgm.epub html: dvisvgm.html man: dvisvgm.1 md: dvisvgm.md pdf: dvisvgm.pdf endif clean: rm -f dvisvgm.pdf dvisvgm.html dvisvgm.md dvisvgm-man.xml dvisvgm-article.xml dvisvgm.txt dvisvgm.sty dvisvgm.dvi dvisvgm.epub distclean-local: rm -f dvisvgm.pdf dvisvgm.html dvisvgm.md dvisvgm-man.xml dvisvgm-article.xml dvisvgm.txt dvisvgm.sty dvisvgm.dvi dvisvgm.epub dvisvgm.1 if !BUILD_MANPAGE # Ensure that distribution tarballs always contain a recent manpage, i.e. # let "make dist" and "make distcheck" fail if dvisvgm.1 can't be built. dist-hook: @echo "----------------------------------------------------------------"; \ echo "manpage file dvisvgm.1 could not be built because one or more of"; \ echo "the following utilities are missing: asciidoc, xmlto, xsltproc "; \ echo "----------------------------------------------------------------"; \ false; endif dvisvgm-3.5/doc/conf-dblatex-man.xsl000066400000000000000000000020071501401750600174520ustar00rootroot00000000000000 \fB \fR (\m[blue] \m[]) x dvisvgm-3.5/doc/conf-dblatex-pdf.xsl000066400000000000000000000052361501401750600174570ustar00rootroot00000000000000 \setmainfont{Source Serif 4} \setsansfont{Source Sans 3} \setmonofont[Scale=0.9]{Source Code Pro Medium} 0 0 caution note tabular 0 1 basicstyle=\ttfamily\small,backgroundcolor=\color[gray]{0.9},columns=fullflexible,frame=single \tableofcontents 2 1 2 1 \phantomsection\pdfbookmark[3]{ dvisvgm-3.5/doc/dvisvgm.txt.in000066400000000000000000002162231501401750600164370ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////// // This file is part of dvisvgm -- a fast DVI to SVG converter // // Copyright (C) 2005-2025 Martin Gieseking // // // // 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 . // ////////////////////////////////////////////////////////////////////////// dvisvgm(1) ========== Martin Gieseking <@PACKAGE_BUGREPORT@> :man source: dvisvgm :man version: @VERSION@ :man manual: dvisvgm Manual :revdate: 2025-05-22 18:08 +0200 Name ---- dvisvgm - converts DVI, EPS, and PDF files to the XML-based SVG format Synopsis -------- *dvisvgm* ['options'] 'file'[.dvi] *dvisvgm* --eps ['options'] 'file1'[.eps] 'file2'[.eps] ... *dvisvgm* --pdf ['options'] 'file'[.pdf] Description ----------- The command-line utility *dvisvgm* converts DVI files, as generated by TeX/LaTeX, to the XML-based scalable vector graphics format SVG. It supports the classic DVI version 2 as well as version 3 (created by pTeX in vertical mode), and the XeTeX versions 5 to 7 which are also known as XDV. Besides the basic DVI commands, dvisvgm also evaluates many so-called 'specials' which heavily extend the capabilities of the plain DVI format. For a more detailed overview, see section <> below. Since the current SVG standard 1.1 doesn't specify multi-page graphics, dvisvgm creates separate SVG files for each DVI page. Because of compatibility reasons, only the first page is converted by default. In order to select a different page or arbitrary page sequences, use option *-p* which is described below. SVG is a vector-based graphics format and therefore dvisvgm tries to convert the glyph outlines of all fonts referenced in a DVI page section to scalable path descriptions. The fastest way to achieve this is to extract the path information from vector-based font files available in PFB, TTF, or OTF format. If dvisvgm is able to find such a file, it extracts all necessary outline information about the glyphs from it. However, TeX's former main source for font descriptions is Metafont, which produces bitmap output in terms of GF files. That's why not all obtainable TeX fonts are available in a scalable format. In these cases, dvisvgm tries to vectorize Metafont's output by tracing the glyph bitmaps. The results are not as perfect as most (manually optimized) PFB or OTF counterparts, but are nonetheless really nice in most cases. When running dvisvgm without option *--no-fonts*, it creates 'font' elements (++...++) to embed the font data into the SVG files. Unfortunately, only few SVG renderers support these elements. Most web browsers and vector graphics applications don't evaluate them properly so that the text components of the resulting graphics might look strange. In order to create more compatible SVG files, command-line option *--no-fonts* can be given to replace the font elements by plain graphics paths. Most web browsers (but only few external SVG renderers) also support WOFF and WOFF2 fonts that can be used instead of the default SVG fonts. Option *--font-format* offers the functionality to change the format applied to the fonts being embedded. This, however, only works when converting DVI files. Text present in PDF and PostScript files is always converted to path elements. Options ------- dvisvgm provides a POSIX-compliant command-line interface with short and long option names. They may be given before and/or after the name of the file to be converted. Also, the order of specifying the options is not significant, i.e. you can add them in any order without changing dvisvgm's behavior. Certain options accept or require additional parameters which are directly appended to or separated by whitespace from a short option (e.g. +-v0+ or +-v 0+). Long options require an additional equals sign (+=+) between option name and argument but without any surrounding whitespace (e.g. +--verbosity=0+). Multiple short options that don't expect further parameters can be combined after a single dash (e.g. +-ejs+ rather than +-e -j -s+). Long option names may also be shortened by omitting trailing characters as long as the shortened name is still unambiguous. For example, option +--exact-bbox+ can be shortened to +--exact+, +--exa+, or +--ex+. In case of ambiguous abbreviations, dvisvgm prints an error message together with all matching option names. *-b, --bbox*='fmt':: Sets the bounding box of the generated SVG graphic to the specified format. This option only affects the conversion of DVI files. SVG documents generated from PDF and PostScript always inherit the bounding boxes of the input files. + Parameter 'fmt' takes either one of the format specifiers listed below, or a sequence of four comma- or whitespace-separated length values 'x1', 'y1', 'x2' and 'y2'. The latter define the absolute coordinates of two diagonal corners of the bounding box. Each length value consists of a floating point number and an optional length unit (pt, bp, cm, mm, in, pc, dd, cc, or sp). If the unit is omitted, TeX points (pt) are assumed. + It's also possible to give only one length value 'l'. In this case, the minimal bounding box is computed and enlarged by adding (-'l',-'l') to the upper left and ('l','l') to the lower right corner. + Additionally, dvisvgm also supports the following format specifiers: *International DIN/ISO paper sizes*;; A__n__, B__n__, C__n__, D__n__, where 'n' is a non-negative integer, e.g. A4 or a4 for DIN/ISO A4 format (210mm × 297mm). *North American paper sizes*;; invoice, executive, legal, letter, ledger *Special bounding box sizes*;; [horizontal] *dvi* ::: page size stored in the DVI file *min* ::: computes the minimal/tightest bounding box *none* ::: no bounding box is assigned *papersize* ::: box sizes specified by 'papersize' specials present in the DVI file *preview* ::: bounding box data computed by the preview package (if present in the DVI file) // *Page orientation*;; The default page orientation for DIN/ISO and American paper sizes is 'portrait', i.e. 'width' < 'height'. Appending *-landscape* or simply *-l* to the format string switches to 'landscape' mode ('width' > 'height'). For symmetry reasons you can also explicitly add *-portrait* or *-p* to indicate the default portrait format. Note that these suffixes are part of the size string and not separate options. Thus, they must directly follow the size specifier without additional blanks. Furthermore, the orientation suffixes can't be used with *dvi*, *min*, and *none*. + [NOTE] Option *-b, --bbox* only affects the bounding box and does not transform the page content. Hence, if you choose a landscape format, the page won't be rotated. + // // *-B, --bitmap-format*='fmt':: This option sets the image format used to embed bitmaps that are extracted from PostScript or PDF data. By default, dvisvgm embeds all bitmaps as JPEG images because it's the most compact of the two formats supported by SVG. To select the alternative lossless PNG format, *--bitmap-format=png* can be used. There are some more format variants dvisvgm currently supports even though +jpeg+ and +png+ should be sufficient in most cases. The following list gives an overview of the known format names which correspond to names of Ghostscript output devices. + -- [horizontal] *none* ::: disable processing of bitmap images *jpeg* ::: color JPEG format *jpeggray* ::: grayscale JPEG format *png* ::: grayscale or 24-bit color PNG format depending on current color space *pnggray* ::: grayscale PNG format *pngmono* ::: black-and-white PNG format *pngmonod* ::: dithered black-and-white PNG format *png16* ::: 4-bit color PNG format *png256* ::: 8-bit color PNG format *png16m* ::: 24-bit color PNG format -- + Since the collection of supported output devices can vary among local Ghostscript installations, not all formats may be available in some environments. dvisvgm quits with a PostScript error message if the selected output format requires a locally unsupported output device. + The two JPEG format specifiers accept an optional parameter to set the IJG quality level which must directly follow the format specifier separated by a colon, e.g. *--bitmap-format=jpeg:50*. The quality value is an integer between 0 and 100. Higher values result in better image quality but lower compression rates and therefore larger files. The default quality level is 75 which is applied if no quality parameter is given or if it's set to 0. *-C, --cache*[='dir']:: To speed up the conversion process of bitmap fonts, dvisvgm saves intermediate conversion information in cache files. By default, these files are stored in +$XDG_CACHE_HOME/dvisvgm/+ or +$HOME/.cache/dvisvgm+ if +XDG_CACHE_HOME+ is not set. If you prefer a different location, use option *--cache* to overwrite the default. Furthermore, it is also possible to disable the font caching mechanism completely with option *--cache=none*. If argument 'dir' is omitted, dvisvgm prints the path of the default cache directory together with further information about the stored fonts. Additionally, outdated and corrupted cache files are removed. *-j, --clipjoin*:: This option tells dvisvgm to compute all intersections of clipping paths itself rather than delegating this task to the SVG renderer. The resulting SVG files are more portable because some SVG viewers don't support intersecting clipping paths which are defined by 'clipPath' elements containing a 'clip-path' attribute. *--color*:: Enables colorization of messages printed during the conversion process. The colors can be customized via environment variable *DVISVGM_COLORS*. See the <> below for further information. *--colornames*:: By default, dvisvgm exclusively uses RGB values of the form '#RRGGBB' or '#RGB' to represent colors in the SVG file. The latter is a short form for colors whose RGB components each consist of two identical hex digits, e.g. +#123+ equals +#112233+. According to the SVG standard, it's also possible to use color names (like +black+ and +darkblue+) for a limited number of https://www.w3.org/TR/SVG11/types.html#ColorKeywords[predefined colors]. In order to apply these color names rather than their RGB values, call dvisvgm with option *--colornames*. All colors without an SVG color name will still be represented by RGB values. *--comments*:: Adds comments with further information about selected data to the SVG file. Currently, only font elements and font CSS rules related to native fonts are annotated. *--currentcolor*[='color']:: This option tells dvisvgm to replace the specified color with CSS variable `currentColor` which holds the current foreground color set by CSS property `color`. This way an application or website can change the color via CSS without the need to modify the SVG code. + The optional argument of `--currentcolor` specifies the RGB color value to be replaced and must be given as either https://www.w3.org/TR/css-color/#typedef-hex-color[six or three digit hex color value] preceded by character `#`, e.g. `#0000ff` or `#00f` for blue. If the optional argument is omitted, black is assumed. *--embed-bitmaps*:: Embeds the contents of bitmap files into the generated SVG files instead of adding file references. Because of the base64-encoded data, the SVG files are usually much bigger but at the same time more portable because they don't rely on external bitmap files. + This option only affects bitmaps referenced in DVI/XDV files, e.g. by +\includegraphics+ or special command +dvisvgm:img+ (see below). Bitmaps present in PostScript or PDF files are always embedded. Also see option *bitmap-format*. *-E, --eps*:: If this option is given, dvisvgm does not expect a DVI but a single or multiple EPS input files, and tries to convert them to SVG. In order to do so, a single 'psfile' special command is created and forwarded to the PostScript special handler. This option is only available if dvisvgm was built with PostScript support enabled, and requires Ghostscript to be available. See option *--libgs* for further information. *-e, --exact-bbox*:: This option tells dvisvgm to compute the precise bounding box of each character. By default, the values stored in a font's TFM file are used to determine a glyph's extent. As these values are intended to implement optimal character placements and are not designed to represent the exact dimensions, they don't necessarily correspond with the bounds of the visual glyphs. Thus, width and/or height of some glyphs may be larger (or smaller) than the respective TFM values. As a result, this can lead to clipped characters at the bounds of the SVG graphics. With option *--exact-bbox* given, dvisvgm analyzes the actual shape of each character and derives a usually tight bounding box. + This option only affects the processing of DVI files. When converting EPS or PDF files, the bounding box information stored in these files are used to derive the SVG bounding box. *-f, --font-format*='format':: Selects the file format used to embed font data into the generated SVG output when converting DVI or PDF files. The latter require the new mutool-based PDF handler introduced with dvisvgm 3.0 (also see option *--pdf*). Option *--font-format* has no effect when converting PDF or PostScript files using Ghostscript. Text fragments present in these files are then always converted to path elements. + Following formats are supported: +SVG+ (that's the default), +TTF+ (TrueType), +WOFF+, and +WOFF2+ (Web Open Font Format version 1 and 2). By default, dvisvgm creates unhinted fonts that might look bad on low-resolution devices. In order to improve the display quality, the generated TrueType, WOFF, or WOFF2 fonts can be autohinted. The autohinter is enabled by appending +,autohint+ or +,ah+ to the font format, e.g. +--font-format=woff,autohint+ or +--fwoff,ah+. This functionality requires the https://freetype.org/ttfautohint[ttfautohint library]. If it's not available or can't be found, dvisvgm issues a corresponding warning message. + Option *--font-format* is only available if dvisvgm was built with WOFF support enabled. *-m, --fontmap*='filenames':: Loads and evaluates a single font map file or a sequence of font map files. These files are required to resolve font file names and encodings. dvisvgm does not provide its own map files but tries to read available ones coming with dvips or dvipdfm. If option *--fontmap* is omitted, dvisvgm looks for the default map files 'dvisvgm.map', 'ps2pk.map', 'pdftex.map', 'dvipdfm.map', and 'psfonts.map' (in this order). Otherwise, the files given as option arguments are evaluated in the given order. Multiple filenames must be separated by commas without leading and/or trailing whitespace. + By default, redefined mappings do not replace previous ones. However, each filename can be preceded by an optional mode specifier (*+*, *-*, or *=*) to change this behavior: +mapfile;; Only those entries in the given map file that don't redefine a font mapping are applied, i.e. fonts already mapped keep untouched. That's also the default mode if no mode specifier is given. -mapfile;; Ensures that none of the font mappings defined in the given map file are used, i.e. previously defined mappings for the specified fonts are removed. =mapfile;; All mappings defined in the map file are applied. Previously defined settings for the same fonts are replaced. + If the first filename in the filename sequence is preceded by a mode specifier, dvisvgm loads the default font map (see above) and applies the other map files afterwards. Otherwise, none of default map files will be loaded automatically. + Examples: +--fontmap=myfile1.map,+myfile2.map+ loads 'myfile1.map' followed by 'myfile2.map' where all redefinitions of `myfile2.map` are ignored. +--fontmap==myfile1.map,-myfile2.map+ loads the default map file followed by 'myfile1.map' and 'myfile2.map' where all redefinitions of 'myfile1.map' replace previous entries. Afterwards, all definitions for the fonts given in 'myfile2.map' are removed from the font map tree. + For further information about the map file formats and the mode specifiers, see the manuals of https://tug.org/texinfohtml/dvips.html[dvips] and https://ctan.org/tex-archive/dviware/dvipdfm[dvipdfm]. + dvisvgm supports both the 'dvips' and the 'dvipdfm' map file formats. It extends both variants by two include statements that allow for loading other map files inside a map file. The syntax is as follows: + [listing] ---------------------------------------------- #include [] #includefirst [] ---------------------------------------------- + They must be placed on a separate line and start at the first column of that line. Otherwise, they are ignored. While the first variant always tries to include the specified file, +#includefirst+ is only executed once, i.e. once a file was successfully included by this statement, all subsequent +#includefirst+ lines are skipped. This can be used to include one of several alternative files, whereby the first one found is loaded and all others are ignored. + The optional parameter '' (which can be +pass:[+]+, +-+, or +=+) determines how to integrate the data read from the included file into the already present mapping data. They work the same way as the mode specifiers described above. If '' parameter is omitted, it defaults to +pass:[+]+. + The following filename or file path specifies the file to include. In case of plain filenames (without path indicators), the files are looked up using the TeX file search functionality, i.e. files in the TeX directory tree can easily be added. Relative paths are relative to the location of the file containing the +#include+ statement. Path components must be separated by forward slashes (+/+), also on Windows systems. + Examples: +#include pdftex.map+ looks for _pdftex.map_ in the current working directory and in the TeX directory tree. +#include ./pdftex.map+, on the other hand, looks for _pdftex.map_ only in the directory where the including file is located. *--grad-overlap*:: Tells dvisvgm to create overlapping grid segments when approximating color gradient fills (also see option *--grad-segments* below). By default, adjacent segments don't overlap but only touch each other like separate tiles. However, this alignment can lead to visible gaps between the segments because the background color usually influences the color at the boundary of the segments if the SVG renderer uses anti-aliasing to create smooth contours. One way to avoid this and to create seamlessly touching color regions is to enlarge the segments so that they extend into the area of their right and bottom neighbors. Since the latter are drawn on top of the overlapping parts, the visible size of all segments keeps unchanged. Just the former gaps disappear as the background is now completely covered by the correct colors. Currently, dvisvgm computes the overlapping segments separately for each patch of the mesh (a patch mesh may consist of multiple patches of the same type). Therefore, there still might be visible gaps at the seam of two adjacent patches. *--grad-segments*='number':: Determines the maximum number of segments per column and row used to approximate gradient color fills. Since SVG 1.1 only supports a small subset of the shading algorithms available in PostScript, dvisvgm approximates some of them by subdividing the area to be filled into smaller, monochromatic segments. Each of these segments gets the average color of the region it covers. Thus, increasing the number of segments leads to smaller monochromatic areas and therefore a better approximation of the actual color gradient. As a drawback, more segments imply bigger SVG files because every segment is represented by a separate path element. + Currently, dvisvgm supports free- and lattice-form triangular patch meshes as well as Coons and tensor-product patch meshes. They are approximated by subdividing the area of each patch into a __n__×__n__ grid of smaller segments. The maximum number of segments per column and row can be changed with option *--grad-segments*. *--grad-simplify*='delta':: If the size of the segments created to approximate gradient color fills falls below the given delta value, dvisvgm reduces their level of detail. For example, Bézier curves are replaced by straight lines, and triangular segments are combined to tetragons. For a small 'delta', these simplifications are usually not noticeable but reduce the size of the generated SVG files significantly. *-h, --help*[='mode']:: Prints a short summary of all available command-line options. The optional 'mode' parameter is an integer value between 0 and 2. It selects the display variant of the help text. Mode 0 lists all options divided into categories with section headers. This is also the default if dvisvgm is called without parameters. Mode 1 lists all options ordered by the short option names, while mode 2 sorts the lines by the long option names. + A values in brackets after the description text indicate the default parameter of the option. They are applied if an option with a mandatory parameter is not used or if an optional parameter is omitted. For example, option *--bbox* requires a size parameter which defaults to +min+ if *--bbox* is not used. Option *--zip*, which isn't applied by default, accepts an optional compression level parameter. If it's omitted, the stated default value 9 is used. *--keep*:: Disables the removal of temporary files as created by Metafont (usually .gf, .tfm, and .log files) or the TrueType/WOFF module. *--libgs*='path':: This option is only available if the Ghostscript library is not directly linked to dvisvgm and if PostScript support was not completely disabled during compilation. In this case, dvisvgm tries to load the shared GS library dynamically during runtime. By default, it expects the library's name to be +libgs.so.X+ (on Unix-like systems, where +X+ is the ABI version of the library) or +gsdll32.dll+/+gsdll64.dll+ (Windows). If dvisvgm doesn't find the library, option *--libgs* can be used to specify the correct path and filename, e.g. +--libgs=/usr/local/lib/libgs.so.9+ or +--libgs=\gs\gs9.25\bin\gsdll64.dll+. + Alternatively, it's also possible to assign the path to environment variable *LIBGS*, e.g. +export LIBGS=/usr/local/lib/libgs.so.9+ or +set LIBGS=\gs\gs9.25\bin\gsdll63.dll+. *LIBGS* has less precedence than the command-line option, i.e. dvisvgm ignores variable *LIBGS* if *--libgs* is given. *-L, --linkmark*='style':: Selects the method how to mark hyperlinked areas. The 'style' argument can take one of the values 'none', 'box', and 'line', where 'box' is the default, i.e. a rectangle is drawn around the linked region if option *--linkmark* is omitted. Style argument 'line' just draws the lower edge of the bounding rectangle, and 'none' tells dvisvgm not to add any visible objects to hyperlinks. The lines and boxes get the current text color selected. In order to apply a different, constant color, a colon followed by a color specifier can be appended to the style string. A 'color specifier' is either a hexadecimal RGB value of the form '#RRGGBB', or a https://en.wikibooks.org/wiki/LaTeX/Colors#The_68_standard_colors_known_to_dvips[dvips color name]. + Moreover, argument 'style' can take a single color specifier to highlight the linked region by a frameless box filled with that color. An optional second color specifier separated by a colon selects the frame color. + Examples: +box:red+ or +box:#ff0000+ draws red boxes around the linked areas. +yellow:blue+ creates yellow filled rectangles with blue frames. *-l, --list-specials*:: Prints a list of registered special handlers and exits. Each handler processes a set of special statements belonging to the same category. In most cases, these categories are identified by the prefix of the special statements which is usually a leading string followed by a colon or a blank, e.g. 'color' or 'ps'. The listed handler names, however, don't need to match these prefixes, e.g. if there is no common prefix or if functionality is split into separate handlers in order to allow them to be disabled separately using option *--no-specials*. All special statements not covered by one of the special handlers are silently ignored. *-M, --mag*='factor':: Sets the magnification factor applied in conjunction with Metafont calls prior tracing the glyphs. The larger this value, the better the tracing results. Nevertheless, large magnification values can cause Metafont arithmetic errors due to number overflows. So, use this option with care. The default setting usually produces nice results. *--message*='text':: Prints a given message to the console after an SVG file has been written. Argument 'text' may consist of static text as well as the macros listed below in the description of special command +dvisvgm:raw+. For example, +--message="page {?pageno} written to {?svgfile}"+ prints the message with the macros expanded after the conversion of each page of a DVI or PDF file or after processing an EPS file. + The output of option *--message* is not affected by a specified verbosity level, i.e. dvisvgm prints the text even with +--verbosity=0+. *--no-merge*:: Puts every single character in a separate 'text' element with corresponding 'x' and 'y' attributes. By default, new 'text' or 'tspan' elements are only created if a string starts at a location that differs from the regular position defined by the characters' advance values. *--no-mktexmf*:: Suppresses the generation of missing font files. If dvisvgm can't find a font file through the kpathsea lookup mechanism, it calls the external tools 'mktextfm' or 'mktexmf'. This option disables these calls. *-n, --no-fonts*[='variant']:: If this option is given, dvisvgm doesn't create SVG 'font' elements but uses 'paths' instead. The resulting SVG files tend to be larger but are concurrently more compatible with most applications that don't support SVG fonts. The optional argument 'variant' selects the method how to substitute fonts by paths. Variant 0 creates 'path' and 'use' elements in order to avoid lengthy duplicates. Variant 1 creates 'path' elements only. Option *--no-fonts* implies *--no-styles*. *-c, --scale*='sx'[,'sy']:: Scales the page content horizontally by 'sx' and vertically by 'sy'. This option is equivalent to *-TS*'sx','sy'. *-S, --no-specials*[='names']:: Disable processing of special commands embedded in the DVI file. If no further parameter is given, all specials are ignored. To disable a selected set of specials, an optional comma-separated list of names can be appended to this option. A 'name' is the unique identifier referencing the intended special handler as listed by option *--list-specials*. *--no-styles*:: By default, dvisvgm creates CSS styles and class attributes to reference fonts. This variant is more compact than adding the complete font information to each text element over and over again. However, if you prefer direct font references, the default behavior can be disabled with option *--no-styles*. *-O, --optimize*[='modules']:: Applies several optimizations on the generated SVG tree to reduce the file size. The optimizations are performed by running separate optimizer modules specified by optional argument 'modules'. It may consist of a single module name or a comma-separated list of several module names. The corresponding modules are executed one by one in the given order and thus transform the XML tree gradually. A leading hyphen (+-+) can be used to exclude a module from processing. For example +-Oall,-collapse-groups+ performs all optimizations except +collapse-groups+. If the first module name in the list starts with a hyphen, dvisvgm automatically inserts +all+ at the beginning, i.e. +-O-collapse-groups+ is identical to +-Oall,-collapse-groups+. + The following list describes the currently available optimizer modules. *list*;; Lists all available optimizer modules and exits. *none*;; If this argument is given, dvisvgm doesn't apply any optimization. *none* can't be combined with other module names. *all*;; Performs all optimizations listed below. This is also the default if option *--optimize* is used without any arguments. The modules are executed in a predefined order that usually leads to the best results. *all* must be the only or the first entry in the list of module names. *collapse-groups*;; Combines nested group elements (++...++) that contain only a single attribute each. If possible, the group attributes are moved to the outermost element of the processed subtree. This module also unwraps group elements that have no attributes at all. *group-attributes*;; Creates groups (++...++) for common attributes around adjacent elements. Each attribute is moved to a separate group so that multiple common attributes lead to nested groups. They can be combined by applying optimizer module 'collapse-groups' afterwards. The algorithm only takes inheritable properties, such as +fill+ or +stroke-width+, into account and only removes them from an element if none of the other attributes, like +id+, prevents this. *reassign-clippaths*;; Collects all +clipPath+ elements that differ only by their IDs. Afterwards, the duplicates are removed so that only one remains. All +clip-path+ attributes referencing one of the duplicates are updated accordingly. *remove-clippaths*;; Removes all redundant 'clipPath' elements. This optimization was already present in former versions of dvisvgm and was always applied by default. This behavior is retained, i.e. dvisvgm executes this module even if option *--optimize* is not given. You can use argument 'none' to prevent that. *simplify-text*;; If a +text+ element only contains whitespace nodes and +tspan+ elements, all common inheritable attributes of the latter are moved to the enclosing text element. All +tspan+ elements without further attributes are unwrapped, i.e. the +tspan+ tags are removed. *simplify-transform*;; Tries to shorten all 'transform' attributes. This module combines the transformation commands of each attribute and decomposes the resulting transformation matrix into a sequence of basic transformations, i.e. translation, scaling, rotation, and skewing. If this sequence is shorter than the equivalent 'matrix' expression, it's assigned to the attribute. Otherwise, the matrix expression is used. *-o, --output*='pattern':: Sets the pattern that determines the names of the generated SVG files, optionally including the file path. The required parameter 'pattern' may consist of an arbitrary sequence of characters which make up the filenames or file paths relative to the current working directory. With the exception of the following mentioned variables and expressions, all characters are treated as static parts of the filenames/folders and are therefore identical for all pages processed during a run of dvisvgm. The strings +%f+, +%p+, +%P+, +%n+, +%N+, +%hd+, +%ho+, and +%hc+ are variables that can be used as part of the pattern. +%f+ expands to the base name of the DVI file, i.e. the filename without suffix, +%p+ is the current page number, and +%P+ the total number of pages in the DVI file. The variables +%n+ and +%N+ expand to the number of the current file being converted (starting at 1) and the total number of files given, respectively. + An optional number (0-9) specified directly after the percent sign of a variable holding a numeric value denotes the minimal number of digits to be created. If a particular value consists of less digits, the number is padded with leading zeros. Example: +%3p+ enforces 3 digits for the current page number (001, 002, etc.). Without an explicit width specifier, +%p+ gets the same number of digits as +%P+. + If you need more control over the numbering, you can use arithmetic expressions as part of the pattern. The syntax is +%(+'expr'+)+ where 'expr' may contain additions, subtractions, multiplications, and integer divisions with common precedence. The variables *p* and *P* contain the current page number and the total number of pages, respectively. For example, +--output="%f-%(p-1)"+ creates filenames where the numbering starts with 0 rather than 1. + The variables +%hX+ contain different hash values computed from the DVI page data and the options given on the command-line. +%hd+ and +%hc+ are only set if option *--page-hashes* is present. Otherwise, they are empty. For further information, see the description of option *--page-hashes* below. + The default pattern is +%f-%p.svg+ if the DVI file consists of more than one page, and +%f.svg+ otherwise. That means, a DVI file 'foo.dvi' is converted to 'foo.svg' if 'foo.dvi' is a single-page document. Otherwise, multiple SVG files 'foo-01.svg', 'foo-02.svg', etc. are produced. In Windows environments, the percent sign indicates dereferenced environment variables, and must therefore be protected by a second percent sign, e.g. +--output=%%f-%%p+. *-p, --page*='ranges':: This option selects the pages to be processed. Parameter 'ranges' consists of a comma-separated list of single page numbers and/or page ranges. A page range is a pair of numbers separated by a hyphen, e.g. 5-12. Thus, a page sequence might look like this: 2-4,6,9-12,15. It doesn't matter if a page is given more than once or if page ranges overlap. dvisvgm always extracts the page numbers in ascending order and converts them only once. + In order to stay compatible with previous versions, the default page sequence is 1. dvisvgm therefore converts only the first page and not the whole document if option *--page* is omitted. Usually, page ranges consist of two numbers denoting the first and last page to be converted. If the conversion should start at page 1, or if it should continue up to the last DVI page, the first or second range number can be omitted, respectively. Example: +--page=-10+ converts all pages up to page 10, +--page=10-+ converts all pages starting with page 10. Please consider that the page values don't refer to the page numbers printed on the corresponding page. Instead, the physical page count is expected, where the first page always gets number 1. + At the end of the range sequence an optional filter specifier can be appended in order to remove certain page numbers from the sequence. Currently, the two filters +:even+ and +:odd+ are supported which restrict the preceding values to even and odd numbers, respectively. For example, +--page=1-11,20:even+ is equivalent to +--page=2,4,6,8,10,20+. *-H, --page-hashes*[='params']:: If this option is given, dvisvgm computes hash values of all pages to be processed. As long as the page contents don't change, the hash value of that page stays the same. This property can be used to determine whether a DVI page must be converted again or can be skipped in consecutive runs of dvisvgm. This is done by propagating the hash value to variable +%hd+ which can be accessed in the output pattern (see option *--output*). By default, dvisvgm changes the output pattern to +%f-%hd+ if option *--page-hashes* is given. As a result, all SVG file names contain the hash value instead of the page number. When calling dvisvgm again with option *--page-hashes* with the same output pattern, it checks the existence of the SVG file to be created and skips the conversion if it's already present. This also applies for consecutive calls of dvisvgm with different command-line parameters. If you want to force another conversion of a DVI file that hasn't changed, you must remove the corresponding SVG files beforehand or add the parameter +replace+ (see below). If you manually set the output pattern to not contain a hash value, the conversion won't be skipped. + Alternatively, the output pattern may contain the variables +%ho+ and +%hc+. +%ho+ expands to a 32-bit hash representing the given command-line options that affect the generated SVG output, like *--no-fonts* and *--precision*. Different combinations of options and parameters lead to different hashes. Thus pattern +%f-%hd-%ho+ creates filenames that change depending on the DVI data and the given command-line options. Variable +%hc+ provides a combined hash computed from the DVI data and the command-line options. It has the same length as +%hd+. + Since the page number isn't part of the file name by default, different DVI pages with identical contents get the same file name. Therefore, only the first one is converted while the others are skipped. To create separate files for each page, you can add the page number to the output pattern, e.g. +--output="%f-%p-%hc"+. + By default, dvisvgm uses the fast XXH64 hash algorithm to compute the values provided through +%hd+ and +%hc+. 64-bit hashes should be sufficient for most documents with an average size of pages. Alternatively, XXH32 and MD5 can be used as well. The desired algorithm is specified by argument 'params' of option *--page-hashes*. It takes one of the strings +MD5+, +XXH32+, and +XXH64+, where the names can be given in lower case too, like +--page-hashes=md5+. Since version 0.7.1, xxHash provides an experimental 128-bit hash function whose algorithm has been stabilized as of version 0.8. When using a version prior to 0.8, the 128-bit hash values can vary depending on the used xxHash version. If the corresponding API is available, dvisvgm supports the new hash function, and option *--page-hashes* additionally accepts the algorithm specifier +XXH128+. + Finally, option *--page-hashes* can take a second argument that must be separated by a comma. Currently, only the two parameters 'list' and 'replace' are evaluated, e.g. +--page-hashes=md5,list+ or +--page-hashes=replace+. When 'list' is present, dvisvgm doesn't perform any conversion but just lists the hash values +%hd+ and +%hc+ of the pages specified by option *--page*. Parameter 'replace' forces dvisvgm to convert a DVI page even if a file with the target name already exists. *-P, --pdf*:: If this option is given, dvisvgm does not expect a DVI but a PDF input file, and tries to convert it to SVG. Similar to the conversion of DVI files, only the first page is processed by default. Option *--page* can be used to select different pages, page ranges, and/or page sequences. + If a Ghostscript version < 10.01.0 is found, dvisvgm uses Ghostscript to process the PDF file. In this case, the conversion is realized by creating a single 'pdffile' special command which is forwarded to dvisvgm's PostScript special handler. Therefore, this option is only available if dvisvgm was built with PostScript support enabled, and requires Ghostscript to be accessible. See option *--libgs* for further information. + As of Ghostscript 10.01.0, this will no longer work due to the introduction of a new PDF interpreter. Therefore, an alternative conversion module based on _mutool_, a utility which is part of the https://mupdf.com[MuPDF] package, has been introduced. It's automatically invoked if Ghostscript can't be used and if a working +mutool+ executable is present in a directory which is part of the system's search path. + Alternatively, environment variable +DVISVGM_PDF_PROC+ can be used to select the PDF processor. The currently supported values are +gs+ and +mutool+. *-d, --precision*='digits':: Specifies the maximum number of decimal places applied to floating-point attribute values. All attribute values written to the generated SVG file(s) are rounded accordingly. The parameter 'digits' accepts integer values from 0 to 6, where 0 enables the automatic selection of significant decimal places. This is also the default value if dvisvgm is called without option *--precision*. *--progress*[='delay']:: Enables a simple progress indicator shown when time-consuming operations like PostScript specials are processed. The indicator doesn't appear before the given delay (in seconds) has elapsed. The default delay value is 0.5 seconds. *-r, --rotate*='angle':: Rotates the page content clockwise by 'angle' degrees around the page center. This option is equivalent to *-TR*'angle'. *-R, --relative*:: SVG allows you to define graphics paths by a sequence of absolute and/or relative path commands, i.e. each command expects either absolute coordinates or coordinates relative to the current drawing position. By default, dvisvgm creates paths made up of absolute commands. If option *--relative* is given, relative commands are created instead. This slightly reduces the size of the SVG files in most cases. *--stdin*:: Tells dvisvgm to read the DVI or EPS input data from *stdin* instead from a file. Alternatively to option *--stdin*, a single dash (-) can be given. The default name of the generated SVG file is 'stdin.svg' which can be changed with option *--output*. *-s, --stdout*:: Don't write the SVG output to a file but redirect it to *stdout*. *--tmpdir*[='path']:: In some cases, dvisvgm needs to create temporary files to work properly. These files go to the system's temporary folder by default, e.g. +/tmp+ on Linux systems. Option *--tmpdir* can be used to specify a different location. Please note that dvisvgm does not create this folder if it doesn't exist. Therefore, you must ensure that it's actually present before running dvisvgm. + In order to prevent colliding files caused by parallel calls of dvisvgm, the program doesn't write the files directly in the specified directory but furthermore creates a uniquely named subfolder in there, where the temporary files will be placed. This can be prevented by appending +//+ or +\\+ (on Windows) to the specified directory name. For example, +--tmpdir=.//+ creates the temporary files directly in the current working directory, while +--tmpdir=.+ places them in a dedicated subfolder of the current working directory. + If the optional parameter 'path' of option *--tmpdir* is omitted, dvisvgm prints the location of the system's temp folder and exits. *-a, --trace-all*=['retrace']:: This option forces dvisvgm to vectorize not only the glyphs actually required to render the SVG file correctly – which is the default –, but processes all glyphs of all fonts referenced in the DVI file. Because dvisvgm stores the tracing results in a font cache, all following conversions of these fonts will speed up significantly. The boolean option 'retrace' determines how to handle glyphs already stored in the cache. By default, these glyphs are skipped. Setting argument 'retrace' to 'yes' or 'true' forces dvisvgm to retrace the corresponding bitmaps again. + [NOTE] This option only takes effect if font caching is active. Therefore, *--trace-all* cannot be combined with option *--cache=none*. + *-T, --transform*='commands':: Applies a sequence of transformations to the SVG content. Each transformation is described by a 'command' beginning with a capital letter followed by a list of comma-separated parameters. Following transformation commands are supported: *T* 'tx'[,'ty'];; Translates (moves/shifts) the page in direction of vector ('tx','ty'). If 'ty' is omitted, 'ty'=0 is assumed. The expected unit length of 'tx' and 'ty' are TeX points (1pt = 1/72.27in). However, there are several constants defined to simplify the unit conversion (see below). *S* 'sx'[,'sy'];; Scales the page horizontally by 'sx' and vertically by 'sy'. If 'sy' is omitted, 'sy'='sx' is assumed. *R* 'angle'[,'x','y'];; Rotates the page clockwise by 'angle' degrees around point ('x','y'). If the optional arguments 'x' and 'y' are omitted, the page will be rotated around its center depending on the chosen page format. When option *-bnone* is given, the rotation center is origin (0,0). *KX* 'angle';; Skews the page along the 'x'-axis by 'angle' degrees. Argument 'angle' can take any value except 90+180__k__, where 'k' is an integer. *KY* 'angle';; Skews the page along the 'y'-axis by 'angle' degrees. Argument 'angle' can take any value except 90+180__k__, where 'k' is an integer. *FH* ['y'];; Mirrors (flips) the page at the horizontal line through point (0,'y'). Omitting the optional argument leads to 'y'='h'/2, where 'h' denotes the page height (see <> below). *FV* ['x'];; Mirrors (flips) the page at the vertical line through point ('x',0). Omitting the optional argument leads to 'x'='w'/2, where 'w' denotes the page width (see <> below). *M* 'm1',...,'m6';; Applies a transformation described by the 3×3 matrix \(('m1','m2','m3'),('m4','m5','m6'),(0,0,1)), where the inner triples denote the rows. + [NOTE] ================================================================================================= All transformation commands of option *-T, --transform* are applied in the order of their appearance. Multiple commands can optionally be separated by spaces. In this case the whole transformation string has to be enclosed in double quotes to keep them together. All parameters are expressions of floating point type. You can either give plain numbers or arithmetic terms combined by the operators *+* (addition), *-* (subtraction), *** (multiplication), */* (division) or *%* (modulo) with common associativity and precedence rules. Parentheses may be used as well. [[constants]] Additionally, some pre-defined constants are provided: [horizontal] *ux*:: horizontal position of upper left page corner in TeX point units *uy*:: vertical position of upper left page corner in TeX point units *h*:: page height in TeX point units (0 in case of *-bnone*) *w*:: page width in TeX point units (0 in case of *-bnone*) Furthermore, you can use the 9 length constants +pt+, +bp+, +cm+, +mm+, +in+, +pc+, +dd+, +cc+, and +sp+, e.g. +2cm+ or +1.6in+. Thus, option +-TT1in,0R45+ moves the page content 1 inch to the right and rotates it by 45 degrees around the page center afterwards. For single transformations, there are also the short-hand options *-c*, *-t* and *-r* available. In contrast to the *--transform* commands, the order of these options is not significant, so that it's not possible to describe transformation sequences with them. ================================================================================================= + // // *-t, --translate*='tx'[,'ty']:: Translates (moves) the page content in direction of vector ('tx','ty'). This option is equivalent to *-TT*'tx','ty'. *-v, --verbosity*='level':: Controls the type of messages printed during a dvisvgm run: [horizontal] *0*;; no message output at all *1*;; error messages only *2*;; warning messages only *4*;; informational messages only *8*;; user messages only (e.g. created by special +dvisvgm:message+) + [NOTE] By adding these values you can combine the categories. The default level is 15, i.e. all messages are printed. + *-V, --version*[='extended']:: Prints the version of dvisvgm and exits. If the optional argument is set to 'yes', the version numbers of the linked libraries are printed as well. *-z, --zip*[='level']:: Creates a compressed SVG file with suffix .svgz. The optional argument specifies the compression level. Valid values are in the range of 1 to 9 (default value is 9). Larger values cause better compression results but may take slightly more computation time. *-Z, --zoom*='factor':: Multiplies the values of the 'width' and 'height' attributes of the SVG root element by argument 'factor' while the coordinate system of the graphic content is retained. As a result, most SVG viewers zoom the graphics accordingly. If a negative zoom factor is given, the 'width' and 'height' attributes are omitted. [[specials]] Supported Specials ------------------ dvisvgm supports several 'special commands' that enrich the DVI command set with additional instructions for features, like color, graphics, and hyperlinks. The term 'special command', or just 'special', originates from the TeX command +\special{...}+ which does almost nothing. TeX only forwards the argument of this command to the DVI file using the corresponding 'xxx' opcode, thus delegating its execution to the DVI driver. The driver can then decide to either process or ignore it, depending on the supported statements. The parameter of TeX's +\special+ command is given in curly braces and may consist of an arbitrary character sequence representing the actual instruction, for example +color Red+. It might be worth mentioning that specials are only evaluated when processing DVI files. PS/EPS and PDF don't know anything about the concept of specials and therefore don't provide means to represent them. In order to evaluate the special commands, dvisvgm implements several dedicated handlers. Each handler is responsible for all special statements belonging to the same command set, i.e. commands usually – but not necessarily – beginning with a common prefix. For example, all PDF specials start with the prefix +pdf:+, while the TPIC special set consists of 13 different commands without common identifier. The PDF specials are processed by dvisvgm's 'pdf' handler, the TPIC ones by the 'tpic' handler. To get a list of the actually provided special handlers, use option *--list-specials* (see above). The following list gives an overview of the special sets currently supported. The names of the handlers can also be used to disable the processing of individual sets of specials. For further information on this, see option *--no-specials*. *bgcolor*:: Special statements for changing the background/page color. Currently, dvisvgm only supports the +background+ statement as specified in the https://tug.org/texinfohtml/dvips.html#Color-specifications[dvips manual]. Since SVG 1.1 doesn't support background colors, dvisvgm inserts a rectangle of the chosen color into the generated SVG document. This rectangle always gets the same size as the selected or computed bounding box. This background color command is part of the color special set but is handled separately in order to let the user turn it off. *color*:: Statements of this command set provide instructions to change the text/paint color. For an overview of the exact syntax, see the documentation of dvips, for instance. + dvisvgm extends the dvips syntax of the color specials by two optional modifiers to enable the differentiation between fill and stroke colors, i.e. colors used to fill enclosed areas and to draw lines, respectively. If one of the color specifiers, like a color name or a color model followed by a sequence of color components, is preceded by +fill+ or +stroke+, only the corresponding color is changed. Without these modifiers both colors are affected. Example: +color push fill rgb 1 0 1+ pushes a new color pair onto the color stack whereby the fill color is set to magenta and the stroke color retains its current value. +color push rgb 1 0 1+ pushes a color pair with both colors set to magenta. + Additionally, the new special *color set* is introduced. Its syntax is the same as the one of *color push* including the optional +fill+ and +stroke+ modifiers. Instead of pushing a new color pair it modifies the topmost one on the stack. If the color stack is empty, the default (black) fill/stroke color is changed. *dvisvgm*:: The following list gives a brief overview of dvisvgm's own set of currently supported specials. *dvisvgm:raw* 'text'::: Adds an arbitrary sequence of XML nodes to the page section of the SVG document. dvisvgm checks syntax and proper nesting of the inserted elements but does not perform any validation, thus the user has to ensure that the resulting SVG is still valid. Opening and closing tags may be distributed among different 'raw' specials. The tags themselves can also be split but must be continued with the immediately following 'raw' special. Both syntactically incorrect and wrongly nested tags lead to error messages. + Parameter 'text' may also contain the expressions *{?x}*, *{?y}*, *{?color}*, *{?fillcolor}*, *{?strokecolor}*, *{?matrix}*, *{?pageno}*, *{?svgfile}*, and *{?svgpath}* that respectively expand to the current 'x' and 'y' coordinate, an RGB hex string of the current active fill and stroke color, the current transformation matrix, the current page number, and the relative and absolute path of the SVG file being created. *{?color}* expands to the same string as *{?fillcolor}* and is still available for compatibility with older dvisvgm versions that didn't distinguish between fill and stroke colors (see information about color specials below). + As SVG doesn't support CMYK colors, for example in +fill+ and +stroke+ attributes, dvisvgm provides macro *{?cmyk(_c_,_m_,_y_,_k_)}* to create an RGB hex string from a CMYK color. It can be used instead of a combination of color/PostScript specials and color macros to directly insert a CMYK color value. + Character sequence *{?nl}* expands to a newline character. Finally, constructions of the form *{?(_expr_)}* enable the evaluation of mathematical expressions which may consist of basic arithmetic operations including modulo. As above, the variables 'x' and 'y' represent the current coordinates. Invalid operations, like divisions by zero, lead to an error message on the console. Example: +{?(-10*(x+2y)-5)}+ is a valid expression and expands to the corresponding numeric string. *dvisvgm:rawdef* 'text'::: This command is similar to *dvisvgm:raw*, but puts the XML nodes into the section of the SVG document currently being generated. *dvisvgm:rawset* 'name' ... *dvisvgm:endrawset*::: This pair of specials marks the begin and end of a definition of a named raw SVG fragment. All *dvisvgm:raw* and *dvisvgm:rawdef* specials enclosed by *dvisvgm:rawset* and *dvisvgm:endrawset* are not evaluated immediately but stored together under the given 'name' for later use. Once defined, the named fragment can be referenced throughout the DVI file by *dvisvgm:rawput* (see below). The two commands *dvisvgm:rawset* and *dvisvgm:endrawset* must not be nested, i.e. each call of *dvisvgm:rawset* has to be followed by a corresponding call of *dvisvgm:endrawset* before another *dvisvgm:rawset* may occur. Also, the identifier 'name' must be unique throughout the DVI file. Using *dvisvgm:rawset* multiple times together with the same 'name' leads to warning messages. *dvisvgm:rawput* 'name'::: Inserts raw SVG fragments previously stored under the given 'name'. dvisvgm distinguishes between fragments that were specified with *dvisvgm:raw* or *dvisvgm:rawdef*, and handles them differently: It inserts all *dvisvgm:raw* parts every time *dvisvgm:rawput* is called, whereas the *dvisvgm:rawdef* portions go to the section of the current SVG document only once. *dvisvgm:img* 'width' 'height' 'file'::: Creates an +image+ element using the current graphic position, transformation matrix, the specified extents, and the given filename. This special command also updates the bounding box of the resulting SVG to entirely enclose the transformed image. The image itself is positioned such that the lower left corner of the untransformed image lies at the current graphic position. The length 'width' and 'height' specify the extents of the untransformed image. For a list of supported length units see option *--bbox*. Plain numbers without an appended unit specifier imply TeX points (1in = 72.27pt). + Parameter 'file' can be a plain filename or a relative or absolute path of a file. By default, dvisvgm just creates links referencing the image file so that the SVG renderer will evaluate the filename or path relative to the location of the generated SVG file. If option *--embed-bitmaps* is given, JPEG and PNG images are embedded into the SVG document. As this requires base64-encoding of the image data, the resulting SVG files can become quite big. *dvisvgm:bbox* lock::: Locks the bounding box of the current page and prevents it from further updating, i.e. graphics elements added after calling this special are not taken into account in determining the extent of the bounding box. *dvisvgm:bbox* unlock::: Unlocks the previously locked bounding box of the current page so that it gets updated again when adding graphics elements to the page. *dvisvgm:bbox* n[ew] 'name'::: Defines or resets a local bounding box called 'name'. The name may consist of letters and digits. While processing a DVI page, dvisvgm continuously updates the (global) bounding box of the current page in order to determine the minimal rectangle containing all visible page components (characters, images, drawing elements etc.) Additionally to the global bounding box, the user can request an arbitrary number of named local bounding boxes. Once defined, these boxes are updated together with the global bounding box starting with the first character that follows the definition. Thus, the local boxes can be used to compute the extent of parts of the page. This is useful for scenarios where the generated SVG file is post-processed. + In conjunction with special *dvisvgm:raw*, the macro *{?bbox 'name'}* expands to the four values 'x', 'y', 'w', and 'h' (separated by spaces) specifying the coordinates of the upper left corner, width, and height of the local box 'name'. If box 'name' wasn't previously defined, all four values equal to zero. *dvisvgm:bbox* 'width' 'height' ['depth'] [+transform+]::: Updates the bounding box of the current page by embedding a virtual rectangle ('x', 'y', 'width', 'height') where the lower left corner is located at the current DVI drawing position ('x','y'). If the optional parameter 'depth' is specified, dvisvgm embeds a second rectangle ('x', 'y', 'width', -__depth__). The lengths 'width', 'height', and 'depth' can be given together with a unit specifier (see option *--bbox*) or as plain floating point numbers. In the latter case, TeX point units are assumed (1in = 72.27pt). Depending on size and position of the virtual rectangle, this command either enlarges the overall bounding box or leaves it as is. So, it's not possible to reduce its extent. + This special is supposed to be used together with *dvisvgm:raw* in order to update the viewport of the page properly. By default, the box extents are assigned unchanged and, in particular, are not altered by transformation commands. In order to apply the current transformation matrix, the optional modifier +transform+ can be added at the end of the special statement. *dvisvgm:bbox* a[bs] 'x1' 'y1' 'x2' 'y2' [+transform+]::: This variant of the bbox special updates the bounding box by embedding a virtual rectangle ('x1','y1','x2','y2'). The points ('x1','y1') and ('x2','y2') denote the absolute coordinates of two diagonal corners of the rectangle. As with the relative special variant described above, the optional modifier +transform+ allows for applying the current transformation matrix to the bounding box. *dvisvgm:bbox* f[ix] 'x1' 'y1' 'x2' 'y2' [+transform+]::: This variant of the bbox special assigns an absolute (final) bounding box to the resulting SVG. After executing this command, dvisvgm doesn't further alter the bounding box coordinates, except this special is called again later. The points ('x1','y1') and ('x2','y2') denote the absolute coordinates of two diagonal corners of the rectangle. As with the relative special variant described above, the optional modifier +transform+ allows for applying the current transformation matrix to the bounding box. + The following TeX fragment adds two raw SVG elements to the output and updates the bounding box accordingly: + [source,tex] ------------------------------------------------------------------------------------- \special{dvisvgm:raw }% \special{dvisvgm:bbox 10bp 10bp 10bp transform}% \special{dvisvgm:bbox -10bp 10bp 10bp transform} \special{dvisvgm:raw }% \special{dvisvgm:bbox abs 10bp 200bp 100bp 250bp transform} ------------------------------------------------------------------------------------- *dvisvgm:currentcolor* [on|off]::: This special works similar to option `--currentcolor` but doesn't require an explicit color argument. Instead, it takes the currently active color and replaces it with `currentColor`. Therefore, the result depends on both the placement of the special and the preceding color changes. Argument `on` – which activates the 'currentColor' functionality – can be omitted. When called with argument `off`, the functionality is deactivated again. *dvisvgm:message* 'msg'::: Prints the given text 'msg' to the console. Besides static text it may also contain the macros +{?...}+ mentioned in the description of *dvisvgm:raw*. The messages created by this special can be suppressed with option *--verbosity* (see above). *em*:: These specials were introduced with the 'emTeX' distribution by Eberhard Mattes. They provide line drawing statements, instructions for embedding MSP, PCX, and BMP image files, as well as two PCL commands. dvisvgm supports only the line drawing statements and ignores all other em specials silently. A description of the command syntax can be found in the DVI driver documentation coming with https://ctan.org/pkg/emtex[emTeX]. *html*:: The hyperref specification defines several variants on how to mark hyperlinked areas in a DVI file. dvisvgm supports the plain HyperTeX special constructs as created with hyperref package option 'hypertex'. By default, all linked areas of the document are marked by a rectangle. Option *--linkmark* allows you to change this behavior. See above for further details. Information on syntax and semantics of the HyperTeX specials can be found in the https://ctan.org/pkg/hyperref[hyperref manual]. *papersize*:: The 'papersize' special, which is an extension introduced by dvips, can be used to specify the widths and heights of the pages in the DVI file. It affects the page it appears on as well as all following pages until another papersize special is found. If there is more than one papersize special present on a page, dvisvgm applies the last one. However, in order to stay compatible with previous versions of dvisvgm that did not evaluate these specials, their processing must be explicitly enabled by adding option *--bbox=papersize* on the command-line. Otherwise, dvisvgm ignores them and computes tight bounding boxes. *pdf*:: pdfTeX and dvipdfmx introduced several special commands related to the generation of PDF files. Currently, only 'pdf:mapfile', 'pdf:mapline', 'pdf:pagesize', and PDF hyperlink specials are supported by dvisvgm. The latter are the PDF pendants to the HTML HyperTeX specials. They are generated by the hyperref package in PDF mode, for example. If a DVI page contains unsupported PDF specials, dvisvgm prints a warning message showing the number of ignored special commands. + 'pdf:pagesize' is similar to the 'papersize' special (see above) which specifies the size of the current and all following pages. In order to actually apply the extents to the generated SVG files, option *--bbox=papersize* must be given. + 'pdf:mapfile' and 'pdf:mapline' allow for modifying the font map tree while processing the DVI file. They are used by CTeX, for example. dvisvgm supports both, the dvips and dvipdfm font map format. For further information on the command syntax and semantics, see the documentation of +\pdfmapfile+ in the https://ctan.org/pkg/pdftex[pdfTeX user manual]. *ps*:: The famous DVI driver https://www.tug.org/texinfohtml/dvips.html['dvips'] introduced its own set of specials in order to embed PostScript code into DVI files, which greatly improves the capabilities of DVI documents. One aim of dvisvgm is to completely evaluate all PostScript fragments and to convert as many of them as possible to SVG. In contrast to dvips, dvisvgm uses floating point arithmetic to compute the precise position of each graphic element, i.e. it doesn't round the coordinates. Therefore, the relative locations of the graphic elements may slightly differ from those computed by dvips. + Since PostScript is a rather complex language, dvisvgm does not implement its own PostScript interpreter but relies on https://ghostscript.com[Ghostscript] instead. If the Ghostscript library was not linked to the dvisvgm binary, it is looked up and loaded dynamically during runtime. In this case, dvisvgm looks for 'libgs.so.X' on Unix-like systems (supported ABI versions: 7,8,9), for 'libgs.X.dylib' on macOS, and for 'gsdll32.dll' or 'gsdll64.dll' on Windows. You can override the default file names with environment variable *LIBGS* or the command-line option *--libgs*. The library must be reachable through the ld search path (\*nix) or the PATH environment variable (Windows). Alternatively, the absolute file path can be specified. If the library cannot be found, dvisvgm disables the processing of PostScript specials and prints a warning message. Use option *--list-specials* to check whether PostScript support is available, i.e. entry 'ps' is present. + The PostScript handler also recognizes and evaluates bounding box data generated by the https://ctan.org/pkg/preview[preview package] with option 'tightpage'. If such data is present in the DVI file and if dvisvgm is called with option *--bbox=preview*, dvisvgm sets the width and total height of the SVG file to the values derived from the preview data. Additionally, it prints a message showing the width, height, and depth of the box in TeX point units to the console. Especially, the depth value can be read by a post-processor to vertically align the SVG graphics with the baseline of surrounding text in HTML or XSL-FO documents, for example. Please note that SVG bounding boxes are defined by a width and (total) height. In contrast to TeX, SVG provides no means to differentiate between height and depth, i.e. the vertical extents above and below the baseline, respectively. Therefore, it is generally not possible to retrieve the depth value from the SVG file itself. + If you call dvisvgm with option *--bbox=min* (the default) and preview data is present in the DVI file, dvisvgm doesn't apply the preview extents but computes a bounding box that tightly encloses the page contents. The height, depth and width values written to console are adapted accordingly. *tpic*:: The TPIC special set defines instructions for drawing simple geometric objects. Some LaTeX packages, like eepic and tplot, use these specials to describe graphics. Examples -------- +dvisvgm file+:: Converts the first page of 'file.dvi' to 'file.svg'. +dvisvgm -p1-5 file+:: Converts the first five pages of 'file.dvi' to 'file-1.svg',...,'file-5.svg'. +dvisvgm -p1- file+:: Converts all pages of 'file.dvi' to separate SVG files. +dvisvgm -p1,3 -O file+:: Converts the first and third page of 'file.dvi' to optimized SVG files. +dvisvgm - < file.dvi+:: Converts the first page of 'file.dvi' to 'stdin.svg' where the contents of 'file.dvi' is read from *stdin*. +dvisvgm -z file+:: Converts the first page of 'file.dvi' to 'file.svgz' with default compression level 9. +dvisvgm -p5 -z3 -ba4-l -o newfile file+:: Converts the fifth page of 'file.dvi' to 'newfile.svgz' with compression level 3. The bounding box is set to DIN/ISO A4 in landscape format. +dvisvgm --transform="R20,w/3,2h/5 T1cm,1cm S2,3" file+:: Converts the first page of 'file.dvi' to 'file.svg' where three transformations are applied. [[environment]] Environment ----------- dvisvgm uses the *kpathsea* library for locating the files that it opens. Hence, the environment variables described in the library's documentation influence the converter. If dvisvgm was linked without the Ghostscript library, and if PostScript support has not been disabled, the shared Ghostscript library is looked up during runtime via dlopen(). The environment variable *LIBGS* can be used to specify path and file name of the library. The pre-compiled Windows versions of dvisvgm require a working installation of MiKTeX 2.9 or above. dvisvgm does not work together with the portable edition of MiKTeX because it relies on MiKTeX's COM interface that is only accessible in a local installation. To enable the evaluation of PostScript specials, the original Ghostscript DLL 'gsdll32.dll' must be present and reachable through the search path. 64-bit Windows builds require the 64-bit Ghostscript DLL 'gsdll64.dll'. Both DLLs come with the corresponding Ghostscript installers available from https://ghostscript.com. The environment variable *DVISVGM_COLORS* specifies the colors used to highlight various parts of dvisvgm's message output. It is only evaluated if option *--color* is given. The value of *DVISVGM_COLORS* is a list of colon-separated entries of the form 'gg'='BF', where 'gg' denotes one of the color group indicators listed below, and 'BF' are two hexadecimal digits specifying the background (first digit) and foreground/text color (second digit). The color values are defined as follows: 0=black, 1=red, 2=green, 3=yellow, 4=blue, 5=magenta, 6=cyan, 7=gray, 8=bright red, 9=bright green, A=bright yellow, B=bright blue, C=bright magenta, D=bright cyan, E=bright gray, F=white. Depending on the terminal, the colors may differ. Rather than changing both the text and background color, it's also possible to change only one of them: An asterisk (*) in place of a hexadecimal digit indicates the default text or background color of the terminal. All malformed entries in the list are silently ignored. [horizontal] *er*:: error messages *wn*:: warning messages *pn*:: messages about page numbers *ps*:: page size messages *fw*:: information about the files written *sm*:: state messages *tr*:: messages of the glyph tracer *pi*:: progress indicator *Example:* +er=01:pi=\*5+ sets the colors of error messages (+er+) to red (+1+) on black (+0+), and those of progress indicators (+pi+) to cyan (+5+) on default background (+*+). Variable *DVISVGM_PDF_PROC* allows you to select the desired PDF processor. dvisvgm requires either Ghostscript (version < 10.01.0) or mutool to process PDF files. IF *DVISVGM_PDF_PROC* is not set, dvisvgm tries to detect the available processors. See option *--pdf* for further information. To select a specific PDF processor, you can set *DVISVGM_PDF_PROC* to +gs+ or +mutool+ which forces the use of Ghostscript and mutool respectively. Files ----- The location of the following files is determined by the kpathsea library. To check the actual kpathsea configuration you can use the *kpsewhich* utility. [horizontal] **.enc*:: Font encoding files **.fgd*:: Font glyph data files (cache files created by dvisvgm) **.map*:: Font map files **.mf*:: Metafont input files **.pfb*:: PostScript Type 1 font files **.pro*:: PostScript header/prologue files **.tfm*:: TeX font metric files **.ttf*:: TrueType font files **.vf*:: Virtual font files See also -------- *tex(1), mf(1), mktexmf(1), grodvi(1), potrace(1)*, and the *kpathsea library* info documentation. Resources --------- Project home page::: https://dvisvgm.de Code repository::: https://github.com/mgieseki/dvisvgm Bugs ---- Please report bugs using the bug tracker at https://github.com/mgieseki/dvisvgm/issues[GitHub]. Author ------ Written by {author} <{email}> Copying ------- Copyright (C) 2005-2025 Martin Gieseking. Free use of this software is granted under the terms of the GNU General Public License (GPL) version 3 or, (at your option) any later version. // vim: set syntax=asciidoc: dvisvgm-3.5/doc/generate-dvisvgm-sty.xsl000066400000000000000000000015101501401750600204150ustar00rootroot00000000000000 % This is a generated file -- don't modify it manually. \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{dvisvgm}[2015/02/04 dvisvgm DocBook style] \RequirePackageWithOptions{docbook} \RequirePackage[english]{babel} \RequirePackage[shortcuts]{extdash} \RequirePackage{underscore} \renewcommand*{\arraystretch}{-0.4} \AtBeginDocument{% \thispagestyle{empty} \lhead[]{\refmiscinfomanual} \rhead[]{\thepage} \lfoot[]{\refmiscinfosource{} \refmiscinfoversion} \rfoot[]{} % revision date given in dvisvgm.txt.in \def\tableofcontents{\stdtoc} % keep TOC on current page } dvisvgm-3.5/doc/tweak-db-article.xsl000066400000000000000000000020261501401750600174530ustar00rootroot00000000000000 dvisvgm {VERSION} Manual A fast DVI to SVG converter dvisvgm-3.5/doc/tweak-db-refentry.xsl000066400000000000000000000033671501401750600176770ustar00rootroot00000000000000 dvisvgm-3.5/doc/tweak-dblatex-pdf.xsl000066400000000000000000000020661501401750600176430ustar00rootroot00000000000000 Synopsis dvisvgm-3.5/doc/tweak-dblatex-tex.py000066400000000000000000000013151501401750600175100ustar00rootroot00000000000000import re import os def main (latex_file, stdout): latex_file_old = latex_file+"-old" os.rename(latex_file, latex_file_old) os.remove(os.path.splitext(latex_file)[0]+".pdf") with open(latex_file, "w") as outfile: with open(latex_file_old) as infile: lines = infile.readlines() for line in lines: if re.match(r'(.*\\def)|(.*\\href)', line) == None: line = re.sub(r'([a-zA-Z0-9]+)/', r'\1\\slash{}', line) line = re.sub(r'-{}-{}', r'\=/\=/', line) line = re.sub(r'([^a-zA-Z0-9])-{}', r'\1\=/', line) print(line.rstrip(), file=outfile) os.remove(latex_file_old) return 0 dvisvgm-3.5/libs/000077500000000000000000000000001501401750600137705ustar00rootroot00000000000000dvisvgm-3.5/libs/Makefile.am000066400000000000000000000004231501401750600160230ustar00rootroot00000000000000## This file is part of dvisvgm ## Copyright (C) 2005-2025 Martin Gieseking ## ## Process this file with automake. SUBDIRS = boost clipper md5 variant xxHash if !TEXLIVE_BUILD SUBDIRS += potrace endif if ENABLE_WOFF SUBDIRS += brotli woff2 endif dvisvgm-3.5/libs/boost/000077500000000000000000000000001501401750600151165ustar00rootroot00000000000000dvisvgm-3.5/libs/boost/LICENSE.txt000066400000000000000000000024721501401750600167460ustar00rootroot00000000000000Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. dvisvgm-3.5/libs/boost/Makefile.am000066400000000000000000000001311501401750600171450ustar00rootroot00000000000000noinst_HEADERS = \ boost-vectorstream.hpp \ vectorstream.hpp EXTRA_DIST = LICENSE.txt dvisvgm-3.5/libs/boost/boost-vectorstream.hpp000066400000000000000000000617441501401750600215050ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// // // This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. // Changed internal SGI string to a generic, templatized vector. Added efficient // internal buffer get/set/swap functions, so that we can obtain/establish the // internal buffer without any reallocation or copy. Kill those temporaries! /////////////////////////////////////////////////////////////////////////////// /* * Copyright (c) 1998 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ //!\file //!This file defines basic_vectorbuf, basic_ivectorstream, //!basic_ovectorstream, and basic_vectorstreamclasses. These classes //!represent streamsbufs and streams whose sources or destinations are //!STL-like vectors that can be swapped with external vectors to avoid //!unnecessary allocations/copies. #ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP #define BOOST_INTERPROCESS_VECTORSTREAM_HPP #include #include #include #include #include // char traits #include // ptrdiff_t #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wreorder" #endif namespace boost { namespace interprocess { //!A streambuf class that controls the transmission of elements to and from //!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream. //!It holds a character vector specified by CharVector template parameter //!as its formatting buffer. The vector must have contiguous storage, like //!std::vector, boost::interprocess::vector or boost::interprocess::basic_string template class basic_vectorbuf : public std::basic_streambuf { public: typedef CharVector vector_type; typedef typename CharVector::value_type char_type; typedef typename CharTraits::int_type int_type; typedef typename CharTraits::pos_type pos_type; typedef typename CharTraits::off_type off_type; typedef CharTraits traits_type; #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef std::basic_streambuf base_t; basic_vectorbuf(const basic_vectorbuf&); basic_vectorbuf & operator =(const basic_vectorbuf&); #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Throws if vector_type default //!constructor throws. explicit basic_vectorbuf(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : base_t(), m_mode(mode) { this->initialize_pointers(); } //!Constructor. Throws if //!vector_type(const VectorParameter ¶m) throws. template explicit basic_vectorbuf(const VectorParameter ¶m, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : base_t(), m_mode(mode), m_vect(param) { this->initialize_pointers(); } public: //!Swaps the underlying vector with the passed vector. //!This function resets the read/write position in the stream. //!Does not throw. void swap_vector(vector_type &vect) { if (this->m_mode & std::ios_base::out){ //Update high water if necessary //And resize vector to remove extra size if (mp_high_water < base_t::pptr()){ //Restore the vector's size if necessary mp_high_water = base_t::pptr(); } //This does not reallocate m_vect.resize(std::size_t(mp_high_water - (m_vect.size() ? &m_vect[0] : 0))); } //Now swap vector m_vect.swap(vect); this->initialize_pointers(); } //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const { if (this->m_mode & std::ios_base::out){ if (mp_high_water < base_t::pptr()){ //Restore the vector's size if necessary mp_high_water = base_t::pptr(); } //This shouldn't reallocate typedef typename vector_type::size_type size_type; char_type *old_ptr = base_t::pbase(); size_type high_pos = size_type(mp_high_water-old_ptr); if(m_vect.size() > high_pos){ m_vect.resize(high_pos); //But we must update end write pointer because vector size is now shorter int old_pos = (int)(base_t::pptr() - base_t::pbase()); const_cast(this)->base_t::setp(old_ptr, old_ptr + high_pos); const_cast(this)->base_t::pbump(old_pos); } } return m_vect; } //!Preallocates memory from the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's memory allocation throws. void reserve(typename vector_type::size_type size) { if (this->m_mode & std::ios_base::out && size > m_vect.size()){ typename vector_type::difference_type write_pos = base_t::pptr() - base_t::pbase(); typename vector_type::difference_type read_pos = base_t::gptr() - base_t::eback(); //Now update pointer data m_vect.reserve(size); this->initialize_pointers(); base_t::pbump((int)write_pos); if(this->m_mode & std::ios_base::in){ base_t::gbump((int)read_pos); } } } //!Calls clear() method of the internal vector. //!Resets the stream to the first position. void clear() { m_vect.clear(); this->initialize_pointers(); } #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //Maximizes high watermark to the initial vector size, //initializes read and write iostream buffers to the capacity //and resets stream positions void initialize_pointers() { // The initial read position is the beginning of the vector. if(!(m_mode & std::ios_base::out)){ if(m_vect.empty()){ this->setg(0, 0, 0); } else{ this->setg(&m_vect[0], &m_vect[0], &m_vect[0] + m_vect.size()); } } // The initial write position is the beginning of the vector. if(m_mode & std::ios_base::out){ //First get real size int real_size = (int)m_vect.size(); //Then maximize size for high watermarking m_vect.resize(m_vect.capacity()); BOOST_ASSERT(m_vect.size() == m_vect.capacity()); //Set high watermarking with the expanded size mp_high_water = m_vect.size() ? (&m_vect[0] + real_size) : 0; //Now set formatting pointers if(m_vect.empty()){ this->setp(0, 0); if(m_mode & std::ios_base::in) this->setg(0, 0, 0); } else{ char_type *p = &m_vect[0]; this->setp(p, p + m_vect.size()); if(m_mode & std::ios_base::in) this->setg(p, p, p + real_size); } if (m_mode & (std::ios_base::app | std::ios_base::ate)){ base_t::pbump((int)real_size); } } } protected: virtual int_type underflow() BOOST_OVERRIDE { if (base_t::gptr() == 0) return CharTraits::eof(); if(m_mode & std::ios_base::out){ if (mp_high_water < base_t::pptr()) mp_high_water = base_t::pptr(); if (base_t::egptr() < mp_high_water) base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); } if (base_t::gptr() < base_t::egptr()) return CharTraits::to_int_type(*base_t::gptr()); return CharTraits::eof(); } virtual int_type pbackfail(int_type c = CharTraits::eof()) BOOST_OVERRIDE { if(this->gptr() != this->eback()) { if(!CharTraits::eq_int_type(c, CharTraits::eof())) { if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) { this->gbump(-1); return c; } else if(m_mode & std::ios_base::out) { this->gbump(-1); *this->gptr() = CharTraits::to_char_type(c); return c; } else return CharTraits::eof(); } else { this->gbump(-1); return CharTraits::not_eof(c); } } else return CharTraits::eof(); } virtual int_type overflow(int_type c = CharTraits::eof()) BOOST_OVERRIDE { if(m_mode & std::ios_base::out) { if(!CharTraits::eq_int_type(c, CharTraits::eof())) { typedef typename vector_type::difference_type dif_t; //The new output position is the previous one plus one //because 'overflow' requires putting 'c' on the buffer dif_t new_outpos = base_t::pptr() - base_t::pbase() + 1; //Adjust high water if necessary dif_t hipos = mp_high_water - base_t::pbase(); if (hipos < new_outpos) hipos = new_outpos; //Insert the new data m_vect.push_back(CharTraits::to_char_type(c)); m_vect.resize(m_vect.capacity()); BOOST_ASSERT(m_vect.size() == m_vect.capacity()); char_type* p = const_cast(&m_vect[0]); //A reallocation might have happened, update pointers base_t::setp(p, p + (dif_t)m_vect.size()); mp_high_water = p + hipos; if (m_mode & std::ios_base::in) base_t::setg(p, p + (base_t::gptr() - base_t::eback()), mp_high_water); //Update write position to the old position + 1 base_t::pbump((int)new_outpos); return c; } else // c is EOF, so we don't have to do anything return CharTraits::not_eof(c); } else // Overflow always fails if it's read-only. return CharTraits::eof(); } virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE { //Get seek mode bool in(0 != (mode & std::ios_base::in)), out(0 != (mode & std::ios_base::out)); //Test for logic errors if(!in & !out) return pos_type(off_type(-1)); else if((in && out) && (dir == std::ios_base::cur)) return pos_type(off_type(-1)); else if((in && (!(m_mode & std::ios_base::in) || (off != 0 && this->gptr() == 0) )) || (out && (!(m_mode & std::ios_base::out) || (off != 0 && this->pptr() == 0)))) return pos_type(off_type(-1)); off_type newoff; //Just calculate the end of the stream. If the stream is read-only //the limit is the size of the vector. Otherwise, the high water mark //will mark the real size. off_type limit; if(m_mode & std::ios_base::out){ //Update high water marking because pptr() is going to change and it might //have been updated since last overflow() if(mp_high_water < base_t::pptr()) mp_high_water = base_t::pptr(); //Update read limits in case high water mark was changed if(m_mode & std::ios_base::in){ if (base_t::egptr() < mp_high_water) base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); } limit = static_cast(mp_high_water - base_t::pbase()); } else{ limit = static_cast(m_vect.size()); } switch(dir) { case std::ios_base::beg: newoff = 0; break; case std::ios_base::end: newoff = limit; break; case std::ios_base::cur: newoff = in ? static_cast(this->gptr() - this->eback()) : static_cast(this->pptr() - this->pbase()); break; default: return pos_type(off_type(-1)); } newoff += off; if (newoff < 0 || newoff > limit) return pos_type(-1); if (m_mode & std::ios_base::app && mode & std::ios_base::out && newoff != limit) return pos_type(-1); //This can reassign pointers //if(m_vect.size() != m_vect.capacity()) //this->initialize_pointers(); if (in) base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr()); if (out){ base_t::setp(base_t::pbase(), base_t::epptr()); base_t::pbump(static_cast(newoff)); } return pos_type(newoff); } virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) BOOST_OVERRIDE { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } private: std::ios_base::openmode m_mode; mutable vector_type m_vect; mutable char_type* mp_high_water; #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; //!A basic_istream class that holds a character vector specified by CharVector //!template parameter as its formatting buffer. The vector must have //!contiguous storage, like std::vector, boost::interprocess::vector or //!boost::interprocess::basic_string template class basic_ivectorstream : public std::basic_istream #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) , private basic_vectorbuf #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { public: typedef CharVector vector_type; typedef typename std::basic_ios ::char_type char_type; typedef typename std::basic_ios::int_type int_type; typedef typename std::basic_ios::pos_type pos_type; typedef typename std::basic_ios::off_type off_type; typedef typename std::basic_ios::traits_type traits_type; #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef basic_vectorbuf vectorbuf_t; typedef std::basic_ios basic_ios_t; typedef std::basic_istream base_t; vectorbuf_t & get_buf() { return *this; } const vectorbuf_t & get_buf() const{ return *this; } #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Throws if vector_type default //!constructor throws. basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in) : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base //(via basic_ios::init() call in base_t's constructor) without the risk of a //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. , vectorbuf_t(mode | std::ios_base::in) { this->base_t::rdbuf(&get_buf()); } //!Constructor. Throws if vector_type(const VectorParameter ¶m) //!throws. template basic_ivectorstream(const VectorParameter ¶m, std::ios_base::openmode mode = std::ios_base::in) : vectorbuf_t(param, mode | std::ios_base::in) //basic_ios_t() is constructed uninitialized as virtual base //and initialized inside base_t calling basic_ios::init() , base_t(&get_buf()) {} public: //!Returns the address of the stored //!stream buffer. basic_vectorbuf* rdbuf() const { return const_cast*>(&get_buf()); } //!Swaps the underlying vector with the passed vector. //!This function resets the read position in the stream. //!Does not throw. void swap_vector(vector_type &vect) { get_buf().swap_vector(vect); } //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const { return get_buf().vector(); } //!Calls reserve() method of the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's reserve throws. void reserve(typename vector_type::size_type size) { get_buf().reserve(size); } //!Calls clear() method of the internal vector. //!Resets the stream to the first position. void clear() { get_buf().clear(); } }; //!A basic_ostream class that holds a character vector specified by CharVector //!template parameter as its formatting buffer. The vector must have //!contiguous storage, like std::vector, boost::interprocess::vector or //!boost::interprocess::basic_string template class basic_ovectorstream : public std::basic_ostream #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) , private basic_vectorbuf #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { public: typedef CharVector vector_type; typedef typename std::basic_ios ::char_type char_type; typedef typename std::basic_ios::int_type int_type; typedef typename std::basic_ios::pos_type pos_type; typedef typename std::basic_ios::off_type off_type; typedef typename std::basic_ios::traits_type traits_type; #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef basic_vectorbuf vectorbuf_t; typedef std::basic_ios basic_ios_t; typedef std::basic_ostream base_t; vectorbuf_t & get_buf() { return *this; } const vectorbuf_t & get_buf()const { return *this; } #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Throws if vector_type default //!constructor throws. basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out) : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base //(via basic_ios::init() call in base_t's constructor) without the risk of a //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. , vectorbuf_t(mode | std::ios_base::out) { this->base_t::rdbuf(&get_buf()); } //!Constructor. Throws if vector_type(const VectorParameter ¶m) //!throws. template basic_ovectorstream(const VectorParameter ¶m, std::ios_base::openmode mode = std::ios_base::out) : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base //(via basic_ios::init() call in base_t's constructor) without the risk of a //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. , vectorbuf_t(param, mode | std::ios_base::out) { this->base_t::rdbuf(&get_buf()); } public: //!Returns the address of the stored //!stream buffer. basic_vectorbuf* rdbuf() const { return const_cast*>(&get_buf()); } //!Swaps the underlying vector with the passed vector. //!This function resets the write position in the stream. //!Does not throw. void swap_vector(vector_type &vect) { get_buf().swap_vector(vect); } //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const { return get_buf().vector(); } //!Calls reserve() method of the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's reserve throws. void reserve(typename vector_type::size_type size) { get_buf().reserve(size); } }; //!A basic_iostream class that holds a character vector specified by CharVector //!template parameter as its formatting buffer. The vector must have //!contiguous storage, like std::vector, boost::interprocess::vector or //!boost::interprocess::basic_string template class basic_vectorstream : public std::basic_iostream #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) , private basic_vectorbuf #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED { public: typedef CharVector vector_type; typedef typename std::basic_ios ::char_type char_type; typedef typename std::basic_ios::int_type int_type; typedef typename std::basic_ios::pos_type pos_type; typedef typename std::basic_ios::off_type off_type; typedef typename std::basic_ios::traits_type traits_type; #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef basic_vectorbuf vectorbuf_t; typedef std::basic_ios basic_ios_t; typedef std::basic_iostream base_t; vectorbuf_t & get_buf() { return *this; } const vectorbuf_t & get_buf() const{ return *this; } #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Constructor. Throws if vector_type default //!constructor throws. basic_vectorstream(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base //(via basic_ios::init() call in base_t's constructor) without the risk of a //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. , vectorbuf_t(mode) { this->base_t::rdbuf(&get_buf()); } //!Constructor. Throws if vector_type(const VectorParameter ¶m) //!throws. template basic_vectorstream(const VectorParameter ¶m, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base //(via basic_ios::init() call in base_t's constructor) without the risk of a //previous throwing vectorbuf constructor. Set the streambuf after risk has gone. , vectorbuf_t(param, mode) { this->base_t::rdbuf(&get_buf()); } public: //Returns the address of the stored stream buffer. basic_vectorbuf* rdbuf() const { return const_cast*>(&get_buf()); } //!Swaps the underlying vector with the passed vector. //!This function resets the read/write position in the stream. //!Does not throw. void swap_vector(vector_type &vect) { get_buf().swap_vector(vect); } //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const { return get_buf().vector(); } //!Calls reserve() method of the internal vector. //!Resets the stream to the first position. //!Throws if the internals vector's reserve throws. void reserve(typename vector_type::size_type size) { get_buf().reserve(size); } //!Calls clear() method of the internal vector. //!Resets the stream to the first position. void clear() { get_buf().clear(); } }; //Some typedefs to simplify usage //! //!typedef basic_vectorbuf > vectorbuf; //!typedef basic_vectorstream > vectorstream; //!typedef basic_ivectorstream > ivectorstream; //!typedef basic_ovectorstream > ovectorstream; //! //!typedef basic_vectorbuf > wvectorbuf; //!typedef basic_vectorstream > wvectorstream; //!typedef basic_ivectorstream > wivectorstream; //!typedef basic_ovectorstream > wovectorstream; }} //namespace boost { namespace interprocess { #ifdef __GNUC__ #pragma GCC diagnostic pop #endif #endif /* BOOST_INTERPROCESS_VECTORSTREAM_HPP */ dvisvgm-3.5/libs/boost/vectorstream.hpp000066400000000000000000000007371501401750600203540ustar00rootroot00000000000000#pragma once #ifndef BOOST_OVERRIDE #define BOOST_OVERRIDE override #endif #ifndef BOOST_ASSERT #define BOOST_ASSERT(expr) #endif #include "boost-vectorstream.hpp" template using ovectorstream = boost::interprocess::basic_ovectorstream>; template using ivectorstream = boost::interprocess::basic_ivectorstream>; dvisvgm-3.5/libs/brotli/000077500000000000000000000000001501401750600152635ustar00rootroot00000000000000dvisvgm-3.5/libs/brotli/LICENSE000066400000000000000000000020741501401750600162730ustar00rootroot00000000000000Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. 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. dvisvgm-3.5/libs/brotli/Makefile.am000066400000000000000000000041151501401750600173200ustar00rootroot00000000000000if !HAVE_BROTLI noinst_LIBRARIES = libbrotli.a libbrotli_a_SOURCES = \ common/constants.c \ common/constants.h \ common/context.c \ common/context.h \ common/dictionary.c \ common/dictionary.h \ common/platform.c \ common/platform.h \ common/shared_dictionary_internal.h \ common/transform.c \ common/transform.h \ common/version.h \ enc/backward_references.c \ enc/backward_references.h \ enc/backward_references_hq.c \ enc/backward_references_hq.h \ enc/backward_references_inc.h \ enc/bit_cost.c \ enc/bit_cost.h \ enc/bit_cost_inc.h \ enc/block_encoder_inc.h \ enc/block_splitter.c \ enc/block_splitter.h \ enc/block_splitter_inc.h \ enc/brotli_bit_stream.c \ enc/brotli_bit_stream.h \ enc/cluster.c \ enc/cluster.h \ enc/cluster_inc.h \ enc/command.c \ enc/command.h \ enc/compound_dictionary.c \ enc/compound_dictionary.h \ enc/compress_fragment.c \ enc/compress_fragment.h \ enc/compress_fragment_two_pass.c \ enc/compress_fragment_two_pass.h \ enc/dictionary_hash.c \ enc/dictionary_hash.h \ enc/encode.c \ enc/encoder_dict.c \ enc/encoder_dict.h \ enc/entropy_encode.c \ enc/entropy_encode.h \ enc/entropy_encode_static.h \ enc/fast_log.c \ enc/fast_log.h \ enc/find_match_length.h \ enc/hash_composite_inc.h \ enc/hash_forgetful_chain_inc.h \ enc/hash.h \ enc/hash_longest_match64_inc.h \ enc/hash_longest_match_inc.h \ enc/hash_longest_match_quickly_inc.h \ enc/hash_rolling_inc.h \ enc/hash_to_binary_tree_inc.h \ enc/histogram.c \ enc/histogram.h \ enc/histogram_inc.h \ enc/literal_cost.c \ enc/literal_cost.h \ enc/memory.c \ enc/memory.h \ enc/metablock.c \ enc/metablock.h \ enc/metablock_inc.h \ enc/params.h \ enc/prefix.h \ enc/quality.h \ enc/ringbuffer.h \ enc/state.h \ enc/static_dict.c \ enc/static_dict.h \ enc/static_dict_lut.h \ enc/utf8_util.c \ enc/utf8_util.h \ enc/write_bits.h \ include/brotli/decode.h \ include/brotli/encode.h \ include/brotli/port.h \ include/brotli/shared_dictionary.h \ include/brotli/types.h AM_CFLAGS = -Wall -I$(srcdir)/include endif EXTRA_DIST = LICENSE CLEANFILES = *.gcda *.gcno dvisvgm-3.5/libs/brotli/common/000077500000000000000000000000001501401750600165535ustar00rootroot00000000000000dvisvgm-3.5/libs/brotli/common/constants.c000066400000000000000000000011551501401750600207350ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "constants.h" const BrotliPrefixCodeRange _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = { {1, 2}, {5, 2}, {9, 2}, {13, 2}, {17, 3}, {25, 3}, {33, 3}, {41, 3}, {49, 4}, {65, 4}, {81, 4}, {97, 4}, {113, 5}, {145, 5}, {177, 5}, {209, 5}, {241, 6}, {305, 6}, {369, 7}, {497, 8}, {753, 9}, {1265, 10}, {2289, 11}, {4337, 12}, {8433, 13}, {16625, 24}}; dvisvgm-3.5/libs/brotli/common/constants.h000066400000000000000000000175131501401750600207470ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /** * @file * Common constants used in decoder and encoder API. */ #ifndef BROTLI_COMMON_CONSTANTS_H_ #define BROTLI_COMMON_CONSTANTS_H_ #include #include #include "platform.h" /* Specification: 7.3. Encoding of the context map */ #define BROTLI_CONTEXT_MAP_MAX_RLE 16 /* Specification: 2. Compressed representation overview */ #define BROTLI_MAX_NUMBER_OF_BLOCK_TYPES 256 /* Specification: 3.3. Alphabet sizes: insert-and-copy length */ #define BROTLI_NUM_LITERAL_SYMBOLS 256 #define BROTLI_NUM_COMMAND_SYMBOLS 704 #define BROTLI_NUM_BLOCK_LEN_SYMBOLS 26 #define BROTLI_MAX_CONTEXT_MAP_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + \ BROTLI_CONTEXT_MAP_MAX_RLE) #define BROTLI_MAX_BLOCK_TYPE_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 2) /* Specification: 3.5. Complex prefix codes */ #define BROTLI_REPEAT_PREVIOUS_CODE_LENGTH 16 #define BROTLI_REPEAT_ZERO_CODE_LENGTH 17 #define BROTLI_CODE_LENGTH_CODES (BROTLI_REPEAT_ZERO_CODE_LENGTH + 1) /* "code length of 8 is repeated" */ #define BROTLI_INITIAL_REPEATED_CODE_LENGTH 8 /* "Large Window Brotli" */ /** * The theoretical maximum number of distance bits specified for large window * brotli, for 64-bit encoders and decoders. Even when in practice 32-bit * encoders and decoders only support up to 30 max distance bits, the value is * set to 62 because it affects the large window brotli file format. * Specifically, it affects the encoding of simple huffman tree for distances, * see Specification RFC 7932 chapter 3.4. */ #define BROTLI_LARGE_MAX_DISTANCE_BITS 62U #define BROTLI_LARGE_MIN_WBITS 10 /** * The maximum supported large brotli window bits by the encoder and decoder. * Large window brotli allows up to 62 bits, however the current encoder and * decoder, designed for 32-bit integers, only support up to 30 bits maximum. */ #define BROTLI_LARGE_MAX_WBITS 30 /* Specification: 4. Encoding of distances */ #define BROTLI_NUM_DISTANCE_SHORT_CODES 16 /** * Maximal number of "postfix" bits. * * Number of "postfix" bits is stored as 2 bits in meta-block header. */ #define BROTLI_MAX_NPOSTFIX 3 #define BROTLI_MAX_NDIRECT 120 #define BROTLI_MAX_DISTANCE_BITS 24U #define BROTLI_DISTANCE_ALPHABET_SIZE(NPOSTFIX, NDIRECT, MAXNBITS) ( \ BROTLI_NUM_DISTANCE_SHORT_CODES + (NDIRECT) + \ ((MAXNBITS) << ((NPOSTFIX) + 1))) /* BROTLI_NUM_DISTANCE_SYMBOLS == 1128 */ #define BROTLI_NUM_DISTANCE_SYMBOLS \ BROTLI_DISTANCE_ALPHABET_SIZE( \ BROTLI_MAX_NDIRECT, BROTLI_MAX_NPOSTFIX, BROTLI_LARGE_MAX_DISTANCE_BITS) /* ((1 << 26) - 4) is the maximal distance that can be expressed in RFC 7932 brotli stream using NPOSTFIX = 0 and NDIRECT = 0. With other NPOSTFIX and NDIRECT values distances up to ((1 << 29) + 88) could be expressed. */ #define BROTLI_MAX_DISTANCE 0x3FFFFFC /* ((1 << 31) - 4) is the safe distance limit. Using this number as a limit allows safe distance calculation without overflows, given the distance alphabet size is limited to corresponding size (see kLargeWindowDistanceCodeLimits). */ #define BROTLI_MAX_ALLOWED_DISTANCE 0x7FFFFFFC /* Specification: 4. Encoding of Literal Insertion Lengths and Copy Lengths */ #define BROTLI_NUM_INS_COPY_CODES 24 /* 7.1. Context modes and context ID lookup for literals */ /* "context IDs for literals are in the range of 0..63" */ #define BROTLI_LITERAL_CONTEXT_BITS 6 /* 7.2. Context ID for distances */ #define BROTLI_DISTANCE_CONTEXT_BITS 2 /* 9.1. Format of the Stream Header */ /* Number of slack bytes for window size. Don't confuse with BROTLI_NUM_DISTANCE_SHORT_CODES. */ #define BROTLI_WINDOW_GAP 16 #define BROTLI_MAX_BACKWARD_LIMIT(W) (((size_t)1 << (W)) - BROTLI_WINDOW_GAP) typedef struct BrotliDistanceCodeLimit { uint32_t max_alphabet_size; uint32_t max_distance; } BrotliDistanceCodeLimit; /* This function calculates maximal size of distance alphabet, such that the distances greater than the given values can not be represented. This limits are designed to support fast and safe 32-bit decoders. "32-bit" means that signed integer values up to ((1 << 31) - 1) could be safely expressed. Brotli distance alphabet symbols do not represent consecutive distance ranges. Each distance alphabet symbol (excluding direct distances and short codes), represent interleaved (for NPOSTFIX > 0) range of distances. A "group" of consecutive (1 << NPOSTFIX) symbols represent non-interleaved range. Two consecutive groups require the same amount of "extra bits". It is important that distance alphabet represents complete "groups". To avoid complex logic on encoder side about interleaved ranges it was decided to restrict both sides to complete distance code "groups". */ BROTLI_UNUSED_FUNCTION BrotliDistanceCodeLimit BrotliCalculateDistanceCodeLimit( uint32_t max_distance, uint32_t npostfix, uint32_t ndirect) { BrotliDistanceCodeLimit result; /* Marking this function as unused, because not all files including "constants.h" use it -> compiler warns about that. */ BROTLI_UNUSED(&BrotliCalculateDistanceCodeLimit); if (max_distance <= ndirect) { /* This case never happens / exists only for the sake of completeness. */ result.max_alphabet_size = max_distance + BROTLI_NUM_DISTANCE_SHORT_CODES; result.max_distance = max_distance; return result; } else { /* The first prohibited value. */ uint32_t forbidden_distance = max_distance + 1; /* Subtract "directly" encoded region. */ uint32_t offset = forbidden_distance - ndirect - 1; uint32_t ndistbits = 0; uint32_t tmp; uint32_t half; uint32_t group; /* Postfix for the last dcode in the group. */ uint32_t postfix = (1u << npostfix) - 1; uint32_t extra; uint32_t start; /* Remove postfix and "head-start". */ offset = (offset >> npostfix) + 4; /* Calculate the number of distance bits. */ tmp = offset / 2; /* Poor-man's log2floor, to avoid extra dependencies. */ while (tmp != 0) {ndistbits++; tmp = tmp >> 1;} /* One bit is covered with subrange addressing ("half"). */ ndistbits--; /* Find subrange. */ half = (offset >> ndistbits) & 1; /* Calculate the "group" part of dcode. */ group = ((ndistbits - 1) << 1) | half; /* Calculated "group" covers the prohibited distance value. */ if (group == 0) { /* This case is added for correctness; does not occur for limit > 128. */ result.max_alphabet_size = ndirect + BROTLI_NUM_DISTANCE_SHORT_CODES; result.max_distance = ndirect; return result; } /* Decrement "group", so it is the last permitted "group". */ group--; /* After group was decremented, ndistbits and half must be recalculated. */ ndistbits = (group >> 1) + 1; /* The last available distance in the subrange has all extra bits set. */ extra = (1u << ndistbits) - 1; /* Calculate region start. NB: ndistbits >= 1. */ start = (1u << (ndistbits + 1)) - 4; /* Move to subregion. */ start += (group & 1) << ndistbits; /* Calculate the alphabet size. */ result.max_alphabet_size = ((group << npostfix) | postfix) + ndirect + BROTLI_NUM_DISTANCE_SHORT_CODES + 1; /* Calculate the maximal distance representable by alphabet. */ result.max_distance = ((start + extra) << npostfix) + postfix + ndirect + 1; return result; } } /* Represents the range of values belonging to a prefix code: [offset, offset + 2^nbits) */ typedef struct { uint16_t offset; uint8_t nbits; } BrotliPrefixCodeRange; /* "Soft-private", it is exported, but not "advertised" as API. */ BROTLI_COMMON_API extern const BrotliPrefixCodeRange _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; #endif /* BROTLI_COMMON_CONSTANTS_H_ */ dvisvgm-3.5/libs/brotli/common/context.c000066400000000000000000000174351501401750600204150ustar00rootroot00000000000000#include "context.h" #include /* Common context lookup table for all context modes. */ const uint8_t _kBrotliContextLookupTable[2048] = { /* CONTEXT_LSB6, last byte. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* CONTEXT_LSB6, second last byte, */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* CONTEXT_MSB6, last byte. */ 0, 0, 0, 0, 1, 1, 1, 1, 2, 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, 58, 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, /* CONTEXT_MSB6, second last byte, */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* CONTEXT_UTF8, last byte. */ /* ASCII range. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 32, 32, 24, 40, 28, 12, 12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12, 12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12, 0, /* UTF8 continuation byte range. */ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, /* UTF8 lead byte range. */ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, /* CONTEXT_UTF8 second last byte. */ /* ASCII range. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1, 1, 0, /* UTF8 continuation byte range. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* UTF8 lead byte range. */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, /* CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits. */ 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56, /* CONTEXT_SIGNED, second last byte. */ 0, 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, 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, 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, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, }; dvisvgm-3.5/libs/brotli/common/context.h000066400000000000000000000110721501401750600204110ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Lookup table to map the previous two bytes to a context id. There are four different context modeling modes defined here: CONTEXT_LSB6: context id is the least significant 6 bits of the last byte, CONTEXT_MSB6: context id is the most significant 6 bits of the last byte, CONTEXT_UTF8: second-order context model tuned for UTF8-encoded text, CONTEXT_SIGNED: second-order context model tuned for signed integers. If |p1| and |p2| are the previous two bytes, and |mode| is current context mode, we calculate the context as: context = ContextLut(mode)[p1] | ContextLut(mode)[p2 + 256]. For CONTEXT_UTF8 mode, if the previous two bytes are ASCII characters (i.e. < 128), this will be equivalent to context = 4 * context1(p1) + context2(p2), where context1 is based on the previous byte in the following way: 0 : non-ASCII control 1 : \t, \n, \r 2 : space 3 : other punctuation 4 : " ' 5 : % 6 : ( < [ { 7 : ) > ] } 8 : , ; : 9 : . 10 : = 11 : number 12 : upper-case vowel 13 : upper-case consonant 14 : lower-case vowel 15 : lower-case consonant and context2 is based on the second last byte: 0 : control, space 1 : punctuation 2 : upper-case letter, number 3 : lower-case letter If the last byte is ASCII, and the second last byte is not (in a valid UTF8 stream it will be a continuation byte, value between 128 and 191), the context is the same as if the second last byte was an ASCII control or space. If the last byte is a UTF8 lead byte (value >= 192), then the next byte will be a continuation byte and the context id is 2 or 3 depending on the LSB of the last byte and to a lesser extent on the second last byte if it is ASCII. If the last byte is a UTF8 continuation byte, the second last byte can be: - continuation byte: the next byte is probably ASCII or lead byte (assuming 4-byte UTF8 characters are rare) and the context id is 0 or 1. - lead byte (192 - 207): next byte is ASCII or lead byte, context is 0 or 1 - lead byte (208 - 255): next byte is continuation byte, context is 2 or 3 The possible value combinations of the previous two bytes, the range of context ids and the type of the next byte is summarized in the table below: |--------\-----------------------------------------------------------------| | \ Last byte | | Second \---------------------------------------------------------------| | last byte \ ASCII | cont. byte | lead byte | | \ (0-127) | (128-191) | (192-) | |=============|===================|=====================|==================| | ASCII | next: ASCII/lead | not valid | next: cont. | | (0-127) | context: 4 - 63 | | context: 2 - 3 | |-------------|-------------------|---------------------|------------------| | cont. byte | next: ASCII/lead | next: ASCII/lead | next: cont. | | (128-191) | context: 4 - 63 | context: 0 - 1 | context: 2 - 3 | |-------------|-------------------|---------------------|------------------| | lead byte | not valid | next: ASCII/lead | not valid | | (192-207) | | context: 0 - 1 | | |-------------|-------------------|---------------------|------------------| | lead byte | not valid | next: cont. | not valid | | (208-) | | context: 2 - 3 | | |-------------|-------------------|---------------------|------------------| */ #ifndef BROTLI_COMMON_CONTEXT_H_ #define BROTLI_COMMON_CONTEXT_H_ #include #include typedef enum ContextType { CONTEXT_LSB6 = 0, CONTEXT_MSB6 = 1, CONTEXT_UTF8 = 2, CONTEXT_SIGNED = 3 } ContextType; /* "Soft-private", it is exported, but not "advertised" as API. */ /* Common context lookup table for all context modes. */ BROTLI_COMMON_API extern const uint8_t _kBrotliContextLookupTable[2048]; typedef const uint8_t* ContextLut; /* typeof(MODE) == ContextType; returns ContextLut */ #define BROTLI_CONTEXT_LUT(MODE) (&_kBrotliContextLookupTable[(MODE) << 9]) /* typeof(LUT) == ContextLut */ #define BROTLI_CONTEXT(P1, P2, LUT) ((LUT)[P1] | ((LUT) + 256)[P2]) #endif /* BROTLI_COMMON_CONTEXT_H_ */ dvisvgm-3.5/libs/brotli/common/dictionary.c000066400000000000000000016317111501401750600210760ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "dictionary.h" #include "platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA) static const uint8_t kBrotliDictionaryData[] = /* GENERATED CODE START */ { 116,105,109,101,100,111,119,110,108,105,102,101,108,101,102,116,98,97,99,107,99, 111,100,101,100,97,116,97,115,104,111,119,111,110,108,121,115,105,116,101,99,105 ,116,121,111,112,101,110,106,117,115,116,108,105,107,101,102,114,101,101,119,111 ,114,107,116,101,120,116,121,101,97,114,111,118,101,114,98,111,100,121,108,111, 118,101,102,111,114,109,98,111,111,107,112,108,97,121,108,105,118,101,108,105, 110,101,104,101,108,112,104,111,109,101,115,105,100,101,109,111,114,101,119,111, 114,100,108,111,110,103,116,104,101,109,118,105,101,119,102,105,110,100,112,97, 103,101,100,97,121,115,102,117,108,108,104,101,97,100,116,101,114,109,101,97,99, 104,97,114,101,97,102,114,111,109,116,114,117,101,109,97,114,107,97,98,108,101, 117,112,111,110,104,105,103,104,100,97,116,101,108,97,110,100,110,101,119,115, 101,118,101,110,110,101,120,116,99,97,115,101,98,111,116,104,112,111,115,116,117 ,115,101,100,109,97,100,101,104,97,110,100,104,101,114,101,119,104,97,116,110,97 ,109,101,76,105,110,107,98,108,111,103,115,105,122,101,98,97,115,101,104,101,108 ,100,109,97,107,101,109,97,105,110,117,115,101,114,39,41,32,43,104,111,108,100, 101,110,100,115,119,105,116,104,78,101,119,115,114,101,97,100,119,101,114,101, 115,105,103,110,116,97,107,101,104,97,118,101,103,97,109,101,115,101,101,110,99, 97,108,108,112,97,116,104,119,101,108,108,112,108,117,115,109,101,110,117,102, 105,108,109,112,97,114,116,106,111,105,110,116,104,105,115,108,105,115,116,103, 111,111,100,110,101,101,100,119,97,121,115,119,101,115,116,106,111,98,115,109, 105,110,100,97,108,115,111,108,111,103,111,114,105,99,104,117,115,101,115,108,97 ,115,116,116,101,97,109,97,114,109,121,102,111,111,100,107,105,110,103,119,105, 108,108,101,97,115,116,119,97,114,100,98,101,115,116,102,105,114,101,80,97,103, 101,107,110,111,119,97,119,97,121,46,112,110,103,109,111,118,101,116,104,97,110, 108,111,97,100,103,105,118,101,115,101,108,102,110,111,116,101,109,117,99,104, 102,101,101,100,109,97,110,121,114,111,99,107,105,99,111,110,111,110,99,101,108, 111,111,107,104,105,100,101,100,105,101,100,72,111,109,101,114,117,108,101,104, 111,115,116,97,106,97,120,105,110,102,111,99,108,117,98,108,97,119,115,108,101, 115,115,104,97,108,102,115,111,109,101,115,117,99,104,122,111,110,101,49,48,48, 37,111,110,101,115,99,97,114,101,84,105,109,101,114,97,99,101,98,108,117,101,102 ,111,117,114,119,101,101,107,102,97,99,101,104,111,112,101,103,97,118,101,104,97 ,114,100,108,111,115,116,119,104,101,110,112,97,114,107,107,101,112,116,112,97, 115,115,115,104,105,112,114,111,111,109,72,84,77,76,112,108,97,110,84,121,112, 101,100,111,110,101,115,97,118,101,107,101,101,112,102,108,97,103,108,105,110, 107,115,111,108,100,102,105,118,101,116,111,111,107,114,97,116,101,116,111,119, 110,106,117,109,112,116,104,117,115,100,97,114,107,99,97,114,100,102,105,108,101 ,102,101,97,114,115,116,97,121,107,105,108,108,116,104,97,116,102,97,108,108,97, 117,116,111,101,118,101,114,46,99,111,109,116,97,108,107,115,104,111,112,118,111 ,116,101,100,101,101,112,109,111,100,101,114,101,115,116,116,117,114,110,98,111, 114,110,98,97,110,100,102,101,108,108,114,111,115,101,117,114,108,40,115,107,105 ,110,114,111,108,101,99,111,109,101,97,99,116,115,97,103,101,115,109,101,101,116 ,103,111,108,100,46,106,112,103,105,116,101,109,118,97,114,121,102,101,108,116, 116,104,101,110,115,101,110,100,100,114,111,112,86,105,101,119,99,111,112,121,49 ,46,48,34,60,47,97,62,115,116,111,112,101,108,115,101,108,105,101,115,116,111, 117,114,112,97,99,107,46,103,105,102,112,97,115,116,99,115,115,63,103,114,97,121 ,109,101,97,110,38,103,116,59,114,105,100,101,115,104,111,116,108,97,116,101,115 ,97,105,100,114,111,97,100,118,97,114,32,102,101,101,108,106,111,104,110,114,105 ,99,107,112,111,114,116,102,97,115,116,39,85,65,45,100,101,97,100,60,47,98,62, 112,111,111,114,98,105,108,108,116,121,112,101,85,46,83,46,119,111,111,100,109, 117,115,116,50,112,120,59,73,110,102,111,114,97,110,107,119,105,100,101,119,97, 110,116,119,97,108,108,108,101,97,100,91,48,93,59,112,97,117,108,119,97,118,101, 115,117,114,101,36,40,39,35,119,97,105,116,109,97,115,115,97,114,109,115,103,111 ,101,115,103,97,105,110,108,97,110,103,112,97,105,100,33,45,45,32,108,111,99,107 ,117,110,105,116,114,111,111,116,119,97,108,107,102,105,114,109,119,105,102,101, 120,109,108,34,115,111,110,103,116,101,115,116,50,48,112,120,107,105,110,100,114 ,111,119,115,116,111,111,108,102,111,110,116,109,97,105,108,115,97,102,101,115, 116,97,114,109,97,112,115,99,111,114,101,114,97,105,110,102,108,111,119,98,97,98 ,121,115,112,97,110,115,97,121,115,52,112,120,59,54,112,120,59,97,114,116,115, 102,111,111,116,114,101,97,108,119,105,107,105,104,101,97,116,115,116,101,112, 116,114,105,112,111,114,103,47,108,97,107,101,119,101,97,107,116,111,108,100,70, 111,114,109,99,97,115,116,102,97,110,115,98,97,110,107,118,101,114,121,114,117, 110,115,106,117,108,121,116,97,115,107,49,112,120,59,103,111,97,108,103,114,101, 119,115,108,111,119,101,100,103,101,105,100,61,34,115,101,116,115,53,112,120,59, 46,106,115,63,52,48,112,120,105,102,32,40,115,111,111,110,115,101,97,116,110,111 ,110,101,116,117,98,101,122,101,114,111,115,101,110,116,114,101,101,100,102,97, 99,116,105,110,116,111,103,105,102,116,104,97,114,109,49,56,112,120,99,97,109, 101,104,105,108,108,98,111,108,100,122,111,111,109,118,111,105,100,101,97,115, 121,114,105,110,103,102,105,108,108,112,101,97,107,105,110,105,116,99,111,115, 116,51,112,120,59,106,97,99,107,116,97,103,115,98,105,116,115,114,111,108,108, 101,100,105,116,107,110,101,119,110,101,97,114,60,33,45,45,103,114,111,119,74,83 ,79,78,100,117,116,121,78,97,109,101,115,97,108,101,121,111,117,32,108,111,116, 115,112,97,105,110,106,97,122,122,99,111,108,100,101,121,101,115,102,105,115,104 ,119,119,119,46,114,105,115,107,116,97,98,115,112,114,101,118,49,48,112,120,114, 105,115,101,50,53,112,120,66,108,117,101,100,105,110,103,51,48,48,44,98,97,108, 108,102,111,114,100,101,97,114,110,119,105,108,100,98,111,120,46,102,97,105,114, 108,97,99,107,118,101,114,115,112,97,105,114,106,117,110,101,116,101,99,104,105, 102,40,33,112,105,99,107,101,118,105,108,36,40,34,35,119,97,114,109,108,111,114, 100,100,111,101,115,112,117,108,108,44,48,48,48,105,100,101,97,100,114,97,119, 104,117,103,101,115,112,111,116,102,117,110,100,98,117,114,110,104,114,101,102, 99,101,108,108,107,101,121,115,116,105,99,107,104,111,117,114,108,111,115,115, 102,117,101,108,49,50,112,120,115,117,105,116,100,101,97,108,82,83,83,34,97,103, 101,100,103,114,101,121,71,69,84,34,101,97,115,101,97,105,109,115,103,105,114, 108,97,105,100,115,56,112,120,59,110,97,118,121,103,114,105,100,116,105,112,115, 35,57,57,57,119,97,114,115,108,97,100,121,99,97,114,115,41,59,32,125,112,104,112 ,63,104,101,108,108,116,97,108,108,119,104,111,109,122,104,58,229,42,47,13,10,32 ,49,48,48,104,97,108,108,46,10,10,65,55,112,120,59,112,117,115,104,99,104,97,116 ,48,112,120,59,99,114,101,119,42,47,60,47,104,97,115,104,55,53,112,120,102,108, 97,116,114,97,114,101,32,38,38,32,116,101,108,108,99,97,109,112,111,110,116,111, 108,97,105,100,109,105,115,115,115,107,105,112,116,101,110,116,102,105,110,101, 109,97,108,101,103,101,116,115,112,108,111,116,52,48,48,44,13,10,13,10,99,111, 111,108,102,101,101,116,46,112,104,112,60,98,114,62,101,114,105,99,109,111,115, 116,103,117,105,100,98,101,108,108,100,101,115,99,104,97,105,114,109,97,116,104, 97,116,111,109,47,105,109,103,38,35,56,50,108,117,99,107,99,101,110,116,48,48,48 ,59,116,105,110,121,103,111,110,101,104,116,109,108,115,101,108,108,100,114,117, 103,70,82,69,69,110,111,100,101,110,105,99,107,63,105,100,61,108,111,115,101,110 ,117,108,108,118,97,115,116,119,105,110,100,82,83,83,32,119,101,97,114,114,101, 108,121,98,101,101,110,115,97,109,101,100,117,107,101,110,97,115,97,99,97,112, 101,119,105,115,104,103,117,108,102,84,50,51,58,104,105,116,115,115,108,111,116, 103,97,116,101,107,105,99,107,98,108,117,114,116,104,101,121,49,53,112,120,39,39 ,41,59,41,59,34,62,109,115,105,101,119,105,110,115,98,105,114,100,115,111,114, 116,98,101,116,97,115,101,101,107,84,49,56,58,111,114,100,115,116,114,101,101, 109,97,108,108,54,48,112,120,102,97,114,109,226,128,153,115,98,111,121,115,91,48 ,93,46,39,41,59,34,80,79,83,84,98,101,97,114,107,105,100,115,41,59,125,125,109, 97,114,121,116,101,110,100,40,85,75,41,113,117,97,100,122,104,58,230,45,115,105, 122,45,45,45,45,112,114,111,112,39,41,59,13,108,105,102,116,84,49,57,58,118,105, 99,101,97,110,100,121,100,101,98,116,62,82,83,83,112,111,111,108,110,101,99,107, 98,108,111,119,84,49,54,58,100,111,111,114,101,118,97,108,84,49,55,58,108,101, 116,115,102,97,105,108,111,114,97,108,112,111,108,108,110,111,118,97,99,111,108, 115,103,101,110,101,32,226,128,148,115,111,102,116,114,111,109,101,116,105,108, 108,114,111,115,115,60,104,51,62,112,111,117,114,102,97,100,101,112,105,110,107, 60,116,114,62,109,105,110,105,41,124,33,40,109,105,110,101,122,104,58,232,98,97, 114,115,104,101,97,114,48,48,41,59,109,105,108,107,32,45,45,62,105,114,111,110, 102,114,101,100,100,105,115,107,119,101,110,116,115,111,105,108,112,117,116,115, 47,106,115,47,104,111,108,121,84,50,50,58,73,83,66,78,84,50,48,58,97,100,97,109, 115,101,101,115,60,104,50,62,106,115,111,110,39,44,32,39,99,111,110,116,84,50,49 ,58,32,82,83,83,108,111,111,112,97,115,105,97,109,111,111,110,60,47,112,62,115, 111,117,108,76,73,78,69,102,111,114,116,99,97,114,116,84,49,52,58,60,104,49,62, 56,48,112,120,33,45,45,60,57,112,120,59,84,48,52,58,109,105,107,101,58,52,54,90, 110,105,99,101,105,110,99,104,89,111,114,107,114,105,99,101,122,104,58,228,39,41 ,41,59,112,117,114,101,109,97,103,101,112,97,114,97,116,111,110,101,98,111,110, 100,58,51,55,90,95,111,102,95,39,93,41,59,48,48,48,44,122,104,58,231,116,97,110, 107,121,97,114,100,98,111,119,108,98,117,115,104,58,53,54,90,74,97,118,97,51,48, 112,120,10,124,125,10,37,67,51,37,58,51,52,90,106,101,102,102,69,88,80,73,99,97, 115,104,118,105,115,97,103,111,108,102,115,110,111,119,122,104,58,233,113,117, 101,114,46,99,115,115,115,105,99,107,109,101,97,116,109,105,110,46,98,105,110, 100,100,101,108,108,104,105,114,101,112,105,99,115,114,101,110,116,58,51,54,90, 72,84,84,80,45,50,48,49,102,111,116,111,119,111,108,102,69,78,68,32,120,98,111, 120,58,53,52,90,66,79,68,89,100,105,99,107,59,10,125,10,101,120,105,116,58,51,53 ,90,118,97,114,115,98,101,97,116,39,125,41,59,100,105,101,116,57,57,57,59,97,110 ,110,101,125,125,60,47,91,105,93,46,76,97,110,103,107,109,194,178,119,105,114, 101,116,111,121,115,97,100,100,115,115,101,97,108,97,108,101,120,59,10,9,125,101 ,99,104,111,110,105,110,101,46,111,114,103,48,48,53,41,116,111,110,121,106,101, 119,115,115,97,110,100,108,101,103,115,114,111,111,102,48,48,48,41,32,50,48,48, 119,105,110,101,103,101,97,114,100,111,103,115,98,111,111,116,103,97,114,121,99, 117,116,115,116,121,108,101,116,101,109,112,116,105,111,110,46,120,109,108,99, 111,99,107,103,97,110,103,36,40,39,46,53,48,112,120,80,104,46,68,109,105,115,99, 97,108,97,110,108,111,97,110,100,101,115,107,109,105,108,101,114,121,97,110,117, 110,105,120,100,105,115,99,41,59,125,10,100,117,115,116,99,108,105,112,41,46,10, 10,55,48,112,120,45,50,48,48,68,86,68,115,55,93,62,60,116,97,112,101,100,101,109 ,111,105,43,43,41,119,97,103,101,101,117,114,111,112,104,105,108,111,112,116,115 ,104,111,108,101,70,65,81,115,97,115,105,110,45,50,54,84,108,97,98,115,112,101, 116,115,85,82,76,32,98,117,108,107,99,111,111,107,59,125,13,10,72,69,65,68,91,48 ,93,41,97,98,98,114,106,117,97,110,40,49,57,56,108,101,115,104,116,119,105,110, 60,47,105,62,115,111,110,121,103,117,121,115,102,117,99,107,112,105,112,101,124, 45,10,33,48,48,50,41,110,100,111,119,91,49,93,59,91,93,59,10,76,111,103,32,115, 97,108,116,13,10,9,9,98,97,110,103,116,114,105,109,98,97,116,104,41,123,13,10,48 ,48,112,120,10,125,41,59,107,111,58,236,102,101,101,115,97,100,62,13,115,58,47, 47,32,91,93,59,116,111,108,108,112,108,117,103,40,41,123,10,123,13,10,32,46,106, 115,39,50,48,48,112,100,117,97,108,98,111,97,116,46,74,80,71,41,59,10,125,113, 117,111,116,41,59,10,10,39,41,59,10,13,10,125,13,50,48,49,52,50,48,49,53,50,48, 49,54,50,48,49,55,50,48,49,56,50,48,49,57,50,48,50,48,50,48,50,49,50,48,50,50,50 ,48,50,51,50,48,50,52,50,48,50,53,50,48,50,54,50,48,50,55,50,48,50,56,50,48,50, 57,50,48,51,48,50,48,51,49,50,48,51,50,50,48,51,51,50,48,51,52,50,48,51,53,50,48 ,51,54,50,48,51,55,50,48,49,51,50,48,49,50,50,48,49,49,50,48,49,48,50,48,48,57, 50,48,48,56,50,48,48,55,50,48,48,54,50,48,48,53,50,48,48,52,50,48,48,51,50,48,48 ,50,50,48,48,49,50,48,48,48,49,57,57,57,49,57,57,56,49,57,57,55,49,57,57,54,49, 57,57,53,49,57,57,52,49,57,57,51,49,57,57,50,49,57,57,49,49,57,57,48,49,57,56,57 ,49,57,56,56,49,57,56,55,49,57,56,54,49,57,56,53,49,57,56,52,49,57,56,51,49,57, 56,50,49,57,56,49,49,57,56,48,49,57,55,57,49,57,55,56,49,57,55,55,49,57,55,54,49 ,57,55,53,49,57,55,52,49,57,55,51,49,57,55,50,49,57,55,49,49,57,55,48,49,57,54, 57,49,57,54,56,49,57,54,55,49,57,54,54,49,57,54,53,49,57,54,52,49,57,54,51,49,57 ,54,50,49,57,54,49,49,57,54,48,49,57,53,57,49,57,53,56,49,57,53,55,49,57,53,54, 49,57,53,53,49,57,53,52,49,57,53,51,49,57,53,50,49,57,53,49,49,57,53,48,49,48,48 ,48,49,48,50,52,49,51,57,52,48,48,48,48,57,57,57,57,99,111,109,111,109,195,161, 115,101,115,116,101,101,115,116,97,112,101,114,111,116,111,100,111,104,97,99,101 ,99,97,100,97,97,195,177,111,98,105,101,110,100,195,173,97,97,115,195,173,118, 105,100,97,99,97,115,111,111,116,114,111,102,111,114,111,115,111,108,111,111,116 ,114,97,99,117,97,108,100,105,106,111,115,105,100,111,103,114,97,110,116,105,112 ,111,116,101,109,97,100,101,98,101,97,108,103,111,113,117,195,169,101,115,116, 111,110,97,100,97,116,114,101,115,112,111,99,111,99,97,115,97,98,97,106,111,116, 111,100,97,115,105,110,111,97,103,117,97,112,117,101,115,117,110,111,115,97,110, 116,101,100,105,99,101,108,117,105,115,101,108,108,97,109,97,121,111,122,111,110 ,97,97,109,111,114,112,105,115,111,111,98,114,97,99,108,105,99,101,108,108,111, 100,105,111,115,104,111,114,97,99,97,115,105,208,183,208,176,208,189,208,176,208 ,190,208,188,209,128,208,176,209,128,209,131,209,130,208,176,208,189,208,181,208 ,191,208,190,208,190,209,130,208,184,208,183,208,189,208,190,208,180,208,190,209 ,130,208,190,208,182,208,181,208,190,208,189,208,184,209,133,208,157,208,176,208 ,181,208,181,208,177,209,139,208,188,209,139,208,146,209,139,209,129,208,190,208 ,178,209,139,208,178,208,190,208,157,208,190,208,190,208,177,208,159,208,190,208 ,187,208,184,208,189,208,184,208,160,208,164,208,157,208,181,208,156,209,139,209 ,130,209,139,208,158,208,189,208,184,208,188,208,180,208,176,208,151,208,176,208 ,148,208,176,208,157,209,131,208,158,208,177,209,130,208,181,208,152,208,183,208 ,181,208,185,208,189,209,131,208,188,208,188,208,162,209,139,209,131,208,182,217 ,129,217,138,216,163,217,134,217,133,216,167,217,133,216,185,217,131,217,132,216 ,163,217,136,216,177,216,175,217,138,216,167,217,129,217,137,217,135,217,136,217 ,132,217,133,217,132,217,131,216,167,217,136,217,132,217,135,216,168,216,179,216 ,167,217,132,216,165,217,134,217,135,217,138,216,163,217,138,217,130,216,175,217 ,135,217,132,216,171,217,133,216,168,217,135,217,132,217,136,217,132,217,138,216 ,168,217,132,216,167,217,138,216,168,217,131,216,180,217,138,216,167,217,133,216 ,163,217,133,217,134,216,170,216,168,217,138,217,132,217,134,216,173,216,168,217 ,135,217,133,217,133,216,180,217,136,216,180,102,105,114,115,116,118,105,100,101 ,111,108,105,103,104,116,119,111,114,108,100,109,101,100,105,97,119,104,105,116, 101,99,108,111,115,101,98,108,97,99,107,114,105,103,104,116,115,109,97,108,108, 98,111,111,107,115,112,108,97,99,101,109,117,115,105,99,102,105,101,108,100,111, 114,100,101,114,112,111,105,110,116,118,97,108,117,101,108,101,118,101,108,116, 97,98,108,101,98,111,97,114,100,104,111,117,115,101,103,114,111,117,112,119,111, 114,107,115,121,101,97,114,115,115,116,97,116,101,116,111,100,97,121,119,97,116, 101,114,115,116,97,114,116,115,116,121,108,101,100,101,97,116,104,112,111,119, 101,114,112,104,111,110,101,110,105,103,104,116,101,114,114,111,114,105,110,112, 117,116,97,98,111,117,116,116,101,114,109,115,116,105,116,108,101,116,111,111, 108,115,101,118,101,110,116,108,111,99,97,108,116,105,109,101,115,108,97,114,103 ,101,119,111,114,100,115,103,97,109,101,115,115,104,111,114,116,115,112,97,99, 101,102,111,99,117,115,99,108,101,97,114,109,111,100,101,108,98,108,111,99,107, 103,117,105,100,101,114,97,100,105,111,115,104,97,114,101,119,111,109,101,110,97 ,103,97,105,110,109,111,110,101,121,105,109,97,103,101,110,97,109,101,115,121, 111,117,110,103,108,105,110,101,115,108,97,116,101,114,99,111,108,111,114,103, 114,101,101,110,102,114,111,110,116,38,97,109,112,59,119,97,116,99,104,102,111, 114,99,101,112,114,105,99,101,114,117,108,101,115,98,101,103,105,110,97,102,116, 101,114,118,105,115,105,116,105,115,115,117,101,97,114,101,97,115,98,101,108,111 ,119,105,110,100,101,120,116,111,116,97,108,104,111,117,114,115,108,97,98,101, 108,112,114,105,110,116,112,114,101,115,115,98,117,105,108,116,108,105,110,107, 115,115,112,101,101,100,115,116,117,100,121,116,114,97,100,101,102,111,117,110, 100,115,101,110,115,101,117,110,100,101,114,115,104,111,119,110,102,111,114,109, 115,114,97,110,103,101,97,100,100,101,100,115,116,105,108,108,109,111,118,101, 100,116,97,107,101,110,97,98,111,118,101,102,108,97,115,104,102,105,120,101,100, 111,102,116,101,110,111,116,104,101,114,118,105,101,119,115,99,104,101,99,107, 108,101,103,97,108,114,105,118,101,114,105,116,101,109,115,113,117,105,99,107, 115,104,97,112,101,104,117,109,97,110,101,120,105,115,116,103,111,105,110,103, 109,111,118,105,101,116,104,105,114,100,98,97,115,105,99,112,101,97,99,101,115, 116,97,103,101,119,105,100,116,104,108,111,103,105,110,105,100,101,97,115,119, 114,111,116,101,112,97,103,101,115,117,115,101,114,115,100,114,105,118,101,115, 116,111,114,101,98,114,101,97,107,115,111,117,116,104,118,111,105,99,101,115,105 ,116,101,115,109,111,110,116,104,119,104,101,114,101,98,117,105,108,100,119,104, 105,99,104,101,97,114,116,104,102,111,114,117,109,116,104,114,101,101,115,112, 111,114,116,112,97,114,116,121,67,108,105,99,107,108,111,119,101,114,108,105,118 ,101,115,99,108,97,115,115,108,97,121,101,114,101,110,116,114,121,115,116,111, 114,121,117,115,97,103,101,115,111,117,110,100,99,111,117,114,116,121,111,117, 114,32,98,105,114,116,104,112,111,112,117,112,116,121,112,101,115,97,112,112,108 ,121,73,109,97,103,101,98,101,105,110,103,117,112,112,101,114,110,111,116,101, 115,101,118,101,114,121,115,104,111,119,115,109,101,97,110,115,101,120,116,114, 97,109,97,116,99,104,116,114,97,99,107,107,110,111,119,110,101,97,114,108,121,98 ,101,103,97,110,115,117,112,101,114,112,97,112,101,114,110,111,114,116,104,108, 101,97,114,110,103,105,118,101,110,110,97,109,101,100,101,110,100,101,100,84,101 ,114,109,115,112,97,114,116,115,71,114,111,117,112,98,114,97,110,100,117,115,105 ,110,103,119,111,109,97,110,102,97,108,115,101,114,101,97,100,121,97,117,100,105 ,111,116,97,107,101,115,119,104,105,108,101,46,99,111,109,47,108,105,118,101,100 ,99,97,115,101,115,100,97,105,108,121,99,104,105,108,100,103,114,101,97,116,106, 117,100,103,101,116,104,111,115,101,117,110,105,116,115,110,101,118,101,114,98, 114,111,97,100,99,111,97,115,116,99,111,118,101,114,97,112,112,108,101,102,105, 108,101,115,99,121,99,108,101,115,99,101,110,101,112,108,97,110,115,99,108,105, 99,107,119,114,105,116,101,113,117,101,101,110,112,105,101,99,101,101,109,97,105 ,108,102,114,97,109,101,111,108,100,101,114,112,104,111,116,111,108,105,109,105, 116,99,97,99,104,101,99,105,118,105,108,115,99,97,108,101,101,110,116,101,114, 116,104,101,109,101,116,104,101,114,101,116,111,117,99,104,98,111,117,110,100, 114,111,121,97,108,97,115,107,101,100,119,104,111,108,101,115,105,110,99,101,115 ,116,111,99,107,32,110,97,109,101,102,97,105,116,104,104,101,97,114,116,101,109, 112,116,121,111,102,102,101,114,115,99,111,112,101,111,119,110,101,100,109,105, 103,104,116,97,108,98,117,109,116,104,105,110,107,98,108,111,111,100,97,114,114, 97,121,109,97,106,111,114,116,114,117,115,116,99,97,110,111,110,117,110,105,111, 110,99,111,117,110,116,118,97,108,105,100,115,116,111,110,101,83,116,121,108,101 ,76,111,103,105,110,104,97,112,112,121,111,99,99,117,114,108,101,102,116,58,102, 114,101,115,104,113,117,105,116,101,102,105,108,109,115,103,114,97,100,101,110, 101,101,100,115,117,114,98,97,110,102,105,103,104,116,98,97,115,105,115,104,111, 118,101,114,97,117,116,111,59,114,111,117,116,101,46,104,116,109,108,109,105,120 ,101,100,102,105,110,97,108,89,111,117,114,32,115,108,105,100,101,116,111,112, 105,99,98,114,111,119,110,97,108,111,110,101,100,114,97,119,110,115,112,108,105, 116,114,101,97,99,104,82,105,103,104,116,100,97,116,101,115,109,97,114,99,104, 113,117,111,116,101,103,111,111,100,115,76,105,110,107,115,100,111,117,98,116,97 ,115,121,110,99,116,104,117,109,98,97,108,108,111,119,99,104,105,101,102,121,111 ,117,116,104,110,111,118,101,108,49,48,112,120,59,115,101,114,118,101,117,110, 116,105,108,104,97,110,100,115,67,104,101,99,107,83,112,97,99,101,113,117,101, 114,121,106,97,109,101,115,101,113,117,97,108,116,119,105,99,101,48,44,48,48,48, 83,116,97,114,116,112,97,110,101,108,115,111,110,103,115,114,111,117,110,100,101 ,105,103,104,116,115,104,105,102,116,119,111,114,116,104,112,111,115,116,115,108 ,101,97,100,115,119,101,101,107,115,97,118,111,105,100,116,104,101,115,101,109, 105,108,101,115,112,108,97,110,101,115,109,97,114,116,97,108,112,104,97,112,108, 97,110,116,109,97,114,107,115,114,97,116,101,115,112,108,97,121,115,99,108,97, 105,109,115,97,108,101,115,116,101,120,116,115,115,116,97,114,115,119,114,111, 110,103,60,47,104,51,62,116,104,105,110,103,46,111,114,103,47,109,117,108,116, 105,104,101,97,114,100,80,111,119,101,114,115,116,97,110,100,116,111,107,101,110 ,115,111,108,105,100,40,116,104,105,115,98,114,105,110,103,115,104,105,112,115, 115,116,97,102,102,116,114,105,101,100,99,97,108,108,115,102,117,108,108,121,102 ,97,99,116,115,97,103,101,110,116,84,104,105,115,32,47,47,45,45,62,97,100,109, 105,110,101,103,121,112,116,69,118,101,110,116,49,53,112,120,59,69,109,97,105, 108,116,114,117,101,34,99,114,111,115,115,115,112,101,110,116,98,108,111,103,115 ,98,111,120,34,62,110,111,116,101,100,108,101,97,118,101,99,104,105,110,97,115, 105,122,101,115,103,117,101,115,116,60,47,104,52,62,114,111,98,111,116,104,101, 97,118,121,116,114,117,101,44,115,101,118,101,110,103,114,97,110,100,99,114,105, 109,101,115,105,103,110,115,97,119,97,114,101,100,97,110,99,101,112,104,97,115, 101,62,60,33,45,45,101,110,95,85,83,38,35,51,57,59,50,48,48,112,120,95,110,97, 109,101,108,97,116,105,110,101,110,106,111,121,97,106,97,120,46,97,116,105,111, 110,115,109,105,116,104,85,46,83,46,32,104,111,108,100,115,112,101,116,101,114, 105,110,100,105,97,110,97,118,34,62,99,104,97,105,110,115,99,111,114,101,99,111, 109,101,115,100,111,105,110,103,112,114,105,111,114,83,104,97,114,101,49,57,57, 48,115,114,111,109,97,110,108,105,115,116,115,106,97,112,97,110,102,97,108,108, 115,116,114,105,97,108,111,119,110,101,114,97,103,114,101,101,60,47,104,50,62,97 ,98,117,115,101,97,108,101,114,116,111,112,101,114,97,34,45,47,47,87,99,97,114, 100,115,104,105,108,108,115,116,101,97,109,115,80,104,111,116,111,116,114,117, 116,104,99,108,101,97,110,46,112,104,112,63,115,97,105,110,116,109,101,116,97, 108,108,111,117,105,115,109,101,97,110,116,112,114,111,111,102,98,114,105,101, 102,114,111,119,34,62,103,101,110,114,101,116,114,117,99,107,108,111,111,107,115 ,86,97,108,117,101,70,114,97,109,101,46,110,101,116,47,45,45,62,10,60,116,114, 121,32,123,10,118,97,114,32,109,97,107,101,115,99,111,115,116,115,112,108,97,105 ,110,97,100,117,108,116,113,117,101,115,116,116,114,97,105,110,108,97,98,111,114 ,104,101,108,112,115,99,97,117,115,101,109,97,103,105,99,109,111,116,111,114,116 ,104,101,105,114,50,53,48,112,120,108,101,97,115,116,115,116,101,112,115,67,111, 117,110,116,99,111,117,108,100,103,108,97,115,115,115,105,100,101,115,102,117, 110,100,115,104,111,116,101,108,97,119,97,114,100,109,111,117,116,104,109,111, 118,101,115,112,97,114,105,115,103,105,118,101,115,100,117,116,99,104,116,101, 120,97,115,102,114,117,105,116,110,117,108,108,44,124,124,91,93,59,116,111,112, 34,62,10,60,33,45,45,80,79,83,84,34,111,99,101,97,110,60,98,114,47,62,102,108, 111,111,114,115,112,101,97,107,100,101,112,116,104,32,115,105,122,101,98,97,110, 107,115,99,97,116,99,104,99,104,97,114,116,50,48,112,120,59,97,108,105,103,110, 100,101,97,108,115,119,111,117,108,100,53,48,112,120,59,117,114,108,61,34,112,97 ,114,107,115,109,111,117,115,101,77,111,115,116,32,46,46,46,60,47,97,109,111,110 ,103,98,114,97,105,110,98,111,100,121,32,110,111,110,101,59,98,97,115,101,100,99 ,97,114,114,121,100,114,97,102,116,114,101,102,101,114,112,97,103,101,95,104,111 ,109,101,46,109,101,116,101,114,100,101,108,97,121,100,114,101,97,109,112,114, 111,118,101,106,111,105,110,116,60,47,116,114,62,100,114,117,103,115,60,33,45,45 ,32,97,112,114,105,108,105,100,101,97,108,97,108,108,101,110,101,120,97,99,116, 102,111,114,116,104,99,111,100,101,115,108,111,103,105,99,86,105,101,119,32,115, 101,101,109,115,98,108,97,110,107,112,111,114,116,115,32,40,50,48,48,115,97,118, 101,100,95,108,105,110,107,103,111,97,108,115,103,114,97,110,116,103,114,101,101 ,107,104,111,109,101,115,114,105,110,103,115,114,97,116,101,100,51,48,112,120,59 ,119,104,111,115,101,112,97,114,115,101,40,41,59,34,32,66,108,111,99,107,108,105 ,110,117,120,106,111,110,101,115,112,105,120,101,108,39,41,59,34,62,41,59,105, 102,40,45,108,101,102,116,100,97,118,105,100,104,111,114,115,101,70,111,99,117, 115,114,97,105,115,101,98,111,120,101,115,84,114,97,99,107,101,109,101,110,116, 60,47,101,109,62,98,97,114,34,62,46,115,114,99,61,116,111,119,101,114,97,108,116 ,61,34,99,97,98,108,101,104,101,110,114,121,50,52,112,120,59,115,101,116,117,112 ,105,116,97,108,121,115,104,97,114,112,109,105,110,111,114,116,97,115,116,101, 119,97,110,116,115,116,104,105,115,46,114,101,115,101,116,119,104,101,101,108, 103,105,114,108,115,47,99,115,115,47,49,48,48,37,59,99,108,117,98,115,115,116, 117,102,102,98,105,98,108,101,118,111,116,101,115,32,49,48,48,48,107,111,114,101 ,97,125,41,59,13,10,98,97,110,100,115,113,117,101,117,101,61,32,123,125,59,56,48 ,112,120,59,99,107,105,110,103,123,13,10,9,9,97,104,101,97,100,99,108,111,99,107 ,105,114,105,115,104,108,105,107,101,32,114,97,116,105,111,115,116,97,116,115,70 ,111,114,109,34,121,97,104,111,111,41,91,48,93,59,65,98,111,117,116,102,105,110, 100,115,60,47,104,49,62,100,101,98,117,103,116,97,115,107,115,85,82,76,32,61,99, 101,108,108,115,125,41,40,41,59,49,50,112,120,59,112,114,105,109,101,116,101,108 ,108,115,116,117,114,110,115,48,120,54,48,48,46,106,112,103,34,115,112,97,105, 110,98,101,97,99,104,116,97,120,101,115,109,105,99,114,111,97,110,103,101,108,45 ,45,62,60,47,103,105,102,116,115,115,116,101,118,101,45,108,105,110,107,98,111, 100,121,46,125,41,59,10,9,109,111,117,110,116,32,40,49,57,57,70,65,81,60,47,114, 111,103,101,114,102,114,97,110,107,67,108,97,115,115,50,56,112,120,59,102,101, 101,100,115,60,104,49,62,60,115,99,111,116,116,116,101,115,116,115,50,50,112,120 ,59,100,114,105,110,107,41,32,124,124,32,108,101,119,105,115,115,104,97,108,108, 35,48,51,57,59,32,102,111,114,32,108,111,118,101,100,119,97,115,116,101,48,48, 112,120,59,106,97,58,227,130,115,105,109,111,110,60,102,111,110,116,114,101,112, 108,121,109,101,101,116,115,117,110,116,101,114,99,104,101,97,112,116,105,103, 104,116,66,114,97,110,100,41,32,33,61,32,100,114,101,115,115,99,108,105,112,115, 114,111,111,109,115,111,110,107,101,121,109,111,98,105,108,109,97,105,110,46,78, 97,109,101,32,112,108,97,116,101,102,117,110,110,121,116,114,101,101,115,99,111, 109,47,34,49,46,106,112,103,119,109,111,100,101,112,97,114,97,109,83,84,65,82,84 ,108,101,102,116,32,105,100,100,101,110,44,32,50,48,49,41,59,10,125,10,102,111, 114,109,46,118,105,114,117,115,99,104,97,105,114,116,114,97,110,115,119,111,114, 115,116,80,97,103,101,115,105,116,105,111,110,112,97,116,99,104,60,33,45,45,10, 111,45,99,97,99,102,105,114,109,115,116,111,117,114,115,44,48,48,48,32,97,115, 105,97,110,105,43,43,41,123,97,100,111,98,101,39,41,91,48,93,105,100,61,49,48,98 ,111,116,104,59,109,101,110,117,32,46,50,46,109,105,46,112,110,103,34,107,101, 118,105,110,99,111,97,99,104,67,104,105,108,100,98,114,117,99,101,50,46,106,112, 103,85,82,76,41,43,46,106,112,103,124,115,117,105,116,101,115,108,105,99,101,104 ,97,114,114,121,49,50,48,34,32,115,119,101,101,116,116,114,62,13,10,110,97,109, 101,61,100,105,101,103,111,112,97,103,101,32,115,119,105,115,115,45,45,62,10,10, 35,102,102,102,59,34,62,76,111,103,46,99,111,109,34,116,114,101,97,116,115,104, 101,101,116,41,32,38,38,32,49,52,112,120,59,115,108,101,101,112,110,116,101,110, 116,102,105,108,101,100,106,97,58,227,131,105,100,61,34,99,78,97,109,101,34,119, 111,114,115,101,115,104,111,116,115,45,98,111,120,45,100,101,108,116,97,10,38, 108,116,59,98,101,97,114,115,58,52,56,90,60,100,97,116,97,45,114,117,114,97,108, 60,47,97,62,32,115,112,101,110,100,98,97,107,101,114,115,104,111,112,115,61,32, 34,34,59,112,104,112,34,62,99,116,105,111,110,49,51,112,120,59,98,114,105,97,110 ,104,101,108,108,111,115,105,122,101,61,111,61,37,50,70,32,106,111,105,110,109, 97,121,98,101,60,105,109,103,32,105,109,103,34,62,44,32,102,106,115,105,109,103, 34,32,34,41,91,48,93,77,84,111,112,66,84,121,112,101,34,110,101,119,108,121,68, 97,110,115,107,99,122,101,99,104,116,114,97,105,108,107,110,111,119,115,60,47, 104,53,62,102,97,113,34,62,122,104,45,99,110,49,48,41,59,10,45,49,34,41,59,116, 121,112,101,61,98,108,117,101,115,116,114,117,108,121,100,97,118,105,115,46,106, 115,39,59,62,13,10,60,33,115,116,101,101,108,32,121,111,117,32,104,50,62,13,10, 102,111,114,109,32,106,101,115,117,115,49,48,48,37,32,109,101,110,117,46,13,10,9 ,13,10,119,97,108,101,115,114,105,115,107,115,117,109,101,110,116,100,100,105, 110,103,98,45,108,105,107,116,101,97,99,104,103,105,102,34,32,118,101,103,97,115 ,100,97,110,115,107,101,101,115,116,105,115,104,113,105,112,115,117,111,109,105, 115,111,98,114,101,100,101,115,100,101,101,110,116,114,101,116,111,100,111,115, 112,117,101,100,101,97,195,177,111,115,101,115,116,195,161,116,105,101,110,101, 104,97,115,116,97,111,116,114,111,115,112,97,114,116,101,100,111,110,100,101,110 ,117,101,118,111,104,97,99,101,114,102,111,114,109,97,109,105,115,109,111,109, 101,106,111,114,109,117,110,100,111,97,113,117,195,173,100,195,173,97,115,115, 195,179,108,111,97,121,117,100,97,102,101,99,104,97,116,111,100,97,115,116,97, 110,116,111,109,101,110,111,115,100,97,116,111,115,111,116,114,97,115,115,105, 116,105,111,109,117,99,104,111,97,104,111,114,97,108,117,103,97,114,109,97,121, 111,114,101,115,116,111,115,104,111,114,97,115,116,101,110,101,114,97,110,116, 101,115,102,111,116,111,115,101,115,116,97,115,112,97,195,173,115,110,117,101, 118,97,115,97,108,117,100,102,111,114,111,115,109,101,100,105,111,113,117,105, 101,110,109,101,115,101,115,112,111,100,101,114,99,104,105,108,101,115,101,114, 195,161,118,101,99,101,115,100,101,99,105,114,106,111,115,195,169,101,115,116,97 ,114,118,101,110,116,97,103,114,117,112,111,104,101,99,104,111,101,108,108,111, 115,116,101,110,103,111,97,109,105,103,111,99,111,115,97,115,110,105,118,101,108 ,103,101,110,116,101,109,105,115,109,97,97,105,114,101,115,106,117,108,105,111, 116,101,109,97,115,104,97,99,105,97,102,97,118,111,114,106,117,110,105,111,108, 105,98,114,101,112,117,110,116,111,98,117,101,110,111,97,117,116,111,114,97,98, 114,105,108,98,117,101,110,97,116,101,120,116,111,109,97,114,122,111,115,97,98, 101,114,108,105,115,116,97,108,117,101,103,111,99,195,179,109,111,101,110,101, 114,111,106,117,101,103,111,112,101,114,195,186,104,97,98,101,114,101,115,116, 111,121,110,117,110,99,97,109,117,106,101,114,118,97,108,111,114,102,117,101,114 ,97,108,105,98,114,111,103,117,115,116,97,105,103,117,97,108,118,111,116,111,115 ,99,97,115,111,115,103,117,195,173,97,112,117,101,100,111,115,111,109,111,115,97 ,118,105,115,111,117,115,116,101,100,100,101,98,101,110,110,111,99,104,101,98, 117,115,99,97,102,97,108,116,97,101,117,114,111,115,115,101,114,105,101,100,105, 99,104,111,99,117,114,115,111,99,108,97,118,101,99,97,115,97,115,108,101,195,179 ,110,112,108,97,122,111,108,97,114,103,111,111,98,114,97,115,118,105,115,116,97, 97,112,111,121,111,106,117,110,116,111,116,114,97,116,97,118,105,115,116,111,99, 114,101,97,114,99,97,109,112,111,104,101,109,111,115,99,105,110,99,111,99,97,114 ,103,111,112,105,115,111,115,111,114,100,101,110,104,97,99,101,110,195,161,114, 101,97,100,105,115,99,111,112,101,100,114,111,99,101,114,99,97,112,117,101,100, 97,112,97,112,101,108,109,101,110,111,114,195,186,116,105,108,99,108,97,114,111, 106,111,114,103,101,99,97,108,108,101,112,111,110,101,114,116,97,114,100,101,110 ,97,100,105,101,109,97,114,99,97,115,105,103,117,101,101,108,108,97,115,115,105, 103,108,111,99,111,99,104,101,109,111,116,111,115,109,97,100,114,101,99,108,97, 115,101,114,101,115,116,111,110,105,195,177,111,113,117,101,100,97,112,97,115,97 ,114,98,97,110,99,111,104,105,106,111,115,118,105,97,106,101,112,97,98,108,111, 195,169,115,116,101,118,105,101,110,101,114,101,105,110,111,100,101,106,97,114, 102,111,110,100,111,99,97,110,97,108,110,111,114,116,101,108,101,116,114,97,99, 97,117,115,97,116,111,109,97,114,109,97,110,111,115,108,117,110,101,115,97,117, 116,111,115,118,105,108,108,97,118,101,110,100,111,112,101,115,97,114,116,105, 112,111,115,116,101,110,103,97,109,97,114,99,111,108,108,101,118,97,112,97,100, 114,101,117,110,105,100,111,118,97,109,111,115,122,111,110,97,115,97,109,98,111, 115,98,97,110,100,97,109,97,114,105,97,97,98,117,115,111,109,117,99,104,97,115, 117,98,105,114,114,105,111,106,97,118,105,118,105,114,103,114,97,100,111,99,104, 105,99,97,97,108,108,195,173,106,111,118,101,110,100,105,99,104,97,101,115,116, 97,110,116,97,108,101,115,115,97,108,105,114,115,117,101,108,111,112,101,115,111 ,115,102,105,110,101,115,108,108,97,109,97,98,117,115,99,111,195,169,115,116,97, 108,108,101,103,97,110,101,103,114,111,112,108,97,122,97,104,117,109,111,114,112 ,97,103,97,114,106,117,110,116,97,100,111,98,108,101,105,115,108,97,115,98,111, 108,115,97,98,97,195,177,111,104,97,98,108,97,108,117,99,104,97,195,129,114,101, 97,100,105,99,101,110,106,117,103,97,114,110,111,116,97,115,118,97,108,108,101, 97,108,108,195,161,99,97,114,103,97,100,111,108,111,114,97,98,97,106,111,101,115 ,116,195,169,103,117,115,116,111,109,101,110,116,101,109,97,114,105,111,102,105, 114,109,97,99,111,115,116,111,102,105,99,104,97,112,108,97,116,97,104,111,103,97 ,114,97,114,116,101,115,108,101,121,101,115,97,113,117,101,108,109,117,115,101, 111,98,97,115,101,115,112,111,99,111,115,109,105,116,97,100,99,105,101,108,111, 99,104,105,99,111,109,105,101,100,111,103,97,110,97,114,115,97,110,116,111,101, 116,97,112,97,100,101,98,101,115,112,108,97,121,97,114,101,100,101,115,115,105, 101,116,101,99,111,114,116,101,99,111,114,101,97,100,117,100,97,115,100,101,115, 101,111,118,105,101,106,111,100,101,115,101,97,97,103,117,97,115,38,113,117,111, 116,59,100,111,109,97,105,110,99,111,109,109,111,110,115,116,97,116,117,115,101, 118,101,110,116,115,109,97,115,116,101,114,115,121,115,116,101,109,97,99,116,105 ,111,110,98,97,110,110,101,114,114,101,109,111,118,101,115,99,114,111,108,108, 117,112,100,97,116,101,103,108,111,98,97,108,109,101,100,105,117,109,102,105,108 ,116,101,114,110,117,109,98,101,114,99,104,97,110,103,101,114,101,115,117,108, 116,112,117,98,108,105,99,115,99,114,101,101,110,99,104,111,111,115,101,110,111, 114,109,97,108,116,114,97,118,101,108,105,115,115,117,101,115,115,111,117,114,99 ,101,116,97,114,103,101,116,115,112,114,105,110,103,109,111,100,117,108,101,109, 111,98,105,108,101,115,119,105,116,99,104,112,104,111,116,111,115,98,111,114,100 ,101,114,114,101,103,105,111,110,105,116,115,101,108,102,115,111,99,105,97,108, 97,99,116,105,118,101,99,111,108,117,109,110,114,101,99,111,114,100,102,111,108, 108,111,119,116,105,116,108,101,62,101,105,116,104,101,114,108,101,110,103,116, 104,102,97,109,105,108,121,102,114,105,101,110,100,108,97,121,111,117,116,97,117 ,116,104,111,114,99,114,101,97,116,101,114,101,118,105,101,119,115,117,109,109, 101,114,115,101,114,118,101,114,112,108,97,121,101,100,112,108,97,121,101,114, 101,120,112,97,110,100,112,111,108,105,99,121,102,111,114,109,97,116,100,111,117 ,98,108,101,112,111,105,110,116,115,115,101,114,105,101,115,112,101,114,115,111, 110,108,105,118,105,110,103,100,101,115,105,103,110,109,111,110,116,104,115,102, 111,114,99,101,115,117,110,105,113,117,101,119,101,105,103,104,116,112,101,111, 112,108,101,101,110,101,114,103,121,110,97,116,117,114,101,115,101,97,114,99,104 ,102,105,103,117,114,101,104,97,118,105,110,103,99,117,115,116,111,109,111,102, 102,115,101,116,108,101,116,116,101,114,119,105,110,100,111,119,115,117,98,109, 105,116,114,101,110,100,101,114,103,114,111,117,112,115,117,112,108,111,97,100, 104,101,97,108,116,104,109,101,116,104,111,100,118,105,100,101,111,115,115,99, 104,111,111,108,102,117,116,117,114,101,115,104,97,100,111,119,100,101,98,97,116 ,101,118,97,108,117,101,115,79,98,106,101,99,116,111,116,104,101,114,115,114,105 ,103,104,116,115,108,101,97,103,117,101,99,104,114,111,109,101,115,105,109,112, 108,101,110,111,116,105,99,101,115,104,97,114,101,100,101,110,100,105,110,103, 115,101,97,115,111,110,114,101,112,111,114,116,111,110,108,105,110,101,115,113, 117,97,114,101,98,117,116,116,111,110,105,109,97,103,101,115,101,110,97,98,108, 101,109,111,118,105,110,103,108,97,116,101,115,116,119,105,110,116,101,114,70, 114,97,110,99,101,112,101,114,105,111,100,115,116,114,111,110,103,114,101,112, 101,97,116,76,111,110,100,111,110,100,101,116,97,105,108,102,111,114,109,101,100 ,100,101,109,97,110,100,115,101,99,117,114,101,112,97,115,115,101,100,116,111, 103,103,108,101,112,108,97,99,101,115,100,101,118,105,99,101,115,116,97,116,105, 99,99,105,116,105,101,115,115,116,114,101,97,109,121,101,108,108,111,119,97,116, 116,97,99,107,115,116,114,101,101,116,102,108,105,103,104,116,104,105,100,100, 101,110,105,110,102,111,34,62,111,112,101,110,101,100,117,115,101,102,117,108, 118,97,108,108,101,121,99,97,117,115,101,115,108,101,97,100,101,114,115,101,99, 114,101,116,115,101,99,111,110,100,100,97,109,97,103,101,115,112,111,114,116,115 ,101,120,99,101,112,116,114,97,116,105,110,103,115,105,103,110,101,100,116,104, 105,110,103,115,101,102,102,101,99,116,102,105,101,108,100,115,115,116,97,116, 101,115,111,102,102,105,99,101,118,105,115,117,97,108,101,100,105,116,111,114, 118,111,108,117,109,101,82,101,112,111,114,116,109,117,115,101,117,109,109,111, 118,105,101,115,112,97,114,101,110,116,97,99,99,101,115,115,109,111,115,116,108, 121,109,111,116,104,101,114,34,32,105,100,61,34,109,97,114,107,101,116,103,114, 111,117,110,100,99,104,97,110,99,101,115,117,114,118,101,121,98,101,102,111,114, 101,115,121,109,98,111,108,109,111,109,101,110,116,115,112,101,101,99,104,109, 111,116,105,111,110,105,110,115,105,100,101,109,97,116,116,101,114,67,101,110, 116,101,114,111,98,106,101,99,116,101,120,105,115,116,115,109,105,100,100,108, 101,69,117,114,111,112,101,103,114,111,119,116,104,108,101,103,97,99,121,109,97, 110,110,101,114,101,110,111,117,103,104,99,97,114,101,101,114,97,110,115,119,101 ,114,111,114,105,103,105,110,112,111,114,116,97,108,99,108,105,101,110,116,115, 101,108,101,99,116,114,97,110,100,111,109,99,108,111,115,101,100,116,111,112,105 ,99,115,99,111,109,105,110,103,102,97,116,104,101,114,111,112,116,105,111,110, 115,105,109,112,108,121,114,97,105,115,101,100,101,115,99,97,112,101,99,104,111, 115,101,110,99,104,117,114,99,104,100,101,102,105,110,101,114,101,97,115,111,110 ,99,111,114,110,101,114,111,117,116,112,117,116,109,101,109,111,114,121,105,102, 114,97,109,101,112,111,108,105,99,101,109,111,100,101,108,115,78,117,109,98,101, 114,100,117,114,105,110,103,111,102,102,101,114,115,115,116,121,108,101,115,107, 105,108,108,101,100,108,105,115,116,101,100,99,97,108,108,101,100,115,105,108, 118,101,114,109,97,114,103,105,110,100,101,108,101,116,101,98,101,116,116,101, 114,98,114,111,119,115,101,108,105,109,105,116,115,71,108,111,98,97,108,115,105, 110,103,108,101,119,105,100,103,101,116,99,101,110,116,101,114,98,117,100,103, 101,116,110,111,119,114,97,112,99,114,101,100,105,116,99,108,97,105,109,115,101, 110,103,105,110,101,115,97,102,101,116,121,99,104,111,105,99,101,115,112,105,114 ,105,116,45,115,116,121,108,101,115,112,114,101,97,100,109,97,107,105,110,103, 110,101,101,100,101,100,114,117,115,115,105,97,112,108,101,97,115,101,101,120, 116,101,110,116,83,99,114,105,112,116,98,114,111,107,101,110,97,108,108,111,119, 115,99,104,97,114,103,101,100,105,118,105,100,101,102,97,99,116,111,114,109,101, 109,98,101,114,45,98,97,115,101,100,116,104,101,111,114,121,99,111,110,102,105, 103,97,114,111,117,110,100,119,111,114,107,101,100,104,101,108,112,101,100,67, 104,117,114,99,104,105,109,112,97,99,116,115,104,111,117,108,100,97,108,119,97, 121,115,108,111,103,111,34,32,98,111,116,116,111,109,108,105,115,116,34,62,41, 123,118,97,114,32,112,114,101,102,105,120,111,114,97,110,103,101,72,101,97,100, 101,114,46,112,117,115,104,40,99,111,117,112,108,101,103,97,114,100,101,110,98, 114,105,100,103,101,108,97,117,110,99,104,82,101,118,105,101,119,116,97,107,105, 110,103,118,105,115,105,111,110,108,105,116,116,108,101,100,97,116,105,110,103, 66,117,116,116,111,110,98,101,97,117,116,121,116,104,101,109,101,115,102,111,114 ,103,111,116,83,101,97,114,99,104,97,110,99,104,111,114,97,108,109,111,115,116, 108,111,97,100,101,100,67,104,97,110,103,101,114,101,116,117,114,110,115,116,114 ,105,110,103,114,101,108,111,97,100,77,111,98,105,108,101,105,110,99,111,109,101 ,115,117,112,112,108,121,83,111,117,114,99,101,111,114,100,101,114,115,118,105, 101,119,101,100,38,110,98,115,112,59,99,111,117,114,115,101,65,98,111,117,116,32 ,105,115,108,97,110,100,60,104,116,109,108,32,99,111,111,107,105,101,110,97,109, 101,61,34,97,109,97,122,111,110,109,111,100,101,114,110,97,100,118,105,99,101, 105,110,60,47,97,62,58,32,84,104,101,32,100,105,97,108,111,103,104,111,117,115, 101,115,66,69,71,73,78,32,77,101,120,105,99,111,115,116,97,114,116,115,99,101, 110,116,114,101,104,101,105,103,104,116,97,100,100,105,110,103,73,115,108,97,110 ,100,97,115,115,101,116,115,69,109,112,105,114,101,83,99,104,111,111,108,101,102 ,102,111,114,116,100,105,114,101,99,116,110,101,97,114,108,121,109,97,110,117,97 ,108,83,101,108,101,99,116,46,10,10,79,110,101,106,111,105,110,101,100,109,101, 110,117,34,62,80,104,105,108,105,112,97,119,97,114,100,115,104,97,110,100,108, 101,105,109,112,111,114,116,79,102,102,105,99,101,114,101,103,97,114,100,115,107 ,105,108,108,115,110,97,116,105,111,110,83,112,111,114,116,115,100,101,103,114, 101,101,119,101,101,107,108,121,32,40,101,46,103,46,98,101,104,105,110,100,100, 111,99,116,111,114,108,111,103,103,101,100,117,110,105,116,101,100,60,47,98,62, 60,47,98,101,103,105,110,115,112,108,97,110,116,115,97,115,115,105,115,116,97, 114,116,105,115,116,105,115,115,117,101,100,51,48,48,112,120,124,99,97,110,97, 100,97,97,103,101,110,99,121,115,99,104,101,109,101,114,101,109,97,105,110,66, 114,97,122,105,108,115,97,109,112,108,101,108,111,103,111,34,62,98,101,121,111, 110,100,45,115,99,97,108,101,97,99,99,101,112,116,115,101,114,118,101,100,109,97 ,114,105,110,101,70,111,111,116,101,114,99,97,109,101,114,97,60,47,104,49,62,10, 95,102,111,114,109,34,108,101,97,118,101,115,115,116,114,101,115,115,34,32,47,62 ,13,10,46,103,105,102,34,32,111,110,108,111,97,100,108,111,97,100,101,114,79,120 ,102,111,114,100,115,105,115,116,101,114,115,117,114,118,105,118,108,105,115,116 ,101,110,102,101,109,97,108,101,68,101,115,105,103,110,115,105,122,101,61,34,97, 112,112,101,97,108,116,101,120,116,34,62,108,101,118,101,108,115,116,104,97,110, 107,115,104,105,103,104,101,114,102,111,114,99,101,100,97,110,105,109,97,108,97, 110,121,111,110,101,65,102,114,105,99,97,97,103,114,101,101,100,114,101,99,101, 110,116,80,101,111,112,108,101,60,98,114,32,47,62,119,111,110,100,101,114,112, 114,105,99,101,115,116,117,114,110,101,100,124,124,32,123,125,59,109,97,105,110, 34,62,105,110,108,105,110,101,115,117,110,100,97,121,119,114,97,112,34,62,102,97 ,105,108,101,100,99,101,110,115,117,115,109,105,110,117,116,101,98,101,97,99,111 ,110,113,117,111,116,101,115,49,53,48,112,120,124,101,115,116,97,116,101,114,101 ,109,111,116,101,101,109,97,105,108,34,108,105,110,107,101,100,114,105,103,104, 116,59,115,105,103,110,97,108,102,111,114,109,97,108,49,46,104,116,109,108,115, 105,103,110,117,112,112,114,105,110,99,101,102,108,111,97,116,58,46,112,110,103, 34,32,102,111,114,117,109,46,65,99,99,101,115,115,112,97,112,101,114,115,115,111 ,117,110,100,115,101,120,116,101,110,100,72,101,105,103,104,116,115,108,105,100, 101,114,85,84,70,45,56,34,38,97,109,112,59,32,66,101,102,111,114,101,46,32,87, 105,116,104,115,116,117,100,105,111,111,119,110,101,114,115,109,97,110,97,103, 101,112,114,111,102,105,116,106,81,117,101,114,121,97,110,110,117,97,108,112,97, 114,97,109,115,98,111,117,103,104,116,102,97,109,111,117,115,103,111,111,103,108 ,101,108,111,110,103,101,114,105,43,43,41,32,123,105,115,114,97,101,108,115,97, 121,105,110,103,100,101,99,105,100,101,104,111,109,101,34,62,104,101,97,100,101, 114,101,110,115,117,114,101,98,114,97,110,99,104,112,105,101,99,101,115,98,108, 111,99,107,59,115,116,97,116,101,100,116,111,112,34,62,60,114,97,99,105,110,103, 114,101,115,105,122,101,45,45,38,103,116,59,112,97,99,105,116,121,115,101,120, 117,97,108,98,117,114,101,97,117,46,106,112,103,34,32,49,48,44,48,48,48,111,98, 116,97,105,110,116,105,116,108,101,115,97,109,111,117,110,116,44,32,73,110,99,46 ,99,111,109,101,100,121,109,101,110,117,34,32,108,121,114,105,99,115,116,111,100 ,97,121,46,105,110,100,101,101,100,99,111,117,110,116,121,95,108,111,103,111,46, 70,97,109,105,108,121,108,111,111,107,101,100,77,97,114,107,101,116,108,115,101, 32,105,102,80,108,97,121,101,114,116,117,114,107,101,121,41,59,118,97,114,32,102 ,111,114,101,115,116,103,105,118,105,110,103,101,114,114,111,114,115,68,111,109, 97,105,110,125,101,108,115,101,123,105,110,115,101,114,116,66,108,111,103,60,47, 102,111,111,116,101,114,108,111,103,105,110,46,102,97,115,116,101,114,97,103,101 ,110,116,115,60,98,111,100,121,32,49,48,112,120,32,48,112,114,97,103,109,97,102, 114,105,100,97,121,106,117,110,105,111,114,100,111,108,108,97,114,112,108,97,99, 101,100,99,111,118,101,114,115,112,108,117,103,105,110,53,44,48,48,48,32,112,97, 103,101,34,62,98,111,115,116,111,110,46,116,101,115,116,40,97,118,97,116,97,114, 116,101,115,116,101,100,95,99,111,117,110,116,102,111,114,117,109,115,115,99,104 ,101,109,97,105,110,100,101,120,44,102,105,108,108,101,100,115,104,97,114,101, 115,114,101,97,100,101,114,97,108,101,114,116,40,97,112,112,101,97,114,83,117,98 ,109,105,116,108,105,110,101,34,62,98,111,100,121,34,62,10,42,32,84,104,101,84, 104,111,117,103,104,115,101,101,105,110,103,106,101,114,115,101,121,78,101,119, 115,60,47,118,101,114,105,102,121,101,120,112,101,114,116,105,110,106,117,114, 121,119,105,100,116,104,61,67,111,111,107,105,101,83,84,65,82,84,32,97,99,114, 111,115,115,95,105,109,97,103,101,116,104,114,101,97,100,110,97,116,105,118,101, 112,111,99,107,101,116,98,111,120,34,62,10,83,121,115,116,101,109,32,68,97,118, 105,100,99,97,110,99,101,114,116,97,98,108,101,115,112,114,111,118,101,100,65, 112,114,105,108,32,114,101,97,108,108,121,100,114,105,118,101,114,105,116,101, 109,34,62,109,111,114,101,34,62,98,111,97,114,100,115,99,111,108,111,114,115,99, 97,109,112,117,115,102,105,114,115,116,32,124,124,32,91,93,59,109,101,100,105,97 ,46,103,117,105,116,97,114,102,105,110,105,115,104,119,105,100,116,104,58,115, 104,111,119,101,100,79,116,104,101,114,32,46,112,104,112,34,32,97,115,115,117, 109,101,108,97,121,101,114,115,119,105,108,115,111,110,115,116,111,114,101,115, 114,101,108,105,101,102,115,119,101,100,101,110,67,117,115,116,111,109,101,97, 115,105,108,121,32,121,111,117,114,32,83,116,114,105,110,103,10,10,87,104,105, 108,116,97,121,108,111,114,99,108,101,97,114,58,114,101,115,111,114,116,102,114, 101,110,99,104,116,104,111,117,103,104,34,41,32,43,32,34,60,98,111,100,121,62,98 ,117,121,105,110,103,98,114,97,110,100,115,77,101,109,98,101,114,110,97,109,101, 34,62,111,112,112,105,110,103,115,101,99,116,111,114,53,112,120,59,34,62,118,115 ,112,97,99,101,112,111,115,116,101,114,109,97,106,111,114,32,99,111,102,102,101, 101,109,97,114,116,105,110,109,97,116,117,114,101,104,97,112,112,101,110,60,47, 110,97,118,62,107,97,110,115,97,115,108,105,110,107,34,62,73,109,97,103,101,115, 61,102,97,108,115,101,119,104,105,108,101,32,104,115,112,97,99,101,48,38,97,109, 112,59,32,10,10,73,110,32,32,112,111,119,101,114,80,111,108,115,107,105,45,99, 111,108,111,114,106,111,114,100,97,110,66,111,116,116,111,109,83,116,97,114,116, 32,45,99,111,117,110,116,50,46,104,116,109,108,110,101,119,115,34,62,48,49,46, 106,112,103,79,110,108,105,110,101,45,114,105,103,104,116,109,105,108,108,101, 114,115,101,110,105,111,114,73,83,66,78,32,48,48,44,48,48,48,32,103,117,105,100, 101,115,118,97,108,117,101,41,101,99,116,105,111,110,114,101,112,97,105,114,46, 120,109,108,34,32,32,114,105,103,104,116,115,46,104,116,109,108,45,98,108,111,99 ,107,114,101,103,69,120,112,58,104,111,118,101,114,119,105,116,104,105,110,118, 105,114,103,105,110,112,104,111,110,101,115,60,47,116,114,62,13,117,115,105,110, 103,32,10,9,118,97,114,32,62,39,41,59,10,9,60,47,116,100,62,10,60,47,116,114,62, 10,98,97,104,97,115,97,98,114,97,115,105,108,103,97,108,101,103,111,109,97,103, 121,97,114,112,111,108,115,107,105,115,114,112,115,107,105,216,177,216,175,217, 136,228,184,173,230,150,135,231,174,128,228,189,147,231,185,129,233,171,148,228, 191,161,230,129,175,228,184,173,229,155,189,230,136,145,228,187,172,228,184,128, 228,184,170,229,133,172,229,143,184,231,174,161,231,144,134,232,174,186,229,157, 155,229,143,175,228,187,165,230,156,141,229,138,161,230,151,182,233,151,180,228, 184,170,228,186,186,228,186,167,229,147,129,232,135,170,229,183,177,228,188,129, 228,184,154,230,159,165,231,156,139,229,183,165,228,189,156,232,129,148,231,179, 187,230,178,161,230,156,137,231,189,145,231,171,153,230,137,128,230,156,137,232, 175,132,232,174,186,228,184,173,229,191,131,230,150,135,231,171,160,231,148,168, 230,136,183,233,166,150,233,161,181,228,189,156,232,128,133,230,138,128,230,156, 175,233,151,174,233,162,152,231,155,184,229,133,179,228,184,139,232,189,189,230, 144,156,231,180,162,228,189,191,231,148,168,232,189,175,228,187,182,229,156,168, 231,186,191,228,184,187,233,162,152,232,181,132,230,150,153,232,167,134,233,162, 145,229,155,158,229,164,141,230,179,168,229,134,140,231,189,145,231,187,156,230, 148,182,232,151,143,229,134,133,229,174,185,230,142,168,232,141,144,229,184,130, 229,156,186,230,182,136,230,129,175,231,169,186,233,151,180,229,143,145,229,184, 131,228,187,128,228,185,136,229,165,189,229,143,139,231,148,159,230,180,187,229, 155,190,231,137,135,229,143,145,229,177,149,229,166,130,230,158,156,230,137,139, 230,156,186,230,150,176,233,151,187,230,156,128,230,150,176,230,150,185,229,188, 143,229,140,151,228,186,172,230,143,144,228,190,155,229,133,179,228,186,142,230, 155,180,229,164,154,232,191,153,228,184,170,231,179,187,231,187,159,231,159,165, 233,129,147,230,184,184,230,136,143,229,185,191,229,145,138,229,133,182,228,187, 150,229,143,145,232,161,168,229,174,137,229,133,168,231,172,172,228,184,128,228, 188,154,229,145,152,232,191,155,232,161,140,231,130,185,229,135,187,231,137,136, 230,157,131,231,148,181,229,173,144,228,184,150,231,149,140,232,174,190,232,174, 161,229,133,141,232,180,185,230,149,153,232,130,178,229,138,160,229,133,165,230, 180,187,229,138,168,228,187,150,228,187,172,229,149,134,229,147,129,229,141,154, 229,174,162,231,142,176,229,156,168,228,184,138,230,181,183,229,166,130,228,189, 149,229,183,178,231,187,143,231,149,153,232,168,128,232,175,166,231,187,134,231, 164,190,229,140,186,231,153,187,229,189,149,230,156,172,231,171,153,233,156,128, 232,166,129,228,187,183,230,160,188,230,148,175,230,140,129,229,155,189,233,153, 133,233,147,190,230,142,165,229,155,189,229,174,182,229,187,186,232,174,190,230, 156,139,229,143,139,233,152,133,232,175,187,230,179,149,229,190,139,228,189,141, 231,189,174,231,187,143,230,181,142,233,128,137,230,139,169,232,191,153,230,160, 183,229,189,147,229,137,141,229,136,134,231,177,187,230,142,146,232,161,140,229, 155,160,228,184,186,228,186,164,230,152,147,230,156,128,229,144,142,233,159,179, 228,185,144,228,184,141,232,131,189,233,128,154,232,191,135,232,161,140,228,184, 154,231,167,145,230,138,128,229,143,175,232,131,189,232,174,190,229,164,135,229, 144,136,228,189,156,229,164,167,229,174,182,231,164,190,228,188,154,231,160,148, 231,169,182,228,184,147,228,184,154,229,133,168,233,131,168,233,161,185,231,155, 174,232,191,153,233,135,140,232,191,152,230,152,175,229,188,128,229,167,139,230, 131,133,229,134,181,231,148,181,232,132,145,230,150,135,228,187,182,229,147,129, 231,137,140,229,184,174,229,138,169,230,150,135,229,140,150,232,181,132,230,186, 144,229,164,167,229,173,166,229,173,166,228,185,160,229,156,176,229,157,128,230, 181,143,232,167,136,230,138,149,232,181,132,229,183,165,231,168,139,232,166,129, 230,177,130,230,128,142,228,185,136,230,151,182,229,128,153,229,138,159,232,131, 189,228,184,187,232,166,129,231,155,174,229,137,141,232,181,132,232,174,175,229, 159,142,229,184,130,230,150,185,230,179,149,231,148,181,229,189,177,230,139,155, 232,129,152,229,163,176,230,152,142,228,187,187,228,189,149,229,129,165,229,186, 183,230,149,176,230,141,174,231,190,142,229,155,189,230,177,189,232,189,166,228, 187,139,231,187,141,228,189,134,230,152,175,228,186,164,230,181,129,231,148,159, 228,186,167,230,137,128,228,187,165,231,148,181,232,175,157,230,152,190,231,164, 186,228,184,128,228,186,155,229,141,149,228,189,141,228,186,186,229,145,152,229, 136,134,230,158,144,229,156,176,229,155,190,230,151,133,230,184,184,229,183,165, 229,133,183,229,173,166,231,148,159,231,179,187,229,136,151,231,189,145,229,143, 139,229,184,150,229,173,144,229,175,134,231,160,129,233,162,145,233,129,147,230, 142,167,229,136,182,229,156,176,229,140,186,229,159,186,230,156,172,229,133,168, 229,155,189,231,189,145,228,184,138,233,135,141,232,166,129,231,172,172,228,186, 140,229,150,156,230,172,162,232,191,155,229,133,165,229,143,139,230,131,133,232, 191,153,228,186,155,232,128,131,232,175,149,229,143,145,231,142,176,229,159,185, 232,174,173,228,187,165,228,184,138,230,148,191,229,186,156,230,136,144,228,184, 186,231,142,175,229,162,131,233,166,153,230,184,175,229,144,140,230,151,182,229, 168,177,228,185,144,229,143,145,233,128,129,228,184,128,229,174,154,229,188,128, 229,143,145,228,189,156,229,147,129,230,160,135,229,135,134,230,172,162,232,191, 142,232,167,163,229,134,179,229,156,176,230,150,185,228,184,128,228,184,139,228, 187,165,229,143,138,232,180,163,228,187,187,230,136,150,232,128,133,229,174,162, 230,136,183,228,187,163,232,161,168,231,167,175,229,136,134,229,165,179,228,186, 186,230,149,176,231,160,129,233,148,128,229,148,174,229,135,186,231,142,176,231, 166,187,231,186,191,229,186,148,231,148,168,229,136,151,232,161,168,228,184,141, 229,144,140,231,188,150,232,190,145,231,187,159,232,174,161,230,159,165,232,175, 162,228,184,141,232,166,129,230,156,137,229,133,179,230,156,186,230,158,132,229, 190,136,229,164,154,230,146,173,230,148,190,231,187,132,231,187,135,230,148,191, 231,173,150,231,155,180,230,142,165,232,131,189,229,138,155,230,157,165,230,186, 144,230,153,130,233,150,147,231,156,139,229,136,176,231,131,173,233,151,168,229, 133,179,233,148,174,228,184,147,229,140,186,233,157,158,229,184,184,232,139,177, 232,175,173,231,153,190,229,186,166,229,184,140,230,156,155,231,190,142,229,165, 179,230,175,148,232,190,131,231,159,165,232,175,134,232,167,132,229,174,154,229, 187,186,232,174,174,233,131,168,233,151,168,230,132,143,232,167,129,231,178,190, 229,189,169,230,151,165,230,156,172,230,143,144,233,171,152,229,143,145,232,168, 128,230,150,185,233,157,162,229,159,186,233,135,145,229,164,132,231,144,134,230, 157,131,233,153,144,229,189,177,231,137,135,233,147,182,232,161,140,232,191,152, 230,156,137,229,136,134,228,186,171,231,137,169,229,147,129,231,187,143,232,144, 165,230,183,187,229,138,160,228,184,147,229,174,182,232,191,153,231,167,141,232, 175,157,233,162,152,232,181,183,230,157,165,228,184,154,229,138,161,229,133,172, 229,145,138,232,174,176,229,189,149,231,174,128,228,187,139,232,180,168,233,135, 143,231,148,183,228,186,186,229,189,177,229,147,141,229,188,149,231,148,168,230, 138,165,229,145,138,233,131,168,229,136,134,229,191,171,233,128,159,229,146,168, 232,175,162,230,151,182,229,176,154,230,179,168,230,132,143,231,148,179,232,175, 183,229,173,166,230,160,161,229,186,148,232,175,165,229,142,134,229,143,178,229, 143,170,230,152,175,232,191,148,229,155,158,232,180,173,228,185,176,229,144,141, 231,167,176,228,184,186,228,186,134,230,136,144,229,138,159,232,175,180,230,152, 142,228,190,155,229,186,148,229,173,169,229,173,144,228,184,147,233,162,152,231, 168,139,229,186,143,228,184,128,232,136,172,230,156,131,229,147,161,229,143,170, 230,156,137,229,133,182,229,174,131,228,191,157,230,138,164,232,128,140,228,184, 148,228,187,138,229,164,169,231,170,151,229,143,163,229,138,168,230,128,129,231, 138,182,230,128,129,231,137,185,229,136,171,232,174,164,228,184,186,229,191,133, 233,161,187,230,155,180,230,150,176,229,176,143,232,175,180,230,136,145,229,128, 145,228,189,156,228,184,186,229,170,146,228,189,147,229,140,133,230,139,172,233, 130,163,228,185,136,228,184,128,230,160,183,229,155,189,229,134,133,230,152,175, 229,144,166,230,160,185,230,141,174,231,148,181,232,167,134,229,173,166,233,153, 162,229,133,183,230,156,137,232,191,135,231,168,139,231,148,177,228,186,142,228, 186,186,230,137,141,229,135,186,230,157,165,228,184,141,232,191,135,230,173,163, 229,156,168,230,152,142,230,152,159,230,149,133,228,186,139,229,133,179,231,179, 187,230,160,135,233,162,152,229,149,134,229,138,161,232,190,147,229,133,165,228, 184,128,231,155,180,229,159,186,231,161,128,230,149,153,229,173,166,228,186,134, 232,167,163,229,187,186,231,173,145,231,187,147,230,158,156,229,133,168,231,144, 131,233,128,154,231,159,165,232,174,161,229,136,146,229,175,185,228,186,142,232, 137,186,230,156,175,231,155,184,229,134,140,229,143,145,231,148,159,231,156,159, 231,154,132,229,187,186,231,171,139,231,173,137,231,186,167,231,177,187,229,158, 139,231,187,143,233,170,140,229,174,158,231,142,176,229,136,182,228,189,156,230, 157,165,232,135,170,230,160,135,231,173,190,228,187,165,228,184,139,229,142,159, 229,136,155,230,151,160,230,179,149,229,133,182,228,184,173,229,128,139,228,186, 186,228,184,128,229,136,135,230,140,135,229,141,151,229,133,179,233,151,173,233, 155,134,229,155,162,231,172,172,228,184,137,229,133,179,230,179,168,229,155,160, 230,173,164,231,133,167,231,137,135,230,183,177,229,156,179,229,149,134,228,184, 154,229,185,191,229,183,158,230,151,165,230,156,159,233,171,152,231,186,167,230, 156,128,232,191,145,231,187,188,229,144,136,232,161,168,231,164,186,228,184,147, 232,190,145,232,161,140,228,184,186,228,186,164,233,128,154,232,175,132,228,187, 183,232,167,137,229,190,151,231,178,190,229,141,142,229,174,182,229,186,173,229, 174,140,230,136,144,230,132,159,232,167,137,229,174,137,232,163,133,229,190,151, 229,136,176,233,130,174,228,187,182,229,136,182,229,186,166,233,163,159,229,147, 129,232,153,189,231,132,182,232,189,172,232,189,189,230,138,165,228,187,183,232, 174,176,232,128,133,230,150,185,230,161,136,232,161,140,230,148,191,228,186,186, 230,176,145,231,148,168,229,147,129,228,184,156,232,165,191,230,143,144,229,135, 186,233,133,146,229,186,151,231,132,182,229,144,142,228,187,152,230,172,190,231, 131,173,231,130,185,228,187,165,229,137,141,229,174,140,229,133,168,229,143,145, 229,184,150,232,174,190,231,189,174,233,162,134,229,175,188,229,183,165,228,184, 154,229,140,187,233,153,162,231,156,139,231,156,139,231,187,143,229,133,184,229, 142,159,229,155,160,229,185,179,229,143,176,229,144,132,231,167,141,229,162,158, 229,138,160,230,157,144,230,150,153,230,150,176,229,162,158,228,185,139,229,144, 142,232,129,140,228,184,154,230,149,136,230,158,156,228,187,138,229,185,180,232, 174,186,230,150,135,230,136,145,229,155,189,229,145,138,232,175,137,231,137,136, 228,184,187,228,191,174,230,148,185,229,143,130,228,184,142,230,137,147,229,141, 176,229,191,171,228,185,144,230,156,186,230,162,176,232,167,130,231,130,185,229, 173,152,229,156,168,231,178,190,231,165,158,232,142,183,229,190,151,229,136,169, 231,148,168,231,187,167,231,187,173,228,189,160,228,187,172,232,191,153,228,185, 136,230,168,161,229,188,143,232,175,173,232,168,128,232,131,189,229,164,159,233, 155,133,232,153,142,230,147,141,228,189,156,233,163,142,230,160,188,228,184,128, 232,181,183,231,167,145,229,173,166,228,189,147,232,130,178,231,159,173,228,191, 161,230,157,161,228,187,182,230,178,187,231,150,151,232,191,144,229,138,168,228, 186,167,228,184,154,228,188,154,232,174,174,229,175,188,232,136,170,229,133,136, 231,148,159,232,129,148,231,155,159,229,143,175,230,152,175,229,149,143,233,161, 140,231,187,147,230,158,132,228,189,156,231,148,168,232,176,131,230,159,165,232, 179,135,230,150,153,232,135,170,229,138,168,232,180,159,232,180,163,229,134,156, 228,184,154,232,174,191,233,151,174,229,174,158,230,150,189,230,142,165,229,143, 151,232,174,168,232,174,186,233,130,163,228,184,170,229,143,141,233,166,136,229, 138,160,229,188,186,229,165,179,230,128,167,232,140,131,229,155,180,230,156,141, 229,139,153,228,188,145,233,151,178,228,187,138,230,151,165,229,174,162,230,156, 141,232,167,128,231,156,139,229,143,130,229,138,160,231,154,132,232,175,157,228, 184,128,231,130,185,228,191,157,232,175,129,229,155,190,228,185,166,230,156,137, 230,149,136,230,181,139,232,175,149,231,167,187,229,138,168,230,137,141,232,131, 189,229,134,179,229,174,154,232,130,161,231,165,168,228,184,141,230,150,173,233, 156,128,230,177,130,228,184,141,229,190,151,229,138,158,230,179,149,228,185,139, 233,151,180,233,135,135,231,148,168,232,144,165,233,148,128,230,138,149,232,175, 137,231,155,174,230,160,135,231,136,177,230,131,133,230,145,132,229,189,177,230, 156,137,228,186,155,232,164,135,232,163,189,230,150,135,229,173,166,230,156,186, 228,188,154,230,149,176,229,173,151,232,163,133,228,191,174,232,180,173,231,137, 169,229,134,156,230,157,145,229,133,168,233,157,162,231,178,190,229,147,129,229, 133,182,229,174,158,228,186,139,230,131,133,230,176,180,229,185,179,230,143,144, 231,164,186,228,184,138,229,184,130,232,176,162,232,176,162,230,153,174,233,128, 154,230,149,153,229,184,136,228,184,138,228,188,160,231,177,187,229,136,171,230, 173,140,230,155,178,230,139,165,230,156,137,229,136,155,230,150,176,233,133,141, 228,187,182,229,143,170,232,166,129,230,151,182,228,187,163,232,179,135,232,168, 138,232,190,190,229,136,176,228,186,186,231,148,159,232,174,162,233,152,133,232, 128,129,229,184,136,229,177,149,231,164,186,229,191,131,231,144,134,232,180,180, 229,173,144,231,182,178,231,171,153,228,184,187,233,161,140,232,135,170,231,132, 182,231,186,167,229,136,171,231,174,128,229,141,149,230,148,185,233,157,169,233, 130,163,228,186,155,230,157,165,232,175,180,230,137,147,229,188,128,228,187,163, 231,160,129,229,136,160,233,153,164,232,175,129,229,136,184,232,138,130,231,155, 174,233,135,141,231,130,185,230,172,161,230,149,184,229,164,154,229,176,145,232, 167,132,229,136,146,232,181,132,233,135,145,230,137,190,229,136,176,228,187,165, 229,144,142,229,164,167,229,133,168,228,184,187,233,161,181,230,156,128,228,189, 179,229,155,158,231,173,148,229,164,169,228,184,139,228,191,157,233,154,156,231, 142,176,228,187,163,230,163,128,230,159,165,230,138,149,231,165,168,229,176,143, 230,151,182,230,178,146,230,156,137,230,173,163,229,184,184,231,148,154,232,135, 179,228,187,163,231,144,134,231,155,174,229,189,149,229,133,172,229,188,128,229, 164,141,229,136,182,233,135,145,232,158,141,229,185,184,231,166,143,231,137,136, 230,156,172,229,189,162,230,136,144,229,135,134,229,164,135,232,161,140,230,131, 133,229,155,158,229,136,176,230,128,157,230,131,179,230,128,142,230,160,183,229, 141,143,232,174,174,232,174,164,232,175,129,230,156,128,229,165,189,228,186,167, 231,148,159,230,140,137,231,133,167,230,156,141,232,163,133,229,185,191,228,184, 156,229,138,168,230,188,171,233,135,135,232,180,173,230,150,176,230,137,139,231, 187,132,229,155,190,233,157,162,230,157,191,229,143,130,232,128,131,230,148,191, 230,178,187,229,174,185,230,152,147,229,164,169,229,156,176,229,138,170,229,138, 155,228,186,186,228,187,172,229,141,135,231,186,167,233,128,159,229,186,166,228, 186,186,231,137,169,232,176,131,230,149,180,230,181,129,232,161,140,233,128,160, 230,136,144,230,150,135,229,173,151,233,159,169,229,155,189,232,180,184,230,152, 147,229,188,128,229,177,149,231,155,184,233,151,156,232,161,168,231,142,176,229, 189,177,232,167,134,229,166,130,230,173,164,231,190,142,229,174,185,229,164,167, 229,176,143,230,138,165,233,129,147,230,157,161,230,172,190,229,191,131,230,131, 133,232,174,184,229,164,154,230,179,149,232,167,132,229,174,182,229,177,133,228, 185,166,229,186,151,232,191,158,230,142,165,231,171,139,229,141,179,228,184,190, 230,138,165,230,138,128,229,183,167,229,165,165,232,191,144,231,153,187,229,133, 165,228,187,165,230,157,165,231,144,134,232,174,186,228,186,139,228,187,182,232, 135,170,231,148,177,228,184,173,229,141,142,229,138,158,229,133,172,229,166,136, 229,166,136,231,156,159,230,173,163,228,184,141,233,148,153,229,133,168,230,150, 135,229,144,136,229,144,140,228,187,183,229,128,188,229,136,171,228,186,186,231, 155,145,231,157,163,229,133,183,228,189,147,228,184,150,231,186,170,229,155,162, 233,152,159,229,136,155,228,184,154,230,137,191,230,139,133,229,162,158,233,149, 191,230,156,137,228,186,186,228,191,157,230,140,129,229,149,134,229,174,182,231, 187,180,228,191,174,229,143,176,230,185,190,229,183,166,229,143,179,232,130,161, 228,187,189,231,173,148,230,161,136,229,174,158,233,153,133,231,148,181,228,191, 161,231,187,143,231,144,134,231,148,159,229,145,189,229,174,163,228,188,160,228, 187,187,229,138,161,230,173,163,229,188,143,231,137,185,232,137,178,228,184,139, 230,157,165,229,141,143,228,188,154,229,143,170,232,131,189,229,189,147,231,132, 182,233,135,141,230,150,176,229,133,167,229,174,185,230,140,135,229,175,188,232, 191,144,232,161,140,230,151,165,229,191,151,232,179,163,229,174,182,232,182,133, 232,191,135,229,156,159,229,156,176,230,181,153,230,177,159,230,148,175,228,187, 152,230,142,168,229,135,186,231,171,153,233,149,191,230,157,173,229,183,158,230, 137,167,232,161,140,229,136,182,233,128,160,228,185,139,228,184,128,230,142,168, 229,185,191,231,142,176,229,156,186,230,143,143,232,191,176,229,143,152,229,140, 150,228,188,160,231,187,159,230,173,140,230,137,139,228,191,157,233,153,169,232, 175,190,231,168,139,229,140,187,231,150,151,231,187,143,232,191,135,232,191,135, 229,142,187,228,185,139,229,137,141,230,148,182,229,133,165,229,185,180,229,186, 166,230,157,130,229,191,151,231,190,142,228,184,189,230,156,128,233,171,152,231, 153,187,233,153,134,230,156,170,230,157,165,229,138,160,229,183,165,229,133,141, 232,180,163,230,149,153,231,168,139,231,137,136,229,157,151,232,186,171,228,189, 147,233,135,141,229,186,134,229,135,186,229,148,174,230,136,144,230,156,172,229, 189,162,229,188,143,229,156,159,232,177,134,229,135,186,229,131,185,228,184,156, 230,150,185,233,130,174,231,174,177,229,141,151,228,186,172,230,177,130,232,129, 140,229,143,150,229,190,151,232,129,140,228,189,141,231,155,184,228,191,161,233, 161,181,233,157,162,229,136,134,233,146,159,231,189,145,233,161,181,231,161,174, 229,174,154,229,155,190,228,190,139,231,189,145,229,157,128,231,167,175,230,158, 129,233,148,153,232,175,175,231,155,174,231,154,132,229,174,157,232,180,157,230, 156,186,229,133,179,233,163,142,233,153,169,230,142,136,230,157,131,231,151,133, 230,175,146,229,174,160,231,137,169,233,153,164,228,186,134,232,169,149,232,171, 150,231,150,190,231,151,133,229,143,138,230,151,182,230,177,130,232,180,173,231, 171,153,231,130,185,229,132,191,231,171,165,230,175,143,229,164,169,228,184,173, 229,164,174,232,174,164,232,175,134,230,175,143,228,184,170,229,164,169,230,180, 165,229,173,151,228,189,147,229,143,176,231,129,163,231,187,180,230,138,164,230, 156,172,233,161,181,228,184,170,230,128,167,229,174,152,230,150,185,229,184,184, 232,167,129,231,155,184,230,156,186,230,136,152,231,149,165,229,186,148,229,189, 147,229,190,139,229,184,136,230,150,185,228,190,191,230,160,161,229,155,173,232, 130,161,229,184,130,230,136,191,229,177,139,230,160,143,231,155,174,229,145,152, 229,183,165,229,175,188,232,135,180,231,170,129,231,132,182,233,129,147,229,133, 183,230,156,172,231,189,145,231,187,147,229,144,136,230,161,163,230,161,136,229, 138,179,229,138,168,229,143,166,229,164,150,231,190,142,229,133,131,229,188,149, 232,181,183,230,148,185,229,143,152,231,172,172,229,155,155,228,188,154,232,174, 161,232,170,170,230,152,142,233,154,144,231,167,129,229,174,157,229,174,157,232, 167,132,232,140,131,230,182,136,232,180,185,229,133,177,229,144,140,229,191,152, 232,174,176,228,189,147,231,179,187,229,184,166,230,157,165,229,144,141,229,173, 151,231,153,188,232,161,168,229,188,128,230,148,190,229,138,160,231,155,159,229, 143,151,229,136,176,228,186,140,230,137,139,229,164,167,233,135,143,230,136,144, 228,186,186,230,149,176,233,135,143,229,133,177,228,186,171,229,140,186,229,159, 159,229,165,179,229,173,169,229,142,159,229,136,153,230,137,128,229,156,168,231, 187,147,230,157,159,233,128,154,228,191,161,232,182,133,231,186,167,233,133,141, 231,189,174,229,189,147,230,151,182,228,188,152,231,167,128,230,128,167,230,132, 159,230,136,191,228,186,167,233,129,138,230,136,178,229,135,186,229,143,163,230, 143,144,228,186,164,229,176,177,228,184,154,228,191,157,229,129,165,231,168,139, 229,186,166,229,143,130,230,149,176,228,186,139,228,184,154,230,149,180,228,184, 170,229,177,177,228,184,156,230,131,133,230,132,159,231,137,185,230,174,138,229, 136,134,233,161,158,230,144,156,229,176,139,229,177,158,228,186,142,233,151,168, 230,136,183,232,180,162,229,138,161,229,163,176,233,159,179,229,143,138,229,133, 182,232,180,162,231,187,143,229,157,154,230,140,129,229,185,178,233,131,168,230, 136,144,231,171,139,229,136,169,231,155,138,232,128,131,232,153,145,230,136,144, 233,131,189,229,140,133,232,163,133,231,148,168,230,136,182,230,175,148,232,181, 155,230,150,135,230,152,142,230,139,155,229,149,134,229,174,140,230,149,180,231, 156,159,230,152,175,231,156,188,231,157,155,228,188,153,228,188,180,229,168,129, 230,156,155,233,162,134,229,159,159,229,141,171,231,148,159,228,188,152,230,131, 160,232,171,150,229,163,135,229,133,172,229,133,177,232,137,175,229,165,189,229, 133,133,229,136,134,231,172,166,229,144,136,233,153,132,228,187,182,231,137,185, 231,130,185,228,184,141,229,143,175,232,139,177,230,150,135,232,181,132,228,186, 167,230,160,185,230,156,172,230,152,142,230,152,190,229,175,134,231,162,188,229, 133,172,228,188,151,230,176,145,230,151,143,230,155,180,229,138,160,228,186,171, 229,143,151,229,144,140,229,173,166,229,144,175,229,138,168,233,128,130,229,144, 136,229,142,159,230,157,165,233,151,174,231,173,148,230,156,172,230,150,135,231, 190,142,233,163,159,231,187,191,232,137,178,231,168,179,229,174,154,231,187,136, 228,186,142,231,148,159,231,137,169,228,190,155,230,177,130,230,144,156,231,139, 144,229,138,155,233,135,143,228,184,165,233,135,141,230,176,184,232,191,156,229, 134,153,231,156,159,230,156,137,233,153,144,231,171,158,228,186,137,229,175,185, 232,177,161,232,180,185,231,148,168,228,184,141,229,165,189,231,187,157,229,175, 185,229,141,129,229,136,134,228,191,131,232,191,155,231,130,185,232,175,132,229, 189,177,233,159,179,228,188,152,229,138,191,228,184,141,229,176,145,230,172,163, 232,181,143,229,185,182,228,184,148,230,156,137,231,130,185,230,150,185,229,144, 145,229,133,168,230,150,176,228,191,161,231,148,168,232,174,190,230,150,189,229, 189,162,232,177,161,232,181,132,230,160,188,231,170,129,231,160,180,233,154,143, 231,157,128,233,135,141,229,164,167,228,186,142,230,152,175,230,175,149,228,184, 154,230,153,186,232,131,189,229,140,150,229,183,165,229,174,140,231,190,142,229, 149,134,229,159,142,231,187,159,228,184,128,229,135,186,231,137,136,230,137,147, 233,128,160,231,148,162,229,147,129,230,166,130,229,134,181,231,148,168,228,186, 142,228,191,157,231,149,153,229,155,160,231,180,160,228,184,173,229,156,139,229, 173,152,229,130,168,232,180,180,229,155,190,230,156,128,230,132,155,233,149,191, 230,156,159,229,143,163,228,187,183,231,144,134,232,180,162,229,159,186,229,156, 176,229,174,137,230,142,146,230,173,166,230,177,137,233,135,140,233,157,162,229, 136,155,229,187,186,229,164,169,231,169,186,233,166,150,229,133,136,229,174,140, 229,150,132,233,169,177,229,138,168,228,184,139,233,157,162,228,184,141,229,134, 141,232,175,154,228,191,161,230,132,143,228,185,137,233,152,179,229,133,137,232, 139,177,229,155,189,230,188,130,228,186,174,229,134,155,228,186,139,231,142,169, 229,174,182,231,190,164,228,188,151,229,134,156,230,176,145,229,141,179,229,143, 175,229,144,141,231,168,177,229,174,182,229,133,183,229,138,168,231,148,187,230, 131,179,229,136,176,230,179,168,230,152,142,229,176,143,229,173,166,230,128,167, 232,131,189,232,128,131,231,160,148,231,161,172,228,187,182,232,167,130,231,156, 139,230,184,133,230,165,154,230,144,158,231,172,145,233,166,150,233,160,129,233, 187,132,233,135,145,233,128,130,231,148,168,230,177,159,232,139,143,231,156,159, 229,174,158,228,184,187,231,174,161,233,152,182,230,174,181,232,168,187,229,134, 138,231,191,187,232,175,145,230,157,131,229,136,169,229,129,154,229,165,189,228, 188,188,228,185,142,233,128,154,232,174,175,230,150,189,229,183,165,231,139,128, 230,133,139,228,185,159,232,174,184,231,142,175,228,191,157,229,159,185,229,133, 187,230,166,130,229,191,181,229,164,167,229,158,139,230,156,186,231,165,168,231, 144,134,232,167,163,229,140,191,229,144,141,99,117,97,110,100,111,101,110,118, 105,97,114,109,97,100,114,105,100,98,117,115,99,97,114,105,110,105,99,105,111, 116,105,101,109,112,111,112,111,114,113,117,101,99,117,101,110,116,97,101,115, 116,97,100,111,112,117,101,100,101,110,106,117,101,103,111,115,99,111,110,116, 114,97,101,115,116,195,161,110,110,111,109,98,114,101,116,105,101,110,101,110, 112,101,114,102,105,108,109,97,110,101,114,97,97,109,105,103,111,115,99,105,117, 100,97,100,99,101,110,116,114,111,97,117,110,113,117,101,112,117,101,100,101,115 ,100,101,110,116,114,111,112,114,105,109,101,114,112,114,101,99,105,111,115,101, 103,195,186,110,98,117,101,110,111,115,118,111,108,118,101,114,112,117,110,116, 111,115,115,101,109,97,110,97,104,97,98,195,173,97,97,103,111,115,116,111,110, 117,101,118,111,115,117,110,105,100,111,115,99,97,114,108,111,115,101,113,117, 105,112,111,110,105,195,177,111,115,109,117,99,104,111,115,97,108,103,117,110,97 ,99,111,114,114,101,111,105,109,97,103,101,110,112,97,114,116,105,114,97,114,114 ,105,98,97,109,97,114,195,173,97,104,111,109,98,114,101,101,109,112,108,101,111, 118,101,114,100,97,100,99,97,109,98,105,111,109,117,99,104,97,115,102,117,101, 114,111,110,112,97,115,97,100,111,108,195,173,110,101,97,112,97,114,101,99,101, 110,117,101,118,97,115,99,117,114,115,111,115,101,115,116,97,98,97,113,117,105, 101,114,111,108,105,98,114,111,115,99,117,97,110,116,111,97,99,99,101,115,111, 109,105,103,117,101,108,118,97,114,105,111,115,99,117,97,116,114,111,116,105,101 ,110,101,115,103,114,117,112,111,115,115,101,114,195,161,110,101,117,114,111,112 ,97,109,101,100,105,111,115,102,114,101,110,116,101,97,99,101,114,99,97,100,101, 109,195,161,115,111,102,101,114,116,97,99,111,99,104,101,115,109,111,100,101,108 ,111,105,116,97,108,105,97,108,101,116,114,97,115,97,108,103,195,186,110,99,111, 109,112,114,97,99,117,97,108,101,115,101,120,105,115,116,101,99,117,101,114,112, 111,115,105,101,110,100,111,112,114,101,110,115,97,108,108,101,103,97,114,118, 105,97,106,101,115,100,105,110,101,114,111,109,117,114,99,105,97,112,111,100,114 ,195,161,112,117,101,115,116,111,100,105,97,114,105,111,112,117,101,98,108,111, 113,117,105,101,114,101,109,97,110,117,101,108,112,114,111,112,105,111,99,114, 105,115,105,115,99,105,101,114,116,111,115,101,103,117,114,111,109,117,101,114, 116,101,102,117,101,110,116,101,99,101,114,114,97,114,103,114,97,110,100,101,101 ,102,101,99,116,111,112,97,114,116,101,115,109,101,100,105,100,97,112,114,111, 112,105,97,111,102,114,101,99,101,116,105,101,114,114,97,101,45,109,97,105,108, 118,97,114,105,97,115,102,111,114,109,97,115,102,117,116,117,114,111,111,98,106, 101,116,111,115,101,103,117,105,114,114,105,101,115,103,111,110,111,114,109,97, 115,109,105,115,109,111,115,195,186,110,105,99,111,99,97,109,105,110,111,115,105 ,116,105,111,115,114,97,122,195,179,110,100,101,98,105,100,111,112,114,117,101, 98,97,116,111,108,101,100,111,116,101,110,195,173,97,106,101,115,195,186,115,101 ,115,112,101,114,111,99,111,99,105,110,97,111,114,105,103,101,110,116,105,101, 110,100,97,99,105,101,110,116,111,99,195,161,100,105,122,104,97,98,108,97,114, 115,101,114,195,173,97,108,97,116,105,110,97,102,117,101,114,122,97,101,115,116, 105,108,111,103,117,101,114,114,97,101,110,116,114,97,114,195,169,120,105,116, 111,108,195,179,112,101,122,97,103,101,110,100,97,118,195,173,100,101,111,101, 118,105,116,97,114,112,97,103,105,110,97,109,101,116,114,111,115,106,97,118,105, 101,114,112,97,100,114,101,115,102,195,161,99,105,108,99,97,98,101,122,97,195, 161,114,101,97,115,115,97,108,105,100,97,101,110,118,195,173,111,106,97,112,195, 179,110,97,98,117,115,111,115,98,105,101,110,101,115,116,101,120,116,111,115,108 ,108,101,118,97,114,112,117,101,100,97,110,102,117,101,114,116,101,99,111,109, 195,186,110,99,108,97,115,101,115,104,117,109,97,110,111,116,101,110,105,100,111 ,98,105,108,98,97,111,117,110,105,100,97,100,101,115,116,195,161,115,101,100,105 ,116,97,114,99,114,101,97,100,111,208,180,208,187,209,143,209,135,209,130,208, 190,208,186,208,176,208,186,208,184,208,187,208,184,209,141,209,130,208,190,208, 178,209,129,208,181,208,181,208,179,208,190,208,191,209,128,208,184,209,130,208, 176,208,186,208,181,209,137,208,181,209,131,208,182,208,181,208,154,208,176,208, 186,208,177,208,181,208,183,208,177,209,139,208,187,208,190,208,189,208,184,208, 146,209,129,208,181,208,191,208,190,208,180,208,173,209,130,208,190,209,130,208, 190,208,188,209,135,208,181,208,188,208,189,208,181,209,130,208,187,208,181,209, 130,209,128,208,176,208,183,208,190,208,189,208,176,208,179,208,180,208,181,208, 188,208,189,208,181,208,148,208,187,209,143,208,159,209,128,208,184,208,189,208, 176,209,129,208,189,208,184,209,133,209,130,208,181,208,188,208,186,209,130,208, 190,208,179,208,190,208,180,208,178,208,190,209,130,209,130,208,176,208,188,208, 161,208,168,208,144,208,188,208,176,209,143,208,167,209,130,208,190,208,178,208, 176,209,129,208,178,208,176,208,188,208,181,208,188,209,131,208,162,208,176,208, 186,208,180,208,178,208,176,208,189,208,176,208,188,209,141,209,130,208,184,209, 141,209,130,209,131,208,146,208,176,208,188,209,130,208,181,209,133,208,191,209, 128,208,190,209,130,209,131,209,130,208,189,208,176,208,180,208,180,208,189,209, 143,208,146,208,190,209,130,209,130,209,128,208,184,208,189,208,181,208,185,208, 146,208,176,209,129,208,189,208,184,208,188,209,129,208,176,208,188,209,130,208, 190,209,130,209,128,209,131,208,177,208,158,208,189,208,184,208,188,208,184,209, 128,208,189,208,181,208,181,208,158,208,158,208,158,208,187,208,184,209,134,209, 141,209,130,208,176,208,158,208,189,208,176,208,189,208,181,208,188,208,180,208, 190,208,188,208,188,208,190,208,185,208,180,208,178,208,181,208,190,208,189,208, 190,209,129,209,131,208,180,224,164,149,224,165,135,224,164,185,224,165,136,224, 164,149,224,165,128,224,164,184,224,165,135,224,164,149,224,164,190,224,164,149, 224,165,139,224,164,148,224,164,176,224,164,170,224,164,176,224,164,168,224,165, 135,224,164,143,224,164,149,224,164,149,224,164,191,224,164,173,224,165,128,224, 164,135,224,164,184,224,164,149,224,164,176,224,164,164,224,165,139,224,164,185, 224,165,139,224,164,134,224,164,170,224,164,185,224,165,128,224,164,175,224,164, 185,224,164,175,224,164,190,224,164,164,224,164,149,224,164,165,224,164,190,106, 97,103,114,97,110,224,164,134,224,164,156,224,164,156,224,165,139,224,164,133, 224,164,172,224,164,166,224,165,139,224,164,151,224,164,136,224,164,156,224,164, 190,224,164,151,224,164,143,224,164,185,224,164,174,224,164,135,224,164,168,224, 164,181,224,164,185,224,164,175,224,165,135,224,164,165,224,165,135,224,164,165, 224,165,128,224,164,152,224,164,176,224,164,156,224,164,172,224,164,166,224,165, 128,224,164,149,224,164,136,224,164,156,224,165,128,224,164,181,224,165,135,224, 164,168,224,164,136,224,164,168,224,164,143,224,164,185,224,164,176,224,164,137, 224,164,184,224,164,174,224,165,135,224,164,149,224,164,174,224,164,181,224,165, 139,224,164,178,224,165,135,224,164,184,224,164,172,224,164,174,224,164,136,224, 164,166,224,165,135,224,164,147,224,164,176,224,164,134,224,164,174,224,164,172, 224,164,184,224,164,173,224,164,176,224,164,172,224,164,168,224,164,154,224,164, 178,224,164,174,224,164,168,224,164,134,224,164,151,224,164,184,224,165,128,224, 164,178,224,165,128,216,185,217,132,217,137,216,165,217,132,217,137,217,135,216, 176,216,167,216,162,216,174,216,177,216,185,216,175,216,175,216,167,217,132,217, 137,217,135,216,176,217,135,216,181,217,136,216,177,216,186,217,138,216,177,217, 131,216,167,217,134,217,136,217,132,216,167,216,168,217,138,217,134,216,185,216, 177,216,182,216,176,217,132,217,131,217,135,217,134,216,167,217,138,217,136,217, 133,217,130,216,167,217,132,216,185,217,132,217,138,216,167,217,134,216,167,217, 132,217,131,217,134,216,173,216,170,217,137,217,130,216,168,217,132,217,136,216, 173,216,169,216,167,216,174,216,177,217,129,217,130,216,183,216,185,216,168,216, 175,216,177,217,131,217,134,216,165,216,176,216,167,217,131,217,133,216,167,216, 167,216,173,216,175,216,165,217,132,216,167,217,129,217,138,217,135,216,168,216, 185,216,182,217,131,217,138,217,129,216,168,216,173,216,171,217,136,217,133,217, 134,217,136,217,135,217,136,216,163,217,134,216,167,216,172,216,175,216,167,217, 132,217,135,216,167,216,179,217,132,217,133,216,185,217,134,216,175,217,132,217, 138,216,179,216,185,216,168,216,177,216,181,217,132,217,137,217,133,217,134,216, 176,216,168,217,135,216,167,216,163,217,134,217,135,217,133,216,171,217,132,217, 131,217,134,216,170,216,167,217,132,216,167,216,173,217,138,216,171,217,133,216, 181,216,177,216,180,216,177,216,173,216,173,217,136,217,132,217,136,217,129,217, 138,216,167,216,176,216,167,217,132,217,131,217,132,217,133,216,177,216,169,216, 167,217,134,216,170,216,167,217,132,217,129,216,163,216,168,217,136,216,174,216, 167,216,181,216,163,217,134,216,170,216,167,217,134,217,135,216,167,217,132,217, 138,216,185,216,182,217,136,217,136,217,130,216,175,216,167,216,168,217,134,216, 174,217,138,216,177,216,168,217,134,216,170,217,132,217,131,217,133,216,180,216, 167,216,161,217,136,217,135,217,138,216,167,216,168,217,136,217,130,216,181,216, 181,217,136,217,133,216,167,216,177,217,130,217,133,216,163,216,173,216,175,217, 134,216,173,217,134,216,185,216,175,217,133,216,177,216,163,217,138,216,167,216, 173,216,169,217,131,216,170,216,168,216,175,217,136,217,134,217,138,216,172,216, 168,217,133,217,134,217,135,216,170,216,173,216,170,216,172,217,135,216,169,216, 179,217,134,216,169,217,138,216,170,217,133,217,131,216,177,216,169,216,186,216, 178,216,169,217,134,217,129,216,179,216,168,217,138,216,170,217,132,217,132,217, 135,217,132,217,134,216,167,216,170,217,132,217,131,217,130,217,132,216,168,217, 132,217,133,216,167,216,185,217,134,217,135,216,163,217,136,217,132,216,180,217, 138,216,161,217,134,217,136,216,177,216,163,217,133,216,167,217,129,217,138,217, 131,216,168,217,131,217,132,216,176,216,167,216,170,216,177,216,170,216,168,216, 168,216,163,217,134,217,135,217,133,216,179,216,167,217,134,217,131,216,168,217, 138,216,185,217,129,217,130,216,175,216,173,216,179,217,134,217,132,217,135,217, 133,216,180,216,185,216,177,216,163,217,135,217,132,216,180,217,135,216,177,217, 130,216,183,216,177,216,183,217,132,216,168,112,114,111,102,105,108,101,115,101, 114,118,105,99,101,100,101,102,97,117,108,116,104,105,109,115,101,108,102,100, 101,116,97,105,108,115,99,111,110,116,101,110,116,115,117,112,112,111,114,116, 115,116,97,114,116,101,100,109,101,115,115,97,103,101,115,117,99,99,101,115,115, 102,97,115,104,105,111,110,60,116,105,116,108,101,62,99,111,117,110,116,114,121, 97,99,99,111,117,110,116,99,114,101,97,116,101,100,115,116,111,114,105,101,115, 114,101,115,117,108,116,115,114,117,110,110,105,110,103,112,114,111,99,101,115, 115,119,114,105,116,105,110,103,111,98,106,101,99,116,115,118,105,115,105,98,108 ,101,119,101,108,99,111,109,101,97,114,116,105,99,108,101,117,110,107,110,111, 119,110,110,101,116,119,111,114,107,99,111,109,112,97,110,121,100,121,110,97,109 ,105,99,98,114,111,119,115,101,114,112,114,105,118,97,99,121,112,114,111,98,108, 101,109,83,101,114,118,105,99,101,114,101,115,112,101,99,116,100,105,115,112,108 ,97,121,114,101,113,117,101,115,116,114,101,115,101,114,118,101,119,101,98,115, 105,116,101,104,105,115,116,111,114,121,102,114,105,101,110,100,115,111,112,116, 105,111,110,115,119,111,114,107,105,110,103,118,101,114,115,105,111,110,109,105, 108,108,105,111,110,99,104,97,110,110,101,108,119,105,110,100,111,119,46,97,100, 100,114,101,115,115,118,105,115,105,116,101,100,119,101,97,116,104,101,114,99, 111,114,114,101,99,116,112,114,111,100,117,99,116,101,100,105,114,101,99,116,102 ,111,114,119,97,114,100,121,111,117,32,99,97,110,114,101,109,111,118,101,100,115 ,117,98,106,101,99,116,99,111,110,116,114,111,108,97,114,99,104,105,118,101,99, 117,114,114,101,110,116,114,101,97,100,105,110,103,108,105,98,114,97,114,121,108 ,105,109,105,116,101,100,109,97,110,97,103,101,114,102,117,114,116,104,101,114, 115,117,109,109,97,114,121,109,97,99,104,105,110,101,109,105,110,117,116,101,115 ,112,114,105,118,97,116,101,99,111,110,116,101,120,116,112,114,111,103,114,97, 109,115,111,99,105,101,116,121,110,117,109,98,101,114,115,119,114,105,116,116, 101,110,101,110,97,98,108,101,100,116,114,105,103,103,101,114,115,111,117,114,99 ,101,115,108,111,97,100,105,110,103,101,108,101,109,101,110,116,112,97,114,116, 110,101,114,102,105,110,97,108,108,121,112,101,114,102,101,99,116,109,101,97,110 ,105,110,103,115,121,115,116,101,109,115,107,101,101,112,105,110,103,99,117,108, 116,117,114,101,38,113,117,111,116,59,44,106,111,117,114,110,97,108,112,114,111, 106,101,99,116,115,117,114,102,97,99,101,115,38,113,117,111,116,59,101,120,112, 105,114,101,115,114,101,118,105,101,119,115,98,97,108,97,110,99,101,69,110,103, 108,105,115,104,67,111,110,116,101,110,116,116,104,114,111,117,103,104,80,108, 101,97,115,101,32,111,112,105,110,105,111,110,99,111,110,116,97,99,116,97,118, 101,114,97,103,101,112,114,105,109,97,114,121,118,105,108,108,97,103,101,83,112, 97,110,105,115,104,103,97,108,108,101,114,121,100,101,99,108,105,110,101,109,101 ,101,116,105,110,103,109,105,115,115,105,111,110,112,111,112,117,108,97,114,113, 117,97,108,105,116,121,109,101,97,115,117,114,101,103,101,110,101,114,97,108,115 ,112,101,99,105,101,115,115,101,115,115,105,111,110,115,101,99,116,105,111,110, 119,114,105,116,101,114,115,99,111,117,110,116,101,114,105,110,105,116,105,97, 108,114,101,112,111,114,116,115,102,105,103,117,114,101,115,109,101,109,98,101, 114,115,104,111,108,100,105,110,103,100,105,115,112,117,116,101,101,97,114,108, 105,101,114,101,120,112,114,101,115,115,100,105,103,105,116,97,108,112,105,99, 116,117,114,101,65,110,111,116,104,101,114,109,97,114,114,105,101,100,116,114,97 ,102,102,105,99,108,101,97,100,105,110,103,99,104,97,110,103,101,100,99,101,110, 116,114,97,108,118,105,99,116,111,114,121,105,109,97,103,101,115,47,114,101,97, 115,111,110,115,115,116,117,100,105,101,115,102,101,97,116,117,114,101,108,105, 115,116,105,110,103,109,117,115,116,32,98,101,115,99,104,111,111,108,115,86,101, 114,115,105,111,110,117,115,117,97,108,108,121,101,112,105,115,111,100,101,112, 108,97,121,105,110,103,103,114,111,119,105,110,103,111,98,118,105,111,117,115, 111,118,101,114,108,97,121,112,114,101,115,101,110,116,97,99,116,105,111,110,115 ,60,47,117,108,62,13,10,119,114,97,112,112,101,114,97,108,114,101,97,100,121,99, 101,114,116,97,105,110,114,101,97,108,105,116,121,115,116,111,114,97,103,101,97, 110,111,116,104,101,114,100,101,115,107,116,111,112,111,102,102,101,114,101,100, 112,97,116,116,101,114,110,117,110,117,115,117,97,108,68,105,103,105,116,97,108, 99,97,112,105,116,97,108,87,101,98,115,105,116,101,102,97,105,108,117,114,101,99 ,111,110,110,101,99,116,114,101,100,117,99,101,100,65,110,100,114,111,105,100, 100,101,99,97,100,101,115,114,101,103,117,108,97,114,32,38,97,109,112,59,32,97, 110,105,109,97,108,115,114,101,108,101,97,115,101,65,117,116,111,109,97,116,103, 101,116,116,105,110,103,109,101,116,104,111,100,115,110,111,116,104,105,110,103, 80,111,112,117,108,97,114,99,97,112,116,105,111,110,108,101,116,116,101,114,115, 99,97,112,116,117,114,101,115,99,105,101,110,99,101,108,105,99,101,110,115,101, 99,104,97,110,103,101,115,69,110,103,108,97,110,100,61,49,38,97,109,112,59,72, 105,115,116,111,114,121,32,61,32,110,101,119,32,67,101,110,116,114,97,108,117, 112,100,97,116,101,100,83,112,101,99,105,97,108,78,101,116,119,111,114,107,114, 101,113,117,105,114,101,99,111,109,109,101,110,116,119,97,114,110,105,110,103,67 ,111,108,108,101,103,101,116,111,111,108,98,97,114,114,101,109,97,105,110,115,98 ,101,99,97,117,115,101,101,108,101,99,116,101,100,68,101,117,116,115,99,104,102, 105,110,97,110,99,101,119,111,114,107,101,114,115,113,117,105,99,107,108,121,98, 101,116,119,101,101,110,101,120,97,99,116,108,121,115,101,116,116,105,110,103, 100,105,115,101,97,115,101,83,111,99,105,101,116,121,119,101,97,112,111,110,115, 101,120,104,105,98,105,116,38,108,116,59,33,45,45,67,111,110,116,114,111,108,99, 108,97,115,115,101,115,99,111,118,101,114,101,100,111,117,116,108,105,110,101,97 ,116,116,97,99,107,115,100,101,118,105,99,101,115,40,119,105,110,100,111,119,112 ,117,114,112,111,115,101,116,105,116,108,101,61,34,77,111,98,105,108,101,32,107, 105,108,108,105,110,103,115,104,111,119,105,110,103,73,116,97,108,105,97,110,100 ,114,111,112,112,101,100,104,101,97,118,105,108,121,101,102,102,101,99,116,115, 45,49,39,93,41,59,10,99,111,110,102,105,114,109,67,117,114,114,101,110,116,97, 100,118,97,110,99,101,115,104,97,114,105,110,103,111,112,101,110,105,110,103,100 ,114,97,119,105,110,103,98,105,108,108,105,111,110,111,114,100,101,114,101,100, 71,101,114,109,97,110,121,114,101,108,97,116,101,100,60,47,102,111,114,109,62, 105,110,99,108,117,100,101,119,104,101,116,104,101,114,100,101,102,105,110,101, 100,83,99,105,101,110,99,101,99,97,116,97,108,111,103,65,114,116,105,99,108,101, 98,117,116,116,111,110,115,108,97,114,103,101,115,116,117,110,105,102,111,114, 109,106,111,117,114,110,101,121,115,105,100,101,98,97,114,67,104,105,99,97,103, 111,104,111,108,105,100,97,121,71,101,110,101,114,97,108,112,97,115,115,97,103, 101,44,38,113,117,111,116,59,97,110,105,109,97,116,101,102,101,101,108,105,110, 103,97,114,114,105,118,101,100,112,97,115,115,105,110,103,110,97,116,117,114,97, 108,114,111,117,103,104,108,121,46,10,10,84,104,101,32,98,117,116,32,110,111,116 ,100,101,110,115,105,116,121,66,114,105,116,97,105,110,67,104,105,110,101,115, 101,108,97,99,107,32,111,102,116,114,105,98,117,116,101,73,114,101,108,97,110, 100,34,32,100,97,116,97,45,102,97,99,116,111,114,115,114,101,99,101,105,118,101, 116,104,97,116,32,105,115,76,105,98,114,97,114,121,104,117,115,98,97,110,100,105 ,110,32,102,97,99,116,97,102,102,97,105,114,115,67,104,97,114,108,101,115,114,97 ,100,105,99,97,108,98,114,111,117,103,104,116,102,105,110,100,105,110,103,108,97 ,110,100,105,110,103,58,108,97,110,103,61,34,114,101,116,117,114,110,32,108,101, 97,100,101,114,115,112,108,97,110,110,101,100,112,114,101,109,105,117,109,112,97 ,99,107,97,103,101,65,109,101,114,105,99,97,69,100,105,116,105,111,110,93,38,113 ,117,111,116,59,77,101,115,115,97,103,101,110,101,101,100,32,116,111,118,97,108, 117,101,61,34,99,111,109,112,108,101,120,108,111,111,107,105,110,103,115,116,97, 116,105,111,110,98,101,108,105,101,118,101,115,109,97,108,108,101,114,45,109,111 ,98,105,108,101,114,101,99,111,114,100,115,119,97,110,116,32,116,111,107,105,110 ,100,32,111,102,70,105,114,101,102,111,120,121,111,117,32,97,114,101,115,105,109 ,105,108,97,114,115,116,117,100,105,101,100,109,97,120,105,109,117,109,104,101, 97,100,105,110,103,114,97,112,105,100,108,121,99,108,105,109,97,116,101,107,105, 110,103,100,111,109,101,109,101,114,103,101,100,97,109,111,117,110,116,115,102, 111,117,110,100,101,100,112,105,111,110,101,101,114,102,111,114,109,117,108,97, 100,121,110,97,115,116,121,104,111,119,32,116,111,32,83,117,112,112,111,114,116, 114,101,118,101,110,117,101,101,99,111,110,111,109,121,82,101,115,117,108,116, 115,98,114,111,116,104,101,114,115,111,108,100,105,101,114,108,97,114,103,101, 108,121,99,97,108,108,105,110,103,46,38,113,117,111,116,59,65,99,99,111,117,110, 116,69,100,119,97,114,100,32,115,101,103,109,101,110,116,82,111,98,101,114,116, 32,101,102,102,111,114,116,115,80,97,99,105,102,105,99,108,101,97,114,110,101, 100,117,112,32,119,105,116,104,104,101,105,103,104,116,58,119,101,32,104,97,118, 101,65,110,103,101,108,101,115,110,97,116,105,111,110,115,95,115,101,97,114,99, 104,97,112,112,108,105,101,100,97,99,113,117,105,114,101,109,97,115,115,105,118, 101,103,114,97,110,116,101,100,58,32,102,97,108,115,101,116,114,101,97,116,101, 100,98,105,103,103,101,115,116,98,101,110,101,102,105,116,100,114,105,118,105, 110,103,83,116,117,100,105,101,115,109,105,110,105,109,117,109,112,101,114,104, 97,112,115,109,111,114,110,105,110,103,115,101,108,108,105,110,103,105,115,32, 117,115,101,100,114,101,118,101,114,115,101,118,97,114,105,97,110,116,32,114,111 ,108,101,61,34,109,105,115,115,105,110,103,97,99,104,105,101,118,101,112,114,111 ,109,111,116,101,115,116,117,100,101,110,116,115,111,109,101,111,110,101,101,120 ,116,114,101,109,101,114,101,115,116,111,114,101,98,111,116,116,111,109,58,101, 118,111,108,118,101,100,97,108,108,32,116,104,101,115,105,116,101,109,97,112,101 ,110,103,108,105,115,104,119,97,121,32,116,111,32,32,65,117,103,117,115,116,115, 121,109,98,111,108,115,67,111,109,112,97,110,121,109,97,116,116,101,114,115,109, 117,115,105,99,97,108,97,103,97,105,110,115,116,115,101,114,118,105,110,103,125, 41,40,41,59,13,10,112,97,121,109,101,110,116,116,114,111,117,98,108,101,99,111, 110,99,101,112,116,99,111,109,112,97,114,101,112,97,114,101,110,116,115,112,108, 97,121,101,114,115,114,101,103,105,111,110,115,109,111,110,105,116,111,114,32,39 ,39,84,104,101,32,119,105,110,110,105,110,103,101,120,112,108,111,114,101,97,100 ,97,112,116,101,100,71,97,108,108,101,114,121,112,114,111,100,117,99,101,97,98, 105,108,105,116,121,101,110,104,97,110,99,101,99,97,114,101,101,114,115,41,46,32 ,84,104,101,32,99,111,108,108,101,99,116,83,101,97,114,99,104,32,97,110,99,105, 101,110,116,101,120,105,115,116,101,100,102,111,111,116,101,114,32,104,97,110, 100,108,101,114,112,114,105,110,116,101,100,99,111,110,115,111,108,101,69,97,115 ,116,101,114,110,101,120,112,111,114,116,115,119,105,110,100,111,119,115,67,104, 97,110,110,101,108,105,108,108,101,103,97,108,110,101,117,116,114,97,108,115,117 ,103,103,101,115,116,95,104,101,97,100,101,114,115,105,103,110,105,110,103,46, 104,116,109,108,34,62,115,101,116,116,108,101,100,119,101,115,116,101,114,110,99 ,97,117,115,105,110,103,45,119,101,98,107,105,116,99,108,97,105,109,101,100,74, 117,115,116,105,99,101,99,104,97,112,116,101,114,118,105,99,116,105,109,115,84, 104,111,109,97,115,32,109,111,122,105,108,108,97,112,114,111,109,105,115,101,112 ,97,114,116,105,101,115,101,100,105,116,105,111,110,111,117,116,115,105,100,101, 58,102,97,108,115,101,44,104,117,110,100,114,101,100,79,108,121,109,112,105,99, 95,98,117,116,116,111,110,97,117,116,104,111,114,115,114,101,97,99,104,101,100, 99,104,114,111,110,105,99,100,101,109,97,110,100,115,115,101,99,111,110,100,115, 112,114,111,116,101,99,116,97,100,111,112,116,101,100,112,114,101,112,97,114,101 ,110,101,105,116,104,101,114,103,114,101,97,116,108,121,103,114,101,97,116,101, 114,111,118,101,114,97,108,108,105,109,112,114,111,118,101,99,111,109,109,97,110 ,100,115,112,101,99,105,97,108,115,101,97,114,99,104,46,119,111,114,115,104,105, 112,102,117,110,100,105,110,103,116,104,111,117,103,104,116,104,105,103,104,101, 115,116,105,110,115,116,101,97,100,117,116,105,108,105,116,121,113,117,97,114, 116,101,114,67,117,108,116,117,114,101,116,101,115,116,105,110,103,99,108,101,97 ,114,108,121,101,120,112,111,115,101,100,66,114,111,119,115,101,114,108,105,98, 101,114,97,108,125,32,99,97,116,99,104,80,114,111,106,101,99,116,101,120,97,109, 112,108,101,104,105,100,101,40,41,59,70,108,111,114,105,100,97,97,110,115,119, 101,114,115,97,108,108,111,119,101,100,69,109,112,101,114,111,114,100,101,102, 101,110,115,101,115,101,114,105,111,117,115,102,114,101,101,100,111,109,83,101, 118,101,114,97,108,45,98,117,116,116,111,110,70,117,114,116,104,101,114,111,117, 116,32,111,102,32,33,61,32,110,117,108,108,116,114,97,105,110,101,100,68,101,110 ,109,97,114,107,118,111,105,100,40,48,41,47,97,108,108,46,106,115,112,114,101, 118,101,110,116,82,101,113,117,101,115,116,83,116,101,112,104,101,110,10,10,87, 104,101,110,32,111,98,115,101,114,118,101,60,47,104,50,62,13,10,77,111,100,101, 114,110,32,112,114,111,118,105,100,101,34,32,97,108,116,61,34,98,111,114,100,101 ,114,115,46,10,10,70,111,114,32,10,10,77,97,110,121,32,97,114,116,105,115,116, 115,112,111,119,101,114,101,100,112,101,114,102,111,114,109,102,105,99,116,105, 111,110,116,121,112,101,32,111,102,109,101,100,105,99,97,108,116,105,99,107,101, 116,115,111,112,112,111,115,101,100,67,111,117,110,99,105,108,119,105,116,110, 101,115,115,106,117,115,116,105,99,101,71,101,111,114,103,101,32,66,101,108,103, 105,117,109,46,46,46,60,47,97,62,116,119,105,116,116,101,114,110,111,116,97,98, 108,121,119,97,105,116,105,110,103,119,97,114,102,97,114,101,32,79,116,104,101, 114,32,114,97,110,107,105,110,103,112,104,114,97,115,101,115,109,101,110,116,105 ,111,110,115,117,114,118,105,118,101,115,99,104,111,108,97,114,60,47,112,62,13, 10,32,67,111,117,110,116,114,121,105,103,110,111,114,101,100,108,111,115,115,32, 111,102,106,117,115,116,32,97,115,71,101,111,114,103,105,97,115,116,114,97,110, 103,101,60,104,101,97,100,62,60,115,116,111,112,112,101,100,49,39,93,41,59,13,10 ,105,115,108,97,110,100,115,110,111,116,97,98,108,101,98,111,114,100,101,114,58, 108,105,115,116,32,111,102,99,97,114,114,105,101,100,49,48,48,44,48,48,48,60,47, 104,51,62,10,32,115,101,118,101,114,97,108,98,101,99,111,109,101,115,115,101,108 ,101,99,116,32,119,101,100,100,105,110,103,48,48,46,104,116,109,108,109,111,110, 97,114,99,104,111,102,102,32,116,104,101,116,101,97,99,104,101,114,104,105,103, 104,108,121,32,98,105,111,108,111,103,121,108,105,102,101,32,111,102,111,114,32, 101,118,101,110,114,105,115,101,32,111,102,38,114,97,113,117,111,59,112,108,117, 115,111,110,101,104,117,110,116,105,110,103,40,116,104,111,117,103,104,68,111, 117,103,108,97,115,106,111,105,110,105,110,103,99,105,114,99,108,101,115,70,111, 114,32,116,104,101,65,110,99,105,101,110,116,86,105,101,116,110,97,109,118,101, 104,105,99,108,101,115,117,99,104,32,97,115,99,114,121,115,116,97,108,118,97,108 ,117,101,32,61,87,105,110,100,111,119,115,101,110,106,111,121,101,100,97,32,115, 109,97,108,108,97,115,115,117,109,101,100,60,97,32,105,100,61,34,102,111,114,101 ,105,103,110,32,65,108,108,32,114,105,104,111,119,32,116,104,101,68,105,115,112, 108,97,121,114,101,116,105,114,101,100,104,111,119,101,118,101,114,104,105,100, 100,101,110,59,98,97,116,116,108,101,115,115,101,101,107,105,110,103,99,97,98, 105,110,101,116,119,97,115,32,110,111,116,108,111,111,107,32,97,116,99,111,110, 100,117,99,116,103,101,116,32,116,104,101,74,97,110,117,97,114,121,104,97,112, 112,101,110,115,116,117,114,110,105,110,103,97,58,104,111,118,101,114,79,110,108 ,105,110,101,32,70,114,101,110,99,104,32,108,97,99,107,105,110,103,116,121,112, 105,99,97,108,101,120,116,114,97,99,116,101,110,101,109,105,101,115,101,118,101, 110,32,105,102,103,101,110,101,114,97,116,100,101,99,105,100,101,100,97,114,101, 32,110,111,116,47,115,101,97,114,99,104,98,101,108,105,101,102,115,45,105,109,97 ,103,101,58,108,111,99,97,116,101,100,115,116,97,116,105,99,46,108,111,103,105, 110,34,62,99,111,110,118,101,114,116,118,105,111,108,101,110,116,101,110,116,101 ,114,101,100,102,105,114,115,116,34,62,99,105,114,99,117,105,116,70,105,110,108, 97,110,100,99,104,101,109,105,115,116,115,104,101,32,119,97,115,49,48,112,120,59 ,34,62,97,115,32,115,117,99,104,100,105,118,105,100,101,100,60,47,115,112,97,110 ,62,119,105,108,108,32,98,101,108,105,110,101,32,111,102,97,32,103,114,101,97, 116,109,121,115,116,101,114,121,47,105,110,100,101,120,46,102,97,108,108,105,110 ,103,100,117,101,32,116,111,32,114,97,105,108,119,97,121,99,111,108,108,101,103, 101,109,111,110,115,116,101,114,100,101,115,99,101,110,116,105,116,32,119,105, 116,104,110,117,99,108,101,97,114,74,101,119,105,115,104,32,112,114,111,116,101, 115,116,66,114,105,116,105,115,104,102,108,111,119,101,114,115,112,114,101,100, 105,99,116,114,101,102,111,114,109,115,98,117,116,116,111,110,32,119,104,111,32, 119,97,115,108,101,99,116,117,114,101,105,110,115,116,97,110,116,115,117,105,99, 105,100,101,103,101,110,101,114,105,99,112,101,114,105,111,100,115,109,97,114, 107,101,116,115,83,111,99,105,97,108,32,102,105,115,104,105,110,103,99,111,109, 98,105,110,101,103,114,97,112,104,105,99,119,105,110,110,101,114,115,60,98,114, 32,47,62,60,98,121,32,116,104,101,32,78,97,116,117,114,97,108,80,114,105,118,97, 99,121,99,111,111,107,105,101,115,111,117,116,99,111,109,101,114,101,115,111,108 ,118,101,83,119,101,100,105,115,104,98,114,105,101,102,108,121,80,101,114,115, 105,97,110,115,111,32,109,117,99,104,67,101,110,116,117,114,121,100,101,112,105, 99,116,115,99,111,108,117,109,110,115,104,111,117,115,105,110,103,115,99,114,105 ,112,116,115,110,101,120,116,32,116,111,98,101,97,114,105,110,103,109,97,112,112 ,105,110,103,114,101,118,105,115,101,100,106,81,117,101,114,121,40,45,119,105, 100,116,104,58,116,105,116,108,101,34,62,116,111,111,108,116,105,112,83,101,99, 116,105,111,110,100,101,115,105,103,110,115,84,117,114,107,105,115,104,121,111, 117,110,103,101,114,46,109,97,116,99,104,40,125,41,40,41,59,10,10,98,117,114,110 ,105,110,103,111,112,101,114,97,116,101,100,101,103,114,101,101,115,115,111,117, 114,99,101,61,82,105,99,104,97,114,100,99,108,111,115,101,108,121,112,108,97,115 ,116,105,99,101,110,116,114,105,101,115,60,47,116,114,62,13,10,99,111,108,111, 114,58,35,117,108,32,105,100,61,34,112,111,115,115,101,115,115,114,111,108,108, 105,110,103,112,104,121,115,105,99,115,102,97,105,108,105,110,103,101,120,101,99 ,117,116,101,99,111,110,116,101,115,116,108,105,110,107,32,116,111,68,101,102,97 ,117,108,116,60,98,114,32,47,62,10,58,32,116,114,117,101,44,99,104,97,114,116, 101,114,116,111,117,114,105,115,109,99,108,97,115,115,105,99,112,114,111,99,101, 101,100,101,120,112,108,97,105,110,60,47,104,49,62,13,10,111,110,108,105,110,101 ,46,63,120,109,108,32,118,101,104,101,108,112,105,110,103,100,105,97,109,111,110 ,100,117,115,101,32,116,104,101,97,105,114,108,105,110,101,101,110,100,32,45,45, 62,41,46,97,116,116,114,40,114,101,97,100,101,114,115,104,111,115,116,105,110, 103,35,102,102,102,102,102,102,114,101,97,108,105,122,101,86,105,110,99,101,110, 116,115,105,103,110,97,108,115,32,115,114,99,61,34,47,80,114,111,100,117,99,116, 100,101,115,112,105,116,101,100,105,118,101,114,115,101,116,101,108,108,105,110, 103,80,117,98,108,105,99,32,104,101,108,100,32,105,110,74,111,115,101,112,104,32 ,116,104,101,97,116,114,101,97,102,102,101,99,116,115,60,115,116,121,108,101,62, 97,32,108,97,114,103,101,100,111,101,115,110,39,116,108,97,116,101,114,44,32,69, 108,101,109,101,110,116,102,97,118,105,99,111,110,99,114,101,97,116,111,114,72, 117,110,103,97,114,121,65,105,114,112,111,114,116,115,101,101,32,116,104,101,115 ,111,32,116,104,97,116,77,105,99,104,97,101,108,83,121,115,116,101,109,115,80, 114,111,103,114,97,109,115,44,32,97,110,100,32,32,119,105,100,116,104,61,101,38, 113,117,111,116,59,116,114,97,100,105,110,103,108,101,102,116,34,62,10,112,101, 114,115,111,110,115,71,111,108,100,101,110,32,65,102,102,97,105,114,115,103,114, 97,109,109,97,114,102,111,114,109,105,110,103,100,101,115,116,114,111,121,105, 100,101,97,32,111,102,99,97,115,101,32,111,102,111,108,100,101,115,116,32,116, 104,105,115,32,105,115,46,115,114,99,32,61,32,99,97,114,116,111,111,110,114,101, 103,105,115,116,114,67,111,109,109,111,110,115,77,117,115,108,105,109,115,87,104 ,97,116,32,105,115,105,110,32,109,97,110,121,109,97,114,107,105,110,103,114,101, 118,101,97,108,115,73,110,100,101,101,100,44,101,113,117,97,108,108,121,47,115, 104,111,119,95,97,111,117,116,100,111,111,114,101,115,99,97,112,101,40,65,117, 115,116,114,105,97,103,101,110,101,116,105,99,115,121,115,116,101,109,44,73,110, 32,116,104,101,32,115,105,116,116,105,110,103,72,101,32,97,108,115,111,73,115, 108,97,110,100,115,65,99,97,100,101,109,121,10,9,9,60,33,45,45,68,97,110,105,101 ,108,32,98,105,110,100,105,110,103,98,108,111,99,107,34,62,105,109,112,111,115, 101,100,117,116,105,108,105,122,101,65,98,114,97,104,97,109,40,101,120,99,101, 112,116,123,119,105,100,116,104,58,112,117,116,116,105,110,103,41,46,104,116,109 ,108,40,124,124,32,91,93,59,10,68,65,84,65,91,32,42,107,105,116,99,104,101,110, 109,111,117,110,116,101,100,97,99,116,117,97,108,32,100,105,97,108,101,99,116, 109,97,105,110,108,121,32,95,98,108,97,110,107,39,105,110,115,116,97,108,108,101 ,120,112,101,114,116,115,105,102,40,116,121,112,101,73,116,32,97,108,115,111,38, 99,111,112,121,59,32,34,62,84,101,114,109,115,98,111,114,110,32,105,110,79,112, 116,105,111,110,115,101,97,115,116,101,114,110,116,97,108,107,105,110,103,99,111 ,110,99,101,114,110,103,97,105,110,101,100,32,111,110,103,111,105,110,103,106, 117,115,116,105,102,121,99,114,105,116,105,99,115,102,97,99,116,111,114,121,105, 116,115,32,111,119,110,97,115,115,97,117,108,116,105,110,118,105,116,101,100,108 ,97,115,116,105,110,103,104,105,115,32,111,119,110,104,114,101,102,61,34,47,34, 32,114,101,108,61,34,100,101,118,101,108,111,112,99,111,110,99,101,114,116,100, 105,97,103,114,97,109,100,111,108,108,97,114,115,99,108,117,115,116,101,114,112, 104,112,63,105,100,61,97,108,99,111,104,111,108,41,59,125,41,40,41,59,117,115, 105,110,103,32,97,62,60,115,112,97,110,62,118,101,115,115,101,108,115,114,101, 118,105,118,97,108,65,100,100,114,101,115,115,97,109,97,116,101,117,114,97,110, 100,114,111,105,100,97,108,108,101,103,101,100,105,108,108,110,101,115,115,119, 97,108,107,105,110,103,99,101,110,116,101,114,115,113,117,97,108,105,102,121,109 ,97,116,99,104,101,115,117,110,105,102,105,101,100,101,120,116,105,110,99,116,68 ,101,102,101,110,115,101,100,105,101,100,32,105,110,10,9,60,33,45,45,32,99,117, 115,116,111,109,115,108,105,110,107,105,110,103,76,105,116,116,108,101,32,66,111 ,111,107,32,111,102,101,118,101,110,105,110,103,109,105,110,46,106,115,63,97,114 ,101,32,116,104,101,107,111,110,116,97,107,116,116,111,100,97,121,39,115,46,104, 116,109,108,34,32,116,97,114,103,101,116,61,119,101,97,114,105,110,103,65,108, 108,32,82,105,103,59,10,125,41,40,41,59,114,97,105,115,105,110,103,32,65,108,115 ,111,44,32,99,114,117,99,105,97,108,97,98,111,117,116,34,62,100,101,99,108,97, 114,101,45,45,62,10,60,115,99,102,105,114,101,102,111,120,97,115,32,109,117,99, 104,97,112,112,108,105,101,115,105,110,100,101,120,44,32,115,44,32,98,117,116,32 ,116,121,112,101,32,61,32,10,13,10,60,33,45,45,116,111,119,97,114,100,115,82,101 ,99,111,114,100,115,80,114,105,118,97,116,101,70,111,114,101,105,103,110,80,114, 101,109,105,101,114,99,104,111,105,99,101,115,86,105,114,116,117,97,108,114,101, 116,117,114,110,115,67,111,109,109,101,110,116,80,111,119,101,114,101,100,105, 110,108,105,110,101,59,112,111,118,101,114,116,121,99,104,97,109,98,101,114,76, 105,118,105,110,103,32,118,111,108,117,109,101,115,65,110,116,104,111,110,121, 108,111,103,105,110,34,32,82,101,108,97,116,101,100,69,99,111,110,111,109,121, 114,101,97,99,104,101,115,99,117,116,116,105,110,103,103,114,97,118,105,116,121, 108,105,102,101,32,105,110,67,104,97,112,116,101,114,45,115,104,97,100,111,119, 78,111,116,97,98,108,101,60,47,116,100,62,13,10,32,114,101,116,117,114,110,115, 116,97,100,105,117,109,119,105,100,103,101,116,115,118,97,114,121,105,110,103, 116,114,97,118,101,108,115,104,101,108,100,32,98,121,119,104,111,32,97,114,101, 119,111,114,107,32,105,110,102,97,99,117,108,116,121,97,110,103,117,108,97,114, 119,104,111,32,104,97,100,97,105,114,112,111,114,116,116,111,119,110,32,111,102, 10,10,83,111,109,101,32,39,99,108,105,99,107,39,99,104,97,114,103,101,115,107, 101,121,119,111,114,100,105,116,32,119,105,108,108,99,105,116,121,32,111,102,40, 116,104,105,115,41,59,65,110,100,114,101,119,32,117,110,105,113,117,101,32,99, 104,101,99,107,101,100,111,114,32,109,111,114,101,51,48,48,112,120,59,32,114,101 ,116,117,114,110,59,114,115,105,111,110,61,34,112,108,117,103,105,110,115,119, 105,116,104,105,110,32,104,101,114,115,101,108,102,83,116,97,116,105,111,110,70, 101,100,101,114,97,108,118,101,110,116,117,114,101,112,117,98,108,105,115,104, 115,101,110,116,32,116,111,116,101,110,115,105,111,110,97,99,116,114,101,115,115 ,99,111,109,101,32,116,111,102,105,110,103,101,114,115,68,117,107,101,32,111,102 ,112,101,111,112,108,101,44,101,120,112,108,111,105,116,119,104,97,116,32,105, 115,104,97,114,109,111,110,121,97,32,109,97,106,111,114,34,58,34,104,116,116,112 ,105,110,32,104,105,115,32,109,101,110,117,34,62,10,109,111,110,116,104,108,121, 111,102,102,105,99,101,114,99,111,117,110,99,105,108,103,97,105,110,105,110,103, 101,118,101,110,32,105,110,83,117,109,109,97,114,121,100,97,116,101,32,111,102, 108,111,121,97,108,116,121,102,105,116,110,101,115,115,97,110,100,32,119,97,115, 101,109,112,101,114,111,114,115,117,112,114,101,109,101,83,101,99,111,110,100,32 ,104,101,97,114,105,110,103,82,117,115,115,105,97,110,108,111,110,103,101,115, 116,65,108,98,101,114,116,97,108,97,116,101,114,97,108,115,101,116,32,111,102,32 ,115,109,97,108,108,34,62,46,97,112,112,101,110,100,100,111,32,119,105,116,104, 102,101,100,101,114,97,108,98,97,110,107,32,111,102,98,101,110,101,97,116,104,68 ,101,115,112,105,116,101,67,97,112,105,116,97,108,103,114,111,117,110,100,115,41 ,44,32,97,110,100,32,112,101,114,99,101,110,116,105,116,32,102,114,111,109,99, 108,111,115,105,110,103,99,111,110,116,97,105,110,73,110,115,116,101,97,100,102, 105,102,116,101,101,110,97,115,32,119,101,108,108,46,121,97,104,111,111,46,114, 101,115,112,111,110,100,102,105,103,104,116,101,114,111,98,115,99,117,114,101, 114,101,102,108,101,99,116,111,114,103,97,110,105,99,61,32,77,97,116,104,46,101, 100,105,116,105,110,103,111,110,108,105,110,101,32,112,97,100,100,105,110,103,97 ,32,119,104,111,108,101,111,110,101,114,114,111,114,121,101,97,114,32,111,102, 101,110,100,32,111,102,32,98,97,114,114,105,101,114,119,104,101,110,32,105,116, 104,101,97,100,101,114,32,104,111,109,101,32,111,102,114,101,115,117,109,101,100 ,114,101,110,97,109,101,100,115,116,114,111,110,103,62,104,101,97,116,105,110, 103,114,101,116,97,105,110,115,99,108,111,117,100,102,114,119,97,121,32,111,102, 32,77,97,114,99,104,32,49,107,110,111,119,105,110,103,105,110,32,112,97,114,116, 66,101,116,119,101,101,110,108,101,115,115,111,110,115,99,108,111,115,101,115, 116,118,105,114,116,117,97,108,108,105,110,107,115,34,62,99,114,111,115,115,101, 100,69,78,68,32,45,45,62,102,97,109,111,117,115,32,97,119,97,114,100,101,100,76, 105,99,101,110,115,101,72,101,97,108,116,104,32,102,97,105,114,108,121,32,119, 101,97,108,116,104,121,109,105,110,105,109,97,108,65,102,114,105,99,97,110,99, 111,109,112,101,116,101,108,97,98,101,108,34,62,115,105,110,103,105,110,103,102, 97,114,109,101,114,115,66,114,97,115,105,108,41,100,105,115,99,117,115,115,114, 101,112,108,97,99,101,71,114,101,103,111,114,121,102,111,110,116,32,99,111,112, 117,114,115,117,101,100,97,112,112,101,97,114,115,109,97,107,101,32,117,112,114, 111,117,110,100,101,100,98,111,116,104,32,111,102,98,108,111,99,107,101,100,115, 97,119,32,116,104,101,111,102,102,105,99,101,115,99,111,108,111,117,114,115,105, 102,40,100,111,99,117,119,104,101,110,32,104,101,101,110,102,111,114,99,101,112, 117,115,104,40,102,117,65,117,103,117,115,116,32,85,84,70,45,56,34,62,70,97,110, 116,97,115,121,105,110,32,109,111,115,116,105,110,106,117,114,101,100,85,115,117 ,97,108,108,121,102,97,114,109,105,110,103,99,108,111,115,117,114,101,111,98,106 ,101,99,116,32,100,101,102,101,110,99,101,117,115,101,32,111,102,32,77,101,100, 105,99,97,108,60,98,111,100,121,62,10,101,118,105,100,101,110,116,98,101,32,117, 115,101,100,107,101,121,67,111,100,101,115,105,120,116,101,101,110,73,115,108,97 ,109,105,99,35,48,48,48,48,48,48,101,110,116,105,114,101,32,119,105,100,101,108, 121,32,97,99,116,105,118,101,32,40,116,121,112,101,111,102,111,110,101,32,99,97, 110,99,111,108,111,114,32,61,115,112,101,97,107,101,114,101,120,116,101,110,100, 115,80,104,121,115,105,99,115,116,101,114,114,97,105,110,60,116,98,111,100,121, 62,102,117,110,101,114,97,108,118,105,101,119,105,110,103,109,105,100,100,108, 101,32,99,114,105,99,107,101,116,112,114,111,112,104,101,116,115,104,105,102,116 ,101,100,100,111,99,116,111,114,115,82,117,115,115,101,108,108,32,116,97,114,103 ,101,116,99,111,109,112,97,99,116,97,108,103,101,98,114,97,115,111,99,105,97,108 ,45,98,117,108,107,32,111,102,109,97,110,32,97,110,100,60,47,116,100,62,10,32, 104,101,32,108,101,102,116,41,46,118,97,108,40,41,102,97,108,115,101,41,59,108, 111,103,105,99,97,108,98,97,110,107,105,110,103,104,111,109,101,32,116,111,110, 97,109,105,110,103,32,65,114,105,122,111,110,97,99,114,101,100,105,116,115,41,59 ,10,125,41,59,10,102,111,117,110,100,101,114,105,110,32,116,117,114,110,67,111, 108,108,105,110,115,98,101,102,111,114,101,32,66,117,116,32,116,104,101,99,104, 97,114,103,101,100,84,105,116,108,101,34,62,67,97,112,116,97,105,110,115,112,101 ,108,108,101,100,103,111,100,100,101,115,115,84,97,103,32,45,45,62,65,100,100, 105,110,103,58,98,117,116,32,119,97,115,82,101,99,101,110,116,32,112,97,116,105, 101,110,116,98,97,99,107,32,105,110,61,102,97,108,115,101,38,76,105,110,99,111, 108,110,119,101,32,107,110,111,119,67,111,117,110,116,101,114,74,117,100,97,105, 115,109,115,99,114,105,112,116,32,97,108,116,101,114,101,100,39,93,41,59,10,32, 32,104,97,115,32,116,104,101,117,110,99,108,101,97,114,69,118,101,110,116,39,44, 98,111,116,104,32,105,110,110,111,116,32,97,108,108,10,10,60,33,45,45,32,112,108 ,97,99,105,110,103,104,97,114,100,32,116,111,32,99,101,110,116,101,114,115,111, 114,116,32,111,102,99,108,105,101,110,116,115,115,116,114,101,101,116,115,66,101 ,114,110,97,114,100,97,115,115,101,114,116,115,116,101,110,100,32,116,111,102,97 ,110,116,97,115,121,100,111,119,110,32,105,110,104,97,114,98,111,117,114,70,114, 101,101,100,111,109,106,101,119,101,108,114,121,47,97,98,111,117,116,46,46,115, 101,97,114,99,104,108,101,103,101,110,100,115,105,115,32,109,97,100,101,109,111, 100,101,114,110,32,111,110,108,121,32,111,110,111,110,108,121,32,116,111,105,109 ,97,103,101,34,32,108,105,110,101,97,114,32,112,97,105,110,116,101,114,97,110, 100,32,110,111,116,114,97,114,101,108,121,32,97,99,114,111,110,121,109,100,101, 108,105,118,101,114,115,104,111,114,116,101,114,48,48,38,97,109,112,59,97,115,32 ,109,97,110,121,119,105,100,116,104,61,34,47,42,32,60,33,91,67,116,105,116,108, 101,32,61,111,102,32,116,104,101,32,108,111,119,101,115,116,32,112,105,99,107, 101,100,32,101,115,99,97,112,101,100,117,115,101,115,32,111,102,112,101,111,112, 108,101,115,32,80,117,98,108,105,99,77,97,116,116,104,101,119,116,97,99,116,105, 99,115,100,97,109,97,103,101,100,119,97,121,32,102,111,114,108,97,119,115,32,111 ,102,101,97,115,121,32,116,111,32,119,105,110,100,111,119,115,116,114,111,110, 103,32,32,115,105,109,112,108,101,125,99,97,116,99,104,40,115,101,118,101,110, 116,104,105,110,102,111,98,111,120,119,101,110,116,32,116,111,112,97,105,110,116 ,101,100,99,105,116,105,122,101,110,73,32,100,111,110,39,116,114,101,116,114,101 ,97,116,46,32,83,111,109,101,32,119,119,46,34,41,59,10,98,111,109,98,105,110,103 ,109,97,105,108,116,111,58,109,97,100,101,32,105,110,46,32,77,97,110,121,32,99, 97,114,114,105,101,115,124,124,123,125,59,119,105,119,111,114,107,32,111,102,115 ,121,110,111,110,121,109,100,101,102,101,97,116,115,102,97,118,111,114,101,100, 111,112,116,105,99,97,108,112,97,103,101,84,114,97,117,110,108,101,115,115,32, 115,101,110,100,105,110,103,108,101,102,116,34,62,60,99,111,109,83,99,111,114,65 ,108,108,32,116,104,101,106,81,117,101,114,121,46,116,111,117,114,105,115,116,67 ,108,97,115,115,105,99,102,97,108,115,101,34,32,87,105,108,104,101,108,109,115, 117,98,117,114,98,115,103,101,110,117,105,110,101,98,105,115,104,111,112,115,46, 115,112,108,105,116,40,103,108,111,98,97,108,32,102,111,108,108,111,119,115,98, 111,100,121,32,111,102,110,111,109,105,110,97,108,67,111,110,116,97,99,116,115, 101,99,117,108,97,114,108,101,102,116,32,116,111,99,104,105,101,102,108,121,45, 104,105,100,100,101,110,45,98,97,110,110,101,114,60,47,108,105,62,10,10,46,32,87 ,104,101,110,32,105,110,32,98,111,116,104,100,105,115,109,105,115,115,69,120,112 ,108,111,114,101,97,108,119,97,121,115,32,118,105,97,32,116,104,101,115,112,97, 195,177,111,108,119,101,108,102,97,114,101,114,117,108,105,110,103,32,97,114,114 ,97,110,103,101,99,97,112,116,97,105,110,104,105,115,32,115,111,110,114,117,108, 101,32,111,102,104,101,32,116,111,111,107,105,116,115,101,108,102,44,61,48,38,97 ,109,112,59,40,99,97,108,108,101,100,115,97,109,112,108,101,115,116,111,32,109, 97,107,101,99,111,109,47,112,97,103,77,97,114,116,105,110,32,75,101,110,110,101, 100,121,97,99,99,101,112,116,115,102,117,108,108,32,111,102,104,97,110,100,108, 101,100,66,101,115,105,100,101,115,47,47,45,45,62,60,47,97,98,108,101,32,116,111 ,116,97,114,103,101,116,115,101,115,115,101,110,99,101,104,105,109,32,116,111,32 ,105,116,115,32,98,121,32,99,111,109,109,111,110,46,109,105,110,101,114,97,108, 116,111,32,116,97,107,101,119,97,121,115,32,116,111,115,46,111,114,103,47,108,97 ,100,118,105,115,101,100,112,101,110,97,108,116,121,115,105,109,112,108,101,58, 105,102,32,116,104,101,121,76,101,116,116,101,114,115,97,32,115,104,111,114,116, 72,101,114,98,101,114,116,115,116,114,105,107,101,115,32,103,114,111,117,112,115 ,46,108,101,110,103,116,104,102,108,105,103,104,116,115,111,118,101,114,108,97, 112,115,108,111,119,108,121,32,108,101,115,115,101,114,32,115,111,99,105,97,108, 32,60,47,112,62,10,9,9,105,116,32,105,110,116,111,114,97,110,107,101,100,32,114, 97,116,101,32,111,102,117,108,62,13,10,32,32,97,116,116,101,109,112,116,112,97, 105,114,32,111,102,109,97,107,101,32,105,116,75,111,110,116,97,107,116,65,110, 116,111,110,105,111,104,97,118,105,110,103,32,114,97,116,105,110,103,115,32,97, 99,116,105,118,101,115,116,114,101,97,109,115,116,114,97,112,112,101,100,34,41, 46,99,115,115,40,104,111,115,116,105,108,101,108,101,97,100,32,116,111,108,105, 116,116,108,101,32,103,114,111,117,112,115,44,80,105,99,116,117,114,101,45,45,62 ,13,10,13,10,32,114,111,119,115,61,34,32,111,98,106,101,99,116,105,110,118,101, 114,115,101,60,102,111,111,116,101,114,67,117,115,116,111,109,86,62,60,92,47,115 ,99,114,115,111,108,118,105,110,103,67,104,97,109,98,101,114,115,108,97,118,101, 114,121,119,111,117,110,100,101,100,119,104,101,114,101,97,115,33,61,32,39,117, 110,100,102,111,114,32,97,108,108,112,97,114,116,108,121,32,45,114,105,103,104, 116,58,65,114,97,98,105,97,110,98,97,99,107,101,100,32,99,101,110,116,117,114, 121,117,110,105,116,32,111,102,109,111,98,105,108,101,45,69,117,114,111,112,101, 44,105,115,32,104,111,109,101,114,105,115,107,32,111,102,100,101,115,105,114,101 ,100,67,108,105,110,116,111,110,99,111,115,116,32,111,102,97,103,101,32,111,102, 32,98,101,99,111,109,101,32,110,111,110,101,32,111,102,112,38,113,117,111,116,59 ,77,105,100,100,108,101,32,101,97,100,39,41,91,48,67,114,105,116,105,99,115,115, 116,117,100,105,111,115,62,38,99,111,112,121,59,103,114,111,117,112,34,62,97,115 ,115,101,109,98,108,109,97,107,105,110,103,32,112,114,101,115,115,101,100,119, 105,100,103,101,116,46,112,115,58,34,32,63,32,114,101,98,117,105,108,116,98,121, 32,115,111,109,101,70,111,114,109,101,114,32,101,100,105,116,111,114,115,100,101 ,108,97,121,101,100,67,97,110,111,110,105,99,104,97,100,32,116,104,101,112,117, 115,104,105,110,103,99,108,97,115,115,61,34,98,117,116,32,97,114,101,112,97,114, 116,105,97,108,66,97,98,121,108,111,110,98,111,116,116,111,109,32,99,97,114,114, 105,101,114,67,111,109,109,97,110,100,105,116,115,32,117,115,101,65,115,32,119, 105,116,104,99,111,117,114,115,101,115,97,32,116,104,105,114,100,100,101,110,111 ,116,101,115,97,108,115,111,32,105,110,72,111,117,115,116,111,110,50,48,112,120, 59,34,62,97,99,99,117,115,101,100,100,111,117,98,108,101,32,103,111,97,108,32, 111,102,70,97,109,111,117,115,32,41,46,98,105,110,100,40,112,114,105,101,115,116 ,115,32,79,110,108,105,110,101,105,110,32,74,117,108,121,115,116,32,43,32,34,103 ,99,111,110,115,117,108,116,100,101,99,105,109,97,108,104,101,108,112,102,117, 108,114,101,118,105,118,101,100,105,115,32,118,101,114,121,114,39,43,39,105,112, 116,108,111,115,105,110,103,32,102,101,109,97,108,101,115,105,115,32,97,108,115, 111,115,116,114,105,110,103,115,100,97,121,115,32,111,102,97,114,114,105,118,97, 108,102,117,116,117,114,101,32,60,111,98,106,101,99,116,102,111,114,99,105,110, 103,83,116,114,105,110,103,40,34,32,47,62,10,9,9,104,101,114,101,32,105,115,101, 110,99,111,100,101,100,46,32,32,84,104,101,32,98,97,108,108,111,111,110,100,111, 110,101,32,98,121,47,99,111,109,109,111,110,98,103,99,111,108,111,114,108,97,119 ,32,111,102,32,73,110,100,105,97,110,97,97,118,111,105,100,101,100,98,117,116,32 ,116,104,101,50,112,120,32,51,112,120,106,113,117,101,114,121,46,97,102,116,101, 114,32,97,112,111,108,105,99,121,46,109,101,110,32,97,110,100,102,111,111,116, 101,114,45,61,32,116,114,117,101,59,102,111,114,32,117,115,101,115,99,114,101, 101,110,46,73,110,100,105,97,110,32,105,109,97,103,101,32,61,102,97,109,105,108, 121,44,104,116,116,112,58,47,47,32,38,110,98,115,112,59,100,114,105,118,101,114, 115,101,116,101,114,110,97,108,115,97,109,101,32,97,115,110,111,116,105,99,101, 100,118,105,101,119,101,114,115,125,41,40,41,59,10,32,105,115,32,109,111,114,101 ,115,101,97,115,111,110,115,102,111,114,109,101,114,32,116,104,101,32,110,101, 119,105,115,32,106,117,115,116,99,111,110,115,101,110,116,32,83,101,97,114,99, 104,119,97,115,32,116,104,101,119,104,121,32,116,104,101,115,104,105,112,112,101 ,100,98,114,62,60,98,114,62,119,105,100,116,104,58,32,104,101,105,103,104,116,61 ,109,97,100,101,32,111,102,99,117,105,115,105,110,101,105,115,32,116,104,97,116, 97,32,118,101,114,121,32,65,100,109,105,114,97,108,32,102,105,120,101,100,59,110 ,111,114,109,97,108,32,77,105,115,115,105,111,110,80,114,101,115,115,44,32,111, 110,116,97,114,105,111,99,104,97,114,115,101,116,116,114,121,32,116,111,32,105, 110,118,97,100,101,100,61,34,116,114,117,101,34,115,112,97,99,105,110,103,105, 115,32,109,111,115,116,97,32,109,111,114,101,32,116,111,116,97,108,108,121,102, 97,108,108,32,111,102,125,41,59,13,10,32,32,105,109,109,101,110,115,101,116,105, 109,101,32,105,110,115,101,116,32,111,117,116,115,97,116,105,115,102,121,116,111 ,32,102,105,110,100,100,111,119,110,32,116,111,108,111,116,32,111,102,32,80,108, 97,121,101,114,115,105,110,32,74,117,110,101,113,117,97,110,116,117,109,110,111, 116,32,116,104,101,116,105,109,101,32,116,111,100,105,115,116,97,110,116,70,105, 110,110,105,115,104,115,114,99,32,61,32,40,115,105,110,103,108,101,32,104,101, 108,112,32,111,102,71,101,114,109,97,110,32,108,97,119,32,97,110,100,108,97,98, 101,108,101,100,102,111,114,101,115,116,115,99,111,111,107,105,110,103,115,112, 97,99,101,34,62,104,101,97,100,101,114,45,119,101,108,108,32,97,115,83,116,97, 110,108,101,121,98,114,105,100,103,101,115,47,103,108,111,98,97,108,67,114,111, 97,116,105,97,32,65,98,111,117,116,32,91,48,93,59,10,32,32,105,116,44,32,97,110, 100,103,114,111,117,112,101,100,98,101,105,110,103,32,97,41,123,116,104,114,111, 119,104,101,32,109,97,100,101,108,105,103,104,116,101,114,101,116,104,105,99,97, 108,70,70,70,70,70,70,34,98,111,116,116,111,109,34,108,105,107,101,32,97,32,101, 109,112,108,111,121,115,108,105,118,101,32,105,110,97,115,32,115,101,101,110,112 ,114,105,110,116,101,114,109,111,115,116,32,111,102,117,98,45,108,105,110,107, 114,101,106,101,99,116,115,97,110,100,32,117,115,101,105,109,97,103,101,34,62, 115,117,99,99,101,101,100,102,101,101,100,105,110,103,78,117,99,108,101,97,114, 105,110,102,111,114,109,97,116,111,32,104,101,108,112,87,111,109,101,110,39,115, 78,101,105,116,104,101,114,77,101,120,105,99,97,110,112,114,111,116,101,105,110, 60,116,97,98,108,101,32,98,121,32,109,97,110,121,104,101,97,108,116,104,121,108, 97,119,115,117,105,116,100,101,118,105,115,101,100,46,112,117,115,104,40,123,115 ,101,108,108,101,114,115,115,105,109,112,108,121,32,84,104,114,111,117,103,104, 46,99,111,111,107,105,101,32,73,109,97,103,101,40,111,108,100,101,114,34,62,117, 115,46,106,115,34,62,32,83,105,110,99,101,32,117,110,105,118,101,114,115,108,97, 114,103,101,114,32,111,112,101,110,32,116,111,33,45,45,32,101,110,100,108,105, 101,115,32,105,110,39,93,41,59,13,10,32,32,109,97,114,107,101,116,119,104,111,32 ,105,115,32,40,34,68,79,77,67,111,109,97,110,97,103,101,100,111,110,101,32,102, 111,114,116,121,112,101,111,102,32,75,105,110,103,100,111,109,112,114,111,102, 105,116,115,112,114,111,112,111,115,101,116,111,32,115,104,111,119,99,101,110, 116,101,114,59,109,97,100,101,32,105,116,100,114,101,115,115,101,100,119,101,114 ,101,32,105,110,109,105,120,116,117,114,101,112,114,101,99,105,115,101,97,114, 105,115,105,110,103,115,114,99,32,61,32,39,109,97,107,101,32,97,32,115,101,99, 117,114,101,100,66,97,112,116,105,115,116,118,111,116,105,110,103,32,10,9,9,118, 97,114,32,77,97,114,99,104,32,50,103,114,101,119,32,117,112,67,108,105,109,97, 116,101,46,114,101,109,111,118,101,115,107,105,108,108,101,100,119,97,121,32,116 ,104,101,60,47,104,101,97,100,62,102,97,99,101,32,111,102,97,99,116,105,110,103, 32,114,105,103,104,116,34,62,116,111,32,119,111,114,107,114,101,100,117,99,101, 115,104,97,115,32,104,97,100,101,114,101,99,116,101,100,115,104,111,119,40,41,59 ,97,99,116,105,111,110,61,98,111,111,107,32,111,102,97,110,32,97,114,101,97,61, 61,32,34,104,116,116,60,104,101,97,100,101,114,10,60,104,116,109,108,62,99,111, 110,102,111,114,109,102,97,99,105,110,103,32,99,111,111,107,105,101,46,114,101, 108,121,32,111,110,104,111,115,116,101,100,32,46,99,117,115,116,111,109,104,101, 32,119,101,110,116,98,117,116,32,102,111,114,115,112,114,101,97,100,32,70,97,109 ,105,108,121,32,97,32,109,101,97,110,115,111,117,116,32,116,104,101,102,111,114, 117,109,115,46,102,111,111,116,97,103,101,34,62,77,111,98,105,108,67,108,101,109 ,101,110,116,115,34,32,105,100,61,34,97,115,32,104,105,103,104,105,110,116,101, 110,115,101,45,45,62,60,33,45,45,102,101,109,97,108,101,32,105,115,32,115,101, 101,110,105,109,112,108,105,101,100,115,101,116,32,116,104,101,97,32,115,116,97, 116,101,97,110,100,32,104,105,115,102,97,115,116,101,115,116,98,101,115,105,100, 101,115,98,117,116,116,111,110,95,98,111,117,110,100,101,100,34,62,60,105,109, 103,32,73,110,102,111,98,111,120,101,118,101,110,116,115,44,97,32,121,111,117, 110,103,97,110,100,32,97,114,101,78,97,116,105,118,101,32,99,104,101,97,112,101, 114,84,105,109,101,111,117,116,97,110,100,32,104,97,115,101,110,103,105,110,101, 115,119,111,110,32,116,104,101,40,109,111,115,116,108,121,114,105,103,104,116,58 ,32,102,105,110,100,32,97,32,45,98,111,116,116,111,109,80,114,105,110,99,101,32, 97,114,101,97,32,111,102,109,111,114,101,32,111,102,115,101,97,114,99,104,95,110 ,97,116,117,114,101,44,108,101,103,97,108,108,121,112,101,114,105,111,100,44,108 ,97,110,100,32,111,102,111,114,32,119,105,116,104,105,110,100,117,99,101,100,112 ,114,111,118,105,110,103,109,105,115,115,105,108,101,108,111,99,97,108,108,121, 65,103,97,105,110,115,116,116,104,101,32,119,97,121,107,38,113,117,111,116,59, 112,120,59,34,62,13,10,112,117,115,104,101,100,32,97,98,97,110,100,111,110,110, 117,109,101,114,97,108,67,101,114,116,97,105,110,73,110,32,116,104,105,115,109, 111,114,101,32,105,110,111,114,32,115,111,109,101,110,97,109,101,32,105,115,97, 110,100,44,32,105,110,99,114,111,119,110,101,100,73,83,66,78,32,48,45,99,114,101 ,97,116,101,115,79,99,116,111,98,101,114,109,97,121,32,110,111,116,99,101,110, 116,101,114,32,108,97,116,101,32,105,110,68,101,102,101,110,99,101,101,110,97,99 ,116,101,100,119,105,115,104,32,116,111,98,114,111,97,100,108,121,99,111,111,108 ,105,110,103,111,110,108,111,97,100,61,105,116,46,32,84,104,101,114,101,99,111, 118,101,114,77,101,109,98,101,114,115,104,101,105,103,104,116,32,97,115,115,117, 109,101,115,60,104,116,109,108,62,10,112,101,111,112,108,101,46,105,110,32,111, 110,101,32,61,119,105,110,100,111,119,102,111,111,116,101,114,95,97,32,103,111, 111,100,32,114,101,107,108,97,109,97,111,116,104,101,114,115,44,116,111,32,116, 104,105,115,95,99,111,111,107,105,101,112,97,110,101,108,34,62,76,111,110,100, 111,110,44,100,101,102,105,110,101,115,99,114,117,115,104,101,100,98,97,112,116, 105,115,109,99,111,97,115,116,97,108,115,116,97,116,117,115,32,116,105,116,108, 101,34,32,109,111,118,101,32,116,111,108,111,115,116,32,105,110,98,101,116,116, 101,114,32,105,109,112,108,105,101,115,114,105,118,97,108,114,121,115,101,114, 118,101,114,115,32,83,121,115,116,101,109,80,101,114,104,97,112,115,101,115,32, 97,110,100,32,99,111,110,116,101,110,100,102,108,111,119,105,110,103,108,97,115, 116,101,100,32,114,105,115,101,32,105,110,71,101,110,101,115,105,115,118,105,101 ,119,32,111,102,114,105,115,105,110,103,32,115,101,101,109,32,116,111,98,117,116 ,32,105,110,32,98,97,99,107,105,110,103,104,101,32,119,105,108,108,103,105,118, 101,110,32,97,103,105,118,105,110,103,32,99,105,116,105,101,115,46,102,108,111, 119,32,111,102,32,76,97,116,101,114,32,97,108,108,32,98,117,116,72,105,103,104, 119,97,121,111,110,108,121,32,98,121,115,105,103,110,32,111,102,104,101,32,100, 111,101,115,100,105,102,102,101,114,115,98,97,116,116,101,114,121,38,97,109,112, 59,108,97,115,105,110,103,108,101,115,116,104,114,101,97,116,115,105,110,116,101 ,103,101,114,116,97,107,101,32,111,110,114,101,102,117,115,101,100,99,97,108,108 ,101,100,32,61,85,83,38,97,109,112,83,101,101,32,116,104,101,110,97,116,105,118, 101,115,98,121,32,116,104,105,115,115,121,115,116,101,109,46,104,101,97,100,32, 111,102,58,104,111,118,101,114,44,108,101,115,98,105,97,110,115,117,114,110,97, 109,101,97,110,100,32,97,108,108,99,111,109,109,111,110,47,104,101,97,100,101, 114,95,95,112,97,114,97,109,115,72,97,114,118,97,114,100,47,112,105,120,101,108, 46,114,101,109,111,118,97,108,115,111,32,108,111,110,103,114,111,108,101,32,111, 102,106,111,105,110,116,108,121,115,107,121,115,99,114,97,85,110,105,99,111,100, 101,98,114,32,47,62,13,10,65,116,108,97,110,116,97,110,117,99,108,101,117,115,67 ,111,117,110,116,121,44,112,117,114,101,108,121,32,99,111,117,110,116,34,62,101, 97,115,105,108,121,32,98,117,105,108,100,32,97,111,110,99,108,105,99,107,97,32, 103,105,118,101,110,112,111,105,110,116,101,114,104,38,113,117,111,116,59,101, 118,101,110,116,115,32,101,108,115,101,32,123,10,100,105,116,105,111,110,115,110 ,111,119,32,116,104,101,44,32,119,105,116,104,32,109,97,110,32,119,104,111,111, 114,103,47,87,101,98,111,110,101,32,97,110,100,99,97,118,97,108,114,121,72,101, 32,100,105,101,100,115,101,97,116,116,108,101,48,48,44,48,48,48,32,123,119,105, 110,100,111,119,104,97,118,101,32,116,111,105,102,40,119,105,110,100,97,110,100, 32,105,116,115,115,111,108,101,108,121,32,109,38,113,117,111,116,59,114,101,110, 101,119,101,100,68,101,116,114,111,105,116,97,109,111,110,103,115,116,101,105, 116,104,101,114,32,116,104,101,109,32,105,110,83,101,110,97,116,111,114,85,115, 60,47,97,62,60,75,105,110,103,32,111,102,70,114,97,110,99,105,115,45,112,114,111 ,100,117,99,104,101,32,117,115,101,100,97,114,116,32,97,110,100,104,105,109,32, 97,110,100,117,115,101,100,32,98,121,115,99,111,114,105,110,103,97,116,32,104, 111,109,101,116,111,32,104,97,118,101,114,101,108,97,116,101,115,105,98,105,108, 105,116,121,102,97,99,116,105,111,110,66,117,102,102,97,108,111,108,105,110,107, 34,62,60,119,104,97,116,32,104,101,102,114,101,101,32,116,111,67,105,116,121,32, 111,102,99,111,109,101,32,105,110,115,101,99,116,111,114,115,99,111,117,110,116, 101,100,111,110,101,32,100,97,121,110,101,114,118,111,117,115,115,113,117,97,114 ,101,32,125,59,105,102,40,103,111,105,110,32,119,104,97,116,105,109,103,34,32,97 ,108,105,115,32,111,110,108,121,115,101,97,114,99,104,47,116,117,101,115,100,97, 121,108,111,111,115,101,108,121,83,111,108,111,109,111,110,115,101,120,117,97, 108,32,45,32,60,97,32,104,114,109,101,100,105,117,109,34,68,79,32,78,79,84,32,70 ,114,97,110,99,101,44,119,105,116,104,32,97,32,119,97,114,32,97,110,100,115,101, 99,111,110,100,32,116,97,107,101,32,97,32,62,13,10,13,10,13,10,109,97,114,107, 101,116,46,104,105,103,104,119,97,121,100,111,110,101,32,105,110,99,116,105,118, 105,116,121,34,108,97,115,116,34,62,111,98,108,105,103,101,100,114,105,115,101, 32,116,111,34,117,110,100,101,102,105,109,97,100,101,32,116,111,32,69,97,114,108 ,121,32,112,114,97,105,115,101,100,105,110,32,105,116,115,32,102,111,114,32,104, 105,115,97,116,104,108,101,116,101,74,117,112,105,116,101,114,89,97,104,111,111, 33,32,116,101,114,109,101,100,32,115,111,32,109,97,110,121,114,101,97,108,108, 121,32,115,46,32,84,104,101,32,97,32,119,111,109,97,110,63,118,97,108,117,101,61 ,100,105,114,101,99,116,32,114,105,103,104,116,34,32,98,105,99,121,99,108,101,97 ,99,105,110,103,61,34,100,97,121,32,97,110,100,115,116,97,116,105,110,103,82,97, 116,104,101,114,44,104,105,103,104,101,114,32,79,102,102,105,99,101,32,97,114, 101,32,110,111,119,116,105,109,101,115,44,32,119,104,101,110,32,97,32,112,97,121 ,32,102,111,114,111,110,32,116,104,105,115,45,108,105,110,107,34,62,59,98,111, 114,100,101,114,97,114,111,117,110,100,32,97,110,110,117,97,108,32,116,104,101, 32,78,101,119,112,117,116,32,116,104,101,46,99,111,109,34,32,116,97,107,105,110, 32,116,111,97,32,98,114,105,101,102,40,105,110,32,116,104,101,103,114,111,117, 112,115,46,59,32,119,105,100,116,104,101,110,122,121,109,101,115,115,105,109,112 ,108,101,32,105,110,32,108,97,116,101,123,114,101,116,117,114,110,116,104,101, 114,97,112,121,97,32,112,111,105,110,116,98,97,110,110,105,110,103,105,110,107, 115,34,62,10,40,41,59,34,32,114,101,97,32,112,108,97,99,101,92,117,48,48,51,67, 97,97,98,111,117,116,32,97,116,114,62,13,10,9,9,99,99,111,117,110,116,32,103,105 ,118,101,115,32,97,60,83,67,82,73,80,84,82,97,105,108,119,97,121,116,104,101,109 ,101,115,47,116,111,111,108,98,111,120,66,121,73,100,40,34,120,104,117,109,97, 110,115,44,119,97,116,99,104,101,115,105,110,32,115,111,109,101,32,105,102,32,40 ,119,105,99,111,109,105,110,103,32,102,111,114,109,97,116,115,32,85,110,100,101, 114,32,98,117,116,32,104,97,115,104,97,110,100,101,100,32,109,97,100,101,32,98, 121,116,104,97,110,32,105,110,102,101,97,114,32,111,102,100,101,110,111,116,101, 100,47,105,102,114,97,109,101,108,101,102,116,32,105,110,118,111,108,116,97,103, 101,105,110,32,101,97,99,104,97,38,113,117,111,116,59,98,97,115,101,32,111,102, 73,110,32,109,97,110,121,117,110,100,101,114,103,111,114,101,103,105,109,101,115 ,97,99,116,105,111,110,32,60,47,112,62,13,10,60,117,115,116,111,109,86,97,59,38, 103,116,59,60,47,105,109,112,111,114,116,115,111,114,32,116,104,97,116,109,111, 115,116,108,121,32,38,97,109,112,59,114,101,32,115,105,122,101,61,34,60,47,97,62 ,60,47,104,97,32,99,108,97,115,115,112,97,115,115,105,118,101,72,111,115,116,32, 61,32,87,104,101,116,104,101,114,102,101,114,116,105,108,101,86,97,114,105,111, 117,115,61,91,93,59,40,102,117,99,97,109,101,114,97,115,47,62,60,47,116,100,62, 97,99,116,115,32,97,115,73,110,32,115,111,109,101,62,13,10,13,10,60,33,111,114, 103,97,110,105,115,32,60,98,114,32,47,62,66,101,105,106,105,110,103,99,97,116,97 ,108,195,160,100,101,117,116,115,99,104,101,117,114,111,112,101,117,101,117,115, 107,97,114,97,103,97,101,105,108,103,101,115,118,101,110,115,107,97,101,115,112, 97,195,177,97,109,101,110,115,97,106,101,117,115,117,97,114,105,111,116,114,97, 98,97,106,111,109,195,169,120,105,99,111,112,195,161,103,105,110,97,115,105,101, 109,112,114,101,115,105,115,116,101,109,97,111,99,116,117,98,114,101,100,117,114 ,97,110,116,101,97,195,177,97,100,105,114,101,109,112,114,101,115,97,109,111,109 ,101,110,116,111,110,117,101,115,116,114,111,112,114,105,109,101,114,97,116,114, 97,118,195,169,115,103,114,97,99,105,97,115,110,117,101,115,116,114,97,112,114, 111,99,101,115,111,101,115,116,97,100,111,115,99,97,108,105,100,97,100,112,101, 114,115,111,110,97,110,195,186,109,101,114,111,97,99,117,101,114,100,111,109,195 ,186,115,105,99,97,109,105,101,109,98,114,111,111,102,101,114,116,97,115,97,108, 103,117,110,111,115,112,97,195,173,115,101,115,101,106,101,109,112,108,111,100, 101,114,101,99,104,111,97,100,101,109,195,161,115,112,114,105,118,97,100,111,97, 103,114,101,103,97,114,101,110,108,97,99,101,115,112,111,115,105,98,108,101,104, 111,116,101,108,101,115,115,101,118,105,108,108,97,112,114,105,109,101,114,111, 195,186,108,116,105,109,111,101,118,101,110,116,111,115,97,114,99,104,105,118, 111,99,117,108,116,117,114,97,109,117,106,101,114,101,115,101,110,116,114,97,100 ,97,97,110,117,110,99,105,111,101,109,98,97,114,103,111,109,101,114,99,97,100, 111,103,114,97,110,100,101,115,101,115,116,117,100,105,111,109,101,106,111,114, 101,115,102,101,98,114,101,114,111,100,105,115,101,195,177,111,116,117,114,105, 115,109,111,99,195,179,100,105,103,111,112,111,114,116,97,100,97,101,115,112,97, 99,105,111,102,97,109,105,108,105,97,97,110,116,111,110,105,111,112,101,114,109, 105,116,101,103,117,97,114,100,97,114,97,108,103,117,110,97,115,112,114,101,99, 105,111,115,97,108,103,117,105,101,110,115,101,110,116,105,100,111,118,105,115, 105,116,97,115,116,195,173,116,117,108,111,99,111,110,111,99,101,114,115,101,103 ,117,110,100,111,99,111,110,115,101,106,111,102,114,97,110,99,105,97,109,105,110 ,117,116,111,115,115,101,103,117,110,100,97,116,101,110,101,109,111,115,101,102, 101,99,116,111,115,109,195,161,108,97,103,97,115,101,115,105,195,179,110,114,101 ,118,105,115,116,97,103,114,97,110,97,100,97,99,111,109,112,114,97,114,105,110, 103,114,101,115,111,103,97,114,99,195,173,97,97,99,99,105,195,179,110,101,99,117 ,97,100,111,114,113,117,105,101,110,101,115,105,110,99,108,117,115,111,100,101, 98,101,114,195,161,109,97,116,101,114,105,97,104,111,109,98,114,101,115,109,117, 101,115,116,114,97,112,111,100,114,195,173,97,109,97,195,177,97,110,97,195,186, 108,116,105,109,97,101,115,116,97,109,111,115,111,102,105,99,105,97,108,116,97, 109,98,105,101,110,110,105,110,103,195,186,110,115,97,108,117,100,111,115,112, 111,100,101,109,111,115,109,101,106,111,114,97,114,112,111,115,105,116,105,111, 110,98,117,115,105,110,101,115,115,104,111,109,101,112,97,103,101,115,101,99,117 ,114,105,116,121,108,97,110,103,117,97,103,101,115,116,97,110,100,97,114,100,99, 97,109,112,97,105,103,110,102,101,97,116,117,114,101,115,99,97,116,101,103,111, 114,121,101,120,116,101,114,110,97,108,99,104,105,108,100,114,101,110,114,101, 115,101,114,118,101,100,114,101,115,101,97,114,99,104,101,120,99,104,97,110,103, 101,102,97,118,111,114,105,116,101,116,101,109,112,108,97,116,101,109,105,108, 105,116,97,114,121,105,110,100,117,115,116,114,121,115,101,114,118,105,99,101, 115,109,97,116,101,114,105,97,108,112,114,111,100,117,99,116,115,122,45,105,110, 100,101,120,58,99,111,109,109,101,110,116,115,115,111,102,116,119,97,114,101,99, 111,109,112,108,101,116,101,99,97,108,101,110,100,97,114,112,108,97,116,102,111, 114,109,97,114,116,105,99,108,101,115,114,101,113,117,105,114,101,100,109,111, 118,101,109,101,110,116,113,117,101,115,116,105,111,110,98,117,105,108,100,105, 110,103,112,111,108,105,116,105,99,115,112,111,115,115,105,98,108,101,114,101, 108,105,103,105,111,110,112,104,121,115,105,99,97,108,102,101,101,100,98,97,99, 107,114,101,103,105,115,116,101,114,112,105,99,116,117,114,101,115,100,105,115, 97,98,108,101,100,112,114,111,116,111,99,111,108,97,117,100,105,101,110,99,101, 115,101,116,116,105,110,103,115,97,99,116,105,118,105,116,121,101,108,101,109, 101,110,116,115,108,101,97,114,110,105,110,103,97,110,121,116,104,105,110,103,97 ,98,115,116,114,97,99,116,112,114,111,103,114,101,115,115,111,118,101,114,118, 105,101,119,109,97,103,97,122,105,110,101,101,99,111,110,111,109,105,99,116,114, 97,105,110,105,110,103,112,114,101,115,115,117,114,101,118,97,114,105,111,117, 115,32,60,115,116,114,111,110,103,62,112,114,111,112,101,114,116,121,115,104,111 ,112,112,105,110,103,116,111,103,101,116,104,101,114,97,100,118,97,110,99,101, 100,98,101,104,97,118,105,111,114,100,111,119,110,108,111,97,100,102,101,97,116, 117,114,101,100,102,111,111,116,98,97,108,108,115,101,108,101,99,116,101,100,76, 97,110,103,117,97,103,101,100,105,115,116,97,110,99,101,114,101,109,101,109,98, 101,114,116,114,97,99,107,105,110,103,112,97,115,115,119,111,114,100,109,111,100 ,105,102,105,101,100,115,116,117,100,101,110,116,115,100,105,114,101,99,116,108, 121,102,105,103,104,116,105,110,103,110,111,114,116,104,101,114,110,100,97,116, 97,98,97,115,101,102,101,115,116,105,118,97,108,98,114,101,97,107,105,110,103, 108,111,99,97,116,105,111,110,105,110,116,101,114,110,101,116,100,114,111,112, 100,111,119,110,112,114,97,99,116,105,99,101,101,118,105,100,101,110,99,101,102, 117,110,99,116,105,111,110,109,97,114,114,105,97,103,101,114,101,115,112,111,110 ,115,101,112,114,111,98,108,101,109,115,110,101,103,97,116,105,118,101,112,114, 111,103,114,97,109,115,97,110,97,108,121,115,105,115,114,101,108,101,97,115,101, 100,98,97,110,110,101,114,34,62,112,117,114,99,104,97,115,101,112,111,108,105,99 ,105,101,115,114,101,103,105,111,110,97,108,99,114,101,97,116,105,118,101,97,114 ,103,117,109,101,110,116,98,111,111,107,109,97,114,107,114,101,102,101,114,114, 101,114,99,104,101,109,105,99,97,108,100,105,118,105,115,105,111,110,99,97,108, 108,98,97,99,107,115,101,112,97,114,97,116,101,112,114,111,106,101,99,116,115,99 ,111,110,102,108,105,99,116,104,97,114,100,119,97,114,101,105,110,116,101,114, 101,115,116,100,101,108,105,118,101,114,121,109,111,117,110,116,97,105,110,111, 98,116,97,105,110,101,100,61,32,102,97,108,115,101,59,102,111,114,40,118,97,114, 32,97,99,99,101,112,116,101,100,99,97,112,97,99,105,116,121,99,111,109,112,117, 116,101,114,105,100,101,110,116,105,116,121,97,105,114,99,114,97,102,116,101,109 ,112,108,111,121,101,100,112,114,111,112,111,115,101,100,100,111,109,101,115,116 ,105,99,105,110,99,108,117,100,101,115,112,114,111,118,105,100,101,100,104,111, 115,112,105,116,97,108,118,101,114,116,105,99,97,108,99,111,108,108,97,112,115, 101,97,112,112,114,111,97,99,104,112,97,114,116,110,101,114,115,108,111,103,111, 34,62,60,97,100,97,117,103,104,116,101,114,97,117,116,104,111,114,34,32,99,117, 108,116,117,114,97,108,102,97,109,105,108,105,101,115,47,105,109,97,103,101,115, 47,97,115,115,101,109,98,108,121,112,111,119,101,114,102,117,108,116,101,97,99, 104,105,110,103,102,105,110,105,115,104,101,100,100,105,115,116,114,105,99,116, 99,114,105,116,105,99,97,108,99,103,105,45,98,105,110,47,112,117,114,112,111,115 ,101,115,114,101,113,117,105,114,101,115,101,108,101,99,116,105,111,110,98,101, 99,111,109,105,110,103,112,114,111,118,105,100,101,115,97,99,97,100,101,109,105, 99,101,120,101,114,99,105,115,101,97,99,116,117,97,108,108,121,109,101,100,105, 99,105,110,101,99,111,110,115,116,97,110,116,97,99,99,105,100,101,110,116,77,97, 103,97,122,105,110,101,100,111,99,117,109,101,110,116,115,116,97,114,116,105,110 ,103,98,111,116,116,111,109,34,62,111,98,115,101,114,118,101,100,58,32,38,113, 117,111,116,59,101,120,116,101,110,100,101,100,112,114,101,118,105,111,117,115, 83,111,102,116,119,97,114,101,99,117,115,116,111,109,101,114,100,101,99,105,115, 105,111,110,115,116,114,101,110,103,116,104,100,101,116,97,105,108,101,100,115, 108,105,103,104,116,108,121,112,108,97,110,110,105,110,103,116,101,120,116,97, 114,101,97,99,117,114,114,101,110,99,121,101,118,101,114,121,111,110,101,115,116 ,114,97,105,103,104,116,116,114,97,110,115,102,101,114,112,111,115,105,116,105, 118,101,112,114,111,100,117,99,101,100,104,101,114,105,116,97,103,101,115,104, 105,112,112,105,110,103,97,98,115,111,108,117,116,101,114,101,99,101,105,118,101 ,100,114,101,108,101,118,97,110,116,98,117,116,116,111,110,34,32,118,105,111,108 ,101,110,99,101,97,110,121,119,104,101,114,101,98,101,110,101,102,105,116,115, 108,97,117,110,99,104,101,100,114,101,99,101,110,116,108,121,97,108,108,105,97, 110,99,101,102,111,108,108,111,119,101,100,109,117,108,116,105,112,108,101,98, 117,108,108,101,116,105,110,105,110,99,108,117,100,101,100,111,99,99,117,114,114 ,101,100,105,110,116,101,114,110,97,108,36,40,116,104,105,115,41,46,114,101,112, 117,98,108,105,99,62,60,116,114,62,60,116,100,99,111,110,103,114,101,115,115,114 ,101,99,111,114,100,101,100,117,108,116,105,109,97,116,101,115,111,108,117,116, 105,111,110,60,117,108,32,105,100,61,34,100,105,115,99,111,118,101,114,72,111, 109,101,60,47,97,62,119,101,98,115,105,116,101,115,110,101,116,119,111,114,107, 115,97,108,116,104,111,117,103,104,101,110,116,105,114,101,108,121,109,101,109, 111,114,105,97,108,109,101,115,115,97,103,101,115,99,111,110,116,105,110,117,101 ,97,99,116,105,118,101,34,62,115,111,109,101,119,104,97,116,118,105,99,116,111, 114,105,97,87,101,115,116,101,114,110,32,32,116,105,116,108,101,61,34,76,111,99, 97,116,105,111,110,99,111,110,116,114,97,99,116,118,105,115,105,116,111,114,115, 68,111,119,110,108,111,97,100,119,105,116,104,111,117,116,32,114,105,103,104,116 ,34,62,10,109,101,97,115,117,114,101,115,119,105,100,116,104,32,61,32,118,97,114 ,105,97,98,108,101,105,110,118,111,108,118,101,100,118,105,114,103,105,110,105, 97,110,111,114,109,97,108,108,121,104,97,112,112,101,110,101,100,97,99,99,111, 117,110,116,115,115,116,97,110,100,105,110,103,110,97,116,105,111,110,97,108,82, 101,103,105,115,116,101,114,112,114,101,112,97,114,101,100,99,111,110,116,114, 111,108,115,97,99,99,117,114,97,116,101,98,105,114,116,104,100,97,121,115,116, 114,97,116,101,103,121,111,102,102,105,99,105,97,108,103,114,97,112,104,105,99, 115,99,114,105,109,105,110,97,108,112,111,115,115,105,98,108,121,99,111,110,115, 117,109,101,114,80,101,114,115,111,110,97,108,115,112,101,97,107,105,110,103,118 ,97,108,105,100,97,116,101,97,99,104,105,101,118,101,100,46,106,112,103,34,32,47 ,62,109,97,99,104,105,110,101,115,60,47,104,50,62,10,32,32,107,101,121,119,111, 114,100,115,102,114,105,101,110,100,108,121,98,114,111,116,104,101,114,115,99, 111,109,98,105,110,101,100,111,114,105,103,105,110,97,108,99,111,109,112,111,115 ,101,100,101,120,112,101,99,116,101,100,97,100,101,113,117,97,116,101,112,97,107 ,105,115,116,97,110,102,111,108,108,111,119,34,32,118,97,108,117,97,98,108,101, 60,47,108,97,98,101,108,62,114,101,108,97,116,105,118,101,98,114,105,110,103,105 ,110,103,105,110,99,114,101,97,115,101,103,111,118,101,114,110,111,114,112,108, 117,103,105,110,115,47,76,105,115,116,32,111,102,32,72,101,97,100,101,114,34,62, 34,32,110,97,109,101,61,34,32,40,38,113,117,111,116,59,103,114,97,100,117,97,116 ,101,60,47,104,101,97,100,62,10,99,111,109,109,101,114,99,101,109,97,108,97,121, 115,105,97,100,105,114,101,99,116,111,114,109,97,105,110,116,97,105,110,59,104, 101,105,103,104,116,58,115,99,104,101,100,117,108,101,99,104,97,110,103,105,110, 103,98,97,99,107,32,116,111,32,99,97,116,104,111,108,105,99,112,97,116,116,101, 114,110,115,99,111,108,111,114,58,32,35,103,114,101,97,116,101,115,116,115,117, 112,112,108,105,101,115,114,101,108,105,97,98,108,101,60,47,117,108,62,10,9,9,60 ,115,101,108,101,99,116,32,99,105,116,105,122,101,110,115,99,108,111,116,104,105 ,110,103,119,97,116,99,104,105,110,103,60,108,105,32,105,100,61,34,115,112,101, 99,105,102,105,99,99,97,114,114,121,105,110,103,115,101,110,116,101,110,99,101, 60,99,101,110,116,101,114,62,99,111,110,116,114,97,115,116,116,104,105,110,107, 105,110,103,99,97,116,99,104,40,101,41,115,111,117,116,104,101,114,110,77,105,99 ,104,97,101,108,32,109,101,114,99,104,97,110,116,99,97,114,111,117,115,101,108, 112,97,100,100,105,110,103,58,105,110,116,101,114,105,111,114,46,115,112,108,105 ,116,40,34,108,105,122,97,116,105,111,110,79,99,116,111,98,101,114,32,41,123,114 ,101,116,117,114,110,105,109,112,114,111,118,101,100,45,45,38,103,116,59,10,10, 99,111,118,101,114,97,103,101,99,104,97,105,114,109,97,110,46,112,110,103,34,32, 47,62,115,117,98,106,101,99,116,115,82,105,99,104,97,114,100,32,119,104,97,116, 101,118,101,114,112,114,111,98,97,98,108,121,114,101,99,111,118,101,114,121,98, 97,115,101,98,97,108,108,106,117,100,103,109,101,110,116,99,111,110,110,101,99, 116,46,46,99,115,115,34,32,47,62,32,119,101,98,115,105,116,101,114,101,112,111, 114,116,101,100,100,101,102,97,117,108,116,34,47,62,60,47,97,62,13,10,101,108, 101,99,116,114,105,99,115,99,111,116,108,97,110,100,99,114,101,97,116,105,111, 110,113,117,97,110,116,105,116,121,46,32,73,83,66,78,32,48,100,105,100,32,110, 111,116,32,105,110,115,116,97,110,99,101,45,115,101,97,114,99,104,45,34,32,108, 97,110,103,61,34,115,112,101,97,107,101,114,115,67,111,109,112,117,116,101,114, 99,111,110,116,97,105,110,115,97,114,99,104,105,118,101,115,109,105,110,105,115, 116,101,114,114,101,97,99,116,105,111,110,100,105,115,99,111,117,110,116,73,116, 97,108,105,97,110,111,99,114,105,116,101,114,105,97,115,116,114,111,110,103,108, 121,58,32,39,104,116,116,112,58,39,115,99,114,105,112,116,39,99,111,118,101,114, 105,110,103,111,102,102,101,114,105,110,103,97,112,112,101,97,114,101,100,66,114 ,105,116,105,115,104,32,105,100,101,110,116,105,102,121,70,97,99,101,98,111,111, 107,110,117,109,101,114,111,117,115,118,101,104,105,99,108,101,115,99,111,110,99 ,101,114,110,115,65,109,101,114,105,99,97,110,104,97,110,100,108,105,110,103,100 ,105,118,32,105,100,61,34,87,105,108,108,105,97,109,32,112,114,111,118,105,100, 101,114,95,99,111,110,116,101,110,116,97,99,99,117,114,97,99,121,115,101,99,116, 105,111,110,32,97,110,100,101,114,115,111,110,102,108,101,120,105,98,108,101,67, 97,116,101,103,111,114,121,108,97,119,114,101,110,99,101,60,115,99,114,105,112, 116,62,108,97,121,111,117,116,61,34,97,112,112,114,111,118,101,100,32,109,97,120 ,105,109,117,109,104,101,97,100,101,114,34,62,60,47,116,97,98,108,101,62,83,101, 114,118,105,99,101,115,104,97,109,105,108,116,111,110,99,117,114,114,101,110,116 ,32,99,97,110,97,100,105,97,110,99,104,97,110,110,101,108,115,47,116,104,101,109 ,101,115,47,47,97,114,116,105,99,108,101,111,112,116,105,111,110,97,108,112,111, 114,116,117,103,97,108,118,97,108,117,101,61,34,34,105,110,116,101,114,118,97, 108,119,105,114,101,108,101,115,115,101,110,116,105,116,108,101,100,97,103,101, 110,99,105,101,115,83,101,97,114,99,104,34,32,109,101,97,115,117,114,101,100,116 ,104,111,117,115,97,110,100,115,112,101,110,100,105,110,103,38,104,101,108,108, 105,112,59,110,101,119,32,68,97,116,101,34,32,115,105,122,101,61,34,112,97,103, 101,78,97,109,101,109,105,100,100,108,101,34,32,34,32,47,62,60,47,97,62,104,105, 100,100,101,110,34,62,115,101,113,117,101,110,99,101,112,101,114,115,111,110,97, 108,111,118,101,114,102,108,111,119,111,112,105,110,105,111,110,115,105,108,108, 105,110,111,105,115,108,105,110,107,115,34,62,10,9,60,116,105,116,108,101,62,118 ,101,114,115,105,111,110,115,115,97,116,117,114,100,97,121,116,101,114,109,105, 110,97,108,105,116,101,109,112,114,111,112,101,110,103,105,110,101,101,114,115, 101,99,116,105,111,110,115,100,101,115,105,103,110,101,114,112,114,111,112,111, 115,97,108,61,34,102,97,108,115,101,34,69,115,112,97,195,177,111,108,114,101,108 ,101,97,115,101,115,115,117,98,109,105,116,34,32,101,114,38,113,117,111,116,59, 97,100,100,105,116,105,111,110,115,121,109,112,116,111,109,115,111,114,105,101, 110,116,101,100,114,101,115,111,117,114,99,101,114,105,103,104,116,34,62,60,112, 108,101,97,115,117,114,101,115,116,97,116,105,111,110,115,104,105,115,116,111, 114,121,46,108,101,97,118,105,110,103,32,32,98,111,114,100,101,114,61,99,111,110 ,116,101,110,116,115,99,101,110,116,101,114,34,62,46,10,10,83,111,109,101,32,100 ,105,114,101,99,116,101,100,115,117,105,116,97,98,108,101,98,117,108,103,97,114, 105,97,46,115,104,111,119,40,41,59,100,101,115,105,103,110,101,100,71,101,110, 101,114,97,108,32,99,111,110,99,101,112,116,115,69,120,97,109,112,108,101,115, 119,105,108,108,105,97,109,115,79,114,105,103,105,110,97,108,34,62,60,115,112,97 ,110,62,115,101,97,114,99,104,34,62,111,112,101,114,97,116,111,114,114,101,113, 117,101,115,116,115,97,32,38,113,117,111,116,59,97,108,108,111,119,105,110,103, 68,111,99,117,109,101,110,116,114,101,118,105,115,105,111,110,46,32,10,10,84,104 ,101,32,121,111,117,114,115,101,108,102,67,111,110,116,97,99,116,32,109,105,99, 104,105,103,97,110,69,110,103,108,105,115,104,32,99,111,108,117,109,98,105,97, 112,114,105,111,114,105,116,121,112,114,105,110,116,105,110,103,100,114,105,110, 107,105,110,103,102,97,99,105,108,105,116,121,114,101,116,117,114,110,101,100,67 ,111,110,116,101,110,116,32,111,102,102,105,99,101,114,115,82,117,115,115,105,97 ,110,32,103,101,110,101,114,97,116,101,45,56,56,53,57,45,49,34,105,110,100,105, 99,97,116,101,102,97,109,105,108,105,97,114,32,113,117,97,108,105,116,121,109,97 ,114,103,105,110,58,48,32,99,111,110,116,101,110,116,118,105,101,119,112,111,114 ,116,99,111,110,116,97,99,116,115,45,116,105,116,108,101,34,62,112,111,114,116, 97,98,108,101,46,108,101,110,103,116,104,32,101,108,105,103,105,98,108,101,105, 110,118,111,108,118,101,115,97,116,108,97,110,116,105,99,111,110,108,111,97,100, 61,34,100,101,102,97,117,108,116,46,115,117,112,112,108,105,101,100,112,97,121, 109,101,110,116,115,103,108,111,115,115,97,114,121,10,10,65,102,116,101,114,32, 103,117,105,100,97,110,99,101,60,47,116,100,62,60,116,100,101,110,99,111,100,105 ,110,103,109,105,100,100,108,101,34,62,99,97,109,101,32,116,111,32,100,105,115, 112,108,97,121,115,115,99,111,116,116,105,115,104,106,111,110,97,116,104,97,110, 109,97,106,111,114,105,116,121,119,105,100,103,101,116,115,46,99,108,105,110,105 ,99,97,108,116,104,97,105,108,97,110,100,116,101,97,99,104,101,114,115,60,104, 101,97,100,62,10,9,97,102,102,101,99,116,101,100,115,117,112,112,111,114,116,115 ,112,111,105,110,116,101,114,59,116,111,83,116,114,105,110,103,60,47,115,109,97, 108,108,62,111,107,108,97,104,111,109,97,119,105,108,108,32,98,101,32,105,110, 118,101,115,116,111,114,48,34,32,97,108,116,61,34,104,111,108,105,100,97,121,115 ,82,101,115,111,117,114,99,101,108,105,99,101,110,115,101,100,32,40,119,104,105, 99,104,32,46,32,65,102,116,101,114,32,99,111,110,115,105,100,101,114,118,105,115 ,105,116,105,110,103,101,120,112,108,111,114,101,114,112,114,105,109,97,114,121, 32,115,101,97,114,99,104,34,32,97,110,100,114,111,105,100,34,113,117,105,99,107, 108,121,32,109,101,101,116,105,110,103,115,101,115,116,105,109,97,116,101,59,114 ,101,116,117,114,110,32,59,99,111,108,111,114,58,35,32,104,101,105,103,104,116, 61,97,112,112,114,111,118,97,108,44,32,38,113,117,111,116,59,32,99,104,101,99, 107,101,100,46,109,105,110,46,106,115,34,109,97,103,110,101,116,105,99,62,60,47, 97,62,60,47,104,102,111,114,101,99,97,115,116,46,32,87,104,105,108,101,32,116, 104,117,114,115,100,97,121,100,118,101,114,116,105,115,101,38,101,97,99,117,116, 101,59,104,97,115,67,108,97,115,115,101,118,97,108,117,97,116,101,111,114,100, 101,114,105,110,103,101,120,105,115,116,105,110,103,112,97,116,105,101,110,116, 115,32,79,110,108,105,110,101,32,99,111,108,111,114,97,100,111,79,112,116,105, 111,110,115,34,99,97,109,112,98,101,108,108,60,33,45,45,32,101,110,100,60,47,115 ,112,97,110,62,60,60,98,114,32,47,62,13,10,95,112,111,112,117,112,115,124,115,99 ,105,101,110,99,101,115,44,38,113,117,111,116,59,32,113,117,97,108,105,116,121, 32,87,105,110,100,111,119,115,32,97,115,115,105,103,110,101,100,104,101,105,103, 104,116,58,32,60,98,32,99,108,97,115,115,108,101,38,113,117,111,116,59,32,118,97 ,108,117,101,61,34,32,67,111,109,112,97,110,121,101,120,97,109,112,108,101,115, 60,105,102,114,97,109,101,32,98,101,108,105,101,118,101,115,112,114,101,115,101, 110,116,115,109,97,114,115,104,97,108,108,112,97,114,116,32,111,102,32,112,114, 111,112,101,114,108,121,41,46,10,10,84,104,101,32,116,97,120,111,110,111,109,121 ,109,117,99,104,32,111,102,32,60,47,115,112,97,110,62,10,34,32,100,97,116,97,45, 115,114,116,117,103,117,195,170,115,115,99,114,111,108,108,84,111,32,112,114,111 ,106,101,99,116,60,104,101,97,100,62,13,10,97,116,116,111,114,110,101,121,101, 109,112,104,97,115,105,115,115,112,111,110,115,111,114,115,102,97,110,99,121,98, 111,120,119,111,114,108,100,39,115,32,119,105,108,100,108,105,102,101,99,104,101 ,99,107,101,100,61,115,101,115,115,105,111,110,115,112,114,111,103,114,97,109, 109,112,120,59,102,111,110,116,45,32,80,114,111,106,101,99,116,106,111,117,114, 110,97,108,115,98,101,108,105,101,118,101,100,118,97,99,97,116,105,111,110,116, 104,111,109,112,115,111,110,108,105,103,104,116,105,110,103,97,110,100,32,116, 104,101,32,115,112,101,99,105,97,108,32,98,111,114,100,101,114,61,48,99,104,101, 99,107,105,110,103,60,47,116,98,111,100,121,62,60,98,117,116,116,111,110,32,67, 111,109,112,108,101,116,101,99,108,101,97,114,102,105,120,10,60,104,101,97,100, 62,10,97,114,116,105,99,108,101,32,60,115,101,99,116,105,111,110,102,105,110,100 ,105,110,103,115,114,111,108,101,32,105,110,32,112,111,112,117,108,97,114,32,32, 79,99,116,111,98,101,114,119,101,98,115,105,116,101,32,101,120,112,111,115,117, 114,101,117,115,101,100,32,116,111,32,32,99,104,97,110,103,101,115,111,112,101, 114,97,116,101,100,99,108,105,99,107,105,110,103,101,110,116,101,114,105,110,103 ,99,111,109,109,97,110,100,115,105,110,102,111,114,109,101,100,32,110,117,109,98 ,101,114,115,32,32,60,47,100,105,118,62,99,114,101,97,116,105,110,103,111,110,83 ,117,98,109,105,116,109,97,114,121,108,97,110,100,99,111,108,108,101,103,101,115 ,97,110,97,108,121,116,105,99,108,105,115,116,105,110,103,115,99,111,110,116,97, 99,116,46,108,111,103,103,101,100,73,110,97,100,118,105,115,111,114,121,115,105, 98,108,105,110,103,115,99,111,110,116,101,110,116,34,115,38,113,117,111,116,59, 41,115,46,32,84,104,105,115,32,112,97,99,107,97,103,101,115,99,104,101,99,107,98 ,111,120,115,117,103,103,101,115,116,115,112,114,101,103,110,97,110,116,116,111, 109,111,114,114,111,119,115,112,97,99,105,110,103,61,105,99,111,110,46,112,110, 103,106,97,112,97,110,101,115,101,99,111,100,101,98,97,115,101,98,117,116,116, 111,110,34,62,103,97,109,98,108,105,110,103,115,117,99,104,32,97,115,32,44,32, 119,104,105,108,101,32,60,47,115,112,97,110,62,32,109,105,115,115,111,117,114, 105,115,112,111,114,116,105,110,103,116,111,112,58,49,112,120,32,46,60,47,115, 112,97,110,62,116,101,110,115,105,111,110,115,119,105,100,116,104,61,34,50,108, 97,122,121,108,111,97,100,110,111,118,101,109,98,101,114,117,115,101,100,32,105, 110,32,104,101,105,103,104,116,61,34,99,114,105,112,116,34,62,10,38,110,98,115, 112,59,60,47,60,116,114,62,60,116,100,32,104,101,105,103,104,116,58,50,47,112, 114,111,100,117,99,116,99,111,117,110,116,114,121,32,105,110,99,108,117,100,101, 32,102,111,111,116,101,114,34,32,38,108,116,59,33,45,45,32,116,105,116,108,101, 34,62,60,47,106,113,117,101,114,121,46,60,47,102,111,114,109,62,10,40,231,174, 128,228,189,147,41,40,231,185,129,233,171,148,41,104,114,118,97,116,115,107,105, 105,116,97,108,105,97,110,111,114,111,109,195,162,110,196,131,116,195,188,114, 107,195,167,101,216,167,216,177,216,175,217,136,116,97,109,98,105,195,169,110, 110,111,116,105,99,105,97,115,109,101,110,115,97,106,101,115,112,101,114,115,111 ,110,97,115,100,101,114,101,99,104,111,115,110,97,99,105,111,110,97,108,115,101, 114,118,105,99,105,111,99,111,110,116,97,99,116,111,117,115,117,97,114,105,111, 115,112,114,111,103,114,97,109,97,103,111,98,105,101,114,110,111,101,109,112,114 ,101,115,97,115,97,110,117,110,99,105,111,115,118,97,108,101,110,99,105,97,99, 111,108,111,109,98,105,97,100,101,115,112,117,195,169,115,100,101,112,111,114, 116,101,115,112,114,111,121,101,99,116,111,112,114,111,100,117,99,116,111,112, 195,186,98,108,105,99,111,110,111,115,111,116,114,111,115,104,105,115,116,111, 114,105,97,112,114,101,115,101,110,116,101,109,105,108,108,111,110,101,115,109, 101,100,105,97,110,116,101,112,114,101,103,117,110,116,97,97,110,116,101,114,105 ,111,114,114,101,99,117,114,115,111,115,112,114,111,98,108,101,109,97,115,97,110 ,116,105,97,103,111,110,117,101,115,116,114,111,115,111,112,105,110,105,195,179, 110,105,109,112,114,105,109,105,114,109,105,101,110,116,114,97,115,97,109,195, 169,114,105,99,97,118,101,110,100,101,100,111,114,115,111,99,105,101,100,97,100, 114,101,115,112,101,99,116,111,114,101,97,108,105,122,97,114,114,101,103,105,115 ,116,114,111,112,97,108,97,98,114,97,115,105,110,116,101,114,195,169,115,101,110 ,116,111,110,99,101,115,101,115,112,101,99,105,97,108,109,105,101,109,98,114,111 ,115,114,101,97,108,105,100,97,100,99,195,179,114,100,111,98,97,122,97,114,97, 103,111,122,97,112,195,161,103,105,110,97,115,115,111,99,105,97,108,101,115,98, 108,111,113,117,101,97,114,103,101,115,116,105,195,179,110,97,108,113,117,105, 108,101,114,115,105,115,116,101,109,97,115,99,105,101,110,99,105,97,115,99,111, 109,112,108,101,116,111,118,101,114,115,105,195,179,110,99,111,109,112,108,101, 116,97,101,115,116,117,100,105,111,115,112,195,186,98,108,105,99,97,111,98,106, 101,116,105,118,111,97,108,105,99,97,110,116,101,98,117,115,99,97,100,111,114,99 ,97,110,116,105,100,97,100,101,110,116,114,97,100,97,115,97,99,99,105,111,110, 101,115,97,114,99,104,105,118,111,115,115,117,112,101,114,105,111,114,109,97,121 ,111,114,195,173,97,97,108,101,109,97,110,105,97,102,117,110,99,105,195,179,110, 195,186,108,116,105,109,111,115,104,97,99,105,101,110,100,111,97,113,117,101,108 ,108,111,115,101,100,105,99,105,195,179,110,102,101,114,110,97,110,100,111,97, 109,98,105,101,110,116,101,102,97,99,101,98,111,111,107,110,117,101,115,116,114, 97,115,99,108,105,101,110,116,101,115,112,114,111,99,101,115,111,115,98,97,115, 116,97,110,116,101,112,114,101,115,101,110,116,97,114,101,112,111,114,116,97,114 ,99,111,110,103,114,101,115,111,112,117,98,108,105,99,97,114,99,111,109,101,114, 99,105,111,99,111,110,116,114,97,116,111,106,195,179,118,101,110,101,115,100,105 ,115,116,114,105,116,111,116,195,169,99,110,105,99,97,99,111,110,106,117,110,116 ,111,101,110,101,114,103,195,173,97,116,114,97,98,97,106,97,114,97,115,116,117, 114,105,97,115,114,101,99,105,101,110,116,101,117,116,105,108,105,122,97,114,98, 111,108,101,116,195,173,110,115,97,108,118,97,100,111,114,99,111,114,114,101,99, 116,97,116,114,97,98,97,106,111,115,112,114,105,109,101,114,111,115,110,101,103, 111,99,105,111,115,108,105,98,101,114,116,97,100,100,101,116,97,108,108,101,115, 112,97,110,116,97,108,108,97,112,114,195,179,120,105,109,111,97,108,109,101,114, 195,173,97,97,110,105,109,97,108,101,115,113,117,105,195,169,110,101,115,99,111, 114,97,122,195,179,110,115,101,99,99,105,195,179,110,98,117,115,99,97,110,100, 111,111,112,99,105,111,110,101,115,101,120,116,101,114,105,111,114,99,111,110,99 ,101,112,116,111,116,111,100,97,118,195,173,97,103,97,108,101,114,195,173,97,101 ,115,99,114,105,98,105,114,109,101,100,105,99,105,110,97,108,105,99,101,110,99, 105,97,99,111,110,115,117,108,116,97,97,115,112,101,99,116,111,115,99,114,195, 173,116,105,99,97,100,195,179,108,97,114,101,115,106,117,115,116,105,99,105,97, 100,101,98,101,114,195,161,110,112,101,114,195,173,111,100,111,110,101,99,101, 115,105,116,97,109,97,110,116,101,110,101,114,112,101,113,117,101,195,177,111, 114,101,99,105,98,105,100,97,116,114,105,98,117,110,97,108,116,101,110,101,114, 105,102,101,99,97,110,99,105,195,179,110,99,97,110,97,114,105,97,115,100,101,115 ,99,97,114,103,97,100,105,118,101,114,115,111,115,109,97,108,108,111,114,99,97, 114,101,113,117,105,101,114,101,116,195,169,99,110,105,99,111,100,101,98,101,114 ,195,173,97,118,105,118,105,101,110,100,97,102,105,110,97,110,122,97,115,97,100, 101,108,97,110,116,101,102,117,110,99,105,111,110,97,99,111,110,115,101,106,111, 115,100,105,102,195,173,99,105,108,99,105,117,100,97,100,101,115,97,110,116,105, 103,117,97,115,97,118,97,110,122,97,100,97,116,195,169,114,109,105,110,111,117, 110,105,100,97,100,101,115,115,195,161,110,99,104,101,122,99,97,109,112,97,195, 177,97,115,111,102,116,111,110,105,99,114,101,118,105,115,116,97,115,99,111,110, 116,105,101,110,101,115,101,99,116,111,114,101,115,109,111,109,101,110,116,111, 115,102,97,99,117,108,116,97,100,99,114,195,169,100,105,116,111,100,105,118,101, 114,115,97,115,115,117,112,117,101,115,116,111,102,97,99,116,111,114,101,115,115 ,101,103,117,110,100,111,115,112,101,113,117,101,195,177,97,208,179,208,190,208, 180,208,176,208,181,209,129,208,187,208,184,208,181,209,129,209,130,209,140,208, 177,209,139,208,187,208,190,208,177,209,139,209,130,209,140,209,141,209,130,208, 190,208,188,208,149,209,129,208,187,208,184,209,130,208,190,208,179,208,190,208, 188,208,181,208,189,209,143,208,178,209,129,208,181,209,133,209,141,209,130,208, 190,208,185,208,180,208,176,208,182,208,181,208,177,209,139,208,187,208,184,208, 179,208,190,208,180,209,131,208,180,208,181,208,189,209,140,209,141,209,130,208, 190,209,130,208,177,209,139,208,187,208,176,209,129,208,181,208,177,209,143,208, 190,208,180,208,184,208,189,209,129,208,181,208,177,208,181,208,189,208,176,208, 180,208,190,209,129,208,176,208,185,209,130,209,132,208,190,209,130,208,190,208, 189,208,181,208,179,208,190,209,129,208,178,208,190,208,184,209,129,208,178,208, 190,208,185,208,184,208,179,209,128,209,139,209,130,208,190,208,182,208,181,208, 178,209,129,208,181,208,188,209,129,208,178,208,190,209,142,208,187,208,184,209, 136,209,140,209,141,209,130,208,184,209,133,208,191,208,190,208,186,208,176,208, 180,208,189,208,181,208,185,208,180,208,190,208,188,208,176,208,188,208,184,209, 128,208,176,208,187,208,184,208,177,208,190,209,130,208,181,208,188,209,131,209, 133,208,190,209,130,209,143,208,180,208,178,209,131,209,133,209,129,208,181,209, 130,208,184,208,187,209,142,208,180,208,184,208,180,208,181,208,187,208,190,208, 188,208,184,209,128,208,181,209,130,208,181,208,177,209,143,209,129,208,178,208, 190,208,181,208,178,208,184,208,180,208,181,209,135,208,181,208,179,208,190,209, 141,209,130,208,184,208,188,209,129,209,135,208,181,209,130,209,130,208,181,208, 188,209,139,209,134,208,181,208,189,209,139,209,129,209,130,208,176,208,187,208, 178,208,181,208,180,209,140,209,130,208,181,208,188,208,181,208,178,208,190,208, 180,209,139,209,130,208,181,208,177,208,181,208,178,209,139,209,136,208,181,208, 189,208,176,208,188,208,184,209,130,208,184,208,191,208,176,209,130,208,190,208, 188,209,131,208,191,209,128,208,176,208,178,208,187,208,184,209,134,208,176,208, 190,208,180,208,189,208,176,208,179,208,190,208,180,209,139,208,183,208,189,208, 176,209,142,208,188,208,190,208,179,209,131,208,180,209,128,209,131,208,179,208, 178,209,129,208,181,208,185,208,184,208,180,208,181,209,130,208,186,208,184,208, 189,208,190,208,190,208,180,208,189,208,190,208,180,208,181,208,187,208,176,208, 180,208,181,208,187,208,181,209,129,209,128,208,190,208,186,208,184,209,142,208, 189,209,143,208,178,208,181,209,129,209,140,208,149,209,129,209,130,209,140,209, 128,208,176,208,183,208,176,208,189,208,176,209,136,208,184,216,167,217,132,217, 132,217,135,216,167,217,132,216,170,217,138,216,172,217,133,217,138,216,185,216, 174,216,167,216,181,216,169,216,167,217,132,216,176,217,138,216,185,217,132,217, 138,217,135,216,172,216,175,217,138,216,175,216,167,217,132,216,162,217,134,216, 167,217,132,216,177,216,175,216,170,216,173,217,131,217,133,216,181,217,129,216, 173,216,169,217,131,216,167,217,134,216,170,216,167,217,132,217,132,217,138,217, 138,217,131,217,136,217,134,216,180,216,168,217,131,216,169,217,129,217,138,217, 135,216,167,216,168,217,134,216,167,216,170,216,173,217,136,216,167,216,161,216, 163,217,131,216,171,216,177,216,174,217,132,216,167,217,132,216,167,217,132,216, 173,216,168,216,175,217,132,217,138,217,132,216,175,216,177,217,136,216,179,216, 167,216,182,216,186,216,183,216,170,217,131,217,136,217,134,217,135,217,134,216, 167,217,131,216,179,216,167,216,173,216,169,217,134,216,167,216,175,217,138,216, 167,217,132,216,183,216,168,216,185,217,132,217,138,217,131,216,180,217,131,216, 177,216,167,217,138,217,133,217,131,217,134,217,133,217,134,217,135,216,167,216, 180,216,177,217,131,216,169,216,177,216,166,217,138,216,179,217,134,216,180,217, 138,216,183,217,133,216,167,216,176,216,167,216,167,217,132,217,129,217,134,216, 180,216,168,216,167,216,168,216,170,216,185,216,168,216,177,216,177,216,173,217, 133,216,169,217,131,216,167,217,129,216,169,217,138,217,130,217,136,217,132,217, 133,216,177,217,131,216,178,217,131,217,132,217,133,216,169,216,163,216,173,217, 133,216,175,217,130,217,132,216,168,217,138,217,138,216,185,217,134,217,138,216, 181,217,136,216,177,216,169,216,183,216,177,217,138,217,130,216,180,216,167,216, 177,217,131,216,172,217,136,216,167,217,132,216,163,216,174,216,177,217,137,217, 133,216,185,217,134,216,167,216,167,216,168,216,173,216,171,216,185,216,177,217, 136,216,182,216,168,216,180,217,131,217,132,217,133,216,179,216,172,217,132,216, 168,217,134,216,167,217,134,216,174,216,167,217,132,216,175,217,131,216,170,216, 167,216,168,217,131,217,132,217,138,216,169,216,168,216,175,217,136,217,134,216, 163,217,138,216,182,216,167,217,138,217,136,216,172,216,175,217,129,216,177,217, 138,217,130,217,131,216,170,216,168,216,170,216,163,217,129,216,182,217,132,217, 133,216,183,216,168,216,174,216,167,217,131,216,171,216,177,216,168,216,167,216, 177,217,131,216,167,217,129,216,182,217,132,216,167,216,173,217,132,217,137,217, 134,217,129,216,179,217,135,216,163,217,138,216,167,217,133,216,177,216,175,217, 136,216,175,216,163,217,134,217,135,216,167,216,175,217,138,217,134,216,167,216, 167,217,132,216,167,217,134,217,133,216,185,216,177,216,182,216,170,216,185,217, 132,217,133,216,175,216,167,216,174,217,132,217,133,217,133,217,131,217,134,0,0, 0,0,0,0,0,0,1,0,1,0,1,0,1,0,2,0,2,0,2,0,2,0,4,0,4,0,4,0,4,0,0,1,2,3,4,5,6,7,7,6, 5,4,3,2,1,0,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,16,17,18,19,20,21,22,23, 23,22,21,20,19,18,17,16,24,25,26,27,28,29,30,31,31,30,29,28,27,26,25,24,255,255, 255,255,0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,1,0,0,0, 3,0,0,0,255,255,0,1,0,0,0,1,0,0,255,255,0,1,0,0,0,8,0,8,0,8,0,8,0,0,0,1,0,2,0,3, 0,4,0,5,0,6,0,7,114,101,115,111,117,114,99,101,115,99,111,117,110,116,114,105, 101,115,113,117,101,115,116,105,111,110,115,101,113,117,105,112,109,101,110,116, 99,111,109,109,117,110,105,116,121,97,118,97,105,108,97,98,108,101,104,105,103, 104,108,105,103,104,116,68,84,68,47,120,104,116,109,108,109,97,114,107,101,116, 105,110,103,107,110,111,119,108,101,100,103,101,115,111,109,101,116,104,105,110, 103,99,111,110,116,97,105,110,101,114,100,105,114,101,99,116,105,111,110,115,117 ,98,115,99,114,105,98,101,97,100,118,101,114,116,105,115,101,99,104,97,114,97,99 ,116,101,114,34,32,118,97,108,117,101,61,34,60,47,115,101,108,101,99,116,62,65, 117,115,116,114,97,108,105,97,34,32,99,108,97,115,115,61,34,115,105,116,117,97, 116,105,111,110,97,117,116,104,111,114,105,116,121,102,111,108,108,111,119,105, 110,103,112,114,105,109,97,114,105,108,121,111,112,101,114,97,116,105,111,110,99 ,104,97,108,108,101,110,103,101,100,101,118,101,108,111,112,101,100,97,110,111, 110,121,109,111,117,115,102,117,110,99,116,105,111,110,32,102,117,110,99,116,105 ,111,110,115,99,111,109,112,97,110,105,101,115,115,116,114,117,99,116,117,114, 101,97,103,114,101,101,109,101,110,116,34,32,116,105,116,108,101,61,34,112,111, 116,101,110,116,105,97,108,101,100,117,99,97,116,105,111,110,97,114,103,117,109, 101,110,116,115,115,101,99,111,110,100,97,114,121,99,111,112,121,114,105,103,104 ,116,108,97,110,103,117,97,103,101,115,101,120,99,108,117,115,105,118,101,99,111 ,110,100,105,116,105,111,110,60,47,102,111,114,109,62,13,10,115,116,97,116,101, 109,101,110,116,97,116,116,101,110,116,105,111,110,66,105,111,103,114,97,112,104 ,121,125,32,101,108,115,101,32,123,10,115,111,108,117,116,105,111,110,115,119, 104,101,110,32,116,104,101,32,65,110,97,108,121,116,105,99,115,116,101,109,112, 108,97,116,101,115,100,97,110,103,101,114,111,117,115,115,97,116,101,108,108,105 ,116,101,100,111,99,117,109,101,110,116,115,112,117,98,108,105,115,104,101,114, 105,109,112,111,114,116,97,110,116,112,114,111,116,111,116,121,112,101,105,110, 102,108,117,101,110,99,101,38,114,97,113,117,111,59,60,47,101,102,102,101,99,116 ,105,118,101,103,101,110,101,114,97,108,108,121,116,114,97,110,115,102,111,114, 109,98,101,97,117,116,105,102,117,108,116,114,97,110,115,112,111,114,116,111,114 ,103,97,110,105,122,101,100,112,117,98,108,105,115,104,101,100,112,114,111,109, 105,110,101,110,116,117,110,116,105,108,32,116,104,101,116,104,117,109,98,110,97 ,105,108,78,97,116,105,111,110,97,108,32,46,102,111,99,117,115,40,41,59,111,118, 101,114,32,116,104,101,32,109,105,103,114,97,116,105,111,110,97,110,110,111,117, 110,99,101,100,102,111,111,116,101,114,34,62,10,101,120,99,101,112,116,105,111, 110,108,101,115,115,32,116,104,97,110,101,120,112,101,110,115,105,118,101,102, 111,114,109,97,116,105,111,110,102,114,97,109,101,119,111,114,107,116,101,114, 114,105,116,111,114,121,110,100,105,99,97,116,105,111,110,99,117,114,114,101,110 ,116,108,121,99,108,97,115,115,78,97,109,101,99,114,105,116,105,99,105,115,109, 116,114,97,100,105,116,105,111,110,101,108,115,101,119,104,101,114,101,65,108, 101,120,97,110,100,101,114,97,112,112,111,105,110,116,101,100,109,97,116,101,114 ,105,97,108,115,98,114,111,97,100,99,97,115,116,109,101,110,116,105,111,110,101, 100,97,102,102,105,108,105,97,116,101,60,47,111,112,116,105,111,110,62,116,114, 101,97,116,109,101,110,116,100,105,102,102,101,114,101,110,116,47,100,101,102,97 ,117,108,116,46,80,114,101,115,105,100,101,110,116,111,110,99,108,105,99,107,61, 34,98,105,111,103,114,97,112,104,121,111,116,104,101,114,119,105,115,101,112,101 ,114,109,97,110,101,110,116,70,114,97,110,195,167,97,105,115,72,111,108,108,121, 119,111,111,100,101,120,112,97,110,115,105,111,110,115,116,97,110,100,97,114,100 ,115,60,47,115,116,121,108,101,62,10,114,101,100,117,99,116,105,111,110,68,101, 99,101,109,98,101,114,32,112,114,101,102,101,114,114,101,100,67,97,109,98,114, 105,100,103,101,111,112,112,111,110,101,110,116,115,66,117,115,105,110,101,115, 115,32,99,111,110,102,117,115,105,111,110,62,10,60,116,105,116,108,101,62,112, 114,101,115,101,110,116,101,100,101,120,112,108,97,105,110,101,100,100,111,101, 115,32,110,111,116,32,119,111,114,108,100,119,105,100,101,105,110,116,101,114, 102,97,99,101,112,111,115,105,116,105,111,110,115,110,101,119,115,112,97,112,101 ,114,60,47,116,97,98,108,101,62,10,109,111,117,110,116,97,105,110,115,108,105, 107,101,32,116,104,101,32,101,115,115,101,110,116,105,97,108,102,105,110,97,110, 99,105,97,108,115,101,108,101,99,116,105,111,110,97,99,116,105,111,110,61,34,47, 97,98,97,110,100,111,110,101,100,69,100,117,99,97,116,105,111,110,112,97,114,115 ,101,73,110,116,40,115,116,97,98,105,108,105,116,121,117,110,97,98,108,101,32, 116,111,60,47,116,105,116,108,101,62,10,114,101,108,97,116,105,111,110,115,78, 111,116,101,32,116,104,97,116,101,102,102,105,99,105,101,110,116,112,101,114,102 ,111,114,109,101,100,116,119,111,32,121,101,97,114,115,83,105,110,99,101,32,116, 104,101,116,104,101,114,101,102,111,114,101,119,114,97,112,112,101,114,34,62,97, 108,116,101,114,110,97,116,101,105,110,99,114,101,97,115,101,100,66,97,116,116, 108,101,32,111,102,112,101,114,99,101,105,118,101,100,116,114,121,105,110,103,32 ,116,111,110,101,99,101,115,115,97,114,121,112,111,114,116,114,97,121,101,100, 101,108,101,99,116,105,111,110,115,69,108,105,122,97,98,101,116,104,60,47,105, 102,114,97,109,101,62,100,105,115,99,111,118,101,114,121,105,110,115,117,114,97, 110,99,101,115,46,108,101,110,103,116,104,59,108,101,103,101,110,100,97,114,121, 71,101,111,103,114,97,112,104,121,99,97,110,100,105,100,97,116,101,99,111,114, 112,111,114,97,116,101,115,111,109,101,116,105,109,101,115,115,101,114,118,105, 99,101,115,46,105,110,104,101,114,105,116,101,100,60,47,115,116,114,111,110,103, 62,67,111,109,109,117,110,105,116,121,114,101,108,105,103,105,111,117,115,108, 111,99,97,116,105,111,110,115,67,111,109,109,105,116,116,101,101,98,117,105,108, 100,105,110,103,115,116,104,101,32,119,111,114,108,100,110,111,32,108,111,110, 103,101,114,98,101,103,105,110,110,105,110,103,114,101,102,101,114,101,110,99, 101,99,97,110,110,111,116,32,98,101,102,114,101,113,117,101,110,99,121,116,121, 112,105,99,97,108,108,121,105,110,116,111,32,116,104,101,32,114,101,108,97,116, 105,118,101,59,114,101,99,111,114,100,105,110,103,112,114,101,115,105,100,101, 110,116,105,110,105,116,105,97,108,108,121,116,101,99,104,110,105,113,117,101, 116,104,101,32,111,116,104,101,114,105,116,32,99,97,110,32,98,101,101,120,105, 115,116,101,110,99,101,117,110,100,101,114,108,105,110,101,116,104,105,115,32, 116,105,109,101,116,101,108,101,112,104,111,110,101,105,116,101,109,115,99,111, 112,101,112,114,97,99,116,105,99,101,115,97,100,118,97,110,116,97,103,101,41,59, 114,101,116,117,114,110,32,70,111,114,32,111,116,104,101,114,112,114,111,118,105 ,100,105,110,103,100,101,109,111,99,114,97,99,121,98,111,116,104,32,116,104,101, 32,101,120,116,101,110,115,105,118,101,115,117,102,102,101,114,105,110,103,115, 117,112,112,111,114,116,101,100,99,111,109,112,117,116,101,114,115,32,102,117, 110,99,116,105,111,110,112,114,97,99,116,105,99,97,108,115,97,105,100,32,116,104 ,97,116,105,116,32,109,97,121,32,98,101,69,110,103,108,105,115,104,60,47,102,114 ,111,109,32,116,104,101,32,115,99,104,101,100,117,108,101,100,100,111,119,110, 108,111,97,100,115,60,47,108,97,98,101,108,62,10,115,117,115,112,101,99,116,101, 100,109,97,114,103,105,110,58,32,48,115,112,105,114,105,116,117,97,108,60,47,104 ,101,97,100,62,10,10,109,105,99,114,111,115,111,102,116,103,114,97,100,117,97, 108,108,121,100,105,115,99,117,115,115,101,100,104,101,32,98,101,99,97,109,101, 101,120,101,99,117,116,105,118,101,106,113,117,101,114,121,46,106,115,104,111, 117,115,101,104,111,108,100,99,111,110,102,105,114,109,101,100,112,117,114,99, 104,97,115,101,100,108,105,116,101,114,97,108,108,121,100,101,115,116,114,111, 121,101,100,117,112,32,116,111,32,116,104,101,118,97,114,105,97,116,105,111,110, 114,101,109,97,105,110,105,110,103,105,116,32,105,115,32,110,111,116,99,101,110, 116,117,114,105,101,115,74,97,112,97,110,101,115,101,32,97,109,111,110,103,32, 116,104,101,99,111,109,112,108,101,116,101,100,97,108,103,111,114,105,116,104, 109,105,110,116,101,114,101,115,116,115,114,101,98,101,108,108,105,111,110,117, 110,100,101,102,105,110,101,100,101,110,99,111,117,114,97,103,101,114,101,115, 105,122,97,98,108,101,105,110,118,111,108,118,105,110,103,115,101,110,115,105, 116,105,118,101,117,110,105,118,101,114,115,97,108,112,114,111,118,105,115,105, 111,110,40,97,108,116,104,111,117,103,104,102,101,97,116,117,114,105,110,103,99, 111,110,100,117,99,116,101,100,41,44,32,119,104,105,99,104,32,99,111,110,116,105 ,110,117,101,100,45,104,101,97,100,101,114,34,62,70,101,98,114,117,97,114,121,32 ,110,117,109,101,114,111,117,115,32,111,118,101,114,102,108,111,119,58,99,111, 109,112,111,110,101,110,116,102,114,97,103,109,101,110,116,115,101,120,99,101, 108,108,101,110,116,99,111,108,115,112,97,110,61,34,116,101,99,104,110,105,99,97 ,108,110,101,97,114,32,116,104,101,32,65,100,118,97,110,99,101,100,32,115,111, 117,114,99,101,32,111,102,101,120,112,114,101,115,115,101,100,72,111,110,103,32, 75,111,110,103,32,70,97,99,101,98,111,111,107,109,117,108,116,105,112,108,101,32 ,109,101,99,104,97,110,105,115,109,101,108,101,118,97,116,105,111,110,111,102, 102,101,110,115,105,118,101,60,47,102,111,114,109,62,10,9,115,112,111,110,115, 111,114,101,100,100,111,99,117,109,101,110,116,46,111,114,32,38,113,117,111,116, 59,116,104,101,114,101,32,97,114,101,116,104,111,115,101,32,119,104,111,109,111, 118,101,109,101,110,116,115,112,114,111,99,101,115,115,101,115,100,105,102,102, 105,99,117,108,116,115,117,98,109,105,116,116,101,100,114,101,99,111,109,109,101 ,110,100,99,111,110,118,105,110,99,101,100,112,114,111,109,111,116,105,110,103, 34,32,119,105,100,116,104,61,34,46,114,101,112,108,97,99,101,40,99,108,97,115, 115,105,99,97,108,99,111,97,108,105,116,105,111,110,104,105,115,32,102,105,114, 115,116,100,101,99,105,115,105,111,110,115,97,115,115,105,115,116,97,110,116,105 ,110,100,105,99,97,116,101,100,101,118,111,108,117,116,105,111,110,45,119,114,97 ,112,112,101,114,34,101,110,111,117,103,104,32,116,111,97,108,111,110,103,32,116 ,104,101,100,101,108,105,118,101,114,101,100,45,45,62,13,10,60,33,45,45,65,109, 101,114,105,99,97,110,32,112,114,111,116,101,99,116,101,100,78,111,118,101,109, 98,101,114,32,60,47,115,116,121,108,101,62,60,102,117,114,110,105,116,117,114, 101,73,110,116,101,114,110,101,116,32,32,111,110,98,108,117,114,61,34,115,117, 115,112,101,110,100,101,100,114,101,99,105,112,105,101,110,116,98,97,115,101,100 ,32,111,110,32,77,111,114,101,111,118,101,114,44,97,98,111,108,105,115,104,101, 100,99,111,108,108,101,99,116,101,100,119,101,114,101,32,109,97,100,101,101,109, 111,116,105,111,110,97,108,101,109,101,114,103,101,110,99,121,110,97,114,114,97, 116,105,118,101,97,100,118,111,99,97,116,101,115,112,120,59,98,111,114,100,101, 114,99,111,109,109,105,116,116,101,100,100,105,114,61,34,108,116,114,34,101,109, 112,108,111,121,101,101,115,114,101,115,101,97,114,99,104,46,32,115,101,108,101, 99,116,101,100,115,117,99,99,101,115,115,111,114,99,117,115,116,111,109,101,114, 115,100,105,115,112,108,97,121,101,100,83,101,112,116,101,109,98,101,114,97,100, 100,67,108,97,115,115,40,70,97,99,101,98,111,111,107,32,115,117,103,103,101,115, 116,101,100,97,110,100,32,108,97,116,101,114,111,112,101,114,97,116,105,110,103, 101,108,97,98,111,114,97,116,101,83,111,109,101,116,105,109,101,115,73,110,115, 116,105,116,117,116,101,99,101,114,116,97,105,110,108,121,105,110,115,116,97,108 ,108,101,100,102,111,108,108,111,119,101,114,115,74,101,114,117,115,97,108,101, 109,116,104,101,121,32,104,97,118,101,99,111,109,112,117,116,105,110,103,103,101 ,110,101,114,97,116,101,100,112,114,111,118,105,110,99,101,115,103,117,97,114,97 ,110,116,101,101,97,114,98,105,116,114,97,114,121,114,101,99,111,103,110,105,122 ,101,119,97,110,116,101,100,32,116,111,112,120,59,119,105,100,116,104,58,116,104 ,101,111,114,121,32,111,102,98,101,104,97,118,105,111,117,114,87,104,105,108,101 ,32,116,104,101,101,115,116,105,109,97,116,101,100,98,101,103,97,110,32,116,111, 32,105,116,32,98,101,99,97,109,101,109,97,103,110,105,116,117,100,101,109,117, 115,116,32,104,97,118,101,109,111,114,101,32,116,104,97,110,68,105,114,101,99, 116,111,114,121,101,120,116,101,110,115,105,111,110,115,101,99,114,101,116,97, 114,121,110,97,116,117,114,97,108,108,121,111,99,99,117,114,114,105,110,103,118, 97,114,105,97,98,108,101,115,103,105,118,101,110,32,116,104,101,112,108,97,116, 102,111,114,109,46,60,47,108,97,98,101,108,62,60,102,97,105,108,101,100,32,116, 111,99,111,109,112,111,117,110,100,115,107,105,110,100,115,32,111,102,32,115,111 ,99,105,101,116,105,101,115,97,108,111,110,103,115,105,100,101,32,45,45,38,103, 116,59,10,10,115,111,117,116,104,119,101,115,116,116,104,101,32,114,105,103,104, 116,114,97,100,105,97,116,105,111,110,109,97,121,32,104,97,118,101,32,117,110, 101,115,99,97,112,101,40,115,112,111,107,101,110,32,105,110,34,32,104,114,101, 102,61,34,47,112,114,111,103,114,97,109,109,101,111,110,108,121,32,116,104,101, 32,99,111,109,101,32,102,114,111,109,100,105,114,101,99,116,111,114,121,98,117, 114,105,101,100,32,105,110,97,32,115,105,109,105,108,97,114,116,104,101,121,32, 119,101,114,101,60,47,102,111,110,116,62,60,47,78,111,114,119,101,103,105,97,110 ,115,112,101,99,105,102,105,101,100,112,114,111,100,117,99,105,110,103,112,97, 115,115,101,110,103,101,114,40,110,101,119,32,68,97,116,101,116,101,109,112,111, 114,97,114,121,102,105,99,116,105,111,110,97,108,65,102,116,101,114,32,116,104, 101,101,113,117,97,116,105,111,110,115,100,111,119,110,108,111,97,100,46,114,101 ,103,117,108,97,114,108,121,100,101,118,101,108,111,112,101,114,97,98,111,118, 101,32,116,104,101,108,105,110,107,101,100,32,116,111,112,104,101,110,111,109, 101,110,97,112,101,114,105,111,100,32,111,102,116,111,111,108,116,105,112,34,62, 115,117,98,115,116,97,110,99,101,97,117,116,111,109,97,116,105,99,97,115,112,101 ,99,116,32,111,102,65,109,111,110,103,32,116,104,101,99,111,110,110,101,99,116, 101,100,101,115,116,105,109,97,116,101,115,65,105,114,32,70,111,114,99,101,115, 121,115,116,101,109,32,111,102,111,98,106,101,99,116,105,118,101,105,109,109,101 ,100,105,97,116,101,109,97,107,105,110,103,32,105,116,112,97,105,110,116,105,110 ,103,115,99,111,110,113,117,101,114,101,100,97,114,101,32,115,116,105,108,108, 112,114,111,99,101,100,117,114,101,103,114,111,119,116,104,32,111,102,104,101,97 ,100,101,100,32,98,121,69,117,114,111,112,101,97,110,32,100,105,118,105,115,105, 111,110,115,109,111,108,101,99,117,108,101,115,102,114,97,110,99,104,105,115,101 ,105,110,116,101,110,116,105,111,110,97,116,116,114,97,99,116,101,100,99,104,105 ,108,100,104,111,111,100,97,108,115,111,32,117,115,101,100,100,101,100,105,99,97 ,116,101,100,115,105,110,103,97,112,111,114,101,100,101,103,114,101,101,32,111, 102,102,97,116,104,101,114,32,111,102,99,111,110,102,108,105,99,116,115,60,47,97 ,62,60,47,112,62,10,99,97,109,101,32,102,114,111,109,119,101,114,101,32,117,115, 101,100,110,111,116,101,32,116,104,97,116,114,101,99,101,105,118,105,110,103,69, 120,101,99,117,116,105,118,101,101,118,101,110,32,109,111,114,101,97,99,99,101, 115,115,32,116,111,99,111,109,109,97,110,100,101,114,80,111,108,105,116,105,99, 97,108,109,117,115,105,99,105,97,110,115,100,101,108,105,99,105,111,117,115,112, 114,105,115,111,110,101,114,115,97,100,118,101,110,116,32,111,102,85,84,70,45,56 ,34,32,47,62,60,33,91,67,68,65,84,65,91,34,62,67,111,110,116,97,99,116,83,111, 117,116,104,101,114,110,32,98,103,99,111,108,111,114,61,34,115,101,114,105,101, 115,32,111,102,46,32,73,116,32,119,97,115,32,105,110,32,69,117,114,111,112,101, 112,101,114,109,105,116,116,101,100,118,97,108,105,100,97,116,101,46,97,112,112, 101,97,114,105,110,103,111,102,102,105,99,105,97,108,115,115,101,114,105,111,117 ,115,108,121,45,108,97,110,103,117,97,103,101,105,110,105,116,105,97,116,101,100 ,101,120,116,101,110,100,105,110,103,108,111,110,103,45,116,101,114,109,105,110, 102,108,97,116,105,111,110,115,117,99,104,32,116,104,97,116,103,101,116,67,111, 111,107,105,101,109,97,114,107,101,100,32,98,121,60,47,98,117,116,116,111,110,62 ,105,109,112,108,101,109,101,110,116,98,117,116,32,105,116,32,105,115,105,110,99 ,114,101,97,115,101,115,100,111,119,110,32,116,104,101,32,114,101,113,117,105, 114,105,110,103,100,101,112,101,110,100,101,110,116,45,45,62,10,60,33,45,45,32, 105,110,116,101,114,118,105,101,119,87,105,116,104,32,116,104,101,32,99,111,112, 105,101,115,32,111,102,99,111,110,115,101,110,115,117,115,119,97,115,32,98,117, 105,108,116,86,101,110,101,122,117,101,108,97,40,102,111,114,109,101,114,108,121 ,116,104,101,32,115,116,97,116,101,112,101,114,115,111,110,110,101,108,115,116, 114,97,116,101,103,105,99,102,97,118,111,117,114,32,111,102,105,110,118,101,110, 116,105,111,110,87,105,107,105,112,101,100,105,97,99,111,110,116,105,110,101,110 ,116,118,105,114,116,117,97,108,108,121,119,104,105,99,104,32,119,97,115,112,114 ,105,110,99,105,112,108,101,67,111,109,112,108,101,116,101,32,105,100,101,110, 116,105,99,97,108,115,104,111,119,32,116,104,97,116,112,114,105,109,105,116,105, 118,101,97,119,97,121,32,102,114,111,109,109,111,108,101,99,117,108,97,114,112, 114,101,99,105,115,101,108,121,100,105,115,115,111,108,118,101,100,85,110,100, 101,114,32,116,104,101,118,101,114,115,105,111,110,61,34,62,38,110,98,115,112,59 ,60,47,73,116,32,105,115,32,116,104,101,32,84,104,105,115,32,105,115,32,119,105, 108,108,32,104,97,118,101,111,114,103,97,110,105,115,109,115,115,111,109,101,32, 116,105,109,101,70,114,105,101,100,114,105,99,104,119,97,115,32,102,105,114,115, 116,116,104,101,32,111,110,108,121,32,102,97,99,116,32,116,104,97,116,102,111, 114,109,32,105,100,61,34,112,114,101,99,101,100,105,110,103,84,101,99,104,110, 105,99,97,108,112,104,121,115,105,99,105,115,116,111,99,99,117,114,115,32,105, 110,110,97,118,105,103,97,116,111,114,115,101,99,116,105,111,110,34,62,115,112, 97,110,32,105,100,61,34,115,111,117,103,104,116,32,116,111,98,101,108,111,119,32 ,116,104,101,115,117,114,118,105,118,105,110,103,125,60,47,115,116,121,108,101, 62,104,105,115,32,100,101,97,116,104,97,115,32,105,110,32,116,104,101,99,97,117, 115,101,100,32,98,121,112,97,114,116,105,97,108,108,121,101,120,105,115,116,105, 110,103,32,117,115,105,110,103,32,116,104,101,119,97,115,32,103,105,118,101,110, 97,32,108,105,115,116,32,111,102,108,101,118,101,108,115,32,111,102,110,111,116, 105,111,110,32,111,102,79,102,102,105,99,105,97,108,32,100,105,115,109,105,115, 115,101,100,115,99,105,101,110,116,105,115,116,114,101,115,101,109,98,108,101, 115,100,117,112,108,105,99,97,116,101,101,120,112,108,111,115,105,118,101,114, 101,99,111,118,101,114,101,100,97,108,108,32,111,116,104,101,114,103,97,108,108, 101,114,105,101,115,123,112,97,100,100,105,110,103,58,112,101,111,112,108,101,32 ,111,102,114,101,103,105,111,110,32,111,102,97,100,100,114,101,115,115,101,115, 97,115,115,111,99,105,97,116,101,105,109,103,32,97,108,116,61,34,105,110,32,109, 111,100,101,114,110,115,104,111,117,108,100,32,98,101,109,101,116,104,111,100,32 ,111,102,114,101,112,111,114,116,105,110,103,116,105,109,101,115,116,97,109,112, 110,101,101,100,101,100,32,116,111,116,104,101,32,71,114,101,97,116,114,101,103, 97,114,100,105,110,103,115,101,101,109,101,100,32,116,111,118,105,101,119,101, 100,32,97,115,105,109,112,97,99,116,32,111,110,105,100,101,97,32,116,104,97,116, 116,104,101,32,87,111,114,108,100,104,101,105,103,104,116,32,111,102,101,120,112 ,97,110,100,105,110,103,84,104,101,115,101,32,97,114,101,99,117,114,114,101,110, 116,34,62,99,97,114,101,102,117,108,108,121,109,97,105,110,116,97,105,110,115,99 ,104,97,114,103,101,32,111,102,67,108,97,115,115,105,99,97,108,97,100,100,114, 101,115,115,101,100,112,114,101,100,105,99,116,101,100,111,119,110,101,114,115, 104,105,112,60,100,105,118,32,105,100,61,34,114,105,103,104,116,34,62,13,10,114, 101,115,105,100,101,110,99,101,108,101,97,118,101,32,116,104,101,99,111,110,116, 101,110,116,34,62,97,114,101,32,111,102,116,101,110,32,32,125,41,40,41,59,13,10, 112,114,111,98,97,98,108,121,32,80,114,111,102,101,115,115,111,114,45,98,117,116 ,116,111,110,34,32,114,101,115,112,111,110,100,101,100,115,97,121,115,32,116,104 ,97,116,104,97,100,32,116,111,32,98,101,112,108,97,99,101,100,32,105,110,72,117, 110,103,97,114,105,97,110,115,116,97,116,117,115,32,111,102,115,101,114,118,101, 115,32,97,115,85,110,105,118,101,114,115,97,108,101,120,101,99,117,116,105,111, 110,97,103,103,114,101,103,97,116,101,102,111,114,32,119,104,105,99,104,105,110, 102,101,99,116,105,111,110,97,103,114,101,101,100,32,116,111,104,111,119,101,118 ,101,114,44,32,112,111,112,117,108,97,114,34,62,112,108,97,99,101,100,32,111,110 ,99,111,110,115,116,114,117,99,116,101,108,101,99,116,111,114,97,108,115,121,109 ,98,111,108,32,111,102,105,110,99,108,117,100,105,110,103,114,101,116,117,114, 110,32,116,111,97,114,99,104,105,116,101,99,116,67,104,114,105,115,116,105,97, 110,112,114,101,118,105,111,117,115,32,108,105,118,105,110,103,32,105,110,101,97 ,115,105,101,114,32,116,111,112,114,111,102,101,115,115,111,114,10,38,108,116,59 ,33,45,45,32,101,102,102,101,99,116,32,111,102,97,110,97,108,121,116,105,99,115, 119,97,115,32,116,97,107,101,110,119,104,101,114,101,32,116,104,101,116,111,111, 107,32,111,118,101,114,98,101,108,105,101,102,32,105,110,65,102,114,105,107,97, 97,110,115,97,115,32,102,97,114,32,97,115,112,114,101,118,101,110,116,101,100, 119,111,114,107,32,119,105,116,104,97,32,115,112,101,99,105,97,108,60,102,105, 101,108,100,115,101,116,67,104,114,105,115,116,109,97,115,82,101,116,114,105,101 ,118,101,100,10,10,73,110,32,116,104,101,32,98,97,99,107,32,105,110,116,111,110, 111,114,116,104,101,97,115,116,109,97,103,97,122,105,110,101,115,62,60,115,116, 114,111,110,103,62,99,111,109,109,105,116,116,101,101,103,111,118,101,114,110, 105,110,103,103,114,111,117,112,115,32,111,102,115,116,111,114,101,100,32,105, 110,101,115,116,97,98,108,105,115,104,97,32,103,101,110,101,114,97,108,105,116, 115,32,102,105,114,115,116,116,104,101,105,114,32,111,119,110,112,111,112,117, 108,97,116,101,100,97,110,32,111,98,106,101,99,116,67,97,114,105,98,98,101,97, 110,97,108,108,111,119,32,116,104,101,100,105,115,116,114,105,99,116,115,119,105 ,115,99,111,110,115,105,110,108,111,99,97,116,105,111,110,46,59,32,119,105,100, 116,104,58,32,105,110,104,97,98,105,116,101,100,83,111,99,105,97,108,105,115,116 ,74,97,110,117,97,114,121,32,49,60,47,102,111,111,116,101,114,62,115,105,109,105 ,108,97,114,108,121,99,104,111,105,99,101,32,111,102,116,104,101,32,115,97,109, 101,32,115,112,101,99,105,102,105,99,32,98,117,115,105,110,101,115,115,32,84,104 ,101,32,102,105,114,115,116,46,108,101,110,103,116,104,59,32,100,101,115,105,114 ,101,32,116,111,100,101,97,108,32,119,105,116,104,115,105,110,99,101,32,116,104, 101,117,115,101,114,65,103,101,110,116,99,111,110,99,101,105,118,101,100,105,110 ,100,101,120,46,112,104,112,97,115,32,38,113,117,111,116,59,101,110,103,97,103, 101,32,105,110,114,101,99,101,110,116,108,121,44,102,101,119,32,121,101,97,114, 115,119,101,114,101,32,97,108,115,111,10,60,104,101,97,100,62,10,60,101,100,105, 116,101,100,32,98,121,97,114,101,32,107,110,111,119,110,99,105,116,105,101,115, 32,105,110,97,99,99,101,115,115,107,101,121,99,111,110,100,101,109,110,101,100, 97,108,115,111,32,104,97,118,101,115,101,114,118,105,99,101,115,44,102,97,109, 105,108,121,32,111,102,83,99,104,111,111,108,32,111,102,99,111,110,118,101,114, 116,101,100,110,97,116,117,114,101,32,111,102,32,108,97,110,103,117,97,103,101, 109,105,110,105,115,116,101,114,115,60,47,111,98,106,101,99,116,62,116,104,101, 114,101,32,105,115,32,97,32,112,111,112,117,108,97,114,115,101,113,117,101,110, 99,101,115,97,100,118,111,99,97,116,101,100,84,104,101,121,32,119,101,114,101,97 ,110,121,32,111,116,104,101,114,108,111,99,97,116,105,111,110,61,101,110,116,101 ,114,32,116,104,101,109,117,99,104,32,109,111,114,101,114,101,102,108,101,99,116 ,101,100,119,97,115,32,110,97,109,101,100,111,114,105,103,105,110,97,108,32,97, 32,116,121,112,105,99,97,108,119,104,101,110,32,116,104,101,121,101,110,103,105, 110,101,101,114,115,99,111,117,108,100,32,110,111,116,114,101,115,105,100,101, 110,116,115,119,101,100,110,101,115,100,97,121,116,104,101,32,116,104,105,114, 100,32,112,114,111,100,117,99,116,115,74,97,110,117,97,114,121,32,50,119,104,97, 116,32,116,104,101,121,97,32,99,101,114,116,97,105,110,114,101,97,99,116,105,111 ,110,115,112,114,111,99,101,115,115,111,114,97,102,116,101,114,32,104,105,115, 116,104,101,32,108,97,115,116,32,99,111,110,116,97,105,110,101,100,34,62,60,47, 100,105,118,62,10,60,47,97,62,60,47,116,100,62,100,101,112,101,110,100,32,111, 110,115,101,97,114,99,104,34,62,10,112,105,101,99,101,115,32,111,102,99,111,109, 112,101,116,105,110,103,82,101,102,101,114,101,110,99,101,116,101,110,110,101, 115,115,101,101,119,104,105,99,104,32,104,97,115,32,118,101,114,115,105,111,110, 61,60,47,115,112,97,110,62,32,60,60,47,104,101,97,100,101,114,62,103,105,118,101 ,115,32,116,104,101,104,105,115,116,111,114,105,97,110,118,97,108,117,101,61,34, 34,62,112,97,100,100,105,110,103,58,48,118,105,101,119,32,116,104,97,116,116,111 ,103,101,116,104,101,114,44,116,104,101,32,109,111,115,116,32,119,97,115,32,102, 111,117,110,100,115,117,98,115,101,116,32,111,102,97,116,116,97,99,107,32,111, 110,99,104,105,108,100,114,101,110,44,112,111,105,110,116,115,32,111,102,112,101 ,114,115,111,110,97,108,32,112,111,115,105,116,105,111,110,58,97,108,108,101,103 ,101,100,108,121,67,108,101,118,101,108,97,110,100,119,97,115,32,108,97,116,101, 114,97,110,100,32,97,102,116,101,114,97,114,101,32,103,105,118,101,110,119,97, 115,32,115,116,105,108,108,115,99,114,111,108,108,105,110,103,100,101,115,105, 103,110,32,111,102,109,97,107,101,115,32,116,104,101,109,117,99,104,32,108,101, 115,115,65,109,101,114,105,99,97,110,115,46,10,10,65,102,116,101,114,32,44,32,98 ,117,116,32,116,104,101,77,117,115,101,117,109,32,111,102,108,111,117,105,115, 105,97,110,97,40,102,114,111,109,32,116,104,101,109,105,110,110,101,115,111,116, 97,112,97,114,116,105,99,108,101,115,97,32,112,114,111,99,101,115,115,68,111,109 ,105,110,105,99,97,110,118,111,108,117,109,101,32,111,102,114,101,116,117,114, 110,105,110,103,100,101,102,101,110,115,105,118,101,48,48,112,120,124,114,105, 103,104,109,97,100,101,32,102,114,111,109,109,111,117,115,101,111,118,101,114,34 ,32,115,116,121,108,101,61,34,115,116,97,116,101,115,32,111,102,40,119,104,105, 99,104,32,105,115,99,111,110,116,105,110,117,101,115,70,114,97,110,99,105,115,99 ,111,98,117,105,108,100,105,110,103,32,119,105,116,104,111,117,116,32,97,119,105 ,116,104,32,115,111,109,101,119,104,111,32,119,111,117,108,100,97,32,102,111,114 ,109,32,111,102,97,32,112,97,114,116,32,111,102,98,101,102,111,114,101,32,105, 116,107,110,111,119,110,32,97,115,32,32,83,101,114,118,105,99,101,115,108,111,99 ,97,116,105,111,110,32,97,110,100,32,111,102,116,101,110,109,101,97,115,117,114, 105,110,103,97,110,100,32,105,116,32,105,115,112,97,112,101,114,98,97,99,107,118 ,97,108,117,101,115,32,111,102,13,10,60,116,105,116,108,101,62,61,32,119,105,110 ,100,111,119,46,100,101,116,101,114,109,105,110,101,101,114,38,113,117,111,116, 59,32,112,108,97,121,101,100,32,98,121,97,110,100,32,101,97,114,108,121,60,47,99 ,101,110,116,101,114,62,102,114,111,109,32,116,104,105,115,116,104,101,32,116, 104,114,101,101,112,111,119,101,114,32,97,110,100,111,102,32,38,113,117,111,116, 59,105,110,110,101,114,72,84,77,76,60,97,32,104,114,101,102,61,34,121,58,105,110 ,108,105,110,101,59,67,104,117,114,99,104,32,111,102,116,104,101,32,101,118,101, 110,116,118,101,114,121,32,104,105,103,104,111,102,102,105,99,105,97,108,32,45, 104,101,105,103,104,116,58,32,99,111,110,116,101,110,116,61,34,47,99,103,105,45, 98,105,110,47,116,111,32,99,114,101,97,116,101,97,102,114,105,107,97,97,110,115, 101,115,112,101,114,97,110,116,111,102,114,97,110,195,167,97,105,115,108,97,116, 118,105,101,197,161,117,108,105,101,116,117,118,105,197,179,196,140,101,197,161, 116,105,110,97,196,141,101,197,161,116,105,110,97,224,185,132,224,184,151,224, 184,162,230,151,165,230,156,172,232,170,158,231,174,128,228,189,147,229,173,151, 231,185,129,233,171,148,229,173,151,237,149,156,234,181,173,236,150,180,228,184, 186,228,187,128,228,185,136,232,174,161,231,174,151,230,156,186,231,172,148,232, 174,176,230,156,172,232,168,142,232,171,150,229,141,128,230,156,141,229,138,161, 229,153,168,228,186,146,232,129,148,231,189,145,230,136,191,229,156,176,228,186, 167,228,191,177,228,185,144,233,131,168,229,135,186,231,137,136,231,164,190,230, 142,146,232,161,140,230,166,156,233,131,168,232,144,189,230,160,188,232,191,155, 228,184,128,230,173,165,230,148,175,228,187,152,229,174,157,233,170,140,232,175, 129,231,160,129,229,167,148,229,145,152,228,188,154,230,149,176,230,141,174,229, 186,147,230,182,136,232,180,185,232,128,133,229,138,158,229,133,172,229,174,164, 232,174,168,232,174,186,229,140,186,230,183,177,229,156,179,229,184,130,230,146, 173,230,148,190,229,153,168,229,140,151,228,186,172,229,184,130,229,164,167,229, 173,166,231,148,159,232,182,138,230,157,165,232,182,138,231,174,161,231,144,134, 229,145,152,228,191,161,230,129,175,231,189,145,115,101,114,118,105,99,105,111, 115,97,114,116,195,173,99,117,108,111,97,114,103,101,110,116,105,110,97,98,97, 114,99,101,108,111,110,97,99,117,97,108,113,117,105,101,114,112,117,98,108,105, 99,97,100,111,112,114,111,100,117,99,116,111,115,112,111,108,195,173,116,105,99, 97,114,101,115,112,117,101,115,116,97,119,105,107,105,112,101,100,105,97,115,105 ,103,117,105,101,110,116,101,98,195,186,115,113,117,101,100,97,99,111,109,117, 110,105,100,97,100,115,101,103,117,114,105,100,97,100,112,114,105,110,99,105,112 ,97,108,112,114,101,103,117,110,116,97,115,99,111,110,116,101,110,105,100,111, 114,101,115,112,111,110,100,101,114,118,101,110,101,122,117,101,108,97,112,114, 111,98,108,101,109,97,115,100,105,99,105,101,109,98,114,101,114,101,108,97,99, 105,195,179,110,110,111,118,105,101,109,98,114,101,115,105,109,105,108,97,114, 101,115,112,114,111,121,101,99,116,111,115,112,114,111,103,114,97,109,97,115,105 ,110,115,116,105,116,117,116,111,97,99,116,105,118,105,100,97,100,101,110,99,117 ,101,110,116,114,97,101,99,111,110,111,109,195,173,97,105,109,195,161,103,101, 110,101,115,99,111,110,116,97,99,116,97,114,100,101,115,99,97,114,103,97,114,110 ,101,99,101,115,97,114,105,111,97,116,101,110,99,105,195,179,110,116,101,108,195 ,169,102,111,110,111,99,111,109,105,115,105,195,179,110,99,97,110,99,105,111,110 ,101,115,99,97,112,97,99,105,100,97,100,101,110,99,111,110,116,114,97,114,97,110 ,195,161,108,105,115,105,115,102,97,118,111,114,105,116,111,115,116,195,169,114, 109,105,110,111,115,112,114,111,118,105,110,99,105,97,101,116,105,113,117,101, 116,97,115,101,108,101,109,101,110,116,111,115,102,117,110,99,105,111,110,101, 115,114,101,115,117,108,116,97,100,111,99,97,114,195,161,99,116,101,114,112,114, 111,112,105,101,100,97,100,112,114,105,110,99,105,112,105,111,110,101,99,101,115 ,105,100,97,100,109,117,110,105,99,105,112,97,108,99,114,101,97,99,105,195,179, 110,100,101,115,99,97,114,103,97,115,112,114,101,115,101,110,99,105,97,99,111, 109,101,114,99,105,97,108,111,112,105,110,105,111,110,101,115,101,106,101,114,99 ,105,99,105,111,101,100,105,116,111,114,105,97,108,115,97,108,97,109,97,110,99, 97,103,111,110,122,195,161,108,101,122,100,111,99,117,109,101,110,116,111,112, 101,108,195,173,99,117,108,97,114,101,99,105,101,110,116,101,115,103,101,110,101 ,114,97,108,101,115,116,97,114,114,97,103,111,110,97,112,114,195,161,99,116,105, 99,97,110,111,118,101,100,97,100,101,115,112,114,111,112,117,101,115,116,97,112, 97,99,105,101,110,116,101,115,116,195,169,99,110,105,99,97,115,111,98,106,101, 116,105,118,111,115,99,111,110,116,97,99,116,111,115,224,164,174,224,165,135,224 ,164,130,224,164,178,224,164,191,224,164,143,224,164,185,224,165,136,224,164,130 ,224,164,151,224,164,175,224,164,190,224,164,184,224,164,190,224,164,165,224,164 ,143,224,164,181,224,164,130,224,164,176,224,164,185,224,165,135,224,164,149,224 ,165,139,224,164,136,224,164,149,224,165,129,224,164,155,224,164,176,224,164,185 ,224,164,190,224,164,172,224,164,190,224,164,166,224,164,149,224,164,185,224,164 ,190,224,164,184,224,164,173,224,165,128,224,164,185,224,165,129,224,164,143,224 ,164,176,224,164,185,224,165,128,224,164,174,224,165,136,224,164,130,224,164,166 ,224,164,191,224,164,168,224,164,172,224,164,190,224,164,164,100,105,112,108,111 ,100,111,99,115,224,164,184,224,164,174,224,164,175,224,164,176,224,165,130,224, 164,170,224,164,168,224,164,190,224,164,174,224,164,170,224,164,164,224,164,190, 224,164,171,224,164,191,224,164,176,224,164,148,224,164,184,224,164,164,224,164, 164,224,164,176,224,164,185,224,164,178,224,165,139,224,164,151,224,164,185,224, 165,129,224,164,134,224,164,172,224,164,190,224,164,176,224,164,166,224,165,135, 224,164,182,224,164,185,224,165,129,224,164,136,224,164,150,224,165,135,224,164, 178,224,164,175,224,164,166,224,164,191,224,164,149,224,164,190,224,164,174,224, 164,181,224,165,135,224,164,172,224,164,164,224,165,128,224,164,168,224,164,172, 224,165,128,224,164,154,224,164,174,224,165,140,224,164,164,224,164,184,224,164, 190,224,164,178,224,164,178,224,165,135,224,164,150,224,164,156,224,165,137,224, 164,172,224,164,174,224,164,166,224,164,166,224,164,164,224,164,165,224,164,190, 224,164,168,224,164,185,224,165,128,224,164,182,224,164,185,224,164,176,224,164, 133,224,164,178,224,164,151,224,164,149,224,164,173,224,165,128,224,164,168,224, 164,151,224,164,176,224,164,170,224,164,190,224,164,184,224,164,176,224,164,190, 224,164,164,224,164,149,224,164,191,224,164,143,224,164,137,224,164,184,224,165, 135,224,164,151,224,164,175,224,165,128,224,164,185,224,165,130,224,164,129,224, 164,134,224,164,151,224,165,135,224,164,159,224,165,128,224,164,174,224,164,150, 224,165,139,224,164,156,224,164,149,224,164,190,224,164,176,224,164,133,224,164, 173,224,165,128,224,164,151,224,164,175,224,165,135,224,164,164,224,165,129,224, 164,174,224,164,181,224,165,139,224,164,159,224,164,166,224,165,135,224,164,130, 224,164,133,224,164,151,224,164,176,224,164,144,224,164,184,224,165,135,224,164, 174,224,165,135,224,164,178,224,164,178,224,164,151,224,164,190,224,164,185,224, 164,190,224,164,178,224,164,138,224,164,170,224,164,176,224,164,154,224,164,190, 224,164,176,224,164,144,224,164,184,224,164,190,224,164,166,224,165,135,224,164, 176,224,164,156,224,164,191,224,164,184,224,164,166,224,164,191,224,164,178,224, 164,172,224,164,130,224,164,166,224,164,172,224,164,168,224,164,190,224,164,185, 224,165,130,224,164,130,224,164,178,224,164,190,224,164,150,224,164,156,224,165, 128,224,164,164,224,164,172,224,164,159,224,164,168,224,164,174,224,164,191,224, 164,178,224,164,135,224,164,184,224,165,135,224,164,134,224,164,168,224,165,135, 224,164,168,224,164,175,224,164,190,224,164,149,224,165,129,224,164,178,224,164, 178,224,165,137,224,164,151,224,164,173,224,164,190,224,164,151,224,164,176,224, 165,135,224,164,178,224,164,156,224,164,151,224,164,185,224,164,176,224,164,190, 224,164,174,224,164,178,224,164,151,224,165,135,224,164,170,224,165,135,224,164, 156,224,164,185,224,164,190,224,164,165,224,164,135,224,164,184,224,165,128,224, 164,184,224,164,185,224,165,128,224,164,149,224,164,178,224,164,190,224,164,160, 224,165,128,224,164,149,224,164,185,224,164,190,224,164,129,224,164,166,224,165, 130,224,164,176,224,164,164,224,164,185,224,164,164,224,164,184,224,164,190,224, 164,164,224,164,175,224,164,190,224,164,166,224,164,134,224,164,175,224,164,190, 224,164,170,224,164,190,224,164,149,224,164,149,224,165,140,224,164,168,224,164, 182,224,164,190,224,164,174,224,164,166,224,165,135,224,164,150,224,164,175,224, 164,185,224,165,128,224,164,176,224,164,190,224,164,175,224,164,150,224,165,129, 224,164,166,224,164,178,224,164,151,224,165,128,99,97,116,101,103,111,114,105, 101,115,101,120,112,101,114,105,101,110,99,101,60,47,116,105,116,108,101,62,13, 10,67,111,112,121,114,105,103,104,116,32,106,97,118,97,115,99,114,105,112,116,99 ,111,110,100,105,116,105,111,110,115,101,118,101,114,121,116,104,105,110,103,60, 112,32,99,108,97,115,115,61,34,116,101,99,104,110,111,108,111,103,121,98,97,99, 107,103,114,111,117,110,100,60,97,32,99,108,97,115,115,61,34,109,97,110,97,103, 101,109,101,110,116,38,99,111,112,121,59,32,50,48,49,106,97,118,97,83,99,114,105 ,112,116,99,104,97,114,97,99,116,101,114,115,98,114,101,97,100,99,114,117,109,98 ,116,104,101,109,115,101,108,118,101,115,104,111,114,105,122,111,110,116,97,108, 103,111,118,101,114,110,109,101,110,116,67,97,108,105,102,111,114,110,105,97,97, 99,116,105,118,105,116,105,101,115,100,105,115,99,111,118,101,114,101,100,78,97, 118,105,103,97,116,105,111,110,116,114,97,110,115,105,116,105,111,110,99,111,110 ,110,101,99,116,105,111,110,110,97,118,105,103,97,116,105,111,110,97,112,112,101 ,97,114,97,110,99,101,60,47,116,105,116,108,101,62,60,109,99,104,101,99,107,98, 111,120,34,32,116,101,99,104,110,105,113,117,101,115,112,114,111,116,101,99,116, 105,111,110,97,112,112,97,114,101,110,116,108,121,97,115,32,119,101,108,108,32, 97,115,117,110,116,39,44,32,39,85,65,45,114,101,115,111,108,117,116,105,111,110, 111,112,101,114,97,116,105,111,110,115,116,101,108,101,118,105,115,105,111,110, 116,114,97,110,115,108,97,116,101,100,87,97,115,104,105,110,103,116,111,110,110, 97,118,105,103,97,116,111,114,46,32,61,32,119,105,110,100,111,119,46,105,109,112 ,114,101,115,115,105,111,110,38,108,116,59,98,114,38,103,116,59,108,105,116,101, 114,97,116,117,114,101,112,111,112,117,108,97,116,105,111,110,98,103,99,111,108, 111,114,61,34,35,101,115,112,101,99,105,97,108,108,121,32,99,111,110,116,101,110 ,116,61,34,112,114,111,100,117,99,116,105,111,110,110,101,119,115,108,101,116, 116,101,114,112,114,111,112,101,114,116,105,101,115,100,101,102,105,110,105,116, 105,111,110,108,101,97,100,101,114,115,104,105,112,84,101,99,104,110,111,108,111 ,103,121,80,97,114,108,105,97,109,101,110,116,99,111,109,112,97,114,105,115,111, 110,117,108,32,99,108,97,115,115,61,34,46,105,110,100,101,120,79,102,40,34,99, 111,110,99,108,117,115,105,111,110,100,105,115,99,117,115,115,105,111,110,99,111 ,109,112,111,110,101,110,116,115,98,105,111,108,111,103,105,99,97,108,82,101,118 ,111,108,117,116,105,111,110,95,99,111,110,116,97,105,110,101,114,117,110,100, 101,114,115,116,111,111,100,110,111,115,99,114,105,112,116,62,60,112,101,114,109 ,105,115,115,105,111,110,101,97,99,104,32,111,116,104,101,114,97,116,109,111,115 ,112,104,101,114,101,32,111,110,102,111,99,117,115,61,34,60,102,111,114,109,32, 105,100,61,34,112,114,111,99,101,115,115,105,110,103,116,104,105,115,46,118,97, 108,117,101,103,101,110,101,114,97,116,105,111,110,67,111,110,102,101,114,101, 110,99,101,115,117,98,115,101,113,117,101,110,116,119,101,108,108,45,107,110,111 ,119,110,118,97,114,105,97,116,105,111,110,115,114,101,112,117,116,97,116,105, 111,110,112,104,101,110,111,109,101,110,111,110,100,105,115,99,105,112,108,105, 110,101,108,111,103,111,46,112,110,103,34,32,40,100,111,99,117,109,101,110,116, 44,98,111,117,110,100,97,114,105,101,115,101,120,112,114,101,115,115,105,111,110 ,115,101,116,116,108,101,109,101,110,116,66,97,99,107,103,114,111,117,110,100, 111,117,116,32,111,102,32,116,104,101,101,110,116,101,114,112,114,105,115,101,40 ,34,104,116,116,112,115,58,34,32,117,110,101,115,99,97,112,101,40,34,112,97,115, 115,119,111,114,100,34,32,100,101,109,111,99,114,97,116,105,99,60,97,32,104,114, 101,102,61,34,47,119,114,97,112,112,101,114,34,62,10,109,101,109,98,101,114,115, 104,105,112,108,105,110,103,117,105,115,116,105,99,112,120,59,112,97,100,100,105 ,110,103,112,104,105,108,111,115,111,112,104,121,97,115,115,105,115,116,97,110, 99,101,117,110,105,118,101,114,115,105,116,121,102,97,99,105,108,105,116,105,101 ,115,114,101,99,111,103,110,105,122,101,100,112,114,101,102,101,114,101,110,99, 101,105,102,32,40,116,121,112,101,111,102,109,97,105,110,116,97,105,110,101,100, 118,111,99,97,98,117,108,97,114,121,104,121,112,111,116,104,101,115,105,115,46, 115,117,98,109,105,116,40,41,59,38,97,109,112,59,110,98,115,112,59,97,110,110, 111,116,97,116,105,111,110,98,101,104,105,110,100,32,116,104,101,70,111,117,110, 100,97,116,105,111,110,112,117,98,108,105,115,104,101,114,34,97,115,115,117,109, 112,116,105,111,110,105,110,116,114,111,100,117,99,101,100,99,111,114,114,117, 112,116,105,111,110,115,99,105,101,110,116,105,115,116,115,101,120,112,108,105, 99,105,116,108,121,105,110,115,116,101,97,100,32,111,102,100,105,109,101,110,115 ,105,111,110,115,32,111,110,67,108,105,99,107,61,34,99,111,110,115,105,100,101, 114,101,100,100,101,112,97,114,116,109,101,110,116,111,99,99,117,112,97,116,105, 111,110,115,111,111,110,32,97,102,116,101,114,105,110,118,101,115,116,109,101, 110,116,112,114,111,110,111,117,110,99,101,100,105,100,101,110,116,105,102,105, 101,100,101,120,112,101,114,105,109,101,110,116,77,97,110,97,103,101,109,101,110 ,116,103,101,111,103,114,97,112,104,105,99,34,32,104,101,105,103,104,116,61,34, 108,105,110,107,32,114,101,108,61,34,46,114,101,112,108,97,99,101,40,47,100,101, 112,114,101,115,115,105,111,110,99,111,110,102,101,114,101,110,99,101,112,117, 110,105,115,104,109,101,110,116,101,108,105,109,105,110,97,116,101,100,114,101, 115,105,115,116,97,110,99,101,97,100,97,112,116,97,116,105,111,110,111,112,112, 111,115,105,116,105,111,110,119,101,108,108,32,107,110,111,119,110,115,117,112, 112,108,101,109,101,110,116,100,101,116,101,114,109,105,110,101,100,104,49,32,99 ,108,97,115,115,61,34,48,112,120,59,109,97,114,103,105,110,109,101,99,104,97,110 ,105,99,97,108,115,116,97,116,105,115,116,105,99,115,99,101,108,101,98,114,97, 116,101,100,71,111,118,101,114,110,109,101,110,116,10,10,68,117,114,105,110,103, 32,116,100,101,118,101,108,111,112,101,114,115,97,114,116,105,102,105,99,105,97, 108,101,113,117,105,118,97,108,101,110,116,111,114,105,103,105,110,97,116,101, 100,67,111,109,109,105,115,115,105,111,110,97,116,116,97,99,104,109,101,110,116, 60,115,112,97,110,32,105,100,61,34,116,104,101,114,101,32,119,101,114,101,78,101 ,100,101,114,108,97,110,100,115,98,101,121,111,110,100,32,116,104,101,114,101, 103,105,115,116,101,114,101,100,106,111,117,114,110,97,108,105,115,116,102,114, 101,113,117,101,110,116,108,121,97,108,108,32,111,102,32,116,104,101,108,97,110, 103,61,34,101,110,34,32,60,47,115,116,121,108,101,62,13,10,97,98,115,111,108,117 ,116,101,59,32,115,117,112,112,111,114,116,105,110,103,101,120,116,114,101,109, 101,108,121,32,109,97,105,110,115,116,114,101,97,109,60,47,115,116,114,111,110, 103,62,32,112,111,112,117,108,97,114,105,116,121,101,109,112,108,111,121,109,101 ,110,116,60,47,116,97,98,108,101,62,13,10,32,99,111,108,115,112,97,110,61,34,60, 47,102,111,114,109,62,10,32,32,99,111,110,118,101,114,115,105,111,110,97,98,111, 117,116,32,116,104,101,32,60,47,112,62,60,47,100,105,118,62,105,110,116,101,103, 114,97,116,101,100,34,32,108,97,110,103,61,34,101,110,80,111,114,116,117,103,117 ,101,115,101,115,117,98,115,116,105,116,117,116,101,105,110,100,105,118,105,100, 117,97,108,105,109,112,111,115,115,105,98,108,101,109,117,108,116,105,109,101, 100,105,97,97,108,109,111,115,116,32,97,108,108,112,120,32,115,111,108,105,100, 32,35,97,112,97,114,116,32,102,114,111,109,115,117,98,106,101,99,116,32,116,111, 105,110,32,69,110,103,108,105,115,104,99,114,105,116,105,99,105,122,101,100,101, 120,99,101,112,116,32,102,111,114,103,117,105,100,101,108,105,110,101,115,111, 114,105,103,105,110,97,108,108,121,114,101,109,97,114,107,97,98,108,101,116,104, 101,32,115,101,99,111,110,100,104,50,32,99,108,97,115,115,61,34,60,97,32,116,105 ,116,108,101,61,34,40,105,110,99,108,117,100,105,110,103,112,97,114,97,109,101, 116,101,114,115,112,114,111,104,105,98,105,116,101,100,61,32,34,104,116,116,112, 58,47,47,100,105,99,116,105,111,110,97,114,121,112,101,114,99,101,112,116,105, 111,110,114,101,118,111,108,117,116,105,111,110,102,111,117,110,100,97,116,105, 111,110,112,120,59,104,101,105,103,104,116,58,115,117,99,99,101,115,115,102,117, 108,115,117,112,112,111,114,116,101,114,115,109,105,108,108,101,110,110,105,117, 109,104,105,115,32,102,97,116,104,101,114,116,104,101,32,38,113,117,111,116,59, 110,111,45,114,101,112,101,97,116,59,99,111,109,109,101,114,99,105,97,108,105, 110,100,117,115,116,114,105,97,108,101,110,99,111,117,114,97,103,101,100,97,109, 111,117,110,116,32,111,102,32,117,110,111,102,102,105,99,105,97,108,101,102,102, 105,99,105,101,110,99,121,82,101,102,101,114,101,110,99,101,115,99,111,111,114, 100,105,110,97,116,101,100,105,115,99,108,97,105,109,101,114,101,120,112,101,100 ,105,116,105,111,110,100,101,118,101,108,111,112,105,110,103,99,97,108,99,117, 108,97,116,101,100,115,105,109,112,108,105,102,105,101,100,108,101,103,105,116, 105,109,97,116,101,115,117,98,115,116,114,105,110,103,40,48,34,32,99,108,97,115, 115,61,34,99,111,109,112,108,101,116,101,108,121,105,108,108,117,115,116,114,97, 116,101,102,105,118,101,32,121,101,97,114,115,105,110,115,116,114,117,109,101, 110,116,80,117,98,108,105,115,104,105,110,103,49,34,32,99,108,97,115,115,61,34, 112,115,121,99,104,111,108,111,103,121,99,111,110,102,105,100,101,110,99,101,110 ,117,109,98,101,114,32,111,102,32,97,98,115,101,110,99,101,32,111,102,102,111,99 ,117,115,101,100,32,111,110,106,111,105,110,101,100,32,116,104,101,115,116,114, 117,99,116,117,114,101,115,112,114,101,118,105,111,117,115,108,121,62,60,47,105, 102,114,97,109,101,62,111,110,99,101,32,97,103,97,105,110,98,117,116,32,114,97, 116,104,101,114,105,109,109,105,103,114,97,110,116,115,111,102,32,99,111,117,114 ,115,101,44,97,32,103,114,111,117,112,32,111,102,76,105,116,101,114,97,116,117, 114,101,85,110,108,105,107,101,32,116,104,101,60,47,97,62,38,110,98,115,112,59, 10,102,117,110,99,116,105,111,110,32,105,116,32,119,97,115,32,116,104,101,67,111 ,110,118,101,110,116,105,111,110,97,117,116,111,109,111,98,105,108,101,80,114, 111,116,101,115,116,97,110,116,97,103,103,114,101,115,115,105,118,101,97,102,116 ,101,114,32,116,104,101,32,83,105,109,105,108,97,114,108,121,44,34,32,47,62,60, 47,100,105,118,62,99,111,108,108,101,99,116,105,111,110,13,10,102,117,110,99,116 ,105,111,110,118,105,115,105,98,105,108,105,116,121,116,104,101,32,117,115,101, 32,111,102,118,111,108,117,110,116,101,101,114,115,97,116,116,114,97,99,116,105, 111,110,117,110,100,101,114,32,116,104,101,32,116,104,114,101,97,116,101,110,101 ,100,42,60,33,91,67,68,65,84,65,91,105,109,112,111,114,116,97,110,99,101,105,110 ,32,103,101,110,101,114,97,108,116,104,101,32,108,97,116,116,101,114,60,47,102, 111,114,109,62,10,60,47,46,105,110,100,101,120,79,102,40,39,105,32,61,32,48,59, 32,105,32,60,100,105,102,102,101,114,101,110,99,101,100,101,118,111,116,101,100, 32,116,111,116,114,97,100,105,116,105,111,110,115,115,101,97,114,99,104,32,102, 111,114,117,108,116,105,109,97,116,101,108,121,116,111,117,114,110,97,109,101, 110,116,97,116,116,114,105,98,117,116,101,115,115,111,45,99,97,108,108,101,100, 32,125,10,60,47,115,116,121,108,101,62,101,118,97,108,117,97,116,105,111,110,101 ,109,112,104,97,115,105,122,101,100,97,99,99,101,115,115,105,98,108,101,60,47, 115,101,99,116,105,111,110,62,115,117,99,99,101,115,115,105,111,110,97,108,111, 110,103,32,119,105,116,104,77,101,97,110,119,104,105,108,101,44,105,110,100,117, 115,116,114,105,101,115,60,47,97,62,60,98,114,32,47,62,104,97,115,32,98,101,99, 111,109,101,97,115,112,101,99,116,115,32,111,102,84,101,108,101,118,105,115,105, 111,110,115,117,102,102,105,99,105,101,110,116,98,97,115,107,101,116,98,97,108, 108,98,111,116,104,32,115,105,100,101,115,99,111,110,116,105,110,117,105,110,103 ,97,110,32,97,114,116,105,99,108,101,60,105,109,103,32,97,108,116,61,34,97,100, 118,101,110,116,117,114,101,115,104,105,115,32,109,111,116,104,101,114,109,97, 110,99,104,101,115,116,101,114,112,114,105,110,99,105,112,108,101,115,112,97,114 ,116,105,99,117,108,97,114,99,111,109,109,101,110,116,97,114,121,101,102,102,101 ,99,116,115,32,111,102,100,101,99,105,100,101,100,32,116,111,34,62,60,115,116, 114,111,110,103,62,112,117,98,108,105,115,104,101,114,115,74,111,117,114,110,97, 108,32,111,102,100,105,102,102,105,99,117,108,116,121,102,97,99,105,108,105,116, 97,116,101,97,99,99,101,112,116,97,98,108,101,115,116,121,108,101,46,99,115,115, 34,9,102,117,110,99,116,105,111,110,32,105,110,110,111,118,97,116,105,111,110,62 ,67,111,112,121,114,105,103,104,116,115,105,116,117,97,116,105,111,110,115,119, 111,117,108,100,32,104,97,118,101,98,117,115,105,110,101,115,115,101,115,68,105, 99,116,105,111,110,97,114,121,115,116,97,116,101,109,101,110,116,115,111,102,116 ,101,110,32,117,115,101,100,112,101,114,115,105,115,116,101,110,116,105,110,32, 74,97,110,117,97,114,121,99,111,109,112,114,105,115,105,110,103,60,47,116,105, 116,108,101,62,10,9,100,105,112,108,111,109,97,116,105,99,99,111,110,116,97,105, 110,105,110,103,112,101,114,102,111,114,109,105,110,103,101,120,116,101,110,115, 105,111,110,115,109,97,121,32,110,111,116,32,98,101,99,111,110,99,101,112,116,32 ,111,102,32,111,110,99,108,105,99,107,61,34,73,116,32,105,115,32,97,108,115,111, 102,105,110,97,110,99,105,97,108,32,109,97,107,105,110,103,32,116,104,101,76,117 ,120,101,109,98,111,117,114,103,97,100,100,105,116,105,111,110,97,108,97,114,101 ,32,99,97,108,108,101,100,101,110,103,97,103,101,100,32,105,110,34,115,99,114, 105,112,116,34,41,59,98,117,116,32,105,116,32,119,97,115,101,108,101,99,116,114, 111,110,105,99,111,110,115,117,98,109,105,116,61,34,10,60,33,45,45,32,69,110,100 ,32,101,108,101,99,116,114,105,99,97,108,111,102,102,105,99,105,97,108,108,121, 115,117,103,103,101,115,116,105,111,110,116,111,112,32,111,102,32,116,104,101, 117,110,108,105,107,101,32,116,104,101,65,117,115,116,114,97,108,105,97,110,79, 114,105,103,105,110,97,108,108,121,114,101,102,101,114,101,110,99,101,115,10,60, 47,104,101,97,100,62,13,10,114,101,99,111,103,110,105,115,101,100,105,110,105, 116,105,97,108,105,122,101,108,105,109,105,116,101,100,32,116,111,65,108,101,120 ,97,110,100,114,105,97,114,101,116,105,114,101,109,101,110,116,65,100,118,101, 110,116,117,114,101,115,102,111,117,114,32,121,101,97,114,115,10,10,38,108,116, 59,33,45,45,32,105,110,99,114,101,97,115,105,110,103,100,101,99,111,114,97,116, 105,111,110,104,51,32,99,108,97,115,115,61,34,111,114,105,103,105,110,115,32,111 ,102,111,98,108,105,103,97,116,105,111,110,114,101,103,117,108,97,116,105,111, 110,99,108,97,115,115,105,102,105,101,100,40,102,117,110,99,116,105,111,110,40, 97,100,118,97,110,116,97,103,101,115,98,101,105,110,103,32,116,104,101,32,104, 105,115,116,111,114,105,97,110,115,60,98,97,115,101,32,104,114,101,102,114,101, 112,101,97,116,101,100,108,121,119,105,108,108,105,110,103,32,116,111,99,111,109 ,112,97,114,97,98,108,101,100,101,115,105,103,110,97,116,101,100,110,111,109,105 ,110,97,116,105,111,110,102,117,110,99,116,105,111,110,97,108,105,110,115,105, 100,101,32,116,104,101,114,101,118,101,108,97,116,105,111,110,101,110,100,32,111 ,102,32,116,104,101,115,32,102,111,114,32,116,104,101,32,97,117,116,104,111,114, 105,122,101,100,114,101,102,117,115,101,100,32,116,111,116,97,107,101,32,112,108 ,97,99,101,97,117,116,111,110,111,109,111,117,115,99,111,109,112,114,111,109,105 ,115,101,112,111,108,105,116,105,99,97,108,32,114,101,115,116,97,117,114,97,110, 116,116,119,111,32,111,102,32,116,104,101,70,101,98,114,117,97,114,121,32,50,113 ,117,97,108,105,116,121,32,111,102,115,119,102,111,98,106,101,99,116,46,117,110, 100,101,114,115,116,97,110,100,110,101,97,114,108,121,32,97,108,108,119,114,105, 116,116,101,110,32,98,121,105,110,116,101,114,118,105,101,119,115,34,32,119,105, 100,116,104,61,34,49,119,105,116,104,100,114,97,119,97,108,102,108,111,97,116,58 ,108,101,102,116,105,115,32,117,115,117,97,108,108,121,99,97,110,100,105,100,97, 116,101,115,110,101,119,115,112,97,112,101,114,115,109,121,115,116,101,114,105, 111,117,115,68,101,112,97,114,116,109,101,110,116,98,101,115,116,32,107,110,111, 119,110,112,97,114,108,105,97,109,101,110,116,115,117,112,112,114,101,115,115, 101,100,99,111,110,118,101,110,105,101,110,116,114,101,109,101,109,98,101,114, 101,100,100,105,102,102,101,114,101,110,116,32,115,121,115,116,101,109,97,116, 105,99,104,97,115,32,108,101,100,32,116,111,112,114,111,112,97,103,97,110,100,97 ,99,111,110,116,114,111,108,108,101,100,105,110,102,108,117,101,110,99,101,115, 99,101,114,101,109,111,110,105,97,108,112,114,111,99,108,97,105,109,101,100,80, 114,111,116,101,99,116,105,111,110,108,105,32,99,108,97,115,115,61,34,83,99,105, 101,110,116,105,102,105,99,99,108,97,115,115,61,34,110,111,45,116,114,97,100,101 ,109,97,114,107,115,109,111,114,101,32,116,104,97,110,32,119,105,100,101,115,112 ,114,101,97,100,76,105,98,101,114,97,116,105,111,110,116,111,111,107,32,112,108, 97,99,101,100,97,121,32,111,102,32,116,104,101,97,115,32,108,111,110,103,32,97, 115,105,109,112,114,105,115,111,110,101,100,65,100,100,105,116,105,111,110,97, 108,10,60,104,101,97,100,62,10,60,109,76,97,98,111,114,97,116,111,114,121,78,111 ,118,101,109,98,101,114,32,50,101,120,99,101,112,116,105,111,110,115,73,110,100, 117,115,116,114,105,97,108,118,97,114,105,101,116,121,32,111,102,102,108,111,97, 116,58,32,108,101,102,68,117,114,105,110,103,32,116,104,101,97,115,115,101,115, 115,109,101,110,116,104,97,118,101,32,98,101,101,110,32,100,101,97,108,115,32, 119,105,116,104,83,116,97,116,105,115,116,105,99,115,111,99,99,117,114,114,101, 110,99,101,47,117,108,62,60,47,100,105,118,62,99,108,101,97,114,102,105,120,34, 62,116,104,101,32,112,117,98,108,105,99,109,97,110,121,32,121,101,97,114,115,119 ,104,105,99,104,32,119,101,114,101,111,118,101,114,32,116,105,109,101,44,115,121 ,110,111,110,121,109,111,117,115,99,111,110,116,101,110,116,34,62,10,112,114,101 ,115,117,109,97,98,108,121,104,105,115,32,102,97,109,105,108,121,117,115,101,114 ,65,103,101,110,116,46,117,110,101,120,112,101,99,116,101,100,105,110,99,108,117 ,100,105,110,103,32,99,104,97,108,108,101,110,103,101,100,97,32,109,105,110,111, 114,105,116,121,117,110,100,101,102,105,110,101,100,34,98,101,108,111,110,103, 115,32,116,111,116,97,107,101,110,32,102,114,111,109,105,110,32,79,99,116,111,98 ,101,114,112,111,115,105,116,105,111,110,58,32,115,97,105,100,32,116,111,32,98, 101,114,101,108,105,103,105,111,117,115,32,70,101,100,101,114,97,116,105,111,110 ,32,114,111,119,115,112,97,110,61,34,111,110,108,121,32,97,32,102,101,119,109, 101,97,110,116,32,116,104,97,116,108,101,100,32,116,111,32,116,104,101,45,45,62, 13,10,60,100,105,118,32,60,102,105,101,108,100,115,101,116,62,65,114,99,104,98, 105,115,104,111,112,32,99,108,97,115,115,61,34,110,111,98,101,105,110,103,32,117 ,115,101,100,97,112,112,114,111,97,99,104,101,115,112,114,105,118,105,108,101, 103,101,115,110,111,115,99,114,105,112,116,62,10,114,101,115,117,108,116,115,32, 105,110,109,97,121,32,98,101,32,116,104,101,69,97,115,116,101,114,32,101,103,103 ,109,101,99,104,97,110,105,115,109,115,114,101,97,115,111,110,97,98,108,101,80, 111,112,117,108,97,116,105,111,110,67,111,108,108,101,99,116,105,111,110,115,101 ,108,101,99,116,101,100,34,62,110,111,115,99,114,105,112,116,62,13,47,105,110, 100,101,120,46,112,104,112,97,114,114,105,118,97,108,32,111,102,45,106,115,115, 100,107,39,41,41,59,109,97,110,97,103,101,100,32,116,111,105,110,99,111,109,112, 108,101,116,101,99,97,115,117,97,108,116,105,101,115,99,111,109,112,108,101,116, 105,111,110,67,104,114,105,115,116,105,97,110,115,83,101,112,116,101,109,98,101, 114,32,97,114,105,116,104,109,101,116,105,99,112,114,111,99,101,100,117,114,101, 115,109,105,103,104,116,32,104,97,118,101,80,114,111,100,117,99,116,105,111,110, 105,116,32,97,112,112,101,97,114,115,80,104,105,108,111,115,111,112,104,121,102, 114,105,101,110,100,115,104,105,112,108,101,97,100,105,110,103,32,116,111,103, 105,118,105,110,103,32,116,104,101,116,111,119,97,114,100,32,116,104,101,103,117 ,97,114,97,110,116,101,101,100,100,111,99,117,109,101,110,116,101,100,99,111,108 ,111,114,58,35,48,48,48,118,105,100,101,111,32,103,97,109,101,99,111,109,109,105 ,115,115,105,111,110,114,101,102,108,101,99,116,105,110,103,99,104,97,110,103, 101,32,116,104,101,97,115,115,111,99,105,97,116,101,100,115,97,110,115,45,115, 101,114,105,102,111,110,107,101,121,112,114,101,115,115,59,32,112,97,100,100,105 ,110,103,58,72,101,32,119,97,115,32,116,104,101,117,110,100,101,114,108,121,105, 110,103,116,121,112,105,99,97,108,108,121,32,44,32,97,110,100,32,116,104,101,32, 115,114,99,69,108,101,109,101,110,116,115,117,99,99,101,115,115,105,118,101,115, 105,110,99,101,32,116,104,101,32,115,104,111,117,108,100,32,98,101,32,110,101, 116,119,111,114,107,105,110,103,97,99,99,111,117,110,116,105,110,103,117,115,101 ,32,111,102,32,116,104,101,108,111,119,101,114,32,116,104,97,110,115,104,111,119 ,115,32,116,104,97,116,60,47,115,112,97,110,62,10,9,9,99,111,109,112,108,97,105, 110,116,115,99,111,110,116,105,110,117,111,117,115,113,117,97,110,116,105,116, 105,101,115,97,115,116,114,111,110,111,109,101,114,104,101,32,100,105,100,32,110 ,111,116,100,117,101,32,116,111,32,105,116,115,97,112,112,108,105,101,100,32,116 ,111,97,110,32,97,118,101,114,97,103,101,101,102,102,111,114,116,115,32,116,111, 116,104,101,32,102,117,116,117,114,101,97,116,116,101,109,112,116,32,116,111,84, 104,101,114,101,102,111,114,101,44,99,97,112,97,98,105,108,105,116,121,82,101, 112,117,98,108,105,99,97,110,119,97,115,32,102,111,114,109,101,100,69,108,101,99 ,116,114,111,110,105,99,107,105,108,111,109,101,116,101,114,115,99,104,97,108, 108,101,110,103,101,115,112,117,98,108,105,115,104,105,110,103,116,104,101,32, 102,111,114,109,101,114,105,110,100,105,103,101,110,111,117,115,100,105,114,101, 99,116,105,111,110,115,115,117,98,115,105,100,105,97,114,121,99,111,110,115,112, 105,114,97,99,121,100,101,116,97,105,108,115,32,111,102,97,110,100,32,105,110,32 ,116,104,101,97,102,102,111,114,100,97,98,108,101,115,117,98,115,116,97,110,99, 101,115,114,101,97,115,111,110,32,102,111,114,99,111,110,118,101,110,116,105,111 ,110,105,116,101,109,116,121,112,101,61,34,97,98,115,111,108,117,116,101,108,121 ,115,117,112,112,111,115,101,100,108,121,114,101,109,97,105,110,101,100,32,97,97 ,116,116,114,97,99,116,105,118,101,116,114,97,118,101,108,108,105,110,103,115, 101,112,97,114,97,116,101,108,121,102,111,99,117,115,101,115,32,111,110,101,108, 101,109,101,110,116,97,114,121,97,112,112,108,105,99,97,98,108,101,102,111,117, 110,100,32,116,104,97,116,115,116,121,108,101,115,104,101,101,116,109,97,110,117 ,115,99,114,105,112,116,115,116,97,110,100,115,32,102,111,114,32,110,111,45,114, 101,112,101,97,116,40,115,111,109,101,116,105,109,101,115,67,111,109,109,101,114 ,99,105,97,108,105,110,32,65,109,101,114,105,99,97,117,110,100,101,114,116,97, 107,101,110,113,117,97,114,116,101,114,32,111,102,97,110,32,101,120,97,109,112, 108,101,112,101,114,115,111,110,97,108,108,121,105,110,100,101,120,46,112,104, 112,63,60,47,98,117,116,116,111,110,62,10,112,101,114,99,101,110,116,97,103,101, 98,101,115,116,45,107,110,111,119,110,99,114,101,97,116,105,110,103,32,97,34,32, 100,105,114,61,34,108,116,114,76,105,101,117,116,101,110,97,110,116,10,60,100, 105,118,32,105,100,61,34,116,104,101,121,32,119,111,117,108,100,97,98,105,108, 105,116,121,32,111,102,109,97,100,101,32,117,112,32,111,102,110,111,116,101,100, 32,116,104,97,116,99,108,101,97,114,32,116,104,97,116,97,114,103,117,101,32,116, 104,97,116,116,111,32,97,110,111,116,104,101,114,99,104,105,108,100,114,101,110, 39,115,112,117,114,112,111,115,101,32,111,102,102,111,114,109,117,108,97,116,101 ,100,98,97,115,101,100,32,117,112,111,110,116,104,101,32,114,101,103,105,111,110 ,115,117,98,106,101,99,116,32,111,102,112,97,115,115,101,110,103,101,114,115,112 ,111,115,115,101,115,115,105,111,110,46,10,10,73,110,32,116,104,101,32,66,101, 102,111,114,101,32,116,104,101,97,102,116,101,114,119,97,114,100,115,99,117,114, 114,101,110,116,108,121,32,97,99,114,111,115,115,32,116,104,101,115,99,105,101, 110,116,105,102,105,99,99,111,109,109,117,110,105,116,121,46,99,97,112,105,116, 97,108,105,115,109,105,110,32,71,101,114,109,97,110,121,114,105,103,104,116,45, 119,105,110,103,116,104,101,32,115,121,115,116,101,109,83,111,99,105,101,116,121 ,32,111,102,112,111,108,105,116,105,99,105,97,110,100,105,114,101,99,116,105,111 ,110,58,119,101,110,116,32,111,110,32,116,111,114,101,109,111,118,97,108,32,111, 102,32,78,101,119,32,89,111,114,107,32,97,112,97,114,116,109,101,110,116,115,105 ,110,100,105,99,97,116,105,111,110,100,117,114,105,110,103,32,116,104,101,117, 110,108,101,115,115,32,116,104,101,104,105,115,116,111,114,105,99,97,108,104,97, 100,32,98,101,101,110,32,97,100,101,102,105,110,105,116,105,118,101,105,110,103, 114,101,100,105,101,110,116,97,116,116,101,110,100,97,110,99,101,67,101,110,116, 101,114,32,102,111,114,112,114,111,109,105,110,101,110,99,101,114,101,97,100,121 ,83,116,97,116,101,115,116,114,97,116,101,103,105,101,115,98,117,116,32,105,110, 32,116,104,101,97,115,32,112,97,114,116,32,111,102,99,111,110,115,116,105,116, 117,116,101,99,108,97,105,109,32,116,104,97,116,108,97,98,111,114,97,116,111,114 ,121,99,111,109,112,97,116,105,98,108,101,102,97,105,108,117,114,101,32,111,102, 44,32,115,117,99,104,32,97,115,32,98,101,103,97,110,32,119,105,116,104,117,115, 105,110,103,32,116,104,101,32,116,111,32,112,114,111,118,105,100,101,102,101,97, 116,117,114,101,32,111,102,102,114,111,109,32,119,104,105,99,104,47,34,32,99,108 ,97,115,115,61,34,103,101,111,108,111,103,105,99,97,108,115,101,118,101,114,97, 108,32,111,102,100,101,108,105,98,101,114,97,116,101,105,109,112,111,114,116,97, 110,116,32,104,111,108,100,115,32,116,104,97,116,105,110,103,38,113,117,111,116, 59,32,118,97,108,105,103,110,61,116,111,112,116,104,101,32,71,101,114,109,97,110 ,111,117,116,115,105,100,101,32,111,102,110,101,103,111,116,105,97,116,101,100, 104,105,115,32,99,97,114,101,101,114,115,101,112,97,114,97,116,105,111,110,105, 100,61,34,115,101,97,114,99,104,119,97,115,32,99,97,108,108,101,100,116,104,101, 32,102,111,117,114,116,104,114,101,99,114,101,97,116,105,111,110,111,116,104,101 ,114,32,116,104,97,110,112,114,101,118,101,110,116,105,111,110,119,104,105,108, 101,32,116,104,101,32,101,100,117,99,97,116,105,111,110,44,99,111,110,110,101,99 ,116,105,110,103,97,99,99,117,114,97,116,101,108,121,119,101,114,101,32,98,117, 105,108,116,119,97,115,32,107,105,108,108,101,100,97,103,114,101,101,109,101,110 ,116,115,109,117,99,104,32,109,111,114,101,32,68,117,101,32,116,111,32,116,104, 101,119,105,100,116,104,58,32,49,48,48,115,111,109,101,32,111,116,104,101,114,75 ,105,110,103,100,111,109,32,111,102,116,104,101,32,101,110,116,105,114,101,102, 97,109,111,117,115,32,102,111,114,116,111,32,99,111,110,110,101,99,116,111,98, 106,101,99,116,105,118,101,115,116,104,101,32,70,114,101,110,99,104,112,101,111, 112,108,101,32,97,110,100,102,101,97,116,117,114,101,100,34,62,105,115,32,115,97 ,105,100,32,116,111,115,116,114,117,99,116,117,114,97,108,114,101,102,101,114, 101,110,100,117,109,109,111,115,116,32,111,102,116,101,110,97,32,115,101,112,97, 114,97,116,101,45,62,10,60,100,105,118,32,105,100,32,79,102,102,105,99,105,97, 108,32,119,111,114,108,100,119,105,100,101,46,97,114,105,97,45,108,97,98,101,108 ,116,104,101,32,112,108,97,110,101,116,97,110,100,32,105,116,32,119,97,115,100, 34,32,118,97,108,117,101,61,34,108,111,111,107,105,110,103,32,97,116,98,101,110, 101,102,105,99,105,97,108,97,114,101,32,105,110,32,116,104,101,109,111,110,105, 116,111,114,105,110,103,114,101,112,111,114,116,101,100,108,121,116,104,101,32, 109,111,100,101,114,110,119,111,114,107,105,110,103,32,111,110,97,108,108,111, 119,101,100,32,116,111,119,104,101,114,101,32,116,104,101,32,105,110,110,111,118 ,97,116,105,118,101,60,47,97,62,60,47,100,105,118,62,115,111,117,110,100,116,114 ,97,99,107,115,101,97,114,99,104,70,111,114,109,116,101,110,100,32,116,111,32,98 ,101,105,110,112,117,116,32,105,100,61,34,111,112,101,110,105,110,103,32,111,102 ,114,101,115,116,114,105,99,116,101,100,97,100,111,112,116,101,100,32,98,121,97, 100,100,114,101,115,115,105,110,103,116,104,101,111,108,111,103,105,97,110,109, 101,116,104,111,100,115,32,111,102,118,97,114,105,97,110,116,32,111,102,67,104, 114,105,115,116,105,97,110,32,118,101,114,121,32,108,97,114,103,101,97,117,116, 111,109,111,116,105,118,101,98,121,32,102,97,114,32,116,104,101,114,97,110,103, 101,32,102,114,111,109,112,117,114,115,117,105,116,32,111,102,102,111,108,108, 111,119,32,116,104,101,98,114,111,117,103,104,116,32,116,111,105,110,32,69,110, 103,108,97,110,100,97,103,114,101,101,32,116,104,97,116,97,99,99,117,115,101,100 ,32,111,102,99,111,109,101,115,32,102,114,111,109,112,114,101,118,101,110,116, 105,110,103,100,105,118,32,115,116,121,108,101,61,104,105,115,32,111,114,32,104, 101,114,116,114,101,109,101,110,100,111,117,115,102,114,101,101,100,111,109,32, 111,102,99,111,110,99,101,114,110,105,110,103,48,32,49,101,109,32,49,101,109,59, 66,97,115,107,101,116,98,97,108,108,47,115,116,121,108,101,46,99,115,115,97,110, 32,101,97,114,108,105,101,114,101,118,101,110,32,97,102,116,101,114,47,34,32,116 ,105,116,108,101,61,34,46,99,111,109,47,105,110,100,101,120,116,97,107,105,110, 103,32,116,104,101,112,105,116,116,115,98,117,114,103,104,99,111,110,116,101,110 ,116,34,62,13,60,115,99,114,105,112,116,62,40,102,116,117,114,110,101,100,32,111 ,117,116,104,97,118,105,110,103,32,116,104,101,60,47,115,112,97,110,62,13,10,32, 111,99,99,97,115,105,111,110,97,108,98,101,99,97,117,115,101,32,105,116,115,116, 97,114,116,101,100,32,116,111,112,104,121,115,105,99,97,108,108,121,62,60,47,100 ,105,118,62,10,32,32,99,114,101,97,116,101,100,32,98,121,67,117,114,114,101,110, 116,108,121,44,32,98,103,99,111,108,111,114,61,34,116,97,98,105,110,100,101,120, 61,34,100,105,115,97,115,116,114,111,117,115,65,110,97,108,121,116,105,99,115,32 ,97,108,115,111,32,104,97,115,32,97,62,60,100,105,118,32,105,100,61,34,60,47,115 ,116,121,108,101,62,10,60,99,97,108,108,101,100,32,102,111,114,115,105,110,103, 101,114,32,97,110,100,46,115,114,99,32,61,32,34,47,47,118,105,111,108,97,116,105 ,111,110,115,116,104,105,115,32,112,111,105,110,116,99,111,110,115,116,97,110, 116,108,121,105,115,32,108,111,99,97,116,101,100,114,101,99,111,114,100,105,110, 103,115,100,32,102,114,111,109,32,116,104,101,110,101,100,101,114,108,97,110,100 ,115,112,111,114,116,117,103,117,195,170,115,215,162,215,145,215,168,215,153,215 ,170,217,129,216,167,216,177,216,179,219,140,100,101,115,97,114,114,111,108,108, 111,99,111,109,101,110,116,97,114,105,111,101,100,117,99,97,99,105,195,179,110, 115,101,112,116,105,101,109,98,114,101,114,101,103,105,115,116,114,97,100,111, 100,105,114,101,99,99,105,195,179,110,117,98,105,99,97,99,105,195,179,110,112, 117,98,108,105,99,105,100,97,100,114,101,115,112,117,101,115,116,97,115,114,101, 115,117,108,116,97,100,111,115,105,109,112,111,114,116,97,110,116,101,114,101, 115,101,114,118,97,100,111,115,97,114,116,195,173,99,117,108,111,115,100,105,102 ,101,114,101,110,116,101,115,115,105,103,117,105,101,110,116,101,115,114,101,112 ,195,186,98,108,105,99,97,115,105,116,117,97,99,105,195,179,110,109,105,110,105, 115,116,101,114,105,111,112,114,105,118,97,99,105,100,97,100,100,105,114,101,99, 116,111,114,105,111,102,111,114,109,97,99,105,195,179,110,112,111,98,108,97,99, 105,195,179,110,112,114,101,115,105,100,101,110,116,101,99,111,110,116,101,110, 105,100,111,115,97,99,99,101,115,111,114,105,111,115,116,101,99,104,110,111,114, 97,116,105,112,101,114,115,111,110,97,108,101,115,99,97,116,101,103,111,114,195, 173,97,101,115,112,101,99,105,97,108,101,115,100,105,115,112,111,110,105,98,108, 101,97,99,116,117,97,108,105,100,97,100,114,101,102,101,114,101,110,99,105,97, 118,97,108,108,97,100,111,108,105,100,98,105,98,108,105,111,116,101,99,97,114, 101,108,97,99,105,111,110,101,115,99,97,108,101,110,100,97,114,105,111,112,111, 108,195,173,116,105,99,97,115,97,110,116,101,114,105,111,114,101,115,100,111,99, 117,109,101,110,116,111,115,110,97,116,117,114,97,108,101,122,97,109,97,116,101, 114,105,97,108,101,115,100,105,102,101,114,101,110,99,105,97,101,99,111,110,195, 179,109,105,99,97,116,114,97,110,115,112,111,114,116,101,114,111,100,114,195,173 ,103,117,101,122,112,97,114,116,105,99,105,112,97,114,101,110,99,117,101,110,116 ,114,97,110,100,105,115,99,117,115,105,195,179,110,101,115,116,114,117,99,116, 117,114,97,102,117,110,100,97,99,105,195,179,110,102,114,101,99,117,101,110,116, 101,115,112,101,114,109,97,110,101,110,116,101,116,111,116,97,108,109,101,110, 116,101,208,188,208,190,208,182,208,189,208,190,208,177,209,131,208,180,208,181, 209,130,208,188,208,190,208,182,208,181,209,130,208,178,209,128,208,181,208,188, 209,143,209,130,208,176,208,186,208,182,208,181,209,135,209,130,208,190,208,177, 209,139,208,177,208,190,208,187,208,181,208,181,208,190,209,135,208,181,208,189, 209,140,209,141,209,130,208,190,208,179,208,190,208,186,208,190,208,179,208,180, 208,176,208,191,208,190,209,129,208,187,208,181,208,178,209,129,208,181,208,179, 208,190,209,129,208,176,208,185,209,130,208,181,209,135,208,181,209,128,208,181, 208,183,208,188,208,190,208,179,209,131,209,130,209,129,208,176,208,185,209,130, 208,176,208,182,208,184,208,183,208,189,208,184,208,188,208,181,208,182,208,180, 209,131,208,177,209,131,208,180,209,131,209,130,208,159,208,190,208,184,209,129, 208,186,208,183,208,180,208,181,209,129,209,140,208,178,208,184,208,180,208,181, 208,190,209,129,208,178,209,143,208,183,208,184,208,189,209,131,208,182,208,189, 208,190,209,129,208,178,208,190,208,181,208,185,208,187,209,142,208,180,208,181, 208,185,208,191,208,190,209,128,208,189,208,190,208,188,208,189,208,190,208,179, 208,190,208,180,208,181,209,130,208,181,208,185,209,129,208,178,208,190,208,184, 209,133,208,191,209,128,208,176,208,178,208,176,209,130,208,176,208,186,208,190, 208,185,208,188,208,181,209,129,209,130,208,190,208,184,208,188,208,181,208,181, 209,130,208,182,208,184,208,183,208,189,209,140,208,190,208,180,208,189,208,190, 208,185,208,187,209,131,209,135,209,136,208,181,208,191,208,181,209,128,208,181, 208,180,209,135,208,176,209,129,209,130,208,184,209,135,208,176,209,129,209,130, 209,140,209,128,208,176,208,177,208,190,209,130,208,189,208,190,208,178,209,139, 209,133,208,191,209,128,208,176,208,178,208,190,209,129,208,190,208,177,208,190, 208,185,208,191,208,190,209,130,208,190,208,188,208,188,208,181,208,189,208,181, 208,181,209,135,208,184,209,129,208,187,208,181,208,189,208,190,208,178,209,139, 208,181,209,131,209,129,208,187,209,131,208,179,208,190,208,186,208,190,208,187, 208,190,208,189,208,176,208,183,208,176,208,180,209,130,208,176,208,186,208,190, 208,181,209,130,208,190,208,179,208,180,208,176,208,191,208,190,209,135,209,130, 208,184,208,159,208,190,209,129,208,187,208,181,209,130,208,176,208,186,208,184, 208,181,208,189,208,190,208,178,209,139,208,185,209,129,209,130,208,190,208,184, 209,130,209,130,208,176,208,186,208,184,209,133,209,129,209,128,208,176,208,183, 209,131,208,161,208,176,208,189,208,186,209,130,209,132,208,190,209,128,209,131, 208,188,208,154,208,190,208,179,208,180,208,176,208,186,208,189,208,184,208,179, 208,184,209,129,208,187,208,190,208,178,208,176,208,189,208,176,209,136,208,181, 208,185,208,189,208,176,208,185,209,130,208,184,209,129,208,178,208,190,208,184, 208,188,209,129,208,178,209,143,208,183,209,140,208,187,209,142,208,177,208,190, 208,185,209,135,208,176,209,129,209,130,208,190,209,129,209,128,208,181,208,180, 208,184,208,154,209,128,208,190,208,188,208,181,208,164,208,190,209,128,209,131, 208,188,209,128,209,139,208,189,208,186,208,181,209,129,209,130,208,176,208,187, 208,184,208,191,208,190,208,184,209,129,208,186,209,130,209,139,209,129,209,143, 209,135,208,188,208,181,209,129,209,143,209,134,209,134,208,181,208,189,209,130, 209,128,209,130,209,128,209,131,208,180,208,176,209,129,208,176,208,188,209,139, 209,133,209,128,209,139,208,189,208,186,208,176,208,157,208,190,208,178,209,139, 208,185,209,135,208,176,209,129,208,190,208,178,208,188,208,181,209,129,209,130, 208,176,209,132,208,184,208,187,209,140,208,188,208,188,208,176,209,128,209,130, 208,176,209,129,209,130,209,128,208,176,208,189,208,188,208,181,209,129,209,130, 208,181,209,130,208,181,208,186,209,129,209,130,208,189,208,176,209,136,208,184, 209,133,208,188,208,184,208,189,209,131,209,130,208,184,208,188,208,181,208,189, 208,184,208,184,208,188,208,181,209,142,209,130,208,189,208,190,208,188,208,181, 209,128,208,179,208,190,209,128,208,190,208,180,209,129,208,176,208,188,208,190, 208,188,209,141,209,130,208,190,208,188,209,131,208,186,208,190,208,189,209,134, 208,181,209,129,208,178,208,190,208,181,208,188,208,186,208,176,208,186,208,190, 208,185,208,144,209,128,209,133,208,184,208,178,217,133,217,134,216,170,216,175, 217,137,216,165,216,177,216,179,216,167,217,132,216,177,216,179,216,167,217,132, 216,169,216,167,217,132,216,185,216,167,217,133,217,131,216,170,216,168,217,135, 216,167,216,168,216,177,216,167,217,133,216,172,216,167,217,132,217,138,217,136, 217,133,216,167,217,132,216,181,217,136,216,177,216,172,216,175,217,138,216,175, 216,169,216,167,217,132,216,185,216,182,217,136,216,165,216,182,216,167,217,129, 216,169,216,167,217,132,217,130,216,179,217,133,216,167,217,132,216,185,216,167, 216,168,216,170,216,173,217,133,217,138,217,132,217,133,217,132,217,129,216,167, 216,170,217,133,217,132,216,170,217,130,217,137,216,170,216,185,216,175,217,138, 217,132,216,167,217,132,216,180,216,185,216,177,216,163,216,174,216,168,216,167, 216,177,216,170,216,183,217,136,217,138,216,177,216,185,217,132,217,138,217,131, 217,133,216,165,216,177,217,129,216,167,217,130,216,183,217,132,216,168,216,167, 216,170,216,167,217,132,217,132,216,186,216,169,216,170,216,177,216,170,217,138, 216,168,216,167,217,132,217,134,216,167,216,179,216,167,217,132,216,180,217,138, 216,174,217,133,217,134,216,170,216,175,217,138,216,167,217,132,216,185,216,177, 216,168,216,167,217,132,217,130,216,181,216,181,216,167,217,129,217,132,216,167, 217,133,216,185,217,132,217,138,217,135,216,167,216,170,216,173,216,175,217,138, 216,171,216,167,217,132,217,132,217,135,217,133,216,167,217,132,216,185,217,133, 217,132,217,133,217,131,216,170,216,168,216,169,217,138,217,133,217,131,217,134, 217,131,216,167,217,132,216,183,217,129,217,132,217,129,217,138,216,175,217,138, 217,136,216,165,216,175,216,167,216,177,216,169,216,170,216,167,216,177,217,138, 216,174,216,167,217,132,216,181,216,173,216,169,216,170,216,179,216,172,217,138, 217,132,216,167,217,132,217,136,217,130,216,170,216,185,217,134,216,175,217,133, 216,167,217,133,216,175,217,138,217,134,216,169,216,170,216,181,217,133,217,138, 217,133,216,163,216,177,216,180,217,138,217,129,216,167,217,132,216,176,217,138, 217,134,216,185,216,177,216,168,217,138,216,169,216,168,217,136,216,167,216,168, 216,169,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,179,217,129, 216,177,217,133,216,180,216,167,217,131,217,132,216,170,216,185,216,167,217,132, 217,137,216,167,217,132,216,163,217,136,217,132,216,167,217,132,216,179,217,134, 216,169,216,172,216,167,217,133,216,185,216,169,216,167,217,132,216,181,216,173, 217,129,216,167,217,132,216,175,217,138,217,134,217,131,217,132,217,133,216,167, 216,170,216,167,217,132,216,174,216,167,216,181,216,167,217,132,217,133,217,132, 217,129,216,163,216,185,216,182,216,167,216,161,217,131,216,170,216,167,216,168, 216,169,216,167,217,132,216,174,217,138,216,177,216,177,216,179,216,167,216,166, 217,132,216,167,217,132,217,130,217,132,216,168,216,167,217,132,216,163,216,175, 216,168,217,133,217,130,216,167,216,183,216,185,217,133,216,177,216,167,216,179, 217,132,217,133,217,134,216,183,217,130,216,169,216,167,217,132,217,131,216,170, 216,168,216,167,217,132,216,177,216,172,217,132,216,167,216,180,216,170,216,177, 217,131,216,167,217,132,217,130,216,175,217,133,217,138,216,185,216,183,217,138, 217,131,115,66,121,84,97,103,78,97,109,101,40,46,106,112,103,34,32,97,108,116,61 ,34,49,112,120,32,115,111,108,105,100,32,35,46,103,105,102,34,32,97,108,116,61, 34,116,114,97,110,115,112,97,114,101,110,116,105,110,102,111,114,109,97,116,105, 111,110,97,112,112,108,105,99,97,116,105,111,110,34,32,111,110,99,108,105,99,107 ,61,34,101,115,116,97,98,108,105,115,104,101,100,97,100,118,101,114,116,105,115, 105,110,103,46,112,110,103,34,32,97,108,116,61,34,101,110,118,105,114,111,110, 109,101,110,116,112,101,114,102,111,114,109,97,110,99,101,97,112,112,114,111,112 ,114,105,97,116,101,38,97,109,112,59,109,100,97,115,104,59,105,109,109,101,100, 105,97,116,101,108,121,60,47,115,116,114,111,110,103,62,60,47,114,97,116,104,101 ,114,32,116,104,97,110,116,101,109,112,101,114,97,116,117,114,101,100,101,118, 101,108,111,112,109,101,110,116,99,111,109,112,101,116,105,116,105,111,110,112, 108,97,99,101,104,111,108,100,101,114,118,105,115,105,98,105,108,105,116,121,58, 99,111,112,121,114,105,103,104,116,34,62,48,34,32,104,101,105,103,104,116,61,34, 101,118,101,110,32,116,104,111,117,103,104,114,101,112,108,97,99,101,109,101,110 ,116,100,101,115,116,105,110,97,116,105,111,110,67,111,114,112,111,114,97,116, 105,111,110,60,117,108,32,99,108,97,115,115,61,34,65,115,115,111,99,105,97,116, 105,111,110,105,110,100,105,118,105,100,117,97,108,115,112,101,114,115,112,101, 99,116,105,118,101,115,101,116,84,105,109,101,111,117,116,40,117,114,108,40,104, 116,116,112,58,47,47,109,97,116,104,101,109,97,116,105,99,115,109,97,114,103,105 ,110,45,116,111,112,58,101,118,101,110,116,117,97,108,108,121,32,100,101,115,99, 114,105,112,116,105,111,110,41,32,110,111,45,114,101,112,101,97,116,99,111,108, 108,101,99,116,105,111,110,115,46,74,80,71,124,116,104,117,109,98,124,112,97,114 ,116,105,99,105,112,97,116,101,47,104,101,97,100,62,60,98,111,100,121,102,108, 111,97,116,58,108,101,102,116,59,60,108,105,32,99,108,97,115,115,61,34,104,117, 110,100,114,101,100,115,32,111,102,10,10,72,111,119,101,118,101,114,44,32,99,111 ,109,112,111,115,105,116,105,111,110,99,108,101,97,114,58,98,111,116,104,59,99, 111,111,112,101,114,97,116,105,111,110,119,105,116,104,105,110,32,116,104,101,32 ,108,97,98,101,108,32,102,111,114,61,34,98,111,114,100,101,114,45,116,111,112,58 ,78,101,119,32,90,101,97,108,97,110,100,114,101,99,111,109,109,101,110,100,101, 100,112,104,111,116,111,103,114,97,112,104,121,105,110,116,101,114,101,115,116, 105,110,103,38,108,116,59,115,117,112,38,103,116,59,99,111,110,116,114,111,118, 101,114,115,121,78,101,116,104,101,114,108,97,110,100,115,97,108,116,101,114,110 ,97,116,105,118,101,109,97,120,108,101,110,103,116,104,61,34,115,119,105,116,122 ,101,114,108,97,110,100,68,101,118,101,108,111,112,109,101,110,116,101,115,115, 101,110,116,105,97,108,108,121,10,10,65,108,116,104,111,117,103,104,32,60,47,116 ,101,120,116,97,114,101,97,62,116,104,117,110,100,101,114,98,105,114,100,114,101 ,112,114,101,115,101,110,116,101,100,38,97,109,112,59,110,100,97,115,104,59,115, 112,101,99,117,108,97,116,105,111,110,99,111,109,109,117,110,105,116,105,101,115 ,108,101,103,105,115,108,97,116,105,111,110,101,108,101,99,116,114,111,110,105, 99,115,10,9,60,100,105,118,32,105,100,61,34,105,108,108,117,115,116,114,97,116, 101,100,101,110,103,105,110,101,101,114,105,110,103,116,101,114,114,105,116,111, 114,105,101,115,97,117,116,104,111,114,105,116,105,101,115,100,105,115,116,114, 105,98,117,116,101,100,54,34,32,104,101,105,103,104,116,61,34,115,97,110,115,45, 115,101,114,105,102,59,99,97,112,97,98,108,101,32,111,102,32,100,105,115,97,112, 112,101,97,114,101,100,105,110,116,101,114,97,99,116,105,118,101,108,111,111,107 ,105,110,103,32,102,111,114,105,116,32,119,111,117,108,100,32,98,101,65,102,103, 104,97,110,105,115,116,97,110,119,97,115,32,99,114,101,97,116,101,100,77,97,116, 104,46,102,108,111,111,114,40,115,117,114,114,111,117,110,100,105,110,103,99,97, 110,32,97,108,115,111,32,98,101,111,98,115,101,114,118,97,116,105,111,110,109,97 ,105,110,116,101,110,97,110,99,101,101,110,99,111,117,110,116,101,114,101,100,60 ,104,50,32,99,108,97,115,115,61,34,109,111,114,101,32,114,101,99,101,110,116,105 ,116,32,104,97,115,32,98,101,101,110,105,110,118,97,115,105,111,110,32,111,102, 41,46,103,101,116,84,105,109,101,40,41,102,117,110,100,97,109,101,110,116,97,108 ,68,101,115,112,105,116,101,32,116,104,101,34,62,60,100,105,118,32,105,100,61,34 ,105,110,115,112,105,114,97,116,105,111,110,101,120,97,109,105,110,97,116,105, 111,110,112,114,101,112,97,114,97,116,105,111,110,101,120,112,108,97,110,97,116, 105,111,110,60,105,110,112,117,116,32,105,100,61,34,60,47,97,62,60,47,115,112,97 ,110,62,118,101,114,115,105,111,110,115,32,111,102,105,110,115,116,114,117,109, 101,110,116,115,98,101,102,111,114,101,32,116,104,101,32,32,61,32,39,104,116,116 ,112,58,47,47,68,101,115,99,114,105,112,116,105,111,110,114,101,108,97,116,105, 118,101,108,121,32,46,115,117,98,115,116,114,105,110,103,40,101,97,99,104,32,111 ,102,32,116,104,101,101,120,112,101,114,105,109,101,110,116,115,105,110,102,108, 117,101,110,116,105,97,108,105,110,116,101,103,114,97,116,105,111,110,109,97,110 ,121,32,112,101,111,112,108,101,100,117,101,32,116,111,32,116,104,101,32,99,111, 109,98,105,110,97,116,105,111,110,100,111,32,110,111,116,32,104,97,118,101,77, 105,100,100,108,101,32,69,97,115,116,60,110,111,115,99,114,105,112,116,62,60,99, 111,112,121,114,105,103,104,116,34,32,112,101,114,104,97,112,115,32,116,104,101, 105,110,115,116,105,116,117,116,105,111,110,105,110,32,68,101,99,101,109,98,101, 114,97,114,114,97,110,103,101,109,101,110,116,109,111,115,116,32,102,97,109,111, 117,115,112,101,114,115,111,110,97,108,105,116,121,99,114,101,97,116,105,111,110 ,32,111,102,108,105,109,105,116,97,116,105,111,110,115,101,120,99,108,117,115, 105,118,101,108,121,115,111,118,101,114,101,105,103,110,116,121,45,99,111,110, 116,101,110,116,34,62,10,60,116,100,32,99,108,97,115,115,61,34,117,110,100,101, 114,103,114,111,117,110,100,112,97,114,97,108,108,101,108,32,116,111,100,111,99, 116,114,105,110,101,32,111,102,111,99,99,117,112,105,101,100,32,98,121,116,101, 114,109,105,110,111,108,111,103,121,82,101,110,97,105,115,115,97,110,99,101,97, 32,110,117,109,98,101,114,32,111,102,115,117,112,112,111,114,116,32,102,111,114, 101,120,112,108,111,114,97,116,105,111,110,114,101,99,111,103,110,105,116,105, 111,110,112,114,101,100,101,99,101,115,115,111,114,60,105,109,103,32,115,114,99, 61,34,47,60,104,49,32,99,108,97,115,115,61,34,112,117,98,108,105,99,97,116,105, 111,110,109,97,121,32,97,108,115,111,32,98,101,115,112,101,99,105,97,108,105,122 ,101,100,60,47,102,105,101,108,100,115,101,116,62,112,114,111,103,114,101,115, 115,105,118,101,109,105,108,108,105,111,110,115,32,111,102,115,116,97,116,101, 115,32,116,104,97,116,101,110,102,111,114,99,101,109,101,110,116,97,114,111,117, 110,100,32,116,104,101,32,111,110,101,32,97,110,111,116,104,101,114,46,112,97, 114,101,110,116,78,111,100,101,97,103,114,105,99,117,108,116,117,114,101,65,108, 116,101,114,110,97,116,105,118,101,114,101,115,101,97,114,99,104,101,114,115,116 ,111,119,97,114,100,115,32,116,104,101,77,111,115,116,32,111,102,32,116,104,101, 109,97,110,121,32,111,116,104,101,114,32,40,101,115,112,101,99,105,97,108,108, 121,60,116,100,32,119,105,100,116,104,61,34,59,119,105,100,116,104,58,49,48,48, 37,105,110,100,101,112,101,110,100,101,110,116,60,104,51,32,99,108,97,115,115,61 ,34,32,111,110,99,104,97,110,103,101,61,34,41,46,97,100,100,67,108,97,115,115,40 ,105,110,116,101,114,97,99,116,105,111,110,79,110,101,32,111,102,32,116,104,101, 32,100,97,117,103,104,116,101,114,32,111,102,97,99,99,101,115,115,111,114,105, 101,115,98,114,97,110,99,104,101,115,32,111,102,13,10,60,100,105,118,32,105,100, 61,34,116,104,101,32,108,97,114,103,101,115,116,100,101,99,108,97,114,97,116,105 ,111,110,114,101,103,117,108,97,116,105,111,110,115,73,110,102,111,114,109,97, 116,105,111,110,116,114,97,110,115,108,97,116,105,111,110,100,111,99,117,109,101 ,110,116,97,114,121,105,110,32,111,114,100,101,114,32,116,111,34,62,10,60,104, 101,97,100,62,10,60,34,32,104,101,105,103,104,116,61,34,49,97,99,114,111,115,115 ,32,116,104,101,32,111,114,105,101,110,116,97,116,105,111,110,41,59,60,47,115,99 ,114,105,112,116,62,105,109,112,108,101,109,101,110,116,101,100,99,97,110,32,98, 101,32,115,101,101,110,116,104,101,114,101,32,119,97,115,32,97,100,101,109,111, 110,115,116,114,97,116,101,99,111,110,116,97,105,110,101,114,34,62,99,111,110, 110,101,99,116,105,111,110,115,116,104,101,32,66,114,105,116,105,115,104,119,97, 115,32,119,114,105,116,116,101,110,33,105,109,112,111,114,116,97,110,116,59,112, 120,59,32,109,97,114,103,105,110,45,102,111,108,108,111,119,101,100,32,98,121,97 ,98,105,108,105,116,121,32,116,111,32,99,111,109,112,108,105,99,97,116,101,100, 100,117,114,105,110,103,32,116,104,101,32,105,109,109,105,103,114,97,116,105,111 ,110,97,108,115,111,32,99,97,108,108,101,100,60,104,52,32,99,108,97,115,115,61, 34,100,105,115,116,105,110,99,116,105,111,110,114,101,112,108,97,99,101,100,32, 98,121,103,111,118,101,114,110,109,101,110,116,115,108,111,99,97,116,105,111,110 ,32,111,102,105,110,32,78,111,118,101,109,98,101,114,119,104,101,116,104,101,114 ,32,116,104,101,60,47,112,62,10,60,47,100,105,118,62,97,99,113,117,105,115,105, 116,105,111,110,99,97,108,108,101,100,32,116,104,101,32,112,101,114,115,101,99, 117,116,105,111,110,100,101,115,105,103,110,97,116,105,111,110,123,102,111,110, 116,45,115,105,122,101,58,97,112,112,101,97,114,101,100,32,105,110,105,110,118, 101,115,116,105,103,97,116,101,101,120,112,101,114,105,101,110,99,101,100,109, 111,115,116,32,108,105,107,101,108,121,119,105,100,101,108,121,32,117,115,101, 100,100,105,115,99,117,115,115,105,111,110,115,112,114,101,115,101,110,99,101,32 ,111,102,32,40,100,111,99,117,109,101,110,116,46,101,120,116,101,110,115,105,118 ,101,108,121,73,116,32,104,97,115,32,98,101,101,110,105,116,32,100,111,101,115, 32,110,111,116,99,111,110,116,114,97,114,121,32,116,111,105,110,104,97,98,105, 116,97,110,116,115,105,109,112,114,111,118,101,109,101,110,116,115,99,104,111, 108,97,114,115,104,105,112,99,111,110,115,117,109,112,116,105,111,110,105,110, 115,116,114,117,99,116,105,111,110,102,111,114,32,101,120,97,109,112,108,101,111 ,110,101,32,111,114,32,109,111,114,101,112,120,59,32,112,97,100,100,105,110,103, 116,104,101,32,99,117,114,114,101,110,116,97,32,115,101,114,105,101,115,32,111, 102,97,114,101,32,117,115,117,97,108,108,121,114,111,108,101,32,105,110,32,116, 104,101,112,114,101,118,105,111,117,115,108,121,32,100,101,114,105,118,97,116, 105,118,101,115,101,118,105,100,101,110,99,101,32,111,102,101,120,112,101,114, 105,101,110,99,101,115,99,111,108,111,114,115,99,104,101,109,101,115,116,97,116, 101,100,32,116,104,97,116,99,101,114,116,105,102,105,99,97,116,101,60,47,97,62, 60,47,100,105,118,62,10,32,115,101,108,101,99,116,101,100,61,34,104,105,103,104, 32,115,99,104,111,111,108,114,101,115,112,111,110,115,101,32,116,111,99,111,109, 102,111,114,116,97,98,108,101,97,100,111,112,116,105,111,110,32,111,102,116,104, 114,101,101,32,121,101,97,114,115,116,104,101,32,99,111,117,110,116,114,121,105, 110,32,70,101,98,114,117,97,114,121,115,111,32,116,104,97,116,32,116,104,101,112 ,101,111,112,108,101,32,119,104,111,32,112,114,111,118,105,100,101,100,32,98,121 ,60,112,97,114,97,109,32,110,97,109,101,97,102,102,101,99,116,101,100,32,98,121, 105,110,32,116,101,114,109,115,32,111,102,97,112,112,111,105,110,116,109,101,110 ,116,73,83,79,45,56,56,53,57,45,49,34,119,97,115,32,98,111,114,110,32,105,110, 104,105,115,116,111,114,105,99,97,108,32,114,101,103,97,114,100,101,100,32,97, 115,109,101,97,115,117,114,101,109,101,110,116,105,115,32,98,97,115,101,100,32, 111,110,32,97,110,100,32,111,116,104,101,114,32,58,32,102,117,110,99,116,105,111 ,110,40,115,105,103,110,105,102,105,99,97,110,116,99,101,108,101,98,114,97,116, 105,111,110,116,114,97,110,115,109,105,116,116,101,100,47,106,115,47,106,113,117 ,101,114,121,46,105,115,32,107,110,111,119,110,32,97,115,116,104,101,111,114,101 ,116,105,99,97,108,32,116,97,98,105,110,100,101,120,61,34,105,116,32,99,111,117, 108,100,32,98,101,60,110,111,115,99,114,105,112,116,62,10,104,97,118,105,110,103 ,32,98,101,101,110,13,10,60,104,101,97,100,62,13,10,60,32,38,113,117,111,116,59, 84,104,101,32,99,111,109,112,105,108,97,116,105,111,110,104,101,32,104,97,100,32 ,98,101,101,110,112,114,111,100,117,99,101,100,32,98,121,112,104,105,108,111,115 ,111,112,104,101,114,99,111,110,115,116,114,117,99,116,101,100,105,110,116,101, 110,100,101,100,32,116,111,97,109,111,110,103,32,111,116,104,101,114,99,111,109, 112,97,114,101,100,32,116,111,116,111,32,115,97,121,32,116,104,97,116,69,110,103 ,105,110,101,101,114,105,110,103,97,32,100,105,102,102,101,114,101,110,116,114, 101,102,101,114,114,101,100,32,116,111,100,105,102,102,101,114,101,110,99,101, 115,98,101,108,105,101,102,32,116,104,97,116,112,104,111,116,111,103,114,97,112, 104,115,105,100,101,110,116,105,102,121,105,110,103,72,105,115,116,111,114,121, 32,111,102,32,82,101,112,117,98,108,105,99,32,111,102,110,101,99,101,115,115,97, 114,105,108,121,112,114,111,98,97,98,105,108,105,116,121,116,101,99,104,110,105, 99,97,108,108,121,108,101,97,118,105,110,103,32,116,104,101,115,112,101,99,116, 97,99,117,108,97,114,102,114,97,99,116,105,111,110,32,111,102,101,108,101,99,116 ,114,105,99,105,116,121,104,101,97,100,32,111,102,32,116,104,101,114,101,115,116 ,97,117,114,97,110,116,115,112,97,114,116,110,101,114,115,104,105,112,101,109, 112,104,97,115,105,115,32,111,110,109,111,115,116,32,114,101,99,101,110,116,115, 104,97,114,101,32,119,105,116,104,32,115,97,121,105,110,103,32,116,104,97,116, 102,105,108,108,101,100,32,119,105,116,104,100,101,115,105,103,110,101,100,32, 116,111,105,116,32,105,115,32,111,102,116,101,110,34,62,60,47,105,102,114,97,109 ,101,62,97,115,32,102,111,108,108,111,119,115,58,109,101,114,103,101,100,32,119, 105,116,104,116,104,114,111,117,103,104,32,116,104,101,99,111,109,109,101,114,99 ,105,97,108,32,112,111,105,110,116,101,100,32,111,117,116,111,112,112,111,114, 116,117,110,105,116,121,118,105,101,119,32,111,102,32,116,104,101,114,101,113, 117,105,114,101,109,101,110,116,100,105,118,105,115,105,111,110,32,111,102,112, 114,111,103,114,97,109,109,105,110,103,104,101,32,114,101,99,101,105,118,101,100 ,115,101,116,73,110,116,101,114,118,97,108,34,62,60,47,115,112,97,110,62,60,47, 105,110,32,78,101,119,32,89,111,114,107,97,100,100,105,116,105,111,110,97,108,32 ,99,111,109,112,114,101,115,115,105,111,110,10,10,60,100,105,118,32,105,100,61, 34,105,110,99,111,114,112,111,114,97,116,101,59,60,47,115,99,114,105,112,116,62, 60,97,116,116,97,99,104,69,118,101,110,116,98,101,99,97,109,101,32,116,104,101, 32,34,32,116,97,114,103,101,116,61,34,95,99,97,114,114,105,101,100,32,111,117, 116,83,111,109,101,32,111,102,32,116,104,101,115,99,105,101,110,99,101,32,97,110 ,100,116,104,101,32,116,105,109,101,32,111,102,67,111,110,116,97,105,110,101,114 ,34,62,109,97,105,110,116,97,105,110,105,110,103,67,104,114,105,115,116,111,112, 104,101,114,77,117,99,104,32,111,102,32,116,104,101,119,114,105,116,105,110,103, 115,32,111,102,34,32,104,101,105,103,104,116,61,34,50,115,105,122,101,32,111,102 ,32,116,104,101,118,101,114,115,105,111,110,32,111,102,32,109,105,120,116,117, 114,101,32,111,102,32,98,101,116,119,101,101,110,32,116,104,101,69,120,97,109, 112,108,101,115,32,111,102,101,100,117,99,97,116,105,111,110,97,108,99,111,109, 112,101,116,105,116,105,118,101,32,111,110,115,117,98,109,105,116,61,34,100,105, 114,101,99,116,111,114,32,111,102,100,105,115,116,105,110,99,116,105,118,101,47, 68,84,68,32,88,72,84,77,76,32,114,101,108,97,116,105,110,103,32,116,111,116,101, 110,100,101,110,99,121,32,116,111,112,114,111,118,105,110,99,101,32,111,102,119, 104,105,99,104,32,119,111,117,108,100,100,101,115,112,105,116,101,32,116,104,101 ,115,99,105,101,110,116,105,102,105,99,32,108,101,103,105,115,108,97,116,117,114 ,101,46,105,110,110,101,114,72,84,77,76,32,97,108,108,101,103,97,116,105,111,110 ,115,65,103,114,105,99,117,108,116,117,114,101,119,97,115,32,117,115,101,100,32, 105,110,97,112,112,114,111,97,99,104,32,116,111,105,110,116,101,108,108,105,103, 101,110,116,121,101,97,114,115,32,108,97,116,101,114,44,115,97,110,115,45,115, 101,114,105,102,100,101,116,101,114,109,105,110,105,110,103,80,101,114,102,111, 114,109,97,110,99,101,97,112,112,101,97,114,97,110,99,101,115,44,32,119,104,105, 99,104,32,105,115,32,102,111,117,110,100,97,116,105,111,110,115,97,98,98,114,101 ,118,105,97,116,101,100,104,105,103,104,101,114,32,116,104,97,110,115,32,102,114 ,111,109,32,116,104,101,32,105,110,100,105,118,105,100,117,97,108,32,99,111,109, 112,111,115,101,100,32,111,102,115,117,112,112,111,115,101,100,32,116,111,99,108 ,97,105,109,115,32,116,104,97,116,97,116,116,114,105,98,117,116,105,111,110,102, 111,110,116,45,115,105,122,101,58,49,101,108,101,109,101,110,116,115,32,111,102, 72,105,115,116,111,114,105,99,97,108,32,104,105,115,32,98,114,111,116,104,101, 114,97,116,32,116,104,101,32,116,105,109,101,97,110,110,105,118,101,114,115,97, 114,121,103,111,118,101,114,110,101,100,32,98,121,114,101,108,97,116,101,100,32, 116,111,32,117,108,116,105,109,97,116,101,108,121,32,105,110,110,111,118,97,116, 105,111,110,115,105,116,32,105,115,32,115,116,105,108,108,99,97,110,32,111,110, 108,121,32,98,101,100,101,102,105,110,105,116,105,111,110,115,116,111,71,77,84, 83,116,114,105,110,103,65,32,110,117,109,98,101,114,32,111,102,105,109,103,32,99 ,108,97,115,115,61,34,69,118,101,110,116,117,97,108,108,121,44,119,97,115,32,99, 104,97,110,103,101,100,111,99,99,117,114,114,101,100,32,105,110,110,101,105,103, 104,98,111,114,105,110,103,100,105,115,116,105,110,103,117,105,115,104,119,104, 101,110,32,104,101,32,119,97,115,105,110,116,114,111,100,117,99,105,110,103,116, 101,114,114,101,115,116,114,105,97,108,77,97,110,121,32,111,102,32,116,104,101, 97,114,103,117,101,115,32,116,104,97,116,97,110,32,65,109,101,114,105,99,97,110, 99,111,110,113,117,101,115,116,32,111,102,119,105,100,101,115,112,114,101,97,100 ,32,119,101,114,101,32,107,105,108,108,101,100,115,99,114,101,101,110,32,97,110, 100,32,73,110,32,111,114,100,101,114,32,116,111,101,120,112,101,99,116,101,100, 32,116,111,100,101,115,99,101,110,100,97,110,116,115,97,114,101,32,108,111,99,97 ,116,101,100,108,101,103,105,115,108,97,116,105,118,101,103,101,110,101,114,97, 116,105,111,110,115,32,98,97,99,107,103,114,111,117,110,100,109,111,115,116,32, 112,101,111,112,108,101,121,101,97,114,115,32,97,102,116,101,114,116,104,101,114 ,101,32,105,115,32,110,111,116,104,101,32,104,105,103,104,101,115,116,102,114, 101,113,117,101,110,116,108,121,32,116,104,101,121,32,100,111,32,110,111,116,97, 114,103,117,101,100,32,116,104,97,116,115,104,111,119,101,100,32,116,104,97,116, 112,114,101,100,111,109,105,110,97,110,116,116,104,101,111,108,111,103,105,99,97 ,108,98,121,32,116,104,101,32,116,105,109,101,99,111,110,115,105,100,101,114,105 ,110,103,115,104,111,114,116,45,108,105,118,101,100,60,47,115,112,97,110,62,60, 47,97,62,99,97,110,32,98,101,32,117,115,101,100,118,101,114,121,32,108,105,116, 116,108,101,111,110,101,32,111,102,32,116,104,101,32,104,97,100,32,97,108,114, 101,97,100,121,105,110,116,101,114,112,114,101,116,101,100,99,111,109,109,117, 110,105,99,97,116,101,102,101,97,116,117,114,101,115,32,111,102,103,111,118,101, 114,110,109,101,110,116,44,60,47,110,111,115,99,114,105,112,116,62,101,110,116, 101,114,101,100,32,116,104,101,34,32,104,101,105,103,104,116,61,34,51,73,110,100 ,101,112,101,110,100,101,110,116,112,111,112,117,108,97,116,105,111,110,115,108, 97,114,103,101,45,115,99,97,108,101,46,32,65,108,116,104,111,117,103,104,32,117, 115,101,100,32,105,110,32,116,104,101,100,101,115,116,114,117,99,116,105,111,110 ,112,111,115,115,105,98,105,108,105,116,121,115,116,97,114,116,105,110,103,32, 105,110,116,119,111,32,111,114,32,109,111,114,101,101,120,112,114,101,115,115, 105,111,110,115,115,117,98,111,114,100,105,110,97,116,101,108,97,114,103,101,114 ,32,116,104,97,110,104,105,115,116,111,114,121,32,97,110,100,60,47,111,112,116, 105,111,110,62,13,10,67,111,110,116,105,110,101,110,116,97,108,101,108,105,109, 105,110,97,116,105,110,103,119,105,108,108,32,110,111,116,32,98,101,112,114,97, 99,116,105,99,101,32,111,102,105,110,32,102,114,111,110,116,32,111,102,115,105, 116,101,32,111,102,32,116,104,101,101,110,115,117,114,101,32,116,104,97,116,116, 111,32,99,114,101,97,116,101,32,97,109,105,115,115,105,115,115,105,112,112,105, 112,111,116,101,110,116,105,97,108,108,121,111,117,116,115,116,97,110,100,105, 110,103,98,101,116,116,101,114,32,116,104,97,110,119,104,97,116,32,105,115,32, 110,111,119,115,105,116,117,97,116,101,100,32,105,110,109,101,116,97,32,110,97, 109,101,61,34,84,114,97,100,105,116,105,111,110,97,108,115,117,103,103,101,115, 116,105,111,110,115,84,114,97,110,115,108,97,116,105,111,110,116,104,101,32,102, 111,114,109,32,111,102,97,116,109,111,115,112,104,101,114,105,99,105,100,101,111 ,108,111,103,105,99,97,108,101,110,116,101,114,112,114,105,115,101,115,99,97,108 ,99,117,108,97,116,105,110,103,101,97,115,116,32,111,102,32,116,104,101,114,101, 109,110,97,110,116,115,32,111,102,112,108,117,103,105,110,115,112,97,103,101,47, 105,110,100,101,120,46,112,104,112,63,114,101,109,97,105,110,101,100,32,105,110, 116,114,97,110,115,102,111,114,109,101,100,72,101,32,119,97,115,32,97,108,115, 111,119,97,115,32,97,108,114,101,97,100,121,115,116,97,116,105,115,116,105,99,97 ,108,105,110,32,102,97,118,111,114,32,111,102,77,105,110,105,115,116,114,121,32, 111,102,109,111,118,101,109,101,110,116,32,111,102,102,111,114,109,117,108,97, 116,105,111,110,105,115,32,114,101,113,117,105,114,101,100,60,108,105,110,107,32 ,114,101,108,61,34,84,104,105,115,32,105,115,32,116,104,101,32,60,97,32,104,114, 101,102,61,34,47,112,111,112,117,108,97,114,105,122,101,100,105,110,118,111,108, 118,101,100,32,105,110,97,114,101,32,117,115,101,100,32,116,111,97,110,100,32, 115,101,118,101,114,97,108,109,97,100,101,32,98,121,32,116,104,101,115,101,101, 109,115,32,116,111,32,98,101,108,105,107,101,108,121,32,116,104,97,116,80,97,108 ,101,115,116,105,110,105,97,110,110,97,109,101,100,32,97,102,116,101,114,105,116 ,32,104,97,100,32,98,101,101,110,109,111,115,116,32,99,111,109,109,111,110,116, 111,32,114,101,102,101,114,32,116,111,98,117,116,32,116,104,105,115,32,105,115, 99,111,110,115,101,99,117,116,105,118,101,116,101,109,112,111,114,97,114,105,108 ,121,73,110,32,103,101,110,101,114,97,108,44,99,111,110,118,101,110,116,105,111, 110,115,116,97,107,101,115,32,112,108,97,99,101,115,117,98,100,105,118,105,115, 105,111,110,116,101,114,114,105,116,111,114,105,97,108,111,112,101,114,97,116, 105,111,110,97,108,112,101,114,109,97,110,101,110,116,108,121,119,97,115,32,108, 97,114,103,101,108,121,111,117,116,98,114,101,97,107,32,111,102,105,110,32,116, 104,101,32,112,97,115,116,102,111,108,108,111,119,105,110,103,32,97,32,120,109, 108,110,115,58,111,103,61,34,62,60,97,32,99,108,97,115,115,61,34,99,108,97,115, 115,61,34,116,101,120,116,67,111,110,118,101,114,115,105,111,110,32,109,97,121, 32,98,101,32,117,115,101,100,109,97,110,117,102,97,99,116,117,114,101,97,102,116 ,101,114,32,98,101,105,110,103,99,108,101,97,114,102,105,120,34,62,10,113,117, 101,115,116,105,111,110,32,111,102,119,97,115,32,101,108,101,99,116,101,100,116, 111,32,98,101,99,111,109,101,32,97,98,101,99,97,117,115,101,32,111,102,32,115, 111,109,101,32,112,101,111,112,108,101,105,110,115,112,105,114,101,100,32,98,121 ,115,117,99,99,101,115,115,102,117,108,32,97,32,116,105,109,101,32,119,104,101, 110,109,111,114,101,32,99,111,109,109,111,110,97,109,111,110,103,115,116,32,116, 104,101,97,110,32,111,102,102,105,99,105,97,108,119,105,100,116,104,58,49,48,48, 37,59,116,101,99,104,110,111,108,111,103,121,44,119,97,115,32,97,100,111,112,116 ,101,100,116,111,32,107,101,101,112,32,116,104,101,115,101,116,116,108,101,109, 101,110,116,115,108,105,118,101,32,98,105,114,116,104,115,105,110,100,101,120,46 ,104,116,109,108,34,67,111,110,110,101,99,116,105,99,117,116,97,115,115,105,103, 110,101,100,32,116,111,38,97,109,112,59,116,105,109,101,115,59,97,99,99,111,117, 110,116,32,102,111,114,97,108,105,103,110,61,114,105,103,104,116,116,104,101,32, 99,111,109,112,97,110,121,97,108,119,97,121,115,32,98,101,101,110,114,101,116, 117,114,110,101,100,32,116,111,105,110,118,111,108,118,101,109,101,110,116,66, 101,99,97,117,115,101,32,116,104,101,116,104,105,115,32,112,101,114,105,111,100, 34,32,110,97,109,101,61,34,113,34,32,99,111,110,102,105,110,101,100,32,116,111, 97,32,114,101,115,117,108,116,32,111,102,118,97,108,117,101,61,34,34,32,47,62, 105,115,32,97,99,116,117,97,108,108,121,69,110,118,105,114,111,110,109,101,110, 116,13,10,60,47,104,101,97,100,62,13,10,67,111,110,118,101,114,115,101,108,121, 44,62,10,60,100,105,118,32,105,100,61,34,48,34,32,119,105,100,116,104,61,34,49, 105,115,32,112,114,111,98,97,98,108,121,104,97,118,101,32,98,101,99,111,109,101, 99,111,110,116,114,111,108,108,105,110,103,116,104,101,32,112,114,111,98,108,101 ,109,99,105,116,105,122,101,110,115,32,111,102,112,111,108,105,116,105,99,105,97 ,110,115,114,101,97,99,104,101,100,32,116,104,101,97,115,32,101,97,114,108,121, 32,97,115,58,110,111,110,101,59,32,111,118,101,114,60,116,97,98,108,101,32,99, 101,108,108,118,97,108,105,100,105,116,121,32,111,102,100,105,114,101,99,116,108 ,121,32,116,111,111,110,109,111,117,115,101,100,111,119,110,119,104,101,114,101, 32,105,116,32,105,115,119,104,101,110,32,105,116,32,119,97,115,109,101,109,98, 101,114,115,32,111,102,32,114,101,108,97,116,105,111,110,32,116,111,97,99,99,111 ,109,109,111,100,97,116,101,97,108,111,110,103,32,119,105,116,104,32,73,110,32, 116,104,101,32,108,97,116,101,116,104,101,32,69,110,103,108,105,115,104,100,101, 108,105,99,105,111,117,115,34,62,116,104,105,115,32,105,115,32,110,111,116,116, 104,101,32,112,114,101,115,101,110,116,105,102,32,116,104,101,121,32,97,114,101, 97,110,100,32,102,105,110,97,108,108,121,97,32,109,97,116,116,101,114,32,111,102 ,13,10,9,60,47,100,105,118,62,13,10,13,10,60,47,115,99,114,105,112,116,62,102,97 ,115,116,101,114,32,116,104,97,110,109,97,106,111,114,105,116,121,32,111,102,97, 102,116,101,114,32,119,104,105,99,104,99,111,109,112,97,114,97,116,105,118,101, 116,111,32,109,97,105,110,116,97,105,110,105,109,112,114,111,118,101,32,116,104, 101,97,119,97,114,100,101,100,32,116,104,101,101,114,34,32,99,108,97,115,115,61, 34,102,114,97,109,101,98,111,114,100,101,114,114,101,115,116,111,114,97,116,105, 111,110,105,110,32,116,104,101,32,115,97,109,101,97,110,97,108,121,115,105,115, 32,111,102,116,104,101,105,114,32,102,105,114,115,116,68,117,114,105,110,103,32, 116,104,101,32,99,111,110,116,105,110,101,110,116,97,108,115,101,113,117,101,110 ,99,101,32,111,102,102,117,110,99,116,105,111,110,40,41,123,102,111,110,116,45, 115,105,122,101,58,32,119,111,114,107,32,111,110,32,116,104,101,60,47,115,99,114 ,105,112,116,62,10,60,98,101,103,105,110,115,32,119,105,116,104,106,97,118,97, 115,99,114,105,112,116,58,99,111,110,115,116,105,116,117,101,110,116,119,97,115, 32,102,111,117,110,100,101,100,101,113,117,105,108,105,98,114,105,117,109,97,115 ,115,117,109,101,32,116,104,97,116,105,115,32,103,105,118,101,110,32,98,121,110, 101,101,100,115,32,116,111,32,98,101,99,111,111,114,100,105,110,97,116,101,115, 116,104,101,32,118,97,114,105,111,117,115,97,114,101,32,112,97,114,116,32,111, 102,111,110,108,121,32,105,110,32,116,104,101,115,101,99,116,105,111,110,115,32, 111,102,105,115,32,97,32,99,111,109,109,111,110,116,104,101,111,114,105,101,115, 32,111,102,100,105,115,99,111,118,101,114,105,101,115,97,115,115,111,99,105,97, 116,105,111,110,101,100,103,101,32,111,102,32,116,104,101,115,116,114,101,110, 103,116,104,32,111,102,112,111,115,105,116,105,111,110,32,105,110,112,114,101, 115,101,110,116,45,100,97,121,117,110,105,118,101,114,115,97,108,108,121,116,111 ,32,102,111,114,109,32,116,104,101,98,117,116,32,105,110,115,116,101,97,100,99, 111,114,112,111,114,97,116,105,111,110,97,116,116,97,99,104,101,100,32,116,111, 105,115,32,99,111,109,109,111,110,108,121,114,101,97,115,111,110,115,32,102,111, 114,32,38,113,117,111,116,59,116,104,101,32,99,97,110,32,98,101,32,109,97,100, 101,119,97,115,32,97,98,108,101,32,116,111,119,104,105,99,104,32,109,101,97,110, 115,98,117,116,32,100,105,100,32,110,111,116,111,110,77,111,117,115,101,79,118, 101,114,97,115,32,112,111,115,115,105,98,108,101,111,112,101,114,97,116,101,100, 32,98,121,99,111,109,105,110,103,32,102,114,111,109,116,104,101,32,112,114,105, 109,97,114,121,97,100,100,105,116,105,111,110,32,111,102,102,111,114,32,115,101, 118,101,114,97,108,116,114,97,110,115,102,101,114,114,101,100,97,32,112,101,114, 105,111,100,32,111,102,97,114,101,32,97,98,108,101,32,116,111,104,111,119,101, 118,101,114,44,32,105,116,115,104,111,117,108,100,32,104,97,118,101,109,117,99, 104,32,108,97,114,103,101,114,10,9,60,47,115,99,114,105,112,116,62,97,100,111, 112,116,101,100,32,116,104,101,112,114,111,112,101,114,116,121,32,111,102,100, 105,114,101,99,116,101,100,32,98,121,101,102,102,101,99,116,105,118,101,108,121, 119,97,115,32,98,114,111,117,103,104,116,99,104,105,108,100,114,101,110,32,111, 102,80,114,111,103,114,97,109,109,105,110,103,108,111,110,103,101,114,32,116,104 ,97,110,109,97,110,117,115,99,114,105,112,116,115,119,97,114,32,97,103,97,105, 110,115,116,98,121,32,109,101,97,110,115,32,111,102,97,110,100,32,109,111,115, 116,32,111,102,115,105,109,105,108,97,114,32,116,111,32,112,114,111,112,114,105, 101,116,97,114,121,111,114,105,103,105,110,97,116,105,110,103,112,114,101,115, 116,105,103,105,111,117,115,103,114,97,109,109,97,116,105,99,97,108,101,120,112, 101,114,105,101,110,99,101,46,116,111,32,109,97,107,101,32,116,104,101,73,116,32 ,119,97,115,32,97,108,115,111,105,115,32,102,111,117,110,100,32,105,110,99,111, 109,112,101,116,105,116,111,114,115,105,110,32,116,104,101,32,85,46,83,46,114, 101,112,108,97,99,101,32,116,104,101,98,114,111,117,103,104,116,32,116,104,101, 99,97,108,99,117,108,97,116,105,111,110,102,97,108,108,32,111,102,32,116,104,101 ,116,104,101,32,103,101,110,101,114,97,108,112,114,97,99,116,105,99,97,108,108, 121,105,110,32,104,111,110,111,114,32,111,102,114,101,108,101,97,115,101,100,32, 105,110,114,101,115,105,100,101,110,116,105,97,108,97,110,100,32,115,111,109,101 ,32,111,102,107,105,110,103,32,111,102,32,116,104,101,114,101,97,99,116,105,111, 110,32,116,111,49,115,116,32,69,97,114,108,32,111,102,99,117,108,116,117,114,101 ,32,97,110,100,112,114,105,110,99,105,112,97,108,108,121,60,47,116,105,116,108, 101,62,10,32,32,116,104,101,121,32,99,97,110,32,98,101,98,97,99,107,32,116,111, 32,116,104,101,115,111,109,101,32,111,102,32,104,105,115,101,120,112,111,115,117 ,114,101,32,116,111,97,114,101,32,115,105,109,105,108,97,114,102,111,114,109,32, 111,102,32,116,104,101,97,100,100,70,97,118,111,114,105,116,101,99,105,116,105, 122,101,110,115,104,105,112,112,97,114,116,32,105,110,32,116,104,101,112,101,111 ,112,108,101,32,119,105,116,104,105,110,32,112,114,97,99,116,105,99,101,116,111, 32,99,111,110,116,105,110,117,101,38,97,109,112,59,109,105,110,117,115,59,97,112 ,112,114,111,118,101,100,32,98,121,32,116,104,101,32,102,105,114,115,116,32,97, 108,108,111,119,101,100,32,116,104,101,97,110,100,32,102,111,114,32,116,104,101, 102,117,110,99,116,105,111,110,105,110,103,112,108,97,121,105,110,103,32,116,104 ,101,115,111,108,117,116,105,111,110,32,116,111,104,101,105,103,104,116,61,34,48 ,34,32,105,110,32,104,105,115,32,98,111,111,107,109,111,114,101,32,116,104,97, 110,32,97,102,111,108,108,111,119,115,32,116,104,101,99,114,101,97,116,101,100, 32,116,104,101,112,114,101,115,101,110,99,101,32,105,110,38,110,98,115,112,59,60 ,47,116,100,62,110,97,116,105,111,110,97,108,105,115,116,116,104,101,32,105,100, 101,97,32,111,102,97,32,99,104,97,114,97,99,116,101,114,119,101,114,101,32,102, 111,114,99,101,100,32,99,108,97,115,115,61,34,98,116,110,100,97,121,115,32,111, 102,32,116,104,101,102,101,97,116,117,114,101,100,32,105,110,115,104,111,119,105 ,110,103,32,116,104,101,105,110,116,101,114,101,115,116,32,105,110,105,110,32, 112,108,97,99,101,32,111,102,116,117,114,110,32,111,102,32,116,104,101,116,104, 101,32,104,101,97,100,32,111,102,76,111,114,100,32,111,102,32,116,104,101,112, 111,108,105,116,105,99,97,108,108,121,104,97,115,32,105,116,115,32,111,119,110, 69,100,117,99,97,116,105,111,110,97,108,97,112,112,114,111,118,97,108,32,111,102 ,115,111,109,101,32,111,102,32,116,104,101,101,97,99,104,32,111,116,104,101,114, 44,98,101,104,97,118,105,111,114,32,111,102,97,110,100,32,98,101,99,97,117,115, 101,97,110,100,32,97,110,111,116,104,101,114,97,112,112,101,97,114,101,100,32, 111,110,114,101,99,111,114,100,101,100,32,105,110,98,108,97,99,107,38,113,117, 111,116,59,109,97,121,32,105,110,99,108,117,100,101,116,104,101,32,119,111,114, 108,100,39,115,99,97,110,32,108,101,97,100,32,116,111,114,101,102,101,114,115,32 ,116,111,32,97,98,111,114,100,101,114,61,34,48,34,32,103,111,118,101,114,110,109 ,101,110,116,32,119,105,110,110,105,110,103,32,116,104,101,114,101,115,117,108, 116,101,100,32,105,110,32,119,104,105,108,101,32,116,104,101,32,87,97,115,104, 105,110,103,116,111,110,44,116,104,101,32,115,117,98,106,101,99,116,99,105,116, 121,32,105,110,32,116,104,101,62,60,47,100,105,118,62,13,10,9,9,114,101,102,108, 101,99,116,32,116,104,101,116,111,32,99,111,109,112,108,101,116,101,98,101,99,97 ,109,101,32,109,111,114,101,114,97,100,105,111,97,99,116,105,118,101,114,101,106 ,101,99,116,101,100,32,98,121,119,105,116,104,111,117,116,32,97,110,121,104,105, 115,32,102,97,116,104,101,114,44,119,104,105,99,104,32,99,111,117,108,100,99,111 ,112,121,32,111,102,32,116,104,101,116,111,32,105,110,100,105,99,97,116,101,97, 32,112,111,108,105,116,105,99,97,108,97,99,99,111,117,110,116,115,32,111,102,99, 111,110,115,116,105,116,117,116,101,115,119,111,114,107,101,100,32,119,105,116, 104,101,114,60,47,97,62,60,47,108,105,62,111,102,32,104,105,115,32,108,105,102, 101,97,99,99,111,109,112,97,110,105,101,100,99,108,105,101,110,116,87,105,100, 116,104,112,114,101,118,101,110,116,32,116,104,101,76,101,103,105,115,108,97,116 ,105,118,101,100,105,102,102,101,114,101,110,116,108,121,116,111,103,101,116,104 ,101,114,32,105,110,104,97,115,32,115,101,118,101,114,97,108,102,111,114,32,97, 110,111,116,104,101,114,116,101,120,116,32,111,102,32,116,104,101,102,111,117, 110,100,101,100,32,116,104,101,101,32,119,105,116,104,32,116,104,101,32,105,115, 32,117,115,101,100,32,102,111,114,99,104,97,110,103,101,100,32,116,104,101,117, 115,117,97,108,108,121,32,116,104,101,112,108,97,99,101,32,119,104,101,114,101, 119,104,101,114,101,97,115,32,116,104,101,62,32,60,97,32,104,114,101,102,61,34, 34,62,60,97,32,104,114,101,102,61,34,116,104,101,109,115,101,108,118,101,115,44, 97,108,116,104,111,117,103,104,32,104,101,116,104,97,116,32,99,97,110,32,98,101, 116,114,97,100,105,116,105,111,110,97,108,114,111,108,101,32,111,102,32,116,104, 101,97,115,32,97,32,114,101,115,117,108,116,114,101,109,111,118,101,67,104,105, 108,100,100,101,115,105,103,110,101,100,32,98,121,119,101,115,116,32,111,102,32, 116,104,101,83,111,109,101,32,112,101,111,112,108,101,112,114,111,100,117,99,116 ,105,111,110,44,115,105,100,101,32,111,102,32,116,104,101,110,101,119,115,108, 101,116,116,101,114,115,117,115,101,100,32,98,121,32,116,104,101,100,111,119,110 ,32,116,111,32,116,104,101,97,99,99,101,112,116,101,100,32,98,121,108,105,118, 101,32,105,110,32,116,104,101,97,116,116,101,109,112,116,115,32,116,111,111,117, 116,115,105,100,101,32,116,104,101,102,114,101,113,117,101,110,99,105,101,115,72 ,111,119,101,118,101,114,44,32,105,110,112,114,111,103,114,97,109,109,101,114, 115,97,116,32,108,101,97,115,116,32,105,110,97,112,112,114,111,120,105,109,97, 116,101,97,108,116,104,111,117,103,104,32,105,116,119,97,115,32,112,97,114,116, 32,111,102,97,110,100,32,118,97,114,105,111,117,115,71,111,118,101,114,110,111, 114,32,111,102,116,104,101,32,97,114,116,105,99,108,101,116,117,114,110,101,100, 32,105,110,116,111,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,101,99, 111,110,111,109,121,105,115,32,116,104,101,32,109,111,115,116,109,111,115,116,32 ,119,105,100,101,108,121,119,111,117,108,100,32,108,97,116,101,114,97,110,100,32 ,112,101,114,104,97,112,115,114,105,115,101,32,116,111,32,116,104,101,111,99,99, 117,114,115,32,119,104,101,110,117,110,100,101,114,32,119,104,105,99,104,99,111, 110,100,105,116,105,111,110,115,46,116,104,101,32,119,101,115,116,101,114,110, 116,104,101,111,114,121,32,116,104,97,116,105,115,32,112,114,111,100,117,99,101, 100,116,104,101,32,99,105,116,121,32,111,102,105,110,32,119,104,105,99,104,32, 104,101,115,101,101,110,32,105,110,32,116,104,101,116,104,101,32,99,101,110,116, 114,97,108,98,117,105,108,100,105,110,103,32,111,102,109,97,110,121,32,111,102, 32,104,105,115,97,114,101,97,32,111,102,32,116,104,101,105,115,32,116,104,101,32 ,111,110,108,121,109,111,115,116,32,111,102,32,116,104,101,109,97,110,121,32,111 ,102,32,116,104,101,116,104,101,32,87,101,115,116,101,114,110,84,104,101,114,101 ,32,105,115,32,110,111,101,120,116,101,110,100,101,100,32,116,111,83,116,97,116, 105,115,116,105,99,97,108,99,111,108,115,112,97,110,61,50,32,124,115,104,111,114 ,116,32,115,116,111,114,121,112,111,115,115,105,98,108,101,32,116,111,116,111, 112,111,108,111,103,105,99,97,108,99,114,105,116,105,99,97,108,32,111,102,114, 101,112,111,114,116,101,100,32,116,111,97,32,67,104,114,105,115,116,105,97,110, 100,101,99,105,115,105,111,110,32,116,111,105,115,32,101,113,117,97,108,32,116, 111,112,114,111,98,108,101,109,115,32,111,102,84,104,105,115,32,99,97,110,32,98, 101,109,101,114,99,104,97,110,100,105,115,101,102,111,114,32,109,111,115,116,32, 111,102,110,111,32,101,118,105,100,101,110,99,101,101,100,105,116,105,111,110, 115,32,111,102,101,108,101,109,101,110,116,115,32,105,110,38,113,117,111,116,59, 46,32,84,104,101,99,111,109,47,105,109,97,103,101,115,47,119,104,105,99,104,32, 109,97,107,101,115,116,104,101,32,112,114,111,99,101,115,115,114,101,109,97,105, 110,115,32,116,104,101,108,105,116,101,114,97,116,117,114,101,44,105,115,32,97, 32,109,101,109,98,101,114,116,104,101,32,112,111,112,117,108,97,114,116,104,101, 32,97,110,99,105,101,110,116,112,114,111,98,108,101,109,115,32,105,110,116,105, 109,101,32,111,102,32,116,104,101,100,101,102,101,97,116,101,100,32,98,121,98, 111,100,121,32,111,102,32,116,104,101,97,32,102,101,119,32,121,101,97,114,115, 109,117,99,104,32,111,102,32,116,104,101,116,104,101,32,119,111,114,107,32,111, 102,67,97,108,105,102,111,114,110,105,97,44,115,101,114,118,101,100,32,97,115,32 ,97,103,111,118,101,114,110,109,101,110,116,46,99,111,110,99,101,112,116,115,32, 111,102,109,111,118,101,109,101,110,116,32,105,110,9,9,60,100,105,118,32,105,100 ,61,34,105,116,34,32,118,97,108,117,101,61,34,108,97,110,103,117,97,103,101,32, 111,102,97,115,32,116,104,101,121,32,97,114,101,112,114,111,100,117,99,101,100, 32,105,110,105,115,32,116,104,97,116,32,116,104,101,101,120,112,108,97,105,110, 32,116,104,101,100,105,118,62,60,47,100,105,118,62,10,72,111,119,101,118,101,114 ,32,116,104,101,108,101,97,100,32,116,111,32,116,104,101,9,60,97,32,104,114,101, 102,61,34,47,119,97,115,32,103,114,97,110,116,101,100,112,101,111,112,108,101,32 ,104,97,118,101,99,111,110,116,105,110,117,97,108,108,121,119,97,115,32,115,101, 101,110,32,97,115,97,110,100,32,114,101,108,97,116,101,100,116,104,101,32,114, 111,108,101,32,111,102,112,114,111,112,111,115,101,100,32,98,121,111,102,32,116, 104,101,32,98,101,115,116,101,97,99,104,32,111,116,104,101,114,46,67,111,110,115 ,116,97,110,116,105,110,101,112,101,111,112,108,101,32,102,114,111,109,100,105, 97,108,101,99,116,115,32,111,102,116,111,32,114,101,118,105,115,105,111,110,119, 97,115,32,114,101,110,97,109,101,100,97,32,115,111,117,114,99,101,32,111,102,116 ,104,101,32,105,110,105,116,105,97,108,108,97,117,110,99,104,101,100,32,105,110, 112,114,111,118,105,100,101,32,116,104,101,116,111,32,116,104,101,32,119,101,115 ,116,119,104,101,114,101,32,116,104,101,114,101,97,110,100,32,115,105,109,105, 108,97,114,98,101,116,119,101,101,110,32,116,119,111,105,115,32,97,108,115,111, 32,116,104,101,69,110,103,108,105,115,104,32,97,110,100,99,111,110,100,105,116, 105,111,110,115,44,116,104,97,116,32,105,116,32,119,97,115,101,110,116,105,116, 108,101,100,32,116,111,116,104,101,109,115,101,108,118,101,115,46,113,117,97,110 ,116,105,116,121,32,111,102,114,97,110,115,112,97,114,101,110,99,121,116,104,101 ,32,115,97,109,101,32,97,115,116,111,32,106,111,105,110,32,116,104,101,99,111, 117,110,116,114,121,32,97,110,100,116,104,105,115,32,105,115,32,116,104,101,84, 104,105,115,32,108,101,100,32,116,111,97,32,115,116,97,116,101,109,101,110,116, 99,111,110,116,114,97,115,116,32,116,111,108,97,115,116,73,110,100,101,120,79, 102,116,104,114,111,117,103,104,32,104,105,115,105,115,32,100,101,115,105,103, 110,101,100,116,104,101,32,116,101,114,109,32,105,115,105,115,32,112,114,111,118 ,105,100,101,100,112,114,111,116,101,99,116,32,116,104,101,110,103,60,47,97,62, 60,47,108,105,62,84,104,101,32,99,117,114,114,101,110,116,116,104,101,32,115,105 ,116,101,32,111,102,115,117,98,115,116,97,110,116,105,97,108,101,120,112,101,114 ,105,101,110,99,101,44,105,110,32,116,104,101,32,87,101,115,116,116,104,101,121, 32,115,104,111,117,108,100,115,108,111,118,101,110,196,141,105,110,97,99,111,109 ,101,110,116,97,114,105,111,115,117,110,105,118,101,114,115,105,100,97,100,99, 111,110,100,105,99,105,111,110,101,115,97,99,116,105,118,105,100,97,100,101,115, 101,120,112,101,114,105,101,110,99,105,97,116,101,99,110,111,108,111,103,195,173 ,97,112,114,111,100,117,99,99,105,195,179,110,112,117,110,116,117,97,99,105,195, 179,110,97,112,108,105,99,97,99,105,195,179,110,99,111,110,116,114,97,115,101, 195,177,97,99,97,116,101,103,111,114,195,173,97,115,114,101,103,105,115,116,114, 97,114,115,101,112,114,111,102,101,115,105,111,110,97,108,116,114,97,116,97,109, 105,101,110,116,111,114,101,103,195,173,115,116,114,97,116,101,115,101,99,114, 101,116,97,114,195,173,97,112,114,105,110,99,105,112,97,108,101,115,112,114,111, 116,101,99,99,105,195,179,110,105,109,112,111,114,116,97,110,116,101,115,105,109 ,112,111,114,116,97,110,99,105,97,112,111,115,105,98,105,108,105,100,97,100,105, 110,116,101,114,101,115,97,110,116,101,99,114,101,99,105,109,105,101,110,116,111 ,110,101,99,101,115,105,100,97,100,101,115,115,117,115,99,114,105,98,105,114,115 ,101,97,115,111,99,105,97,99,105,195,179,110,100,105,115,112,111,110,105,98,108, 101,115,101,118,97,108,117,97,99,105,195,179,110,101,115,116,117,100,105,97,110, 116,101,115,114,101,115,112,111,110,115,97,98,108,101,114,101,115,111,108,117,99 ,105,195,179,110,103,117,97,100,97,108,97,106,97,114,97,114,101,103,105,115,116, 114,97,100,111,115,111,112,111,114,116,117,110,105,100,97,100,99,111,109,101,114 ,99,105,97,108,101,115,102,111,116,111,103,114,97,102,195,173,97,97,117,116,111, 114,105,100,97,100,101,115,105,110,103,101,110,105,101,114,195,173,97,116,101, 108,101,118,105,115,105,195,179,110,99,111,109,112,101,116,101,110,99,105,97,111 ,112,101,114,97,99,105,111,110,101,115,101,115,116,97,98,108,101,99,105,100,111, 115,105,109,112,108,101,109,101,110,116,101,97,99,116,117,97,108,109,101,110,116 ,101,110,97,118,101,103,97,99,105,195,179,110,99,111,110,102,111,114,109,105,100 ,97,100,108,105,110,101,45,104,101,105,103,104,116,58,102,111,110,116,45,102,97, 109,105,108,121,58,34,32,58,32,34,104,116,116,112,58,47,47,97,112,112,108,105,99 ,97,116,105,111,110,115,108,105,110,107,34,32,104,114,101,102,61,34,115,112,101, 99,105,102,105,99,97,108,108,121,47,47,60,33,91,67,68,65,84,65,91,10,79,114,103, 97,110,105,122,97,116,105,111,110,100,105,115,116,114,105,98,117,116,105,111,110 ,48,112,120,59,32,104,101,105,103,104,116,58,114,101,108,97,116,105,111,110,115, 104,105,112,100,101,118,105,99,101,45,119,105,100,116,104,60,100,105,118,32,99, 108,97,115,115,61,34,60,108,97,98,101,108,32,102,111,114,61,34,114,101,103,105, 115,116,114,97,116,105,111,110,60,47,110,111,115,99,114,105,112,116,62,10,47,105 ,110,100,101,120,46,104,116,109,108,34,119,105,110,100,111,119,46,111,112,101, 110,40,32,33,105,109,112,111,114,116,97,110,116,59,97,112,112,108,105,99,97,116, 105,111,110,47,105,110,100,101,112,101,110,100,101,110,99,101,47,47,119,119,119, 46,103,111,111,103,108,101,111,114,103,97,110,105,122,97,116,105,111,110,97,117, 116,111,99,111,109,112,108,101,116,101,114,101,113,117,105,114,101,109,101,110, 116,115,99,111,110,115,101,114,118,97,116,105,118,101,60,102,111,114,109,32,110, 97,109,101,61,34,105,110,116,101,108,108,101,99,116,117,97,108,109,97,114,103, 105,110,45,108,101,102,116,58,49,56,116,104,32,99,101,110,116,117,114,121,97,110 ,32,105,109,112,111,114,116,97,110,116,105,110,115,116,105,116,117,116,105,111, 110,115,97,98,98,114,101,118,105,97,116,105,111,110,60,105,109,103,32,99,108,97, 115,115,61,34,111,114,103,97,110,105,115,97,116,105,111,110,99,105,118,105,108, 105,122,97,116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,97,114,99 ,104,105,116,101,99,116,117,114,101,105,110,99,111,114,112,111,114,97,116,101, 100,50,48,116,104,32,99,101,110,116,117,114,121,45,99,111,110,116,97,105,110,101 ,114,34,62,109,111,115,116,32,110,111,116,97,98,108,121,47,62,60,47,97,62,60,47, 100,105,118,62,110,111,116,105,102,105,99,97,116,105,111,110,39,117,110,100,101, 102,105,110,101,100,39,41,70,117,114,116,104,101,114,109,111,114,101,44,98,101, 108,105,101,118,101,32,116,104,97,116,105,110,110,101,114,72,84,77,76,32,61,32, 112,114,105,111,114,32,116,111,32,116,104,101,100,114,97,109,97,116,105,99,97, 108,108,121,114,101,102,101,114,114,105,110,103,32,116,111,110,101,103,111,116, 105,97,116,105,111,110,115,104,101,97,100,113,117,97,114,116,101,114,115,83,111, 117,116,104,32,65,102,114,105,99,97,117,110,115,117,99,99,101,115,115,102,117, 108,80,101,110,110,115,121,108,118,97,110,105,97,65,115,32,97,32,114,101,115,117 ,108,116,44,60,104,116,109,108,32,108,97,110,103,61,34,38,108,116,59,47,115,117, 112,38,103,116,59,100,101,97,108,105,110,103,32,119,105,116,104,112,104,105,108, 97,100,101,108,112,104,105,97,104,105,115,116,111,114,105,99,97,108,108,121,41, 59,60,47,115,99,114,105,112,116,62,10,112,97,100,100,105,110,103,45,116,111,112, 58,101,120,112,101,114,105,109,101,110,116,97,108,103,101,116,65,116,116,114,105 ,98,117,116,101,105,110,115,116,114,117,99,116,105,111,110,115,116,101,99,104, 110,111,108,111,103,105,101,115,112,97,114,116,32,111,102,32,116,104,101,32,61, 102,117,110,99,116,105,111,110,40,41,123,115,117,98,115,99,114,105,112,116,105, 111,110,108,46,100,116,100,34,62,13,10,60,104,116,103,101,111,103,114,97,112,104 ,105,99,97,108,67,111,110,115,116,105,116,117,116,105,111,110,39,44,32,102,117, 110,99,116,105,111,110,40,115,117,112,112,111,114,116,101,100,32,98,121,97,103, 114,105,99,117,108,116,117,114,97,108,99,111,110,115,116,114,117,99,116,105,111, 110,112,117,98,108,105,99,97,116,105,111,110,115,102,111,110,116,45,115,105,122, 101,58,32,49,97,32,118,97,114,105,101,116,121,32,111,102,60,100,105,118,32,115, 116,121,108,101,61,34,69,110,99,121,99,108,111,112,101,100,105,97,105,102,114,97 ,109,101,32,115,114,99,61,34,100,101,109,111,110,115,116,114,97,116,101,100,97, 99,99,111,109,112,108,105,115,104,101,100,117,110,105,118,101,114,115,105,116, 105,101,115,68,101,109,111,103,114,97,112,104,105,99,115,41,59,60,47,115,99,114, 105,112,116,62,60,100,101,100,105,99,97,116,101,100,32,116,111,107,110,111,119, 108,101,100,103,101,32,111,102,115,97,116,105,115,102,97,99,116,105,111,110,112, 97,114,116,105,99,117,108,97,114,108,121,60,47,100,105,118,62,60,47,100,105,118, 62,69,110,103,108,105,115,104,32,40,85,83,41,97,112,112,101,110,100,67,104,105, 108,100,40,116,114,97,110,115,109,105,115,115,105,111,110,115,46,32,72,111,119, 101,118,101,114,44,32,105,110,116,101,108,108,105,103,101,110,99,101,34,32,116, 97,98,105,110,100,101,120,61,34,102,108,111,97,116,58,114,105,103,104,116,59,67, 111,109,109,111,110,119,101,97,108,116,104,114,97,110,103,105,110,103,32,102,114 ,111,109,105,110,32,119,104,105,99,104,32,116,104,101,97,116,32,108,101,97,115, 116,32,111,110,101,114,101,112,114,111,100,117,99,116,105,111,110,101,110,99,121 ,99,108,111,112,101,100,105,97,59,102,111,110,116,45,115,105,122,101,58,49,106, 117,114,105,115,100,105,99,116,105,111,110,97,116,32,116,104,97,116,32,116,105, 109,101,34,62,60,97,32,99,108,97,115,115,61,34,73,110,32,97,100,100,105,116,105, 111,110,44,100,101,115,99,114,105,112,116,105,111,110,43,99,111,110,118,101,114, 115,97,116,105,111,110,99,111,110,116,97,99,116,32,119,105,116,104,105,115,32, 103,101,110,101,114,97,108,108,121,114,34,32,99,111,110,116,101,110,116,61,34, 114,101,112,114,101,115,101,110,116,105,110,103,38,108,116,59,109,97,116,104,38, 103,116,59,112,114,101,115,101,110,116,97,116,105,111,110,111,99,99,97,115,105, 111,110,97,108,108,121,60,105,109,103,32,119,105,100,116,104,61,34,110,97,118, 105,103,97,116,105,111,110,34,62,99,111,109,112,101,110,115,97,116,105,111,110, 99,104,97,109,112,105,111,110,115,104,105,112,109,101,100,105,97,61,34,97,108, 108,34,32,118,105,111,108,97,116,105,111,110,32,111,102,114,101,102,101,114,101, 110,99,101,32,116,111,114,101,116,117,114,110,32,116,114,117,101,59,83,116,114, 105,99,116,47,47,69,78,34,32,116,114,97,110,115,97,99,116,105,111,110,115,105, 110,116,101,114,118,101,110,116,105,111,110,118,101,114,105,102,105,99,97,116, 105,111,110,73,110,102,111,114,109,97,116,105,111,110,32,100,105,102,102,105,99, 117,108,116,105,101,115,67,104,97,109,112,105,111,110,115,104,105,112,99,97,112, 97,98,105,108,105,116,105,101,115,60,33,91,101,110,100,105,102,93,45,45,62,125, 10,60,47,115,99,114,105,112,116,62,10,67,104,114,105,115,116,105,97,110,105,116, 121,102,111,114,32,101,120,97,109,112,108,101,44,80,114,111,102,101,115,115,105, 111,110,97,108,114,101,115,116,114,105,99,116,105,111,110,115,115,117,103,103, 101,115,116,32,116,104,97,116,119,97,115,32,114,101,108,101,97,115,101,100,40, 115,117,99,104,32,97,115,32,116,104,101,114,101,109,111,118,101,67,108,97,115, 115,40,117,110,101,109,112,108,111,121,109,101,110,116,116,104,101,32,65,109,101 ,114,105,99,97,110,115,116,114,117,99,116,117,114,101,32,111,102,47,105,110,100, 101,120,46,104,116,109,108,32,112,117,98,108,105,115,104,101,100,32,105,110,115, 112,97,110,32,99,108,97,115,115,61,34,34,62,60,97,32,104,114,101,102,61,34,47, 105,110,116,114,111,100,117,99,116,105,111,110,98,101,108,111,110,103,105,110, 103,32,116,111,99,108,97,105,109,101,100,32,116,104,97,116,99,111,110,115,101, 113,117,101,110,99,101,115,60,109,101,116,97,32,110,97,109,101,61,34,71,117,105, 100,101,32,116,111,32,116,104,101,111,118,101,114,119,104,101,108,109,105,110, 103,97,103,97,105,110,115,116,32,116,104,101,32,99,111,110,99,101,110,116,114,97 ,116,101,100,44,10,46,110,111,110,116,111,117,99,104,32,111,98,115,101,114,118, 97,116,105,111,110,115,60,47,97,62,10,60,47,100,105,118,62,10,102,32,40,100,111, 99,117,109,101,110,116,46,98,111,114,100,101,114,58,32,49,112,120,32,123,102,111 ,110,116,45,115,105,122,101,58,49,116,114,101,97,116,109,101,110,116,32,111,102, 48,34,32,104,101,105,103,104,116,61,34,49,109,111,100,105,102,105,99,97,116,105, 111,110,73,110,100,101,112,101,110,100,101,110,99,101,100,105,118,105,100,101, 100,32,105,110,116,111,103,114,101,97,116,101,114,32,116,104,97,110,97,99,104, 105,101,118,101,109,101,110,116,115,101,115,116,97,98,108,105,115,104,105,110, 103,74,97,118,97,83,99,114,105,112,116,34,32,110,101,118,101,114,116,104,101,108 ,101,115,115,115,105,103,110,105,102,105,99,97,110,99,101,66,114,111,97,100,99, 97,115,116,105,110,103,62,38,110,98,115,112,59,60,47,116,100,62,99,111,110,116, 97,105,110,101,114,34,62,10,115,117,99,104,32,97,115,32,116,104,101,32,105,110, 102,108,117,101,110,99,101,32,111,102,97,32,112,97,114,116,105,99,117,108,97,114 ,115,114,99,61,39,104,116,116,112,58,47,47,110,97,118,105,103,97,116,105,111,110 ,34,32,104,97,108,102,32,111,102,32,116,104,101,32,115,117,98,115,116,97,110,116 ,105,97,108,32,38,110,98,115,112,59,60,47,100,105,118,62,97,100,118,97,110,116, 97,103,101,32,111,102,100,105,115,99,111,118,101,114,121,32,111,102,102,117,110, 100,97,109,101,110,116,97,108,32,109,101,116,114,111,112,111,108,105,116,97,110, 116,104,101,32,111,112,112,111,115,105,116,101,34,32,120,109,108,58,108,97,110, 103,61,34,100,101,108,105,98,101,114,97,116,101,108,121,97,108,105,103,110,61,99 ,101,110,116,101,114,101,118,111,108,117,116,105,111,110,32,111,102,112,114,101, 115,101,114,118,97,116,105,111,110,105,109,112,114,111,118,101,109,101,110,116, 115,98,101,103,105,110,110,105,110,103,32,105,110,74,101,115,117,115,32,67,104, 114,105,115,116,80,117,98,108,105,99,97,116,105,111,110,115,100,105,115,97,103, 114,101,101,109,101,110,116,116,101,120,116,45,97,108,105,103,110,58,114,44,32, 102,117,110,99,116,105,111,110,40,41,115,105,109,105,108,97,114,105,116,105,101, 115,98,111,100,121,62,60,47,104,116,109,108,62,105,115,32,99,117,114,114,101,110 ,116,108,121,97,108,112,104,97,98,101,116,105,99,97,108,105,115,32,115,111,109, 101,116,105,109,101,115,116,121,112,101,61,34,105,109,97,103,101,47,109,97,110, 121,32,111,102,32,116,104,101,32,102,108,111,119,58,104,105,100,100,101,110,59, 97,118,97,105,108,97,98,108,101,32,105,110,100,101,115,99,114,105,98,101,32,116, 104,101,101,120,105,115,116,101,110,99,101,32,111,102,97,108,108,32,111,118,101, 114,32,116,104,101,116,104,101,32,73,110,116,101,114,110,101,116,9,60,117,108,32 ,99,108,97,115,115,61,34,105,110,115,116,97,108,108,97,116,105,111,110,110,101, 105,103,104,98,111,114,104,111,111,100,97,114,109,101,100,32,102,111,114,99,101, 115,114,101,100,117,99,105,110,103,32,116,104,101,99,111,110,116,105,110,117,101 ,115,32,116,111,78,111,110,101,116,104,101,108,101,115,115,44,116,101,109,112, 101,114,97,116,117,114,101,115,10,9,9,60,97,32,104,114,101,102,61,34,99,108,111, 115,101,32,116,111,32,116,104,101,101,120,97,109,112,108,101,115,32,111,102,32, 105,115,32,97,98,111,117,116,32,116,104,101,40,115,101,101,32,98,101,108,111,119 ,41,46,34,32,105,100,61,34,115,101,97,114,99,104,112,114,111,102,101,115,115,105 ,111,110,97,108,105,115,32,97,118,97,105,108,97,98,108,101,116,104,101,32,111, 102,102,105,99,105,97,108,9,9,60,47,115,99,114,105,112,116,62,10,10,9,9,60,100, 105,118,32,105,100,61,34,97,99,99,101,108,101,114,97,116,105,111,110,116,104,114 ,111,117,103,104,32,116,104,101,32,72,97,108,108,32,111,102,32,70,97,109,101,100 ,101,115,99,114,105,112,116,105,111,110,115,116,114,97,110,115,108,97,116,105, 111,110,115,105,110,116,101,114,102,101,114,101,110,99,101,32,116,121,112,101,61 ,39,116,101,120,116,47,114,101,99,101,110,116,32,121,101,97,114,115,105,110,32, 116,104,101,32,119,111,114,108,100,118,101,114,121,32,112,111,112,117,108,97,114 ,123,98,97,99,107,103,114,111,117,110,100,58,116,114,97,100,105,116,105,111,110, 97,108,32,115,111,109,101,32,111,102,32,116,104,101,32,99,111,110,110,101,99,116 ,101,100,32,116,111,101,120,112,108,111,105,116,97,116,105,111,110,101,109,101, 114,103,101,110,99,101,32,111,102,99,111,110,115,116,105,116,117,116,105,111,110 ,65,32,72,105,115,116,111,114,121,32,111,102,115,105,103,110,105,102,105,99,97, 110,116,32,109,97,110,117,102,97,99,116,117,114,101,100,101,120,112,101,99,116, 97,116,105,111,110,115,62,60,110,111,115,99,114,105,112,116,62,60,99,97,110,32, 98,101,32,102,111,117,110,100,98,101,99,97,117,115,101,32,116,104,101,32,104,97, 115,32,110,111,116,32,98,101,101,110,110,101,105,103,104,98,111,117,114,105,110, 103,119,105,116,104,111,117,116,32,116,104,101,32,97,100,100,101,100,32,116,111, 32,116,104,101,9,60,108,105,32,99,108,97,115,115,61,34,105,110,115,116,114,117, 109,101,110,116,97,108,83,111,118,105,101,116,32,85,110,105,111,110,97,99,107, 110,111,119,108,101,100,103,101,100,119,104,105,99,104,32,99,97,110,32,98,101, 110,97,109,101,32,102,111,114,32,116,104,101,97,116,116,101,110,116,105,111,110, 32,116,111,97,116,116,101,109,112,116,115,32,116,111,32,100,101,118,101,108,111, 112,109,101,110,116,115,73,110,32,102,97,99,116,44,32,116,104,101,60,108,105,32, 99,108,97,115,115,61,34,97,105,109,112,108,105,99,97,116,105,111,110,115,115,117 ,105,116,97,98,108,101,32,102,111,114,109,117,99,104,32,111,102,32,116,104,101, 32,99,111,108,111,110,105,122,97,116,105,111,110,112,114,101,115,105,100,101,110 ,116,105,97,108,99,97,110,99,101,108,66,117,98,98,108,101,32,73,110,102,111,114, 109,97,116,105,111,110,109,111,115,116,32,111,102,32,116,104,101,32,105,115,32, 100,101,115,99,114,105,98,101,100,114,101,115,116,32,111,102,32,116,104,101,32, 109,111,114,101,32,111,114,32,108,101,115,115,105,110,32,83,101,112,116,101,109, 98,101,114,73,110,116,101,108,108,105,103,101,110,99,101,115,114,99,61,34,104, 116,116,112,58,47,47,112,120,59,32,104,101,105,103,104,116,58,32,97,118,97,105, 108,97,98,108,101,32,116,111,109,97,110,117,102,97,99,116,117,114,101,114,104, 117,109,97,110,32,114,105,103,104,116,115,108,105,110,107,32,104,114,101,102,61, 34,47,97,118,97,105,108,97,98,105,108,105,116,121,112,114,111,112,111,114,116, 105,111,110,97,108,111,117,116,115,105,100,101,32,116,104,101,32,97,115,116,114, 111,110,111,109,105,99,97,108,104,117,109,97,110,32,98,101,105,110,103,115,110, 97,109,101,32,111,102,32,116,104,101,32,97,114,101,32,102,111,117,110,100,32,105 ,110,97,114,101,32,98,97,115,101,100,32,111,110,115,109,97,108,108,101,114,32, 116,104,97,110,97,32,112,101,114,115,111,110,32,119,104,111,101,120,112,97,110, 115,105,111,110,32,111,102,97,114,103,117,105,110,103,32,116,104,97,116,110,111, 119,32,107,110,111,119,110,32,97,115,73,110,32,116,104,101,32,101,97,114,108,121 ,105,110,116,101,114,109,101,100,105,97,116,101,100,101,114,105,118,101,100,32, 102,114,111,109,83,99,97,110,100,105,110,97,118,105,97,110,60,47,97,62,60,47,100 ,105,118,62,13,10,99,111,110,115,105,100,101,114,32,116,104,101,97,110,32,101, 115,116,105,109,97,116,101,100,116,104,101,32,78,97,116,105,111,110,97,108,60, 100,105,118,32,105,100,61,34,112,97,103,114,101,115,117,108,116,105,110,103,32, 105,110,99,111,109,109,105,115,115,105,111,110,101,100,97,110,97,108,111,103,111 ,117,115,32,116,111,97,114,101,32,114,101,113,117,105,114,101,100,47,117,108,62, 10,60,47,100,105,118,62,10,119,97,115,32,98,97,115,101,100,32,111,110,97,110,100 ,32,98,101,99,97,109,101,32,97,38,110,98,115,112,59,38,110,98,115,112,59,116,34, 32,118,97,108,117,101,61,34,34,32,119,97,115,32,99,97,112,116,117,114,101,100, 110,111,32,109,111,114,101,32,116,104,97,110,114,101,115,112,101,99,116,105,118, 101,108,121,99,111,110,116,105,110,117,101,32,116,111,32,62,13,10,60,104,101,97, 100,62,13,10,60,119,101,114,101,32,99,114,101,97,116,101,100,109,111,114,101,32, 103,101,110,101,114,97,108,105,110,102,111,114,109,97,116,105,111,110,32,117,115 ,101,100,32,102,111,114,32,116,104,101,105,110,100,101,112,101,110,100,101,110, 116,32,116,104,101,32,73,109,112,101,114,105,97,108,99,111,109,112,111,110,101, 110,116,32,111,102,116,111,32,116,104,101,32,110,111,114,116,104,105,110,99,108, 117,100,101,32,116,104,101,32,67,111,110,115,116,114,117,99,116,105,111,110,115, 105,100,101,32,111,102,32,116,104,101,32,119,111,117,108,100,32,110,111,116,32, 98,101,102,111,114,32,105,110,115,116,97,110,99,101,105,110,118,101,110,116,105, 111,110,32,111,102,109,111,114,101,32,99,111,109,112,108,101,120,99,111,108,108, 101,99,116,105,118,101,108,121,98,97,99,107,103,114,111,117,110,100,58,32,116, 101,120,116,45,97,108,105,103,110,58,32,105,116,115,32,111,114,105,103,105,110, 97,108,105,110,116,111,32,97,99,99,111,117,110,116,116,104,105,115,32,112,114, 111,99,101,115,115,97,110,32,101,120,116,101,110,115,105,118,101,104,111,119,101 ,118,101,114,44,32,116,104,101,116,104,101,121,32,97,114,101,32,110,111,116,114, 101,106,101,99,116,101,100,32,116,104,101,99,114,105,116,105,99,105,115,109,32, 111,102,100,117,114,105,110,103,32,119,104,105,99,104,112,114,111,98,97,98,108, 121,32,116,104,101,116,104,105,115,32,97,114,116,105,99,108,101,40,102,117,110, 99,116,105,111,110,40,41,123,73,116,32,115,104,111,117,108,100,32,98,101,97,110, 32,97,103,114,101,101,109,101,110,116,97,99,99,105,100,101,110,116,97,108,108, 121,100,105,102,102,101,114,115,32,102,114,111,109,65,114,99,104,105,116,101,99, 116,117,114,101,98,101,116,116,101,114,32,107,110,111,119,110,97,114,114,97,110, 103,101,109,101,110,116,115,105,110,102,108,117,101,110,99,101,32,111,110,97,116 ,116,101,110,100,101,100,32,116,104,101,105,100,101,110,116,105,99,97,108,32,116 ,111,115,111,117,116,104,32,111,102,32,116,104,101,112,97,115,115,32,116,104,114 ,111,117,103,104,120,109,108,34,32,116,105,116,108,101,61,34,119,101,105,103,104 ,116,58,98,111,108,100,59,99,114,101,97,116,105,110,103,32,116,104,101,100,105, 115,112,108,97,121,58,110,111,110,101,114,101,112,108,97,99,101,100,32,116,104, 101,60,105,109,103,32,115,114,99,61,34,47,105,104,116,116,112,115,58,47,47,119, 119,119,46,87,111,114,108,100,32,87,97,114,32,73,73,116,101,115,116,105,109,111, 110,105,97,108,115,102,111,117,110,100,32,105,110,32,116,104,101,114,101,113,117 ,105,114,101,100,32,116,111,32,97,110,100,32,116,104,97,116,32,116,104,101,98, 101,116,119,101,101,110,32,116,104,101,32,119,97,115,32,100,101,115,105,103,110, 101,100,99,111,110,115,105,115,116,115,32,111,102,32,99,111,110,115,105,100,101, 114,97,98,108,121,112,117,98,108,105,115,104,101,100,32,98,121,116,104,101,32, 108,97,110,103,117,97,103,101,67,111,110,115,101,114,118,97,116,105,111,110,99, 111,110,115,105,115,116,101,100,32,111,102,114,101,102,101,114,32,116,111,32,116 ,104,101,98,97,99,107,32,116,111,32,116,104,101,32,99,115,115,34,32,109,101,100, 105,97,61,34,80,101,111,112,108,101,32,102,114,111,109,32,97,118,97,105,108,97, 98,108,101,32,111,110,112,114,111,118,101,100,32,116,111,32,98,101,115,117,103, 103,101,115,116,105,111,110,115,34,119,97,115,32,107,110,111,119,110,32,97,115, 118,97,114,105,101,116,105,101,115,32,111,102,108,105,107,101,108,121,32,116,111 ,32,98,101,99,111,109,112,114,105,115,101,100,32,111,102,115,117,112,112,111,114 ,116,32,116,104,101,32,104,97,110,100,115,32,111,102,32,116,104,101,99,111,117, 112,108,101,100,32,119,105,116,104,99,111,110,110,101,99,116,32,97,110,100,32,98 ,111,114,100,101,114,58,110,111,110,101,59,112,101,114,102,111,114,109,97,110,99 ,101,115,98,101,102,111,114,101,32,98,101,105,110,103,108,97,116,101,114,32,98, 101,99,97,109,101,99,97,108,99,117,108,97,116,105,111,110,115,111,102,116,101, 110,32,99,97,108,108,101,100,114,101,115,105,100,101,110,116,115,32,111,102,109, 101,97,110,105,110,103,32,116,104,97,116,62,60,108,105,32,99,108,97,115,115,61, 34,101,118,105,100,101,110,99,101,32,102,111,114,101,120,112,108,97,110,97,116, 105,111,110,115,101,110,118,105,114,111,110,109,101,110,116,115,34,62,60,47,97, 62,60,47,100,105,118,62,119,104,105,99,104,32,97,108,108,111,119,115,73,110,116, 114,111,100,117,99,116,105,111,110,100,101,118,101,108,111,112,101,100,32,98,121 ,97,32,119,105,100,101,32,114,97,110,103,101,111,110,32,98,101,104,97,108,102,32 ,111,102,118,97,108,105,103,110,61,34,116,111,112,34,112,114,105,110,99,105,112, 108,101,32,111,102,97,116,32,116,104,101,32,116,105,109,101,44,60,47,110,111,115 ,99,114,105,112,116,62,13,115,97,105,100,32,116,111,32,104,97,118,101,105,110,32 ,116,104,101,32,102,105,114,115,116,119,104,105,108,101,32,111,116,104,101,114, 115,104,121,112,111,116,104,101,116,105,99,97,108,112,104,105,108,111,115,111, 112,104,101,114,115,112,111,119,101,114,32,111,102,32,116,104,101,99,111,110,116 ,97,105,110,101,100,32,105,110,112,101,114,102,111,114,109,101,100,32,98,121,105 ,110,97,98,105,108,105,116,121,32,116,111,119,101,114,101,32,119,114,105,116,116 ,101,110,115,112,97,110,32,115,116,121,108,101,61,34,105,110,112,117,116,32,110, 97,109,101,61,34,116,104,101,32,113,117,101,115,116,105,111,110,105,110,116,101, 110,100,101,100,32,102,111,114,114,101,106,101,99,116,105,111,110,32,111,102,105 ,109,112,108,105,101,115,32,116,104,97,116,105,110,118,101,110,116,101,100,32, 116,104,101,116,104,101,32,115,116,97,110,100,97,114,100,119,97,115,32,112,114, 111,98,97,98,108,121,108,105,110,107,32,98,101,116,119,101,101,110,112,114,111, 102,101,115,115,111,114,32,111,102,105,110,116,101,114,97,99,116,105,111,110,115 ,99,104,97,110,103,105,110,103,32,116,104,101,73,110,100,105,97,110,32,79,99,101 ,97,110,32,99,108,97,115,115,61,34,108,97,115,116,119,111,114,107,105,110,103,32 ,119,105,116,104,39,104,116,116,112,58,47,47,119,119,119,46,121,101,97,114,115, 32,98,101,102,111,114,101,84,104,105,115,32,119,97,115,32,116,104,101,114,101,99 ,114,101,97,116,105,111,110,97,108,101,110,116,101,114,105,110,103,32,116,104, 101,109,101,97,115,117,114,101,109,101,110,116,115,97,110,32,101,120,116,114,101 ,109,101,108,121,118,97,108,117,101,32,111,102,32,116,104,101,115,116,97,114,116 ,32,111,102,32,116,104,101,10,60,47,115,99,114,105,112,116,62,10,10,97,110,32, 101,102,102,111,114,116,32,116,111,105,110,99,114,101,97,115,101,32,116,104,101, 116,111,32,116,104,101,32,115,111,117,116,104,115,112,97,99,105,110,103,61,34,48 ,34,62,115,117,102,102,105,99,105,101,110,116,108,121,116,104,101,32,69,117,114, 111,112,101,97,110,99,111,110,118,101,114,116,101,100,32,116,111,99,108,101,97, 114,84,105,109,101,111,117,116,100,105,100,32,110,111,116,32,104,97,118,101,99, 111,110,115,101,113,117,101,110,116,108,121,102,111,114,32,116,104,101,32,110, 101,120,116,101,120,116,101,110,115,105,111,110,32,111,102,101,99,111,110,111, 109,105,99,32,97,110,100,97,108,116,104,111,117,103,104,32,116,104,101,97,114, 101,32,112,114,111,100,117,99,101,100,97,110,100,32,119,105,116,104,32,116,104, 101,105,110,115,117,102,102,105,99,105,101,110,116,103,105,118,101,110,32,98,121 ,32,116,104,101,115,116,97,116,105,110,103,32,116,104,97,116,101,120,112,101,110 ,100,105,116,117,114,101,115,60,47,115,112,97,110,62,60,47,97,62,10,116,104,111, 117,103,104,116,32,116,104,97,116,111,110,32,116,104,101,32,98,97,115,105,115,99 ,101,108,108,112,97,100,100,105,110,103,61,105,109,97,103,101,32,111,102,32,116, 104,101,114,101,116,117,114,110,105,110,103,32,116,111,105,110,102,111,114,109, 97,116,105,111,110,44,115,101,112,97,114,97,116,101,100,32,98,121,97,115,115,97, 115,115,105,110,97,116,101,100,115,34,32,99,111,110,116,101,110,116,61,34,97,117 ,116,104,111,114,105,116,121,32,111,102,110,111,114,116,104,119,101,115,116,101, 114,110,60,47,100,105,118,62,10,60,100,105,118,32,34,62,60,47,100,105,118,62,13, 10,32,32,99,111,110,115,117,108,116,97,116,105,111,110,99,111,109,109,117,110, 105,116,121,32,111,102,116,104,101,32,110,97,116,105,111,110,97,108,105,116,32, 115,104,111,117,108,100,32,98,101,112,97,114,116,105,99,105,112,97,110,116,115, 32,97,108,105,103,110,61,34,108,101,102,116,116,104,101,32,103,114,101,97,116, 101,115,116,115,101,108,101,99,116,105,111,110,32,111,102,115,117,112,101,114, 110,97,116,117,114,97,108,100,101,112,101,110,100,101,110,116,32,111,110,105,115 ,32,109,101,110,116,105,111,110,101,100,97,108,108,111,119,105,110,103,32,116, 104,101,119,97,115,32,105,110,118,101,110,116,101,100,97,99,99,111,109,112,97, 110,121,105,110,103,104,105,115,32,112,101,114,115,111,110,97,108,97,118,97,105, 108,97,98,108,101,32,97,116,115,116,117,100,121,32,111,102,32,116,104,101,111, 110,32,116,104,101,32,111,116,104,101,114,101,120,101,99,117,116,105,111,110,32, 111,102,72,117,109,97,110,32,82,105,103,104,116,115,116,101,114,109,115,32,111, 102,32,116,104,101,97,115,115,111,99,105,97,116,105,111,110,115,114,101,115,101, 97,114,99,104,32,97,110,100,115,117,99,99,101,101,100,101,100,32,98,121,100,101, 102,101,97,116,101,100,32,116,104,101,97,110,100,32,102,114,111,109,32,116,104, 101,98,117,116,32,116,104,101,121,32,97,114,101,99,111,109,109,97,110,100,101, 114,32,111,102,115,116,97,116,101,32,111,102,32,116,104,101,121,101,97,114,115, 32,111,102,32,97,103,101,116,104,101,32,115,116,117,100,121,32,111,102,60,117, 108,32,99,108,97,115,115,61,34,115,112,108,97,99,101,32,105,110,32,116,104,101, 119,104,101,114,101,32,104,101,32,119,97,115,60,108,105,32,99,108,97,115,115,61, 34,102,116,104,101,114,101,32,97,114,101,32,110,111,119,104,105,99,104,32,98,101 ,99,97,109,101,104,101,32,112,117,98,108,105,115,104,101,100,101,120,112,114,101 ,115,115,101,100,32,105,110,116,111,32,119,104,105,99,104,32,116,104,101,99,111, 109,109,105,115,115,105,111,110,101,114,102,111,110,116,45,119,101,105,103,104, 116,58,116,101,114,114,105,116,111,114,121,32,111,102,101,120,116,101,110,115, 105,111,110,115,34,62,82,111,109,97,110,32,69,109,112,105,114,101,101,113,117,97 ,108,32,116,111,32,116,104,101,73,110,32,99,111,110,116,114,97,115,116,44,104, 111,119,101,118,101,114,44,32,97,110,100,105,115,32,116,121,112,105,99,97,108, 108,121,97,110,100,32,104,105,115,32,119,105,102,101,40,97,108,115,111,32,99,97, 108,108,101,100,62,60,117,108,32,99,108,97,115,115,61,34,101,102,102,101,99,116, 105,118,101,108,121,32,101,118,111,108,118,101,100,32,105,110,116,111,115,101, 101,109,32,116,111,32,104,97,118,101,119,104,105,99,104,32,105,115,32,116,104, 101,116,104,101,114,101,32,119,97,115,32,110,111,97,110,32,101,120,99,101,108, 108,101,110,116,97,108,108,32,111,102,32,116,104,101,115,101,100,101,115,99,114, 105,98,101,100,32,98,121,73,110,32,112,114,97,99,116,105,99,101,44,98,114,111,97 ,100,99,97,115,116,105,110,103,99,104,97,114,103,101,100,32,119,105,116,104,114, 101,102,108,101,99,116,101,100,32,105,110,115,117,98,106,101,99,116,101,100,32, 116,111,109,105,108,105,116,97,114,121,32,97,110,100,116,111,32,116,104,101,32, 112,111,105,110,116,101,99,111,110,111,109,105,99,97,108,108,121,115,101,116,84, 97,114,103,101,116,105,110,103,97,114,101,32,97,99,116,117,97,108,108,121,118, 105,99,116,111,114,121,32,111,118,101,114,40,41,59,60,47,115,99,114,105,112,116, 62,99,111,110,116,105,110,117,111,117,115,108,121,114,101,113,117,105,114,101, 100,32,102,111,114,101,118,111,108,117,116,105,111,110,97,114,121,97,110,32,101, 102,102,101,99,116,105,118,101,110,111,114,116,104,32,111,102,32,116,104,101,44, 32,119,104,105,99,104,32,119,97,115,32,102,114,111,110,116,32,111,102,32,116,104 ,101,111,114,32,111,116,104,101,114,119,105,115,101,115,111,109,101,32,102,111, 114,109,32,111,102,104,97,100,32,110,111,116,32,98,101,101,110,103,101,110,101, 114,97,116,101,100,32,98,121,105,110,102,111,114,109,97,116,105,111,110,46,112, 101,114,109,105,116,116,101,100,32,116,111,105,110,99,108,117,100,101,115,32,116 ,104,101,100,101,118,101,108,111,112,109,101,110,116,44,101,110,116,101,114,101, 100,32,105,110,116,111,116,104,101,32,112,114,101,118,105,111,117,115,99,111,110 ,115,105,115,116,101,110,116,108,121,97,114,101,32,107,110,111,119,110,32,97,115 ,116,104,101,32,102,105,101,108,100,32,111,102,116,104,105,115,32,116,121,112, 101,32,111,102,103,105,118,101,110,32,116,111,32,116,104,101,116,104,101,32,116, 105,116,108,101,32,111,102,99,111,110,116,97,105,110,115,32,116,104,101,105,110, 115,116,97,110,99,101,115,32,111,102,105,110,32,116,104,101,32,110,111,114,116, 104,100,117,101,32,116,111,32,116,104,101,105,114,97,114,101,32,100,101,115,105, 103,110,101,100,99,111,114,112,111,114,97,116,105,111,110,115,119,97,115,32,116, 104,97,116,32,116,104,101,111,110,101,32,111,102,32,116,104,101,115,101,109,111, 114,101,32,112,111,112,117,108,97,114,115,117,99,99,101,101,100,101,100,32,105, 110,115,117,112,112,111,114,116,32,102,114,111,109,105,110,32,100,105,102,102, 101,114,101,110,116,100,111,109,105,110,97,116,101,100,32,98,121,100,101,115,105 ,103,110,101,100,32,102,111,114,111,119,110,101,114,115,104,105,112,32,111,102, 97,110,100,32,112,111,115,115,105,98,108,121,115,116,97,110,100,97,114,100,105, 122,101,100,114,101,115,112,111,110,115,101,84,101,120,116,119,97,115,32,105,110 ,116,101,110,100,101,100,114,101,99,101,105,118,101,100,32,116,104,101,97,115, 115,117,109,101,100,32,116,104,97,116,97,114,101,97,115,32,111,102,32,116,104, 101,112,114,105,109,97,114,105,108,121,32,105,110,116,104,101,32,98,97,115,105, 115,32,111,102,105,110,32,116,104,101,32,115,101,110,115,101,97,99,99,111,117, 110,116,115,32,102,111,114,100,101,115,116,114,111,121,101,100,32,98,121,97,116, 32,108,101,97,115,116,32,116,119,111,119,97,115,32,100,101,99,108,97,114,101,100 ,99,111,117,108,100,32,110,111,116,32,98,101,83,101,99,114,101,116,97,114,121,32 ,111,102,97,112,112,101,97,114,32,116,111,32,98,101,109,97,114,103,105,110,45, 116,111,112,58,49,47,94,92,115,43,124,92,115,43,36,47,103,101,41,123,116,104,114 ,111,119,32,101,125,59,116,104,101,32,115,116,97,114,116,32,111,102,116,119,111, 32,115,101,112,97,114,97,116,101,108,97,110,103,117,97,103,101,32,97,110,100,119 ,104,111,32,104,97,100,32,98,101,101,110,111,112,101,114,97,116,105,111,110,32, 111,102,100,101,97,116,104,32,111,102,32,116,104,101,114,101,97,108,32,110,117, 109,98,101,114,115,9,60,108,105,110,107,32,114,101,108,61,34,112,114,111,118,105 ,100,101,100,32,116,104,101,116,104,101,32,115,116,111,114,121,32,111,102,99,111 ,109,112,101,116,105,116,105,111,110,115,101,110,103,108,105,115,104,32,40,85,75 ,41,101,110,103,108,105,115,104,32,40,85,83,41,208,156,208,190,208,189,208,179, 208,190,208,187,208,161,209,128,208,191,209,129,208,186,208,184,209,129,209,128, 208,191,209,129,208,186,208,184,209,129,209,128,208,191,209,129,208,186,208,190, 217,132,216,185,216,177,216,168,217,138,216,169,230,173,163,233,171,148,228,184, 173,230,150,135,231,174,128,228,189,147,228,184,173,230,150,135,231,185,129,228, 189,147,228,184,173,230,150,135,230,156,137,233,153,144,229,133,172,229,143,184, 228,186,186,230,176,145,230,148,191,229,186,156,233,152,191,233,135,140,229,183, 180,229,183,180,231,164,190,228,188,154,228,184,187,228,185,137,230,147,141,228, 189,156,231,179,187,231,187,159,230,148,191,231,173,150,230,179,149,232,167,132, 105,110,102,111,114,109,97,99,105,195,179,110,104,101,114,114,97,109,105,101,110 ,116,97,115,101,108,101,99,116,114,195,179,110,105,99,111,100,101,115,99,114,105 ,112,99,105,195,179,110,99,108,97,115,105,102,105,99,97,100,111,115,99,111,110, 111,99,105,109,105,101,110,116,111,112,117,98,108,105,99,97,99,105,195,179,110, 114,101,108,97,99,105,111,110,97,100,97,115,105,110,102,111,114,109,195,161,116, 105,99,97,114,101,108,97,99,105,111,110,97,100,111,115,100,101,112,97,114,116,97 ,109,101,110,116,111,116,114,97,98,97,106,97,100,111,114,101,115,100,105,114,101 ,99,116,97,109,101,110,116,101,97,121,117,110,116,97,109,105,101,110,116,111,109 ,101,114,99,97,100,111,76,105,98,114,101,99,111,110,116,195,161,99,116,101,110, 111,115,104,97,98,105,116,97,99,105,111,110,101,115,99,117,109,112,108,105,109, 105,101,110,116,111,114,101,115,116,97,117,114,97,110,116,101,115,100,105,115, 112,111,115,105,99,105,195,179,110,99,111,110,115,101,99,117,101,110,99,105,97, 101,108,101,99,116,114,195,179,110,105,99,97,97,112,108,105,99,97,99,105,111,110 ,101,115,100,101,115,99,111,110,101,99,116,97,100,111,105,110,115,116,97,108,97, 99,105,195,179,110,114,101,97,108,105,122,97,99,105,195,179,110,117,116,105,108, 105,122,97,99,105,195,179,110,101,110,99,105,99,108,111,112,101,100,105,97,101, 110,102,101,114,109,101,100,97,100,101,115,105,110,115,116,114,117,109,101,110, 116,111,115,101,120,112,101,114,105,101,110,99,105,97,115,105,110,115,116,105, 116,117,99,105,195,179,110,112,97,114,116,105,99,117,108,97,114,101,115,115,117, 98,99,97,116,101,103,111,114,105,97,209,130,208,190,208,187,209,140,208,186,208, 190,208,160,208,190,209,129,209,129,208,184,208,184,209,128,208,176,208,177,208, 190,209,130,209,139,208,177,208,190,208,187,209,140,209,136,208,181,208,191,209, 128,208,190,209,129,209,130,208,190,208,188,208,190,208,182,208,181,209,130,208, 181,208,180,209,128,209,131,208,179,208,184,209,133,209,129,208,187,209,131,209, 135,208,176,208,181,209,129,208,181,208,185,209,135,208,176,209,129,208,178,209, 129,208,181,208,179,208,180,208,176,208,160,208,190,209,129,209,129,208,184,209, 143,208,156,208,190,209,129,208,186,208,178,208,181,208,180,209,128,209,131,208, 179,208,184,208,181,208,179,208,190,209,128,208,190,208,180,208,176,208,178,208, 190,208,191,209,128,208,190,209,129,208,180,208,176,208,189,208,189,209,139,209, 133,208,180,208,190,208,187,208,182,208,189,209,139,208,184,208,188,208,181,208, 189,208,189,208,190,208,156,208,190,209,129,208,186,208,178,209,139,209,128,209, 131,208,177,208,187,208,181,208,185,208,156,208,190,209,129,208,186,208,178,208, 176,209,129,209,130,209,128,208,176,208,189,209,139,208,189,208,184,209,135,208, 181,208,179,208,190,209,128,208,176,208,177,208,190,209,130,208,181,208,180,208, 190,208,187,208,182,208,181,208,189,209,131,209,129,208,187,209,131,208,179,208, 184,209,130,208,181,208,191,208,181,209,128,209,140,208,158,208,180,208,189,208, 176,208,186,208,190,208,191,208,190,209,130,208,190,208,188,209,131,209,128,208, 176,208,177,208,190,209,130,209,131,208,176,208,191,209,128,208,181,208,187,209, 143,208,178,208,190,208,190,208,177,209,137,208,181,208,190,208,180,208,189,208, 190,208,179,208,190,209,129,208,178,208,190,208,181,208,179,208,190,209,129,209, 130,208,176,209,130,209,140,208,184,208,180,209,128,209,131,208,179,208,190,208, 185,209,132,208,190,209,128,209,131,208,188,208,181,209,133,208,190,209,128,208, 190,209,136,208,190,208,191,209,128,208,190,209,130,208,184,208,178,209,129,209, 129,209,139,208,187,208,186,208,176,208,186,208,176,208,182,208,180,209,139,208, 185,208,178,208,187,208,176,209,129,209,130,208,184,208,179,209,128,209,131,208, 191,208,191,209,139,208,178,208,188,208,181,209,129,209,130,208,181,209,128,208, 176,208,177,208,190,209,130,208,176,209,129,208,186,208,176,208,183,208,176,208, 187,208,191,208,181,209,128,208,178,209,139,208,185,208,180,208,181,208,187,208, 176,209,130,209,140,208,180,208,181,208,189,209,140,208,179,208,184,208,191,208, 181,209,128,208,184,208,190,208,180,208,177,208,184,208,183,208,189,208,181,209, 129,208,190,209,129,208,189,208,190,208,178,208,181,208,188,208,190,208,188,208, 181,208,189,209,130,208,186,209,131,208,191,208,184,209,130,209,140,208,180,208, 190,208,187,208,182,208,189,208,176,209,128,208,176,208,188,208,186,208,176,209, 133,208,189,208,176,209,135,208,176,208,187,208,190,208,160,208,176,208,177,208, 190,209,130,208,176,208,162,208,190,208,187,209,140,208,186,208,190,209,129,208, 190,208,178,209,129,208,181,208,188,208,178,209,130,208,190,209,128,208,190,208, 185,208,189,208,176,209,135,208,176,208,187,208,176,209,129,208,191,208,184,209, 129,208,190,208,186,209,129,208,187,209,131,208,182,208,177,209,139,209,129,208, 184,209,129,209,130,208,181,208,188,208,191,208,181,209,135,208,176,209,130,208, 184,208,189,208,190,208,178,208,190,208,179,208,190,208,191,208,190,208,188,208, 190,209,137,208,184,209,129,208,176,208,185,209,130,208,190,208,178,208,191,208, 190,209,135,208,181,208,188,209,131,208,191,208,190,208,188,208,190,209,137,209, 140,208,180,208,190,208,187,208,182,208,189,208,190,209,129,209,129,209,139,208, 187,208,186,208,184,208,177,209,139,209,129,209,130,209,128,208,190,208,180,208, 176,208,189,208,189,209,139,208,181,208,188,208,189,208,190,208,179,208,184,208, 181,208,191,209,128,208,190,208,181,208,186,209,130,208,161,208,181,208,185,209, 135,208,176,209,129,208,188,208,190,208,180,208,181,208,187,208,184,209,130,208, 176,208,186,208,190,208,179,208,190,208,190,208,189,208,187,208,176,208,185,208, 189,208,179,208,190,209,128,208,190,208,180,208,181,208,178,208,181,209,128,209, 129,208,184,209,143,209,129,209,130,209,128,208,176,208,189,208,181,209,132,208, 184,208,187,209,140,208,188,209,139,209,131,209,128,208,190,208,178,208,189,209, 143,209,128,208,176,208,183,208,189,209,139,209,133,208,184,209,129,208,186,208, 176,209,130,209,140,208,189,208,181,208,180,208,181,208,187,209,142,209,143,208, 189,208,178,208,176,209,128,209,143,208,188,208,181,208,189,209,140,209,136,208, 181,208,188,208,189,208,190,208,179,208,184,209,133,208,180,208,176,208,189,208, 189,208,190,208,185,208,183,208,189,208,176,209,135,208,184,209,130,208,189,208, 181,208,187,209,140,208,183,209,143,209,132,208,190,209,128,209,131,208,188,208, 176,208,162,208,181,208,191,208,181,209,128,209,140,208,188,208,181,209,129,209, 143,209,134,208,176,208,183,208,176,209,137,208,184,209,130,209,139,208,155,209, 131,209,135,209,136,208,184,208,181,224,164,168,224,164,185,224,165,128,224,164, 130,224,164,149,224,164,176,224,164,168,224,165,135,224,164,133,224,164,170,224, 164,168,224,165,135,224,164,149,224,164,191,224,164,175,224,164,190,224,164,149, 224,164,176,224,165,135,224,164,130,224,164,133,224,164,168,224,165,141,224,164, 175,224,164,149,224,165,141,224,164,175,224,164,190,224,164,151,224,164,190,224, 164,135,224,164,161,224,164,172,224,164,190,224,164,176,224,165,135,224,164,149, 224,164,191,224,164,184,224,165,128,224,164,166,224,164,191,224,164,175,224,164, 190,224,164,170,224,164,185,224,164,178,224,165,135,224,164,184,224,164,191,224, 164,130,224,164,185,224,164,173,224,164,190,224,164,176,224,164,164,224,164,133, 224,164,170,224,164,168,224,165,128,224,164,181,224,164,190,224,164,178,224,165, 135,224,164,184,224,165,135,224,164,181,224,164,190,224,164,149,224,164,176,224, 164,164,224,165,135,224,164,174,224,165,135,224,164,176,224,165,135,224,164,185, 224,165,139,224,164,168,224,165,135,224,164,184,224,164,149,224,164,164,224,165, 135,224,164,172,224,164,185,224,165,129,224,164,164,224,164,184,224,164,190,224, 164,135,224,164,159,224,164,185,224,165,139,224,164,151,224,164,190,224,164,156, 224,164,190,224,164,168,224,165,135,224,164,174,224,164,191,224,164,168,224,164, 159,224,164,149,224,164,176,224,164,164,224,164,190,224,164,149,224,164,176,224, 164,168,224,164,190,224,164,137,224,164,168,224,164,149,224,165,135,224,164,175, 224,164,185,224,164,190,224,164,129,224,164,184,224,164,172,224,164,184,224,165, 135,224,164,173,224,164,190,224,164,183,224,164,190,224,164,134,224,164,170,224, 164,149,224,165,135,224,164,178,224,164,191,224,164,175,224,165,135,224,164,182, 224,165,129,224,164,176,224,165,130,224,164,135,224,164,184,224,164,149,224,165, 135,224,164,152,224,164,130,224,164,159,224,165,135,224,164,174,224,165,135,224, 164,176,224,165,128,224,164,184,224,164,149,224,164,164,224,164,190,224,164,174, 224,165,135,224,164,176,224,164,190,224,164,178,224,165,135,224,164,149,224,164, 176,224,164,133,224,164,167,224,164,191,224,164,149,224,164,133,224,164,170,224, 164,168,224,164,190,224,164,184,224,164,174,224,164,190,224,164,156,224,164,174, 224,165,129,224,164,157,224,165,135,224,164,149,224,164,190,224,164,176,224,164, 163,224,164,185,224,165,139,224,164,164,224,164,190,224,164,149,224,164,161,224, 164,188,224,165,128,224,164,175,224,164,185,224,164,190,224,164,130,224,164,185, 224,165,139,224,164,159,224,164,178,224,164,182,224,164,172,224,165,141,224,164, 166,224,164,178,224,164,191,224,164,175,224,164,190,224,164,156,224,165,128,224, 164,181,224,164,168,224,164,156,224,164,190,224,164,164,224,164,190,224,164,149, 224,165,136,224,164,184,224,165,135,224,164,134,224,164,170,224,164,149,224,164, 190,224,164,181,224,164,190,224,164,178,224,165,128,224,164,166,224,165,135,224, 164,168,224,165,135,224,164,170,224,165,130,224,164,176,224,165,128,224,164,170, 224,164,190,224,164,168,224,165,128,224,164,137,224,164,184,224,164,149,224,165, 135,224,164,185,224,165,139,224,164,151,224,165,128,224,164,172,224,165,136,224, 164,160,224,164,149,224,164,134,224,164,170,224,164,149,224,165,128,224,164,181, 224,164,176,224,165,141,224,164,183,224,164,151,224,164,190,224,164,130,224,164, 181,224,164,134,224,164,170,224,164,149,224,165,139,224,164,156,224,164,191,224, 164,178,224,164,190,224,164,156,224,164,190,224,164,168,224,164,190,224,164,184, 224,164,185,224,164,174,224,164,164,224,164,185,224,164,174,224,165,135,224,164, 130,224,164,137,224,164,168,224,164,149,224,165,128,224,164,175,224,164,190,224, 164,185,224,165,130,224,164,166,224,164,176,224,165,141,224,164,156,224,164,184, 224,165,130,224,164,154,224,165,128,224,164,170,224,164,184,224,164,130,224,164, 166,224,164,184,224,164,181,224,164,190,224,164,178,224,164,185,224,165,139,224, 164,168,224,164,190,224,164,185,224,165,139,224,164,164,224,165,128,224,164,156, 224,165,136,224,164,184,224,165,135,224,164,181,224,164,190,224,164,170,224,164, 184,224,164,156,224,164,168,224,164,164,224,164,190,224,164,168,224,165,135,224, 164,164,224,164,190,224,164,156,224,164,190,224,164,176,224,165,128,224,164,152, 224,164,190,224,164,175,224,164,178,224,164,156,224,164,191,224,164,178,224,165, 135,224,164,168,224,165,128,224,164,154,224,165,135,224,164,156,224,164,190,224, 164,130,224,164,154,224,164,170,224,164,164,224,165,141,224,164,176,224,164,151, 224,165,130,224,164,151,224,164,178,224,164,156,224,164,190,224,164,164,224,165, 135,224,164,172,224,164,190,224,164,185,224,164,176,224,164,134,224,164,170,224, 164,168,224,165,135,224,164,181,224,164,190,224,164,185,224,164,168,224,164,135, 224,164,184,224,164,149,224,164,190,224,164,184,224,165,129,224,164,172,224,164, 185,224,164,176,224,164,185,224,164,168,224,165,135,224,164,135,224,164,184,224, 164,184,224,165,135,224,164,184,224,164,185,224,164,191,224,164,164,224,164,172, 224,164,161,224,164,188,224,165,135,224,164,152,224,164,159,224,164,168,224,164, 190,224,164,164,224,164,178,224,164,190,224,164,182,224,164,170,224,164,190,224, 164,130,224,164,154,224,164,182,224,165,141,224,164,176,224,165,128,224,164,172, 224,164,161,224,164,188,224,165,128,224,164,185,224,165,139,224,164,164,224,165, 135,224,164,184,224,164,190,224,164,136,224,164,159,224,164,182,224,164,190,224, 164,175,224,164,166,224,164,184,224,164,149,224,164,164,224,165,128,224,164,156, 224,164,190,224,164,164,224,165,128,224,164,181,224,164,190,224,164,178,224,164, 190,224,164,185,224,164,156,224,164,190,224,164,176,224,164,170,224,164,159,224, 164,168,224,164,190,224,164,176,224,164,150,224,164,168,224,165,135,224,164,184, 224,164,161,224,164,188,224,164,149,224,164,174,224,164,191,224,164,178,224,164, 190,224,164,137,224,164,184,224,164,149,224,165,128,224,164,149,224,165,135,224, 164,181,224,164,178,224,164,178,224,164,151,224,164,164,224,164,190,224,164,150, 224,164,190,224,164,168,224,164,190,224,164,133,224,164,176,224,165,141,224,164, 165,224,164,156,224,164,185,224,164,190,224,164,130,224,164,166,224,165,135,224, 164,150,224,164,190,224,164,170,224,164,185,224,164,178,224,165,128,224,164,168, 224,164,191,224,164,175,224,164,174,224,164,172,224,164,191,224,164,168,224,164, 190,224,164,172,224,165,136,224,164,130,224,164,149,224,164,149,224,164,185,224, 165,128,224,164,130,224,164,149,224,164,185,224,164,168,224,164,190,224,164,166, 224,165,135,224,164,164,224,164,190,224,164,185,224,164,174,224,164,178,224,165, 135,224,164,149,224,164,190,224,164,171,224,165,128,224,164,156,224,164,172,224, 164,149,224,164,191,224,164,164,224,165,129,224,164,176,224,164,164,224,164,174, 224,164,190,224,164,130,224,164,151,224,164,181,224,164,185,224,165,128,224,164, 130,224,164,176,224,165,139,224,164,156,224,164,188,224,164,174,224,164,191,224, 164,178,224,165,128,224,164,134,224,164,176,224,165,139,224,164,170,224,164,184, 224,165,135,224,164,168,224,164,190,224,164,175,224,164,190,224,164,166,224,164, 181,224,164,178,224,165,135,224,164,168,224,165,135,224,164,150,224,164,190,224, 164,164,224,164,190,224,164,149,224,164,176,224,165,128,224,164,172,224,164,137, 224,164,168,224,164,149,224,164,190,224,164,156,224,164,181,224,164,190,224,164, 172,224,164,170,224,165,130,224,164,176,224,164,190,224,164,172,224,164,161,224, 164,188,224,164,190,224,164,184,224,165,140,224,164,166,224,164,190,224,164,182, 224,165,135,224,164,175,224,164,176,224,164,149,224,164,191,224,164,175,224,165, 135,224,164,149,224,164,185,224,164,190,224,164,130,224,164,133,224,164,149,224, 164,184,224,164,176,224,164,172,224,164,168,224,164,190,224,164,143,224,164,181, 224,164,185,224,164,190,224,164,130,224,164,184,224,165,141,224,164,165,224,164, 178,224,164,174,224,164,191,224,164,178,224,165,135,224,164,178,224,165,135,224, 164,150,224,164,149,224,164,181,224,164,191,224,164,183,224,164,175,224,164,149, 224,165,141,224,164,176,224,164,130,224,164,184,224,164,174,224,165,130,224,164, 185,224,164,165,224,164,190,224,164,168,224,164,190,216,170,216,179,216,170,216, 183,217,138,216,185,217,133,216,180,216,167,216,177,217,131,216,169,216,168,217, 136,216,167,216,179,216,183,216,169,216,167,217,132,216,181,217,129,216,173,216, 169,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,174,216, 167,216,181,216,169,216,167,217,132,217,133,216,178,217,138,216,175,216,167,217, 132,216,185,216,167,217,133,216,169,216,167,217,132,217,131,216,167,216,170,216, 168,216,167,217,132,216,177,216,175,217,136,216,175,216,168,216,177,217,134,216, 167,217,133,216,172,216,167,217,132,216,175,217,136,217,132,216,169,216,167,217, 132,216,185,216,167,217,132,217,133,216,167,217,132,217,133,217,136,217,130,216, 185,216,167,217,132,216,185,216,177,216,168,217,138,216,167,217,132,216,179,216, 177,217,138,216,185,216,167,217,132,216,172,217,136,216,167,217,132,216,167,217, 132,216,176,217,135,216,167,216,168,216,167,217,132,216,173,217,138,216,167,216, 169,216,167,217,132,216,173,217,130,217,136,217,130,216,167,217,132,217,131,216, 177,217,138,217,133,216,167,217,132,216,185,216,177,216,167,217,130,217,133,216, 173,217,129,217,136,216,184,216,169,216,167,217,132,216,171,216,167,217,134,217, 138,217,133,216,180,216,167,217,135,216,175,216,169,216,167,217,132,217,133,216, 177,216,163,216,169,216,167,217,132,217,130,216,177,216,162,217,134,216,167,217, 132,216,180,216,168,216,167,216,168,216,167,217,132,216,173,217,136,216,167,216, 177,216,167,217,132,216,172,216,175,217,138,216,175,216,167,217,132,216,163,216, 179,216,177,216,169,216,167,217,132,216,185,217,132,217,136,217,133,217,133,216, 172,217,133,217,136,216,185,216,169,216,167,217,132,216,177,216,173,217,133,217, 134,216,167,217,132,217,134,217,130,216,167,216,183,217,129,217,132,216,179,216, 183,217,138,217,134,216,167,217,132,217,131,217,136,217,138,216,170,216,167,217, 132,216,175,217,134,217,138,216,167,216,168,216,177,217,131,216,167,216,170,217, 135,216,167,217,132,216,177,217,138,216,167,216,182,216,170,216,173,217,138,216, 167,216,170,217,138,216,168,216,170,217,136,217,130,217,138,216,170,216,167,217, 132,216,163,217,136,217,132,217,137,216,167,217,132,216,168,216,177,217,138,216, 175,216,167,217,132,217,131,217,132,216,167,217,133,216,167,217,132,216,177,216, 167,216,168,216,183,216,167,217,132,216,180,216,174,216,181,217,138,216,179,217, 138,216,167,216,177,216,167,216,170,216,167,217,132,216,171,216,167,217,132,216, 171,216,167,217,132,216,181,217,132,216,167,216,169,216,167,217,132,216,173,216, 175,217,138,216,171,216,167,217,132,216,178,217,136,216,167,216,177,216,167,217, 132,216,174,217,132,217,138,216,172,216,167,217,132,216,172,217,133,217,138,216, 185,216,167,217,132,216,185,216,167,217,133,217,135,216,167,217,132,216,172,217, 133,216,167,217,132,216,167,217,132,216,179,216,167,216,185,216,169,217,133,216, 180,216,167,217,135,216,175,217,135,216,167,217,132,216,177,216,166,217,138,216, 179,216,167,217,132,216,175,216,174,217,136,217,132,216,167,217,132,217,129,217, 134,217,138,216,169,216,167,217,132,217,131,216,170,216,167,216,168,216,167,217, 132,216,175,217,136,216,177,217,138,216,167,217,132,216,175,216,177,217,136,216, 179,216,167,216,179,216,170,216,186,216,177,217,130,216,170,216,181,216,167,217, 133,217,138,217,133,216,167,217,132,216,168,217,134,216,167,216,170,216,167,217, 132,216,185,216,184,217,138,217,133,101,110,116,101,114,116,97,105,110,109,101, 110,116,117,110,100,101,114,115,116,97,110,100,105,110,103,32,61,32,102,117,110, 99,116,105,111,110,40,41,46,106,112,103,34,32,119,105,100,116,104,61,34,99,111, 110,102,105,103,117,114,97,116,105,111,110,46,112,110,103,34,32,119,105,100,116, 104,61,34,60,98,111,100,121,32,99,108,97,115,115,61,34,77,97,116,104,46,114,97, 110,100,111,109,40,41,99,111,110,116,101,109,112,111,114,97,114,121,32,85,110, 105,116,101,100,32,83,116,97,116,101,115,99,105,114,99,117,109,115,116,97,110,99 ,101,115,46,97,112,112,101,110,100,67,104,105,108,100,40,111,114,103,97,110,105, 122,97,116,105,111,110,115,60,115,112,97,110,32,99,108,97,115,115,61,34,34,62,60 ,105,109,103,32,115,114,99,61,34,47,100,105,115,116,105,110,103,117,105,115,104, 101,100,116,104,111,117,115,97,110,100,115,32,111,102,32,99,111,109,109,117,110, 105,99,97,116,105,111,110,99,108,101,97,114,34,62,60,47,100,105,118,62,105,110, 118,101,115,116,105,103,97,116,105,111,110,102,97,118,105,99,111,110,46,105,99, 111,34,32,109,97,114,103,105,110,45,114,105,103,104,116,58,98,97,115,101,100,32, 111,110,32,116,104,101,32,77,97,115,115,97,99,104,117,115,101,116,116,115,116,97 ,98,108,101,32,98,111,114,100,101,114,61,105,110,116,101,114,110,97,116,105,111, 110,97,108,97,108,115,111,32,107,110,111,119,110,32,97,115,112,114,111,110,117, 110,99,105,97,116,105,111,110,98,97,99,107,103,114,111,117,110,100,58,35,102,112 ,97,100,100,105,110,103,45,108,101,102,116,58,70,111,114,32,101,120,97,109,112, 108,101,44,32,109,105,115,99,101,108,108,97,110,101,111,117,115,38,108,116,59,47 ,109,97,116,104,38,103,116,59,112,115,121,99,104,111,108,111,103,105,99,97,108, 105,110,32,112,97,114,116,105,99,117,108,97,114,101,97,114,99,104,34,32,116,121, 112,101,61,34,102,111,114,109,32,109,101,116,104,111,100,61,34,97,115,32,111,112 ,112,111,115,101,100,32,116,111,83,117,112,114,101,109,101,32,67,111,117,114,116 ,111,99,99,97,115,105,111,110,97,108,108,121,32,65,100,100,105,116,105,111,110, 97,108,108,121,44,78,111,114,116,104,32,65,109,101,114,105,99,97,112,120,59,98, 97,99,107,103,114,111,117,110,100,111,112,112,111,114,116,117,110,105,116,105, 101,115,69,110,116,101,114,116,97,105,110,109,101,110,116,46,116,111,76,111,119, 101,114,67,97,115,101,40,109,97,110,117,102,97,99,116,117,114,105,110,103,112, 114,111,102,101,115,115,105,111,110,97,108,32,99,111,109,98,105,110,101,100,32, 119,105,116,104,70,111,114,32,105,110,115,116,97,110,99,101,44,99,111,110,115, 105,115,116,105,110,103,32,111,102,34,32,109,97,120,108,101,110,103,116,104,61, 34,114,101,116,117,114,110,32,102,97,108,115,101,59,99,111,110,115,99,105,111, 117,115,110,101,115,115,77,101,100,105,116,101,114,114,97,110,101,97,110,101,120 ,116,114,97,111,114,100,105,110,97,114,121,97,115,115,97,115,115,105,110,97,116, 105,111,110,115,117,98,115,101,113,117,101,110,116,108,121,32,98,117,116,116,111 ,110,32,116,121,112,101,61,34,116,104,101,32,110,117,109,98,101,114,32,111,102, 116,104,101,32,111,114,105,103,105,110,97,108,32,99,111,109,112,114,101,104,101, 110,115,105,118,101,114,101,102,101,114,115,32,116,111,32,116,104,101,60,47,117, 108,62,10,60,47,100,105,118,62,10,112,104,105,108,111,115,111,112,104,105,99,97, 108,108,111,99,97,116,105,111,110,46,104,114,101,102,119,97,115,32,112,117,98, 108,105,115,104,101,100,83,97,110,32,70,114,97,110,99,105,115,99,111,40,102,117, 110,99,116,105,111,110,40,41,123,10,60,100,105,118,32,105,100,61,34,109,97,105, 110,115,111,112,104,105,115,116,105,99,97,116,101,100,109,97,116,104,101,109,97, 116,105,99,97,108,32,47,104,101,97,100,62,13,10,60,98,111,100,121,115,117,103, 103,101,115,116,115,32,116,104,97,116,100,111,99,117,109,101,110,116,97,116,105, 111,110,99,111,110,99,101,110,116,114,97,116,105,111,110,114,101,108,97,116,105, 111,110,115,104,105,112,115,109,97,121,32,104,97,118,101,32,98,101,101,110,40, 102,111,114,32,101,120,97,109,112,108,101,44,84,104,105,115,32,97,114,116,105,99 ,108,101,32,105,110,32,115,111,109,101,32,99,97,115,101,115,112,97,114,116,115, 32,111,102,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102, 71,114,101,97,116,32,66,114,105,116,97,105,110,32,99,101,108,108,112,97,100,100, 105,110,103,61,101,113,117,105,118,97,108,101,110,116,32,116,111,112,108,97,99, 101,104,111,108,100,101,114,61,34,59,32,102,111,110,116,45,115,105,122,101,58,32 ,106,117,115,116,105,102,105,99,97,116,105,111,110,98,101,108,105,101,118,101, 100,32,116,104,97,116,115,117,102,102,101,114,101,100,32,102,114,111,109,97,116, 116,101,109,112,116,101,100,32,116,111,32,108,101,97,100,101,114,32,111,102,32, 116,104,101,99,114,105,112,116,34,32,115,114,99,61,34,47,40,102,117,110,99,116, 105,111,110,40,41,32,123,97,114,101,32,97,118,97,105,108,97,98,108,101,10,9,60, 108,105,110,107,32,114,101,108,61,34,32,115,114,99,61,39,104,116,116,112,58,47, 47,105,110,116,101,114,101,115,116,101,100,32,105,110,99,111,110,118,101,110,116 ,105,111,110,97,108,32,34,32,97,108,116,61,34,34,32,47,62,60,47,97,114,101,32, 103,101,110,101,114,97,108,108,121,104,97,115,32,97,108,115,111,32,98,101,101, 110,109,111,115,116,32,112,111,112,117,108,97,114,32,99,111,114,114,101,115,112, 111,110,100,105,110,103,99,114,101,100,105,116,101,100,32,119,105,116,104,116, 121,108,101,61,34,98,111,114,100,101,114,58,60,47,97,62,60,47,115,112,97,110,62, 60,47,46,103,105,102,34,32,119,105,100,116,104,61,34,60,105,102,114,97,109,101, 32,115,114,99,61,34,116,97,98,108,101,32,99,108,97,115,115,61,34,105,110,108,105 ,110,101,45,98,108,111,99,107,59,97,99,99,111,114,100,105,110,103,32,116,111,32, 116,111,103,101,116,104,101,114,32,119,105,116,104,97,112,112,114,111,120,105, 109,97,116,101,108,121,112,97,114,108,105,97,109,101,110,116,97,114,121,109,111, 114,101,32,97,110,100,32,109,111,114,101,100,105,115,112,108,97,121,58,110,111, 110,101,59,116,114,97,100,105,116,105,111,110,97,108,108,121,112,114,101,100,111 ,109,105,110,97,110,116,108,121,38,110,98,115,112,59,124,38,110,98,115,112,59,38 ,110,98,115,112,59,60,47,115,112,97,110,62,32,99,101,108,108,115,112,97,99,105, 110,103,61,60,105,110,112,117,116,32,110,97,109,101,61,34,111,114,34,32,99,111, 110,116,101,110,116,61,34,99,111,110,116,114,111,118,101,114,115,105,97,108,112, 114,111,112,101,114,116,121,61,34,111,103,58,47,120,45,115,104,111,99,107,119,97 ,118,101,45,100,101,109,111,110,115,116,114,97,116,105,111,110,115,117,114,114, 111,117,110,100,101,100,32,98,121,78,101,118,101,114,116,104,101,108,101,115,115 ,44,119,97,115,32,116,104,101,32,102,105,114,115,116,99,111,110,115,105,100,101, 114,97,98,108,101,32,65,108,116,104,111,117,103,104,32,116,104,101,32,99,111,108 ,108,97,98,111,114,97,116,105,111,110,115,104,111,117,108,100,32,110,111,116,32, 98,101,112,114,111,112,111,114,116,105,111,110,32,111,102,60,115,112,97,110,32, 115,116,121,108,101,61,34,107,110,111,119,110,32,97,115,32,116,104,101,32,115, 104,111,114,116,108,121,32,97,102,116,101,114,102,111,114,32,105,110,115,116,97, 110,99,101,44,100,101,115,99,114,105,98,101,100,32,97,115,32,47,104,101,97,100, 62,10,60,98,111,100,121,32,115,116,97,114,116,105,110,103,32,119,105,116,104,105 ,110,99,114,101,97,115,105,110,103,108,121,32,116,104,101,32,102,97,99,116,32, 116,104,97,116,100,105,115,99,117,115,115,105,111,110,32,111,102,109,105,100,100 ,108,101,32,111,102,32,116,104,101,97,110,32,105,110,100,105,118,105,100,117,97, 108,100,105,102,102,105,99,117,108,116,32,116,111,32,112,111,105,110,116,32,111, 102,32,118,105,101,119,104,111,109,111,115,101,120,117,97,108,105,116,121,97,99, 99,101,112,116,97,110,99,101,32,111,102,60,47,115,112,97,110,62,60,47,100,105, 118,62,109,97,110,117,102,97,99,116,117,114,101,114,115,111,114,105,103,105,110, 32,111,102,32,116,104,101,99,111,109,109,111,110,108,121,32,117,115,101,100,105, 109,112,111,114,116,97,110,99,101,32,111,102,100,101,110,111,109,105,110,97,116, 105,111,110,115,98,97,99,107,103,114,111,117,110,100,58,32,35,108,101,110,103, 116,104,32,111,102,32,116,104,101,100,101,116,101,114,109,105,110,97,116,105,111 ,110,97,32,115,105,103,110,105,102,105,99,97,110,116,34,32,98,111,114,100,101, 114,61,34,48,34,62,114,101,118,111,108,117,116,105,111,110,97,114,121,112,114, 105,110,99,105,112,108,101,115,32,111,102,105,115,32,99,111,110,115,105,100,101, 114,101,100,119,97,115,32,100,101,118,101,108,111,112,101,100,73,110,100,111,45, 69,117,114,111,112,101,97,110,118,117,108,110,101,114,97,98,108,101,32,116,111, 112,114,111,112,111,110,101,110,116,115,32,111,102,97,114,101,32,115,111,109,101 ,116,105,109,101,115,99,108,111,115,101,114,32,116,111,32,116,104,101,78,101,119 ,32,89,111,114,107,32,67,105,116,121,32,110,97,109,101,61,34,115,101,97,114,99, 104,97,116,116,114,105,98,117,116,101,100,32,116,111,99,111,117,114,115,101,32, 111,102,32,116,104,101,109,97,116,104,101,109,97,116,105,99,105,97,110,98,121,32 ,116,104,101,32,101,110,100,32,111,102,97,116,32,116,104,101,32,101,110,100,32, 111,102,34,32,98,111,114,100,101,114,61,34,48,34,32,116,101,99,104,110,111,108, 111,103,105,99,97,108,46,114,101,109,111,118,101,67,108,97,115,115,40,98,114,97, 110,99,104,32,111,102,32,116,104,101,101,118,105,100,101,110,99,101,32,116,104, 97,116,33,91,101,110,100,105,102,93,45,45,62,13,10,73,110,115,116,105,116,117, 116,101,32,111,102,32,105,110,116,111,32,97,32,115,105,110,103,108,101,114,101, 115,112,101,99,116,105,118,101,108,121,46,97,110,100,32,116,104,101,114,101,102, 111,114,101,112,114,111,112,101,114,116,105,101,115,32,111,102,105,115,32,108, 111,99,97,116,101,100,32,105,110,115,111,109,101,32,111,102,32,119,104,105,99, 104,84,104,101,114,101,32,105,115,32,97,108,115,111,99,111,110,116,105,110,117, 101,100,32,116,111,32,97,112,112,101,97,114,97,110,99,101,32,111,102,32,38,97, 109,112,59,110,100,97,115,104,59,32,100,101,115,99,114,105,98,101,115,32,116,104 ,101,99,111,110,115,105,100,101,114,97,116,105,111,110,97,117,116,104,111,114,32 ,111,102,32,116,104,101,105,110,100,101,112,101,110,100,101,110,116,108,121,101, 113,117,105,112,112,101,100,32,119,105,116,104,100,111,101,115,32,110,111,116,32 ,104,97,118,101,60,47,97,62,60,97,32,104,114,101,102,61,34,99,111,110,102,117, 115,101,100,32,119,105,116,104,60,108,105,110,107,32,104,114,101,102,61,34,47,97 ,116,32,116,104,101,32,97,103,101,32,111,102,97,112,112,101,97,114,32,105,110,32 ,116,104,101,84,104,101,115,101,32,105,110,99,108,117,100,101,114,101,103,97,114 ,100,108,101,115,115,32,111,102,99,111,117,108,100,32,98,101,32,117,115,101,100, 32,115,116,121,108,101,61,38,113,117,111,116,59,115,101,118,101,114,97,108,32, 116,105,109,101,115,114,101,112,114,101,115,101,110,116,32,116,104,101,98,111, 100,121,62,10,60,47,104,116,109,108,62,116,104,111,117,103,104,116,32,116,111,32 ,98,101,112,111,112,117,108,97,116,105,111,110,32,111,102,112,111,115,115,105,98 ,105,108,105,116,105,101,115,112,101,114,99,101,110,116,97,103,101,32,111,102,97 ,99,99,101,115,115,32,116,111,32,116,104,101,97,110,32,97,116,116,101,109,112, 116,32,116,111,112,114,111,100,117,99,116,105,111,110,32,111,102,106,113,117,101 ,114,121,47,106,113,117,101,114,121,116,119,111,32,100,105,102,102,101,114,101, 110,116,98,101,108,111,110,103,32,116,111,32,116,104,101,101,115,116,97,98,108, 105,115,104,109,101,110,116,114,101,112,108,97,99,105,110,103,32,116,104,101,100 ,101,115,99,114,105,112,116,105,111,110,34,32,100,101,116,101,114,109,105,110, 101,32,116,104,101,97,118,97,105,108,97,98,108,101,32,102,111,114,65,99,99,111, 114,100,105,110,103,32,116,111,32,119,105,100,101,32,114,97,110,103,101,32,111, 102,9,60,100,105,118,32,99,108,97,115,115,61,34,109,111,114,101,32,99,111,109, 109,111,110,108,121,111,114,103,97,110,105,115,97,116,105,111,110,115,102,117, 110,99,116,105,111,110,97,108,105,116,121,119,97,115,32,99,111,109,112,108,101, 116,101,100,32,38,97,109,112,59,109,100,97,115,104,59,32,112,97,114,116,105,99, 105,112,97,116,105,111,110,116,104,101,32,99,104,97,114,97,99,116,101,114,97,110 ,32,97,100,100,105,116,105,111,110,97,108,97,112,112,101,97,114,115,32,116,111, 32,98,101,102,97,99,116,32,116,104,97,116,32,116,104,101,97,110,32,101,120,97, 109,112,108,101,32,111,102,115,105,103,110,105,102,105,99,97,110,116,108,121,111 ,110,109,111,117,115,101,111,118,101,114,61,34,98,101,99,97,117,115,101,32,116, 104,101,121,32,97,115,121,110,99,32,61,32,116,114,117,101,59,112,114,111,98,108, 101,109,115,32,119,105,116,104,115,101,101,109,115,32,116,111,32,104,97,118,101, 116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,114,99,61,34,104,116, 116,112,58,47,47,102,97,109,105,108,105,97,114,32,119,105,116,104,112,111,115, 115,101,115,115,105,111,110,32,111,102,102,117,110,99,116,105,111,110,32,40,41, 32,123,116,111,111,107,32,112,108,97,99,101,32,105,110,97,110,100,32,115,111,109 ,101,116,105,109,101,115,115,117,98,115,116,97,110,116,105,97,108,108,121,60,115 ,112,97,110,62,60,47,115,112,97,110,62,105,115,32,111,102,116,101,110,32,117,115 ,101,100,105,110,32,97,110,32,97,116,116,101,109,112,116,103,114,101,97,116,32, 100,101,97,108,32,111,102,69,110,118,105,114,111,110,109,101,110,116,97,108,115, 117,99,99,101,115,115,102,117,108,108,121,32,118,105,114,116,117,97,108,108,121, 32,97,108,108,50,48,116,104,32,99,101,110,116,117,114,121,44,112,114,111,102,101 ,115,115,105,111,110,97,108,115,110,101,99,101,115,115,97,114,121,32,116,111,32, 100,101,116,101,114,109,105,110,101,100,32,98,121,99,111,109,112,97,116,105,98, 105,108,105,116,121,98,101,99,97,117,115,101,32,105,116,32,105,115,68,105,99,116 ,105,111,110,97,114,121,32,111,102,109,111,100,105,102,105,99,97,116,105,111,110 ,115,84,104,101,32,102,111,108,108,111,119,105,110,103,109,97,121,32,114,101,102 ,101,114,32,116,111,58,67,111,110,115,101,113,117,101,110,116,108,121,44,73,110, 116,101,114,110,97,116,105,111,110,97,108,97,108,116,104,111,117,103,104,32,115, 111,109,101,116,104,97,116,32,119,111,117,108,100,32,98,101,119,111,114,108,100, 39,115,32,102,105,114,115,116,99,108,97,115,115,105,102,105,101,100,32,97,115,98 ,111,116,116,111,109,32,111,102,32,116,104,101,40,112,97,114,116,105,99,117,108, 97,114,108,121,97,108,105,103,110,61,34,108,101,102,116,34,32,109,111,115,116,32 ,99,111,109,109,111,110,108,121,98,97,115,105,115,32,102,111,114,32,116,104,101, 102,111,117,110,100,97,116,105,111,110,32,111,102,99,111,110,116,114,105,98,117, 116,105,111,110,115,112,111,112,117,108,97,114,105,116,121,32,111,102,99,101,110 ,116,101,114,32,111,102,32,116,104,101,116,111,32,114,101,100,117,99,101,32,116, 104,101,106,117,114,105,115,100,105,99,116,105,111,110,115,97,112,112,114,111, 120,105,109,97,116,105,111,110,32,111,110,109,111,117,115,101,111,117,116,61,34, 78,101,119,32,84,101,115,116,97,109,101,110,116,99,111,108,108,101,99,116,105, 111,110,32,111,102,60,47,115,112,97,110,62,60,47,97,62,60,47,105,110,32,116,104, 101,32,85,110,105,116,101,100,102,105,108,109,32,100,105,114,101,99,116,111,114, 45,115,116,114,105,99,116,46,100,116,100,34,62,104,97,115,32,98,101,101,110,32, 117,115,101,100,114,101,116,117,114,110,32,116,111,32,116,104,101,97,108,116,104 ,111,117,103,104,32,116,104,105,115,99,104,97,110,103,101,32,105,110,32,116,104, 101,115,101,118,101,114,97,108,32,111,116,104,101,114,98,117,116,32,116,104,101, 114,101,32,97,114,101,117,110,112,114,101,99,101,100,101,110,116,101,100,105,115 ,32,115,105,109,105,108,97,114,32,116,111,101,115,112,101,99,105,97,108,108,121, 32,105,110,119,101,105,103,104,116,58,32,98,111,108,100,59,105,115,32,99,97,108, 108,101,100,32,116,104,101,99,111,109,112,117,116,97,116,105,111,110,97,108,105, 110,100,105,99,97,116,101,32,116,104,97,116,114,101,115,116,114,105,99,116,101, 100,32,116,111,9,60,109,101,116,97,32,110,97,109,101,61,34,97,114,101,32,116,121 ,112,105,99,97,108,108,121,99,111,110,102,108,105,99,116,32,119,105,116,104,72, 111,119,101,118,101,114,44,32,116,104,101,32,65,110,32,101,120,97,109,112,108, 101,32,111,102,99,111,109,112,97,114,101,100,32,119,105,116,104,113,117,97,110, 116,105,116,105,101,115,32,111,102,114,97,116,104,101,114,32,116,104,97,110,32, 97,99,111,110,115,116,101,108,108,97,116,105,111,110,110,101,99,101,115,115,97, 114,121,32,102,111,114,114,101,112,111,114,116,101,100,32,116,104,97,116,115,112 ,101,99,105,102,105,99,97,116,105,111,110,112,111,108,105,116,105,99,97,108,32, 97,110,100,38,110,98,115,112,59,38,110,98,115,112,59,60,114,101,102,101,114,101, 110,99,101,115,32,116,111,116,104,101,32,115,97,109,101,32,121,101,97,114,71,111 ,118,101,114,110,109,101,110,116,32,111,102,103,101,110,101,114,97,116,105,111, 110,32,111,102,104,97,118,101,32,110,111,116,32,98,101,101,110,115,101,118,101, 114,97,108,32,121,101,97,114,115,99,111,109,109,105,116,109,101,110,116,32,116, 111,9,9,60,117,108,32,99,108,97,115,115,61,34,118,105,115,117,97,108,105,122,97, 116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,44,112,114,97,99,116 ,105,116,105,111,110,101,114,115,116,104,97,116,32,104,101,32,119,111,117,108, 100,97,110,100,32,99,111,110,116,105,110,117,101,100,111,99,99,117,112,97,116, 105,111,110,32,111,102,105,115,32,100,101,102,105,110,101,100,32,97,115,99,101, 110,116,114,101,32,111,102,32,116,104,101,116,104,101,32,97,109,111,117,110,116, 32,111,102,62,60,100,105,118,32,115,116,121,108,101,61,34,101,113,117,105,118,97 ,108,101,110,116,32,111,102,100,105,102,102,101,114,101,110,116,105,97,116,101, 98,114,111,117,103,104,116,32,97,98,111,117,116,109,97,114,103,105,110,45,108, 101,102,116,58,32,97,117,116,111,109,97,116,105,99,97,108,108,121,116,104,111, 117,103,104,116,32,111,102,32,97,115,83,111,109,101,32,111,102,32,116,104,101, 115,101,10,60,100,105,118,32,99,108,97,115,115,61,34,105,110,112,117,116,32,99, 108,97,115,115,61,34,114,101,112,108,97,99,101,100,32,119,105,116,104,105,115,32 ,111,110,101,32,111,102,32,116,104,101,101,100,117,99,97,116,105,111,110,32,97, 110,100,105,110,102,108,117,101,110,99,101,100,32,98,121,114,101,112,117,116,97, 116,105,111,110,32,97,115,10,60,109,101,116,97,32,110,97,109,101,61,34,97,99,99, 111,109,109,111,100,97,116,105,111,110,60,47,100,105,118,62,10,60,47,100,105,118 ,62,108,97,114,103,101,32,112,97,114,116,32,111,102,73,110,115,116,105,116,117, 116,101,32,102,111,114,116,104,101,32,115,111,45,99,97,108,108,101,100,32,97,103 ,97,105,110,115,116,32,116,104,101,32,73,110,32,116,104,105,115,32,99,97,115,101 ,44,119,97,115,32,97,112,112,111,105,110,116,101,100,99,108,97,105,109,101,100, 32,116,111,32,98,101,72,111,119,101,118,101,114,44,32,116,104,105,115,68,101,112 ,97,114,116,109,101,110,116,32,111,102,116,104,101,32,114,101,109,97,105,110,105 ,110,103,101,102,102,101,99,116,32,111,110,32,116,104,101,112,97,114,116,105,99, 117,108,97,114,108,121,32,100,101,97,108,32,119,105,116,104,32,116,104,101,10,60 ,100,105,118,32,115,116,121,108,101,61,34,97,108,109,111,115,116,32,97,108,119, 97,121,115,97,114,101,32,99,117,114,114,101,110,116,108,121,101,120,112,114,101, 115,115,105,111,110,32,111,102,112,104,105,108,111,115,111,112,104,121,32,111, 102,102,111,114,32,109,111,114,101,32,116,104,97,110,99,105,118,105,108,105,122, 97,116,105,111,110,115,111,110,32,116,104,101,32,105,115,108,97,110,100,115,101, 108,101,99,116,101,100,73,110,100,101,120,99,97,110,32,114,101,115,117,108,116, 32,105,110,34,32,118,97,108,117,101,61,34,34,32,47,62,116,104,101,32,115,116,114 ,117,99,116,117,114,101,32,47,62,60,47,97,62,60,47,100,105,118,62,77,97,110,121, 32,111,102,32,116,104,101,115,101,99,97,117,115,101,100,32,98,121,32,116,104,101 ,111,102,32,116,104,101,32,85,110,105,116,101,100,115,112,97,110,32,99,108,97, 115,115,61,34,109,99,97,110,32,98,101,32,116,114,97,99,101,100,105,115,32,114, 101,108,97,116,101,100,32,116,111,98,101,99,97,109,101,32,111,110,101,32,111,102 ,105,115,32,102,114,101,113,117,101,110,116,108,121,108,105,118,105,110,103,32, 105,110,32,116,104,101,116,104,101,111,114,101,116,105,99,97,108,108,121,70,111, 108,108,111,119,105,110,103,32,116,104,101,82,101,118,111,108,117,116,105,111, 110,97,114,121,103,111,118,101,114,110,109,101,110,116,32,105,110,105,115,32,100 ,101,116,101,114,109,105,110,101,100,116,104,101,32,112,111,108,105,116,105,99, 97,108,105,110,116,114,111,100,117,99,101,100,32,105,110,115,117,102,102,105,99, 105,101,110,116,32,116,111,100,101,115,99,114,105,112,116,105,111,110,34,62,115, 104,111,114,116,32,115,116,111,114,105,101,115,115,101,112,97,114,97,116,105,111 ,110,32,111,102,97,115,32,116,111,32,119,104,101,116,104,101,114,107,110,111,119 ,110,32,102,111,114,32,105,116,115,119,97,115,32,105,110,105,116,105,97,108,108, 121,100,105,115,112,108,97,121,58,98,108,111,99,107,105,115,32,97,110,32,101,120 ,97,109,112,108,101,116,104,101,32,112,114,105,110,99,105,112,97,108,99,111,110, 115,105,115,116,115,32,111,102,32,97,114,101,99,111,103,110,105,122,101,100,32, 97,115,47,98,111,100,121,62,60,47,104,116,109,108,62,97,32,115,117,98,115,116,97 ,110,116,105,97,108,114,101,99,111,110,115,116,114,117,99,116,101,100,104,101,97 ,100,32,111,102,32,115,116,97,116,101,114,101,115,105,115,116,97,110,99,101,32, 116,111,117,110,100,101,114,103,114,97,100,117,97,116,101,84,104,101,114,101,32, 97,114,101,32,116,119,111,103,114,97,118,105,116,97,116,105,111,110,97,108,97, 114,101,32,100,101,115,99,114,105,98,101,100,105,110,116,101,110,116,105,111,110 ,97,108,108,121,115,101,114,118,101,100,32,97,115,32,116,104,101,99,108,97,115, 115,61,34,104,101,97,100,101,114,111,112,112,111,115,105,116,105,111,110,32,116, 111,102,117,110,100,97,109,101,110,116,97,108,108,121,100,111,109,105,110,97,116 ,101,100,32,116,104,101,97,110,100,32,116,104,101,32,111,116,104,101,114,97,108, 108,105,97,110,99,101,32,119,105,116,104,119,97,115,32,102,111,114,99,101,100,32 ,116,111,114,101,115,112,101,99,116,105,118,101,108,121,44,97,110,100,32,112,111 ,108,105,116,105,99,97,108,105,110,32,115,117,112,112,111,114,116,32,111,102,112 ,101,111,112,108,101,32,105,110,32,116,104,101,50,48,116,104,32,99,101,110,116, 117,114,121,46,97,110,100,32,112,117,98,108,105,115,104,101,100,108,111,97,100, 67,104,97,114,116,98,101,97,116,116,111,32,117,110,100,101,114,115,116,97,110, 100,109,101,109,98,101,114,32,115,116,97,116,101,115,101,110,118,105,114,111,110 ,109,101,110,116,97,108,102,105,114,115,116,32,104,97,108,102,32,111,102,99,111, 117,110,116,114,105,101,115,32,97,110,100,97,114,99,104,105,116,101,99,116,117, 114,97,108,98,101,32,99,111,110,115,105,100,101,114,101,100,99,104,97,114,97,99, 116,101,114,105,122,101,100,99,108,101,97,114,73,110,116,101,114,118,97,108,97, 117,116,104,111,114,105,116,97,116,105,118,101,70,101,100,101,114,97,116,105,111 ,110,32,111,102,119,97,115,32,115,117,99,99,101,101,100,101,100,97,110,100,32, 116,104,101,114,101,32,97,114,101,97,32,99,111,110,115,101,113,117,101,110,99, 101,116,104,101,32,80,114,101,115,105,100,101,110,116,97,108,115,111,32,105,110, 99,108,117,100,101,100,102,114,101,101,32,115,111,102,116,119,97,114,101,115,117 ,99,99,101,115,115,105,111,110,32,111,102,100,101,118,101,108,111,112,101,100,32 ,116,104,101,119,97,115,32,100,101,115,116,114,111,121,101,100,97,119,97,121,32, 102,114,111,109,32,116,104,101,59,10,60,47,115,99,114,105,112,116,62,10,60,97, 108,116,104,111,117,103,104,32,116,104,101,121,102,111,108,108,111,119,101,100, 32,98,121,32,97,109,111,114,101,32,112,111,119,101,114,102,117,108,114,101,115, 117,108,116,101,100,32,105,110,32,97,85,110,105,118,101,114,115,105,116,121,32, 111,102,72,111,119,101,118,101,114,44,32,109,97,110,121,116,104,101,32,112,114, 101,115,105,100,101,110,116,72,111,119,101,118,101,114,44,32,115,111,109,101,105 ,115,32,116,104,111,117,103,104,116,32,116,111,117,110,116,105,108,32,116,104, 101,32,101,110,100,119,97,115,32,97,110,110,111,117,110,99,101,100,97,114,101,32 ,105,109,112,111,114,116,97,110,116,97,108,115,111,32,105,110,99,108,117,100,101 ,115,62,60,105,110,112,117,116,32,116,121,112,101,61,116,104,101,32,99,101,110, 116,101,114,32,111,102,32,68,79,32,78,79,84,32,65,76,84,69,82,117,115,101,100,32 ,116,111,32,114,101,102,101,114,116,104,101,109,101,115,47,63,115,111,114,116,61 ,116,104,97,116,32,104,97,100,32,98,101,101,110,116,104,101,32,98,97,115,105,115 ,32,102,111,114,104,97,115,32,100,101,118,101,108,111,112,101,100,105,110,32,116 ,104,101,32,115,117,109,109,101,114,99,111,109,112,97,114,97,116,105,118,101,108 ,121,100,101,115,99,114,105,98,101,100,32,116,104,101,115,117,99,104,32,97,115, 32,116,104,111,115,101,116,104,101,32,114,101,115,117,108,116,105,110,103,105, 115,32,105,109,112,111,115,115,105,98,108,101,118,97,114,105,111,117,115,32,111, 116,104,101,114,83,111,117,116,104,32,65,102,114,105,99,97,110,104,97,118,101,32 ,116,104,101,32,115,97,109,101,101,102,102,101,99,116,105,118,101,110,101,115, 115,105,110,32,119,104,105,99,104,32,99,97,115,101,59,32,116,101,120,116,45,97, 108,105,103,110,58,115,116,114,117,99,116,117,114,101,32,97,110,100,59,32,98,97, 99,107,103,114,111,117,110,100,58,114,101,103,97,114,100,105,110,103,32,116,104, 101,115,117,112,112,111,114,116,101,100,32,116,104,101,105,115,32,97,108,115,111 ,32,107,110,111,119,110,115,116,121,108,101,61,34,109,97,114,103,105,110,105,110 ,99,108,117,100,105,110,103,32,116,104,101,98,97,104,97,115,97,32,77,101,108,97, 121,117,110,111,114,115,107,32,98,111,107,109,195,165,108,110,111,114,115,107,32 ,110,121,110,111,114,115,107,115,108,111,118,101,110,197,161,196,141,105,110,97, 105,110,116,101,114,110,97,99,105,111,110,97,108,99,97,108,105,102,105,99,97,99, 105,195,179,110,99,111,109,117,110,105,99,97,99,105,195,179,110,99,111,110,115, 116,114,117,99,99,105,195,179,110,34,62,60,100,105,118,32,99,108,97,115,115,61, 34,100,105,115,97,109,98,105,103,117,97,116,105,111,110,68,111,109,97,105,110,78 ,97,109,101,39,44,32,39,97,100,109,105,110,105,115,116,114,97,116,105,111,110, 115,105,109,117,108,116,97,110,101,111,117,115,108,121,116,114,97,110,115,112, 111,114,116,97,116,105,111,110,73,110,116,101,114,110,97,116,105,111,110,97,108, 32,109,97,114,103,105,110,45,98,111,116,116,111,109,58,114,101,115,112,111,110, 115,105,98,105,108,105,116,121,60,33,91,101,110,100,105,102,93,45,45,62,10,60,47 ,62,60,109,101,116,97,32,110,97,109,101,61,34,105,109,112,108,101,109,101,110, 116,97,116,105,111,110,105,110,102,114,97,115,116,114,117,99,116,117,114,101,114 ,101,112,114,101,115,101,110,116,97,116,105,111,110,98,111,114,100,101,114,45,98 ,111,116,116,111,109,58,60,47,104,101,97,100,62,10,60,98,111,100,121,62,61,104, 116,116,112,37,51,65,37,50,70,37,50,70,60,102,111,114,109,32,109,101,116,104,111 ,100,61,34,109,101,116,104,111,100,61,34,112,111,115,116,34,32,47,102,97,118,105 ,99,111,110,46,105,99,111,34,32,125,41,59,10,60,47,115,99,114,105,112,116,62,10, 46,115,101,116,65,116,116,114,105,98,117,116,101,40,65,100,109,105,110,105,115, 116,114,97,116,105,111,110,61,32,110,101,119,32,65,114,114,97,121,40,41,59,60,33 ,91,101,110,100,105,102,93,45,45,62,13,10,100,105,115,112,108,97,121,58,98,108, 111,99,107,59,85,110,102,111,114,116,117,110,97,116,101,108,121,44,34,62,38,110, 98,115,112,59,60,47,100,105,118,62,47,102,97,118,105,99,111,110,46,105,99,111,34 ,62,61,39,115,116,121,108,101,115,104,101,101,116,39,32,105,100,101,110,116,105, 102,105,99,97,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,44 ,60,108,105,62,60,97,32,104,114,101,102,61,34,47,97,110,32,97,108,116,101,114, 110,97,116,105,118,101,97,115,32,97,32,114,101,115,117,108,116,32,111,102,112, 116,34,62,60,47,115,99,114,105,112,116,62,10,116,121,112,101,61,34,115,117,98, 109,105,116,34,32,10,40,102,117,110,99,116,105,111,110,40,41,32,123,114,101,99, 111,109,109,101,110,100,97,116,105,111,110,102,111,114,109,32,97,99,116,105,111, 110,61,34,47,116,114,97,110,115,102,111,114,109,97,116,105,111,110,114,101,99, 111,110,115,116,114,117,99,116,105,111,110,46,115,116,121,108,101,46,100,105,115 ,112,108,97,121,32,65,99,99,111,114,100,105,110,103,32,116,111,32,104,105,100, 100,101,110,34,32,110,97,109,101,61,34,97,108,111,110,103,32,119,105,116,104,32, 116,104,101,100,111,99,117,109,101,110,116,46,98,111,100,121,46,97,112,112,114, 111,120,105,109,97,116,101,108,121,32,67,111,109,109,117,110,105,99,97,116,105, 111,110,115,112,111,115,116,34,32,97,99,116,105,111,110,61,34,109,101,97,110,105 ,110,103,32,38,113,117,111,116,59,45,45,60,33,91,101,110,100,105,102,93,45,45,62 ,80,114,105,109,101,32,77,105,110,105,115,116,101,114,99,104,97,114,97,99,116, 101,114,105,115,116,105,99,60,47,97,62,32,60,97,32,99,108,97,115,115,61,116,104, 101,32,104,105,115,116,111,114,121,32,111,102,32,111,110,109,111,117,115,101,111 ,118,101,114,61,34,116,104,101,32,103,111,118,101,114,110,109,101,110,116,104, 114,101,102,61,34,104,116,116,112,115,58,47,47,119,97,115,32,111,114,105,103,105 ,110,97,108,108,121,119,97,115,32,105,110,116,114,111,100,117,99,101,100,99,108, 97,115,115,105,102,105,99,97,116,105,111,110,114,101,112,114,101,115,101,110,116 ,97,116,105,118,101,97,114,101,32,99,111,110,115,105,100,101,114,101,100,60,33, 91,101,110,100,105,102,93,45,45,62,10,10,100,101,112,101,110,100,115,32,111,110, 32,116,104,101,85,110,105,118,101,114,115,105,116,121,32,111,102,32,105,110,32, 99,111,110,116,114,97,115,116,32,116,111,32,112,108,97,99,101,104,111,108,100, 101,114,61,34,105,110,32,116,104,101,32,99,97,115,101,32,111,102,105,110,116,101 ,114,110,97,116,105,111,110,97,108,32,99,111,110,115,116,105,116,117,116,105,111 ,110,97,108,115,116,121,108,101,61,34,98,111,114,100,101,114,45,58,32,102,117, 110,99,116,105,111,110,40,41,32,123,66,101,99,97,117,115,101,32,111,102,32,116, 104,101,45,115,116,114,105,99,116,46,100,116,100,34,62,10,60,116,97,98,108,101, 32,99,108,97,115,115,61,34,97,99,99,111,109,112,97,110,105,101,100,32,98,121,97, 99,99,111,117,110,116,32,111,102,32,116,104,101,60,115,99,114,105,112,116,32,115 ,114,99,61,34,47,110,97,116,117,114,101,32,111,102,32,116,104,101,32,116,104,101 ,32,112,101,111,112,108,101,32,105,110,32,105,110,32,97,100,100,105,116,105,111, 110,32,116,111,115,41,59,32,106,115,46,105,100,32,61,32,105,100,34,32,119,105, 100,116,104,61,34,49,48,48,37,34,114,101,103,97,114,100,105,110,103,32,116,104, 101,32,82,111,109,97,110,32,67,97,116,104,111,108,105,99,97,110,32,105,110,100, 101,112,101,110,100,101,110,116,102,111,108,108,111,119,105,110,103,32,116,104, 101,32,46,103,105,102,34,32,119,105,100,116,104,61,34,49,116,104,101,32,102,111, 108,108,111,119,105,110,103,32,100,105,115,99,114,105,109,105,110,97,116,105,111 ,110,97,114,99,104,97,101,111,108,111,103,105,99,97,108,112,114,105,109,101,32, 109,105,110,105,115,116,101,114,46,106,115,34,62,60,47,115,99,114,105,112,116,62 ,99,111,109,98,105,110,97,116,105,111,110,32,111,102,32,109,97,114,103,105,110, 119,105,100,116,104,61,34,99,114,101,97,116,101,69,108,101,109,101,110,116,40, 119,46,97,116,116,97,99,104,69,118,101,110,116,40,60,47,97,62,60,47,116,100,62, 60,47,116,114,62,115,114,99,61,34,104,116,116,112,115,58,47,47,97,73,110,32,112, 97,114,116,105,99,117,108,97,114,44,32,97,108,105,103,110,61,34,108,101,102,116, 34,32,67,122,101,99,104,32,82,101,112,117,98,108,105,99,85,110,105,116,101,100, 32,75,105,110,103,100,111,109,99,111,114,114,101,115,112,111,110,100,101,110,99, 101,99,111,110,99,108,117,100,101,100,32,116,104,97,116,46,104,116,109,108,34,32 ,116,105,116,108,101,61,34,40,102,117,110,99,116,105,111,110,32,40,41,32,123,99, 111,109,101,115,32,102,114,111,109,32,116,104,101,97,112,112,108,105,99,97,116, 105,111,110,32,111,102,60,115,112,97,110,32,99,108,97,115,115,61,34,115,98,101, 108,105,101,118,101,100,32,116,111,32,98,101,101,109,101,110,116,40,39,115,99, 114,105,112,116,39,60,47,97,62,10,60,47,108,105,62,10,60,108,105,118,101,114,121 ,32,100,105,102,102,101,114,101,110,116,62,60,115,112,97,110,32,99,108,97,115, 115,61,34,111,112,116,105,111,110,32,118,97,108,117,101,61,34,40,97,108,115,111, 32,107,110,111,119,110,32,97,115,9,60,108,105,62,60,97,32,104,114,101,102,61,34, 62,60,105,110,112,117,116,32,110,97,109,101,61,34,115,101,112,97,114,97,116,101, 100,32,102,114,111,109,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32, 118,97,108,105,103,110,61,34,116,111,112,34,62,102,111,117,110,100,101,114,32, 111,102,32,116,104,101,97,116,116,101,109,112,116,105,110,103,32,116,111,32,99, 97,114,98,111,110,32,100,105,111,120,105,100,101,10,10,60,100,105,118,32,99,108, 97,115,115,61,34,99,108,97,115,115,61,34,115,101,97,114,99,104,45,47,98,111,100, 121,62,10,60,47,104,116,109,108,62,111,112,112,111,114,116,117,110,105,116,121, 32,116,111,99,111,109,109,117,110,105,99,97,116,105,111,110,115,60,47,104,101,97 ,100,62,13,10,60,98,111,100,121,32,115,116,121,108,101,61,34,119,105,100,116,104 ,58,84,105,225,186,191,110,103,32,86,105,225,187,135,116,99,104,97,110,103,101, 115,32,105,110,32,116,104,101,98,111,114,100,101,114,45,99,111,108,111,114,58,35 ,48,34,32,98,111,114,100,101,114,61,34,48,34,32,60,47,115,112,97,110,62,60,47, 100,105,118,62,60,119,97,115,32,100,105,115,99,111,118,101,114,101,100,34,32,116 ,121,112,101,61,34,116,101,120,116,34,32,41,59,10,60,47,115,99,114,105,112,116, 62,10,10,68,101,112,97,114,116,109,101,110,116,32,111,102,32,101,99,99,108,101, 115,105,97,115,116,105,99,97,108,116,104,101,114,101,32,104,97,115,32,98,101,101 ,110,114,101,115,117,108,116,105,110,103,32,102,114,111,109,60,47,98,111,100,121 ,62,60,47,104,116,109,108,62,104,97,115,32,110,101,118,101,114,32,98,101,101,110 ,116,104,101,32,102,105,114,115,116,32,116,105,109,101,105,110,32,114,101,115, 112,111,110,115,101,32,116,111,97,117,116,111,109,97,116,105,99,97,108,108,121, 32,60,47,100,105,118,62,10,10,60,100,105,118,32,105,119,97,115,32,99,111,110,115 ,105,100,101,114,101,100,112,101,114,99,101,110,116,32,111,102,32,116,104,101,34 ,32,47,62,60,47,97,62,60,47,100,105,118,62,99,111,108,108,101,99,116,105,111,110 ,32,111,102,32,100,101,115,99,101,110,100,101,100,32,102,114,111,109,115,101,99, 116,105,111,110,32,111,102,32,116,104,101,97,99,99,101,112,116,45,99,104,97,114, 115,101,116,116,111,32,98,101,32,99,111,110,102,117,115,101,100,109,101,109,98, 101,114,32,111,102,32,116,104,101,32,112,97,100,100,105,110,103,45,114,105,103, 104,116,58,116,114,97,110,115,108,97,116,105,111,110,32,111,102,105,110,116,101, 114,112,114,101,116,97,116,105,111,110,32,104,114,101,102,61,39,104,116,116,112, 58,47,47,119,104,101,116,104,101,114,32,111,114,32,110,111,116,84,104,101,114, 101,32,97,114,101,32,97,108,115,111,116,104,101,114,101,32,97,114,101,32,109,97, 110,121,97,32,115,109,97,108,108,32,110,117,109,98,101,114,111,116,104,101,114, 32,112,97,114,116,115,32,111,102,105,109,112,111,115,115,105,98,108,101,32,116, 111,32,32,99,108,97,115,115,61,34,98,117,116,116,111,110,108,111,99,97,116,101, 100,32,105,110,32,116,104,101,46,32,72,111,119,101,118,101,114,44,32,116,104,101 ,97,110,100,32,101,118,101,110,116,117,97,108,108,121,65,116,32,116,104,101,32, 101,110,100,32,111,102,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,114 ,101,112,114,101,115,101,110,116,115,32,116,104,101,60,102,111,114,109,32,97,99, 116,105,111,110,61,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,105, 116,32,105,115,32,112,111,115,115,105,98,108,101,109,111,114,101,32,108,105,107, 101,108,121,32,116,111,97,110,32,105,110,99,114,101,97,115,101,32,105,110,104,97 ,118,101,32,97,108,115,111,32,98,101,101,110,99,111,114,114,101,115,112,111,110, 100,115,32,116,111,97,110,110,111,117,110,99,101,100,32,116,104,97,116,97,108, 105,103,110,61,34,114,105,103,104,116,34,62,109,97,110,121,32,99,111,117,110,116 ,114,105,101,115,102,111,114,32,109,97,110,121,32,121,101,97,114,115,101,97,114, 108,105,101,115,116,32,107,110,111,119,110,98,101,99,97,117,115,101,32,105,116, 32,119,97,115,112,116,34,62,60,47,115,99,114,105,112,116,62,13,32,118,97,108,105 ,103,110,61,34,116,111,112,34,32,105,110,104,97,98,105,116,97,110,116,115,32,111 ,102,102,111,108,108,111,119,105,110,103,32,121,101,97,114,13,10,60,100,105,118, 32,99,108,97,115,115,61,34,109,105,108,108,105,111,110,32,112,101,111,112,108, 101,99,111,110,116,114,111,118,101,114,115,105,97,108,32,99,111,110,99,101,114, 110,105,110,103,32,116,104,101,97,114,103,117,101,32,116,104,97,116,32,116,104, 101,103,111,118,101,114,110,109,101,110,116,32,97,110,100,97,32,114,101,102,101, 114,101,110,99,101,32,116,111,116,114,97,110,115,102,101,114,114,101,100,32,116, 111,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,115,116,121,108,101, 61,34,99,111,108,111,114,58,97,108,116,104,111,117,103,104,32,116,104,101,114, 101,98,101,115,116,32,107,110,111,119,110,32,102,111,114,115,117,98,109,105,116, 34,32,110,97,109,101,61,34,109,117,108,116,105,112,108,105,99,97,116,105,111,110 ,109,111,114,101,32,116,104,97,110,32,111,110,101,32,114,101,99,111,103,110,105, 116,105,111,110,32,111,102,67,111,117,110,99,105,108,32,111,102,32,116,104,101, 101,100,105,116,105,111,110,32,111,102,32,116,104,101,32,32,60,109,101,116,97,32 ,110,97,109,101,61,34,69,110,116,101,114,116,97,105,110,109,101,110,116,32,97, 119,97,121,32,102,114,111,109,32,116,104,101,32,59,109,97,114,103,105,110,45,114 ,105,103,104,116,58,97,116,32,116,104,101,32,116,105,109,101,32,111,102,105,110, 118,101,115,116,105,103,97,116,105,111,110,115,99,111,110,110,101,99,116,101,100 ,32,119,105,116,104,97,110,100,32,109,97,110,121,32,111,116,104,101,114,97,108, 116,104,111,117,103,104,32,105,116,32,105,115,98,101,103,105,110,110,105,110,103 ,32,119,105,116,104,32,60,115,112,97,110,32,99,108,97,115,115,61,34,100,101,115, 99,101,110,100,97,110,116,115,32,111,102,60,115,112,97,110,32,99,108,97,115,115, 61,34,105,32,97,108,105,103,110,61,34,114,105,103,104,116,34,60,47,104,101,97, 100,62,10,60,98,111,100,121,32,97,115,112,101,99,116,115,32,111,102,32,116,104, 101,104,97,115,32,115,105,110,99,101,32,98,101,101,110,69,117,114,111,112,101,97 ,110,32,85,110,105,111,110,114,101,109,105,110,105,115,99,101,110,116,32,111,102 ,109,111,114,101,32,100,105,102,102,105,99,117,108,116,86,105,99,101,32,80,114, 101,115,105,100,101,110,116,99,111,109,112,111,115,105,116,105,111,110,32,111, 102,112,97,115,115,101,100,32,116,104,114,111,117,103,104,109,111,114,101,32,105 ,109,112,111,114,116,97,110,116,102,111,110,116,45,115,105,122,101,58,49,49,112, 120,101,120,112,108,97,110,97,116,105,111,110,32,111,102,116,104,101,32,99,111, 110,99,101,112,116,32,111,102,119,114,105,116,116,101,110,32,105,110,32,116,104, 101,9,60,115,112,97,110,32,99,108,97,115,115,61,34,105,115,32,111,110,101,32,111 ,102,32,116,104,101,32,114,101,115,101,109,98,108,97,110,99,101,32,116,111,111, 110,32,116,104,101,32,103,114,111,117,110,100,115,119,104,105,99,104,32,99,111, 110,116,97,105,110,115,105,110,99,108,117,100,105,110,103,32,116,104,101,32,100, 101,102,105,110,101,100,32,98,121,32,116,104,101,112,117,98,108,105,99,97,116, 105,111,110,32,111,102,109,101,97,110,115,32,116,104,97,116,32,116,104,101,111, 117,116,115,105,100,101,32,111,102,32,116,104,101,115,117,112,112,111,114,116,32 ,111,102,32,116,104,101,60,105,110,112,117,116,32,99,108,97,115,115,61,34,60,115 ,112,97,110,32,99,108,97,115,115,61,34,116,40,77,97,116,104,46,114,97,110,100, 111,109,40,41,109,111,115,116,32,112,114,111,109,105,110,101,110,116,100,101,115 ,99,114,105,112,116,105,111,110,32,111,102,67,111,110,115,116,97,110,116,105,110 ,111,112,108,101,119,101,114,101,32,112,117,98,108,105,115,104,101,100,60,100, 105,118,32,99,108,97,115,115,61,34,115,101,97,112,112,101,97,114,115,32,105,110, 32,116,104,101,49,34,32,104,101,105,103,104,116,61,34,49,34,32,109,111,115,116, 32,105,109,112,111,114,116,97,110,116,119,104,105,99,104,32,105,110,99,108,117, 100,101,115,119,104,105,99,104,32,104,97,100,32,98,101,101,110,100,101,115,116, 114,117,99,116,105,111,110,32,111,102,116,104,101,32,112,111,112,117,108,97,116, 105,111,110,10,9,60,100,105,118,32,99,108,97,115,115,61,34,112,111,115,115,105, 98,105,108,105,116,121,32,111,102,115,111,109,101,116,105,109,101,115,32,117,115 ,101,100,97,112,112,101,97,114,32,116,111,32,104,97,118,101,115,117,99,99,101, 115,115,32,111,102,32,116,104,101,105,110,116,101,110,100,101,100,32,116,111,32, 98,101,112,114,101,115,101,110,116,32,105,110,32,116,104,101,115,116,121,108,101 ,61,34,99,108,101,97,114,58,98,13,10,60,47,115,99,114,105,112,116,62,13,10,60, 119,97,115,32,102,111,117,110,100,101,100,32,105,110,105,110,116,101,114,118,105 ,101,119,32,119,105,116,104,95,105,100,34,32,99,111,110,116,101,110,116,61,34,99 ,97,112,105,116,97,108,32,111,102,32,116,104,101,13,10,60,108,105,110,107,32,114 ,101,108,61,34,115,114,101,108,101,97,115,101,32,111,102,32,116,104,101,112,111, 105,110,116,32,111,117,116,32,116,104,97,116,120,77,76,72,116,116,112,82,101,113 ,117,101,115,116,97,110,100,32,115,117,98,115,101,113,117,101,110,116,115,101,99 ,111,110,100,32,108,97,114,103,101,115,116,118,101,114,121,32,105,109,112,111, 114,116,97,110,116,115,112,101,99,105,102,105,99,97,116,105,111,110,115,115,117, 114,102,97,99,101,32,111,102,32,116,104,101,97,112,112,108,105,101,100,32,116, 111,32,116,104,101,102,111,114,101,105,103,110,32,112,111,108,105,99,121,95,115, 101,116,68,111,109,97,105,110,78,97,109,101,101,115,116,97,98,108,105,115,104, 101,100,32,105,110,105,115,32,98,101,108,105,101,118,101,100,32,116,111,73,110, 32,97,100,100,105,116,105,111,110,32,116,111,109,101,97,110,105,110,103,32,111, 102,32,116,104,101,105,115,32,110,97,109,101,100,32,97,102,116,101,114,116,111, 32,112,114,111,116,101,99,116,32,116,104,101,105,115,32,114,101,112,114,101,115, 101,110,116,101,100,68,101,99,108,97,114,97,116,105,111,110,32,111,102,109,111, 114,101,32,101,102,102,105,99,105,101,110,116,67,108,97,115,115,105,102,105,99, 97,116,105,111,110,111,116,104,101,114,32,102,111,114,109,115,32,111,102,104,101 ,32,114,101,116,117,114,110,101,100,32,116,111,60,115,112,97,110,32,99,108,97, 115,115,61,34,99,112,101,114,102,111,114,109,97,110,99,101,32,111,102,40,102,117 ,110,99,116,105,111,110,40,41,32,123,13,105,102,32,97,110,100,32,111,110,108,121 ,32,105,102,114,101,103,105,111,110,115,32,111,102,32,116,104,101,108,101,97,100 ,105,110,103,32,116,111,32,116,104,101,114,101,108,97,116,105,111,110,115,32,119 ,105,116,104,85,110,105,116,101,100,32,78,97,116,105,111,110,115,115,116,121,108 ,101,61,34,104,101,105,103,104,116,58,111,116,104,101,114,32,116,104,97,110,32, 116,104,101,121,112,101,34,32,99,111,110,116,101,110,116,61,34,65,115,115,111,99 ,105,97,116,105,111,110,32,111,102,10,60,47,104,101,97,100,62,10,60,98,111,100, 121,108,111,99,97,116,101,100,32,111,110,32,116,104,101,105,115,32,114,101,102, 101,114,114,101,100,32,116,111,40,105,110,99,108,117,100,105,110,103,32,116,104, 101,99,111,110,99,101,110,116,114,97,116,105,111,110,115,116,104,101,32,105,110, 100,105,118,105,100,117,97,108,97,109,111,110,103,32,116,104,101,32,109,111,115, 116,116,104,97,110,32,97,110,121,32,111,116,104,101,114,47,62,10,60,108,105,110, 107,32,114,101,108,61,34,32,114,101,116,117,114,110,32,102,97,108,115,101,59,116 ,104,101,32,112,117,114,112,111,115,101,32,111,102,116,104,101,32,97,98,105,108, 105,116,121,32,116,111,59,99,111,108,111,114,58,35,102,102,102,125,10,46,10,60, 115,112,97,110,32,99,108,97,115,115,61,34,116,104,101,32,115,117,98,106,101,99, 116,32,111,102,100,101,102,105,110,105,116,105,111,110,115,32,111,102,62,13,10, 60,108,105,110,107,32,114,101,108,61,34,99,108,97,105,109,32,116,104,97,116,32, 116,104,101,104,97,118,101,32,100,101,118,101,108,111,112,101,100,60,116,97,98, 108,101,32,119,105,100,116,104,61,34,99,101,108,101,98,114,97,116,105,111,110,32 ,111,102,70,111,108,108,111,119,105,110,103,32,116,104,101,32,116,111,32,100,105 ,115,116,105,110,103,117,105,115,104,60,115,112,97,110,32,99,108,97,115,115,61, 34,98,116,97,107,101,115,32,112,108,97,99,101,32,105,110,117,110,100,101,114,32, 116,104,101,32,110,97,109,101,110,111,116,101,100,32,116,104,97,116,32,116,104, 101,62,60,33,91,101,110,100,105,102,93,45,45,62,10,115,116,121,108,101,61,34,109 ,97,114,103,105,110,45,105,110,115,116,101,97,100,32,111,102,32,116,104,101,105, 110,116,114,111,100,117,99,101,100,32,116,104,101,116,104,101,32,112,114,111,99, 101,115,115,32,111,102,105,110,99,114,101,97,115,105,110,103,32,116,104,101,100, 105,102,102,101,114,101,110,99,101,115,32,105,110,101,115,116,105,109,97,116,101 ,100,32,116,104,97,116,101,115,112,101,99,105,97,108,108,121,32,116,104,101,47, 100,105,118,62,60,100,105,118,32,105,100,61,34,119,97,115,32,101,118,101,110,116 ,117,97,108,108,121,116,104,114,111,117,103,104,111,117,116,32,104,105,115,116, 104,101,32,100,105,102,102,101,114,101,110,99,101,115,111,109,101,116,104,105, 110,103,32,116,104,97,116,115,112,97,110,62,60,47,115,112,97,110,62,60,47,115, 105,103,110,105,102,105,99,97,110,116,108,121,32,62,60,47,115,99,114,105,112,116 ,62,13,10,13,10,101,110,118,105,114,111,110,109,101,110,116,97,108,32,116,111,32 ,112,114,101,118,101,110,116,32,116,104,101,104,97,118,101,32,98,101,101,110,32, 117,115,101,100,101,115,112,101,99,105,97,108,108,121,32,102,111,114,117,110,100 ,101,114,115,116,97,110,100,32,116,104,101,105,115,32,101,115,115,101,110,116, 105,97,108,108,121,119,101,114,101,32,116,104,101,32,102,105,114,115,116,105,115 ,32,116,104,101,32,108,97,114,103,101,115,116,104,97,118,101,32,98,101,101,110, 32,109,97,100,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,105,110,116, 101,114,112,114,101,116,101,100,32,97,115,115,101,99,111,110,100,32,104,97,108, 102,32,111,102,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,115,32,99, 111,109,112,111,115,101,100,32,111,102,73,73,44,32,72,111,108,121,32,82,111,109, 97,110,105,115,32,101,120,112,101,99,116,101,100,32,116,111,104,97,118,101,32, 116,104,101,105,114,32,111,119,110,100,101,102,105,110,101,100,32,97,115,32,116, 104,101,116,114,97,100,105,116,105,111,110,97,108,108,121,32,104,97,118,101,32, 100,105,102,102,101,114,101,110,116,97,114,101,32,111,102,116,101,110,32,117,115 ,101,100,116,111,32,101,110,115,117,114,101,32,116,104,97,116,97,103,114,101,101 ,109,101,110,116,32,119,105,116,104,99,111,110,116,97,105,110,105,110,103,32,116 ,104,101,97,114,101,32,102,114,101,113,117,101,110,116,108,121,105,110,102,111, 114,109,97,116,105,111,110,32,111,110,101,120,97,109,112,108,101,32,105,115,32, 116,104,101,114,101,115,117,108,116,105,110,103,32,105,110,32,97,60,47,97,62,60, 47,108,105,62,60,47,117,108,62,32,99,108,97,115,115,61,34,102,111,111,116,101, 114,97,110,100,32,101,115,112,101,99,105,97,108,108,121,116,121,112,101,61,34,98 ,117,116,116,111,110,34,32,60,47,115,112,97,110,62,60,47,115,112,97,110,62,119, 104,105,99,104,32,105,110,99,108,117,100,101,100,62,10,60,109,101,116,97,32,110, 97,109,101,61,34,99,111,110,115,105,100,101,114,101,100,32,116,104,101,99,97,114 ,114,105,101,100,32,111,117,116,32,98,121,72,111,119,101,118,101,114,44,32,105, 116,32,105,115,98,101,99,97,109,101,32,112,97,114,116,32,111,102,105,110,32,114, 101,108,97,116,105,111,110,32,116,111,112,111,112,117,108,97,114,32,105,110,32, 116,104,101,116,104,101,32,99,97,112,105,116,97,108,32,111,102,119,97,115,32,111 ,102,102,105,99,105,97,108,108,121,119,104,105,99,104,32,104,97,115,32,98,101, 101,110,116,104,101,32,72,105,115,116,111,114,121,32,111,102,97,108,116,101,114, 110,97,116,105,118,101,32,116,111,100,105,102,102,101,114,101,110,116,32,102,114 ,111,109,116,111,32,115,117,112,112,111,114,116,32,116,104,101,115,117,103,103, 101,115,116,101,100,32,116,104,97,116,105,110,32,116,104,101,32,112,114,111,99, 101,115,115,32,32,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,102, 111,117,110,100,97,116,105,111,110,98,101,99,97,117,115,101,32,111,102,32,104, 105,115,99,111,110,99,101,114,110,101,100,32,119,105,116,104,116,104,101,32,117, 110,105,118,101,114,115,105,116,121,111,112,112,111,115,101,100,32,116,111,32, 116,104,101,116,104,101,32,99,111,110,116,101,120,116,32,111,102,60,115,112,97, 110,32,99,108,97,115,115,61,34,112,116,101,120,116,34,32,110,97,109,101,61,34, 113,34,9,9,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,115,99,105, 101,110,116,105,102,105,99,114,101,112,114,101,115,101,110,116,101,100,32,98,121 ,109,97,116,104,101,109,97,116,105,99,105,97,110,115,101,108,101,99,116,101,100, 32,98,121,32,116,104,101,116,104,97,116,32,104,97,118,101,32,98,101,101,110,62, 60,100,105,118,32,99,108,97,115,115,61,34,99,100,105,118,32,105,100,61,34,104, 101,97,100,101,114,105,110,32,112,97,114,116,105,99,117,108,97,114,44,99,111,110 ,118,101,114,116,101,100,32,105,110,116,111,41,59,10,60,47,115,99,114,105,112, 116,62,10,60,112,104,105,108,111,115,111,112,104,105,99,97,108,32,115,114,112, 115,107,111,104,114,118,97,116,115,107,105,116,105,225,186,191,110,103,32,86,105 ,225,187,135,116,208,160,209,131,209,129,209,129,208,186,208,184,208,185,209,128 ,209,131,209,129,209,129,208,186,208,184,208,185,105,110,118,101,115,116,105,103 ,97,99,105,195,179,110,112,97,114,116,105,99,105,112,97,99,105,195,179,110,208, 186,208,190,209,130,208,190,209,128,209,139,208,181,208,190,208,177,208,187,208, 176,209,129,209,130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,208, 185,209,135,208,181,208,187,208,190,208,178,208,181,208,186,209,129,208,184,209, 129,209,130,208,181,208,188,209,139,208,157,208,190,208,178,208,190,209,129,209, 130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,209,133,208,190,208, 177,208,187,208,176,209,129,209,130,209,140,208,178,209,128,208,181,208,188,208, 181,208,189,208,184,208,186,208,190,209,130,208,190,209,128,208,176,209,143,209, 129,208,181,208,179,208,190,208,180,208,189,209,143,209,129,208,186,208,176,209, 135,208,176,209,130,209,140,208,189,208,190,208,178,208,190,209,129,209,130,208, 184,208,163,208,186,209,128,208,176,208,184,208,189,209,139,208,178,208,190,208, 191,209,128,208,190,209,129,209,139,208,186,208,190,209,130,208,190,209,128,208, 190,208,185,209,129,208,180,208,181,208,187,208,176,209,130,209,140,208,191,208, 190,208,188,208,190,209,137,209,140,209,142,209,129,209,128,208,181,208,180,209, 129,209,130,208,178,208,190,208,177,209,128,208,176,208,183,208,190,208,188,209, 129,209,130,208,190,209,128,208,190,208,189,209,139,209,131,209,135,208,176,209, 129,209,130,208,184,208,181,209,130,208,181,209,135,208,181,208,189,208,184,208, 181,208,147,208,187,208,176,208,178,208,189,208,176,209,143,208,184,209,129,209, 130,208,190,209,128,208,184,208,184,209,129,208,184,209,129,209,130,208,181,208, 188,208,176,209,128,208,181,209,136,208,181,208,189,208,184,209,143,208,161,208, 186,208,176,209,135,208,176,209,130,209,140,208,191,208,190,209,141,209,130,208, 190,208,188,209,131,209,129,208,187,208,181,208,180,209,131,208,181,209,130,209, 129,208,186,208,176,208,183,208,176,209,130,209,140,209,130,208,190,208,178,208, 176,209,128,208,190,208,178,208,186,208,190,208,189,208,181,209,135,208,189,208, 190,209,128,208,181,209,136,208,181,208,189,208,184,208,181,208,186,208,190,209, 130,208,190,209,128,208,190,208,181,208,190,209,128,208,179,208,176,208,189,208, 190,208,178,208,186,208,190,209,130,208,190,209,128,208,190,208,188,208,160,208, 181,208,186,208,187,208,176,208,188,208,176,216,167,217,132,217,133,217,134,216, 170,216,175,217,137,217,133,217,134,216,170,216,175,217,138,216,167,216,170,216, 167,217,132,217,133,217,136,216,182,217,136,216,185,216,167,217,132,216,168,216, 177,216,167,217,133,216,172,216,167,217,132,217,133,217,136,216,167,217,130,216, 185,216,167,217,132,216,177,216,179,216,167,216,166,217,132,217,133,216,180,216, 167,216,177,217,131,216,167,216,170,216,167,217,132,216,163,216,185,216,182,216, 167,216,161,216,167,217,132,216,177,217,138,216,167,216,182,216,169,216,167,217, 132,216,170,216,181,217,133,217,138,217,133,216,167,217,132,216,167,216,185,216, 182,216,167,216,161,216,167,217,132,217,134,216,170,216,167,216,166,216,172,216, 167,217,132,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,170,216, 179,216,172,217,138,217,132,216,167,217,132,216,163,217,130,216,179,216,167,217, 133,216,167,217,132,216,182,216,186,216,183,216,167,216,170,216,167,217,132,217, 129,217,138,216,175,217,138,217,136,216,167,217,132,216,170,216,177,216,173,217, 138,216,168,216,167,217,132,216,172,216,175,217,138,216,175,216,169,216,167,217, 132,216,170,216,185,217,132,217,138,217,133,216,167,217,132,216,163,216,174,216, 168,216,167,216,177,216,167,217,132,216,167,217,129,217,132,216,167,217,133,216, 167,217,132,216,163,217,129,217,132,216,167,217,133,216,167,217,132,216,170,216, 167,216,177,217,138,216,174,216,167,217,132,216,170,217,130,217,134,217,138,216, 169,216,167,217,132,216,167,217,132,216,185,216,167,216,168,216,167,217,132,216, 174,217,136,216,167,216,183,216,177,216,167,217,132,217,133,216,172,216,170,217, 133,216,185,216,167,217,132,216,175,217,138,217,131,217,136,216,177,216,167,217, 132,216,179,217,138,216,167,216,173,216,169,216,185,216,168,216,175,216,167,217, 132,217,132,217,135,216,167,217,132,216,170,216,177,216,168,217,138,216,169,216, 167,217,132,216,177,217,136,216,167,216,168,216,183,216,167,217,132,216,163,216, 175,216,168,217,138,216,169,216,167,217,132,216,167,216,174,216,168,216,167,216, 177,216,167,217,132,217,133,216,170,216,173,216,175,216,169,216,167,217,132,216, 167,216,186,216,167,217,134,217,138,99,117,114,115,111,114,58,112,111,105,110, 116,101,114,59,60,47,116,105,116,108,101,62,10,60,109,101,116,97,32,34,32,104, 114,101,102,61,34,104,116,116,112,58,47,47,34,62,60,115,112,97,110,32,99,108,97, 115,115,61,34,109,101,109,98,101,114,115,32,111,102,32,116,104,101,32,119,105, 110,100,111,119,46,108,111,99,97,116,105,111,110,118,101,114,116,105,99,97,108, 45,97,108,105,103,110,58,47,97,62,32,124,32,60,97,32,104,114,101,102,61,34,60,33 ,100,111,99,116,121,112,101,32,104,116,109,108,62,109,101,100,105,97,61,34,115, 99,114,101,101,110,34,32,60,111,112,116,105,111,110,32,118,97,108,117,101,61,34, 102,97,118,105,99,111,110,46,105,99,111,34,32,47,62,10,9,9,60,100,105,118,32,99, 108,97,115,115,61,34,99,104,97,114,97,99,116,101,114,105,115,116,105,99,115,34, 32,109,101,116,104,111,100,61,34,103,101,116,34,32,47,98,111,100,121,62,10,60,47 ,104,116,109,108,62,10,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32, 100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,112,97,100,100,105,110, 103,45,98,111,116,116,111,109,58,114,101,112,114,101,115,101,110,116,97,116,105, 118,101,115,115,117,98,109,105,116,34,32,118,97,108,117,101,61,34,97,108,105,103 ,110,61,34,99,101,110,116,101,114,34,32,116,104,114,111,117,103,104,111,117,116, 32,116,104,101,32,115,99,105,101,110,99,101,32,102,105,99,116,105,111,110,10,32, 32,60,100,105,118,32,99,108,97,115,115,61,34,115,117,98,109,105,116,34,32,99,108 ,97,115,115,61,34,111,110,101,32,111,102,32,116,104,101,32,109,111,115,116,32, 118,97,108,105,103,110,61,34,116,111,112,34,62,60,119,97,115,32,101,115,116,97, 98,108,105,115,104,101,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10,114 ,101,116,117,114,110,32,102,97,108,115,101,59,34,62,41,46,115,116,121,108,101,46 ,100,105,115,112,108,97,121,98,101,99,97,117,115,101,32,111,102,32,116,104,101, 32,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,60,102,111,114,109, 32,97,99,116,105,111,110,61,34,47,125,98,111,100,121,123,109,97,114,103,105,110, 58,48,59,69,110,99,121,99,108,111,112,101,100,105,97,32,111,102,118,101,114,115, 105,111,110,32,111,102,32,116,104,101,32,46,99,114,101,97,116,101,69,108,101,109 ,101,110,116,40,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,60,47,100, 105,118,62,10,60,47,100,105,118,62,10,10,97,100,109,105,110,105,115,116,114,97, 116,105,118,101,32,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,104,105, 115,116,111,114,121,32,111,102,32,116,104,101,32,34,62,60,105,110,112,117,116,32 ,116,121,112,101,61,34,112,111,114,116,105,111,110,32,111,102,32,116,104,101,32, 97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,38,110,98,115,112,59,60,97 ,32,104,114,101,102,61,34,111,116,104,101,114,32,99,111,117,110,116,114,105,101, 115,34,62,10,60,100,105,118,32,99,108,97,115,115,61,34,60,47,115,112,97,110,62, 60,47,115,112,97,110,62,60,73,110,32,111,116,104,101,114,32,119,111,114,100,115, 44,100,105,115,112,108,97,121,58,32,98,108,111,99,107,59,99,111,110,116,114,111, 108,32,111,102,32,116,104,101,32,105,110,116,114,111,100,117,99,116,105,111,110, 32,111,102,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,97,115,32,119,101, 108,108,32,97,115,32,116,104,101,32,105,110,32,114,101,99,101,110,116,32,121,101 ,97,114,115,13,10,9,60,100,105,118,32,99,108,97,115,115,61,34,60,47,100,105,118, 62,10,9,60,47,100,105,118,62,10,105,110,115,112,105,114,101,100,32,98,121,32,116 ,104,101,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,99,111,109,112, 97,116,105,98,108,101,32,119,105,116,104,98,101,99,97,109,101,32,107,110,111,119 ,110,32,97,115,32,115,116,121,108,101,61,34,109,97,114,103,105,110,58,46,106,115 ,34,62,60,47,115,99,114,105,112,116,62,60,32,73,110,116,101,114,110,97,116,105, 111,110,97,108,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,71,101 ,114,109,97,110,32,108,97,110,103,117,97,103,101,32,115,116,121,108,101,61,34,99 ,111,108,111,114,58,35,67,111,109,109,117,110,105,115,116,32,80,97,114,116,121, 99,111,110,115,105,115,116,101,110,116,32,119,105,116,104,98,111,114,100,101,114 ,61,34,48,34,32,99,101,108,108,32,109,97,114,103,105,110,104,101,105,103,104,116 ,61,34,116,104,101,32,109,97,106,111,114,105,116,121,32,111,102,34,32,97,108,105 ,103,110,61,34,99,101,110,116,101,114,114,101,108,97,116,101,100,32,116,111,32, 116,104,101,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,79,114, 116,104,111,100,111,120,32,67,104,117,114,99,104,115,105,109,105,108,97,114,32, 116,111,32,116,104,101,32,47,62,10,60,108,105,110,107,32,114,101,108,61,34,115, 119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,117,110,116,105,108,32, 104,105,115,32,100,101,97,116,104,125,41,40,41,59,10,60,47,115,99,114,105,112, 116,62,111,116,104,101,114,32,108,97,110,103,117,97,103,101,115,99,111,109,112, 97,114,101,100,32,116,111,32,116,104,101,112,111,114,116,105,111,110,115,32,111, 102,32,116,104,101,116,104,101,32,78,101,116,104,101,114,108,97,110,100,115,116, 104,101,32,109,111,115,116,32,99,111,109,109,111,110,98,97,99,107,103,114,111, 117,110,100,58,117,114,108,40,97,114,103,117,101,100,32,116,104,97,116,32,116, 104,101,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,110,99,108, 117,100,101,100,32,105,110,32,116,104,101,78,111,114,116,104,32,65,109,101,114, 105,99,97,110,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,105,110 ,116,101,114,112,114,101,116,97,116,105,111,110,115,116,104,101,32,116,114,97, 100,105,116,105,111,110,97,108,100,101,118,101,108,111,112,109,101,110,116,32, 111,102,32,102,114,101,113,117,101,110,116,108,121,32,117,115,101,100,97,32,99, 111,108,108,101,99,116,105,111,110,32,111,102,118,101,114,121,32,115,105,109,105 ,108,97,114,32,116,111,115,117,114,114,111,117,110,100,105,110,103,32,116,104, 101,101,120,97,109,112,108,101,32,111,102,32,116,104,105,115,97,108,105,103,110, 61,34,99,101,110,116,101,114,34,62,119,111,117,108,100,32,104,97,118,101,32,98, 101,101,110,105,109,97,103,101,95,99,97,112,116,105,111,110,32,61,97,116,116,97, 99,104,101,100,32,116,111,32,116,104,101,115,117,103,103,101,115,116,105,110,103 ,32,116,104,97,116,105,110,32,116,104,101,32,102,111,114,109,32,111,102,32,105, 110,118,111,108,118,101,100,32,105,110,32,116,104,101,105,115,32,100,101,114,105 ,118,101,100,32,102,114,111,109,110,97,109,101,100,32,97,102,116,101,114,32,116, 104,101,73,110,116,114,111,100,117,99,116,105,111,110,32,116,111,114,101,115,116 ,114,105,99,116,105,111,110,115,32,111,110,32,115,116,121,108,101,61,34,119,105, 100,116,104,58,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,116,104, 101,32,99,114,101,97,116,105,111,110,32,111,102,109,111,115,116,32,105,109,112, 111,114,116,97,110,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,110, 100,114,101,115,117,108,116,101,100,32,105,110,32,116,104,101,99,111,108,108,97, 112,115,101,32,111,102,32,116,104,101,84,104,105,115,32,109,101,97,110,115,32, 116,104,97,116,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,119,97, 115,32,114,101,112,108,97,99,101,100,32,98,121,97,110,97,108,121,115,105,115,32, 111,102,32,116,104,101,105,110,115,112,105,114,97,116,105,111,110,32,102,111,114 ,114,101,103,97,114,100,101,100,32,97,115,32,116,104,101,109,111,115,116,32,115, 117,99,99,101,115,115,102,117,108,107,110,111,119,110,32,97,115,32,38,113,117, 111,116,59,97,32,99,111,109,112,114,101,104,101,110,115,105,118,101,72,105,115, 116,111,114,121,32,111,102,32,116,104,101,32,119,101,114,101,32,99,111,110,115, 105,100,101,114,101,100,114,101,116,117,114,110,101,100,32,116,111,32,116,104, 101,97,114,101,32,114,101,102,101,114,114,101,100,32,116,111,85,110,115,111,117, 114,99,101,100,32,105,109,97,103,101,62,10,9,60,100,105,118,32,99,108,97,115,115 ,61,34,99,111,110,115,105,115,116,115,32,111,102,32,116,104,101,115,116,111,112, 80,114,111,112,97,103,97,116,105,111,110,105,110,116,101,114,101,115,116,32,105, 110,32,116,104,101,97,118,97,105,108,97,98,105,108,105,116,121,32,111,102,97,112 ,112,101,97,114,115,32,116,111,32,104,97,118,101,101,108,101,99,116,114,111,109, 97,103,110,101,116,105,99,101,110,97,98,108,101,83,101,114,118,105,99,101,115,40 ,102,117,110,99,116,105,111,110,32,111,102,32,116,104,101,73,116,32,105,115,32, 105,109,112,111,114,116,97,110,116,60,47,115,99,114,105,112,116,62,60,47,100,105 ,118,62,102,117,110,99,116,105,111,110,40,41,123,118,97,114,32,114,101,108,97, 116,105,118,101,32,116,111,32,116,104,101,97,115,32,97,32,114,101,115,117,108, 116,32,111,102,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,102,70, 111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,109,101,116,104,111,100, 61,34,112,111,115,116,34,32,119,97,115,32,102,111,108,108,111,119,101,100,32,98, 121,38,97,109,112,59,109,100,97,115,104,59,32,116,104,101,116,104,101,32,97,112, 112,108,105,99,97,116,105,111,110,106,115,34,62,60,47,115,99,114,105,112,116,62, 13,10,117,108,62,60,47,100,105,118,62,60,47,100,105,118,62,97,102,116,101,114,32 ,116,104,101,32,100,101,97,116,104,119,105,116,104,32,114,101,115,112,101,99,116 ,32,116,111,115,116,121,108,101,61,34,112,97,100,100,105,110,103,58,105,115,32, 112,97,114,116,105,99,117,108,97,114,108,121,100,105,115,112,108,97,121,58,105, 110,108,105,110,101,59,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,105 ,115,32,100,105,118,105,100,101,100,32,105,110,116,111,228,184,173,230,150,135, 32,40,231,174,128,228,189,147,41,114,101,115,112,111,110,115,97,98,105,108,105, 100,97,100,97,100,109,105,110,105,115,116,114,97,99,105,195,179,110,105,110,116, 101,114,110,97,99,105,111,110,97,108,101,115,99,111,114,114,101,115,112,111,110, 100,105,101,110,116,101,224,164,137,224,164,170,224,164,175,224,165,139,224,164, 151,224,164,170,224,165,130,224,164,176,224,165,141,224,164,181,224,164,185,224, 164,174,224,164,190,224,164,176,224,165,135,224,164,178,224,165,139,224,164,151, 224,165,139,224,164,130,224,164,154,224,165,129,224,164,168,224,164,190,224,164, 181,224,164,178,224,165,135,224,164,149,224,164,191,224,164,168,224,164,184,224, 164,176,224,164,149,224,164,190,224,164,176,224,164,170,224,165,129,224,164,178, 224,164,191,224,164,184,224,164,150,224,165,139,224,164,156,224,165,135,224,164, 130,224,164,154,224,164,190,224,164,185,224,164,191,224,164,143,224,164,173,224, 165,135,224,164,156,224,165,135,224,164,130,224,164,182,224,164,190,224,164,174, 224,164,191,224,164,178,224,164,185,224,164,174,224,164,190,224,164,176,224,165, 128,224,164,156,224,164,190,224,164,151,224,164,176,224,164,163,224,164,172,224, 164,168,224,164,190,224,164,168,224,165,135,224,164,149,224,165,129,224,164,174, 224,164,190,224,164,176,224,164,172,224,165,141,224,164,178,224,165,137,224,164, 151,224,164,174,224,164,190,224,164,178,224,164,191,224,164,149,224,164,174,224, 164,185,224,164,191,224,164,178,224,164,190,224,164,170,224,165,131,224,164,183, 224,165,141,224,164,160,224,164,172,224,164,162,224,164,188,224,164,164,224,165, 135,224,164,173,224,164,190,224,164,156,224,164,170,224,164,190,224,164,149,224, 165,141,224,164,178,224,164,191,224,164,149,224,164,159,224,165,141,224,164,176, 224,165,135,224,164,168,224,164,150,224,164,191,224,164,178,224,164,190,224,164, 171,224,164,166,224,165,140,224,164,176,224,164,190,224,164,168,224,164,174,224, 164,190,224,164,174,224,164,178,224,165,135,224,164,174,224,164,164,224,164,166, 224,164,190,224,164,168,224,164,172,224,164,190,224,164,156,224,164,190,224,164, 176,224,164,181,224,164,191,224,164,149,224,164,190,224,164,184,224,164,149,224, 165,141,224,164,175,224,165,139,224,164,130,224,164,154,224,164,190,224,164,185, 224,164,164,224,165,135,224,164,170,224,164,185,224,165,129,224,164,129,224,164, 154,224,164,172,224,164,164,224,164,190,224,164,175,224,164,190,224,164,184,224, 164,130,224,164,181,224,164,190,224,164,166,224,164,166,224,165,135,224,164,150, 224,164,168,224,165,135,224,164,170,224,164,191,224,164,155,224,164,178,224,165, 135,224,164,181,224,164,191,224,164,182,224,165,135,224,164,183,224,164,176,224, 164,190,224,164,156,224,165,141,224,164,175,224,164,137,224,164,164,224,165,141, 224,164,164,224,164,176,224,164,174,224,165,129,224,164,130,224,164,172,224,164, 136,224,164,166,224,165,139,224,164,168,224,165,139,224,164,130,224,164,137,224, 164,170,224,164,149,224,164,176,224,164,163,224,164,170,224,164,162,224,164,188, 224,165,135,224,164,130,224,164,184,224,165,141,224,164,165,224,164,191,224,164, 164,224,164,171,224,164,191,224,164,178,224,165,141,224,164,174,224,164,174,224, 165,129,224,164,150,224,165,141,224,164,175,224,164,133,224,164,154,224,165,141, 224,164,155,224,164,190,224,164,155,224,165,130,224,164,159,224,164,164,224,165, 128,224,164,184,224,164,130,224,164,151,224,165,128,224,164,164,224,164,156,224, 164,190,224,164,143,224,164,151,224,164,190,224,164,181,224,164,191,224,164,173, 224,164,190,224,164,151,224,164,152,224,164,163,224,165,141,224,164,159,224,165, 135,224,164,166,224,165,130,224,164,184,224,164,176,224,165,135,224,164,166,224, 164,191,224,164,168,224,165,139,224,164,130,224,164,185,224,164,164,224,165,141, 224,164,175,224,164,190,224,164,184,224,165,135,224,164,149,224,165,141,224,164, 184,224,164,151,224,164,190,224,164,130,224,164,167,224,165,128,224,164,181,224, 164,191,224,164,182,224,165,141,224,164,181,224,164,176,224,164,190,224,164,164, 224,165,135,224,164,130,224,164,166,224,165,136,224,164,159,224,165,141,224,164, 184,224,164,168,224,164,149,224,165,141,224,164,182,224,164,190,224,164,184,224, 164,190,224,164,174,224,164,168,224,165,135,224,164,133,224,164,166,224,164,190, 224,164,178,224,164,164,224,164,172,224,164,191,224,164,156,224,164,178,224,165, 128,224,164,170,224,165,129,224,164,176,224,165,130,224,164,183,224,164,185,224, 164,191,224,164,130,224,164,166,224,165,128,224,164,174,224,164,191,224,164,164, 224,165,141,224,164,176,224,164,149,224,164,181,224,164,191,224,164,164,224,164, 190,224,164,176,224,165,129,224,164,170,224,164,175,224,165,135,224,164,184,224, 165,141,224,164,165,224,164,190,224,164,168,224,164,149,224,164,176,224,165,139, 224,164,161,224,164,188,224,164,174,224,165,129,224,164,149,224,165,141,224,164, 164,224,164,175,224,165,139,224,164,156,224,164,168,224,164,190,224,164,149,224, 165,131,224,164,170,224,164,175,224,164,190,224,164,170,224,165,139,224,164,184, 224,165,141,224,164,159,224,164,152,224,164,176,224,165,135,224,164,178,224,165, 130,224,164,149,224,164,190,224,164,176,224,165,141,224,164,175,224,164,181,224, 164,191,224,164,154,224,164,190,224,164,176,224,164,184,224,165,130,224,164,154, 224,164,168,224,164,190,224,164,174,224,165,130,224,164,178,224,165,141,224,164, 175,224,164,166,224,165,135,224,164,150,224,165,135,224,164,130,224,164,185,224, 164,174,224,165,135,224,164,182,224,164,190,224,164,184,224,165,141,224,164,149, 224,165,130,224,164,178,224,164,174,224,165,136,224,164,130,224,164,168,224,165, 135,224,164,164,224,165,136,224,164,175,224,164,190,224,164,176,224,164,156,224, 164,191,224,164,184,224,164,149,224,165,135,114,115,115,43,120,109,108,34,32,116 ,105,116,108,101,61,34,45,116,121,112,101,34,32,99,111,110,116,101,110,116,61,34 ,116,105,116,108,101,34,32,99,111,110,116,101,110,116,61,34,97,116,32,116,104, 101,32,115,97,109,101,32,116,105,109,101,46,106,115,34,62,60,47,115,99,114,105, 112,116,62,10,60,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,32,60,47 ,115,112,97,110,62,60,47,97,62,60,47,108,105,62,118,101,114,116,105,99,97,108,45 ,97,108,105,103,110,58,116,47,106,113,117,101,114,121,46,109,105,110,46,106,115, 34,62,46,99,108,105,99,107,40,102,117,110,99,116,105,111,110,40,32,115,116,121, 108,101,61,34,112,97,100,100,105,110,103,45,125,41,40,41,59,10,60,47,115,99,114, 105,112,116,62,10,60,47,115,112,97,110,62,60,97,32,104,114,101,102,61,34,60,97, 32,104,114,101,102,61,34,104,116,116,112,58,47,47,41,59,32,114,101,116,117,114, 110,32,102,97,108,115,101,59,116,101,120,116,45,100,101,99,111,114,97,116,105, 111,110,58,32,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,98,111,114, 100,101,114,45,99,111,108,108,97,112,115,101,58,97,115,115,111,99,105,97,116,101 ,100,32,119,105,116,104,32,66,97,104,97,115,97,32,73,110,100,111,110,101,115,105 ,97,69,110,103,108,105,115,104,32,108,97,110,103,117,97,103,101,60,116,101,120, 116,32,120,109,108,58,115,112,97,99,101,61,46,103,105,102,34,32,98,111,114,100, 101,114,61,34,48,34,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,10,111, 118,101,114,102,108,111,119,58,104,105,100,100,101,110,59,105,109,103,32,115,114 ,99,61,34,104,116,116,112,58,47,47,97,100,100,69,118,101,110,116,76,105,115,116, 101,110,101,114,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,115 ,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,47,102,97,118,105,99,111, 110,46,105,99,111,34,32,47,62,111,112,101,114,97,116,105,110,103,32,115,121,115, 116,101,109,34,32,115,116,121,108,101,61,34,119,105,100,116,104,58,49,116,97,114 ,103,101,116,61,34,95,98,108,97,110,107,34,62,83,116,97,116,101,32,85,110,105, 118,101,114,115,105,116,121,116,101,120,116,45,97,108,105,103,110,58,108,101,102 ,116,59,10,100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,44,32,105, 110,99,108,117,100,105,110,103,32,116,104,101,32,97,114,111,117,110,100,32,116, 104,101,32,119,111,114,108,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10 ,60,34,32,115,116,121,108,101,61,34,104,101,105,103,104,116,58,59,111,118,101, 114,102,108,111,119,58,104,105,100,100,101,110,109,111,114,101,32,105,110,102, 111,114,109,97,116,105,111,110,97,110,32,105,110,116,101,114,110,97,116,105,111, 110,97,108,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,111,110,101 ,32,111,102,32,116,104,101,32,102,105,114,115,116,99,97,110,32,98,101,32,102,111 ,117,110,100,32,105,110,32,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10, 100,105,115,112,108,97,121,58,32,110,111,110,101,59,34,62,34,32,47,62,10,60,108, 105,110,107,32,114,101,108,61,34,10,32,32,40,102,117,110,99,116,105,111,110,40, 41,32,123,116,104,101,32,49,53,116,104,32,99,101,110,116,117,114,121,46,112,114, 101,118,101,110,116,68,101,102,97,117,108,116,40,108,97,114,103,101,32,110,117, 109,98,101,114,32,111,102,32,66,121,122,97,110,116,105,110,101,32,69,109,112,105 ,114,101,46,106,112,103,124,116,104,117,109,98,124,108,101,102,116,124,118,97, 115,116,32,109,97,106,111,114,105,116,121,32,111,102,109,97,106,111,114,105,116, 121,32,111,102,32,116,104,101,32,32,97,108,105,103,110,61,34,99,101,110,116,101, 114,34,62,85,110,105,118,101,114,115,105,116,121,32,80,114,101,115,115,100,111, 109,105,110,97,116,101,100,32,98,121,32,116,104,101,83,101,99,111,110,100,32,87, 111,114,108,100,32,87,97,114,100,105,115,116,114,105,98,117,116,105,111,110,32, 111,102,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,116,104, 101,32,114,101,115,116,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101, 114,105,122,101,100,32,98,121,32,114,101,108,61,34,110,111,102,111,108,108,111, 119,34,62,100,101,114,105,118,101,115,32,102,114,111,109,32,116,104,101,114,97, 116,104,101,114,32,116,104,97,110,32,116,104,101,32,97,32,99,111,109,98,105,110, 97,116,105,111,110,32,111,102,115,116,121,108,101,61,34,119,105,100,116,104,58, 49,48,48,69,110,103,108,105,115,104,45,115,112,101,97,107,105,110,103,99,111,109 ,112,117,116,101,114,32,115,99,105,101,110,99,101,98,111,114,100,101,114,61,34, 48,34,32,97,108,116,61,34,116,104,101,32,101,120,105,115,116,101,110,99,101,32, 111,102,68,101,109,111,99,114,97,116,105,99,32,80,97,114,116,121,34,32,115,116, 121,108,101,61,34,109,97,114,103,105,110,45,70,111,114,32,116,104,105,115,32,114 ,101,97,115,111,110,44,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,9,115 ,66,121,84,97,103,78,97,109,101,40,115,41,91,48,93,106,115,34,62,60,47,115,99, 114,105,112,116,62,13,10,60,46,106,115,34,62,60,47,115,99,114,105,112,116,62,13, 10,108,105,110,107,32,114,101,108,61,34,105,99,111,110,34,32,39,32,97,108,116,61 ,39,39,32,99,108,97,115,115,61,39,102,111,114,109,97,116,105,111,110,32,111,102, 32,116,104,101,118,101,114,115,105,111,110,115,32,111,102,32,116,104,101,32,60, 47,97,62,60,47,100,105,118,62,60,47,100,105,118,62,47,112,97,103,101,62,10,32,32 ,60,112,97,103,101,62,10,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110, 116,98,101,99,97,109,101,32,116,104,101,32,102,105,114,115,116,98,97,104,97,115, 97,32,73,110,100,111,110,101,115,105,97,101,110,103,108,105,115,104,32,40,115, 105,109,112,108,101,41,206,149,206,187,206,187,206,183,206,189,206,185,206,186, 206,172,209,133,209,128,208,178,208,176,209,130,209,129,208,186,208,184,208,186, 208,190,208,188,208,191,208,176,208,189,208,184,208,184,209,143,208,178,208,187, 209,143,208,181,209,130,209,129,209,143,208,148,208,190,208,177,208,176,208,178, 208,184,209,130,209,140,209,135,208,181,208,187,208,190,208,178,208,181,208,186, 208,176,209,128,208,176,208,183,208,178,208,184,209,130,208,184,209,143,208,152, 208,189,209,130,208,181,209,128,208,189,208,181,209,130,208,158,209,130,208,178, 208,181,209,130,208,184,209,130,209,140,208,189,208,176,208,191,209,128,208,184, 208,188,208,181,209,128,208,184,208,189,209,130,208,181,209,128,208,189,208,181, 209,130,208,186,208,190,209,130,208,190,209,128,208,190,208,179,208,190,209,129, 209,130,209,128,208,176,208,189,208,184,209,134,209,139,208,186,208,176,209,135, 208,181,209,129,209,130,208,178,208,181,209,131,209,129,208,187,208,190,208,178, 208,184,209,143,209,133,208,191,209,128,208,190,208,177,208,187,208,181,208,188, 209,139,208,191,208,190,208,187,209,131,209,135,208,184,209,130,209,140,209,143, 208,178,208,187,209,143,209,142,209,130,209,129,209,143,208,189,208,176,208,184, 208,177,208,190,208,187,208,181,208,181,208,186,208,190,208,188,208,191,208,176, 208,189,208,184,209,143,208,178,208,189,208,184,208,188,208,176,208,189,208,184, 208,181,209,129,209,128,208,181,208,180,209,129,209,130,208,178,208,176,216,167, 217,132,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,177, 216,166,217,138,216,179,217,138,216,169,216,167,217,132,216,167,217,134,216,170, 217,130,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216,167,216,170, 217,131,216,167,217,132,216,179,217,138,216,167,216,177,216,167,216,170,216,167, 217,132,217,133,217,131,216,170,217,136,216,168,216,169,216,167,217,132,216,179, 216,185,217,136,216,175,217,138,216,169,216,167,216,173,216,181,216,167,216,166, 217,138,216,167,216,170,216,167,217,132,216,185,216,167,217,132,217,133,217,138, 216,169,216,167,217,132,216,181,217,136,216,170,217,138,216,167,216,170,216,167, 217,132,216,167,217,134,216,170,216,177,217,134,216,170,216,167,217,132,216,170, 216,181,216,167,217,133,217,138,217,133,216,167,217,132,216,165,216,179,217,132, 216,167,217,133,217,138,216,167,217,132,217,133,216,180,216,167,216,177,217,131, 216,169,216,167,217,132,217,133,216,177,216,166,217,138,216,167,216,170,114,111, 98,111,116,115,34,32,99,111,110,116,101,110,116,61,34,60,100,105,118,32,105,100, 61,34,102,111,111,116,101,114,34,62,116,104,101,32,85,110,105,116,101,100,32,83, 116,97,116,101,115,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47, 46,106,112,103,124,114,105,103,104,116,124,116,104,117,109,98,124,46,106,115,34, 62,60,47,115,99,114,105,112,116,62,13,10,60,108,111,99,97,116,105,111,110,46,112 ,114,111,116,111,99,111,108,102,114,97,109,101,98,111,114,100,101,114,61,34,48, 34,32,115,34,32,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,60,47,97,62, 60,47,100,105,118,62,60,47,100,105,118,62,60,102,111,110,116,45,119,101,105,103, 104,116,58,98,111,108,100,59,38,113,117,111,116,59,32,97,110,100,32,38,113,117, 111,116,59,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,109, 97,114,103,105,110,58,48,59,112,97,100,100,105,110,103,58,34,32,114,101,108,61, 34,110,111,102,111,108,108,111,119,34,32,80,114,101,115,105,100,101,110,116,32, 111,102,32,116,104,101,32,116,119,101,110,116,105,101,116,104,32,99,101,110,116, 117,114,121,101,118,105,115,105,111,110,62,10,32,32,60,47,112,97,103,101,73,110, 116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,97,46,97,115,121,110, 99,32,61,32,116,114,117,101,59,13,10,105,110,102,111,114,109,97,116,105,111,110, 32,97,98,111,117,116,60,100,105,118,32,105,100,61,34,104,101,97,100,101,114,34, 62,34,32,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,60,97,32,104,114, 101,102,61,34,104,116,116,112,115,58,47,47,60,100,105,118,32,105,100,61,34,99, 111,110,116,101,110,116,34,60,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10 ,60,100,101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32,60,105,109, 103,32,115,114,99,61,39,104,116,116,112,58,47,47,97,99,99,111,114,100,105,110, 103,32,116,111,32,116,104,101,32,10,60,47,98,111,100,121,62,10,60,47,104,116,109 ,108,62,10,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,115, 99,114,105,112,116,32,108,97,110,103,117,97,103,101,61,34,65,114,105,97,108,44, 32,72,101,108,118,101,116,105,99,97,44,60,47,97,62,60,115,112,97,110,32,99,108, 97,115,115,61,34,60,47,115,99,114,105,112,116,62,60,115,99,114,105,112,116,32, 112,111,108,105,116,105,99,97,108,32,112,97,114,116,105,101,115,116,100,62,60,47 ,116,114,62,60,47,116,97,98,108,101,62,60,104,114,101,102,61,34,104,116,116,112, 58,47,47,119,119,119,46,105,110,116,101,114,112,114,101,116,97,116,105,111,110, 32,111,102,114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,100, 111,99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,99,104,97,114,115,101 ,116,61,34,117,116,102,45,56,34,62,10,98,101,103,105,110,110,105,110,103,32,111, 102,32,116,104,101,32,114,101,118,101,97,108,101,100,32,116,104,97,116,32,116, 104,101,116,101,108,101,118,105,115,105,111,110,32,115,101,114,105,101,115,34,32 ,114,101,108,61,34,110,111,102,111,108,108,111,119,34,62,32,116,97,114,103,101, 116,61,34,95,98,108,97,110,107,34,62,99,108,97,105,109,105,110,103,32,116,104,97 ,116,32,116,104,101,104,116,116,112,37,51,65,37,50,70,37,50,70,119,119,119,46, 109,97,110,105,102,101,115,116,97,116,105,111,110,115,32,111,102,80,114,105,109, 101,32,77,105,110,105,115,116,101,114,32,111,102,105,110,102,108,117,101,110,99, 101,100,32,98,121,32,116,104,101,99,108,97,115,115,61,34,99,108,101,97,114,102, 105,120,34,62,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10,13,10,116,104, 114,101,101,45,100,105,109,101,110,115,105,111,110,97,108,67,104,117,114,99,104, 32,111,102,32,69,110,103,108,97,110,100,111,102,32,78,111,114,116,104,32,67,97, 114,111,108,105,110,97,115,113,117,97,114,101,32,107,105,108,111,109,101,116,114 ,101,115,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,101,114,100,105 ,115,116,105,110,99,116,32,102,114,111,109,32,116,104,101,99,111,109,109,111,110 ,108,121,32,107,110,111,119,110,32,97,115,80,104,111,110,101,116,105,99,32,65, 108,112,104,97,98,101,116,100,101,99,108,97,114,101,100,32,116,104,97,116,32,116 ,104,101,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,66,101, 110,106,97,109,105,110,32,70,114,97,110,107,108,105,110,114,111,108,101,45,112, 108,97,121,105,110,103,32,103,97,109,101,116,104,101,32,85,110,105,118,101,114, 115,105,116,121,32,111,102,105,110,32,87,101,115,116,101,114,110,32,69,117,114, 111,112,101,112,101,114,115,111,110,97,108,32,99,111,109,112,117,116,101,114,80, 114,111,106,101,99,116,32,71,117,116,101,110,98,101,114,103,114,101,103,97,114, 100,108,101,115,115,32,111,102,32,116,104,101,104,97,115,32,98,101,101,110,32, 112,114,111,112,111,115,101,100,116,111,103,101,116,104,101,114,32,119,105,116, 104,32,116,104,101,62,60,47,108,105,62,60,108,105,32,99,108,97,115,115,61,34,105 ,110,32,115,111,109,101,32,99,111,117,110,116,114,105,101,115,109,105,110,46,106 ,115,34,62,60,47,115,99,114,105,112,116,62,111,102,32,116,104,101,32,112,111,112 ,117,108,97,116,105,111,110,111,102,102,105,99,105,97,108,32,108,97,110,103,117, 97,103,101,60,105,109,103,32,115,114,99,61,34,105,109,97,103,101,115,47,105,100, 101,110,116,105,102,105,101,100,32,98,121,32,116,104,101,110,97,116,117,114,97, 108,32,114,101,115,111,117,114,99,101,115,99,108,97,115,115,105,102,105,99,97, 116,105,111,110,32,111,102,99,97,110,32,98,101,32,99,111,110,115,105,100,101,114 ,101,100,113,117,97,110,116,117,109,32,109,101,99,104,97,110,105,99,115,78,101, 118,101,114,116,104,101,108,101,115,115,44,32,116,104,101,109,105,108,108,105, 111,110,32,121,101,97,114,115,32,97,103,111,60,47,98,111,100,121,62,13,10,60,47, 104,116,109,108,62,13,206,149,206,187,206,187,206,183,206,189,206,185,206,186, 206,172,10,116,97,107,101,32,97,100,118,97,110,116,97,103,101,32,111,102,97,110, 100,44,32,97,99,99,111,114,100,105,110,103,32,116,111,97,116,116,114,105,98,117, 116,101,100,32,116,111,32,116,104,101,77,105,99,114,111,115,111,102,116,32,87, 105,110,100,111,119,115,116,104,101,32,102,105,114,115,116,32,99,101,110,116,117 ,114,121,117,110,100,101,114,32,116,104,101,32,99,111,110,116,114,111,108,100, 105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,115,104,111,114,116, 108,121,32,97,102,116,101,114,32,116,104,101,110,111,116,97,98,108,101,32,101, 120,99,101,112,116,105,111,110,116,101,110,115,32,111,102,32,116,104,111,117,115 ,97,110,100,115,115,101,118,101,114,97,108,32,100,105,102,102,101,114,101,110, 116,97,114,111,117,110,100,32,116,104,101,32,119,111,114,108,100,46,114,101,97, 99,104,105,110,103,32,109,105,108,105,116,97,114,121,105,115,111,108,97,116,101, 100,32,102,114,111,109,32,116,104,101,111,112,112,111,115,105,116,105,111,110,32 ,116,111,32,116,104,101,116,104,101,32,79,108,100,32,84,101,115,116,97,109,101, 110,116,65,102,114,105,99,97,110,32,65,109,101,114,105,99,97,110,115,105,110,115 ,101,114,116,101,100,32,105,110,116,111,32,116,104,101,115,101,112,97,114,97,116 ,101,32,102,114,111,109,32,116,104,101,109,101,116,114,111,112,111,108,105,116, 97,110,32,97,114,101,97,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98, 108,101,97,99,107,110,111,119,108,101,100,103,101,100,32,116,104,97,116,97,114, 103,117,97,98,108,121,32,116,104,101,32,109,111,115,116,116,121,112,101,61,34, 116,101,120,116,47,99,115,115,34,62,10,116,104,101,32,73,110,116,101,114,110,97, 116,105,111,110,97,108,65,99,99,111,114,100,105,110,103,32,116,111,32,116,104, 101,32,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,99,111,105,110 ,99,105,100,101,32,119,105,116,104,32,116,104,101,116,119,111,45,116,104,105,114 ,100,115,32,111,102,32,116,104,101,68,117,114,105,110,103,32,116,104,105,115,32, 116,105,109,101,44,100,117,114,105,110,103,32,116,104,101,32,112,101,114,105,111 ,100,97,110,110,111,117,110,99,101,100,32,116,104,97,116,32,104,101,116,104,101, 32,105,110,116,101,114,110,97,116,105,111,110,97,108,97,110,100,32,109,111,114, 101,32,114,101,99,101,110,116,108,121,98,101,108,105,101,118,101,100,32,116,104, 97,116,32,116,104,101,99,111,110,115,99,105,111,117,115,110,101,115,115,32,97, 110,100,102,111,114,109,101,114,108,121,32,107,110,111,119,110,32,97,115,115,117 ,114,114,111,117,110,100,101,100,32,98,121,32,116,104,101,102,105,114,115,116,32 ,97,112,112,101,97,114,101,100,32,105,110,111,99,99,97,115,105,111,110,97,108, 108,121,32,117,115,101,100,112,111,115,105,116,105,111,110,58,97,98,115,111,108, 117,116,101,59,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,112 ,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,116,101,120, 116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,106,97,120,47,108,105,98, 115,47,106,113,117,101,114,121,47,49,46,98,97,99,107,103,114,111,117,110,100,45, 99,111,108,111,114,58,35,116,121,112,101,61,34,97,112,112,108,105,99,97,116,105, 111,110,47,97,110,103,117,97,103,101,34,32,99,111,110,116,101,110,116,61,34,60, 109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,80,114,105,118,97 ,99,121,32,80,111,108,105,99,121,60,47,97,62,101,40,34,37,51,67,115,99,114,105, 112,116,32,115,114,99,61,39,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110, 107,34,62,79,110,32,116,104,101,32,111,116,104,101,114,32,104,97,110,100,44,46, 106,112,103,124,116,104,117,109,98,124,114,105,103,104,116,124,50,60,47,100,105, 118,62,60,100,105,118,32,99,108,97,115,115,61,34,60,100,105,118,32,115,116,121, 108,101,61,34,102,108,111,97,116,58,110,105,110,101,116,101,101,110,116,104,32, 99,101,110,116,117,114,121,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108, 62,13,10,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,115,59,116, 101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,102,111,110,116,45, 119,101,105,103,104,116,58,32,98,111,108,100,59,32,65,99,99,111,114,100,105,110, 103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98, 101,116,119,101,101,110,34,32,102,114,97,109,101,98,111,114,100,101,114,61,34,48 ,34,32,34,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,108, 105,110,107,32,104,114,101,102,61,34,104,116,116,112,58,47,47,104,116,109,108,52 ,47,108,111,111,115,101,46,100,116,100,34,62,10,100,117,114,105,110,103,32,116, 104,105,115,32,112,101,114,105,111,100,60,47,116,100,62,60,47,116,114,62,60,47, 116,97,98,108,101,62,99,108,111,115,101,108,121,32,114,101,108,97,116,101,100,32 ,116,111,102,111,114,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,59 ,102,111,110,116,45,119,101,105,103,104,116,58,98,111,108,100,59,105,110,112,117 ,116,32,116,121,112,101,61,34,116,101,120,116,34,32,60,115,112,97,110,32,115,116 ,121,108,101,61,34,102,111,110,116,45,111,110,114,101,97,100,121,115,116,97,116, 101,99,104,97,110,103,101,9,60,100,105,118,32,99,108,97,115,115,61,34,99,108,101 ,97,114,100,111,99,117,109,101,110,116,46,108,111,99,97,116,105,111,110,46,32,70 ,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,97,32,119,105,100, 101,32,118,97,114,105,101,116,121,32,111,102,32,60,33,68,79,67,84,89,80,69,32, 104,116,109,108,62,13,10,60,38,110,98,115,112,59,38,110,98,115,112,59,38,110,98, 115,112,59,34,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,115,116 ,121,108,101,61,34,102,108,111,97,116,58,108,101,102,116,59,99,111,110,99,101, 114,110,101,100,32,119,105,116,104,32,116,104,101,61,104,116,116,112,37,51,65,37 ,50,70,37,50,70,119,119,119,46,105,110,32,112,111,112,117,108,97,114,32,99,117, 108,116,117,114,101,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47 ,62,105,116,32,105,115,32,112,111,115,115,105,98,108,101,32,116,111,32,72,97,114 ,118,97,114,100,32,85,110,105,118,101,114,115,105,116,121,116,121,108,101,115, 104,101,101,116,34,32,104,114,101,102,61,34,47,116,104,101,32,109,97,105,110,32, 99,104,97,114,97,99,116,101,114,79,120,102,111,114,100,32,85,110,105,118,101,114 ,115,105,116,121,32,32,110,97,109,101,61,34,107,101,121,119,111,114,100,115,34, 32,99,115,116,121,108,101,61,34,116,101,120,116,45,97,108,105,103,110,58,116,104 ,101,32,85,110,105,116,101,100,32,75,105,110,103,100,111,109,102,101,100,101,114 ,97,108,32,103,111,118,101,114,110,109,101,110,116,60,100,105,118,32,115,116,121 ,108,101,61,34,109,97,114,103,105,110,32,100,101,112,101,110,100,105,110,103,32, 111,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102, 32,116,104,101,60,100,105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114, 46,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,100,101,115,116, 114,117,99,116,105,111,110,32,111,102,32,116,104,101,115,108,105,103,104,116,108 ,121,32,100,105,102,102,101,114,101,110,116,105,110,32,97,99,99,111,114,100,97, 110,99,101,32,119,105,116,104,116,101,108,101,99,111,109,109,117,110,105,99,97, 116,105,111,110,115,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32,116, 104,101,115,104,111,114,116,108,121,32,116,104,101,114,101,97,102,116,101,114, 101,115,112,101,99,105,97,108,108,121,32,105,110,32,116,104,101,32,69,117,114, 111,112,101,97,110,32,99,111,117,110,116,114,105,101,115,72,111,119,101,118,101, 114,44,32,116,104,101,114,101,32,97,114,101,115,114,99,61,34,104,116,116,112,58, 47,47,115,116,97,116,105,99,115,117,103,103,101,115,116,101,100,32,116,104,97, 116,32,116,104,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,119,119,119, 46,97,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,84,101,108, 101,99,111,109,109,117,110,105,99,97,116,105,111,110,115,34,32,114,101,108,61,34 ,110,111,102,111,108,108,111,119,34,32,116,72,111,108,121,32,82,111,109,97,110, 32,69,109,112,101,114,111,114,97,108,109,111,115,116,32,101,120,99,108,117,115, 105,118,101,108,121,34,32,98,111,114,100,101,114,61,34,48,34,32,97,108,116,61,34 ,83,101,99,114,101,116,97,114,121,32,111,102,32,83,116,97,116,101,99,117,108,109 ,105,110,97,116,105,110,103,32,105,110,32,116,104,101,67,73,65,32,87,111,114,108 ,100,32,70,97,99,116,98,111,111,107,116,104,101,32,109,111,115,116,32,105,109, 112,111,114,116,97,110,116,97,110,110,105,118,101,114,115,97,114,121,32,111,102, 32,116,104,101,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45 ,60,108,105,62,60,101,109,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,65 ,116,108,97,110,116,105,99,32,79,99,101,97,110,115,116,114,105,99,116,108,121,32 ,115,112,101,97,107,105,110,103,44,115,104,111,114,116,108,121,32,98,101,102,111 ,114,101,32,116,104,101,100,105,102,102,101,114,101,110,116,32,116,121,112,101, 115,32,111,102,116,104,101,32,79,116,116,111,109,97,110,32,69,109,112,105,114, 101,62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,65,110,32,73, 110,116,114,111,100,117,99,116,105,111,110,32,116,111,99,111,110,115,101,113,117 ,101,110,99,101,32,111,102,32,116,104,101,100,101,112,97,114,116,117,114,101,32, 102,114,111,109,32,116,104,101,67,111,110,102,101,100,101,114,97,116,101,32,83, 116,97,116,101,115,105,110,100,105,103,101,110,111,117,115,32,112,101,111,112, 108,101,115,80,114,111,99,101,101,100,105,110,103,115,32,111,102,32,116,104,101, 105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,104,101,116,104,101 ,111,114,105,101,115,32,104,97,118,101,32,98,101,101,110,105,110,118,111,108,118 ,101,109,101,110,116,32,105,110,32,116,104,101,100,105,118,105,100,101,100,32, 105,110,116,111,32,116,104,114,101,101,97,100,106,97,99,101,110,116,32,99,111, 117,110,116,114,105,101,115,105,115,32,114,101,115,112,111,110,115,105,98,108, 101,32,102,111,114,100,105,115,115,111,108,117,116,105,111,110,32,111,102,32,116 ,104,101,99,111,108,108,97,98,111,114,97,116,105,111,110,32,119,105,116,104,119, 105,100,101,108,121,32,114,101,103,97,114,100,101,100,32,97,115,104,105,115,32, 99,111,110,116,101,109,112,111,114,97,114,105,101,115,102,111,117,110,100,105, 110,103,32,109,101,109,98,101,114,32,111,102,68,111,109,105,110,105,99,97,110,32 ,82,101,112,117,98,108,105,99,103,101,110,101,114,97,108,108,121,32,97,99,99,101 ,112,116,101,100,116,104,101,32,112,111,115,115,105,98,105,108,105,116,121,32, 111,102,97,114,101,32,97,108,115,111,32,97,118,97,105,108,97,98,108,101,117,110, 100,101,114,32,99,111,110,115,116,114,117,99,116,105,111,110,114,101,115,116,111 ,114,97,116,105,111,110,32,111,102,32,116,104,101,116,104,101,32,103,101,110,101 ,114,97,108,32,112,117,98,108,105,99,105,115,32,97,108,109,111,115,116,32,101, 110,116,105,114,101,108,121,112,97,115,115,101,115,32,116,104,114,111,117,103, 104,32,116,104,101,104,97,115,32,98,101,101,110,32,115,117,103,103,101,115,116, 101,100,99,111,109,112,117,116,101,114,32,97,110,100,32,118,105,100,101,111,71, 101,114,109,97,110,105,99,32,108,97,110,103,117,97,103,101,115,32,97,99,99,111, 114,100,105,110,103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110 ,116,32,102,114,111,109,32,116,104,101,115,104,111,114,116,108,121,32,97,102,116 ,101,114,119,97,114,100,115,104,114,101,102,61,34,104,116,116,112,115,58,47,47, 119,119,119,46,114,101,99,101,110,116,32,100,101,118,101,108,111,112,109,101,110 ,116,66,111,97,114,100,32,111,102,32,68,105,114,101,99,116,111,114,115,60,100, 105,118,32,99,108,97,115,115,61,34,115,101,97,114,99,104,124,32,60,97,32,104,114 ,101,102,61,34,104,116,116,112,58,47,47,73,110,32,112,97,114,116,105,99,117,108, 97,114,44,32,116,104,101,77,117,108,116,105,112,108,101,32,102,111,111,116,110, 111,116,101,115,111,114,32,111,116,104,101,114,32,115,117,98,115,116,97,110,99, 101,116,104,111,117,115,97,110,100,115,32,111,102,32,121,101,97,114,115,116,114, 97,110,115,108,97,116,105,111,110,32,111,102,32,116,104,101,60,47,100,105,118,62 ,13,10,60,47,100,105,118,62,13,10,13,10,60,97,32,104,114,101,102,61,34,105,110, 100,101,120,46,112,104,112,119,97,115,32,101,115,116,97,98,108,105,115,104,101, 100,32,105,110,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10, 112,97,114,116,105,99,105,112,97,116,101,32,105,110,32,116,104,101,97,32,115,116 ,114,111,110,103,32,105,110,102,108,117,101,110,99,101,115,116,121,108,101,61,34 ,109,97,114,103,105,110,45,116,111,112,58,114,101,112,114,101,115,101,110,116, 101,100,32,98,121,32,116,104,101,103,114,97,100,117,97,116,101,100,32,102,114, 111,109,32,116,104,101,84,114,97,100,105,116,105,111,110,97,108,108,121,44,32, 116,104,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,72, 111,119,101,118,101,114,44,32,115,105,110,99,101,32,116,104,101,47,100,105,118, 62,10,60,47,100,105,118,62,10,60,100,105,118,32,108,101,102,116,59,32,109,97,114 ,103,105,110,45,108,101,102,116,58,112,114,111,116,101,99,116,105,111,110,32,97, 103,97,105,110,115,116,48,59,32,118,101,114,116,105,99,97,108,45,97,108,105,103, 110,58,85,110,102,111,114,116,117,110,97,116,101,108,121,44,32,116,104,101,116, 121,112,101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,47,100,105,118,62, 10,60,100,105,118,32,99,108,97,115,115,61,34,32,99,108,97,115,115,61,34,99,108, 101,97,114,102,105,120,34,62,60,100,105,118,32,99,108,97,115,115,61,34,102,111, 111,116,101,114,9,9,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,116,104, 101,32,109,111,116,105,111,110,32,112,105,99,116,117,114,101,208,145,209,138,208 ,187,208,179,208,176,209,128,209,129,208,186,208,184,208,177,209,138,208,187,208 ,179,208,176,209,128,209,129,208,186,208,184,208,164,208,181,208,180,208,181,209 ,128,208,176,209,134,208,184,208,184,208,189,208,181,209,129,208,186,208,190,208 ,187,209,140,208,186,208,190,209,129,208,190,208,190,208,177,209,137,208,181,208 ,189,208,184,208,181,209,129,208,190,208,190,208,177,209,137,208,181,208,189,208 ,184,209,143,208,191,209,128,208,190,208,179,209,128,208,176,208,188,208,188,209 ,139,208,158,209,130,208,191,209,128,208,176,208,178,208,184,209,130,209,140,208 ,177,208,181,209,129,208,191,208,187,208,176,209,130,208,189,208,190,208,188,208 ,176,209,130,208,181,209,128,208,184,208,176,208,187,209,139,208,191,208,190,208 ,183,208,178,208,190,208,187,209,143,208,181,209,130,208,191,208,190,209,129,208 ,187,208,181,208,180,208,189,208,184,208,181,209,128,208,176,208,183,208,187,208 ,184,209,135,208,189,209,139,209,133,208,191,209,128,208,190,208,180,209,131,208 ,186,209,134,208,184,208,184,208,191,209,128,208,190,208,179,209,128,208,176,208 ,188,208,188,208,176,208,191,208,190,208,187,208,189,208,190,209,129,209,130,209 ,140,209,142,208,189,208,176,209,133,208,190,208,180,208,184,209,130,209,129,209 ,143,208,184,208,183,208,177,209,128,208,176,208,189,208,189,208,190,208,181,208 ,189,208,176,209,129,208,181,208,187,208,181,208,189,208,184,209,143,208,184,208 ,183,208,188,208,181,208,189,208,181,208,189,208,184,209,143,208,186,208,176,209 ,130,208,181,208,179,208,190,209,128,208,184,208,184,208,144,208,187,208,181,208 ,186,209,129,208,176,208,189,208,180,209,128,224,164,166,224,165,141,224,164,181 ,224,164,190,224,164,176,224,164,190,224,164,174,224,165,136,224,164,168,224,165 ,129,224,164,133,224,164,178,224,164,170,224,165,141,224,164,176,224,164,166,224 ,164,190,224,164,168,224,164,173,224,164,190,224,164,176,224,164,164,224,165,128 ,224,164,175,224,164,133,224,164,168,224,165,129,224,164,166,224,165,135,224,164 ,182,224,164,185,224,164,191,224,164,168,224,165,141,224,164,166,224,165,128,224 ,164,135,224,164,130,224,164,161,224,164,191,224,164,175,224,164,190,224,164,166 ,224,164,191,224,164,178,224,165,141,224,164,178,224,165,128,224,164,133,224,164 ,167,224,164,191,224,164,149,224,164,190,224,164,176,224,164,181,224,165,128,224 ,164,161,224,164,191,224,164,175,224,165,139,224,164,154,224,164,191,224,164,159 ,224,165,141,224,164,160,224,165,135,224,164,184,224,164,174,224,164,190,224,164 ,154,224,164,190,224,164,176,224,164,156,224,164,130,224,164,149,224,165,141,224 ,164,182,224,164,168,224,164,166,224,165,129,224,164,168,224,164,191,224,164,175 ,224,164,190,224,164,170,224,165,141,224,164,176,224,164,175,224,165,139,224,164 ,151,224,164,133,224,164,168,224,165,129,224,164,184,224,164,190,224,164,176,224 ,164,145,224,164,168,224,164,178,224,164,190,224,164,135,224,164,168,224,164,170 ,224,164,190,224,164,176,224,165,141,224,164,159,224,165,128,224,164,182,224,164 ,176,224,165,141,224,164,164,224,165,139,224,164,130,224,164,178,224,165,139,224 ,164,149,224,164,184,224,164,173,224,164,190,224,164,171,224,164,188,224,165,141 ,224,164,178,224,165,136,224,164,182,224,164,182,224,164,176,224,165,141,224,164 ,164,224,165,135,224,164,130,224,164,170,224,165,141,224,164,176,224,164,166,224 ,165,135,224,164,182,224,164,170,224,165,141,224,164,178,224,165,135,224,164,175 ,224,164,176,224,164,149,224,165,135,224,164,130,224,164,166,224,165,141,224,164 ,176,224,164,184,224,165,141,224,164,165,224,164,191,224,164,164,224,164,191,224 ,164,137,224,164,164,224,165,141,224,164,170,224,164,190,224,164,166,224,164,137 ,224,164,168,224,165,141,224,164,185,224,165,135,224,164,130,224,164,154,224,164 ,191,224,164,159,224,165,141,224,164,160,224,164,190,224,164,175,224,164,190,224 ,164,164,224,165,141,224,164,176,224,164,190,224,164,156,224,165,141,224,164,175 ,224,164,190,224,164,166,224,164,190,224,164,170,224,165,129,224,164,176,224,164 ,190,224,164,168,224,165,135,224,164,156,224,165,139,224,164,161,224,164,188,224 ,165,135,224,164,130,224,164,133,224,164,168,224,165,129,224,164,181,224,164,190 ,224,164,166,224,164,182,224,165,141,224,164,176,224,165,135,224,164,163,224,165 ,128,224,164,182,224,164,191,224,164,149,224,165,141,224,164,183,224,164,190,224 ,164,184,224,164,176,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184 ,224,164,130,224,164,151,224,165,141,224,164,176,224,164,185,224,164,170,224,164 ,176,224,164,191,224,164,163,224,164,190,224,164,174,224,164,172,224,165,141,224 ,164,176,224,164,190,224,164,130,224,164,161,224,164,172,224,164,154,224,165,141 ,224,164,154,224,165,139,224,164,130,224,164,137,224,164,170,224,164,178,224,164 ,172,224,165,141,224,164,167,224,164,174,224,164,130,224,164,164,224,165,141,224 ,164,176,224,165,128,224,164,184,224,164,130,224,164,170,224,164,176,224,165,141 ,224,164,149,224,164,137,224,164,174,224,165,141,224,164,174,224,165,128,224,164 ,166,224,164,174,224,164,190,224,164,167,224,165,141,224,164,175,224,164,174,224 ,164,184,224,164,185,224,164,190,224,164,175,224,164,164,224,164,190,224,164,182 ,224,164,172,224,165,141,224,164,166,224,165,139,224,164,130,224,164,174,224,165 ,128,224,164,161,224,164,191,224,164,175,224,164,190,224,164,134,224,164,136,224 ,164,170,224,165,128,224,164,143,224,164,178,224,164,174,224,165,139,224,164,172 ,224,164,190,224,164,135,224,164,178,224,164,184,224,164,130,224,164,150,224,165 ,141,224,164,175,224,164,190,224,164,134,224,164,170,224,164,176,224,165,135,224 ,164,182,224,164,168,224,164,133,224,164,168,224,165,129,224,164,172,224,164,130 ,224,164,167,224,164,172,224,164,190,224,164,156,224,164,188,224,164,190,224,164 ,176,224,164,168,224,164,181,224,165,128,224,164,168,224,164,164,224,164,174,224 ,164,170,224,165,141,224,164,176,224,164,174,224,165,129,224,164,150,224,164,170 ,224,165,141,224,164,176,224,164,182,224,165,141,224,164,168,224,164,170,224,164 ,176,224,164,191,224,164,181,224,164,190,224,164,176,224,164,168,224,165,129,224 ,164,149,224,164,184,224,164,190,224,164,168,224,164,184,224,164,174,224,164,176 ,224,165,141,224,164,165,224,164,168,224,164,134,224,164,175,224,165,139,224,164 ,156,224,164,191,224,164,164,224,164,184,224,165,139,224,164,174,224,164,181,224 ,164,190,224,164,176,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216 ,167,216,170,216,167,217,132,217,133,217,134,216,170,216,175,217,138,216,167,216 ,170,216,167,217,132,217,131,217,133,216,168,217,138,217,136,216,170,216,177,216 ,167,217,132,217,133,216,180,216,167,217,135,216,175,216,167,216,170,216,185,216 ,175,216,175,216,167,217,132,216,178,217,136,216,167,216,177,216,185,216,175,216 ,175,216,167,217,132,216,177,216,175,217,136,216,175,216,167,217,132,216,165,216 ,179,217,132,216,167,217,133,217,138,216,169,216,167,217,132,217,129,217,136,216 ,170,217,136,216,180,217,136,216,168,216,167,217,132,217,133,216,179,216,167,216 ,168,217,130,216,167,216,170,216,167,217,132,217,133,216,185,217,132,217,136,217 ,133,216,167,216,170,216,167,217,132,217,133,216,179,217,132,216,179,217,132,216 ,167,216,170,216,167,217,132,216,172,216,177,216,167,217,129,217,138,217,131,216 ,179,216,167,217,132,216,167,216,179,217,132,216,167,217,133,217,138,216,169,216 ,167,217,132,216,167,216,170,216,181,216,167,217,132,216,167,216,170,107,101,121 ,119,111,114,100,115,34,32,99,111,110,116,101,110,116,61,34,119,51,46,111,114, 103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,97,32,116,97,114,103,101,116, 61,34,95,98,108,97,110,107,34,32,116,101,120,116,47,104,116,109,108,59,32,99,104 ,97,114,115,101,116,61,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107, 34,62,60,116,97,98,108,101,32,99,101,108,108,112,97,100,100,105,110,103,61,34,97 ,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,116,101,120, 116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,116,111,32,108,97,115, 116,32,118,101,114,115,105,111,110,32,98,121,32,98,97,99,107,103,114,111,117,110 ,100,45,99,111,108,111,114,58,32,35,34,32,104,114,101,102,61,34,104,116,116,112, 58,47,47,119,119,119,46,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,32 ,105,100,61,60,97,32,104,114,101,102,61,34,35,34,32,99,108,97,115,115,61,34,34, 62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,99,114,105,112, 116,34,32,115,114,99,61,34,104,116,116,112,58,47,47,10,60,115,99,114,105,112,116 ,32,108,97,110,103,117,97,103,101,61,34,47,47,69,78,34,32,34,104,116,116,112,58, 47,47,119,119,119,46,119,101,110,99,111,100,101,85,82,73,67,111,109,112,111,110, 101,110,116,40,34,32,104,114,101,102,61,34,106,97,118,97,115,99,114,105,112,116, 58,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,116,101,110,116,100,111, 99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,115,99,112,111,115,105, 116,105,111,110,58,32,97,98,115,111,108,117,116,101,59,115,99,114,105,112,116,32 ,115,114,99,61,34,104,116,116,112,58,47,47,32,115,116,121,108,101,61,34,109,97, 114,103,105,110,45,116,111,112,58,46,109,105,110,46,106,115,34,62,60,47,115,99, 114,105,112,116,62,10,60,47,100,105,118,62,10,60,100,105,118,32,99,108,97,115, 115,61,34,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,32,10, 13,10,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,62,100,105,115,116,105 ,110,99,116,105,111,110,32,98,101,116,119,101,101,110,47,34,32,116,97,114,103, 101,116,61,34,95,98,108,97,110,107,34,62,60,108,105,110,107,32,104,114,101,102, 61,34,104,116,116,112,58,47,47,101,110,99,111,100,105,110,103,61,34,117,116,102, 45,56,34,63,62,10,119,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110, 101,114,63,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,119,119,119,46, 105,99,111,110,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,32,115,116, 121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,58,116,121,112,101,61,34, 116,101,120,116,47,99,115,115,34,32,47,62,10,109,101,116,97,32,112,114,111,112, 101,114,116,121,61,34,111,103,58,116,60,105,110,112,117,116,32,116,121,112,101, 61,34,116,101,120,116,34,32,32,115,116,121,108,101,61,34,116,101,120,116,45,97, 108,105,103,110,58,116,104,101,32,100,101,118,101,108,111,112,109,101,110,116,32 ,111,102,32,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116, 101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,105,115 ,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,116,97,98,108, 101,32,119,105,100,116,104,61,34,49,48,48,37,34,32,73,110,32,97,100,100,105,116, 105,111,110,32,116,111,32,116,104,101,32,99,111,110,116,114,105,98,117,116,101, 100,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,115,32, 98,101,116,119,101,101,110,100,101,118,101,108,111,112,109,101,110,116,32,111, 102,32,116,104,101,32,73,116,32,105,115,32,105,109,112,111,114,116,97,110,116,32 ,116,111,32,60,47,115,99,114,105,112,116,62,10,10,60,115,99,114,105,112,116,32, 32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,62,60,47, 115,112,97,110,62,60,115,112,97,110,32,105,100,61,103,98,76,105,98,114,97,114, 121,32,111,102,32,67,111,110,103,114,101,115,115,60,105,109,103,32,115,114,99,61 ,34,104,116,116,112,58,47,47,105,109,69,110,103,108,105,115,104,32,116,114,97, 110,115,108,97,116,105,111,110,65,99,97,100,101,109,121,32,111,102,32,83,99,105, 101,110,99,101,115,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108, 97,121,58,99,111,110,115,116,114,117,99,116,105,111,110,32,111,102,32,116,104, 101,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,105,100,41,105, 110,32,99,111,110,106,117,110,99,116,105,111,110,32,119,105,116,104,69,108,101, 109,101,110,116,40,39,115,99,114,105,112,116,39,41,59,32,60,109,101,116,97,32, 112,114,111,112,101,114,116,121,61,34,111,103,58,208,145,209,138,208,187,208,179 ,208,176,209,128,209,129,208,186,208,184,10,32,116,121,112,101,61,34,116,101,120 ,116,34,32,110,97,109,101,61,34,62,80,114,105,118,97,99,121,32,80,111,108,105,99 ,121,60,47,97,62,97,100,109,105,110,105,115,116,101,114,101,100,32,98,121,32,116 ,104,101,101,110,97,98,108,101,83,105,110,103,108,101,82,101,113,117,101,115,116 ,115,116,121,108,101,61,38,113,117,111,116,59,109,97,114,103,105,110,58,60,47, 100,105,118,62,60,47,100,105,118,62,60,47,100,105,118,62,60,62,60,105,109,103,32 ,115,114,99,61,34,104,116,116,112,58,47,47,105,32,115,116,121,108,101,61,38,113, 117,111,116,59,102,108,111,97,116,58,114,101,102,101,114,114,101,100,32,116,111, 32,97,115,32,116,104,101,32,116,111,116,97,108,32,112,111,112,117,108,97,116,105 ,111,110,32,111,102,105,110,32,87,97,115,104,105,110,103,116,111,110,44,32,68,46 ,67,46,32,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45,97, 109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,44,111,114,103 ,97,110,105,122,97,116,105,111,110,32,111,102,32,116,104,101,112,97,114,116,105, 99,105,112,97,116,101,100,32,105,110,32,116,104,101,116,104,101,32,105,110,116, 114,111,100,117,99,116,105,111,110,32,111,102,105,100,101,110,116,105,102,105, 101,100,32,119,105,116,104,32,116,104,101,102,105,99,116,105,111,110,97,108,32, 99,104,97,114,97,99,116,101,114,32,79,120,102,111,114,100,32,85,110,105,118,101, 114,115,105,116,121,32,109,105,115,117,110,100,101,114,115,116,97,110,100,105, 110,103,32,111,102,84,104,101,114,101,32,97,114,101,44,32,104,111,119,101,118, 101,114,44,115,116,121,108,101,115,104,101,101,116,34,32,104,114,101,102,61,34, 47,67,111,108,117,109,98,105,97,32,85,110,105,118,101,114,115,105,116,121,101, 120,112,97,110,100,101,100,32,116,111,32,105,110,99,108,117,100,101,117,115,117, 97,108,108,121,32,114,101,102,101,114,114,101,100,32,116,111,105,110,100,105,99, 97,116,105,110,103,32,116,104,97,116,32,116,104,101,104,97,118,101,32,115,117, 103,103,101,115,116,101,100,32,116,104,97,116,97,102,102,105,108,105,97,116,101, 100,32,119,105,116,104,32,116,104,101,99,111,114,114,101,108,97,116,105,111,110, 32,98,101,116,119,101,101,110,110,117,109,98,101,114,32,111,102,32,100,105,102, 102,101,114,101,110,116,62,60,47,116,100,62,60,47,116,114,62,60,47,116,97,98,108 ,101,62,82,101,112,117,98,108,105,99,32,111,102,32,73,114,101,108,97,110,100,10, 60,47,115,99,114,105,112,116,62,10,60,115,99,114,105,112,116,32,117,110,100,101, 114,32,116,104,101,32,105,110,102,108,117,101,110,99,101,99,111,110,116,114,105, 98,117,116,105,111,110,32,116,111,32,116,104,101,79,102,102,105,99,105,97,108,32 ,119,101,98,115,105,116,101,32,111,102,104,101,97,100,113,117,97,114,116,101,114 ,115,32,111,102,32,116,104,101,99,101,110,116,101,114,101,100,32,97,114,111,117, 110,100,32,116,104,101,105,109,112,108,105,99,97,116,105,111,110,115,32,111,102, 32,116,104,101,104,97,118,101,32,98,101,101,110,32,100,101,118,101,108,111,112, 101,100,70,101,100,101,114,97,108,32,82,101,112,117,98,108,105,99,32,111,102,98, 101,99,97,109,101,32,105,110,99,114,101,97,115,105,110,103,108,121,99,111,110, 116,105,110,117,97,116,105,111,110,32,111,102,32,116,104,101,78,111,116,101,44, 32,104,111,119,101,118,101,114,44,32,116,104,97,116,115,105,109,105,108,97,114, 32,116,111,32,116,104,97,116,32,111,102,32,99,97,112,97,98,105,108,105,116,105, 101,115,32,111,102,32,116,104,101,97,99,99,111,114,100,97,110,99,101,32,119,105, 116,104,32,116,104,101,112,97,114,116,105,99,105,112,97,110,116,115,32,105,110, 32,116,104,101,102,117,114,116,104,101,114,32,100,101,118,101,108,111,112,109, 101,110,116,117,110,100,101,114,32,116,104,101,32,100,105,114,101,99,116,105,111 ,110,105,115,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,101,100, 104,105,115,32,121,111,117,110,103,101,114,32,98,114,111,116,104,101,114,60,47, 116,100,62,60,47,116,114,62,60,47,116,97,98,108,101,62,60,97,32,104,116,116,112, 45,101,113,117,105,118,61,34,88,45,85,65,45,112,104,121,115,105,99,97,108,32,112 ,114,111,112,101,114,116,105,101,115,111,102,32,66,114,105,116,105,115,104,32,67 ,111,108,117,109,98,105,97,104,97,115,32,98,101,101,110,32,99,114,105,116,105,99 ,105,122,101,100,40,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105 ,111,110,113,117,101,115,116,105,111,110,115,32,97,98,111,117,116,32,116,104,101 ,112,97,115,115,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,48,34, 32,99,101,108,108,112,97,100,100,105,110,103,61,34,48,34,32,116,104,111,117,115, 97,110,100,115,32,111,102,32,112,101,111,112,108,101,114,101,100,105,114,101,99, 116,115,32,104,101,114,101,46,32,70,111,114,104,97,118,101,32,99,104,105,108,100 ,114,101,110,32,117,110,100,101,114,37,51,69,37,51,67,47,115,99,114,105,112,116, 37,51,69,34,41,41,59,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119 ,119,119,46,60,108,105,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47, 47,115,105,116,101,95,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,116, 101,120,116,45,100,101,99,111,114,97,116,105,111,110,58,110,111,110,101,115,116, 121,108,101,61,34,100,105,115,112,108,97,121,58,32,110,111,110,101,60,109,101, 116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,88,45,110,101,119,32,68, 97,116,101,40,41,46,103,101,116,84,105,109,101,40,41,32,116,121,112,101,61,34, 105,109,97,103,101,47,120,45,105,99,111,110,34,60,47,115,112,97,110,62,60,115, 112,97,110,32,99,108,97,115,115,61,34,108,97,110,103,117,97,103,101,61,34,106,97 ,118,97,115,99,114,105,112,116,119,105,110,100,111,119,46,108,111,99,97,116,105, 111,110,46,104,114,101,102,60,97,32,104,114,101,102,61,34,106,97,118,97,115,99, 114,105,112,116,58,45,45,62,13,10,60,115,99,114,105,112,116,32,116,121,112,101, 61,34,116,60,97,32,104,114,101,102,61,39,104,116,116,112,58,47,47,119,119,119,46 ,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,114,101,102,61,34,60,47, 100,105,118,62,13,10,60,100,105,118,32,99,108,97,115,115,61,34,60,115,99,114,105 ,112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,34,32,114,101,108,61,34, 115,116,121,108,101,115,104,101,101,116,34,32,116,60,47,100,105,118,62,10,60,115 ,99,114,105,112,116,32,116,121,112,101,61,47,97,62,32,60,97,32,104,114,101,102, 61,34,104,116,116,112,58,47,47,32,97,108,108,111,119,84,114,97,110,115,112,97, 114,101,110,99,121,61,34,88,45,85,65,45,67,111,109,112,97,116,105,98,108,101,34, 32,99,111,110,114,101,108,97,116,105,111,110,115,104,105,112,32,98,101,116,119, 101,101,110,10,60,47,115,99,114,105,112,116,62,13,10,60,115,99,114,105,112,116, 32,60,47,97,62,60,47,108,105,62,60,47,117,108,62,60,47,100,105,118,62,97,115,115 ,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,112,114,111,103, 114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,60,47,97,62,60,97,32 ,104,114,101,102,61,34,104,116,116,112,58,47,47,60,47,97,62,60,47,108,105,62,60, 108,105,32,99,108,97,115,115,61,34,102,111,114,109,32,97,99,116,105,111,110,61, 34,104,116,116,112,58,47,47,60,100,105,118,32,115,116,121,108,101,61,34,100,105, 115,112,108,97,121,58,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101 ,61,34,113,34,60,116,97,98,108,101,32,119,105,100,116,104,61,34,49,48,48,37,34, 32,98,97,99,107,103,114,111,117,110,100,45,112,111,115,105,116,105,111,110,58,34 ,32,98,111,114,100,101,114,61,34,48,34,32,119,105,100,116,104,61,34,114,101,108, 61,34,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,54,62,60,117, 108,62,60,108,105,62,60,97,32,104,114,101,102,61,34,32,32,60,109,101,116,97,32, 104,116,116,112,45,101,113,117,105,118,61,34,99,115,115,34,32,109,101,100,105,97 ,61,34,115,99,114,101,101,110,34,32,114,101,115,112,111,110,115,105,98,108,101, 32,102,111,114,32,116,104,101,32,34,32,116,121,112,101,61,34,97,112,112,108,105, 99,97,116,105,111,110,47,34,32,115,116,121,108,101,61,34,98,97,99,107,103,114, 111,117,110,100,45,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116, 102,45,56,34,32,97,108,108,111,119,116,114,97,110,115,112,97,114,101,110,99,121, 61,34,115,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116, 101,13,10,60,109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,62, 60,47,115,112,97,110,62,60,115,112,97,110,32,99,108,97,115,115,61,34,48,34,32,99 ,101,108,108,115,112,97,99,105,110,103,61,34,48,34,62,59,10,60,47,115,99,114,105 ,112,116,62,10,60,115,99,114,105,112,116,32,115,111,109,101,116,105,109,101,115, 32,99,97,108,108,101,100,32,116,104,101,100,111,101,115,32,110,111,116,32,110, 101,99,101,115,115,97,114,105,108,121,70,111,114,32,109,111,114,101,32,105,110, 102,111,114,109,97,116,105,111,110,97,116,32,116,104,101,32,98,101,103,105,110, 110,105,110,103,32,111,102,32,60,33,68,79,67,84,89,80,69,32,104,116,109,108,62, 60,104,116,109,108,112,97,114,116,105,99,117,108,97,114,108,121,32,105,110,32, 116,104,101,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,97,109, 101,61,34,106,97,118,97,115,99,114,105,112,116,58,118,111,105,100,40,48,41,59,34 ,101,102,102,101,99,116,105,118,101,110,101,115,115,32,111,102,32,116,104,101,32 ,97,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,103,101, 110,101,114,97,108,108,121,32,99,111,110,115,105,100,101,114,101,100,62,60,105, 110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,34,62,60,47,115, 99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,116,104,114,111,117,103, 104,111,117,116,32,116,104,101,32,119,111,114,108,100,99,111,109,109,111,110,32, 109,105,115,99,111,110,99,101,112,116,105,111,110,97,115,115,111,99,105,97,116, 105,111,110,32,119,105,116,104,32,116,104,101,60,47,100,105,118,62,10,60,47,100, 105,118,62,10,60,100,105,118,32,99,100,117,114,105,110,103,32,104,105,115,32,108 ,105,102,101,116,105,109,101,44,99,111,114,114,101,115,112,111,110,100,105,110, 103,32,116,111,32,116,104,101,116,121,112,101,61,34,105,109,97,103,101,47,120,45 ,105,99,111,110,34,32,97,110,32,105,110,99,114,101,97,115,105,110,103,32,110,117 ,109,98,101,114,100,105,112,108,111,109,97,116,105,99,32,114,101,108,97,116,105, 111,110,115,97,114,101,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114, 101,100,109,101,116,97,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34, 32,60,105,110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,101,120 ,97,109,112,108,101,115,32,105,110,99,108,117,100,101,32,116,104,101,34,62,60, 105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,105,112,97,114,116,105, 99,105,112,97,116,105,111,110,32,105,110,32,116,104,101,116,104,101,32,101,115, 116,97,98,108,105,115,104,109,101,110,116,32,111,102,10,60,47,100,105,118,62,10, 60,100,105,118,32,99,108,97,115,115,61,34,38,97,109,112,59,110,98,115,112,59,38, 97,109,112,59,110,98,115,112,59,116,111,32,100,101,116,101,114,109,105,110,101, 32,119,104,101,116,104,101,114,113,117,105,116,101,32,100,105,102,102,101,114, 101,110,116,32,102,114,111,109,109,97,114,107,101,100,32,116,104,101,32,98,101, 103,105,110,110,105,110,103,100,105,115,116,97,110,99,101,32,98,101,116,119,101, 101,110,32,116,104,101,99,111,110,116,114,105,98,117,116,105,111,110,115,32,116, 111,32,116,104,101,99,111,110,102,108,105,99,116,32,98,101,116,119,101,101,110, 32,116,104,101,119,105,100,101,108,121,32,99,111,110,115,105,100,101,114,101,100 ,32,116,111,119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,102,105,114, 115,116,119,105,116,104,32,118,97,114,121,105,110,103,32,100,101,103,114,101,101 ,115,104,97,118,101,32,115,112,101,99,117,108,97,116,101,100,32,116,104,97,116, 40,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,112, 97,114,116,105,99,105,112,97,116,105,110,103,32,105,110,32,116,104,101,111,114, 105,103,105,110,97,108,108,121,32,100,101,118,101,108,111,112,101,100,101,116,97 ,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,32,116,121,112,101, 61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,105,110,116,101,114,99,104,97 ,110,103,101,97,98,108,121,32,119,105,116,104,109,111,114,101,32,99,108,111,115, 101,108,121,32,114,101,108,97,116,101,100,115,111,99,105,97,108,32,97,110,100,32 ,112,111,108,105,116,105,99,97,108,116,104,97,116,32,119,111,117,108,100,32,111, 116,104,101,114,119,105,115,101,112,101,114,112,101,110,100,105,99,117,108,97, 114,32,116,111,32,116,104,101,115,116,121,108,101,32,116,121,112,101,61,34,116, 101,120,116,47,99,115,115,116,121,112,101,61,34,115,117,98,109,105,116,34,32,110 ,97,109,101,61,34,102,97,109,105,108,105,101,115,32,114,101,115,105,100,105,110, 103,32,105,110,100,101,118,101,108,111,112,105,110,103,32,99,111,117,110,116,114 ,105,101,115,99,111,109,112,117,116,101,114,32,112,114,111,103,114,97,109,109, 105,110,103,101,99,111,110,111,109,105,99,32,100,101,118,101,108,111,112,109,101 ,110,116,100,101,116,101,114,109,105,110,97,116,105,111,110,32,111,102,32,116, 104,101,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111 ,110,111,110,32,115,101,118,101,114,97,108,32,111,99,99,97,115,105,111,110,115, 112,111,114,116,117,103,117,195,170,115,32,40,69,117,114,111,112,101,117,41,208, 163,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,209, 131,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,208, 160,208,190,209,129,209,129,208,184,208,185,209,129,208,186,208,190,208,185,208, 188,208,176,209,130,208,181,209,128,208,184,208,176,208,187,208,190,208,178,208, 184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,208,184,209, 131,208,191,209,128,208,176,208,178,208,187,208,181,208,189,208,184,209,143,208, 189,208,181,208,190,208,177,209,133,208,190,208,180,208,184,208,188,208,190,208, 184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208, 152,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208, 160,208,181,209,129,208,191,209,131,208,177,208,187,208,184,208,186,208,184,208, 186,208,190,208,187,208,184,209,135,208,181,209,129,209,130,208,178,208,190,208, 184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,142,209, 130,208,181,209,128,209,128,208,184,209,130,208,190,209,128,208,184,208,184,208, 180,208,190,209,129,209,130,208,176,209,130,208,190,209,135,208,189,208,190,216, 167,217,132,217,133,216,170,217,136,216,167,216,172,216,175,217,136,217,134,216, 167,217,132,216,167,216,180,216,170,216,177,216,167,217,131,216,167,216,170,216, 167,217,132,216,167,217,130,216,170,216,177,216,167,216,173,216,167,216,170,104, 116,109,108,59,32,99,104,97,114,115,101,116,61,85,84,70,45,56,34,32,115,101,116, 84,105,109,101,111,117,116,40,102,117,110,99,116,105,111,110,40,41,100,105,115, 112,108,97,121,58,105,110,108,105,110,101,45,98,108,111,99,107,59,60,105,110,112 ,117,116,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,116,121,112,101, 32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,60,105,109,103,32, 115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,46,34,32,34,104,116,116, 112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,115,104,111,114,116,99,117, 116,32,105,99,111,110,34,32,104,114,101,102,61,34,34,32,97,117,116,111,99,111, 109,112,108,101,116,101,61,34,111,102,102,34,32,60,47,97,62,60,47,100,105,118,62 ,60,100,105,118,32,99,108,97,115,115,61,60,47,97,62,60,47,108,105,62,10,60,108, 105,32,99,108,97,115,115,61,34,99,115,115,34,32,116,121,112,101,61,34,116,101, 120,116,47,99,115,115,34,32,60,102,111,114,109,32,97,99,116,105,111,110,61,34, 104,116,116,112,58,47,47,120,116,47,99,115,115,34,32,104,114,101,102,61,34,104, 116,116,112,58,47,47,108,105,110,107,32,114,101,108,61,34,97,108,116,101,114,110 ,97,116,101,34,32,13,10,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116, 101,120,116,47,32,111,110,99,108,105,99,107,61,34,106,97,118,97,115,99,114,105, 112,116,58,40,110,101,119,32,68,97,116,101,41,46,103,101,116,84,105,109,101,40, 41,125,104,101,105,103,104,116,61,34,49,34,32,119,105,100,116,104,61,34,49,34,32 ,80,101,111,112,108,101,39,115,32,82,101,112,117,98,108,105,99,32,111,102,32,32, 60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,116,101, 120,116,45,100,101,99,111,114,97,116,105,111,110,58,117,110,100,101,114,116,104, 101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,60,47,100 ,105,118,62,10,60,47,100,105,118,62,10,60,47,100,105,118,62,10,101,115,116,97,98 ,108,105,115,104,109,101,110,116,32,111,102,32,116,104,101,32,60,47,100,105,118, 62,60,47,100,105,118,62,60,47,100,105,118,62,60,47,100,35,118,105,101,119,112, 111,114,116,123,109,105,110,45,104,101,105,103,104,116,58,10,60,115,99,114,105, 112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,111,112,116,105,111,110,62, 60,111,112,116,105,111,110,32,118,97,108,117,101,61,111,102,116,101,110,32,114, 101,102,101,114,114,101,100,32,116,111,32,97,115,32,47,111,112,116,105,111,110, 62,10,60,111,112,116,105,111,110,32,118,97,108,117,60,33,68,79,67,84,89,80,69,32 ,104,116,109,108,62,10,60,33,45,45,91,73,110,116,101,114,110,97,116,105,111,110, 97,108,32,65,105,114,112,111,114,116,62,10,60,97,32,104,114,101,102,61,34,104, 116,116,112,58,47,47,119,119,119,60,47,97,62,60,97,32,104,114,101,102,61,34,104, 116,116,112,58,47,47,119,224,184,160,224,184,178,224,184,169,224,184,178,224,185 ,132,224,184,151,224,184,162,225,131,165,225,131,144,225,131,160,225,131,151,225 ,131,163,225,131,154,225,131,152,230,173,163,233,171,148,228,184,173,230,150,135 ,32,40,231,185,129,233,171,148,41,224,164,168,224,164,191,224,164,176,224,165, 141,224,164,166,224,165,135,224,164,182,224,164,161,224,164,190,224,164,137,224, 164,168,224,164,178,224,165,139,224,164,161,224,164,149,224,165,141,224,164,183, 224,165,135,224,164,164,224,165,141,224,164,176,224,164,156,224,164,190,224,164, 168,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184,224,164,130,224, 164,172,224,164,130,224,164,167,224,164,191,224,164,164,224,164,184,224,165,141, 224,164,165,224,164,190,224,164,170,224,164,168,224,164,190,224,164,184,224,165, 141,224,164,181,224,165,128,224,164,149,224,164,190,224,164,176,224,164,184,224, 164,130,224,164,184,224,165,141,224,164,149,224,164,176,224,164,163,224,164,184, 224,164,190,224,164,174,224,164,151,224,165,141,224,164,176,224,165,128,224,164, 154,224,164,191,224,164,159,224,165,141,224,164,160,224,165,139,224,164,130,224, 164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164,168, 224,164,133,224,164,174,224,165,135,224,164,176,224,164,191,224,164,149,224,164, 190,224,164,181,224,164,191,224,164,173,224,164,191,224,164,168,224,165,141,224, 164,168,224,164,151,224,164,190,224,164,161,224,164,191,224,164,175,224,164,190, 224,164,129,224,164,149,224,165,141,224,164,175,224,165,139,224,164,130,224,164, 149,224,164,191,224,164,184,224,165,129,224,164,176,224,164,149,224,165,141,224, 164,183,224,164,190,224,164,170,224,164,185,224,165,129,224,164,129,224,164,154, 224,164,164,224,165,128,224,164,170,224,165,141,224,164,176,224,164,172,224,164, 130,224,164,167,224,164,168,224,164,159,224,164,191,224,164,170,224,165,141,224, 164,170,224,164,163,224,165,128,224,164,149,224,165,141,224,164,176,224,164,191, 224,164,149,224,165,135,224,164,159,224,164,170,224,165,141,224,164,176,224,164, 190,224,164,176,224,164,130,224,164,173,224,164,170,224,165,141,224,164,176,224, 164,190,224,164,170,224,165,141,224,164,164,224,164,174,224,164,190,224,164,178, 224,164,191,224,164,149,224,165,139,224,164,130,224,164,176,224,164,171,224,164, 188,224,165,141,224,164,164,224,164,190,224,164,176,224,164,168,224,164,191,224, 164,176,224,165,141,224,164,174,224,164,190,224,164,163,224,164,178,224,164,191, 224,164,174,224,164,191,224,164,159,224,165,135,224,164,161,100,101,115,99,114, 105,112,116,105,111,110,34,32,99,111,110,116,101,110,116,61,34,100,111,99,117, 109,101,110,116,46,108,111,99,97,116,105,111,110,46,112,114,111,116,46,103,101, 116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,60,33,68,79 ,67,84,89,80,69,32,104,116,109,108,62,10,60,104,116,109,108,32,60,109,101,116,97 ,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,58,117,114,108,34,32 ,99,111,110,116,101,110,116,61,34,104,116,116,112,58,47,47,46,99,115,115,34,32, 114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,115,116,121,108,101 ,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,62,116,121,112,101,61 ,34,116,101,120,116,47,99,115,115,34,32,104,114,101,102,61,34,119,51,46,111,114, 103,47,49,57,57,57,47,120,104,116,109,108,34,32,120,109,108,116,121,112,101,61, 34,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,34,32,109,101,116,104 ,111,100,61,34,103,101,116,34,32,97,99,116,105,111,110,61,34,108,105,110,107,32, 114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,32,61,32,100,111 ,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,116,121,112, 101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,34,32,47,62,99,101,108,108 ,112,97,100,100,105,110,103,61,34,48,34,32,99,101,108,108,115,112,46,99,115,115, 34,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,60,47,97,62,60, 47,108,105,62,60,108,105,62,60,97,32,104,114,101,102,61,34,34,32,119,105,100,116 ,104,61,34,49,34,32,104,101,105,103,104,116,61,34,49,34,34,62,60,97,32,104,114, 101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,115,116,121,108,101,61,34, 100,105,115,112,108,97,121,58,110,111,110,101,59,34,62,97,108,116,101,114,110,97 ,116,101,34,32,116,121,112,101,61,34,97,112,112,108,105,45,47,47,87,51,67,47,47, 68,84,68,32,88,72,84,77,76,32,49,46,48,32,101,108,108,115,112,97,99,105,110,103, 61,34,48,34,32,99,101,108,108,112,97,100,32,116,121,112,101,61,34,104,105,100, 100,101,110,34,32,118,97,108,117,101,61,34,47,97,62,38,110,98,115,112,59,60,115, 112,97,110,32,114,111,108,101,61,34,115,10,60,105,110,112,117,116,32,116,121,112 ,101,61,34,104,105,100,100,101,110,34,32,108,97,110,103,117,97,103,101,61,34,74, 97,118,97,83,99,114,105,112,116,34,32,32,100,111,99,117,109,101,110,116,46,103, 101,116,69,108,101,109,101,110,116,115,66,103,61,34,48,34,32,99,101,108,108,115, 112,97,99,105,110,103,61,34,48,34,32,121,112,101,61,34,116,101,120,116,47,99,115 ,115,34,32,109,101,100,105,97,61,34,116,121,112,101,61,39,116,101,120,116,47,106 ,97,118,97,115,99,114,105,112,116,39,119,105,116,104,32,116,104,101,32,101,120, 99,101,112,116,105,111,110,32,111,102,32,121,112,101,61,34,116,101,120,116,47,99 ,115,115,34,32,114,101,108,61,34,115,116,32,104,101,105,103,104,116,61,34,49,34, 32,119,105,100,116,104,61,34,49,34,32,61,39,43,101,110,99,111,100,101,85,82,73, 67,111,109,112,111,110,101,110,116,40,60,108,105,110,107,32,114,101,108,61,34,97 ,108,116,101,114,110,97,116,101,34,32,10,98,111,100,121,44,32,116,114,44,32,105, 110,112,117,116,44,32,116,101,120,116,109,101,116,97,32,110,97,109,101,61,34,114 ,111,98,111,116,115,34,32,99,111,110,109,101,116,104,111,100,61,34,112,111,115, 116,34,32,97,99,116,105,111,110,61,34,62,10,60,97,32,104,114,101,102,61,34,104, 116,116,112,58,47,47,119,119,119,46,99,115,115,34,32,114,101,108,61,34,115,116, 121,108,101,115,104,101,101,116,34,32,60,47,100,105,118,62,60,47,100,105,118,62, 60,100,105,118,32,99,108,97,115,115,108,97,110,103,117,97,103,101,61,34,106,97, 118,97,115,99,114,105,112,116,34,62,97,114,105,97,45,104,105,100,100,101,110,61, 34,116,114,117,101,34,62,194,183,60,114,105,112,116,34,32,116,121,112,101,61,34, 116,101,120,116,47,106,97,118,97,115,108,61,48,59,125,41,40,41,59,10,40,102,117, 110,99,116,105,111,110,40,41,123,98,97,99,107,103,114,111,117,110,100,45,105,109 ,97,103,101,58,32,117,114,108,40,47,97,62,60,47,108,105,62,60,108,105,62,60,97, 32,104,114,101,102,61,34,104,9,9,60,108,105,62,60,97,32,104,114,101,102,61,34, 104,116,116,112,58,47,47,97,116,111,114,34,32,97,114,105,97,45,104,105,100,100, 101,110,61,34,116,114,117,62,32,60,97,32,104,114,101,102,61,34,104,116,116,112, 58,47,47,119,119,119,46,108,97,110,103,117,97,103,101,61,34,106,97,118,97,115,99 ,114,105,112,116,34,32,47,111,112,116,105,111,110,62,10,60,111,112,116,105,111, 110,32,118,97,108,117,101,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118, 32,99,108,97,115,115,61,114,97,116,111,114,34,32,97,114,105,97,45,104,105,100, 100,101,110,61,34,116,114,101,61,40,110,101,119,32,68,97,116,101,41,46,103,101, 116,84,105,109,101,40,41,112,111,114,116,117,103,117,195,170,115,32,40,100,111, 32,66,114,97,115,105,108,41,208,190,209,128,208,179,208,176,208,189,208,184,208, 183,208,176,209,134,208,184,208,184,208,178,208,190,208,183,208,188,208,190,208, 182,208,189,208,190,209,129,209,130,209,140,208,190,208,177,209,128,208,176,208, 183,208,190,208,178,208,176,208,189,208,184,209,143,209,128,208,181,208,179,208, 184,209,129,209,130,209,128,208,176,209,134,208,184,208,184,208,178,208,190,208, 183,208,188,208,190,208,182,208,189,208,190,209,129,209,130,208,184,208,190,208, 177,209,143,208,183,208,176,209,130,208,181,208,187,209,140,208,189,208,176,60, 33,68,79,67,84,89,80,69,32,104,116,109,108,32,80,85,66,76,73,67,32,34,110,116,45 ,84,121,112,101,34,32,99,111,110,116,101,110,116,61,34,116,101,120,116,47,60,109 ,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,116,101, 114,97,110,115,105,116,105,111,110,97,108,47,47,69,78,34,32,34,104,116,116,112, 58,60,104,116,109,108,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119, 119,119,45,47,47,87,51,67,47,47,68,84,68,32,88,72,84,77,76,32,49,46,48,32,84,68, 84,68,47,120,104,116,109,108,49,45,116,114,97,110,115,105,116,105,111,110,97,108 ,47,47,119,119,119,46,119,51,46,111,114,103,47,84,82,47,120,104,116,109,108,49, 47,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116, 39,59,60,109,101,116,97,32,110,97,109,101,61,34,100,101,115,99,114,105,112,116, 105,111,110,112,97,114,101,110,116,78,111,100,101,46,105,110,115,101,114,116,66, 101,102,111,114,101,60,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100, 100,101,110,34,32,110,97,106,115,34,32,116,121,112,101,61,34,116,101,120,116,47, 106,97,118,97,115,99,114,105,40,100,111,99,117,109,101,110,116,41,46,114,101,97, 100,121,40,102,117,110,99,116,105,115,99,114,105,112,116,32,116,121,112,101,61, 34,116,101,120,116,47,106,97,118,97,115,105,109,97,103,101,34,32,99,111,110,116, 101,110,116,61,34,104,116,116,112,58,47,47,85,65,45,67,111,109,112,97,116,105,98 ,108,101,34,32,99,111,110,116,101,110,116,61,116,109,108,59,32,99,104,97,114,115 ,101,116,61,117,116,102,45,56,34,32,47,62,10,108,105,110,107,32,114,101,108,61, 34,115,104,111,114,116,99,117,116,32,105,99,111,110,60,108,105,110,107,32,114, 101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,60,47,115,99,114,105 ,112,116,62,10,60,115,99,114,105,112,116,32,116,121,112,101,61,61,32,100,111,99, 117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,60,97,32,116 ,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,104,114,101,102,61,32,100, 111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,105, 110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61 ,97,46,116,121,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114, 105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110, 97,109,101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56, 34,32,47,62,100,116,100,34,62,10,60,104,116,109,108,32,120,109,108,110,115,61,34 ,104,116,116,112,45,47,47,87,51,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49, 32,84,101,110,116,115,66,121,84,97,103,78,97,109,101,40,39,115,99,114,105,112, 116,39,41,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110, 34,32,110,97,109,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,101,120, 116,47,106,97,118,97,115,34,32,115,116,121,108,101,61,34,100,105,115,112,108,97, 121,58,110,111,110,101,59,34,62,100,111,99,117,109,101,110,116,46,103,101,116,69 ,108,101,109,101,110,116,66,121,73,100,40,61,100,111,99,117,109,101,110,116,46, 99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,32,116,121,112,101,61,39, 116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,105,110,112,117,116, 32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61,34,100,46,103, 101,116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,115,110 ,105,99,97,108,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119, 46,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,32,84,114,97,110,115,105,116, 60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34 ,62,10,10,60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99, 115,115,34,62,105,111,110,97,108,46,100,116,100,34,62,10,60,104,116,109,108,32, 120,109,108,110,115,61,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110, 116,101,110,116,45,84,121,112,101,100,105,110,103,61,34,48,34,32,99,101,108,108, 115,112,97,99,105,110,103,61,34,48,34,104,116,109,108,59,32,99,104,97,114,115, 101,116,61,117,116,102,45,56,34,32,47,62,10,32,115,116,121,108,101,61,34,100,105 ,115,112,108,97,121,58,110,111,110,101,59,34,62,60,60,108,105,62,60,97,32,104, 114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,32,116,121,112,101,61, 39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,62,208,180,208,181 ,209,143,209,130,208,181,208,187,209,140,208,189,208,190,209,129,209,130,208,184 ,209,129,208,190,208,190,209,130,208,178,208,181,209,130,209,129,209,130,208,178 ,208,184,208,184,208,191,209,128,208,190,208,184,208,183,208,178,208,190,208,180 ,209,129,209,130,208,178,208,176,208,177,208,181,208,183,208,190,208,191,208,176 ,209,129,208,189,208,190,209,129,209,130,208,184,224,164,170,224,165,129,224,164 ,184,224,165,141,224,164,164,224,164,191,224,164,149,224,164,190,224,164,149,224 ,164,190,224,164,130,224,164,151,224,165,141,224,164,176,224,165,135,224,164,184 ,224,164,137,224,164,168,224,165,141,224,164,185,224,165,139,224,164,130,224,164 ,168,224,165,135,224,164,181,224,164,191,224,164,167,224,164,190,224,164,168,224 ,164,184,224,164,173,224,164,190,224,164,171,224,164,191,224,164,149,224,165,141 ,224,164,184,224,164,191,224,164,130,224,164,151,224,164,184,224,165,129,224,164 ,176,224,164,149,224,165,141,224,164,183,224,164,191,224,164,164,224,164,149,224 ,165,137,224,164,170,224,165,128,224,164,176,224,164,190,224,164,135,224,164,159 ,224,164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164 ,170,224,164,168,224,164,149,224,164,190,224,164,176,224,165,141,224,164,176,224 ,164,181,224,164,190,224,164,136,224,164,184,224,164,149,224,165,141,224,164,176 ,224,164,191,224,164,175,224,164,164,224,164,190 } /* GENERATED CODE END */ ; #endif /* !BROTLI_EXTERNAL_DICTIONARY_DATA */ #if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA) static const BrotliDictionary kBrotliDictionary = { #else static BrotliDictionary kBrotliDictionary = { #endif /* size_bits_by_length */ { 0, 0, 0, 0, 10, 10, 11, 11, 10, 10, 10, 10, 10, 9, 9, 8, 7, 7, 8, 7, 7, 6, 6, 5, 5, 0, 0, 0, 0, 0, 0, 0 }, /* offsets_by_length */ { 0, 0, 0, 0, 0, 4096, 9216, 21504, 35840, 44032, 53248, 63488, 74752, 87040, 93696, 100864, 104704, 106752, 108928, 113536, 115968, 118528, 119872, 121280, 122016, 122784, 122784, 122784, 122784, 122784, 122784, 122784 }, /* data_size == sizeof(kBrotliDictionaryData) */ 122784, /* data */ #if defined(BROTLI_EXTERNAL_DICTIONARY_DATA) NULL #else kBrotliDictionaryData #endif }; const BrotliDictionary* BrotliGetDictionary(void) { return &kBrotliDictionary; } void BrotliSetDictionaryData(const uint8_t* data) { #if defined(BROTLI_EXTERNAL_DICTIONARY_DATA) if (!!data && !kBrotliDictionary.data) { kBrotliDictionary.data = data; } #else BROTLI_UNUSED(data); // Appease -Werror=unused-parameter #endif } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/common/dictionary.h000066400000000000000000000036371501401750600211020ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Collection of static dictionary words. */ #ifndef BROTLI_COMMON_DICTIONARY_H_ #define BROTLI_COMMON_DICTIONARY_H_ #include #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct BrotliDictionary { /** * Number of bits to encode index of dictionary word in a bucket. * * Specification: Appendix A. Static Dictionary Data * * Words in a dictionary are bucketed by length. * @c 0 means that there are no words of a given length. * Dictionary consists of words with length of [4..24] bytes. * Values at [0..3] and [25..31] indices should not be addressed. */ uint8_t size_bits_by_length[32]; /* assert(offset[i + 1] == offset[i] + (bits[i] ? (i << bits[i]) : 0)) */ uint32_t offsets_by_length[32]; /* assert(data_size == offsets_by_length[31]) */ size_t data_size; /* Data array is not bound, and should obey to size_bits_by_length values. Specified size matches default (RFC 7932) dictionary. Its size is defined by data_size */ const uint8_t* data; } BrotliDictionary; BROTLI_COMMON_API const BrotliDictionary* BrotliGetDictionary(void); /** * Sets dictionary data. * * When dictionary data is already set / present, this method is no-op. * * Dictionary data MUST be provided before BrotliGetDictionary is invoked. * This method is used ONLY in multi-client environment (e.g. C + Java), * to reduce storage by sharing single dictionary between implementations. */ BROTLI_COMMON_API void BrotliSetDictionaryData(const uint8_t* data); #define BROTLI_MIN_DICTIONARY_WORD_LENGTH 4 #define BROTLI_MAX_DICTIONARY_WORD_LENGTH 24 #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_COMMON_DICTIONARY_H_ */ dvisvgm-3.5/libs/brotli/common/platform.c000066400000000000000000000010011501401750600205330ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include #include #include "platform.h" /* Default brotli_alloc_func */ void* BrotliDefaultAllocFunc(void* opaque, size_t size) { BROTLI_UNUSED(opaque); return malloc(size); } /* Default brotli_free_func */ void BrotliDefaultFreeFunc(void* opaque, void* address) { BROTLI_UNUSED(opaque); free(address); } dvisvgm-3.5/libs/brotli/common/platform.h000066400000000000000000000445731501401750600205650ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Macros for compiler / platform specific features and build options. Build options are: * BROTLI_BUILD_32_BIT disables 64-bit optimizations * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs * BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read optimizations (mainly for testing purposes) * BROTLI_DEBUG dumps file name and line number when decoder detects stream or memory error * BROTLI_ENABLE_LOG enables asserts and dumps various state information * BROTLI_ENABLE_DUMP overrides default "dump" behaviour */ #ifndef BROTLI_COMMON_PLATFORM_H_ #define BROTLI_COMMON_PLATFORM_H_ #include /* memcpy */ #include #include #if defined(OS_LINUX) || defined(OS_CYGWIN) || defined(__EMSCRIPTEN__) #include #elif defined(OS_FREEBSD) #include #elif defined(OS_MACOSX) #include /* Let's try and follow the Linux convention */ #define BROTLI_X_BYTE_ORDER BYTE_ORDER #define BROTLI_X_LITTLE_ENDIAN LITTLE_ENDIAN #define BROTLI_X_BIG_ENDIAN BIG_ENDIAN #endif #if BROTLI_MSVC_VERSION_CHECK(18, 0, 0) #include #endif #if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG) #include #include #endif /* The following macros were borrowed from https://github.com/nemequ/hedley * with permission of original author - Evan Nemerson */ /* >>> >>> >>> hedley macros */ /* Define "BROTLI_PREDICT_TRUE" and "BROTLI_PREDICT_FALSE" macros for capable compilers. To apply compiler hint, enclose the branching condition into macros, like this: if (BROTLI_PREDICT_TRUE(zero == 0)) { // main execution path } else { // compiler should place this code outside of main execution path } OR: if (BROTLI_PREDICT_FALSE(something_rare_or_unexpected_happens)) { // compiler should place this code outside of main execution path } */ #if BROTLI_GNUC_HAS_BUILTIN(__builtin_expect, 3, 0, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ BROTLI_SUNPRO_VERSION_CHECK(5, 15, 0) || \ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ BROTLI_TI_VERSION_CHECK(7, 3, 0) || \ BROTLI_TINYC_VERSION_CHECK(0, 9, 27) #define BROTLI_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) #define BROTLI_PREDICT_FALSE(x) (__builtin_expect(x, 0)) #else #define BROTLI_PREDICT_FALSE(x) (x) #define BROTLI_PREDICT_TRUE(x) (x) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ !defined(__cplusplus) #define BROTLI_RESTRICT restrict #elif BROTLI_GNUC_VERSION_CHECK(3, 1, 0) || \ BROTLI_MSVC_VERSION_CHECK(14, 0, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ BROTLI_PGI_VERSION_CHECK(17, 10, 0) || \ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ BROTLI_IAR_VERSION_CHECK(8, 0, 0) || \ (BROTLI_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) #define BROTLI_RESTRICT __restrict #elif BROTLI_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus) #define BROTLI_RESTRICT _Restrict #else #define BROTLI_RESTRICT #endif #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ (defined(__cplusplus) && (__cplusplus >= 199711L)) #define BROTLI_MAYBE_INLINE inline #elif defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__) || \ BROTLI_ARM_VERSION_CHECK(6, 2, 0) #define BROTLI_MAYBE_INLINE __inline__ #elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) || \ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || BROTLI_TI_VERSION_CHECK(8, 0, 0) #define BROTLI_MAYBE_INLINE __inline #else #define BROTLI_MAYBE_INLINE #endif #if BROTLI_GNUC_HAS_ATTRIBUTE(always_inline, 4, 0, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) #define BROTLI_INLINE BROTLI_MAYBE_INLINE __attribute__((__always_inline__)) #elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) #define BROTLI_INLINE BROTLI_MAYBE_INLINE __forceinline #elif BROTLI_TI_VERSION_CHECK(7, 0, 0) && defined(__cplusplus) #define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("FUNC_ALWAYS_INLINE;") #elif BROTLI_IAR_VERSION_CHECK(8, 0, 0) #define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("inline=forced") #else #define BROTLI_INLINE BROTLI_MAYBE_INLINE #endif #if BROTLI_GNUC_HAS_ATTRIBUTE(noinline, 4, 0, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) #define BROTLI_NOINLINE __attribute__((__noinline__)) #elif BROTLI_MSVC_VERSION_CHECK(13, 10, 0) #define BROTLI_NOINLINE __declspec(noinline) #elif BROTLI_PGI_VERSION_CHECK(10, 2, 0) #define BROTLI_NOINLINE _Pragma("noinline") #elif BROTLI_TI_VERSION_CHECK(6, 0, 0) && defined(__cplusplus) #define BROTLI_NOINLINE _Pragma("FUNC_CANNOT_INLINE;") #elif BROTLI_IAR_VERSION_CHECK(8, 0, 0) #define BROTLI_NOINLINE _Pragma("inline=never") #else #define BROTLI_NOINLINE #endif /* <<< <<< <<< end of hedley macros. */ #if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) #define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE __attribute__ ((unused)) #else #define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE #endif #if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) #define BROTLI_ALIGNED(N) __attribute__((aligned(N))) #else #define BROTLI_ALIGNED(N) #endif #if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \ (defined(M_ARM) && (M_ARM == 7)) #define BROTLI_TARGET_ARMV7 #endif /* ARMv7 */ #if (defined(__ARM_ARCH) && (__ARM_ARCH == 8)) || \ defined(__aarch64__) || defined(__ARM64_ARCH_8__) #define BROTLI_TARGET_ARMV8_ANY #if defined(__ARM_32BIT_STATE) #define BROTLI_TARGET_ARMV8_32 #elif defined(__ARM_64BIT_STATE) #define BROTLI_TARGET_ARMV8_64 #endif #endif /* ARMv8 */ #if defined(__ARM_NEON__) || defined(__ARM_NEON) #define BROTLI_TARGET_NEON #endif #if defined(__i386) || defined(_M_IX86) #define BROTLI_TARGET_X86 #endif #if defined(__x86_64__) || defined(_M_X64) #define BROTLI_TARGET_X64 #endif #if defined(__PPC64__) #define BROTLI_TARGET_POWERPC64 #endif #if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64 #define BROTLI_TARGET_RISCV64 #endif #if defined(__loongarch_lp64) #define BROTLI_TARGET_LOONGARCH64 #endif #if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \ defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) || \ defined(BROTLI_TARGET_LOONGARCH64) #define BROTLI_TARGET_64_BITS 1 #else #define BROTLI_TARGET_64_BITS 0 #endif #if defined(BROTLI_BUILD_64_BIT) #define BROTLI_64_BITS 1 #elif defined(BROTLI_BUILD_32_BIT) #define BROTLI_64_BITS 0 #else #define BROTLI_64_BITS BROTLI_TARGET_64_BITS #endif #if (BROTLI_64_BITS) #define brotli_reg_t uint64_t #else #define brotli_reg_t uint32_t #endif #if defined(BROTLI_BUILD_BIG_ENDIAN) #define BROTLI_BIG_ENDIAN 1 #elif defined(BROTLI_BUILD_LITTLE_ENDIAN) #define BROTLI_LITTLE_ENDIAN 1 #elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL) /* Just break elif chain. */ #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #define BROTLI_LITTLE_ENDIAN 1 #elif defined(_WIN32) || defined(BROTLI_TARGET_X64) /* Win32 & x64 can currently always be assumed to be little endian */ #define BROTLI_LITTLE_ENDIAN 1 #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #define BROTLI_BIG_ENDIAN 1 #elif defined(BROTLI_X_BYTE_ORDER) #if BROTLI_X_BYTE_ORDER == BROTLI_X_LITTLE_ENDIAN #define BROTLI_LITTLE_ENDIAN 1 #elif BROTLI_X_BYTE_ORDER == BROTLI_X_BIG_ENDIAN #define BROTLI_BIG_ENDIAN 1 #endif #endif /* BROTLI_X_BYTE_ORDER */ #if !defined(BROTLI_LITTLE_ENDIAN) #define BROTLI_LITTLE_ENDIAN 0 #endif #if !defined(BROTLI_BIG_ENDIAN) #define BROTLI_BIG_ENDIAN 0 #endif #if defined(BROTLI_X_BYTE_ORDER) #undef BROTLI_X_BYTE_ORDER #undef BROTLI_X_LITTLE_ENDIAN #undef BROTLI_X_BIG_ENDIAN #endif #if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST) #define BROTLI_UNALIGNED_READ_FAST (!!0) #elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \ defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \ defined(BROTLI_TARGET_RISCV64) || defined(BROTLI_TARGET_LOONGARCH64) /* These targets are known to generate efficient code for unaligned reads * (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd * together). */ #define BROTLI_UNALIGNED_READ_FAST (!!1) #else #define BROTLI_UNALIGNED_READ_FAST (!!0) #endif /* Portable unaligned memory access: read / write values via memcpy. */ static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) { uint16_t t; memcpy(&t, p, sizeof t); return t; } static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) { uint32_t t; memcpy(&t, p, sizeof t); return t; } static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) { uint64_t t; memcpy(&t, p, sizeof t); return t; } static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) { memcpy(p, &v, sizeof v); } #if BROTLI_LITTLE_ENDIAN /* Straight endianness. Just read / write values. */ #define BROTLI_UNALIGNED_LOAD16LE BrotliUnalignedRead16 #define BROTLI_UNALIGNED_LOAD32LE BrotliUnalignedRead32 #define BROTLI_UNALIGNED_LOAD64LE BrotliUnalignedRead64 #define BROTLI_UNALIGNED_STORE64LE BrotliUnalignedWrite64 #elif BROTLI_BIG_ENDIAN /* BROTLI_LITTLE_ENDIAN */ /* Explain compiler to byte-swap values. */ #define BROTLI_BSWAP16_(V) ((uint16_t)( \ (((V) & 0xFFU) << 8) | \ (((V) >> 8) & 0xFFU))) static BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) { uint16_t value = BrotliUnalignedRead16(p); return BROTLI_BSWAP16_(value); } #define BROTLI_BSWAP32_(V) ( \ (((V) & 0xFFU) << 24) | (((V) & 0xFF00U) << 8) | \ (((V) >> 8) & 0xFF00U) | (((V) >> 24) & 0xFFU)) static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) { uint32_t value = BrotliUnalignedRead32(p); return BROTLI_BSWAP32_(value); } #define BROTLI_BSWAP64_(V) ( \ (((V) & 0xFFU) << 56) | (((V) & 0xFF00U) << 40) | \ (((V) & 0xFF0000U) << 24) | (((V) & 0xFF000000U) << 8) | \ (((V) >> 8) & 0xFF000000U) | (((V) >> 24) & 0xFF0000U) | \ (((V) >> 40) & 0xFF00U) | (((V) >> 56) & 0xFFU)) static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) { uint64_t value = BrotliUnalignedRead64(p); return BROTLI_BSWAP64_(value); } static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) { uint64_t value = BROTLI_BSWAP64_(v); BrotliUnalignedWrite64(p, value); } #else /* BROTLI_LITTLE_ENDIAN */ /* Read / store values byte-wise; hopefully compiler will understand. */ static BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) { const uint8_t* in = (const uint8_t*)p; return (uint16_t)(in[0] | (in[1] << 8)); } static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) { const uint8_t* in = (const uint8_t*)p; uint32_t value = (uint32_t)(in[0]); value |= (uint32_t)(in[1]) << 8; value |= (uint32_t)(in[2]) << 16; value |= (uint32_t)(in[3]) << 24; return value; } static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) { const uint8_t* in = (const uint8_t*)p; uint64_t value = (uint64_t)(in[0]); value |= (uint64_t)(in[1]) << 8; value |= (uint64_t)(in[2]) << 16; value |= (uint64_t)(in[3]) << 24; value |= (uint64_t)(in[4]) << 32; value |= (uint64_t)(in[5]) << 40; value |= (uint64_t)(in[6]) << 48; value |= (uint64_t)(in[7]) << 56; return value; } static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) { uint8_t* out = (uint8_t*)p; out[0] = (uint8_t)v; out[1] = (uint8_t)(v >> 8); out[2] = (uint8_t)(v >> 16); out[3] = (uint8_t)(v >> 24); out[4] = (uint8_t)(v >> 32); out[5] = (uint8_t)(v >> 40); out[6] = (uint8_t)(v >> 48); out[7] = (uint8_t)(v >> 56); } #endif /* BROTLI_LITTLE_ENDIAN */ static BROTLI_INLINE void* BROTLI_UNALIGNED_LOAD_PTR(const void* p) { void* v; memcpy(&v, p, sizeof(void*)); return v; } static BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR(void* p, const void* v) { memcpy(p, &v, sizeof(void*)); } /* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */ #if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) #define BROTLI_IS_CONSTANT(x) (!!__builtin_constant_p(x)) #else #define BROTLI_IS_CONSTANT(x) (!!0) #endif #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) #define BROTLI_HAS_UBFX (!!1) #else #define BROTLI_HAS_UBFX (!!0) #endif #if defined(BROTLI_ENABLE_LOG) #define BROTLI_LOG(x) printf x #else #define BROTLI_LOG(x) #endif #if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG) #define BROTLI_ENABLE_DUMP_DEFAULT 1 #define BROTLI_DCHECK(x) assert(x) #else #define BROTLI_ENABLE_DUMP_DEFAULT 0 #define BROTLI_DCHECK(x) #endif #if !defined(BROTLI_ENABLE_DUMP) #define BROTLI_ENABLE_DUMP BROTLI_ENABLE_DUMP_DEFAULT #endif #if BROTLI_ENABLE_DUMP static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) { fprintf(stderr, "%s:%d (%s)\n", f, l, fn); fflush(stderr); } #define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__) #else #define BROTLI_DUMP() (void)(0) #endif /* BrotliRBit assumes brotli_reg_t fits native CPU register type. */ #if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS) /* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */ #if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \ !defined(BROTLI_BUILD_NO_RBIT) #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) /* TODO(eustas): detect ARMv6T2 and enable this code for it. */ static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) { brotli_reg_t output; __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input)); return output; } #define BROTLI_RBIT(x) BrotliRBit(x) #endif /* armv7 / armv8 */ #endif /* gcc || clang */ #endif /* brotli_reg_t is native */ #if !defined(BROTLI_RBIT) static BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ } #endif /* BROTLI_RBIT */ #define BROTLI_REPEAT_4(X) {X; X; X; X;} #define BROTLI_REPEAT_5(X) {X; X; X; X; X;} #define BROTLI_REPEAT_6(X) {X; X; X; X; X; X;} #define BROTLI_UNUSED(X) (void)(X) #define BROTLI_MIN_MAX(T) \ static BROTLI_INLINE T brotli_min_ ## T (T a, T b) { return a < b ? a : b; } \ static BROTLI_INLINE T brotli_max_ ## T (T a, T b) { return a > b ? a : b; } BROTLI_MIN_MAX(double) BROTLI_MIN_MAX(float) BROTLI_MIN_MAX(int) BROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t) #undef BROTLI_MIN_MAX #define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B))) #define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B))) #define BROTLI_SWAP(T, A, I, J) { \ T __brotli_swap_tmp = (A)[(I)]; \ (A)[(I)] = (A)[(J)]; \ (A)[(J)] = __brotli_swap_tmp; \ } #if BROTLI_64_BITS #if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) #define BROTLI_TZCNT64 __builtin_ctzll #elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0) #if defined(BROTLI_TARGET_X64) #define BROTLI_TZCNT64 _tzcnt_u64 #else /* BROTLI_TARGET_X64 */ static BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) { uint32_t lsb; _BitScanForward64(&lsb, x); return lsb; } #define BROTLI_TZCNT64 BrotliBsf64Msvc #endif /* BROTLI_TARGET_X64 */ #endif /* __builtin_ctzll */ #endif /* BROTLI_64_BITS */ #if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) #define BROTLI_BSR32(x) (31u ^ (uint32_t)__builtin_clz(x)) #elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0) static BROTLI_INLINE uint32_t BrotliBsr32Msvc(uint32_t x) { unsigned long msb; _BitScanReverse(&msb, x); return (uint32_t)msb; } #define BROTLI_BSR32 BrotliBsr32Msvc #endif /* __builtin_clz */ /* Default brotli_alloc_func */ BROTLI_COMMON_API void* BrotliDefaultAllocFunc(void* opaque, size_t size); /* Default brotli_free_func */ BROTLI_COMMON_API void BrotliDefaultFreeFunc(void* opaque, void* address); BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) { BROTLI_UNUSED(&BrotliSuppressUnusedFunctions); BROTLI_UNUSED(&BrotliUnalignedRead16); BROTLI_UNUSED(&BrotliUnalignedRead32); BROTLI_UNUSED(&BrotliUnalignedRead64); BROTLI_UNUSED(&BrotliUnalignedWrite64); BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD16LE); BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE); BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE); BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE); BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD_PTR); BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE_PTR); BROTLI_UNUSED(&BrotliRBit); BROTLI_UNUSED(&brotli_min_double); BROTLI_UNUSED(&brotli_max_double); BROTLI_UNUSED(&brotli_min_float); BROTLI_UNUSED(&brotli_max_float); BROTLI_UNUSED(&brotli_min_int); BROTLI_UNUSED(&brotli_max_int); BROTLI_UNUSED(&brotli_min_size_t); BROTLI_UNUSED(&brotli_max_size_t); BROTLI_UNUSED(&brotli_min_uint32_t); BROTLI_UNUSED(&brotli_max_uint32_t); BROTLI_UNUSED(&brotli_min_uint8_t); BROTLI_UNUSED(&brotli_max_uint8_t); BROTLI_UNUSED(&BrotliDefaultAllocFunc); BROTLI_UNUSED(&BrotliDefaultFreeFunc); #if BROTLI_ENABLE_DUMP BROTLI_UNUSED(&BrotliDump); #endif } #endif /* BROTLI_COMMON_PLATFORM_H_ */ dvisvgm-3.5/libs/brotli/common/shared_dictionary_internal.h000066400000000000000000000045551501401750600243240ustar00rootroot00000000000000/* Copyright 2017 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* (Transparent) Shared Dictionary definition. */ #ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ #define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ #include #include #include "dictionary.h" #include "transform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif struct BrotliSharedDictionaryStruct { /* LZ77 prefixes (compound dictionary). */ uint32_t num_prefix; /* max SHARED_BROTLI_MAX_COMPOUND_DICTS */ size_t prefix_size[SHARED_BROTLI_MAX_COMPOUND_DICTS]; const uint8_t* prefix[SHARED_BROTLI_MAX_COMPOUND_DICTS]; /* If set, the context map is used to select word and transform list from 64 contexts, if not set, the context map is not used and only words[0] and transforms[0] are to be used. */ BROTLI_BOOL context_based; uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; /* Amount of word_list+transform_list combinations. */ uint8_t num_dictionaries; /* Must use num_dictionaries values. */ const BrotliDictionary* words[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; /* Must use num_dictionaries values. */ const BrotliTransforms* transforms[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; /* Amount of custom word lists. May be 0 if only Brotli's built-in is used */ uint8_t num_word_lists; /* Contents of the custom words lists. Must be NULL if num_word_lists is 0. */ BrotliDictionary* words_instances; /* Amount of custom transform lists. May be 0 if only Brotli's built-in is used */ uint8_t num_transform_lists; /* Contents of the custom transform lists. Must be NULL if num_transform_lists is 0. */ BrotliTransforms* transforms_instances; /* Concatenated prefix_suffix_maps of the custom transform lists. Must be NULL if num_transform_lists is 0. */ uint16_t* prefix_suffix_maps; /* Memory management */ brotli_alloc_func alloc_func; brotli_free_func free_func; void* memory_manager_opaque; }; typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionaryInternal; #define BrotliSharedDictionary BrotliSharedDictionaryInternal #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ */ dvisvgm-3.5/libs/brotli/common/transform.c000066400000000000000000000246651501401750600207470ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "transform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* RFC 7932 transforms string data */ static const char kPrefixSuffix[217] = "\1 \2, \10 of the \4 of \2s \1.\5 and \4 " /* 0x _0 _2 __5 _E _3 _6 _8 _E */ "in \1\"\4 to \2\">\1\n\2. \1]\5 for \3 a \6 " /* 2x _3_ _5 _A_ _D_ _F _2 _4 _A _E */ "that \1\'\6 with \6 from \4 by \1(\6. T" /* 4x _5_ _7 _E _5 _A _C */ "he \4 on \4 as \4 is \4ing \2\n\t\1:\3ed " /* 6x _3 _8 _D _2 _7_ _ _A _C */ "\2=\"\4 at \3ly \1,\2=\'\5.com/\7. This \5" /* 8x _0 _ _3 _8 _C _E _ _1 _7 _F */ " not \3er \3al \4ful \4ive \5less \4es" /* Ax _5 _9 _D _2 _7 _D */ "t \4ize \2\xc2\xa0\4ous \5 the \2e "; /* \0 - implicit trailing zero. */ /* Cx _2 _7___ ___ _A _F _5 _8 */ static const uint16_t kPrefixSuffixMap[50] = { 0x00, 0x02, 0x05, 0x0E, 0x13, 0x16, 0x18, 0x1E, 0x23, 0x25, 0x2A, 0x2D, 0x2F, 0x32, 0x34, 0x3A, 0x3E, 0x45, 0x47, 0x4E, 0x55, 0x5A, 0x5C, 0x63, 0x68, 0x6D, 0x72, 0x77, 0x7A, 0x7C, 0x80, 0x83, 0x88, 0x8C, 0x8E, 0x91, 0x97, 0x9F, 0xA5, 0xA9, 0xAD, 0xB2, 0xB7, 0xBD, 0xC2, 0xC7, 0xCA, 0xCF, 0xD5, 0xD8 }; /* RFC 7932 transforms */ static const uint8_t kTransformsData[] = { 49, BROTLI_TRANSFORM_IDENTITY, 49, 49, BROTLI_TRANSFORM_IDENTITY, 0, 0, BROTLI_TRANSFORM_IDENTITY, 0, 49, BROTLI_TRANSFORM_OMIT_FIRST_1, 49, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0, 49, BROTLI_TRANSFORM_IDENTITY, 47, 0, BROTLI_TRANSFORM_IDENTITY, 49, 4, BROTLI_TRANSFORM_IDENTITY, 0, 49, BROTLI_TRANSFORM_IDENTITY, 3, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49, 49, BROTLI_TRANSFORM_IDENTITY, 6, 49, BROTLI_TRANSFORM_OMIT_FIRST_2, 49, 49, BROTLI_TRANSFORM_OMIT_LAST_1, 49, 1, BROTLI_TRANSFORM_IDENTITY, 0, 49, BROTLI_TRANSFORM_IDENTITY, 1, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0, 49, BROTLI_TRANSFORM_IDENTITY, 7, 49, BROTLI_TRANSFORM_IDENTITY, 9, 48, BROTLI_TRANSFORM_IDENTITY, 0, 49, BROTLI_TRANSFORM_IDENTITY, 8, 49, BROTLI_TRANSFORM_IDENTITY, 5, 49, BROTLI_TRANSFORM_IDENTITY, 10, 49, BROTLI_TRANSFORM_IDENTITY, 11, 49, BROTLI_TRANSFORM_OMIT_LAST_3, 49, 49, BROTLI_TRANSFORM_IDENTITY, 13, 49, BROTLI_TRANSFORM_IDENTITY, 14, 49, BROTLI_TRANSFORM_OMIT_FIRST_3, 49, 49, BROTLI_TRANSFORM_OMIT_LAST_2, 49, 49, BROTLI_TRANSFORM_IDENTITY, 15, 49, BROTLI_TRANSFORM_IDENTITY, 16, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49, 49, BROTLI_TRANSFORM_IDENTITY, 12, 5, BROTLI_TRANSFORM_IDENTITY, 49, 0, BROTLI_TRANSFORM_IDENTITY, 1, 49, BROTLI_TRANSFORM_OMIT_FIRST_4, 49, 49, BROTLI_TRANSFORM_IDENTITY, 18, 49, BROTLI_TRANSFORM_IDENTITY, 17, 49, BROTLI_TRANSFORM_IDENTITY, 19, 49, BROTLI_TRANSFORM_IDENTITY, 20, 49, BROTLI_TRANSFORM_OMIT_FIRST_5, 49, 49, BROTLI_TRANSFORM_OMIT_FIRST_6, 49, 47, BROTLI_TRANSFORM_IDENTITY, 49, 49, BROTLI_TRANSFORM_OMIT_LAST_4, 49, 49, BROTLI_TRANSFORM_IDENTITY, 22, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 49, 49, BROTLI_TRANSFORM_IDENTITY, 23, 49, BROTLI_TRANSFORM_IDENTITY, 24, 49, BROTLI_TRANSFORM_IDENTITY, 25, 49, BROTLI_TRANSFORM_OMIT_LAST_7, 49, 49, BROTLI_TRANSFORM_OMIT_LAST_1, 26, 49, BROTLI_TRANSFORM_IDENTITY, 27, 49, BROTLI_TRANSFORM_IDENTITY, 28, 0, BROTLI_TRANSFORM_IDENTITY, 12, 49, BROTLI_TRANSFORM_IDENTITY, 29, 49, BROTLI_TRANSFORM_OMIT_FIRST_9, 49, 49, BROTLI_TRANSFORM_OMIT_FIRST_7, 49, 49, BROTLI_TRANSFORM_OMIT_LAST_6, 49, 49, BROTLI_TRANSFORM_IDENTITY, 21, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1, 49, BROTLI_TRANSFORM_OMIT_LAST_8, 49, 49, BROTLI_TRANSFORM_IDENTITY, 31, 49, BROTLI_TRANSFORM_IDENTITY, 32, 47, BROTLI_TRANSFORM_IDENTITY, 3, 49, BROTLI_TRANSFORM_OMIT_LAST_5, 49, 49, BROTLI_TRANSFORM_OMIT_LAST_9, 49, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 8, 5, BROTLI_TRANSFORM_IDENTITY, 21, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 0, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 10, 49, BROTLI_TRANSFORM_IDENTITY, 30, 0, BROTLI_TRANSFORM_IDENTITY, 5, 35, BROTLI_TRANSFORM_IDENTITY, 49, 47, BROTLI_TRANSFORM_IDENTITY, 2, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 17, 49, BROTLI_TRANSFORM_IDENTITY, 36, 49, BROTLI_TRANSFORM_IDENTITY, 33, 5, BROTLI_TRANSFORM_IDENTITY, 0, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 21, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5, 49, BROTLI_TRANSFORM_IDENTITY, 37, 0, BROTLI_TRANSFORM_IDENTITY, 30, 49, BROTLI_TRANSFORM_IDENTITY, 38, 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 0, 49, BROTLI_TRANSFORM_IDENTITY, 39, 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 49, 49, BROTLI_TRANSFORM_IDENTITY, 34, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 8, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12, 0, BROTLI_TRANSFORM_IDENTITY, 21, 49, BROTLI_TRANSFORM_IDENTITY, 40, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12, 49, BROTLI_TRANSFORM_IDENTITY, 41, 49, BROTLI_TRANSFORM_IDENTITY, 42, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 17, 49, BROTLI_TRANSFORM_IDENTITY, 43, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 10, 0, BROTLI_TRANSFORM_IDENTITY, 34, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33, 49, BROTLI_TRANSFORM_IDENTITY, 44, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 5, 45, BROTLI_TRANSFORM_IDENTITY, 49, 0, BROTLI_TRANSFORM_IDENTITY, 33, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 30, 49, BROTLI_TRANSFORM_IDENTITY, 46, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 1, 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33, 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 30, 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 1, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 33, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 21, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 12, 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 5, 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 34, 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 12, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30, 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 34, 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34, }; static const BrotliTransforms kBrotliTransforms = { sizeof(kPrefixSuffix), (const uint8_t*)kPrefixSuffix, kPrefixSuffixMap, sizeof(kTransformsData) / (3 * sizeof(kTransformsData[0])), kTransformsData, NULL, /* no extra parameters */ {0, 12, 27, 23, 42, 63, 56, 48, 59, 64} }; const BrotliTransforms* BrotliGetTransforms(void) { return &kBrotliTransforms; } static int ToUpperCase(uint8_t* p) { if (p[0] < 0xC0) { if (p[0] >= 'a' && p[0] <= 'z') { p[0] ^= 32; } return 1; } /* An overly simplified uppercasing model for UTF-8. */ if (p[0] < 0xE0) { p[1] ^= 32; return 2; } /* An arbitrary transform for three byte characters. */ p[2] ^= 5; return 3; } static int Shift(uint8_t* word, int word_len, uint16_t parameter) { /* Limited sign extension: scalar < (1 << 24). */ uint32_t scalar = (parameter & 0x7FFFu) + (0x1000000u - (parameter & 0x8000u)); if (word[0] < 0x80) { /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */ scalar += (uint32_t)word[0]; word[0] = (uint8_t)(scalar & 0x7Fu); return 1; } else if (word[0] < 0xC0) { /* Continuation / 10AAAAAA. */ return 1; } else if (word[0] < 0xE0) { /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */ if (word_len < 2) return 1; scalar += (uint32_t)((word[1] & 0x3Fu) | ((word[0] & 0x1Fu) << 6u)); word[0] = (uint8_t)(0xC0 | ((scalar >> 6u) & 0x1F)); word[1] = (uint8_t)((word[1] & 0xC0) | (scalar & 0x3F)); return 2; } else if (word[0] < 0xF0) { /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */ if (word_len < 3) return word_len; scalar += (uint32_t)((word[2] & 0x3Fu) | ((word[1] & 0x3Fu) << 6u) | ((word[0] & 0x0Fu) << 12u)); word[0] = (uint8_t)(0xE0 | ((scalar >> 12u) & 0x0F)); word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 6u) & 0x3F)); word[2] = (uint8_t)((word[2] & 0xC0) | (scalar & 0x3F)); return 3; } else if (word[0] < 0xF8) { /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */ if (word_len < 4) return word_len; scalar += (uint32_t)((word[3] & 0x3Fu) | ((word[2] & 0x3Fu) << 6u) | ((word[1] & 0x3Fu) << 12u) | ((word[0] & 0x07u) << 18u)); word[0] = (uint8_t)(0xF0 | ((scalar >> 18u) & 0x07)); word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 12u) & 0x3F)); word[2] = (uint8_t)((word[2] & 0xC0) | ((scalar >> 6u) & 0x3F)); word[3] = (uint8_t)((word[3] & 0xC0) | (scalar & 0x3F)); return 4; } return 1; } int BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len, const BrotliTransforms* transforms, int transform_idx) { int idx = 0; const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transform_idx); uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, transform_idx); const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, transform_idx); { int prefix_len = *prefix++; while (prefix_len--) { dst[idx++] = *prefix++; } } { const int t = type; int i = 0; if (t <= BROTLI_TRANSFORM_OMIT_LAST_9) { len -= t; } else if (t >= BROTLI_TRANSFORM_OMIT_FIRST_1 && t <= BROTLI_TRANSFORM_OMIT_FIRST_9) { int skip = t - (BROTLI_TRANSFORM_OMIT_FIRST_1 - 1); word += skip; len -= skip; } while (i < len) { dst[idx++] = word[i++]; } if (t == BROTLI_TRANSFORM_UPPERCASE_FIRST) { ToUpperCase(&dst[idx - len]); } else if (t == BROTLI_TRANSFORM_UPPERCASE_ALL) { uint8_t* uppercase = &dst[idx - len]; while (len > 0) { int step = ToUpperCase(uppercase); uppercase += step; len -= step; } } else if (t == BROTLI_TRANSFORM_SHIFT_FIRST) { uint16_t param = (uint16_t)(transforms->params[transform_idx * 2] + (transforms->params[transform_idx * 2 + 1] << 8u)); Shift(&dst[idx - len], len, param); } else if (t == BROTLI_TRANSFORM_SHIFT_ALL) { uint16_t param = (uint16_t)(transforms->params[transform_idx * 2] + (transforms->params[transform_idx * 2 + 1] << 8u)); uint8_t* shift = &dst[idx - len]; while (len > 0) { int step = Shift(shift, len, param); shift += step; len -= step; } } } { int suffix_len = *suffix++; while (suffix_len--) { dst[idx++] = *suffix++; } return idx; } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/common/transform.h000066400000000000000000000062111501401750600207370ustar00rootroot00000000000000/* transforms is a part of ABI, but not API. It means that there are some functions that are supposed to be in "common" library, but header itself is not placed into include/brotli. This way, aforementioned functions will be available only to brotli internals. */ #ifndef BROTLI_COMMON_TRANSFORM_H_ #define BROTLI_COMMON_TRANSFORM_H_ #include #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif enum BrotliWordTransformType { BROTLI_TRANSFORM_IDENTITY = 0, BROTLI_TRANSFORM_OMIT_LAST_1 = 1, BROTLI_TRANSFORM_OMIT_LAST_2 = 2, BROTLI_TRANSFORM_OMIT_LAST_3 = 3, BROTLI_TRANSFORM_OMIT_LAST_4 = 4, BROTLI_TRANSFORM_OMIT_LAST_5 = 5, BROTLI_TRANSFORM_OMIT_LAST_6 = 6, BROTLI_TRANSFORM_OMIT_LAST_7 = 7, BROTLI_TRANSFORM_OMIT_LAST_8 = 8, BROTLI_TRANSFORM_OMIT_LAST_9 = 9, BROTLI_TRANSFORM_UPPERCASE_FIRST = 10, BROTLI_TRANSFORM_UPPERCASE_ALL = 11, BROTLI_TRANSFORM_OMIT_FIRST_1 = 12, BROTLI_TRANSFORM_OMIT_FIRST_2 = 13, BROTLI_TRANSFORM_OMIT_FIRST_3 = 14, BROTLI_TRANSFORM_OMIT_FIRST_4 = 15, BROTLI_TRANSFORM_OMIT_FIRST_5 = 16, BROTLI_TRANSFORM_OMIT_FIRST_6 = 17, BROTLI_TRANSFORM_OMIT_FIRST_7 = 18, BROTLI_TRANSFORM_OMIT_FIRST_8 = 19, BROTLI_TRANSFORM_OMIT_FIRST_9 = 20, BROTLI_TRANSFORM_SHIFT_FIRST = 21, BROTLI_TRANSFORM_SHIFT_ALL = 22, BROTLI_NUM_TRANSFORM_TYPES /* Counts transforms, not a transform itself. */ }; #define BROTLI_TRANSFORMS_MAX_CUT_OFF BROTLI_TRANSFORM_OMIT_LAST_9 typedef struct BrotliTransforms { uint16_t prefix_suffix_size; /* Last character must be null, so prefix_suffix_size must be at least 1. */ const uint8_t* prefix_suffix; const uint16_t* prefix_suffix_map; uint32_t num_transforms; /* Each entry is a [prefix_id, transform, suffix_id] triplet. */ const uint8_t* transforms; /* Shift for BROTLI_TRANSFORM_SHIFT_FIRST and BROTLI_TRANSFORM_SHIFT_ALL, must be NULL if and only if no such transforms are present. */ const uint8_t* params; /* Indices of transforms like ["", BROTLI_TRANSFORM_OMIT_LAST_#, ""]. 0-th element corresponds to ["", BROTLI_TRANSFORM_IDENTITY, ""]. -1, if cut-off transform does not exist. */ int16_t cutOffTransforms[BROTLI_TRANSFORMS_MAX_CUT_OFF + 1]; } BrotliTransforms; /* T is BrotliTransforms*; result is uint8_t. */ #define BROTLI_TRANSFORM_PREFIX_ID(T, I) ((T)->transforms[((I) * 3) + 0]) #define BROTLI_TRANSFORM_TYPE(T, I) ((T)->transforms[((I) * 3) + 1]) #define BROTLI_TRANSFORM_SUFFIX_ID(T, I) ((T)->transforms[((I) * 3) + 2]) /* T is BrotliTransforms*; result is const uint8_t*. */ #define BROTLI_TRANSFORM_PREFIX(T, I) (&(T)->prefix_suffix[ \ (T)->prefix_suffix_map[BROTLI_TRANSFORM_PREFIX_ID(T, I)]]) #define BROTLI_TRANSFORM_SUFFIX(T, I) (&(T)->prefix_suffix[ \ (T)->prefix_suffix_map[BROTLI_TRANSFORM_SUFFIX_ID(T, I)]]) BROTLI_COMMON_API const BrotliTransforms* BrotliGetTransforms(void); BROTLI_COMMON_API int BrotliTransformDictionaryWord( uint8_t* dst, const uint8_t* word, int len, const BrotliTransforms* transforms, int transform_idx); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_COMMON_TRANSFORM_H_ */ dvisvgm-3.5/libs/brotli/common/version.h000066400000000000000000000032731501401750600204160ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Version definition. */ #ifndef BROTLI_COMMON_VERSION_H_ #define BROTLI_COMMON_VERSION_H_ /* Compose 3 components into a single number. In a hexadecimal representation B and C components occupy exactly 3 digits. */ #define BROTLI_MAKE_HEX_VERSION(A, B, C) ((A << 24) | (B << 12) | C) /* Those macros should only be used when library is compiled together with the client. If library is dynamically linked, use BrotliDecoderVersion and BrotliEncoderVersion methods. */ #define BROTLI_VERSION_MAJOR 1 #define BROTLI_VERSION_MINOR 1 #define BROTLI_VERSION_PATCH 0 #define BROTLI_VERSION BROTLI_MAKE_HEX_VERSION( \ BROTLI_VERSION_MAJOR, BROTLI_VERSION_MINOR, BROTLI_VERSION_PATCH) /* This macro is used by build system to produce Libtool-friendly soname. See https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html Version evolution rules: - interfaces added (or change is compatible) -> current+1:0:age+1 - interfaces removed (or changed is incompatible) -> current+1:0:0 - interfaces not changed -> current:revision+1:age */ #define BROTLI_ABI_CURRENT 2 #define BROTLI_ABI_REVISION 0 #define BROTLI_ABI_AGE 1 #if BROTLI_VERSION_MAJOR != (BROTLI_ABI_CURRENT - BROTLI_ABI_AGE) #error ABI/API version inconsistency #endif #if BROTLI_VERSION_MINOR != BROTLI_ABI_AGE #error ABI/API version inconsistency #endif #if BROTLI_VERSION_PATCH != BROTLI_ABI_REVISION #error ABI/API version inconsistency #endif #endif /* BROTLI_COMMON_VERSION_H_ */ dvisvgm-3.5/libs/brotli/enc/000077500000000000000000000000001501401750600160305ustar00rootroot00000000000000dvisvgm-3.5/libs/brotli/enc/backward_references.c000066400000000000000000000130511501401750600221530ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function to find backward reference copies. */ #include "backward_references.h" #include #include "../common/constants.h" #include "../common/dictionary.h" #include "../common/platform.h" #include "command.h" #include "compound_dictionary.h" #include "dictionary_hash.h" #include "encoder_dict.h" #include "memory.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static BROTLI_INLINE size_t ComputeDistanceCode(size_t distance, size_t max_distance, const int* dist_cache) { if (distance <= max_distance) { size_t distance_plus_3 = distance + 3; size_t offset0 = distance_plus_3 - (size_t)dist_cache[0]; size_t offset1 = distance_plus_3 - (size_t)dist_cache[1]; if (distance == (size_t)dist_cache[0]) { return 0; } else if (distance == (size_t)dist_cache[1]) { return 1; } else if (offset0 < 7) { return (0x9750468 >> (4 * offset0)) & 0xF; } else if (offset1 < 7) { return (0xFDB1ACE >> (4 * offset1)) & 0xF; } else if (distance == (size_t)dist_cache[2]) { return 2; } else if (distance == (size_t)dist_cache[3]) { return 3; } } return distance + BROTLI_NUM_DISTANCE_SHORT_CODES - 1; } #define EXPAND_CAT(a, b) CAT(a, b) #define CAT(a, b) a ## b #define FN(X) EXPAND_CAT(X, HASHER()) #define EXPORT_FN(X) EXPAND_CAT(X, EXPAND_CAT(PREFIX(), HASHER())) #define PREFIX() N #define ENABLE_COMPOUND_DICTIONARY 0 #define HASHER() H2 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H3 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H4 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H5 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H6 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H40 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H41 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H42 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H54 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H35 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H55 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H65 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #undef ENABLE_COMPOUND_DICTIONARY #undef PREFIX #define PREFIX() D #define ENABLE_COMPOUND_DICTIONARY 1 #define HASHER() H5 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H6 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H40 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H41 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H42 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H55 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #define HASHER() H65 /* NOLINTNEXTLINE(build/include) */ #include "backward_references_inc.h" #undef HASHER #undef ENABLE_COMPOUND_DICTIONARY #undef PREFIX #undef EXPORT_FN #undef FN #undef CAT #undef EXPAND_CAT void BrotliCreateBackwardReferences(size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, Hasher* hasher, int* dist_cache, size_t* last_insert_len, Command* commands, size_t* num_commands, size_t* num_literals) { if (params->dictionary.compound.num_chunks != 0) { switch (params->hasher.type) { #define CASE_(N) \ case N: \ CreateBackwardReferencesDH ## N(num_bytes, \ position, ringbuffer, ringbuffer_mask, \ literal_context_lut, params, hasher, dist_cache, \ last_insert_len, commands, num_commands, num_literals); \ return; CASE_(5) CASE_(6) CASE_(40) CASE_(41) CASE_(42) CASE_(55) CASE_(65) #undef CASE_ default: BROTLI_DCHECK(false); break; } } switch (params->hasher.type) { #define CASE_(N) \ case N: \ CreateBackwardReferencesNH ## N(num_bytes, \ position, ringbuffer, ringbuffer_mask, \ literal_context_lut, params, hasher, dist_cache, \ last_insert_len, commands, num_commands, num_literals); \ return; FOR_GENERIC_HASHERS(CASE_) #undef CASE_ default: BROTLI_DCHECK(false); break; } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/backward_references.h000066400000000000000000000024251501401750600221630ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function to find backward reference copies. */ #ifndef BROTLI_ENC_BACKWARD_REFERENCES_H_ #define BROTLI_ENC_BACKWARD_REFERENCES_H_ #include #include "../common/constants.h" #include "../common/context.h" #include "../common/dictionary.h" #include "../common/platform.h" #include "command.h" #include "hash.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* "commands" points to the next output command to write to, "*num_commands" is initially the total amount of commands output by previous CreateBackwardReferences calls, and must be incremented by the amount written by this call. */ BROTLI_INTERNAL void BrotliCreateBackwardReferences(size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, Hasher* hasher, int* dist_cache, size_t* last_insert_len, Command* commands, size_t* num_commands, size_t* num_literals); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_BACKWARD_REFERENCES_H_ */ dvisvgm-3.5/libs/brotli/enc/backward_references_hq.c000066400000000000000000001074371501401750600226570ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function to find backward reference copies. */ #include "backward_references_hq.h" #include /* memcpy, memset */ #include #include "../common/constants.h" #include "../common/platform.h" #include "command.h" #include "compound_dictionary.h" #include "encoder_dict.h" #include "fast_log.h" #include "find_match_length.h" #include "literal_cost.h" #include "memory.h" #include "params.h" #include "prefix.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* BrotliCalculateDistanceCodeLimit(BROTLI_MAX_ALLOWED_DISTANCE, 3, 120). */ #define BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE 544 static const float kInfinity = 1.7e38f; /* ~= 2 ^ 127 */ static const uint32_t kDistanceCacheIndex[] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, }; static const int kDistanceCacheOffset[] = { 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3 }; void BrotliInitZopfliNodes(ZopfliNode* array, size_t length) { ZopfliNode stub; size_t i; stub.length = 1; stub.distance = 0; stub.dcode_insert_length = 0; stub.u.cost = kInfinity; for (i = 0; i < length; ++i) array[i] = stub; } static BROTLI_INLINE uint32_t ZopfliNodeCopyLength(const ZopfliNode* self) { return self->length & 0x1FFFFFF; } static BROTLI_INLINE uint32_t ZopfliNodeLengthCode(const ZopfliNode* self) { const uint32_t modifier = self->length >> 25; return ZopfliNodeCopyLength(self) + 9u - modifier; } static BROTLI_INLINE uint32_t ZopfliNodeCopyDistance(const ZopfliNode* self) { return self->distance; } static BROTLI_INLINE uint32_t ZopfliNodeDistanceCode(const ZopfliNode* self) { const uint32_t short_code = self->dcode_insert_length >> 27; return short_code == 0 ? ZopfliNodeCopyDistance(self) + BROTLI_NUM_DISTANCE_SHORT_CODES - 1 : short_code - 1; } static BROTLI_INLINE uint32_t ZopfliNodeCommandLength(const ZopfliNode* self) { return ZopfliNodeCopyLength(self) + (self->dcode_insert_length & 0x7FFFFFF); } /* Temporary data for ZopfliCostModelSetFromCommands. */ typedef struct ZopfliCostModelArena { uint32_t histogram_literal[BROTLI_NUM_LITERAL_SYMBOLS]; uint32_t histogram_cmd[BROTLI_NUM_COMMAND_SYMBOLS]; uint32_t histogram_dist[BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE]; float cost_literal[BROTLI_NUM_LITERAL_SYMBOLS]; } ZopfliCostModelArena; /* Histogram based cost model for zopflification. */ typedef struct ZopfliCostModel { /* The insert and copy length symbols. */ float cost_cmd_[BROTLI_NUM_COMMAND_SYMBOLS]; float* cost_dist_; uint32_t distance_histogram_size; /* Cumulative costs of literals per position in the stream. */ float* literal_costs_; float min_cost_cmd_; size_t num_bytes_; /* Temporary data. */ union { size_t literal_histograms[3 * 256]; ZopfliCostModelArena arena; }; } ZopfliCostModel; static void InitZopfliCostModel( MemoryManager* m, ZopfliCostModel* self, const BrotliDistanceParams* dist, size_t num_bytes) { self->num_bytes_ = num_bytes; self->literal_costs_ = BROTLI_ALLOC(m, float, num_bytes + 2); self->cost_dist_ = BROTLI_ALLOC(m, float, dist->alphabet_size_limit); self->distance_histogram_size = dist->alphabet_size_limit; if (BROTLI_IS_OOM(m)) return; } static void CleanupZopfliCostModel(MemoryManager* m, ZopfliCostModel* self) { BROTLI_FREE(m, self->literal_costs_); BROTLI_FREE(m, self->cost_dist_); } static void SetCost(const uint32_t* histogram, size_t histogram_size, BROTLI_BOOL literal_histogram, float* cost) { size_t sum = 0; size_t missing_symbol_sum; float log2sum; float missing_symbol_cost; size_t i; for (i = 0; i < histogram_size; i++) { sum += histogram[i]; } log2sum = (float)FastLog2(sum); missing_symbol_sum = sum; if (!literal_histogram) { for (i = 0; i < histogram_size; i++) { if (histogram[i] == 0) missing_symbol_sum++; } } missing_symbol_cost = (float)FastLog2(missing_symbol_sum) + 2; for (i = 0; i < histogram_size; i++) { if (histogram[i] == 0) { cost[i] = missing_symbol_cost; continue; } /* Shannon bits for this symbol. */ cost[i] = log2sum - (float)FastLog2(histogram[i]); /* Cannot be coded with less than 1 bit */ if (cost[i] < 1) cost[i] = 1; } } static void ZopfliCostModelSetFromCommands(ZopfliCostModel* self, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, const Command* commands, size_t num_commands, size_t last_insert_len) { ZopfliCostModelArena* arena = &self->arena; size_t pos = position - last_insert_len; float min_cost_cmd = kInfinity; size_t i; float* cost_cmd = self->cost_cmd_; memset(arena->histogram_literal, 0, sizeof(arena->histogram_literal)); memset(arena->histogram_cmd, 0, sizeof(arena->histogram_cmd)); memset(arena->histogram_dist, 0, sizeof(arena->histogram_dist)); for (i = 0; i < num_commands; i++) { size_t inslength = commands[i].insert_len_; size_t copylength = CommandCopyLen(&commands[i]); size_t distcode = commands[i].dist_prefix_ & 0x3FF; size_t cmdcode = commands[i].cmd_prefix_; size_t j; arena->histogram_cmd[cmdcode]++; if (cmdcode >= 128) arena->histogram_dist[distcode]++; for (j = 0; j < inslength; j++) { arena->histogram_literal[ringbuffer[(pos + j) & ringbuffer_mask]]++; } pos += inslength + copylength; } SetCost(arena->histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, BROTLI_TRUE, arena->cost_literal); SetCost(arena->histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, BROTLI_FALSE, cost_cmd); SetCost(arena->histogram_dist, self->distance_histogram_size, BROTLI_FALSE, self->cost_dist_); for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) { min_cost_cmd = BROTLI_MIN(float, min_cost_cmd, cost_cmd[i]); } self->min_cost_cmd_ = min_cost_cmd; { float* literal_costs = self->literal_costs_; float literal_carry = 0.0; size_t num_bytes = self->num_bytes_; literal_costs[0] = 0.0; for (i = 0; i < num_bytes; ++i) { literal_carry += arena->cost_literal[ringbuffer[(position + i) & ringbuffer_mask]]; literal_costs[i + 1] = literal_costs[i] + literal_carry; literal_carry -= literal_costs[i + 1] - literal_costs[i]; } } } static void ZopfliCostModelSetFromLiteralCosts(ZopfliCostModel* self, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask) { float* literal_costs = self->literal_costs_; float literal_carry = 0.0; float* cost_dist = self->cost_dist_; float* cost_cmd = self->cost_cmd_; size_t num_bytes = self->num_bytes_; size_t i; BrotliEstimateBitCostsForLiterals(position, num_bytes, ringbuffer_mask, ringbuffer, self->literal_histograms, &literal_costs[1]); literal_costs[0] = 0.0; for (i = 0; i < num_bytes; ++i) { literal_carry += literal_costs[i + 1]; literal_costs[i + 1] = literal_costs[i] + literal_carry; literal_carry -= literal_costs[i + 1] - literal_costs[i]; } for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) { cost_cmd[i] = (float)FastLog2(11 + (uint32_t)i); } for (i = 0; i < self->distance_histogram_size; ++i) { cost_dist[i] = (float)FastLog2(20 + (uint32_t)i); } self->min_cost_cmd_ = (float)FastLog2(11); } static BROTLI_INLINE float ZopfliCostModelGetCommandCost( const ZopfliCostModel* self, uint16_t cmdcode) { return self->cost_cmd_[cmdcode]; } static BROTLI_INLINE float ZopfliCostModelGetDistanceCost( const ZopfliCostModel* self, size_t distcode) { return self->cost_dist_[distcode]; } static BROTLI_INLINE float ZopfliCostModelGetLiteralCosts( const ZopfliCostModel* self, size_t from, size_t to) { return self->literal_costs_[to] - self->literal_costs_[from]; } static BROTLI_INLINE float ZopfliCostModelGetMinCostCmd( const ZopfliCostModel* self) { return self->min_cost_cmd_; } /* REQUIRES: len >= 2, start_pos <= pos */ /* REQUIRES: cost < kInfinity, nodes[start_pos].cost < kInfinity */ /* Maintains the "ZopfliNode array invariant". */ static BROTLI_INLINE void UpdateZopfliNode(ZopfliNode* nodes, size_t pos, size_t start_pos, size_t len, size_t len_code, size_t dist, size_t short_code, float cost) { ZopfliNode* next = &nodes[pos + len]; next->length = (uint32_t)(len | ((len + 9u - len_code) << 25)); next->distance = (uint32_t)dist; next->dcode_insert_length = (uint32_t)( (short_code << 27) | (pos - start_pos)); next->u.cost = cost; } typedef struct PosData { size_t pos; int distance_cache[4]; float costdiff; float cost; } PosData; /* Maintains the smallest 8 cost difference together with their positions */ typedef struct StartPosQueue { PosData q_[8]; size_t idx_; } StartPosQueue; static BROTLI_INLINE void InitStartPosQueue(StartPosQueue* self) { self->idx_ = 0; } static size_t StartPosQueueSize(const StartPosQueue* self) { return BROTLI_MIN(size_t, self->idx_, 8); } static void StartPosQueuePush(StartPosQueue* self, const PosData* posdata) { size_t offset = ~(self->idx_++) & 7; size_t len = StartPosQueueSize(self); size_t i; PosData* q = self->q_; q[offset] = *posdata; /* Restore the sorted order. In the list of |len| items at most |len - 1| adjacent element comparisons / swaps are required. */ for (i = 1; i < len; ++i) { if (q[offset & 7].costdiff > q[(offset + 1) & 7].costdiff) { BROTLI_SWAP(PosData, q, offset & 7, (offset + 1) & 7); } ++offset; } } static const PosData* StartPosQueueAt(const StartPosQueue* self, size_t k) { return &self->q_[(k - self->idx_) & 7]; } /* Returns the minimum possible copy length that can improve the cost of any */ /* future position. */ static size_t ComputeMinimumCopyLength(const float start_cost, const ZopfliNode* nodes, const size_t num_bytes, const size_t pos) { /* Compute the minimum possible cost of reaching any future position. */ float min_cost = start_cost; size_t len = 2; size_t next_len_bucket = 4; size_t next_len_offset = 10; while (pos + len <= num_bytes && nodes[pos + len].u.cost <= min_cost) { /* We already reached (pos + len) with no more cost than the minimum possible cost of reaching anything from this pos, so there is no point in looking for lengths <= len. */ ++len; if (len == next_len_offset) { /* We reached the next copy length code bucket, so we add one more extra bit to the minimum cost. */ min_cost += 1.0f; next_len_offset += next_len_bucket; next_len_bucket *= 2; } } return len; } /* REQUIRES: nodes[pos].cost < kInfinity REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */ static uint32_t ComputeDistanceShortcut(const size_t block_start, const size_t pos, const size_t max_backward_limit, const size_t gap, const ZopfliNode* nodes) { const size_t clen = ZopfliNodeCopyLength(&nodes[pos]); const size_t ilen = nodes[pos].dcode_insert_length & 0x7FFFFFF; const size_t dist = ZopfliNodeCopyDistance(&nodes[pos]); /* Since |block_start + pos| is the end position of the command, the copy part starts from |block_start + pos - clen|. Distances that are greater than this or greater than |max_backward_limit| + |gap| are static dictionary references, and do not update the last distances. Also distance code 0 (last distance) does not update the last distances. */ if (pos == 0) { return 0; } else if (dist + clen <= block_start + pos + gap && dist <= max_backward_limit + gap && ZopfliNodeDistanceCode(&nodes[pos]) > 0) { return (uint32_t)pos; } else { return nodes[pos - clen - ilen].u.shortcut; } } /* Fills in dist_cache[0..3] with the last four distances (as defined by Section 4. of the Spec) that would be used at (block_start + pos) if we used the shortest path of commands from block_start, computed from nodes[0..pos]. The last four distances at block_start are in starting_dist_cache[0..3]. REQUIRES: nodes[pos].cost < kInfinity REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */ static void ComputeDistanceCache(const size_t pos, const int* starting_dist_cache, const ZopfliNode* nodes, int* dist_cache) { int idx = 0; size_t p = nodes[pos].u.shortcut; while (idx < 4 && p > 0) { const size_t ilen = nodes[p].dcode_insert_length & 0x7FFFFFF; const size_t clen = ZopfliNodeCopyLength(&nodes[p]); const size_t dist = ZopfliNodeCopyDistance(&nodes[p]); dist_cache[idx++] = (int)dist; /* Because of prerequisite, p >= clen + ilen >= 2. */ p = nodes[p - clen - ilen].u.shortcut; } for (; idx < 4; ++idx) { dist_cache[idx] = *starting_dist_cache++; } } /* Maintains "ZopfliNode array invariant" and pushes node to the queue, if it is eligible. */ static void EvaluateNode( const size_t block_start, const size_t pos, const size_t max_backward_limit, const size_t gap, const int* starting_dist_cache, const ZopfliCostModel* model, StartPosQueue* queue, ZopfliNode* nodes) { /* Save cost, because ComputeDistanceCache invalidates it. */ float node_cost = nodes[pos].u.cost; nodes[pos].u.shortcut = ComputeDistanceShortcut( block_start, pos, max_backward_limit, gap, nodes); if (node_cost <= ZopfliCostModelGetLiteralCosts(model, 0, pos)) { PosData posdata; posdata.pos = pos; posdata.cost = node_cost; posdata.costdiff = node_cost - ZopfliCostModelGetLiteralCosts(model, 0, pos); ComputeDistanceCache( pos, starting_dist_cache, nodes, posdata.distance_cache); StartPosQueuePush(queue, &posdata); } } /* Returns longest copy length. */ static size_t UpdateNodes( const size_t num_bytes, const size_t block_start, const size_t pos, const uint8_t* ringbuffer, const size_t ringbuffer_mask, const BrotliEncoderParams* params, const size_t max_backward_limit, const int* starting_dist_cache, const size_t num_matches, const BackwardMatch* matches, const ZopfliCostModel* model, StartPosQueue* queue, ZopfliNode* nodes) { const size_t stream_offset = params->stream_offset; const size_t cur_ix = block_start + pos; const size_t cur_ix_masked = cur_ix & ringbuffer_mask; const size_t max_distance = BROTLI_MIN(size_t, cur_ix, max_backward_limit); const size_t dictionary_start = BROTLI_MIN(size_t, cur_ix + stream_offset, max_backward_limit); const size_t max_len = num_bytes - pos; const size_t max_zopfli_len = MaxZopfliLen(params); const size_t max_iters = MaxZopfliCandidates(params); size_t min_len; size_t result = 0; size_t k; const CompoundDictionary* addon = ¶ms->dictionary.compound; size_t gap = addon->total_size; EvaluateNode(block_start + stream_offset, pos, max_backward_limit, gap, starting_dist_cache, model, queue, nodes); { const PosData* posdata = StartPosQueueAt(queue, 0); float min_cost = (posdata->cost + ZopfliCostModelGetMinCostCmd(model) + ZopfliCostModelGetLiteralCosts(model, posdata->pos, pos)); min_len = ComputeMinimumCopyLength(min_cost, nodes, num_bytes, pos); } /* Go over the command starting positions in order of increasing cost difference. */ for (k = 0; k < max_iters && k < StartPosQueueSize(queue); ++k) { const PosData* posdata = StartPosQueueAt(queue, k); const size_t start = posdata->pos; const uint16_t inscode = GetInsertLengthCode(pos - start); const float start_costdiff = posdata->costdiff; const float base_cost = start_costdiff + (float)GetInsertExtra(inscode) + ZopfliCostModelGetLiteralCosts(model, 0, pos); /* Look for last distance matches using the distance cache from this starting position. */ size_t best_len = min_len - 1; size_t j = 0; for (; j < BROTLI_NUM_DISTANCE_SHORT_CODES && best_len < max_len; ++j) { const size_t idx = kDistanceCacheIndex[j]; const size_t backward = (size_t)(posdata->distance_cache[idx] + kDistanceCacheOffset[j]); size_t prev_ix = cur_ix - backward; size_t len = 0; uint8_t continuation = ringbuffer[cur_ix_masked + best_len]; if (cur_ix_masked + best_len > ringbuffer_mask) { break; } if (BROTLI_PREDICT_FALSE(backward > dictionary_start + gap)) { /* Word dictionary -> ignore. */ continue; } if (backward <= max_distance) { /* Regular backward reference. */ if (prev_ix >= cur_ix) { continue; } prev_ix &= ringbuffer_mask; if (prev_ix + best_len > ringbuffer_mask || continuation != ringbuffer[prev_ix + best_len]) { continue; } len = FindMatchLengthWithLimit(&ringbuffer[prev_ix], &ringbuffer[cur_ix_masked], max_len); } else if (backward > dictionary_start) { size_t d = 0; size_t offset; size_t limit; const uint8_t* source; offset = dictionary_start + 1 + addon->total_size - 1; while (offset >= backward + addon->chunk_offsets[d + 1]) d++; source = addon->chunk_source[d]; offset = offset - addon->chunk_offsets[d] - backward; limit = addon->chunk_offsets[d + 1] - addon->chunk_offsets[d] - offset; limit = limit > max_len ? max_len : limit; if (best_len >= limit || continuation != source[offset + best_len]) { continue; } len = FindMatchLengthWithLimit(&source[offset], &ringbuffer[cur_ix_masked], limit); } else { /* "Gray" area. It is addressable by decoder, but this encoder instance does not have that data -> should not touch it. */ continue; } { const float dist_cost = base_cost + ZopfliCostModelGetDistanceCost(model, j); size_t l; for (l = best_len + 1; l <= len; ++l) { const uint16_t copycode = GetCopyLengthCode(l); const uint16_t cmdcode = CombineLengthCodes(inscode, copycode, j == 0); const float cost = (cmdcode < 128 ? base_cost : dist_cost) + (float)GetCopyExtra(copycode) + ZopfliCostModelGetCommandCost(model, cmdcode); if (cost < nodes[pos + l].u.cost) { UpdateZopfliNode(nodes, pos, start, l, l, backward, j + 1, cost); result = BROTLI_MAX(size_t, result, l); } best_len = l; } } } /* At higher iterations look only for new last distance matches, since looking only for new command start positions with the same distances does not help much. */ if (k >= 2) continue; { /* Loop through all possible copy lengths at this position. */ size_t len = min_len; for (j = 0; j < num_matches; ++j) { BackwardMatch match = matches[j]; size_t dist = match.distance; BROTLI_BOOL is_dictionary_match = TO_BROTLI_BOOL(dist > dictionary_start + gap); /* We already tried all possible last distance matches, so we can use normal distance code here. */ size_t dist_code = dist + BROTLI_NUM_DISTANCE_SHORT_CODES - 1; uint16_t dist_symbol; uint32_t distextra; uint32_t distnumextra; float dist_cost; size_t max_match_len; PrefixEncodeCopyDistance( dist_code, params->dist.num_direct_distance_codes, params->dist.distance_postfix_bits, &dist_symbol, &distextra); distnumextra = dist_symbol >> 10; dist_cost = base_cost + (float)distnumextra + ZopfliCostModelGetDistanceCost(model, dist_symbol & 0x3FF); /* Try all copy lengths up until the maximum copy length corresponding to this distance. If the distance refers to the static dictionary, or the maximum length is long enough, try only one maximum length. */ max_match_len = BackwardMatchLength(&match); if (len < max_match_len && (is_dictionary_match || max_match_len > max_zopfli_len)) { len = max_match_len; } for (; len <= max_match_len; ++len) { const size_t len_code = is_dictionary_match ? BackwardMatchLengthCode(&match) : len; const uint16_t copycode = GetCopyLengthCode(len_code); const uint16_t cmdcode = CombineLengthCodes(inscode, copycode, 0); const float cost = dist_cost + (float)GetCopyExtra(copycode) + ZopfliCostModelGetCommandCost(model, cmdcode); if (cost < nodes[pos + len].u.cost) { UpdateZopfliNode(nodes, pos, start, len, len_code, dist, 0, cost); result = BROTLI_MAX(size_t, result, len); } } } } } return result; } static size_t ComputeShortestPathFromNodes(size_t num_bytes, ZopfliNode* nodes) { size_t index = num_bytes; size_t num_commands = 0; while ((nodes[index].dcode_insert_length & 0x7FFFFFF) == 0 && nodes[index].length == 1) --index; nodes[index].u.next = BROTLI_UINT32_MAX; while (index != 0) { size_t len = ZopfliNodeCommandLength(&nodes[index]); index -= len; nodes[index].u.next = (uint32_t)len; num_commands++; } return num_commands; } /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */ void BrotliZopfliCreateCommands(const size_t num_bytes, const size_t block_start, const ZopfliNode* nodes, int* dist_cache, size_t* last_insert_len, const BrotliEncoderParams* params, Command* commands, size_t* num_literals) { const size_t stream_offset = params->stream_offset; const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); size_t pos = 0; uint32_t offset = nodes[0].u.next; size_t i; size_t gap = params->dictionary.compound.total_size; for (i = 0; offset != BROTLI_UINT32_MAX; i++) { const ZopfliNode* next = &nodes[pos + offset]; size_t copy_length = ZopfliNodeCopyLength(next); size_t insert_length = next->dcode_insert_length & 0x7FFFFFF; pos += insert_length; offset = next->u.next; if (i == 0) { insert_length += *last_insert_len; *last_insert_len = 0; } { size_t distance = ZopfliNodeCopyDistance(next); size_t len_code = ZopfliNodeLengthCode(next); size_t dictionary_start = BROTLI_MIN(size_t, block_start + pos + stream_offset, max_backward_limit); BROTLI_BOOL is_dictionary = TO_BROTLI_BOOL(distance > dictionary_start + gap); size_t dist_code = ZopfliNodeDistanceCode(next); InitCommand(&commands[i], ¶ms->dist, insert_length, copy_length, (int)len_code - (int)copy_length, dist_code); if (!is_dictionary && dist_code > 0) { dist_cache[3] = dist_cache[2]; dist_cache[2] = dist_cache[1]; dist_cache[1] = dist_cache[0]; dist_cache[0] = (int)distance; } } *num_literals += insert_length; pos += copy_length; } *last_insert_len += num_bytes - pos; } static size_t ZopfliIterate(size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, const BrotliEncoderParams* params, const size_t gap, const int* dist_cache, const ZopfliCostModel* model, const uint32_t* num_matches, const BackwardMatch* matches, ZopfliNode* nodes) { const size_t stream_offset = params->stream_offset; const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); const size_t max_zopfli_len = MaxZopfliLen(params); StartPosQueue queue; size_t cur_match_pos = 0; size_t i; nodes[0].length = 0; nodes[0].u.cost = 0; InitStartPosQueue(&queue); for (i = 0; i + 3 < num_bytes; i++) { size_t skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask, params, max_backward_limit, dist_cache, num_matches[i], &matches[cur_match_pos], model, &queue, nodes); if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0; cur_match_pos += num_matches[i]; if (num_matches[i] == 1 && BackwardMatchLength(&matches[cur_match_pos - 1]) > max_zopfli_len) { skip = BROTLI_MAX(size_t, BackwardMatchLength(&matches[cur_match_pos - 1]), skip); } if (skip > 1) { skip--; while (skip) { i++; if (i + 3 >= num_bytes) break; EvaluateNode(position + stream_offset, i, max_backward_limit, gap, dist_cache, model, &queue, nodes); cur_match_pos += num_matches[i]; skip--; } } } return ComputeShortestPathFromNodes(num_bytes, nodes); } static void MergeMatches(BackwardMatch* dst, BackwardMatch* src1, size_t len1, BackwardMatch* src2, size_t len2) { while (len1 > 0 && len2 > 0) { size_t l1 = BackwardMatchLength(src1); size_t l2 = BackwardMatchLength(src2); if (l1 < l2 || ((l1 == l2) && (src1->distance < src2->distance))) { *dst++ = *src1++; len1--; } else { *dst++ = *src2++; len2--; } } while (len1-- > 0) *dst++ = *src1++; while (len2-- > 0) *dst++ = *src2++; } /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, const int* dist_cache, Hasher* hasher, ZopfliNode* nodes) { const size_t stream_offset = params->stream_offset; const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); const size_t max_zopfli_len = MaxZopfliLen(params); StartPosQueue queue; BackwardMatch* BROTLI_RESTRICT matches = BROTLI_ALLOC(m, BackwardMatch, 2 * (MAX_NUM_MATCHES_H10 + 64)); const size_t store_end = num_bytes >= StoreLookaheadH10() ? position + num_bytes - StoreLookaheadH10() + 1 : position; size_t i; const CompoundDictionary* addon = ¶ms->dictionary.compound; size_t gap = addon->total_size; size_t lz_matches_offset = (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0; ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) || BROTLI_IS_NULL(matches)) { return 0; } nodes[0].length = 0; nodes[0].u.cost = 0; InitZopfliCostModel(m, model, ¶ms->dist, num_bytes); if (BROTLI_IS_OOM(m)) return 0; ZopfliCostModelSetFromLiteralCosts( model, position, ringbuffer, ringbuffer_mask); InitStartPosQueue(&queue); for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; i++) { const size_t pos = position + i; const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit); const size_t dictionary_start = BROTLI_MIN(size_t, pos + stream_offset, max_backward_limit); size_t skip; size_t num_matches; int dict_id = 0; if (params->dictionary.contextual.context_based) { uint8_t p1 = pos >= 1 ? ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0; uint8_t p2 = pos >= 2 ? ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0; dict_id = params->dictionary.contextual.context_map[ BROTLI_CONTEXT(p1, p2, literal_context_lut)]; } num_matches = FindAllMatchesH10(&hasher->privat._H10, params->dictionary.contextual.dict[dict_id], ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance, dictionary_start + gap, params, &matches[lz_matches_offset]); if (addon->num_chunks != 0) { size_t cd_matches = LookupAllCompoundDictionaryMatches(addon, ringbuffer, ringbuffer_mask, pos, 3, num_bytes - i, dictionary_start, params->dist.max_distance, &matches[lz_matches_offset - 64], 64); MergeMatches(matches, &matches[lz_matches_offset - 64], cd_matches, &matches[lz_matches_offset], num_matches); num_matches += cd_matches; } if (num_matches > 0 && BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) { matches[0] = matches[num_matches - 1]; num_matches = 1; } skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask, params, max_backward_limit, dist_cache, num_matches, matches, model, &queue, nodes); if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0; if (num_matches == 1 && BackwardMatchLength(&matches[0]) > max_zopfli_len) { skip = BROTLI_MAX(size_t, BackwardMatchLength(&matches[0]), skip); } if (skip > 1) { /* Add the tail of the copy to the hasher. */ StoreRangeH10(&hasher->privat._H10, ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN( size_t, pos + skip, store_end)); skip--; while (skip) { i++; if (i + HashTypeLengthH10() - 1 >= num_bytes) break; EvaluateNode(position + stream_offset, i, max_backward_limit, gap, dist_cache, model, &queue, nodes); skip--; } } } CleanupZopfliCostModel(m, model); BROTLI_FREE(m, model); BROTLI_FREE(m, matches); return ComputeShortestPathFromNodes(num_bytes, nodes); } void BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, Hasher* hasher, int* dist_cache, size_t* last_insert_len, Command* commands, size_t* num_commands, size_t* num_literals) { ZopfliNode* nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return; BrotliInitZopfliNodes(nodes, num_bytes + 1); *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes, position, ringbuffer, ringbuffer_mask, literal_context_lut, params, dist_cache, hasher, nodes); if (BROTLI_IS_OOM(m)) return; BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache, last_insert_len, params, commands, num_literals); BROTLI_FREE(m, nodes); } void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, Hasher* hasher, int* dist_cache, size_t* last_insert_len, Command* commands, size_t* num_commands, size_t* num_literals) { const size_t stream_offset = params->stream_offset; const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); uint32_t* num_matches = BROTLI_ALLOC(m, uint32_t, num_bytes); size_t matches_size = 4 * num_bytes; const size_t store_end = num_bytes >= StoreLookaheadH10() ? position + num_bytes - StoreLookaheadH10() + 1 : position; size_t cur_match_pos = 0; size_t i; size_t orig_num_literals; size_t orig_last_insert_len; int orig_dist_cache[4]; size_t orig_num_commands; ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1); ZopfliNode* nodes; BackwardMatch* matches = BROTLI_ALLOC(m, BackwardMatch, matches_size); const CompoundDictionary* addon = ¶ms->dictionary.compound; size_t gap = addon->total_size; size_t shadow_matches = (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) || BROTLI_IS_NULL(num_matches) || BROTLI_IS_NULL(matches)) { return; } for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; ++i) { const size_t pos = position + i; size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit); size_t dictionary_start = BROTLI_MIN(size_t, pos + stream_offset, max_backward_limit); size_t max_length = num_bytes - i; size_t num_found_matches; size_t cur_match_end; size_t j; int dict_id = 0; if (params->dictionary.contextual.context_based) { uint8_t p1 = pos >= 1 ? ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0; uint8_t p2 = pos >= 2 ? ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0; dict_id = params->dictionary.contextual.context_map[ BROTLI_CONTEXT(p1, p2, literal_context_lut)]; } /* Ensure that we have enough free slots. */ BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size, cur_match_pos + MAX_NUM_MATCHES_H10 + shadow_matches); if (BROTLI_IS_OOM(m)) return; num_found_matches = FindAllMatchesH10(&hasher->privat._H10, params->dictionary.contextual.dict[dict_id], ringbuffer, ringbuffer_mask, pos, max_length, max_distance, dictionary_start + gap, params, &matches[cur_match_pos + shadow_matches]); if (addon->num_chunks != 0) { size_t cd_matches = LookupAllCompoundDictionaryMatches(addon, ringbuffer, ringbuffer_mask, pos, 3, max_length, dictionary_start, params->dist.max_distance, &matches[cur_match_pos + shadow_matches - 64], 64); MergeMatches(&matches[cur_match_pos], &matches[cur_match_pos + shadow_matches - 64], cd_matches, &matches[cur_match_pos + shadow_matches], num_found_matches); num_found_matches += cd_matches; } cur_match_end = cur_match_pos + num_found_matches; for (j = cur_match_pos; j + 1 < cur_match_end; ++j) { BROTLI_DCHECK(BackwardMatchLength(&matches[j]) <= BackwardMatchLength(&matches[j + 1])); } num_matches[i] = (uint32_t)num_found_matches; if (num_found_matches > 0) { const size_t match_len = BackwardMatchLength(&matches[cur_match_end - 1]); if (match_len > MAX_ZOPFLI_LEN_QUALITY_11) { const size_t skip = match_len - 1; matches[cur_match_pos++] = matches[cur_match_end - 1]; num_matches[i] = 1; /* Add the tail of the copy to the hasher. */ StoreRangeH10(&hasher->privat._H10, ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN(size_t, pos + match_len, store_end)); memset(&num_matches[i + 1], 0, skip * sizeof(num_matches[0])); i += skip; } else { cur_match_pos = cur_match_end; } } } orig_num_literals = *num_literals; orig_last_insert_len = *last_insert_len; memcpy(orig_dist_cache, dist_cache, 4 * sizeof(dist_cache[0])); orig_num_commands = *num_commands; nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return; InitZopfliCostModel(m, model, ¶ms->dist, num_bytes); if (BROTLI_IS_OOM(m)) return; for (i = 0; i < 2; i++) { BrotliInitZopfliNodes(nodes, num_bytes + 1); if (i == 0) { ZopfliCostModelSetFromLiteralCosts( model, position, ringbuffer, ringbuffer_mask); } else { ZopfliCostModelSetFromCommands(model, position, ringbuffer, ringbuffer_mask, commands, *num_commands - orig_num_commands, orig_last_insert_len); } *num_commands = orig_num_commands; *num_literals = orig_num_literals; *last_insert_len = orig_last_insert_len; memcpy(dist_cache, orig_dist_cache, 4 * sizeof(dist_cache[0])); *num_commands += ZopfliIterate(num_bytes, position, ringbuffer, ringbuffer_mask, params, gap, dist_cache, model, num_matches, matches, nodes); BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache, last_insert_len, params, commands, num_literals); } CleanupZopfliCostModel(m, model); BROTLI_FREE(m, model); BROTLI_FREE(m, nodes); BROTLI_FREE(m, matches); BROTLI_FREE(m, num_matches); } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/backward_references_hq.h000066400000000000000000000074341501401750600226600ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function to find backward reference copies. */ #ifndef BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ #define BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ #include #include "../common/constants.h" #include "../common/context.h" #include "../common/dictionary.h" #include "../common/platform.h" #include "command.h" #include "hash.h" #include "memory.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif BROTLI_INTERNAL void BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, Hasher* hasher, int* dist_cache, size_t* last_insert_len, Command* commands, size_t* num_commands, size_t* num_literals); BROTLI_INTERNAL void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, Hasher* hasher, int* dist_cache, size_t* last_insert_len, Command* commands, size_t* num_commands, size_t* num_literals); typedef struct ZopfliNode { /* Best length to get up to this byte (not including this byte itself) highest 7 bit is used to reconstruct the length code. */ uint32_t length; /* Distance associated with the length. */ uint32_t distance; /* Number of literal inserts before this copy; highest 5 bits contain distance short code + 1 (or zero if no short code). */ uint32_t dcode_insert_length; /* This union holds information used by dynamic-programming. During forward pass |cost| it used to store the goal function. When node is processed its |cost| is invalidated in favor of |shortcut|. On path back-tracing pass |next| is assigned the offset to next node on the path. */ union { /* Smallest cost to get to this byte from the beginning, as found so far. */ float cost; /* Offset to the next node on the path. Equals to command_length() of the next node on the path. For last node equals to BROTLI_UINT32_MAX */ uint32_t next; /* Node position that provides next distance for distance cache. */ uint32_t shortcut; } u; } ZopfliNode; BROTLI_INTERNAL void BrotliInitZopfliNodes(ZopfliNode* array, size_t length); /* Computes the shortest path of commands from position to at most position + num_bytes. On return, path->size() is the number of commands found and path[i] is the length of the i-th command (copy length plus insert length). Note that the sum of the lengths of all commands can be less than num_bytes. On return, the nodes[0..num_bytes] array will have the following "ZopfliNode array invariant": For each i in [1..num_bytes], if nodes[i].cost < kInfinity, then (1) nodes[i].copy_length() >= 2 (2) nodes[i].command_length() <= i and (3) nodes[i - nodes[i].command_length()].cost < kInfinity */ BROTLI_INTERNAL size_t BrotliZopfliComputeShortestPath( MemoryManager* m, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, const int* dist_cache, Hasher* hasher, ZopfliNode* nodes); BROTLI_INTERNAL void BrotliZopfliCreateCommands( const size_t num_bytes, const size_t block_start, const ZopfliNode* nodes, int* dist_cache, size_t* last_insert_len, const BrotliEncoderParams* params, Command* commands, size_t* num_literals); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ */ dvisvgm-3.5/libs/brotli/enc/backward_references_inc.h000066400000000000000000000177651501401750600230310ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: EXPORT_FN, FN */ static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, ContextLut literal_context_lut, const BrotliEncoderParams* params, Hasher* hasher, int* dist_cache, size_t* last_insert_len, Command* commands, size_t* num_commands, size_t* num_literals) { HASHER()* privat = &hasher->privat.FN(_); /* Set maximum distance, see section 9.1. of the spec. */ const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); const size_t position_offset = params->stream_offset; const Command* const orig_commands = commands; size_t insert_length = *last_insert_len; const size_t pos_end = position + num_bytes; const size_t store_end = num_bytes >= FN(StoreLookahead)() ? position + num_bytes - FN(StoreLookahead)() + 1 : position; /* For speed up heuristics for random data. */ const size_t random_heuristics_window_size = LiteralSpreeLengthForSparseSearch(params); size_t apply_random_heuristics = position + random_heuristics_window_size; const size_t gap = params->dictionary.compound.total_size; /* Minimum score to accept a backward reference. */ const score_t kMinScore = BROTLI_SCORE_BASE + 100; FN(PrepareDistanceCache)(privat, dist_cache); while (position + FN(HashTypeLength)() < pos_end) { size_t max_length = pos_end - position; size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); size_t dictionary_start = BROTLI_MIN(size_t, position + position_offset, max_backward_limit); HasherSearchResult sr; int dict_id = 0; uint8_t p1 = 0; uint8_t p2 = 0; if (params->dictionary.contextual.context_based) { p1 = position >= 1 ? ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; p2 = position >= 2 ? ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; dict_id = params->dictionary.contextual.context_map[ BROTLI_CONTEXT(p1, p2, literal_context_lut)]; } sr.len = 0; sr.len_code_delta = 0; sr.distance = 0; sr.score = kMinScore; FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], ringbuffer, ringbuffer_mask, dist_cache, position, max_length, max_distance, dictionary_start + gap, params->dist.max_distance, &sr); if (ENABLE_COMPOUND_DICTIONARY) { LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, ringbuffer_mask, dist_cache, position, max_length, dictionary_start, params->dist.max_distance, &sr); } if (sr.score > kMinScore) { /* Found a match. Let's look for something even better ahead. */ int delayed_backward_references_in_row = 0; --max_length; for (;; --max_length) { const score_t cost_diff_lazy = 175; HasherSearchResult sr2; sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; sr2.len_code_delta = 0; sr2.distance = 0; sr2.score = kMinScore; max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); dictionary_start = BROTLI_MIN(size_t, position + 1 + position_offset, max_backward_limit); if (params->dictionary.contextual.context_based) { p2 = p1; p1 = ringbuffer[position & ringbuffer_mask]; dict_id = params->dictionary.contextual.context_map[ BROTLI_CONTEXT(p1, p2, literal_context_lut)]; } FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, max_distance, dictionary_start + gap, params->dist.max_distance, &sr2); if (ENABLE_COMPOUND_DICTIONARY) { LookupCompoundDictionaryMatch( ¶ms->dictionary.compound, ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, dictionary_start, params->dist.max_distance, &sr2); } if (sr2.score >= sr.score + cost_diff_lazy) { /* Ok, let's just write one byte for now and start a match from the next byte. */ ++position; ++insert_length; sr = sr2; if (++delayed_backward_references_in_row < 4 && position + FN(HashTypeLength)() < pos_end) { continue; } } break; } apply_random_heuristics = position + 2 * sr.len + random_heuristics_window_size; dictionary_start = BROTLI_MIN(size_t, position + position_offset, max_backward_limit); { /* The first 16 codes are special short-codes, and the minimum offset is 1. */ size_t distance_code = ComputeDistanceCode( sr.distance, dictionary_start + gap, dist_cache); if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { dist_cache[3] = dist_cache[2]; dist_cache[2] = dist_cache[1]; dist_cache[1] = dist_cache[0]; dist_cache[0] = (int)sr.distance; FN(PrepareDistanceCache)(privat, dist_cache); } InitCommand(commands++, ¶ms->dist, insert_length, sr.len, sr.len_code_delta, distance_code); } *num_literals += insert_length; insert_length = 0; /* Put the hash keys into the table, if there are enough bytes left. Depending on the hasher implementation, it can push all positions in the given range or only a subset of them. Avoid hash poisoning with RLE data. */ { size_t range_start = position + 2; size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); if (sr.distance < (sr.len >> 2)) { range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, range_start, position + sr.len - (sr.distance << 2))); } FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, range_end); } position += sr.len; } else { ++insert_length; ++position; /* If we have not seen matches for a long time, we can skip some match lookups. Unsuccessful match lookups are very very expensive and this kind of a heuristic speeds up compression quite a lot. */ if (position > apply_random_heuristics) { /* Going through uncompressible data, jump. */ if (position > apply_random_heuristics + 4 * random_heuristics_window_size) { /* It is quite a long time since we saw a copy, so we assume that this data is not compressible, and store hashes less often. Hashes of non compressible data are less likely to turn out to be useful in the future, too, so we store less of them to not to flood out the hash table of good compressible data. */ const size_t kMargin = BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); size_t pos_jump = BROTLI_MIN(size_t, position + 16, pos_end - kMargin); for (; position < pos_jump; position += 4) { FN(Store)(privat, ringbuffer, ringbuffer_mask, position); insert_length += 4; } } else { const size_t kMargin = BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); size_t pos_jump = BROTLI_MIN(size_t, position + 8, pos_end - kMargin); for (; position < pos_jump; position += 2) { FN(Store)(privat, ringbuffer, ringbuffer_mask, position); insert_length += 2; } } } } } insert_length += pos_end - position; *last_insert_len = insert_length; *num_commands += (size_t)(commands - orig_commands); } dvisvgm-3.5/libs/brotli/enc/bit_cost.c000066400000000000000000000014551501401750600200070ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Functions to estimate the bit cost of Huffman trees. */ #include "bit_cost.h" #include #include "../common/constants.h" #include "../common/platform.h" #include "fast_log.h" #include "histogram.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define FN(X) X ## Literal #include "bit_cost_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Command #include "bit_cost_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Distance #include "bit_cost_inc.h" /* NOLINT(build/include) */ #undef FN #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/bit_cost.h000066400000000000000000000032251501401750600200110ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Functions to estimate the bit cost of Huffman trees. */ #ifndef BROTLI_ENC_BIT_COST_H_ #define BROTLI_ENC_BIT_COST_H_ #include #include "../common/platform.h" #include "fast_log.h" #include "histogram.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static BROTLI_INLINE double ShannonEntropy( const uint32_t* population, size_t size, size_t* total) { size_t sum = 0; double retval = 0; const uint32_t* population_end = population + size; size_t p; if (size & 1) { goto odd_number_of_elements_left; } while (population < population_end) { p = *population++; sum += p; retval -= (double)p * FastLog2(p); odd_number_of_elements_left: p = *population++; sum += p; retval -= (double)p * FastLog2(p); } if (sum) retval += (double)sum * FastLog2(sum); *total = sum; return retval; } static BROTLI_INLINE double BitsEntropy( const uint32_t* population, size_t size) { size_t sum; double retval = ShannonEntropy(population, size, &sum); if (retval < (double)sum) { /* At least one bit per literal is needed. */ retval = (double)sum; } return retval; } BROTLI_INTERNAL double BrotliPopulationCostLiteral(const HistogramLiteral*); BROTLI_INTERNAL double BrotliPopulationCostCommand(const HistogramCommand*); BROTLI_INTERNAL double BrotliPopulationCostDistance(const HistogramDistance*); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_BIT_COST_H_ */ dvisvgm-3.5/libs/brotli/enc/bit_cost_inc.h000066400000000000000000000100151501401750600206350ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN */ #define HistogramType FN(Histogram) double FN(BrotliPopulationCost)(const HistogramType* histogram) { static const double kOneSymbolHistogramCost = 12; static const double kTwoSymbolHistogramCost = 20; static const double kThreeSymbolHistogramCost = 28; static const double kFourSymbolHistogramCost = 37; const size_t data_size = FN(HistogramDataSize)(); int count = 0; size_t s[5]; double bits = 0.0; size_t i; if (histogram->total_count_ == 0) { return kOneSymbolHistogramCost; } for (i = 0; i < data_size; ++i) { if (histogram->data_[i] > 0) { s[count] = i; ++count; if (count > 4) break; } } if (count == 1) { return kOneSymbolHistogramCost; } if (count == 2) { return (kTwoSymbolHistogramCost + (double)histogram->total_count_); } if (count == 3) { const uint32_t histo0 = histogram->data_[s[0]]; const uint32_t histo1 = histogram->data_[s[1]]; const uint32_t histo2 = histogram->data_[s[2]]; const uint32_t histomax = BROTLI_MAX(uint32_t, histo0, BROTLI_MAX(uint32_t, histo1, histo2)); return (kThreeSymbolHistogramCost + 2 * (histo0 + histo1 + histo2) - histomax); } if (count == 4) { uint32_t histo[4]; uint32_t h23; uint32_t histomax; for (i = 0; i < 4; ++i) { histo[i] = histogram->data_[s[i]]; } /* Sort */ for (i = 0; i < 4; ++i) { size_t j; for (j = i + 1; j < 4; ++j) { if (histo[j] > histo[i]) { BROTLI_SWAP(uint32_t, histo, j, i); } } } h23 = histo[2] + histo[3]; histomax = BROTLI_MAX(uint32_t, h23, histo[0]); return (kFourSymbolHistogramCost + 3 * h23 + 2 * (histo[0] + histo[1]) - histomax); } { /* In this loop we compute the entropy of the histogram and simultaneously build a simplified histogram of the code length codes where we use the zero repeat code 17, but we don't use the non-zero repeat code 16. */ size_t max_depth = 1; uint32_t depth_histo[BROTLI_CODE_LENGTH_CODES] = { 0 }; const double log2total = FastLog2(histogram->total_count_); for (i = 0; i < data_size;) { if (histogram->data_[i] > 0) { /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) = = log2(total_count) - log2(count(symbol)) */ double log2p = log2total - FastLog2(histogram->data_[i]); /* Approximate the bit depth by round(-log2(P(symbol))) */ size_t depth = (size_t)(log2p + 0.5); bits += histogram->data_[i] * log2p; if (depth > 15) { depth = 15; } if (depth > max_depth) { max_depth = depth; } ++depth_histo[depth]; ++i; } else { /* Compute the run length of zeros and add the appropriate number of 0 and 17 code length codes to the code length code histogram. */ uint32_t reps = 1; size_t k; for (k = i + 1; k < data_size && histogram->data_[k] == 0; ++k) { ++reps; } i += reps; if (i == data_size) { /* Don't add any cost for the last zero run, since these are encoded only implicitly. */ break; } if (reps < 3) { depth_histo[0] += reps; } else { reps -= 2; while (reps > 0) { ++depth_histo[BROTLI_REPEAT_ZERO_CODE_LENGTH]; /* Add the 3 extra bits for the 17 code length code. */ bits += 3; reps >>= 3; } } } } /* Add the estimated encoding cost of the code length code histogram. */ bits += (double)(18 + 2 * max_depth); /* Add the entropy of the code length code histogram. */ bits += BitsEntropy(depth_histo, BROTLI_CODE_LENGTH_CODES); } return bits; } #undef HistogramType dvisvgm-3.5/libs/brotli/enc/block_encoder_inc.h000066400000000000000000000021611501401750600216230ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN */ #define HistogramType FN(Histogram) /* Creates entropy codes for all block types and stores them to the bit stream. */ static void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self, const HistogramType* histograms, const size_t histograms_size, const size_t alphabet_size, HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) { const size_t table_size = histograms_size * self->histogram_length_; self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size); self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size); if (BROTLI_IS_OOM(m)) return; { size_t i; for (i = 0; i < histograms_size; ++i) { size_t ix = i * self->histogram_length_; BuildAndStoreHuffmanTree(&histograms[i].data_[0], self->histogram_length_, alphabet_size, tree, &self->depths_[ix], &self->bits_[ix], storage_ix, storage); } } } #undef HistogramType dvisvgm-3.5/libs/brotli/enc/block_splitter.c000066400000000000000000000163431501401750600212230ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Block split point selection utilities. */ #include "block_splitter.h" #include /* memcpy, memset */ #include "../common/platform.h" #include "bit_cost.h" #include "cluster.h" #include "command.h" #include "fast_log.h" #include "histogram.h" #include "memory.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static const size_t kMaxLiteralHistograms = 100; static const size_t kMaxCommandHistograms = 50; static const double kLiteralBlockSwitchCost = 28.1; static const double kCommandBlockSwitchCost = 13.5; static const double kDistanceBlockSwitchCost = 14.6; static const size_t kLiteralStrideLength = 70; static const size_t kCommandStrideLength = 40; static const size_t kDistanceStrideLength = 40; static const size_t kSymbolsPerLiteralHistogram = 544; static const size_t kSymbolsPerCommandHistogram = 530; static const size_t kSymbolsPerDistanceHistogram = 544; static const size_t kMinLengthForBlockSplitting = 128; static const size_t kIterMulForRefining = 2; static const size_t kMinItersForRefining = 100; static size_t CountLiterals(const Command* cmds, const size_t num_commands) { /* Count how many we have. */ size_t total_length = 0; size_t i; for (i = 0; i < num_commands; ++i) { total_length += cmds[i].insert_len_; } return total_length; } static void CopyLiteralsToByteArray(const Command* cmds, const size_t num_commands, const uint8_t* data, const size_t offset, const size_t mask, uint8_t* literals) { size_t pos = 0; size_t from_pos = offset & mask; size_t i; for (i = 0; i < num_commands; ++i) { size_t insert_len = cmds[i].insert_len_; if (from_pos + insert_len > mask) { size_t head_size = mask + 1 - from_pos; memcpy(literals + pos, data + from_pos, head_size); from_pos = 0; pos += head_size; insert_len -= head_size; } if (insert_len > 0) { memcpy(literals + pos, data + from_pos, insert_len); pos += insert_len; } from_pos = (from_pos + insert_len + CommandCopyLen(&cmds[i])) & mask; } } static BROTLI_INLINE uint32_t MyRand(uint32_t* seed) { /* Initial seed should be 7. In this case, loop length is (1 << 29). */ *seed *= 16807U; return *seed; } static BROTLI_INLINE double BitCost(size_t count) { return count == 0 ? -2.0 : FastLog2(count); } #define HISTOGRAMS_PER_BATCH 64 #define CLUSTERS_PER_BATCH 16 #define FN(X) X ## Literal #define DataType uint8_t /* NOLINTNEXTLINE(build/include) */ #include "block_splitter_inc.h" #undef DataType #undef FN #define FN(X) X ## Command #define DataType uint16_t /* NOLINTNEXTLINE(build/include) */ #include "block_splitter_inc.h" #undef FN #define FN(X) X ## Distance /* NOLINTNEXTLINE(build/include) */ #include "block_splitter_inc.h" #undef DataType #undef FN void BrotliInitBlockSplit(BlockSplit* self) { self->num_types = 0; self->num_blocks = 0; self->types = 0; self->lengths = 0; self->types_alloc_size = 0; self->lengths_alloc_size = 0; } void BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self) { BROTLI_FREE(m, self->types); BROTLI_FREE(m, self->lengths); } /* Extracts literals, command distance and prefix codes, then applies * SplitByteVector to create partitioning. */ void BrotliSplitBlock(MemoryManager* m, const Command* cmds, const size_t num_commands, const uint8_t* data, const size_t pos, const size_t mask, const BrotliEncoderParams* params, BlockSplit* literal_split, BlockSplit* insert_and_copy_split, BlockSplit* dist_split) { { size_t literals_count = CountLiterals(cmds, num_commands); uint8_t* literals = BROTLI_ALLOC(m, uint8_t, literals_count); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literals)) return; /* Create a continuous array of literals. */ CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals); /* Create the block split on the array of literals. * Literal histograms can have alphabet size up to 256. * Though, to accomodate context modeling, less than half of maximum size * is allowed. */ SplitByteVectorLiteral( m, literals, literals_count, kSymbolsPerLiteralHistogram, kMaxLiteralHistograms, kLiteralStrideLength, kLiteralBlockSwitchCost, params, literal_split); if (BROTLI_IS_OOM(m)) return; BROTLI_FREE(m, literals); /* NB: this might be a good place for injecting extra splitting without * increasing encoder complexity; however, output parition would be less * optimal than one produced with forced splitting inside * SplitByteVector (FindBlocks / ClusterBlocks). */ } { /* Compute prefix codes for commands. */ uint16_t* insert_and_copy_codes = BROTLI_ALLOC(m, uint16_t, num_commands); size_t i; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(insert_and_copy_codes)) return; for (i = 0; i < num_commands; ++i) { insert_and_copy_codes[i] = cmds[i].cmd_prefix_; } /* Create the block split on the array of command prefixes. */ SplitByteVectorCommand( m, insert_and_copy_codes, num_commands, kSymbolsPerCommandHistogram, kMaxCommandHistograms, kCommandStrideLength, kCommandBlockSwitchCost, params, insert_and_copy_split); if (BROTLI_IS_OOM(m)) return; /* TODO(eustas): reuse for distances? */ BROTLI_FREE(m, insert_and_copy_codes); } { /* Create a continuous array of distance prefixes. */ uint16_t* distance_prefixes = BROTLI_ALLOC(m, uint16_t, num_commands); size_t j = 0; size_t i; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_prefixes)) return; for (i = 0; i < num_commands; ++i) { const Command* cmd = &cmds[i]; if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { distance_prefixes[j++] = cmd->dist_prefix_ & 0x3FF; } } /* Create the block split on the array of distance prefixes. */ SplitByteVectorDistance( m, distance_prefixes, j, kSymbolsPerDistanceHistogram, kMaxCommandHistograms, kDistanceStrideLength, kDistanceBlockSwitchCost, params, dist_split); if (BROTLI_IS_OOM(m)) return; BROTLI_FREE(m, distance_prefixes); } } #if defined(BROTLI_TEST) size_t CountLiteralsForTest(const Command*, const size_t); size_t CountLiteralsForTest(const Command* cmds, const size_t num_commands) { return CountLiterals(cmds, num_commands); } void CopyLiteralsToByteArrayForTest(const Command*, const size_t, const uint8_t*, const size_t, const size_t, uint8_t*); void CopyLiteralsToByteArrayForTest(const Command* cmds, const size_t num_commands, const uint8_t* data, const size_t offset, const size_t mask, uint8_t* literals) { CopyLiteralsToByteArray(cmds, num_commands, data, offset, mask, literals); } #endif #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/block_splitter.h000066400000000000000000000032121501401750600212170ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Block split point selection utilities. */ #ifndef BROTLI_ENC_BLOCK_SPLITTER_H_ #define BROTLI_ENC_BLOCK_SPLITTER_H_ #include #include "../common/platform.h" #include "command.h" #include "memory.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct BlockSplit { size_t num_types; /* Amount of distinct types */ size_t num_blocks; /* Amount of values in types and length */ uint8_t* types; uint32_t* lengths; size_t types_alloc_size; size_t lengths_alloc_size; } BlockSplit; BROTLI_INTERNAL void BrotliInitBlockSplit(BlockSplit* self); BROTLI_INTERNAL void BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self); BROTLI_INTERNAL void BrotliSplitBlock(MemoryManager* m, const Command* cmds, const size_t num_commands, const uint8_t* data, const size_t offset, const size_t mask, const BrotliEncoderParams* params, BlockSplit* literal_split, BlockSplit* insert_and_copy_split, BlockSplit* dist_split); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_BLOCK_SPLITTER_H_ */ dvisvgm-3.5/libs/brotli/enc/block_splitter_inc.h000066400000000000000000000443611501401750600220620ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN, DataType */ #define HistogramType FN(Histogram) static void FN(InitialEntropyCodes)(const DataType* data, size_t length, size_t stride, size_t num_histograms, HistogramType* histograms) { uint32_t seed = 7; size_t block_length = length / num_histograms; size_t i; FN(ClearHistograms)(histograms, num_histograms); for (i = 0; i < num_histograms; ++i) { size_t pos = length * i / num_histograms; if (i != 0) { pos += MyRand(&seed) % block_length; } if (pos + stride >= length) { pos = length - stride - 1; } FN(HistogramAddVector)(&histograms[i], data + pos, stride); } } static void FN(RandomSample)(uint32_t* seed, const DataType* data, size_t length, size_t stride, HistogramType* sample) { size_t pos = 0; if (stride >= length) { stride = length; } else { pos = MyRand(seed) % (length - stride + 1); } FN(HistogramAddVector)(sample, data + pos, stride); } static void FN(RefineEntropyCodes)(const DataType* data, size_t length, size_t stride, size_t num_histograms, HistogramType* histograms, HistogramType* tmp) { size_t iters = kIterMulForRefining * length / stride + kMinItersForRefining; uint32_t seed = 7; size_t iter; iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms; for (iter = 0; iter < iters; ++iter) { FN(HistogramClear)(tmp); FN(RandomSample)(&seed, data, length, stride, tmp); FN(HistogramAddHistogram)(&histograms[iter % num_histograms], tmp); } } /* Assigns a block id from the range [0, num_histograms) to each data element in data[0..length) and fills in block_id[0..length) with the assigned values. Returns the number of blocks, i.e. one plus the number of block switches. */ static size_t FN(FindBlocks)(const DataType* data, const size_t length, const double block_switch_bitcost, const size_t num_histograms, const HistogramType* histograms, double* insert_cost, double* cost, uint8_t* switch_signal, uint8_t* block_id) { const size_t alphabet_size = FN(HistogramDataSize)(); const size_t bitmap_len = (num_histograms + 7) >> 3; size_t num_blocks = 1; size_t byte_ix; size_t i; size_t j; BROTLI_DCHECK(num_histograms <= 256); /* Trivial case: single historgram -> single block type. */ if (num_histograms <= 1) { for (i = 0; i < length; ++i) { block_id[i] = 0; } return 1; } /* Fill bitcost for each symbol of all histograms. * Non-existing symbol cost: 2 + log2(total_count). * Regular symbol cost: -log2(symbol_count / total_count). */ memset(insert_cost, 0, sizeof(insert_cost[0]) * alphabet_size * num_histograms); for (i = 0; i < num_histograms; ++i) { insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_); } for (i = alphabet_size; i != 0;) { /* Reverse order to use the 0-th row as a temporary storage. */ --i; for (j = 0; j < num_histograms; ++j) { insert_cost[i * num_histograms + j] = insert_cost[j] - BitCost(histograms[j].data_[i]); } } /* After each iteration of this loop, cost[k] will contain the difference between the minimum cost of arriving at the current byte position using entropy code k, and the minimum cost of arriving at the current byte position. This difference is capped at the block switch cost, and if it reaches block switch cost, it means that when we trace back from the last position, we need to switch here. */ memset(cost, 0, sizeof(cost[0]) * num_histograms); memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmap_len); for (byte_ix = 0; byte_ix < length; ++byte_ix) { size_t ix = byte_ix * bitmap_len; size_t symbol = data[byte_ix]; size_t insert_cost_ix = symbol * num_histograms; double min_cost = 1e99; double block_switch_cost = block_switch_bitcost; size_t k; for (k = 0; k < num_histograms; ++k) { /* We are coding the symbol with entropy code k. */ cost[k] += insert_cost[insert_cost_ix + k]; if (cost[k] < min_cost) { min_cost = cost[k]; block_id[byte_ix] = (uint8_t)k; } } /* More blocks for the beginning. */ if (byte_ix < 2000) { block_switch_cost *= 0.77 + 0.07 * (double)byte_ix / 2000; } for (k = 0; k < num_histograms; ++k) { cost[k] -= min_cost; if (cost[k] >= block_switch_cost) { const uint8_t mask = (uint8_t)(1u << (k & 7)); cost[k] = block_switch_cost; BROTLI_DCHECK((k >> 3) < bitmap_len); switch_signal[ix + (k >> 3)] |= mask; } } } byte_ix = length - 1; { /* Trace back from the last position and switch at the marked places. */ size_t ix = byte_ix * bitmap_len; uint8_t cur_id = block_id[byte_ix]; while (byte_ix > 0) { const uint8_t mask = (uint8_t)(1u << (cur_id & 7)); BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmap_len); --byte_ix; ix -= bitmap_len; if (switch_signal[ix + (cur_id >> 3)] & mask) { if (cur_id != block_id[byte_ix]) { cur_id = block_id[byte_ix]; ++num_blocks; } } block_id[byte_ix] = cur_id; } } return num_blocks; } static size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length, uint16_t* new_id, const size_t num_histograms) { static const uint16_t kInvalidId = 256; uint16_t next_id = 0; size_t i; for (i = 0; i < num_histograms; ++i) { new_id[i] = kInvalidId; } for (i = 0; i < length; ++i) { BROTLI_DCHECK(block_ids[i] < num_histograms); if (new_id[block_ids[i]] == kInvalidId) { new_id[block_ids[i]] = next_id++; } } for (i = 0; i < length; ++i) { block_ids[i] = (uint8_t)new_id[block_ids[i]]; BROTLI_DCHECK(block_ids[i] < num_histograms); } BROTLI_DCHECK(next_id <= num_histograms); return next_id; } static void FN(BuildBlockHistograms)(const DataType* data, const size_t length, const uint8_t* block_ids, const size_t num_histograms, HistogramType* histograms) { size_t i; FN(ClearHistograms)(histograms, num_histograms); for (i = 0; i < length; ++i) { FN(HistogramAdd)(&histograms[block_ids[i]], data[i]); } } /* Given the initial partitioning build partitioning with limited number * of histograms (and block types). */ static void FN(ClusterBlocks)(MemoryManager* m, const DataType* data, const size_t length, const size_t num_blocks, uint8_t* block_ids, BlockSplit* split) { uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks); uint32_t* u32 = BROTLI_ALLOC(m, uint32_t, num_blocks + 4 * HISTOGRAMS_PER_BATCH); const size_t expected_num_clusters = CLUSTERS_PER_BATCH * (num_blocks + HISTOGRAMS_PER_BATCH - 1) / HISTOGRAMS_PER_BATCH; size_t all_histograms_size = 0; size_t all_histograms_capacity = expected_num_clusters; HistogramType* all_histograms = BROTLI_ALLOC(m, HistogramType, all_histograms_capacity); size_t cluster_size_size = 0; size_t cluster_size_capacity = expected_num_clusters; uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity); size_t num_clusters = 0; HistogramType* histograms = BROTLI_ALLOC(m, HistogramType, BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH)); size_t max_num_pairs = HISTOGRAMS_PER_BATCH * HISTOGRAMS_PER_BATCH / 2; size_t pairs_capacity = max_num_pairs + 1; HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity); size_t pos = 0; uint32_t* clusters; size_t num_final_clusters; static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; uint32_t* new_index; size_t i; uint32_t* BROTLI_RESTRICT const sizes = u32 + 0 * HISTOGRAMS_PER_BATCH; uint32_t* BROTLI_RESTRICT const new_clusters = u32 + 1 * HISTOGRAMS_PER_BATCH; uint32_t* BROTLI_RESTRICT const symbols = u32 + 2 * HISTOGRAMS_PER_BATCH; uint32_t* BROTLI_RESTRICT const remap = u32 + 3 * HISTOGRAMS_PER_BATCH; uint32_t* BROTLI_RESTRICT const block_lengths = u32 + 4 * HISTOGRAMS_PER_BATCH; /* TODO(eustas): move to arena? */ HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 2); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histogram_symbols) || BROTLI_IS_NULL(u32) || BROTLI_IS_NULL(all_histograms) || BROTLI_IS_NULL(cluster_size) || BROTLI_IS_NULL(histograms) || BROTLI_IS_NULL(pairs) || BROTLI_IS_NULL(tmp)) { return; } memset(u32, 0, (num_blocks + 4 * HISTOGRAMS_PER_BATCH) * sizeof(uint32_t)); /* Calculate block lengths (convert repeating values -> series length). */ { size_t block_idx = 0; for (i = 0; i < length; ++i) { BROTLI_DCHECK(block_idx < num_blocks); ++block_lengths[block_idx]; if (i + 1 == length || block_ids[i] != block_ids[i + 1]) { ++block_idx; } } BROTLI_DCHECK(block_idx == num_blocks); } /* Pre-cluster blocks (cluster batches). */ for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH) { const size_t num_to_combine = BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH); size_t num_new_clusters; size_t j; for (j = 0; j < num_to_combine; ++j) { size_t k; size_t block_length = block_lengths[i + j]; FN(HistogramClear)(&histograms[j]); for (k = 0; k < block_length; ++k) { FN(HistogramAdd)(&histograms[j], data[pos++]); } histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]); new_clusters[j] = (uint32_t)j; symbols[j] = (uint32_t)j; sizes[j] = 1; } num_new_clusters = FN(BrotliHistogramCombine)( histograms, tmp, sizes, symbols, new_clusters, pairs, num_to_combine, num_to_combine, HISTOGRAMS_PER_BATCH, max_num_pairs); BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms, all_histograms_capacity, all_histograms_size + num_new_clusters); BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size, cluster_size_capacity, cluster_size_size + num_new_clusters); if (BROTLI_IS_OOM(m)) return; for (j = 0; j < num_new_clusters; ++j) { all_histograms[all_histograms_size++] = histograms[new_clusters[j]]; cluster_size[cluster_size_size++] = sizes[new_clusters[j]]; remap[new_clusters[j]] = (uint32_t)j; } for (j = 0; j < num_to_combine; ++j) { histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]]; } num_clusters += num_new_clusters; BROTLI_DCHECK(num_clusters == cluster_size_size); BROTLI_DCHECK(num_clusters == all_histograms_size); } BROTLI_FREE(m, histograms); /* Final clustering. */ max_num_pairs = BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters); if (pairs_capacity < max_num_pairs + 1) { BROTLI_FREE(m, pairs); pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(pairs)) return; } clusters = BROTLI_ALLOC(m, uint32_t, num_clusters); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(clusters)) return; for (i = 0; i < num_clusters; ++i) { clusters[i] = (uint32_t)i; } num_final_clusters = FN(BrotliHistogramCombine)( all_histograms, tmp, cluster_size, histogram_symbols, clusters, pairs, num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES, max_num_pairs); BROTLI_FREE(m, pairs); BROTLI_FREE(m, cluster_size); /* Assign blocks to final histograms. */ new_index = BROTLI_ALLOC(m, uint32_t, num_clusters); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return; for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex; pos = 0; { uint32_t next_index = 0; for (i = 0; i < num_blocks; ++i) { size_t j; uint32_t best_out; double best_bits; FN(HistogramClear)(tmp); for (j = 0; j < block_lengths[i]; ++j) { FN(HistogramAdd)(tmp, data[pos++]); } /* Among equally good histograms prefer last used. */ /* TODO(eustas): should we give a block-switch discount here? */ best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1]; best_bits = FN(BrotliHistogramBitCostDistance)( tmp, &all_histograms[best_out], tmp + 1); for (j = 0; j < num_final_clusters; ++j) { const double cur_bits = FN(BrotliHistogramBitCostDistance)( tmp, &all_histograms[clusters[j]], tmp + 1); if (cur_bits < best_bits) { best_bits = cur_bits; best_out = clusters[j]; } } histogram_symbols[i] = best_out; if (new_index[best_out] == kInvalidIndex) { new_index[best_out] = next_index++; } } } BROTLI_FREE(m, tmp); BROTLI_FREE(m, clusters); BROTLI_FREE(m, all_histograms); BROTLI_ENSURE_CAPACITY( m, uint8_t, split->types, split->types_alloc_size, num_blocks); BROTLI_ENSURE_CAPACITY( m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks); if (BROTLI_IS_OOM(m)) return; /* Rewrite final assignment to block-split. There might be less blocks * than |num_blocks| due to clustering. */ { uint32_t cur_length = 0; size_t block_idx = 0; uint8_t max_type = 0; for (i = 0; i < num_blocks; ++i) { cur_length += block_lengths[i]; if (i + 1 == num_blocks || histogram_symbols[i] != histogram_symbols[i + 1]) { const uint8_t id = (uint8_t)new_index[histogram_symbols[i]]; split->types[block_idx] = id; split->lengths[block_idx] = cur_length; max_type = BROTLI_MAX(uint8_t, max_type, id); cur_length = 0; ++block_idx; } } split->num_blocks = block_idx; split->num_types = (size_t)max_type + 1; } BROTLI_FREE(m, new_index); BROTLI_FREE(m, u32); BROTLI_FREE(m, histogram_symbols); } /* Create BlockSplit (partitioning) given the limits, estimates and "effort" * parameters. * * NB: max_histograms is often less than number of histograms allowed by format; * this is done intentionally, to save some "space" for context-aware * clustering (here entropy is estimated for context-free symbols). */ static void FN(SplitByteVector)(MemoryManager* m, const DataType* data, const size_t length, const size_t symbols_per_histogram, const size_t max_histograms, const size_t sampling_stride_length, const double block_switch_cost, const BrotliEncoderParams* params, BlockSplit* split) { const size_t data_size = FN(HistogramDataSize)(); HistogramType* histograms; HistogramType* tmp; /* Calculate number of histograms; initial estimate is one histogram per * specified amount of symbols; however, this value is capped. */ size_t num_histograms = length / symbols_per_histogram + 1; if (num_histograms > max_histograms) { num_histograms = max_histograms; } /* Corner case: no input. */ if (length == 0) { split->num_types = 1; return; } if (length < kMinLengthForBlockSplitting) { BROTLI_ENSURE_CAPACITY(m, uint8_t, split->types, split->types_alloc_size, split->num_blocks + 1); BROTLI_ENSURE_CAPACITY(m, uint32_t, split->lengths, split->lengths_alloc_size, split->num_blocks + 1); if (BROTLI_IS_OOM(m)) return; split->num_types = 1; split->types[split->num_blocks] = 0; split->lengths[split->num_blocks] = (uint32_t)length; split->num_blocks++; return; } histograms = BROTLI_ALLOC(m, HistogramType, num_histograms + 1); tmp = histograms + num_histograms; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histograms)) return; /* Find good entropy codes. */ FN(InitialEntropyCodes)(data, length, sampling_stride_length, num_histograms, histograms); FN(RefineEntropyCodes)(data, length, sampling_stride_length, num_histograms, histograms, tmp); { /* Find a good path through literals with the good entropy codes. */ uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length); size_t num_blocks = 0; const size_t bitmaplen = (num_histograms + 7) >> 3; double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms); double* cost = BROTLI_ALLOC(m, double, num_histograms); uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen); uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms); const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY ? 3 : 10; size_t i; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(block_ids) || BROTLI_IS_NULL(insert_cost) || BROTLI_IS_NULL(cost) || BROTLI_IS_NULL(switch_signal) || BROTLI_IS_NULL(new_id)) { return; } for (i = 0; i < iters; ++i) { num_blocks = FN(FindBlocks)(data, length, block_switch_cost, num_histograms, histograms, insert_cost, cost, switch_signal, block_ids); num_histograms = FN(RemapBlockIds)(block_ids, length, new_id, num_histograms); FN(BuildBlockHistograms)(data, length, block_ids, num_histograms, histograms); } BROTLI_FREE(m, insert_cost); BROTLI_FREE(m, cost); BROTLI_FREE(m, switch_signal); BROTLI_FREE(m, new_id); BROTLI_FREE(m, histograms); FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split); if (BROTLI_IS_OOM(m)) return; BROTLI_FREE(m, block_ids); } } #undef HistogramType dvisvgm-3.5/libs/brotli/enc/brotli_bit_stream.c000066400000000000000000001430761501401750600217130ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Brotli bit stream functions to support the low level format. There are no compression algorithms here, just the right ordering of bits to match the specs. */ #include "brotli_bit_stream.h" #include /* memcpy, memset */ #include #include "../common/constants.h" #include "../common/context.h" #include "../common/platform.h" #include "entropy_encode.h" #include "entropy_encode_static.h" #include "fast_log.h" #include "histogram.h" #include "memory.h" #include "write_bits.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define MAX_HUFFMAN_TREE_SIZE (2 * BROTLI_NUM_COMMAND_SYMBOLS + 1) /* The maximum size of Huffman dictionary for distances assuming that NPOSTFIX = 0 and NDIRECT = 0. */ #define MAX_SIMPLE_DISTANCE_ALPHABET_SIZE \ BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_LARGE_MAX_DISTANCE_BITS) /* MAX_SIMPLE_DISTANCE_ALPHABET_SIZE == 140 */ static BROTLI_INLINE uint32_t BlockLengthPrefixCode(uint32_t len) { uint32_t code = (len >= 177) ? (len >= 753 ? 20 : 14) : (len >= 41 ? 7 : 0); while (code < (BROTLI_NUM_BLOCK_LEN_SYMBOLS - 1) && len >= _kBrotliPrefixCodeRanges[code + 1].offset) ++code; return code; } static BROTLI_INLINE void GetBlockLengthPrefixCode(uint32_t len, size_t* code, uint32_t* n_extra, uint32_t* extra) { *code = BlockLengthPrefixCode(len); *n_extra = _kBrotliPrefixCodeRanges[*code].nbits; *extra = len - _kBrotliPrefixCodeRanges[*code].offset; } typedef struct BlockTypeCodeCalculator { size_t last_type; size_t second_last_type; } BlockTypeCodeCalculator; static void InitBlockTypeCodeCalculator(BlockTypeCodeCalculator* self) { self->last_type = 1; self->second_last_type = 0; } static BROTLI_INLINE size_t NextBlockTypeCode( BlockTypeCodeCalculator* calculator, uint8_t type) { size_t type_code = (type == calculator->last_type + 1) ? 1u : (type == calculator->second_last_type) ? 0u : type + 2u; calculator->second_last_type = calculator->last_type; calculator->last_type = type; return type_code; } /* |nibblesbits| represents the 2 bits to encode MNIBBLES (0-3) REQUIRES: length > 0 REQUIRES: length <= (1 << 24) */ static void BrotliEncodeMlen(size_t length, uint64_t* bits, size_t* numbits, uint64_t* nibblesbits) { size_t lg = (length == 1) ? 1 : Log2FloorNonZero((uint32_t)(length - 1)) + 1; size_t mnibbles = (lg < 16 ? 16 : (lg + 3)) / 4; BROTLI_DCHECK(length > 0); BROTLI_DCHECK(length <= (1 << 24)); BROTLI_DCHECK(lg <= 24); *nibblesbits = mnibbles - 4; *numbits = mnibbles * 4; *bits = length - 1; } static BROTLI_INLINE void StoreCommandExtra( const Command* cmd, size_t* storage_ix, uint8_t* storage) { uint32_t copylen_code = CommandCopyLenCode(cmd); uint16_t inscode = GetInsertLengthCode(cmd->insert_len_); uint16_t copycode = GetCopyLengthCode(copylen_code); uint32_t insnumextra = GetInsertExtra(inscode); uint64_t insextraval = cmd->insert_len_ - GetInsertBase(inscode); uint64_t copyextraval = copylen_code - GetCopyBase(copycode); uint64_t bits = (copyextraval << insnumextra) | insextraval; BrotliWriteBits( insnumextra + GetCopyExtra(copycode), bits, storage_ix, storage); } /* Data structure that stores almost everything that is needed to encode each block switch command. */ typedef struct BlockSplitCode { BlockTypeCodeCalculator type_code_calculator; uint8_t type_depths[BROTLI_MAX_BLOCK_TYPE_SYMBOLS]; uint16_t type_bits[BROTLI_MAX_BLOCK_TYPE_SYMBOLS]; uint8_t length_depths[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; uint16_t length_bits[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; } BlockSplitCode; /* Stores a number between 0 and 255. */ static void StoreVarLenUint8(size_t n, size_t* storage_ix, uint8_t* storage) { if (n == 0) { BrotliWriteBits(1, 0, storage_ix, storage); } else { size_t nbits = Log2FloorNonZero(n); BrotliWriteBits(1, 1, storage_ix, storage); BrotliWriteBits(3, nbits, storage_ix, storage); BrotliWriteBits(nbits, n - ((size_t)1 << nbits), storage_ix, storage); } } /* Stores the compressed meta-block header. REQUIRES: length > 0 REQUIRES: length <= (1 << 24) */ static void StoreCompressedMetaBlockHeader(BROTLI_BOOL is_final_block, size_t length, size_t* storage_ix, uint8_t* storage) { uint64_t lenbits; size_t nlenbits; uint64_t nibblesbits; /* Write ISLAST bit. */ BrotliWriteBits(1, (uint64_t)is_final_block, storage_ix, storage); /* Write ISEMPTY bit. */ if (is_final_block) { BrotliWriteBits(1, 0, storage_ix, storage); } BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits); BrotliWriteBits(2, nibblesbits, storage_ix, storage); BrotliWriteBits(nlenbits, lenbits, storage_ix, storage); if (!is_final_block) { /* Write ISUNCOMPRESSED bit. */ BrotliWriteBits(1, 0, storage_ix, storage); } } /* Stores the uncompressed meta-block header. REQUIRES: length > 0 REQUIRES: length <= (1 << 24) */ static void BrotliStoreUncompressedMetaBlockHeader(size_t length, size_t* storage_ix, uint8_t* storage) { uint64_t lenbits; size_t nlenbits; uint64_t nibblesbits; /* Write ISLAST bit. Uncompressed block cannot be the last one, so set to 0. */ BrotliWriteBits(1, 0, storage_ix, storage); BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits); BrotliWriteBits(2, nibblesbits, storage_ix, storage); BrotliWriteBits(nlenbits, lenbits, storage_ix, storage); /* Write ISUNCOMPRESSED bit. */ BrotliWriteBits(1, 1, storage_ix, storage); } static void BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask( const int num_codes, const uint8_t* code_length_bitdepth, size_t* storage_ix, uint8_t* storage) { static const uint8_t kStorageOrder[BROTLI_CODE_LENGTH_CODES] = { 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; /* The bit lengths of the Huffman code over the code length alphabet are compressed with the following static Huffman code: Symbol Code ------ ---- 0 00 1 1110 2 110 3 01 4 10 5 1111 */ static const uint8_t kHuffmanBitLengthHuffmanCodeSymbols[6] = { 0, 7, 3, 2, 1, 15 }; static const uint8_t kHuffmanBitLengthHuffmanCodeBitLengths[6] = { 2, 4, 3, 2, 2, 4 }; size_t skip_some = 0; /* skips none. */ /* Throw away trailing zeros: */ size_t codes_to_store = BROTLI_CODE_LENGTH_CODES; if (num_codes > 1) { for (; codes_to_store > 0; --codes_to_store) { if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { break; } } } if (code_length_bitdepth[kStorageOrder[0]] == 0 && code_length_bitdepth[kStorageOrder[1]] == 0) { skip_some = 2; /* skips two. */ if (code_length_bitdepth[kStorageOrder[2]] == 0) { skip_some = 3; /* skips three. */ } } BrotliWriteBits(2, skip_some, storage_ix, storage); { size_t i; for (i = skip_some; i < codes_to_store; ++i) { size_t l = code_length_bitdepth[kStorageOrder[i]]; BrotliWriteBits(kHuffmanBitLengthHuffmanCodeBitLengths[l], kHuffmanBitLengthHuffmanCodeSymbols[l], storage_ix, storage); } } } static void BrotliStoreHuffmanTreeToBitMask( const size_t huffman_tree_size, const uint8_t* huffman_tree, const uint8_t* huffman_tree_extra_bits, const uint8_t* code_length_bitdepth, const uint16_t* code_length_bitdepth_symbols, size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage) { size_t i; for (i = 0; i < huffman_tree_size; ++i) { size_t ix = huffman_tree[i]; BrotliWriteBits(code_length_bitdepth[ix], code_length_bitdepth_symbols[ix], storage_ix, storage); /* Extra bits */ switch (ix) { case BROTLI_REPEAT_PREVIOUS_CODE_LENGTH: BrotliWriteBits(2, huffman_tree_extra_bits[i], storage_ix, storage); break; case BROTLI_REPEAT_ZERO_CODE_LENGTH: BrotliWriteBits(3, huffman_tree_extra_bits[i], storage_ix, storage); break; } } } static void StoreSimpleHuffmanTree(const uint8_t* depths, size_t symbols[4], size_t num_symbols, size_t max_bits, size_t* storage_ix, uint8_t* storage) { /* value of 1 indicates a simple Huffman code */ BrotliWriteBits(2, 1, storage_ix, storage); BrotliWriteBits(2, num_symbols - 1, storage_ix, storage); /* NSYM - 1 */ { /* Sort */ size_t i; for (i = 0; i < num_symbols; i++) { size_t j; for (j = i + 1; j < num_symbols; j++) { if (depths[symbols[j]] < depths[symbols[i]]) { BROTLI_SWAP(size_t, symbols, j, i); } } } } if (num_symbols == 2) { BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); } else if (num_symbols == 3) { BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); } else { BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); BrotliWriteBits(max_bits, symbols[3], storage_ix, storage); /* tree-select */ BrotliWriteBits(1, depths[symbols[0]] == 1 ? 1 : 0, storage_ix, storage); } } /* num = alphabet size depths = symbol depths */ void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num, HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) { /* Write the Huffman tree into the brotli-representation. The command alphabet is the largest, so this allocation will fit all alphabets. */ /* TODO(eustas): fix me */ uint8_t huffman_tree[BROTLI_NUM_COMMAND_SYMBOLS]; uint8_t huffman_tree_extra_bits[BROTLI_NUM_COMMAND_SYMBOLS]; size_t huffman_tree_size = 0; uint8_t code_length_bitdepth[BROTLI_CODE_LENGTH_CODES] = { 0 }; uint16_t code_length_bitdepth_symbols[BROTLI_CODE_LENGTH_CODES]; uint32_t huffman_tree_histogram[BROTLI_CODE_LENGTH_CODES] = { 0 }; size_t i; int num_codes = 0; size_t code = 0; BROTLI_DCHECK(num <= BROTLI_NUM_COMMAND_SYMBOLS); BrotliWriteHuffmanTree(depths, num, &huffman_tree_size, huffman_tree, huffman_tree_extra_bits); /* Calculate the statistics of the Huffman tree in brotli-representation. */ for (i = 0; i < huffman_tree_size; ++i) { ++huffman_tree_histogram[huffman_tree[i]]; } for (i = 0; i < BROTLI_CODE_LENGTH_CODES; ++i) { if (huffman_tree_histogram[i]) { if (num_codes == 0) { code = i; num_codes = 1; } else if (num_codes == 1) { num_codes = 2; break; } } } /* Calculate another Huffman tree to use for compressing both the earlier Huffman tree with. */ BrotliCreateHuffmanTree(huffman_tree_histogram, BROTLI_CODE_LENGTH_CODES, 5, tree, code_length_bitdepth); BrotliConvertBitDepthsToSymbols(code_length_bitdepth, BROTLI_CODE_LENGTH_CODES, code_length_bitdepth_symbols); /* Now, we have all the data, let's start storing it */ BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth, storage_ix, storage); if (num_codes == 1) { code_length_bitdepth[code] = 0; } /* Store the real Huffman tree now. */ BrotliStoreHuffmanTreeToBitMask(huffman_tree_size, huffman_tree, huffman_tree_extra_bits, code_length_bitdepth, code_length_bitdepth_symbols, storage_ix, storage); } /* Builds a Huffman tree from histogram[0:length] into depth[0:length] and bits[0:length] and stores the encoded tree to the bit stream. */ static void BuildAndStoreHuffmanTree(const uint32_t* histogram, const size_t histogram_length, const size_t alphabet_size, HuffmanTree* tree, uint8_t* depth, uint16_t* bits, size_t* storage_ix, uint8_t* storage) { size_t count = 0; size_t s4[4] = { 0 }; size_t i; size_t max_bits = 0; for (i = 0; i < histogram_length; i++) { if (histogram[i]) { if (count < 4) { s4[count] = i; } else if (count > 4) { break; } count++; } } { size_t max_bits_counter = alphabet_size - 1; while (max_bits_counter) { max_bits_counter >>= 1; ++max_bits; } } if (count <= 1) { BrotliWriteBits(4, 1, storage_ix, storage); BrotliWriteBits(max_bits, s4[0], storage_ix, storage); depth[s4[0]] = 0; bits[s4[0]] = 0; return; } memset(depth, 0, histogram_length * sizeof(depth[0])); BrotliCreateHuffmanTree(histogram, histogram_length, 15, tree, depth); BrotliConvertBitDepthsToSymbols(depth, histogram_length, bits); if (count <= 4) { StoreSimpleHuffmanTree(depth, s4, count, max_bits, storage_ix, storage); } else { BrotliStoreHuffmanTree(depth, histogram_length, tree, storage_ix, storage); } } static BROTLI_INLINE BROTLI_BOOL SortHuffmanTree( const HuffmanTree* v0, const HuffmanTree* v1) { return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_); } void BrotliBuildAndStoreHuffmanTreeFast(HuffmanTree* tree, const uint32_t* histogram, const size_t histogram_total, const size_t max_bits, uint8_t* depth, uint16_t* bits, size_t* storage_ix, uint8_t* storage) { size_t count = 0; size_t symbols[4] = { 0 }; size_t length = 0; size_t total = histogram_total; while (total != 0) { if (histogram[length]) { if (count < 4) { symbols[count] = length; } ++count; total -= histogram[length]; } ++length; } if (count <= 1) { BrotliWriteBits(4, 1, storage_ix, storage); BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); depth[symbols[0]] = 0; bits[symbols[0]] = 0; return; } memset(depth, 0, length * sizeof(depth[0])); { uint32_t count_limit; for (count_limit = 1; ; count_limit *= 2) { HuffmanTree* node = tree; size_t l; for (l = length; l != 0;) { --l; if (histogram[l]) { if (BROTLI_PREDICT_TRUE(histogram[l] >= count_limit)) { InitHuffmanTree(node, histogram[l], -1, (int16_t)l); } else { InitHuffmanTree(node, count_limit, -1, (int16_t)l); } ++node; } } { const int n = (int)(node - tree); HuffmanTree sentinel; int i = 0; /* Points to the next leaf node. */ int j = n + 1; /* Points to the next non-leaf node. */ int k; SortHuffmanTreeItems(tree, (size_t)n, SortHuffmanTree); /* The nodes are: [0, n): the sorted leaf nodes that we start with. [n]: we add a sentinel here. [n + 1, 2n): new parent nodes are added here, starting from (n+1). These are naturally in ascending order. [2n]: we add a sentinel at the end as well. There will be (2n+1) elements at the end. */ InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1); *node++ = sentinel; *node++ = sentinel; for (k = n - 1; k > 0; --k) { int left, right; if (tree[i].total_count_ <= tree[j].total_count_) { left = i; ++i; } else { left = j; ++j; } if (tree[i].total_count_ <= tree[j].total_count_) { right = i; ++i; } else { right = j; ++j; } /* The sentinel node becomes the parent node. */ node[-1].total_count_ = tree[left].total_count_ + tree[right].total_count_; node[-1].index_left_ = (int16_t)left; node[-1].index_right_or_value_ = (int16_t)right; /* Add back the last sentinel node. */ *node++ = sentinel; } if (BrotliSetDepth(2 * n - 1, tree, depth, 14)) { /* We need to pack the Huffman tree in 14 bits. If this was not successful, add fake entities to the lowest values and retry. */ break; } } } } BrotliConvertBitDepthsToSymbols(depth, length, bits); if (count <= 4) { size_t i; /* value of 1 indicates a simple Huffman code */ BrotliWriteBits(2, 1, storage_ix, storage); BrotliWriteBits(2, count - 1, storage_ix, storage); /* NSYM - 1 */ /* Sort */ for (i = 0; i < count; i++) { size_t j; for (j = i + 1; j < count; j++) { if (depth[symbols[j]] < depth[symbols[i]]) { BROTLI_SWAP(size_t, symbols, j, i); } } } if (count == 2) { BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); } else if (count == 3) { BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); } else { BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); BrotliWriteBits(max_bits, symbols[3], storage_ix, storage); /* tree-select */ BrotliWriteBits(1, depth[symbols[0]] == 1 ? 1 : 0, storage_ix, storage); } } else { uint8_t previous_value = 8; size_t i; /* Complex Huffman Tree */ StoreStaticCodeLengthCode(storage_ix, storage); /* Actual RLE coding. */ for (i = 0; i < length;) { const uint8_t value = depth[i]; size_t reps = 1; size_t k; for (k = i + 1; k < length && depth[k] == value; ++k) { ++reps; } i += reps; if (value == 0) { BrotliWriteBits(kZeroRepsDepth[reps], kZeroRepsBits[reps], storage_ix, storage); } else { if (previous_value != value) { BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value], storage_ix, storage); --reps; } if (reps < 3) { while (reps != 0) { reps--; BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value], storage_ix, storage); } } else { reps -= 3; BrotliWriteBits(kNonZeroRepsDepth[reps], kNonZeroRepsBits[reps], storage_ix, storage); } previous_value = value; } } } } static size_t IndexOf(const uint8_t* v, size_t v_size, uint8_t value) { size_t i = 0; for (; i < v_size; ++i) { if (v[i] == value) return i; } return i; } static void MoveToFront(uint8_t* v, size_t index) { uint8_t value = v[index]; size_t i; for (i = index; i != 0; --i) { v[i] = v[i - 1]; } v[0] = value; } static void MoveToFrontTransform(const uint32_t* BROTLI_RESTRICT v_in, const size_t v_size, uint32_t* v_out) { size_t i; uint8_t mtf[256]; uint32_t max_value; if (v_size == 0) { return; } max_value = v_in[0]; for (i = 1; i < v_size; ++i) { if (v_in[i] > max_value) max_value = v_in[i]; } BROTLI_DCHECK(max_value < 256u); for (i = 0; i <= max_value; ++i) { mtf[i] = (uint8_t)i; } { size_t mtf_size = max_value + 1; for (i = 0; i < v_size; ++i) { size_t index = IndexOf(mtf, mtf_size, (uint8_t)v_in[i]); BROTLI_DCHECK(index < mtf_size); v_out[i] = (uint32_t)index; MoveToFront(mtf, index); } } } /* Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of the run length plus extra bits (lower 9 bits is the prefix code and the rest are the extra bits). Non-zero values in v[] are shifted by *max_length_prefix. Will not create prefix codes bigger than the initial value of *max_run_length_prefix. The prefix code of run length L is simply Log2Floor(L) and the number of extra bits is the same as the prefix code. */ static void RunLengthCodeZeros(const size_t in_size, uint32_t* BROTLI_RESTRICT v, size_t* BROTLI_RESTRICT out_size, uint32_t* BROTLI_RESTRICT max_run_length_prefix) { uint32_t max_reps = 0; size_t i; uint32_t max_prefix; for (i = 0; i < in_size;) { uint32_t reps = 0; for (; i < in_size && v[i] != 0; ++i) ; for (; i < in_size && v[i] == 0; ++i) { ++reps; } max_reps = BROTLI_MAX(uint32_t, reps, max_reps); } max_prefix = max_reps > 0 ? Log2FloorNonZero(max_reps) : 0; max_prefix = BROTLI_MIN(uint32_t, max_prefix, *max_run_length_prefix); *max_run_length_prefix = max_prefix; *out_size = 0; for (i = 0; i < in_size;) { BROTLI_DCHECK(*out_size <= i); if (v[i] != 0) { v[*out_size] = v[i] + *max_run_length_prefix; ++i; ++(*out_size); } else { uint32_t reps = 1; size_t k; for (k = i + 1; k < in_size && v[k] == 0; ++k) { ++reps; } i += reps; while (reps != 0) { if (reps < (2u << max_prefix)) { uint32_t run_length_prefix = Log2FloorNonZero(reps); const uint32_t extra_bits = reps - (1u << run_length_prefix); v[*out_size] = run_length_prefix + (extra_bits << 9); ++(*out_size); break; } else { const uint32_t extra_bits = (1u << max_prefix) - 1u; v[*out_size] = max_prefix + (extra_bits << 9); reps -= (2u << max_prefix) - 1u; ++(*out_size); } } } } } #define SYMBOL_BITS 9 typedef struct EncodeContextMapArena { uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS]; uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS]; uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS]; } EncodeContextMapArena; static void EncodeContextMap(MemoryManager* m, EncodeContextMapArena* arena, const uint32_t* context_map, size_t context_map_size, size_t num_clusters, HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) { size_t i; uint32_t* rle_symbols; uint32_t max_run_length_prefix = 6; size_t num_rle_symbols = 0; uint32_t* BROTLI_RESTRICT const histogram = arena->histogram; static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u; uint8_t* BROTLI_RESTRICT const depths = arena->depths; uint16_t* BROTLI_RESTRICT const bits = arena->bits; StoreVarLenUint8(num_clusters - 1, storage_ix, storage); if (num_clusters == 1) { return; } rle_symbols = BROTLI_ALLOC(m, uint32_t, context_map_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(rle_symbols)) return; MoveToFrontTransform(context_map, context_map_size, rle_symbols); RunLengthCodeZeros(context_map_size, rle_symbols, &num_rle_symbols, &max_run_length_prefix); memset(histogram, 0, sizeof(arena->histogram)); for (i = 0; i < num_rle_symbols; ++i) { ++histogram[rle_symbols[i] & kSymbolMask]; } { BROTLI_BOOL use_rle = TO_BROTLI_BOOL(max_run_length_prefix > 0); BrotliWriteBits(1, (uint64_t)use_rle, storage_ix, storage); if (use_rle) { BrotliWriteBits(4, max_run_length_prefix - 1, storage_ix, storage); } } BuildAndStoreHuffmanTree(histogram, num_clusters + max_run_length_prefix, num_clusters + max_run_length_prefix, tree, depths, bits, storage_ix, storage); for (i = 0; i < num_rle_symbols; ++i) { const uint32_t rle_symbol = rle_symbols[i] & kSymbolMask; const uint32_t extra_bits_val = rle_symbols[i] >> SYMBOL_BITS; BrotliWriteBits(depths[rle_symbol], bits[rle_symbol], storage_ix, storage); if (rle_symbol > 0 && rle_symbol <= max_run_length_prefix) { BrotliWriteBits(rle_symbol, extra_bits_val, storage_ix, storage); } } BrotliWriteBits(1, 1, storage_ix, storage); /* use move-to-front */ BROTLI_FREE(m, rle_symbols); } /* Stores the block switch command with index block_ix to the bit stream. */ static BROTLI_INLINE void StoreBlockSwitch(BlockSplitCode* code, const uint32_t block_len, const uint8_t block_type, BROTLI_BOOL is_first_block, size_t* storage_ix, uint8_t* storage) { size_t typecode = NextBlockTypeCode(&code->type_code_calculator, block_type); size_t lencode; uint32_t len_nextra; uint32_t len_extra; if (!is_first_block) { BrotliWriteBits(code->type_depths[typecode], code->type_bits[typecode], storage_ix, storage); } GetBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra); BrotliWriteBits(code->length_depths[lencode], code->length_bits[lencode], storage_ix, storage); BrotliWriteBits(len_nextra, len_extra, storage_ix, storage); } /* Builds a BlockSplitCode data structure from the block split given by the vector of block types and block lengths and stores it to the bit stream. */ static void BuildAndStoreBlockSplitCode(const uint8_t* types, const uint32_t* lengths, const size_t num_blocks, const size_t num_types, HuffmanTree* tree, BlockSplitCode* code, size_t* storage_ix, uint8_t* storage) { uint32_t type_histo[BROTLI_MAX_BLOCK_TYPE_SYMBOLS]; uint32_t length_histo[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; size_t i; BlockTypeCodeCalculator type_code_calculator; memset(type_histo, 0, (num_types + 2) * sizeof(type_histo[0])); memset(length_histo, 0, sizeof(length_histo)); InitBlockTypeCodeCalculator(&type_code_calculator); for (i = 0; i < num_blocks; ++i) { size_t type_code = NextBlockTypeCode(&type_code_calculator, types[i]); if (i != 0) ++type_histo[type_code]; ++length_histo[BlockLengthPrefixCode(lengths[i])]; } StoreVarLenUint8(num_types - 1, storage_ix, storage); if (num_types > 1) { /* TODO(eustas): else? could StoreBlockSwitch occur? */ BuildAndStoreHuffmanTree(&type_histo[0], num_types + 2, num_types + 2, tree, &code->type_depths[0], &code->type_bits[0], storage_ix, storage); BuildAndStoreHuffmanTree(&length_histo[0], BROTLI_NUM_BLOCK_LEN_SYMBOLS, BROTLI_NUM_BLOCK_LEN_SYMBOLS, tree, &code->length_depths[0], &code->length_bits[0], storage_ix, storage); StoreBlockSwitch(code, lengths[0], types[0], 1, storage_ix, storage); } } /* Stores a context map where the histogram type is always the block type. */ static void StoreTrivialContextMap(EncodeContextMapArena* arena, size_t num_types, size_t context_bits, HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) { StoreVarLenUint8(num_types - 1, storage_ix, storage); if (num_types > 1) { size_t repeat_code = context_bits - 1u; size_t repeat_bits = (1u << repeat_code) - 1u; size_t alphabet_size = num_types + repeat_code; uint32_t* BROTLI_RESTRICT const histogram = arena->histogram; uint8_t* BROTLI_RESTRICT const depths = arena->depths; uint16_t* BROTLI_RESTRICT const bits = arena->bits; size_t i; memset(histogram, 0, alphabet_size * sizeof(histogram[0])); /* Write RLEMAX. */ BrotliWriteBits(1, 1, storage_ix, storage); BrotliWriteBits(4, repeat_code - 1, storage_ix, storage); histogram[repeat_code] = (uint32_t)num_types; histogram[0] = 1; for (i = context_bits; i < alphabet_size; ++i) { histogram[i] = 1; } BuildAndStoreHuffmanTree(histogram, alphabet_size, alphabet_size, tree, depths, bits, storage_ix, storage); for (i = 0; i < num_types; ++i) { size_t code = (i == 0 ? 0 : i + context_bits - 1); BrotliWriteBits(depths[code], bits[code], storage_ix, storage); BrotliWriteBits( depths[repeat_code], bits[repeat_code], storage_ix, storage); BrotliWriteBits(repeat_code, repeat_bits, storage_ix, storage); } /* Write IMTF (inverse-move-to-front) bit. */ BrotliWriteBits(1, 1, storage_ix, storage); } } /* Manages the encoding of one block category (literal, command or distance). */ typedef struct BlockEncoder { size_t histogram_length_; size_t num_block_types_; const uint8_t* block_types_; /* Not owned. */ const uint32_t* block_lengths_; /* Not owned. */ size_t num_blocks_; BlockSplitCode block_split_code_; size_t block_ix_; size_t block_len_; size_t entropy_ix_; uint8_t* depths_; uint16_t* bits_; } BlockEncoder; static void InitBlockEncoder(BlockEncoder* self, size_t histogram_length, size_t num_block_types, const uint8_t* block_types, const uint32_t* block_lengths, const size_t num_blocks) { self->histogram_length_ = histogram_length; self->num_block_types_ = num_block_types; self->block_types_ = block_types; self->block_lengths_ = block_lengths; self->num_blocks_ = num_blocks; InitBlockTypeCodeCalculator(&self->block_split_code_.type_code_calculator); self->block_ix_ = 0; self->block_len_ = num_blocks == 0 ? 0 : block_lengths[0]; self->entropy_ix_ = 0; self->depths_ = 0; self->bits_ = 0; } static void CleanupBlockEncoder(MemoryManager* m, BlockEncoder* self) { BROTLI_FREE(m, self->depths_); BROTLI_FREE(m, self->bits_); } /* Creates entropy codes of block lengths and block types and stores them to the bit stream. */ static void BuildAndStoreBlockSwitchEntropyCodes(BlockEncoder* self, HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) { BuildAndStoreBlockSplitCode(self->block_types_, self->block_lengths_, self->num_blocks_, self->num_block_types_, tree, &self->block_split_code_, storage_ix, storage); } /* Stores the next symbol with the entropy code of the current block type. Updates the block type and block length at block boundaries. */ static void StoreSymbol(BlockEncoder* self, size_t symbol, size_t* storage_ix, uint8_t* storage) { if (self->block_len_ == 0) { size_t block_ix = ++self->block_ix_; uint32_t block_len = self->block_lengths_[block_ix]; uint8_t block_type = self->block_types_[block_ix]; self->block_len_ = block_len; self->entropy_ix_ = block_type * self->histogram_length_; StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0, storage_ix, storage); } --self->block_len_; { size_t ix = self->entropy_ix_ + symbol; BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage); } } /* Stores the next symbol with the entropy code of the current block type and context value. Updates the block type and block length at block boundaries. */ static void StoreSymbolWithContext(BlockEncoder* self, size_t symbol, size_t context, const uint32_t* context_map, size_t* storage_ix, uint8_t* storage, const size_t context_bits) { if (self->block_len_ == 0) { size_t block_ix = ++self->block_ix_; uint32_t block_len = self->block_lengths_[block_ix]; uint8_t block_type = self->block_types_[block_ix]; self->block_len_ = block_len; self->entropy_ix_ = (size_t)block_type << context_bits; StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0, storage_ix, storage); } --self->block_len_; { size_t histo_ix = context_map[self->entropy_ix_ + context]; size_t ix = histo_ix * self->histogram_length_ + symbol; BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage); } } #define FN(X) X ## Literal /* NOLINTNEXTLINE(build/include) */ #include "block_encoder_inc.h" #undef FN #define FN(X) X ## Command /* NOLINTNEXTLINE(build/include) */ #include "block_encoder_inc.h" #undef FN #define FN(X) X ## Distance /* NOLINTNEXTLINE(build/include) */ #include "block_encoder_inc.h" #undef FN static void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) { *storage_ix = (*storage_ix + 7u) & ~7u; storage[*storage_ix >> 3] = 0; } typedef struct StoreMetablockArena { BlockEncoder literal_enc; BlockEncoder command_enc; BlockEncoder distance_enc; EncodeContextMapArena context_map_arena; } StoreMetablockArena; void BrotliStoreMetaBlock(MemoryManager* m, const uint8_t* input, size_t start_pos, size_t length, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last, const BrotliEncoderParams* params, ContextType literal_context_mode, const Command* commands, size_t n_commands, const MetaBlockSplit* mb, size_t* storage_ix, uint8_t* storage) { size_t pos = start_pos; size_t i; uint32_t num_distance_symbols = params->dist.alphabet_size_max; uint32_t num_effective_distance_symbols = params->dist.alphabet_size_limit; HuffmanTree* tree; ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode); StoreMetablockArena* arena = NULL; BlockEncoder* literal_enc = NULL; BlockEncoder* command_enc = NULL; BlockEncoder* distance_enc = NULL; const BrotliDistanceParams* dist = ¶ms->dist; BROTLI_DCHECK( num_effective_distance_symbols <= BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS); StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage); tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE); arena = BROTLI_ALLOC(m, StoreMetablockArena, 1); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree) || BROTLI_IS_NULL(arena)) return; literal_enc = &arena->literal_enc; command_enc = &arena->command_enc; distance_enc = &arena->distance_enc; InitBlockEncoder(literal_enc, BROTLI_NUM_LITERAL_SYMBOLS, mb->literal_split.num_types, mb->literal_split.types, mb->literal_split.lengths, mb->literal_split.num_blocks); InitBlockEncoder(command_enc, BROTLI_NUM_COMMAND_SYMBOLS, mb->command_split.num_types, mb->command_split.types, mb->command_split.lengths, mb->command_split.num_blocks); InitBlockEncoder(distance_enc, num_effective_distance_symbols, mb->distance_split.num_types, mb->distance_split.types, mb->distance_split.lengths, mb->distance_split.num_blocks); BuildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, storage_ix, storage); BuildAndStoreBlockSwitchEntropyCodes(command_enc, tree, storage_ix, storage); BuildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, storage_ix, storage); BrotliWriteBits(2, dist->distance_postfix_bits, storage_ix, storage); BrotliWriteBits( 4, dist->num_direct_distance_codes >> dist->distance_postfix_bits, storage_ix, storage); for (i = 0; i < mb->literal_split.num_types; ++i) { BrotliWriteBits(2, literal_context_mode, storage_ix, storage); } if (mb->literal_context_map_size == 0) { StoreTrivialContextMap( &arena->context_map_arena, mb->literal_histograms_size, BROTLI_LITERAL_CONTEXT_BITS, tree, storage_ix, storage); } else { EncodeContextMap(m, &arena->context_map_arena, mb->literal_context_map, mb->literal_context_map_size, mb->literal_histograms_size, tree, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; } if (mb->distance_context_map_size == 0) { StoreTrivialContextMap( &arena->context_map_arena, mb->distance_histograms_size, BROTLI_DISTANCE_CONTEXT_BITS, tree, storage_ix, storage); } else { EncodeContextMap(m, &arena->context_map_arena, mb->distance_context_map, mb->distance_context_map_size, mb->distance_histograms_size, tree, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; } BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms, mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; BuildAndStoreEntropyCodesCommand(m, command_enc, mb->command_histograms, mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; BuildAndStoreEntropyCodesDistance(m, distance_enc, mb->distance_histograms, mb->distance_histograms_size, num_distance_symbols, tree, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; BROTLI_FREE(m, tree); for (i = 0; i < n_commands; ++i) { const Command cmd = commands[i]; size_t cmd_code = cmd.cmd_prefix_; StoreSymbol(command_enc, cmd_code, storage_ix, storage); StoreCommandExtra(&cmd, storage_ix, storage); if (mb->literal_context_map_size == 0) { size_t j; for (j = cmd.insert_len_; j != 0; --j) { StoreSymbol(literal_enc, input[pos & mask], storage_ix, storage); ++pos; } } else { size_t j; for (j = cmd.insert_len_; j != 0; --j) { size_t context = BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut); uint8_t literal = input[pos & mask]; StoreSymbolWithContext(literal_enc, literal, context, mb->literal_context_map, storage_ix, storage, BROTLI_LITERAL_CONTEXT_BITS); prev_byte2 = prev_byte; prev_byte = literal; ++pos; } } pos += CommandCopyLen(&cmd); if (CommandCopyLen(&cmd)) { prev_byte2 = input[(pos - 2) & mask]; prev_byte = input[(pos - 1) & mask]; if (cmd.cmd_prefix_ >= 128) { size_t dist_code = cmd.dist_prefix_ & 0x3FF; uint32_t distnumextra = cmd.dist_prefix_ >> 10; uint64_t distextra = cmd.dist_extra_; if (mb->distance_context_map_size == 0) { StoreSymbol(distance_enc, dist_code, storage_ix, storage); } else { size_t context = CommandDistanceContext(&cmd); StoreSymbolWithContext(distance_enc, dist_code, context, mb->distance_context_map, storage_ix, storage, BROTLI_DISTANCE_CONTEXT_BITS); } BrotliWriteBits(distnumextra, distextra, storage_ix, storage); } } } CleanupBlockEncoder(m, distance_enc); CleanupBlockEncoder(m, command_enc); CleanupBlockEncoder(m, literal_enc); BROTLI_FREE(m, arena); if (is_last) { JumpToByteBoundary(storage_ix, storage); } } static void BuildHistograms(const uint8_t* input, size_t start_pos, size_t mask, const Command* commands, size_t n_commands, HistogramLiteral* lit_histo, HistogramCommand* cmd_histo, HistogramDistance* dist_histo) { size_t pos = start_pos; size_t i; for (i = 0; i < n_commands; ++i) { const Command cmd = commands[i]; size_t j; HistogramAddCommand(cmd_histo, cmd.cmd_prefix_); for (j = cmd.insert_len_; j != 0; --j) { HistogramAddLiteral(lit_histo, input[pos & mask]); ++pos; } pos += CommandCopyLen(&cmd); if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) { HistogramAddDistance(dist_histo, cmd.dist_prefix_ & 0x3FF); } } } static void StoreDataWithHuffmanCodes(const uint8_t* input, size_t start_pos, size_t mask, const Command* commands, size_t n_commands, const uint8_t* lit_depth, const uint16_t* lit_bits, const uint8_t* cmd_depth, const uint16_t* cmd_bits, const uint8_t* dist_depth, const uint16_t* dist_bits, size_t* storage_ix, uint8_t* storage) { size_t pos = start_pos; size_t i; for (i = 0; i < n_commands; ++i) { const Command cmd = commands[i]; const size_t cmd_code = cmd.cmd_prefix_; size_t j; BrotliWriteBits( cmd_depth[cmd_code], cmd_bits[cmd_code], storage_ix, storage); StoreCommandExtra(&cmd, storage_ix, storage); for (j = cmd.insert_len_; j != 0; --j) { const uint8_t literal = input[pos & mask]; BrotliWriteBits( lit_depth[literal], lit_bits[literal], storage_ix, storage); ++pos; } pos += CommandCopyLen(&cmd); if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) { const size_t dist_code = cmd.dist_prefix_ & 0x3FF; const uint32_t distnumextra = cmd.dist_prefix_ >> 10; const uint32_t distextra = cmd.dist_extra_; BrotliWriteBits(dist_depth[dist_code], dist_bits[dist_code], storage_ix, storage); BrotliWriteBits(distnumextra, distextra, storage_ix, storage); } } } /* TODO(eustas): pull alloc/dealloc to caller? */ typedef struct MetablockArena { HistogramLiteral lit_histo; HistogramCommand cmd_histo; HistogramDistance dist_histo; /* TODO(eustas): merge bits and depth? */ uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS]; uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS]; uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS]; uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS]; uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE]; uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE]; HuffmanTree tree[MAX_HUFFMAN_TREE_SIZE]; } MetablockArena; void BrotliStoreMetaBlockTrivial(MemoryManager* m, const uint8_t* input, size_t start_pos, size_t length, size_t mask, BROTLI_BOOL is_last, const BrotliEncoderParams* params, const Command* commands, size_t n_commands, size_t* storage_ix, uint8_t* storage) { MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1); uint32_t num_distance_symbols = params->dist.alphabet_size_max; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage); HistogramClearLiteral(&arena->lit_histo); HistogramClearCommand(&arena->cmd_histo); HistogramClearDistance(&arena->dist_histo); BuildHistograms(input, start_pos, mask, commands, n_commands, &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo); BrotliWriteBits(13, 0, storage_ix, storage); BuildAndStoreHuffmanTree(arena->lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS, BROTLI_NUM_LITERAL_SYMBOLS, arena->tree, arena->lit_depth, arena->lit_bits, storage_ix, storage); BuildAndStoreHuffmanTree(arena->cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS, BROTLI_NUM_COMMAND_SYMBOLS, arena->tree, arena->cmd_depth, arena->cmd_bits, storage_ix, storage); BuildAndStoreHuffmanTree(arena->dist_histo.data_, MAX_SIMPLE_DISTANCE_ALPHABET_SIZE, num_distance_symbols, arena->tree, arena->dist_depth, arena->dist_bits, storage_ix, storage); StoreDataWithHuffmanCodes(input, start_pos, mask, commands, n_commands, arena->lit_depth, arena->lit_bits, arena->cmd_depth, arena->cmd_bits, arena->dist_depth, arena->dist_bits, storage_ix, storage); BROTLI_FREE(m, arena); if (is_last) { JumpToByteBoundary(storage_ix, storage); } } void BrotliStoreMetaBlockFast(MemoryManager* m, const uint8_t* input, size_t start_pos, size_t length, size_t mask, BROTLI_BOOL is_last, const BrotliEncoderParams* params, const Command* commands, size_t n_commands, size_t* storage_ix, uint8_t* storage) { MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1); uint32_t num_distance_symbols = params->dist.alphabet_size_max; uint32_t distance_alphabet_bits = Log2FloorNonZero(num_distance_symbols - 1) + 1; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage); BrotliWriteBits(13, 0, storage_ix, storage); if (n_commands <= 128) { uint32_t histogram[BROTLI_NUM_LITERAL_SYMBOLS] = { 0 }; size_t pos = start_pos; size_t num_literals = 0; size_t i; for (i = 0; i < n_commands; ++i) { const Command cmd = commands[i]; size_t j; for (j = cmd.insert_len_; j != 0; --j) { ++histogram[input[pos & mask]]; ++pos; } num_literals += cmd.insert_len_; pos += CommandCopyLen(&cmd); } BrotliBuildAndStoreHuffmanTreeFast(arena->tree, histogram, num_literals, /* max_bits = */ 8, arena->lit_depth, arena->lit_bits, storage_ix, storage); StoreStaticCommandHuffmanTree(storage_ix, storage); StoreStaticDistanceHuffmanTree(storage_ix, storage); StoreDataWithHuffmanCodes(input, start_pos, mask, commands, n_commands, arena->lit_depth, arena->lit_bits, kStaticCommandCodeDepth, kStaticCommandCodeBits, kStaticDistanceCodeDepth, kStaticDistanceCodeBits, storage_ix, storage); } else { HistogramClearLiteral(&arena->lit_histo); HistogramClearCommand(&arena->cmd_histo); HistogramClearDistance(&arena->dist_histo); BuildHistograms(input, start_pos, mask, commands, n_commands, &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo); BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->lit_histo.data_, arena->lit_histo.total_count_, /* max_bits = */ 8, arena->lit_depth, arena->lit_bits, storage_ix, storage); BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->cmd_histo.data_, arena->cmd_histo.total_count_, /* max_bits = */ 10, arena->cmd_depth, arena->cmd_bits, storage_ix, storage); BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->dist_histo.data_, arena->dist_histo.total_count_, /* max_bits = */ distance_alphabet_bits, arena->dist_depth, arena->dist_bits, storage_ix, storage); StoreDataWithHuffmanCodes(input, start_pos, mask, commands, n_commands, arena->lit_depth, arena->lit_bits, arena->cmd_depth, arena->cmd_bits, arena->dist_depth, arena->dist_bits, storage_ix, storage); } BROTLI_FREE(m, arena); if (is_last) { JumpToByteBoundary(storage_ix, storage); } } /* This is for storing uncompressed blocks (simple raw storage of bytes-as-bytes). */ void BrotliStoreUncompressedMetaBlock(BROTLI_BOOL is_final_block, const uint8_t* BROTLI_RESTRICT input, size_t position, size_t mask, size_t len, size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage) { size_t masked_pos = position & mask; BrotliStoreUncompressedMetaBlockHeader(len, storage_ix, storage); JumpToByteBoundary(storage_ix, storage); if (masked_pos + len > mask + 1) { size_t len1 = mask + 1 - masked_pos; memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len1); *storage_ix += len1 << 3; len -= len1; masked_pos = 0; } memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len); *storage_ix += len << 3; /* We need to clear the next 4 bytes to continue to be compatible with BrotliWriteBits. */ BrotliWriteBitsPrepareStorage(*storage_ix, storage); /* Since the uncompressed block itself may not be the final block, add an empty one after this. */ if (is_final_block) { BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ JumpToByteBoundary(storage_ix, storage); } } #if defined(BROTLI_TEST) void GetBlockLengthPrefixCodeForTest(uint32_t len, size_t* code, uint32_t* n_extra, uint32_t* extra) { GetBlockLengthPrefixCode(len, code, n_extra, extra); } #endif #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/brotli_bit_stream.h000066400000000000000000000066251501401750600217160ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Functions to convert brotli-related data structures into the brotli bit stream. The functions here operate under assumption that there is enough space in the storage, i.e., there are no out-of-range checks anywhere. These functions do bit addressing into a byte array. The byte array is called "storage" and the index to the bit is called storage_ix in function arguments. */ #ifndef BROTLI_ENC_BROTLI_BIT_STREAM_H_ #define BROTLI_ENC_BROTLI_BIT_STREAM_H_ #include #include "../common/context.h" #include "../common/platform.h" #include "command.h" #include "entropy_encode.h" #include "memory.h" #include "metablock.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* All Store functions here will use a storage_ix, which is always the bit position for the current storage. */ BROTLI_INTERNAL void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num, HuffmanTree* tree, size_t* storage_ix, uint8_t* storage); BROTLI_INTERNAL void BrotliBuildAndStoreHuffmanTreeFast( HuffmanTree* tree, const uint32_t* histogram, const size_t histogram_total, const size_t max_bits, uint8_t* depth, uint16_t* bits, size_t* storage_ix, uint8_t* storage); /* REQUIRES: length > 0 */ /* REQUIRES: length <= (1 << 24) */ BROTLI_INTERNAL void BrotliStoreMetaBlock(MemoryManager* m, const uint8_t* input, size_t start_pos, size_t length, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last, const BrotliEncoderParams* params, ContextType literal_context_mode, const Command* commands, size_t n_commands, const MetaBlockSplit* mb, size_t* storage_ix, uint8_t* storage); /* Stores the meta-block without doing any block splitting, just collects one histogram per block category and uses that for entropy coding. REQUIRES: length > 0 REQUIRES: length <= (1 << 24) */ BROTLI_INTERNAL void BrotliStoreMetaBlockTrivial(MemoryManager* m, const uint8_t* input, size_t start_pos, size_t length, size_t mask, BROTLI_BOOL is_last, const BrotliEncoderParams* params, const Command* commands, size_t n_commands, size_t* storage_ix, uint8_t* storage); /* Same as above, but uses static prefix codes for histograms with a only a few symbols, and uses static code length prefix codes for all other histograms. REQUIRES: length > 0 REQUIRES: length <= (1 << 24) */ BROTLI_INTERNAL void BrotliStoreMetaBlockFast(MemoryManager* m, const uint8_t* input, size_t start_pos, size_t length, size_t mask, BROTLI_BOOL is_last, const BrotliEncoderParams* params, const Command* commands, size_t n_commands, size_t* storage_ix, uint8_t* storage); /* This is for storing uncompressed blocks (simple raw storage of bytes-as-bytes). REQUIRES: length > 0 REQUIRES: length <= (1 << 24) */ BROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock( BROTLI_BOOL is_final_block, const uint8_t* BROTLI_RESTRICT input, size_t position, size_t mask, size_t len, size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage); #if defined(BROTLI_TEST) void GetBlockLengthPrefixCodeForTest(uint32_t, size_t*, uint32_t*, uint32_t*); #endif #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_BROTLI_BIT_STREAM_H_ */ dvisvgm-3.5/libs/brotli/enc/cluster.c000066400000000000000000000027151501401750600176620ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Functions for clustering similar histograms together. */ #include "cluster.h" #include #include "../common/platform.h" #include "bit_cost.h" /* BrotliPopulationCost */ #include "fast_log.h" #include "histogram.h" #include "memory.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static BROTLI_INLINE BROTLI_BOOL HistogramPairIsLess( const HistogramPair* p1, const HistogramPair* p2) { if (p1->cost_diff != p2->cost_diff) { return TO_BROTLI_BOOL(p1->cost_diff > p2->cost_diff); } return TO_BROTLI_BOOL((p1->idx2 - p1->idx1) > (p2->idx2 - p2->idx1)); } /* Returns entropy reduction of the context map when we combine two clusters. */ static BROTLI_INLINE double ClusterCostDiff(size_t size_a, size_t size_b) { size_t size_c = size_a + size_b; return (double)size_a * FastLog2(size_a) + (double)size_b * FastLog2(size_b) - (double)size_c * FastLog2(size_c); } #define CODE(X) X #define FN(X) X ## Literal #include "cluster_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Command #include "cluster_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Distance #include "cluster_inc.h" /* NOLINT(build/include) */ #undef FN #undef CODE #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/cluster.h000066400000000000000000000020001501401750600176520ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Functions for clustering similar histograms together. */ #ifndef BROTLI_ENC_CLUSTER_H_ #define BROTLI_ENC_CLUSTER_H_ #include #include "../common/platform.h" #include "histogram.h" #include "memory.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct HistogramPair { uint32_t idx1; uint32_t idx2; double cost_combo; double cost_diff; } HistogramPair; #define CODE(X) /* Declaration */; #define FN(X) X ## Literal #include "cluster_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Command #include "cluster_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Distance #include "cluster_inc.h" /* NOLINT(build/include) */ #undef FN #undef CODE #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_CLUSTER_H_ */ dvisvgm-3.5/libs/brotli/enc/cluster_inc.h000066400000000000000000000270621501401750600205220ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN, CODE */ #define HistogramType FN(Histogram) /* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ BROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)( const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size, uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs, size_t* num_pairs) CODE({ BROTLI_BOOL is_good_pair = BROTLI_FALSE; HistogramPair p; p.idx1 = p.idx2 = 0; p.cost_diff = p.cost_combo = 0; if (idx1 == idx2) { return; } if (idx2 < idx1) { uint32_t t = idx2; idx2 = idx1; idx1 = t; } p.idx1 = idx1; p.idx2 = idx2; p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]); p.cost_diff -= out[idx1].bit_cost_; p.cost_diff -= out[idx2].bit_cost_; if (out[idx1].total_count_ == 0) { p.cost_combo = out[idx2].bit_cost_; is_good_pair = BROTLI_TRUE; } else if (out[idx2].total_count_ == 0) { p.cost_combo = out[idx1].bit_cost_; is_good_pair = BROTLI_TRUE; } else { double threshold = *num_pairs == 0 ? 1e99 : BROTLI_MAX(double, 0.0, pairs[0].cost_diff); double cost_combo; *tmp = out[idx1]; FN(HistogramAddHistogram)(tmp, &out[idx2]); cost_combo = FN(BrotliPopulationCost)(tmp); if (cost_combo < threshold - p.cost_diff) { p.cost_combo = cost_combo; is_good_pair = BROTLI_TRUE; } } if (is_good_pair) { p.cost_diff += p.cost_combo; if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) { /* Replace the top of the queue if needed. */ if (*num_pairs < max_num_pairs) { pairs[*num_pairs] = pairs[0]; ++(*num_pairs); } pairs[0] = p; } else if (*num_pairs < max_num_pairs) { pairs[*num_pairs] = p; ++(*num_pairs); } } }) BROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out, HistogramType* tmp, uint32_t* cluster_size, uint32_t* symbols, uint32_t* clusters, HistogramPair* pairs, size_t num_clusters, size_t symbols_size, size_t max_clusters, size_t max_num_pairs) CODE({ double cost_diff_threshold = 0.0; size_t min_cluster_size = 1; size_t num_pairs = 0; { /* We maintain a vector of histogram pairs, with the property that the pair with the maximum bit cost reduction is the first. */ size_t idx1; for (idx1 = 0; idx1 < num_clusters; ++idx1) { size_t idx2; for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) { FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1], clusters[idx2], max_num_pairs, &pairs[0], &num_pairs); } } } while (num_clusters > min_cluster_size) { uint32_t best_idx1; uint32_t best_idx2; size_t i; if (pairs[0].cost_diff >= cost_diff_threshold) { cost_diff_threshold = 1e99; min_cluster_size = max_clusters; continue; } /* Take the best pair from the top of heap. */ best_idx1 = pairs[0].idx1; best_idx2 = pairs[0].idx2; FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]); out[best_idx1].bit_cost_ = pairs[0].cost_combo; cluster_size[best_idx1] += cluster_size[best_idx2]; for (i = 0; i < symbols_size; ++i) { if (symbols[i] == best_idx2) { symbols[i] = best_idx1; } } for (i = 0; i < num_clusters; ++i) { if (clusters[i] == best_idx2) { memmove(&clusters[i], &clusters[i + 1], (num_clusters - i - 1) * sizeof(clusters[0])); break; } } --num_clusters; { /* Remove pairs intersecting the just combined best pair. */ size_t copy_to_idx = 0; for (i = 0; i < num_pairs; ++i) { HistogramPair* p = &pairs[i]; if (p->idx1 == best_idx1 || p->idx2 == best_idx1 || p->idx1 == best_idx2 || p->idx2 == best_idx2) { /* Remove invalid pair from the queue. */ continue; } if (HistogramPairIsLess(&pairs[0], p)) { /* Replace the top of the queue if needed. */ HistogramPair front = pairs[0]; pairs[0] = *p; pairs[copy_to_idx] = front; } else { pairs[copy_to_idx] = *p; } ++copy_to_idx; } num_pairs = copy_to_idx; } /* Push new pairs formed with the combined histogram to the heap. */ for (i = 0; i < num_clusters; ++i) { FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1, clusters[i], max_num_pairs, &pairs[0], &num_pairs); } } return num_clusters; }) /* What is the bit cost of moving histogram from cur_symbol to candidate. */ BROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)( const HistogramType* histogram, const HistogramType* candidate, HistogramType* tmp) CODE({ if (histogram->total_count_ == 0) { return 0.0; } else { *tmp = *histogram; FN(HistogramAddHistogram)(tmp, candidate); return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_; } }) /* Find the best 'out' histogram for each of the 'in' histograms. When called, clusters[0..num_clusters) contains the unique values from symbols[0..in_size), but this property is not preserved in this function. Note: we assume that out[]->bit_cost_ is already up-to-date. */ BROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in, size_t in_size, const uint32_t* clusters, size_t num_clusters, HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({ size_t i; for (i = 0; i < in_size; ++i) { uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1]; double best_bits = FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp); size_t j; for (j = 0; j < num_clusters; ++j) { const double cur_bits = FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp); if (cur_bits < best_bits) { best_bits = cur_bits; best_out = clusters[j]; } } symbols[i] = best_out; } /* Recompute each out based on raw and symbols. */ for (i = 0; i < num_clusters; ++i) { FN(HistogramClear)(&out[clusters[i]]); } for (i = 0; i < in_size; ++i) { FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]); } }) /* Reorders elements of the out[0..length) array and changes values in symbols[0..length) array in the following way: * when called, symbols[] contains indexes into out[], and has N unique values (possibly N < length) * on return, symbols'[i] = f(symbols[i]) and out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, where f is a bijection between the range of symbols[] and [0..N), and the first occurrences of values in symbols'[i] come in consecutive increasing order. Returns N, the number of unique values in symbols[]. */ BROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m, HistogramType* out, uint32_t* symbols, size_t length) CODE({ static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length); uint32_t next_index; HistogramType* tmp; size_t i; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0; for (i = 0; i < length; ++i) { new_index[i] = kInvalidIndex; } next_index = 0; for (i = 0; i < length; ++i) { if (new_index[symbols[i]] == kInvalidIndex) { new_index[symbols[i]] = next_index; ++next_index; } } /* TODO(eustas): by using idea of "cycle-sort" we can avoid allocation of tmp and reduce the number of copying by the factor of 2. */ tmp = BROTLI_ALLOC(m, HistogramType, next_index); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0; next_index = 0; for (i = 0; i < length; ++i) { if (new_index[symbols[i]] == next_index) { tmp[next_index] = out[symbols[i]]; ++next_index; } symbols[i] = new_index[symbols[i]]; } BROTLI_FREE(m, new_index); for (i = 0; i < next_index; ++i) { out[i] = tmp[i]; } BROTLI_FREE(m, tmp); return next_index; }) BROTLI_INTERNAL void FN(BrotliClusterHistograms)( MemoryManager* m, const HistogramType* in, const size_t in_size, size_t max_histograms, HistogramType* out, size_t* out_size, uint32_t* histogram_symbols) CODE({ uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size); uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size); size_t num_clusters = 0; const size_t max_input_histograms = 64; size_t pairs_capacity = max_input_histograms * max_input_histograms / 2; /* For the first pass of clustering, we allow all pairs. */ HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1); /* TODO(eustas): move to "persistent" arena? */ HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1); size_t i; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) || BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) { return; } for (i = 0; i < in_size; ++i) { cluster_size[i] = 1; } for (i = 0; i < in_size; ++i) { out[i] = in[i]; out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]); histogram_symbols[i] = (uint32_t)i; } for (i = 0; i < in_size; i += max_input_histograms) { size_t num_to_combine = BROTLI_MIN(size_t, in_size - i, max_input_histograms); size_t num_new_clusters; size_t j; for (j = 0; j < num_to_combine; ++j) { clusters[num_clusters + j] = (uint32_t)(i + j); } num_new_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, &histogram_symbols[i], &clusters[num_clusters], pairs, num_to_combine, num_to_combine, max_histograms, pairs_capacity); num_clusters += num_new_clusters; } { /* For the second pass, we limit the total number of histogram pairs. After this limit is reached, we only keep searching for the best pair. */ size_t max_num_pairs = BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters); BROTLI_ENSURE_CAPACITY( m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1); if (BROTLI_IS_OOM(m)) return; /* Collapse similar histograms. */ num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, histogram_symbols, clusters, pairs, num_clusters, in_size, max_histograms, max_num_pairs); } BROTLI_FREE(m, pairs); BROTLI_FREE(m, cluster_size); /* Find the optimal map from original histograms to the final ones. */ FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters, out, tmp, histogram_symbols); BROTLI_FREE(m, tmp); BROTLI_FREE(m, clusters); /* Convert the context map to a canonical form. */ *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size); if (BROTLI_IS_OOM(m)) return; }) #undef HistogramType dvisvgm-3.5/libs/brotli/enc/command.c000066400000000000000000000017731501401750600176220ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "command.h" #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif const uint32_t kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES] = { 0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, 34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594}; const uint32_t kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES] = { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24}; const uint32_t kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18, 22, 30, 38, 54, 70, 102, 134, 198, 326, 582, 1094, 2118}; const uint32_t kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24}; #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/command.h000066400000000000000000000153541501401750600176270ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* This class models a sequence of literals and a backward reference copy. */ #ifndef BROTLI_ENC_COMMAND_H_ #define BROTLI_ENC_COMMAND_H_ #include #include "../common/constants.h" #include "../common/platform.h" #include "fast_log.h" #include "params.h" #include "prefix.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif BROTLI_INTERNAL extern const uint32_t kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES]; BROTLI_INTERNAL extern const uint32_t kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES]; BROTLI_INTERNAL extern const uint32_t kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES]; BROTLI_INTERNAL extern const uint32_t kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES]; static BROTLI_INLINE uint16_t GetInsertLengthCode(size_t insertlen) { if (insertlen < 6) { return (uint16_t)insertlen; } else if (insertlen < 130) { uint32_t nbits = Log2FloorNonZero(insertlen - 2) - 1u; return (uint16_t)((nbits << 1) + ((insertlen - 2) >> nbits) + 2); } else if (insertlen < 2114) { return (uint16_t)(Log2FloorNonZero(insertlen - 66) + 10); } else if (insertlen < 6210) { return 21u; } else if (insertlen < 22594) { return 22u; } else { return 23u; } } static BROTLI_INLINE uint16_t GetCopyLengthCode(size_t copylen) { if (copylen < 10) { return (uint16_t)(copylen - 2); } else if (copylen < 134) { uint32_t nbits = Log2FloorNonZero(copylen - 6) - 1u; return (uint16_t)((nbits << 1) + ((copylen - 6) >> nbits) + 4); } else if (copylen < 2118) { return (uint16_t)(Log2FloorNonZero(copylen - 70) + 12); } else { return 23u; } } static BROTLI_INLINE uint16_t CombineLengthCodes( uint16_t inscode, uint16_t copycode, BROTLI_BOOL use_last_distance) { uint16_t bits64 = (uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3u)); if (use_last_distance && inscode < 8u && copycode < 16u) { return (copycode < 8u) ? bits64 : (bits64 | 64u); } else { /* Specification: 5 Encoding of ... (last table) */ /* offset = 2 * index, where index is in range [0..8] */ uint32_t offset = 2u * ((copycode >> 3u) + 3u * (inscode >> 3u)); /* All values in specification are K * 64, where K = [2, 3, 6, 4, 5, 8, 7, 9, 10], i + 1 = [1, 2, 3, 4, 5, 6, 7, 8, 9], K - i - 1 = [1, 1, 3, 0, 0, 2, 0, 1, 2] = D. All values in D require only 2 bits to encode. Magic constant is shifted 6 bits left, to avoid final multiplication. */ offset = (offset << 5u) + 0x40u + ((0x520D40u >> offset) & 0xC0u); return (uint16_t)(offset | bits64); } } static BROTLI_INLINE void GetLengthCode(size_t insertlen, size_t copylen, BROTLI_BOOL use_last_distance, uint16_t* code) { uint16_t inscode = GetInsertLengthCode(insertlen); uint16_t copycode = GetCopyLengthCode(copylen); *code = CombineLengthCodes(inscode, copycode, use_last_distance); } static BROTLI_INLINE uint32_t GetInsertBase(uint16_t inscode) { return kBrotliInsBase[inscode]; } static BROTLI_INLINE uint32_t GetInsertExtra(uint16_t inscode) { return kBrotliInsExtra[inscode]; } static BROTLI_INLINE uint32_t GetCopyBase(uint16_t copycode) { return kBrotliCopyBase[copycode]; } static BROTLI_INLINE uint32_t GetCopyExtra(uint16_t copycode) { return kBrotliCopyExtra[copycode]; } typedef struct Command { uint32_t insert_len_; /* Stores copy_len in low 25 bits and copy_code - copy_len in high 7 bit. */ uint32_t copy_len_; /* Stores distance extra bits. */ uint32_t dist_extra_; uint16_t cmd_prefix_; /* Stores distance code in low 10 bits and number of extra bits in high 6 bits. */ uint16_t dist_prefix_; } Command; /* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */ static BROTLI_INLINE void InitCommand(Command* self, const BrotliDistanceParams* dist, size_t insertlen, size_t copylen, int copylen_code_delta, size_t distance_code) { /* Don't rely on signed int representation, use honest casts. */ uint32_t delta = (uint8_t)((int8_t)copylen_code_delta); self->insert_len_ = (uint32_t)insertlen; self->copy_len_ = (uint32_t)(copylen | (delta << 25)); /* The distance prefix and extra bits are stored in this Command as if npostfix and ndirect were 0, they are only recomputed later after the clustering if needed. */ PrefixEncodeCopyDistance( distance_code, dist->num_direct_distance_codes, dist->distance_postfix_bits, &self->dist_prefix_, &self->dist_extra_); GetLengthCode( insertlen, (size_t)((int)copylen + copylen_code_delta), TO_BROTLI_BOOL((self->dist_prefix_ & 0x3FF) == 0), &self->cmd_prefix_); } static BROTLI_INLINE void InitInsertCommand(Command* self, size_t insertlen) { self->insert_len_ = (uint32_t)insertlen; self->copy_len_ = 4 << 25; self->dist_extra_ = 0; self->dist_prefix_ = BROTLI_NUM_DISTANCE_SHORT_CODES; GetLengthCode(insertlen, 4, BROTLI_FALSE, &self->cmd_prefix_); } static BROTLI_INLINE uint32_t CommandRestoreDistanceCode( const Command* self, const BrotliDistanceParams* dist) { if ((self->dist_prefix_ & 0x3FFu) < BROTLI_NUM_DISTANCE_SHORT_CODES + dist->num_direct_distance_codes) { return self->dist_prefix_ & 0x3FFu; } else { uint32_t dcode = self->dist_prefix_ & 0x3FFu; uint32_t nbits = self->dist_prefix_ >> 10; uint32_t extra = self->dist_extra_; uint32_t postfix_mask = (1U << dist->distance_postfix_bits) - 1U; uint32_t hcode = (dcode - dist->num_direct_distance_codes - BROTLI_NUM_DISTANCE_SHORT_CODES) >> dist->distance_postfix_bits; uint32_t lcode = (dcode - dist->num_direct_distance_codes - BROTLI_NUM_DISTANCE_SHORT_CODES) & postfix_mask; uint32_t offset = ((2U + (hcode & 1U)) << nbits) - 4U; return ((offset + extra) << dist->distance_postfix_bits) + lcode + dist->num_direct_distance_codes + BROTLI_NUM_DISTANCE_SHORT_CODES; } } static BROTLI_INLINE uint32_t CommandDistanceContext(const Command* self) { uint32_t r = self->cmd_prefix_ >> 6; uint32_t c = self->cmd_prefix_ & 7; if ((r == 0 || r == 2 || r == 4 || r == 7) && (c <= 2)) { return c; } return 3; } static BROTLI_INLINE uint32_t CommandCopyLen(const Command* self) { return self->copy_len_ & 0x1FFFFFF; } static BROTLI_INLINE uint32_t CommandCopyLenCode(const Command* self) { uint32_t modifier = self->copy_len_ >> 25; int32_t delta = (int8_t)((uint8_t)(modifier | ((modifier & 0x40) << 1))); return (uint32_t)((int32_t)(self->copy_len_ & 0x1FFFFFF) + delta); } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_COMMAND_H_ */ dvisvgm-3.5/libs/brotli/enc/compound_dictionary.c000066400000000000000000000147651501401750600222620ustar00rootroot00000000000000/* Copyright 2017 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "compound_dictionary.h" #include #include "../common/platform.h" #include "memory.h" #include "quality.h" static PreparedDictionary* CreatePreparedDictionaryWithParams(MemoryManager* m, const uint8_t* source, size_t source_size, uint32_t bucket_bits, uint32_t slot_bits, uint32_t hash_bits, uint16_t bucket_limit) { /* Step 1: create "bloated" hasher. */ uint32_t num_slots = 1u << slot_bits; uint32_t num_buckets = 1u << bucket_bits; uint32_t hash_shift = 64u - bucket_bits; uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits); uint32_t slot_mask = num_slots - 1; size_t alloc_size = (sizeof(uint32_t) << slot_bits) + (sizeof(uint32_t) << slot_bits) + (sizeof(uint16_t) << bucket_bits) + (sizeof(uint32_t) << bucket_bits) + (sizeof(uint32_t) * source_size); uint8_t* flat = NULL; PreparedDictionary* result = NULL; uint16_t* num = NULL; uint32_t* bucket_heads = NULL; uint32_t* next_bucket = NULL; uint32_t* slot_offsets = NULL; uint16_t* heads = NULL; uint32_t* items = NULL; uint8_t** source_ref = NULL; uint32_t i; uint32_t* slot_size = NULL; uint32_t* slot_limit = NULL; uint32_t total_items = 0; if (slot_bits > 16) return NULL; if (slot_bits > bucket_bits) return NULL; if (bucket_bits - slot_bits >= 16) return NULL; flat = BROTLI_ALLOC(m, uint8_t, alloc_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(flat)) return NULL; slot_size = (uint32_t*)flat; slot_limit = (uint32_t*)(&slot_size[num_slots]); num = (uint16_t*)(&slot_limit[num_slots]); bucket_heads = (uint32_t*)(&num[num_buckets]); next_bucket = (uint32_t*)(&bucket_heads[num_buckets]); memset(num, 0, num_buckets * sizeof(num[0])); /* TODO(eustas): apply custom "store" order. */ for (i = 0; i + 7 < source_size; ++i) { const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(&source[i]) & hash_mask) * kPreparedDictionaryHashMul64Long; const uint32_t key = (uint32_t)(h >> hash_shift); uint16_t count = num[key]; next_bucket[i] = (count == 0) ? ((uint32_t)(-1)) : bucket_heads[key]; bucket_heads[key] = i; count++; if (count > bucket_limit) count = bucket_limit; num[key] = count; } /* Step 2: find slot limits. */ for (i = 0; i < num_slots; ++i) { BROTLI_BOOL overflow = BROTLI_FALSE; slot_limit[i] = bucket_limit; while (BROTLI_TRUE) { uint32_t limit = slot_limit[i]; size_t j; uint32_t count = 0; overflow = BROTLI_FALSE; for (j = i; j < num_buckets; j += num_slots) { uint32_t size = num[j]; /* Last chain may span behind 64K limit; overflow happens only if we are about to use 0xFFFF+ as item offset. */ if (count >= 0xFFFF) { overflow = BROTLI_TRUE; break; } if (size > limit) size = limit; count += size; } if (!overflow) { slot_size[i] = count; total_items += count; break; } slot_limit[i]--; } } /* Step 3: transfer data to "slim" hasher. */ alloc_size = sizeof(PreparedDictionary) + (sizeof(uint32_t) << slot_bits) + (sizeof(uint16_t) << bucket_bits) + (sizeof(uint32_t) * total_items) + sizeof(uint8_t*); result = (PreparedDictionary*)BROTLI_ALLOC(m, uint8_t, alloc_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(result)) { BROTLI_FREE(m, flat); return NULL; } slot_offsets = (uint32_t*)(&result[1]); heads = (uint16_t*)(&slot_offsets[num_slots]); items = (uint32_t*)(&heads[num_buckets]); source_ref = (uint8_t**)(&items[total_items]); result->magic = kLeanPreparedDictionaryMagic; result->num_items = total_items; result->source_size = (uint32_t)source_size; result->hash_bits = hash_bits; result->bucket_bits = bucket_bits; result->slot_bits = slot_bits; BROTLI_UNALIGNED_STORE_PTR(source_ref, source); total_items = 0; for (i = 0; i < num_slots; ++i) { slot_offsets[i] = total_items; total_items += slot_size[i]; slot_size[i] = 0; } for (i = 0; i < num_buckets; ++i) { uint32_t slot = i & slot_mask; uint32_t count = num[i]; uint32_t pos; size_t j; size_t cursor = slot_size[slot]; if (count > slot_limit[slot]) count = slot_limit[slot]; if (count == 0) { heads[i] = 0xFFFF; continue; } heads[i] = (uint16_t)cursor; cursor += slot_offsets[slot]; slot_size[slot] += count; pos = bucket_heads[i]; for (j = 0; j < count; j++) { items[cursor++] = pos; pos = next_bucket[pos]; } items[cursor - 1] |= 0x80000000; } BROTLI_FREE(m, flat); return result; } PreparedDictionary* CreatePreparedDictionary(MemoryManager* m, const uint8_t* source, size_t source_size) { uint32_t bucket_bits = 17; uint32_t slot_bits = 7; uint32_t hash_bits = 40; uint16_t bucket_limit = 32; size_t volume = 16u << bucket_bits; /* Tune parameters to fit dictionary size. */ while (volume < source_size && bucket_bits < 22) { bucket_bits++; slot_bits++; volume <<= 1; } return CreatePreparedDictionaryWithParams(m, source, source_size, bucket_bits, slot_bits, hash_bits, bucket_limit); } void DestroyPreparedDictionary(MemoryManager* m, PreparedDictionary* dictionary) { if (!dictionary) return; BROTLI_FREE(m, dictionary); } BROTLI_BOOL AttachPreparedDictionary( CompoundDictionary* compound, const PreparedDictionary* dictionary) { size_t length = 0; size_t index = 0; if (compound->num_chunks == SHARED_BROTLI_MAX_COMPOUND_DICTS) { return BROTLI_FALSE; } if (!dictionary) return BROTLI_FALSE; length = dictionary->source_size; index = compound->num_chunks; compound->total_size += length; compound->chunks[index] = dictionary; compound->chunk_offsets[index + 1] = compound->total_size; { uint32_t* slot_offsets = (uint32_t*)(&dictionary[1]); uint16_t* heads = (uint16_t*)(&slot_offsets[1u << dictionary->slot_bits]); uint32_t* items = (uint32_t*)(&heads[1u << dictionary->bucket_bits]); const void* tail = (void*)&items[dictionary->num_items]; if (dictionary->magic == kPreparedDictionaryMagic) { compound->chunk_source[index] = (const uint8_t*)tail; } else { /* dictionary->magic == kLeanPreparedDictionaryMagic */ compound->chunk_source[index] = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail); } } compound->num_chunks++; return BROTLI_TRUE; } dvisvgm-3.5/libs/brotli/enc/compound_dictionary.h000066400000000000000000000046751501401750600222660ustar00rootroot00000000000000/* Copyright 2017 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #ifndef BROTLI_ENC_PREPARED_DICTIONARY_H_ #define BROTLI_ENC_PREPARED_DICTIONARY_H_ #include #include #include "../common/platform.h" #include "../common/constants.h" #include "memory.h" /* "Fat" prepared dictionary, could be cooked outside of C implementation, * e.g. on Java side. LZ77 data is copied inside PreparedDictionary struct. */ static const uint32_t kPreparedDictionaryMagic = 0xDEBCEDE0; static const uint32_t kSharedDictionaryMagic = 0xDEBCEDE1; static const uint32_t kManagedDictionaryMagic = 0xDEBCEDE2; /* "Lean" prepared dictionary. LZ77 data is referenced. It is the responsibility * of caller of "prepare dictionary" to keep the LZ77 data while prepared * dictionary is in use. */ static const uint32_t kLeanPreparedDictionaryMagic = 0xDEBCEDE3; static const uint64_t kPreparedDictionaryHashMul64Long = BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u); typedef struct PreparedDictionary { uint32_t magic; uint32_t num_items; uint32_t source_size; uint32_t hash_bits; uint32_t bucket_bits; uint32_t slot_bits; /* --- Dynamic size members --- */ /* uint32_t slot_offsets[1 << slot_bits]; */ /* uint16_t heads[1 << bucket_bits]; */ /* uint32_t items[variable]; */ /* [maybe] uint8_t* source_ref, depending on magic. */ /* [maybe] uint8_t source[source_size], depending on magic. */ } PreparedDictionary; BROTLI_INTERNAL PreparedDictionary* CreatePreparedDictionary(MemoryManager* m, const uint8_t* source, size_t source_size); BROTLI_INTERNAL void DestroyPreparedDictionary(MemoryManager* m, PreparedDictionary* dictionary); typedef struct CompoundDictionary { /* LZ77 prefix, compound dictionary */ size_t num_chunks; size_t total_size; /* Client instances. */ const PreparedDictionary* chunks[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; const uint8_t* chunk_source[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; size_t chunk_offsets[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; size_t num_prepared_instances_; /* Owned instances. */ PreparedDictionary* prepared_instances_[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; } CompoundDictionary; BROTLI_INTERNAL BROTLI_BOOL AttachPreparedDictionary( CompoundDictionary* compound, const PreparedDictionary* dictionary); #endif /* BROTLI_ENC_PREPARED_DICTIONARY */ dvisvgm-3.5/libs/brotli/enc/compress_fragment.c000066400000000000000000001007471501401750600217230ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function for fast encoding of an input fragment, independently from the input history. This function uses one-pass processing: when we find a backward match, we immediately emit the corresponding command and literal codes to the bit stream. Adapted from the CompressFragment() function in https://github.com/google/snappy/blob/master/snappy.cc */ #include "compress_fragment.h" #include /* memcmp, memcpy, memset */ #include #include "../common/platform.h" #include "brotli_bit_stream.h" #include "entropy_encode.h" #include "fast_log.h" #include "find_match_length.h" #include "write_bits.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18) /* kHashMul32 multiplier has these properties: * The multiplier must be odd. Otherwise we may lose the highest bit. * No long streaks of ones or zeros. * There is no effort to ensure that it is a prime, the oddity is enough for this use. * The number has been tuned heuristically against compression benchmarks. */ static const uint32_t kHashMul32 = 0x1E35A7BD; static BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) { const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << 24) * kHashMul32; return (uint32_t)(h >> shift); } static BROTLI_INLINE uint32_t HashBytesAtOffset( uint64_t v, int offset, size_t shift) { BROTLI_DCHECK(offset >= 0); BROTLI_DCHECK(offset <= 3); { const uint64_t h = ((v >> (8 * offset)) << 24) * kHashMul32; return (uint32_t)(h >> shift); } } static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2) { return TO_BROTLI_BOOL( BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2) && p1[4] == p2[4]); } /* Builds a literal prefix code into "depths" and "bits" based on the statistics of the "input" string and stores it into the bit stream. Note that the prefix code here is built from the pre-LZ77 input, therefore we can only approximate the statistics of the actual literal stream. Moreover, for long inputs we build a histogram from a sample of the input and thus have to assign a non-zero depth for each literal. Returns estimated compression ratio millibytes/char for encoding given input with generated code. */ static size_t BuildAndStoreLiteralPrefixCode(BrotliOnePassArena* s, const uint8_t* input, const size_t input_size, uint8_t depths[256], uint16_t bits[256], size_t* storage_ix, uint8_t* storage) { uint32_t* BROTLI_RESTRICT const histogram = s->histogram; size_t histogram_total; size_t i; memset(histogram, 0, sizeof(s->histogram)); if (input_size < (1 << 15)) { for (i = 0; i < input_size; ++i) { ++histogram[input[i]]; } histogram_total = input_size; for (i = 0; i < 256; ++i) { /* We weigh the first 11 samples with weight 3 to account for the balancing effect of the LZ77 phase on the histogram. */ const uint32_t adjust = 2 * BROTLI_MIN(uint32_t, histogram[i], 11u); histogram[i] += adjust; histogram_total += adjust; } } else { static const size_t kSampleRate = 29; for (i = 0; i < input_size; i += kSampleRate) { ++histogram[input[i]]; } histogram_total = (input_size + kSampleRate - 1) / kSampleRate; for (i = 0; i < 256; ++i) { /* We add 1 to each population count to avoid 0 bit depths (since this is only a sample and we don't know if the symbol appears or not), and we weigh the first 11 samples with weight 3 to account for the balancing effect of the LZ77 phase on the histogram (more frequent symbols are more likely to be in backward references instead as literals). */ const uint32_t adjust = 1 + 2 * BROTLI_MIN(uint32_t, histogram[i], 11u); histogram[i] += adjust; histogram_total += adjust; } } BrotliBuildAndStoreHuffmanTreeFast(s->tree, histogram, histogram_total, /* max_bits = */ 8, depths, bits, storage_ix, storage); { size_t literal_ratio = 0; for (i = 0; i < 256; ++i) { if (histogram[i]) literal_ratio += histogram[i] * depths[i]; } /* Estimated encoding ratio, millibytes per symbol. */ return (literal_ratio * 125) / histogram_total; } } /* Builds a command and distance prefix code (each 64 symbols) into "depth" and "bits" based on "histogram" and stores it into the bit stream. */ static void BuildAndStoreCommandPrefixCode(BrotliOnePassArena* s, size_t* storage_ix, uint8_t* storage) { const uint32_t* const histogram = s->cmd_histo; uint8_t* const depth = s->cmd_depth; uint16_t* const bits = s->cmd_bits; uint8_t* BROTLI_RESTRICT const tmp_depth = s->tmp_depth; uint16_t* BROTLI_RESTRICT const tmp_bits = s->tmp_bits; /* TODO(eustas): do only once on initialization. */ memset(tmp_depth, 0, BROTLI_NUM_COMMAND_SYMBOLS); BrotliCreateHuffmanTree(histogram, 64, 15, s->tree, depth); BrotliCreateHuffmanTree(&histogram[64], 64, 14, s->tree, &depth[64]); /* We have to jump through a few hoops here in order to compute the command bits because the symbols are in a different order than in the full alphabet. This looks complicated, but having the symbols in this order in the command bits saves a few branches in the Emit* functions. */ memcpy(tmp_depth, depth, 24); memcpy(tmp_depth + 24, depth + 40, 8); memcpy(tmp_depth + 32, depth + 24, 8); memcpy(tmp_depth + 40, depth + 48, 8); memcpy(tmp_depth + 48, depth + 32, 8); memcpy(tmp_depth + 56, depth + 56, 8); BrotliConvertBitDepthsToSymbols(tmp_depth, 64, tmp_bits); memcpy(bits, tmp_bits, 48); memcpy(bits + 24, tmp_bits + 32, 16); memcpy(bits + 32, tmp_bits + 48, 16); memcpy(bits + 40, tmp_bits + 24, 16); memcpy(bits + 48, tmp_bits + 40, 16); memcpy(bits + 56, tmp_bits + 56, 16); BrotliConvertBitDepthsToSymbols(&depth[64], 64, &bits[64]); { /* Create the bit length array for the full command alphabet. */ size_t i; memset(tmp_depth, 0, 64); /* only 64 first values were used */ memcpy(tmp_depth, depth, 8); memcpy(tmp_depth + 64, depth + 8, 8); memcpy(tmp_depth + 128, depth + 16, 8); memcpy(tmp_depth + 192, depth + 24, 8); memcpy(tmp_depth + 384, depth + 32, 8); for (i = 0; i < 8; ++i) { tmp_depth[128 + 8 * i] = depth[40 + i]; tmp_depth[256 + 8 * i] = depth[48 + i]; tmp_depth[448 + 8 * i] = depth[56 + i]; } /* TODO(eustas): could/should full-length machinery be avoided? */ BrotliStoreHuffmanTree( tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS, s->tree, storage_ix, storage); } BrotliStoreHuffmanTree(&depth[64], 64, s->tree, storage_ix, storage); } /* REQUIRES: insertlen < 6210 */ static BROTLI_INLINE void EmitInsertLen(size_t insertlen, const uint8_t depth[128], const uint16_t bits[128], uint32_t histo[128], size_t* storage_ix, uint8_t* storage) { if (insertlen < 6) { const size_t code = insertlen + 40; BrotliWriteBits(depth[code], bits[code], storage_ix, storage); ++histo[code]; } else if (insertlen < 130) { const size_t tail = insertlen - 2; const uint32_t nbits = Log2FloorNonZero(tail) - 1u; const size_t prefix = tail >> nbits; const size_t inscode = (nbits << 1) + prefix + 42; BrotliWriteBits(depth[inscode], bits[inscode], storage_ix, storage); BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage); ++histo[inscode]; } else if (insertlen < 2114) { const size_t tail = insertlen - 66; const uint32_t nbits = Log2FloorNonZero(tail); const size_t code = nbits + 50; BrotliWriteBits(depth[code], bits[code], storage_ix, storage); BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage); ++histo[code]; } else { BrotliWriteBits(depth[61], bits[61], storage_ix, storage); BrotliWriteBits(12, insertlen - 2114, storage_ix, storage); ++histo[61]; } } static BROTLI_INLINE void EmitLongInsertLen(size_t insertlen, const uint8_t depth[128], const uint16_t bits[128], uint32_t histo[128], size_t* storage_ix, uint8_t* storage) { if (insertlen < 22594) { BrotliWriteBits(depth[62], bits[62], storage_ix, storage); BrotliWriteBits(14, insertlen - 6210, storage_ix, storage); ++histo[62]; } else { BrotliWriteBits(depth[63], bits[63], storage_ix, storage); BrotliWriteBits(24, insertlen - 22594, storage_ix, storage); ++histo[63]; } } static BROTLI_INLINE void EmitCopyLen(size_t copylen, const uint8_t depth[128], const uint16_t bits[128], uint32_t histo[128], size_t* storage_ix, uint8_t* storage) { if (copylen < 10) { BrotliWriteBits( depth[copylen + 14], bits[copylen + 14], storage_ix, storage); ++histo[copylen + 14]; } else if (copylen < 134) { const size_t tail = copylen - 6; const uint32_t nbits = Log2FloorNonZero(tail) - 1u; const size_t prefix = tail >> nbits; const size_t code = (nbits << 1) + prefix + 20; BrotliWriteBits(depth[code], bits[code], storage_ix, storage); BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage); ++histo[code]; } else if (copylen < 2118) { const size_t tail = copylen - 70; const uint32_t nbits = Log2FloorNonZero(tail); const size_t code = nbits + 28; BrotliWriteBits(depth[code], bits[code], storage_ix, storage); BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage); ++histo[code]; } else { BrotliWriteBits(depth[39], bits[39], storage_ix, storage); BrotliWriteBits(24, copylen - 2118, storage_ix, storage); ++histo[39]; } } static BROTLI_INLINE void EmitCopyLenLastDistance(size_t copylen, const uint8_t depth[128], const uint16_t bits[128], uint32_t histo[128], size_t* storage_ix, uint8_t* storage) { if (copylen < 12) { BrotliWriteBits(depth[copylen - 4], bits[copylen - 4], storage_ix, storage); ++histo[copylen - 4]; } else if (copylen < 72) { const size_t tail = copylen - 8; const uint32_t nbits = Log2FloorNonZero(tail) - 1; const size_t prefix = tail >> nbits; const size_t code = (nbits << 1) + prefix + 4; BrotliWriteBits(depth[code], bits[code], storage_ix, storage); BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage); ++histo[code]; } else if (copylen < 136) { const size_t tail = copylen - 8; const size_t code = (tail >> 5) + 30; BrotliWriteBits(depth[code], bits[code], storage_ix, storage); BrotliWriteBits(5, tail & 31, storage_ix, storage); BrotliWriteBits(depth[64], bits[64], storage_ix, storage); ++histo[code]; ++histo[64]; } else if (copylen < 2120) { const size_t tail = copylen - 72; const uint32_t nbits = Log2FloorNonZero(tail); const size_t code = nbits + 28; BrotliWriteBits(depth[code], bits[code], storage_ix, storage); BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage); BrotliWriteBits(depth[64], bits[64], storage_ix, storage); ++histo[code]; ++histo[64]; } else { BrotliWriteBits(depth[39], bits[39], storage_ix, storage); BrotliWriteBits(24, copylen - 2120, storage_ix, storage); BrotliWriteBits(depth[64], bits[64], storage_ix, storage); ++histo[39]; ++histo[64]; } } static BROTLI_INLINE void EmitDistance(size_t distance, const uint8_t depth[128], const uint16_t bits[128], uint32_t histo[128], size_t* storage_ix, uint8_t* storage) { const size_t d = distance + 3; const uint32_t nbits = Log2FloorNonZero(d) - 1u; const size_t prefix = (d >> nbits) & 1; const size_t offset = (2 + prefix) << nbits; const size_t distcode = 2 * (nbits - 1) + prefix + 80; BrotliWriteBits(depth[distcode], bits[distcode], storage_ix, storage); BrotliWriteBits(nbits, d - offset, storage_ix, storage); ++histo[distcode]; } static BROTLI_INLINE void EmitLiterals(const uint8_t* input, const size_t len, const uint8_t depth[256], const uint16_t bits[256], size_t* storage_ix, uint8_t* storage) { size_t j; for (j = 0; j < len; j++) { const uint8_t lit = input[j]; BrotliWriteBits(depth[lit], bits[lit], storage_ix, storage); } } /* REQUIRES: len <= 1 << 24. */ static void BrotliStoreMetaBlockHeader( size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix, uint8_t* storage) { size_t nibbles = 6; /* ISLAST */ BrotliWriteBits(1, 0, storage_ix, storage); if (len <= (1U << 16)) { nibbles = 4; } else if (len <= (1U << 20)) { nibbles = 5; } BrotliWriteBits(2, nibbles - 4, storage_ix, storage); BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage); /* ISUNCOMPRESSED */ BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage); } static void UpdateBits(size_t n_bits, uint32_t bits, size_t pos, uint8_t* array) { while (n_bits > 0) { size_t byte_pos = pos >> 3; size_t n_unchanged_bits = pos & 7; size_t n_changed_bits = BROTLI_MIN(size_t, n_bits, 8 - n_unchanged_bits); size_t total_bits = n_unchanged_bits + n_changed_bits; uint32_t mask = (~((1u << total_bits) - 1u)) | ((1u << n_unchanged_bits) - 1u); uint32_t unchanged_bits = array[byte_pos] & mask; uint32_t changed_bits = bits & ((1u << n_changed_bits) - 1u); array[byte_pos] = (uint8_t)((changed_bits << n_unchanged_bits) | unchanged_bits); n_bits -= n_changed_bits; bits >>= n_changed_bits; pos += n_changed_bits; } } static void RewindBitPosition(const size_t new_storage_ix, size_t* storage_ix, uint8_t* storage) { const size_t bitpos = new_storage_ix & 7; const size_t mask = (1u << bitpos) - 1; storage[new_storage_ix >> 3] &= (uint8_t)mask; *storage_ix = new_storage_ix; } static BROTLI_BOOL ShouldMergeBlock(BrotliOnePassArena* s, const uint8_t* data, size_t len, const uint8_t* depths) { uint32_t* BROTLI_RESTRICT const histo = s->histogram; static const size_t kSampleRate = 43; size_t i; memset(histo, 0, sizeof(s->histogram)); for (i = 0; i < len; i += kSampleRate) { ++histo[data[i]]; } { const size_t total = (len + kSampleRate - 1) / kSampleRate; double r = (FastLog2(total) + 0.5) * (double)total + 200; for (i = 0; i < 256; ++i) { r -= (double)histo[i] * (depths[i] + FastLog2(histo[i])); } return TO_BROTLI_BOOL(r >= 0.0); } } /* Acceptable loss for uncompressible speedup is 2% */ #define MIN_RATIO 980 static BROTLI_INLINE BROTLI_BOOL ShouldUseUncompressedMode( const uint8_t* metablock_start, const uint8_t* next_emit, const size_t insertlen, const size_t literal_ratio) { const size_t compressed = (size_t)(next_emit - metablock_start); if (compressed * 50 > insertlen) { return BROTLI_FALSE; } else { return TO_BROTLI_BOOL(literal_ratio > MIN_RATIO); } } static void EmitUncompressedMetaBlock(const uint8_t* begin, const uint8_t* end, const size_t storage_ix_start, size_t* storage_ix, uint8_t* storage) { const size_t len = (size_t)(end - begin); RewindBitPosition(storage_ix_start, storage_ix, storage); BrotliStoreMetaBlockHeader(len, 1, storage_ix, storage); *storage_ix = (*storage_ix + 7u) & ~7u; memcpy(&storage[*storage_ix >> 3], begin, len); *storage_ix += len << 3; storage[*storage_ix >> 3] = 0; } static uint32_t kCmdHistoSeed[128] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, }; static BROTLI_INLINE void BrotliCompressFragmentFastImpl( BrotliOnePassArena* s, const uint8_t* input, size_t input_size, BROTLI_BOOL is_last, int* table, size_t table_bits, size_t* storage_ix, uint8_t* storage) { uint8_t* BROTLI_RESTRICT const cmd_depth = s->cmd_depth; uint16_t* BROTLI_RESTRICT const cmd_bits = s->cmd_bits; uint32_t* BROTLI_RESTRICT const cmd_histo = s->cmd_histo; uint8_t* BROTLI_RESTRICT const lit_depth = s->lit_depth; uint16_t* BROTLI_RESTRICT const lit_bits = s->lit_bits; const uint8_t* ip_end; /* "next_emit" is a pointer to the first byte that is not covered by a previous copy. Bytes between "next_emit" and the start of the next copy or the end of the input will be emitted as literal bytes. */ const uint8_t* next_emit = input; /* Save the start of the first block for position and distance computations. */ const uint8_t* base_ip = input; static const size_t kFirstBlockSize = 3 << 15; static const size_t kMergeBlockSize = 1 << 16; const size_t kInputMarginBytes = BROTLI_WINDOW_GAP; const size_t kMinMatchLen = 5; const uint8_t* metablock_start = input; size_t block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize); size_t total_block_size = block_size; /* Save the bit position of the MLEN field of the meta-block header, so that we can update it later if we decide to extend this meta-block. */ size_t mlen_storage_ix = *storage_ix + 3; size_t literal_ratio; const uint8_t* ip; int last_distance; const size_t shift = 64u - table_bits; BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage); /* No block splits, no contexts. */ BrotliWriteBits(13, 0, storage_ix, storage); literal_ratio = BuildAndStoreLiteralPrefixCode( s, input, block_size, s->lit_depth, s->lit_bits, storage_ix, storage); { /* Store the pre-compressed command and distance prefix codes. */ size_t i; for (i = 0; i + 7 < s->cmd_code_numbits; i += 8) { BrotliWriteBits(8, s->cmd_code[i >> 3], storage_ix, storage); } } BrotliWriteBits(s->cmd_code_numbits & 7, s->cmd_code[s->cmd_code_numbits >> 3], storage_ix, storage); emit_commands: /* Initialize the command and distance histograms. We will gather statistics of command and distance codes during the processing of this block and use it to update the command and distance prefix codes for the next block. */ memcpy(s->cmd_histo, kCmdHistoSeed, sizeof(kCmdHistoSeed)); /* "ip" is the input pointer. */ ip = input; last_distance = -1; ip_end = input + block_size; if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) { /* For the last block, we need to keep a 16 bytes margin so that we can be sure that all distances are at most window size - 16. For all other blocks, we only need to keep a margin of 5 bytes so that we don't go over the block size with a copy. */ const size_t len_limit = BROTLI_MIN(size_t, block_size - kMinMatchLen, input_size - kInputMarginBytes); const uint8_t* ip_limit = input + len_limit; uint32_t next_hash; for (next_hash = Hash(++ip, shift); ; ) { /* Step 1: Scan forward in the input looking for a 5-byte-long match. If we get close to exhausting the input then goto emit_remainder. Heuristic match skipping: If 32 bytes are scanned with no matches found, start looking only at every other byte. If 32 more bytes are scanned, look at every third byte, etc.. When a match is found, immediately go back to looking at every byte. This is a small loss (~5% performance, ~0.1% density) for compressible data due to more bookkeeping, but for non-compressible data (such as JPEG) it's a huge win since the compressor quickly "realizes" the data is incompressible and doesn't bother looking for matches everywhere. The "skip" variable keeps track of how many bytes there are since the last match; dividing it by 32 (i.e. right-shifting by five) gives the number of bytes to move ahead for each iteration. */ uint32_t skip = 32; const uint8_t* next_ip = ip; const uint8_t* candidate; BROTLI_DCHECK(next_emit < ip); trawl: do { uint32_t hash = next_hash; uint32_t bytes_between_hash_lookups = skip++ >> 5; BROTLI_DCHECK(hash == Hash(next_ip, shift)); ip = next_ip; next_ip = ip + bytes_between_hash_lookups; if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) { goto emit_remainder; } next_hash = Hash(next_ip, shift); candidate = ip - last_distance; if (IsMatch(ip, candidate)) { if (BROTLI_PREDICT_TRUE(candidate < ip)) { table[hash] = (int)(ip - base_ip); break; } } candidate = base_ip + table[hash]; BROTLI_DCHECK(candidate >= base_ip); BROTLI_DCHECK(candidate < ip); table[hash] = (int)(ip - base_ip); } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate))); /* Check copy distance. If candidate is not feasible, continue search. Checking is done outside of hot loop to reduce overhead. */ if (ip - candidate > MAX_DISTANCE) goto trawl; /* Step 2: Emit the found match together with the literal bytes from "next_emit" to the bit stream, and then see if we can find a next match immediately afterwards. Repeat until we find no match for the input without emitting some literal bytes. */ { /* We have a 5-byte match at ip, and we need to emit bytes in [next_emit, ip). */ const uint8_t* base = ip; size_t matched = 5 + FindMatchLengthWithLimit( candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5); int distance = (int)(base - candidate); /* > 0 */ size_t insert = (size_t)(base - next_emit); ip += matched; BROTLI_LOG(("[CompressFragment] pos = %d insert = %lu copy = %d\n", (int)(next_emit - base_ip), (unsigned long)insert, 2)); BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); if (BROTLI_PREDICT_TRUE(insert < 6210)) { EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert, literal_ratio)) { EmitUncompressedMetaBlock(metablock_start, base, mlen_storage_ix - 3, storage_ix, storage); input_size -= (size_t)(base - input); input = base; next_emit = input; goto next_block; } else { EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); } EmitLiterals(next_emit, insert, lit_depth, lit_bits, storage_ix, storage); if (distance == last_distance) { BrotliWriteBits(cmd_depth[64], cmd_bits[64], storage_ix, storage); ++cmd_histo[64]; } else { EmitDistance((size_t)distance, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); last_distance = distance; } EmitCopyLenLastDistance(matched, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); BROTLI_LOG(("[CompressFragment] pos = %d distance = %d\n" "[CompressFragment] pos = %d insert = %d copy = %d\n" "[CompressFragment] pos = %d distance = %d\n", (int)(base - base_ip), (int)distance, (int)(base - base_ip) + 2, 0, (int)matched - 2, (int)(base - base_ip) + 2, (int)distance)); next_emit = ip; if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { goto emit_remainder; } /* We could immediately start working at ip now, but to improve compression we first update "table" with the hashes of some positions within the last copy. */ { uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift); uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift); table[prev_hash] = (int)(ip - base_ip - 3); prev_hash = HashBytesAtOffset(input_bytes, 1, shift); table[prev_hash] = (int)(ip - base_ip - 2); prev_hash = HashBytesAtOffset(input_bytes, 2, shift); table[prev_hash] = (int)(ip - base_ip - 1); candidate = base_ip + table[cur_hash]; table[cur_hash] = (int)(ip - base_ip); } } while (IsMatch(ip, candidate)) { /* We have a 5-byte match at ip, and no need to emit any literal bytes prior to ip. */ const uint8_t* base = ip; size_t matched = 5 + FindMatchLengthWithLimit( candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5); if (ip - candidate > MAX_DISTANCE) break; ip += matched; last_distance = (int)(base - candidate); /* > 0 */ BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); EmitCopyLen(matched, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); EmitDistance((size_t)last_distance, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n" "[CompressFragment] pos = %d distance = %d\n", (int)(base - base_ip), 0, (int)matched, (int)(base - base_ip), (int)last_distance)); next_emit = ip; if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { goto emit_remainder; } /* We could immediately start working at ip now, but to improve compression we first update "table" with the hashes of some positions within the last copy. */ { uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift); uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift); table[prev_hash] = (int)(ip - base_ip - 3); prev_hash = HashBytesAtOffset(input_bytes, 1, shift); table[prev_hash] = (int)(ip - base_ip - 2); prev_hash = HashBytesAtOffset(input_bytes, 2, shift); table[prev_hash] = (int)(ip - base_ip - 1); candidate = base_ip + table[cur_hash]; table[cur_hash] = (int)(ip - base_ip); } } next_hash = Hash(++ip, shift); } } emit_remainder: BROTLI_DCHECK(next_emit <= ip_end); input += block_size; input_size -= block_size; block_size = BROTLI_MIN(size_t, input_size, kMergeBlockSize); /* Decide if we want to continue this meta-block instead of emitting the last insert-only command. */ if (input_size > 0 && total_block_size + block_size <= (1 << 20) && ShouldMergeBlock(s, input, block_size, lit_depth)) { BROTLI_DCHECK(total_block_size > (1 << 16)); /* Update the size of the current meta-block and continue emitting commands. We can do this because the current size and the new size both have 5 nibbles. */ total_block_size += block_size; UpdateBits(20, (uint32_t)(total_block_size - 1), mlen_storage_ix, storage); goto emit_commands; } /* Emit the remaining bytes as literals. */ if (next_emit < ip_end) { const size_t insert = (size_t)(ip_end - next_emit); BROTLI_LOG(("[CompressFragment] pos = %d insert = %lu copy = %d\n", (int)(next_emit - base_ip), (unsigned long)insert, 2)); if (BROTLI_PREDICT_TRUE(insert < 6210)) { EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); EmitLiterals(next_emit, insert, lit_depth, lit_bits, storage_ix, storage); } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert, literal_ratio)) { EmitUncompressedMetaBlock(metablock_start, ip_end, mlen_storage_ix - 3, storage_ix, storage); } else { EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, storage_ix, storage); EmitLiterals(next_emit, insert, lit_depth, lit_bits, storage_ix, storage); } } next_emit = ip_end; next_block: /* If we have more data, write a new meta-block header and prefix codes and then continue emitting commands. */ if (input_size > 0) { metablock_start = input; block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize); total_block_size = block_size; /* Save the bit position of the MLEN field of the meta-block header, so that we can update it later if we decide to extend this meta-block. */ mlen_storage_ix = *storage_ix + 3; BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage); /* No block splits, no contexts. */ BrotliWriteBits(13, 0, storage_ix, storage); literal_ratio = BuildAndStoreLiteralPrefixCode( s, input, block_size, lit_depth, lit_bits, storage_ix, storage); BuildAndStoreCommandPrefixCode(s, storage_ix, storage); goto emit_commands; } if (!is_last) { /* If this is not the last block, update the command and distance prefix codes for the next block and store the compressed forms. */ s->cmd_code[0] = 0; s->cmd_code_numbits = 0; BuildAndStoreCommandPrefixCode(s, &s->cmd_code_numbits, s->cmd_code); } } #define FOR_TABLE_BITS_(X) X(9) X(11) X(13) X(15) #define BAKE_METHOD_PARAM_(B) \ static BROTLI_NOINLINE void BrotliCompressFragmentFastImpl ## B( \ BrotliOnePassArena* s, const uint8_t* input, size_t input_size, \ BROTLI_BOOL is_last, int* table, size_t* storage_ix, uint8_t* storage) { \ BrotliCompressFragmentFastImpl(s, input, input_size, is_last, table, B, \ storage_ix, storage); \ } FOR_TABLE_BITS_(BAKE_METHOD_PARAM_) #undef BAKE_METHOD_PARAM_ void BrotliCompressFragmentFast( BrotliOnePassArena* s, const uint8_t* input, size_t input_size, BROTLI_BOOL is_last, int* table, size_t table_size, size_t* storage_ix, uint8_t* storage) { const size_t initial_storage_ix = *storage_ix; const size_t table_bits = Log2FloorNonZero(table_size); if (input_size == 0) { BROTLI_DCHECK(is_last); BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ *storage_ix = (*storage_ix + 7u) & ~7u; return; } switch (table_bits) { #define CASE_(B) \ case B: \ BrotliCompressFragmentFastImpl ## B( \ s, input, input_size, is_last, table, storage_ix, storage);\ break; FOR_TABLE_BITS_(CASE_) #undef CASE_ default: BROTLI_DCHECK(0); break; } /* If output is larger than single uncompressed block, rewrite it. */ if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) { EmitUncompressedMetaBlock(input, input + input_size, initial_storage_ix, storage_ix, storage); } if (is_last) { BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ *storage_ix = (*storage_ix + 7u) & ~7u; } } #undef FOR_TABLE_BITS_ #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/compress_fragment.h000066400000000000000000000070161501401750600217230ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function for fast encoding of an input fragment, independently from the input history. This function uses one-pass processing: when we find a backward match, we immediately emit the corresponding command and literal codes to the bit stream. */ #ifndef BROTLI_ENC_COMPRESS_FRAGMENT_H_ #define BROTLI_ENC_COMPRESS_FRAGMENT_H_ #include #include "../common/constants.h" #include "../common/platform.h" #include "entropy_encode.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct BrotliOnePassArena { uint8_t lit_depth[256]; uint16_t lit_bits[256]; /* Command and distance prefix codes (each 64 symbols, stored back-to-back) used for the next block. The command prefix code is over a smaller alphabet with the following 64 symbols: 0 - 15: insert length code 0, copy length code 0 - 15, same distance 16 - 39: insert length code 0, copy length code 0 - 23 40 - 63: insert length code 0 - 23, copy length code 0 Note that symbols 16 and 40 represent the same code in the full alphabet, but we do not use either of them. */ uint8_t cmd_depth[128]; uint16_t cmd_bits[128]; uint32_t cmd_histo[128]; /* The compressed form of the command and distance prefix codes for the next block. */ uint8_t cmd_code[512]; size_t cmd_code_numbits; HuffmanTree tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1]; uint32_t histogram[256]; uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS]; uint16_t tmp_bits[64]; } BrotliOnePassArena; /* Compresses "input" string to the "*storage" buffer as one or more complete meta-blocks, and updates the "*storage_ix" bit position. If "is_last" is 1, emits an additional empty last meta-block. "cmd_depth" and "cmd_bits" contain the command and distance prefix codes (see comment in encode.h) used for the encoding of this input fragment. If "is_last" is 0, they are updated to reflect the statistics of this input fragment, to be used for the encoding of the next fragment. "*cmd_code_numbits" is the number of bits of the compressed representation of the command and distance prefix codes, and "cmd_code" is an array of at least "(*cmd_code_numbits + 7) >> 3" size that contains the compressed command and distance prefix codes. If "is_last" is 0, these are also updated to represent the updated "cmd_depth" and "cmd_bits". REQUIRES: "input_size" is greater than zero, or "is_last" is 1. REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24). REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. REQUIRES: "table_size" is an odd (9, 11, 13, 15) power of two OUTPUT: maximal copy distance <= |input_size| OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */ BROTLI_INTERNAL void BrotliCompressFragmentFast(BrotliOnePassArena* s, const uint8_t* input, size_t input_size, BROTLI_BOOL is_last, int* table, size_t table_size, size_t* storage_ix, uint8_t* storage); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_COMPRESS_FRAGMENT_H_ */ dvisvgm-3.5/libs/brotli/enc/compress_fragment_two_pass.c000066400000000000000000000650561501401750600236450ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function for fast encoding of an input fragment, independently from the input history. This function uses two-pass processing: in the first pass we save the found backward matches and literal bytes into a buffer, and in the second pass we emit them into the bit stream using prefix codes built based on the actual command and literal byte histograms. */ #include "compress_fragment_two_pass.h" #include /* memcmp, memcpy, memset */ #include #include "../common/constants.h" #include "../common/platform.h" #include "bit_cost.h" #include "brotli_bit_stream.h" #include "entropy_encode.h" #include "fast_log.h" #include "find_match_length.h" #include "write_bits.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18) /* kHashMul32 multiplier has these properties: * The multiplier must be odd. Otherwise we may lose the highest bit. * No long streaks of ones or zeros. * There is no effort to ensure that it is a prime, the oddity is enough for this use. * The number has been tuned heuristically against compression benchmarks. */ static const uint32_t kHashMul32 = 0x1E35A7BD; static BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift, size_t length) { const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << ((8 - length) * 8)) * kHashMul32; return (uint32_t)(h >> shift); } static BROTLI_INLINE uint32_t HashBytesAtOffset(uint64_t v, size_t offset, size_t shift, size_t length) { BROTLI_DCHECK(offset <= 8 - length); { const uint64_t h = ((v >> (8 * offset)) << ((8 - length) * 8)) * kHashMul32; return (uint32_t)(h >> shift); } } static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2, size_t length) { if (BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2)) { if (length == 4) return BROTLI_TRUE; return TO_BROTLI_BOOL(p1[4] == p2[4] && p1[5] == p2[5]); } return BROTLI_FALSE; } /* Builds a command and distance prefix code (each 64 symbols) into "depth" and "bits" based on "histogram" and stores it into the bit stream. */ static void BuildAndStoreCommandPrefixCode(BrotliTwoPassArena* s, size_t* storage_ix, uint8_t* storage) { /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */ /* TODO(eustas): initialize once. */ memset(s->tmp_depth, 0, sizeof(s->tmp_depth)); BrotliCreateHuffmanTree(s->cmd_histo, 64, 15, s->tmp_tree, s->cmd_depth); BrotliCreateHuffmanTree(&s->cmd_histo[64], 64, 14, s->tmp_tree, &s->cmd_depth[64]); /* We have to jump through a few hoops here in order to compute the command bits because the symbols are in a different order than in the full alphabet. This looks complicated, but having the symbols in this order in the command bits saves a few branches in the Emit* functions. */ memcpy(s->tmp_depth, s->cmd_depth + 24, 24); memcpy(s->tmp_depth + 24, s->cmd_depth, 8); memcpy(s->tmp_depth + 32, s->cmd_depth + 48, 8); memcpy(s->tmp_depth + 40, s->cmd_depth + 8, 8); memcpy(s->tmp_depth + 48, s->cmd_depth + 56, 8); memcpy(s->tmp_depth + 56, s->cmd_depth + 16, 8); BrotliConvertBitDepthsToSymbols(s->tmp_depth, 64, s->tmp_bits); memcpy(s->cmd_bits, s->tmp_bits + 24, 16); memcpy(s->cmd_bits + 8, s->tmp_bits + 40, 16); memcpy(s->cmd_bits + 16, s->tmp_bits + 56, 16); memcpy(s->cmd_bits + 24, s->tmp_bits, 48); memcpy(s->cmd_bits + 48, s->tmp_bits + 32, 16); memcpy(s->cmd_bits + 56, s->tmp_bits + 48, 16); BrotliConvertBitDepthsToSymbols(&s->cmd_depth[64], 64, &s->cmd_bits[64]); { /* Create the bit length array for the full command alphabet. */ size_t i; memset(s->tmp_depth, 0, 64); /* only 64 first values were used */ memcpy(s->tmp_depth, s->cmd_depth + 24, 8); memcpy(s->tmp_depth + 64, s->cmd_depth + 32, 8); memcpy(s->tmp_depth + 128, s->cmd_depth + 40, 8); memcpy(s->tmp_depth + 192, s->cmd_depth + 48, 8); memcpy(s->tmp_depth + 384, s->cmd_depth + 56, 8); for (i = 0; i < 8; ++i) { s->tmp_depth[128 + 8 * i] = s->cmd_depth[i]; s->tmp_depth[256 + 8 * i] = s->cmd_depth[8 + i]; s->tmp_depth[448 + 8 * i] = s->cmd_depth[16 + i]; } BrotliStoreHuffmanTree(s->tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS, s->tmp_tree, storage_ix, storage); } BrotliStoreHuffmanTree(&s->cmd_depth[64], 64, s->tmp_tree, storage_ix, storage); } static BROTLI_INLINE void EmitInsertLen( uint32_t insertlen, uint32_t** commands) { if (insertlen < 6) { **commands = insertlen; } else if (insertlen < 130) { const uint32_t tail = insertlen - 2; const uint32_t nbits = Log2FloorNonZero(tail) - 1u; const uint32_t prefix = tail >> nbits; const uint32_t inscode = (nbits << 1) + prefix + 2; const uint32_t extra = tail - (prefix << nbits); **commands = inscode | (extra << 8); } else if (insertlen < 2114) { const uint32_t tail = insertlen - 66; const uint32_t nbits = Log2FloorNonZero(tail); const uint32_t code = nbits + 10; const uint32_t extra = tail - (1u << nbits); **commands = code | (extra << 8); } else if (insertlen < 6210) { const uint32_t extra = insertlen - 2114; **commands = 21 | (extra << 8); } else if (insertlen < 22594) { const uint32_t extra = insertlen - 6210; **commands = 22 | (extra << 8); } else { const uint32_t extra = insertlen - 22594; **commands = 23 | (extra << 8); } ++(*commands); } static BROTLI_INLINE void EmitCopyLen(size_t copylen, uint32_t** commands) { if (copylen < 10) { **commands = (uint32_t)(copylen + 38); } else if (copylen < 134) { const size_t tail = copylen - 6; const size_t nbits = Log2FloorNonZero(tail) - 1; const size_t prefix = tail >> nbits; const size_t code = (nbits << 1) + prefix + 44; const size_t extra = tail - (prefix << nbits); **commands = (uint32_t)(code | (extra << 8)); } else if (copylen < 2118) { const size_t tail = copylen - 70; const size_t nbits = Log2FloorNonZero(tail); const size_t code = nbits + 52; const size_t extra = tail - ((size_t)1 << nbits); **commands = (uint32_t)(code | (extra << 8)); } else { const size_t extra = copylen - 2118; **commands = (uint32_t)(63 | (extra << 8)); } ++(*commands); } static BROTLI_INLINE void EmitCopyLenLastDistance( size_t copylen, uint32_t** commands) { if (copylen < 12) { **commands = (uint32_t)(copylen + 20); ++(*commands); } else if (copylen < 72) { const size_t tail = copylen - 8; const size_t nbits = Log2FloorNonZero(tail) - 1; const size_t prefix = tail >> nbits; const size_t code = (nbits << 1) + prefix + 28; const size_t extra = tail - (prefix << nbits); **commands = (uint32_t)(code | (extra << 8)); ++(*commands); } else if (copylen < 136) { const size_t tail = copylen - 8; const size_t code = (tail >> 5) + 54; const size_t extra = tail & 31; **commands = (uint32_t)(code | (extra << 8)); ++(*commands); **commands = 64; ++(*commands); } else if (copylen < 2120) { const size_t tail = copylen - 72; const size_t nbits = Log2FloorNonZero(tail); const size_t code = nbits + 52; const size_t extra = tail - ((size_t)1 << nbits); **commands = (uint32_t)(code | (extra << 8)); ++(*commands); **commands = 64; ++(*commands); } else { const size_t extra = copylen - 2120; **commands = (uint32_t)(63 | (extra << 8)); ++(*commands); **commands = 64; ++(*commands); } } static BROTLI_INLINE void EmitDistance(uint32_t distance, uint32_t** commands) { uint32_t d = distance + 3; uint32_t nbits = Log2FloorNonZero(d) - 1; const uint32_t prefix = (d >> nbits) & 1; const uint32_t offset = (2 + prefix) << nbits; const uint32_t distcode = 2 * (nbits - 1) + prefix + 80; uint32_t extra = d - offset; **commands = distcode | (extra << 8); ++(*commands); } /* REQUIRES: len <= 1 << 24. */ static void BrotliStoreMetaBlockHeader( size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix, uint8_t* storage) { size_t nibbles = 6; /* ISLAST */ BrotliWriteBits(1, 0, storage_ix, storage); if (len <= (1U << 16)) { nibbles = 4; } else if (len <= (1U << 20)) { nibbles = 5; } BrotliWriteBits(2, nibbles - 4, storage_ix, storage); BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage); /* ISUNCOMPRESSED */ BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage); } static BROTLI_INLINE void CreateCommands(const uint8_t* input, size_t block_size, size_t input_size, const uint8_t* base_ip, int* table, size_t table_bits, size_t min_match, uint8_t** literals, uint32_t** commands) { /* "ip" is the input pointer. */ const uint8_t* ip = input; const size_t shift = 64u - table_bits; const uint8_t* ip_end = input + block_size; /* "next_emit" is a pointer to the first byte that is not covered by a previous copy. Bytes between "next_emit" and the start of the next copy or the end of the input will be emitted as literal bytes. */ const uint8_t* next_emit = input; int last_distance = -1; const size_t kInputMarginBytes = BROTLI_WINDOW_GAP; if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) { /* For the last block, we need to keep a 16 bytes margin so that we can be sure that all distances are at most window size - 16. For all other blocks, we only need to keep a margin of 5 bytes so that we don't go over the block size with a copy. */ const size_t len_limit = BROTLI_MIN(size_t, block_size - min_match, input_size - kInputMarginBytes); const uint8_t* ip_limit = input + len_limit; uint32_t next_hash; for (next_hash = Hash(++ip, shift, min_match); ; ) { /* Step 1: Scan forward in the input looking for a 6-byte-long match. If we get close to exhausting the input then goto emit_remainder. Heuristic match skipping: If 32 bytes are scanned with no matches found, start looking only at every other byte. If 32 more bytes are scanned, look at every third byte, etc.. When a match is found, immediately go back to looking at every byte. This is a small loss (~5% performance, ~0.1% density) for compressible data due to more bookkeeping, but for non-compressible data (such as JPEG) it's a huge win since the compressor quickly "realizes" the data is incompressible and doesn't bother looking for matches everywhere. The "skip" variable keeps track of how many bytes there are since the last match; dividing it by 32 (ie. right-shifting by five) gives the number of bytes to move ahead for each iteration. */ uint32_t skip = 32; const uint8_t* next_ip = ip; const uint8_t* candidate; BROTLI_DCHECK(next_emit < ip); trawl: do { uint32_t hash = next_hash; uint32_t bytes_between_hash_lookups = skip++ >> 5; ip = next_ip; BROTLI_DCHECK(hash == Hash(ip, shift, min_match)); next_ip = ip + bytes_between_hash_lookups; if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) { goto emit_remainder; } next_hash = Hash(next_ip, shift, min_match); candidate = ip - last_distance; if (IsMatch(ip, candidate, min_match)) { if (BROTLI_PREDICT_TRUE(candidate < ip)) { table[hash] = (int)(ip - base_ip); break; } } candidate = base_ip + table[hash]; BROTLI_DCHECK(candidate >= base_ip); BROTLI_DCHECK(candidate < ip); table[hash] = (int)(ip - base_ip); } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate, min_match))); /* Check copy distance. If candidate is not feasible, continue search. Checking is done outside of hot loop to reduce overhead. */ if (ip - candidate > MAX_DISTANCE) goto trawl; /* Step 2: Emit the found match together with the literal bytes from "next_emit", and then see if we can find a next match immediately afterwards. Repeat until we find no match for the input without emitting some literal bytes. */ { /* We have a 6-byte match at ip, and we need to emit bytes in [next_emit, ip). */ const uint8_t* base = ip; size_t matched = min_match + FindMatchLengthWithLimit( candidate + min_match, ip + min_match, (size_t)(ip_end - ip) - min_match); int distance = (int)(base - candidate); /* > 0 */ int insert = (int)(base - next_emit); ip += matched; BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); EmitInsertLen((uint32_t)insert, commands); BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n", (int)(next_emit - base_ip), insert, 2)); memcpy(*literals, next_emit, (size_t)insert); *literals += insert; if (distance == last_distance) { **commands = 64; ++(*commands); } else { EmitDistance((uint32_t)distance, commands); last_distance = distance; } EmitCopyLenLastDistance(matched, commands); BROTLI_LOG(("[CompressFragment] pos = %d distance = %d\n" "[CompressFragment] pos = %d insert = %d copy = %d\n" "[CompressFragment] pos = %d distance = %d\n", (int)(base - base_ip), (int)distance, (int)(base - base_ip) + 2, 0, (int)matched - 2, (int)(base - base_ip) + 2, (int)distance)); next_emit = ip; if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { goto emit_remainder; } { /* We could immediately start working at ip now, but to improve compression we first update "table" with the hashes of some positions within the last copy. */ uint64_t input_bytes; uint32_t cur_hash; uint32_t prev_hash; if (min_match == 4) { input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match); prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 3); prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 2); prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 1); } else { input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 5); prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 4); prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 3); input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 2); prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 1); } candidate = base_ip + table[cur_hash]; table[cur_hash] = (int)(ip - base_ip); } } while (ip - candidate <= MAX_DISTANCE && IsMatch(ip, candidate, min_match)) { /* We have a 6-byte match at ip, and no need to emit any literal bytes prior to ip. */ const uint8_t* base = ip; size_t matched = min_match + FindMatchLengthWithLimit( candidate + min_match, ip + min_match, (size_t)(ip_end - ip) - min_match); ip += matched; last_distance = (int)(base - candidate); /* > 0 */ BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); EmitCopyLen(matched, commands); EmitDistance((uint32_t)last_distance, commands); BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n" "[CompressFragment] pos = %d distance = %d\n", (int)(base - base_ip), 0, (int)matched, (int)(base - base_ip), (int)last_distance)); next_emit = ip; if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { goto emit_remainder; } { /* We could immediately start working at ip now, but to improve compression we first update "table" with the hashes of some positions within the last copy. */ uint64_t input_bytes; uint32_t cur_hash; uint32_t prev_hash; if (min_match == 4) { input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match); prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 3); prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 2); prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 1); } else { input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 5); prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 4); prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 3); input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 2); prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); table[prev_hash] = (int)(ip - base_ip - 1); } candidate = base_ip + table[cur_hash]; table[cur_hash] = (int)(ip - base_ip); } } next_hash = Hash(++ip, shift, min_match); } } emit_remainder: BROTLI_DCHECK(next_emit <= ip_end); /* Emit the remaining bytes as literals. */ if (next_emit < ip_end) { const uint32_t insert = (uint32_t)(ip_end - next_emit); EmitInsertLen(insert, commands); BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n", (int)(next_emit - base_ip), insert, 2)); memcpy(*literals, next_emit, insert); *literals += insert; } } static void StoreCommands(BrotliTwoPassArena* s, const uint8_t* literals, const size_t num_literals, const uint32_t* commands, const size_t num_commands, size_t* storage_ix, uint8_t* storage) { static const uint32_t kNumExtraBits[128] = { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, }; static const uint32_t kInsertOffset[24] = { 0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, 34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594, }; size_t i; memset(s->lit_histo, 0, sizeof(s->lit_histo)); /* TODO(eustas): is that necessary? */ memset(s->cmd_depth, 0, sizeof(s->cmd_depth)); /* TODO(eustas): is that necessary? */ memset(s->cmd_bits, 0, sizeof(s->cmd_bits)); memset(s->cmd_histo, 0, sizeof(s->cmd_histo)); for (i = 0; i < num_literals; ++i) { ++s->lit_histo[literals[i]]; } BrotliBuildAndStoreHuffmanTreeFast(s->tmp_tree, s->lit_histo, num_literals, /* max_bits = */ 8, s->lit_depth, s->lit_bits, storage_ix, storage); for (i = 0; i < num_commands; ++i) { const uint32_t code = commands[i] & 0xFF; BROTLI_DCHECK(code < 128); ++s->cmd_histo[code]; } s->cmd_histo[1] += 1; s->cmd_histo[2] += 1; s->cmd_histo[64] += 1; s->cmd_histo[84] += 1; BuildAndStoreCommandPrefixCode(s, storage_ix, storage); for (i = 0; i < num_commands; ++i) { const uint32_t cmd = commands[i]; const uint32_t code = cmd & 0xFF; const uint32_t extra = cmd >> 8; BROTLI_DCHECK(code < 128); BrotliWriteBits(s->cmd_depth[code], s->cmd_bits[code], storage_ix, storage); BrotliWriteBits(kNumExtraBits[code], extra, storage_ix, storage); if (code < 24) { const uint32_t insert = kInsertOffset[code] + extra; uint32_t j; for (j = 0; j < insert; ++j) { const uint8_t lit = *literals; BrotliWriteBits(s->lit_depth[lit], s->lit_bits[lit], storage_ix, storage); ++literals; } } } } /* Acceptable loss for uncompressible speedup is 2% */ #define MIN_RATIO 0.98 #define SAMPLE_RATE 43 static BROTLI_BOOL ShouldCompress(BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, size_t num_literals) { double corpus_size = (double)input_size; if ((double)num_literals < MIN_RATIO * corpus_size) { return BROTLI_TRUE; } else { const double max_total_bit_cost = corpus_size * 8 * MIN_RATIO / SAMPLE_RATE; size_t i; memset(s->lit_histo, 0, sizeof(s->lit_histo)); for (i = 0; i < input_size; i += SAMPLE_RATE) { ++s->lit_histo[input[i]]; } return TO_BROTLI_BOOL(BitsEntropy(s->lit_histo, 256) < max_total_bit_cost); } } static void RewindBitPosition(const size_t new_storage_ix, size_t* storage_ix, uint8_t* storage) { const size_t bitpos = new_storage_ix & 7; const size_t mask = (1u << bitpos) - 1; storage[new_storage_ix >> 3] &= (uint8_t)mask; *storage_ix = new_storage_ix; } static void EmitUncompressedMetaBlock(const uint8_t* input, size_t input_size, size_t* storage_ix, uint8_t* storage) { BrotliStoreMetaBlockHeader(input_size, 1, storage_ix, storage); *storage_ix = (*storage_ix + 7u) & ~7u; memcpy(&storage[*storage_ix >> 3], input, input_size); *storage_ix += input_size << 3; storage[*storage_ix >> 3] = 0; } static BROTLI_INLINE void BrotliCompressFragmentTwoPassImpl( BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, int* table, size_t table_bits, size_t min_match, size_t* storage_ix, uint8_t* storage) { /* Save the start of the first block for position and distance computations. */ const uint8_t* base_ip = input; BROTLI_UNUSED(is_last); while (input_size > 0) { size_t block_size = BROTLI_MIN(size_t, input_size, kCompressFragmentTwoPassBlockSize); uint32_t* commands = command_buf; uint8_t* literals = literal_buf; size_t num_literals; CreateCommands(input, block_size, input_size, base_ip, table, table_bits, min_match, &literals, &commands); num_literals = (size_t)(literals - literal_buf); if (ShouldCompress(s, input, block_size, num_literals)) { const size_t num_commands = (size_t)(commands - command_buf); BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage); /* No block splits, no contexts. */ BrotliWriteBits(13, 0, storage_ix, storage); StoreCommands(s, literal_buf, num_literals, command_buf, num_commands, storage_ix, storage); } else { /* Since we did not find many backward references and the entropy of the data is close to 8 bits, we can simply emit an uncompressed block. This makes compression speed of uncompressible data about 3x faster. */ EmitUncompressedMetaBlock(input, block_size, storage_ix, storage); } input += block_size; input_size -= block_size; } } #define FOR_TABLE_BITS_(X) \ X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) #define BAKE_METHOD_PARAM_(B) \ static BROTLI_NOINLINE void BrotliCompressFragmentTwoPassImpl ## B( \ BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, \ BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, \ int* table, size_t* storage_ix, uint8_t* storage) { \ size_t min_match = (B <= 15) ? 4 : 6; \ BrotliCompressFragmentTwoPassImpl(s, input, input_size, is_last, command_buf,\ literal_buf, table, B, min_match, storage_ix, storage); \ } FOR_TABLE_BITS_(BAKE_METHOD_PARAM_) #undef BAKE_METHOD_PARAM_ void BrotliCompressFragmentTwoPass( BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, int* table, size_t table_size, size_t* storage_ix, uint8_t* storage) { const size_t initial_storage_ix = *storage_ix; const size_t table_bits = Log2FloorNonZero(table_size); switch (table_bits) { #define CASE_(B) \ case B: \ BrotliCompressFragmentTwoPassImpl ## B( \ s, input, input_size, is_last, command_buf, \ literal_buf, table, storage_ix, storage); \ break; FOR_TABLE_BITS_(CASE_) #undef CASE_ default: BROTLI_DCHECK(0); break; } /* If output is larger than single uncompressed block, rewrite it. */ if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) { RewindBitPosition(initial_storage_ix, storage_ix, storage); EmitUncompressedMetaBlock(input, input_size, storage_ix, storage); } if (is_last) { BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ *storage_ix = (*storage_ix + 7u) & ~7u; } } #undef FOR_TABLE_BITS_ #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/compress_fragment_two_pass.h000066400000000000000000000054771501401750600236530ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function for fast encoding of an input fragment, independently from the input history. This function uses two-pass processing: in the first pass we save the found backward matches and literal bytes into a buffer, and in the second pass we emit them into the bit stream using prefix codes built based on the actual command and literal byte histograms. */ #ifndef BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ #define BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ #include #include "../common/constants.h" #include "../common/platform.h" #include "entropy_encode.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* TODO(eustas): turn to macro. */ static const size_t kCompressFragmentTwoPassBlockSize = 1 << 17; typedef struct BrotliTwoPassArena { uint32_t lit_histo[256]; uint8_t lit_depth[256]; uint16_t lit_bits[256]; uint32_t cmd_histo[128]; uint8_t cmd_depth[128]; uint16_t cmd_bits[128]; /* BuildAndStoreCommandPrefixCode */ HuffmanTree tmp_tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1]; uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS]; uint16_t tmp_bits[64]; } BrotliTwoPassArena; /* Compresses "input" string to the "*storage" buffer as one or more complete meta-blocks, and updates the "*storage_ix" bit position. If "is_last" is 1, emits an additional empty last meta-block. REQUIRES: "input_size" is greater than zero, or "is_last" is 1. REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24). REQUIRES: "command_buf" and "literal_buf" point to at least kCompressFragmentTwoPassBlockSize long arrays. REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. REQUIRES: "table_size" is a power of two OUTPUT: maximal copy distance <= |input_size| OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */ BROTLI_INTERNAL void BrotliCompressFragmentTwoPass(BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, int* table, size_t table_size, size_t* storage_ix, uint8_t* storage); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ */ dvisvgm-3.5/libs/brotli/enc/dictionary_hash.c000066400000000000000000004373221501401750600213570ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Hash table on the 4-byte prefixes of static dictionary words. */ #include "../common/platform.h" #include "dictionary_hash.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* GENERATED CODE START */ BROTLI_INTERNAL const uint16_t kStaticDictionaryHashWords[32768] = { 1002,0,0,0,0,0,0,0,0,683,0,0,0,0,0,0,0,1265,0,0,0,0,0,1431,0,0,0,0,0,0,40,0,0,0, 0,155,8,741,0,624,0,0,0,0,0,0,0,0,0,0,0,0,66,503,0,0,0,451,0,0,0,0,0,0,0,835,70, 0,0,539,0,0,0,0,0,0,0,0,0,113,0,0,0,0,718,0,0,0,0,0,0,520,0,1070,0,0,0,0,0,1515, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,610,0,0,750,0,0,0,307,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,964,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,999,0,0,0,0,0,0,0,0, 645,75,0,649,52,282,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1621,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,211,225,0,0,687,718,0,0,110,0,58,0,0,0,0,0,0,345,0,0,301,0,0, 0,203,0,0,1154,674,1949,0,0,0,0,0,0,0,0,0,259,0,0,0,0,0,0,0,1275,0,0,0,1231,254, 0,0,0,0,0,0,0,277,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,0,0,800,0,0,0,29, 116,100,490,0,0,0,0,0,1641,0,543,0,0,0,0,41,181,0,657,0,0,202,25,0,0,0,0,0,0,0, 0,0,0,423,0,0,0,113,0,0,0,927,963,0,976,0,206,0,0,0,0,0,0,0,0,0,2002,0,0,0,0,0, 0,0,0,0,0,0,696,0,1170,0,0,0,0,226,13,0,769,678,551,0,0,0,0,0,0,57,0,0,0,10,188, 0,0,0,624,0,0,0,0,0,0,0,0,0,1941,130,0,0,0,0,378,269,0,0,528,0,1146,0,0,0,1105, 0,1616,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,656,0,1940,0,0,0,0,0,173,0,0,0,0,0,0,0,0,0, 0,0,457,342,810,0,0,0,0,620,0,0,0,0,0,0,0,967,95,447,406,0,0,0,477,0,1268,944, 1941,0,0,0,629,0,0,0,0,0,375,0,0,0,1636,0,0,0,0,774,0,1,1034,0,0,0,0,0,824,0,0, 0,0,0,118,0,0,560,296,0,0,0,0,0,0,0,0,1009,894,0,0,0,0,0,0,0,0,0,0,0,0,0,1474, 366,0,0,0,0,0,0,0,0,0,79,1723,0,0,200,0,0,0,0,0,0,0,0,1759,372,0,16,0,943,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,900,1839,707,30,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,2004,0,0,10,115,0,50,0,0,0,0,0,0,0,0,0,0,520,1,0,738,98,482,0,0,0,0, 0,0,0,0,0,0,701,2,0,0,0,0,0,0,0,0,557,0,0,0,0,0,0,0,0,0,347,0,0,0,0,572,0,0,0,0, 0,0,0,0,0,832,0,0,797,809,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,861,0,0,294,0,0,0,109, 0,0,0,0,0,0,0,0,1187,290,266,0,0,0,0,49,50,748,0,0,466,399,0,0,0,0,0,0,0,378,0, 519,0,0,0,0,0,0,0,0,0,0,0,0,667,351,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,180, 0,0,869,0,0,0,0,0,0,0,260,0,0,0,0,0,0,0,0,0,0,523,36,0,0,587,510,809,29,260,0,0, 0,0,0,0,0,0,570,0,565,0,1464,0,0,0,0,0,0,10,0,0,787,399,380,200,0,0,0,0,516,0, 844,887,0,0,0,0,0,0,0,44,0,0,0,305,1655,0,0,0,0,0,0,0,0,0,0,0,0,0,0,786,10,0,0, 0,0,0,0,0,0,0,2031,0,0,0,0,0,684,0,0,0,0,0,1480,0,0,0,27,0,0,0,395,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,813,511,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,206, 496,0,0,0,0,0,909,0,891,0,0,0,0,0,0,0,0,0,687,0,0,0,1342,0,0,0,0,0,0,0,0,0,0, 160,41,0,0,0,0,0,0,0,0,0,0,0,1718,778,0,0,0,0,0,0,0,0,0,0,1610,0,0,0,0,0,115,0, 0,0,0,314,294,0,0,0,983,178,193,0,0,0,0,0,0,0,0,0,174,0,0,0,0,0,0,0,0,0,0,848, 1796,0,0,0,0,0,0,221,0,687,1660,0,0,0,0,262,0,0,179,0,0,0,0,0,66,0,773,0,352,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,152,0,0,1197,0,0,0,0,0,0,0,0,0,0,0,0,560,0,0, 564,0,0,0,797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,819,0,0,0,0,0,0,0,0,719,544, 637,5,0,0,0,0,0,0,0,0,0,0,0,101,0,1441,0,0,0,893,0,0,0,0,0,0,0,0,0,238,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1296,0,0,969,1729,314,60,0,0,0,0,0,1144,0,1147,0,0,0,0,0, 0,0,0,0,0,437,1853,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,828,0,176,0,0,0,0,0,0,434,39,0, 0,0,0,0,159,0,0,0,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,270,0,0,0,0,801,556,0,0, 0,0,0,0,0,416,19,197,369,0,0,0,0,0,0,0,0,0,28,34,0,757,0,0,898,1553,0,721,0,0,0, 0,1012,0,0,0,0,1102,0,898,183,0,0,0,0,0,0,0,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,277,0,0,0,435,0,0,0,0,0,1311,0,0,0,0, 0,0,211,437,0,0,0,28,0,0,750,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2012,0,702, 0,808,0,0,0,0,739,166,0,0,0,0,0,0,719,170,500,0,0,0,0,0,0,0,0,1500,327,0,0,450, 0,0,0,1318,0,0,0,1602,0,0,331,754,0,0,0,0,0,1368,0,0,557,0,0,0,799,850,0,0,0,0, 0,0,0,0,908,0,0,0,0,0,19,62,459,0,0,0,0,0,0,0,0,0,0,0,0,1802,0,0,0,0,0,0,0,0,0, 1397,0,0,0,0,120,238,0,0,0,0,0,0,0,0,0,0,0,1324,0,0,0,0,0,0,0,0,602,201,0,0,164, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,615,0,0,0,0,0,0,0,0,0,0,0,0,0,1243,0,0,0,0,968,0,0, 0,0,0,0,882,0,0,0,907,329,100,0,0,0,0,0,0,0,0,0,0,0,176,26,9,0,0,265,256,0,0,0, 0,0,0,0,0,0,643,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,610,0,0,0,0,973,2001,0, 0,0,0,0,0,522,0,0,0,0,0,0,0,0,0,0,0,553,0,0,0,0,0,0,1582,0,1578,0,0,0,0,0,0,0,0, 0,0,0,795,0,0,0,432,0,0,0,0,0,0,84,126,0,0,0,0,790,0,377,64,0,1529,0,0,0,0,530, 1857,539,1104,0,0,0,0,0,0,0,0,0,0,0,0,977,0,0,0,34,0,0,0,0,0,0,0,0,0,0,0,24,26, 0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,183,379,0,0,0,0,0,0,0,792, 0,0,0,0,0,0,0,0,0,1920,0,0,0,0,0,0,0,0,0,771,0,0,0,1979,0,901,254,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,0,0,0,0,0,440,37,0, 508,0,0,0,513,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,533,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,752,920,0,1048,0,153,0, 0,391,0,0,1952,0,0,0,0,0,0,0,0,0,0,126,0,0,0,0,640,0,483,69,1616,0,0,0,0,0,734, 0,0,0,0,0,0,480,0,495,0,472,0,0,0,0,0,0,0,0,874,229,0,0,0,0,948,0,0,0,0,0,0,0,0, 1009,748,0,555,0,0,0,0,0,0,193,0,653,0,0,0,0,0,0,0,0,0,0,984,0,0,0,172,0,0,0,0, 0,0,0,0,83,1568,0,0,384,0,0,0,0,0,0,0,164,880,0,0,0,0,0,0,0,0,0,0,0,367,121,0,0, 828,0,0,0,0,0,0,0,1541,0,0,0,0,0,0,0,343,0,0,0,0,0,0,0,0,561,57,0,0,0,0,0,0,0, 926,0,0,0,0,827,0,194,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0, 0,0,0,896,1249,0,0,0,0,0,1614,0,0,0,860,0,0,0,0,0,0,0,0,964,102,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,569,0,0,0,0,795,2045,0,0,0, 0,0,0,104,52,0,0,0,0,0,604,0,0,0,0,779,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0, 494,0,677,0,0,0,0,0,0,0,508,0,0,0,0,0,0,0,0,0,1014,0,957,0,0,630,310,0,0,0,570, 0,0,449,0,64,537,0,0,0,0,0,0,0,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,702,1650,49,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,1279,0,0,0,0,0,0,0,896,0,0, 178,0,0,0,0,0,0,0,0,0,0,0,0,0,808,695,0,0,0,0,539,1117,0,0,0,0,0,0,0,0,257,0, 1003,0,0,0,1,448,0,516,0,0,960,0,125,4,0,1268,30,748,0,0,852,0,0,0,6,0,0,848, 236,1385,862,1811,0,0,0,0,698,803,0,0,0,0,0,0,0,610,992,0,0,878,0,1847,0,0,0,0, 0,0,0,383,0,1404,0,0,0,0,986,0,347,0,0,0,0,0,0,0,0,0,0,0,592,572,0,1411,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,606,0,0,0,0,0,0, 0,0,0,0,0,0,0,1829,0,0,0,0,0,0,0,0,0,0,0,0,700,748,0,0,0,0,0,0,365,0,0,127,0,0, 83,198,0,0,0,0,0,0,864,55,0,0,0,0,726,1752,0,0,0,0,0,0,0,0,0,0,0,0,0,1066,0,764, 0,0,0,0,683,0,550,309,0,0,874,1212,0,0,0,1364,0,986,381,723,0,0,0,1573,0,0,0,0, 0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1559,0,0,0,0,493,133,0,0,0,0,148, 119,0,0,0,0,0,0,537,14,541,0,635,126,0,0,0,495,0,0,0,0,861,998,1009,0,0,0,0,0,0, 0,359,368,0,0,0,0,304,1577,0,0,0,0,0,1107,0,0,0,0,0,929,0,0,0,1142,0,0,0,0,289, 175,0,432,0,219,0,0,0,0,0,785,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,0,0,0, 931,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1323,0,0,0,0,290,0,559,1751,127,0,0,0, 934,1167,0,963,0,260,0,0,0,573,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 580,1689,0,0,0,0,0,0,0,0,0,1164,0,0,982,1922,0,63,0,0,0,0,0,793,0,0,0,0,0,0,0,0, 0,0,0,0,0,67,790,0,0,0,0,0,0,0,0,0,0,391,443,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,271,0,0,0,0,0,0,0,0,0,0,0,1140,0,0,0,0,340,300,0,897,0,0,0,0,0,0, 0,0,0,0,890,0,0,0,0,818,321,53,0,0,0,0,0,0,0,0,0,468,0,243,0,870,0,0,0,1765,121, 0,0,0,180,518,0,822,419,634,0,0,0,0,0,0,0,0,0,898,0,0,0,0,454,36,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,0,0,0,0,0,0,1326,0,104,0,0,0,0,0,0,0, 0,0,260,0,0,0,0,0,0,0,0,0,0,0,0,542,45,0,0,263,1516,42,0,0,0,0,0,468,0,1005,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,288,87,0,0,0,0,0,0,0,0,502,988,133,0,0,0,0,0,0, 141,0,0,872,1842,0,0,0,0,0,0,0,0,261,619,0,0,0,0,189,246,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,678,0,0,0,0,0,0,0,0,0,0,0,0,285,35,0,517,0,0,0,0,0,0,0,0,0,0, 540,214,667,0,74,0,0,125,0,0,0,0,0,761,131,0,0,0,0,0,0,0,0,0,0,0,0,0,333,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1338,94,0,0,0,0,0,0,0,0,0,0,0,0,449,0,646,103, 86,641,2028,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,869,87,277,117,39,0,0,0,0,0,0,0,0,938, 297,0,0,0,0,558,464,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1608,0, 0,0,0,0,0,0,1429,0,0,733,1010,0,0,338,1656,0,0,0,1038,979,2010,0,0,0,0,0,0,0, 1005,0,0,121,0,0,0,219,20,0,0,0,0,0,0,872,1440,0,0,0,683,0,1070,0,0,522,0,0,0,0, 439,669,0,0,0,0,0,0,0,0,1245,0,0,0,0,0,1218,0,0,547,233,0,0,0,0,0,0,0,0,0,482,0, 0,0,0,0,0,0,886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,795,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,371,0,0,0,0,0,0,0,0,0,0,0,0,0,622,0,625,0,0,0,339,29,0,0,338,0,0,0, 0,130,0,0,0,0,0,0,0,0,0,307,0,0,0,0,0,0,0,0,0,0,2044,0,0,0,0,0,0,0,0,308,770,0, 0,0,0,0,1266,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,690,739,0,0, 0,0,0,0,0,990,0,0,0,1831,0,0,0,0,0,0,0,0,0,0,0,0,0,613,0,0,0,0,0,0,0,0,0,0,0,0, 0,763,0,878,0,0,0,977,0,100,0,0,0,0,0,0,0,0,0,463,0,0,0,0,623,318,0,0,296,463, 137,0,0,454,0,0,0,1527,58,0,0,0,0,0,0,0,18,48,0,0,0,0,0,729,0,0,0,442,0,0,0,0, 40,449,0,853,0,0,0,0,0,0,227,0,0,0,0,0,0,1491,0,0,0,0,0,0,0,0,0,0,161,55,0,450, 0,1174,62,0,207,0,0,0,0,0,0,0,0,869,0,0,0,0,80,213,0,0,0,0,0,0,0,0,0,0,354,820, 0,0,747,0,0,0,954,0,0,1073,0,556,0,0,0,692,0,191,0,804,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,831,162,0,0,35,0,0,0,0,0,0,0,0,1235,0,0,0,0,0,1234,0,0, 0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,149,0,0,0,902,204,0,0,833,0,287,366,0,0,0,0,0, 0,992,2020,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,784,0,0,567, 630,0,0,0,539,0,0,27,0,0,0,0,0,0,0,0,0,0,755,0,0,0,0,0,0,0,0,0,0,0,0,814,0,0,0, 0,0,0,0,0,0,0,0,0,0,987,0,0,255,761,194,0,1086,0,0,0,0,0,0,1016,0,0,1396,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,562,271,913,0,0,0,0,0,0,0,0,320,153,45,475,0,0, 0,0,0,0,0,713,0,327,0,0,0,0,0,0,604,552,3,359,0,0,0,0,853,80,0,0,0,0,0,0,0,2016, 6,887,0,0,0,0,975,0,961,0,0,0,0,0,916,1891,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,100,101,390,708,0,0,0,587,983,512,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,851,0,0,0, 0,0,498,140,217,0,0,0,1448,0,0,0,0,0,0,0,0,0,905,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 643,105,0,792,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,0,535,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1748,0,0,0,0,0,754,0,0,0,0,0,0,0,0,0,0,0,0,91,0,0,1565,0,91,792, 939,3,370,0,0,0,0,95,0,0,0,0,551,7,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1150,0, 0,0,0,0,0,0,0,0,0,0,0,0,671,0,0,0,0,0,888,368,149,0,0,105,1134,0,983,0,0,458,31, 0,643,0,0,0,312,0,740,0,0,0,1642,0,0,0,0,0,0,0,236,0,0,0,0,0,0,0,59,68,0,0,0,0, 0,867,795,0,0,0,0,970,1977,0,0,0,0,0,0,0,1148,0,775,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,970,0,0,0,0,0,0,0,0,0,665,71,0,0,0,0,827,0,0,0,0,0,0,0,0,0, 0,479,0,0,0,0,0,0,0,0,99,607,0,0,0,0,0,0,0,1960,0,0,0,793,0,0,871,41,0,0,241,94, 0,0,0,0,209,0,0,1497,0,0,0,0,0,0,0,0,0,98,0,0,0,463,0,0,0,0,291,0,0,0,0,0,0,0,0, 0,0,984,0,0,0,0,0,205,0,0,0,0,0,0,205,42,0,801,0,0,0,0,0,635,0,0,533,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,371,0,1282,0,0,0,825,0,0,0,0,0,0,0,0,0,357,879,467,0,317,0,0, 0,0,0,0,0,924,0,0,0,0,849,1795,0,0,0,0,895,1799,43,0,0,0,0,0,0,0,0,0,0,1820,0,0, 0,0,0,0,0,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,0,493,0,174,417,0,0, 0,0,0,583,733,0,0,0,0,0,0,481,215,0,0,0,0,477,0,0,0,0,0,0,0,0,308,0,0,0,0,0,0,0, 0,297,126,0,0,361,1551,0,0,0,0,0,0,871,1807,0,0,0,0,0,1307,0,685,0,0,0,0,0,0,0, 797,0,858,0,565,0,0,0,0,0,0,0,0,0,0,0,0,434,252,826,0,0,0,0,0,0,791,0,0,0,0,509, 231,178,601,0,0,0,0,0,0,0,0,43,1591,0,0,0,0,0,1683,0,0,0,0,45,0,0,0,0,0,0,0,0,0, 0,1120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,494,0,398,0,0,0,1030,0,0,0,0,0,0, 168,0,0,0,0,0,0,0,0,0,0,973,0,642,0,0,0,0,0,0,0,0,0,1615,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,378,594,0,1093,0,679,112,0,0,0,0,1492,540,1374,714, 1486,0,0,0,0,825,1511,0,0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,736,143,0,700,0,1540,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1557,0,0,0,860,990,0,0,0,807,0,0,0,0,0,131, 515,0,646,0,0,0,0,117,728,508,121,0,0,0,0,0,0,357,0,0,0,0,0,0,237,0,0,0,0,0,0,0, 0,0,1784,0,0,0,0,0,0,0,0,0,0,0,713,348,1536,0,738,0,0,0,0,0,0,0,434,0,0,0,0,0,0, 366,1877,39,0,0,0,0,0,0,580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,873,0,0,0,0,171,0,625, 550,107,343,943,0,0,0,0,0,0,0,768,0,0,0,0,0,0,0,799,0,0,0,894,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1673,0,0,0,0,0,0,0,0,0,0,0,1052,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 272,0,441,0,0,3,9,0,0,0,1182,0,1346,0,0,0,0,0,0,0,0,682,0,0,1004,24,0,0,968,0,0, 0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,0,0,0,578, 474,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,530,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,556,0,0,0,0,0,0,16,1317,0,0,97,0,0,0,703,0,0,0,0,0,0,0,0,892,0,0,0,1571,0,0, 426,186,0,1101,0,0,0,0,0,0,0,0,937,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,644,291, 0,0,0,0,749,0,162,0,0,381,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,762,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,628,21,0,0,0,0,0,0,0,0,919,0,0,0,0,0,0,0,0,0, 633,0,0,0,0,332,0,0,0,0,0,0,0,0,0,1489,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,832,398,0,645,0,0,0,13,0,0,0,0,0,0,0,0,0,0,20,0,800,0,0,0,0,0,0,0,0,0, 0,0,0,0,1993,0,0,0,0,769,0,0,0,665,0,0,0,0,0,0,0,0,0,0,1426,0,0,0,0,60,0,0,0, 641,1874,0,644,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1757,0,0,0,0,0,937,0,1652,0,654,0, 0,0,0,0,0,0,527,0,0,0,0,0,0,0,0,0,0,0,0,0,226,0,0,0,0,0,1486,0,0,0,0,0,0,0,0,0, 0,0,325,0,0,0,0,0,0,0,1345,0,0,91,0,404,0,0,0,0,0,0,0,0,0,0,0,0,973,0,0,0,0,0,0, 0,1176,0,549,0,0,0,0,0,0,0,0,0,0,976,0,0,0,0,0,21,0,0,0,0,0,51,0,0,0,0,314,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,198,6,0,1093,0,0,0,0,0,0,0,0,0, 0,0,0,0,1776,0,0,0,0,0,1528,0,419,0,0,0,0,0,0,0,0,76,138,0,0,0,0,638,29,0,0,0,0, 0,0,0,1418,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1710,0,0,0,0,0, 0,0,0,0,0,0,0,532,23,0,0,0,0,0,0,0,862,0,0,946,592,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,70,0,0,0,0,0,0,0,0,0,812,0,0,0,76,0,0,988,0,442,0,0,0,896,0,0,0,0,0,0, 483,0,0,0,0,1709,0,0,0,0,0,0,119,0,0,0,117,0,309,0,0,0,0,0,596,976,0,0,0,0,0,0, 0,0,0,0,0,768,0,0,0,0,0,0,0,0,0,518,0,0,0,0,0,0,0,0,0,0,0,0,0,0,863,0,0,0,24, 145,1020,0,0,1984,0,0,0,0,0,0,0,658,0,0,0,0,0,0,0,0,0,0,106,1827,0,1010,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,582,87,0,0,0,0,0,0,0,267,0,0,0,703,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,496,0,0,0,0,1121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,561,0,0,0,0,0, 0,0,760,0,0,154,0,0,0,255,0,419,323,0,0,0,0,0,368,0,0,0,0,0,0,0,0,0,0,522,0,0,0, 0,0,0,0,551,562,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,0,0,0,0, 0,0,0,284,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,958,0,0,594,0,0,0,0,0,0,6,479,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,820,1641,0,1556,0,0,0,0,0,0,0,302,0,0, 0,0,0,148,0,0,676,0,0,0,0,0,0,1674,0,0,0,0,0,0,178,0,0,0,0,0,0,0,94,389,0,0,0,0, 91,8,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,747,0,0,0,0,0,0,0,1746,0,0,0,0, 0,24,0,1352,158,1530,0,0,718,130,280,1401,0,0,0,0,0,1946,8,0,0,0,0,1607,0,0,0,0, 0,0,882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,417,0,0,0,1597,633,433,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,234,0,0,0,0,0,0,0,0,680,1950,0,0,0,0,249,5,0,0,0, 0,0,0,0,0,0,1216,0,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,180,0,0,0,0,0,0,0,1002, 0,0,0,0,0,0,0,0,0,0,0,0,0,931,0,0,0,0,0,0,0,0,747,943,0,1837,0,0,0,0,0,0,0,641, 0,0,0,0,280,0,0,0,5,0,0,0,0,0,72,545,0,0,0,0,0,0,0,0,0,742,0,0,254,151,872,0,0, 0,0,0,0,0,0,0,0,0,0,921,0,0,517,833,0,1680,0,0,436,251,584,0,0,0,0,0,0,0,0,0,0, 0,24,500,0,0,0,0,0,0,0,0,195,1775,514,389,0,0,0,0,0,0,0,743,0,0,0,0,0,0,292,0,0, 0,227,1283,774,1805,0,0,0,0,0,0,0,0,0,0,119,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913, 1910,0,0,0,1826,490,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1162,700,30, 0,0,0,721,839,0,0,0,617,0,0,0,0,0,0,0,0,0,169,428,0,0,0,0,0,1648,637,1205,0,0,0, 1596,0,0,4,266,0,0,0,0,0,0,0,0,0,0,0,862,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0, 0,279,157,391,604,0,0,713,945,877,973,0,0,0,0,0,0,0,0,0,0,0,0,0,0,859,567,628, 1846,0,0,0,0,0,0,0,0,0,762,0,0,191,0,0,0,0,298,0,0,767,909,0,0,0,0,0,0,0,795,0, 0,301,0,0,1970,0,0,0,0,0,0,0,0,0,1236,0,0,0,0,0,0,644,369,15,0,160,71,0,0,0,0,0, 1447,0,0,0,0,0,0,0,0,735,1255,76,0,0,0,0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,0, 841,0,0,0,0,0,0,0,0,0,0,836,0,0,0,0,0,1622,0,0,735,0,0,0,0,1601,804,1390,394,0, 0,0,0,0,0,96,0,289,0,0,35,688,0,0,0,667,0,513,0,0,0,0,0,0,0,2034,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,704,0,1524,0,1078,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,306, 0,0,0,0,0,0,0,431,0,1196,0,0,54,0,15,1448,0,1418,0,0,0,0,0,0,0,0,0,907,0,0,0,0, 0,0,194,1767,0,0,0,0,0,840,0,900,0,0,0,0,0,0,0,0,0,0,0,1436,0,0,0,0,642,1560,0, 0,0,0,0,0,94,386,0,0,0,0,0,0,0,0,0,0,830,416,0,0,20,731,0,0,0,0,0,0,0,0,697,0,0, 662,0,0,0,0,0,0,0,0,0,861,0,0,0,0,0,0,0,871,671,864,0,928,7,0,332,0,0,0,0,1055, 0,0,0,0,0,0,986,0,0,0,0,0,44,76,0,0,0,0,0,0,0,0,0,0,300,0,0,0,0,0,0,0,175,518, 831,1108,0,0,0,836,0,1852,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,843,1804,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,246,0,0,0,610,202,0,0,36,0,0,0,240,654,13,0,0,0,0,0,0,0, 0,391,0,403,0,0,0,0,0,0,0,0,0,0,75,0,366,815,0,0,631,0,0,0,0,0,0,0,0,345,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,0,0,0,0,0,0,0,0,0,673,35,662,0,287,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,5,34,0,0,0,0,0,0,0,0,151,0,427,0,0,382,0,0,0,329,0,0,279,0,0,0, 0,0,0,0,0,0,0,906,0,0,366,843,0,1443,0,1372,992,0,36,123,0,649,0,0,0,0,0,767,0, 1018,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,995,0,0,0,0,0,0,0,72,368,0,0,1345,0,0,0, 589,0,0,0,0,0,0,0,0,0,1988,0,0,220,541,0,0,0,686,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,32,196,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0,0,0,1452,0, 0,0,616,0,0,0,0,0,0,0,0,0,1229,0,0,0,0,0,0,0,0,0,0,667,120,0,0,0,0,0,0,0,1146,0, 0,0,0,0,0,0,0,0,0,0,352,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,935,0,1050,0, 147,88,0,0,923,0,0,0,0,0,934,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,341,222,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0, 637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1159,0,0,0,847,0,0,0,0,0,0,683,0,867,944,0,0, 0,0,0,1809,0,0,0,0,0,0,0,0,0,0,395,170,0,0,0,0,0,0,0,0,0,0,618,535,0,1625,0,0,0, 0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,778,0,0,0,0,0,46,0,2032,0,0,37, 1458,0,938,363,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,889,0,0,0,0,0,0,0, 0,0,0,0,462,0,0,0,0,525,0,0,23,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0, 0,498,725,0,0,0,0,7,0,0,0,0,773,0,0,0,164,0,0,0,0,0,0,0,0,936,583,659,1462,0, 220,0,0,0,0,803,0,0,544,119,0,0,0,0,0,0,0,0,0,0,0,181,176,0,1192,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1878,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,0,0,0, 944,0,0,0,0,0,0,0,273,0,0,0,0,0,855,0,0,0,0,5,127,0,0,0,0,0,0,0,0,752,230,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,162,0,654,48,156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197, 0,0,0,0,0,0,0,963,0,0,0,0,0,0,0,0,0,0,858,0,0,0,0,0,0,0,0,0,0,676,1978,0,0,102, 972,0,0,0,0,0,0,0,361,0,461,0,0,0,472,0,0,0,0,0,0,0,0,0,0,0,0,0,0,747,905,0,0,0, 155,0,0,0,0,0,0,0,0,0,0,319,163,0,0,0,0,0,0,0,0,0,848,0,0,36,631,0,0,0,0,0,1769, 0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,555,247,0,0, 996,0,0,189,0,0,0,0,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,0,0,0,526,746,0,0,345,0,0,0, 1017,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,651,428,0,0,0,1162,230,327,546,792,0,0,0, 1203,0,0,0,0,0,0,0,0,0,672,189,0,0,0,0,0,0,99,0,0,0,298,0,0,0,0,0,0,555,397,0,0, 0,0,0,1157,0,0,0,0,0,0,0,0,0,0,398,1523,0,366,0,0,787,0,0,0,282,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,157,0,941,0,0,0,0,0,1336,0,0,116,0,0,0,0,0,0,787,0,0,0,0,0,0,0,0,0, 0,170,160,0,1815,0,0,0,0,0,866,0,0,0,0,0,0,0,0,0,689,0,0,0,0,820,0,498,108,0,0, 0,1119,0,0,0,244,609,1005,0,581,0,0,0,0,0,895,0,0,0,1898,0,0,0,0,0,926,0,0,0,0, 0,0,0,0,0,0,0,0,0,538,496,294,301,0,0,0,18,0,0,757,0,0,0,0,0,1263,0,820,0,722,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2028,0,0,0,0,124,1875,0,0,0,881,0,0,0,1348, 0,0,0,0,0,0,0,911,0,954,0,0,0,0,414,0,0,0,0,517,0,0,0,0,0,816,0,0,0,0,0,0,0,0, 713,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,593,150,0,0,0,0, 0,553,0,0,0,0,0,0,0,0,0,0,108,0,0,0,0,420,0,0,0,0,0,0,0,0,0,0,0,1777,0,0,55,493, 0,0,81,0,321,980,0,0,0,0,0,0,0,0,0,0,0,0,0,0,362,112,0,74,0,0,0,0,0,0,0,625,0,0, 0,0,0,0,377,16,0,0,61,281,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,1031,0,0,0,0,0,0,51,0, 0,0,0,0,0,0,211,309,15,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,789,173,0,439,9,648, 0,0,294,0,0,0,0,0,0,0,374,8,0,1099,0,0,0,0,0,0,0,575,0,0,0,518,0,0,0,702,0,0,0, 0,0,0,87,0,0,0,438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,464,122,0,0,0,1802,0,0,0,0, 0,0,499,0,0,0,87,476,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,840,283,0,0,0,0,1620,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,609,1160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600, 323,372,0,0,0,0,471,722,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0, 477,1304,0,1774,0,0,88,0,438,12,0,0,0,0,0,0,0,0,671,997,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,639,22,0,0,782,681,0,0,0,0,0,0,0,0,0,0,1013,664,0,942,0,1349,0,0,0,0,0,0,0, 0,0,0,0,0,356,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,289,0,1975, 109,450,0,0,0,0,0,0,0,0,0,0,705,0,0,664,0,0,0,0,0,0,0,1238,0,0,318,0,0,0,0,0,0, 0,0,0,0,0,0,0,960,1872,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,0,0,0,0,0,0,0,0,0,239, 777,0,26,0,0,0,0,0,0,0,0,0,0,0,0,375,414,0,17,0,0,0,1350,0,955,0,0,0,0,0,0,0,0, 887,960,0,0,0,0,0,0,0,0,0,0,708,710,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,919,0,0,0, 0,502,280,7,45,0,0,0,0,777,0,0,0,0,410,0,1110,0,0,0,0,0,0,414,341,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,787,0,0,0,436,0,0,0,0,0,0,0,1707,613,377,96,0,0,0,0,451, 0,0,0,0,0,0,0,0,0,0,0,0,0,680,0,483,916,0,0,0,0,0,0,937,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,739,0,0,0,0,0,0,0,0,82,0,0,663,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,128,0,0,0,0,0,0,0,0,1087,0,0,0,0,0,0,0,503,0,0,0,0,0,0,9,113,104,324,0,460,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,935,702,434,485,1014,949,423,0,900, 0,0,0,0,0,0,0,2018,574,0,0,0,0,0,0,0,0,0,0,0,0,1206,0,0,0,0,0,0,0,0,38,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,1022,0,0,0,0,143,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,2029,0,0,0,0,0,0,0,0,0,0,0,0,523,0,0,0,0,0,0,625,0,0,425,37,0,0,0,1943,0,0,0, 0,0,765,0,0,0,0,0,0,0,0,0,0,551,0,0,0,0,0,0,0,0,0,0,0,0,168,0,0,1010,0,0,1994,0, 0,0,91,0,0,0,0,532,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1884,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,240,15,0,0,0,1227,0,1534,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0, 0,0,0,0,0,0,0,0,0,0,0,655,562,395,0,0,0,501,1019,0,0,0,0,509,267,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1099,0,0,0,0,0,0,948,0,0,0,0,0,0,0, 462,114,0,0,258,404,0,1717,0,0,0,0,82,1061,0,724,0,0,0,0,0,1133,0,0,0,0,0,0, 1021,841,0,1021,0,0,0,0,0,0,0,0,0,0,488,373,37,0,0,0,0,564,0,0,0,0,0,513,0,0,0, 825,0,0,899,0,0,778,0,0,12,1417,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,545,0,5, 0,0,0,0,0,0,0,192,0,0,763,0,0,0,0,0,0,0,755,759,0,0,0,0,0,0,0,0,0,370,0,1237,0, 0,0,0,0,0,298,87,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0, 0,0,0,0,814,991,0,757,57,0,0,0,0,0,0,0,0,0,540,0,0,0,0,608,0,0,0,0,0,0,0,0,1014, 0,0,0,902,0,0,0,0,553,1668,0,0,0,0,0,0,0,0,0,559,60,0,0,0,0,0,511,0,0,675,0,0, 156,0,0,0,0,0,0,709,0,698,0,0,0,1745,0,0,0,0,0,0,0,0,0,714,0,0,0,0,0,0,0,0,206, 8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,776,0,0,0,0,0,0,0,0,0,1272,0,0, 0,0,0,1059,0,0,0,0,0,0,406,0,0,0,0,0,0,0,0,0,0,947,0,0,0,0,0,0,168,0,0,0,0,0,0, 870,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,554,0,0,0,0,784,908,0,0,0,0,0,0, 0,396,358,0,0,0,0,0,0,0,0,2,228,0,0,0,0,0,0,0,0,0,0,0,845,14,0,716,1820,594,0, 81,1428,0,161,0,782,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,998,0, 0,0,0,0,0,0,0,0,0,0,0,1043,0,1496,0,0,0,0,0,0,0,0,781,0,0,0,0,0,0,0,817,1114,0, 1814,958,0,0,0,0,812,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,236,643,0,0,0,0,0,0,0,0,0,1172,0,0,0,0,0,0,0,0,0,1338,0,0,0, 0,0,0,0,0,0,0,0,54,0,0,0,256,0,0,351,0,955,1885,0,469,0,0,0,1270,0,744,0,313,0, 0,0,0,0,0,0,0,402,969,0,0,0,0,0,0,50,0,0,0,0,572,0,0,0,0,847,0,0,0,0,0,0,0,248, 43,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,766,0,363,0,0,0,0,0,0,0,0,0,0,0,678,0,0,409, 258,82,249,0,0,0,0,0,0,0,0,0,0,0,0,32,393,0,788,0,0,0,1281,509,1968,0,0,0,0,39, 291,0,0,0,589,0,0,54,1059,0,0,0,0,0,0,824,0,0,0,0,0,0,0,0,0,0,1005,0,1598,0,0,0, 0,0,919,0,0,0,0,0,0,0,0,52,132,0,0,0,0,0,328,0,0,0,0,173,0,0,0,0,0,65,1411,0,0, 0,0,0,0,0,0,0,0,442,0,842,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0,0,0,845, 210,0,0,0,0,0,0,0,0,892,0,0,223,0,0,0,0,529,0,0,0,807,0,137,218,0,1444,0,0,0,0, 0,332,661,0,0,0,0,0,0,0,76,1517,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,0,0,0,0,0,481, 379,0,0,0,0,0,149,18,0,0,0,0,0,0,0,0,742,304,142,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,799,925,195,51,0,0,0,0,688,0,0,0,0,697,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,1169,751,0,0,0,452,929,0,221,0,1437,0,0,0,0,955,1251,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,132,0,0,0,0,0,865,0,0,0,0,0,0,0,767, 672,42,0,0,0,1050,0,0,0,0,0,0,0,0,368,44,0,0,0,0,0,0,0,570,29,0,0,0,0,0,0,227,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,522,0,0,0,0,0,0,0,1529,0,0,0,0,0,0,739,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1667,0,0,0,0,0,0,132,511,0,138,208,1020,0,0,23,565,0,344,0,0,0, 0,0,922,0,0,0,0,0,0,0,240,0,0,415,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,402,0,0,754,31,716,0,982,731,0,0,0,0,0,0,0,888,0,0,0,803,847,0,0,823, 0,0,0,0,0,0,785,0,0,2,0,0,0,0,0,0,0,532,0,0,681,0,0,314,0,384,684,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,649,447,0,1818,1007,0,321,0,66,360,0,0,0,385,0,0,0,0,0,0, 0,900,73,254,0,0,0,0,683,1959,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,86,0,0,725,0,0,0,0,0,196,0,0,0,0,0,831,0,0,0,0,723,0,0,0,0,0,994,627,0,0, 0,0,0,0,0,0,0,0,764,66,0,0,0,0,205,36,0,0,0,0,0,0,0,950,0,0,0,887,111,0,0,831, 388,165,0,0,0,0,0,155,0,0,0,0,0,0,0,0,0,0,0,0,0,0,780,755,0,0,0,0,898,146,0,0,0, 0,0,0,0,45,7,0,0,0,0,0,0,0,0,607,0,0,0,0,0,0,65,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0, 621,600,0,367,0,0,0,0,0,0,0,561,0,559,0,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,672,157,0,0,0,0,714,0,0,0, 0,0,456,0,925,0,0,0,0,0,0,0,0,19,0,0,0,0,1473,0,0,0,0,0,0,0,0,0,0,113,0,0,0,0,0, 0,0,0,0,0,0,0,0,69,463,0,0,82,193,2,471,0,0,0,0,633,0,0,0,0,0,0,1148,129,1392, 542,803,0,0,0,0,0,0,0,0,0,0,0,0,438,0,0,0,0,0,0,875,0,0,0,0,0,237,0,0,0,0,0,0,0, 65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,563,0,0,0,9,444,0,0,43,1260,0,0,0,0,0,0, 971,0,0,699,0,0,0,0,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,829,242,0, 0,593,0,0,0,0,0,0,0,0,201,36,224,0,0,0,0,0,0,1430,0,1806,0,523,0,0,212,1889,0,0, 0,827,0,0,0,0,0,2043,136,242,0,0,0,0,0,0,284,148,10,0,0,0,0,0,0,1249,0,0,0,807, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,0,0,0,494,0,0,0,0,0,0,0,0,1510,0,0,0,0,0, 0,0,0,0,0,505,1306,0,0,764,268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1703,0,0,0,0,159,964,583,0,0,0, 0,0,0,515,0,0,854,0,0,0,0,0,0,0,0,0,0,0,0,1123,0,0,0,0,0,0,0,136,0,0,0,0,0,1782, 0,0,44,1287,0,0,0,0,0,732,0,0,0,0,313,679,0,0,316,0,0,0,0,595,0,0,0,0,0,0,753, 147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,137,0,0,0,0,414,0,1762,0,0,0,0,0,0,0,0, 0,0,0,599,0,0,0,0,0,0,0,0,0,1749,0,0,0,1627,0,488,0,0,0,0,0,83,0,0,0,0,676,0,0, 1639,0,0,0,0,0,0,0,0,0,278,0,0,0,0,0,0,97,0,14,1085,0,0,0,0,0,0,781,388,0,849, 59,229,0,0,0,0,0,1115,0,0,0,0,108,0,0,0,0,700,0,0,0,0,0,0,0,0,0,1414,0,0,0,0,0, 0,0,0,0,0,0,0,0,660,737,1035,0,0,0,0,0,0,521,690,0,0,0,0,0,0,0,0,0,0,0,0,272,0, 0,0,0,0,0,0,0,0,0,1744,0,0,0,0,0,0,128,733,0,0,277,0,0,0,0,0,0,0,0,0,4,0,0,0,0, 0,0,0,0,0,0,0,0,0,936,1981,40,0,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,306,0,0,0,0, 0,0,0,979,0,0,0,0,0,611,0,0,0,0,0,178,0,0,0,1969,0,0,0,0,0,0,0,664,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,390,0,0,0,1510,0,0,0,0,0,0,0,0,0,0,0,493,0,0,37,0,0,0,0,724,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,1537,0,0,168,473,0,0,0,105,0,0,0,0, 627,438,0,0,0,0,0,0,0,0,0,0,11,1256,0,0,0,1626,0,779,0,0,0,0,25,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,308,0,0,0,0,0,741,0,671,0,0,0,0,649,150,0,0,99,521,0,0,3,339,0,0,0, 543,0,0,0,0,0,0,0,0,0,1358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,234,155, 0,0,0,0,0,0,0,1628,0,766,0,0,0,0,0,0,0,0,0,0,0,0,0,829,0,0,0,1445,0,0,0,486,0,0, 0,0,2,1635,0,0,0,0,558,0,0,0,0,0,0,0,0,0,0,1461,0,0,0,0,0,599,0,0,0,0,0,0,0,0,0, 1376,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,0,0,0,0,0,0,447,0,0,66,1432,0,0,0,0, 0,0,307,0,413,609,0,0,0,930,0,0,0,0,21,939,0,0,0,0,0,962,4,651,0,0,0,0,15,579,0, 0,0,0,0,597,0,0,0,0,0,981,0,0,0,545,0,0,0,0,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,800,17,0,0,17,0,907,0,0,0,110,0,0,0,53,458,0,1983,0,0,0,0,0,0,0,0,0,0,443,0, 0,0,0,0,0,0,0,0,0,0,924,1844,0,1232,0,0,0,0,70,519,0,993,0,0,0,0,0,0,14,530,0, 907,0,0,0,0,0,733,0,0,0,0,0,0,0,0,55,0,188,531,56,0,0,1693,0,0,0,0,0,0,0,0,441, 0,192,928,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1525,0,259,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,512,185,0,464,1603,0,0,0,0,0,0,0,0,0,0,0,1113, 284,720,0,0,722,0,0,0,0,0,13,0,0,0,0,0,0,0,4,289,43,0,0,0,0,0,0,1694,0,0,0,0, 193,0,0,0,0,409,0,0,0,0,0,0,0,0,0,0,0,0,308,0,0,1863,0,0,0,0,0,0,0,0,0,790,0,0, 745,1002,0,0,0,0,0,0,0,0,0,289,68,477,13,0,0,0,0,0,0,0,0,0,0,609,0,0,0,0,0,0,0, 0,0,0,0,367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,0,0,0,0,0,0,694,58, 548,0,0,0,0,0,0,687,0,0,0,0,1749,0,0,0,0,0,0,0,0,1004,661,0,0,0,0,0,0,445,0,0,0, 74,0,0,0,0,213,0,0,0,0,0,0,0,0,0,0,0,0,0,834,0,0,189,1672,0,0,0,0,0,0,0,1548, 192,0,0,0,0,0,0,0,0,0,0,0,0,0,32,751,0,78,0,0,0,0,0,0,544,1602,105,473,0,0,0,0, 0,0,156,1949,0,1779,0,0,0,0,0,0,0,0,0,0,0,763,0,0,0,0,0,0,0,0,29,0,0,0,0,0,0,0, 0,0,0,883,0,0,0,0,0,0,0,488,0,617,0,0,50,0,694,1518,785,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,546,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,1016,0,0,0,577,0,0,0,0,0,0, 184,935,114,720,0,0,100,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,95,14,0,969,0,0,0,0,0,0,0, 727,0,1021,0,0,0,0,0,1190,0,0,0,0,0,0,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,0,0,798,0, 587,0,0,695,42,0,1929,141,957,0,465,7,908,0,0,450,148,0,0,0,1166,0,0,0,0,0,0,0, 0,0,0,0,0,253,0,1003,0,0,0,0,0,0,0,0,0,0,0,46,0,0,879,0,806,0,1868,0,0,0,0,0, 1846,0,0,0,730,0,0,0,0,0,0,0,965,0,0,0,0,506,0,0,0,10,0,0,0,22,0,0,0,0,0,0,0,0, 0,0,0,0,0,960,296,0,0,0,0,0,0,0,0,0,0,0,587,0,0,0,0,20,0,0,0,32,982,0,0,0,0,0,0, 0,0,0,0,941,0,0,0,0,435,0,0,0,0,0,0,71,419,0,0,0,0,0,0,688,740,94,345,0,0,679, 582,0,0,0,0,0,0,0,945,0,0,0,0,0,0,0,0,0,0,0,0,539,0,684,1993,0,0,0,659,0,583,0, 803,0,704,0,0,0,0,0,198,181,347,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,481,405,203,0,0,99,826,0,0,0,0,0,0,0,492,0,408,0,0,0,0,0,0,0,0,0,0,4,0,0, 0,0,665,349,137,0,0,0,0,612,1270,0,0,0,0,0,371,0,0,0,826,0,0,0,0,21,1535,858, 374,0,0,0,0,0,0,311,0,0,0,991,1968,0,0,0,0,494,1647,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,769,0,0,0,0,0,642,0,0,157,123,0,0,0,1435,0,0,0,0,0,0,0,0,0,0,79,0,0,0, 0,0,0,1425,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,106,393,486,1690,0,0,0,0, 0,0,0,0,0,0,0,0,756,184,0,0,0,1382,0,0,0,175,0,1493,0,1007,0,0,0,0,0,0,0,0,0,0, 0,219,0,0,0,0,515,99,0,851,0,0,0,0,0,1278,0,0,0,0,0,0,0,1000,982,0,762,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,910,1819,0,0,0,0,0,0,906,0,0,0,0,0,0,0,0,0,0,1730,0,0, 0,0,0,0,0,0,0,0,0,1185,0,0,0,0,0,0,0,0,40,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,0,0, 650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,30,0,553,0,0,20,597,0,1614,0,0,0,0,0,327, 49,0,0,0,0,0,0,0,78,0,0,786,134,0,0,0,12,496,0,0,0,0,0,0,0,0,0,0,42,204,0,614,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,147,247,0,0,0,0,942,0,0,2023,0,0,0,0, 0,0,67,285,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,532,0,0,0,0,0,0,0, 1692,0,0,0,0,55,1704,0,0,0,0,988,0,0,0,223,0,0,0,0,0,0,0,57,1123,0,0,0,0,0,1764, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2015,0,0,0,1599,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0, 0,0,504,621,1248,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1397,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,441,75,0,0,0,0,0,0,0,0,0,0,841,0,0,0,0,0,693,0,650,314,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913,0,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,475,0, 0,1016,179,602,111,329,0,0,0,1864,0,0,0,0,846,1888,0,0,780,0,0,0,82,0,0,0,0,821, 0,0,0,0,0,0,0,0,0,0,0,956,112,0,0,0,261,455,0,0,0,0,0,0,337,385,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,184,1865,0,0,721,16,0,486,0,0,0,265,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,621,0,0,0,0,0,0,0,0,234,0,0,815,0,0,743, 1987,205,197,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,219,452,589,0, 176,333,0,0,0,0,0,0,0,1110,47,0,0,0,0,0,0,0,0,0,0,0,864,0,0,300,0,1237,0,0,0,0, 0,0,0,0,0,0,0,1685,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,135,395,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,631,0,0,0,0,0,0,835,0,0,0,606,459,0,979,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,612,0,0,0,0,0,0,0,0,158,372,0,854,0,0,0,0,0, 0,0,1492,0,0,0,833,0,0,0,0,0,0,0,1739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 195,0,0,0,0,0,0,0,0,730,1997,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,266,751,0,0,0,0,0, 0,0,821,0,0,0,715,0,0,0,868,0,959,0,0,0,0,0,0,0,0,0,0,0,1053,0,0,0,950,0,1081,0, 1595,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,47,684,0,0,0,0,0,0,1606,0,777,0,1020,0,0,0, 1094,0,0,0,0,0,0,0,350,0,0,0,0,0,0,242,1812,0,0,0,967,0,0,0,473,286,0,0,0,0,0,0, 798,629,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,513,337,306,0,0,0,0,0,0,0,0,0, 146,0,0,1646,0,0,0,0,0,465,0,0,0,525,0,0,0,0,0,0,299,165,0,0,0,0,0,0,0,1064,0,0, 0,0,0,596,0,0,0,0,0,0,0,0,0,0,0,0,0,0,238,1741,0,1233,451,1824,0,0,0,0,733,495, 0,0,0,0,0,1204,0,0,0,559,341,0,224,21,0,0,0,0,0,0,0,0,97,1446,0,0,0,0,0,0,0,729, 0,0,565,727,0,1948,0,0,0,519,0,0,0,0,0,0,0,0,0,1193,0,0,0,0,0,0,790,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,323,2,201,0,0,59,0,0,34,0,896,961,0,1285,0,0,46,0,479,0,0, 0,0,549,0,663,0,0,0,0,0,783,65,682,0,0,0,0,0,11,0,0,0,0,0,522,0,0,0,52,0,0,0,0, 0,383,0,0,0,0,0,0,0,0,127,0,0,0,0,0,397,194,0,0,635,0,0,0,0,0,0,0,0,0,0,975,0,0, 0,0,0,0,0,0,0,0,116,0,51,0,0,858,0,1075,535,448,0,0,0,0,0,610,0,0,0,0,0,0,0,0,0, 0,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,267,673,319,94,92,0,551,0,0,218, 1406,69,256,0,0,952,1980,0,833,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,81,0,0, 0,352,634,0,0,0,0,0,618,0,0,0,0,0,0,73,339,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,759, 0,0,0,0,0,0,0,0,0,0,0,0,0,1075,0,0,0,0,0,0,482,649,0,0,0,0,0,0,0,0,386,336,0,0, 0,1035,0,0,0,0,0,0,0,0,0,0,0,924,0,73,0,0,0,0,0,1971,0,0,0,0,0,0,0,0,0,1344,0, 501,0,0,0,0,0,0,0,0,46,799,0,0,0,0,0,0,0,276,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,0, 0,0,0,0,0,158,0,0,0,0,0,1432,0,0,0,0,0,0,0,0,0,0,25,0,0,2001,0,0,0,0,0,0,0,0,0, 0,0,0,0,478,0,0,0,0,0,0,91,1461,211,602,0,0,0,0,0,0,0,0,0,1068,0,0,124,567,0,0, 0,1006,0,0,0,0,0,0,0,0,0,735,812,0,0,323,0,0,0,304,0,0,0,0,0,0,0,0,0,148,0,0,0, 0,0,0,0,0,0,523,0,0,144,730,0,0,981,0,0,111,0,0,132,0,0,0,0,0,0,890,0,0,0,0,0, 444,0,1787,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,2041,932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,937,0,995,0,0,255,0,0,138,863,965,0,0,631,0,0,0,0,1394,16,652,0,0,0,0,0,0, 0,0,0,0,0,0,0,897,0,321,0,0,0,0,0,922,0,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,844,0,0,0,0,0,0,1659,0,1100,0,0,0,1173,0,1930,268,251,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,390,711,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,0,0,0,0,624,0,0,0, 1998,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1125,0,0,0,594,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,268,0,0,0,0,0,0,0,563,0,0,0,0,0,0,0,0,2,39,0,0,0,1332,0,0,0,0,0, 0,0,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,796,0,0,0,0,527,0,0,0,0,98,0,0,576,0, 0,0,0,0,122,0,276,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,0, 0,0,0,0,0,0,0,290,0,0,762,1292,0,0,0,1315,0,1955,0,0,0,0,0,0,0,0,0,0,210,131,0, 0,0,0,797,0,38,0,11,488,0,936,0,441,0,0,0,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 991,0,0,0,0,0,0,0,0,0,0,0,653,0,523,0,0,0,903,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0, 0,0,0,0,0,0,432,0,0,314,0,0,0,0,232,1368,534,0,0,0,0,0,27,0,0,0,12,0,0,0,0,0,0, 0,0,0,264,736,0,1657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1117,0,127,0,0,0,1208,0,1294, 0,0,0,0,364,0,0,0,0,0,125,1334,0,0,0,0,0,0,0,0,0,0,0,0,0,0,792,0,0,0,0,0,0,0, 849,699,0,0,0,0,0,968,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1446, 124,397,0,0,0,0,0,0,0,0,0,0,0,641,0,0,0,0,0,0,0,0,0,0,0,0,127,346,0,0,517,75,0, 0,0,0,0,0,0,0,83,0,0,0,0,0,0,1031,0,0,0,0,0,0,0,1470,0,954,0,0,345,304,410,0,0, 0,0,734,0,0,0,0,0,1822,0,0,0,1798,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,161, 1865,69,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,0,0,0,541,0,627,0,0,0,0,0,0,0,0,0,166,0, 0,0,0,0,0,0,0,0,849,0,0,0,0,0,0,0,717,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600,0,0,0,0,0, 0,654,0,0,188,273,0,0,0,543,0,410,87,0,0,941,0,0,186,250,0,1785,0,0,0,0,0,1339, 462,961,0,780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,0,0,474,1276,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,24,948,0,0,0,0,657,753,0,0,0,0,941,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,706,985,837,0,1861,0,0,0,0,0,0,0,0,0,0,0,0,0,0,292,933,0,0,0,0,0, 0,0,0,0,767,0,0,0,0,0,0,0,641,0,0,0,1233,114,0,883,0,274,2008,0,1794,285,0,0, 571,0,0,0,0,0,0,0,0,0,0,823,960,16,617,0,431,0,0,0,0,0,0,0,0,0,0,567,0,401,0,2, 781,424,33,0,2006,0,0,274,0,0,1882,0,794,0,0,0,1848,0,0,0,0,0,0,448,47,0,0,0, 1199,0,0,0,0,0,0,0,0,417,0,0,0,0,0,0,0,0,0,0,295,0,0,0,0,0,0,0,1019,0,0,0,0,0,0, 0,0,0,0,0,0,0,620,0,0,0,0,464,0,0,0,0,208,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,442,0,930,0,0,0,0,0,516,68,0,0,0,0,0,1128,104,0,0,0,0,0,0,0,0,787,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,491,0,0,0,0,0,0,711,0,0,9,0,101,441,0,0,0,0,0,0,0,0, 0,0,160,396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,679,326,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1128,0,0,0,0,0,737,0,1796,0,0,0,0,0,0,0,0,0,0,0,0,338,574,0,0, 0,0,0,1096,491,405,0,0,0,0,0,1081,0,0,0,0,0,0,0,0,0,0,0,0,0,1676,0,1207,0,0,0,0, 0,0,969,354,0,0,0,0,598,0,297,0,0,0,0,0,0,0,0,1772,751,0,37,0,0,1828,0,0,0,0,0, 0,0,0,0,257,191,582,0,0,0,0,0,0,790,0,0,0,0,0,47,0,0,0,0,0,0,0,449,306,1011,0,0, 0,0,0,299,0,0,0,0,0,0,837,0,0,0,0,0,0,10,329,0,0,0,0,0,1320,0,0,0,0,0,0,158,657, 0,1191,0,0,0,0,0,0,7,0,974,1939,0,1665,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,288, 66,0,0,0,0,494,175,0,1643,0,0,0,0,0,0,0,0,570,750,719,0,0,0,0,0,0,0,0,0,0,0,0,0, 13,0,0,1247,0,0,221,356,0,0,0,0,0,0,0,0,0,0,694,1809,0,0,0,0,0,0,0,411,0,44,31, 0,0,0,0,669,0,673,0,0,0,0,0,0,0,0,0,1303,704,299,0,0,0,275,0,0,216,1761,0,0,0,0, 0,0,0,0,0,0,0,1319,0,0,428,0,0,0,0,0,0,0,0,0,0,514,0,0,0,0,0,0,49,55,102,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,364,0,0,0,0,379,0,921,971,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1258,0,0,0,1058,0,0,0,0,0,656,0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0, 0,1373,10,605,0,0,0,0,0,0,0,838,0,1012,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154,365,0,0, 0,0,0,0,0,0,0,340,0,0,0,0,0,810,0,0,0,0,0,0,495,0,0,0,0,0,0,0,0,0,261,0,535,248, 0,358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,567,445,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,697,0,0,0,1336,0,0,0,0,0,0,0,0,917,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,972,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,351,0,0,0,0,0,0,0,0,0,0, 0,0,0,286,0,0,56,438,0,0,0,0,0,1950,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,738,0,0,0,0,0, 0,0,0,0,0,969,2047,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,866,0,0,0,0,0,0,0,1467,0,0,0, 0,0,0,0,0,0,0,0,0,0,972,0,355,0,0,0,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,267,189,104,0,0,0,0,1613,0,0,0,0,0,0,0,116,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,886,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,863,0,0,0,0,0, 0,0,1953,450,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0, 0,0,0,0,0,1142,0,1189,0,0,0,663,0,0,0,0,0,0,0,846,0,0,528,0,393,378,0,0,0,0,0,0, 325,899,680,1880,0,1770,0,0,0,0,0,648,0,0,0,0,0,0,185,167,0,2046,0,0,0,0,0,0, 249,1645,0,152,0,0,0,1733,0,0,0,0,0,1006,0,0,0,0,0,420,0,0,0,832,0,0,0,0,0,351, 0,0,0,0,6,40,0,0,60,0,0,0,0,1354,745,724,0,0,0,0,0,0,0,0,772,1951,275,108,639,0, 0,0,0,0,0,0,0,0,500,1758,0,0,0,0,0,0,0,0,0,0,0,1886,711,205,0,0,965,865,0,0,0, 534,0,0,0,0,691,0,0,0,237,443,0,878,0,0,0,0,0,1410,0,0,0,0,0,0,0,0,0,0,0,0,0, 995,0,0,0,0,0,0,0,0,0,0,0,0,0,578,0,0,0,0,881,0,0,0,0,0,0,0,0,822,0,923,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,924,0,0,0,665,0,0,0,0,0,1901,0,0,0,0,0,950,498,93, 0,0,0,1451,0,0,0,0,0,747,828,788,400,184,0,198,0,0,0,0,0,0,0,0,0,0,0,994,0,0,0, 0,0,0,0,0,615,320,0,0,0,978,843,905,0,0,0,0,0,0,0,0,850,974,0,0,0,0,6,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,0,0,0,0,0,273,0,0,0,0,0,0,0,0,0,0,0,0,0, 201,0,0,0,1041,0,0,0,1040,0,0,0,0,0,0,0,0,0,693,234,774,0,336,0,1399,22,0,805, 802,777,167,789,0,0,1705,0,0,0,0,0,0,0,0,0,0,0,10,13,11,0,0,204,264,0,0,56,0,0, 1917,0,470,0,0,0,0,0,0,0,0,0,0,0,1198,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,715,0,0,1002,0,0,0,298,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,867,0,0,724,0,0,0,0,0,0,0,0,0,0,0,0,768,0,0,0,0,0,1066,0,0,0,0,67,0,174,948, 0,0,0,0,0,0,0,0,0,0,0,0,0,764,0,0,0,0,75,137,0,756,0,0,0,0,0,0,1008,842,643,0,0, 0,67,0,0,0,0,0,0,0,0,0,0,0,135,821,0,0,0,0,0,0,0,0,736,0,389,355,0,0,786,0,0,0, 0,0,0,2044,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1030,0,0,0,1083,0,0,0,0,0, 1226,0,0,0,0,356,319,8,389,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,474,0,0,0,427, 0,413,0,730,0,0,0,0,0,373,0,0,0,0,0,0,0,0,0,799,0,0,0,1793,0,0,0,322,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,290,2,0,0,0,0,0,0,0,0,0,0,672, 699,1860,0,0,0,737,0,0,0,1612,0,0,0,0,0,0,0,0,0,0,0,145,124,884,0,0,0,0,0,387,0, 0,0,0,0,0,0,0,0,0,0,679,0,550,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1305,0,0,0,0,0,0,0, 576,0,0,0,0,0,0,0,686,0,607,0,0,37,0,0,0,0,0,0,0,0,0,101,1726,0,0,0,0,0,958,0,0, 0,903,0,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,367,0,0,0,0,690,0,705,273,0,0,887,0,0,0, 0,0,0,0,0,0,0,0,90,0,0,0,0,0,0,0,908,0,0,0,0,0,0,0,1261,0,0,497,1235,0,429,0,0, 0,0,904,0,12,125,0,0,0,841,0,0,0,0,0,860,946,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,768,0,770,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,271,0,0,0,0,0,0,0,719,0,699,581,0,0,0,0,0,0,0,0,0,0,862,304,0,631,0,0,0,0,880, 1513,0,0,0,0,0,981,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,434,0,0,0,0,0,550,0,0,476,930, 824,553,0,0,452,0,151,0,0,0,0,0,0,772,0,292,135,0,0,0,0,0,0,0,504,0,0,1089,0,0, 0,0,0,0,0,0,0,0,0,783,0,0,0,0,0,0,206,393,0,0,0,0,0,0,0,0,232,912,0,0,0,0,0,977, 0,0,716,98,0,0,0,0,0,733,0,0,0,0,0,0,0,0,19,0,0,0,0,668,0,360,0,0,0,0,0,0,656,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,726,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,1269,0,0,463,0, 0,0,0,0,0,1454,0,1287,245,0,989,0,0,0,0,0,0,0,0,0,107,164,0,0,0,0,0,0,0,1061,0, 0,0,0,2,484,0,0,0,0,0,0,0,1127,0,0,0,0,0,0,0,460,0,0,0,0,0,932,0,0,0,0,0,0,0, 588,625,0,0,0,0,76,92,0,0,0,0,0,0,0,0,0,0,0,0,0,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 763,0,622,0,0,0,253,0,546,0,0,110,0,256,916,0,0,35,212,0,0,746,0,0,0,150,0,0, 1466,0,0,0,1299,0,0,0,0,0,0,0,0,0,1518,0,0,0,0,0,0,0,0,0,0,0,0,0,1229,0,0,0,816, 0,0,0,0,0,0,159,0,0,0,0,0,734,869,126,1716,0,0,0,0,0,0,202,232,0,0,0,0,212,0,0, 0,0,0,111,1003,0,0,0,0,0,0,0,0,0,0,0,1712,0,0,216,0,0,0,0,516,0,0,0,0,0,650,0,0, 0,0,57,99,0,0,0,0,300,574,0,0,0,0,1023,0,0,302,0,1871,0,728,252,0,0,461,0,0,0, 323,0,0,0,0,0,0,775,461,0,0,0,0,0,0,172,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,73,727,0,1023,0,0,0,0,0,0,0,0,0,0,577,0,0,0,0,0,0,0,0,1037,0,0,0,0,0,0, 0,0,280,677,0,0,0,0,0,0,0,0,0,0,0,799,0,0,0,0,159,0,446,1730,0,0,0,0,0,0,0,0,0, 395,0,0,0,0,145,0,0,0,0,0,0,0,20,0,0,426,608,0,0,0,0,0,977,0,250,0,0,0,0,0,100, 0,0,0,0,1982,0,0,0,0,0,476,0,0,0,0,0,0,594,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,447,0,0,0,0,526,0,0,14,1124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,188,0,0,0,0,0,0,0,0,362,301,0,0,0,1743,0,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,831,0,0,208,202,0,0,0,0,0,0,0,1954,0, 0,0,0,516,872,0,0,313,224,0,0,24,0,11,546,0,0,0,1937,242,241,46,0,0,0,830,1273, 0,0,0,0,0,0,0,825,327,1006,0,0,0,0,0,1580,516,366,0,0,0,0,0,1736,0,0,0,0,0,0,0, 0,0,0,0,1935,0,826,0,0,0,0,139,331,0,0,0,0,0,0,0,0,0,0,0,288,0,916,0,0,0,0,0, 1888,0,0,0,0,0,0,0,1471,0,1570,0,394,0,0,0,0,0,0,0,1931,0,1719,0,658,228,0,0,0, 0,0,374,0,0,0,0,735,0,0,0,0,0,0,323,498,0,1063,0,0,0,0,155,0,0,0,0,0,0,0,0,906, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1139,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,616, 902,0,0,0,0,0,692,0,0,0,0,0,0,823,0,0,0,305,0,0,0,0,0,0,0,681,0,0,0,0,0,214, 1004,0,0,0,0,0,0,0,23,0,0,1703,0,0,0,0,0,0,0,0,0,1443,0,0,19,714,0,0,0,0,64,737, 0,0,345,1758,0,0,579,47,0,0,539,139,0,0,0,0,388,0,0,0,0,253,0,0,0,0,0,0,252,0, 745,0,0,0,0,0,0,0,0,0,0,0,504,107,0,871,0,0,0,229,0,0,0,0,0,903,0,0,71,0,0,549, 6,47,0,0,0,0,0,0,0,0,0,980,865,705,0,0,0,161,0,0,0,0,143,1331,0,0,0,1388,33,724, 0,0,0,19,0,0,0,395,0,0,0,0,0,846,210,0,0,0,122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,937,497,0,0,0,0,0,718,0,0,0,0,0,0,0,1581,0, 0,0,0,0,0,161,49,0,0,0,0,0,0,0,0,0,597,0,0,0,1094,0,0,0,811,908,0,0,0,0,0,0,0,0, 0,0,1471,0,0,0,0,0,0,0,0,0,0,42,1935,0,0,0,2014,66,2007,0,0,586,0,0,0,0,0,0,0,0, 0,28,1077,0,0,0,1221,0,0,62,0,0,0,0,0,0,0,0,0,0,1766,0,0,0,0,0,0,0,0,0,0,0,0,25, 0,499,1388,0,0,97,10,0,0,0,0,0,481,0,0,0,0,0,0,0,0,0,0,37,134,155,486,0,1442,0, 0,0,0,0,591,0,0,0,0,0,0,310,1173,0,0,0,0,409,1156,0,0,0,482,0,0,263,926,0,0,0,0, 0,0,0,0,0,0,0,0,0,804,0,0,0,0,0,0,0,0,0,0,0,0,0,1265,0,415,0,348,0,0,0,1012,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,165,1803,0,0,0,0,0,0,0,408, 0,0,0,0,0,0,257,1321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1138,0,0,0,249,0, 0,0,576,0,0,0,0,231,0,0,0,288,0,0,0,0,0,0,0,0,0,433,1487,569,1678,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,0,0,0,0,0,779,538,0,0,0,413,0,0,0, 0,0,0,0,0,0,0,495,0,0,0,0,0,191,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,530,567, 0,0,0,0,0,1484,0,0,0,0,0,0,815,609,0,0,0,0,0,484,0,0,0,0,0,0,0,0,0,0,900,0,0,0, 0,1335,0,1724,0,0,0,0,0,0,0,0,0,0,0,640,0,0,0,0,0,0,0,0,0,0,0,1831,0,0,0,0,0,0, 0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,1103,0,1504,655,1034,0,0,0,0,0,305,0,0,0,0, 0,0,0,0,0,1236,0,0,429,217,0,0,0,0,739,278,0,0,0,0,0,0,0,708,0,0,0,0,0,1840,233, 0,0,0,0,0,0,0,0,2017,0,0,0,0,0,1488,0,0,0,1590,0,0,0,0,0,1800,28,0,0,0,0,0,0,0, 0,0,45,0,36,0,22,1442,378,0,0,0,0,0,0,1507,0,0,0,0,0,0,0,0,0,0,39,0,0,1054,725, 1955,0,2036,0,0,0,0,0,0,0,0,0,0,896,1871,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,2046,0, 0,0,0,17,712,0,617,55,320,271,0,0,0,0,0,0,0,0,0,445,0,184,103,0,0,0,0,0,0,0,0, 659,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 337,0,0,0,506,0,0,0,0,0,843,77,0,458,0,0,0,0,0,1420,382,109,142,330,0,0,0,0,0,0, 0,0,0,0,0,0,87,0,0,0,492,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1239,0,0,0,0,0,0, 211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1049,0,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1985,0,0,122,0,0,234,0,0,0,1098,0,0,0,0,0,0,549,253,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,522,131,0,0,149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,507,0,0,0,0,811,630,0,0,0,343, 0,0,0,0,0,448,591,455,0,1381,0,0,0,0,0,0,0,575,0,0,0,0,0,1175,0,0,0,0,0,0,0,0,0, 653,0,0,0,1761,0,1198,0,0,0,0,297,1127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,678,0,0, 164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,45,0,0,0,0,0,121,0,0,0,0,0,0, 0,0,125,0,0,0,1622,0,0,0,0,0,721,145,0,0,0,970,792,0,0,0,715,0,0,0,0,0,1999,0,0, 74,531,0,0,65,0,0,0,105,220,0,0,0,0,0,0,0,960,0,0,0,0,0,0,428,19,0,0,401,96,0,0, 0,0,0,1595,116,0,1021,0,0,0,0,0,750,1961,0,0,148,0,0,0,0,0,0,0,0,0,0,0,0,0,75,0, 0,1383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,779,0,0,0,0,0,0,0,0,598,0,424,0,0,0,0,0,0,0, 1222,0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,0,0,0,187,0,8,0,0,0,0,0, 0,0,429,0,685,0,0,0,0,0,0,0,0,0,0,0,132,472,0,0,0,0,0,0,0,0,0,938,0,0,874,0,0,0, 0,0,774,0,0,0,0,0,92,0,0,0,0,0,0,830,701,0,0,0,0,0,426,350,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,603,59,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,441,163,4,0, 0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,233,0,0,0,0,1994,0,1739,0,0,393,0,47,1038,0,0,0, 309,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,363,0,0,0,175,0,0,0,0,0,0,0,666, 0,0,1675,0,1600,0,0,0,808,0,0,0,0,0,0,0,0,0,0,0,280,54,0,0,0,0,0,0,0,0,421,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,0,0,103,254,0,262,1,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,1630,0,0,0,0,0,0,0,0,0,0,0,0,0,671,972,989,0,0, 0,0,0,0,0,889,0,0,0,1382,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,0,388,202,0,0,0,0, 16,560,0,0,0,841,0,0,566,0,0,0,938,0,0,0,0,0,0,0,0,0,0,912,0,0,0,1361,0,0,0,0,0, 0,618,236,0,1854,0,0,318,190,0,1376,0,0,0,0,0,0,0,349,0,0,0,0,951,1972,0,0,0,0, 0,0,344,0,0,0,0,0,0,0,0,850,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,163,85,0,487,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,145,0,83,0,0,1013,0,0,0,1922,0,0,169,557,66,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1193,82,0,352,454,57,0,0,1333,396,107,0,370,0,0,0,0,0,0,0,0,0,204,0,0,0, 0,0,1706,0,0,0,0,0,0,0,0,0,0,0,0,394,1204,0,0,0,0,0,1007,0,0,0,1696,0,1519,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,981,0,0,0,0,1072,0,0,0,712,0,1629,0,0,0,0,0,0,0,728,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1271,0,0,0,1608,16,0,0,0,0,485,0,0,0,0,0,0, 153,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1991,0,0,0,0,0,0,0,0,52,0,21,0, 0,0,0,0,0,0,0,0,819,0,0,0,0,0,917,0,0,0,0,784,0,0,0,0,135,0,0,0,0,0,454,0,0,0,0, 0,0,0,0,0,852,1719,0,0,0,0,0,852,0,0,0,0,0,952,0,0,0,0,568,0,0,0,0,0,448,0,0,0, 67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1826,657,0,729,666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 669,0,0,0,0,0,0,0,402,0,0,152,0,0,0,0,912,0,0,0,0,0,0,51,320,0,445,0,0,0,0,308, 0,0,0,0,0,386,0,0,239,0,0,130,83,0,143,0,348,0,0,0,0,0,0,0,958,0,0,0,0,0,210,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,430,0,0,0,0,0,0,0,0,0,0,0,0,7,213,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,801,0,0,0,0,0,0,0,0,0,936,0,108,0,0, 0,0,0,0,0,0,0,885,587,219,398,364,0,1165,0,0,342,241,303,0,0,0,0,0,0,0,0,0,0, 1454,0,0,0,0,0,0,0,0,0,0,254,562,0,786,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1294,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,493,216,0,0,0,0,219,341,0,0,0,0,0, 0,0,0,0,0,130,1734,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,701,604,0,0,879,0,195, 666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1669,0,0,0,1791,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1228,0,0,0,0,0,623,0,0,0,0,0,0,0,798,0,0,0,0,0,0,0,0,0,0,0,0,84, 122,0,0,0,837,0,0,0,0,0,0,1013,0,0,577,0,0,0,460,932,0,0,0,0,0,0,0,0,0,0,0,31, 131,0,0,0,605,0,0,0,1246,0,0,0,0,68,278,165,307,781,0,0,0,0,0,0,33,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,1113,0,0,720,1953,203,0,0,0,0,0,0,0,425,326,0,0,0,0,0, 0,0,0,0,0,241,1316,0,0,0,0,0,416,0,0,0,1300,0,847,0,0,662,358,0,0,0,0,839,1823, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,654,1522,0,0,0,0,0,0,163,0,0,0,0,0,314,978,0,0,0, 601,0,0,0,0,0,946,434,0,0,0,402,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,1467, 410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,0,70,0,0,0,0,1405,0,0,0,0,0,0,108,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,777,0,0,0,0,0,747,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,505,0,326,0,0,164,628,654,0,0,0, 37,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,668,152,0,0,0,0,0,0,0,0,0,0,0,581, 0,0,0,0,44,126,89,0,0,0,0,0,0,0,0,1531,0,0,0,0,0,0,0,0,203,1167,0,0,0,0,0,0,0,0, 531,1232,0,0,0,0,0,943,0,670,231,880,0,1617,0,0,0,1957,0,0,0,0,0,0,0,975,0,0,0, 0,0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,0,0,421,0,0,14,834,0,0,0,0,0,0,0,0,0,0,0,0, 465,0,0,0,0,0,834,688,413,855,0,0,0,590,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0, 0,45,169,0,0,0,0,0,0,0,0,0,0,0,198,0,0,565,585,0,0,0,0,0,0,0,0,0,0,0,0,0,691,0, 0,0,593,0,0,0,0,0,0,0,0,0,913,116,0,0,0,0,1360,0,0,0,802,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,673,308,0,709,1006,1895,0,228,0,0,0,1840,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,608,0,0,0,0,0,0,0,0,0,1573,0,2039,136,540,0,0,0,0,0,0,0, 897,0,0,938,1878,0,0,0,0,0,0,0,0,0,1469,0,999,0,299,0,0,0,0,0,0,0,578,0,0,0,0,0, 456,0,0,0,1679,163,693,0,0,0,0,0,0,48,755,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0, 1091,0,0,0,0,695,0,0,1464,0,0,0,0,0,975,0,0,335,0,0,1979,0,0,0,0,269,1566,630, 396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1815,634,0,0,0,966,0,0,0,0,0,0,0,9, 412,0,958,0,0,579,382,0,212,0,0,0,0,965,681,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,655, 0,0,0,0,67,0,0,0,0,0,0,751,0,0,0,0,423,231,0,0,1016,300,0,0,0,0,100,237,0,0,0, 1370,0,0,0,1208,0,0,0,0,0,1219,129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,199,0,0,427,0,0, 0,0,949,665,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,712,0,0,0,0,0,1186,0,0,0,0,0,0,0,0,0,0,295,312,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 151,0,0,0,0,588,4,0,0,0,0,0,414,104,0,0,757,263,0,561,0,0,0,320,0,0,0,0,0,0,0,0, 0,0,0,225,0,0,0,0,37,817,0,974,0,0,0,0,0,0,0,0,0,0,0,0,0,2026,131,235,16,0,590, 1157,0,0,0,0,0,0,0,0,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,390,0,0,0,0, 0,0,0,1144,0,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,204,407,303,1218,0,0,0,0,5,325,0,0, 0,0,12,800,0,1783,0,0,0,0,0,0,0,0,0,0,504,621,0,0,0,0,0,0,0,0,0,920,0,376,0,0,0, 0,0,218,580,0,768,454,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,164,0,0,0,0,0,0,0, 0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,120,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,343, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,0,0,1812,0,0,8,0,0,0,21,1125,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1327,0,0,0,0,575,1598,0,0,0,0,0,0,0,0,0,895,0,0,0,959,0,0, 0,0,0,1759,173,0,0,0,0,266,261,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,1427,0,0,300,1033,0,0,0,0,0,0,0,0,0,0,0,584,0,0,0,0,52,734, 0,0,217,239,0,1129,0,0,0,0,0,0,0,0,732,20,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,613,0, 0,0,0,0,0,0,0,0,632,0,0,85,984,0,0,0,0,909,694,7,1109,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,167,0,0,0,0,280,62,0,0,33,0,0,359,186,980,0,0,0,0,0,0,0,0,0,0,0,585,0,0,0, 211,0,0,336,145,0,1130,0,873,0,0,840,263,0,0,0,0,0,0,0,0,0,916,0,0,0,0,0,0,0,0, 0,0,155,0,0,0,461,97,0,0,0,0,0,1356,0,0,0,0,0,0,0,593,0,0,0,0,0,1392,0,0,0,0, 126,0,0,0,0,1179,0,0,0,0,0,162,0,0,0,0,0,765,0,187,0,1286,0,0,0,0,0,0,0,0,0,635, 0,0,23,215,0,0,0,1306,0,0,97,716,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,657,0, 0,0,0,0,0,0,0,299,0,0,0,0,0,0,134,0,0,0,0,0,0,0,0,0,0,0,658,1082,0,0,0,0,0,2002, 0,0,0,0,0,0,833,248,0,0,0,0,0,1654,0,0,531,0,0,0,0,0,0,634,0,0,0,0,0,0,0,0,0, 853,573,249,0,0,0,0,0,0,0,0,527,0,0,0,0,1419,0,0,0,0,0,0,20,49,0,0,0,992,0,0,0, 728,0,0,0,0,0,0,0,0,0,0,0,0,497,1579,0,0,0,0,62,268,0,0,0,0,0,0,0,1201,0,0,0,0, 0,0,0,0,0,0,0,0,495,193,0,0,0,0,106,0,0,859,0,0,23,0,0,0,0,0,0,0,813,925,0,0, 223,613,953,0,0,0,0,0,0,0,0,666,0,0,0,0,0,0,0,0,0,670,0,0,40,216,0,0,0,0,0,0, 259,0,0,0,440,1114,0,0,0,0,0,0,0,0,74,475,0,0,188,139,0,797,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,1572,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,1594,0,0,0,0,0,0,0,290,0,232, 0,0,887,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,14,0,0,0,0,0,741,0,0,0,992,0, 0,0,0,0,0,0,0,111,0,0,425,0,0,0,0,0,789,0,0,0,1593,0,1768,0,0,233,0,0,0,0,943,0, 0,0,0,0,0,0,955,225,245,0,0,0,0,0,0,241,0,0,0,0,1943,0,0,0,1284,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,709,0,0,0,0,0,0,554,0,0,0,0,0,0,0,0,1564,0,0,0, 443,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,729,0,0,0,348,0,0,0,0,0,0,0,758,848,298,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,829,1422,189,121,0,0,632,812,0,0,556,0,0,0,0,0,436,172, 530,844,232,984,0,0,0,0,0,0,0,0,0,0,147,0,0,0,0,0,0,0,0,537,0,0,0,0,0,859,0,0, 842,0,0,0,0,0,0,0,0,0,0,1291,0,0,0,0,0,0,0,0,0,0,0,1482,612,392,0,0,0,262,31,0, 0,0,0,0,0,0,0,0,0,753,549,0,0,0,0,0,0,696,0,0,0,0,0,0,0,834,0,0,0,0,0,771,0,0,0, 0,0,0,0,0,0,0,0,0,0,921,0,0,0,674,0,0,0,0,0,0,0,0,0,0,308,444,0,0,0,0,0,0,805, 180,0,0,278,271,0,0,214,505,0,1215,0,0,0,0,0,0,387,271,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,1645,42,92,0,459,0,0,330,1557,0,0,0,0,0,0,0,0,113,18,0,0,0, 1742,0,0,0,965,0,0,0,0,0,0,0,0,0,0,0,0,0,182,0,0,65,0,0,0,0,0,0,0,0,0,0,0,0,973, 0,0,0,0,0,328,0,0,588,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1786, 0,0,962,1985,0,0,0,308,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,588,0,0,0,0,0,0,614,793,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,290,0,0,0,0,0,0,0,0,0,0,1136,0,0,0,0,0,0,0,0,0,0,796,719,0,0, 326,210,0,0,0,701,758,472,0,0,0,1947,278,1079,0,0,0,0,0,0,497,41,0,0,634,46,961, 0,810,524,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,532,0,997,0,0,0,0,0,0,0,0,0,0,0,1301,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1298,0,671,0,0,0,306,0,0,0,0,0,0,0,0,0,0, 693,1823,0,0,0,759,0,0,0,0,0,1932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,182,0,0,0,1964, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,0,0,0,0,0,0,424,857,0,0,0,0,671,328,0, 529,0,0,0,0,0,716,0,1509,80,67,0,0,0,0,59,141,0,0,0,0,0,0,783,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1498,0,0,0,0,343,430,803,1183,677, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1357,53,0,0,0,0,590,0,0,0,0,0,0,0,0,0,0, 0,0,0,329,0,0,0,0,0,0,0,469,0,0,0,0,0,0,0,0,0,0,460,0,0,1743,0,0,963,340,0,0,0, 0,0,1603,0,0,250,0,0,0,0,0,646,218,0,1794,0,0,0,571,0,455,0,0,0,1012,0,0,0,0,0, 0,0,0,0,0,0,0,597,161,0,349,0,524,0,0,0,0,0,0,0,0,0,0,0,0,322,432,0,0,0,0,0,0, 325,223,0,0,0,0,0,566,0,0,0,1394,481,436,0,48,457,610,756,618,0,0,0,755,0,1217, 0,0,0,0,0,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,544,492,107,414,0,0,0,0,0,0,0,0,0,0,0, 1007,0,0,0,0,5,0,0,1580,0,0,0,0,0,0,0,0,0,0,0,0,0,673,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,1843,0,0,0,0,0,0,0,0,0,165,0,0,0,0,0,0,809,885,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,498,0,0,0,306,9,0,0,0,0,0,0,0,437,721,146,0,0,0,0,0,0,0,0,0,0,0,177,0,0,0,0, 0,0,0,1377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,0,959,0,0,0,1928,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1435,0,481,0,0,0,0,0,0,142,84,0,0,0,0,0, 1015,0,0,0,315,0,0,0,0,0,0,759,0,0,0,0,0,0,0,0,712,0,0,0,1722,0,0,0,0,0,0,0,0,0, 0,0,0,222,0,985,1414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1273, 538,706,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,1781,0,0,0,0,0,431,97,665,42, 237,0,0,0,264,0,0,213,0,0,0,0,0,0,0,455,0,0,0,906,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 624,0,574,0,0,0,0,0,0,0,0,0,0,0,0,354,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68, 235,723,1813,0,0,0,957,0,830,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,496,0,0,0,0,0,0,0, 547,239,88,0,0,0,0,0,0,0,0,0,1310,0,0,0,0,0,0,0,0,80,1076,0,0,118,0,0,0,479,274, 0,0,0,0,0,0,0,0,0,0,0,497,0,0,669,261,0,0,0,0,13,0,0,0,0,0,0,791,250,642,0,0,0, 1429,939,949,0,0,0,0,0,0,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,982,330,0,0,0,0,545,0,0,0,0,0,0,947,0,1188,0,0,0,0,0,904,0,0,0,0,0,1372,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,693,377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,0,0, 713,386,0,0,0,0,128,1575,0,0,0,0,0,0,424,893,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,904,0,0,0,0,0,552,322,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,1808,49,0,0,0,0, 1832,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,421,0,0,442,415,0,0,289, 0,0,0,0,0,206,110,0,0,0,0,0,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 19,1539,0,0,0,0,0,1340,0,1194,0,0,0,0,0,0,0,0,549,0,0,0,0,0,0,0,0,1720,0,0,0,0, 0,0,0,0,0,319,0,0,0,0,112,1180,0,0,0,0,0,0,0,0,0,0,0,967,0,0,0,0,0,0,0,0,0,1940, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,735,0,0,0,0,0,0,0,0,0,897,132,0,0,0,0,0,0,0, 0,0,0,38,838,0,0,0,379,218,8,660,1017,0,0,0,0,0,0,111,387,647,877,0,0,53,790,0, 0,0,0,0,0,0,0,458,0,0,0,0,0,0,954,0,0,0,394,0,1367,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,882,0,0,0,0,0,0,0,1409,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,124,342,199,0,0,0,0, 0,0,0,0,0,0,724,628,0,0,0,0,804,266,0,0,0,0,0,208,0,79,0,0,0,0,0,0,0,0,741,0,0, 0,0,0,0,0,0,0,0,606,0,1494,821,1553,0,0,135,405,0,0,178,100,0,0,0,0,0,0,0,0,0,0, 0,0,0,481,0,0,0,1378,0,0,0,0,0,0,0,0,0,0,0,0,0,791,33,1227,857,0,467,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,447,0,0,0,0,0,0,86,128,0,0,0,0,0,0,587,0,0,0,692,1018,0, 195,0,0,0,0,0,0,0,1546,0,0,0,0,0,0,0,0,0,0,0,684,0,0,345,0,0,0,0,0,0,365,0,1683, 0,0,472,0,433,0,0,0,0,0,0,0,28,0,0,0,997,0,705,3,0,0,0,0,0,0,0,0,0,229,0,0,0,0, 102,0,0,0,0,866,1022,0,0,0,0,0,0,0,0,0,55,0,115,0,0,0,0,933,0,0,0,0,0,0,0,702,0, 0,0,0,0,0,0,1728,26,484,0,0,0,185,618,417,0,803,0,0,0,0,0,0,0,0,0,0,0,1262,0,0, 0,0,0,0,0,0,0,0,0,0,0,633,0,0,0,0,0,0,0,0,0,0,0,0,0,479,262,0,0,0,0,0,0,830,0,0, 0,0,26,70,0,0,0,0,0,0,0,0,217,0,640,51,0,0,360,1586,0,0,0,0,0,652,0,0,0,0,0,766, 0,0,0,0,298,737,0,0,0,0,0,0,0,0,0,0,655,222,906,0,0,1013,991,2009,0,0,0,0,503,0, 0,0,216,154,0,0,0,716,0,844,0,0,0,0,621,252,0,0,0,0,748,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,103,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,576,0,0,0,648,0,0,0,331,0,0,0, 0,0,0,0,0,0,0,0,0,632,0,0,0,518,107,0,0,0,0,0,0,0,0,851,0,0,0,0,504,0,0,0,0,0,0, 0,0,0,0,0,0,7,883,0,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,91,993,0,0,0,0,0,0,200,131, 10,0,0,0,0,0,0,0,0,0,0,0,0,0,365,1433,0,0,0,0,28,103,0,0,798,1013,0,0,0,0,0,0,0, 0,39,1925,0,853,0,0,271,519,0,0,0,0,338,0,0,300,470,419,0,0,0,0,0,0,836,0,0,0,0, 0,0,1937,0,0,0,0,0,393,0,0,357,0,0,0,0,0,703,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,387,0,0,0,0,0,0,75,708,453,1351,0,303,0,0,772,0,0,0,0,0,0,0,0,749,0,0, 0,0,0,0,0,0,0,0,0,0,0,1065,0,0,717,226,0,0,0,0,0,890,431,626,0,0,0,0,706,0,0,0, 51,698,0,0,0,0,0,0,0,0,0,0,0,828,0,0,17,0,0,0,0,1929,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,84,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,871,498,0,101,1793,0,0,0,0,0,0,435,0, 0,0,0,0,966,0,129,1644,0,0,0,0,0,0,0,0,0,0,0,0,0,997,502,0,0,0,0,0,0,0,0,0,0,0, 0,823,0,1927,0,0,0,0,98,1756,0,0,0,0,0,0,0,0,0,0,0,0,8,0,160,1046,0,492,0,0,0,0, 0,0,129,45,0,0,0,0,0,0,353,558,0,0,0,0,0,785,0,0,0,1145,189,0,0,0,26,353,0,0,0, 0,0,2024,0,0,0,606,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,855,0,0,0,0,0,0,0,0,0,0,0, 0,0,2011,0,0,5,4,0,0,461,764,0,0,0,1449,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1445,0,0, 0,1168,0,0,0,233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,216,0,0,0,286,0,0,0, 3,0,0,0,723,536,0,0,0,0,0,285,0,0,0,560,0,0,0,0,0,690,0,0,0,0,0,1246,0,0,63,0, 33,0,0,0,0,0,520,1862,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,0,0,554,0,0,0,0,0,1001,0, 0,0,0,0,446,0,0,0,0,0,0,0,1313,0,0,837,636,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278, 0,0,0,0,0,0,0,0,868,0,0,0,0,1010,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1231,0,304,0,506,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,93,1408,794, 843,704,0,285,114,485,898,145,0,19,2035,0,0,0,1933,0,0,0,0,0,0,0,1728,0,0,0,0,0, 0,0,0,746,0,0,0,0,0,0,0,995,1964,0,0,0,0,0,0,0,0,0,0,0,1550,0,874,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1018,0,0,0,814,126,0,0,1264,0,0,814,955,0,0,0,0,0,0, 0,981,0,0,0,0,0,0,0,0,915,56,0,0,100,0,0,0,0,0,0,0,0,0,638,0,0,0,0,738,0,0,0,0, 0,0,0,0,0,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1112,0,0,214,0,0,0,133,0,196, 168,0,0,0,0,0,1152,0,1245,0,0,538,169,871,1816,0,0,413,133,0,0,0,978,0,0,43,93, 371,0,0,0,0,0,0,526,25,0,754,335,0,0,0,0,182,0,0,0,0,0,0,0,0,0,0,0,39,601,0,0,0, 0,0,0,0,181,370,0,0,1652,358,0,0,0,0,0,0,0,0,0,176,286,0,788,0,0,0,0,0,1223,780, 254,1003,896,0,0,0,1447,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,126,0, 41,788,0,0,0,629,0,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,420,37,1900,0,0,0,0,542,1570,957,0,0,0,0,0,0, 0,373,31,0,0,0,0,125,325,0,0,0,0,0,0,323,0,0,1547,0,0,0,0,0,0,0,0,0,0,0,0,0, 1216,0,0,0,0,0,0,198,1905,629,15,0,0,0,0,0,0,20,75,543,1353,0,0,0,533,0,0,6,0,0, 0,0,0,0,538,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,11,0,0,0,284,659,0,989,0,0,0,0,0, 0,0,0,0,848,0,0,507,0,0,0,0,0,0,0,0,188,991,884,0,0,0,0,60,959,0,0,0,0,0,1653,0, 0,922,337,0,638,0,0,500,0,0,0,0,0,0,0,0,0,0,0,166,0,0,0,0,0,0,0,0,0,0,0,0,418,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,760,0,0,0,0,0,0,1277,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,243,89,0,0,0,0,0,0,0,0,0,1396,0, 560,0,0,3,1658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,586,0,0,1271,0,0,0,505,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1947, 41,445,0,0,0,0,0,0,0,0,57,189,0,0,371,0,0,0,0,552,0,883,0,923,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,875,0,0,0,1788,49,0,0,0,0,0, 0,0,0,0,0,0,661,0,0,1945,0,0,0,0,0,794,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1135,0,0,0,745,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,410,0,976,0,0,0,0,0,703,0,0, 0,0,0,0,187,322,0,0,0,227,0,0,0,0,560,0,31,1395,0,0,0,0,0,466,0,0,0,0,643,167,0, 0,0,1428,0,412,0,0,0,0,0,0,0,0,0,1118,562,0,0,0,0,0,256,0,0,0,0,0,0,1771,0,0,0, 0,0,1190,132,0,66,0,0,0,0,0,0,0,0,0,0,317,0,0,0,63,0,0,0,0,0,0,0,1475,0,0,0,0,0, 0,0,288,0,0,0,0,608,0,0,0,0,0,0,0,0,1225,0,1189,0,0,0,0,0,0,0,1468,0,0,0,0,0, 689,120,0,0,0,0,0,0,0,1,0,329,0,0,0,0,226,0,0,0,0,0,1855,0,0,461,0,0,0,0,1346,0, 0,0,0,0,85,0,0,299,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1171,0,0, 0,980,0,0,0,0,0,0,0,0,637,279,0,0,0,0,0,293,0,0,0,0,528,17,0,0,0,0,5,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,601,0,0,0,0,0,0,779,0, 196,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1322,737,752,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,412,192,80,0,0,8,1470,0,0,0,0,0,0,0,0,0,873,0,0,0,0,0,835,0,0,0,0,256, 38,986,0,0,0,0,0,0,0,0,0,91,257,278,911,0,0,0,0,0,0,0,0,749,151,0,0,0,0,0,0,0,0, 0,0,0,0,989,0,0,990,0,0,90,194,0,0,0,0,0,425,0,0,0,0,0,774,0,0,0,0,0,0,0,0,0,0, 646,827,752,0,0,0,662,0,22,21,0,0,0,0,0,0,95,239,0,0,0,431,0,0,0,0,0,874,0,0, 265,65,0,0,0,1350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1887,0,0,0,0,0,0,0,809, 0,696,0,1074,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,802,0,0,0,56,776,0, 970,0,0,797,0,0,0,0,0,400,0,0,1951,0,0,41,0,11,118,0,0,0,0,0,0,0,0,251,615,0,0, 0,1044,0,0,0,0,0,0,0,0,0,0,0,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,370,0,0,0,0, 104,48,209,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,930,0,0,0,0, 0,0,0,0,0,0,0,1286,0,759,0,120,385,0,0,0,429,0,0,0,0,0,0,0,0,820,0,0,0,0,0,0, 199,0,10,151,0,0,0,761,365,0,0,0,0,0,0,0,0,0,46,1086,0,0,0,0,11,1624,58,344,0,0, 1008,1868,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,711,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,440,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,914,1913,0,958,0,885,0,0,0,0,0,0,0,0,0,0,0, 0,0,847,276,0,302,65,0,0,0,510,0,1514,0,0,0,0,0,0,152,291,0,0,0,0,0,0,0,0,0,0,0, 0,282,589,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,463,42,0,0,0,0,0,372,0,0,0,0,0,0,0, 0,0,680,0,0,0,0,0,0,0,0,977,1997,0,0,0,810,0,0,0,0,0,0,0,0,0,1390,0,0,0,644,0,0, 867,982,0,0,0,0,0,0,0,540,0,123,0,0,0,1978,0,0,0,0,789,623,0,1723,0,1220,0,0,0, 0,0,0,0,480,0,0,0,0,0,0,0,0,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,299,1995,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,788,179,0,0,0,0,0,0,431,156,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1373,39,80,196,0,0,507,0,0,0,646,0,0,0,0, 0,1214,0,0,0,0,926,0,0,0,1,114,0,0,0,0,0,446,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,490,0,0,0,491,0,1584,0,0,507,250,0,0,0,158, 10,362,1,0,0,0,0,0,0,0,0,0,408,228,860,480,0,779,0,0,0,557,0,0,142,197,0,0,0,0, 0,0,0,0,0,0,0,1490,11,378,316,1057,0,0,18,579,299,1546,0,177,0,0,0,0,0,0,0,0,0, 411,0,0,0,0,727,439,0,0,0,0,0,1528,0,0,0,0,0,0,58,0,482,0,0,0,505,1952,0,0,0,0, 0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,953,0,0,0,0,802,0,0,0,0,0,0,0,0,0,0,290,0,0,791, 52,0,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,1028,0,0,138,0,0,0,0,1811,0,0,0,0,0,0, 934,1821,0,0,0,0,371,38,0,0,0,1296,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,723,0,0,0,0,0, 0,0,0,0,0,0,0,0,1330,0,0,0,0,0,0,0,1255,296,109,0,0,0,0,0,660,0,0,0,0,270,591,0, 0,0,0,0,0,0,1090,81,0,0,0,0,391,0,0,0,0,249,322,0,0,0,0,0,0,0,1412,0,0,0,0,0,0, 0,0,0,0,526,632,0,0,0,0,0,0,235,144,0,0,0,0,0,940,0,0,0,52,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,309,196,0,0,0,0,0,1912,0,1290,0,686,0,0,625,0,0,0,0,0,0,0,0,0,0,0,412,0, 0,0,0,43,0,0,0,0,11,967,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,0,0,0, 873,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,890,0,0,2,0,0,0,0,0,0,0,0,1774, 393,263,0,0,0,0,0,0,818,456,0,0,251,178,393,97,0,0,0,0,0,674,168,0,0,0,0,0,0,0, 159,1639,0,0,0,0,0,0,0,0,59,934,0,191,0,0,0,0,346,165,0,877,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,128,0,0,0,0,0,0,1297,0,0,0,0,0,0,164,0,0,0,15,132,241,1073,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,324,53,0,0,910,0,0,0,0,0,0,0,0,734,705, 217,73,0,0,0,0,0,0,0,0,636,389,0,1409,0,0,0,0,0,893,0,0,0,0,21,0,0,0,0,0,0,0,0, 0,0,0,0,0,721,0,0,0,959,0,0,0,0,1433,0,0,0,0,0,0,0,0,0,0,0,0,174,189,0,0,0,0,0, 0,0,0,0,0,22,2,0,0,815,354,0,0,0,0,425,0,411,60,13,1611,0,0,0,0,0,0,0,0,0,0,0,0, 0,1478,596,0,0,398,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,1159,0,0,0,0,0, 592,223,0,0,0,0,0,0,0,245,64,0,0,0,0,278,0,604,0,0,1502,265,0,0,0,0,0,0,0,310, 1763,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,1356,0,0,0,0,0,0,0, 0,505,0,0,0,0,0,0,0,1000,0,0,966,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0, 0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,590,0,0,0,0,280,0,0,0,1386,0,0,0, 281,0,1064,0,0,0,0,0,917,0,0,15,555,0,0,1014,1883,0,0,0,965,0,0,117,33,0,0,0, 801,0,0,0,0,0,877,0,824,0,0,0,0,0,0,0,0,0,0,0,365,0,0,0,0,0,0,774,7,0,430,0,0, 231,360,0,0,0,0,0,0,0,0,822,740,0,0,929,1485,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,852,0,0,0,0,17,0,0,0,0,0,0,1001,0,0,0,0,35,831,0,0,384,457,0,0,0,1351,0,27, 0,0,984,0,264,552,0,401,0,0,0,710,0,1211,0,0,11,205,0,0,0,0,0,0,0,0,0,0,0,0,5, 579,0,717,0,0,1011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,0,0,489,0, 0,0,1024,0,0,0,0,0,0,0,0,0,892,0,0,0,0,0,0,0,0,0,0,0,0,473,0,0,0,659,864,0,0,0, 0,0,0,152,819,0,51,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,229,0,0,0,0,674,0,0,0,0,0, 0,0,0,0,770,52,79,0,0,0,1666,0,409,0,0,0,0,0,0,0,195,0,688,0,0,0,0,0,0,0,0,0,0, 0,889,174,160,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,918,569,268,0,0,0,1224,0,1361,0,0, 0,0,0,0,0,0,0,374,0,0,0,0,0,731,0,0,0,0,190,0,0,0,0,0,0,0,202,506,444,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,835,0,17,1526,0,0,0,0,0,477,0,0, 994,1374,76,0,0,0,0,0,0,0,355,287,0,1389,0,0,0,0,0,0,455,384,0,0,0,264,0,0,0,0, 0,0,0,0,0,0,0,0,1001,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,851,175,359,0,0,0,0,0,0,0, 0,287,740,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,857,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 819,1402,0,0,0,0,0,0,174,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1649, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,655,573,0,0,0,0,0,0,0,0,128,351,0,0,0,0,0,0, 0,0,0,0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,687,0,0,0,0,0,0,0,0,0,1525, 0,0,0,1009,0,0,0,0,0,0,0,340,0,0,0,0,0,0,0,0,0,0,861,0,176,0,0,0,0,0,0,0,0,0,96, 985,0,615,0,0,0,0,0,0,0,1919,0,0,0,0,0,1131,0,0,0,0,0,0,0,247,0,0,0,0,27,23,0,0, 0,0,0,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,1088,0,0, 0,0,0,1585,0,0,0,0,227,0,0,0,478,360,0,0,0,95,0,0,0,0,0,0,699,0,0,0,26,0,0,0,0, 1119,0,0,0,739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,741,67,0,0,0,0,0,0,464,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,0,96,0,0,0,26,342,0,0,0,0,0,0,203,0,0,449,0, 0,0,0,0,0,0,0,0,0,256,311,0,0,0,0,0,0,758,0,0,0,0,0,0,0,0,827,0,0,0,0,581,64,0, 1047,0,0,0,0,0,288,0,0,0,0,0,1375,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0, 376,12,0,0,0,0,0,154,0,1520,0,1753,95,502,0,0,0,0,0,0,0,269,291,1197,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,1341,0,1017,0,0,0,0,0,0,0, 0,857,1810,533,0,0,1453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,836,211,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,19,0,156,0,0,0,0,1009,0,0,0,0,0,0,0,0,0,0,0,0,0,820,0,0, 0,0,0,0,0,0,0,228,0,0,0,1131,0,1276,0,0,0,0,0,0,0,0,0,0,0,0,849,1792,0,0,389, 291,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,525,0,0, 0,453,0,0,0,0,666,0,0,0,422,0,355,0,0,0,0,165,0,260,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,865,0,0,0,0,0,0,0,1625,0,0,0,234,0,1383,0,0,0,0,0,0,0,0,306,0,0,0,802,1921, 0,0,0,0,0,0,180,0,0,0,0,1312,814,0,0,0,0,0,0,0,0,0,0,707,0,0,0,1493,11,61,733,0, 0,0,341,0,0,0,98,0,0,0,0,0,0,0,0,0,0,0,1014,0,0,0,0,0,0,0,142,102,0,0,30,0,0, 823,0,1045,0,0,0,1930,0,1512,0,0,0,0,0,0,0,87,0,1243,245,0,0,0,0,0,0,0,48,68,0, 0,0,0,0,0,0,0,126,77,625,938,0,0,351,0,0,0,174,1668,0,707,0,0,0,0,0,0,0,0,0,0,0, 403,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,282,0,0,0,0,0,0,8,44,0,0,363,115,0,0,0,0,0,0, 0,0,0,0,0,0,545,761,0,0,835,1254,0,0,0,0,930,1936,0,0,0,0,0,0,0,0,653,0,0,0,0,0, 344,0,0,1483,673,185,0,0,460,93,753,478,0,0,0,0,0,1020,0,0,0,0,0,0,0,103,0,0,0, 499,0,0,0,0,0,0,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,968,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,3,0,0,0,0,399,0,0,0,0,224,563,0,0,0,0,0,704,0,0,0,0,0,0,0,0,0,0,0, 1559,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,861,0,0,0,0,946,333,746,0,0,0,0,0, 0,0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,652,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1393,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1514,0,0,0,0,201,0,510,717,0,0,528,0,0,0,0, 20,0,0,0,1251,0,0,0,1163,0,0,0,307,0,0,0,0,0,1091,0,0,0,0,0,0,0,0,0,0,0,429,0,0, 0,881,0,0,0,0,0,621,0,0,0,0,0,0,0,736,0,348,0,868,0,0,0,0,433,0,0,0,771,1495,0, 0,0,0,215,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,0,0,55,0,0,0,0,0,0,0,112,62,0,856,270, 0,572,0,0,0,0,939,0,0,0,0,0,0,0,352,0,0,0,0,0,0,0,0,0,647,0,0,0,0,10,0,0,0,0,0, 0,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,464,0,0,109,0,0,0,1746,0,0,0,515,0,0,0,566,0, 0,0,0,0,0,67,40,0,0,722,992,0,0,923,0,0,0,0,0,0,1145,0,0,0,0,0,0,0,0,0,0,0,568, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,0,0,0,0,645,0,0,328,0,0,0,0,0,0,0,0,0,0,0,0, 1363,0,0,0,0,0,1280,0,0,0,0,0,0,0,0,0,0,7,28,360,162,0,0,0,0,0,0,0,0,0,0,0,764, 0,0,833,862,0,856,0,0,0,0,0,0,736,92,0,0,948,1944,0,1479,63,590,0,0,0,1521,0,0, 0,709,0,0,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,1213, 0,0,0,0,29,1022,0,1712,0,466,0,0,0,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,171,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,964,2005,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1100,0,0,0,954,0,0,0,0,0,0,0,0,0,1958,0,0,34,549,994,0,0,449, 137,850,0,0,670,146,0,0,0,0,518,159,0,0,0,0,0,0,0,0,151,0,0,1027,0,0,0,0,0,0,0, 0,0,0,983,0,0,0,0,993,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,141,501,0,0,0, 0,0,0,0,0,0,452,0,0,0,0,0,0,0,0,0,0,233,149,0,0,0,0,0,0,0,0,582,0,0,0,801,0,0,0, 0,0,0,70,0,0,369,0,36,0,0,0,0,0,0,0,204,721,430,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1817,16,1078,1021,0,0, 406,0,0,0,0,0,69,0,0,0,0,0,1830,0,0,0,824,0,0,0,0,0,0,0,0,0,826,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,816,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,717,1845,0,423,0,0, 0,0,0,0,0,0,510,0,0,1048,0,0,0,618,0,0,0,520,0,0,0,0,990,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,321,0,0,0,0,0,0,0,1135,0,0,921,0,0,0,24,397,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,856,0,0,0,139,282,981,0,288,0,0,0,1890,651,56,0,0,0,0,0,0,0, 0,261,0,0,0,0,0,0,0,0,0,0,0,617,1403,0,1205,0,0,563,0,0,0,0,0,0,0,0,333,0,0,0,0, 0,369,0,0,0,0,0,0,0,0,0,622,0,0,0,1407,0,0,0,0,0,0,0,0,0,0,0,0,624,160,0,363,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,619,0,174,292,0,0,656,616,0,0,0,685,0,0,0,0,0,0,0,0,0,0,0,0,0,647,0,0,0,631,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1267,0,0,0,1797,0,0,0,1684,0,0,469,0,531, 1230,73,0,0,0,0,0,0,0,0,0,268,0,0,0,0,0,102,558,109,65,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,595,0,0,0,0,0,374,1832,0,0,0,0,0,0,16,0,405,6,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,881,0,1495,0,0,0,0,0,0,0,0,0,142,0,0,0,0,0,0,0,0,0,0,21,466,23, 257,0,0,0,0,0,0,77,404,0,0,0,0,0,0,712,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,860, 1848,0,0,652,629,0,0,0,0,13,377,0,1842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1501,0, 0,0,1906,0,0,0,0,0,0,0,0,0,0,0,0,0,491,234,171,0,0,0,0,631,1186,0,0,0,0,0,0,0,0, 0,0,0,0,931,0,170,0,0,0,0,0,0,0,0,0,0,1587,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 765,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,424,0,0,714,0,0,0,0,685,0,0,0,0,0, 0,285,0,0,0,0,0,0,429,0,0,0,0,0,0,0,0,0,0,71,18,0,0,0,0,0,0,0,0,0,0,116,828,0,0, 0,0,0,0,289,0,0,0,0,0,0,0,0,675,0,0,0,1424,0,0,0,0,0,647,0,0,0,1334,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,36,209,0,0,0,0,0,0,0,342,0,0,0,928,0,0,0,0,0,1838,118,856,654, 318,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,915,895,454,0,0,513,1425,0,0, 0,0,0,0,791,0,153,0,0,0,0,0,0,796,909,445,345,0,0,0,0,0,0,0,0,578,0,0,0,1387,0, 0,0,555,0,0,0,0,0,0,766,0,0,0,0,0,0,0,0,0,0,541,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0, 0,0,0,0,1506,0,0,983,0,768,0,0,0,0,584,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,737, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,30,426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,462,0,0,0,385,0,398,0,0,0,0,0,0, 0,0,0,347,0,0,0,0,125,1259,644,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,469,0,0,0,0,0, 1367,0,0,0,0,0,0,0,0,0,0,0,719,0,0,0,0,0,0,0,0,0,0,0,0,0,1423,0,0,0,0,0,0,0,0,0, 749,0,0,0,0,546,645,0,0,0,0,0,0,277,0,0,1275,0,0,0,0,0,0,0,453,536,555,0,0,987, 1107,0,0,90,0,0,0,0,0,0,0,0,860,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 257,0,1768,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,83, 0,835,0,0,0,0,0,0,0,2006,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,696,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,95,1718,0,0,0,0,0,0,0,26,0,550,0,0,0,0,0,901,0,0,0,0,0, 0,822,0,0,122,0,0,0,807,0,0,0,0,0,262,0,620,601,34,0,0,170,0,0,0,0,537,0,0,0,0, 0,0,0,0,0,332,0,0,208,1909,182,261,0,0,0,1721,0,0,0,0,0,933,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,1609,0,895,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,812,0,0,942,1916,0,0,0,0, 0,0,0,778,0,0,0,137,0,1314,0,0,0,0,0,0,0,1661,0,0,0,0,0,0,0,1591,0,0,0,0,0,0, 820,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,89,0,1160,230,6,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,63,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1740,0,0,177, 170,0,1961,0,0,0,0,0,0,0,0,0,0,0,0,91,0,17,44,0,0,0,0,0,0,0,0,0,270,0,296,0,0,0, 0,0,0,0,1523,0,0,0,0,0,0,0,0,0,0,757,7,0,0,0,0,0,0,0,0,0,0,530,588,0,0,0,0,0,0, 0,0,0,786,0,0,0,0,0,580,627,88,447,57,0,0,0,0,0,0,0,0,845,735,0,0,0,0,0,31,15,0, 460,521,12,424,0,0,0,1302,0,0,0,0,0,0,0,595,0,0,0,13,548,97,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,1472,452,1767,0,0,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,1543,0,1111,0,0,0,0, 1,0,359,488,0,267,0,0,0,1983,0,0,0,0,0,0,0,1155,0,1575,0,1438,31,0,0,377,101,0, 0,0,0,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,0,0,0,2023,0,0,0,0,0,1836,0,0,0,0,35,843, 0,0,0,0,0,0,0,554,0,0,0,536,625,207,0,1371,0,0,0,424,785,336,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,896,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,750,0,0,0,0,238,0,0, 0,0,0,383,0,0,0,0,0,0,0,0,603,725,11,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,1552,0,0,0, 0,0,0,0,680,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,435,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1431,0,0,13,112,0,0,356,0,0,0,0,0,0,0,0,0,0,1963,0,0,0,1244,18,0,0,0,0,0,0,867, 0,0,0,0,0,0,50,708,73,592,0,502,0,0,0,0,0,0,161,347,0,0,0,0,470,33,0,246,571,10, 0,465,614,0,237,0,0,0,0,0,24,18,0,506,0,0,0,0,0,0,33,309,0,0,0,0,0,0,0,0,0,0, 140,0,0,0,0,1056,0,0,0,1704,0,0,0,0,0,0,0,1036,0,0,0,0,0,0,0,0,0,1315,432,86, 264,524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,107,0,0,0,0,0,123,927,0,0,957,1149,0,0, 0,0,0,778,0,502,196,0,0,0,0,1312,0,0,0,0,0,0,0,855,0,0,0,0,0,0,0,0,0,0,45,1400, 0,0,0,1003,0,0,0,0,0,1097,0,0,0,0,0,0,0,0,545,612,0,0,0,0,0,0,0,0,0,0,0,0,54,0, 0,0,0,172,0,0,0,1029,0,0,0,0,0,0,0,0,0,568,0,0,0,732,617,0,0,974,94,989,733,0,0, 0,0,0,0,1789,0,0,665,2015,0,0,0,0,0,0,806,287,0,0,0,0,0,1539,0,0,0,0,0,0,0,0,0, 0,182,1563,0,0,0,0,0,0,0,0,0,484,0,0,0,0,0,1623,0,0,0,0,0,0,0,0,878,1833,0,1569, 0,0,0,0,0,0,0,0,93,0,715,994,0,0,0,0,0,63,0,591,0,0,0,0,0,0,0,749,0,0,0,0,547, 366,0,0,0,1747,0,0,0,0,0,0,0,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1463,0,772, 893,0,0,0,48,0,0,941,0,0,690,1785,106,440,0,0,0,0,0,0,0,0,0,0,32,0,332,216,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,852,0, 0,416,564,0,918,0,1764,0,0,3,0,0,274,0,0,0,0,501,0,0,0,0,0,0,0,851,743,0,49,0, 879,0,0,47,0,0,0,0,0,0,865,0,1202,0,0,0,0,0,0,47,272,0,0,0,0,0,0,0,0,0,0,0,1455, 0,0,0,0,891,1911,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,761,0,0,0,0,0,0,0,0,0,407,0, 183,0,0,490,0,0,0,0,0,0,0,35,731,0,0,0,0,0,0,0,819,0,0,0,0,0,0,0,0,0,0,0,0,0, 575,0,0,0,0,45,818,0,0,77,222,0,0,0,0,849,1880,0,0,0,633,0,1308,0,0,0,0,0,0,0,0, 0,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,817,0,0,0,0,0,0,0,0,0,882,0,0,0,914,0,0,0,0, 0,0,0,0,0,0,865,0,0,426,399,58,0,0,0,0,0,0,538,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,566,0,63,12,0,0,0, 0,0,0,0,0,0,0,0,0,0,3,114,0,0,0,0,0,0,0,0,576,0,0,0,0,0,0,0,0,933,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,692,0,0,0,0,0,0,0,0,0,0,0,0,752,0,0,0,0, 0,0,0,0,375,0,1011,0,0,96,0,0,0,0,0,0,0,0,0,148,0,0,0,0,0,0,0,0,0,0,0,337,56, 666,0,246,394,0,0,0,0,0,0,0,0,437,0,0,0,506,0,0,0,0,1003,0,1163,0,328,0,0,0,0,0, 0,0,0,1000,0,0,0,0,0,744,101,0,0,0,0,0,726,0,0,176,0,146,9,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,246,1931,29,0,0,1771,0,0,0,0,0,846,6,157,0,0,0,0,0,0,0,0,0,875,0,0,477, 773,177,639,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1747,0,0,0,0,158,873,0,659,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,391,0,0,0,0,0,0,0,0,0,0,0,0,668,883,0,78,628,0,0,0, 0,0,0,0,0,0,0,0,0,1460,0,962,0,0,0,0,0,460,0,0,0,0,0,0,0,0,0,0,0,0,0,0,34,199,0, 0,0,388,474,0,271,0,333,608,0,0,0,0,0,0,49,0,988,0,707,617,0,0,0,0,0,0,0,756,0, 0,0,0,0,1583,0,0,0,0,0,0,0,0,0,0,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,344,0,0,0,0,0, 0,0,0,515,1709,0,0,0,0,0,0,0,0,404,0,0,0,0,500,0,0,0,0,0,0,0,0,0,68,216,0,0,0,0, 0,0,0,488,353,0,0,177,236,0,0,458,490,0,0,0,0,0,0,756,1504,0,757,0,1735,0,0,108, 598,0,0,0,0}; BROTLI_INTERNAL const uint8_t kStaticDictionaryHashLengths[32768] = { 8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,4,22,5,0, 4,0,0,0,0,0,0,0,0,0,0,0,0,14,6,0,0,0,5,0,0,0,0,0,0,0,7,13,0,0,4,0,0,0,0,0,0,0,0, 0,6,0,0,0,0,8,0,0,0,0,0,0,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,4,0,5,13,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,9,0,8,0,0,0,0,0,0,6,0, 0,9,0,0,0,11,0,0,6,8,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,6,8,0,0,0,0,0, 0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0,8,4,13,7,0,0,0,0,0, 7,0,5,0,0,0,0,8,5,0,5,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,8,0,0,0,10,4,0,5,0,4, 0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,8,7,0,4,9,4,0,0,0,0,0,0, 9,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,7,18,0,0,0,0,4,9,0,0,4,0,6,0,0,0,6,0,6,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,0,0, 0,9,0,0,0,0,0,0,0,8,6,10,6,0,0,0,4,0,6,8,6,0,0,0,4,0,0,0,0,0,5,0,0,0,6,0,0,0,0, 10,0,12,7,0,0,0,0,0,4,0,0,0,0,0,5,0,0,8,7,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0, 0,0,0,0,6,11,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,6,10,0,17,0,8,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,6,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 7,0,0,11,4,0,5,0,0,0,0,0,0,0,0,0,0,10,5,0,6,8,5,0,0,0,0,0,0,0,0,0,0,11,5,0,0,0, 0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,0,0,0,0, 0,0,0,0,0,0,5,0,0,0,6,0,0,10,0,0,0,20,0,0,0,0,0,0,0,0,6,9,5,0,0,0,0,10,4,8,0,0, 4,13,0,0,0,0,0,0,0,9,0,9,0,0,0,0,0,0,0,0,0,0,0,0,4,8,6,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,12,5,0,0,10,4,10,7,13, 0,0,0,0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,19,0,0,4,12,6,9,0,0,0,0,4,0,4,11,0,0,0,0, 0,0,0,12,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0, 0,5,0,0,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,9,6,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0, 6,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,6,0,0, 0,0,0,5,0,0,0,0,14,4,0,0,0,4,12,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0, 0,0,0,0,0,12,0,9,6,0,0,0,0,13,0,0,5,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,13,0,9,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,8,7,8,4,0,0,0,0,0,0,0,0,0,0,0,7,0,7,0,0,0,4,0, 0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,8,4,0,0,0,0,0,6,0,7,0, 0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,0,9,5,0,0, 0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,4,0,0,0,0,0,0,0,4, 12,5,11,0,0,0,0,0,0,0,0,0,8,7,0,5,0,0,8,7,0,5,0,0,0,0,8,0,0,0,0,7,0,4,10,0,0,0, 0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 13,5,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,14,5,0,0,0,7,0,0,10,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,6,0,4,0,5,0,0,0,0,8,5,0,0,0,0,0,0,9,5,9,0,0,0,0,0,0,0,0,6,9,0, 0,4,0,0,0,7,0,0,0,6,0,0,10,4,0,0,0,0,0,6,0,0,10,0,0,0,8,5,0,0,0,0,0,0,0,0,10,0, 0,0,0,0,18,4,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,7,0,0,0, 0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, 0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0, 0,4,8,7,0,0,8,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0, 0,0,0,8,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0, 0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,8,7,0,0,0,0,8,0,12,6,0,6,0,0,0,0,9,7,11,7,0,0,0, 0,0,0,0,0,0,0,0,0,11,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0, 0,0,0,6,0,0,0,7,0,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,14,0,0,0,0,0,8,4,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,20,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,12,5,0,7,0,5,0,0,10,0,0,7,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,6,0,4,9,7,0,0,0, 0,0,7,0,0,0,0,0,0,10,0,9,0,9,0,0,0,0,0,0,0,0,4,9,0,0,0,0,6,0,0,0,0,0,0,0,0,11,4, 0,6,0,0,0,0,0,0,8,0,8,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,13,6,0,0,11, 0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,6,18,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0, 0,5,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,11, 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,0,8, 6,0,0,0,0,0,0,9,6,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0, 0,6,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,6,0,0,10,6,0,0,0,7,0,0,8,0,8,7,0, 0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0, 0,0,0,8,7,0,0,0,0,0,0,0,0,12,0,12,0,0,0,11,6,0,5,0,0,12,0,12,5,0,7,11,6,0,0,11, 0,0,0,12,0,0,4,12,7,8,6,0,0,0,0,8,5,0,0,0,0,0,0,0,4,11,0,0,6,0,7,0,0,0,0,0,0,0, 5,0,6,0,0,0,0,8,0,10,0,0,0,0,0,0,0,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0, 0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,0,10,0,0,5,0,0,12,6,0,0,0,0,0,0,10,6,0,0,0,0,8, 6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,5,0,0,0,0,11,0,10,6,0,0,8,6,0,0,0,6,0,7,10,6,0, 0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,10,7,0,0,0,0, 10,6,0,0,0,0,0,0,8,5,11,0,8,4,0,0,0,4,0,0,0,0,9,4,8,0,0,0,0,0,0,0,11,6,0,0,0,0, 10,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,7,0,0,11,0,0, 0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, 0,0,0,0,13,0,8,6,13,0,0,0,11,7,0,7,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,9,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0, 0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0,0,4,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0, 5,11,5,0,0,0,0,0,0,0,0,0,4,0,7,0,6,0,0,0,6,20,0,0,0,10,7,0,5,14,4,0,0,0,0,0,0,0, 0,0,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0, 0,0,6,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,11,6,15,0,0,0,0,0, 10,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,9,7,13,0,0,0,0,0, 0,7,0,0,8,6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,0,0,0,0,0,0,0,0,0,0,12,6,8,0,12,0,0,7,0,0,0, 0,0,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7, 14,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,8,7,10,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,18,6, 14,7,0,0,0,0,0,0,0,0,11,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,11,7,0,0,10,7,0,0,0,6,8,6,0,0,0,0,0,0,0,6,0,0, 19,0,0,0,9,5,0,0,0,0,0,0,11,7,0,0,0,7,0,6,0,0,11,0,0,0,0,4,8,0,0,0,0,0,0,0,0,6, 0,0,0,0,0,6,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7, 0,7,0,0,0,7,15,0,0,5,0,0,0,0,10,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,7,0,0, 0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 11,7,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, 0,0,5,0,4,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,6,0,0,8,5,14,0,0,4,0,0,0,7, 17,0,0,0,0,0,0,0,13,5,0,0,0,0,0,5,0,0,0,5,0,0,0,0,16,6,0,4,0,0,0,0,0,0,12,0,0,0, 0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,5,0,5,0,6,10,0,12,0,0,0,0,0,0,0,0,7,0,0,0,0,8,4, 0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,0,0,0,8,0,0,6,0,7,0,0,0,5,0,6,0,4,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,22,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0, 0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,18,0,0,0,9,4,0,0,8,0,9,7,0,0,0,0,0,0,8,6,0,0,0,0, 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,7,0,0,0,6,0,0,14,0,0,0,0, 0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,7,10,4, 0,6,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,6,0,0,0,0,0,0, 0,0,11,6,12,7,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,9,6,11,6,0,0,0,0,9,5,0,0,0,0,0,0, 0,6,8,5,0,0,0,0,8,0,10,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9, 5,10,7,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,8,7,0,0,0,6,0,0, 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0, 0,0,0,0,0,17,0,0,6,0,6,12,4,19,6,0,0,0,0,16,0,0,0,0,7,15,7,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,10,4,0,0,8,7,0,7,0,0,9, 4,0,6,0,0,0,4,0,5,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,10,0,0,0,0,0,11,7,0,0, 0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8, 0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,8,7,0,0, 0,0,0,0,0,6,0,0,0,4,0,0,11,4,0,0,12,7,0,0,0,0,9,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0, 4,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,9,4,0,6,0,0,0,0,0,4, 0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,7,9,6,0,7,0, 0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,0,0,10,6,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,4,8,0,0,0,0,0,9,7,0,0,0,0,0,0, 13,5,0,0,0,0,8,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,5,0,0,11,7,0,0,0,0,0,0,8,6,0, 0,0,0,0,7,0,4,0,0,0,0,0,0,0,5,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,10,4,9,0,0,0,0,0, 0,4,0,0,0,0,10,5,10,7,0,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,0,0,0, 0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,4,0,0,0,7,0,0,0,0,0,0,13,0,0, 0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,13,7,0,7,0,4,16,0,0,0,0,6,8,7,9,7,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0, 0,6,0,0,8,5,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,11,7,0,0,11, 0,0,0,0,0,9,5,0,4,0,0,0,0,9,7,8,6,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0, 0,7,0,0,0,0,0,0,0,0,0,0,0,4,10,6,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,10,7,10,0,0,0, 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,6,8,7,12,4,0,0,0,0,0,0,0,5,14, 0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0, 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,20,4,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0, 0,6,15,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,12,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0,18,0,0,0,10,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,9,6,0, 6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,9,0,9,0,0,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,9,5,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,7,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,8,0,0,0,16,0,0,0,0,0,0,0, 0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,0,0,11,0,0,0,0,0,0,0,0,0,0, 6,0,0,0,0,11,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,7,0,6, 0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6, 0,0,0,0,0,0,0,6,0,0,18,0,8,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0,4,0,0,0, 0,0,0,0,0,0,0,8,0,0,0,0,0,16,0,0,0,0,0,16,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,18,0,0,0,0,0,0,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,4,0, 0,0,0,0,0,0,0,9,4,0,0,0,0,12,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,5,0,0,10,6,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,11,0,0,6,0,6,0,0, 0,7,0,0,0,0,0,0,8,0,0,0,0,6,0,0,0,0,0,0,19,0,0,0,12,0,9,0,0,0,0,0,10,7,0,0,0,0, 0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,16,7,12, 0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,10,5,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,4,0,0,9,0,0,0,8,0,12,4,0,0,0,0, 0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0, 0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,8,6,0,6,0,0,0,0,0,0, 0,4,0,0,0,0,0,6,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,10,6,0,0,0,0,8, 6,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,6, 10,7,0,0,10,5,11,6,0,0,0,0,0,7,16,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0, 0,0,0,0,0,8,7,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,12,7,0,7,0,0,0, 0,0,0,0,6,0,0,0,0,9,0,0,0,23,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,4,0,0,11,7,10,0,0, 0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,7,0,0,8,7,8,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0, 0,0,0,0,18,6,8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11,0,0,0,9,7,12,6,0,0,0,0,0,0,0,0, 0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,6,10,0,0,0,9,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,6, 10,7,0,0,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0, 0,0,0,8,7,8,6,0,0,11,7,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,4,8,7,0,0,0,0,0,0,0,0, 0,5,0,0,13,0,0,0,0,5,0,0,9,7,0,0,0,0,0,0,0,4,0,0,11,0,0,7,0,0,0,0,0,0,0,0,0,6,0, 0,0,0,0,0,12,7,19,0,8,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0,0,0,0,0,0,0,0,0, 6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,0,0,12,0,0,0,0,6,9,6, 14,0,0,0,0,0,0,6,0,5,0,0,8,7,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0, 7,0,0,10,0,9,7,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,0,0,0,0,5,0,6,0,0,0,0, 0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,13,7, 0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,11,5,0,5,13,0,8,0, 0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,11,5, 9,6,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,10,0,0,0,8,5,0,0,9,0,0,0,8,7,9,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0, 0,11,0,13,6,0,0,9,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0, 0,0,0,0,0,5,21,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,5,0,0,0,0,0,0,0,0,10,0,8,0, 0,6,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,4,0,0,8,6,0,6,0,7,10,0,8,4,0,4,0,0,0,0,0, 5,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,12,0,0,7,0,0,0,5,0,0, 0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 15,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,24,7,0,0,0,0,0,0,0,0,0, 7,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0, 0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,12,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,15,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0, 0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,9,0,9,6, 0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,4,0,7,0,0,0,0,0,0,0,0, 22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,7,0,0,21,7,0,7,9,6,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,6, 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,23,0,0,0,0,7,0,0,0, 4,0,0,0,0,0,0,0,0,9,4,11,7,0,5,0,0,0,0,11,0,0,4,20,0,0,0,0,0,0,0,0,0,0,0,11,5,0, 7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 21,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,11,6,0,0,0,0,0,0,0,0,9,6,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0, 0,0,0,10,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,11,7,0,0,0,0,0,0,0,4, 0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,7,0, 0,0,0,0,0,0,0,0,6,0,0,21,6,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0, 0,0,0,8,7,0,0,11,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,13,7,10,4,0, 0,0,6,0,0,0,0,0,0,0,0,0,5,10,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,8,4,0,0,0,0,0,6, 0,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0, 0,0,0,0,7,0,0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,5,0,6,0,0,0,0,0,4,0,0,0,0, 0,0,0,0,0,4,0,0,0,0,9,0,11,4,0,0,0,6,0,0,0,5,12,7,0,5,0,0,0,0,0,4,0,0,0,7,0,0,0, 0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,13,6,10,0,0,0,17,0,0,4,0,0,0,0,0,6,0,4,0,5,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,7,0,0,0,7,0,0,0,6,0,0,0,0,0,0, 0,6,0,4,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,4,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,0,0, 0,0,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,16,4,0,0,11,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 8,7,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,8,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10, 7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,5,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0, 5,18,7,0,0,14,0,0,0,0,0,0,0,9,4,0,7,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,0,0,0, 8,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,0,0,0,0,0,0,11,0,0,0, 10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,14,6,0,0,0,0,11,4,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,10,7,0,6,0,0,9,0,9,5,0,0,0,0,0, 0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,8,5,0,0,0,0,0,0,0,0,0,0,11,4,0,6, 0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,12,4,0,6,8,6,0,0,0,0,0,0,0,0,0,0,8,0,0,5,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0, 0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,0, 0,0,0,0,0,0,0,0,0,13,4,0,7,0,0,0,7,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0, 9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,6,21,5,0,0,0,0,8,0,0,0,0,4,0, 7,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0, 0,7,9,6,11,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,10,0,0,0,0,0,0,6,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,19,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,9,4,10,4,0,7,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,9,7,9,7,10,4,0,7,0,0,0,0,0,0,0,6,12,0, 0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0, 0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0, 0,0,0,0,0,5,0,0,8,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0, 0,0,0,0,4,0,0,8,0,0,6,0,0,0,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,0,4,8,0,0,0,0,6,11,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,13,4,0,0, 12,6,0,6,0,0,0,0,8,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,4,0,0,0,0,0,0,0,0,0,0,9, 7,22,0,0,0,0,4,0,0,0,0,0,6,0,0,0,4,0,0,9,0,0,6,0,0,24,7,0,7,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,10,6,0,5,0,0,0,0,0,0,0,7,0,0,8,0,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,7,0, 7,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0, 0,0,0,0,0,7,12,0,9,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,4,0,0,0,7,0, 0,0,0,8,7,0,0,0,0,0,0,0,0,0,4,18,0,0,0,0,0,10,0,0,5,0,0,11,0,0,0,0,0,0,5,0,6,0, 0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0, 0,0,0,5,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,20,7,0,0,0,0,0,0,0,0,0,0,0,4,9,0,12, 6,8,0,14,7,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,10,0,0, 0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,9,6,0,7,12,0,0,0,0,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7, 0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,0,9,0, 12,6,0,5,0,0,0,6,0,4,0,6,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0, 10,0,0,0,0,0,0,0,8,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0, 6,0,0,12,6,20,5,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,5,0,0,0,6,13,7,0,0,0,0,15,6,0,0,0, 6,0,0,13,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0, 10,6,0,0,0,0,0,6,0,0,0,0,9,0,0,0,0,0,19,6,0,0,0,0,0,0,0,0,0,0,13,0,11,0,0,0,0,0, 0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,10,0,0,6,0,0,0,0,8,0,0, 0,9,0,15,4,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, 0,0,0,0,0,8,7,0,0,0,0,0,6,10,0,0,0,0,0,0,0,0,7,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,10,5,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,6,12,0,0,0,10,7,0,5,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,6,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,4,9,6,0,0,0,7,0,0,0,0,0,0,0,0,8,6,0,0, 0,0,0,0,0,4,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0, 0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,6,9,4,0,0,8,4,0,6, 0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,8,0,0,6,13,4,0,5,8,0,0,0,0,0,0,0,8,0,0,0,10,5,0,0,9,0,0,0,0,0,0,6,0,0, 24,0,0,0,0,0,0,0,8,0,0,7,0,0,12,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0, 6,8,0,10,0,9,7,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,4,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,8,0,0, 0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,10,4,0,0,0,0,0,0,0,6,0,0,0,4,20,0,0,7, 10,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,9,6,0,0,0,0,0,0,0,4, 12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,9,4,0,5,0,0, 0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,6,9,0,0,0,0,7,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0,0,9,0,0,0, 0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,17,7,0,0,13,6,14,6,0,0,0,0, 8,0,0,0,0,0,0,7,12,7,8,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,4,0,0,0,0,0,4,0, 0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,12,4,0,0,10,7,0,0,0, 0,0,0,10,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,12,0,0,6, 0,0,0,0,0,0,0,0,8,7,12,0,0,0,0,0,0,6,0,6,0,4,0,0,18,6,0,0,0,6,0,0,0,0,0,6,10,6, 0,0,0,0,0,0,8,7,14,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19, 0,0,0,8,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,5,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, 0,0,9,4,8,0,0,0,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0, 0,6,0,0,9,7,0,0,0,0,0,5,0,0,0,0,8,7,0,0,14,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0, 0,0,0,6,0,0,0,6,0,4,0,0,0,0,0,4,0,0,0,0,12,0,0,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0, 0,12,0,16,6,0,0,0,0,0,0,11,7,0,4,8,7,0,0,0,0,0,6,0,0,0,0,16,0,0,0,0,6,0,0,0,0,0, 0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,10,7,0,0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0, 0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,13,4,0,0,10,0,0,0,0,0,0,0,0,0,19,0,0,0, 0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,18,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,14,7,0,0,11,5,0,0,0,5,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,24,6,0,0, 0,7,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,4,0,0,0,0,8,7,0,0, 9,6,0,0,14,5,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,5,0,0, 0,0,12,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,13,7,0,0,0,0,0,0,14,0,11,4,0, 0,0,4,0,0,0,0,14,5,0,0,0,0,0,5,11,5,0,0,0,0,22,5,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0, 4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,17,0,10,0,0,0,8,0,0,0,19, 5,18,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,10,6,0,6,0,0,0,0,10,4,0,4,0, 0,0,0,0,0,14,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,0,9,6,12,0,0,6,0,0,0,0,0,0,0,0, 12,0,10,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,5,13,0,9,7,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,8,0,0,0,0,0, 22,0,0,0,0,0,0,0,23,6,14,0,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0, 0,0,10,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,8,5,0,0,0,0,0,0,0,0,0,7,11,6,21,0,0,0,0,0, 0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0, 0,0,0,0,0,0,0,4,9,7,0,0,0,0,0,0,12,0,0,0,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,9, 0,0,0,20,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,7,0,0,0,0,0,0,0,6,15,0,0, 0,0,0,0,0,0,0,0,0,0,0,12,4,0,5,0,0,0,0,0,0,11,7,17,6,0,0,0,0,0,0,15,6,0,7,0,0,0, 0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,5, 0,0,11,0,11,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0, 17,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,7,9,6,0,0,14,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0, 8,7,0,4,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, 0,0,0,5,0,4,0,0,8,7,0,6,12,5,0,7,18,7,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, 10,0,11,0,0,0,0,0,0,0,0,0,0,0,9,0,0,4,0,6,0,7,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0, 7,0,0,0,0,8,0,0,0,15,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0, 0,0,6,0,0,0,0,23,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0, 0,0,0,0,12,7,9,7,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,9,0,8,7,0,0,0, 6,0,6,0,4,0,5,0,0,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,7,10,5,0,0,11,6,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,4,9,7,0, 0,0,0,11,7,0,0,0,0,0,5,0,0,0,7,0,0,0,0,23,6,11,4,0,0,0,0,0,0,9,0,0,0,10,6,0,0,0, 0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,10,6,0,0,0,7,0,0, 0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13, 6,11,7,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,6,0,0,0,5,0,6,0,6,0,0,0,0,0,0,0,0,0,0, 0,6,0,0,0,0,8,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,4,10,0,8,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0, 0,0,0,0,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,11,6,0,4,0,0,14,5,0,7,0,0,0,0,0,6,16,0,0,0,0,0,0,0,10,0,0,7,15,0,0,0,11,7,0,0, 0,0,0,0,0,0,0,0,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,5,0,0,0, 0,8,0,0,6,0,0,0,0,0,0,9,5,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,6,0, 0,0,0,0,0,0,7,0,0,0,0,15,7,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,12,6,11,7, 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13, 7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,8,0,0,5,8,7,10,6,0,0,0,7,0,0,0,0,12,6, 0,0,9,0,0,0,12,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,10,0,0,0,10,5,0,0,0,0,0,0,9,6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,9,5,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,0,0,5,0,0,8,7,8, 6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,10,0,9,4,0,0,0,0,0,0,0,6, 11,0,0,0,0,0,0,0,0,0,0,0,8,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,8,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, 0,0,0,10,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0, 0,0,8,4,0,5,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,8,5,0,0,0, 0,0,0,0,7,0,0,0,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,6,0,7,0,0,0,0, 20,0,0,0,0,0,0,0,0,0,0,7,9,0,0,0,0,0,0,6,0,6,0,7,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0, 0,0,0,14,7,0,0,0,5,0,0,22,4,10,0,0,0,0,0,0,4,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,11,5,13,0,0,0,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,10,7,0, 0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,7,14,6,0,0,0,0,9,5, 0,0,0,0,0,6,0,0,0,5,10,0,8,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,8,4,0,6,0, 0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7, 14,0,0,5,0,0,18,0,8,4,0,6,0,0,20,0,13,0,0,0,0,7,0,4,0,0,0,0,0,4,8,4,0,0,0,0,0,6, 0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,14,0,0,0,0,0,9,7,0,0,9,0,0,0,0, 0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,20,0,14,0,0,4,0,6,8,5,0,0,0,0,0,7,0,0,0,0,0,0, 0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,4,12,7,0,6,0,0,9,7,10,5, 0,0,8,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,18,0,0,0,14,7,0,0,0,0,0,4, 0,0,0,0,0,0,17,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0, 0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0, 7,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0, 0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,23,0,0,7,0,0,0,0,0,0, 0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,7,8,4,0,0,0,0,0,0,0,0,0,6,0,0,9,5,0,0,0,7,0,0,0, 0,0,0,0,0,0,4,10,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,18,7, 0,0,8,0,0,5,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0, 6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,10,0,0,5,10,4,0,0,12,0,0,0,0, 6,22,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, 0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,16,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,12,7,0,0,0,0,9,0,0,0,0,6,0,0,11,0,0,0,0,0,13,0,9,6,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,10,7,0,0,0,7,0,6,0, 0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,11,0,15,0,22,7,0,4,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, 18,0,0,0,0,0,0,0,0,0,14,0,0,4,0,0,0,0,8,7,9,0,0,0,0,0,9,0,0,0,14,0,0,0,0,0,0,0, 0,0,11,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,0,0,0,0,8,0,0,0,0, 0,11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,4,0,0,0,0,0,4,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0, 0,0,0,0,0,0,8,6,0,0,9,5,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0, 0,10,6,9,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0, 11,7,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0, 0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,5,0,0,10,6, 0,0,0,4,0,7,13,0,0,4,0,0,11,4,0,6,0,0,0,0,0,6,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,5,0,0,0,0,12,6,0,0,0,0, 11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,11,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8, 7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,6,17,0,9,0,10,6,0,6,12,0,0,4,0,0,0, 0,0,0,0,0,0,0,8,5,12,7,0,4,0,0,0,0,0,0,0,0,0,0,11,0,9,0,10,6,11,5,0,7,0,0,8,0,0, 7,0,4,0,0,0,7,0,0,0,0,0,0,8,6,0,0,0,6,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0, 0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,10,0,0,0,0,0,8,6,0,0,0,0,0,6,12,0,0,0,0,0, 0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,16,0,11,5,0,0,0,0,0, 0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,10, 7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,9,5,0,0,0,0,8,0,9,0,0, 0,0,0,0,0,0,7,10,0,13,0,0,6,0,0,0,0,0,0,0,0,0,6,9,4,0,0,0,0,0,0,10,0,0,0,0,0,10, 0,0,0,0,0,0,0,10,6,11,0,0,0,0,0,9,0,0,0,0,0,0,4,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0, 0,0,0,0,0,18,4,0,7,0,0,0,0,0,0,24,0,8,6,0,7,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0, 0,8,5,0,0,0,0,10,7,0,6,0,0,0,0,0,0,0,0,8,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0, 6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,4,0,5,15,0,0,0,0,7,0,7,0,0,0,0, 0,0,0,0,0,6,10,5,0,0,0,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,12,0,0,0,0,0,0,0,0, 0,0,5,0,0,0,0,0,0,14,4,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,11,0,10,4,9,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0, 0,0,0,0,0,0,0,0,7,13,7,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0, 0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,8,0,10,6,0,4,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0, 0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,9,7,0,0,0,0,0,6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0, 0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,11,0,0,0,0,6,0,0,0,0,0,0,0,6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0, 6,0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0, 0,0,0,0,0,0,0,6,0,6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,10,0,11,5,0,0,0,0,0,0,14,7,9,7, 0,6,0,0,0,0,0,4,0,0,0,0,0,0,11,7,0,6,0,0,0,0,0,0,9,7,0,4,0,0,0,7,0,0,0,0,0,5,0, 0,0,0,0,5,0,0,0,7,0,0,0,0,0,5,0,0,0,0,17,5,0,0,8,0,0,0,0,6,9,4,0,0,0,0,0,0,0,0, 8,7,11,7,9,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,9,5,0,0,8,6,0,0,0,5,0, 0,0,0,9,0,0,0,9,6,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0, 0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,4,0,0,0,5,0,0,0,0,0,7,0,0,0,0,0,7,13,5,0,0,0,7,0,0,0,0,0,7,9,6,11,7,0,7,0,0,0, 0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,8,5,0,0,0,5,9,4,0,0,0,0,0,0,0,0,8,4,0,0,0,0, 24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0, 0,0,0,0,6,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6,0,4,0,7,20,0,8,5,9,5,9,0,0,6, 0,0,0,0,0,0,0,0,0,0,0,7,23,5,0,0,8,4,0,0,10,0,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,7,0, 0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0, 10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0, 6,0,0,0,0,14,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,6,0,4,0,0,0,0,0,0,8,4, 11,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,12,0,10,7,0,0,10,0,0,0,0, 0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,6,0,0,0,0,8, 6,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,6,0,4,0,0,0,0,0,5,0,0, 0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,17,7,11,0,0,0,0,0,0,0,0,0,0,4,12,6,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0, 0,5,12,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,0,20,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,4, 0,0,0,5,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,4,13,0,0,7,0,0,0,0,0,0, 0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,12,6,0,7,0,0,0,0,10,0,23,6,0,0, 0,4,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 10,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,11,0,9,7,0,0, 0,0,0,0,0,0,0,0,9,7,0,4,0,0,0,0,8,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, 0,0,0,0,0,6,0,0,10,7,10,5,0,0,8,0,8,0,0,0,0,0,0,4,0,5,10,0,0,0,0,0,0,0,9,0,0,6, 0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,6,0,0,8, 7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,24,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,6,0,0,9,0,0,0,0,0,0,7,0,6,13,0,8, 0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0, 4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,5,0,7,0,0,10,0,10,7,0,0,12,5,0,0,9,0,0,0,10,0, 0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0, 12,0,0,0,0,0,8,5,13,6,0,0,0,0,0,0,9,4,0,0,0,0,8,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0, 0,0,6,0,0,14,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,17,6,0,0,0,0,12,6,0,0,0,0,8,0,0,7,0, 7,0,4,9,0,0,6,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,0,0,0,11,0,0,4,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,18,7,0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0, 0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,11,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0, 11,0,0,0,0,0,0,0,21,0,0,6,10,0,0,0,0,0,9,0,10,0,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0, 5,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,4,0,0,23,7,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,0,7, 0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0, 11,6,0,0,0,0,0,0,0,6,0,0,0,0,10,7,0,0,9,4,0,0,11,0,8,5,0,0,0,7,8,5,22,0,0,0,9,6, 0,0,0,0,0,0,0,6,10,4,0,0,0,0,0,7,9,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0, 0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,6,0,4,0,0, 0,0,0,0,0,7,0,7,0,4,13,0,0,0,0,0,8,0,0,0,0,7,0,0,0,0,0,0,11,6,0,7,0,0,0,0,9,0,0, 0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,8,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,13,5,8,0,0, 0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,17,6,0,0,0,0,13,4,0,0,9,6,0,0,10,5,0, 0,10,5,0,0,0,0,13,0,0,0,0,6,0,0,0,0,0,0,10,0,12,0,0,0,0,0,0,0,0,0,0,0,8,4,0,4,0, 0,0,4,0,0,0,0,0,4,0,0,12,0,0,5,9,4,0,0,0,0,0,0,0,0,0,5,8,5,0,0,0,7,0,0,0,0,8,7, 0,0,0,6,12,5,0,0,0,5,0,0,0,5,0,0,0,0,0,4,12,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0, 0,9,6,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,4,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0, 0,0,0,0,12,7,0,0,0,7,10,7,0,0,11,0,0,0,0,0,0,0,0,0,11,7,0,0,0,6,0,0,11,0,0,0,0, 0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22,0,10,7,0,0,8,5,0,0,0,0,0,5,0,0,0,0,0,0, 0,0,0,0,9,6,8,7,0,6,0,0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,9,7,0,0,0,6,0,0,8,7,0,0, 0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,5,0,0,0,4,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9, 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,5,0,0,0,0,14,0,0,0, 9,0,0,0,0,0,0,0,0,0,9,7,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,12,0,0,0,0,0,12,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0, 0,0,0,0,0,9,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0, 0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0,7,12,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0, 0,7,0,0,8,6,0,0,0,0,10,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,0,6,0,0,0, 0,0,6,0,0,0,6,0,0,0,0,0,6,16,0,0,0,0,0,0,0,0,0,9,0,17,0,14,7,8,0,0,0,0,0,0,6,0, 0,0,0,0,0,0,0,0,0,11,0,0,6,8,7,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0, 9,0,0,0,0,7,0,0,0,0,11,5,0,4,9,6,8,0,0,0,0,0,0,0,0,0,10,0,11,7,0,0,0,0,0,0,0,0, 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 0,0,0,12,0,0,0,0,0,10,5,0,4,0,0,0,0,0,7,10,6,11,6,0,0,0,0,0,0,0,0,0,0,0,0,17,0, 0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,8,0,0,4,0,0,0,6,0,0,0, 0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,4,0,0,0,0,9,6,0,0,0,4,0,0,0,0,0,4,10,7,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0, 0,0,0,0,0,0,6,0,0,0,6,0,6,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,18,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,13,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4, 0,0,0,6,0,0,0,0,0,4,8,0,0,0,11,7,0,0,0,4,0,0,0,0,0,7,0,0,8,5,0,0,16,0,0,0,13,6, 0,0,0,0,0,0,0,6,0,0,0,0,20,0,11,6,0,0,8,7,0,0,0,0,0,6,17,0,8,0,0,0,0,0,8,7,0,0, 9,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0, 0,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,8, 0,8,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,6,0,0,9,0, 0,0,0,0,8,0,0,0,0,0,18,0,0,0,0,0,0,4,9,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,9,6,0,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,7,0,0,0,0,0,0,0,0, 0,4,0,0,0,0,0,0,14,0,0,0,0,7,0,6,0,0,8,0,20,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,8,0,0,7,0,6,0,0,0,7,0,0,0,0,0,0,0,0, 0,0,0,4,12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,6,0, 5,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0, 0,0,0,5,8,4,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,12,7,0, 0,0,0,13,6,0,0,0,7,0,0,8,0,0,0,8,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,11,5, 0,6,0,0,8,5,0,7,0,0,0,0,0,0,0,7,0,0,0,0,8,6,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,4,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 14,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,19,0,0,4,0,0,0,7, 0,0,11,5,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,16,0,10,5,18,0,0,7,9,6,0,5,0,0,0,0,0, 0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0,0,7,0,6,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,4,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,23,0,0,0,0,5,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,20,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0, 11,0,0,0,0,7,0,0,0,0,15,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0, 0,4,0,0,0,0,10,0,0,0,0,0,9,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,0,11,6,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,5,0,0,11,0,0,0,0,7,0,0,0,0,0,0,8,7,0, 4,0,0,0,0,11,0,0,0,0,0,11,0,0,5,0,0,8,7,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0, 0,0,4,11,5,10,7,0,7,0,0,9,6,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,9,4,0,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,8,6,0,0,0,0,11,7,0,0,0,0,0,0,0,0,0,0,11,7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,8,5,0,0,8,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0, 10,7,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,10,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0, 0,0,6,0,0,0,0,9,5,8,5,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0, 0,8,7,10,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,5,0,0,0,6,0,7,0,0, 10,5,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,11,0,0,0,0,0,13,4, 0,0,0,4,0,0,0,0,0,5,8,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,7,14,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,15,6,10,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,14,6,10,0,0,0,0,0,0,0,0,6,0, 0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,6,0,5,11,4,0,6,0,0,0,7,0,0,0,0, 0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,8,5,0,0,0,0,0,0,0,0,0,0, 0,0,10,0,0,0,0,0,9,6,9,4,0,0,0,4,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0, 0,0,0,0,0,0,0,0,0,0,4,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0, 0,0,0,7,12,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0, 4,9,6,0,4,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0, 7,8,6,0,0,0,0,0,0,0,4,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,5,0,4,0,0,0,0,0,0,0,5,0,0,0, 0,0,5,0,0,0,7,12,7,0,0,0,0,0,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,6,0,0,0, 0,12,0,0,7,0,0,0,0,0,7,0,0,13,0,0,6,0,0,0,0,8,7,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,7,10,5,0,0,8,0,0,0,0,0,0,0,8,6,0,7,0,0,8,4,0,4,0,0,0,0,10,4,0,0,14,0, 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,17,0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,10,5,0,0,0,0,8, 6,0,0,0,6,0,0,0,7,0,0,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,12,0,0,0,0,6, 8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, 0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,24,0,0, 0,0,0,12,6,0,0,10,6,0,5,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,7,0,5,0,0,0, 0,0,0,0,0,0,0,0,0,0,6,11,5,9,0,8,7,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,5,8,7,0,0,0, 0,8,5,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0, 0,6,12,0,8,7,0,0,0,0,0,0,0,0,0,0,16,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,22,0,0,0, 0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,22,0,0,6,0,0,21,0,0,0,22,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,7,8,0,0,0,0,6,14,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,0,0,0, 0,0,0,0,0,6,0,0,0,0,8,5,0,0,11,7,0,6,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0, 6,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,8,7,0,0,0,0,8,5,11,7,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,0,8,5,0,0,10,0,0,4,13,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,13,6, 0,6,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,15,0,0,0,10,7,0,0,0,0,0, 7,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,19,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,5, 0,7,0,0,0,0,0,0,0,0,0,6,0,0,11,4,0,0,0,6,0,0,13,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0, 0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6, 0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0, 0,0,0,8,7,0,0,0,0,9,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,10,0, 0,6,0,0,13,0,0,0,0,0,0,0,9,6,0,0,8,6,8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0, 0,9,7,0,0,0,0,0,0,11,0,0,0,10,7,0,0,0,0,0,0,0,0,9,6,0,0,12,4,0,4,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,6,0,0,0,0,21,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0,0, 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0, 16,0,0,4,0,0,0,0,0,7,0,0,0,6,0,6,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0, 0,14,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0, 0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, 0,0,0,0,6,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,14,7,0,0,9,7,0,0,11,0,0,0,0,0,10, 4,11,5,13,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,5,0,0,0,0,0,4,0,0,9,0,0,0,0, 0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,12,5,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,4,9,4, 0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0,0, 0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,11,6,0,0,13,7,0,0,13,6,0,7,0,0,0,0,0,0,8,6,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,6,0,4,0,0,12,6,0,0,0,0,0,0,0,0,10,6, 0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,6,0, 0,0,0,0,7,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0, 0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0, 0,0,0,5,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0, 0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,5,0,0,0,4,9,5,0,0,0,7,10,6,0,0, 0,0,0,0,9,7,0,0,8,5,8,0,8,4,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0, 0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0, 0,11,7,0,0,0,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,5,0,0,0,7,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,7,0,0,0,0,8,5,0,4,0,0,0,0,0,6,0,6,14, 6,0,0,0,0,9,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,6,0,0,0,0,14,7,9,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16, 0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0, 0,6,0,0,8,6,0,0,0,0,0,6,0,0,12,0,0,0,0,0,8,5,0,7,11,0,0,5,0,4,0,0,0,6,0,0,0,0,0, 0,0,0,0,0,0,0,9,6,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,10,5,0,0,0,0, 0,4,0,0,0,7,11,6,0,4,8,5,9,5,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,8,5,14,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,16,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,6,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,5,0,0,0,0,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0,0,6,0, 0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,4,0,0,0,6,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,10,4,0,0,0,0,0,5,0,0,0,4, 0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,0,10,7,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,7,0,0,0,0,0,0,0,0,15,0,0,0, 0,0,0,0,0,0,0,7,0,0,0,0,0,7,10,7,9,7,0,0,0,7,0,0,8,0,0,0,0,0,0,0,9,0,0,0,8,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,15,7,12,6,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,5,0,0,0,0, 0,0,0,6,9,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,14,0,0,0,11,7,0,0,0,0,0, 0,0,0,0,0,0,4,0,0,11,7,0,0,0,0,8,0,0,0,0,0,0,6,8,7,0,0,0,7,10,4,0,0,0,0,0,0,0,0, 0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,10,0,0,0,0,0,0, 6,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,7,0,0,0,0,9,7,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,12,0, 0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,9,6,0,0,11,0,0, 0,0,0,14,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,7,0,0, 0,0,0,6,0,7,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,20, 7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,8,0,0,0,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,5,8,5,10,4,0,0,0,0,0, 0,13,6,9,7,0,0,10,7,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,7,0,6,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,10,7,0,0, 0,0,0,0,0,0,0,0,12,4,0,0,0,0,8,7,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0, 0,0,0,0,6,0,6,9,6,0,0,12,5,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0, 0,0,0,0,0,0,0,0,0,5,8,7,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11, 4,0,0,0,0,0,0,8,0,0,0,10,7,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,0, 0,0,0,0,0,5,0,6,0,0,10,0,14,0,0,0,0,0,0,0,23,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0, 5,0,0,0,0,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,22,0,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0, 0,0,0,0,0,6,18,4,0,0,0,7,10,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0, 0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,0,0,0,0,0,0,6,0,0,0,0,11,5,0,0,0,0,0,0,0,0, 15,0,8,6,0,0,13,7,0,0,0,0,0,7,0,0,0,0,0,7,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,5,9, 0,0,6,8,6,0,0,0,0,10,0,0,0,18,5,0,0,0,5,0,7,0,0,0,0,8,6,0,0,0,0,9,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,14,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,5,0, 0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0, 0,0,0,0,20,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,8,4,24,0,0,0,0,0,0, 0,0,0,0,0,0,0,9,7,0,0,0,0,10,5,0,0,8,5,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,6,0,0,0, 0,14,0,0,4,9,5,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,8,0,0,0,0,0,11,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,8,5,11,7,0,4,0,0,10,0,0,0,0, 0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,6,0,0,0,0,0,5,14,6,0,0,0,0,10,0,0, 0,13,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,12,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,10,0,9, 7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,9,7,0,0,0, 0,0,0,0,0,0,0,0,0,24,0,11,7,0,7,0,0,0,0,0,0,8,6,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0, 0,6,9,0,0,0,23,5,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,7,0,0,0, 0,0,0,0,0,0,0,0,0,0,6,0,0,18,4,0,0,11,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, 0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,0,0,0,11,0,0,0,23,0,0, 0,10,4,0,0,0,0,0,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,7,0,0,19,0,11,0,0,0,0,0,12,7,0, 0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0, 9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,22,0,8,7,10,4,11,0,13,5,8,7,9,0,8,7,0,0,0,7,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 0,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,4,0,0,0,4,11,0,0,6,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,5,0,0, 20,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,7,0,0,14,0,0,0,9,0,13,7,0,0,0,0,0,6,0,7,0,0,8,6,10,6,0,0,8,6,0,0,0,6,0, 0,12,6,9,0,0,0,0,0,0,5,9,0,12,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0, 0,0,4,8,0,0,6,8,0,0,0,0,0,0,0,0,0,13,6,0,7,0,0,0,0,0,6,8,7,8,6,0,0,0,7,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,18,0,11,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0, 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14, 6,0,0,0,0,12,7,8,0,0,0,0,0,0,0,8,7,0,0,0,0,10,4,0,0,0,0,0,0,10,0,0,6,0,0,0,0,0, 0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,15,6,9,7,0,0,0,0,0,0,15,6,11,7,0,0,0,7,0,0,21,0,0, 0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,6,0,0,10,5,0,5,0,0,0,0,0,0,0,0,0,7, 0,0,10,0,0,0,0,0,0,0,0,4,11,5,0,0,0,0,16,7,0,0,0,0,0,6,0,0,8,7,0,4,0,0,10,0,0,0, 0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0, 0,0,0,10,4,0,0,0,0,0,0,0,0,0,6,0,5,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0, 0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,8,4,0,0,10,0,0,0,0,4,0,6,0,6,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,17,0,0,0,0,0, 0,0,0,0,0,0,10,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,4,0,0,0,0,0,6,0,0,0,0,0,0,10,5,0,0, 0,5,0,0,0,0,9,0,19,7,0,0,0,0,0,7,0,0,0,0,10,6,0,0,0,6,0,5,0,0,0,0,0,0,0,0,0,6,8, 0,0,0,0,0,11,0,0,0,0,0,0,6,0,0,0,0,0,7,9,0,15,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0, 0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,6,0,0, 0,0,0,6,10,0,0,0,0,0,0,0,23,0,14,0,0,0,0,7,0,0,0,0,0,7,0,0,9,0,0,0,0,7,0,0,0,0, 0,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0, 0,0,0,0,0,9,5,0,0,0,0,0,4,0,0,0,0,9,5,0,0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,6,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,14,7,0,0,12,7,0,0,0, 0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,8,6,10,0,0,0,0,0,0,0,0,0,10,7,8,5,0,0,0,0,0,0, 0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,5,0,0,9,5,0,0,0,0,0,5,0,0,0,0,0,4,0,0,0, 0,0,0,0,0,0,0,12,4,11,0,0,0,9,0,11,7,0,0,0,0,0,0,10,6,0,0,0,6,0,0,0,0,15,5,0,0, 11,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,4,0,6,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,0,0,0,19,7,0,4,0,0,9,0,0,0,0,0,10,0, 0,6,0,0,13,0,12,6,0,0,0,0,0,0,0,0,10,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,13,7,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,9,0,0,0,10,0,0,0,0,0,0,0, 0,5,0,0,0,0,0,0,10,0,23,6,0,0,0,6,8,0,0,0,0,0,0,0,0,0,17,7,0,0,0,0,11,6,22,5,0, 0,9,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,9,4,0,0, 0,7,0,7,0,0,0,0,0,0,12,4,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,11,5,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,6,0,0,0,4,0,0,0,0, 0,0,0,0,0,7,0,0,0,4,0,0,10,4,0,0,0,0,0,0,0,7,0,7,0,0,0,6,0,0,0,0,8,6,0,6,0,6,0, 0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,6,22,6,12,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,11,0,0,0, 9,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,6,0,0,0,6,0,6,0,0,8,7,0,0,0,4,9,7,19,0,0,0,0,0,0,0,0,0,9,6,10,6,0,6,0,0,0, 4,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,16,7,10,6,0,0,23,6,11,7,0,4,0,0,0,0,0,0,0,0,0, 5,0,0,0,0,10,7,0,0,0,0,0,7,0,0,0,0,0,0,15,0,10,0,0,0,14,6,0,0,0,0,0,0,0,0,0,0,0, 5,0,0,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,5,0,0,11,5,0,0,0,0,0,0,0,0,0,0, 0,4,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,10,6,0,0,0,0,8,4,0,0,0,7,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,12,5,0,0,0,0, 0,6,0,0,0,0,9,6,0,0,0,0,0,0,0,6,9,0,0,0,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,6,0,0,0,0, 0,0,0,0,0,0,10,5,0,0,0,0,0,0,8,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,8,5,0,0,0,0,0,7,0,7,0,4,0,0,10,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,13, 7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0,0,7,10,5,0,0,0,0,0,0,9,7,0,0,8,6,9, 5,0,0,0,0,0,6,12,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,0,19,7,0,4,0,0,0,0,9,5,0,5,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,7,0,0,0,0,0,0,14,0,0,0,23,7,8,7,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,7,0,0,0,0,0,0,0,0,9,7,8,4,0, 0,0,0,0,0,0,0,8,5,0,6,0,0,0,0,0,6,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0, 8,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,8,6,0,0,11,7,0,0,0, 0,12,0,8,6,19,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,11,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,11,7,0,0,0,0,0,4,10,0,0,0,0,0,0,0,8,7,0,0,0,0,14,0,8,0,0,6,10,0,0, 0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0, 0,0,0,0,13,0,0,0,0,0,0,0,11,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0, 0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,6,0,0,0,5,0,7,0,0,0, 0,0,6,0,0,21,7,0,0,9,6,0,0,0,6,0,0,13,7,0,0,0,5,0,0,0,0,0,4,0,6,0,0,0,0,0,0,0,0, 0,0,0,4,0,0,0,0,0,0,11,5,0,6,0,0,10,5,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,15,4,0,0,12,7,0,0,0,6, 0,7,0,0,8,0,9,5,0,4,0,0,0,6,0,6,0,0,23,4,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,8, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0, 7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,6,0,0,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0, 9,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,11,5,0,0,0,6,0,6,0,0,0,0,0,0,0,6,0, 4,0,0,0,0,0,0,0,0,0,0,0,5,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,8,7,0,0,0,6,0,6,0, 0,0,0,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,10,5,9,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,23,7,0,0,0,0,0,7,0,0,10,6,18,0,0,0, 0,0,0,0,8,7,0,6,0,0,0,0,0,0,8,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0, 0,0,0,0,0,6,0,0,0,4,12,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,13,5,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0, 11,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0, 0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,0,11,0,0,0,0,0,0,0,0,0, 17,5,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,8,7,0,0,0,0,0,0,0, 0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0, 10,0,0,0,8,6,0,0,0,7,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0, 10,0,0,0,16,5,0,0,0,0,0,0,8,0,0,4,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,10,0,0,0, 0,0,0,0,0,5,0,0,0,0,12,5,0,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0, 0,0,0,0,0,0,0,12,6,0,0,0,0,0,7,0,6,0,6,12,6,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0, 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 16,0,8,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,23,5,0,0,0,7,0,6,0, 0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,14,0,0,0,0,7,0,0,0,4,17,5,0,0,0,0,11,0,9,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,5,0,7,0,0,0,0,0,0,0,0,8,0,0,0, 12,6,0,0,0,0,0,0,13,0,0,0,0,7,9,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,10,7,12,0,0,0,9,0, 0,0,14,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,15,6,0,0,23,0,0,7,0,6,0,0,0,7,0,6, 0,0,0,0,0,0,0,6,0,6,9,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,8,7,9,4,0,0,10,0,0,0,10, 6,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,6,0,0,0,0,0,0,9,4, 0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,9,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,12,0,0, 0,0,0,8,0,0,6,11,6,0,0,8,7,8,5,0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0, 10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0, 7,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,8,0,0,0,0,6,12,5,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,0,10, 7,0,0,8,0,0,0,0,4,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0, 0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,5,0,0,0,0,8,0,0,0,10,7,0,0,0,0,10,0,0,0, 0,0,13,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,19,7,0,4,12,0,8,0,0,0,0,6,0,0,0,0, 0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,18,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0, 0,14,0,0,4,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,0,0,0,10,4,0,0,9,7,0,0,11,0,0,0,0,0,0, 7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,12,0,0,0, 0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,22,5,9,7,0,0,0,0,0,0,0,0,0, 0,0,6,0,0,9,6,0,5,0,0,0,0,0,0,10,5,0,0,8,6,0,6,10,5,0,0,0,6,0,0,0,6,0,0,20,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,17,4,0,7,0,6, 0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10, 0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0, 0,0,7,0,0,8,6,12,0,0,7,18,7,0,0,8,4,0,0,0,0,9,6,0,0,0,0,0,0,0,0,13,0,0,6,0,0,0, 0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0, 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,12,0,0,0,8,0,0,0,0,0,0, 4,0,0,10,0,16,0,0,0,0,0,0,0,12,7,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16,6,10,0,0,5,0,0,0,0,0,6,0,0,0,0, 0,7,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,7,0,0,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,4,0,0,0,0, 8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,8,0,0,0, 9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,13,5,0,5,0,0,0,7,8,4,0,0,0,0,0,0,0, 0,12,0,0,0,0,0,0,0,0,0,0,0,8,6,0,6,0,0,11,0,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0, 0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,6,0,0,10,6,0,0, 0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, 0,0,0,6,0,0,0,7,0,0,9,0,8,7,11,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,9,6,10,5,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0,0,11,0,9,6,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,15,5,12,5, 0,0,0,0,0,0,12,7,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,12,6,0, 0,0,0,24,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0, 0,0,0,4,10,4,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,0,0,0,0,0,0,0,0,0,0,6, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, 0,0,8,0,0,0,0,7,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0, 0,0,0,0,0,14,7,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,6,0,0,0,6,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,7,20,7,11,4,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,9,6,0,0,12,7,0,0,0,0,0,0,10,0,12,0, 0,0,0,0,0,4,9,6,13,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,0,0,0,0,0,0, 0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,11,0,9,0,0,0,0,4,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, 0,4,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,7,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, 0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6, 0,0,0,0,8,7,0,0,0,0,0,0,12,0,0,6,0,0,0,0,0,0,0,6,8,4,0,0,10,7,0,0,10,0,0,0,0,0, 0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,5, 0,4,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,0,0,7,0,5,8,4,0,0,9,0,0,0,0,4, 0,0,0,0,0,0,0,0,0,5,0,0,15,6,8,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,4,0, 6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,9,5,0,6,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,12,7,0,0,0,0, 0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,10, 7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,8,7,9,6,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,5,12,0, 10,5,12,6,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,5,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7, 11,7,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,6,0,7,0,0,0,0,8,0,8,5,0,6,0,0,0,6,0,0,0, 0,0,0,0,6,0,6,0,6,9,0,0,5,17,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,7,0,0, 0,0,0,7,0,0,0,0,16,5,0,0,0,0,0,0,0,4,0,0,0,5,11,5,0,7,0,0,0,4,8,7,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,12,0,0,0, 0,0,12,0,0,0,0,0,0,0,0,4,10,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,20,5,0,0, 10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,12,0,0,0,0,0,0,6,0,0,0,0,0,0,9,4,10,7,0,4,0,0, 0,0,0,0,10,6,0,0,0,0,8,4,0,7,8,6,0,6,8,0,10,0,0,0,0,0,13,5,0,6,0,0,0,0,0,0,22,4, 0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,10, 5,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,10,4,0,0,10,7,0,0,0,0,0,5,0, 5,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,4,0,0,0,0,0,6,0,0, 0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0, 4,0,0,0,4,10,0,0,6,13,7,8,0,0,0,0,0,0,7,0,0,12,7,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0, 0,0,0,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,6,0,6, 0,0,0,0,0,0,0,0,12,0,8,4,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,5,0,0,0,0,12,5,0,0,0,7,0, 0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,10,0,0,0,20,0,0,5,0,0,10, 7,11,7,0,0,0,0,0,0,0,0,0,0,17,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,10,7,0,4,0,6,0,0,24,0,0,5,0,0,0,0,8,0,0, 0,0,0,0,0,10,5,0,4,0,6,0,0,8,0,0,0,0,0,0,4,0,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0, 0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,7, 0,0,13,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0, 17,7,0,0,11,6,0,0,0,0,12,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,4,8,6,0,0,0, 0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,9,5,0,7,18,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,0,0,0, 0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0, 0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,6,0,0,9,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0, 0,0,0,8,7,10,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,10,0,0,0,0,6,0,7,0,4,0,0,0,0,0,0,0,0, 8,0,0,0,0,0,8,4,0,0,0,0,0,5,0,0,10,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,11,0,0, 7,0,0,0,0,0,6,10,5,0,0,0,0,0,0,0,0,0,5,0,0,9,5,12,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,6,0,0,0,0,13,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0, 0,0,0,8,4,0,6,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,11,4,0,0,0,6,14,0,11,0,9,6,0,0,0,0,0,0,22,0,12,0,8,6,0,0,0,0,0,0,0,6,0, 0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0, 10,7,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,11,0,0,0,0,0,0,0,8,6,0,0,9, 7,0,0,12,4,0,0,0,0,0,0,12,6,0,6,0,7,0,0,8,5,0,0,0,0}; /* GENERATED CODE END */ #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/dictionary_hash.h000066400000000000000000000012061501401750600213500ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Hash table on the 4-byte prefixes of static dictionary words. */ #ifndef BROTLI_ENC_DICTIONARY_HASH_H_ #define BROTLI_ENC_DICTIONARY_HASH_H_ #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif extern const uint16_t kStaticDictionaryHashWords[32768]; extern const uint8_t kStaticDictionaryHashLengths[32768]; #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_DICTIONARY_HASH_H_ */ dvisvgm-3.5/libs/brotli/enc/encode.c000066400000000000000000002271751501401750600174470ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Implementation of Brotli compressor. */ #include #include #include #include /* free, malloc */ #include /* memcpy, memset */ #include "../common/constants.h" #include "../common/context.h" #include "../common/platform.h" #include "../common/version.h" #include "backward_references.h" #include "backward_references_hq.h" #include "bit_cost.h" #include "brotli_bit_stream.h" #include "compress_fragment.h" #include "compress_fragment_two_pass.h" #include "dictionary_hash.h" #include "encoder_dict.h" #include "entropy_encode.h" #include "fast_log.h" #include "hash.h" #include "histogram.h" #include "memory.h" #include "metablock.h" #include "prefix.h" #include "state.h" #include "quality.h" #include "ringbuffer.h" #include "utf8_util.h" #include "write_bits.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define COPY_ARRAY(dst, src) memcpy(dst, src, sizeof(src)); static size_t InputBlockSize(BrotliEncoderState* s) { return (size_t)1 << s->params.lgblock; } static uint64_t UnprocessedInputSize(BrotliEncoderState* s) { return s->input_pos_ - s->last_processed_pos_; } static size_t RemainingInputBlockSize(BrotliEncoderState* s) { const uint64_t delta = UnprocessedInputSize(s); size_t block_size = InputBlockSize(s); if (delta >= block_size) return 0; return block_size - (size_t)delta; } BROTLI_BOOL BrotliEncoderSetParameter( BrotliEncoderState* state, BrotliEncoderParameter p, uint32_t value) { /* Changing parameters on the fly is not implemented yet. */ if (state->is_initialized_) return BROTLI_FALSE; /* TODO(eustas): Validate/clamp parameters here. */ switch (p) { case BROTLI_PARAM_MODE: state->params.mode = (BrotliEncoderMode)value; return BROTLI_TRUE; case BROTLI_PARAM_QUALITY: state->params.quality = (int)value; return BROTLI_TRUE; case BROTLI_PARAM_LGWIN: state->params.lgwin = (int)value; return BROTLI_TRUE; case BROTLI_PARAM_LGBLOCK: state->params.lgblock = (int)value; return BROTLI_TRUE; case BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: if ((value != 0) && (value != 1)) return BROTLI_FALSE; state->params.disable_literal_context_modeling = TO_BROTLI_BOOL(!!value); return BROTLI_TRUE; case BROTLI_PARAM_SIZE_HINT: state->params.size_hint = value; return BROTLI_TRUE; case BROTLI_PARAM_LARGE_WINDOW: state->params.large_window = TO_BROTLI_BOOL(!!value); return BROTLI_TRUE; case BROTLI_PARAM_NPOSTFIX: state->params.dist.distance_postfix_bits = value; return BROTLI_TRUE; case BROTLI_PARAM_NDIRECT: state->params.dist.num_direct_distance_codes = value; return BROTLI_TRUE; case BROTLI_PARAM_STREAM_OFFSET: if (value > (1u << 30)) return BROTLI_FALSE; state->params.stream_offset = value; return BROTLI_TRUE; default: return BROTLI_FALSE; } } /* Wraps 64-bit input position to 32-bit ring-buffer position preserving "not-a-first-lap" feature. */ static uint32_t WrapPosition(uint64_t position) { uint32_t result = (uint32_t)position; uint64_t gb = position >> 30; if (gb > 2) { /* Wrap every 2GiB; The first 3GB are continuous. */ result = (result & ((1u << 30) - 1)) | ((uint32_t)((gb - 1) & 1) + 1) << 30; } return result; } static uint8_t* GetBrotliStorage(BrotliEncoderState* s, size_t size) { MemoryManager* m = &s->memory_manager_; if (s->storage_size_ < size) { BROTLI_FREE(m, s->storage_); s->storage_ = BROTLI_ALLOC(m, uint8_t, size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->storage_)) return NULL; s->storage_size_ = size; } return s->storage_; } static size_t HashTableSize(size_t max_table_size, size_t input_size) { size_t htsize = 256; while (htsize < max_table_size && htsize < input_size) { htsize <<= 1; } return htsize; } static int* GetHashTable(BrotliEncoderState* s, int quality, size_t input_size, size_t* table_size) { /* Use smaller hash table when input.size() is smaller, since we fill the table, incurring O(hash table size) overhead for compression, and if the input is short, we won't need that many hash table entries anyway. */ MemoryManager* m = &s->memory_manager_; const size_t max_table_size = MaxHashTableSize(quality); size_t htsize = HashTableSize(max_table_size, input_size); int* table; BROTLI_DCHECK(max_table_size >= 256); if (quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { /* Only odd shifts are supported by fast-one-pass. */ if ((htsize & 0xAAAAA) == 0) { htsize <<= 1; } } if (htsize <= sizeof(s->small_table_) / sizeof(s->small_table_[0])) { table = s->small_table_; } else { if (htsize > s->large_table_size_) { s->large_table_size_ = htsize; BROTLI_FREE(m, s->large_table_); s->large_table_ = BROTLI_ALLOC(m, int, htsize); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->large_table_)) return 0; } table = s->large_table_; } *table_size = htsize; memset(table, 0, htsize * sizeof(*table)); return table; } static void EncodeWindowBits(int lgwin, BROTLI_BOOL large_window, uint16_t* last_bytes, uint8_t* last_bytes_bits) { if (large_window) { *last_bytes = (uint16_t)(((lgwin & 0x3F) << 8) | 0x11); *last_bytes_bits = 14; } else { if (lgwin == 16) { *last_bytes = 0; *last_bytes_bits = 1; } else if (lgwin == 17) { *last_bytes = 1; *last_bytes_bits = 7; } else if (lgwin > 17) { *last_bytes = (uint16_t)(((lgwin - 17) << 1) | 0x01); *last_bytes_bits = 4; } else { *last_bytes = (uint16_t)(((lgwin - 8) << 4) | 0x01); *last_bytes_bits = 7; } } } /* TODO(eustas): move to compress_fragment.c? */ /* Initializes the command and distance prefix codes for the first block. */ static void InitCommandPrefixCodes(BrotliOnePassArena* s) { static const uint8_t kDefaultCommandDepths[128] = { 0, 4, 4, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 0, 0, 0, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 0, 4, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, }; static const uint16_t kDefaultCommandBits[128] = { 0, 0, 8, 9, 3, 35, 7, 71, 39, 103, 23, 47, 175, 111, 239, 31, 0, 0, 0, 4, 12, 2, 10, 6, 13, 29, 11, 43, 27, 59, 87, 55, 15, 79, 319, 831, 191, 703, 447, 959, 0, 14, 1, 25, 5, 21, 19, 51, 119, 159, 95, 223, 479, 991, 63, 575, 127, 639, 383, 895, 255, 767, 511, 1023, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 59, 7, 39, 23, 55, 30, 1, 17, 9, 25, 5, 0, 8, 4, 12, 2, 10, 6, 21, 13, 29, 3, 19, 11, 15, 47, 31, 95, 63, 127, 255, 767, 2815, 1791, 3839, 511, 2559, 1535, 3583, 1023, 3071, 2047, 4095, }; static const uint8_t kDefaultCommandCode[] = { 0xff, 0x77, 0xd5, 0xbf, 0xe7, 0xde, 0xea, 0x9e, 0x51, 0x5d, 0xde, 0xc6, 0x70, 0x57, 0xbc, 0x58, 0x58, 0x58, 0xd8, 0xd8, 0x58, 0xd5, 0xcb, 0x8c, 0xea, 0xe0, 0xc3, 0x87, 0x1f, 0x83, 0xc1, 0x60, 0x1c, 0x67, 0xb2, 0xaa, 0x06, 0x83, 0xc1, 0x60, 0x30, 0x18, 0xcc, 0xa1, 0xce, 0x88, 0x54, 0x94, 0x46, 0xe1, 0xb0, 0xd0, 0x4e, 0xb2, 0xf7, 0x04, 0x00, }; static const size_t kDefaultCommandCodeNumBits = 448; COPY_ARRAY(s->cmd_depth, kDefaultCommandDepths); COPY_ARRAY(s->cmd_bits, kDefaultCommandBits); /* Initialize the pre-compressed form of the command and distance prefix codes. */ COPY_ARRAY(s->cmd_code, kDefaultCommandCode); s->cmd_code_numbits = kDefaultCommandCodeNumBits; } /* Decide about the context map based on the ability of the prediction ability of the previous byte UTF8-prefix on the next byte. The prediction ability is calculated as Shannon entropy. Here we need Shannon entropy instead of 'BitsEntropy' since the prefix will be encoded with the remaining 6 bits of the following byte, and BitsEntropy will assume that symbol to be stored alone using Huffman coding. */ static void ChooseContextMap(int quality, uint32_t* bigram_histo, size_t* num_literal_contexts, const uint32_t** literal_context_map) { static const uint32_t kStaticContextMapContinuation[64] = { 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const uint32_t kStaticContextMapSimpleUTF8[64] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; uint32_t monogram_histo[3] = { 0 }; uint32_t two_prefix_histo[6] = { 0 }; size_t total; size_t i; size_t dummy; double entropy[4]; for (i = 0; i < 9; ++i) { monogram_histo[i % 3] += bigram_histo[i]; two_prefix_histo[i % 6] += bigram_histo[i]; } entropy[1] = ShannonEntropy(monogram_histo, 3, &dummy); entropy[2] = (ShannonEntropy(two_prefix_histo, 3, &dummy) + ShannonEntropy(two_prefix_histo + 3, 3, &dummy)); entropy[3] = 0; for (i = 0; i < 3; ++i) { entropy[3] += ShannonEntropy(bigram_histo + 3 * i, 3, &dummy); } total = monogram_histo[0] + monogram_histo[1] + monogram_histo[2]; BROTLI_DCHECK(total != 0); entropy[0] = 1.0 / (double)total; entropy[1] *= entropy[0]; entropy[2] *= entropy[0]; entropy[3] *= entropy[0]; if (quality < MIN_QUALITY_FOR_HQ_CONTEXT_MODELING) { /* 3 context models is a bit slower, don't use it at lower qualities. */ entropy[3] = entropy[1] * 10; } /* If expected savings by symbol are less than 0.2 bits, skip the context modeling -- in exchange for faster decoding speed. */ if (entropy[1] - entropy[2] < 0.2 && entropy[1] - entropy[3] < 0.2) { *num_literal_contexts = 1; } else if (entropy[2] - entropy[3] < 0.02) { *num_literal_contexts = 2; *literal_context_map = kStaticContextMapSimpleUTF8; } else { *num_literal_contexts = 3; *literal_context_map = kStaticContextMapContinuation; } } /* Decide if we want to use a more complex static context map containing 13 context values, based on the entropy reduction of histograms over the first 5 bits of literals. */ static BROTLI_BOOL ShouldUseComplexStaticContextMap(const uint8_t* input, size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint, size_t* num_literal_contexts, const uint32_t** literal_context_map, uint32_t* arena) { static const uint32_t kStaticContextMapComplexUTF8[64] = { 11, 11, 12, 12, /* 0 special */ 0, 0, 0, 0, /* 4 lf */ 1, 1, 9, 9, /* 8 space */ 2, 2, 2, 2, /* !, first after space/lf and after something else. */ 1, 1, 1, 1, /* " */ 8, 3, 3, 3, /* % */ 1, 1, 1, 1, /* ({[ */ 2, 2, 2, 2, /* }]) */ 8, 4, 4, 4, /* :; */ 8, 7, 4, 4, /* . */ 8, 0, 0, 0, /* > */ 3, 3, 3, 3, /* [0..9] */ 5, 5, 10, 5, /* [A-Z] */ 5, 5, 10, 5, 6, 6, 6, 6, /* [a-z] */ 6, 6, 6, 6, }; BROTLI_UNUSED(quality); /* Try the more complex static context map only for long data. */ if (size_hint < (1 << 20)) { return BROTLI_FALSE; } else { const size_t end_pos = start_pos + length; /* To make entropy calculations faster, we collect histograms over the 5 most significant bits of literals. One histogram without context and 13 additional histograms for each context value. */ uint32_t* BROTLI_RESTRICT const combined_histo = arena; uint32_t* BROTLI_RESTRICT const context_histo = arena + 32; uint32_t total = 0; double entropy[3]; size_t dummy; size_t i; ContextLut utf8_lut = BROTLI_CONTEXT_LUT(CONTEXT_UTF8); memset(arena, 0, sizeof(arena[0]) * 32 * 14); for (; start_pos + 64 <= end_pos; start_pos += 4096) { const size_t stride_end_pos = start_pos + 64; uint8_t prev2 = input[start_pos & mask]; uint8_t prev1 = input[(start_pos + 1) & mask]; size_t pos; /* To make the analysis of the data faster we only examine 64 byte long strides at every 4kB intervals. */ for (pos = start_pos + 2; pos < stride_end_pos; ++pos) { const uint8_t literal = input[pos & mask]; const uint8_t context = (uint8_t)kStaticContextMapComplexUTF8[ BROTLI_CONTEXT(prev1, prev2, utf8_lut)]; ++total; ++combined_histo[literal >> 3]; ++context_histo[(context << 5) + (literal >> 3)]; prev2 = prev1; prev1 = literal; } } entropy[1] = ShannonEntropy(combined_histo, 32, &dummy); entropy[2] = 0; for (i = 0; i < 13; ++i) { entropy[2] += ShannonEntropy(context_histo + (i << 5), 32, &dummy); } entropy[0] = 1.0 / (double)total; entropy[1] *= entropy[0]; entropy[2] *= entropy[0]; /* The triggering heuristics below were tuned by compressing the individual files of the silesia corpus. If we skip this kind of context modeling for not very well compressible input (i.e. entropy using context modeling is 60% of maximal entropy) or if expected savings by symbol are less than 0.2 bits, then in every case when it triggers, the final compression ratio is improved. Note however that this heuristics might be too strict for some cases and could be tuned further. */ if (entropy[2] > 3.0 || entropy[1] - entropy[2] < 0.2) { return BROTLI_FALSE; } else { *num_literal_contexts = 13; *literal_context_map = kStaticContextMapComplexUTF8; return BROTLI_TRUE; } } } static void DecideOverLiteralContextModeling(const uint8_t* input, size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint, size_t* num_literal_contexts, const uint32_t** literal_context_map, uint32_t* arena) { if (quality < MIN_QUALITY_FOR_CONTEXT_MODELING || length < 64) { return; } else if (ShouldUseComplexStaticContextMap( input, start_pos, length, mask, quality, size_hint, num_literal_contexts, literal_context_map, arena)) { /* Context map was already set, nothing else to do. */ } else { /* Gather bi-gram data of the UTF8 byte prefixes. To make the analysis of UTF8 data faster we only examine 64 byte long strides at every 4kB intervals. */ const size_t end_pos = start_pos + length; uint32_t* BROTLI_RESTRICT const bigram_prefix_histo = arena; memset(bigram_prefix_histo, 0, sizeof(arena[0]) * 9); for (; start_pos + 64 <= end_pos; start_pos += 4096) { static const int lut[4] = { 0, 0, 1, 2 }; const size_t stride_end_pos = start_pos + 64; int prev = lut[input[start_pos & mask] >> 6] * 3; size_t pos; for (pos = start_pos + 1; pos < stride_end_pos; ++pos) { const uint8_t literal = input[pos & mask]; ++bigram_prefix_histo[prev + lut[literal >> 6]]; prev = lut[literal >> 6] * 3; } } ChooseContextMap(quality, &bigram_prefix_histo[0], num_literal_contexts, literal_context_map); } } static BROTLI_BOOL ShouldCompress( const uint8_t* data, const size_t mask, const uint64_t last_flush_pos, const size_t bytes, const size_t num_literals, const size_t num_commands) { /* TODO(eustas): find more precise minimal block overhead. */ if (bytes <= 2) return BROTLI_FALSE; if (num_commands < (bytes >> 8) + 2) { if ((double)num_literals > 0.99 * (double)bytes) { uint32_t literal_histo[256] = { 0 }; static const uint32_t kSampleRate = 13; static const double kMinEntropy = 7.92; const double bit_cost_threshold = (double)bytes * kMinEntropy / kSampleRate; size_t t = (bytes + kSampleRate - 1) / kSampleRate; uint32_t pos = (uint32_t)last_flush_pos; size_t i; for (i = 0; i < t; i++) { ++literal_histo[data[pos & mask]]; pos += kSampleRate; } if (BitsEntropy(literal_histo, 256) > bit_cost_threshold) { return BROTLI_FALSE; } } } return BROTLI_TRUE; } /* Chooses the literal context mode for a metablock */ static ContextType ChooseContextMode(const BrotliEncoderParams* params, const uint8_t* data, const size_t pos, const size_t mask, const size_t length) { /* We only do the computation for the option of something else than CONTEXT_UTF8 for the highest qualities */ if (params->quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING && !BrotliIsMostlyUTF8(data, pos, mask, length, kMinUTF8Ratio)) { return CONTEXT_SIGNED; } return CONTEXT_UTF8; } static void WriteMetaBlockInternal(MemoryManager* m, const uint8_t* data, const size_t mask, const uint64_t last_flush_pos, const size_t bytes, const BROTLI_BOOL is_last, ContextType literal_context_mode, const BrotliEncoderParams* params, const uint8_t prev_byte, const uint8_t prev_byte2, const size_t num_literals, const size_t num_commands, Command* commands, const int* saved_dist_cache, int* dist_cache, size_t* storage_ix, uint8_t* storage) { const uint32_t wrapped_last_flush_pos = WrapPosition(last_flush_pos); uint16_t last_bytes; uint8_t last_bytes_bits; ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode); BrotliEncoderParams block_params = *params; if (bytes == 0) { /* Write the ISLAST and ISEMPTY bits. */ BrotliWriteBits(2, 3, storage_ix, storage); *storage_ix = (*storage_ix + 7u) & ~7u; return; } if (!ShouldCompress(data, mask, last_flush_pos, bytes, num_literals, num_commands)) { /* Restore the distance cache, as its last update by CreateBackwardReferences is now unused. */ memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0])); BrotliStoreUncompressedMetaBlock(is_last, data, wrapped_last_flush_pos, mask, bytes, storage_ix, storage); return; } BROTLI_DCHECK(*storage_ix <= 14); last_bytes = (uint16_t)((storage[1] << 8) | storage[0]); last_bytes_bits = (uint8_t)(*storage_ix); if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) { BrotliStoreMetaBlockFast(m, data, wrapped_last_flush_pos, bytes, mask, is_last, params, commands, num_commands, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) { BrotliStoreMetaBlockTrivial(m, data, wrapped_last_flush_pos, bytes, mask, is_last, params, commands, num_commands, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; } else { MetaBlockSplit mb; InitMetaBlockSplit(&mb); if (params->quality < MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) { size_t num_literal_contexts = 1; const uint32_t* literal_context_map = NULL; if (!params->disable_literal_context_modeling) { /* TODO(eustas): pull to higher level and reuse. */ uint32_t* arena = BROTLI_ALLOC(m, uint32_t, 14 * 32); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; DecideOverLiteralContextModeling( data, wrapped_last_flush_pos, bytes, mask, params->quality, params->size_hint, &num_literal_contexts, &literal_context_map, arena); BROTLI_FREE(m, arena); } BrotliBuildMetaBlockGreedy(m, data, wrapped_last_flush_pos, mask, prev_byte, prev_byte2, literal_context_lut, num_literal_contexts, literal_context_map, commands, num_commands, &mb); if (BROTLI_IS_OOM(m)) return; } else { BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, &block_params, prev_byte, prev_byte2, commands, num_commands, literal_context_mode, &mb); if (BROTLI_IS_OOM(m)) return; } if (params->quality >= MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS) { /* The number of distance symbols effectively used for distance histograms. It might be less than distance alphabet size for "Large Window Brotli" (32-bit). */ BrotliOptimizeHistograms(block_params.dist.alphabet_size_limit, &mb); } BrotliStoreMetaBlock(m, data, wrapped_last_flush_pos, bytes, mask, prev_byte, prev_byte2, is_last, &block_params, literal_context_mode, commands, num_commands, &mb, storage_ix, storage); if (BROTLI_IS_OOM(m)) return; DestroyMetaBlockSplit(m, &mb); } if (bytes + 4 < (*storage_ix >> 3)) { /* Restore the distance cache and last byte. */ memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0])); storage[0] = (uint8_t)last_bytes; storage[1] = (uint8_t)(last_bytes >> 8); *storage_ix = last_bytes_bits; BrotliStoreUncompressedMetaBlock(is_last, data, wrapped_last_flush_pos, mask, bytes, storage_ix, storage); } } static void ChooseDistanceParams(BrotliEncoderParams* params) { uint32_t distance_postfix_bits = 0; uint32_t num_direct_distance_codes = 0; if (params->quality >= MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS) { uint32_t ndirect_msb; if (params->mode == BROTLI_MODE_FONT) { distance_postfix_bits = 1; num_direct_distance_codes = 12; } else { distance_postfix_bits = params->dist.distance_postfix_bits; num_direct_distance_codes = params->dist.num_direct_distance_codes; } ndirect_msb = (num_direct_distance_codes >> distance_postfix_bits) & 0x0F; if (distance_postfix_bits > BROTLI_MAX_NPOSTFIX || num_direct_distance_codes > BROTLI_MAX_NDIRECT || (ndirect_msb << distance_postfix_bits) != num_direct_distance_codes) { distance_postfix_bits = 0; num_direct_distance_codes = 0; } } BrotliInitDistanceParams(¶ms->dist, distance_postfix_bits, num_direct_distance_codes, params->large_window); } static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) { MemoryManager* m = &s->memory_manager_; if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; if (s->is_initialized_) return BROTLI_TRUE; s->last_bytes_bits_ = 0; s->last_bytes_ = 0; s->flint_ = BROTLI_FLINT_DONE; s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX; SanitizeParams(&s->params); s->params.lgblock = ComputeLgBlock(&s->params); ChooseDistanceParams(&s->params); if (s->params.stream_offset != 0) { s->flint_ = BROTLI_FLINT_NEEDS_2_BYTES; /* Poison the distance cache. -16 +- 3 is still less than zero (invalid). */ s->dist_cache_[0] = -16; s->dist_cache_[1] = -16; s->dist_cache_[2] = -16; s->dist_cache_[3] = -16; memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_)); } RingBufferSetup(&s->params, &s->ringbuffer_); /* Initialize last byte with stream header. */ { int lgwin = s->params.lgwin; if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { lgwin = BROTLI_MAX(int, lgwin, 18); } if (s->params.stream_offset == 0) { EncodeWindowBits(lgwin, s->params.large_window, &s->last_bytes_, &s->last_bytes_bits_); } else { /* Bigger values have the same effect, but could cause overflows. */ s->params.stream_offset = BROTLI_MIN(size_t, s->params.stream_offset, BROTLI_MAX_BACKWARD_LIMIT(lgwin)); } } if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { s->one_pass_arena_ = BROTLI_ALLOC(m, BrotliOnePassArena, 1); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; InitCommandPrefixCodes(s->one_pass_arena_); } else if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { s->two_pass_arena_ = BROTLI_ALLOC(m, BrotliTwoPassArena, 1); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } s->is_initialized_ = BROTLI_TRUE; return BROTLI_TRUE; } static void BrotliEncoderInitParams(BrotliEncoderParams* params) { params->mode = BROTLI_DEFAULT_MODE; params->large_window = BROTLI_FALSE; params->quality = BROTLI_DEFAULT_QUALITY; params->lgwin = BROTLI_DEFAULT_WINDOW; params->lgblock = 0; params->stream_offset = 0; params->size_hint = 0; params->disable_literal_context_modeling = BROTLI_FALSE; BrotliInitSharedEncoderDictionary(¶ms->dictionary); params->dist.distance_postfix_bits = 0; params->dist.num_direct_distance_codes = 0; params->dist.alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_MAX_DISTANCE_BITS); params->dist.alphabet_size_limit = params->dist.alphabet_size_max; params->dist.max_distance = BROTLI_MAX_DISTANCE; } static void BrotliEncoderCleanupParams(MemoryManager* m, BrotliEncoderParams* params) { BrotliCleanupSharedEncoderDictionary(m, ¶ms->dictionary); } static void BrotliEncoderInitState(BrotliEncoderState* s) { BrotliEncoderInitParams(&s->params); s->input_pos_ = 0; s->num_commands_ = 0; s->num_literals_ = 0; s->last_insert_len_ = 0; s->last_flush_pos_ = 0; s->last_processed_pos_ = 0; s->prev_byte_ = 0; s->prev_byte2_ = 0; s->storage_size_ = 0; s->storage_ = 0; HasherInit(&s->hasher_); s->large_table_ = NULL; s->large_table_size_ = 0; s->one_pass_arena_ = NULL; s->two_pass_arena_ = NULL; s->command_buf_ = NULL; s->literal_buf_ = NULL; s->total_in_ = 0; s->next_out_ = NULL; s->available_out_ = 0; s->total_out_ = 0; s->stream_state_ = BROTLI_STREAM_PROCESSING; s->is_last_block_emitted_ = BROTLI_FALSE; s->is_initialized_ = BROTLI_FALSE; RingBufferInit(&s->ringbuffer_); s->commands_ = 0; s->cmd_alloc_size_ = 0; /* Initialize distance cache. */ s->dist_cache_[0] = 4; s->dist_cache_[1] = 11; s->dist_cache_[2] = 15; s->dist_cache_[3] = 16; /* Save the state of the distance cache in case we need to restore it for emitting an uncompressed block. */ memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_)); } BrotliEncoderState* BrotliEncoderCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { BrotliEncoderState* state = (BrotliEncoderState*)BrotliBootstrapAlloc( sizeof(BrotliEncoderState), alloc_func, free_func, opaque); if (state == NULL) { /* BROTLI_DUMP(); */ return 0; } BrotliInitMemoryManager( &state->memory_manager_, alloc_func, free_func, opaque); BrotliEncoderInitState(state); return state; } #ifdef BROTLI_REPORTING /* When BROTLI_REPORTING is defined extra reporting module have to be linked. */ void BrotliEncoderOnFinish(const BrotliEncoderState* s); #define BROTLI_ENCODER_ON_FINISH(s) BrotliEncoderOnFinish(s); #else #if !defined(BROTLI_ENCODER_ON_FINISH) #define BROTLI_ENCODER_ON_FINISH(s) (void)(s); #endif #endif static void BrotliEncoderCleanupState(BrotliEncoderState* s) { MemoryManager* m = &s->memory_manager_; BROTLI_ENCODER_ON_FINISH(s); if (BROTLI_IS_OOM(m)) { BrotliWipeOutMemoryManager(m); return; } BROTLI_FREE(m, s->storage_); BROTLI_FREE(m, s->commands_); RingBufferFree(m, &s->ringbuffer_); DestroyHasher(m, &s->hasher_); BROTLI_FREE(m, s->large_table_); BROTLI_FREE(m, s->one_pass_arena_); BROTLI_FREE(m, s->two_pass_arena_); BROTLI_FREE(m, s->command_buf_); BROTLI_FREE(m, s->literal_buf_); BrotliEncoderCleanupParams(m, &s->params); } /* Deinitializes and frees BrotliEncoderState instance. */ void BrotliEncoderDestroyInstance(BrotliEncoderState* state) { if (!state) { return; } else { BrotliEncoderCleanupState(state); BrotliBootstrapFree(state, &state->memory_manager_); } } /* Copies the given input data to the internal ring buffer of the compressor. No processing of the data occurs at this time and this function can be called multiple times before calling WriteBrotliData() to process the accumulated input. At most input_block_size() bytes of input data can be copied to the ring buffer, otherwise the next WriteBrotliData() will fail. */ static void CopyInputToRingBuffer(BrotliEncoderState* s, const size_t input_size, const uint8_t* input_buffer) { RingBuffer* ringbuffer_ = &s->ringbuffer_; MemoryManager* m = &s->memory_manager_; RingBufferWrite(m, input_buffer, input_size, ringbuffer_); if (BROTLI_IS_OOM(m)) return; s->input_pos_ += input_size; /* TL;DR: If needed, initialize 7 more bytes in the ring buffer to make the hashing not depend on uninitialized data. This makes compression deterministic and it prevents uninitialized memory warnings in Valgrind. Even without erasing, the output would be valid (but nondeterministic). Background information: The compressor stores short (at most 8 bytes) substrings of the input already read in a hash table, and detects repetitions by looking up such substrings in the hash table. If it can find a substring, it checks whether the substring is really there in the ring buffer (or it's just a hash collision). Should the hash table become corrupt, this check makes sure that the output is still valid, albeit the compression ratio would be bad. The compressor populates the hash table from the ring buffer as it's reading new bytes from the input. However, at the last few indexes of the ring buffer, there are not enough bytes to build full-length substrings from. Since the hash table always contains full-length substrings, we erase with dummy zeros here to make sure that those substrings will contain zeros at the end instead of uninitialized data. Please note that erasing is not necessary (because the memory region is already initialized since he ring buffer has a `tail' that holds a copy of the beginning,) so we skip erasing if we have already gone around at least once in the ring buffer. Only clear during the first round of ring-buffer writes. On subsequent rounds data in the ring-buffer would be affected. */ if (ringbuffer_->pos_ <= ringbuffer_->mask_) { /* This is the first time when the ring buffer is being written. We clear 7 bytes just after the bytes that have been copied from the input buffer. The ring-buffer has a "tail" that holds a copy of the beginning, but only once the ring buffer has been fully written once, i.e., pos <= mask. For the first time, we need to write values in this tail (where index may be larger than mask), so that we have exactly defined behavior and don't read uninitialized memory. Due to performance reasons, hashing reads data using a LOAD64, which can go 7 bytes beyond the bytes written in the ring-buffer. */ memset(ringbuffer_->buffer_ + ringbuffer_->pos_, 0, 7); } } /* Marks all input as processed. Returns true if position wrapping occurs. */ static BROTLI_BOOL UpdateLastProcessedPos(BrotliEncoderState* s) { uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_); uint32_t wrapped_input_pos = WrapPosition(s->input_pos_); s->last_processed_pos_ = s->input_pos_; return TO_BROTLI_BOOL(wrapped_input_pos < wrapped_last_processed_pos); } static void ExtendLastCommand(BrotliEncoderState* s, uint32_t* bytes, uint32_t* wrapped_last_processed_pos) { Command* last_command = &s->commands_[s->num_commands_ - 1]; const uint8_t* data = s->ringbuffer_.buffer_; const uint32_t mask = s->ringbuffer_.mask_; uint64_t max_backward_distance = (((uint64_t)1) << s->params.lgwin) - BROTLI_WINDOW_GAP; uint64_t last_copy_len = last_command->copy_len_ & 0x1FFFFFF; uint64_t last_processed_pos = s->last_processed_pos_ - last_copy_len; uint64_t max_distance = last_processed_pos < max_backward_distance ? last_processed_pos : max_backward_distance; uint64_t cmd_dist = (uint64_t)s->dist_cache_[0]; uint32_t distance_code = CommandRestoreDistanceCode(last_command, &s->params.dist); const CompoundDictionary* dict = &s->params.dictionary.compound; size_t compound_dictionary_size = dict->total_size; if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES || distance_code - (BROTLI_NUM_DISTANCE_SHORT_CODES - 1) == cmd_dist) { if (cmd_dist <= max_distance) { while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] == data[(*wrapped_last_processed_pos - cmd_dist) & mask]) { last_command->copy_len_++; (*bytes)--; (*wrapped_last_processed_pos)++; } } else { if ((cmd_dist - max_distance - 1) < compound_dictionary_size && last_copy_len < cmd_dist - max_distance) { size_t address = compound_dictionary_size - (size_t)(cmd_dist - max_distance) + (size_t)last_copy_len; size_t br_index = 0; size_t br_offset; const uint8_t* chunk; size_t chunk_length; while (address >= dict->chunk_offsets[br_index + 1]) br_index++; br_offset = address - dict->chunk_offsets[br_index]; chunk = dict->chunk_source[br_index]; chunk_length = dict->chunk_offsets[br_index + 1] - dict->chunk_offsets[br_index]; while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] == chunk[br_offset]) { last_command->copy_len_++; (*bytes)--; (*wrapped_last_processed_pos)++; if (++br_offset == chunk_length) { br_index++; br_offset = 0; if (br_index != dict->num_chunks) { chunk = dict->chunk_source[br_index]; chunk_length = dict->chunk_offsets[br_index + 1] - dict->chunk_offsets[br_index]; } else { break; } } } } } /* The copy length is at most the metablock size, and thus expressible. */ GetLengthCode(last_command->insert_len_, (size_t)((int)(last_command->copy_len_ & 0x1FFFFFF) + (int)(last_command->copy_len_ >> 25)), TO_BROTLI_BOOL((last_command->dist_prefix_ & 0x3FF) == 0), &last_command->cmd_prefix_); } } /* Processes the accumulated input data and sets |*out_size| to the length of the new output meta-block, or to zero if no new output meta-block has been created (in this case the processed input data is buffered internally). If |*out_size| is positive, |*output| points to the start of the output data. If |is_last| or |force_flush| is BROTLI_TRUE, an output meta-block is always created. However, until |is_last| is BROTLI_TRUE encoder may retain up to 7 bits of the last byte of output. Byte-alignment could be enforced by emitting an empty meta-data block. Returns BROTLI_FALSE if the size of the input data is larger than input_block_size(). */ static BROTLI_BOOL EncodeData( BrotliEncoderState* s, const BROTLI_BOOL is_last, const BROTLI_BOOL force_flush, size_t* out_size, uint8_t** output) { const uint64_t delta = UnprocessedInputSize(s); uint32_t bytes = (uint32_t)delta; uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_); uint8_t* data; uint32_t mask; MemoryManager* m = &s->memory_manager_; ContextType literal_context_mode; ContextLut literal_context_lut; BROTLI_BOOL fast_compress = s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY; data = s->ringbuffer_.buffer_; mask = s->ringbuffer_.mask_; if (delta == 0) { /* No new input; still might want to flush or finish. */ if (!data) { /* No input has been processed so far. */ if (is_last) { /* Emit complete finalized stream. */ BROTLI_DCHECK(s->last_bytes_bits_ <= 14); s->last_bytes_ |= (uint16_t)(3u << s->last_bytes_bits_); s->last_bytes_bits_ = (uint8_t)(s->last_bytes_bits_ + 2u); s->tiny_buf_.u8[0] = (uint8_t)s->last_bytes_; s->tiny_buf_.u8[1] = (uint8_t)(s->last_bytes_ >> 8); *output = s->tiny_buf_.u8; *out_size = (s->last_bytes_bits_ + 7u) >> 3u; return BROTLI_TRUE; } else { /* No data, not last -> no-op. */ *out_size = 0; return BROTLI_TRUE; } } else { /* Fast compress performs flush every block -> flush is no-op. */ if (!is_last && (!force_flush || fast_compress)) { /* Another no-op. */ *out_size = 0; return BROTLI_TRUE; } } } BROTLI_DCHECK(data); if (s->params.quality > s->params.dictionary.max_quality) return BROTLI_FALSE; /* Adding more blocks after "last" block is forbidden. */ if (s->is_last_block_emitted_) return BROTLI_FALSE; if (is_last) s->is_last_block_emitted_ = BROTLI_TRUE; if (delta > InputBlockSize(s)) { return BROTLI_FALSE; } if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY && !s->command_buf_) { s->command_buf_ = BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize); s->literal_buf_ = BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) || BROTLI_IS_NULL(s->literal_buf_)) { return BROTLI_FALSE; } } if (fast_compress) { uint8_t* storage; size_t storage_ix = s->last_bytes_bits_; size_t table_size; int* table; storage = GetBrotliStorage(s, 2 * bytes + 503); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; storage[0] = (uint8_t)s->last_bytes_; storage[1] = (uint8_t)(s->last_bytes_ >> 8); table = GetHashTable(s, s->params.quality, bytes, &table_size); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { BrotliCompressFragmentFast( s->one_pass_arena_, &data[wrapped_last_processed_pos & mask], bytes, is_last, table, table_size, &storage_ix, storage); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } else { BrotliCompressFragmentTwoPass( s->two_pass_arena_, &data[wrapped_last_processed_pos & mask], bytes, is_last, s->command_buf_, s->literal_buf_, table, table_size, &storage_ix, storage); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]); s->last_bytes_bits_ = storage_ix & 7u; UpdateLastProcessedPos(s); *output = &storage[0]; *out_size = storage_ix >> 3; return BROTLI_TRUE; } { /* Theoretical max number of commands is 1 per 2 bytes. */ size_t newsize = s->num_commands_ + bytes / 2 + 1; if (newsize > s->cmd_alloc_size_) { Command* new_commands; /* Reserve a bit more memory to allow merging with a next block without reallocation: that would impact speed. */ newsize += (bytes / 4) + 16; s->cmd_alloc_size_ = newsize; new_commands = BROTLI_ALLOC(m, Command, newsize); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_commands)) return BROTLI_FALSE; if (s->commands_) { memcpy(new_commands, s->commands_, sizeof(Command) * s->num_commands_); BROTLI_FREE(m, s->commands_); } s->commands_ = new_commands; } } InitOrStitchToPreviousBlock(m, &s->hasher_, data, mask, &s->params, wrapped_last_processed_pos, bytes, is_last); literal_context_mode = ChooseContextMode( &s->params, data, WrapPosition(s->last_flush_pos_), mask, (size_t)(s->input_pos_ - s->last_flush_pos_)); literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; if (s->num_commands_ && s->last_insert_len_ == 0) { ExtendLastCommand(s, &bytes, &wrapped_last_processed_pos); } if (s->params.quality == ZOPFLIFICATION_QUALITY) { BROTLI_DCHECK(s->params.hasher.type == 10); BrotliCreateZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos, data, mask, literal_context_lut, &s->params, &s->hasher_, s->dist_cache_, &s->last_insert_len_, &s->commands_[s->num_commands_], &s->num_commands_, &s->num_literals_); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } else if (s->params.quality == HQ_ZOPFLIFICATION_QUALITY) { BROTLI_DCHECK(s->params.hasher.type == 10); BrotliCreateHqZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos, data, mask, literal_context_lut, &s->params, &s->hasher_, s->dist_cache_, &s->last_insert_len_, &s->commands_[s->num_commands_], &s->num_commands_, &s->num_literals_); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } else { BrotliCreateBackwardReferences(bytes, wrapped_last_processed_pos, data, mask, literal_context_lut, &s->params, &s->hasher_, s->dist_cache_, &s->last_insert_len_, &s->commands_[s->num_commands_], &s->num_commands_, &s->num_literals_); } { const size_t max_length = MaxMetablockSize(&s->params); const size_t max_literals = max_length / 8; const size_t max_commands = max_length / 8; const size_t processed_bytes = (size_t)(s->input_pos_ - s->last_flush_pos_); /* If maximal possible additional block doesn't fit metablock, flush now. */ /* TODO(eustas): Postpone decision until next block arrives? */ const BROTLI_BOOL next_input_fits_metablock = TO_BROTLI_BOOL( processed_bytes + InputBlockSize(s) <= max_length); /* If block splitting is not used, then flush as soon as there is some amount of commands / literals produced. */ const BROTLI_BOOL should_flush = TO_BROTLI_BOOL( s->params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT && s->num_literals_ + s->num_commands_ >= MAX_NUM_DELAYED_SYMBOLS); if (!is_last && !force_flush && !should_flush && next_input_fits_metablock && s->num_literals_ < max_literals && s->num_commands_ < max_commands) { /* Merge with next input block. Everything will happen later. */ if (UpdateLastProcessedPos(s)) { HasherReset(&s->hasher_); } *out_size = 0; return BROTLI_TRUE; } } /* Create the last insert-only command. */ if (s->last_insert_len_ > 0) { InitInsertCommand(&s->commands_[s->num_commands_++], s->last_insert_len_); s->num_literals_ += s->last_insert_len_; s->last_insert_len_ = 0; } if (!is_last && s->input_pos_ == s->last_flush_pos_) { /* We have no new input data and we don't have to finish the stream, so nothing to do. */ *out_size = 0; return BROTLI_TRUE; } BROTLI_DCHECK(s->input_pos_ >= s->last_flush_pos_); BROTLI_DCHECK(s->input_pos_ > s->last_flush_pos_ || is_last); BROTLI_DCHECK(s->input_pos_ - s->last_flush_pos_ <= 1u << 24); { const uint32_t metablock_size = (uint32_t)(s->input_pos_ - s->last_flush_pos_); uint8_t* storage = GetBrotliStorage(s, 2 * metablock_size + 503); size_t storage_ix = s->last_bytes_bits_; if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; storage[0] = (uint8_t)s->last_bytes_; storage[1] = (uint8_t)(s->last_bytes_ >> 8); WriteMetaBlockInternal( m, data, mask, s->last_flush_pos_, metablock_size, is_last, literal_context_mode, &s->params, s->prev_byte_, s->prev_byte2_, s->num_literals_, s->num_commands_, s->commands_, s->saved_dist_cache_, s->dist_cache_, &storage_ix, storage); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]); s->last_bytes_bits_ = storage_ix & 7u; s->last_flush_pos_ = s->input_pos_; if (UpdateLastProcessedPos(s)) { HasherReset(&s->hasher_); } if (s->last_flush_pos_ > 0) { s->prev_byte_ = data[((uint32_t)s->last_flush_pos_ - 1) & mask]; } if (s->last_flush_pos_ > 1) { s->prev_byte2_ = data[(uint32_t)(s->last_flush_pos_ - 2) & mask]; } s->num_commands_ = 0; s->num_literals_ = 0; /* Save the state of the distance cache in case we need to restore it for emitting an uncompressed block. */ memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_)); *output = &storage[0]; *out_size = storage_ix >> 3; return BROTLI_TRUE; } } /* Dumps remaining output bits and metadata header to |header|. Returns number of produced bytes. REQUIRED: |header| should be 8-byte aligned and at least 16 bytes long. REQUIRED: |block_size| <= (1 << 24). */ static size_t WriteMetadataHeader( BrotliEncoderState* s, const size_t block_size, uint8_t* header) { size_t storage_ix; storage_ix = s->last_bytes_bits_; header[0] = (uint8_t)s->last_bytes_; header[1] = (uint8_t)(s->last_bytes_ >> 8); s->last_bytes_ = 0; s->last_bytes_bits_ = 0; BrotliWriteBits(1, 0, &storage_ix, header); BrotliWriteBits(2, 3, &storage_ix, header); BrotliWriteBits(1, 0, &storage_ix, header); if (block_size == 0) { BrotliWriteBits(2, 0, &storage_ix, header); } else { uint32_t nbits = (block_size == 1) ? 1 : (Log2FloorNonZero((uint32_t)block_size - 1) + 1); uint32_t nbytes = (nbits + 7) / 8; BrotliWriteBits(2, nbytes, &storage_ix, header); BrotliWriteBits(8 * nbytes, block_size - 1, &storage_ix, header); } return (storage_ix + 7u) >> 3; } size_t BrotliEncoderMaxCompressedSize(size_t input_size) { /* [window bits / empty metadata] + N * [uncompressed] + [last empty] */ size_t num_large_blocks = input_size >> 14; size_t overhead = 2 + (4 * num_large_blocks) + 3 + 1; size_t result = input_size + overhead; if (input_size == 0) return 2; return (result < input_size) ? 0 : result; } /* Wraps data to uncompressed brotli stream with minimal window size. |output| should point at region with at least BrotliEncoderMaxCompressedSize addressable bytes. Returns the length of stream. */ static size_t MakeUncompressedStream( const uint8_t* input, size_t input_size, uint8_t* output) { size_t size = input_size; size_t result = 0; size_t offset = 0; if (input_size == 0) { output[0] = 6; return 1; } output[result++] = 0x21; /* window bits = 10, is_last = false */ output[result++] = 0x03; /* empty metadata, padding */ while (size > 0) { uint32_t nibbles = 0; uint32_t chunk_size; uint32_t bits; chunk_size = (size > (1u << 24)) ? (1u << 24) : (uint32_t)size; if (chunk_size > (1u << 16)) nibbles = (chunk_size > (1u << 20)) ? 2 : 1; bits = (nibbles << 1) | ((chunk_size - 1) << 3) | (1u << (19 + 4 * nibbles)); output[result++] = (uint8_t)bits; output[result++] = (uint8_t)(bits >> 8); output[result++] = (uint8_t)(bits >> 16); if (nibbles == 2) output[result++] = (uint8_t)(bits >> 24); memcpy(&output[result], &input[offset], chunk_size); result += chunk_size; offset += chunk_size; size -= chunk_size; } output[result++] = 3; return result; } BROTLI_BOOL BrotliEncoderCompress( int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)], size_t* encoded_size, uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]) { BrotliEncoderState* s; size_t out_size = *encoded_size; const uint8_t* input_start = input_buffer; uint8_t* output_start = encoded_buffer; size_t max_out_size = BrotliEncoderMaxCompressedSize(input_size); if (out_size == 0) { /* Output buffer needs at least one byte. */ return BROTLI_FALSE; } if (input_size == 0) { /* Handle the special case of empty input. */ *encoded_size = 1; *encoded_buffer = 6; return BROTLI_TRUE; } s = BrotliEncoderCreateInstance(0, 0, 0); if (!s) { return BROTLI_FALSE; } else { size_t available_in = input_size; const uint8_t* next_in = input_buffer; size_t available_out = *encoded_size; uint8_t* next_out = encoded_buffer; size_t total_out = 0; BROTLI_BOOL result = BROTLI_FALSE; /* TODO(eustas): check that parameters are sane. */ BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality); BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin); BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode); BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size); if (lgwin > BROTLI_MAX_WINDOW_BITS) { BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE); } result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH, &available_in, &next_in, &available_out, &next_out, &total_out); if (!BrotliEncoderIsFinished(s)) result = 0; *encoded_size = total_out; BrotliEncoderDestroyInstance(s); if (!result || (max_out_size && *encoded_size > max_out_size)) { goto fallback; } return BROTLI_TRUE; } fallback: *encoded_size = 0; if (!max_out_size) return BROTLI_FALSE; if (out_size >= max_out_size) { *encoded_size = MakeUncompressedStream(input_start, input_size, output_start); return BROTLI_TRUE; } return BROTLI_FALSE; } static void InjectBytePaddingBlock(BrotliEncoderState* s) { uint32_t seal = s->last_bytes_; size_t seal_bits = s->last_bytes_bits_; uint8_t* destination; s->last_bytes_ = 0; s->last_bytes_bits_ = 0; /* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */ seal |= 0x6u << seal_bits; seal_bits += 6; /* If we have already created storage, then append to it. Storage is valid until next block is being compressed. */ if (s->next_out_) { destination = s->next_out_ + s->available_out_; } else { destination = s->tiny_buf_.u8; s->next_out_ = destination; } destination[0] = (uint8_t)seal; if (seal_bits > 8) destination[1] = (uint8_t)(seal >> 8); if (seal_bits > 16) destination[2] = (uint8_t)(seal >> 16); s->available_out_ += (seal_bits + 7) >> 3; } /* Fills the |total_out|, if it is not NULL. */ static void SetTotalOut(BrotliEncoderState* s, size_t* total_out) { if (total_out) { /* Saturating conversion uint64_t -> size_t */ size_t result = (size_t)-1; if (s->total_out_ < result) { result = (size_t)s->total_out_; } *total_out = result; } } /* Injects padding bits or pushes compressed data to output. Returns false if nothing is done. */ static BROTLI_BOOL InjectFlushOrPushOutput(BrotliEncoderState* s, size_t* available_out, uint8_t** next_out, size_t* total_out) { if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED && s->last_bytes_bits_ != 0) { InjectBytePaddingBlock(s); return BROTLI_TRUE; } if (s->available_out_ != 0 && *available_out != 0) { size_t copy_output_size = BROTLI_MIN(size_t, s->available_out_, *available_out); memcpy(*next_out, s->next_out_, copy_output_size); *next_out += copy_output_size; *available_out -= copy_output_size; s->next_out_ += copy_output_size; s->available_out_ -= copy_output_size; s->total_out_ += copy_output_size; SetTotalOut(s, total_out); return BROTLI_TRUE; } return BROTLI_FALSE; } static void CheckFlushComplete(BrotliEncoderState* s) { if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED && s->available_out_ == 0) { s->stream_state_ = BROTLI_STREAM_PROCESSING; s->next_out_ = 0; } } static BROTLI_BOOL BrotliEncoderCompressStreamFast( BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out) { const size_t block_size_limit = (size_t)1 << s->params.lgwin; const size_t buf_size = BROTLI_MIN(size_t, kCompressFragmentTwoPassBlockSize, BROTLI_MIN(size_t, *available_in, block_size_limit)); uint32_t* tmp_command_buf = NULL; uint32_t* command_buf = NULL; uint8_t* tmp_literal_buf = NULL; uint8_t* literal_buf = NULL; MemoryManager* m = &s->memory_manager_; if (s->params.quality != FAST_ONE_PASS_COMPRESSION_QUALITY && s->params.quality != FAST_TWO_PASS_COMPRESSION_QUALITY) { return BROTLI_FALSE; } if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { if (!s->command_buf_ && buf_size == kCompressFragmentTwoPassBlockSize) { s->command_buf_ = BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize); s->literal_buf_ = BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) || BROTLI_IS_NULL(s->literal_buf_)) { return BROTLI_FALSE; } } if (s->command_buf_) { command_buf = s->command_buf_; literal_buf = s->literal_buf_; } else { tmp_command_buf = BROTLI_ALLOC(m, uint32_t, buf_size); tmp_literal_buf = BROTLI_ALLOC(m, uint8_t, buf_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp_command_buf) || BROTLI_IS_NULL(tmp_literal_buf)) { return BROTLI_FALSE; } command_buf = tmp_command_buf; literal_buf = tmp_literal_buf; } } while (BROTLI_TRUE) { if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) { continue; } /* Compress block only when internal output buffer is empty, stream is not finished, there is no pending flush request, and there is either additional input or pending operation. */ if (s->available_out_ == 0 && s->stream_state_ == BROTLI_STREAM_PROCESSING && (*available_in != 0 || op != BROTLI_OPERATION_PROCESS)) { size_t block_size = BROTLI_MIN(size_t, block_size_limit, *available_in); BROTLI_BOOL is_last = (*available_in == block_size) && (op == BROTLI_OPERATION_FINISH); BROTLI_BOOL force_flush = (*available_in == block_size) && (op == BROTLI_OPERATION_FLUSH); size_t max_out_size = 2 * block_size + 503; BROTLI_BOOL inplace = BROTLI_TRUE; uint8_t* storage = NULL; size_t storage_ix = s->last_bytes_bits_; size_t table_size; int* table; if (force_flush && block_size == 0) { s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED; continue; } if (max_out_size <= *available_out) { storage = *next_out; } else { inplace = BROTLI_FALSE; storage = GetBrotliStorage(s, max_out_size); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } storage[0] = (uint8_t)s->last_bytes_; storage[1] = (uint8_t)(s->last_bytes_ >> 8); table = GetHashTable(s, s->params.quality, block_size, &table_size); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { BrotliCompressFragmentFast(s->one_pass_arena_, *next_in, block_size, is_last, table, table_size, &storage_ix, storage); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } else { BrotliCompressFragmentTwoPass(s->two_pass_arena_, *next_in, block_size, is_last, command_buf, literal_buf, table, table_size, &storage_ix, storage); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; } if (block_size != 0) { *next_in += block_size; *available_in -= block_size; s->total_in_ += block_size; } if (inplace) { size_t out_bytes = storage_ix >> 3; BROTLI_DCHECK(out_bytes <= *available_out); BROTLI_DCHECK((storage_ix & 7) == 0 || out_bytes < *available_out); *next_out += out_bytes; *available_out -= out_bytes; s->total_out_ += out_bytes; SetTotalOut(s, total_out); } else { size_t out_bytes = storage_ix >> 3; s->next_out_ = storage; s->available_out_ = out_bytes; } s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]); s->last_bytes_bits_ = storage_ix & 7u; if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED; if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED; continue; } break; } BROTLI_FREE(m, tmp_command_buf); BROTLI_FREE(m, tmp_literal_buf); CheckFlushComplete(s); return BROTLI_TRUE; } static BROTLI_BOOL ProcessMetadata( BrotliEncoderState* s, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out) { if (*available_in > (1u << 24)) return BROTLI_FALSE; /* Switch to metadata block workflow, if required. */ if (s->stream_state_ == BROTLI_STREAM_PROCESSING) { s->remaining_metadata_bytes_ = (uint32_t)*available_in; s->stream_state_ = BROTLI_STREAM_METADATA_HEAD; } if (s->stream_state_ != BROTLI_STREAM_METADATA_HEAD && s->stream_state_ != BROTLI_STREAM_METADATA_BODY) { return BROTLI_FALSE; } while (BROTLI_TRUE) { if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) { continue; } if (s->available_out_ != 0) break; if (s->input_pos_ != s->last_flush_pos_) { BROTLI_BOOL result = EncodeData(s, BROTLI_FALSE, BROTLI_TRUE, &s->available_out_, &s->next_out_); if (!result) return BROTLI_FALSE; continue; } if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD) { s->next_out_ = s->tiny_buf_.u8; s->available_out_ = WriteMetadataHeader(s, s->remaining_metadata_bytes_, s->next_out_); s->stream_state_ = BROTLI_STREAM_METADATA_BODY; continue; } else { /* Exit workflow only when there is no more input and no more output. Otherwise client may continue producing empty metadata blocks. */ if (s->remaining_metadata_bytes_ == 0) { s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX; s->stream_state_ = BROTLI_STREAM_PROCESSING; break; } if (*available_out) { /* Directly copy input to output. */ uint32_t copy = (uint32_t)BROTLI_MIN( size_t, s->remaining_metadata_bytes_, *available_out); memcpy(*next_out, *next_in, copy); *next_in += copy; *available_in -= copy; s->total_in_ += copy; /* not actually data input, though */ s->remaining_metadata_bytes_ -= copy; *next_out += copy; *available_out -= copy; } else { /* This guarantees progress in "TakeOutput" workflow. */ uint32_t copy = BROTLI_MIN(uint32_t, s->remaining_metadata_bytes_, 16); s->next_out_ = s->tiny_buf_.u8; memcpy(s->next_out_, *next_in, copy); *next_in += copy; *available_in -= copy; s->total_in_ += copy; /* not actually data input, though */ s->remaining_metadata_bytes_ -= copy; s->available_out_ = copy; } continue; } } return BROTLI_TRUE; } static void UpdateSizeHint(BrotliEncoderState* s, size_t available_in) { if (s->params.size_hint == 0) { uint64_t delta = UnprocessedInputSize(s); uint64_t tail = available_in; uint32_t limit = 1u << 30; uint32_t total; if ((delta >= limit) || (tail >= limit) || ((delta + tail) >= limit)) { total = limit; } else { total = (uint32_t)(delta + tail); } s->params.size_hint = total; } } BROTLI_BOOL BrotliEncoderCompressStream( BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out) { if (!EnsureInitialized(s)) return BROTLI_FALSE; /* Unfinished metadata block; check requirements. */ if (s->remaining_metadata_bytes_ != BROTLI_UINT32_MAX) { if (*available_in != s->remaining_metadata_bytes_) return BROTLI_FALSE; if (op != BROTLI_OPERATION_EMIT_METADATA) return BROTLI_FALSE; } if (op == BROTLI_OPERATION_EMIT_METADATA) { UpdateSizeHint(s, 0); /* First data metablock might be emitted here. */ return ProcessMetadata( s, available_in, next_in, available_out, next_out, total_out); } if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD || s->stream_state_ == BROTLI_STREAM_METADATA_BODY) { return BROTLI_FALSE; } if (s->stream_state_ != BROTLI_STREAM_PROCESSING && *available_in != 0) { return BROTLI_FALSE; } if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { return BrotliEncoderCompressStreamFast(s, op, available_in, next_in, available_out, next_out, total_out); } while (BROTLI_TRUE) { size_t remaining_block_size = RemainingInputBlockSize(s); /* Shorten input to flint size. */ if (s->flint_ >= 0 && remaining_block_size > (size_t)s->flint_) { remaining_block_size = (size_t)s->flint_; } if (remaining_block_size != 0 && *available_in != 0) { size_t copy_input_size = BROTLI_MIN(size_t, remaining_block_size, *available_in); CopyInputToRingBuffer(s, copy_input_size, *next_in); *next_in += copy_input_size; *available_in -= copy_input_size; s->total_in_ += copy_input_size; if (s->flint_ > 0) s->flint_ = (int8_t)(s->flint_ - (int)copy_input_size); continue; } if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) { /* Exit the "emit flint" workflow. */ if (s->flint_ == BROTLI_FLINT_WAITING_FOR_FLUSHING) { CheckFlushComplete(s); if (s->stream_state_ == BROTLI_STREAM_PROCESSING) { s->flint_ = BROTLI_FLINT_DONE; } } continue; } /* Compress data only when internal output buffer is empty, stream is not finished and there is no pending flush request. */ if (s->available_out_ == 0 && s->stream_state_ == BROTLI_STREAM_PROCESSING) { if (remaining_block_size == 0 || op != BROTLI_OPERATION_PROCESS) { BROTLI_BOOL is_last = TO_BROTLI_BOOL( (*available_in == 0) && op == BROTLI_OPERATION_FINISH); BROTLI_BOOL force_flush = TO_BROTLI_BOOL( (*available_in == 0) && op == BROTLI_OPERATION_FLUSH); BROTLI_BOOL result; /* Force emitting (uncompressed) piece containing flint. */ if (!is_last && s->flint_ == 0) { s->flint_ = BROTLI_FLINT_WAITING_FOR_FLUSHING; force_flush = BROTLI_TRUE; } UpdateSizeHint(s, *available_in); result = EncodeData(s, is_last, force_flush, &s->available_out_, &s->next_out_); if (!result) return BROTLI_FALSE; if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED; if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED; continue; } } break; } CheckFlushComplete(s); return BROTLI_TRUE; } BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* s) { return TO_BROTLI_BOOL(s->stream_state_ == BROTLI_STREAM_FINISHED && !BrotliEncoderHasMoreOutput(s)); } BROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState* s) { return TO_BROTLI_BOOL(s->available_out_ != 0); } const uint8_t* BrotliEncoderTakeOutput(BrotliEncoderState* s, size_t* size) { size_t consumed_size = s->available_out_; uint8_t* result = s->next_out_; if (*size) { consumed_size = BROTLI_MIN(size_t, *size, s->available_out_); } if (consumed_size) { s->next_out_ += consumed_size; s->available_out_ -= consumed_size; s->total_out_ += consumed_size; CheckFlushComplete(s); *size = consumed_size; } else { *size = 0; result = 0; } return result; } uint32_t BrotliEncoderVersion(void) { return BROTLI_VERSION; } BrotliEncoderPreparedDictionary* BrotliEncoderPrepareDictionary( BrotliSharedDictionaryType type, size_t size, const uint8_t data[BROTLI_ARRAY_PARAM(size)], int quality, brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { ManagedDictionary* managed_dictionary = NULL; BROTLI_BOOL type_is_known = BROTLI_FALSE; type_is_known |= (type == BROTLI_SHARED_DICTIONARY_RAW); #if defined(BROTLI_EXPERIMENTAL) type_is_known |= (type == BROTLI_SHARED_DICTIONARY_SERIALIZED); #endif /* BROTLI_EXPERIMENTAL */ if (!type_is_known) { return NULL; } managed_dictionary = BrotliCreateManagedDictionary(alloc_func, free_func, opaque); if (managed_dictionary == NULL) { return NULL; } if (type == BROTLI_SHARED_DICTIONARY_RAW) { managed_dictionary->dictionary = (uint32_t*)CreatePreparedDictionary( &managed_dictionary->memory_manager_, data, size); } #if defined(BROTLI_EXPERIMENTAL) if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) { SharedEncoderDictionary* dict = (SharedEncoderDictionary*)BrotliAllocate( &managed_dictionary->memory_manager_, sizeof(SharedEncoderDictionary)); managed_dictionary->dictionary = (uint32_t*)dict; if (dict != NULL) { BROTLI_BOOL ok = BrotliInitCustomSharedEncoderDictionary( &managed_dictionary->memory_manager_, data, size, quality, dict); if (!ok) { BrotliFree(&managed_dictionary->memory_manager_, dict); managed_dictionary->dictionary = NULL; } } } #else /* BROTLI_EXPERIMENTAL */ (void)quality; #endif /* BROTLI_EXPERIMENTAL */ if (managed_dictionary->dictionary == NULL) { BrotliDestroyManagedDictionary(managed_dictionary); return NULL; } return (BrotliEncoderPreparedDictionary*)managed_dictionary; } void BrotliEncoderDestroyPreparedDictionary( BrotliEncoderPreparedDictionary* dictionary) { ManagedDictionary* dict = (ManagedDictionary*)dictionary; if (!dictionary) return; /* First field of dictionary structs. */ /* Only managed dictionaries are eligible for destruction by this method. */ if (dict->magic != kManagedDictionaryMagic) { return; } if (dict->dictionary == NULL) { /* This should never ever happen. */ } else if (*dict->dictionary == kLeanPreparedDictionaryMagic) { DestroyPreparedDictionary( &dict->memory_manager_, (PreparedDictionary*)dict->dictionary); } else if (*dict->dictionary == kSharedDictionaryMagic) { BrotliCleanupSharedEncoderDictionary(&dict->memory_manager_, (SharedEncoderDictionary*)dict->dictionary); BrotliFree(&dict->memory_manager_, dict->dictionary); } else { /* There is also kPreparedDictionaryMagic, but such instances should be * constructed and destroyed by different means. */ } dict->dictionary = NULL; BrotliDestroyManagedDictionary(dict); } BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(BrotliEncoderState* state, const BrotliEncoderPreparedDictionary* dictionary) { /* First field of dictionary structs */ const BrotliEncoderPreparedDictionary* dict = dictionary; uint32_t magic = *((const uint32_t*)dict); SharedEncoderDictionary* current = NULL; if (magic == kManagedDictionaryMagic) { /* Unwrap managed dictionary. */ ManagedDictionary* managed_dictionary = (ManagedDictionary*)dict; magic = *managed_dictionary->dictionary; dict = (BrotliEncoderPreparedDictionary*)managed_dictionary->dictionary; } current = &state->params.dictionary; if (magic == kPreparedDictionaryMagic || magic == kLeanPreparedDictionaryMagic) { const PreparedDictionary* prepared = (const PreparedDictionary*)dict; if (!AttachPreparedDictionary(¤t->compound, prepared)) { return BROTLI_FALSE; } } else if (magic == kSharedDictionaryMagic) { const SharedEncoderDictionary* attached = (const SharedEncoderDictionary*)dict; BROTLI_BOOL was_default = !current->contextual.context_based && current->contextual.num_dictionaries == 1 && current->contextual.dict[0]->hash_table_words == kStaticDictionaryHashWords && current->contextual.dict[0]->hash_table_lengths == kStaticDictionaryHashLengths; BROTLI_BOOL new_default = !attached->contextual.context_based && attached->contextual.num_dictionaries == 1 && attached->contextual.dict[0]->hash_table_words == kStaticDictionaryHashWords && attached->contextual.dict[0]->hash_table_lengths == kStaticDictionaryHashLengths; size_t i; if (state->is_initialized_) return BROTLI_FALSE; current->max_quality = BROTLI_MIN(int, current->max_quality, attached->max_quality); for (i = 0; i < attached->compound.num_chunks; i++) { if (!AttachPreparedDictionary(¤t->compound, attached->compound.chunks[i])) { return BROTLI_FALSE; } } if (!new_default) { if (!was_default) return BROTLI_FALSE; /* Copy by value, but then set num_instances_ to 0 because their memory is managed by attached, not by current */ current->contextual = attached->contextual; current->contextual.num_instances_ = 0; } } else { return BROTLI_FALSE; } return BROTLI_TRUE; } size_t BrotliEncoderEstimatePeakMemoryUsage(int quality, int lgwin, size_t input_size) { BrotliEncoderParams params; size_t memory_manager_slots = BROTLI_ENCODER_MEMORY_MANAGER_SLOTS; size_t memory_manager_size = memory_manager_slots * sizeof(void*); BrotliEncoderInitParams(¶ms); params.quality = quality; params.lgwin = lgwin; params.size_hint = input_size; params.large_window = lgwin > BROTLI_MAX_WINDOW_BITS; SanitizeParams(¶ms); params.lgblock = ComputeLgBlock(¶ms); ChooseHasher(¶ms, ¶ms.hasher); if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { size_t state_size = sizeof(BrotliEncoderState); size_t block_size = BROTLI_MIN(size_t, input_size, (1ul << params.lgwin)); size_t hash_table_size = HashTableSize(MaxHashTableSize(params.quality), block_size); size_t hash_size = (hash_table_size < (1u << 10)) ? 0 : sizeof(int) * hash_table_size; size_t cmdbuf_size = params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY ? 5 * BROTLI_MIN(size_t, block_size, 1ul << 17) : 0; if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { state_size += sizeof(BrotliOnePassArena); } else { state_size += sizeof(BrotliTwoPassArena); } return hash_size + cmdbuf_size + state_size; } else { size_t short_ringbuffer_size = (size_t)1 << params.lgblock; int ringbuffer_bits = ComputeRbBits(¶ms); size_t ringbuffer_size = input_size < short_ringbuffer_size ? input_size : (1u << ringbuffer_bits) + short_ringbuffer_size; size_t hash_size[4] = {0}; size_t metablock_size = BROTLI_MIN(size_t, input_size, MaxMetablockSize(¶ms)); size_t inputblock_size = BROTLI_MIN(size_t, input_size, (size_t)1 << params.lgblock); size_t cmdbuf_size = metablock_size * 2 + inputblock_size * 6; size_t outbuf_size = metablock_size * 2 + 503; size_t histogram_size = 0; HasherSize(¶ms, BROTLI_TRUE, input_size, hash_size); if (params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT) { cmdbuf_size = BROTLI_MIN(size_t, cmdbuf_size, MAX_NUM_DELAYED_SYMBOLS * sizeof(Command) + inputblock_size * 12); } if (params.quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) { /* Only a very rough estimation, based on enwik8. */ histogram_size = 200 << 20; } else if (params.quality >= MIN_QUALITY_FOR_BLOCK_SPLIT) { size_t literal_histograms = BROTLI_MIN(size_t, metablock_size / 6144, 256); size_t command_histograms = BROTLI_MIN(size_t, metablock_size / 6144, 256); size_t distance_histograms = BROTLI_MIN(size_t, metablock_size / 6144, 256); histogram_size = literal_histograms * sizeof(HistogramLiteral) + command_histograms * sizeof(HistogramCommand) + distance_histograms * sizeof(HistogramDistance); } return (memory_manager_size + ringbuffer_size + hash_size[0] + hash_size[1] + hash_size[2] + hash_size[3] + cmdbuf_size + outbuf_size + histogram_size); } } size_t BrotliEncoderGetPreparedDictionarySize( const BrotliEncoderPreparedDictionary* prepared_dictionary) { /* First field of dictionary structs */ const BrotliEncoderPreparedDictionary* prepared = prepared_dictionary; uint32_t magic = *((const uint32_t*)prepared); size_t overhead = 0; if (magic == kManagedDictionaryMagic) { const ManagedDictionary* managed = (const ManagedDictionary*)prepared; overhead = sizeof(ManagedDictionary); magic = *managed->dictionary; prepared = (const BrotliEncoderPreparedDictionary*)managed->dictionary; } if (magic == kPreparedDictionaryMagic) { const PreparedDictionary* dictionary = (const PreparedDictionary*)prepared; /* Keep in sync with step 3 of CreatePreparedDictionary */ return sizeof(PreparedDictionary) + dictionary->source_size + (sizeof(uint32_t) << dictionary->slot_bits) + (sizeof(uint16_t) << dictionary->bucket_bits) + (sizeof(uint32_t) * dictionary->num_items) + overhead; } else if (magic == kLeanPreparedDictionaryMagic) { const PreparedDictionary* dictionary = (const PreparedDictionary*)prepared; /* Keep in sync with step 3 of CreatePreparedDictionary */ return sizeof(PreparedDictionary) + sizeof(uint8_t*) + (sizeof(uint32_t) << dictionary->slot_bits) + (sizeof(uint16_t) << dictionary->bucket_bits) + (sizeof(uint32_t) * dictionary->num_items) + overhead; } else if (magic == kSharedDictionaryMagic) { const SharedEncoderDictionary* dictionary = (const SharedEncoderDictionary*)prepared; const CompoundDictionary* compound = &dictionary->compound; const ContextualEncoderDictionary* contextual = &dictionary->contextual; size_t result = sizeof(*dictionary); size_t i; size_t num_instances; const BrotliEncoderDictionary* instances; for (i = 0; i < compound->num_prepared_instances_; i++) { size_t size = BrotliEncoderGetPreparedDictionarySize( (const BrotliEncoderPreparedDictionary*) compound->prepared_instances_[i]); if (!size) return 0; /* error */ result += size; } if (contextual->context_based) { num_instances = contextual->num_instances_; instances = contextual->instances_; result += sizeof(*instances) * num_instances; } else { num_instances = 1; instances = &contextual->instance_; } for (i = 0; i < num_instances; i++) { const BrotliEncoderDictionary* dict = &instances[i]; result += dict->trie.pool_capacity * sizeof(BrotliTrieNode); if (dict->hash_table_data_words_) { result += sizeof(kStaticDictionaryHashWords); } if (dict->hash_table_data_lengths_) { result += sizeof(kStaticDictionaryHashLengths); } if (dict->buckets_data_) { result += sizeof(*dict->buckets_data_) * dict->buckets_alloc_size_; } if (dict->dict_words_data_) { result += sizeof(*dict->dict_words) * dict->dict_words_alloc_size_; } if (dict->words_instance_) { result += sizeof(*dict->words_instance_); /* data_size not added here: it is never allocated by the SharedEncoderDictionary, instead it always points to the file already loaded in memory. So if the caller wants to include this memory as well, add the size of the loaded dictionary file to this. */ } } return result + overhead; } return 0; /* error */ } #if defined(BROTLI_TEST) size_t MakeUncompressedStreamForTest(const uint8_t*, size_t, uint8_t*); size_t MakeUncompressedStreamForTest( const uint8_t* input, size_t input_size, uint8_t* output) { return MakeUncompressedStream(input, input_size, output); } #endif #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/encoder_dict.c000066400000000000000000000553611501401750600206300ustar00rootroot00000000000000/* Copyright 2017 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "encoder_dict.h" #include /* malloc, free */ #include "../common/dictionary.h" #include "../common/platform.h" #include "../common/shared_dictionary_internal.h" #include "../common/transform.h" #include "compound_dictionary.h" #include "dictionary_hash.h" #include "memory.h" #include "quality.h" #include "hash.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define NUM_HASH_BITS 15u #define NUM_HASH_BUCKETS (1u << NUM_HASH_BITS) static void BrotliTrieInit(BrotliTrie* trie) { trie->pool_capacity = 0; trie->pool_size = 0; trie->pool = 0; /* Set up the root node */ trie->root.single = 0; trie->root.len_ = 0; trie->root.idx_ = 0; trie->root.sub = 0; } static void BrotliTrieFree(MemoryManager* m, BrotliTrie* trie) { BrotliFree(m, trie->pool); } /* Initializes to RFC 7932 static dictionary / transforms. */ static void InitEncoderDictionary(BrotliEncoderDictionary* dict) { dict->words = BrotliGetDictionary(); dict->num_transforms = (uint32_t)BrotliGetTransforms()->num_transforms; dict->hash_table_words = kStaticDictionaryHashWords; dict->hash_table_lengths = kStaticDictionaryHashLengths; dict->buckets = kStaticDictionaryBuckets; dict->dict_words = kStaticDictionaryWords; dict->cutoffTransformsCount = kCutoffTransformsCount; dict->cutoffTransforms = kCutoffTransforms; dict->parent = 0; dict->hash_table_data_words_ = 0; dict->hash_table_data_lengths_ = 0; dict->buckets_alloc_size_ = 0; dict->buckets_data_ = 0; dict->dict_words_alloc_size_ = 0; dict->dict_words_data_ = 0; dict->words_instance_ = 0; dict->has_words_heavy = BROTLI_FALSE; BrotliTrieInit(&dict->trie); } static void BrotliDestroyEncoderDictionary(MemoryManager* m, BrotliEncoderDictionary* dict) { BrotliFree(m, dict->hash_table_data_words_); BrotliFree(m, dict->hash_table_data_lengths_); BrotliFree(m, dict->buckets_data_); BrotliFree(m, dict->dict_words_data_); BrotliFree(m, dict->words_instance_); BrotliTrieFree(m, &dict->trie); } #if defined(BROTLI_EXPERIMENTAL) /* Word length must be at least 4 bytes */ static uint32_t Hash(const uint8_t* data, int bits) { uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return h >> (32 - bits); } /* Theoretical max possible word size after transform */ #define kTransformedBufferSize \ (256 + 256 + SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) /* To be safe buffer must have at least kTransformedBufferSize */ static void TransformedDictionaryWord(uint32_t word_idx, int len, int transform, const BrotliTransforms* transforms, const BrotliEncoderDictionary* dict, uint8_t* buffer, size_t* size) { const uint8_t* dict_word = &dict->words->data[ dict->words->offsets_by_length[len] + (uint32_t)len * word_idx]; *size = (size_t)BrotliTransformDictionaryWord(buffer, dict_word, len, transforms, transform); } static DictWord MakeDictWord(uint8_t len, uint8_t transform, uint16_t idx) { DictWord result; result.len = len; result.transform = transform; result.idx = idx; return result; } static uint32_t BrotliTrieAlloc(MemoryManager* m, size_t num, BrotliTrie* trie, BrotliTrieNode** keep) { uint32_t result; uint32_t keep_index = 0; if (keep && *keep != &trie->root) { /* Optional node to keep, since address may change after re-allocating */ keep_index = (uint32_t)(*keep - trie->pool); } if (trie->pool_size == 0) { /* Have a dummy node in the front. We do not want the result to be 0, it must be at least 1, 0 represents "null pointer" */ trie->pool_size = 1; } BROTLI_ENSURE_CAPACITY(m, BrotliTrieNode, trie->pool, trie->pool_capacity, trie->pool_size + num); if (BROTLI_IS_OOM(m)) return 0; /* Init the new nodes to empty */ memset(trie->pool + trie->pool_size, 0, sizeof(*trie->pool) * num); result = (uint32_t)trie->pool_size; trie->pool_size += num; if (keep && *keep != &trie->root) { *keep = trie->pool + keep_index; } return result; } /** * len and idx: payload for last node * word, size: the string * index: position in the string */ static BROTLI_BOOL BrotliTrieNodeAdd(MemoryManager* m, uint8_t len, uint32_t idx, const uint8_t* word, size_t size, int index, BrotliTrieNode* node, BrotliTrie* trie) { BrotliTrieNode* child = 0; uint8_t c; if ((size_t)index == size) { if (!node->len_ || idx < node->idx_) { node->len_ = len; node->idx_ = idx; } return BROTLI_TRUE; } c = word[index]; if (node->single && c != node->c) { BrotliTrieNode old = trie->pool[node->sub]; uint32_t new_nodes = BrotliTrieAlloc(m, 32, trie, &node); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; node->single = 0; node->sub = new_nodes; trie->pool[node->sub + (node->c >> 4)].sub = new_nodes + 16; trie->pool[trie->pool[node->sub + (node->c >> 4)].sub + (node->c & 15)] = old; } if (!node->sub) { uint32_t new_node = BrotliTrieAlloc(m, 1, trie, &node); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; node->single = 1; node->c = c; node->sub = new_node; } if (node->single) { child = &trie->pool[node->sub]; } else { if (!trie->pool[node->sub + (c >> 4)].sub) { uint32_t new_nodes = BrotliTrieAlloc(m, 16, trie, &node); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; trie->pool[node->sub + (c >> 4)].sub = new_nodes; } child = &trie->pool[trie->pool[node->sub + (c >> 4)].sub + (c & 15)]; } return BrotliTrieNodeAdd(m, len, idx, word, size, index + 1, child, trie); } static BROTLI_BOOL BrotliTrieAdd(MemoryManager* m, uint8_t len, uint32_t idx, const uint8_t* word, size_t size, BrotliTrie* trie) { return BrotliTrieNodeAdd(m, len, idx, word, size, 0, &trie->root, trie); } const BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie, const BrotliTrieNode* node, uint8_t c) { BrotliTrieNode* temp_node; if (node->single) { if (node->c == c) return &trie->pool[node->sub]; return 0; } if (!node->sub) return 0; temp_node = &trie->pool[node->sub + (c >> 4)]; if (!temp_node->sub) return 0; return &trie->pool[temp_node->sub + (c & 15)]; } static const BrotliTrieNode* BrotliTrieFind(const BrotliTrie* trie, const uint8_t* word, size_t size) { const BrotliTrieNode* node = &trie->root; size_t i; for (i = 0; i < size; i++) { node = BrotliTrieSub(trie, node, word[i]); if (!node) return 0; } return node; } static BROTLI_BOOL BuildDictionaryLut(MemoryManager* m, const BrotliTransforms* transforms, BrotliEncoderDictionary* dict) { uint32_t i; DictWord* dict_words; uint16_t* buckets; DictWord** words_by_hash; size_t* words_by_hash_size; size_t* words_by_hash_capacity; BrotliTrie dedup; uint8_t word[kTransformedBufferSize]; size_t word_size; size_t total = 0; uint8_t l; uint16_t idx; BrotliTrieInit(&dedup); words_by_hash = (DictWord**)BrotliAllocate(m, sizeof(*words_by_hash) * NUM_HASH_BUCKETS); words_by_hash_size = (size_t*)BrotliAllocate(m, sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS); words_by_hash_capacity = (size_t*)BrotliAllocate(m, sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; memset(words_by_hash, 0, sizeof(*words_by_hash) * NUM_HASH_BUCKETS); memset(words_by_hash_size, 0, sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS); memset(words_by_hash_capacity, 0, sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS); if (transforms->num_transforms > 0) { for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) { uint16_t n = dict->words->size_bits_by_length[l] ? (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u; for (idx = 0; idx < n; ++idx) { uint32_t key; /* First transform (usually identity) */ TransformedDictionaryWord(idx, l, 0, transforms, dict, word, &word_size); /* Cannot hash words smaller than 4 bytes */ if (word_size < 4) { /* Break instead of continue, all next words of this length will have same length after transform */ break; } if (!BrotliTrieAdd(m, 0, idx, word, word_size, &dedup)) { return BROTLI_FALSE; } key = Hash(word, NUM_HASH_BITS); BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key], words_by_hash_capacity[key], words_by_hash_size[key], MakeDictWord(l, 0, idx)); ++total; } } } /* These LUT transforms only supported if no custom transforms. This is ok, we will use the heavy trie instead. */ if (transforms == BrotliGetTransforms()) { for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) { uint16_t n = dict->words->size_bits_by_length[l] ? (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u; for (idx = 0; idx < n; ++idx) { int k; BROTLI_BOOL is_ascii = BROTLI_TRUE; size_t offset = dict->words->offsets_by_length[l] + (size_t)l * idx; const uint8_t* data = &dict->words->data[offset]; for (k = 0; k < l; ++k) { if (data[k] >= 128) is_ascii = BROTLI_FALSE; } if (data[0] < 128) { int transform = 9; /* {empty, uppercase first, empty} */ uint32_t ix = idx + (uint32_t)transform * n; const BrotliTrieNode* it; TransformedDictionaryWord(idx, l, transform, transforms, dict, word, &word_size); it = BrotliTrieFind(&dedup, word, word_size); if (!it || it->idx_ > ix) { uint32_t key = Hash(word, NUM_HASH_BITS); if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) { return BROTLI_FALSE; } BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key], words_by_hash_capacity[key], words_by_hash_size[key], MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_FIRST, idx)); ++total; } } if (is_ascii) { int transform = 44; /* {empty, uppercase all, empty} */ uint32_t ix = idx + (uint32_t)transform * n; const BrotliTrieNode* it; TransformedDictionaryWord(idx, l, transform, transforms, dict, word, &word_size); it = BrotliTrieFind(&dedup, word, word_size); if (!it || it->idx_ > ix) { uint32_t key = Hash(word, NUM_HASH_BITS); if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) { return BROTLI_FALSE; } BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key], words_by_hash_capacity[key], words_by_hash_size[key], MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_ALL, idx)); ++total; } } } } } dict_words = (DictWord*)BrotliAllocate(m, sizeof(*dict->dict_words) * (total + 1)); buckets = (uint16_t*)BrotliAllocate(m, sizeof(*dict->buckets) * NUM_HASH_BUCKETS); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; dict->dict_words_alloc_size_ = total + 1; dict->dict_words = dict->dict_words_data_ = dict_words; dict->buckets_alloc_size_ = NUM_HASH_BUCKETS; dict->buckets = dict->buckets_data_ = buckets; /* Unused; makes offsets start from 1. */ dict_words[0] = MakeDictWord(0, 0, 0); total = 1; for (i = 0; i < NUM_HASH_BUCKETS; ++i) { size_t num_words = words_by_hash_size[i]; if (num_words > 0) { buckets[i] = (uint16_t)(total); memcpy(&dict_words[total], &words_by_hash[i][0], sizeof(dict_words[0]) * num_words); total += num_words; dict_words[total - 1].len |= 0x80; } else { buckets[i] = 0; } } for (i = 0; i < NUM_HASH_BUCKETS; ++i) { BrotliFree(m, words_by_hash[i]); } BrotliFree(m, words_by_hash); BrotliFree(m, words_by_hash_size); BrotliFree(m, words_by_hash_capacity); BrotliTrieFree(m, &dedup); return BROTLI_TRUE; } static void BuildDictionaryHashTable(uint16_t* hash_table_words, uint8_t* hash_table_lengths, const BrotliDictionary* dict) { int j, len; /* The order of the loops is such that in case of collision, words with shorter length are preferred, and in case of same length, words with smaller index. There is only a single word per bucket. */ /* TODO(lode): consider adding optional user-supplied frequency_map to use for preferred words instead, this can make the encoder better for quality 9 and below without affecting the decoder */ memset(hash_table_words, 0, sizeof(kStaticDictionaryHashWords)); memset(hash_table_lengths, 0, sizeof(kStaticDictionaryHashLengths)); for (len = SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; len >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; --len) { const size_t num_words = dict->size_bits_by_length[len] ? (1u << dict->size_bits_by_length[len]) : 0; for (j = (int)num_words - 1; j >= 0; --j) { size_t offset = dict->offsets_by_length[len] + (size_t)len * (size_t)j; const uint8_t* word = &dict->data[offset]; const uint32_t key = Hash(word, 14); int idx = (int)(key << 1) + (len < 8 ? 1 : 0); BROTLI_DCHECK(idx < (int)NUM_HASH_BUCKETS); hash_table_words[idx] = (uint16_t)j; hash_table_lengths[idx] = (uint8_t)len; } } } static BROTLI_BOOL GenerateWordsHeavy(MemoryManager* m, const BrotliTransforms* transforms, BrotliEncoderDictionary* dict) { int i, j, l; for (j = (int)transforms->num_transforms - 1; j >= 0 ; --j) { for (l = 0; l < 32; l++) { int num = (int)((1u << dict->words->size_bits_by_length[l]) & ~1u); for (i = 0; i < num; i++) { uint8_t transformed[kTransformedBufferSize]; size_t size; TransformedDictionaryWord( (uint32_t)i, l, j, transforms, dict, transformed, &size); if (size < 4) continue; if (!BrotliTrieAdd(m, (uint8_t)l, (uint32_t)(i + num * j), transformed, size, &dict->trie)) { return BROTLI_FALSE; } } } } return BROTLI_TRUE; } /* Computes cutoffTransformsCount (in count) and cutoffTransforms (in data) for the custom transforms, where possible within the limits of the cutoffTransforms encoding. The fast encoder uses this to do fast lookup for transforms that remove the N last characters (OmitLast). */ static void ComputeCutoffTransforms( const BrotliTransforms* transforms, uint32_t* count, uint64_t* data) { int i; /* The encoding in a 64-bit integer of transform N in the data is: (N << 2) + ((cutoffTransforms >> (N * 6)) & 0x3F), so for example the identity transform code must be 0-63, for N=1 the transform code must be 4-67, ..., for N=9 it must be 36-99. TODO(lode): consider a simple flexible uint8_t[10] instead of the uint64_t for the cutoff transforms, so that shared dictionaries can have the OmitLast transforms anywhere without loss. */ *count = 0; *data = 0; for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) { int idx = transforms->cutOffTransforms[i]; if (idx == -1) break; /* Not found */ if (idx < (i << 2)) break; /* Too small for the encoding */ if (idx >= (i << 2) + 64) break; /* Too large for the encoding */ (*count)++; *data |= (uint64_t)(((uint64_t)idx - ((uint64_t)i << 2u)) << ((uint64_t)i * 6u)); } } static BROTLI_BOOL ComputeDictionary(MemoryManager* m, int quality, const BrotliTransforms* transforms, BrotliEncoderDictionary* current) { int default_words = current->words == BrotliGetDictionary(); int default_transforms = transforms == BrotliGetTransforms(); if (default_words && default_transforms) { /* hashes are already set to Brotli defaults */ return BROTLI_TRUE; } current->hash_table_data_words_ = (uint16_t*)BrotliAllocate( m, sizeof(kStaticDictionaryHashWords)); current->hash_table_data_lengths_ = (uint8_t*)BrotliAllocate( m, sizeof(kStaticDictionaryHashLengths)); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; current->hash_table_words = current->hash_table_data_words_; current->hash_table_lengths = current->hash_table_data_lengths_; BuildDictionaryHashTable(current->hash_table_data_words_, current->hash_table_data_lengths_, current->words); ComputeCutoffTransforms(transforms, ¤t->cutoffTransformsCount, ¤t->cutoffTransforms); /* Only compute the data for slow encoder if the requested quality is high enough to need it */ if (quality >= ZOPFLIFICATION_QUALITY) { if (!BuildDictionaryLut(m, transforms, current)) return BROTLI_FALSE; /* For the built-in Brotli transforms, there is a hard-coded function to handle all transforms, but for custom transforms, we use the following large hammer instead */ current->has_words_heavy = !default_transforms; if (current->has_words_heavy) { if (!GenerateWordsHeavy(m, transforms, current)) return BROTLI_FALSE; } } return BROTLI_TRUE; } #endif /* BROTLI_EXPERIMENTAL */ void BrotliInitSharedEncoderDictionary(SharedEncoderDictionary* dict) { dict->magic = kSharedDictionaryMagic; dict->compound.num_chunks = 0; dict->compound.total_size = 0; dict->compound.chunk_offsets[0] = 0; dict->compound.num_prepared_instances_ = 0; dict->contextual.context_based = 0; dict->contextual.num_dictionaries = 1; dict->contextual.instances_ = 0; dict->contextual.num_instances_ = 1; /* The instance_ field */ dict->contextual.dict[0] = &dict->contextual.instance_; InitEncoderDictionary(&dict->contextual.instance_); dict->contextual.instance_.parent = &dict->contextual; dict->max_quality = BROTLI_MAX_QUALITY; } #if defined(BROTLI_EXPERIMENTAL) /* TODO(eustas): make sure that tooling will warn user if not all the cutoff transforms are available (for low-quality encoder). */ static BROTLI_BOOL InitCustomSharedEncoderDictionary( MemoryManager* m, const BrotliSharedDictionary* decoded_dict, int quality, SharedEncoderDictionary* dict) { ContextualEncoderDictionary* contextual; CompoundDictionary* compound; BrotliEncoderDictionary* instances; int i; BrotliInitSharedEncoderDictionary(dict); contextual = &dict->contextual; compound = &dict->compound; for (i = 0; i < (int)decoded_dict->num_prefix; i++) { PreparedDictionary* prepared = CreatePreparedDictionary(m, decoded_dict->prefix[i], decoded_dict->prefix_size[i]); AttachPreparedDictionary(compound, prepared); /* remember for cleanup */ compound->prepared_instances_[ compound->num_prepared_instances_++] = prepared; } dict->max_quality = quality; contextual->context_based = decoded_dict->context_based; if (decoded_dict->context_based) { memcpy(contextual->context_map, decoded_dict->context_map, SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS); } contextual->num_dictionaries = decoded_dict->num_dictionaries; contextual->num_instances_ = decoded_dict->num_dictionaries; if (contextual->num_instances_ == 1) { instances = &contextual->instance_; } else { contextual->instances_ = (BrotliEncoderDictionary*) BrotliAllocate(m, sizeof(*contextual->instances_) * contextual->num_instances_); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; instances = contextual->instances_; } for (i = 0; i < (int)contextual->num_instances_; i++) { BrotliEncoderDictionary* current = &instances[i]; InitEncoderDictionary(current); current->parent = &dict->contextual; if (decoded_dict->words[i] == BrotliGetDictionary()) { current->words = BrotliGetDictionary(); } else { current->words_instance_ = (BrotliDictionary*)BrotliAllocate( m, sizeof(BrotliDictionary)); if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; *current->words_instance_ = *decoded_dict->words[i]; current->words = current->words_instance_; } current->num_transforms = (uint32_t)decoded_dict->transforms[i]->num_transforms; if (!ComputeDictionary( m, quality, decoded_dict->transforms[i], current)) { return BROTLI_FALSE; } contextual->dict[i] = current; } return BROTLI_TRUE; /* success */ } BROTLI_BOOL BrotliInitCustomSharedEncoderDictionary( MemoryManager* m, const uint8_t* encoded_dict, size_t size, int quality, SharedEncoderDictionary* dict) { BROTLI_BOOL success = BROTLI_FALSE; BrotliSharedDictionary* decoded_dict = BrotliSharedDictionaryCreateInstance( m->alloc_func, m->free_func, m->opaque); if (!decoded_dict) { /* OOM */ return BROTLI_FALSE; } success = BrotliSharedDictionaryAttach( decoded_dict, BROTLI_SHARED_DICTIONARY_SERIALIZED, size, encoded_dict); if (success) { success = InitCustomSharedEncoderDictionary(m, decoded_dict, quality, dict); } BrotliSharedDictionaryDestroyInstance(decoded_dict); return success; } #endif /* BROTLI_EXPERIMENTAL */ void BrotliCleanupSharedEncoderDictionary(MemoryManager* m, SharedEncoderDictionary* dict) { size_t i; for (i = 0; i < dict->compound.num_prepared_instances_; i++) { DestroyPreparedDictionary(m, (PreparedDictionary*)dict->compound.prepared_instances_[i]); } if (dict->contextual.num_instances_ == 1) { BrotliDestroyEncoderDictionary(m, &dict->contextual.instance_); } else if (dict->contextual.num_instances_ > 1) { for (i = 0; i < dict->contextual.num_instances_; i++) { BrotliDestroyEncoderDictionary(m, &dict->contextual.instances_[i]); } BrotliFree(m, dict->contextual.instances_); } } ManagedDictionary* BrotliCreateManagedDictionary( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { ManagedDictionary* result = (ManagedDictionary*)BrotliBootstrapAlloc( sizeof(ManagedDictionary), alloc_func, free_func, opaque); if (result == NULL) return NULL; result->magic = kManagedDictionaryMagic; BrotliInitMemoryManager( &result->memory_manager_, alloc_func, free_func, opaque); result->dictionary = NULL; return result; } void BrotliDestroyManagedDictionary(ManagedDictionary* dictionary) { if (!dictionary) return; BrotliBootstrapFree(dictionary, &dictionary->memory_manager_); } /* Escalate internal functions visibility; for testing purposes only. */ #if defined(BROTLI_TEST) void InitEncoderDictionaryForTest(BrotliEncoderDictionary*); void InitEncoderDictionaryForTest(BrotliEncoderDictionary* d) { InitEncoderDictionary(d); } #endif #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/encoder_dict.h000066400000000000000000000116661501401750600206350ustar00rootroot00000000000000/* Copyright 2017 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #ifndef BROTLI_ENC_ENCODER_DICT_H_ #define BROTLI_ENC_ENCODER_DICT_H_ #include #include #include "../common/dictionary.h" #include "../common/platform.h" #include "compound_dictionary.h" #include "memory.h" #include "static_dict_lut.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* Dictionary hierarchy for Encoder: -SharedEncoderDictionary --CompoundDictionary ---PreparedDictionary [up to 15x] = prefix dictionary with precomputed hashes --ContextualEncoderDictionary ---BrotliEncoderDictionary [up to 64x] = for each context, precomputed static dictionary with words + transforms Dictionary hiearchy from common: similar, but without precomputed hashes -BrotliSharedDictionary --BrotliDictionary [up to 64x] --BrotliTransforms [up to 64x] --const uint8_t* prefix [up to 15x]: compound dictionaries */ typedef struct BrotliTrieNode { uint8_t single; /* if 1, sub is a single node for c instead of 256 */ uint8_t c; uint8_t len_; /* untransformed length */ uint32_t idx_; /* word index + num words * transform index */ uint32_t sub; /* index of sub node(s) in the pool */ } BrotliTrieNode; typedef struct BrotliTrie { BrotliTrieNode* pool; size_t pool_capacity; size_t pool_size; BrotliTrieNode root; } BrotliTrie; #if defined(BROTLI_EXPERIMENTAL) BROTLI_INTERNAL const BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie, const BrotliTrieNode* node, uint8_t c); #endif /* BROTLI_EXPERIMENTAL */ /* Dictionary data (words and transforms) for 1 possible context */ typedef struct BrotliEncoderDictionary { const BrotliDictionary* words; uint32_t num_transforms; /* cut off for fast encoder */ uint32_t cutoffTransformsCount; uint64_t cutoffTransforms; /* from dictionary_hash.h, for fast encoder */ const uint16_t* hash_table_words; const uint8_t* hash_table_lengths; /* from static_dict_lut.h, for slow encoder */ const uint16_t* buckets; const DictWord* dict_words; /* Heavy version, for use by slow encoder when there are custom transforms. Contains every possible transformed dictionary word in a trie. It encodes about as fast as the non-heavy encoder but consumes a lot of memory and takes time to build. */ BrotliTrie trie; BROTLI_BOOL has_words_heavy; /* Reference to other dictionaries. */ const struct ContextualEncoderDictionary* parent; /* Allocated memory, used only when not using the Brotli defaults */ uint16_t* hash_table_data_words_; uint8_t* hash_table_data_lengths_; size_t buckets_alloc_size_; uint16_t* buckets_data_; size_t dict_words_alloc_size_; DictWord* dict_words_data_; BrotliDictionary* words_instance_; } BrotliEncoderDictionary; /* Dictionary data for all 64 contexts */ typedef struct ContextualEncoderDictionary { BROTLI_BOOL context_based; uint8_t num_dictionaries; uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; const BrotliEncoderDictionary* dict[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; /* If num_instances_ is 1, instance_ is used, else dynamic allocation with instances_ is used. */ size_t num_instances_; BrotliEncoderDictionary instance_; BrotliEncoderDictionary* instances_; } ContextualEncoderDictionary; typedef struct SharedEncoderDictionary { /* Magic value to distinguish this struct from PreparedDictionary for certain external usages. */ uint32_t magic; /* LZ77 prefix, compound dictionary */ CompoundDictionary compound; /* Custom static dictionary (optionally context-based) */ ContextualEncoderDictionary contextual; /* The maximum quality the dictionary was computed for */ int max_quality; } SharedEncoderDictionary; typedef struct ManagedDictionary { uint32_t magic; MemoryManager memory_manager_; uint32_t* dictionary; } ManagedDictionary; /* Initializes to the brotli built-in dictionary */ BROTLI_INTERNAL void BrotliInitSharedEncoderDictionary( SharedEncoderDictionary* dict); #if defined(BROTLI_EXPERIMENTAL) /* Initializes to shared dictionary that will be parsed from encoded_dict. Requires that you keep the encoded_dict buffer around, parts of data will point to it. */ BROTLI_INTERNAL BROTLI_BOOL BrotliInitCustomSharedEncoderDictionary( MemoryManager* m, const uint8_t* encoded_dict, size_t size, int quality, SharedEncoderDictionary* dict); #endif /* BROTLI_EXPERIMENTAL */ BROTLI_INTERNAL void BrotliCleanupSharedEncoderDictionary( MemoryManager* m, SharedEncoderDictionary* dict); BROTLI_INTERNAL ManagedDictionary* BrotliCreateManagedDictionary( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); BROTLI_INTERNAL void BrotliDestroyManagedDictionary( ManagedDictionary* dictionary); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_ENCODER_DICT_H_ */ dvisvgm-3.5/libs/brotli/enc/entropy_encode.c000066400000000000000000000343701501401750600212200ustar00rootroot00000000000000/* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Entropy encoding (Huffman) utilities. */ #include "entropy_encode.h" #include /* memset */ #include #include "../common/constants.h" #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif const size_t kBrotliShellGaps[] = {132, 57, 23, 10, 4, 1}; BROTLI_BOOL BrotliSetDepth( int p0, HuffmanTree* pool, uint8_t* depth, int max_depth) { int stack[16]; int level = 0; int p = p0; BROTLI_DCHECK(max_depth <= 15); stack[0] = -1; while (BROTLI_TRUE) { if (pool[p].index_left_ >= 0) { level++; if (level > max_depth) return BROTLI_FALSE; stack[level] = pool[p].index_right_or_value_; p = pool[p].index_left_; continue; } else { depth[pool[p].index_right_or_value_] = (uint8_t)level; } while (level >= 0 && stack[level] == -1) level--; if (level < 0) return BROTLI_TRUE; p = stack[level]; stack[level] = -1; } } /* Sort the root nodes, least popular first. */ static BROTLI_INLINE BROTLI_BOOL SortHuffmanTree( const HuffmanTree* v0, const HuffmanTree* v1) { if (v0->total_count_ != v1->total_count_) { return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_); } return TO_BROTLI_BOOL(v0->index_right_or_value_ > v1->index_right_or_value_); } /* This function will create a Huffman tree. The catch here is that the tree cannot be arbitrarily deep. Brotli specifies a maximum depth of 15 bits for "code trees" and 7 bits for "code length code trees." count_limit is the value that is to be faked as the minimum value and this minimum value is raised until the tree matches the maximum length requirement. This algorithm is not of excellent performance for very long data blocks, especially when population counts are longer than 2**tree_limit, but we are not planning to use this with extremely long blocks. See http://en.wikipedia.org/wiki/Huffman_coding */ void BrotliCreateHuffmanTree(const uint32_t* data, const size_t length, const int tree_limit, HuffmanTree* tree, uint8_t* depth) { uint32_t count_limit; HuffmanTree sentinel; InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1); /* For block sizes below 64 kB, we never need to do a second iteration of this loop. Probably all of our block sizes will be smaller than that, so this loop is mostly of academic interest. If we actually would need this, we would be better off with the Katajainen algorithm. */ for (count_limit = 1; ; count_limit *= 2) { size_t n = 0; size_t i; size_t j; size_t k; for (i = length; i != 0;) { --i; if (data[i]) { const uint32_t count = BROTLI_MAX(uint32_t, data[i], count_limit); InitHuffmanTree(&tree[n++], count, -1, (int16_t)i); } } if (n == 1) { depth[tree[0].index_right_or_value_] = 1; /* Only one element. */ break; } SortHuffmanTreeItems(tree, n, SortHuffmanTree); /* The nodes are: [0, n): the sorted leaf nodes that we start with. [n]: we add a sentinel here. [n + 1, 2n): new parent nodes are added here, starting from (n+1). These are naturally in ascending order. [2n]: we add a sentinel at the end as well. There will be (2n+1) elements at the end. */ tree[n] = sentinel; tree[n + 1] = sentinel; i = 0; /* Points to the next leaf node. */ j = n + 1; /* Points to the next non-leaf node. */ for (k = n - 1; k != 0; --k) { size_t left, right; if (tree[i].total_count_ <= tree[j].total_count_) { left = i; ++i; } else { left = j; ++j; } if (tree[i].total_count_ <= tree[j].total_count_) { right = i; ++i; } else { right = j; ++j; } { /* The sentinel node becomes the parent node. */ size_t j_end = 2 * n - k; tree[j_end].total_count_ = tree[left].total_count_ + tree[right].total_count_; tree[j_end].index_left_ = (int16_t)left; tree[j_end].index_right_or_value_ = (int16_t)right; /* Add back the last sentinel node. */ tree[j_end + 1] = sentinel; } } if (BrotliSetDepth((int)(2 * n - 1), &tree[0], depth, tree_limit)) { /* We need to pack the Huffman tree in tree_limit bits. If this was not successful, add fake entities to the lowest values and retry. */ break; } } } static void Reverse(uint8_t* v, size_t start, size_t end) { --end; while (start < end) { uint8_t tmp = v[start]; v[start] = v[end]; v[end] = tmp; ++start; --end; } } static void BrotliWriteHuffmanTreeRepetitions( const uint8_t previous_value, const uint8_t value, size_t repetitions, size_t* tree_size, uint8_t* tree, uint8_t* extra_bits_data) { BROTLI_DCHECK(repetitions > 0); if (previous_value != value) { tree[*tree_size] = value; extra_bits_data[*tree_size] = 0; ++(*tree_size); --repetitions; } if (repetitions == 7) { tree[*tree_size] = value; extra_bits_data[*tree_size] = 0; ++(*tree_size); --repetitions; } if (repetitions < 3) { size_t i; for (i = 0; i < repetitions; ++i) { tree[*tree_size] = value; extra_bits_data[*tree_size] = 0; ++(*tree_size); } } else { size_t start = *tree_size; repetitions -= 3; while (BROTLI_TRUE) { tree[*tree_size] = BROTLI_REPEAT_PREVIOUS_CODE_LENGTH; extra_bits_data[*tree_size] = repetitions & 0x3; ++(*tree_size); repetitions >>= 2; if (repetitions == 0) { break; } --repetitions; } Reverse(tree, start, *tree_size); Reverse(extra_bits_data, start, *tree_size); } } static void BrotliWriteHuffmanTreeRepetitionsZeros( size_t repetitions, size_t* tree_size, uint8_t* tree, uint8_t* extra_bits_data) { if (repetitions == 11) { tree[*tree_size] = 0; extra_bits_data[*tree_size] = 0; ++(*tree_size); --repetitions; } if (repetitions < 3) { size_t i; for (i = 0; i < repetitions; ++i) { tree[*tree_size] = 0; extra_bits_data[*tree_size] = 0; ++(*tree_size); } } else { size_t start = *tree_size; repetitions -= 3; while (BROTLI_TRUE) { tree[*tree_size] = BROTLI_REPEAT_ZERO_CODE_LENGTH; extra_bits_data[*tree_size] = repetitions & 0x7; ++(*tree_size); repetitions >>= 3; if (repetitions == 0) { break; } --repetitions; } Reverse(tree, start, *tree_size); Reverse(extra_bits_data, start, *tree_size); } } void BrotliOptimizeHuffmanCountsForRle(size_t length, uint32_t* counts, uint8_t* good_for_rle) { size_t nonzero_count = 0; size_t stride; size_t limit; size_t sum; const size_t streak_limit = 1240; /* Let's make the Huffman code more compatible with RLE encoding. */ size_t i; for (i = 0; i < length; i++) { if (counts[i]) { ++nonzero_count; } } if (nonzero_count < 16) { return; } while (length != 0 && counts[length - 1] == 0) { --length; } if (length == 0) { return; /* All zeros. */ } /* Now counts[0..length - 1] does not have trailing zeros. */ { size_t nonzeros = 0; uint32_t smallest_nonzero = 1 << 30; for (i = 0; i < length; ++i) { if (counts[i] != 0) { ++nonzeros; if (smallest_nonzero > counts[i]) { smallest_nonzero = counts[i]; } } } if (nonzeros < 5) { /* Small histogram will model it well. */ return; } if (smallest_nonzero < 4) { size_t zeros = length - nonzeros; if (zeros < 6) { for (i = 1; i < length - 1; ++i) { if (counts[i - 1] != 0 && counts[i] == 0 && counts[i + 1] != 0) { counts[i] = 1; } } } } if (nonzeros < 28) { return; } } /* 2) Let's mark all population counts that already can be encoded with an RLE code. */ memset(good_for_rle, 0, length); { /* Let's not spoil any of the existing good RLE codes. Mark any seq of 0's that is longer as 5 as a good_for_rle. Mark any seq of non-0's that is longer as 7 as a good_for_rle. */ uint32_t symbol = counts[0]; size_t step = 0; for (i = 0; i <= length; ++i) { if (i == length || counts[i] != symbol) { if ((symbol == 0 && step >= 5) || (symbol != 0 && step >= 7)) { size_t k; for (k = 0; k < step; ++k) { good_for_rle[i - k - 1] = 1; } } step = 1; if (i != length) { symbol = counts[i]; } } else { ++step; } } } /* 3) Let's replace those population counts that lead to more RLE codes. Math here is in 24.8 fixed point representation. */ stride = 0; limit = 256 * (counts[0] + counts[1] + counts[2]) / 3 + 420; sum = 0; for (i = 0; i <= length; ++i) { if (i == length || good_for_rle[i] || (i != 0 && good_for_rle[i - 1]) || (256 * counts[i] - limit + streak_limit) >= 2 * streak_limit) { if (stride >= 4 || (stride >= 3 && sum == 0)) { size_t k; /* The stride must end, collapse what we have, if we have enough (4). */ size_t count = (sum + stride / 2) / stride; if (count == 0) { count = 1; } if (sum == 0) { /* Don't make an all zeros stride to be upgraded to ones. */ count = 0; } for (k = 0; k < stride; ++k) { /* We don't want to change value at counts[i], that is already belonging to the next stride. Thus - 1. */ counts[i - k - 1] = (uint32_t)count; } } stride = 0; sum = 0; if (i < length - 2) { /* All interesting strides have a count of at least 4, */ /* at least when non-zeros. */ limit = 256 * (counts[i] + counts[i + 1] + counts[i + 2]) / 3 + 420; } else if (i < length) { limit = 256 * counts[i]; } else { limit = 0; } } ++stride; if (i != length) { sum += counts[i]; if (stride >= 4) { limit = (256 * sum + stride / 2) / stride; } if (stride == 4) { limit += 120; } } } } static void DecideOverRleUse(const uint8_t* depth, const size_t length, BROTLI_BOOL* use_rle_for_non_zero, BROTLI_BOOL* use_rle_for_zero) { size_t total_reps_zero = 0; size_t total_reps_non_zero = 0; size_t count_reps_zero = 1; size_t count_reps_non_zero = 1; size_t i; for (i = 0; i < length;) { const uint8_t value = depth[i]; size_t reps = 1; size_t k; for (k = i + 1; k < length && depth[k] == value; ++k) { ++reps; } if (reps >= 3 && value == 0) { total_reps_zero += reps; ++count_reps_zero; } if (reps >= 4 && value != 0) { total_reps_non_zero += reps; ++count_reps_non_zero; } i += reps; } *use_rle_for_non_zero = TO_BROTLI_BOOL(total_reps_non_zero > count_reps_non_zero * 2); *use_rle_for_zero = TO_BROTLI_BOOL(total_reps_zero > count_reps_zero * 2); } void BrotliWriteHuffmanTree(const uint8_t* depth, size_t length, size_t* tree_size, uint8_t* tree, uint8_t* extra_bits_data) { uint8_t previous_value = BROTLI_INITIAL_REPEATED_CODE_LENGTH; size_t i; BROTLI_BOOL use_rle_for_non_zero = BROTLI_FALSE; BROTLI_BOOL use_rle_for_zero = BROTLI_FALSE; /* Throw away trailing zeros. */ size_t new_length = length; for (i = 0; i < length; ++i) { if (depth[length - i - 1] == 0) { --new_length; } else { break; } } /* First gather statistics on if it is a good idea to do RLE. */ if (length > 50) { /* Find RLE coding for longer codes. Shorter codes seem not to benefit from RLE. */ DecideOverRleUse(depth, new_length, &use_rle_for_non_zero, &use_rle_for_zero); } /* Actual RLE coding. */ for (i = 0; i < new_length;) { const uint8_t value = depth[i]; size_t reps = 1; if ((value != 0 && use_rle_for_non_zero) || (value == 0 && use_rle_for_zero)) { size_t k; for (k = i + 1; k < new_length && depth[k] == value; ++k) { ++reps; } } if (value == 0) { BrotliWriteHuffmanTreeRepetitionsZeros( reps, tree_size, tree, extra_bits_data); } else { BrotliWriteHuffmanTreeRepetitions(previous_value, value, reps, tree_size, tree, extra_bits_data); previous_value = value; } i += reps; } } static uint16_t BrotliReverseBits(size_t num_bits, uint16_t bits) { static const size_t kLut[16] = { /* Pre-reversed 4-bit values. */ 0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F }; size_t retval = kLut[bits & 0x0F]; size_t i; for (i = 4; i < num_bits; i += 4) { retval <<= 4; bits = (uint16_t)(bits >> 4); retval |= kLut[bits & 0x0F]; } retval >>= ((0 - num_bits) & 0x03); return (uint16_t)retval; } /* 0..15 are values for bits */ #define MAX_HUFFMAN_BITS 16 void BrotliConvertBitDepthsToSymbols(const uint8_t* depth, size_t len, uint16_t* bits) { /* In Brotli, all bit depths are [1..15] 0 bit depth means that the symbol does not exist. */ uint16_t bl_count[MAX_HUFFMAN_BITS] = { 0 }; uint16_t next_code[MAX_HUFFMAN_BITS]; size_t i; int code = 0; for (i = 0; i < len; ++i) { ++bl_count[depth[i]]; } bl_count[0] = 0; next_code[0] = 0; for (i = 1; i < MAX_HUFFMAN_BITS; ++i) { code = (code + bl_count[i - 1]) << 1; next_code[i] = (uint16_t)code; } for (i = 0; i < len; ++i) { if (depth[i]) { bits[i] = BrotliReverseBits(depth[i], next_code[depth[i]]++); } } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/entropy_encode.h000066400000000000000000000077311501401750600212260ustar00rootroot00000000000000/* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Entropy encoding (Huffman) utilities. */ #ifndef BROTLI_ENC_ENTROPY_ENCODE_H_ #define BROTLI_ENC_ENTROPY_ENCODE_H_ #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* A node of a Huffman tree. */ typedef struct HuffmanTree { uint32_t total_count_; int16_t index_left_; int16_t index_right_or_value_; } HuffmanTree; static BROTLI_INLINE void InitHuffmanTree(HuffmanTree* self, uint32_t count, int16_t left, int16_t right) { self->total_count_ = count; self->index_left_ = left; self->index_right_or_value_ = right; } /* Returns 1 is assignment of depths succeeded, otherwise 0. */ BROTLI_INTERNAL BROTLI_BOOL BrotliSetDepth( int p, HuffmanTree* pool, uint8_t* depth, int max_depth); /* This function will create a Huffman tree. The (data,length) contains the population counts. The tree_limit is the maximum bit depth of the Huffman codes. The depth contains the tree, i.e., how many bits are used for the symbol. The actual Huffman tree is constructed in the tree[] array, which has to be at least 2 * length + 1 long. See http://en.wikipedia.org/wiki/Huffman_coding */ BROTLI_INTERNAL void BrotliCreateHuffmanTree(const uint32_t* data, const size_t length, const int tree_limit, HuffmanTree* tree, uint8_t* depth); /* Change the population counts in a way that the consequent Huffman tree compression, especially its RLE-part will be more likely to compress this data more efficiently. length contains the size of the histogram. counts contains the population counts. good_for_rle is a buffer of at least length size */ BROTLI_INTERNAL void BrotliOptimizeHuffmanCountsForRle( size_t length, uint32_t* counts, uint8_t* good_for_rle); /* Write a Huffman tree from bit depths into the bit-stream representation of a Huffman tree. The generated Huffman tree is to be compressed once more using a Huffman tree */ BROTLI_INTERNAL void BrotliWriteHuffmanTree(const uint8_t* depth, size_t num, size_t* tree_size, uint8_t* tree, uint8_t* extra_bits_data); /* Get the actual bit values for a tree of bit depths. */ BROTLI_INTERNAL void BrotliConvertBitDepthsToSymbols(const uint8_t* depth, size_t len, uint16_t* bits); BROTLI_INTERNAL extern const size_t kBrotliShellGaps[6]; /* Input size optimized Shell sort. */ typedef BROTLI_BOOL (*HuffmanTreeComparator)( const HuffmanTree*, const HuffmanTree*); static BROTLI_INLINE void SortHuffmanTreeItems(HuffmanTree* items, const size_t n, HuffmanTreeComparator comparator) { if (n < 13) { /* Insertion sort. */ size_t i; for (i = 1; i < n; ++i) { HuffmanTree tmp = items[i]; size_t k = i; size_t j = i - 1; while (comparator(&tmp, &items[j])) { items[k] = items[j]; k = j; if (!j--) break; } items[k] = tmp; } return; } else { /* Shell sort. */ int g = n < 57 ? 2 : 0; for (; g < 6; ++g) { size_t gap = kBrotliShellGaps[g]; size_t i; for (i = gap; i < n; ++i) { size_t j = i; HuffmanTree tmp = items[i]; for (; j >= gap && comparator(&tmp, &items[j - gap]); j -= gap) { items[j] = items[j - gap]; } items[j] = tmp; } } } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_ENTROPY_ENCODE_H_ */ dvisvgm-3.5/libs/brotli/enc/entropy_encode_static.h000066400000000000000000001002671501401750600225730ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Static entropy codes used for faster meta-block encoding. */ #ifndef BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ #define BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ #include #include "../common/constants.h" #include "../common/platform.h" #include "write_bits.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static const uint8_t kCodeLengthDepth[18] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 0, 4, 4, }; static const uint8_t kStaticCommandCodeDepth[BROTLI_NUM_COMMAND_SYMBOLS] = { 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, }; static const uint8_t kStaticDistanceCodeDepth[64] = { 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, }; /* GENERATED CODE START */ static const uint32_t kCodeLengthBits[18] = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 15, 31, 0, 11, 7, }; static BROTLI_INLINE void StoreStaticCodeLengthCode( size_t* storage_ix, uint8_t* storage) { BrotliWriteBits( 40, BROTLI_MAKE_UINT64_T(0x0000FFu, 0x55555554u), storage_ix, storage); } static const uint64_t kZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = { 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x00000017, 0x00000027, 0x00000037, 0x00000047, 0x00000057, 0x00000067, 0x00000077, 0x00000770, 0x00000b87, 0x00001387, 0x00001b87, 0x00002387, 0x00002b87, 0x00003387, 0x00003b87, 0x00000397, 0x00000b97, 0x00001397, 0x00001b97, 0x00002397, 0x00002b97, 0x00003397, 0x00003b97, 0x000003a7, 0x00000ba7, 0x000013a7, 0x00001ba7, 0x000023a7, 0x00002ba7, 0x000033a7, 0x00003ba7, 0x000003b7, 0x00000bb7, 0x000013b7, 0x00001bb7, 0x000023b7, 0x00002bb7, 0x000033b7, 0x00003bb7, 0x000003c7, 0x00000bc7, 0x000013c7, 0x00001bc7, 0x000023c7, 0x00002bc7, 0x000033c7, 0x00003bc7, 0x000003d7, 0x00000bd7, 0x000013d7, 0x00001bd7, 0x000023d7, 0x00002bd7, 0x000033d7, 0x00003bd7, 0x000003e7, 0x00000be7, 0x000013e7, 0x00001be7, 0x000023e7, 0x00002be7, 0x000033e7, 0x00003be7, 0x000003f7, 0x00000bf7, 0x000013f7, 0x00001bf7, 0x000023f7, 0x00002bf7, 0x000033f7, 0x00003bf7, 0x0001c387, 0x0005c387, 0x0009c387, 0x000dc387, 0x0011c387, 0x0015c387, 0x0019c387, 0x001dc387, 0x0001cb87, 0x0005cb87, 0x0009cb87, 0x000dcb87, 0x0011cb87, 0x0015cb87, 0x0019cb87, 0x001dcb87, 0x0001d387, 0x0005d387, 0x0009d387, 0x000dd387, 0x0011d387, 0x0015d387, 0x0019d387, 0x001dd387, 0x0001db87, 0x0005db87, 0x0009db87, 0x000ddb87, 0x0011db87, 0x0015db87, 0x0019db87, 0x001ddb87, 0x0001e387, 0x0005e387, 0x0009e387, 0x000de387, 0x0011e387, 0x0015e387, 0x0019e387, 0x001de387, 0x0001eb87, 0x0005eb87, 0x0009eb87, 0x000deb87, 0x0011eb87, 0x0015eb87, 0x0019eb87, 0x001deb87, 0x0001f387, 0x0005f387, 0x0009f387, 0x000df387, 0x0011f387, 0x0015f387, 0x0019f387, 0x001df387, 0x0001fb87, 0x0005fb87, 0x0009fb87, 0x000dfb87, 0x0011fb87, 0x0015fb87, 0x0019fb87, 0x001dfb87, 0x0001c397, 0x0005c397, 0x0009c397, 0x000dc397, 0x0011c397, 0x0015c397, 0x0019c397, 0x001dc397, 0x0001cb97, 0x0005cb97, 0x0009cb97, 0x000dcb97, 0x0011cb97, 0x0015cb97, 0x0019cb97, 0x001dcb97, 0x0001d397, 0x0005d397, 0x0009d397, 0x000dd397, 0x0011d397, 0x0015d397, 0x0019d397, 0x001dd397, 0x0001db97, 0x0005db97, 0x0009db97, 0x000ddb97, 0x0011db97, 0x0015db97, 0x0019db97, 0x001ddb97, 0x0001e397, 0x0005e397, 0x0009e397, 0x000de397, 0x0011e397, 0x0015e397, 0x0019e397, 0x001de397, 0x0001eb97, 0x0005eb97, 0x0009eb97, 0x000deb97, 0x0011eb97, 0x0015eb97, 0x0019eb97, 0x001deb97, 0x0001f397, 0x0005f397, 0x0009f397, 0x000df397, 0x0011f397, 0x0015f397, 0x0019f397, 0x001df397, 0x0001fb97, 0x0005fb97, 0x0009fb97, 0x000dfb97, 0x0011fb97, 0x0015fb97, 0x0019fb97, 0x001dfb97, 0x0001c3a7, 0x0005c3a7, 0x0009c3a7, 0x000dc3a7, 0x0011c3a7, 0x0015c3a7, 0x0019c3a7, 0x001dc3a7, 0x0001cba7, 0x0005cba7, 0x0009cba7, 0x000dcba7, 0x0011cba7, 0x0015cba7, 0x0019cba7, 0x001dcba7, 0x0001d3a7, 0x0005d3a7, 0x0009d3a7, 0x000dd3a7, 0x0011d3a7, 0x0015d3a7, 0x0019d3a7, 0x001dd3a7, 0x0001dba7, 0x0005dba7, 0x0009dba7, 0x000ddba7, 0x0011dba7, 0x0015dba7, 0x0019dba7, 0x001ddba7, 0x0001e3a7, 0x0005e3a7, 0x0009e3a7, 0x000de3a7, 0x0011e3a7, 0x0015e3a7, 0x0019e3a7, 0x001de3a7, 0x0001eba7, 0x0005eba7, 0x0009eba7, 0x000deba7, 0x0011eba7, 0x0015eba7, 0x0019eba7, 0x001deba7, 0x0001f3a7, 0x0005f3a7, 0x0009f3a7, 0x000df3a7, 0x0011f3a7, 0x0015f3a7, 0x0019f3a7, 0x001df3a7, 0x0001fba7, 0x0005fba7, 0x0009fba7, 0x000dfba7, 0x0011fba7, 0x0015fba7, 0x0019fba7, 0x001dfba7, 0x0001c3b7, 0x0005c3b7, 0x0009c3b7, 0x000dc3b7, 0x0011c3b7, 0x0015c3b7, 0x0019c3b7, 0x001dc3b7, 0x0001cbb7, 0x0005cbb7, 0x0009cbb7, 0x000dcbb7, 0x0011cbb7, 0x0015cbb7, 0x0019cbb7, 0x001dcbb7, 0x0001d3b7, 0x0005d3b7, 0x0009d3b7, 0x000dd3b7, 0x0011d3b7, 0x0015d3b7, 0x0019d3b7, 0x001dd3b7, 0x0001dbb7, 0x0005dbb7, 0x0009dbb7, 0x000ddbb7, 0x0011dbb7, 0x0015dbb7, 0x0019dbb7, 0x001ddbb7, 0x0001e3b7, 0x0005e3b7, 0x0009e3b7, 0x000de3b7, 0x0011e3b7, 0x0015e3b7, 0x0019e3b7, 0x001de3b7, 0x0001ebb7, 0x0005ebb7, 0x0009ebb7, 0x000debb7, 0x0011ebb7, 0x0015ebb7, 0x0019ebb7, 0x001debb7, 0x0001f3b7, 0x0005f3b7, 0x0009f3b7, 0x000df3b7, 0x0011f3b7, 0x0015f3b7, 0x0019f3b7, 0x001df3b7, 0x0001fbb7, 0x0005fbb7, 0x0009fbb7, 0x000dfbb7, 0x0011fbb7, 0x0015fbb7, 0x0019fbb7, 0x001dfbb7, 0x0001c3c7, 0x0005c3c7, 0x0009c3c7, 0x000dc3c7, 0x0011c3c7, 0x0015c3c7, 0x0019c3c7, 0x001dc3c7, 0x0001cbc7, 0x0005cbc7, 0x0009cbc7, 0x000dcbc7, 0x0011cbc7, 0x0015cbc7, 0x0019cbc7, 0x001dcbc7, 0x0001d3c7, 0x0005d3c7, 0x0009d3c7, 0x000dd3c7, 0x0011d3c7, 0x0015d3c7, 0x0019d3c7, 0x001dd3c7, 0x0001dbc7, 0x0005dbc7, 0x0009dbc7, 0x000ddbc7, 0x0011dbc7, 0x0015dbc7, 0x0019dbc7, 0x001ddbc7, 0x0001e3c7, 0x0005e3c7, 0x0009e3c7, 0x000de3c7, 0x0011e3c7, 0x0015e3c7, 0x0019e3c7, 0x001de3c7, 0x0001ebc7, 0x0005ebc7, 0x0009ebc7, 0x000debc7, 0x0011ebc7, 0x0015ebc7, 0x0019ebc7, 0x001debc7, 0x0001f3c7, 0x0005f3c7, 0x0009f3c7, 0x000df3c7, 0x0011f3c7, 0x0015f3c7, 0x0019f3c7, 0x001df3c7, 0x0001fbc7, 0x0005fbc7, 0x0009fbc7, 0x000dfbc7, 0x0011fbc7, 0x0015fbc7, 0x0019fbc7, 0x001dfbc7, 0x0001c3d7, 0x0005c3d7, 0x0009c3d7, 0x000dc3d7, 0x0011c3d7, 0x0015c3d7, 0x0019c3d7, 0x001dc3d7, 0x0001cbd7, 0x0005cbd7, 0x0009cbd7, 0x000dcbd7, 0x0011cbd7, 0x0015cbd7, 0x0019cbd7, 0x001dcbd7, 0x0001d3d7, 0x0005d3d7, 0x0009d3d7, 0x000dd3d7, 0x0011d3d7, 0x0015d3d7, 0x0019d3d7, 0x001dd3d7, 0x0001dbd7, 0x0005dbd7, 0x0009dbd7, 0x000ddbd7, 0x0011dbd7, 0x0015dbd7, 0x0019dbd7, 0x001ddbd7, 0x0001e3d7, 0x0005e3d7, 0x0009e3d7, 0x000de3d7, 0x0011e3d7, 0x0015e3d7, 0x0019e3d7, 0x001de3d7, 0x0001ebd7, 0x0005ebd7, 0x0009ebd7, 0x000debd7, 0x0011ebd7, 0x0015ebd7, 0x0019ebd7, 0x001debd7, 0x0001f3d7, 0x0005f3d7, 0x0009f3d7, 0x000df3d7, 0x0011f3d7, 0x0015f3d7, 0x0019f3d7, 0x001df3d7, 0x0001fbd7, 0x0005fbd7, 0x0009fbd7, 0x000dfbd7, 0x0011fbd7, 0x0015fbd7, 0x0019fbd7, 0x001dfbd7, 0x0001c3e7, 0x0005c3e7, 0x0009c3e7, 0x000dc3e7, 0x0011c3e7, 0x0015c3e7, 0x0019c3e7, 0x001dc3e7, 0x0001cbe7, 0x0005cbe7, 0x0009cbe7, 0x000dcbe7, 0x0011cbe7, 0x0015cbe7, 0x0019cbe7, 0x001dcbe7, 0x0001d3e7, 0x0005d3e7, 0x0009d3e7, 0x000dd3e7, 0x0011d3e7, 0x0015d3e7, 0x0019d3e7, 0x001dd3e7, 0x0001dbe7, 0x0005dbe7, 0x0009dbe7, 0x000ddbe7, 0x0011dbe7, 0x0015dbe7, 0x0019dbe7, 0x001ddbe7, 0x0001e3e7, 0x0005e3e7, 0x0009e3e7, 0x000de3e7, 0x0011e3e7, 0x0015e3e7, 0x0019e3e7, 0x001de3e7, 0x0001ebe7, 0x0005ebe7, 0x0009ebe7, 0x000debe7, 0x0011ebe7, 0x0015ebe7, 0x0019ebe7, 0x001debe7, 0x0001f3e7, 0x0005f3e7, 0x0009f3e7, 0x000df3e7, 0x0011f3e7, 0x0015f3e7, 0x0019f3e7, 0x001df3e7, 0x0001fbe7, 0x0005fbe7, 0x0009fbe7, 0x000dfbe7, 0x0011fbe7, 0x0015fbe7, 0x0019fbe7, 0x001dfbe7, 0x0001c3f7, 0x0005c3f7, 0x0009c3f7, 0x000dc3f7, 0x0011c3f7, 0x0015c3f7, 0x0019c3f7, 0x001dc3f7, 0x0001cbf7, 0x0005cbf7, 0x0009cbf7, 0x000dcbf7, 0x0011cbf7, 0x0015cbf7, 0x0019cbf7, 0x001dcbf7, 0x0001d3f7, 0x0005d3f7, 0x0009d3f7, 0x000dd3f7, 0x0011d3f7, 0x0015d3f7, 0x0019d3f7, 0x001dd3f7, 0x0001dbf7, 0x0005dbf7, 0x0009dbf7, 0x000ddbf7, 0x0011dbf7, 0x0015dbf7, 0x0019dbf7, 0x001ddbf7, 0x0001e3f7, 0x0005e3f7, 0x0009e3f7, 0x000de3f7, 0x0011e3f7, 0x0015e3f7, 0x0019e3f7, 0x001de3f7, 0x0001ebf7, 0x0005ebf7, 0x0009ebf7, 0x000debf7, 0x0011ebf7, 0x0015ebf7, 0x0019ebf7, 0x001debf7, 0x0001f3f7, 0x0005f3f7, 0x0009f3f7, 0x000df3f7, 0x0011f3f7, 0x0015f3f7, 0x0019f3f7, 0x001df3f7, 0x0001fbf7, 0x0005fbf7, 0x0009fbf7, 0x000dfbf7, 0x0011fbf7, 0x0015fbf7, 0x0019fbf7, 0x001dfbf7, 0x00e1c387, 0x02e1c387, 0x04e1c387, 0x06e1c387, 0x08e1c387, 0x0ae1c387, 0x0ce1c387, 0x0ee1c387, 0x00e5c387, 0x02e5c387, 0x04e5c387, 0x06e5c387, 0x08e5c387, 0x0ae5c387, 0x0ce5c387, 0x0ee5c387, 0x00e9c387, 0x02e9c387, 0x04e9c387, 0x06e9c387, 0x08e9c387, 0x0ae9c387, 0x0ce9c387, 0x0ee9c387, 0x00edc387, 0x02edc387, 0x04edc387, 0x06edc387, 0x08edc387, 0x0aedc387, 0x0cedc387, 0x0eedc387, 0x00f1c387, 0x02f1c387, 0x04f1c387, 0x06f1c387, 0x08f1c387, 0x0af1c387, 0x0cf1c387, 0x0ef1c387, 0x00f5c387, 0x02f5c387, 0x04f5c387, 0x06f5c387, 0x08f5c387, 0x0af5c387, 0x0cf5c387, 0x0ef5c387, 0x00f9c387, 0x02f9c387, 0x04f9c387, 0x06f9c387, 0x08f9c387, 0x0af9c387, 0x0cf9c387, 0x0ef9c387, 0x00fdc387, 0x02fdc387, 0x04fdc387, 0x06fdc387, 0x08fdc387, 0x0afdc387, 0x0cfdc387, 0x0efdc387, 0x00e1cb87, 0x02e1cb87, 0x04e1cb87, 0x06e1cb87, 0x08e1cb87, 0x0ae1cb87, 0x0ce1cb87, 0x0ee1cb87, 0x00e5cb87, 0x02e5cb87, 0x04e5cb87, 0x06e5cb87, 0x08e5cb87, 0x0ae5cb87, 0x0ce5cb87, 0x0ee5cb87, 0x00e9cb87, 0x02e9cb87, 0x04e9cb87, 0x06e9cb87, 0x08e9cb87, 0x0ae9cb87, 0x0ce9cb87, 0x0ee9cb87, 0x00edcb87, 0x02edcb87, 0x04edcb87, 0x06edcb87, 0x08edcb87, 0x0aedcb87, 0x0cedcb87, 0x0eedcb87, 0x00f1cb87, 0x02f1cb87, 0x04f1cb87, 0x06f1cb87, 0x08f1cb87, 0x0af1cb87, 0x0cf1cb87, 0x0ef1cb87, 0x00f5cb87, 0x02f5cb87, 0x04f5cb87, 0x06f5cb87, 0x08f5cb87, 0x0af5cb87, 0x0cf5cb87, 0x0ef5cb87, 0x00f9cb87, 0x02f9cb87, 0x04f9cb87, 0x06f9cb87, 0x08f9cb87, }; static const uint32_t kZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = { 0, 4, 8, 7, 7, 7, 7, 7, 7, 7, 7, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, }; static const uint64_t kNonZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = { 0x0000000b, 0x0000001b, 0x0000002b, 0x0000003b, 0x000002cb, 0x000006cb, 0x00000acb, 0x00000ecb, 0x000002db, 0x000006db, 0x00000adb, 0x00000edb, 0x000002eb, 0x000006eb, 0x00000aeb, 0x00000eeb, 0x000002fb, 0x000006fb, 0x00000afb, 0x00000efb, 0x0000b2cb, 0x0001b2cb, 0x0002b2cb, 0x0003b2cb, 0x0000b6cb, 0x0001b6cb, 0x0002b6cb, 0x0003b6cb, 0x0000bacb, 0x0001bacb, 0x0002bacb, 0x0003bacb, 0x0000becb, 0x0001becb, 0x0002becb, 0x0003becb, 0x0000b2db, 0x0001b2db, 0x0002b2db, 0x0003b2db, 0x0000b6db, 0x0001b6db, 0x0002b6db, 0x0003b6db, 0x0000badb, 0x0001badb, 0x0002badb, 0x0003badb, 0x0000bedb, 0x0001bedb, 0x0002bedb, 0x0003bedb, 0x0000b2eb, 0x0001b2eb, 0x0002b2eb, 0x0003b2eb, 0x0000b6eb, 0x0001b6eb, 0x0002b6eb, 0x0003b6eb, 0x0000baeb, 0x0001baeb, 0x0002baeb, 0x0003baeb, 0x0000beeb, 0x0001beeb, 0x0002beeb, 0x0003beeb, 0x0000b2fb, 0x0001b2fb, 0x0002b2fb, 0x0003b2fb, 0x0000b6fb, 0x0001b6fb, 0x0002b6fb, 0x0003b6fb, 0x0000bafb, 0x0001bafb, 0x0002bafb, 0x0003bafb, 0x0000befb, 0x0001befb, 0x0002befb, 0x0003befb, 0x002cb2cb, 0x006cb2cb, 0x00acb2cb, 0x00ecb2cb, 0x002db2cb, 0x006db2cb, 0x00adb2cb, 0x00edb2cb, 0x002eb2cb, 0x006eb2cb, 0x00aeb2cb, 0x00eeb2cb, 0x002fb2cb, 0x006fb2cb, 0x00afb2cb, 0x00efb2cb, 0x002cb6cb, 0x006cb6cb, 0x00acb6cb, 0x00ecb6cb, 0x002db6cb, 0x006db6cb, 0x00adb6cb, 0x00edb6cb, 0x002eb6cb, 0x006eb6cb, 0x00aeb6cb, 0x00eeb6cb, 0x002fb6cb, 0x006fb6cb, 0x00afb6cb, 0x00efb6cb, 0x002cbacb, 0x006cbacb, 0x00acbacb, 0x00ecbacb, 0x002dbacb, 0x006dbacb, 0x00adbacb, 0x00edbacb, 0x002ebacb, 0x006ebacb, 0x00aebacb, 0x00eebacb, 0x002fbacb, 0x006fbacb, 0x00afbacb, 0x00efbacb, 0x002cbecb, 0x006cbecb, 0x00acbecb, 0x00ecbecb, 0x002dbecb, 0x006dbecb, 0x00adbecb, 0x00edbecb, 0x002ebecb, 0x006ebecb, 0x00aebecb, 0x00eebecb, 0x002fbecb, 0x006fbecb, 0x00afbecb, 0x00efbecb, 0x002cb2db, 0x006cb2db, 0x00acb2db, 0x00ecb2db, 0x002db2db, 0x006db2db, 0x00adb2db, 0x00edb2db, 0x002eb2db, 0x006eb2db, 0x00aeb2db, 0x00eeb2db, 0x002fb2db, 0x006fb2db, 0x00afb2db, 0x00efb2db, 0x002cb6db, 0x006cb6db, 0x00acb6db, 0x00ecb6db, 0x002db6db, 0x006db6db, 0x00adb6db, 0x00edb6db, 0x002eb6db, 0x006eb6db, 0x00aeb6db, 0x00eeb6db, 0x002fb6db, 0x006fb6db, 0x00afb6db, 0x00efb6db, 0x002cbadb, 0x006cbadb, 0x00acbadb, 0x00ecbadb, 0x002dbadb, 0x006dbadb, 0x00adbadb, 0x00edbadb, 0x002ebadb, 0x006ebadb, 0x00aebadb, 0x00eebadb, 0x002fbadb, 0x006fbadb, 0x00afbadb, 0x00efbadb, 0x002cbedb, 0x006cbedb, 0x00acbedb, 0x00ecbedb, 0x002dbedb, 0x006dbedb, 0x00adbedb, 0x00edbedb, 0x002ebedb, 0x006ebedb, 0x00aebedb, 0x00eebedb, 0x002fbedb, 0x006fbedb, 0x00afbedb, 0x00efbedb, 0x002cb2eb, 0x006cb2eb, 0x00acb2eb, 0x00ecb2eb, 0x002db2eb, 0x006db2eb, 0x00adb2eb, 0x00edb2eb, 0x002eb2eb, 0x006eb2eb, 0x00aeb2eb, 0x00eeb2eb, 0x002fb2eb, 0x006fb2eb, 0x00afb2eb, 0x00efb2eb, 0x002cb6eb, 0x006cb6eb, 0x00acb6eb, 0x00ecb6eb, 0x002db6eb, 0x006db6eb, 0x00adb6eb, 0x00edb6eb, 0x002eb6eb, 0x006eb6eb, 0x00aeb6eb, 0x00eeb6eb, 0x002fb6eb, 0x006fb6eb, 0x00afb6eb, 0x00efb6eb, 0x002cbaeb, 0x006cbaeb, 0x00acbaeb, 0x00ecbaeb, 0x002dbaeb, 0x006dbaeb, 0x00adbaeb, 0x00edbaeb, 0x002ebaeb, 0x006ebaeb, 0x00aebaeb, 0x00eebaeb, 0x002fbaeb, 0x006fbaeb, 0x00afbaeb, 0x00efbaeb, 0x002cbeeb, 0x006cbeeb, 0x00acbeeb, 0x00ecbeeb, 0x002dbeeb, 0x006dbeeb, 0x00adbeeb, 0x00edbeeb, 0x002ebeeb, 0x006ebeeb, 0x00aebeeb, 0x00eebeeb, 0x002fbeeb, 0x006fbeeb, 0x00afbeeb, 0x00efbeeb, 0x002cb2fb, 0x006cb2fb, 0x00acb2fb, 0x00ecb2fb, 0x002db2fb, 0x006db2fb, 0x00adb2fb, 0x00edb2fb, 0x002eb2fb, 0x006eb2fb, 0x00aeb2fb, 0x00eeb2fb, 0x002fb2fb, 0x006fb2fb, 0x00afb2fb, 0x00efb2fb, 0x002cb6fb, 0x006cb6fb, 0x00acb6fb, 0x00ecb6fb, 0x002db6fb, 0x006db6fb, 0x00adb6fb, 0x00edb6fb, 0x002eb6fb, 0x006eb6fb, 0x00aeb6fb, 0x00eeb6fb, 0x002fb6fb, 0x006fb6fb, 0x00afb6fb, 0x00efb6fb, 0x002cbafb, 0x006cbafb, 0x00acbafb, 0x00ecbafb, 0x002dbafb, 0x006dbafb, 0x00adbafb, 0x00edbafb, 0x002ebafb, 0x006ebafb, 0x00aebafb, 0x00eebafb, 0x002fbafb, 0x006fbafb, 0x00afbafb, 0x00efbafb, 0x002cbefb, 0x006cbefb, 0x00acbefb, 0x00ecbefb, 0x002dbefb, 0x006dbefb, 0x00adbefb, 0x00edbefb, 0x002ebefb, 0x006ebefb, 0x00aebefb, 0x00eebefb, 0x002fbefb, 0x006fbefb, 0x00afbefb, 0x00efbefb, 0x0b2cb2cb, 0x1b2cb2cb, 0x2b2cb2cb, 0x3b2cb2cb, 0x0b6cb2cb, 0x1b6cb2cb, 0x2b6cb2cb, 0x3b6cb2cb, 0x0bacb2cb, 0x1bacb2cb, 0x2bacb2cb, 0x3bacb2cb, 0x0becb2cb, 0x1becb2cb, 0x2becb2cb, 0x3becb2cb, 0x0b2db2cb, 0x1b2db2cb, 0x2b2db2cb, 0x3b2db2cb, 0x0b6db2cb, 0x1b6db2cb, 0x2b6db2cb, 0x3b6db2cb, 0x0badb2cb, 0x1badb2cb, 0x2badb2cb, 0x3badb2cb, 0x0bedb2cb, 0x1bedb2cb, 0x2bedb2cb, 0x3bedb2cb, 0x0b2eb2cb, 0x1b2eb2cb, 0x2b2eb2cb, 0x3b2eb2cb, 0x0b6eb2cb, 0x1b6eb2cb, 0x2b6eb2cb, 0x3b6eb2cb, 0x0baeb2cb, 0x1baeb2cb, 0x2baeb2cb, 0x3baeb2cb, 0x0beeb2cb, 0x1beeb2cb, 0x2beeb2cb, 0x3beeb2cb, 0x0b2fb2cb, 0x1b2fb2cb, 0x2b2fb2cb, 0x3b2fb2cb, 0x0b6fb2cb, 0x1b6fb2cb, 0x2b6fb2cb, 0x3b6fb2cb, 0x0bafb2cb, 0x1bafb2cb, 0x2bafb2cb, 0x3bafb2cb, 0x0befb2cb, 0x1befb2cb, 0x2befb2cb, 0x3befb2cb, 0x0b2cb6cb, 0x1b2cb6cb, 0x2b2cb6cb, 0x3b2cb6cb, 0x0b6cb6cb, 0x1b6cb6cb, 0x2b6cb6cb, 0x3b6cb6cb, 0x0bacb6cb, 0x1bacb6cb, 0x2bacb6cb, 0x3bacb6cb, 0x0becb6cb, 0x1becb6cb, 0x2becb6cb, 0x3becb6cb, 0x0b2db6cb, 0x1b2db6cb, 0x2b2db6cb, 0x3b2db6cb, 0x0b6db6cb, 0x1b6db6cb, 0x2b6db6cb, 0x3b6db6cb, 0x0badb6cb, 0x1badb6cb, 0x2badb6cb, 0x3badb6cb, 0x0bedb6cb, 0x1bedb6cb, 0x2bedb6cb, 0x3bedb6cb, 0x0b2eb6cb, 0x1b2eb6cb, 0x2b2eb6cb, 0x3b2eb6cb, 0x0b6eb6cb, 0x1b6eb6cb, 0x2b6eb6cb, 0x3b6eb6cb, 0x0baeb6cb, 0x1baeb6cb, 0x2baeb6cb, 0x3baeb6cb, 0x0beeb6cb, 0x1beeb6cb, 0x2beeb6cb, 0x3beeb6cb, 0x0b2fb6cb, 0x1b2fb6cb, 0x2b2fb6cb, 0x3b2fb6cb, 0x0b6fb6cb, 0x1b6fb6cb, 0x2b6fb6cb, 0x3b6fb6cb, 0x0bafb6cb, 0x1bafb6cb, 0x2bafb6cb, 0x3bafb6cb, 0x0befb6cb, 0x1befb6cb, 0x2befb6cb, 0x3befb6cb, 0x0b2cbacb, 0x1b2cbacb, 0x2b2cbacb, 0x3b2cbacb, 0x0b6cbacb, 0x1b6cbacb, 0x2b6cbacb, 0x3b6cbacb, 0x0bacbacb, 0x1bacbacb, 0x2bacbacb, 0x3bacbacb, 0x0becbacb, 0x1becbacb, 0x2becbacb, 0x3becbacb, 0x0b2dbacb, 0x1b2dbacb, 0x2b2dbacb, 0x3b2dbacb, 0x0b6dbacb, 0x1b6dbacb, 0x2b6dbacb, 0x3b6dbacb, 0x0badbacb, 0x1badbacb, 0x2badbacb, 0x3badbacb, 0x0bedbacb, 0x1bedbacb, 0x2bedbacb, 0x3bedbacb, 0x0b2ebacb, 0x1b2ebacb, 0x2b2ebacb, 0x3b2ebacb, 0x0b6ebacb, 0x1b6ebacb, 0x2b6ebacb, 0x3b6ebacb, 0x0baebacb, 0x1baebacb, 0x2baebacb, 0x3baebacb, 0x0beebacb, 0x1beebacb, 0x2beebacb, 0x3beebacb, 0x0b2fbacb, 0x1b2fbacb, 0x2b2fbacb, 0x3b2fbacb, 0x0b6fbacb, 0x1b6fbacb, 0x2b6fbacb, 0x3b6fbacb, 0x0bafbacb, 0x1bafbacb, 0x2bafbacb, 0x3bafbacb, 0x0befbacb, 0x1befbacb, 0x2befbacb, 0x3befbacb, 0x0b2cbecb, 0x1b2cbecb, 0x2b2cbecb, 0x3b2cbecb, 0x0b6cbecb, 0x1b6cbecb, 0x2b6cbecb, 0x3b6cbecb, 0x0bacbecb, 0x1bacbecb, 0x2bacbecb, 0x3bacbecb, 0x0becbecb, 0x1becbecb, 0x2becbecb, 0x3becbecb, 0x0b2dbecb, 0x1b2dbecb, 0x2b2dbecb, 0x3b2dbecb, 0x0b6dbecb, 0x1b6dbecb, 0x2b6dbecb, 0x3b6dbecb, 0x0badbecb, 0x1badbecb, 0x2badbecb, 0x3badbecb, 0x0bedbecb, 0x1bedbecb, 0x2bedbecb, 0x3bedbecb, 0x0b2ebecb, 0x1b2ebecb, 0x2b2ebecb, 0x3b2ebecb, 0x0b6ebecb, 0x1b6ebecb, 0x2b6ebecb, 0x3b6ebecb, 0x0baebecb, 0x1baebecb, 0x2baebecb, 0x3baebecb, 0x0beebecb, 0x1beebecb, 0x2beebecb, 0x3beebecb, 0x0b2fbecb, 0x1b2fbecb, 0x2b2fbecb, 0x3b2fbecb, 0x0b6fbecb, 0x1b6fbecb, 0x2b6fbecb, 0x3b6fbecb, 0x0bafbecb, 0x1bafbecb, 0x2bafbecb, 0x3bafbecb, 0x0befbecb, 0x1befbecb, 0x2befbecb, 0x3befbecb, 0x0b2cb2db, 0x1b2cb2db, 0x2b2cb2db, 0x3b2cb2db, 0x0b6cb2db, 0x1b6cb2db, 0x2b6cb2db, 0x3b6cb2db, 0x0bacb2db, 0x1bacb2db, 0x2bacb2db, 0x3bacb2db, 0x0becb2db, 0x1becb2db, 0x2becb2db, 0x3becb2db, 0x0b2db2db, 0x1b2db2db, 0x2b2db2db, 0x3b2db2db, 0x0b6db2db, 0x1b6db2db, 0x2b6db2db, 0x3b6db2db, 0x0badb2db, 0x1badb2db, 0x2badb2db, 0x3badb2db, 0x0bedb2db, 0x1bedb2db, 0x2bedb2db, 0x3bedb2db, 0x0b2eb2db, 0x1b2eb2db, 0x2b2eb2db, 0x3b2eb2db, 0x0b6eb2db, 0x1b6eb2db, 0x2b6eb2db, 0x3b6eb2db, 0x0baeb2db, 0x1baeb2db, 0x2baeb2db, 0x3baeb2db, 0x0beeb2db, 0x1beeb2db, 0x2beeb2db, 0x3beeb2db, 0x0b2fb2db, 0x1b2fb2db, 0x2b2fb2db, 0x3b2fb2db, 0x0b6fb2db, 0x1b6fb2db, 0x2b6fb2db, 0x3b6fb2db, 0x0bafb2db, 0x1bafb2db, 0x2bafb2db, 0x3bafb2db, 0x0befb2db, 0x1befb2db, 0x2befb2db, 0x3befb2db, 0x0b2cb6db, 0x1b2cb6db, 0x2b2cb6db, 0x3b2cb6db, 0x0b6cb6db, 0x1b6cb6db, 0x2b6cb6db, 0x3b6cb6db, 0x0bacb6db, 0x1bacb6db, 0x2bacb6db, 0x3bacb6db, 0x0becb6db, 0x1becb6db, 0x2becb6db, 0x3becb6db, 0x0b2db6db, 0x1b2db6db, 0x2b2db6db, 0x3b2db6db, 0x0b6db6db, 0x1b6db6db, 0x2b6db6db, 0x3b6db6db, 0x0badb6db, 0x1badb6db, 0x2badb6db, 0x3badb6db, 0x0bedb6db, 0x1bedb6db, 0x2bedb6db, 0x3bedb6db, 0x0b2eb6db, 0x1b2eb6db, 0x2b2eb6db, 0x3b2eb6db, 0x0b6eb6db, 0x1b6eb6db, 0x2b6eb6db, 0x3b6eb6db, 0x0baeb6db, 0x1baeb6db, 0x2baeb6db, 0x3baeb6db, }; static const uint32_t kNonZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = { 6, 6, 6, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, }; static const uint16_t kStaticCommandCodeBits[BROTLI_NUM_COMMAND_SYMBOLS] = { 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, 240, 496, 8, 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, 120, 376, 248, 504, 4, 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, 180, 436, 116, 372, 244, 500, 12, 268, 140, 396, 76, 332, 204, 460, 44, 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, 60, 316, 188, 444, 124, 380, 252, 508, 2, 258, 130, 386, 66, 322, 194, 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, 266, 138, 394, 74, 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, 262, 134, 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, 510, 1, 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, 369, 241, 497, 9, 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, 441, 121, 377, 249, 505, 5, 261, 133, 389, 69, 325, 197, 453, 37, 293, 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, 309, 181, 437, 117, 373, 245, 501, 13, 269, 141, 397, 77, 333, 205, 461, 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, 259, 131, 387, 67, 323, 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, 267, 139, 395, 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, 1031, 519, 1543, 263, 1287, 775, 1799, 135, 1159, 647, 1671, 391, 1415, 903, 1927, 71, 1095, 583, 1607, 327, 1351, 839, 1863, 199, 1223, 711, 1735, 455, 1479, 967, 1991, 39, 1063, 551, 1575, 295, 1319, 807, 1831, 167, 1191, 679, 1703, 423, 1447, 935, 1959, 103, 1127, 615, 1639, 359, 1383, 871, 1895, 231, 1255, 743, 1767, 487, 1511, 999, 2023, 23, 1047, 535, 1559, 279, 1303, 791, 1815, 151, 1175, 663, 1687, 407, 1431, 919, 1943, 87, 1111, 599, 1623, 343, 1367, 855, 1879, 215, 1239, 727, 1751, 471, 1495, 983, 2007, 55, 1079, 567, 1591, 311, 1335, 823, 1847, 183, 1207, 695, 1719, 439, 1463, 951, 1975, 119, 1143, 631, 1655, 375, 1399, 887, 1911, 247, 1271, 759, 1783, 503, 1527, 1015, 2039, 15, 1039, 527, 1551, 271, 1295, 783, 1807, 143, 1167, 655, 1679, 399, 1423, 911, 1935, 79, 1103, 591, 1615, 335, 1359, 847, 1871, 207, 1231, 719, 1743, 463, 1487, 975, 1999, 47, 1071, 559, 1583, 303, 1327, 815, 1839, 175, 1199, 687, 1711, 431, 1455, 943, 1967, 111, 1135, 623, 1647, 367, 1391, 879, 1903, 239, 1263, 751, 1775, 495, 1519, 1007, 2031, 31, 1055, 543, 1567, 287, 1311, 799, 1823, 159, 1183, 671, 1695, 415, 1439, 927, 1951, 95, 1119, 607, 1631, 351, 1375, 863, 1887, 223, 1247, 735, 1759, 479, 1503, 991, 2015, 63, 1087, 575, 1599, 319, 1343, 831, 1855, 191, 1215, 703, 1727, 447, 1471, 959, 1983, 127, 1151, 639, 1663, 383, 1407, 895, 1919, 255, 1279, 767, 1791, 511, 1535, 1023, 2047, }; static BROTLI_INLINE void StoreStaticCommandHuffmanTree( size_t* storage_ix, uint8_t* storage) { BrotliWriteBits( 56, BROTLI_MAKE_UINT64_T(0x926244U, 0x16307003U), storage_ix, storage); BrotliWriteBits(3, 0x00000000U, storage_ix, storage); } static const uint16_t kStaticDistanceCodeBits[64] = { 0, 32, 16, 48, 8, 40, 24, 56, 4, 36, 20, 52, 12, 44, 28, 60, 2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62, 1, 33, 17, 49, 9, 41, 25, 57, 5, 37, 21, 53, 13, 45, 29, 61, 3, 35, 19, 51, 11, 43, 27, 59, 7, 39, 23, 55, 15, 47, 31, 63, }; static BROTLI_INLINE void StoreStaticDistanceHuffmanTree( size_t* storage_ix, uint8_t* storage) { BrotliWriteBits(28, 0x0369DC03u, storage_ix, storage); } /* GENERATED CODE END */ #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ */ dvisvgm-3.5/libs/brotli/enc/fast_log.c000066400000000000000000000136101501401750600177730ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "fast_log.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* ", ".join(["%.16ff" % x for x in [0.0]+[log2(x) for x in range(1, 256)]]) */ const double kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE] = { 0.0000000000000000f, 0.0000000000000000f, 1.0000000000000000f, 1.5849625007211563f, 2.0000000000000000f, 2.3219280948873622f, 2.5849625007211561f, 2.8073549220576042f, 3.0000000000000000f, 3.1699250014423126f, 3.3219280948873626f, 3.4594316186372978f, 3.5849625007211565f, 3.7004397181410922f, 3.8073549220576037f, 3.9068905956085187f, 4.0000000000000000f, 4.0874628412503400f, 4.1699250014423122f, 4.2479275134435852f, 4.3219280948873626f, 4.3923174227787607f, 4.4594316186372973f, 4.5235619560570131f, 4.5849625007211570f, 4.6438561897747244f, 4.7004397181410926f, 4.7548875021634691f, 4.8073549220576037f, 4.8579809951275728f, 4.9068905956085187f, 4.9541963103868758f, 5.0000000000000000f, 5.0443941193584534f, 5.0874628412503400f, 5.1292830169449664f, 5.1699250014423122f, 5.2094533656289501f, 5.2479275134435852f, 5.2854022188622487f, 5.3219280948873626f, 5.3575520046180838f, 5.3923174227787607f, 5.4262647547020979f, 5.4594316186372973f, 5.4918530963296748f, 5.5235619560570131f, 5.5545888516776376f, 5.5849625007211570f, 5.6147098441152083f, 5.6438561897747244f, 5.6724253419714961f, 5.7004397181410926f, 5.7279204545631996f, 5.7548875021634691f, 5.7813597135246599f, 5.8073549220576046f, 5.8328900141647422f, 5.8579809951275719f, 5.8826430493618416f, 5.9068905956085187f, 5.9307373375628867f, 5.9541963103868758f, 5.9772799234999168f, 6.0000000000000000f, 6.0223678130284544f, 6.0443941193584534f, 6.0660891904577721f, 6.0874628412503400f, 6.1085244567781700f, 6.1292830169449672f, 6.1497471195046822f, 6.1699250014423122f, 6.1898245588800176f, 6.2094533656289510f, 6.2288186904958804f, 6.2479275134435861f, 6.2667865406949019f, 6.2854022188622487f, 6.3037807481771031f, 6.3219280948873617f, 6.3398500028846252f, 6.3575520046180847f, 6.3750394313469254f, 6.3923174227787598f, 6.4093909361377026f, 6.4262647547020979f, 6.4429434958487288f, 6.4594316186372982f, 6.4757334309663976f, 6.4918530963296748f, 6.5077946401986964f, 6.5235619560570131f, 6.5391588111080319f, 6.5545888516776376f, 6.5698556083309478f, 6.5849625007211561f, 6.5999128421871278f, 6.6147098441152092f, 6.6293566200796095f, 6.6438561897747253f, 6.6582114827517955f, 6.6724253419714952f, 6.6865005271832185f, 6.7004397181410917f, 6.7142455176661224f, 6.7279204545631988f, 6.7414669864011465f, 6.7548875021634691f, 6.7681843247769260f, 6.7813597135246599f, 6.7944158663501062f, 6.8073549220576037f, 6.8201789624151887f, 6.8328900141647422f, 6.8454900509443757f, 6.8579809951275719f, 6.8703647195834048f, 6.8826430493618416f, 6.8948177633079437f, 6.9068905956085187f, 6.9188632372745955f, 6.9307373375628867f, 6.9425145053392399f, 6.9541963103868758f, 6.9657842846620879f, 6.9772799234999168f, 6.9886846867721664f, 7.0000000000000000f, 7.0112272554232540f, 7.0223678130284544f, 7.0334230015374501f, 7.0443941193584534f, 7.0552824355011898f, 7.0660891904577721f, 7.0768155970508317f, 7.0874628412503400f, 7.0980320829605272f, 7.1085244567781700f, 7.1189410727235076f, 7.1292830169449664f, 7.1395513523987937f, 7.1497471195046822f, 7.1598713367783891f, 7.1699250014423130f, 7.1799090900149345f, 7.1898245588800176f, 7.1996723448363644f, 7.2094533656289492f, 7.2191685204621621f, 7.2288186904958804f, 7.2384047393250794f, 7.2479275134435861f, 7.2573878426926521f, 7.2667865406949019f, 7.2761244052742384f, 7.2854022188622487f, 7.2946207488916270f, 7.3037807481771031f, 7.3128829552843557f, 7.3219280948873617f, 7.3309168781146177f, 7.3398500028846243f, 7.3487281542310781f, 7.3575520046180847f, 7.3663222142458151f, 7.3750394313469254f, 7.3837042924740528f, 7.3923174227787607f, 7.4008794362821844f, 7.4093909361377026f, 7.4178525148858991f, 7.4262647547020979f, 7.4346282276367255f, 7.4429434958487288f, 7.4512111118323299f, 7.4594316186372973f, 7.4676055500829976f, 7.4757334309663976f, 7.4838157772642564f, 7.4918530963296748f, 7.4998458870832057f, 7.5077946401986964f, 7.5156998382840436f, 7.5235619560570131f, 7.5313814605163119f, 7.5391588111080319f, 7.5468944598876373f, 7.5545888516776376f, 7.5622424242210728f, 7.5698556083309478f, 7.5774288280357487f, 7.5849625007211561f, 7.5924570372680806f, 7.5999128421871278f, 7.6073303137496113f, 7.6147098441152075f, 7.6220518194563764f, 7.6293566200796095f, 7.6366246205436488f, 7.6438561897747244f, 7.6510516911789290f, 7.6582114827517955f, 7.6653359171851765f, 7.6724253419714952f, 7.6794800995054464f, 7.6865005271832185f, 7.6934869574993252f, 7.7004397181410926f, 7.7073591320808825f, 7.7142455176661224f, 7.7210991887071856f, 7.7279204545631996f, 7.7347096202258392f, 7.7414669864011465f, 7.7481928495894596f, 7.7548875021634691f, 7.7615512324444795f, 7.7681843247769260f, 7.7747870596011737f, 7.7813597135246608f, 7.7879025593914317f, 7.7944158663501062f, 7.8008998999203047f, 7.8073549220576037f, 7.8137811912170374f, 7.8201789624151887f, 7.8265484872909159f, 7.8328900141647422f, 7.8392037880969445f, 7.8454900509443757f, 7.8517490414160571f, 7.8579809951275719f, 7.8641861446542798f, 7.8703647195834048f, 7.8765169465650002f, 7.8826430493618425f, 7.8887432488982601f, 7.8948177633079446f, 7.9008668079807496f, 7.9068905956085187f, 7.9128893362299619f, 7.9188632372745955f, 7.9248125036057813f, 7.9307373375628867f, 7.9366379390025719f, 7.9425145053392399f, 7.9483672315846778f, 7.9541963103868758f, 7.9600019320680806f, 7.9657842846620870f, 7.9715435539507720f, 7.9772799234999168f, 7.9829935746943104f, 7.9886846867721664f, 7.9943534368588578f }; #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/fast_log.h000066400000000000000000000031621501401750600200010ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Utilities for fast computation of logarithms. */ #ifndef BROTLI_ENC_FAST_LOG_H_ #define BROTLI_ENC_FAST_LOG_H_ #include #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static BROTLI_INLINE uint32_t Log2FloorNonZero(size_t n) { #if defined(BROTLI_BSR32) return BROTLI_BSR32((uint32_t)n); #else uint32_t result = 0; while (n >>= 1) result++; return result; #endif } #define BROTLI_LOG2_TABLE_SIZE 256 /* A lookup table for small values of log2(int) to be used in entropy computation. */ BROTLI_INTERNAL extern const double kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE]; /* Visual Studio 2012 and Android API levels < 18 do not have the log2() * function defined, so we use log() and a multiplication instead. */ #if !defined(BROTLI_HAVE_LOG2) #if ((defined(_MSC_VER) && _MSC_VER <= 1700) || \ (defined(__ANDROID_API__) && __ANDROID_API__ < 18)) #define BROTLI_HAVE_LOG2 0 #else #define BROTLI_HAVE_LOG2 1 #endif #endif #define LOG_2_INV 1.4426950408889634 /* Faster logarithm for small integers, with the property of log2(0) == 0. */ static BROTLI_INLINE double FastLog2(size_t v) { if (v < BROTLI_LOG2_TABLE_SIZE) { return kBrotliLog2Table[v]; } #if !(BROTLI_HAVE_LOG2) return log((double)v) * LOG_2_INV; #else return log2((double)v); #endif } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_FAST_LOG_H_ */ dvisvgm-3.5/libs/brotli/enc/find_match_length.h000066400000000000000000000042221501401750600216360ustar00rootroot00000000000000/* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Function to find maximal matching prefixes of strings. */ #ifndef BROTLI_ENC_FIND_MATCH_LENGTH_H_ #define BROTLI_ENC_FIND_MATCH_LENGTH_H_ #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* Separate implementation for little-endian 64-bit targets, for speed. */ #if defined(BROTLI_TZCNT64) && BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1, const uint8_t* s2, size_t limit) { const uint8_t *s1_orig = s1; for (; limit >= 8; limit -= 8) { uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^ BROTLI_UNALIGNED_LOAD64LE(s1); s2 += 8; if (x != 0) { size_t matching_bits = (size_t)BROTLI_TZCNT64(x); return (size_t)(s1 - s1_orig) + (matching_bits >> 3); } s1 += 8; } while (limit && *s1 == *s2) { limit--; ++s2; ++s1; } return (size_t)(s1 - s1_orig); } #else static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1, const uint8_t* s2, size_t limit) { size_t matched = 0; const uint8_t* s2_limit = s2 + limit; const uint8_t* s2_ptr = s2; /* Find out how long the match is. We loop over the data 32 bits at a time until we find a 32-bit block that doesn't match; then we find the first non-matching bit and use that to calculate the total length of the match. */ while (s2_ptr <= s2_limit - 4 && BrotliUnalignedRead32(s2_ptr) == BrotliUnalignedRead32(s1 + matched)) { s2_ptr += 4; matched += 4; } while ((s2_ptr < s2_limit) && (s1[matched] == *s2_ptr)) { ++s2_ptr; ++matched; } return matched; } #endif #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_FIND_MATCH_LENGTH_H_ */ dvisvgm-3.5/libs/brotli/enc/hash.h000066400000000000000000000572261501401750600171400ustar00rootroot00000000000000/* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* A (forgetful) hash table to the data seen by the compressor, to help create backward references to previous data. */ #ifndef BROTLI_ENC_HASH_H_ #define BROTLI_ENC_HASH_H_ #include /* exit */ #include /* memcmp, memset */ #include #include "../common/constants.h" #include "../common/dictionary.h" #include "../common/platform.h" #include "compound_dictionary.h" #include "encoder_dict.h" #include "fast_log.h" #include "find_match_length.h" #include "memory.h" #include "quality.h" #include "static_dict.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct { /** * Dynamically allocated areas; regular hasher uses one or two allocations; * "composite" hasher uses up to 4 allocations. */ void* extra[4]; /** * False before the fisrt invocation of HasherSetup (where "extra" memory) * is allocated. */ BROTLI_BOOL is_setup_; size_t dict_num_lookups; size_t dict_num_matches; BrotliHasherParams params; /** * False if hasher needs to be "prepared" before use (before the first * invocation of HasherSetup or after HasherReset). "preparation" is hasher * data initialization (using input ringbuffer). */ BROTLI_BOOL is_prepared_; } HasherCommon; #define score_t size_t static const uint32_t kCutoffTransformsCount = 10; /* 0, 12, 27, 23, 42, 63, 56, 48, 59, 64 */ /* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */ static const uint64_t kCutoffTransforms = BROTLI_MAKE_UINT64_T(0x071B520A, 0xDA2D3200); typedef struct HasherSearchResult { size_t len; size_t distance; score_t score; int len_code_delta; /* == len_code - len */ } HasherSearchResult; /* kHashMul32 multiplier has these properties: * The multiplier must be odd. Otherwise we may lose the highest bit. * No long streaks of ones or zeros. * There is no effort to ensure that it is a prime, the oddity is enough for this use. * The number has been tuned heuristically against compression benchmarks. */ static const uint32_t kHashMul32 = 0x1E35A7BD; static const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u); static BROTLI_INLINE uint32_t Hash14(const uint8_t* data) { uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return h >> (32 - 14); } static BROTLI_INLINE void PrepareDistanceCache( int* BROTLI_RESTRICT distance_cache, const int num_distances) { if (num_distances > 4) { int last_distance = distance_cache[0]; distance_cache[4] = last_distance - 1; distance_cache[5] = last_distance + 1; distance_cache[6] = last_distance - 2; distance_cache[7] = last_distance + 2; distance_cache[8] = last_distance - 3; distance_cache[9] = last_distance + 3; if (num_distances > 10) { int next_last_distance = distance_cache[1]; distance_cache[10] = next_last_distance - 1; distance_cache[11] = next_last_distance + 1; distance_cache[12] = next_last_distance - 2; distance_cache[13] = next_last_distance + 2; distance_cache[14] = next_last_distance - 3; distance_cache[15] = next_last_distance + 3; } } } #define BROTLI_LITERAL_BYTE_SCORE 135 #define BROTLI_DISTANCE_BIT_PENALTY 30 /* Score must be positive after applying maximal penalty. */ #define BROTLI_SCORE_BASE (BROTLI_DISTANCE_BIT_PENALTY * 8 * sizeof(size_t)) /* Usually, we always choose the longest backward reference. This function allows for the exception of that rule. If we choose a backward reference that is further away, it will usually be coded with more bits. We approximate this by assuming log2(distance). If the distance can be expressed in terms of the last four distances, we use some heuristic constants to estimate the bits cost. For the first up to four literals we use the bit cost of the literals from the literal cost model, after that we use the average bit cost of the cost model. This function is used to sometimes discard a longer backward reference when it is not much longer and the bit cost for encoding it is more than the saved literals. backward_reference_offset MUST be positive. */ static BROTLI_INLINE score_t BackwardReferenceScore( size_t copy_length, size_t backward_reference_offset) { return BROTLI_SCORE_BASE + BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length - BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset); } static BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance( size_t copy_length) { return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length + BROTLI_SCORE_BASE + 15; } static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance( size_t distance_short_code) { return (score_t)39 + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE); } static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem( const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx, const uint8_t* data, size_t max_length, size_t max_backward, size_t max_distance, HasherSearchResult* out) { size_t offset; size_t matchlen; size_t backward; score_t score; offset = dictionary->words->offsets_by_length[len] + len * word_idx; if (len > max_length) { return BROTLI_FALSE; } matchlen = FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len); if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) { return BROTLI_FALSE; } { size_t cut = len - matchlen; size_t transform_id = (cut << 2) + (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F); backward = max_backward + 1 + word_idx + (transform_id << dictionary->words->size_bits_by_length[len]); } if (backward > max_distance) { return BROTLI_FALSE; } score = BackwardReferenceScore(matchlen, backward); if (score < out->score) { return BROTLI_FALSE; } out->len = matchlen; out->len_code_delta = (int)len - (int)matchlen; out->distance = backward; out->score = score; return BROTLI_TRUE; } static BROTLI_INLINE void SearchInStaticDictionary( const BrotliEncoderDictionary* dictionary, HasherCommon* common, const uint8_t* data, size_t max_length, size_t max_backward, size_t max_distance, HasherSearchResult* out, BROTLI_BOOL shallow) { size_t key; size_t i; if (common->dict_num_matches < (common->dict_num_lookups >> 7)) { return; } key = Hash14(data) << 1; for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) { common->dict_num_lookups++; if (dictionary->hash_table_lengths[key] != 0) { BROTLI_BOOL item_matches = TestStaticDictionaryItem( dictionary, dictionary->hash_table_lengths[key], dictionary->hash_table_words[key], data, max_length, max_backward, max_distance, out); if (item_matches) { common->dict_num_matches++; } } } } typedef struct BackwardMatch { uint32_t distance; uint32_t length_and_code; } BackwardMatch; static BROTLI_INLINE void InitBackwardMatch(BackwardMatch* self, size_t dist, size_t len) { self->distance = (uint32_t)dist; self->length_and_code = (uint32_t)(len << 5); } static BROTLI_INLINE void InitDictionaryBackwardMatch(BackwardMatch* self, size_t dist, size_t len, size_t len_code) { self->distance = (uint32_t)dist; self->length_and_code = (uint32_t)((len << 5) | (len == len_code ? 0 : len_code)); } static BROTLI_INLINE size_t BackwardMatchLength(const BackwardMatch* self) { return self->length_and_code >> 5; } static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) { size_t code = self->length_and_code & 31; return code ? code : BackwardMatchLength(self); } #define EXPAND_CAT(a, b) CAT(a, b) #define CAT(a, b) a ## b #define FN(X) EXPAND_CAT(X, HASHER()) #define HASHER() H10 #define BUCKET_BITS 17 #define MAX_TREE_SEARCH_DEPTH 64 #define MAX_TREE_COMP_LENGTH 128 #include "hash_to_binary_tree_inc.h" /* NOLINT(build/include) */ #undef MAX_TREE_SEARCH_DEPTH #undef MAX_TREE_COMP_LENGTH #undef BUCKET_BITS #undef HASHER /* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */ #define MAX_NUM_MATCHES_H10 128 /* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression a little faster (0.5% - 1%) and it compresses 0.15% better on small text and HTML inputs. */ #define HASHER() H2 #define BUCKET_BITS 16 #define BUCKET_SWEEP_BITS 0 #define HASH_LEN 5 #define USE_DICTIONARY 1 #include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */ #undef BUCKET_SWEEP_BITS #undef USE_DICTIONARY #undef HASHER #define HASHER() H3 #define BUCKET_SWEEP_BITS 1 #define USE_DICTIONARY 0 #include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */ #undef USE_DICTIONARY #undef BUCKET_SWEEP_BITS #undef BUCKET_BITS #undef HASHER #define HASHER() H4 #define BUCKET_BITS 17 #define BUCKET_SWEEP_BITS 2 #define USE_DICTIONARY 1 #include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */ #undef USE_DICTIONARY #undef HASH_LEN #undef BUCKET_SWEEP_BITS #undef BUCKET_BITS #undef HASHER #define HASHER() H5 #include "hash_longest_match_inc.h" /* NOLINT(build/include) */ #undef HASHER #define HASHER() H6 #include "hash_longest_match64_inc.h" /* NOLINT(build/include) */ #undef HASHER #define BUCKET_BITS 15 #define NUM_LAST_DISTANCES_TO_CHECK 4 #define NUM_BANKS 1 #define BANK_BITS 16 #define HASHER() H40 #include "hash_forgetful_chain_inc.h" /* NOLINT(build/include) */ #undef HASHER #undef NUM_LAST_DISTANCES_TO_CHECK #define NUM_LAST_DISTANCES_TO_CHECK 10 #define HASHER() H41 #include "hash_forgetful_chain_inc.h" /* NOLINT(build/include) */ #undef HASHER #undef NUM_LAST_DISTANCES_TO_CHECK #undef NUM_BANKS #undef BANK_BITS #define NUM_LAST_DISTANCES_TO_CHECK 16 #define NUM_BANKS 512 #define BANK_BITS 9 #define HASHER() H42 #include "hash_forgetful_chain_inc.h" /* NOLINT(build/include) */ #undef HASHER #undef NUM_LAST_DISTANCES_TO_CHECK #undef NUM_BANKS #undef BANK_BITS #undef BUCKET_BITS #define HASHER() H54 #define BUCKET_BITS 20 #define BUCKET_SWEEP_BITS 2 #define HASH_LEN 7 #define USE_DICTIONARY 0 #include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */ #undef USE_DICTIONARY #undef HASH_LEN #undef BUCKET_SWEEP_BITS #undef BUCKET_BITS #undef HASHER /* fast large window hashers */ #define HASHER() HROLLING_FAST #define CHUNKLEN 32 #define JUMP 4 #define NUMBUCKETS 16777216 #define MASK ((NUMBUCKETS * 64) - 1) #include "hash_rolling_inc.h" /* NOLINT(build/include) */ #undef JUMP #undef HASHER #define HASHER() HROLLING #define JUMP 1 #include "hash_rolling_inc.h" /* NOLINT(build/include) */ #undef MASK #undef NUMBUCKETS #undef JUMP #undef CHUNKLEN #undef HASHER #define HASHER() H35 #define HASHER_A H3 #define HASHER_B HROLLING_FAST #include "hash_composite_inc.h" /* NOLINT(build/include) */ #undef HASHER_A #undef HASHER_B #undef HASHER #define HASHER() H55 #define HASHER_A H54 #define HASHER_B HROLLING_FAST #include "hash_composite_inc.h" /* NOLINT(build/include) */ #undef HASHER_A #undef HASHER_B #undef HASHER #define HASHER() H65 #define HASHER_A H6 #define HASHER_B HROLLING #include "hash_composite_inc.h" /* NOLINT(build/include) */ #undef HASHER_A #undef HASHER_B #undef HASHER #undef FN #undef CAT #undef EXPAND_CAT #define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) #define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65) #define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H) #define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10) typedef struct { HasherCommon common; union { #define MEMBER_(N) \ H ## N _H ## N; FOR_ALL_HASHERS(MEMBER_) #undef MEMBER_ } privat; } Hasher; /* MUST be invoked before any other method. */ static BROTLI_INLINE void HasherInit(Hasher* hasher) { hasher->common.is_setup_ = BROTLI_FALSE; hasher->common.extra[0] = NULL; hasher->common.extra[1] = NULL; hasher->common.extra[2] = NULL; hasher->common.extra[3] = NULL; } static BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) { if (hasher->common.extra[0] != NULL) BROTLI_FREE(m, hasher->common.extra[0]); if (hasher->common.extra[1] != NULL) BROTLI_FREE(m, hasher->common.extra[1]); if (hasher->common.extra[2] != NULL) BROTLI_FREE(m, hasher->common.extra[2]); if (hasher->common.extra[3] != NULL) BROTLI_FREE(m, hasher->common.extra[3]); } static BROTLI_INLINE void HasherReset(Hasher* hasher) { hasher->common.is_prepared_ = BROTLI_FALSE; } static BROTLI_INLINE void HasherSize(const BrotliEncoderParams* params, BROTLI_BOOL one_shot, const size_t input_size, size_t* alloc_size) { switch (params->hasher.type) { #define SIZE_(N) \ case N: \ HashMemAllocInBytesH ## N(params, one_shot, input_size, alloc_size); \ break; FOR_ALL_HASHERS(SIZE_) #undef SIZE_ default: break; } } static BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher, BrotliEncoderParams* params, const uint8_t* data, size_t position, size_t input_size, BROTLI_BOOL is_last) { BROTLI_BOOL one_shot = (position == 0 && is_last); if (!hasher->common.is_setup_) { size_t alloc_size[4] = {0}; size_t i; ChooseHasher(params, ¶ms->hasher); hasher->common.params = params->hasher; hasher->common.dict_num_lookups = 0; hasher->common.dict_num_matches = 0; HasherSize(params, one_shot, input_size, alloc_size); for (i = 0; i < 4; ++i) { if (alloc_size[i] == 0) continue; hasher->common.extra[i] = BROTLI_ALLOC(m, uint8_t, alloc_size[i]); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra[i])) return; } switch (hasher->common.params.type) { #define INITIALIZE_(N) \ case N: \ InitializeH ## N(&hasher->common, \ &hasher->privat._H ## N, params); \ break; FOR_ALL_HASHERS(INITIALIZE_); #undef INITIALIZE_ default: break; } HasherReset(hasher); hasher->common.is_setup_ = BROTLI_TRUE; } if (!hasher->common.is_prepared_) { switch (hasher->common.params.type) { #define PREPARE_(N) \ case N: \ PrepareH ## N( \ &hasher->privat._H ## N, \ one_shot, input_size, data); \ break; FOR_ALL_HASHERS(PREPARE_) #undef PREPARE_ default: break; } hasher->common.is_prepared_ = BROTLI_TRUE; } } static BROTLI_INLINE void InitOrStitchToPreviousBlock( MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask, BrotliEncoderParams* params, size_t position, size_t input_size, BROTLI_BOOL is_last) { HasherSetup(m, hasher, params, data, position, input_size, is_last); if (BROTLI_IS_OOM(m)) return; switch (hasher->common.params.type) { #define INIT_(N) \ case N: \ StitchToPreviousBlockH ## N( \ &hasher->privat._H ## N, \ input_size, position, data, mask); \ break; FOR_ALL_HASHERS(INIT_) #undef INIT_ default: break; } } /* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */ static BROTLI_INLINE void FindCompoundDictionaryMatch( const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t distance_offset, const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { const uint32_t source_size = self->source_size; const size_t boundary = distance_offset - source_size; const uint32_t hash_bits = self->hash_bits; const uint32_t bucket_bits = self->bucket_bits; const uint32_t slot_bits = self->slot_bits; const uint32_t hash_shift = 64u - bucket_bits; const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits); const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits); const uint32_t* slot_offsets = (uint32_t*)(&self[1]); const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]); const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]); const uint8_t* source = NULL; const size_t cur_ix_masked = cur_ix & ring_buffer_mask; score_t best_score = out->score; size_t best_len = out->len; size_t i; const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) * kPreparedDictionaryHashMul64Long; const uint32_t key = (uint32_t)(h >> hash_shift); const uint32_t slot = key & slot_mask; const uint32_t head = heads[key]; const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head]; uint32_t item = (head == 0xFFFF) ? 1 : 0; const void* tail = (void*)&items[self->num_items]; if (self->magic == kPreparedDictionaryMagic) { source = (const uint8_t*)tail; } else { /* kLeanPreparedDictionaryMagic */ source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail); } for (i = 0; i < 4; ++i) { const size_t distance = (size_t)distance_cache[i]; size_t offset; size_t limit; size_t len; if (distance <= boundary || distance > distance_offset) continue; offset = distance_offset - distance; limit = source_size - offset; limit = limit > max_length ? max_length : limit; len = FindMatchLengthWithLimit(&source[offset], &data[cur_ix_masked], limit); if (len >= 2) { score_t score = BackwardReferenceScoreUsingLastDistance(len); if (best_score < score) { if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); if (best_score < score) { best_score = score; if (len > best_len) best_len = len; out->len = len; out->len_code_delta = 0; out->distance = distance; out->score = best_score; } } } } while (item == 0) { size_t offset; size_t distance; size_t limit; item = *chain; chain++; offset = item & 0x7FFFFFFF; item &= 0x80000000; distance = distance_offset - offset; limit = source_size - offset; limit = (limit > max_length) ? max_length : limit; if (distance > max_distance) continue; if (cur_ix_masked + best_len > ring_buffer_mask || best_len >= limit || data[cur_ix_masked + best_len] != source[offset + best_len]) { continue; } { const size_t len = FindMatchLengthWithLimit(&source[offset], &data[cur_ix_masked], limit); if (len >= 4) { score_t score = BackwardReferenceScore(len, distance); if (best_score < score) { best_score = score; best_len = len; out->len = best_len; out->len_code_delta = 0; out->distance = distance; out->score = best_score; } } } } } /* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */ static BROTLI_INLINE size_t FindAllCompoundDictionaryMatches( const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const size_t cur_ix, const size_t min_length, const size_t max_length, const size_t distance_offset, const size_t max_distance, BackwardMatch* matches, size_t match_limit) { const uint32_t source_size = self->source_size; const uint32_t hash_bits = self->hash_bits; const uint32_t bucket_bits = self->bucket_bits; const uint32_t slot_bits = self->slot_bits; const uint32_t hash_shift = 64u - bucket_bits; const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits); const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits); const uint32_t* slot_offsets = (uint32_t*)(&self[1]); const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]); const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]); const uint8_t* source = NULL; const size_t cur_ix_masked = cur_ix & ring_buffer_mask; size_t best_len = min_length; const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) * kPreparedDictionaryHashMul64Long; const uint32_t key = (uint32_t)(h >> hash_shift); const uint32_t slot = key & slot_mask; const uint32_t head = heads[key]; const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head]; uint32_t item = (head == 0xFFFF) ? 1 : 0; size_t found = 0; const void* tail = (void*)&items[self->num_items]; if (self->magic == kPreparedDictionaryMagic) { source = (const uint8_t*)tail; } else { /* kLeanPreparedDictionaryMagic */ source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail); } while (item == 0) { size_t offset; size_t distance; size_t limit; size_t len; item = *chain; chain++; offset = item & 0x7FFFFFFF; item &= 0x80000000; distance = distance_offset - offset; limit = source_size - offset; limit = (limit > max_length) ? max_length : limit; if (distance > max_distance) continue; if (cur_ix_masked + best_len > ring_buffer_mask || best_len >= limit || data[cur_ix_masked + best_len] != source[offset + best_len]) { continue; } len = FindMatchLengthWithLimit( &source[offset], &data[cur_ix_masked], limit); if (len > best_len) { best_len = len; InitBackwardMatch(matches++, distance, len); found++; if (found == match_limit) break; } } return found; } static BROTLI_INLINE void LookupCompoundDictionaryMatch( const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t max_ring_buffer_distance, const size_t max_distance, HasherSearchResult* sr) { size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1; size_t d; for (d = 0; d < addon->num_chunks; ++d) { /* Only one prepared dictionary type is currently supported. */ FindCompoundDictionaryMatch( (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask, distance_cache, cur_ix, max_length, base_offset - addon->chunk_offsets[d], max_distance, sr); } } static BROTLI_INLINE size_t LookupAllCompoundDictionaryMatches( const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const size_t cur_ix, size_t min_length, const size_t max_length, const size_t max_ring_buffer_distance, const size_t max_distance, BackwardMatch* matches, size_t match_limit) { size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1; size_t d; size_t total_found = 0; for (d = 0; d < addon->num_chunks; ++d) { /* Only one prepared dictionary type is currently supported. */ total_found += FindAllCompoundDictionaryMatches( (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask, cur_ix, min_length, max_length, base_offset - addon->chunk_offsets[d], max_distance, matches + total_found, match_limit - total_found); if (total_found == match_limit) break; if (total_found > 0) { min_length = BackwardMatchLength(&matches[total_found - 1]); } } return total_found; } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_HASH_H_ */ dvisvgm-3.5/libs/brotli/enc/hash_composite_inc.h000066400000000000000000000117511501401750600220440ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2018 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN, HASHER_A, HASHER_B */ /* Composite hasher: This hasher allows to combine two other hashers, HASHER_A and HASHER_B. */ #define HashComposite HASHER() #define FN_A(X) EXPAND_CAT(X, HASHER_A) #define FN_B(X) EXPAND_CAT(X, HASHER_B) static BROTLI_INLINE size_t FN(HashTypeLength)(void) { size_t a = FN_A(HashTypeLength)(); size_t b = FN_B(HashTypeLength)(); return a > b ? a : b; } static BROTLI_INLINE size_t FN(StoreLookahead)(void) { size_t a = FN_A(StoreLookahead)(); size_t b = FN_B(StoreLookahead)(); return a > b ? a : b; } typedef struct HashComposite { HASHER_A ha; HASHER_B hb; HasherCommon ha_common; HasherCommon hb_common; /* Shortcuts. */ HasherCommon* common; BROTLI_BOOL fresh; const BrotliEncoderParams* params; } HashComposite; static void FN(Initialize)(HasherCommon* common, HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { self->common = common; self->ha_common = *self->common; self->hb_common = *self->common; self->fresh = BROTLI_TRUE; self->params = params; /* TODO(lode): Initialize of the hashers is deferred to Prepare (and params remembered here) because we don't get the one_shot and input_size params here that are needed to know the memory size of them. Instead provide those params to all hashers FN(Initialize) */ } static void FN(Prepare)( HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, size_t input_size, const uint8_t* BROTLI_RESTRICT data) { if (self->fresh) { self->fresh = BROTLI_FALSE; self->ha_common.extra[0] = self->common->extra[0]; self->ha_common.extra[1] = self->common->extra[1]; self->ha_common.extra[2] = NULL; self->ha_common.extra[3] = NULL; self->hb_common.extra[0] = self->common->extra[2]; self->hb_common.extra[1] = self->common->extra[3]; self->hb_common.extra[2] = NULL; self->hb_common.extra[3] = NULL; FN_A(Initialize)(&self->ha_common, &self->ha, self->params); FN_B(Initialize)(&self->hb_common, &self->hb, self->params); } FN_A(Prepare)(&self->ha, one_shot, input_size, data); FN_B(Prepare)(&self->hb, one_shot, input_size, data); } static BROTLI_INLINE void FN(HashMemAllocInBytes)( const BrotliEncoderParams* params, BROTLI_BOOL one_shot, size_t input_size, size_t* alloc_size) { size_t alloc_size_a[4] = {0}; size_t alloc_size_b[4] = {0}; FN_A(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_a); FN_B(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_b); /* Should never happen. */ if (alloc_size_a[2] != 0 || alloc_size_a[3] != 0) exit(EXIT_FAILURE); if (alloc_size_b[2] != 0 || alloc_size_b[3] != 0) exit(EXIT_FAILURE); alloc_size[0] = alloc_size_a[0]; alloc_size[1] = alloc_size_a[1]; alloc_size[2] = alloc_size_b[0]; alloc_size[3] = alloc_size_b[1]; } static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { FN_A(Store)(&self->ha, data, mask, ix); FN_B(Store)(&self->hb, data, mask, ix); } static BROTLI_INLINE void FN(StoreRange)( HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix_start, const size_t ix_end) { FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end); FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end); } static BROTLI_INLINE void FN(StitchToPreviousBlock)( HashComposite* BROTLI_RESTRICT self, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ring_buffer_mask) { FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position, ringbuffer, ring_buffer_mask); FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position, ringbuffer, ring_buffer_mask); } static BROTLI_INLINE void FN(PrepareDistanceCache)( HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { FN_A(PrepareDistanceCache)(&self->ha, distance_cache); FN_B(PrepareDistanceCache)(&self->hb, distance_cache); } static BROTLI_INLINE void FN(FindLongestMatch)( HashComposite* BROTLI_RESTRICT self, const BrotliEncoderDictionary* dictionary, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t max_backward, const size_t dictionary_distance, const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask, distance_cache, cur_ix, max_length, max_backward, dictionary_distance, max_distance, out); FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask, distance_cache, cur_ix, max_length, max_backward, dictionary_distance, max_distance, out); } #undef HashComposite dvisvgm-3.5/libs/brotli/enc/hash_forgetful_chain_inc.h000066400000000000000000000253331501401750600232020ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN, BUCKET_BITS, NUM_BANKS, BANK_BITS, NUM_LAST_DISTANCES_TO_CHECK */ /* A (forgetful) hash table to the data seen by the compressor, to help create backward references to previous data. Hashes are stored in chains which are bucketed to groups. Group of chains share a storage "bank". When more than "bank size" chain nodes are added, oldest nodes are replaced; this way several chains may share a tail. */ #define HashForgetfulChain HASHER() #define BANK_SIZE (1 << BANK_BITS) /* Number of hash buckets. */ #define BUCKET_SIZE (1 << BUCKET_BITS) #define CAPPED_CHAINS 0 static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } /* HashBytes is the function that chooses the bucket to place the address in.*/ static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) { const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return h >> (32 - BUCKET_BITS); } typedef struct FN(Slot) { uint16_t delta; uint16_t next; } FN(Slot); typedef struct FN(Bank) { FN(Slot) slots[BANK_SIZE]; } FN(Bank); typedef struct HashForgetfulChain { uint16_t free_slot_idx[NUM_BANKS]; /* Up to 1KiB. Move to dynamic? */ size_t max_hops; /* Shortcuts. */ void* extra[2]; HasherCommon* common; /* --- Dynamic size members --- */ /* uint32_t addr[BUCKET_SIZE]; */ /* uint16_t head[BUCKET_SIZE]; */ /* Truncated hash used for quick rejection of "distance cache" candidates. */ /* uint8_t tiny_hash[65536];*/ /* FN(Bank) banks[NUM_BANKS]; */ } HashForgetfulChain; static uint32_t* FN(Addr)(void* extra) { return (uint32_t*)extra; } static uint16_t* FN(Head)(void* extra) { return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]); } static uint8_t* FN(TinyHash)(void* extra) { return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]); } static FN(Bank)* FN(Banks)(void* extra) { return (FN(Bank)*)(extra); } static void FN(Initialize)( HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { self->common = common; self->extra[0] = common->extra[0]; self->extra[1] = common->extra[1]; self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4); } static void FN(Prepare)( HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, size_t input_size, const uint8_t* BROTLI_RESTRICT data) { uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); /* Partial preparation is 100 times slower (per socket). */ size_t partial_prepare_threshold = BUCKET_SIZE >> 6; if (one_shot && input_size <= partial_prepare_threshold) { size_t i; for (i = 0; i < input_size; ++i) { size_t bucket = FN(HashBytes)(&data[i]); /* See InitEmpty comment. */ addr[bucket] = 0xCCCCCCCC; head[bucket] = 0xCCCC; } } else { /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position processed by hasher never reaches 3GB + 64M; this makes all new chains to be terminated after the first node. */ memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE); memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE); } memset(tiny_hash, 0, sizeof(uint8_t) * 65536); memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx)); } static BROTLI_INLINE void FN(HashMemAllocInBytes)( const BrotliEncoderParams* params, BROTLI_BOOL one_shot, size_t input_size, size_t* alloc_size) { BROTLI_UNUSED(params); BROTLI_UNUSED(one_shot); BROTLI_UNUSED(input_size); alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE + sizeof(uint16_t) * BUCKET_SIZE + sizeof(uint8_t) * 65536; alloc_size[1] = sizeof(FN(Bank)) * NUM_BANKS; } /* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend node to corresponding chain; also update tiny_hash for current position. */ static BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); const size_t key = FN(HashBytes)(&data[ix & mask]); const size_t bank = key & (NUM_BANKS - 1); const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1); size_t delta = ix - addr[key]; tiny_hash[(uint16_t)ix] = (uint8_t)key; if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF; banks[bank].slots[idx].delta = (uint16_t)delta; banks[bank].slots[idx].next = head[key]; addr[key] = (uint32_t)ix; head[key] = (uint16_t)idx; } static BROTLI_INLINE void FN(StoreRange)( HashForgetfulChain* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix_start, const size_t ix_end) { size_t i; for (i = ix_start; i < ix_end; ++i) { FN(Store)(self, data, mask, i); } } static BROTLI_INLINE void FN(StitchToPreviousBlock)( HashForgetfulChain* BROTLI_RESTRICT self, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ring_buffer_mask) { if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { /* Prepare the hashes for three last bytes of the last write. These could not be calculated before, since they require knowledge of both the previous and the current block. */ FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3); FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2); FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1); } } static BROTLI_INLINE void FN(PrepareDistanceCache)( HashForgetfulChain* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { BROTLI_UNUSED(self); PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK); } /* Find a longest backward match of &data[cur_ix] up to the length of max_length and stores the position cur_ix in the hash table. REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache values; if this method is invoked repeatedly with the same distance cache values, it is enough to invoke FN(PrepareDistanceCache) once. Does not look for matches longer than max_length. Does not look for matches further away than max_backward. Writes the best match into |out|. |out|->score is updated only if a better match is found. */ static BROTLI_INLINE void FN(FindLongestMatch)( HashForgetfulChain* BROTLI_RESTRICT self, const BrotliEncoderDictionary* dictionary, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t max_backward, const size_t dictionary_distance, const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra[0]); FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); const size_t cur_ix_masked = cur_ix & ring_buffer_mask; /* Don't accept a short copy from far away. */ score_t min_score = out->score; score_t best_score = out->score; size_t best_len = out->len; size_t i; const size_t key = FN(HashBytes)(&data[cur_ix_masked]); const uint8_t tiny_hash = (uint8_t)(key); out->len = 0; out->len_code_delta = 0; /* Try last distance first. */ for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) { const size_t backward = (size_t)distance_cache[i]; size_t prev_ix = (cur_ix - backward); /* For distance code 0 we want to consider 2-byte matches. */ if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue; if (prev_ix >= cur_ix || backward > max_backward) { continue; } prev_ix &= ring_buffer_mask; { const size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 2) { score_t score = BackwardReferenceScoreUsingLastDistance(len); if (best_score < score) { if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); if (best_score < score) { best_score = score; best_len = len; out->len = best_len; out->distance = backward; out->score = best_score; } } } } } { const size_t bank = key & (NUM_BANKS - 1); size_t backward = 0; size_t hops = self->max_hops; size_t delta = cur_ix - addr[key]; size_t slot = head[key]; while (hops--) { size_t prev_ix; size_t last = slot; backward += delta; if (backward > max_backward || (CAPPED_CHAINS && !delta)) break; prev_ix = (cur_ix - backward) & ring_buffer_mask; slot = banks[bank].slots[last].next; delta = banks[bank].slots[last].delta; if (cur_ix_masked + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask || data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { continue; } { const size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 4) { /* Comparing for >= 3 does not change the semantics, but just saves for a few unnecessary binary logarithms in backward reference score, since we are not interested in such short matches. */ score_t score = BackwardReferenceScore(len, backward); if (best_score < score) { best_score = score; best_len = len; out->len = best_len; out->distance = backward; out->score = best_score; } } } } FN(Store)(self, data, ring_buffer_mask, cur_ix); } if (out->score == min_score) { SearchInStaticDictionary(dictionary, self->common, &data[cur_ix_masked], max_length, dictionary_distance, max_distance, out, BROTLI_FALSE); } } #undef BANK_SIZE #undef BUCKET_SIZE #undef CAPPED_CHAINS #undef HashForgetfulChain dvisvgm-3.5/libs/brotli/enc/hash_longest_match64_inc.h000066400000000000000000000236261501401750600230470ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN */ /* A (forgetful) hash table to the data seen by the compressor, to help create backward references to previous data. This is a hash map of fixed size (bucket_size_) to a ring buffer of fixed size (block_size_). The ring buffer contains the last block_size_ index positions of the given hash key in the compressed data. */ #define HashLongestMatch HASHER() static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; } static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; } /* HashBytes is the function that chooses the bucket to place the address in. */ static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data, uint64_t hash_mul) { const uint64_t h = BROTLI_UNALIGNED_LOAD64LE(data) * hash_mul; /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return (size_t)(h >> (64 - 15)); } typedef struct HashLongestMatch { /* Number of hash buckets. */ size_t bucket_size_; /* Only block_size_ newest backward references are kept, and the older are forgotten. */ size_t block_size_; /* Hash multiplier tuned to match length. */ uint64_t hash_mul_; /* Mask for accessing entries in a block (in a ring-buffer manner). */ uint32_t block_mask_; int block_bits_; int num_last_distances_to_check_; /* Shortcuts. */ HasherCommon* common_; /* --- Dynamic size members --- */ /* Number of entries in a particular bucket. */ uint16_t* num_; /* uint16_t[bucket_size]; */ /* Buckets containing block_size_ of backward references. */ uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */ } HashLongestMatch; static void FN(Initialize)( HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { self->common_ = common; BROTLI_UNUSED(params); self->hash_mul_ = kHashMul64 << (64 - 5 * 8); BROTLI_DCHECK(common->params.bucket_bits == 15); self->bucket_size_ = (size_t)1 << common->params.bucket_bits; self->block_bits_ = common->params.block_bits; self->block_size_ = (size_t)1 << common->params.block_bits; self->block_mask_ = (uint32_t)(self->block_size_ - 1); self->num_last_distances_to_check_ = common->params.num_last_distances_to_check; self->num_ = (uint16_t*)common->extra[0]; self->buckets_ = (uint32_t*)common->extra[1]; } static void FN(Prepare)( HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, size_t input_size, const uint8_t* BROTLI_RESTRICT data) { uint16_t* BROTLI_RESTRICT num = self->num_; /* Partial preparation is 100 times slower (per socket). */ size_t partial_prepare_threshold = self->bucket_size_ >> 6; if (one_shot && input_size <= partial_prepare_threshold) { size_t i; for (i = 0; i < input_size; ++i) { const size_t key = FN(HashBytes)(&data[i], self->hash_mul_); num[key] = 0; } } else { memset(num, 0, self->bucket_size_ * sizeof(num[0])); } } static BROTLI_INLINE void FN(HashMemAllocInBytes)( const BrotliEncoderParams* params, BROTLI_BOOL one_shot, size_t input_size, size_t* alloc_size) { size_t bucket_size = (size_t)1 << params->hasher.bucket_bits; size_t block_size = (size_t)1 << params->hasher.block_bits; BROTLI_UNUSED(one_shot); BROTLI_UNUSED(input_size); alloc_size[0] = sizeof(uint16_t) * bucket_size; alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size; } /* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and store the value of ix at that position. */ static BROTLI_INLINE void FN(Store)( HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { uint16_t* BROTLI_RESTRICT num = self->num_; uint32_t* BROTLI_RESTRICT buckets = self->buckets_; const size_t key = FN(HashBytes)(&data[ix & mask], self->hash_mul_); const size_t minor_ix = num[key] & self->block_mask_; const size_t offset = minor_ix + (key << self->block_bits_); ++num[key]; buckets[offset] = (uint32_t)ix; } static BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix_start, const size_t ix_end) { size_t i; for (i = ix_start; i < ix_end; ++i) { FN(Store)(self, data, mask, i); } } static BROTLI_INLINE void FN(StitchToPreviousBlock)( HashLongestMatch* BROTLI_RESTRICT self, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask) { if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { /* Prepare the hashes for three last bytes of the last write. These could not be calculated before, since they require knowledge of both the previous and the current block. */ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); } } static BROTLI_INLINE void FN(PrepareDistanceCache)( HashLongestMatch* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_); } /* Find a longest backward match of &data[cur_ix] up to the length of max_length and stores the position cur_ix in the hash table. REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache values; if this method is invoked repeatedly with the same distance cache values, it is enough to invoke FN(PrepareDistanceCache) once. Does not look for matches longer than max_length. Does not look for matches further away than max_backward. Writes the best match into |out|. |out|->score is updated only if a better match is found. */ static BROTLI_INLINE void FN(FindLongestMatch)( HashLongestMatch* BROTLI_RESTRICT self, const BrotliEncoderDictionary* dictionary, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t max_backward, const size_t dictionary_distance, const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { uint16_t* BROTLI_RESTRICT num = self->num_; uint32_t* BROTLI_RESTRICT buckets = self->buckets_; const size_t cur_ix_masked = cur_ix & ring_buffer_mask; /* Don't accept a short copy from far away. */ score_t min_score = out->score; score_t best_score = out->score; size_t best_len = out->len; size_t i; out->len = 0; out->len_code_delta = 0; /* Try last distance first. */ for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) { const size_t backward = (size_t)distance_cache[i]; size_t prev_ix = (size_t)(cur_ix - backward); if (prev_ix >= cur_ix) { continue; } if (BROTLI_PREDICT_FALSE(backward > max_backward)) { continue; } prev_ix &= ring_buffer_mask; if (cur_ix_masked + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask || data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { continue; } { const size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 3 || (len == 2 && i < 2)) { /* Comparing for >= 2 does not change the semantics, but just saves for a few unnecessary binary logarithms in backward reference score, since we are not interested in such short matches. */ score_t score = BackwardReferenceScoreUsingLastDistance(len); if (best_score < score) { if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); if (best_score < score) { best_score = score; best_len = len; out->len = best_len; out->distance = backward; out->score = best_score; } } } } } { const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_); uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_]; const size_t down = (num[key] > self->block_size_) ? (num[key] - self->block_size_) : 0u; const uint32_t first4 = BrotliUnalignedRead32(data + cur_ix_masked); const size_t max_length_m4 = max_length - 4; i = num[key]; for (; i > down;) { size_t prev_ix = bucket[--i & self->block_mask_]; uint32_t current4; const size_t backward = cur_ix - prev_ix; if (BROTLI_PREDICT_FALSE(backward > max_backward)) { break; } prev_ix &= ring_buffer_mask; if (cur_ix_masked + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask || data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { continue; } current4 = BrotliUnalignedRead32(data + prev_ix); if (first4 != current4) continue; { const size_t len = FindMatchLengthWithLimit(&data[prev_ix + 4], &data[cur_ix_masked + 4], max_length_m4) + 4; const score_t score = BackwardReferenceScore(len, backward); if (best_score < score) { best_score = score; best_len = len; out->len = best_len; out->distance = backward; out->score = best_score; } } } bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix; ++num[key]; } if (min_score == out->score) { SearchInStaticDictionary(dictionary, self->common_, &data[cur_ix_masked], max_length, dictionary_distance, max_distance, out, BROTLI_FALSE); } } #undef HashLongestMatch dvisvgm-3.5/libs/brotli/enc/hash_longest_match_inc.h000066400000000000000000000234071501401750600226720ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN */ /* A (forgetful) hash table to the data seen by the compressor, to help create backward references to previous data. This is a hash map of fixed size (bucket_size_) to a ring buffer of fixed size (block_size_). The ring buffer contains the last block_size_ index positions of the given hash key in the compressed data. */ #define HashLongestMatch HASHER() static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } /* HashBytes is the function that chooses the bucket to place the address in. */ static uint32_t FN(HashBytes)( const uint8_t* BROTLI_RESTRICT data, const int shift) { uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return (uint32_t)(h >> shift); } typedef struct HashLongestMatch { /* Number of hash buckets. */ size_t bucket_size_; /* Only block_size_ newest backward references are kept, and the older are forgotten. */ size_t block_size_; /* Left-shift for computing hash bucket index from hash value. */ int hash_shift_; /* Mask for accessing entries in a block (in a ring-buffer manner). */ uint32_t block_mask_; int block_bits_; int num_last_distances_to_check_; /* Shortcuts. */ HasherCommon* common_; /* --- Dynamic size members --- */ /* Number of entries in a particular bucket. */ uint16_t* num_; /* uint16_t[bucket_size]; */ /* Buckets containing block_size_ of backward references. */ uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */ } HashLongestMatch; static void FN(Initialize)( HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { self->common_ = common; BROTLI_UNUSED(params); self->hash_shift_ = 32 - common->params.bucket_bits; self->bucket_size_ = (size_t)1 << common->params.bucket_bits; self->block_size_ = (size_t)1 << common->params.block_bits; self->block_mask_ = (uint32_t)(self->block_size_ - 1); self->num_ = (uint16_t*)common->extra[0]; self->buckets_ = (uint32_t*)common->extra[1]; self->block_bits_ = common->params.block_bits; self->num_last_distances_to_check_ = common->params.num_last_distances_to_check; } static void FN(Prepare)( HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, size_t input_size, const uint8_t* BROTLI_RESTRICT data) { uint16_t* BROTLI_RESTRICT num = self->num_; /* Partial preparation is 100 times slower (per socket). */ size_t partial_prepare_threshold = self->bucket_size_ >> 6; if (one_shot && input_size <= partial_prepare_threshold) { size_t i; for (i = 0; i < input_size; ++i) { const uint32_t key = FN(HashBytes)(&data[i], self->hash_shift_); num[key] = 0; } } else { memset(num, 0, self->bucket_size_ * sizeof(num[0])); } } static BROTLI_INLINE void FN(HashMemAllocInBytes)( const BrotliEncoderParams* params, BROTLI_BOOL one_shot, size_t input_size, size_t* alloc_size) { size_t bucket_size = (size_t)1 << params->hasher.bucket_bits; size_t block_size = (size_t)1 << params->hasher.block_bits; BROTLI_UNUSED(one_shot); BROTLI_UNUSED(input_size); alloc_size[0] = sizeof(uint16_t) * bucket_size; alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size; } /* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and store the value of ix at that position. */ static BROTLI_INLINE void FN(Store)( HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_shift_); const size_t minor_ix = self->num_[key] & self->block_mask_; const size_t offset = minor_ix + (key << self->block_bits_); self->buckets_[offset] = (uint32_t)ix; ++self->num_[key]; } static BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix_start, const size_t ix_end) { size_t i; for (i = ix_start; i < ix_end; ++i) { FN(Store)(self, data, mask, i); } } static BROTLI_INLINE void FN(StitchToPreviousBlock)( HashLongestMatch* BROTLI_RESTRICT self, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask) { if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { /* Prepare the hashes for three last bytes of the last write. These could not be calculated before, since they require knowledge of both the previous and the current block. */ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); } } static BROTLI_INLINE void FN(PrepareDistanceCache)( HashLongestMatch* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_); } /* Find a longest backward match of &data[cur_ix] up to the length of max_length and stores the position cur_ix in the hash table. REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache values; if this method is invoked repeatedly with the same distance cache values, it is enough to invoke FN(PrepareDistanceCache) once. Does not look for matches longer than max_length. Does not look for matches further away than max_backward. Writes the best match into |out|. |out|->score is updated only if a better match is found. */ static BROTLI_INLINE void FN(FindLongestMatch)( HashLongestMatch* BROTLI_RESTRICT self, const BrotliEncoderDictionary* dictionary, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t max_backward, const size_t dictionary_distance, const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { uint16_t* BROTLI_RESTRICT num = self->num_; uint32_t* BROTLI_RESTRICT buckets = self->buckets_; const size_t cur_ix_masked = cur_ix & ring_buffer_mask; /* Don't accept a short copy from far away. */ score_t min_score = out->score; score_t best_score = out->score; size_t best_len = out->len; size_t i; out->len = 0; out->len_code_delta = 0; /* Try last distance first. */ for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) { const size_t backward = (size_t)distance_cache[i]; size_t prev_ix = (size_t)(cur_ix - backward); if (prev_ix >= cur_ix) { continue; } if (BROTLI_PREDICT_FALSE(backward > max_backward)) { continue; } prev_ix &= ring_buffer_mask; if (cur_ix_masked + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask || data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { continue; } { const size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 3 || (len == 2 && i < 2)) { /* Comparing for >= 2 does not change the semantics, but just saves for a few unnecessary binary logarithms in backward reference score, since we are not interested in such short matches. */ score_t score = BackwardReferenceScoreUsingLastDistance(len); if (best_score < score) { if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); if (best_score < score) { best_score = score; best_len = len; out->len = best_len; out->distance = backward; out->score = best_score; } } } } } { const uint32_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_); uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_]; const size_t down = (num[key] > self->block_size_) ? (num[key] - self->block_size_) : 0u; for (i = num[key]; i > down;) { size_t prev_ix = bucket[--i & self->block_mask_]; const size_t backward = cur_ix - prev_ix; if (BROTLI_PREDICT_FALSE(backward > max_backward)) { break; } prev_ix &= ring_buffer_mask; if (cur_ix_masked + best_len > ring_buffer_mask || prev_ix + best_len > ring_buffer_mask || data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { continue; } { const size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 4) { /* Comparing for >= 3 does not change the semantics, but just saves for a few unnecessary binary logarithms in backward reference score, since we are not interested in such short matches. */ score_t score = BackwardReferenceScore(len, backward); if (best_score < score) { best_score = score; best_len = len; out->len = best_len; out->distance = backward; out->score = best_score; } } } } bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix; ++num[key]; } if (min_score == out->score) { SearchInStaticDictionary(dictionary, self->common_, &data[cur_ix_masked], max_length, dictionary_distance, max_distance, out, BROTLI_FALSE); } } #undef HashLongestMatch dvisvgm-3.5/libs/brotli/enc/hash_longest_match_quickly_inc.h000066400000000000000000000221741501401750600244330ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN, USE_DICTIONARY */ #define HashLongestMatchQuickly HASHER() #define BUCKET_SIZE (1 << BUCKET_BITS) #define BUCKET_MASK (BUCKET_SIZE - 1) #define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS) #define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3) static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; } static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; } /* HashBytes is the function that chooses the bucket to place the address in. The HashLongestMatch and HashLongestMatchQuickly classes have separate, different implementations of hashing. */ static uint32_t FN(HashBytes)(const uint8_t* data) { const uint64_t h = ((BROTLI_UNALIGNED_LOAD64LE(data) << (64 - 8 * HASH_LEN)) * kHashMul64); /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return (uint32_t)(h >> (64 - BUCKET_BITS)); } /* A (forgetful) hash table to the data seen by the compressor, to help create backward references to previous data. This is a hash map of fixed size (BUCKET_SIZE). */ typedef struct HashLongestMatchQuickly { /* Shortcuts. */ HasherCommon* common; /* --- Dynamic size members --- */ uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */ } HashLongestMatchQuickly; static void FN(Initialize)( HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { self->common = common; BROTLI_UNUSED(params); self->buckets_ = (uint32_t*)common->extra[0]; } static void FN(Prepare)( HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, size_t input_size, const uint8_t* BROTLI_RESTRICT data) { uint32_t* BROTLI_RESTRICT buckets = self->buckets_; /* Partial preparation is 100 times slower (per socket). */ size_t partial_prepare_threshold = BUCKET_SIZE >> 5; if (one_shot && input_size <= partial_prepare_threshold) { size_t i; for (i = 0; i < input_size; ++i) { const uint32_t key = FN(HashBytes)(&data[i]); if (BUCKET_SWEEP == 1) { buckets[key] = 0; } else { uint32_t j; for (j = 0; j < BUCKET_SWEEP; ++j) { buckets[(key + (j << 3)) & BUCKET_MASK] = 0; } } } } else { /* It is not strictly necessary to fill this buffer here, but not filling will make the results of the compression stochastic (but correct). This is because random data would cause the system to find accidentally good backward references here and there. */ memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE); } } static BROTLI_INLINE void FN(HashMemAllocInBytes)( const BrotliEncoderParams* params, BROTLI_BOOL one_shot, size_t input_size, size_t* alloc_size) { BROTLI_UNUSED(params); BROTLI_UNUSED(one_shot); BROTLI_UNUSED(input_size); alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE; } /* Look at 5 bytes at &data[ix & mask]. Compute a hash from these, and store the value somewhere within [ix .. ix+3]. */ static BROTLI_INLINE void FN(Store)( HashLongestMatchQuickly* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { const uint32_t key = FN(HashBytes)(&data[ix & mask]); if (BUCKET_SWEEP == 1) { self->buckets_[key] = (uint32_t)ix; } else { /* Wiggle the value with the bucket sweep range. */ const uint32_t off = ix & BUCKET_SWEEP_MASK; self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix; } } static BROTLI_INLINE void FN(StoreRange)( HashLongestMatchQuickly* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix_start, const size_t ix_end) { size_t i; for (i = ix_start; i < ix_end; ++i) { FN(Store)(self, data, mask, i); } } static BROTLI_INLINE void FN(StitchToPreviousBlock)( HashLongestMatchQuickly* BROTLI_RESTRICT self, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask) { if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { /* Prepare the hashes for three last bytes of the last write. These could not be calculated before, since they require knowledge of both the previous and the current block. */ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); } } static BROTLI_INLINE void FN(PrepareDistanceCache)( HashLongestMatchQuickly* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { BROTLI_UNUSED(self); BROTLI_UNUSED(distance_cache); } /* Find a longest backward match of &data[cur_ix & ring_buffer_mask] up to the length of max_length and stores the position cur_ix in the hash table. Does not look for matches longer than max_length. Does not look for matches further away than max_backward. Writes the best match into |out|. |out|->score is updated only if a better match is found. */ static BROTLI_INLINE void FN(FindLongestMatch)( HashLongestMatchQuickly* BROTLI_RESTRICT self, const BrotliEncoderDictionary* dictionary, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t max_backward, const size_t dictionary_distance, const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { uint32_t* BROTLI_RESTRICT buckets = self->buckets_; const size_t best_len_in = out->len; const size_t cur_ix_masked = cur_ix & ring_buffer_mask; int compare_char = data[cur_ix_masked + best_len_in]; size_t key = FN(HashBytes)(&data[cur_ix_masked]); size_t key_out; score_t min_score = out->score; score_t best_score = out->score; size_t best_len = best_len_in; size_t cached_backward = (size_t)distance_cache[0]; size_t prev_ix = cur_ix - cached_backward; out->len_code_delta = 0; if (prev_ix < cur_ix) { prev_ix &= (uint32_t)ring_buffer_mask; if (compare_char == data[prev_ix + best_len]) { const size_t len = FindMatchLengthWithLimit( &data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 4) { const score_t score = BackwardReferenceScoreUsingLastDistance(len); if (best_score < score) { out->len = len; out->distance = cached_backward; out->score = score; if (BUCKET_SWEEP == 1) { buckets[key] = (uint32_t)cur_ix; return; } else { best_len = len; best_score = score; compare_char = data[cur_ix_masked + len]; } } } } } if (BUCKET_SWEEP == 1) { size_t backward; size_t len; /* Only one to look for, don't bother to prepare for a loop. */ prev_ix = buckets[key]; buckets[key] = (uint32_t)cur_ix; backward = cur_ix - prev_ix; prev_ix &= (uint32_t)ring_buffer_mask; if (compare_char != data[prev_ix + best_len_in]) { return; } if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { return; } len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 4) { const score_t score = BackwardReferenceScore(len, backward); if (best_score < score) { out->len = len; out->distance = backward; out->score = score; return; } } } else { size_t keys[BUCKET_SWEEP]; size_t i; for (i = 0; i < BUCKET_SWEEP; ++i) { keys[i] = (key + (i << 3)) & BUCKET_MASK; } key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3]; for (i = 0; i < BUCKET_SWEEP; ++i) { size_t len; size_t backward; prev_ix = buckets[keys[i]]; backward = cur_ix - prev_ix; prev_ix &= (uint32_t)ring_buffer_mask; if (compare_char != data[prev_ix + best_len]) { continue; } if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { continue; } len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len >= 4) { const score_t score = BackwardReferenceScore(len, backward); if (best_score < score) { best_len = len; out->len = len; compare_char = data[cur_ix_masked + len]; best_score = score; out->score = score; out->distance = backward; } } } } if (USE_DICTIONARY && min_score == out->score) { SearchInStaticDictionary(dictionary, self->common, &data[cur_ix_masked], max_length, dictionary_distance, max_distance, out, BROTLI_TRUE); } if (BUCKET_SWEEP != 1) { buckets[key_out] = (uint32_t)cur_ix; } } #undef BUCKET_SWEEP_MASK #undef BUCKET_SWEEP #undef BUCKET_MASK #undef BUCKET_SIZE #undef HashLongestMatchQuickly dvisvgm-3.5/libs/brotli/enc/hash_rolling_inc.h000066400000000000000000000160721501401750600215110ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2018 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN, JUMP, NUMBUCKETS, MASK, CHUNKLEN */ /* NUMBUCKETS / (MASK + 1) = probability of storing and using hash code. */ /* JUMP = skip bytes for speedup */ /* Rolling hash for long distance long string matches. Stores one position per bucket, bucket key is computed over a long region. */ #define HashRolling HASHER() static const uint32_t FN(kRollingHashMul32) = 69069; static const uint32_t FN(kInvalidPos) = 0xffffffff; /* This hasher uses a longer forward length, but returning a higher value here will hurt compression by the main hasher when combined with a composite hasher. The hasher tests for forward itself instead. */ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } /* Computes a code from a single byte. A lookup table of 256 values could be used, but simply adding 1 works about as good. */ static uint32_t FN(HashByte)(uint8_t byte) { return (uint32_t)byte + 1u; } static uint32_t FN(HashRollingFunctionInitial)(uint32_t state, uint8_t add, uint32_t factor) { return (uint32_t)(factor * state + FN(HashByte)(add)); } static uint32_t FN(HashRollingFunction)(uint32_t state, uint8_t add, uint8_t rem, uint32_t factor, uint32_t factor_remove) { return (uint32_t)(factor * state + FN(HashByte)(add) - factor_remove * FN(HashByte)(rem)); } typedef struct HashRolling { uint32_t state; uint32_t* table; size_t next_ix; uint32_t chunk_len; uint32_t factor; uint32_t factor_remove; } HashRolling; static void FN(Initialize)( HasherCommon* common, HashRolling* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { size_t i; self->state = 0; self->next_ix = 0; self->factor = FN(kRollingHashMul32); /* Compute the factor of the oldest byte to remove: factor**steps modulo 0xffffffff (the multiplications rely on 32-bit overflow) */ self->factor_remove = 1; for (i = 0; i < CHUNKLEN; i += JUMP) { self->factor_remove *= self->factor; } self->table = (uint32_t*)common->extra[0]; for (i = 0; i < NUMBUCKETS; i++) { self->table[i] = FN(kInvalidPos); } BROTLI_UNUSED(params); } static void FN(Prepare)(HashRolling* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, size_t input_size, const uint8_t* BROTLI_RESTRICT data) { size_t i; /* Too small size, cannot use this hasher. */ if (input_size < CHUNKLEN) return; self->state = 0; for (i = 0; i < CHUNKLEN; i += JUMP) { self->state = FN(HashRollingFunctionInitial)( self->state, data[i], self->factor); } BROTLI_UNUSED(one_shot); } static BROTLI_INLINE void FN(HashMemAllocInBytes)( const BrotliEncoderParams* params, BROTLI_BOOL one_shot, size_t input_size, size_t* alloc_size) { BROTLI_UNUSED(params); BROTLI_UNUSED(one_shot); BROTLI_UNUSED(input_size); alloc_size[0] = NUMBUCKETS * sizeof(uint32_t); } static BROTLI_INLINE void FN(Store)(HashRolling* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { BROTLI_UNUSED(self); BROTLI_UNUSED(data); BROTLI_UNUSED(mask); BROTLI_UNUSED(ix); } static BROTLI_INLINE void FN(StoreRange)(HashRolling* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix_start, const size_t ix_end) { BROTLI_UNUSED(self); BROTLI_UNUSED(data); BROTLI_UNUSED(mask); BROTLI_UNUSED(ix_start); BROTLI_UNUSED(ix_end); } static BROTLI_INLINE void FN(StitchToPreviousBlock)( HashRolling* BROTLI_RESTRICT self, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ring_buffer_mask) { /* In this case we must re-initialize the hasher from scratch from the current position. */ size_t position_masked; size_t available = num_bytes; if ((position & (JUMP - 1)) != 0) { size_t diff = JUMP - (position & (JUMP - 1)); available = (diff > available) ? 0 : (available - diff); position += diff; } position_masked = position & ring_buffer_mask; /* wrapping around ringbuffer not handled. */ if (available > ring_buffer_mask - position_masked) { available = ring_buffer_mask - position_masked; } FN(Prepare)(self, BROTLI_FALSE, available, ringbuffer + (position & ring_buffer_mask)); self->next_ix = position; BROTLI_UNUSED(num_bytes); } static BROTLI_INLINE void FN(PrepareDistanceCache)( HashRolling* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { BROTLI_UNUSED(self); BROTLI_UNUSED(distance_cache); } static BROTLI_INLINE void FN(FindLongestMatch)( HashRolling* BROTLI_RESTRICT self, const BrotliEncoderDictionary* dictionary, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, const size_t max_length, const size_t max_backward, const size_t dictionary_distance, const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { const size_t cur_ix_masked = cur_ix & ring_buffer_mask; size_t pos; if ((cur_ix & (JUMP - 1)) != 0) return; /* Not enough lookahead */ if (max_length < CHUNKLEN) return; for (pos = self->next_ix; pos <= cur_ix; pos += JUMP) { uint32_t code = self->state & MASK; uint8_t rem = data[pos & ring_buffer_mask]; uint8_t add = data[(pos + CHUNKLEN) & ring_buffer_mask]; size_t found_ix = FN(kInvalidPos); self->state = FN(HashRollingFunction)( self->state, add, rem, self->factor, self->factor_remove); if (code < NUMBUCKETS) { found_ix = self->table[code]; self->table[code] = (uint32_t)pos; if (pos == cur_ix && found_ix != FN(kInvalidPos)) { /* The cast to 32-bit makes backward distances up to 4GB work even if cur_ix is above 4GB, despite using 32-bit values in the table. */ size_t backward = (uint32_t)(cur_ix - found_ix); if (backward <= max_backward) { const size_t found_ix_masked = found_ix & ring_buffer_mask; const size_t len = FindMatchLengthWithLimit(&data[found_ix_masked], &data[cur_ix_masked], max_length); if (len >= 4 && len > out->len) { score_t score = BackwardReferenceScore(len, backward); if (score > out->score) { out->len = len; out->distance = backward; out->score = score; out->len_code_delta = 0; } } } } } } self->next_ix = cur_ix + JUMP; /* NOTE: this hasher does not search in the dictionary. It is used as backup-hasher, the main hasher already searches in it. */ BROTLI_UNUSED(dictionary); BROTLI_UNUSED(distance_cache); BROTLI_UNUSED(dictionary_distance); BROTLI_UNUSED(max_distance); } #undef HashRolling dvisvgm-3.5/libs/brotli/enc/hash_to_binary_tree_inc.h000066400000000000000000000314311501401750600230440ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN, BUCKET_BITS, MAX_TREE_COMP_LENGTH, MAX_TREE_SEARCH_DEPTH */ /* A (forgetful) hash table where each hash bucket contains a binary tree of sequences whose first 4 bytes share the same hash code. Each sequence is MAX_TREE_COMP_LENGTH long and is identified by its starting position in the input data. The binary tree is sorted by the lexicographic order of the sequences, and it is also a max-heap with respect to the starting positions. */ #define HashToBinaryTree HASHER() #define BUCKET_SIZE (1 << BUCKET_BITS) static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return MAX_TREE_COMP_LENGTH; } static uint32_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) { uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return h >> (32 - BUCKET_BITS); } typedef struct HashToBinaryTree { /* The window size minus 1 */ size_t window_mask_; /* Hash table that maps the 4-byte hashes of the sequence to the last position where this hash was found, which is the root of the binary tree of sequences that share this hash bucket. */ uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */ /* A position used to mark a non-existent sequence, i.e. a tree is empty if its root is at invalid_pos_ and a node is a leaf if both its children are at invalid_pos_. */ uint32_t invalid_pos_; /* --- Dynamic size members --- */ /* The union of the binary trees of each hash bucket. The root of the tree corresponding to a hash is a sequence starting at buckets_[hash] and the left and right children of a sequence starting at pos are forest_[2 * pos] and forest_[2 * pos + 1]. */ uint32_t* forest_; /* uint32_t[2 * num_nodes] */ } HashToBinaryTree; static void FN(Initialize)( HasherCommon* common, HashToBinaryTree* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { self->buckets_ = (uint32_t*)common->extra[0]; self->forest_ = (uint32_t*)common->extra[1]; self->window_mask_ = (1u << params->lgwin) - 1u; self->invalid_pos_ = (uint32_t)(0 - self->window_mask_); } static void FN(Prepare) (HashToBinaryTree* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, size_t input_size, const uint8_t* BROTLI_RESTRICT data) { uint32_t invalid_pos = self->invalid_pos_; uint32_t i; uint32_t* BROTLI_RESTRICT buckets = self->buckets_; BROTLI_UNUSED(data); BROTLI_UNUSED(one_shot); BROTLI_UNUSED(input_size); for (i = 0; i < BUCKET_SIZE; i++) { buckets[i] = invalid_pos; } } static BROTLI_INLINE void FN(HashMemAllocInBytes)( const BrotliEncoderParams* params, BROTLI_BOOL one_shot, size_t input_size, size_t* alloc_size) { size_t num_nodes = (size_t)1 << params->lgwin; if (one_shot && input_size < num_nodes) { num_nodes = input_size; } alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE; alloc_size[1] = 2 * sizeof(uint32_t) * num_nodes; } static BROTLI_INLINE size_t FN(LeftChildIndex)( HashToBinaryTree* BROTLI_RESTRICT self, const size_t pos) { return 2 * (pos & self->window_mask_); } static BROTLI_INLINE size_t FN(RightChildIndex)( HashToBinaryTree* BROTLI_RESTRICT self, const size_t pos) { return 2 * (pos & self->window_mask_) + 1; } /* Stores the hash of the next 4 bytes and in a single tree-traversal, the hash bucket's binary tree is searched for matches and is re-rooted at the current position. If less than MAX_TREE_COMP_LENGTH data is available, the hash bucket of the current position is searched for matches, but the state of the hash table is not changed, since we can not know the final sorting order of the current (incomplete) sequence. This function must be called with increasing cur_ix positions. */ static BROTLI_INLINE BackwardMatch* FN(StoreAndFindMatches)( HashToBinaryTree* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t cur_ix, const size_t ring_buffer_mask, const size_t max_length, const size_t max_backward, size_t* const BROTLI_RESTRICT best_len, BackwardMatch* BROTLI_RESTRICT matches) { const size_t cur_ix_masked = cur_ix & ring_buffer_mask; const size_t max_comp_len = BROTLI_MIN(size_t, max_length, MAX_TREE_COMP_LENGTH); const BROTLI_BOOL should_reroot_tree = TO_BROTLI_BOOL(max_length >= MAX_TREE_COMP_LENGTH); const uint32_t key = FN(HashBytes)(&data[cur_ix_masked]); uint32_t* BROTLI_RESTRICT buckets = self->buckets_; uint32_t* BROTLI_RESTRICT forest = self->forest_; size_t prev_ix = buckets[key]; /* The forest index of the rightmost node of the left subtree of the new root, updated as we traverse and re-root the tree of the hash bucket. */ size_t node_left = FN(LeftChildIndex)(self, cur_ix); /* The forest index of the leftmost node of the right subtree of the new root, updated as we traverse and re-root the tree of the hash bucket. */ size_t node_right = FN(RightChildIndex)(self, cur_ix); /* The match length of the rightmost node of the left subtree of the new root, updated as we traverse and re-root the tree of the hash bucket. */ size_t best_len_left = 0; /* The match length of the leftmost node of the right subtree of the new root, updated as we traverse and re-root the tree of the hash bucket. */ size_t best_len_right = 0; size_t depth_remaining; if (should_reroot_tree) { buckets[key] = (uint32_t)cur_ix; } for (depth_remaining = MAX_TREE_SEARCH_DEPTH; ; --depth_remaining) { const size_t backward = cur_ix - prev_ix; const size_t prev_ix_masked = prev_ix & ring_buffer_mask; if (backward == 0 || backward > max_backward || depth_remaining == 0) { if (should_reroot_tree) { forest[node_left] = self->invalid_pos_; forest[node_right] = self->invalid_pos_; } break; } { const size_t cur_len = BROTLI_MIN(size_t, best_len_left, best_len_right); size_t len; BROTLI_DCHECK(cur_len <= MAX_TREE_COMP_LENGTH); len = cur_len + FindMatchLengthWithLimit(&data[cur_ix_masked + cur_len], &data[prev_ix_masked + cur_len], max_length - cur_len); BROTLI_DCHECK( 0 == memcmp(&data[cur_ix_masked], &data[prev_ix_masked], len)); if (matches && len > *best_len) { *best_len = len; InitBackwardMatch(matches++, backward, len); } if (len >= max_comp_len) { if (should_reroot_tree) { forest[node_left] = forest[FN(LeftChildIndex)(self, prev_ix)]; forest[node_right] = forest[FN(RightChildIndex)(self, prev_ix)]; } break; } if (data[cur_ix_masked + len] > data[prev_ix_masked + len]) { best_len_left = len; if (should_reroot_tree) { forest[node_left] = (uint32_t)prev_ix; } node_left = FN(RightChildIndex)(self, prev_ix); prev_ix = forest[node_left]; } else { best_len_right = len; if (should_reroot_tree) { forest[node_right] = (uint32_t)prev_ix; } node_right = FN(LeftChildIndex)(self, prev_ix); prev_ix = forest[node_right]; } } } return matches; } /* Finds all backward matches of &data[cur_ix & ring_buffer_mask] up to the length of max_length and stores the position cur_ix in the hash table. Sets *num_matches to the number of matches found, and stores the found matches in matches[0] to matches[*num_matches - 1]. The matches will be sorted by strictly increasing length and (non-strictly) increasing distance. */ static BROTLI_INLINE size_t FN(FindAllMatches)( HashToBinaryTree* BROTLI_RESTRICT self, const BrotliEncoderDictionary* dictionary, const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, const size_t cur_ix, const size_t max_length, const size_t max_backward, const size_t dictionary_distance, const BrotliEncoderParams* params, BackwardMatch* matches) { BackwardMatch* const orig_matches = matches; const size_t cur_ix_masked = cur_ix & ring_buffer_mask; size_t best_len = 1; const size_t short_match_max_backward = params->quality != HQ_ZOPFLIFICATION_QUALITY ? 16 : 64; size_t stop = cur_ix - short_match_max_backward; uint32_t dict_matches[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1]; size_t i; if (cur_ix < short_match_max_backward) { stop = 0; } for (i = cur_ix - 1; i > stop && best_len <= 2; --i) { size_t prev_ix = i; const size_t backward = cur_ix - prev_ix; if (BROTLI_PREDICT_FALSE(backward > max_backward)) { break; } prev_ix &= ring_buffer_mask; if (data[cur_ix_masked] != data[prev_ix] || data[cur_ix_masked + 1] != data[prev_ix + 1]) { continue; } { const size_t len = FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], max_length); if (len > best_len) { best_len = len; InitBackwardMatch(matches++, backward, len); } } } if (best_len < max_length) { matches = FN(StoreAndFindMatches)(self, data, cur_ix, ring_buffer_mask, max_length, max_backward, &best_len, matches); } for (i = 0; i <= BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN; ++i) { dict_matches[i] = kInvalidMatch; } { size_t minlen = BROTLI_MAX(size_t, 4, best_len + 1); if (BrotliFindAllStaticDictionaryMatches(dictionary, &data[cur_ix_masked], minlen, max_length, &dict_matches[0])) { size_t maxlen = BROTLI_MIN( size_t, BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN, max_length); size_t l; for (l = minlen; l <= maxlen; ++l) { uint32_t dict_id = dict_matches[l]; if (dict_id < kInvalidMatch) { size_t distance = dictionary_distance + (dict_id >> 5) + 1; if (distance <= params->dist.max_distance) { InitDictionaryBackwardMatch(matches++, distance, l, dict_id & 31); } } } } } return (size_t)(matches - orig_matches); } /* Stores the hash of the next 4 bytes and re-roots the binary tree at the current sequence, without returning any matches. REQUIRES: ix + MAX_TREE_COMP_LENGTH <= end-of-current-block */ static BROTLI_INLINE void FN(Store)(HashToBinaryTree* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { /* Maximum distance is window size - 16, see section 9.1. of the spec. */ const size_t max_backward = self->window_mask_ - BROTLI_WINDOW_GAP + 1; FN(StoreAndFindMatches)(self, data, ix, mask, MAX_TREE_COMP_LENGTH, max_backward, NULL, NULL); } static BROTLI_INLINE void FN(StoreRange)(HashToBinaryTree* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix_start, const size_t ix_end) { size_t i = ix_start; size_t j = ix_start; if (ix_start + 63 <= ix_end) { i = ix_end - 63; } if (ix_start + 512 <= i) { for (; j < i; j += 8) { FN(Store)(self, data, mask, j); } } for (; i < ix_end; ++i) { FN(Store)(self, data, mask, i); } } static BROTLI_INLINE void FN(StitchToPreviousBlock)( HashToBinaryTree* BROTLI_RESTRICT self, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask) { if (num_bytes >= FN(HashTypeLength)() - 1 && position >= MAX_TREE_COMP_LENGTH) { /* Store the last `MAX_TREE_COMP_LENGTH - 1` positions in the hasher. These could not be calculated before, since they require knowledge of both the previous and the current block. */ const size_t i_start = position - MAX_TREE_COMP_LENGTH + 1; const size_t i_end = BROTLI_MIN(size_t, position, i_start + num_bytes); size_t i; for (i = i_start; i < i_end; ++i) { /* Maximum distance is window size - 16, see section 9.1. of the spec. Furthermore, we have to make sure that we don't look further back from the start of the next block than the window size, otherwise we could access already overwritten areas of the ring-buffer. */ const size_t max_backward = self->window_mask_ - BROTLI_MAX(size_t, BROTLI_WINDOW_GAP - 1, position - i); /* We know that i + MAX_TREE_COMP_LENGTH <= position + num_bytes, i.e. the end of the current block and that we have at least MAX_TREE_COMP_LENGTH tail in the ring-buffer. */ FN(StoreAndFindMatches)(self, ringbuffer, i, ringbuffer_mask, MAX_TREE_COMP_LENGTH, max_backward, NULL, NULL); } } } #undef BUCKET_SIZE #undef HashToBinaryTree dvisvgm-3.5/libs/brotli/enc/histogram.c000066400000000000000000000062351501401750600201770ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Build per-context histograms of literals, commands and distance codes. */ #include "histogram.h" #include "../common/context.h" #include "block_splitter.h" #include "command.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct BlockSplitIterator { const BlockSplit* split_; /* Not owned. */ size_t idx_; size_t type_; size_t length_; } BlockSplitIterator; static void InitBlockSplitIterator(BlockSplitIterator* self, const BlockSplit* split) { self->split_ = split; self->idx_ = 0; self->type_ = 0; self->length_ = split->lengths ? split->lengths[0] : 0; } static void BlockSplitIteratorNext(BlockSplitIterator* self) { if (self->length_ == 0) { ++self->idx_; self->type_ = self->split_->types[self->idx_]; self->length_ = self->split_->lengths[self->idx_]; } --self->length_; } void BrotliBuildHistogramsWithContext( const Command* cmds, const size_t num_commands, const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split, const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, const ContextType* context_modes, HistogramLiteral* literal_histograms, HistogramCommand* insert_and_copy_histograms, HistogramDistance* copy_dist_histograms) { size_t pos = start_pos; BlockSplitIterator literal_it; BlockSplitIterator insert_and_copy_it; BlockSplitIterator dist_it; size_t i; InitBlockSplitIterator(&literal_it, literal_split); InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split); InitBlockSplitIterator(&dist_it, dist_split); for (i = 0; i < num_commands; ++i) { const Command* cmd = &cmds[i]; size_t j; BlockSplitIteratorNext(&insert_and_copy_it); HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_], cmd->cmd_prefix_); /* TODO(eustas): unwrap iterator blocks. */ for (j = cmd->insert_len_; j != 0; --j) { size_t context; BlockSplitIteratorNext(&literal_it); context = literal_it.type_; if (context_modes) { ContextLut lut = BROTLI_CONTEXT_LUT(context_modes[context]); context = (context << BROTLI_LITERAL_CONTEXT_BITS) + BROTLI_CONTEXT(prev_byte, prev_byte2, lut); } HistogramAddLiteral(&literal_histograms[context], ringbuffer[pos & mask]); prev_byte2 = prev_byte; prev_byte = ringbuffer[pos & mask]; ++pos; } pos += CommandCopyLen(cmd); if (CommandCopyLen(cmd)) { prev_byte2 = ringbuffer[(pos - 2) & mask]; prev_byte = ringbuffer[(pos - 1) & mask]; if (cmd->cmd_prefix_ >= 128) { size_t context; BlockSplitIteratorNext(&dist_it); context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) + CommandDistanceContext(cmd); HistogramAddDistance(©_dist_histograms[context], cmd->dist_prefix_ & 0x3FF); } } } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/histogram.h000066400000000000000000000035231501401750600202010ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Models the histograms of literals, commands and distance codes. */ #ifndef BROTLI_ENC_HISTOGRAM_H_ #define BROTLI_ENC_HISTOGRAM_H_ #include /* memset */ #include #include "../common/constants.h" #include "../common/context.h" #include "../common/platform.h" #include "block_splitter.h" #include "command.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* The distance symbols effectively used by "Large Window Brotli" (32-bit). */ #define BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS 544 #define FN(X) X ## Literal #define DATA_SIZE BROTLI_NUM_LITERAL_SYMBOLS #define DataType uint8_t #include "histogram_inc.h" /* NOLINT(build/include) */ #undef DataType #undef DATA_SIZE #undef FN #define FN(X) X ## Command #define DataType uint16_t #define DATA_SIZE BROTLI_NUM_COMMAND_SYMBOLS #include "histogram_inc.h" /* NOLINT(build/include) */ #undef DATA_SIZE #undef FN #define FN(X) X ## Distance #define DATA_SIZE BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS #include "histogram_inc.h" /* NOLINT(build/include) */ #undef DataType #undef DATA_SIZE #undef FN BROTLI_INTERNAL void BrotliBuildHistogramsWithContext( const Command* cmds, const size_t num_commands, const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split, const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, const ContextType* context_modes, HistogramLiteral* literal_histograms, HistogramCommand* insert_and_copy_histograms, HistogramDistance* copy_dist_histograms); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_HISTOGRAM_H_ */ dvisvgm-3.5/libs/brotli/enc/histogram_inc.h000066400000000000000000000025711501401750600210340ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: Histogram, DATA_SIZE, DataType */ /* A simple container for histograms of data in blocks. */ typedef struct FN(Histogram) { uint32_t data_[DATA_SIZE]; size_t total_count_; double bit_cost_; } FN(Histogram); static BROTLI_INLINE void FN(HistogramClear)(FN(Histogram)* self) { memset(self->data_, 0, sizeof(self->data_)); self->total_count_ = 0; self->bit_cost_ = HUGE_VAL; } static BROTLI_INLINE void FN(ClearHistograms)( FN(Histogram)* array, size_t length) { size_t i; for (i = 0; i < length; ++i) FN(HistogramClear)(array + i); } static BROTLI_INLINE void FN(HistogramAdd)(FN(Histogram)* self, size_t val) { ++self->data_[val]; ++self->total_count_; } static BROTLI_INLINE void FN(HistogramAddVector)(FN(Histogram)* self, const DataType* p, size_t n) { self->total_count_ += n; n += 1; while (--n) ++self->data_[*p++]; } static BROTLI_INLINE void FN(HistogramAddHistogram)(FN(Histogram)* self, const FN(Histogram)* v) { size_t i; self->total_count_ += v->total_count_; for (i = 0; i < DATA_SIZE; ++i) { self->data_[i] += v->data_[i]; } } static BROTLI_INLINE size_t FN(HistogramDataSize)(void) { return DATA_SIZE; } dvisvgm-3.5/libs/brotli/enc/literal_cost.c000066400000000000000000000133171501401750600206650ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Literal cost model to allow backward reference replacement to be efficient. */ #include "literal_cost.h" #include /* memset */ #include #include "../common/platform.h" #include "fast_log.h" #include "utf8_util.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static size_t UTF8Position(size_t last, size_t c, size_t clamp) { if (c < 128) { return 0; /* Next one is the 'Byte 1' again. */ } else if (c >= 192) { /* Next one is the 'Byte 2' of utf-8 encoding. */ return BROTLI_MIN(size_t, 1, clamp); } else { /* Let's decide over the last byte if this ends the sequence. */ if (last < 0xE0) { return 0; /* Completed two or three byte coding. */ } else { /* Next one is the 'Byte 3' of utf-8 encoding. */ return BROTLI_MIN(size_t, 2, clamp); } } } static size_t DecideMultiByteStatsLevel(size_t pos, size_t len, size_t mask, const uint8_t* data) { size_t counts[3] = { 0 }; size_t max_utf8 = 1; /* should be 2, but 1 compresses better. */ size_t last_c = 0; size_t i; for (i = 0; i < len; ++i) { size_t c = data[(pos + i) & mask]; ++counts[UTF8Position(last_c, c, 2)]; last_c = c; } if (counts[2] < 500) { max_utf8 = 1; } if (counts[1] + counts[2] < 25) { max_utf8 = 0; } return max_utf8; } static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask, const uint8_t* data, size_t* histogram, float* cost) { /* max_utf8 is 0 (normal ASCII single byte modeling), 1 (for 2-byte UTF-8 modeling), or 2 (for 3-byte UTF-8 modeling). */ const size_t max_utf8 = DecideMultiByteStatsLevel(pos, len, mask, data); size_t window_half = 495; size_t in_window = BROTLI_MIN(size_t, window_half, len); size_t in_window_utf8[3] = { 0 }; size_t i; memset(histogram, 0, 3 * 256 * sizeof(histogram[0])); { /* Bootstrap histograms. */ size_t last_c = 0; size_t utf8_pos = 0; for (i = 0; i < in_window; ++i) { size_t c = data[(pos + i) & mask]; ++histogram[256 * utf8_pos + c]; ++in_window_utf8[utf8_pos]; utf8_pos = UTF8Position(last_c, c, max_utf8); last_c = c; } } /* Compute bit costs with sliding window. */ for (i = 0; i < len; ++i) { if (i >= window_half) { /* Remove a byte in the past. */ size_t c = i < window_half + 1 ? 0 : data[(pos + i - window_half - 1) & mask]; size_t last_c = i < window_half + 2 ? 0 : data[(pos + i - window_half - 2) & mask]; size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8); --histogram[256 * utf8_pos2 + data[(pos + i - window_half) & mask]]; --in_window_utf8[utf8_pos2]; } if (i + window_half < len) { /* Add a byte in the future. */ size_t c = data[(pos + i + window_half - 1) & mask]; size_t last_c = data[(pos + i + window_half - 2) & mask]; size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8); ++histogram[256 * utf8_pos2 + data[(pos + i + window_half) & mask]]; ++in_window_utf8[utf8_pos2]; } { size_t c = i < 1 ? 0 : data[(pos + i - 1) & mask]; size_t last_c = i < 2 ? 0 : data[(pos + i - 2) & mask]; size_t utf8_pos = UTF8Position(last_c, c, max_utf8); size_t masked_pos = (pos + i) & mask; size_t histo = histogram[256 * utf8_pos + data[masked_pos]]; double lit_cost; if (histo == 0) { histo = 1; } lit_cost = FastLog2(in_window_utf8[utf8_pos]) - FastLog2(histo); lit_cost += 0.02905; if (lit_cost < 1.0) { lit_cost *= 0.5; lit_cost += 0.5; } /* Make the first bytes more expensive -- seems to help, not sure why. Perhaps because the entropy source is changing its properties rapidly in the beginning of the file, perhaps because the beginning of the data is a statistical "anomaly". */ if (i < 2000) { lit_cost += 0.7 - ((double)(2000 - i) / 2000.0 * 0.35); } cost[i] = (float)lit_cost; } } } void BrotliEstimateBitCostsForLiterals(size_t pos, size_t len, size_t mask, const uint8_t* data, size_t* histogram, float* cost) { if (BrotliIsMostlyUTF8(data, pos, mask, len, kMinUTF8Ratio)) { EstimateBitCostsForLiteralsUTF8(pos, len, mask, data, histogram, cost); return; } else { size_t window_half = 2000; size_t in_window = BROTLI_MIN(size_t, window_half, len); size_t i; memset(histogram, 0, 256 * sizeof(histogram[0])); /* Bootstrap histogram. */ for (i = 0; i < in_window; ++i) { ++histogram[data[(pos + i) & mask]]; } /* Compute bit costs with sliding window. */ for (i = 0; i < len; ++i) { size_t histo; if (i >= window_half) { /* Remove a byte in the past. */ --histogram[data[(pos + i - window_half) & mask]]; --in_window; } if (i + window_half < len) { /* Add a byte in the future. */ ++histogram[data[(pos + i + window_half) & mask]]; ++in_window; } histo = histogram[data[(pos + i) & mask]]; if (histo == 0) { histo = 1; } { double lit_cost = FastLog2(in_window) - FastLog2(histo); lit_cost += 0.029; if (lit_cost < 1.0) { lit_cost *= 0.5; lit_cost += 0.5; } cost[i] = (float)lit_cost; } } } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/literal_cost.h000066400000000000000000000016241501401750600206700ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Literal cost model to allow backward reference replacement to be efficient. */ #ifndef BROTLI_ENC_LITERAL_COST_H_ #define BROTLI_ENC_LITERAL_COST_H_ #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* Estimates how many bits the literals in the interval [pos, pos + len) in the ring-buffer (data, mask) will take entropy coded and writes these estimates to the cost[0..len) array. */ BROTLI_INTERNAL void BrotliEstimateBitCostsForLiterals( size_t pos, size_t len, size_t mask, const uint8_t* data, size_t* histogram, float* cost); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_LITERAL_COST_H_ */ dvisvgm-3.5/libs/brotli/enc/memory.c000066400000000000000000000127761501401750600175210ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Algorithms for distributing the literals and commands of a metablock between block types and contexts. */ #include "memory.h" #include /* exit, free, malloc */ #include /* memcpy */ #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define MAX_NEW_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2) #define MAX_NEW_FREED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2) #define MAX_PERM_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 1) #define PERM_ALLOCATED_OFFSET 0 #define NEW_ALLOCATED_OFFSET MAX_PERM_ALLOCATED #define NEW_FREED_OFFSET (MAX_PERM_ALLOCATED + MAX_NEW_ALLOCATED) void BrotliInitMemoryManager( MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { if (!alloc_func) { m->alloc_func = BrotliDefaultAllocFunc; m->free_func = BrotliDefaultFreeFunc; m->opaque = 0; } else { m->alloc_func = alloc_func; m->free_func = free_func; m->opaque = opaque; } #if !defined(BROTLI_ENCODER_EXIT_ON_OOM) m->is_oom = BROTLI_FALSE; m->perm_allocated = 0; m->new_allocated = 0; m->new_freed = 0; #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ } #if defined(BROTLI_ENCODER_EXIT_ON_OOM) void* BrotliAllocate(MemoryManager* m, size_t n) { void* result = m->alloc_func(m->opaque, n); if (!result) exit(EXIT_FAILURE); return result; } void BrotliFree(MemoryManager* m, void* p) { m->free_func(m->opaque, p); } void BrotliWipeOutMemoryManager(MemoryManager* m) { BROTLI_UNUSED(m); } #else /* BROTLI_ENCODER_EXIT_ON_OOM */ static void SortPointers(void** items, const size_t n) { /* Shell sort. */ /* TODO(eustas): fine-tune for "many slots" case */ static const size_t gaps[] = {23, 10, 4, 1}; int g = 0; for (; g < 4; ++g) { size_t gap = gaps[g]; size_t i; for (i = gap; i < n; ++i) { size_t j = i; void* tmp = items[i]; for (; j >= gap && tmp < items[j - gap]; j -= gap) { items[j] = items[j - gap]; } items[j] = tmp; } } } static size_t Annihilate(void** a, size_t a_len, void** b, size_t b_len) { size_t a_read_index = 0; size_t b_read_index = 0; size_t a_write_index = 0; size_t b_write_index = 0; size_t annihilated = 0; while (a_read_index < a_len && b_read_index < b_len) { if (a[a_read_index] == b[b_read_index]) { a_read_index++; b_read_index++; annihilated++; } else if (a[a_read_index] < b[b_read_index]) { a[a_write_index++] = a[a_read_index++]; } else { b[b_write_index++] = b[b_read_index++]; } } while (a_read_index < a_len) a[a_write_index++] = a[a_read_index++]; while (b_read_index < b_len) b[b_write_index++] = b[b_read_index++]; return annihilated; } static void CollectGarbagePointers(MemoryManager* m) { size_t annihilated; SortPointers(m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated); SortPointers(m->pointers + NEW_FREED_OFFSET, m->new_freed); annihilated = Annihilate( m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated, m->pointers + NEW_FREED_OFFSET, m->new_freed); m->new_allocated -= annihilated; m->new_freed -= annihilated; if (m->new_freed != 0) { annihilated = Annihilate( m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated, m->pointers + NEW_FREED_OFFSET, m->new_freed); m->perm_allocated -= annihilated; m->new_freed -= annihilated; BROTLI_DCHECK(m->new_freed == 0); } if (m->new_allocated != 0) { BROTLI_DCHECK(m->perm_allocated + m->new_allocated <= MAX_PERM_ALLOCATED); memcpy(m->pointers + PERM_ALLOCATED_OFFSET + m->perm_allocated, m->pointers + NEW_ALLOCATED_OFFSET, sizeof(void*) * m->new_allocated); m->perm_allocated += m->new_allocated; m->new_allocated = 0; SortPointers(m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated); } } void* BrotliAllocate(MemoryManager* m, size_t n) { void* result = m->alloc_func(m->opaque, n); if (!result) { m->is_oom = BROTLI_TRUE; return NULL; } if (m->new_allocated == MAX_NEW_ALLOCATED) CollectGarbagePointers(m); m->pointers[NEW_ALLOCATED_OFFSET + (m->new_allocated++)] = result; return result; } void BrotliFree(MemoryManager* m, void* p) { if (!p) return; m->free_func(m->opaque, p); if (m->new_freed == MAX_NEW_FREED) CollectGarbagePointers(m); m->pointers[NEW_FREED_OFFSET + (m->new_freed++)] = p; } void BrotliWipeOutMemoryManager(MemoryManager* m) { size_t i; CollectGarbagePointers(m); /* Now all unfreed pointers are in perm-allocated list. */ for (i = 0; i < m->perm_allocated; ++i) { m->free_func(m->opaque, m->pointers[PERM_ALLOCATED_OFFSET + i]); } m->perm_allocated = 0; } #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ void* BrotliBootstrapAlloc(size_t size, brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { if (!alloc_func && !free_func) { return malloc(size); } else if (alloc_func && free_func) { return alloc_func(opaque, size); } return NULL; } void BrotliBootstrapFree(void* address, MemoryManager* m) { if (!address) { /* Should not happen! */ return; } else { /* Copy values, as those would be freed. */ brotli_free_func free_func = m->free_func; void* opaque = m->opaque; free_func(opaque, address); } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/memory.h000066400000000000000000000104061501401750600175120ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Macros for memory management. */ #ifndef BROTLI_ENC_MEMORY_H_ #define BROTLI_ENC_MEMORY_H_ #include /* memcpy */ #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #if !defined(BROTLI_ENCODER_CLEANUP_ON_OOM) && \ !defined(BROTLI_ENCODER_EXIT_ON_OOM) #define BROTLI_ENCODER_EXIT_ON_OOM #endif #if !defined(BROTLI_ENCODER_EXIT_ON_OOM) #if defined(BROTLI_EXPERIMENTAL) #define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS (48*1024) #else /* BROTLI_EXPERIMENTAL */ #define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 256 #endif /* BROTLI_EXPERIMENTAL */ #else /* BROTLI_ENCODER_EXIT_ON_OOM */ #define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 0 #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ typedef struct MemoryManager { brotli_alloc_func alloc_func; brotli_free_func free_func; void* opaque; #if !defined(BROTLI_ENCODER_EXIT_ON_OOM) BROTLI_BOOL is_oom; size_t perm_allocated; size_t new_allocated; size_t new_freed; void* pointers[BROTLI_ENCODER_MEMORY_MANAGER_SLOTS]; #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ } MemoryManager; BROTLI_INTERNAL void BrotliInitMemoryManager( MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); BROTLI_INTERNAL void* BrotliAllocate(MemoryManager* m, size_t n); #define BROTLI_ALLOC(M, T, N) \ ((N) > 0 ? ((T*)BrotliAllocate((M), (N) * sizeof(T))) : NULL) BROTLI_INTERNAL void BrotliFree(MemoryManager* m, void* p); #define BROTLI_FREE(M, P) { \ BrotliFree((M), (P)); \ P = NULL; \ } #if defined(BROTLI_ENCODER_EXIT_ON_OOM) #define BROTLI_IS_OOM(M) (!!0) #else /* BROTLI_ENCODER_EXIT_ON_OOM */ #define BROTLI_IS_OOM(M) (!!(M)->is_oom) #endif /* BROTLI_ENCODER_EXIT_ON_OOM */ /* BROTLI_IS_NULL is a fake check, BROTLI_IS_OOM does the heavy lifting. The only purpose of it is to explain static analyzers the state of things. NB: use ONLY together with BROTLI_IS_OOM AND ONLY for allocations in the current scope. */ #if defined(__clang_analyzer__) && !defined(BROTLI_ENCODER_EXIT_ON_OOM) #define BROTLI_IS_NULL(A) ((A) == nullptr) #else /* defined(__clang_analyzer__) */ #define BROTLI_IS_NULL(A) (!!0) #endif /* defined(__clang_analyzer__) */ BROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m); /* Dynamically grows array capacity to at least the requested size M: MemoryManager T: data type A: array C: capacity R: requested size */ #define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) { \ if (C < (R)) { \ size_t _new_size = (C == 0) ? (R) : C; \ T* new_array; \ while (_new_size < (R)) _new_size *= 2; \ new_array = BROTLI_ALLOC((M), T, _new_size); \ if (!BROTLI_IS_OOM(M) && !BROTLI_IS_NULL(new_array) && C != 0) \ memcpy(new_array, A, C * sizeof(T)); \ BROTLI_FREE((M), A); \ A = new_array; \ C = _new_size; \ } \ } /* Appends value and dynamically grows array capacity when needed M: MemoryManager T: data type A: array C: array capacity S: array size V: value to append */ #define BROTLI_ENSURE_CAPACITY_APPEND(M, T, A, C, S, V) { \ (S)++; \ BROTLI_ENSURE_CAPACITY(M, T, A, C, S); \ A[(S) - 1] = (V); \ } /* "Bootstrap" allocations are not tracked by memory manager; should be used only to allocate MemoryManager itself (or structure containing it). */ BROTLI_INTERNAL void* BrotliBootstrapAlloc(size_t size, brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); BROTLI_INTERNAL void BrotliBootstrapFree(void* address, MemoryManager* m); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_MEMORY_H_ */ dvisvgm-3.5/libs/brotli/enc/metablock.c000066400000000000000000000641121501401750600201410ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Algorithms for distributing the literals and commands of a metablock between block types and contexts. */ #include "metablock.h" #include #include "../common/constants.h" #include "../common/context.h" #include "../common/platform.h" #include "bit_cost.h" #include "block_splitter.h" #include "cluster.h" #include "entropy_encode.h" #include "histogram.h" #include "memory.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif void BrotliInitDistanceParams(BrotliDistanceParams* dist_params, uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window) { uint32_t alphabet_size_max; uint32_t alphabet_size_limit; uint32_t max_distance; dist_params->distance_postfix_bits = npostfix; dist_params->num_direct_distance_codes = ndirect; alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE( npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS); alphabet_size_limit = alphabet_size_max; max_distance = ndirect + (1U << (BROTLI_MAX_DISTANCE_BITS + npostfix + 2)) - (1U << (npostfix + 2)); if (large_window) { BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit( BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect); alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE( npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS); alphabet_size_limit = limit.max_alphabet_size; max_distance = limit.max_distance; } dist_params->alphabet_size_max = alphabet_size_max; dist_params->alphabet_size_limit = alphabet_size_limit; dist_params->max_distance = max_distance; } static void RecomputeDistancePrefixes(Command* cmds, size_t num_commands, const BrotliDistanceParams* orig_params, const BrotliDistanceParams* new_params) { size_t i; if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits && orig_params->num_direct_distance_codes == new_params->num_direct_distance_codes) { return; } for (i = 0; i < num_commands; ++i) { Command* cmd = &cmds[i]; if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { PrefixEncodeCopyDistance(CommandRestoreDistanceCode(cmd, orig_params), new_params->num_direct_distance_codes, new_params->distance_postfix_bits, &cmd->dist_prefix_, &cmd->dist_extra_); } } } static BROTLI_BOOL ComputeDistanceCost(const Command* cmds, size_t num_commands, const BrotliDistanceParams* orig_params, const BrotliDistanceParams* new_params, double* cost, HistogramDistance* tmp) { size_t i; BROTLI_BOOL equal_params = BROTLI_FALSE; uint16_t dist_prefix; uint32_t dist_extra; double extra_bits = 0.0; HistogramClearDistance(tmp); if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits && orig_params->num_direct_distance_codes == new_params->num_direct_distance_codes) { equal_params = BROTLI_TRUE; } for (i = 0; i < num_commands; i++) { const Command* cmd = &cmds[i]; if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { if (equal_params) { dist_prefix = cmd->dist_prefix_; } else { uint32_t distance = CommandRestoreDistanceCode(cmd, orig_params); if (distance > new_params->max_distance) { return BROTLI_FALSE; } PrefixEncodeCopyDistance(distance, new_params->num_direct_distance_codes, new_params->distance_postfix_bits, &dist_prefix, &dist_extra); } HistogramAddDistance(tmp, dist_prefix & 0x3FF); extra_bits += dist_prefix >> 10; } } *cost = BrotliPopulationCostDistance(tmp) + extra_bits; return BROTLI_TRUE; } void BrotliBuildMetaBlock(MemoryManager* m, const uint8_t* ringbuffer, const size_t pos, const size_t mask, BrotliEncoderParams* params, uint8_t prev_byte, uint8_t prev_byte2, Command* cmds, size_t num_commands, ContextType literal_context_mode, MetaBlockSplit* mb) { /* Histogram ids need to fit in one byte. */ static const size_t kMaxNumberOfHistograms = 256; HistogramDistance* distance_histograms; HistogramLiteral* literal_histograms; ContextType* literal_context_modes = NULL; size_t literal_histograms_size; size_t distance_histograms_size; size_t i; size_t literal_context_multiplier = 1; uint32_t npostfix; uint32_t ndirect_msb = 0; BROTLI_BOOL check_orig = BROTLI_TRUE; double best_dist_cost = 1e99; BrotliDistanceParams orig_params = params->dist; BrotliDistanceParams new_params = params->dist; HistogramDistance* tmp = BROTLI_ALLOC(m, HistogramDistance, 1); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return; for (npostfix = 0; npostfix <= BROTLI_MAX_NPOSTFIX; npostfix++) { for (; ndirect_msb < 16; ndirect_msb++) { uint32_t ndirect = ndirect_msb << npostfix; BROTLI_BOOL skip; double dist_cost; BrotliInitDistanceParams(&new_params, npostfix, ndirect, params->large_window); if (npostfix == orig_params.distance_postfix_bits && ndirect == orig_params.num_direct_distance_codes) { check_orig = BROTLI_FALSE; } skip = !ComputeDistanceCost( cmds, num_commands, &orig_params, &new_params, &dist_cost, tmp); if (skip || (dist_cost > best_dist_cost)) { break; } best_dist_cost = dist_cost; params->dist = new_params; } if (ndirect_msb > 0) ndirect_msb--; ndirect_msb /= 2; } if (check_orig) { double dist_cost; ComputeDistanceCost(cmds, num_commands, &orig_params, &orig_params, &dist_cost, tmp); if (dist_cost < best_dist_cost) { /* NB: currently unused; uncomment when more param tuning is added. */ /* best_dist_cost = dist_cost; */ params->dist = orig_params; } } BROTLI_FREE(m, tmp); RecomputeDistancePrefixes(cmds, num_commands, &orig_params, ¶ms->dist); BrotliSplitBlock(m, cmds, num_commands, ringbuffer, pos, mask, params, &mb->literal_split, &mb->command_split, &mb->distance_split); if (BROTLI_IS_OOM(m)) return; if (!params->disable_literal_context_modeling) { literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS; literal_context_modes = BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_context_modes)) return; for (i = 0; i < mb->literal_split.num_types; ++i) { literal_context_modes[i] = literal_context_mode; } } literal_histograms_size = mb->literal_split.num_types * literal_context_multiplier; literal_histograms = BROTLI_ALLOC(m, HistogramLiteral, literal_histograms_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_histograms)) return; ClearHistogramsLiteral(literal_histograms, literal_histograms_size); distance_histograms_size = mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS; distance_histograms = BROTLI_ALLOC(m, HistogramDistance, distance_histograms_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_histograms)) return; ClearHistogramsDistance(distance_histograms, distance_histograms_size); BROTLI_DCHECK(mb->command_histograms == 0); mb->command_histograms_size = mb->command_split.num_types; mb->command_histograms = BROTLI_ALLOC(m, HistogramCommand, mb->command_histograms_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->command_histograms)) return; ClearHistogramsCommand(mb->command_histograms, mb->command_histograms_size); BrotliBuildHistogramsWithContext(cmds, num_commands, &mb->literal_split, &mb->command_split, &mb->distance_split, ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes, literal_histograms, mb->command_histograms, distance_histograms); BROTLI_FREE(m, literal_context_modes); BROTLI_DCHECK(mb->literal_context_map == 0); mb->literal_context_map_size = mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS; mb->literal_context_map = BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return; BROTLI_DCHECK(mb->literal_histograms == 0); mb->literal_histograms_size = mb->literal_context_map_size; mb->literal_histograms = BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_histograms)) return; BrotliClusterHistogramsLiteral(m, literal_histograms, literal_histograms_size, kMaxNumberOfHistograms, mb->literal_histograms, &mb->literal_histograms_size, mb->literal_context_map); if (BROTLI_IS_OOM(m)) return; BROTLI_FREE(m, literal_histograms); if (params->disable_literal_context_modeling) { /* Distribute assignment to all contexts. */ for (i = mb->literal_split.num_types; i != 0;) { size_t j = 0; i--; for (; j < (1 << BROTLI_LITERAL_CONTEXT_BITS); j++) { mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] = mb->literal_context_map[i]; } } } BROTLI_DCHECK(mb->distance_context_map == 0); mb->distance_context_map_size = mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS; mb->distance_context_map = BROTLI_ALLOC(m, uint32_t, mb->distance_context_map_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_context_map)) return; BROTLI_DCHECK(mb->distance_histograms == 0); mb->distance_histograms_size = mb->distance_context_map_size; mb->distance_histograms = BROTLI_ALLOC(m, HistogramDistance, mb->distance_histograms_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_histograms)) return; BrotliClusterHistogramsDistance(m, distance_histograms, mb->distance_context_map_size, kMaxNumberOfHistograms, mb->distance_histograms, &mb->distance_histograms_size, mb->distance_context_map); if (BROTLI_IS_OOM(m)) return; BROTLI_FREE(m, distance_histograms); } #define FN(X) X ## Literal #include "metablock_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Command #include "metablock_inc.h" /* NOLINT(build/include) */ #undef FN #define FN(X) X ## Distance #include "metablock_inc.h" /* NOLINT(build/include) */ #undef FN #define BROTLI_MAX_STATIC_CONTEXTS 13 /* Greedy block splitter for one block category (literal, command or distance). Gathers histograms for all context buckets. */ typedef struct ContextBlockSplitter { /* Alphabet size of particular block category. */ size_t alphabet_size_; size_t num_contexts_; size_t max_block_types_; /* We collect at least this many symbols for each block. */ size_t min_block_size_; /* We merge histograms A and B if entropy(A+B) < entropy(A) + entropy(B) + split_threshold_, where A is the current histogram and B is the histogram of the last or the second last block type. */ double split_threshold_; size_t num_blocks_; BlockSplit* split_; /* not owned */ HistogramLiteral* histograms_; /* not owned */ size_t* histograms_size_; /* not owned */ /* The number of symbols that we want to collect before deciding on whether or not to merge the block with a previous one or emit a new block. */ size_t target_block_size_; /* The number of symbols in the current histogram. */ size_t block_size_; /* Offset of the current histogram. */ size_t curr_histogram_ix_; /* Offset of the histograms of the previous two block types. */ size_t last_histogram_ix_[2]; /* Entropy of the previous two block types. */ double last_entropy_[2 * BROTLI_MAX_STATIC_CONTEXTS]; /* The number of times we merged the current block with the last one. */ size_t merge_last_count_; } ContextBlockSplitter; static void InitContextBlockSplitter( MemoryManager* m, ContextBlockSplitter* self, size_t alphabet_size, size_t num_contexts, size_t min_block_size, double split_threshold, size_t num_symbols, BlockSplit* split, HistogramLiteral** histograms, size_t* histograms_size) { size_t max_num_blocks = num_symbols / min_block_size + 1; size_t max_num_types; BROTLI_DCHECK(num_contexts <= BROTLI_MAX_STATIC_CONTEXTS); self->alphabet_size_ = alphabet_size; self->num_contexts_ = num_contexts; self->max_block_types_ = BROTLI_MAX_NUMBER_OF_BLOCK_TYPES / num_contexts; self->min_block_size_ = min_block_size; self->split_threshold_ = split_threshold; self->num_blocks_ = 0; self->split_ = split; self->histograms_size_ = histograms_size; self->target_block_size_ = min_block_size; self->block_size_ = 0; self->curr_histogram_ix_ = 0; self->merge_last_count_ = 0; /* We have to allocate one more histogram than the maximum number of block types for the current histogram when the meta-block is too big. */ max_num_types = BROTLI_MIN(size_t, max_num_blocks, self->max_block_types_ + 1); BROTLI_ENSURE_CAPACITY(m, uint8_t, split->types, split->types_alloc_size, max_num_blocks); BROTLI_ENSURE_CAPACITY(m, uint32_t, split->lengths, split->lengths_alloc_size, max_num_blocks); if (BROTLI_IS_OOM(m)) return; split->num_blocks = max_num_blocks; if (BROTLI_IS_OOM(m)) return; BROTLI_DCHECK(*histograms == 0); *histograms_size = max_num_types * num_contexts; *histograms = BROTLI_ALLOC(m, HistogramLiteral, *histograms_size); self->histograms_ = *histograms; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return; /* Clear only current histogram. */ ClearHistogramsLiteral(&self->histograms_[0], num_contexts); self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0; } /* Does either of three things: (1) emits the current block with a new block type; (2) emits the current block with the type of the second last block; (3) merges the current block with the last block. */ static void ContextBlockSplitterFinishBlock( ContextBlockSplitter* self, MemoryManager* m, BROTLI_BOOL is_final) { BlockSplit* split = self->split_; const size_t num_contexts = self->num_contexts_; double* last_entropy = self->last_entropy_; HistogramLiteral* histograms = self->histograms_; if (self->block_size_ < self->min_block_size_) { self->block_size_ = self->min_block_size_; } if (self->num_blocks_ == 0) { size_t i; /* Create first block. */ split->lengths[0] = (uint32_t)self->block_size_; split->types[0] = 0; for (i = 0; i < num_contexts; ++i) { last_entropy[i] = BitsEntropy(histograms[i].data_, self->alphabet_size_); last_entropy[num_contexts + i] = last_entropy[i]; } ++self->num_blocks_; ++split->num_types; self->curr_histogram_ix_ += num_contexts; if (self->curr_histogram_ix_ < *self->histograms_size_) { ClearHistogramsLiteral( &self->histograms_[self->curr_histogram_ix_], self->num_contexts_); } self->block_size_ = 0; } else if (self->block_size_ > 0) { /* Try merging the set of histograms for the current block type with the respective set of histograms for the last and second last block types. Decide over the split based on the total reduction of entropy across all contexts. */ double entropy[BROTLI_MAX_STATIC_CONTEXTS]; HistogramLiteral* combined_histo = BROTLI_ALLOC(m, HistogramLiteral, 2 * num_contexts); double combined_entropy[2 * BROTLI_MAX_STATIC_CONTEXTS]; double diff[2] = { 0.0 }; size_t i; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(combined_histo)) return; for (i = 0; i < num_contexts; ++i) { size_t curr_histo_ix = self->curr_histogram_ix_ + i; size_t j; entropy[i] = BitsEntropy(histograms[curr_histo_ix].data_, self->alphabet_size_); for (j = 0; j < 2; ++j) { size_t jx = j * num_contexts + i; size_t last_histogram_ix = self->last_histogram_ix_[j] + i; combined_histo[jx] = histograms[curr_histo_ix]; HistogramAddHistogramLiteral(&combined_histo[jx], &histograms[last_histogram_ix]); combined_entropy[jx] = BitsEntropy( &combined_histo[jx].data_[0], self->alphabet_size_); diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx]; } } if (split->num_types < self->max_block_types_ && diff[0] > self->split_threshold_ && diff[1] > self->split_threshold_) { /* Create new block. */ split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; split->types[self->num_blocks_] = (uint8_t)split->num_types; self->last_histogram_ix_[1] = self->last_histogram_ix_[0]; self->last_histogram_ix_[0] = split->num_types * num_contexts; for (i = 0; i < num_contexts; ++i) { last_entropy[num_contexts + i] = last_entropy[i]; last_entropy[i] = entropy[i]; } ++self->num_blocks_; ++split->num_types; self->curr_histogram_ix_ += num_contexts; if (self->curr_histogram_ix_ < *self->histograms_size_) { ClearHistogramsLiteral( &self->histograms_[self->curr_histogram_ix_], self->num_contexts_); } self->block_size_ = 0; self->merge_last_count_ = 0; self->target_block_size_ = self->min_block_size_; } else if (diff[1] < diff[0] - 20.0) { /* Combine this block with second last block. */ split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2]; BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1); for (i = 0; i < num_contexts; ++i) { histograms[self->last_histogram_ix_[0] + i] = combined_histo[num_contexts + i]; last_entropy[num_contexts + i] = last_entropy[i]; last_entropy[i] = combined_entropy[num_contexts + i]; HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]); } ++self->num_blocks_; self->block_size_ = 0; self->merge_last_count_ = 0; self->target_block_size_ = self->min_block_size_; } else { /* Combine this block with last block. */ split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_; for (i = 0; i < num_contexts; ++i) { histograms[self->last_histogram_ix_[0] + i] = combined_histo[i]; last_entropy[i] = combined_entropy[i]; if (split->num_types == 1) { last_entropy[num_contexts + i] = last_entropy[i]; } HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]); } self->block_size_ = 0; if (++self->merge_last_count_ > 1) { self->target_block_size_ += self->min_block_size_; } } BROTLI_FREE(m, combined_histo); } if (is_final) { *self->histograms_size_ = split->num_types * num_contexts; split->num_blocks = self->num_blocks_; } } /* Adds the next symbol to the current block type and context. When the current block reaches the target size, decides on merging the block. */ static void ContextBlockSplitterAddSymbol( ContextBlockSplitter* self, MemoryManager* m, size_t symbol, size_t context) { HistogramAddLiteral(&self->histograms_[self->curr_histogram_ix_ + context], symbol); ++self->block_size_; if (self->block_size_ == self->target_block_size_) { ContextBlockSplitterFinishBlock(self, m, /* is_final = */ BROTLI_FALSE); if (BROTLI_IS_OOM(m)) return; } } static void MapStaticContexts(MemoryManager* m, size_t num_contexts, const uint32_t* static_context_map, MetaBlockSplit* mb) { size_t i; BROTLI_DCHECK(mb->literal_context_map == 0); mb->literal_context_map_size = mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS; mb->literal_context_map = BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return; for (i = 0; i < mb->literal_split.num_types; ++i) { uint32_t offset = (uint32_t)(i * num_contexts); size_t j; for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS); ++j) { mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] = offset + static_context_map[j]; } } } typedef struct GreedyMetablockArena { union { BlockSplitterLiteral plain; ContextBlockSplitter ctx; } lit_blocks; BlockSplitterCommand cmd_blocks; BlockSplitterDistance dist_blocks; } GreedyMetablockArena; static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal( MemoryManager* m, GreedyMetablockArena* arena, const uint8_t* ringbuffer, size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut, const size_t num_contexts, const uint32_t* static_context_map, const Command* commands, size_t n_commands, MetaBlockSplit* mb) { size_t num_literals = 0; size_t i; for (i = 0; i < n_commands; ++i) { num_literals += commands[i].insert_len_; } if (num_contexts == 1) { InitBlockSplitterLiteral(m, &arena->lit_blocks.plain, 256, 512, 400.0, num_literals, &mb->literal_split, &mb->literal_histograms, &mb->literal_histograms_size); } else { InitContextBlockSplitter(m, &arena->lit_blocks.ctx, 256, num_contexts, 512, 400.0, num_literals, &mb->literal_split, &mb->literal_histograms, &mb->literal_histograms_size); } if (BROTLI_IS_OOM(m)) return; InitBlockSplitterCommand(m, &arena->cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS, 1024, 500.0, n_commands, &mb->command_split, &mb->command_histograms, &mb->command_histograms_size); if (BROTLI_IS_OOM(m)) return; InitBlockSplitterDistance(m, &arena->dist_blocks, 64, 512, 100.0, n_commands, &mb->distance_split, &mb->distance_histograms, &mb->distance_histograms_size); if (BROTLI_IS_OOM(m)) return; for (i = 0; i < n_commands; ++i) { const Command cmd = commands[i]; size_t j; BlockSplitterAddSymbolCommand(&arena->cmd_blocks, cmd.cmd_prefix_); for (j = cmd.insert_len_; j != 0; --j) { uint8_t literal = ringbuffer[pos & mask]; if (num_contexts == 1) { BlockSplitterAddSymbolLiteral(&arena->lit_blocks.plain, literal); } else { size_t context = BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut); ContextBlockSplitterAddSymbol(&arena->lit_blocks.ctx, m, literal, static_context_map[context]); if (BROTLI_IS_OOM(m)) return; } prev_byte2 = prev_byte; prev_byte = literal; ++pos; } pos += CommandCopyLen(&cmd); if (CommandCopyLen(&cmd)) { prev_byte2 = ringbuffer[(pos - 2) & mask]; prev_byte = ringbuffer[(pos - 1) & mask]; if (cmd.cmd_prefix_ >= 128) { BlockSplitterAddSymbolDistance( &arena->dist_blocks, cmd.dist_prefix_ & 0x3FF); } } } if (num_contexts == 1) { BlockSplitterFinishBlockLiteral( &arena->lit_blocks.plain, /* is_final = */ BROTLI_TRUE); } else { ContextBlockSplitterFinishBlock( &arena->lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE); if (BROTLI_IS_OOM(m)) return; } BlockSplitterFinishBlockCommand( &arena->cmd_blocks, /* is_final = */ BROTLI_TRUE); BlockSplitterFinishBlockDistance( &arena->dist_blocks, /* is_final = */ BROTLI_TRUE); if (num_contexts > 1) { MapStaticContexts(m, num_contexts, static_context_map, mb); } } void BrotliBuildMetaBlockGreedy(MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut, size_t num_contexts, const uint32_t* static_context_map, const Command* commands, size_t n_commands, MetaBlockSplit* mb) { GreedyMetablockArena* arena = BROTLI_ALLOC(m, GreedyMetablockArena, 1); if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; if (num_contexts == 1) { BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, 1, NULL, commands, n_commands, mb); } else { BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, num_contexts, static_context_map, commands, n_commands, mb); } BROTLI_FREE(m, arena); } void BrotliOptimizeHistograms(uint32_t num_distance_codes, MetaBlockSplit* mb) { uint8_t good_for_rle[BROTLI_NUM_COMMAND_SYMBOLS]; size_t i; for (i = 0; i < mb->literal_histograms_size; ++i) { BrotliOptimizeHuffmanCountsForRle(256, mb->literal_histograms[i].data_, good_for_rle); } for (i = 0; i < mb->command_histograms_size; ++i) { BrotliOptimizeHuffmanCountsForRle(BROTLI_NUM_COMMAND_SYMBOLS, mb->command_histograms[i].data_, good_for_rle); } for (i = 0; i < mb->distance_histograms_size; ++i) { BrotliOptimizeHuffmanCountsForRle(num_distance_codes, mb->distance_histograms[i].data_, good_for_rle); } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/metablock.h000066400000000000000000000076541501401750600201560ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Algorithms for distributing the literals and commands of a metablock between block types and contexts. */ #ifndef BROTLI_ENC_METABLOCK_H_ #define BROTLI_ENC_METABLOCK_H_ #include #include "../common/context.h" #include "../common/platform.h" #include "block_splitter.h" #include "command.h" #include "histogram.h" #include "memory.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct MetaBlockSplit { BlockSplit literal_split; BlockSplit command_split; BlockSplit distance_split; uint32_t* literal_context_map; size_t literal_context_map_size; uint32_t* distance_context_map; size_t distance_context_map_size; HistogramLiteral* literal_histograms; size_t literal_histograms_size; HistogramCommand* command_histograms; size_t command_histograms_size; HistogramDistance* distance_histograms; size_t distance_histograms_size; } MetaBlockSplit; static BROTLI_INLINE void InitMetaBlockSplit(MetaBlockSplit* mb) { BrotliInitBlockSplit(&mb->literal_split); BrotliInitBlockSplit(&mb->command_split); BrotliInitBlockSplit(&mb->distance_split); mb->literal_context_map = 0; mb->literal_context_map_size = 0; mb->distance_context_map = 0; mb->distance_context_map_size = 0; mb->literal_histograms = 0; mb->literal_histograms_size = 0; mb->command_histograms = 0; mb->command_histograms_size = 0; mb->distance_histograms = 0; mb->distance_histograms_size = 0; } static BROTLI_INLINE void DestroyMetaBlockSplit( MemoryManager* m, MetaBlockSplit* mb) { BrotliDestroyBlockSplit(m, &mb->literal_split); BrotliDestroyBlockSplit(m, &mb->command_split); BrotliDestroyBlockSplit(m, &mb->distance_split); BROTLI_FREE(m, mb->literal_context_map); BROTLI_FREE(m, mb->distance_context_map); BROTLI_FREE(m, mb->literal_histograms); BROTLI_FREE(m, mb->command_histograms); BROTLI_FREE(m, mb->distance_histograms); } /* Uses the slow shortest-path block splitter and does context clustering. The distance parameters are dynamically selected based on the commands which get recomputed under the new distance parameters. The new distance parameters are stored into *params. */ BROTLI_INTERNAL void BrotliBuildMetaBlock(MemoryManager* m, const uint8_t* ringbuffer, const size_t pos, const size_t mask, BrotliEncoderParams* params, uint8_t prev_byte, uint8_t prev_byte2, Command* cmds, size_t num_commands, ContextType literal_context_mode, MetaBlockSplit* mb); /* Uses a fast greedy block splitter that tries to merge current block with the last or the second last block and uses a static context clustering which is the same for all block types. */ BROTLI_INTERNAL void BrotliBuildMetaBlockGreedy( MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut, size_t num_contexts, const uint32_t* static_context_map, const Command* commands, size_t n_commands, MetaBlockSplit* mb); BROTLI_INTERNAL void BrotliOptimizeHistograms(uint32_t num_distance_codes, MetaBlockSplit* mb); BROTLI_INTERNAL void BrotliInitDistanceParams(BrotliDistanceParams* params, uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_METABLOCK_H_ */ dvisvgm-3.5/libs/brotli/enc/metablock_inc.h000066400000000000000000000167321501401750600210040ustar00rootroot00000000000000/* NOLINT(build/header_guard) */ /* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* template parameters: FN */ #define HistogramType FN(Histogram) /* Greedy block splitter for one block category (literal, command or distance). */ typedef struct FN(BlockSplitter) { /* Alphabet size of particular block category. */ size_t alphabet_size_; /* We collect at least this many symbols for each block. */ size_t min_block_size_; /* We merge histograms A and B if entropy(A+B) < entropy(A) + entropy(B) + split_threshold_, where A is the current histogram and B is the histogram of the last or the second last block type. */ double split_threshold_; size_t num_blocks_; BlockSplit* split_; /* not owned */ HistogramType* histograms_; /* not owned */ size_t* histograms_size_; /* not owned */ /* Temporary storage for BlockSplitterFinishBlock. */ HistogramType combined_histo[2]; /* The number of symbols that we want to collect before deciding on whether or not to merge the block with a previous one or emit a new block. */ size_t target_block_size_; /* The number of symbols in the current histogram. */ size_t block_size_; /* Offset of the current histogram. */ size_t curr_histogram_ix_; /* Offset of the histograms of the previous two block types. */ size_t last_histogram_ix_[2]; /* Entropy of the previous two block types. */ double last_entropy_[2]; /* The number of times we merged the current block with the last one. */ size_t merge_last_count_; } FN(BlockSplitter); static void FN(InitBlockSplitter)( MemoryManager* m, FN(BlockSplitter)* self, size_t alphabet_size, size_t min_block_size, double split_threshold, size_t num_symbols, BlockSplit* split, HistogramType** histograms, size_t* histograms_size) { size_t max_num_blocks = num_symbols / min_block_size + 1; /* We have to allocate one more histogram than the maximum number of block types for the current histogram when the meta-block is too big. */ size_t max_num_types = BROTLI_MIN(size_t, max_num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 1); self->alphabet_size_ = alphabet_size; self->min_block_size_ = min_block_size; self->split_threshold_ = split_threshold; self->num_blocks_ = 0; self->split_ = split; self->histograms_size_ = histograms_size; self->target_block_size_ = min_block_size; self->block_size_ = 0; self->curr_histogram_ix_ = 0; self->merge_last_count_ = 0; BROTLI_ENSURE_CAPACITY(m, uint8_t, split->types, split->types_alloc_size, max_num_blocks); BROTLI_ENSURE_CAPACITY(m, uint32_t, split->lengths, split->lengths_alloc_size, max_num_blocks); if (BROTLI_IS_OOM(m)) return; self->split_->num_blocks = max_num_blocks; BROTLI_DCHECK(*histograms == 0); *histograms_size = max_num_types; *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size); self->histograms_ = *histograms; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return; /* Clear only current histogram. */ FN(HistogramClear)(&self->histograms_[0]); self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0; } /* Does either of three things: (1) emits the current block with a new block type; (2) emits the current block with the type of the second last block; (3) merges the current block with the last block. */ static void FN(BlockSplitterFinishBlock)( FN(BlockSplitter)* self, BROTLI_BOOL is_final) { BlockSplit* split = self->split_; double* last_entropy = self->last_entropy_; HistogramType* histograms = self->histograms_; self->block_size_ = BROTLI_MAX(size_t, self->block_size_, self->min_block_size_); if (self->num_blocks_ == 0) { /* Create first block. */ split->lengths[0] = (uint32_t)self->block_size_; split->types[0] = 0; last_entropy[0] = BitsEntropy(histograms[0].data_, self->alphabet_size_); last_entropy[1] = last_entropy[0]; ++self->num_blocks_; ++split->num_types; ++self->curr_histogram_ix_; if (self->curr_histogram_ix_ < *self->histograms_size_) FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); self->block_size_ = 0; } else if (self->block_size_ > 0) { double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_, self->alphabet_size_); double combined_entropy[2]; double diff[2]; size_t j; for (j = 0; j < 2; ++j) { size_t last_histogram_ix = self->last_histogram_ix_[j]; self->combined_histo[j] = histograms[self->curr_histogram_ix_]; FN(HistogramAddHistogram)(&self->combined_histo[j], &histograms[last_histogram_ix]); combined_entropy[j] = BitsEntropy( &self->combined_histo[j].data_[0], self->alphabet_size_); diff[j] = combined_entropy[j] - entropy - last_entropy[j]; } if (split->num_types < BROTLI_MAX_NUMBER_OF_BLOCK_TYPES && diff[0] > self->split_threshold_ && diff[1] > self->split_threshold_) { /* Create new block. */ split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; split->types[self->num_blocks_] = (uint8_t)split->num_types; self->last_histogram_ix_[1] = self->last_histogram_ix_[0]; self->last_histogram_ix_[0] = (uint8_t)split->num_types; last_entropy[1] = last_entropy[0]; last_entropy[0] = entropy; ++self->num_blocks_; ++split->num_types; ++self->curr_histogram_ix_; if (self->curr_histogram_ix_ < *self->histograms_size_) FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); self->block_size_ = 0; self->merge_last_count_ = 0; self->target_block_size_ = self->min_block_size_; } else if (diff[1] < diff[0] - 20.0) { /* Combine this block with second last block. */ split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2]; BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1); histograms[self->last_histogram_ix_[0]] = self->combined_histo[1]; last_entropy[1] = last_entropy[0]; last_entropy[0] = combined_entropy[1]; ++self->num_blocks_; self->block_size_ = 0; FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); self->merge_last_count_ = 0; self->target_block_size_ = self->min_block_size_; } else { /* Combine this block with last block. */ split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_; histograms[self->last_histogram_ix_[0]] = self->combined_histo[0]; last_entropy[0] = combined_entropy[0]; if (split->num_types == 1) { last_entropy[1] = last_entropy[0]; } self->block_size_ = 0; FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); if (++self->merge_last_count_ > 1) { self->target_block_size_ += self->min_block_size_; } } } if (is_final) { *self->histograms_size_ = split->num_types; split->num_blocks = self->num_blocks_; } } /* Adds the next symbol to the current histogram. When the current histogram reaches the target size, decides on merging the block. */ static void FN(BlockSplitterAddSymbol)(FN(BlockSplitter)* self, size_t symbol) { FN(HistogramAdd)(&self->histograms_[self->curr_histogram_ix_], symbol); ++self->block_size_; if (self->block_size_ == self->target_block_size_) { FN(BlockSplitterFinishBlock)(self, /* is_final = */ BROTLI_FALSE); } } #undef HistogramType dvisvgm-3.5/libs/brotli/enc/params.h000066400000000000000000000022211501401750600174610ustar00rootroot00000000000000/* Copyright 2017 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Parameters for the Brotli encoder with chosen quality levels. */ #ifndef BROTLI_ENC_PARAMS_H_ #define BROTLI_ENC_PARAMS_H_ #include #include "encoder_dict.h" typedef struct BrotliHasherParams { int type; int bucket_bits; int block_bits; int num_last_distances_to_check; } BrotliHasherParams; typedef struct BrotliDistanceParams { uint32_t distance_postfix_bits; uint32_t num_direct_distance_codes; uint32_t alphabet_size_max; uint32_t alphabet_size_limit; size_t max_distance; } BrotliDistanceParams; /* Encoding parameters */ typedef struct BrotliEncoderParams { BrotliEncoderMode mode; int quality; int lgwin; int lgblock; size_t stream_offset; size_t size_hint; BROTLI_BOOL disable_literal_context_modeling; BROTLI_BOOL large_window; BrotliHasherParams hasher; BrotliDistanceParams dist; /* TODO(eustas): rename to BrotliShared... */ SharedEncoderDictionary dictionary; } BrotliEncoderParams; #endif /* BROTLI_ENC_PARAMS_H_ */ dvisvgm-3.5/libs/brotli/enc/prefix.h000066400000000000000000000036611501401750600175040ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Functions for encoding of integers into prefix codes the amount of extra bits, and the actual values of the extra bits. */ #ifndef BROTLI_ENC_PREFIX_H_ #define BROTLI_ENC_PREFIX_H_ #include #include "../common/constants.h" #include "../common/platform.h" #include "fast_log.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* Here distance_code is an intermediate code, i.e. one of the special codes or the actual distance increased by BROTLI_NUM_DISTANCE_SHORT_CODES - 1. */ static BROTLI_INLINE void PrefixEncodeCopyDistance(size_t distance_code, size_t num_direct_codes, size_t postfix_bits, uint16_t* code, uint32_t* extra_bits) { if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes) { *code = (uint16_t)distance_code; *extra_bits = 0; return; } else { size_t dist = ((size_t)1 << (postfix_bits + 2u)) + (distance_code - BROTLI_NUM_DISTANCE_SHORT_CODES - num_direct_codes); size_t bucket = Log2FloorNonZero(dist) - 1; size_t postfix_mask = (1u << postfix_bits) - 1; size_t postfix = dist & postfix_mask; size_t prefix = (dist >> bucket) & 1; size_t offset = (2 + prefix) << bucket; size_t nbits = bucket - postfix_bits; *code = (uint16_t)((nbits << 10) | (BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes + ((2 * (nbits - 1) + prefix) << postfix_bits) + postfix)); *extra_bits = (uint32_t)((dist - offset) >> postfix_bits); } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_PREFIX_H_ */ dvisvgm-3.5/libs/brotli/enc/quality.h000066400000000000000000000166501501401750600177010ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Constants and formulas that affect speed-ratio trade-offs and thus define quality levels. */ #ifndef BROTLI_ENC_QUALITY_H_ #define BROTLI_ENC_QUALITY_H_ #include #include "../common/platform.h" #include "params.h" #define FAST_ONE_PASS_COMPRESSION_QUALITY 0 #define FAST_TWO_PASS_COMPRESSION_QUALITY 1 #define ZOPFLIFICATION_QUALITY 10 #define HQ_ZOPFLIFICATION_QUALITY 11 #define MAX_QUALITY_FOR_STATIC_ENTROPY_CODES 2 #define MIN_QUALITY_FOR_BLOCK_SPLIT 4 #define MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS 4 #define MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS 4 #define MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH 5 #define MIN_QUALITY_FOR_CONTEXT_MODELING 5 #define MIN_QUALITY_FOR_HQ_CONTEXT_MODELING 7 #define MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING 10 /* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting, so we buffer at most this much literals and commands. */ #define MAX_NUM_DELAYED_SYMBOLS 0x2FFF /* Returns hash-table size for quality levels 0 and 1. */ static BROTLI_INLINE size_t MaxHashTableSize(int quality) { return quality == FAST_ONE_PASS_COMPRESSION_QUALITY ? 1 << 15 : 1 << 17; } /* The maximum length for which the zopflification uses distinct distances. */ #define MAX_ZOPFLI_LEN_QUALITY_10 150 #define MAX_ZOPFLI_LEN_QUALITY_11 325 /* Do not thoroughly search when a long copy is found. */ #define BROTLI_LONG_COPY_QUICK_STEP 16384 static BROTLI_INLINE size_t MaxZopfliLen(const BrotliEncoderParams* params) { return params->quality <= 10 ? MAX_ZOPFLI_LEN_QUALITY_10 : MAX_ZOPFLI_LEN_QUALITY_11; } /* Number of best candidates to evaluate to expand Zopfli chain. */ static BROTLI_INLINE size_t MaxZopfliCandidates( const BrotliEncoderParams* params) { return params->quality <= 10 ? 1 : 5; } static BROTLI_INLINE void SanitizeParams(BrotliEncoderParams* params) { params->quality = BROTLI_MIN(int, BROTLI_MAX_QUALITY, BROTLI_MAX(int, BROTLI_MIN_QUALITY, params->quality)); if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) { params->large_window = BROTLI_FALSE; } if (params->lgwin < BROTLI_MIN_WINDOW_BITS) { params->lgwin = BROTLI_MIN_WINDOW_BITS; } else { int max_lgwin = params->large_window ? BROTLI_LARGE_MAX_WINDOW_BITS : BROTLI_MAX_WINDOW_BITS; if (params->lgwin > max_lgwin) params->lgwin = max_lgwin; } } /* Returns optimized lg_block value. */ static BROTLI_INLINE int ComputeLgBlock(const BrotliEncoderParams* params) { int lgblock = params->lgblock; if (params->quality == FAST_ONE_PASS_COMPRESSION_QUALITY || params->quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { lgblock = params->lgwin; } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) { lgblock = 14; } else if (lgblock == 0) { lgblock = 16; if (params->quality >= 9 && params->lgwin > lgblock) { lgblock = BROTLI_MIN(int, 18, params->lgwin); } } else { lgblock = BROTLI_MIN(int, BROTLI_MAX_INPUT_BLOCK_BITS, BROTLI_MAX(int, BROTLI_MIN_INPUT_BLOCK_BITS, lgblock)); } return lgblock; } /* Returns log2 of the size of main ring buffer area. Allocate at least lgwin + 1 bits for the ring buffer so that the newly added block fits there completely and we still get lgwin bits and at least read_block_size_bits + 1 bits because the copy tail length needs to be smaller than ring-buffer size. */ static BROTLI_INLINE int ComputeRbBits(const BrotliEncoderParams* params) { return 1 + BROTLI_MAX(int, params->lgwin, params->lgblock); } static BROTLI_INLINE size_t MaxMetablockSize( const BrotliEncoderParams* params) { int bits = BROTLI_MIN(int, ComputeRbBits(params), BROTLI_MAX_INPUT_BLOCK_BITS); return (size_t)1 << bits; } /* When searching for backward references and have not seen matches for a long time, we can skip some match lookups. Unsuccessful match lookups are very expensive and this kind of a heuristic speeds up compression quite a lot. At first 8 byte strides are taken and every second byte is put to hasher. After 4x more literals stride by 16 bytes, every put 4-th byte to hasher. Applied only to qualities 2 to 9. */ static BROTLI_INLINE size_t LiteralSpreeLengthForSparseSearch( const BrotliEncoderParams* params) { return params->quality < 9 ? 64 : 512; } /* Quality to hasher mapping: - q02: h02 (longest_match_quickly), b16, l5 - q03: h03 (longest_match_quickly), b17, l5 - q04: h04 (longest_match_quickly), b17, l5 - q04: h54 (longest_match_quickly), b20, l7 | for large files - q05: h05 (longest_match ), b14, l4 - q05: h06 (longest_match64 ), b15, l5 | for large files - q05: h40 (forgetful_chain ), b15, l4 | for small window - q06: h05 (longest_match ), b14, l4 - q06: h06 (longest_match64 ), b15, l5 | for large files - q06: h40 (forgetful_chain ), b15, l4 | for small window - q07: h05 (longest_match ), b15, l4 - q07: h06 (longest_match64 ), b15, l5 | for large files - q07: h41 (forgetful_chain ), b15, l4 | for small window - q08: h05 (longest_match ), b15, l4 - q08: h06 (longest_match64 ), b15, l5 | for large files - q08: h41 (forgetful_chain ), b15, l4 | for small window - q09: h05 (longest_match ), b15, l4 - q09: h06 (longest_match64 ), b15, l5 | for large files - q09: h42 (forgetful_chain ), b15, l4 | for small window - q10: t10 (to_binary_tree ), b17, l128 - q11: t10 (to_binary_tree ), b17, l128 Where "q" is quality, "h" is hasher type, "b" is bucket bits, "l" is source len. */ static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params, BrotliHasherParams* hparams) { if (params->quality > 9) { hparams->type = 10; } else if (params->quality == 4 && params->size_hint >= (1 << 20)) { hparams->type = 54; } else if (params->quality < 5) { hparams->type = params->quality; } else if (params->lgwin <= 16) { hparams->type = params->quality < 7 ? 40 : params->quality < 9 ? 41 : 42; } else if (params->size_hint >= (1 << 20) && params->lgwin >= 19) { hparams->type = 6; hparams->block_bits = params->quality - 1; hparams->bucket_bits = 15; hparams->num_last_distances_to_check = params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16; } else { /* TODO(eustas): often previous setting (H6) is faster and denser; consider adding an option to use it. */ hparams->type = 5; hparams->block_bits = params->quality - 1; hparams->bucket_bits = params->quality < 7 ? 14 : 15; hparams->num_last_distances_to_check = params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16; } if (params->lgwin > 24) { /* Different hashers for large window brotli: not for qualities <= 2, these are too fast for large window. Not for qualities >= 10: their hasher already works well with large window. So the changes are: H3 --> H35: for quality 3. H54 --> H55: for quality 4 with size hint > 1MB H6 --> H65: for qualities 5, 6, 7, 8, 9. */ if (hparams->type == 3) { hparams->type = 35; } if (hparams->type == 54) { hparams->type = 55; } if (hparams->type == 6) { hparams->type = 65; } } } #endif /* BROTLI_ENC_QUALITY_H_ */ dvisvgm-3.5/libs/brotli/enc/ringbuffer.h000066400000000000000000000135711501401750600203410ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Sliding window over the input data. */ #ifndef BROTLI_ENC_RINGBUFFER_H_ #define BROTLI_ENC_RINGBUFFER_H_ #include /* memcpy */ #include #include "../common/platform.h" #include "memory.h" #include "quality.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* A RingBuffer(window_bits, tail_bits) contains `1 << window_bits' bytes of data in a circular manner: writing a byte writes it to: `position() % (1 << window_bits)'. For convenience, the RingBuffer array contains another copy of the first `1 << tail_bits' bytes: buffer_[i] == buffer_[i + (1 << window_bits)], if i < (1 << tail_bits), and another copy of the last two bytes: buffer_[-1] == buffer_[(1 << window_bits) - 1] and buffer_[-2] == buffer_[(1 << window_bits) - 2]. */ typedef struct RingBuffer { /* Size of the ring-buffer is (1 << window_bits) + tail_size_. */ const uint32_t size_; const uint32_t mask_; const uint32_t tail_size_; const uint32_t total_size_; uint32_t cur_size_; /* Position to write in the ring buffer. */ uint32_t pos_; /* The actual ring buffer containing the copy of the last two bytes, the data, and the copy of the beginning as a tail. */ uint8_t* data_; /* The start of the ring-buffer. */ uint8_t* buffer_; } RingBuffer; static BROTLI_INLINE void RingBufferInit(RingBuffer* rb) { rb->cur_size_ = 0; rb->pos_ = 0; rb->data_ = 0; rb->buffer_ = 0; } static BROTLI_INLINE void RingBufferSetup( const BrotliEncoderParams* params, RingBuffer* rb) { int window_bits = ComputeRbBits(params); int tail_bits = params->lgblock; *(uint32_t*)&rb->size_ = 1u << window_bits; *(uint32_t*)&rb->mask_ = (1u << window_bits) - 1; *(uint32_t*)&rb->tail_size_ = 1u << tail_bits; *(uint32_t*)&rb->total_size_ = rb->size_ + rb->tail_size_; } static BROTLI_INLINE void RingBufferFree(MemoryManager* m, RingBuffer* rb) { BROTLI_FREE(m, rb->data_); } /* Allocates or re-allocates data_ to the given length + plus some slack region before and after. Fills the slack regions with zeros. */ static BROTLI_INLINE void RingBufferInitBuffer( MemoryManager* m, const uint32_t buflen, RingBuffer* rb) { static const size_t kSlackForEightByteHashingEverywhere = 7; uint8_t* new_data = BROTLI_ALLOC( m, uint8_t, 2 + buflen + kSlackForEightByteHashingEverywhere); size_t i; if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_data)) return; if (rb->data_) { memcpy(new_data, rb->data_, 2 + rb->cur_size_ + kSlackForEightByteHashingEverywhere); BROTLI_FREE(m, rb->data_); } rb->data_ = new_data; rb->cur_size_ = buflen; rb->buffer_ = rb->data_ + 2; rb->buffer_[-2] = rb->buffer_[-1] = 0; for (i = 0; i < kSlackForEightByteHashingEverywhere; ++i) { rb->buffer_[rb->cur_size_ + i] = 0; } } static BROTLI_INLINE void RingBufferWriteTail( const uint8_t* bytes, size_t n, RingBuffer* rb) { const size_t masked_pos = rb->pos_ & rb->mask_; if (BROTLI_PREDICT_FALSE(masked_pos < rb->tail_size_)) { /* Just fill the tail buffer with the beginning data. */ const size_t p = rb->size_ + masked_pos; memcpy(&rb->buffer_[p], bytes, BROTLI_MIN(size_t, n, rb->tail_size_ - masked_pos)); } } /* Push bytes into the ring buffer. */ static BROTLI_INLINE void RingBufferWrite( MemoryManager* m, const uint8_t* bytes, size_t n, RingBuffer* rb) { if (rb->pos_ == 0 && n < rb->tail_size_) { /* Special case for the first write: to process the first block, we don't need to allocate the whole ring-buffer and we don't need the tail either. However, we do this memory usage optimization only if the first write is less than the tail size, which is also the input block size, otherwise it is likely that other blocks will follow and we will need to reallocate to the full size anyway. */ rb->pos_ = (uint32_t)n; RingBufferInitBuffer(m, rb->pos_, rb); if (BROTLI_IS_OOM(m)) return; memcpy(rb->buffer_, bytes, n); return; } if (rb->cur_size_ < rb->total_size_) { /* Lazily allocate the full buffer. */ RingBufferInitBuffer(m, rb->total_size_, rb); if (BROTLI_IS_OOM(m)) return; /* Initialize the last two bytes to zero, so that we don't have to worry later when we copy the last two bytes to the first two positions. */ rb->buffer_[rb->size_ - 2] = 0; rb->buffer_[rb->size_ - 1] = 0; /* Initialize tail; might be touched by "best_len++" optimization when ring buffer is "full". */ rb->buffer_[rb->size_] = 241; } { const size_t masked_pos = rb->pos_ & rb->mask_; /* The length of the writes is limited so that we do not need to worry about a write */ RingBufferWriteTail(bytes, n, rb); if (BROTLI_PREDICT_TRUE(masked_pos + n <= rb->size_)) { /* A single write fits. */ memcpy(&rb->buffer_[masked_pos], bytes, n); } else { /* Split into two writes. Copy into the end of the buffer, including the tail buffer. */ memcpy(&rb->buffer_[masked_pos], bytes, BROTLI_MIN(size_t, n, rb->total_size_ - masked_pos)); /* Copy into the beginning of the buffer */ memcpy(&rb->buffer_[0], bytes + (rb->size_ - masked_pos), n - (rb->size_ - masked_pos)); } } { BROTLI_BOOL not_first_lap = (rb->pos_ & (1u << 31)) != 0; uint32_t rb_pos_mask = (1u << 31) - 1; rb->buffer_[-2] = rb->buffer_[rb->size_ - 2]; rb->buffer_[-1] = rb->buffer_[rb->size_ - 1]; rb->pos_ = (rb->pos_ & rb_pos_mask) + (uint32_t)(n & rb_pos_mask); if (not_first_lap) { /* Wrap, but preserve not-a-first-lap feature. */ rb->pos_ |= 1u << 31; } } } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_RINGBUFFER_H_ */ dvisvgm-3.5/libs/brotli/enc/state.h000066400000000000000000000057401501401750600173270ustar00rootroot00000000000000/* Copyright 2022 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Encoder state. */ #ifndef BROTLI_ENC_STATE_H_ #define BROTLI_ENC_STATE_H_ #include #include "command.h" #include "compress_fragment.h" #include "compress_fragment_two_pass.h" #include "hash.h" #include "memory.h" #include "params.h" #include "ringbuffer.h" typedef enum BrotliEncoderStreamState { /* Default state. */ BROTLI_STREAM_PROCESSING = 0, /* Intermediate state; after next block is emitted, byte-padding should be performed before getting back to default state. */ BROTLI_STREAM_FLUSH_REQUESTED = 1, /* Last metablock was produced; no more input is acceptable. */ BROTLI_STREAM_FINISHED = 2, /* Flushing compressed block and writing meta-data block header. */ BROTLI_STREAM_METADATA_HEAD = 3, /* Writing metadata block body. */ BROTLI_STREAM_METADATA_BODY = 4 } BrotliEncoderStreamState; typedef enum BrotliEncoderFlintState { BROTLI_FLINT_NEEDS_2_BYTES = 2, BROTLI_FLINT_NEEDS_1_BYTE = 1, BROTLI_FLINT_WAITING_FOR_PROCESSING = 0, BROTLI_FLINT_WAITING_FOR_FLUSHING = -1, BROTLI_FLINT_DONE = -2 } BrotliEncoderFlintState; typedef struct BrotliEncoderStateStruct { BrotliEncoderParams params; MemoryManager memory_manager_; uint64_t input_pos_; RingBuffer ringbuffer_; size_t cmd_alloc_size_; Command* commands_; size_t num_commands_; size_t num_literals_; size_t last_insert_len_; uint64_t last_flush_pos_; uint64_t last_processed_pos_; int dist_cache_[BROTLI_NUM_DISTANCE_SHORT_CODES]; int saved_dist_cache_[4]; uint16_t last_bytes_; uint8_t last_bytes_bits_; /* "Flint" is a tiny uncompressed block emitted before the continuation block to unwire literal context from previous data. Despite being int8_t, field is actually BrotliEncoderFlintState enum. */ int8_t flint_; uint8_t prev_byte_; uint8_t prev_byte2_; size_t storage_size_; uint8_t* storage_; Hasher hasher_; /* Hash table for FAST_ONE_PASS_COMPRESSION_QUALITY mode. */ int small_table_[1 << 10]; /* 4KiB */ int* large_table_; /* Allocated only when needed */ size_t large_table_size_; BrotliOnePassArena* one_pass_arena_; BrotliTwoPassArena* two_pass_arena_; /* Command and literal buffers for FAST_TWO_PASS_COMPRESSION_QUALITY. */ uint32_t* command_buf_; uint8_t* literal_buf_; uint64_t total_in_; uint8_t* next_out_; size_t available_out_; uint64_t total_out_; /* Temporary buffer for padding flush bits or metadata block header / body. */ union { uint64_t u64[2]; uint8_t u8[16]; } tiny_buf_; uint32_t remaining_metadata_bytes_; BrotliEncoderStreamState stream_state_; BROTLI_BOOL is_last_block_emitted_; BROTLI_BOOL is_initialized_; } BrotliEncoderStateStruct; typedef struct BrotliEncoderStateStruct BrotliEncoderStateInternal; #define BrotliEncoderState BrotliEncoderStateInternal #endif // BROTLI_ENC_STATE_H_ dvisvgm-3.5/libs/brotli/enc/static_dict.c000066400000000000000000000511751501401750600204770ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ #include "static_dict.h" #include "../common/dictionary.h" #include "../common/platform.h" #include "../common/transform.h" #include "encoder_dict.h" #include "find_match_length.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static BROTLI_INLINE uint32_t Hash(const uint8_t* data) { uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kDictHashMul32; /* The higher bits contain more mixture from the multiplication, so we take our results from there. */ return h >> (32 - kDictNumBits); } static BROTLI_INLINE void AddMatch(size_t distance, size_t len, size_t len_code, uint32_t* matches) { uint32_t match = (uint32_t)((distance << 5) + len_code); matches[len] = BROTLI_MIN(uint32_t, matches[len], match); } static BROTLI_INLINE size_t DictMatchLength(const BrotliDictionary* dictionary, const uint8_t* data, size_t id, size_t len, size_t maxlen) { const size_t offset = dictionary->offsets_by_length[len] + len * id; return FindMatchLengthWithLimit(&dictionary->data[offset], data, BROTLI_MIN(size_t, len, maxlen)); } static BROTLI_INLINE BROTLI_BOOL IsMatch(const BrotliDictionary* dictionary, DictWord w, const uint8_t* data, size_t max_length) { if (w.len > max_length) { return BROTLI_FALSE; } else { const size_t offset = dictionary->offsets_by_length[w.len] + (size_t)w.len * (size_t)w.idx; const uint8_t* dict = &dictionary->data[offset]; if (w.transform == 0) { /* Match against base dictionary word. */ return TO_BROTLI_BOOL(FindMatchLengthWithLimit(dict, data, w.len) == w.len); } else if (w.transform == 10) { /* Match against uppercase first transform. Note that there are only ASCII uppercase words in the lookup table. */ return TO_BROTLI_BOOL(dict[0] >= 'a' && dict[0] <= 'z' && (dict[0] ^ 32) == data[0] && FindMatchLengthWithLimit(&dict[1], &data[1], w.len - 1u) == w.len - 1u); } else { /* Match against uppercase all transform. Note that there are only ASCII uppercase words in the lookup table. */ size_t i; for (i = 0; i < w.len; ++i) { if (dict[i] >= 'a' && dict[i] <= 'z') { if ((dict[i] ^ 32) != data[i]) return BROTLI_FALSE; } else { if (dict[i] != data[i]) return BROTLI_FALSE; } } return BROTLI_TRUE; } } } /* Finds matches for a single static dictionary */ static BROTLI_BOOL BrotliFindAllStaticDictionaryMatchesFor( const BrotliEncoderDictionary* dictionary, const uint8_t* data, size_t min_length, size_t max_length, uint32_t* matches) { BROTLI_BOOL has_found_match = BROTLI_FALSE; #if defined(BROTLI_EXPERIMENTAL) if (dictionary->has_words_heavy) { const BrotliTrieNode* node = &dictionary->trie.root; size_t l = 0; while (node && l < max_length) { uint8_t c; if (l >= min_length && node->len_) { AddMatch(node->idx_, l, node->len_, matches); has_found_match = BROTLI_TRUE; } c = data[l++]; node = BrotliTrieSub(&dictionary->trie, node, c); } return has_found_match; } #endif /* BROTLI_EXPERIMENTAL */ { size_t offset = dictionary->buckets[Hash(data)]; BROTLI_BOOL end = !offset; while (!end) { DictWord w = dictionary->dict_words[offset++]; const size_t l = w.len & 0x1F; const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; const size_t id = w.idx; end = !!(w.len & 0x80); w.len = (uint8_t)l; if (w.transform == 0) { const size_t matchlen = DictMatchLength(dictionary->words, data, id, l, max_length); const uint8_t* s; size_t minlen; size_t maxlen; size_t len; /* Transform "" + BROTLI_TRANSFORM_IDENTITY + "" */ if (matchlen == l) { AddMatch(id, l, l, matches); has_found_match = BROTLI_TRUE; } /* Transforms "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "" and "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "ing " */ if (matchlen >= l - 1) { AddMatch(id + 12 * n, l - 1, l, matches); if (l + 2 < max_length && data[l - 1] == 'i' && data[l] == 'n' && data[l + 1] == 'g' && data[l + 2] == ' ') { AddMatch(id + 49 * n, l + 3, l, matches); } has_found_match = BROTLI_TRUE; } /* Transform "" + BROTLI_TRANSFORM_OMIT_LAST_# + "" (# = 2 .. 9) */ minlen = min_length; if (l > 9) minlen = BROTLI_MAX(size_t, minlen, l - 9); maxlen = BROTLI_MIN(size_t, matchlen, l - 2); for (len = minlen; len <= maxlen; ++len) { size_t cut = l - len; size_t transform_id = (cut << 2) + (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F); AddMatch(id + transform_id * n, len, l, matches); has_found_match = BROTLI_TRUE; } if (matchlen < l || l + 6 >= max_length) { continue; } s = &data[l]; /* Transforms "" + BROTLI_TRANSFORM_IDENTITY + */ if (s[0] == ' ') { AddMatch(id + n, l + 1, l, matches); if (s[1] == 'a') { if (s[2] == ' ') { AddMatch(id + 28 * n, l + 3, l, matches); } else if (s[2] == 's') { if (s[3] == ' ') AddMatch(id + 46 * n, l + 4, l, matches); } else if (s[2] == 't') { if (s[3] == ' ') AddMatch(id + 60 * n, l + 4, l, matches); } else if (s[2] == 'n') { if (s[3] == 'd' && s[4] == ' ') { AddMatch(id + 10 * n, l + 5, l, matches); } } } else if (s[1] == 'b') { if (s[2] == 'y' && s[3] == ' ') { AddMatch(id + 38 * n, l + 4, l, matches); } } else if (s[1] == 'i') { if (s[2] == 'n') { if (s[3] == ' ') AddMatch(id + 16 * n, l + 4, l, matches); } else if (s[2] == 's') { if (s[3] == ' ') AddMatch(id + 47 * n, l + 4, l, matches); } } else if (s[1] == 'f') { if (s[2] == 'o') { if (s[3] == 'r' && s[4] == ' ') { AddMatch(id + 25 * n, l + 5, l, matches); } } else if (s[2] == 'r') { if (s[3] == 'o' && s[4] == 'm' && s[5] == ' ') { AddMatch(id + 37 * n, l + 6, l, matches); } } } else if (s[1] == 'o') { if (s[2] == 'f') { if (s[3] == ' ') AddMatch(id + 8 * n, l + 4, l, matches); } else if (s[2] == 'n') { if (s[3] == ' ') AddMatch(id + 45 * n, l + 4, l, matches); } } else if (s[1] == 'n') { if (s[2] == 'o' && s[3] == 't' && s[4] == ' ') { AddMatch(id + 80 * n, l + 5, l, matches); } } else if (s[1] == 't') { if (s[2] == 'h') { if (s[3] == 'e') { if (s[4] == ' ') AddMatch(id + 5 * n, l + 5, l, matches); } else if (s[3] == 'a') { if (s[4] == 't' && s[5] == ' ') { AddMatch(id + 29 * n, l + 6, l, matches); } } } else if (s[2] == 'o') { if (s[3] == ' ') AddMatch(id + 17 * n, l + 4, l, matches); } } else if (s[1] == 'w') { if (s[2] == 'i' && s[3] == 't' && s[4] == 'h' && s[5] == ' ') { AddMatch(id + 35 * n, l + 6, l, matches); } } } else if (s[0] == '"') { AddMatch(id + 19 * n, l + 1, l, matches); if (s[1] == '>') { AddMatch(id + 21 * n, l + 2, l, matches); } } else if (s[0] == '.') { AddMatch(id + 20 * n, l + 1, l, matches); if (s[1] == ' ') { AddMatch(id + 31 * n, l + 2, l, matches); if (s[2] == 'T' && s[3] == 'h') { if (s[4] == 'e') { if (s[5] == ' ') AddMatch(id + 43 * n, l + 6, l, matches); } else if (s[4] == 'i') { if (s[5] == 's' && s[6] == ' ') { AddMatch(id + 75 * n, l + 7, l, matches); } } } } } else if (s[0] == ',') { AddMatch(id + 76 * n, l + 1, l, matches); if (s[1] == ' ') { AddMatch(id + 14 * n, l + 2, l, matches); } } else if (s[0] == '\n') { AddMatch(id + 22 * n, l + 1, l, matches); if (s[1] == '\t') { AddMatch(id + 50 * n, l + 2, l, matches); } } else if (s[0] == ']') { AddMatch(id + 24 * n, l + 1, l, matches); } else if (s[0] == '\'') { AddMatch(id + 36 * n, l + 1, l, matches); } else if (s[0] == ':') { AddMatch(id + 51 * n, l + 1, l, matches); } else if (s[0] == '(') { AddMatch(id + 57 * n, l + 1, l, matches); } else if (s[0] == '=') { if (s[1] == '"') { AddMatch(id + 70 * n, l + 2, l, matches); } else if (s[1] == '\'') { AddMatch(id + 86 * n, l + 2, l, matches); } } else if (s[0] == 'a') { if (s[1] == 'l' && s[2] == ' ') { AddMatch(id + 84 * n, l + 3, l, matches); } } else if (s[0] == 'e') { if (s[1] == 'd') { if (s[2] == ' ') AddMatch(id + 53 * n, l + 3, l, matches); } else if (s[1] == 'r') { if (s[2] == ' ') AddMatch(id + 82 * n, l + 3, l, matches); } else if (s[1] == 's') { if (s[2] == 't' && s[3] == ' ') { AddMatch(id + 95 * n, l + 4, l, matches); } } } else if (s[0] == 'f') { if (s[1] == 'u' && s[2] == 'l' && s[3] == ' ') { AddMatch(id + 90 * n, l + 4, l, matches); } } else if (s[0] == 'i') { if (s[1] == 'v') { if (s[2] == 'e' && s[3] == ' ') { AddMatch(id + 92 * n, l + 4, l, matches); } } else if (s[1] == 'z') { if (s[2] == 'e' && s[3] == ' ') { AddMatch(id + 100 * n, l + 4, l, matches); } } } else if (s[0] == 'l') { if (s[1] == 'e') { if (s[2] == 's' && s[3] == 's' && s[4] == ' ') { AddMatch(id + 93 * n, l + 5, l, matches); } } else if (s[1] == 'y') { if (s[2] == ' ') AddMatch(id + 61 * n, l + 3, l, matches); } } else if (s[0] == 'o') { if (s[1] == 'u' && s[2] == 's' && s[3] == ' ') { AddMatch(id + 106 * n, l + 4, l, matches); } } } else { /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL) transform. */ const BROTLI_BOOL is_all_caps = TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST); const uint8_t* s; if (!IsMatch(dictionary->words, w, data, max_length)) { continue; } /* Transform "" + kUppercase{First,All} + "" */ AddMatch(id + (is_all_caps ? 44 : 9) * n, l, l, matches); has_found_match = BROTLI_TRUE; if (l + 1 >= max_length) { continue; } /* Transforms "" + kUppercase{First,All} + */ s = &data[l]; if (s[0] == ' ') { AddMatch(id + (is_all_caps ? 68 : 4) * n, l + 1, l, matches); } else if (s[0] == '"') { AddMatch(id + (is_all_caps ? 87 : 66) * n, l + 1, l, matches); if (s[1] == '>') { AddMatch(id + (is_all_caps ? 97 : 69) * n, l + 2, l, matches); } } else if (s[0] == '.') { AddMatch(id + (is_all_caps ? 101 : 79) * n, l + 1, l, matches); if (s[1] == ' ') { AddMatch(id + (is_all_caps ? 114 : 88) * n, l + 2, l, matches); } } else if (s[0] == ',') { AddMatch(id + (is_all_caps ? 112 : 99) * n, l + 1, l, matches); if (s[1] == ' ') { AddMatch(id + (is_all_caps ? 107 : 58) * n, l + 2, l, matches); } } else if (s[0] == '\'') { AddMatch(id + (is_all_caps ? 94 : 74) * n, l + 1, l, matches); } else if (s[0] == '(') { AddMatch(id + (is_all_caps ? 113 : 78) * n, l + 1, l, matches); } else if (s[0] == '=') { if (s[1] == '"') { AddMatch(id + (is_all_caps ? 105 : 104) * n, l + 2, l, matches); } else if (s[1] == '\'') { AddMatch(id + (is_all_caps ? 116 : 108) * n, l + 2, l, matches); } } } } } /* Transforms with prefixes " " and "." */ if (max_length >= 5 && (data[0] == ' ' || data[0] == '.')) { BROTLI_BOOL is_space = TO_BROTLI_BOOL(data[0] == ' '); size_t offset = dictionary->buckets[Hash(&data[1])]; BROTLI_BOOL end = !offset; while (!end) { DictWord w = dictionary->dict_words[offset++]; const size_t l = w.len & 0x1F; const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; const size_t id = w.idx; end = !!(w.len & 0x80); w.len = (uint8_t)l; if (w.transform == 0) { const uint8_t* s; if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) { continue; } /* Transforms " " + BROTLI_TRANSFORM_IDENTITY + "" and "." + BROTLI_TRANSFORM_IDENTITY + "" */ AddMatch(id + (is_space ? 6 : 32) * n, l + 1, l, matches); has_found_match = BROTLI_TRUE; if (l + 2 >= max_length) { continue; } /* Transforms " " + BROTLI_TRANSFORM_IDENTITY + and "." + BROTLI_TRANSFORM_IDENTITY + */ s = &data[l + 1]; if (s[0] == ' ') { AddMatch(id + (is_space ? 2 : 77) * n, l + 2, l, matches); } else if (s[0] == '(') { AddMatch(id + (is_space ? 89 : 67) * n, l + 2, l, matches); } else if (is_space) { if (s[0] == ',') { AddMatch(id + 103 * n, l + 2, l, matches); if (s[1] == ' ') { AddMatch(id + 33 * n, l + 3, l, matches); } } else if (s[0] == '.') { AddMatch(id + 71 * n, l + 2, l, matches); if (s[1] == ' ') { AddMatch(id + 52 * n, l + 3, l, matches); } } else if (s[0] == '=') { if (s[1] == '"') { AddMatch(id + 81 * n, l + 3, l, matches); } else if (s[1] == '\'') { AddMatch(id + 98 * n, l + 3, l, matches); } } } } else if (is_space) { /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL) transform. */ const BROTLI_BOOL is_all_caps = TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST); const uint8_t* s; if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) { continue; } /* Transforms " " + kUppercase{First,All} + "" */ AddMatch(id + (is_all_caps ? 85 : 30) * n, l + 1, l, matches); has_found_match = BROTLI_TRUE; if (l + 2 >= max_length) { continue; } /* Transforms " " + kUppercase{First,All} + */ s = &data[l + 1]; if (s[0] == ' ') { AddMatch(id + (is_all_caps ? 83 : 15) * n, l + 2, l, matches); } else if (s[0] == ',') { if (!is_all_caps) { AddMatch(id + 109 * n, l + 2, l, matches); } if (s[1] == ' ') { AddMatch(id + (is_all_caps ? 111 : 65) * n, l + 3, l, matches); } } else if (s[0] == '.') { AddMatch(id + (is_all_caps ? 115 : 96) * n, l + 2, l, matches); if (s[1] == ' ') { AddMatch(id + (is_all_caps ? 117 : 91) * n, l + 3, l, matches); } } else if (s[0] == '=') { if (s[1] == '"') { AddMatch(id + (is_all_caps ? 110 : 118) * n, l + 3, l, matches); } else if (s[1] == '\'') { AddMatch(id + (is_all_caps ? 119 : 120) * n, l + 3, l, matches); } } } } } if (max_length >= 6) { /* Transforms with prefixes "e ", "s ", ", " and "\xC2\xA0" */ if ((data[1] == ' ' && (data[0] == 'e' || data[0] == 's' || data[0] == ',')) || (data[0] == 0xC2 && data[1] == 0xA0)) { size_t offset = dictionary->buckets[Hash(&data[2])]; BROTLI_BOOL end = !offset; while (!end) { DictWord w = dictionary->dict_words[offset++]; const size_t l = w.len & 0x1F; const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; const size_t id = w.idx; end = !!(w.len & 0x80); w.len = (uint8_t)l; if (w.transform == 0 && IsMatch(dictionary->words, w, &data[2], max_length - 2)) { if (data[0] == 0xC2) { AddMatch(id + 102 * n, l + 2, l, matches); has_found_match = BROTLI_TRUE; } else if (l + 2 < max_length && data[l + 2] == ' ') { size_t t = data[0] == 'e' ? 18 : (data[0] == 's' ? 7 : 13); AddMatch(id + t * n, l + 3, l, matches); has_found_match = BROTLI_TRUE; } } } } } if (max_length >= 9) { /* Transforms with prefixes " the " and ".com/" */ if ((data[0] == ' ' && data[1] == 't' && data[2] == 'h' && data[3] == 'e' && data[4] == ' ') || (data[0] == '.' && data[1] == 'c' && data[2] == 'o' && data[3] == 'm' && data[4] == '/')) { size_t offset = dictionary->buckets[Hash(&data[5])]; BROTLI_BOOL end = !offset; while (!end) { DictWord w = dictionary->dict_words[offset++]; const size_t l = w.len & 0x1F; const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; const size_t id = w.idx; end = !!(w.len & 0x80); w.len = (uint8_t)l; if (w.transform == 0 && IsMatch(dictionary->words, w, &data[5], max_length - 5)) { AddMatch(id + (data[0] == ' ' ? 41 : 72) * n, l + 5, l, matches); has_found_match = BROTLI_TRUE; if (l + 5 < max_length) { const uint8_t* s = &data[l + 5]; if (data[0] == ' ') { if (l + 8 < max_length && s[0] == ' ' && s[1] == 'o' && s[2] == 'f' && s[3] == ' ') { AddMatch(id + 62 * n, l + 9, l, matches); if (l + 12 < max_length && s[4] == 't' && s[5] == 'h' && s[6] == 'e' && s[7] == ' ') { AddMatch(id + 73 * n, l + 13, l, matches); } } } } } } } } return has_found_match; } /* Finds matches for one or more dictionaries, if multiple are present in the contextual dictionary */ BROTLI_BOOL BrotliFindAllStaticDictionaryMatches( const BrotliEncoderDictionary* dictionary, const uint8_t* data, size_t min_length, size_t max_length, uint32_t* matches) { BROTLI_BOOL has_found_match = BrotliFindAllStaticDictionaryMatchesFor( dictionary, data, min_length, max_length, matches); if (!!dictionary->parent && dictionary->parent->num_dictionaries > 1) { uint32_t matches2[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1]; int l; const BrotliEncoderDictionary* dictionary2 = dictionary->parent->dict[0]; if (dictionary2 == dictionary) { dictionary2 = dictionary->parent->dict[1]; } for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) { matches2[l] = kInvalidMatch; } has_found_match |= BrotliFindAllStaticDictionaryMatchesFor( dictionary2, data, min_length, max_length, matches2); for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) { if (matches2[l] != kInvalidMatch) { uint32_t dist = (uint32_t)(matches2[l] >> 5); uint32_t len_code = matches2[l] & 31; uint32_t skipdist = (uint32_t)((uint32_t)(1 << dictionary->words-> size_bits_by_length[len_code]) & ~1u) * (uint32_t)dictionary->num_transforms; /* TODO(lode): check for dist overflow */ dist += skipdist; AddMatch(dist, (size_t)l, len_code, matches); } } } return has_found_match; } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/static_dict.h000066400000000000000000000023731501401750600205000ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Class to model the static dictionary. */ #ifndef BROTLI_ENC_STATIC_DICT_H_ #define BROTLI_ENC_STATIC_DICT_H_ #include #include "../common/dictionary.h" #include "../common/platform.h" #include "encoder_dict.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN 37 static const uint32_t kInvalidMatch = 0xFFFFFFF; /* Matches data against static dictionary words, and for each length l, for which a match is found, updates matches[l] to be the minimum possible (distance << 5) + len_code. Returns 1 if matches have been found, otherwise 0. Prerequisites: matches array is at least BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1 long all elements are initialized to kInvalidMatch */ BROTLI_INTERNAL BROTLI_BOOL BrotliFindAllStaticDictionaryMatches( const BrotliEncoderDictionary* dictionary, const uint8_t* data, size_t min_length, size_t max_length, uint32_t* matches); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_STATIC_DICT_H_ */ dvisvgm-3.5/libs/brotli/enc/static_dict_lut.h000066400000000000000000016253161501401750600213750ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Lookup table for static dictionary and transforms. */ #ifndef BROTLI_ENC_STATIC_DICT_LUT_H_ #define BROTLI_ENC_STATIC_DICT_LUT_H_ #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif typedef struct DictWord { /* Highest bit is used to indicate end of bucket. */ uint8_t len; uint8_t transform; uint16_t idx; } DictWord; /* GENERATED CODE START */ static const int kDictNumBits = 15; static const uint32_t kDictHashMul32 = 0x1E35A7BD; static const uint16_t kStaticDictionaryBuckets[32768] = { 1,0,0,0,0,0,0,0,0,3,6,0,0,0,0,0,20,0,0,0,21,0,22,0,0,0,0,0,0,0,0,23,0,0,25,0,29, 0,53,0,0,0,0,0,0,55,0,0,0,0,0,0,61,76,0,0,0,94,0,0,0,0,0,0,96,0,97,0,98,0,0,0,0, 0,0,0,99,101,106,108,0,0,0,0,0,110,0,111,112,0,113,118,124,0,0,0,0,0,125,128,0,0 ,0,0,129,0,0,131,0,0,0,0,0,0,132,0,0,135,0,0,0,137,0,0,0,0,0,138,139,0,0,0,0,0,0 ,0,142,143,144,0,0,0,0,0,145,0,0,0,146,149,151,152,0,0,153,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,154,0,0,0,0,0,0,155,0,0,0,0,160,182,0,0,0,0,0,0,183,0,0,0,188,189,0,0, 192,0,0,0,0,0,0,194,0,0,0,0,0,0,0,0,197,202,209,0,0,210,0,224,0,0,0,225,0,0,0,0, 0,0,0,0,0,0,231,0,0,0,232,0,240,0,0,242,0,0,0,0,0,0,0,0,0,0,0,244,0,0,0,246,0,0, 249,251,253,0,0,0,0,0,258,0,0,261,263,0,0,0,267,0,0,268,0,269,0,0,0,0,0,0,0,0,0, 271,0,0,0,0,0,0,272,0,273,0,277,0,278,286,0,0,0,0,287,0,289,290,291,0,0,0,295,0, 0,296,297,0,0,0,0,0,0,0,0,0,0,298,0,0,0,299,0,0,305,0,324,0,0,0,0,0,327,0,328, 329,0,0,0,0,336,0,0,340,0,341,342,343,0,0,346,0,348,0,0,0,0,0,0,349,351,0,0,355, 0,363,0,364,0,368,369,0,370,0,0,0,0,0,0,0,372,0,0,0,0,0,0,0,0,0,0,0,373,0,375,0, 0,0,0,376,377,0,0,394,395,396,0,0,398,0,0,0,0,400,0,0,408,0,0,0,0,420,0,0,0,0,0, 0,421,0,0,422,423,0,0,429,435,436,442,0,0,443,0,444,445,453,456,0,457,0,0,0,0,0, 458,0,0,0,459,0,0,0,460,0,462,463,465,0,0,0,0,0,0,466,469,0,0,0,0,0,0,470,0,0,0, 474,0,476,0,0,0,0,483,0,485,0,0,0,486,0,0,488,491,492,0,0,497,499,500,0,501,0,0, 0,505,0,0,506,0,0,0,507,0,0,0,509,0,0,0,0,511,512,519,0,0,0,0,0,0,529,530,0,0,0, 534,0,0,0,0,543,0,0,0,0,0,0,0,0,0,553,0,0,0,0,557,560,0,0,0,0,0,0,561,0,564,0,0, 0,0,0,0,565,566,0,575,0,619,0,620,0,0,623,624,0,0,0,625,0,0,626,627,0,0,628,0,0, 0,0,630,0,631,0,0,0,0,0,0,0,0,0,641,0,0,0,0,643,656,668,0,0,0,673,0,0,0,674,0,0, 0,0,0,0,0,0,682,0,687,0,690,0,693,699,700,0,0,0,0,0,0,704,705,0,0,0,0,707,710,0, 711,0,0,0,0,726,0,0,729,0,0,0,730,731,0,0,0,0,0,752,0,0,0,762,0,763,0,0,767,0,0, 0,770,774,0,0,775,0,0,0,0,0,0,0,0,0,0,776,0,0,0,777,783,0,0,0,785,788,0,0,0,0, 790,0,0,0,793,0,0,0,0,794,0,0,804,819,821,0,827,0,0,0,834,0,0,835,0,0,0,841,0, 844,0,850,851,859,0,860,0,0,0,0,0,0,0,874,0,876,0,877,890,0,0,0,0,0,0,0,0,893, 894,898,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,0,0,900,904,906,0,0,0,907,0,908,909, 0,910,0,0,0,0,911,0,0,0,0,0,916,0,0,0,922,925,0,930,0,934,0,0,0,0,0,943,0,0,944, 0,953,954,0,0,0,0,0,0,955,0,962,963,0,0,976,0,0,977,978,979,980,0,981,0,0,0,0, 984,0,0,985,0,0,987,989,991,0,0,0,0,0,0,0,0,0,992,0,0,0,993,0,0,0,0,0,0,996,0,0, 0,1000,0,0,0,0,0,1002,0,0,0,0,1005,1007,0,0,0,1009,0,0,0,1010,0,0,0,0,0,0,1011,0 ,1012,0,0,0,0,1014,1016,0,0,0,1020,0,1021,0,0,0,0,1022,0,0,0,1024,0,0,0,0,0,0, 1025,0,0,1026,1027,0,0,0,0,0,1031,0,1033,0,0,0,0,1034,0,0,0,1037,1040,0,0,0,1042 ,1043,0,0,1053,0,1054,0,0,1057,0,0,0,1058,0,0,1060,0,0,0,0,0,0,0,1061,0,0,1062,0 ,0,0,0,1063,0,0,0,0,1064,0,0,0,0,0,1065,0,0,0,0,1066,1067,0,0,0,1069,1070,1072,0 ,0,0,0,0,0,1073,0,1075,0,0,0,0,0,0,1080,1084,0,0,0,0,1088,0,0,0,0,0,0,1094,0, 1095,0,1107,0,0,0,1112,1114,0,1119,0,1122,0,0,1126,0,1129,0,1130,0,0,0,0,0,1132, 0,0,0,0,0,0,1144,0,0,1145,1146,0,1148,1149,0,0,1150,1151,0,0,0,0,1152,0,1153,0,0 ,0,0,0,1154,0,1163,0,0,0,1164,0,0,0,0,0,1165,0,1167,0,1170,0,0,0,0,0,1171,1172,0 ,0,0,0,0,0,0,0,1173,1175,1177,0,1186,0,0,0,0,0,0,0,0,0,0,1195,0,0,1221,0,0,1224, 0,0,1227,0,0,0,0,0,1228,1229,0,0,1230,0,0,0,0,0,0,0,0,0,1231,0,0,0,1233,0,0,1243 ,1244,1246,1248,0,0,0,0,1254,1255,1258,1259,0,0,0,1260,0,0,1261,0,0,0,1262,1264, 0,0,1265,0,0,0,0,0,0,0,0,0,0,0,0,1266,0,1267,0,0,0,0,1273,1274,1276,1289,0,0, 1291,1292,1293,0,0,1294,1295,1296,0,0,0,0,1302,0,1304,0,0,0,0,0,0,0,0,0,1311, 1312,0,1314,0,1316,1320,1321,0,0,0,0,0,0,0,1322,1323,1324,0,1335,0,1336,0,0,0,0, 1341,1342,0,1346,0,1357,0,0,0,1358,1360,0,0,0,0,0,0,1361,0,0,0,1362,1365,0,1366, 0,0,0,0,0,0,0,1379,0,0,0,0,0,0,0,0,0,0,0,0,1386,0,1388,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,1395,0,0,0,0,1403,0,1405,0,0,1407,0,0,0,0,0,1408,1409,0,1410,0,0,0,1412,1413, 1416,0,0,1429,1451,0,0,1454,0,0,0,0,0,0,0,1455,0,0,0,0,0,0,0,1456,0,0,0,0,1459, 1460,1461,1475,0,0,0,0,0,0,1477,0,1480,0,1481,0,0,1486,0,0,1495,0,0,0,1496,0,0, 1498,1499,1501,1520,1521,0,0,0,1526,0,0,0,0,1528,1529,0,1533,1536,0,0,0,1537, 1538,1549,0,1550,1558,1559,1572,0,1573,0,0,0,0,0,0,0,0,0,1575,0,0,0,0,0,1579,0, 1599,0,1603,0,1604,0,1605,0,0,0,0,0,1608,1610,0,0,0,0,1611,0,1615,0,1616,1618,0, 1619,0,0,1622,0,0,0,0,1634,0,0,0,1635,0,0,0,1641,0,0,0,0,0,0,0,0,0,1643,0,0,0, 1650,0,0,1652,0,0,0,0,0,1653,0,0,0,1654,0,0,0,0,1655,0,1662,0,0,1663,1664,0,0, 1668,0,0,1669,1670,0,1672,1673,0,0,0,0,0,1674,0,0,0,1675,1676,1680,0,1682,0,0, 1687,0,0,0,0,0,1704,0,0,1705,0,0,1721,0,0,0,0,1734,1735,0,0,0,0,1737,0,0,0,0, 1739,0,0,1740,0,0,0,0,0,0,0,0,0,0,1741,1743,0,0,0,0,1745,0,0,0,1749,0,0,0,1751,0 ,0,0,0,0,0,1760,0,0,0,0,1765,0,0,0,0,0,1784,0,1785,1787,0,0,0,0,1788,1789,0,0,0, 0,1790,1791,1793,0,1798,1799,0,0,0,0,1801,0,1803,1805,0,0,0,1806,1811,0,1812, 1814,0,1821,0,0,0,0,0,1822,1833,0,0,0,0,0,0,1848,0,0,0,0,0,0,1857,0,0,0,1859,0,0 ,0,0,1861,0,0,0,0,0,0,0,1866,0,1921,1925,0,0,0,1929,1930,0,0,0,0,0,0,0,0,0,1931, 0,0,0,0,1932,0,0,0,1934,0,0,0,0,0,0,0,0,1946,0,0,1948,0,0,0,0,1950,0,1957,0,1958 ,0,0,0,0,0,1965,1967,0,0,0,0,1968,0,1969,0,1971,1972,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,1973,0,0,0,0,1975,0,0,0,0,1976,1979,0,1982,0,0,0,0,1984,1988,0,0,0,0,1990, 2004,2008,0,0,0,2012,2013,0,0,0,0,0,0,0,0,0,0,2015,0,2016,2017,0,0,0,0,2021,0,0, 2025,0,0,0,0,0,2029,2036,2040,0,2042,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2043,0,0,0,0,0, 2045,0,0,0,0,0,0,0,2046,2047,0,2048,2049,0,2059,0,0,2063,0,2064,2065,0,0,2066,0, 0,0,0,0,0,2069,0,0,0,0,2070,0,2071,0,2072,0,0,0,0,2080,2082,2083,0,0,0,0,0,2085, 0,2086,2088,2089,2105,0,0,0,0,2107,0,0,2116,2117,0,2120,0,0,2122,0,0,0,0,0,2123, 0,0,2125,2127,2128,0,0,0,2130,0,0,0,2137,2139,2140,2141,0,0,0,0,0,0,0,0,0,2144, 2145,0,0,2146,2149,0,0,0,0,2150,0,0,2151,2158,0,2159,0,2160,0,0,0,0,0,0,2161, 2162,0,0,2194,2202,0,0,0,0,0,0,2205,2217,0,2220,0,2221,0,2222,2224,0,0,0,0,2237, 0,0,0,0,0,2238,0,2239,2241,0,0,2242,0,0,0,0,0,2243,0,0,0,0,0,0,2252,0,0,2253,0,0 ,0,2257,2258,0,0,0,2260,0,0,0,0,0,0,0,2262,0,2264,0,0,0,0,0,2269,2270,0,0,0,0,0, 0,0,0,0,2271,0,2273,0,0,0,0,2277,0,0,0,0,2278,0,0,0,0,2279,0,2280,0,2283,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2287,0,0,0,0,0,0,0,2289,2290,0,0,0,0,2291,0,2292,0, 0,0,2293,2295,2296,0,0,0,0,0,0,0,2298,0,0,0,0,0,2303,0,2305,0,0,2306,0,2307,0,0, 0,0,0,0,0,0,0,0,0,0,2313,2314,2315,2316,0,0,2318,0,2319,0,2322,0,0,2323,0,2324,0 ,2326,0,0,0,0,0,0,0,2335,0,2336,2338,2339,0,2340,0,0,0,2355,0,2375,0,2382,2386,0 ,2387,0,0,2394,0,0,0,0,2395,0,2397,0,0,0,0,0,2398,0,0,0,0,0,0,0,2399,2402,2404, 2408,2411,0,0,0,2413,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2415,0,0,2416,2417,2419,0,2420, 0,0,0,0,0,2425,0,0,0,2426,0,0,0,0,0,0,0,0,0,0,0,0,2427,2428,0,2429,0,0,2430,2434 ,0,2436,0,0,0,0,0,0,2441,2442,0,2445,0,0,2446,2457,0,2459,0,0,2462,0,2464,0,2477 ,0,2478,2486,0,0,0,2491,0,0,2493,0,0,2494,0,2495,0,2513,2523,0,0,0,0,2524,0,0,0, 0,0,0,2528,2529,2530,0,0,2531,0,2533,0,0,2534,2535,0,2536,2537,0,2538,0,2539, 2540,0,0,0,2545,2546,0,0,0,0,0,0,0,2548,0,0,2549,0,2550,2555,0,0,0,0,0,2557,0, 2560,0,0,0,0,0,0,0,0,0,0,0,2561,0,2576,0,0,0,0,0,0,0,0,0,2577,2578,0,0,0,2579,0, 0,0,0,0,0,0,2580,0,0,0,0,2581,0,0,0,0,2583,0,2584,0,2588,2590,0,0,0,2591,0,0,0,0 ,2593,2594,0,2595,0,2601,2602,0,0,2603,0,2605,0,0,0,2606,2607,2611,0,2615,0,0,0, 2617,0,0,0,0,0,0,0,0,0,0,0,0,0,2619,0,0,2620,0,0,0,2621,0,2623,0,2625,0,0,2628, 2629,0,0,2635,2636,2637,0,0,2639,0,0,0,2642,0,0,0,0,2643,0,2644,0,2649,0,0,0,0,0 ,0,2655,2656,0,0,2657,0,0,0,0,0,2658,0,0,0,0,0,2659,0,0,0,0,2664,2685,0,2687,0, 2688,0,0,2689,0,0,2694,0,2695,0,0,2698,0,2701,2706,0,0,0,2707,0,2709,2710,2711,0 ,0,0,2720,2730,2735,0,0,0,0,2738,2740,0,0,0,0,2747,0,0,0,0,0,0,2748,0,0,2749,0,0 ,0,0,0,2750,0,0,2752,2754,0,0,0,0,0,2758,0,0,0,0,2762,0,0,0,0,2763,0,0,0,0,0,0,0 ,2764,2767,0,0,0,0,2768,0,0,2770,0,0,0,0,0,0,0,2771,0,0,0,0,0,0,0,0,0,2772,0,0,0 ,0,0,2773,2776,0,0,2783,0,0,2784,0,2789,0,2790,0,0,0,2792,0,0,0,0,0,0,0,0,0,0, 2793,2795,0,0,0,0,0,0,2796,0,0,0,0,0,0,2797,2799,0,0,0,0,2803,0,0,0,0,2806,0, 2807,2808,2817,2819,0,0,0,0,0,2821,0,0,0,0,2822,2823,0,0,0,0,0,0,0,2824,0,0,2828 ,0,2834,0,0,0,0,0,0,2836,0,2838,0,0,2839,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2841, 0,0,0,2842,0,0,0,0,0,2843,2844,0,0,0,0,2846,0,0,2847,0,2849,0,2853,0,0,0,0,0, 2857,0,0,0,0,2858,0,2859,0,0,2860,0,2862,2868,0,0,0,0,2875,0,2876,0,0,2877,2878, 2884,2889,2890,0,0,2891,0,0,2892,0,0,0,2906,2912,0,2913,0,0,0,0,0,0,0,0,2916,0, 2934,0,0,0,0,0,2935,0,0,0,0,2939,0,2940,0,0,0,0,0,0,0,2941,0,0,0,2946,0,2949,0,0 ,2950,2954,2955,0,0,0,2959,2961,0,0,2962,0,2963,0,0,0,0,0,0,2964,2965,2966,2967, 0,0,0,0,0,0,0,2969,0,0,0,0,0,2970,2975,0,2982,2983,2984,0,0,0,0,0,2989,0,0,2990, 0,0,0,0,0,0,0,2991,0,0,0,0,0,0,0,0,2998,0,3000,3001,0,0,3002,0,0,0,3003,0,0,3012 ,0,0,3022,0,0,3024,0,0,3025,3027,0,0,0,3030,0,0,0,0,3034,3035,0,0,3036,0,3039,0, 3049,0,0,3050,0,0,0,0,0,0,3051,0,3053,0,0,0,0,3057,0,3058,0,0,0,0,0,0,0,0,3063,0 ,0,3073,3074,3078,3079,0,3080,3086,0,0,0,0,0,0,0,0,3087,0,3092,0,3095,0,3099,0,0 ,0,3100,0,3101,3102,0,3122,0,0,0,3124,0,3125,0,0,0,0,0,0,3132,3134,0,0,3136,0,0, 0,0,0,0,0,3147,0,0,3149,0,0,0,0,0,3150,3151,3152,0,0,0,0,3158,0,0,3160,0,0,3161, 0,0,3162,0,3163,3166,3168,0,0,3169,3170,0,0,3171,0,0,0,0,0,0,0,3182,0,3184,0,0, 3188,0,0,3194,0,0,0,0,0,0,3204,0,0,0,0,3209,0,0,0,0,0,0,0,0,0,0,0,3216,3217,0,0, 0,0,0,0,0,3219,0,0,3220,3222,0,3223,0,0,0,0,3224,0,3225,3226,0,3228,3233,0,3239, 3241,3242,0,0,3251,3252,3253,3255,0,0,0,0,0,0,0,0,3260,0,0,3261,0,0,0,3267,0,0,0 ,0,0,0,0,0,3271,0,0,0,3278,0,3282,0,0,0,3284,0,0,0,3285,3286,0,0,0,0,0,0,0,3287, 3292,0,0,0,0,3294,3296,0,0,3299,3300,3301,0,3302,0,0,0,0,0,3304,3306,0,0,0,0,0,0 ,3308,0,0,0,0,0,0,0,0,0,3311,0,0,0,0,0,0,0,0,3312,3314,3315,0,3318,0,0,0,0,0,0,0 ,0,3319,0,0,0,0,0,3321,0,0,0,0,0,0,0,0,0,3322,0,0,3324,3325,0,0,3326,0,0,3328, 3329,3331,0,0,3335,0,0,3337,0,3338,0,0,0,0,3343,3347,0,0,0,3348,0,0,3351,0,0,0,0 ,0,0,3354,0,0,0,0,0,0,0,0,0,0,3355,0,0,3365,3366,3367,0,0,0,0,0,0,3368,3369,0, 3370,0,0,3373,0,0,3376,0,0,3377,0,3379,3387,0,0,0,0,0,3390,0,0,0,0,0,0,0,3402,0, 3403,3436,3437,3439,0,0,3441,0,0,0,3442,0,0,3449,0,0,0,3450,0,0,0,0,0,0,0,3451,0 ,0,3452,0,3453,3456,0,3457,0,0,3458,0,3459,0,0,0,0,0,0,0,0,0,3460,0,0,3469,3470, 0,0,3475,0,0,0,3480,3487,3489,0,3490,0,0,3491,3499,0,3500,0,0,3501,0,0,0,3502,0, 3514,0,0,0,3516,3517,0,0,0,3518,0,0,0,0,3520,3521,3522,0,0,3526,3530,0,0,0,0, 3531,0,0,0,0,3536,0,0,0,0,0,0,0,3539,3541,0,0,3542,3544,0,3547,3548,0,0,3550,0, 3553,0,0,0,0,0,0,0,3554,0,3555,0,3558,0,3559,0,0,0,0,0,0,0,0,3563,0,3581,0,0,0, 3599,0,0,0,3600,0,3601,0,3602,3603,0,0,3606,3608,0,3610,3611,0,0,0,0,0,0,0,0,0, 3612,3616,3619,0,0,0,0,0,0,0,0,0,0,0,0,0,3624,3628,0,3629,3634,3635,0,0,0,0,0,0, 3636,0,3637,0,0,3638,3651,0,0,0,0,0,0,3652,3653,0,0,0,0,3656,3657,0,0,0,0,0,3658 ,0,0,0,0,3659,0,3661,3663,3664,0,3665,0,3692,0,0,0,3694,3696,0,0,0,0,0,0,0,0,0,0 ,0,0,3698,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3700,0,0,3701,0,0,0,3708,3709,0,0,0,3711 ,3712,0,0,0,0,0,3723,0,3724,3725,0,0,3726,0,0,0,0,0,0,3728,3729,0,3734,3735,3737 ,0,0,0,3743,0,3745,0,0,3746,0,0,3747,3748,0,3757,0,3759,3766,3767,0,3768,0,0,0,0 ,3769,0,0,3771,0,3774,0,0,0,0,0,0,3775,0,0,0,0,0,0,3776,0,3777,3786,0,3788,3789, 0,0,0,0,0,0,0,0,0,3791,0,3811,0,0,0,0,0,3814,3815,3816,3820,0,0,0,0,0,0,0,3821,0 ,0,3825,0,0,0,0,3835,0,0,3848,3849,0,0,0,0,3850,3851,3853,0,0,0,0,3859,0,3860, 3862,0,0,0,0,0,3863,0,0,0,0,0,0,0,0,3873,0,3874,0,3875,3886,0,3887,0,0,0,0,3892, 3913,0,3914,0,0,0,3925,3931,0,0,0,0,3934,3941,3942,0,0,0,0,3943,0,0,0,3944,0,0,0 ,0,0,3945,0,3947,0,0,0,3956,3957,0,0,0,0,0,0,0,0,0,3958,0,3959,3965,0,0,0,0,3966 ,0,0,0,3967,0,0,0,3968,3974,0,0,0,0,0,3975,3977,3978,0,0,0,0,3980,0,3985,0,0,0,0 ,0,0,0,0,3986,4011,0,0,4017,0,0,0,0,0,0,0,0,0,0,0,4018,0,0,0,0,4019,0,4023,0,0,0 ,4027,4028,0,0,0,0,0,0,0,0,4031,4034,0,0,4035,4037,4039,4040,0,0,0,0,0,4059,0, 4060,4061,0,4062,4063,4066,0,0,4072,0,0,0,0,0,0,0,0,0,0,0,0,0,4088,0,0,0,0,0, 4091,0,0,0,0,4094,4095,0,0,4096,0,0,0,0,0,4098,4099,0,0,0,4101,0,4104,0,0,0,4105 ,4108,0,4113,0,0,4115,4116,0,4126,0,0,4127,0,0,0,0,0,0,0,4128,4132,4133,0,4134,0 ,0,0,4137,0,0,4141,0,0,0,0,4144,4146,4147,0,0,0,0,4148,0,0,4311,0,0,0,4314,4329, 0,4331,4332,0,4333,0,4334,0,0,0,4335,0,4336,0,0,0,4337,0,0,0,4342,4345,4346,4350 ,0,4351,4352,0,4354,4355,0,0,4364,0,0,0,0,4369,0,0,0,4373,0,4374,0,0,0,0,4377,0, 0,0,0,4378,0,0,0,4380,0,0,0,4381,4382,0,0,0,0,0,0,0,4384,0,0,0,0,4385,0,0,0,4386 ,0,0,0,4391,4398,0,0,0,0,4407,4409,0,0,0,0,4410,0,0,4411,0,4414,4415,4418,0,4427 ,4428,4430,0,4431,0,4448,0,0,0,0,0,4449,0,0,0,4451,4452,0,4453,4454,0,4456,0,0,0 ,0,0,0,0,4459,0,4463,0,0,0,0,0,4466,0,4467,0,4469,0,0,0,0,0,0,0,0,0,0,0,0,0,4470 ,4471,0,4473,0,0,4475,0,0,0,0,4477,4478,0,0,0,4479,4481,0,4482,0,4484,0,0,0,0,0, 0,0,4486,0,0,4488,0,0,4497,0,4508,0,0,4510,4511,0,4520,4523,0,4524,0,4525,0,4527 ,0,0,4528,0,0,0,0,4530,0,4531,0,0,4532,0,0,0,4533,0,0,0,0,0,4535,0,0,0,4536,0,0, 0,0,0,4541,4543,4544,4545,4547,0,4548,0,0,0,0,4550,4551,0,4553,0,0,0,0,4562,0,0, 4571,0,0,0,4574,0,0,0,4575,0,4576,0,4577,0,0,0,4581,0,0,0,0,0,4582,0,0,4586,0,0, 0,4588,0,0,4597,0,4598,0,0,0,0,4616,4617,0,4618,0,0,0,0,4619,0,4620,0,0,4621,0, 4624,0,0,0,0,0,4625,0,0,0,0,4657,0,4659,0,4667,0,0,0,4668,4670,0,4672,0,0,0,0,0, 4673,4676,0,0,0,0,4687,0,0,0,0,4697,0,0,0,0,4699,0,4701,0,0,0,0,4702,0,0,4706,0, 0,4713,0,0,0,4714,4715,4716,0,0,0,0,0,0,0,0,0,0,0,0,4717,0,0,4720,0,4721,4729, 4735,0,0,0,4737,0,0,0,4739,0,0,0,4740,0,0,0,4741,0,0,0,0,0,4742,0,4745,4746,4747 ,0,0,0,0,0,0,0,0,4748,0,0,0,4749,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4751, 4786,0,4787,0,4788,4796,0,0,4797,4798,0,4799,4806,4807,0,0,0,0,4809,4810,0,0,0,0 ,0,0,4811,0,0,0,0,0,4812,0,4813,0,0,4815,0,4821,4822,0,0,0,0,4823,0,0,0,0,0,0,0, 0,0,0,4824,0,0,0,0,4826,0,0,0,4828,0,4829,0,0,0,4843,0,0,4847,0,4853,4855,4858,0 ,0,0,0,0,4859,0,4864,0,0,4879,0,0,0,0,4880,0,0,0,0,4881,0,4882,0,0,0,0,0,0,0,0,0 ,4883,0,0,0,0,4884,0,0,0,0,0,4886,4887,4888,4894,4896,0,4902,0,0,4905,0,0,4915,0 ,0,0,0,0,0,0,4916,4917,4919,4921,0,0,0,0,0,4926,0,0,0,0,4927,0,0,0,0,0,0,0,0, 4929,0,4930,4931,0,4938,0,4952,0,4953,4957,4960,4964,0,0,0,0,0,0,0,5019,5020, 5022,0,0,0,0,0,5023,0,0,0,5024,0,0,0,5025,0,0,0,0,5028,0,0,0,0,5029,5030,5031,0, 5033,0,0,0,0,0,0,0,0,0,5034,5035,0,5036,0,0,5037,0,0,0,0,5038,0,0,5039,0,0,0, 5041,5042,0,0,0,0,5044,5049,5054,0,5055,0,5057,0,0,0,5060,0,0,0,0,0,5063,0,5064, 5065,0,5067,0,0,0,5068,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5076,0,0,0,0,0,0, 0,5077,0,0,5078,5080,0,0,5083,0,0,0,0,0,0,0,0,5085,0,0,0,0,0,0,5098,5099,5101, 5105,5107,0,5108,0,5109,0,0,0,0,0,0,0,5110,0,0,0,0,0,5117,5118,0,5121,0,5122,0,0 ,5130,0,0,0,5137,0,0,0,5148,0,0,0,0,0,0,0,5151,5154,0,0,0,5155,0,0,5156,5159, 5161,0,0,0,0,5162,0,0,0,0,5163,5164,0,5166,0,0,0,0,0,0,0,0,0,0,5167,0,0,0,5172,0 ,0,0,0,0,0,5178,5179,0,0,5190,0,0,5191,5192,5194,0,0,5198,5201,0,0,0,0,0,5203,0, 5206,5209,0,0,0,0,0,0,5213,0,5214,5216,0,0,0,0,0,5217,0,0,0,0,0,0,0,0,5218,5219, 0,5231,0,0,5244,5249,0,5254,0,5255,0,0,5257,0,0,0,0,0,5258,0,5260,5270,0,5277,0, 0,0,0,0,0,5280,5281,5282,5283,0,0,0,0,0,5284,0,5285,0,0,0,0,0,5287,5288,0,0,0,0, 0,0,0,0,0,0,5289,5291,0,0,5294,0,0,5295,0,0,0,0,0,0,0,5304,0,0,5306,5307,5308,0, 5309,0,0,5310,0,0,0,0,5311,5312,0,5313,0,0,0,0,0,5316,0,0,0,5317,0,0,0,0,0,0,0,0 ,0,5325,0,0,0,0,0,0,5326,0,5327,5329,0,5332,0,0,0,0,5338,0,0,0,0,0,0,0,0,5340,0, 0,5341,0,0,0,5342,0,5343,5344,0,0,5345,0,0,0,0,0,0,5347,5348,0,0,0,0,0,0,0,0,0, 5349,0,5350,0,5354,0,0,0,0,5358,0,0,5359,0,0,5361,0,0,5365,0,5367,0,5373,0,0,0, 5379,0,0,0,5380,0,0,0,5382,0,5384,0,0,0,0,0,0,5385,0,0,0,0,5387,0,0,0,0,0,0,5388 ,5390,5393,0,0,0,0,0,0,0,0,0,0,0,5396,0,0,0,0,5397,5402,0,0,0,0,0,5403,0,0,0, 5404,5405,0,0,0,0,0,0,0,0,0,0,0,0,5406,0,0,0,0,5410,0,0,5411,0,5415,0,0,0,0,5416 ,5434,0,0,0,0,0,0,0,0,0,0,0,5438,0,5440,0,0,0,0,0,0,5441,5442,0,0,0,5443,5444, 5447,0,0,5448,5449,5451,0,0,0,5456,5457,0,0,0,5459,0,0,0,5461,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,5464,0,5466,0,0,5467,0,5470,0,0,5473,0,0,5474,0,0,5476,0,0,0,0,0,0,0,0 ,0,0,0,5477,0,0,0,0,0,0,0,5484,0,0,5485,5486,0,0,0,0,0,5488,0,0,0,0,0,0,0,5489,0 ,0,0,0,0,5507,0,0,0,5510,0,5511,0,0,5512,0,0,0,5513,0,5515,0,0,5516,5517,0,5518, 0,0,5522,0,0,0,0,0,5534,5535,0,0,5536,0,5538,0,0,5543,0,5544,0,0,5545,0,5547,0, 5557,0,0,5558,0,5560,5567,0,0,0,0,5568,0,0,0,5571,5573,0,5574,0,5575,0,0,0,0, 5577,0,0,5598,0,0,0,0,0,0,0,0,0,5600,5609,0,0,0,0,5610,0,0,5612,0,5624,0,5625,0, 0,0,5629,0,5641,0,5642,5643,0,0,0,0,0,0,5651,0,0,0,5652,5653,0,5661,5662,5678,0, 5679,0,0,0,0,5685,5686,0,0,0,0,0,5690,5692,0,5703,0,0,0,0,0,5706,0,0,0,0,5707,0, 0,0,0,0,0,5708,0,0,5709,0,5710,0,0,0,5712,0,5733,0,5734,5735,0,0,5744,5751,0,0,0 ,0,0,0,0,0,0,0,0,0,5752,0,5754,0,0,0,0,0,0,5757,5758,0,5760,5761,0,0,0,0,5763, 5764,5765,0,5766,0,5767,5768,0,5770,0,0,0,0,5776,5780,0,0,0,0,5782,0,0,0,0,5784, 0,0,5788,0,0,0,0,0,0,0,0,0,0,0,5797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5799,0,0,5801, 0,0,0,5811,0,0,0,0,0,0,5816,0,0,5827,0,0,0,0,0,0,0,0,5830,5831,0,0,5832,0,0,5833 ,0,5835,5844,5845,0,5846,0,0,0,0,0,5850,0,0,0,0,0,5852,0,5855,5857,0,0,5859,0, 5861,0,0,5863,0,5865,0,0,0,5873,5875,0,0,0,5877,0,5879,0,0,0,5888,0,0,5889,5891, 0,5894,0,0,0,0,0,0,5895,0,5897,0,0,0,0,0,0,5907,0,5911,0,0,5912,0,5913,5922,5924 ,0,5927,5928,0,0,0,0,5929,5930,0,5933,0,0,0,0,5949,0,0,5951,0,0,0,0,0,0,0,0,5953 ,0,0,5954,0,5959,5960,5961,0,5964,0,0,0,5976,5978,5987,5990,0,0,0,0,0,5991,0, 5992,0,0,0,5994,5995,0,0,5996,0,0,6001,6003,0,0,0,0,6007,0,0,0,0,0,6008,0,0,6009 ,0,6010,0,0,0,6011,6015,0,6017,0,6019,0,6023,0,0,0,0,0,0,0,6025,0,0,0,0,0,0,0,0, 0,0,6026,0,6030,0,0,6032,0,0,0,6033,6038,6040,0,0,0,6041,6045,0,0,6046,0,0,6053, 0,0,6054,0,6055,0,0,0,0,0,0,6057,0,6063,0,0,0,6064,0,6066,6071,6072,0,0,0,0,0,0, 6075,6076,0,0,6077,0,0,0,0,0,0,0,0,0,6078,6079,0,0,0,0,0,0,0,0,6080,0,6083,0,0,0 ,0,0,6084,0,0,6088,0,6089,0,0,6093,6105,0,0,6107,0,6110,0,0,0,6111,6125,6126,0,0 ,0,6129,0,0,0,0,6130,0,0,0,6131,6134,0,0,0,0,0,0,6142,0,0,0,0,0,6144,0,0,6146, 6151,6153,0,6156,0,6163,0,6180,6181,0,0,0,0,0,6182,0,0,0,0,6184,6195,0,0,6206,0, 6208,0,0,6212,6213,6214,0,6215,0,0,0,6228,0,0,0,6234,0,0,0,0,0,0,6235,6240,0, 6242,6243,6244,0,6250,6255,0,0,0,0,0,6257,0,0,0,6258,6278,0,6284,0,0,0,6285,0,0, 0,0,0,0,0,0,6286,0,0,0,6320,0,0,6322,6332,0,0,0,0,0,0,0,0,6334,0,0,0,0,0,0,0, 6335,0,0,6337,0,6338,0,6339,6340,0,0,6356,6357,6369,0,0,0,6370,6371,6372,0,6373, 0,0,0,0,0,6376,0,0,0,0,0,6382,6383,6384,0,0,0,0,6386,0,6389,6397,6400,6411,0, 6414,0,0,0,0,0,0,0,6415,6416,0,0,0,0,0,0,6417,0,0,0,0,6418,0,0,0,0,0,0,0,6420,0, 6421,6423,6425,0,6429,6430,0,6433,6438,0,0,0,0,0,0,0,0,0,0,6439,6440,0,0,6441,0, 0,6444,0,0,0,0,6446,0,0,0,0,6447,6448,0,0,6450,0,0,0,6454,0,0,6455,0,6461,0,0,0, 0,0,0,6462,0,0,6463,0,6464,0,6465,6467,0,0,0,6468,0,6479,6480,0,0,0,0,0,0,0,6481 ,0,0,6485,6487,0,0,0,0,0,0,6493,0,0,0,0,0,0,0,0,6494,6495,6496,0,0,0,0,0,6498,0, 0,0,6507,6508,0,0,0,0,0,0,0,0,0,0,6511,6512,0,0,0,0,6513,0,0,0,6514,0,0,0,0,0, 6516,0,0,6517,6518,0,0,0,6519,6520,6521,0,6523,0,0,0,0,6524,6528,0,6530,0,0,6532 ,0,6578,0,0,0,6583,0,6584,0,0,0,6587,0,0,0,6590,0,6591,0,0,0,0,0,6592,0,0,0,0, 6593,6594,0,0,0,0,0,6599,6600,0,0,6601,6602,6604,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6608,0,0,0,0,0,0,0,0,6610,6611,0,6615,0,6616,6618,6620,0,6637,0,0,0,0,6639,0,0,0 ,0,6641,0,6642,0,0,0,6647,0,6660,6663,0,6664,0,6666,6669,0,6675,6676,6677,0,0,0, 0,0,0,0,0,0,6678,0,0,0,6679,0,6680,0,0,0,0,0,0,0,6693,0,0,0,0,0,0,0,0,0,6704, 6705,6706,0,0,6711,6713,0,0,0,0,0,6716,0,0,0,6717,0,6719,6724,0,0,0,0,0,0,0,0, 6725,6726,0,0,0,0,0,6728,6729,6735,0,6737,6742,0,0,6743,6750,0,6751,0,0,6752, 6753,0,0,0,0,0,0,6754,0,0,0,0,0,6756,0,0,0,0,0,0,6763,0,0,6764,6765,0,0,0,6770,0 ,0,0,6776,6780,0,6781,0,0,0,6783,0,6784,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6785,0,0,0,6792,0,0,0,6793,0,0,6802,0,0,0,0,0,6803,0,0,0,6804,0,0,0,6812,0,0, 6823,0,6824,6839,0,0,0,0,6852,0,0,6854,0,6856,6857,0,0,0,0,0,0,0,0,0,6867,0,6868 ,6870,6872,0,0,0,6873,6874,0,0,0,0,0,6875,0,0,6877,0,0,0,0,0,0,0,6878,0,0,0,6879 ,0,6880,0,0,0,0,0,0,0,0,0,0,6887,0,6888,6891,6893,0,6895,0,0,0,0,0,0,0,0,6899,0, 0,0,0,6901,0,0,0,0,6910,0,6911,0,0,6912,0,0,6913,6914,0,0,0,6915,0,0,0,6916,6919 ,0,0,0,0,0,0,6924,0,6925,0,0,0,6926,6927,6928,0,6929,0,6930,0,0,6931,6935,0,6936 ,0,0,0,0,6939,6940,6941,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6942,6948,6949,0,0,0,0,0,0 ,0,6952,6954,6963,6965,6966,0,0,6967,6968,0,0,0,0,0,0,0,0,0,6969,0,0,6970,6979,0 ,0,6980,0,0,6983,0,0,0,0,0,6984,0,0,0,0,0,0,0,6988,6990,6992,0,0,0,0,0,0,0,6995, 0,0,0,7012,0,0,0,0,0,0,0,0,0,7019,0,0,0,0,0,0,0,0,7021,0,0,7022,7023,7028,0,7030 ,7033,0,0,0,0,0,0,7038,0,0,0,0,0,0,0,0,0,0,7039,0,0,0,0,0,7046,0,7047,0,0,0,0,0, 0,0,0,0,0,0,7048,7052,0,0,0,0,0,7054,0,7060,0,0,0,0,7061,0,7065,0,0,0,0,7067, 7069,0,7070,7071,7072,0,0,7078,0,7080,7081,0,7083,0,0,0,7084,7087,7088,0,0,7090, 0,7093,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7107,0,0,7108,0,0,0,0,0,0,0,0,7110,0,7114,0 ,0,0,0,0,0,0,7115,0,7116,0,0,0,0,0,7117,0,0,7118,0,0,7124,0,7125,0,0,7126,0,0,0, 0,7128,0,0,0,0,0,7129,0,7130,0,7132,7133,0,0,7134,0,0,7139,0,7148,7150,0,0,0,0, 7152,0,0,0,7153,7156,7157,0,0,0,0,0,7158,0,0,0,0,0,0,0,0,0,0,7163,7165,7169,0, 7171,0,0,0,0,0,0,0,0,0,7172,0,7173,7181,0,0,0,0,0,7182,7185,0,0,0,0,7187,0,7201, 7204,0,0,0,0,0,7206,7207,0,0,0,0,7211,7216,0,7218,0,0,0,0,7226,7228,7230,7232, 7233,7235,7237,0,0,0,0,7238,7241,0,7242,0,0,7247,0,0,0,7266,0,0,0,0,0,0,0,7289,0 ,0,7290,7291,0,0,7292,0,7297,0,0,0,0,0,0,0,0,0,0,7300,0,7301,0,0,0,0,0,0,0,0,0,0 ,0,0,7302,0,0,0,0,7305,0,0,0,0,7307,0,7308,0,7310,0,7335,0,0,0,0,0,0,0,7337,0, 7343,7347,0,0,0,0,0,7348,0,7349,7350,7352,7354,0,0,0,0,7357,0,7358,7366,0,7367, 7368,0,0,7373,0,0,0,7374,0,0,0,0,0,0,0,7376,0,0,0,7377,0,0,0,0,0,7378,0,7379, 7380,0,0,0,0,0,7383,0,0,7386,0,0,0,0,7398,0,0,0,7399,7400,0,7401,0,0,0,0,0,0,0, 7402,0,0,0,0,0,7405,0,0,0,0,0,7406,0,0,0,0,0,0,0,0,7421,7427,7429,0,0,0,7435,0,0 ,7436,0,0,0,7437,0,0,0,0,0,0,7438,7443,0,7446,0,7448,0,0,0,0,0,0,0,0,0,0,7456,0, 0,0,0,0,7457,0,0,7461,0,0,0,0,0,7462,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7463,7466,7472, 0,7476,0,0,7490,0,7491,0,0,7493,0,0,0,7498,7499,0,0,7508,0,0,0,0,0,7512,0,0,0, 7513,7514,7516,0,0,0,0,7518,0,0,7519,7521,7522,0,0,0,7526,0,0,7529,0,0,7531,0, 7536,0,7538,0,7539,0,0,7541,7542,7546,0,0,0,0,0,7547,0,7548,0,0,0,0,0,7550,0,0, 7552,7553,0,0,0,0,0,0,0,0,0,0,7554,7563,0,7573,0,0,0,0,0,0,7574,7576,0,7578,7581 ,7583,0,0,0,7584,0,7587,0,0,0,0,0,7589,0,0,0,7594,0,0,7595,0,0,7600,7602,7610,0, 0,0,0,0,7612,0,7613,7614,0,0,7615,0,0,7616,0,7620,0,7621,7622,0,7623,0,0,0,0, 7626,0,0,0,0,7627,7629,7631,0,0,7633,0,0,0,0,0,7639,0,7640,7642,0,0,7643,0,0,0,0 ,7644,0,0,0,0,0,0,0,7645,0,0,0,0,0,7661,7662,7663,7665,0,7666,0,7667,0,7684,7688 ,7690,0,7691,0,0,0,0,0,0,7692,0,0,7700,0,7707,0,7708,0,7709,0,7721,0,0,0,7722,0, 7724,0,0,0,0,0,0,7729,7731,0,7732,0,7733,7735,0,0,0,0,0,0,0,7739,0,0,7741,7745,0 ,7748,0,0,0,7751,0,0,0,7752,0,0,0,0,0,0,0,7753,0,0,7756,0,7757,0,7759,0,7760,0,0 ,0,0,7761,7768,0,0,7769,0,0,7770,0,0,7771,0,0,7772,0,0,7773,0,0,0,0,0,7778,7783, 0,0,0,0,0,7784,7785,0,7790,0,0,0,0,7792,0,7798,0,0,0,0,0,7799,0,7810,0,0,7813,0, 7814,0,7816,0,7818,7824,7825,7826,0,7828,7830,0,0,0,7840,0,7842,0,7843,0,0,0,0, 7844,0,0,0,0,0,0,0,7846,0,0,0,0,0,7856,7857,7858,7862,0,7865,0,0,7866,0,0,7913,0 ,0,0,0,7914,0,0,7915,7917,7918,7919,0,7920,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7921, 7922,0,7924,0,0,7925,0,0,7927,0,7930,7935,0,0,7937,0,0,0,0,0,0,7939,0,7940,0,0,0 ,0,0,7941,0,0,0,0,7945,0,0,0,0,7949,0,0,0,0,0,0,0,0,7950,0,7953,0,0,0,0,0,0,0, 7968,0,0,0,0,7969,7972,7992,0,7993,0,0,0,0,0,0,0,0,0,0,0,7994,0,0,0,0,8007,8008, 0,0,0,0,0,0,0,0,0,0,0,0,8010,0,0,0,8012,0,0,0,0,0,0,0,0,8018,0,8028,8029,0,0, 8030,0,0,8032,8033,0,0,8034,8036,0,0,0,0,0,0,0,0,0,0,8037,0,0,0,8043,8052,8059, 8060,0,0,8061,0,0,0,8062,0,8063,0,8064,0,8066,8068,0,0,0,8080,8081,0,8089,0,0,0, 0,0,8092,0,0,0,0,0,0,8093,8110,0,0,0,0,0,0,0,8111,0,0,0,0,0,8112,8115,0,8117,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8120,8121,8122,8128,8129,8130,8131,0,0,8139,0,0, 8144,0,0,0,0,8145,8146,8153,0,0,0,0,0,0,0,0,8154,0,8157,8160,8162,0,8164,8165,0, 0,0,0,8166,8167,0,0,8179,0,0,0,8185,0,0,0,8186,0,0,8187,0,0,0,8188,0,0,0,0,0, 8204,0,0,0,0,8210,0,0,0,0,0,8213,0,8214,0,0,8215,0,0,0,0,0,0,8218,0,0,0,0,0,0,0, 0,0,8219,0,8221,0,0,8222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8225,0,0,0,8233,0,0, 8242,0,0,0,0,0,0,0,0,0,0,0,8247,0,8248,8252,0,8256,8257,0,0,8261,0,8264,8265,0,0 ,0,0,8267,0,0,0,8269,0,0,0,0,0,0,0,0,0,8270,0,0,0,8278,0,8279,8283,0,0,8285,8286 ,8289,8292,0,0,0,0,8293,8295,8299,8300,8301,0,0,0,0,0,0,8304,8307,0,0,0,0,0,0,0, 8321,0,0,0,8322,8323,8325,8326,8327,0,0,8332,8338,0,0,8340,0,0,0,0,0,8350,0,0, 8351,0,8354,8355,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8360,8372,0,0,0,0,0,0,0,0,8377,0,0, 0,0,8380,0,0,0,8383,0,8384,0,0,0,0,8386,8392,0,0,8394,0,0,0,0,0,0,0,8396,8397,0, 8398,0,8399,0,0,0,0,0,8400,0,8401,8410,8411,0,8412,8413,8422,0,0,0,0,8423,0,0,0, 0,8424,0,0,8425,0,0,0,0,0,0,0,8441,8442,0,0,0,0,0,0,8443,0,0,8444,0,8447,0,0,0,0 ,8451,0,8458,0,8462,0,0,8468,0,8469,0,0,0,8470,0,8473,8479,8480,0,0,0,0,8481, 8483,0,0,0,0,0,0,0,0,0,8484,0,0,8490,0,0,0,0,0,0,8491,8493,8494,0,8528,0,0,0,0,0 ,0,0,8530,0,0,0,0,0,0,0,0,8534,8538,8540,0,0,8541,0,0,8545,0,8557,0,0,8569,8570, 0,0,8571,8574,8575,8579,0,8583,0,0,0,0,8591,0,0,0,0,0,0,0,0,8606,0,8607,0,0,0,0, 0,0,0,0,0,8608,0,0,8609,0,0,0,8610,0,0,0,8611,0,0,8613,8617,8621,0,0,8622,0,8623 ,0,8624,8625,0,0,0,0,0,0,0,0,0,8637,8638,8639,8650,0,0,0,0,8652,8654,8655,0,0,0, 0,0,0,0,0,0,0,8656,0,0,0,0,0,8657,0,0,0,0,0,0,0,0,0,8658,0,0,8659,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,8660,0,0,0,0,0,0,8661,8663,8664,0,0,0,0,8665,0,8669,0, 0,0,0,0,0,0,8671,8674,0,8684,0,8686,0,0,0,8689,0,0,0,8690,0,8706,0,0,0,0,0,0,0,0 ,0,0,0,8710,0,8711,8713,8714,8724,8727,8728,8733,8736,0,8737,8739,0,0,0,0,8742, 8743,8745,8754,0,0,0,0,8756,0,0,0,0,0,0,8757,8760,0,0,0,0,0,8762,8763,8764,0, 8766,8769,8770,8773,0,8774,0,8779,0,0,0,0,8780,0,0,8781,0,0,8783,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8784,0,0,0,0,0,0,0,0,8785,0,0,0,0,8786,0,0,0,0,8788 ,8790,0,0,0,8803,0,8813,8814,0,0,0,0,0,8815,8816,0,0,0,0,8818,0,0,0,0,8822,8828, 8829,0,8831,0,0,0,0,8833,0,0,0,8834,0,0,0,8835,0,8836,0,0,0,8837,0,0,0,0,0,0, 8838,8839,0,0,0,0,0,0,0,0,0,0,0,8840,0,0,0,8841,0,8842,0,0,0,8846,0,0,0,0,0,0,0, 8847,0,8848,0,0,8864,0,0,8866,0,0,8870,8872,0,0,8873,8874,0,0,0,0,0,0,8875,0, 8876,0,0,0,0,8896,8900,0,0,0,0,8901,0,0,0,0,0,8904,0,8907,0,0,0,0,8911,8912,8913 ,0,0,0,8914,0,8915,0,0,0,0,0,0,0,0,0,0,0,0,8916,0,0,0,8929,0,0,0,0,0,0,0,0,0,0, 8930,0,8932,0,8943,0,0,0,8945,8947,0,0,0,0,8949,0,8950,0,8954,8957,0,0,8970,0,0, 0,0,8971,0,8996,0,0,0,0,8997,9000,0,0,0,0,9001,9002,0,9004,9009,9024,0,0,0,0,0,0 ,0,0,0,0,0,0,9027,9082,0,0,9083,9089,0,0,0,0,0,0,9090,0,0,0,9092,0,0,9093,0,9095 ,0,0,9096,9097,9101,9102,0,0,0,0,0,0,0,0,9112,0,0,0,0,0,0,9114,0,0,9120,0,9121, 9122,0,0,0,9123,9124,0,0,9125,0,0,9126,0,9127,0,0,9129,9131,0,0,0,9132,0,0,9136, 0,9144,0,0,9148,0,0,0,0,0,0,9149,0,9152,9163,0,0,9165,0,0,0,0,0,0,0,0,0,0,0,0,0, 9166,0,9169,0,0,0,0,0,0,0,9170,0,0,0,0,9172,0,9174,9175,9176,0,9177,0,0,0,0,0,0, 0,0,9186,0,9187,0,0,0,9188,9189,0,0,9190,0,0,0,0,9191,0,0,0,9193,0,0,0,0,9197, 9198,0,0,0,9208,9211,0,0,0,0,9216,9217,0,9220,0,0,0,0,9221,9222,9223,0,9224,9225 ,0,0,9227,0,9228,9229,0,0,9230,0,9232,0,9233,0,0,0,0,0,9234,9235,0,0,9237,0,0,0, 0,0,0,0,0,9238,9240,0,0,9241,0,0,0,0,9244,0,0,0,0,9247,0,0,0,0,0,0,0,0,0,0,9248, 0,0,0,9249,0,0,0,0,0,9250,0,0,0,0,9251,0,0,9252,9255,0,0,0,9256,0,0,0,0,0,0,0, 9257,0,0,9258,0,0,0,0,0,0,9259,0,0,0,0,0,9262,9263,0,0,9265,9266,0,0,0,0,0,0,0,0 ,9268,9271,0,0,0,0,0,0,0,0,0,9273,0,0,0,9276,9277,9279,0,0,0,0,0,0,0,9280,0,0, 9293,0,0,0,0,0,9297,9301,0,0,0,0,0,0,0,0,0,0,0,9308,9309,9313,9321,9322,0,9326, 9327,0,0,9477,0,9479,0,0,0,0,9482,0,0,0,9483,0,9484,0,0,0,0,0,0,0,0,0,9485,0,0, 9486,0,0,0,9489,0,0,0,0,9490,9491,0,0,0,0,9493,0,9495,9496,0,0,0,0,0,0,0,0,9500, 0,9502,0,0,0,0,0,9504,9507,0,9509,0,9511,0,0,9513,0,0,0,0,0,0,0,0,9515,0,0,0,0,0 ,0,9516,9517,0,0,0,0,9532,0,0,9533,0,0,9538,0,9539,9540,0,0,0,0,9541,0,0,0,9542, 0,0,0,0,0,0,0,0,9544,9545,0,9546,0,0,0,0,0,0,9547,9548,0,0,0,9550,0,9557,0,9558, 0,9561,0,9563,9570,0,9572,9574,9575,0,0,0,9577,9592,0,0,9596,0,0,0,9598,0,9600,0 ,9601,0,0,0,0,0,0,9608,0,9638,9639,0,0,0,0,0,0,0,9641,0,0,9643,9644,9645,9646,0, 0,0,9648,0,0,0,0,0,0,0,9650,9654,0,0,0,0,0,0,0,0,9655,0,0,0,0,0,9656,0,9657,0,0, 0,0,9658,0,0,9659,0,0,9664,0,0,9665,0,9667,9669,0,0,0,0,0,0,0,0,0,0,0,0,9671,0, 9673,9681,0,0,0,0,9682,9683,9684,0,0,0,0,9686,9698,0,0,9700,9701,9702,0,9703, 9717,0,0,0,0,9718,0,9726,0,0,0,0,9727,0,0,0,9728,0,9742,0,9744,0,0,0,9750,0,9754 ,9755,0,0,0,0,0,9756,0,9757,9768,0,9769,0,0,0,9770,9771,0,9773,0,9774,0,9775,0,0 ,0,9776,9777,9784,0,0,0,9786,0,9789,0,0,0,0,9793,9794,0,0,0,9808,0,0,0,0,0,9811, 0,0,0,0,0,0,0,0,0,0,0,0,9812,0,9820,0,9823,0,9828,0,0,0,0,9830,0,0,9833,9836,0,0 ,0,9840,0,0,0,9841,0,0,9842,0,9845,0,0,0,9847,9848,0,0,9855,0,0,0,0,0,0,9856, 9863,9865,0,0,0,0,0,0,0,0,9866,9867,9868,9873,9875,0,0,0,0,0,0,9880,0,9886,0,0,0 ,9887,0,0,9891,0,0,0,0,0,0,0,9906,9907,9908,0,0,0,9909,0,0,0,0,0,0,9910,0,0,0,0, 9913,0,0,0,0,9914,0,0,0,0,0,9922,0,0,0,0,9923,9925,0,0,0,0,0,0,9930,0,0,0,9931,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9932,0,9939,0,0,9940,9962,9966,0,9969,9970,0,0,9974 ,0,9979,9981,9982,0,0,0,9985,0,0,0,0,0,0,9987,0,0,0,0,0,0,0,9988,9993,0,0,9994,0 ,0,0,9997,0,10004,0,0,0,0,0,10007,10019,10020,10022,0,0,0,10031,0,0,0,0,0,10032, 0,0,10034,0,10036,0,0,0,0,10038,0,10039,10040,10041,10042,0,0,0,0,0,10043,0,0,0, 0,0,10045,10054,0,0,0,0,10055,0,0,10057,10058,0,0,0,0,0,0,10059,0,0,0,0,0,0,0, 10060,0,0,0,0,0,0,0,10063,0,10066,0,0,0,10070,0,10072,0,0,10076,10077,0,0,10084, 0,10087,10090,10091,0,0,0,10094,10097,0,0,0,0,0,0,10098,0,0,0,0,0,0,10103,0, 10104,0,10108,0,0,0,0,0,0,0,0,10120,0,0,0,10122,0,0,10125,0,0,0,0,10127,10128,0, 0,10134,0,10135,10136,0,10137,0,0,10147,0,10149,10150,0,0,10156,0,10158,10159, 10160,10168,0,0,10171,0,10173,0,0,0,10176,0,0,0,0,10177,0,0,0,0,10178,0,0,0,0, 10194,0,10202,0,0,10203,10204,0,10205,10206,0,10207,0,0,0,0,10209,0,0,0,0,0,0,0, 10213,0,0,0,0,0,0,10217,0,10229,0,10230,10231,0,0,10232,0,0,10237,10238,10244,0, 0,0,0,0,10250,0,10252,0,0,0,0,0,0,10255,0,0,10257,0,0,0,0,0,0,10258,0,10259,0,0, 0,0,0,0,0,0,10260,0,0,0,0,0,0,0,10284,10288,10289,0,0,0,10290,0,10296,0,0,0,0,0, 10297,0,0,0,0,0,0,10298,0,0,0,0,10299,10303,0,0,0,0,0,10306,0,0,0,10307,0,10308, 0,0,0,0,10311,0,0,0,0,0,0,0,10315,10317,0,0,0,10318,10319,0,10321,0,10326,0, 10328,0,0,0,0,10329,0,0,10331,0,10332,0,0,0,0,0,0,10334,0,0,10335,10338,0,0,0,0, 0,10339,10349,0,0,0,0,0,0,10351,0,10353,0,0,0,0,0,0,10362,0,10368,0,10369,0,0,0, 10372,10373,0,0,0,0,0,10374,0,0,0,10375,0,10376,0,0,10386,10388,10390,0,0,0,0,0, 0,0,10391,0,0,10392,10394,0,0,10396,0,10397,0,10403,0,0,0,0,0,0,0,0,10404,0, 10405,10410,0,0,10411,0,10412,0,0,0,0,0,0,0,10421,10422,10423,0,0,0,0,0,0,0,0,0, 10425,0,0,10427,0,0,10430,0,0,0,0,0,10432,0,10433,10434,0,0,0,0,10436,10437,0, 10438,0,10439,0,10444,10446,0,0,0,0,0,10448,0,0,0,0,0,10449,0,0,0,0,0,0,0,10451, 0,10453,0,0,0,10454,10457,0,0,10459,0,10469,0,0,0,0,0,10472,10481,0,0,0,0,0, 10482,10483,0,10492,0,0,0,0,0,0,0,0,0,0,10499,0,0,0,10502,0,0,10510,0,10521, 10524,0,0,10525,10526,10528,0,0,0,0,0,0,0,0,10530,0,0,0,0,10533,0,10534,0,0,0,0, 0,0,0,0,0,0,10535,10536,0,0,10544,0,10553,10556,0,10557,10559,0,0,0,0,0,10562, 10563,10564,0,10565,0,0,0,10566,0,10567,0,0,0,0,10575,0,0,10576,0,10578,0,0,0,0, 0,0,0,0,0,0,10585,10586,10587,10589,0,10590,0,0,10594,0,0,0,0,0,10598,0,0,10601, 0,0,0,10602,0,10603,0,10604,0,10605,0,0,10607,0,10626,0,10627,0,0,0,0,0,10629, 10630,10631,0,0,0,10646,0,0,0,10647,0,10650,0,10651,0,0,0,10652,10653,10655,0, 10658,0,0,10659,0,10667,0,0,0,0,10669,0,0,0,0,0,0,0,0,0,10670,0,0,0,10671,0,0,0, 0,10672,10673,0,10674,0,0,0,10676,0,0,0,0,0,0,10678,0,10682,0,0,10692,0,10697,0, 0,0,0,10698,0,0,0,10700,0,0,0,0,0,10703,0,10704,0,0,0,0,0,0,0,10705,0,10715, 10718,10720,0,0,10722,0,0,0,0,0,0,0,0,10723,0,0,0,0,10726,0,0,0,0,0,10727,10730, 10743,0,0,0,0,0,0,10744,0,0,10745,0,0,0,0,0,0,10748,0,0,0,0,10750,0,0,10752, 10753,0,0,0,10756,0,0,0,0,0,0,10758,0,0,0,10759,0,10769,0,0,10772,0,0,0,0,0,0, 10773,0,0,0,10777,0,0,10779,0,0,0,0,0,0,0,0,10780,10784,0,0,0,10789,0,0,0,10791, 0,0,0,0,0,0,0,0,0,10795,0,0,10796,0,10808,0,10809,0,0,0,10810,0,0,0,10812,0,0, 10814,0,0,0,0,0,0,0,0,0,10815,0,0,0,0,10816,10817,0,0,0,0,10819,0,10820,0,0,0,0, 10821,10822,10823,0,10826,10849,0,0,0,0,10850,0,0,10852,0,10853,0,0,10856,0,0, 10857,10858,10859,10860,0,0,0,0,0,0,10863,0,10866,10867,10872,10890,0,0,10891, 10892,0,0,0,0,0,10893,0,0,0,10896,10899,0,0,10900,10902,0,0,0,0,0,10903,0,0,0,0, 0,0,0,0,0,0,0,0,10905,0,10906,0,0,0,0,10908,10911,0,10912,0,0,10916,0,0,0,0,0, 10917,0,10918,0,0,0,10923,0,0,0,0,0,10924,0,0,10928,10929,0,0,10930,0,0,0,10932, 0,0,0,0,10939,0,0,10945,0,0,0,10947,0,0,10948,0,0,0,0,0,0,0,0,0,0,0,0,10958,0, 10960,10962,0,0,10964,0,0,0,10966,0,0,0,0,0,0,0,0,0,0,10967,0,0,0,10968,0,0,0, 10973,0,0,0,0,0,10975,0,0,0,10976,10978,0,0,10982,10984,10987,0,0,10988,0,10989, 0,0,10991,0,0,0,0,10992,0,0,0,10993,0,10995,0,0,0,10996,10997,0,0,0,10998,0, 10999,0,11001,0,0,0,0,0,0,11010,11012,0,11013,11016,11017,0,0,11019,11020,11021, 0,0,0,0,0,0,0,0,0,0,0,0,11022,0,0,11023,11029,0,0,0,0,11031,0,0,0,11034,0,0,0,0, 11055,0,0,0,0,0,11056,11060,0,0,0,0,0,0,11061,0,0,11064,11065,0,11066,0,11069,0, 11085,0,0,0,0,0,11086,0,0,0,11088,0,0,0,11094,0,0,0,11095,11096,0,0,0,0,0,0, 11097,11098,0,0,0,0,0,0,11099,0,0,11102,11108,0,0,0,11109,0,11114,11119,0,11131, 0,0,0,11142,0,0,11143,0,11146,0,11147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11148,0, 11149,11152,11153,11154,0,11156,0,11157,0,0,0,11158,0,0,11159,11160,0,0,0,0,0,0, 0,0,0,0,0,0,11163,0,0,11164,11166,0,0,0,11172,11174,0,0,0,11176,0,0,0,0,0,11182, 11183,0,0,0,11184,11187,0,0,11188,11189,0,0,0,0,0,0,11194,0,0,0,0,0,0,0,11200, 11202,0,0,0,0,0,0,11203,0,11204,0,0,0,0,0,11205,0,0,0,11206,0,11207,0,0,11209,0, 11211,0,11214,0,0,11231,0,0,0,11293,11295,0,0,11296,11297,11302,0,0,0,11307,0,0, 0,0,11309,11310,0,11311,0,0,0,11313,0,11314,0,0,0,0,11334,0,11338,0,0,0,11339,0, 0,0,0,0,11340,0,11341,11342,0,11344,0,11345,0,0,0,11348,11349,0,0,11350,0,0,0, 11355,0,0,0,0,0,0,11356,0,11357,11370,0,0,11371,0,11374,11376,0,0,0,11377,0,0, 11378,11383,0,11386,11399,0,11400,11406,0,0,0,11408,0,0,11409,11412,0,0,0,0, 11417,0,0,0,11418,0,11421,0,11426,11429,0,0,0,0,0,11430,0,11437,0,11438,0,0,0,0, 0,11440,11453,0,0,0,0,0,0,11454,0,0,0,0,11455,0,0,11456,11460,11461,11463,0, 11469,0,11473,0,0,0,0,11474,0,0,0,11475,0,11476,11477,11480,0,0,0,0,11481,0,0, 11484,0,0,11487,0,0,0,0,0,0,0,0,0,0,11497,0,0,11502,0,11509,0,0,11510,11511, 11513,0,0,0,0,0,0,0,0,0,0,11515,0,0,0,0,11516,0,11520,11521,0,0,0,0,0,0,0,0,0,0, 0,11529,11530,11531,11534,0,0,11543,0,0,0,0,0,11547,0,11548,0,0,0,0,0,11552, 11556,0,11557,0,0,11559,0,11560,0,0,0,0,0,0,11561,0,0,11563,11564,0,11565,0,0,0, 0,11567,0,0,0,11569,0,11574,0,11575,0,0,0,11577,0,11578,0,0,0,11580,11581,0,0,0, 11582,11584,0,0,0,0,0,0,0,11587,0,11588,11591,0,11595,0,0,0,0,0,0,0,0,11596,0, 11597,0,0,0,0,11598,11601,0,0,0,11602,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11603, 11604,0,11606,0,0,11608,0,0,0,0,11610,0,0,11611,0,0,0,0,11613,0,11622,0,0,0, 11623,0,0,0,0,11625,0,0,11626,11627,11628,11630,0,0,0,0,0,0,11639,0,0,11646,0, 11648,11649,0,11650,0,0,0,0,0,0,0,0,0,11651,0,0,11652,11653,11656,0,0,11677, 11679,0,0,0,0,11680,0,0,11681,0,11685,0,0,0,0,0,0,0,0,11688,0,0,0,11716,0,11719, 0,0,0,0,0,11721,0,0,11724,11743,0,0,0,0,0,0,0,0,11745,11748,11750,0,0,0,0,0, 11751,0,0,0,11752,11754,0,11755,0,0,0,0,0,0,0,11759,0,0,0,0,0,0,11760,0,0,0, 11761,0,0,0,0,0,0,11766,11767,0,11772,11773,0,11774,0,0,11775,0,11777,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,11778,11780,0,0,0,0,0,0,0,11783,0,11784,0,0,0,11785, 0,0,0,11786,0,0,0,0,11788,0,0,11789,11791,11792,0,0,0,0,11795,11834,11835,11836, 0,0,11837,0,0,0,11838,0,0,11846,11851,0,11852,0,11869,0,0,0,11871,0,0,0,11872, 11874,0,0,0,0,0,0,11875,0,11876,11877,0,0,0,0,0,0,0,0,0,0,11883,0,0,0,0,0,0,0, 11884,0,11885,0,11886,0,0,11887,0,11894,11895,11897,11909,11910,0,11912,11918,0, 0,11920,0,11922,11924,11927,11928,0,0,0,0,11929,0,11934,0,0,0,0,0,11941,11943, 11944,0,11945,0,0,0,0,11948,11949,0,0,0,0,11953,0,11954,0,11955,0,11956,0,0,0,0, 0,11957,0,0,11959,0,0,0,0,0,0,0,0,11961,0,0,0,0,0,11978,0,0,0,11979,11980,11986, 11987,0,11992,0,0,0,0,0,11993,0,0,0,11994,0,11999,12004,12005,12006,0,0,0,0,0, 12011,0,0,12012,12014,0,0,12015,0,0,12019,12028,0,0,12029,0,0,12032,12033,0,0,0, 0,12034,0,12041,12043,0,0,12044,0,0,0,0,0,0,0,12046,0,0,0,0,0,0,0,12054,12055,0, 12056,0,0,0,12060,12064,0,0,0,0,0,12065,12067,12068,0,0,0,0,0,0,0,0,12074,0,0,0, 12075,12076,0,0,0,12079,0,12081,12086,12087,0,0,12088,0,0,0,0,12089,0,12092,0,0, 0,0,12097,0,0,0,0,0,0,0,0,12098,0,0,0,0,0,0,0,0,0,0,0,0,0,12102,12103,12104, 12111,0,0,12114,12116,0,0,0,12118,0,0,0,12119,12120,12128,0,0,0,0,12130,0,0,0,0, 0,0,12131,0,0,0,12132,12134,0,0,0,0,12137,0,12139,0,12141,0,0,12142,0,0,0,12144, 0,0,0,0,0,12145,0,12148,0,12153,0,0,0,0,12154,12171,12173,0,0,0,12175,0,0,0,0, 12178,0,0,0,0,0,0,0,12183,0,0,0,0,0,0,0,0,12184,0,0,0,12186,0,0,0,0,0,12187, 12188,0,0,12189,0,12196,0,12197,0,0,12198,0,12201,0,0,0,0,12203,0,12209,0,0,0,0, 12210,12211,12212,12213,0,12217,12218,0,0,0,0,0,0,0,0,0,12222,0,0,0,0,0,0,0, 12223,0,0,12229,0,0,0,0,12233,0,0,0,0,12234,0,0,12236,12242,0,0,0,12243,0,0,0, 12244,12253,0,12254,12256,0,12257,0,0,12275,0,0,0,0,0,12277,0,0,0,0,0,12278,0, 12289,0,0,12290,0,12292,12293,0,0,12294,0,12295,0,0,12296,0,12297,0,12298,0,0,0, 0,12301,0,0,0,0,0,0,0,0,0,0,0,0,0,12309,0,12338,12340,0,0,0,0,12341,0,0,0,0,0,0, 0,0,12342,12343,0,12344,0,0,0,0,0,0,0,0,0,12345,0,0,0,0,0,0,0,0,12346,0,0,0,0, 12348,0,0,0,0,0,0,0,0,0,0,0,0,12350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12351,0,12355, 12356,12357,0,0,12367,12370,12371,0,0,0,0,0,12372,12376,0,0,0,0,0,0,0,0,12379,0, 12382,0,12383,0,0,12384,0,0,0,0,12393,0,0,12394,0,0,0,0,12398,12403,0,0,12404,0, 0,0,0,0,0,0,0,0,0,0,0,0,12410,0,0,0,12411,0,0,0,12412,0,0,0,0,12420,0,12421,0,0, 0,0,0,12423,0,12425,12429,0,0,0,12431,12432,0,0,0,0,0,0,0,0,0,0,0,0,12434,0,0,0, 0,0,12435,12436,0,0,0,0,0,0,0,0,12437,0,0,0,0,0,12438,0,0,0,0,0,0,0,0,12445,0,0, 0,12450,12451,0,0,0,0,0,0,0,0,12452,12475,0,0,12493,12494,0,0,0,12495,0,0,0,0, 12496,12502,12509,0,0,0,0,12510,0,12512,12513,0,0,0,0,12514,0,0,0,12515,0,12520, 0,0,0,12524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12527,0,0,0,12528,0,0,0,12529,0,0,0, 0,0,12530,0,12535,0,0,12536,0,12538,0,0,0,0,0,0,0,0,0,0,0,0,12540,0,12548,0,0,0, 0,0,12550,0,0,0,12551,12552,0,0,0,12554,0,0,0,0,0,0,0,0,12555,0,0,12562,0,12565, 0,12566,0,0,0,0,0,0,0,0,0,0,0,0,12569,0,0,0,12571,12574,0,0,0,0,0,0,0,12577,0,0, 0,0,0,0,0,12578,12579,12603,0,12608,0,0,12611,0,12612,0,12615,0,12625,0,0,0,0, 12627,12646,0,12648,0,0,12657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12670,0,0,12671,0, 12673,12677,0,0,0,0,0,0,0,0,0,0,0,12679,0,12681,0,12682,12693,0,12694,0,12697,0, 12701,0,0,0,12703,12704,0,0,0,0,12707,12737,0,0,12739,0,0,12740,0,0,12742,12743, 0,0,0,0,0,0,0,0,0,12745,0,12746,12747,0,12748,0,0,12759,12767,0,0,0,0,12773,0, 12774,12778,0,0,0,0,0,0,0,12779,0,0,0,0,0,12780,12793,0,12824,0,12825,0,12836,0, 0,0,0,12839,0,12842,0,0,0,0,0,0,0,0,0,0,0,0,12843,12845,0,12846,0,0,0,0,12847,0, 0,12850,12852,12853,0,0,0,12854,0,0,0,12855,0,12856,0,12858,0,0,12859,0,12862,0, 12863,0,0,12866,0,12869,12872,12873,0,0,0,0,0,0,0,0,0,12875,0,12877,0,0,12878,0, 0,0,0,0,0,0,0,0,12884,12885,12888,0,12889,0,0,0,0,12893,0,0,0,12895,12896,12898, 0,0,0,0,0,0,0,12902,0,12909,12910,0,12926,0,12928,0,0,0,12929,0,12930,0,0,0,0, 12931,0,12932,12933,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12934,0,12942,0,0,0,0,12944, 0,0,0,0,0,0,0,0,12946,0,0,12948,0,0,12949,0,0,0,0,12950,0,0,0,0,12951,0,12952,0, 12953,0,0,0,12954,12958,12959,0,0,0,0,0,12960,12964,0,0,0,0,0,12966,0,0,0,0,0,0, 0,0,12970,0,12971,0,0,0,0,0,0,12972,0,0,12982,0,0,0,12984,12985,0,12986,12996, 12997,13001,13002,0,0,0,0,13004,0,0,13005,0,0,13007,13009,0,13017,0,0,0,13020,0, 13021,0,0,0,0,0,0,0,0,0,0,13022,0,0,0,0,0,0,0,0,13024,13027,0,0,0,0,0,13028,0,0, 13029,0,0,0,0,0,0,0,13032,0,13037,0,0,0,0,0,0,13040,0,0,13041,0,0,0,13043,13044, 13046,0,0,0,0,13047,0,0,0,0,0,0,0,13049,13054,0,13056,0,0,13060,13061,0,0,0,0,0, 13067,0,0,13068,0,13071,0,0,0,0,0,13077,13078,0,0,0,0,0,13079,13080,13081,0, 13082,0,0,0,13085,0,0,0,0,0,0,0,13086,0,13087,13088,0,0,0,0,0,13094,0,13099,0, 13100,0,0,0,13101,0,13125,13126,13128,13129,0,0,13130,0,13131,0,0,0,0,0,0,13134, 0,0,0,0,0,0,0,0,0,0,0,13150,0,13168,0,0,0,0,0,0,0,0,0,13169,0,0,13170,0,0,0,0, 13174,0,0,0,13176,0,0,0,0,0,13177,0,13178,13183,13187,0,0,0,13189,0,0,13190,0,0, 13191,0,0,13206,0,0,0,13207,0,0,0,0,0,0,0,0,0,0,13212,0,0,13219,13232,0,0,0, 13241,0,13249,13253,0,0,0,0,0,13255,13259,0,13260,13261,0,13262,0,13272,0,0,0,0, 13276,0,0,0,0,13277,13299,0,0,13301,13302,0,0,13303,0,0,13305,0,13310,0,0,0, 13311,0,0,0,0,13325,0,13328,0,0,0,13329,0,0,0,0,0,0,13330,0,0,13331,0,13335,0,0, 13342,0,0,0,0,0,13343,0,13354,0,13362,0,13366,13367,13369,0,0,13371,13372,0, 13373,13374,0,13376,0,13380,13381,13386,0,13387,13388,0,13389,13391,13395,0,0,0, 0,0,13401,13409,0,13410,0,0,0,0,13420,0,0,0,0,0,13422,0,0,0,0,13423,0,0,0,0, 13425,0,0,0,0,0,13427,0,0,0,13428,0,0,13430,13438,0,13439,0,13445,0,13448,13449, 0,0,0,0,0,0,13451,0,13457,0,0,0,0,13458,13459,0,13460,0,0,0,0,13464,13465,13466, 13470,0,13471,13472,13474,13475,0,13476,0,0,13478,13479,0,13481,0,0,0,0,13487,0, 13490,0,13493,0,0,13494,0,0,13495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13496,13497,0, 13500,0,0,13516,13522,0,0,13525,13528,0,0,0,13530,13535,0,13537,13539,0,13540,0, 13543,0,13544,0,0,0,0,0,0,13545,0,0,0,0,0,0,13547,0,0,0,13549,13555,0,0,0,13556, 13557,0,0,0,0,0,0,0,13558,0,13563,0,0,0,0,13564,0,0,0,0,0,0,0,0,13566,0,0,0,0,0, 0,13569,0,0,13571,0,0,0,0,13573,0,0,0,0,0,0,13578,0,0,0,0,0,0,0,0,0,0,13581,0, 13586,0,13595,0,13600,0,0,0,0,0,0,0,0,13601,13603,0,13604,13605,13606,13607,0,0, 13617,13618,0,0,0,0,0,0,0,13623,0,13625,13627,0,0,0,0,0,0,0,0,13629,0,0,0,13634, 0,0,0,13638,0,0,0,0,0,0,0,0,13654,0,0,0,0,0,0,0,0,0,0,13656,0,13659,0,0,13660,0, 0,13662,0,0,0,13663,0,13664,0,0,0,0,0,13668,0,13669,13671,0,0,13672,0,0,0,0,0,0, 13675,13685,0,13686,0,0,0,13687,0,0,0,13692,13694,13697,0,0,0,13702,0,0,0,0,0, 13705,0,0,0,0,13707,0,0,0,13714,0,0,0,0,0,0,0,0,0,13715,0,13716,13717,0,0,13719, 13724,13730,13731,0,0,0,0,0,0,0,0,13732,0,0,0,0,0,0,0,13734,0,13736,0,0,13737, 13738,13747,0,13751,0,0,13752,0,0,0,13753,0,13757,0,0,13762,13763,0,13764,13765, 0,13766,0,0,13767,0,0,0,13768,0,0,0,0,0,0,0,13769,0,0,13772,0,13775,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,13776,13778,13787,0,0,0,13797,0,13798,0,13801,0,13804, 13806,0,0,0,0,13816,13817,0,0,0,0,0,0,0,0,0,0,0,0,0,13834,0,13836,0,0,13838,0,0, 13839,0,13840,0,0,0,0,13842,0,0,0,0,0,0,13843,0,0,0,0,0,0,0,0,0,13845,0,0,0,0,0, 13858,0,0,13860,0,0,13861,0,0,13862,13863,0,13868,0,13869,13870,0,0,0,0,0,0,0,0, 0,0,13872,0,0,0,0,13873,13878,0,0,0,0,0,0,0,0,0,0,13886,0,13888,13889,13890,0,0, 13891,13894,0,13897,13899,13900,13904,0,0,13906,0,0,0,13909,0,0,0,13910,0,0,0, 13911,0,0,0,0,0,13912,13917,0,0,0,0,13918,0,13919,0,0,13920,0,0,0,13921,0,0, 13922,0,0,0,0,0,0,0,13924,0,13927,0,0,0,0,0,13932,0,13933,0,13934,0,0,13935,0, 13944,0,0,0,13954,0,0,13955,0,0,0,0,13956,0,13957,0,13967,13969,0,0,0,0,0,0,0,0, 0,0,0,0,13970,13990,0,13991,13994,0,13995,0,0,0,0,13996,0,0,13999,0,0,0,14018,0, 14019,0,14021,0,0,0,0,0,0,14041,0,0,0,0,0,0,0,0,14043,0,0,0,0,14046,0,0,0,14048, 14049,0,0,0,0,0,0,0,0,0,0,14051,0,0,14052,14056,0,14063,0,14064,14066,0,0,14067, 0,0,0,0,0,0,0,0,0,14068,0,0,0,14072,0,14074,14075,0,14076,14079,14085,14086, 14087,14093,0,0,0,0,14095,0,0,0,0,0,0,14096,14097,0,0,0,0,0,0,0,14098,0,14102,0, 0,0,0,0,14103,0,0,0,14104,0,0,14105,0,0,0,14107,14108,0,0,14109,0,0,0,0,0,0,0,0, 14117,0,0,0,0,14118,0,0,0,0,14119,0,0,14120,0,0,14121,0,14122,14127,0,14128, 14136,0,0,14138,0,14140,0,0,0,14141,14142,0,0,0,0,14146,0,0,14149,0,14151,0,0,0, 14152,0,0,14153,0,0,0,0,0,0,0,0,0,14154,0,14156,14157,0,0,14159,0,14161,0,0,0,0, 14162,0,0,0,0,0,0,14163,0,0,14173,0,0,0,0,0,0,14174,0,0,14176,0,0,14178,0,0, 14179,14181,0,0,14182,14185,14187,0,14190,0,0,14197,0,0,0,0,0,0,0,0,0,0,0,0, 14198,0,0,0,0,0,0,14199,14200,0,0,0,14204,0,0,14208,0,0,0,0,0,0,0,0,0,0,0,14231, 0,0,0,0,0,0,0,0,0,14234,0,0,14235,0,0,0,14240,14241,0,0,0,14246,0,0,0,14247,0, 14250,0,0,14251,0,0,14254,0,0,14256,0,0,0,14260,0,14261,0,0,0,0,14262,14267, 14269,0,0,14277,0,0,14278,0,14279,14282,0,0,0,14283,0,0,0,14284,14285,0,0,0,0, 14286,0,0,0,14288,0,0,0,14289,0,14290,0,14293,14301,14302,14304,14305,0,14307,0, 14308,14309,0,0,0,0,0,0,0,0,0,0,0,14311,14312,0,0,14317,0,0,0,0,0,0,0,14318,0,0, 0,0,14320,0,0,0,0,14321,14322,0,0,0,0,0,14326,14329,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 14330,14331,0,0,0,0,14332,0,0,0,14333,0,0,14337,14340,0,14341,0,0,14342,0,14345, 14346,0,0,14347,0,14362,0,0,0,0,0,14364,14365,14371,0,14373,0,0,14374,0,14379,0, 14400,0,0,0,0,0,14401,0,0,14405,0,14406,0,14408,14409,0,0,0,14417,0,0,14424,0,0, 0,0,0,0,0,0,0,14430,0,0,0,14431,0,0,14435,0,14440,0,0,0,0,0,0,14442,0,0,14443,0, 0,0,0,0,14446,0,0,0,0,0,0,0,14454,0,14457,0,14460,0,0,14466,0,0,0,0,0,14467,0,0, 0,0,0,0,14469,0,14477,0,0,0,0,0,0,14478,14482,0,0,0,14483,0,0,0,14485,14486,0,0, 0,14487,14488,14489,14492,14493,14494,14495,14496,14497,0,14499,0,14501,0,0,0,0, 0,0,0,0,0,0,14502,0,14507,14512,14513,14514,0,0,0,0,0,0,0,0,0,0,0,14515,14526, 14530,0,14537,0,14544,0,14547,0,0,14548,14550,14551,0,0,14552,0,0,0,14553,0, 14554,0,0,0,0,14556,14564,0,0,14565,14566,0,0,0,0,0,0,14568,0,0,14569,0,0,0, 14571,14576,0,0,14577,14578,14579,0,0,14580,0,0,0,0,14582,0,0,0,0,0,0,0,0,0,0,0, 0,14583,0,0,0,0,0,14587,0,14588,0,0,14600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,14601,0,0,14604,14605,14611,0,14613,0,0,0,0,14615,0,0,0,0,0,0,14627,0,14628,0, 0,0,0,14631,0,14633,14634,0,0,0,0,14635,0,0,0,0,0,0,0,0,14636,0,0,14639,14642,0, 0,0,0,14644,0,0,0,0,14645,14646,0,14653,0,0,14654,0,14658,0,14661,0,0,0,14665,0, 0,0,14668,0,0,0,0,0,0,0,0,0,14669,0,0,14670,0,0,0,14680,0,0,14681,0,0,0,0,0, 14682,14683,0,0,0,0,14686,0,0,0,0,14687,14697,0,0,0,0,14699,14705,14711,0,0,0,0, 0,0,0,0,0,0,14712,0,0,0,14713,0,0,0,0,14719,0,14720,14721,14726,0,0,0,14728, 14729,0,0,0,0,14731,0,0,0,0,0,0,0,14733,14736,14737,0,0,14740,14742,0,0,0,14744, 14753,0,0,0,0,14755,14758,14760,0,0,0,0,0,14761,14762,14765,14771,0,14772,0, 14773,14774,0,0,14775,0,0,14776,0,0,0,0,14777,0,14779,0,0,14782,0,0,14785,14786, 14788,0,0,0,0,0,14795,0,0,0,0,0,0,14798,0,14803,14804,14806,0,0,0,14809,0,0,0,0, 0,0,14810,0,0,0,0,14811,0,14812,0,0,0,0,0,14815,0,0,0,0,0,0,0,0,14816,0,14818,0, 0,0,0,0,0,14819,0,14820,0,14823,0,0,0,14824,0,0,14826,14827,0,0,0,0,0,0,0,0,0,0, 0,0,14830,0,0,0,0,0,14833,0,14845,0,0,0,0,0,14846,0,0,14847,14871,0,14873,0, 14876,0,14877,14878,14880,0,0,0,0,0,14881,0,14882,14894,0,0,0,0,14895,0,14907,0, 14908,0,0,0,0,0,0,0,14911,0,0,0,0,14920,0,0,14931,0,14932,14934,14935,0,0,14936, 0,14945,0,0,0,0,0,0,0,14947,0,0,14948,14949,14951,0,0,14952,0,0,0,14964,14973,0, 0,14990,0,0,0,0,14995,0,0,14998,15001,0,0,15002,15020,0,0,0,0,0,0,15021,0,15022, 0,0,0,0,15023,0,0,15025,15029,15033,0,0,0,15034,0,0,0,15035,0,0,0,0,0,15043, 15044,0,0,0,15045,15046,15048,15050,0,15065,0,0,0,0,15066,0,0,15075,15082,15084, 0,0,15085,15086,0,0,0,0,0,0,0,0,15088,0,0,0,15089,0,0,0,0,15094,0,15096,0,15097, 0,15100,0,0,15102,0,0,0,0,0,0,0,0,15105,0,0,15106,0,15109,15113,0,0,0,15115,0, 15118,0,0,0,0,0,0,15119,0,0,15120,0,0,0,0,0,15123,15129,0,0,0,15130,0,15131,0,0, 15134,0,15135,0,0,0,15137,15138,0,0,0,0,0,0,15139,0,0,0,0,0,15140,0,0,15154, 15162,0,15169,15170,0,15175,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15177,0,15178,15179,0, 0,0,0,0,15183,0,0,0,0,0,0,0,0,0,0,0,0,15185,15187,0,15194,15195,15196,0,0,0,0,0, 0,0,15204,0,0,0,0,15206,0,0,0,0,0,15207,0,0,0,0,0,0,0,0,0,15213,0,15214,0,0,0,0, 0,0,0,15232,0,0,0,0,15234,0,15238,15240,0,15248,0,0,0,0,15250,15251,0,0,0,0,0,0, 0,15252,0,0,0,15255,15262,15266,0,0,0,15267,0,0,0,15277,15279,0,0,0,15280,15281, 15282,0,0,0,0,0,15285,0,0,0,0,15289,0,0,15291,0,0,0,0,0,0,0,15296,15297,0,0, 15304,0,0,0,0,15306,0,0,0,0,0,0,15307,15308,0,15309,0,0,15311,0,0,15312,15313,0, 0,0,0,0,0,0,0,0,0,0,0,15314,15317,0,0,0,15318,15319,0,0,0,0,15320,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,15321,0,0,0,0,0,15324,0,15325,15326,0,15330,0,0,0,0,15334,0, 15335,0,15341,0,0,15342,0,0,15343,15344,0,0,0,0,15345,0,0,0,0,15347,0,0,15348, 15349,15350,0,15356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15357,0,15358,0,0,0,0,0,0,0, 15359,15360,15364,0,15380,0,0,0,0,0,15392,0,0,15393,0,15395,0,0,0,0,0,0,0,0, 15396,0,0,15397,15398,0,0,0,0,0,0,0,0,0,15399,0,15400,0,0,0,15402,0,15405,15410, 0,0,0,0,15411,0,0,0,15412,0,15416,0,0,0,0,0,0,0,15428,0,15435,0,0,15438,0,0,0,0, 15439,0,0,0,15440,0,0,0,15441,15449,15451,0,0,0,0,0,0,0,15452,0,0,15455,0,0,0, 15456,0,0,15458,0,15460,15461,0,0,0,0,0,15462,15464,0,15465,0,0,15466,0,0,15467, 0,0,0,0,0,15468,0,0,0,0,15481,0,0,15484,0,15485,15486,0,0,0,15487,0,0,0,0,0, 15488,0,15492,15498,0,0,0,15499,0,0,0,15500,0,15501,0,0,15512,0,15522,0,0,0, 15524,0,15525,15526,0,0,15527,0,0,15545,15546,0,15548,15552,0,15553,0,0,0,15554, 0,15555,0,15557,15565,15573,15577,15578,0,15582,0,15583,0,0,0,0,0,0,0,0,0,0,0,0, 0,15586,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15588,0,0,0,0,0,15589,0,0,0,0,0,0,0,15593, 15594,0,0,0,0,15595,0,0,0,0,0,0,15596,0,0,0,15597,0,0,0,0,15600,0,0,15601,0,0,0, 0,15602,15603,0,0,0,0,0,0,15604,0,15609,0,0,15612,0,0,15613,0,0,15615,15617, 15618,0,0,15620,0,15636,15637,0,0,15649,0,0,0,0,0,0,0,15650,0,0,15651,0,0,0, 15656,0,15658,0,0,0,15664,0,0,15665,0,0,15668,0,0,0,0,0,15669,0,0,15674,0,0, 15675,0,0,0,0,15676,0,0,0,0,0,0,0,0,0,0,0,15677,0,0,0,0,15678,0,0,0,0,0,15679,0, 0,15681,0,15686,0,0,0,0,15687,0,15688,0,0,15690,0,0,0,15697,0,15699,15700,0,0,0, 0,0,0,0,0,0,15701,0,15702,15703,0,15704,0,15705,0,15707,0,15709,0,15712,15716,0, 15717,0,15718,15720,0,0,0,0,0,15724,0,0,0,15725,0,15726,0,0,0,15740,0,15745, 15746,0,0,15747,0,15748,0,0,0,0,0,15749,0,0,0,15752,0,15753,0,0,0,0,0,0,15759,0, 0,0,15765,0,0,0,0,0,0,0,0,0,15767,0,0,0,15771,0,0,15784,0,0,0,0,15785,15790, 15791,0,0,15792,0,0,0,15807,0,15811,0,0,0,0,0,0,0,0,0,0,0,0,15818,0,0,0,15819,0, 0,0,0,15821,0,0,0,0,0,15822,15824,0,0,15827,0,0,15829,15831,0,15832,0,0,15833,0, 15835,15838,15839,15843,0,0,0,0,0,0,0,0,0,0,0,15844,0,0,0,0,15845,15851,15856,0, 0,0,0,0,0,0,15858,15860,0,15861,0,0,0,15864,0,0,0,0,15865,0,0,0,0,0,0,15866,0, 15872,0,0,15876,0,0,0,0,15877,15878,15883,15885,0,0,15888,0,0,0,0,0,15889,15890, 0,0,0,0,0,0,0,0,15892,0,0,0,0,0,0,0,15893,0,0,15894,0,0,0,15895,0,15896,15897,0, 15898,15901,15902,0,15911,15915,0,15916,0,15924,15935,0,15937,0,0,0,0,0,15950,0, 0,0,0,0,0,0,15958,0,0,0,15961,0,0,15966,0,15967,0,0,15977,0,0,15978,0,0,15981, 15982,15983,0,0,0,0,0,0,0,15986,0,0,0,15990,0,15991,15995,15998,0,15999,0,16000, 0,0,0,0,16008,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16009,16011,0,16013,0,0,0,0, 0,0,0,0,16014,0,0,16015,16023,16024,16025,0,0,16026,0,16030,0,16032,0,16033,0,0, 0,0,0,0,16035,16036,16037,0,0,0,0,0,16039,0,0,0,0,16041,0,0,0,0,0,16043,16044,0, 0,16047,0,0,0,16048,0,0,16049,16050,16052,0,0,0,0,0,16055,0,0,0,0,0,0,0,0,16056, 0,0,0,0,0,0,0,16058,16060,16061,0,0,16063,0,0,16064,0,0,0,16067,16068,0,0,16069, 16078,0,0,0,16079,0,0,0,16080,0,16081,0,0,0,16088,0,0,0,0,0,0,0,0,0,0,0,16089, 16093,0,16097,0,16103,0,16104,16105,0,0,16256,0,0,16259,0,0,0,0,0,0,0,16260, 16261,0,0,16262,0,0,16263,0,16268,0,0,0,0,0,0,0,16269,0,0,16270,16273,0,16274,0, 0,0,0,16275,16276,16277,16280,0,0,0,16281,16284,0,0,0,16286,0,16289,0,0,0,0,0,0, 0,0,0,16290,0,0,0,0,16291,0,0,0,0,0,0,0,16292,0,0,0,0,0,0,0,0,16293,16295,16297, 0,16302,0,16304,0,16305,0,16306,0,0,0,0,0,0,0,0,0,0,0,0,16307,16308,16312,0,0,0, 0,0,0,16313,16315,0,16318,0,0,0,16321,0,0,0,0,0,0,0,16326,16333,16336,0,0,0,0, 16337,16340,0,0,0,0,0,16345,0,0,16346,0,0,0,0,0,0,0,0,0,16347,0,0,16348,0,0,0,0, 16349,0,0,0,16350,0,16357,0,0,0,0,16359,16360,0,0,0,0,16362,16363,16364,16365,0, 0,16366,0,0,0,0,16367,16368,0,16369,16374,0,0,0,0,0,0,0,16376,0,0,0,0,16378, 16379,0,16380,0,0,0,16381,16383,0,0,0,0,0,16390,0,0,0,16399,0,16402,16404,16406, 16407,0,0,0,16409,16411,0,0,0,0,16412,0,16413,16415,16423,0,0,0,0,0,16424,0,0,0, 16428,16434,16435,16449,0,16450,16451,0,0,0,16453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 16454,0,0,16456,16458,0,0,16459,0,0,16460,0,0,0,0,16462,0,16463,0,0,16466,0,0,0, 0,0,16479,0,0,16480,0,16481,16484,0,0,0,0,0,0,0,0,0,0,16485,0,0,0,0,0,0,16489,0, 0,0,0,0,16491,0,0,16498,0,0,16503,0,16505,0,0,0,0,0,0,0,0,16506,0,0,0,16508, 16509,0,0,0,0,0,0,0,0,16511,16513,0,0,0,16516,0,16517,0,16519,0,16529,0,0,16531, 0,0,0,0,0,0,16534,0,0,16541,16542,0,0,0,0,0,0,0,0,0,16543,16547,16548,0,0,0, 16551,0,16552,0,0,0,16553,0,0,16558,0,0,16562,16565,0,0,0,16570,0,0,0,16573, 16585,0,0,0,16586,16587,16595,0,16596,0,16598,0,0,0,16600,0,0,0,0,0,0,0,0,0,0,0, 0,0,16601,0,0,0,0,16603,0,0,0,0,0,0,0,16604,16612,0,0,0,0,16613,0,16618,0,0,0, 16640,0,0,16641,0,0,0,0,0,0,16645,0,0,0,0,16646,0,0,0,0,0,0,16651,0,0,0,0,16653, 16654,0,0,0,16655,0,0,16656,16667,0,0,0,0,16671,0,16672,0,0,0,16673,0,0,0,0,0, 16676,0,16686,0,0,0,0,16689,0,16690,0,16692,0,16693,0,16694,0,16696,0,0,0,16705, 0,0,0,0,0,0,16707,0,0,0,16709,0,0,0,0,16711,0,16712,16713,0,0,0,16715,0,0,0,0, 16716,0,0,0,0,0,0,0,0,0,16718,16724,0,0,16726,16727,0,0,0,0,0,0,0,16728,0,16729, 0,0,16730,0,0,0,0,0,16731,0,0,0,16732,0,0,0,0,16734,16738,0,0,0,0,0,0,0,0,16743, 0,0,16745,0,0,0,0,0,16749,0,16752,0,0,0,0,16756,0,0,16758,0,16759,0,0,0,0,0, 16760,0,0,0,0,0,0,0,16762,0,16769,0,16770,0,16772,0,0,0,16777,16780,0,0,0,0,0,0, 16781,0,0,16782,0,16784,0,0,16785,16787,16792,0,0,16794,0,0,0,16798,0,0,16809,0, 0,16814,16816,16817,0,16819,0,0,0,0,0,0,0,0,0,0,16820,0,0,16836,16839,0,0,16841, 16851,16857,0,0,16858,16859,0,0,16860,0,0,0,0,0,0,0,0,16862,0,16863,0,0,0,0,0,0, 0,16864,0,0,0,0,0,0,0,16876,0,16881,16882,0,16885,16886,0,16887,0,0,0,16889, 16891,0,0,0,0,0,16894,16895,0,0,0,0,0,0,0,0,0,0,0,16897,0,16898,0,0,0,0,0,16913, 0,0,16924,16925,16926,0,0,16927,0,0,0,16937,16938,0,0,0,16940,16941,0,0,0,16942, 16945,0,16946,16949,16950,0,0,0,16952,16955,0,0,0,16965,0,16969,0,0,16975,0,0, 16976,0,0,0,0,16978,0,0,16981,0,16983,16989,0,0,0,0,16990,0,0,16991,0,0,0,16993, 0,16994,16996,17000,0,0,0,0,0,17002,17004,0,17006,0,0,17007,0,0,0,0,17008,17013, 17014,0,0,0,0,0,0,0,0,0,17021,0,17031,0,0,0,0,0,17033,17036,0,17038,0,0,17039,0, 17045,0,0,17046,17047,0,0,0,0,17048,0,17049,17050,0,17051,17053,0,17054,0,17055, 0,0,0,0,0,17063,0,0,17064,0,0,0,0,0,0,0,17065,0,0,17068,0,0,0,0,0,17072,0,0,0,0, 0,0,17073,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17074,0,17080,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,17081,17083,17084,0,0,0,17085,0,0,0,0,17092,0,0,0,0,0,0,0, 0,0,17093,0,17095,17102,0,0,0,0,0,0,17103,0,0,17105,0,17107,0,0,0,0,17114,0,0,0, 0,0,17115,17125,17127,0,0,17128,0,0,0,17129,17130,0,17131,0,0,0,0,0,17132,17135, 17145,0,0,0,0,0,0,0,0,17146,0,17147,0,17148,0,0,0,0,0,0,17149,17150,0,17151, 17153,0,17155,0,0,0,0,17163,17171,0,17174,0,0,0,0,17179,0,0,17182,17185,0,0,0,0, 0,17186,0,0,17188,0,0,0,0,0,0,0,17189,17191,0,17194,0,0,0,0,0,0,0,0,0,17195, 17196,17203,17204,0,0,17205,17217,0,0,0,0,0,17218,0,0,0,0,17219,0,17220,0,17221, 0,0,17230,0,0,0,0,0,17236,0,17238,17239,0,0,0,17241,17244,0,0,17245,0,17248,0,0, 17251,0,17252,0,0,17264,0,17266,0,0,0,17268,0,0,0,0,17271,17272,0,17273,0,17295, 0,17302,0,17305,0,0,0,17306,0,0,0,0,0,0,0,17308,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 17309,0,17310,17313,0,0,0,0,17314,17315,0,17317,0,0,0,0,17318,0,0,0,0,0,0,0, 17320,0,0,0,0,0,0,17334,0,17344,17348,0,0,0,17350,17351,0,0,17353,0,0,17354,0,0, 0,0,0,0,0,0,0,17355,0,0,0,0,0,0,17356,17357,0,0,17359,0,0,0,17371,0,17372,0,0,0, 17393,0,0,0,0,17394,0,0,0,0,0,17395,0,0,17399,0,0,0,17401,17417,0,17418,0,17419, 0,0,0,0,0,17422,17423,0,0,0,0,0,17424,0,0,0,0,0,17428,17429,17433,0,0,0,17437,0, 0,17441,0,0,17442,0,0,17453,0,0,0,0,0,0,0,0,17454,17456,17462,0,0,17466,0,0, 17468,0,0,17469,0,0,0,0,17470,0,17475,0,0,0,0,0,17479,0,0,0,17483,17484,0,17485, 0,17486,0,17491,17492,0,0,17493,0,17494,17495,0,0,0,17496,0,0,0,17497,0,0,0, 17502,0,0,0,0,0,17503,0,17505,0,17507,0,0,0,17512,17513,17514,0,0,17515,0,0,0, 17519,0,0,0,17522,0,0,17523,0,0,0,0,0,0,0,0,0,17527,0,0,0,17528,0,0,0,17534,0,0, 0,0,17536,0,0,0,17539,0,17540,17543,17549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17556, 0,0,17558,0,17559,0,0,17560,0,0,0,17563,0,0,0,0,0,0,17564,0,0,17565,17566,0, 17567,0,0,0,0,0,0,17569,17570,0,17575,0,0,0,0,0,0,0,0,0,0,0,17581,0,0,0,17582, 17583,0,17586,0,0,17587,0,0,0,0,0,0,0,17588,0,0,0,0,17596,17597,0,0,17598,17600, 0,0,0,0,0,0,17601,0,0,0,17604,0,0,17605,0,0,17607,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,17612,0,0,17618,0,17621,17622,0,0,0,0,17623,0,0,17624,0,0,17630,0,0, 17631,17633,17634,0,0,0,0,0,0,0,17635,0,0,17636,0,0,17637,0,17638,0,17640,0,0,0, 0,0,0,0,0,0,0,17641,0,0,0,0,0,0,0,0,0,0,17643,0,0,0,0,17645,0,0,0,0,0,0,0,0, 17646,17662,0,0,0,0,0,0,0,0,0,17663,17664,0,17665,17666,0,0,0,17669,17671,17673, 0,17679,0,0,0,0,0,0,0,17684,0,0,0,17686,0,17714,0,0,17720,17722,17726,0,0,17728, 0,0,17729,0,0,0,17732,0,17733,0,17734,0,0,0,17735,0,0,0,0,17737,0,0,0,0,17739,0, 0,0,17741,17742,0,0,0,0,17743,17744,17745,0,0,0,17749,0,17750,17751,17752,17754, 17761,17762,0,17763,0,17766,0,17772,0,0,0,0,0,17775,0,0,0,0,0,0,0,17776,0,0, 17777,0,0,17778,17779,0,17782,17783,0,0,0,0,0,0,0,0,0,0,17784,0,0,0,0,0,0,0, 17821,0,0,0,17822,0,0,0,17823,17825,0,0,0,0,0,17826,17831,17832,17833,0,0,17845, 0,0,0,17846,0,0,0,17848,17850,17854,0,17855,0,0,17859,0,0,0,0,0,0,17860,17861,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17870,17871,0,0,0,0,0,0,17872,0,0,0,17879,0, 0,0,17881,17883,0,17884,0,17885,0,0,17886,0,0,17887,17891,17953,0,0,0,0,17954,0, 0,17955,0,17968,0,0,17972,0,0,0,0,0,17974,0,0,0,0,17976,17978,0,0,17983,0,0,0,0, 18003,0,0,0,0,0,18007,0,0,0,0,0,18009,0,0,0,0,0,0,0,18010,0,0,0,0,0,0,18012,0,0, 18014,0,0,0,18015,0,0,0,18016,0,18017,0,0,0,18030,0,0,0,0,0,0,0,18031,0,0,18036, 18037,18038,0,0,18049,18056,0,18057,18058,0,18059,0,0,0,0,0,0,0,0,18062,0,0,0,0, 18064,0,0,0,0,0,0,0,0,18067,0,0,0,18068,0,0,18075,0,0,18078,18093,18094,0,0,0,0, 0,0,0,0,18097,0,0,0,0,0,18098,18100,0,0,0,18108,0,18111,0,0,18112,0,18113,0,0, 18115,18116,0,18118,0,0,0,0,18121,0,0,0,0,18123,0,0,0,0,0,0,0,0,0,18124,0,0,0,0, 18125,18126,0,18127,0,0,18128,18135,0,0,0,0,0,0,0,0,0,18150,0,0,0,0,0,18151, 18152,0,0,18156,18164,0,18166,18171,0,0,0,0,0,0,0,0,0,18172,18183,0,18184,0,0,0, 0,18185,0,18187,0,0,0,0,0,18188,0,0,0,0,0,0,0,0,18189,0,0,18190,0,0,18191,18192, 0,0,18194,18195,18196,0,0,0,18197,0,18203,0,18204,0,0,0,0,18205,0,0,0,18207, 18208,0,0,18214,0,0,0,18215,18216,0,0,0,18220,0,0,18222,0,0,0,0,0,18223,0,18225, 18231,0,18234,0,18235,0,0,0,0,18240,0,0,18241,18242,0,0,0,0,0,18243,18251,0, 18253,0,18254,0,0,0,18266,0,0,0,0,0,0,18269,18270,18271,18273,18281,0,0,0,0,0,0, 0,0,0,0,0,0,18282,0,18283,0,18284,0,0,0,0,0,0,18285,0,18287,18289,0,0,18290,0,0, 0,0,18308,0,0,0,18310,0,0,0,0,0,0,0,0,0,0,0,0,18311,0,18312,18313,0,18315,0,0, 18316,18320,0,18331,0,18332,0,18336,0,0,0,0,18337,0,18340,0,0,0,0,0,0,0,0,0, 18341,0,18344,18345,0,18346,0,0,0,0,0,18348,0,18351,0,0,18356,0,0,0,0,0,0,18357, 0,0,0,0,0,18367,0,0,0,18368,0,18369,0,18370,18371,0,0,0,18437,18444,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,18445,18450,0,0,0,0,18451,0,18452,0,0,0,18453,0,0,0,0,0,18455,0, 0,0,18456,0,18457,0,18460,0,0,18461,0,0,0,0,0,0,0,0,18466,0,0,18467,0,0,0,0, 18473,0,0,0,18476,0,18477,0,0,0,18478,18479,18480,0,0,0,18485,0,0,0,18486,0,0,0, 0,0,0,18488,18490,0,0,0,0,0,0,18491,0,0,0,0,0,18495,0,0,18496,0,0,0,0,0,0,18505, 0,18521,0,18522,18523,0,0,0,18525,18526,0,0,0,0,0,18527,0,0,0,0,18532,18533,0, 18534,0,0,0,0,0,0,18535,18537,0,18538,0,0,0,0,0,0,18540,18541,18542,18543,0, 18546,0,0,0,0,18553,18556,0,0,18558,0,0,18569,18571,0,0,0,18572,0,18574,0,0,0,0, 18586,0,0,0,0,0,18588,0,0,18589,0,0,0,0,0,0,18590,0,18592,0,0,0,0,18594,0,0,0, 18596,0,0,18597,18598,0,0,18601,0,0,0,0,18602,0,0,0,18603,18604,0,18605,0,0,0,0, 18608,0,0,18611,0,0,0,0,0,0,0,0,0,18612,0,18616,0,0,18617,18619,0,0,0,18628,0,0, 0,18629,0,0,18630,0,0,0,0,0,0,0,18631,0,18632,0,0,18635,18637,0,0,0,0,0,0,18641, 18643,18648,0,18652,0,0,18653,0,18655,18656,0,0,0,18657,0,0,18666,18674,0,0,0,0, 18677,18684,18685,0,0,18686,0,0,18690,0,0,0,0,0,0,0,18695,18696,0,0,0,0,0,0,0,0, 0,0,18697,0,0,18700,0,0,0,0,0,0,18702,0,18708,0,0,18709,0,18710,0,0,18711,0, 18714,0,0,18718,0,0,0,0,0,0,18719,0,0,18722,0,18726,0,0,0,0,0,0,0,0,0,0,0,0,0, 18731,0,0,0,0,0,18739,18741,0,0,18742,0,18743,18744,18746,18748,0,18752,18753,0, 0,18754,18763,0,18765,0,0,0,18766,0,0,0,18769,0,0,0,0,0,18773,18778,18779,18781, 0,0,18784,18787,0,18788,0,18793,0,0,0,0,0,0,18795,0,0,18800,0,0,0,0,0,18801, 18804,0,0,0,0,0,0,0,18806,0,0,0,18811,18815,18816,0,0,0,0,18825,0,0,18827,18829, 0,0,18830,0,0,0,0,18831,0,0,18832,0,0,0,0,18833,0,18840,0,18841,0,18842,0,0,0,0, 18843,0,18844,0,0,0,0,0,0,18845,18846,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 18848,0,0,0,18853,18860,0,0,18862,18866,0,0,18867,18869,0,0,18874,18881,18891,0, 0,0,0,0,0,0,0,0,0,18892,0,0,0,0,0,0,0,0,18895,0,18896,0,0,0,18900,0,0,0,18901,0, 18902,18915,18916,0,0,0,0,0,0,0,0,18919,0,0,0,0,0,18920,0,0,0,18921,18929,0,0,0, 0,18930,0,0,0,0,0,0,18932,0,0,0,0,18934,18942,0,0,0,18951,18957,0,0,0,0,18958,0, 0,0,0,18959,18960,0,0,18961,0,0,18962,0,0,0,0,18963,18964,0,0,0,18965,0,18967,0, 0,0,0,0,0,0,0,0,18968,0,18969,0,18970,18973,18976,0,0,0,0,0,0,18977,0,0,0,18981, 0,0,0,18990,0,18998,0,0,0,0,0,18999,19003,0,0,19005,0,0,0,19006,0,0,0,0,0,0, 19008,19011,0,0,19018,0,0,19019,0,19024,0,19031,19032,0,19039,0,19041,19050,0,0, 0,19051,19055,19056,0,19059,19063,19064,0,0,19088,0,0,0,19093,19094,0,0,0,0, 19095,0,19096,0,0,0,19097,0,0,19098,0,19099,19100,0,0,19103,0,0,0,0,0,0,0,19111, 0,0,0,0,0,0,19112,0,0,0,19116,19117,0,19121,19122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,19123,19124,0,0,0,0,0,0,0,19125,19126,0,19128,0,0,0,0,0,0,0,0,0,0, 19129,19130,19131,19132,0,0,19146,0,0,19147,19156,19158,0,0,0,0,0,0,0,0,19182, 19185,0,0,19187,0,0,0,19193,0,0,0,0,0,19194,0,19197,0,0,0,0,19198,0,0,0,0,0,0,0, 0,0,0,19202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19203,0,19205,19210, 0,0,0,19213,0,19218,0,0,0,19223,19229,0,0,19230,0,0,19231,19232,19233,19239,0,0, 0,0,0,19240,0,19248,19249,0,0,0,0,19254,0,19256,19258,19259,0,0,19261,0,19266,0, 0,0,19272,0,19278,19281,19282,0,0,0,0,0,0,0,0,0,0,0,0,19283,0,0,19284,0,0,19285, 19287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19288,19291,0,19292,0,0,0,0,19297,0,19298,0,0, 0,0,19302,19303,0,0,0,0,19304,19305,0,0,0,0,19314,0,0,19315,0,0,19321,0,0,0,0,0, 0,0,19322,0,19333,0,19334,19335,0,19336,19337,0,0,0,0,0,0,0,0,0,0,0,19346,0,0, 19353,0,19354,19362,0,19366,19367,0,0,19369,0,19375,0,19377,19380,19388,0,0,0,0, 0,19389,19390,0,0,0,0,19392,0,0,0,0,0,19402,0,0,0,0,0,0,0,0,19412,0,0,19413, 19422,0,19424,0,0,0,19425,0,0,0,19428,0,0,0,0,19431,0,0,0,0,0,19432,0,0,0,0,0, 19448,19459,0,0,19461,0,19462,19463,0,19467,19474,19482,0,0,0,0,19494,0,0,0,0, 19501,0,0,0,0,0,0,0,0,0,0,19502,19504,0,0,0,0,0,0,0,19505,0,0,0,0,19506,19507,0, 0,0,19508,0,0,19511,0,0,19514,0,19515,0,19516,0,19518,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,19530,0,19537,19538,0,19543,19546,0,19547,19551,0,0,0,0,0,0,19552, 19553,0,0,0,0,0,0,0,0,0,0,0,0,19555,0,0,19556,0,0,0,0,0,0,0,0,0,0,0,0,19560, 19561,0,0,19562,0,0,0,0,0,0,19565,19567,0,19568,0,0,0,19569,19570,0,19578,0,0,0, 0,19580,0,0,0,0,19581,19584,0,0,0,0,0,0,0,19585,19586,0,0,0,19587,19588,0,19589, 0,0,0,0,0,0,19592,19593,19599,0,19600,0,0,19604,0,0,19605,0,19606,19608,19610,0, 19613,19614,0,0,0,0,0,0,19616,19617,0,0,19618,0,0,19619,0,0,0,19620,19621,19631, 0,0,19632,19634,19636,0,19643,0,0,19644,19658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,19659,0,0,0,0,0,0,0,0,0,0,0,19675,19677,0,0,0,0,19679,0,19683,0,19684,0,0, 0,0,0,0,19687,0,0,0,0,0,0,0,0,19688,19689,19692,0,0,0,0,0,0,0,19695,19697,0,0,0, 0,0,19698,19699,0,0,19700,0,19702,0,0,19703,0,0,0,0,0,0,19704,19708,0,19710,0, 19713,0,0,0,19715,0,0,0,0,19718,0,0,0,0,0,0,0,19720,0,19722,0,0,19725,0,0,0,0,0, 0,0,0,0,0,0,0,0,19730,0,0,0,0,0,19731,0,19734,19735,19739,0,0,19740,0,19741,0,0, 0,19746,0,0,19747,0,19771,0,0,0,0,0,0,0,0,19772,19775,0,0,0,0,0,0,19778,0,0,0,0, 0,19779,0,0,19780,19790,0,19791,0,0,19792,0,0,0,19793,0,0,19796,19797,0,0,0, 19799,0,0,0,19801,0,0,0,0,19803,0,19804,0,19805,0,0,19807,0,0,0,19808,0,0,0,0,0, 0,19809,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19816,0,19821,0,19822,19830,19831,0,0, 0,19833,0,0,0,0,0,0,0,0,0,0,19838,0,0,0,0,19839,0,0,19843,0,0,0,0,19845,0,0,0,0, 19847,0,0,19848,0,19849,0,0,0,0,0,0,0,19851,0,0,0,19854,0,0,0,0,0,0,0,0,0,19864, 0,19865,0,19866,0,0,0,0,0,0,0,19868,0,0,19870,0,0,19871,0,0,19872,19873,19875,0, 19880,19882,19884,0,0,19885,19886,19888,0,0,0,0,0,0,0,0,0,0,0,0,19890,19892, 19893,0,0,19894,0,0,0,19895,0,19896,19902,0,0,19903,0,0,19905,0,0,0,19906,0, 19908,0,19909,19911,0,0,0,19913,19920,0,19938,19939,19940,0,0,0,0,0,0,0,19942,0, 19943,0,19945,0,0,0,19951,19952,19954,19960,0,19965,0,19971,0,0,0,0,0,19975,0, 19976,0,19990,0,0,19991,0,19993,0,19995,0,0,0,19998,19999,20001,0,20003,20005,0, 20011,20012,0,0,0,0,0,0,20014,0,20020,0,0,0,0,20021,0,0,0,0,0,20023,20024,0,0,0, 0,0,20025,0,0,20027,0,0,20029,0,0,20032,0,0,0,0,20044,20045,0,20048,20049,0,0, 20050,0,20052,0,0,20054,20057,0,0,0,0,0,0,0,0,0,20059,0,0,20061,0,20062,0,20064, 0,0,20066,0,0,20067,0,0,0,0,20069,0,0,0,0,0,0,20070,20071,0,0,0,0,0,0,0,0,0,0,0, 20072,0,0,20073,20074,0,0,0,0,0,20075,0,20078,0,0,0,0,20080,0,20081,0,0,0,0,0,0, 20095,0,20098,0,0,0,0,0,0,0,20107,0,0,0,0,0,0,0,0,20112,0,0,0,20113,20114,0,0,0, 20115,20123,20124,0,0,0,20131,20133,20134,0,0,0,0,20136,0,0,20137,20138,20150,0, 20152,0,0,0,20153,0,0,20154,0,0,0,20158,0,20163,0,0,20164,0,0,0,0,0,0,0,20166,0, 20168,0,20170,0,20175,0,0,20178,0,0,0,0,20223,0,0,0,0,20224,0,20226,0,0,20230,0, 20231,0,0,0,0,20232,0,0,20233,20234,0,20244,0,20247,0,0,0,0,0,0,20249,0,0,0, 20250,0,0,0,0,20251,0,20253,0,20254,0,0,0,0,20256,0,0,20264,0,0,0,0,20266,0,0,0, 20278,0,0,20279,20282,0,0,0,0,0,20283,0,20284,0,20285,0,20287,20290,0,0,0,0, 20292,0,0,0,0,20293,20297,0,0,0,0,0,0,20299,0,20300,20303,0,0,0,0,0,0,20307,0,0, 20308,0,20309,0,20310,0,0,0,0,0,0,20312,0,0,0,20314,0,0,0,0,20315,20316,0,20322, 0,0,0,0,0,0,20339,0,0,0,20342,0,0,0,0,20352,0,0,0,0,0,0,0,0,0,0,20362,0,0,20365, 0,20375,20377,0,0,0,0,0,0,0,0,0,0,0,20378,20379,0,20380,0,0,20381,0,20382,0, 20383,0,20388,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20390,20392,20393,0,0,20395,0,0,0,0,0, 20396,0,0,0,0,0,0,0,0,20398,20415,0,0,0,20417,0,0,20420,0,0,20426,20428,0,20431, 0,0,20432,0,20433,20434,20435,0,0,0,0,20440,0,0,0,0,0,20442,0,20443,0,20446,0,0, 0,0,20448,0,20451,0,0,0,0,0,0,0,0,0,20452,20453,0,0,20454,0,0,0,0,0,0,20457,0, 20458,0,0,0,20465,0,0,0,0,0,20469,0,0,0,20473,0,20476,0,0,0,0,0,0,0,0,20477,0,0, 20485,0,0,20486,0,0,20487,0,20496,0,20497,0,0,20498,0,0,0,0,0,0,0,0,0,0,20499, 20500,0,20501,0,0,0,0,0,20520,20527,0,20529,0,0,0,0,20539,0,0,20540,0,0,0,20543, 0,0,0,20546,0,0,0,0,0,20548,0,0,20563,0,0,20564,0,20566,0,0,0,0,0,20589,0,0,0,0, 20590,0,0,20593,20594,0,0,0,0,20595,0,20597,20598,0,0,0,20618,20620,0,0,0,0, 20621,0,0,0,0,20627,0,0,0,0,0,20628,0,0,0,20629,0,20630,0,0,20639,0,0,0,0,0, 20707,0,0,20709,0,0,0,20713,20714,0,0,0,0,0,20724,20725,0,0,0,0,20726,20728, 20729,0,20733,0,20734,0,20735,20736,0,20737,0,0,20744,0,20745,0,20748,0,0,20749, 0,0,0,0,0,0,0,0,20750,0,0,0,0,20754,0,0,0,20761,0,0,20763,0,0,0,0,0,0,0,20766,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,20767,0,0,0,0,20768,0,20769,20777,0,0,0,0,0,0,20785,0, 0,0,20786,20795,20801,0,20802,0,20807,0,0,20808,0,0,20810,0,0,20811,0,20812,0,0, 0,0,0,20813,0,0,20818,20820,20821,0,0,0,20822,0,20823,0,0,0,20826,0,0,0,0,0,0,0, 20829,20830,20831,0,20832,20836,0,0,20839,0,0,20840,20842,0,20843,0,20844,0, 20854,0,0,0,20855,0,0,0,0,20856,0,0,0,20869,0,0,20871,0,0,0,0,0,0,0,20873,0,0,0, 0,0,20876,0,0,0,0,0,20880,0,0,20882,0,0,0,0,20883,20884,0,0,20890,0,0,0,0,0,0,0, 0,0,20891,0,0,0,0,0,20905,0,20906,20910,0,0,20912,20915,0,0,0,0,0,20916,0,20917, 0,20919,20920,20922,0,20927,0,20928,20929,20930,0,0,20935,0,0,20939,0,0,20941,0, 0,0,20943,0,0,0,20946,20947,0,0,0,0,0,20950,0,20954,0,0,20955,20964,0,0,20967,0, 0,0,0,0,20973,20975,0,0,0,20984,0,20987,20988,0,0,0,0,0,20989,0,0,0,20995,0, 20998,0,20999,0,0,0,0,21000,21001,0,0,0,0,21008,0,21010,0,21016,0,0,0,21017, 21018,0,0,0,0,0,21021,21026,21027,21028,0,0,21029,0,0,0,0,0,21030,0,0,0,0,0,0,0, 0,0,0,0,0,0,21031,21032,0,0,0,0,0,21037,0,0,21038,0,0,0,0,0,0,0,0,0,21039,0, 21041,0,21046,21047,0,0,0,21049,21053,0,0,21057,21064,21065,0,0,21066,21067,0,0, 0,21069,0,0,0,21071,21072,0,0,21073,0,21074,0,0,21078,0,0,0,0,21079,0,0,21080, 21081,0,0,21086,21087,0,21089,0,0,0,0,0,0,0,21091,0,21093,0,21094,0,0,0,0,0,0,0, 0,21095,0,0,0,0,0,21096,0,21098,0,0,0,0,0,0,0,21099,0,0,21100,21101,21102,0,0,0, 0,0,21103,0,21104,0,0,0,0,0,21105,21108,21109,0,0,21112,21113,0,0,0,0,0,0,21115, 21122,21123,0,0,0,0,0,21125,0,0,0,0,0,0,0,0,21129,21131,0,0,21134,0,0,0,21137, 21142,0,21143,0,0,21144,0,21145,21146,0,21152,21154,21155,21156,0,0,0,21160,0,0, 0,0,0,0,21161,0,21164,0,21166,0,0,0,0,21170,0,0,0,0,21171,0,0,21172,0,21174,0, 21175,0,0,0,0,0,21176,21179,21188,0,0,0,21189,0,0,21190,0,0,0,21192,0,0,21193,0, 0,0,21198,0,21212,0,0,21213,0,0,0,0,0,0,21215,21216,0,0,21223,21225,0,21226,0,0, 0,0,21227,21228,0,0,21229,0,0,0,0,21230,21236,0,0,0,0,0,0,0,0,0,0,0,0,0,21237,0, 0,21238,21239,0,0,0,0,21256,0,0,0,0,0,21257,0,0,0,0,0,0,0,21259,0,0,0,21263,0, 21272,0,21274,0,21282,0,0,0,0,0,0,0,0,21283,0,0,0,0,0,0,0,0,21294,0,0,21297,0,0, 0,0,21298,0,0,0,21299,0,21300,21302,0,21316,0,21318,21322,21323,0,21324,0,21326, 0,0,0,21327,21328,0,0,0,21352,0,0,21354,21361,0,0,0,0,0,0,0,0,0,0,0,0,0,21362,0, 0,0,21363,0,0,0,0,0,0,0,0,0,21366,0,0,21367,21372,21374,0,0,0,21375,21377,0, 21378,0,0,0,21380,0,0,0,0,0,0,0,0,0,0,21381,0,0,0,0,0,0,21382,0,21383,0,0,21384, 0,0,21385,0,0,0,0,21389,21390,0,0,0,0,0,0,0,0,0,0,0,0,0,21397,21398,0,0,0,0,0,0, 0,0,0,0,21399,0,21400,0,0,0,0,21402,0,0,0,21403,21404,0,21405,21406,0,0,0,21407, 0,0,0,0,0,0,0,0,0,0,0,0,21408,0,0,0,0,21409,0,21421,0,21422,0,0,0,21425,21428,0, 0,0,0,21429,0,0,0,0,0,21433,0,0,0,0,0,0,0,0,0,0,21434,0,21443,0,21444,21449,0, 21452,0,21453,21454,0,0,0,21457,0,0,21458,0,0,0,21460,21461,0,0,21464,0,0,0, 21473,21478,0,0,21479,0,0,21481,21483,0,0,0,0,0,0,0,0,21484,0,0,21485,21486,0,0, 21488,0,0,0,0,0,0,21523,0,0,21525,0,0,0,0,0,0,0,21526,0,0,0,0,0,0,21529,21530,0, 0,21531,0,0,21533,0,0,21539,21564,0,21567,0,0,0,0,0,0,0,0,21575,0,0,0,0,21577,0, 0,0,0,0,21591,0,0,21604,0,0,0,0,0,0,0,0,0,21605,0,21606,0,0,21617,21618,21619, 21620,0,0,0,0,0,0,0,0,0,0,0,0,0,21623,0,0,0,0,21631,0,21635,0,0,0,0,21639,21646, 21653,21662,0,0,21663,21664,0,21666,0,0,21667,0,21670,21672,21673,0,21674,21683, 0,0,0,0,0,21684,0,21694,0,0,0,0,21695,21700,0,21703,0,21704,0,0,21709,0,0,0, 21710,0,0,0,0,0,0,0,0,21711,0,0,0,21712,0,21717,0,21730,0,0,0,21731,21733,0,0,0, 0,21737,21741,21742,0,21747,0,0,0,21749,0,0,0,0,0,0,0,0,0,0,0,0,0,21750,0,0,0,0, 0,21752,0,0,0,0,21753,0,0,0,0,0,0,21755,21756,0,21757,0,0,0,0,0,0,21760,0,0, 21763,0,0,0,0,0,0,0,0,0,21764,0,0,21766,0,0,21767,0,0,0,0,0,0,0,0,0,21773,0, 21774,0,0,21775,0,0,0,0,21776,0,0,21777,0,0,0,0,0,0,0,0,0,21780,21787,21788, 21791,0,0,0,21797,0,0,0,0,0,21805,0,0,0,0,21806,0,21807,21809,0,21810,21811,0, 21817,21819,21820,0,21823,0,21824,0,0,21825,0,0,21826,21832,0,0,0,0,0,21833, 21848,21849,0,0,21867,21870,21871,21873,0,0,0,21874,0,0,0,0,0,0,0,0,0,21875,0, 21878,0,0,0,21879,0,21881,21886,0,0,0,0,21887,0,0,21888,21894,21895,21897,0, 21901,0,21904,0,0,21906,0,0,0,21909,21910,21911,0,0,21912,0,0,21913,21914,21915, 0,21919,0,0,0,0,0,0,0,21921,0,0,21922,21933,21939,0,0,0,0,0,0,0,0,0,0,0,21944,0, 0,0,0,0,21945,0,21947,0,0,0,0,0,0,0,0,0,0,21949,0,0,0,21950,0,0,0,0,0,0,0,0,0,0, 0,0,0,21951,0,21952,0,0,0,0,0,0,0,0,0,21954,21957,0,0,0,0,21958,0,21959,0,0,0,0, 0,0,21962,21963,0,0,0,0,0,0,0,0,21964,21965,0,0,21969,21970,0,0,0,21974,0,0, 21980,21981,0,21982,0,0,0,0,0,21985,0,21988,0,21992,0,21999,0,0,0,0,0,0,22001,0, 22002,0,0,0,0,0,0,22003,0,0,0,0,0,22004,0,0,0,22008,0,22009,22015,0,0,22016,0,0, 0,22017,22019,0,0,0,0,0,0,0,0,0,22020,0,0,0,0,0,0,0,0,0,0,22021,22037,0,22039,0, 0,0,22040,0,0,0,22048,22049,0,0,22053,22055,22056,22059,0,0,22060,22061,0,0, 22064,0,0,0,0,22066,0,0,0,0,0,0,0,22073,0,0,0,22074,22075,0,0,0,0,0,0,0,22076,0, 0,0,0,22077,22084,22099,0,0,0,0,0,0,0,22104,0,0,22107,0,22108,0,22109,0,22110,0, 0,0,0,0,0,0,22111,22119,0,22120,22122,0,0,0,0,22125,0,0,0,22128,22129,0,0,0,0,0, 0,22141,0,0,0,22142,0,0,22144,22146,0,22148,22149,22151,22154,0,0,0,22162,0,0,0, 0,22164,22177,0,0,0,0,22179,0,22182,22183,0,0,22184,22188,0,0,0,0,0,0,0,0,22190, 0,22194,22201,0,0,22208,0,22209,0,22212,0,0,22215,0,22223,22231,0,0,22232,0, 22234,0,0,22235,22236,0,22237,0,22240,0,0,0,0,0,22241,0,0,0,22242,22246,22247,0, 0,0,22259,22268,0,22269,0,0,0,0,0,0,0,22270,0,0,0,0,22271,0,22272,0,22277,0,0,0, 0,0,22278,22280,22283,22286,0,0,22287,22289,0,0,22290,0,22293,0,0,0,0,0,0,0,0,0, 0,22295,0,22301,22302,0,0,0,22305,0,22308,0,0,0,0,0,0,0,0,0,0,22315,0,0,0,22317, 0,22334,0,0,0,22335,0,0,0,0,0,22336,0,22338,22344,0,22347,22349,0,22350,0,0,0,0, 0,0,0,22357,0,0,0,0,0,22358,0,0,0,0,0,0,0,0,0,0,22359,22360,0,0,0,0,0,0,0,0, 22361,22366,0,0,22369,0,22370,22373,0,0,0,0,0,22375,0,22377,0,0,0,0,0,22378,0,0, 0,0,22381,0,0,0,0,22382,0,22383,0,0,0,0,0,0,0,0,0,22391,0,0,22392,22395,22396, 22402,0,0,0,0,0,0,0,0,0,0,0,0,0,22405,0,0,22406,0,0,22408,0,0,22409,22410,0,0,0, 0,0,0,22424,0,0,0,0,22426,0,0,0,22427,0,22428,0,22432,0,22435,22442,22443,0,0,0, 0,22444,0,0,0,0,0,22446,0,22454,0,22455,0,0,0,22465,0,22470,0,22471,0,0,0,0, 22472,22473,0,22487,0,0,0,22488,0,0,0,0,22489,0,0,22499,0,0,0,0,0,0,22514,0,0, 22515,0,0,0,0,0,0,0,22516,0,0,0,22517,22520,0,0,0,22534,0,0,22535,0,0,22536,0, 22540,22553,0,22555,0,0,0,0,22561,0,0,22562,0,0,0,0,0,0,0,0,0,0,0,22566,0,0,0,0, 22567,22568,0,0,22575,0,22579,0,22582,22583,22585,0,0,0,0,0,22586,0,0,22587,0,0, 22590,0,0,0,0,0,22591,0,22592,0,0,0,0,0,22593,0,22602,0,0,22604,0,0,22609,0,0, 22618,0,0,0,0,0,0,22619,0,22624,22625,0,0,22638,0,0,0,0,0,22639,0,0,22640,0,0,0, 0,0,0,0,22644,0,22645,22647,0,0,0,0,22652,22653,0,0,0,22654,0,22655,0,0,0,22656, 0,0,0,0,0,0,0,0,0,0,22673,22675,22676,0,0,22678,22679,0,22691,0,0,0,0,0,0,0, 22693,0,0,22696,0,22699,22707,22708,0,0,0,0,0,0,0,0,22718,0,22719,0,0,0,0,22723, 0,0,0,22724,22725,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22726,22728,0,0,0,0,0,0,0,0,22729, 0,0,22731,0,0,0,0,22732,22735,22736,0,0,0,0,22739,0,22749,0,0,22751,0,0,0,0,0,0, 0,0,0,0,0,22758,0,0,0,0,0,22760,0,0,0,0,0,22764,22765,22766,0,22768,0,0,0,0,0, 22769,22770,0,0,0,0,0,0,22771,0,0,22772,22775,0,22776,22777,22780,0,0,22782, 22784,0,22787,0,22789,22796,0,0,0,0,0,22798,0,0,0,0,0,0,22802,0,22803,22804,0,0, 0,0,0,0,0,0,0,0,22805,0,0,22810,22811,22814,22816,0,22825,22826,0,22831,22833,0, 0,0,0,0,0,0,0,0,22834,0,22836,22838,0,22839,0,0,0,0,0,22840,0,22847,0,0,0,0,0, 22856,22857,0,22858,22859,0,0,22862,0,0,22864,0,0,0,0,22865,0,0,0,0,0,0,0,0,0,0, 0,22866,0,22867,22868,0,0,0,0,22869,0,22871,0,22872,0,22873,22881,22882,22884, 22885,0,0,0,0,0,0,0,22886,22887,0,22894,0,22895,0,0,0,22900,0,22901,0,0,0,0, 22904,0,0,0,0,22905,22907,0,0,0,22915,22917,0,0,22918,0,0,0,22920,0,0,0,22929, 22930,0,0,0,22941,22942,0,0,0,22943,0,0,0,22944,0,0,0,0,0,0,0,22946,0,22947,0,0, 22954,0,22956,0,0,22962,0,0,0,0,0,0,0,22963,0,0,22964,0,0,0,0,0,0,0,22965,0, 22968,0,0,0,22969,0,0,0,0,0,22970,0,22971,0,0,0,0,0,22978,0,0,22979,0,22987,0,0, 22989,0,0,0,0,0,0,22990,0,23005,0,0,0,0,0,0,0,23006,23007,23008,0,0,23023,23024, 23029,0,0,0,0,23030,0,0,0,0,0,23032,0,0,0,0,0,23035,0,0,0,0,23038,0,0,0,23048,0, 23049,23052,23053,23060,23061,0,23063,0,0,0,0,23067,23068,0,0,0,23069,23073,0,0, 0,23127,0,23128,0,0,0,0,0,23129,0,23138,23141,0,23149,0,0,23150,0,0,0,23152,0,0, 0,0,0,0,0,0,23154,0,0,0,0,23157,23159,23160,0,0,0,0,0,0,0,0,0,0,0,0,23180,0,0,0, 0,23181,0,0,23188,0,23189,0,0,0,0,0,0,0,0,0,0,0,0,23195,0,0,23196,23199,0,0,0,0, 0,0,0,0,0,23202,0,23204,0,23207,0,23209,23210,0,0,0,0,0,0,23227,23229,0,0,23230, 23234,23238,0,0,0,23245,23246,23248,0,0,0,0,23249,23254,0,0,0,23265,0,0,0,0,0,0, 0,23268,0,23276,0,0,0,0,23277,0,23297,0,23298,0,0,0,0,23299,0,23302,0,0,23303, 23312,0,0,23314,0,23320,0,0,0,0,23324,0,23325,0,23328,0,23334,0,0,0,23337,0,0,0, 0,23343,23344,23346,0,23348,0,0,0,0,0,0,0,0,23353,0,0,0,0,23355,0,23356,23358,0, 0,0,23359,23360,0,23361,0,23367,0,23369,0,0,23373,0,23378,23379,0,23382,23383,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,23387,0,0,0,0,0,0,23388,23390,0,0,23393,23398,0,0,0, 23399,0,0,0,23400,0,0,0,0,23401,0,0,0,23415,0,0,0,0,0,0,0,0,23416,0,23422,0, 23443,23444,0,0,0,0,23448,0,23454,0,0,0,0,0,0,23456,0,0,23458,23464,0,0,0,0,0,0, 23465,0,0,0,23470,23471,0,0,23472,0,0,0,23473,23496,0,0,0,0,0,0,0,0,23497,0, 23499,0,0,23502,0,0,23503,0,0,23513,0,0,23515,0,0,0,23517,0,0,0,0,23518,23519, 23521,23524,0,23525,23528,23539,0,0,0,0,0,23541,0,0,23544,0,0,23556,0,0,23557,0, 0,0,0,0,0,0,0,0,0,0,0,0,23559,0,23560,0,0,23561,0,0,23566,0,0,0,0,0,23568,23569, 23570,0,0,0,0,23571,0,23574,0,0,0,0,0,0,0,0,0,0,0,23575,0,23579,0,0,23581,0,0,0, 0,0,0,23587,0,0,0,0,0,0,0,23596,23598,0,0,0,0,23602,23606,0,0,23607,0,23608,0,0, 0,23614,23616,0,0,0,0,0,23618,0,0,23619,0,0,0,0,23621,23626,0,23627,0,0,0,0,0,0, 0,23629,0,23630,0,0,0,0,23634,0,23636,0,0,0,0,0,0,23638,0,0,0,0,23640,23667,0, 23669,0,0,0,23681,0,0,0,0,0,0,0,23682,0,23683,0,0,0,0,0,23684,0,0,0,23685,23689, 0,23693,23694,23700,0,23702,0,23709,0,0,0,0,0,0,0,23712,0,0,0,0,0,23714,0,0, 23715,0,0,0,0,23718,0,0,23720,0,0,0,0,23722,0,0,0,23726,23729,0,23741,23746,0, 23748,0,0,0,0,23749,0,0,0,0,0,23750,0,0,0,0,23751,0,23753,0,0,0,0,23757,23765,0, 0,0,23770,0,0,0,0,0,0,0,23771,0,23772,23781,0,0,23796,0,0,0,0,23798,0,23799,0,0, 0,23802,0,0,23806,0,23807,0,0,23808,0,23809,0,23819,0,0,0,23821,0,23827,0,0,0, 23829,0,0,0,0,0,0,0,23830,0,0,0,0,0,0,23832,23833,23834,23835,0,0,0,0,23837, 23838,0,0,0,0,0,23846,0,0,0,0,0,0,23847,0,0,0,0,0,23879,23881,0,0,23882,23883, 23895,0,23899,0,0,0,0,23901,0,0,0,0,0,0,23902,0,0,0,0,0,23903,23905,0,23906,0, 23907,23918,23919,23920,0,23922,0,23924,0,23927,0,23934,0,23937,23941,0,23942, 23946,0,0,0,0,0,23955,23956,23958,0,0,0,0,0,0,23959,0,23962,23965,0,23966,0,0,0, 0,23967,23968,0,0,23973,0,0,23974,0,0,0,0,23975,0,23976,0,0,0,0,0,0,0,0,0,0,0,0, 0,23977,0,0,0,0,0,0,0,0,23980,0,0,23984,0,23985,0,0,23987,0,0,23988,23990,23991, 0,0,0,0,0,0,23992,0,0,0,0,0,0,0,0,23994,0,0,0,23998,0,0,0,0,0,0,0,0,0,23999,0,0, 24003,0,24004,0,24006,0,0,0,24007,0,0,24008,0,0,0,0,0,0,0,24009,0,0,24010,0,0, 24011,0,0,24013,24014,0,0,24015,24016,24027,0,24028,24029,0,24030,0,0,0,0,0, 24033,24034,0,24035,0,0,24036,0,0,24044,0,24048,24049,24063,24067,0,24068,24070, 0,0,24071,24078,24087,0,24090,0,0,0,24095,0,24098,24101,24104,24106,0,24107,0,0, 0,24108,0,0,0,0,24110,24111,0,24113,0,0,24115,24120,0,0,0,0,0,0,24124,0,24125,0, 24126,0,24127,0,0,0,0,0,24135,0,0,24136,0,24137,24142,0,0,0,24146,0,0,24147, 24149,24154,0,24163,0,0,0,24165,24166,24167,0,0,0,0,0,0,0,0,0,0,24169,24170, 24175,0,0,0,24178,0,0,24179,0,0,24181,0,24184,24197,0,24201,24204,0,0,0,0,0,0, 24206,24212,24220,0,0,0,24224,0,0,0,0,0,0,0,0,24226,0,24234,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,24235,0,24236,0,0,0,0,0,24239,24240,24241,0,0,24248,0,0,24249,0, 24251,0,0,0,0,0,0,24253,0,24268,0,0,0,24269,0,24271,24272,0,0,0,0,24273,0,0, 24274,0,0,24279,0,0,0,0,0,0,0,24280,0,24293,24294,0,0,0,0,0,0,24296,0,0,24323,0, 0,0,24329,24330,24331,24339,0,24351,0,0,24369,24370,0,0,0,24371,0,0,0,0,24372, 24373,24374,0,0,0,0,0,24378,0,0,0,0,24379,0,24381,0,24383,24389,0,24390,0,0, 24394,24395,24400,0,0,0,24401,24402,0,24406,0,0,0,24411,0,0,0,24415,0,24416,0,0, 0,0,0,24417,0,24419,0,24422,0,24423,24428,0,24435,0,0,0,24439,0,0,0,24440,24442, 24446,0,0,0,24447,24448,24449,24452,0,0,0,0,24453,24457,0,0,24458,24459,24460,0, 24465,0,0,0,0,0,0,0,24470,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24471,0,24473, 24474,24475,24476,0,24478,0,0,0,0,24480,0,0,0,0,0,0,0,0,0,0,24481,0,0,0,0,0,0,0, 0,0,0,24482,24485,0,0,0,0,24486,0,0,0,24488,0,0,0,24494,0,0,0,0,24497,0,0,24498, 0,0,0,24499,24506,0,0,0,24507,0,0,24511,0,0,24513,24514,0,0,0,0,0,24517,0,24518, 0,24520,0,24521,24524,24525,0,0,0,0,0,24527,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24528,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24537,24539,0,24540,0,0,0,24548,0,0,0,0,0,24549, 24550,0,0,0,24553,24554,0,24555,0,24556,0,24558,0,0,0,0,0,24560,0,0,0,24561,0,0, 0,0,0,24562,0,0,0,0,0,0,0,0,0,0,0,0,0,24567,0,0,0,0,0,24569,0,0,0,24574,0,24575, 0,0,0,0,0,0,0,0,0,0,0,24577,24581,0,24584,0,0,0,0,0,24585,0,0,0,0,0,24586,0,0, 24587,0,24588,0,0,0,0,0,0,0,0,0,0,24590,24591,0,0,0,0,24592,0,0,0,0,0,0,0,24594, 0,0,0,0,0,0,0,24596,24597,0,0,0,0,24602,24603,0,0,0,0,24604,0,0,24605,0,24610,0, 0,24611,0,0,0,0,24612,24615,24616,24624,0,0,0,24627,0,24638,24639,0,0,0,0,24640, 0,0,0,24655,24656,24657,0,0,0,0,0,0,0,0,24662,0,24663,24664,0,0,0,0,0,24665,0,0, 0,0,24667,0,0,0,0,0,0,24668,24669,0,24670,24674,0,0,0,24675,0,24678,0,0,24679,0, 0,0,24681,0,24683,0,0,0,0,24684,0,24685,0,0,24686,0,0,24688,24689,0,0,0,0,24690, 24691,0,0,0,0,0,0,0,24697,0,24698,0,0,0,0,0,0,0,0,24709,0,0,0,0,0,24710,0,24712, 0,0,0,0,0,0,24713,24714,0,24715,0,24716,24718,0,24719,0,0,0,0,24720,0,0,24725,0, 0,24738,0,24749,24750,0,0,0,24752,0,0,0,24753,0,0,0,24758,0,0,0,0,0,24762,0, 24763,0,0,0,0,0,0,0,24764,0,0,0,0,0,24765,24767,24768,0,24772,0,0,0,0,24773,0,0, 0,0,24777,0,0,0,0,0,24785,0,24786,24788,0,0,0,24789,0,0,0,0,24794,24798,0,24799, 24800,0,0,0,24803,0,24804,24806,0,24807,0,0,0,24810,0,0,0,0,0,0,24827,24828,0, 24835,0,0,0,0,0,0,24836,0,0,0,0,0,24839,0,24843,24844,0,0,0,0,0,0,0,0,0,0,24847, 0,0,24848,0,0,0,0,0,0,24849,0,24850,24851,0,0,0,24852,0,24853,0,0,0,0,0,0,0,0,0, 24854,0,24855,0,0,24868,0,0,0,24883,0,0,0,24884,0,24895,24897,0,0,0,0,0,24899,0, 0,0,0,0,24900,0,24913,0,0,0,0,0,0,24914,0,0,24917,24930,24931,0,0,0,24932,0,0, 24939,0,0,24942,0,0,0,0,0,0,0,0,0,24945,24950,0,24951,0,0,24953,0,0,0,24954,0, 24959,0,0,0,24961,0,0,24962,0,24964,24968,24970,24972,0,0,0,0,0,24976,0,0,0, 24977,0,24982,0,0,24983,0,0,24984,0,0,0,24993,0,0,0,24994,0,0,25001,0,0,0,25003, 0,0,25018,0,0,25023,0,0,0,25034,0,0,25035,25036,0,25037,0,0,0,0,0,0,0,25039,0,0, 0,0,0,25040,0,0,0,0,0,0,0,25042,0,0,25043,25045,0,0,0,0,0,0,25049,0,0,25051,0, 25052,25053,0,0,25054,0,0,0,25055,0,0,0,0,25057,25059,0,0,25060,25064,0,25065, 25069,25070,0,0,0,0,25072,0,25073,0,25090,0,0,25092,25093,25101,0,0,0,0,0,0, 25105,25108,0,0,25113,0,0,25115,25116,0,0,0,0,0,0,25117,0,0,0,25120,25121,0,0,0, 0,0,0,0,25125,0,0,0,25126,0,25130,25134,0,25139,0,25143,0,0,0,25151,0,25161,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25163,0,0,0,0,0,0,0,25174,0,25175,0,25207,0,0, 0,25209,0,0,0,0,25213,0,25219,0,25223,0,25225,0,0,0,25227,0,0,0,25228,0,0,0, 25229,0,0,0,0,0,0,0,25231,25233,0,0,0,0,25237,25239,0,0,0,25243,0,0,0,25252,0, 25257,25258,0,0,0,0,25260,25265,0,25268,0,0,25273,25324,0,25325,0,25326,0,0,0,0, 0,0,0,0,25327,0,0,0,0,0,25328,0,0,0,0,0,0,25332,0,0,0,25333,0,0,0,25336,25337, 25338,0,0,25343,0,25350,0,0,0,0,0,0,0,25352,0,25354,0,25375,0,25379,0,0,0,0, 25384,0,0,0,0,0,0,0,0,0,25386,0,25388,0,25390,0,0,25399,0,0,25401,0,0,0,25402,0, 0,0,25407,0,0,0,0,0,0,0,0,0,0,0,25413,25415,0,0,25417,0,0,0,0,0,0,0,25419,0,0,0, 25421,0,0,0,25424,0,0,0,0,25433,0,0,0,0,0,0,0,0,0,25435,0,0,0,0,0,0,25436,0,0,0, 25437,0,0,25440,0,0,0,0,0,0,25442,0,0,25443,0,25446,0,0,25449,0,0,0,25450,0,0,0, 0,25452,0,25453,25454,25455,0,0,0,25456,0,25457,0,0,0,25459,0,25461,0,25468,0,0, 0,0,0,0,0,0,25469,0,0,0,0,0,25471,0,0,0,0,0,25474,0,0,0,0,0,0,0,0,25475,0,0,0,0, 25477,0,0,0,0,25483,0,0,0,0,0,25484,0,0,0,0,0,0,0,0,0,0,0,0,25485,0,25497,0,0, 25498,0,25504,0,25510,0,25512,0,0,25513,25514,0,0,0,0,0,0,25517,25518,25519,0, 25520,0,0,0,0,0,0,0,25521,0,25522,25527,25534,0,25536,0,25537,0,0,25548,25550,0, 0,25551,0,25552,0,0,0,0,0,25554,0,25555,0,25556,25557,25568,0,0,0,25570,25571,0, 0,0,0,0,0,25574,0,0,0,0,25579,0,0,0,25581,0,0,0,25582,0,0,0,0,0,0,0,0,0,25588,0, 0,0,0,25589,0,0,0,0,25590,0,25591,25592,25593,0,25594,0,0,0,25596,0,25597,25615, 0,0,0,0,0,25618,0,0,0,0,25619,25623,0,0,25629,0,0,25631,0,0,0,25635,25636,0,0, 25649,0,0,0,0,25654,0,0,0,25661,25663,0,0,25671,0,0,25678,25698,0,25699,25702, 25703,0,0,0,0,0,0,0,0,25704,0,0,0,0,0,25706,0,0,25710,0,25711,0,25712,0,25715, 25716,25717,0,0,25718,25728,25732,0,0,0,25734,0,0,0,0,0,0,0,0,0,25737,0,0,25739, 0,0,0,25740,0,25741,25745,0,25746,0,25748,25772,25778,0,0,0,0,0,25780,0,0,0,0, 25781,0,25782,25784,25785,0,0,0,25789,0,0,0,0,0,0,25797,25801,0,0,0,25808,25809, 0,0,25811,25814,25815,0,0,25817,0,0,0,0,0,0,0,0,25820,0,0,0,0,25832,25833,0,0,0, 25846,0,0,0,25847,25848,0,0,0,0,0,0,0,0,0,25849,25850,0,0,25851,0,0,25852,0, 25862,0,0,0,25863,25865,0,0,0,0,0,0,0,25867,25868,0,25869,25874,0,25875,0,25876, 25877,0,0,0,0,25878,25902,0,0,0,0,0,0,0,25903,25904,25905,0,0,0,25908,25909,0,0, 0,0,25910,0,0,0,0,0,0,0,25912,0,25913,0,0,0,0,0,0,0,0,25914,0,0,25916,0,0,0,0,0, 25917,25927,0,0,0,0,25928,0,0,25930,0,0,0,25933,0,0,25938,25942,0,0,0,0,0,0,0, 25945,0,25950,0,25956,0,0,25961,25962,0,0,25963,0,25964,25965,25966,0,0,0,0,0, 25967,0,0,0,0,25968,0,0,0,25969,25971,0,0,0,0,0,25973,25975,0,0,0,0,0,0,0,25978, 0,25981,0,0,0,25982,0,0,0,25984,0,0,0,0,0,0,0,25993,0,0,0,0,0,0,0,0,0,0,0,0,0, 26002,0,0,0,26005,0,0,0,26006,26007,0,0,26014,26015,26016,0,0,0,0,0,0,26017, 26018,26020,0,26022,26023,0,0,0,26024,26028,0,26029,26033,26034,26044,0,0,0,0,0, 26046,0,0,26047,0,0,26049,0,26050,0,26051,0,0,0,0,0,26053,0,0,0,0,26054,26059,0, 0,0,0,0,0,26060,0,26066,0,0,0,0,0,0,0,0,0,0,0,0,26067,0,26069,0,0,26071,0,0,0, 26073,0,26074,26077,0,0,0,0,26078,0,0,0,26079,0,26090,0,0,26094,0,0,0,0,0,0,0,0, 26095,0,0,0,0,0,0,0,0,0,0,0,26096,26101,0,26107,26122,0,26124,0,0,26125,0,0,0,0, 0,0,26136,26141,26155,0,0,0,0,0,0,0,0,0,26164,26166,0,0,0,26167,0,26170,26171,0, 0,26172,0,0,26174,0,0,0,0,0,0,0,0,0,0,0,0,0,26175,0,0,0,26176,26177,0,26321, 26322,0,26323,0,0,26324,0,0,0,0,0,0,0,26325,0,26331,0,0,0,0,0,0,26335,0,0,0, 26350,0,0,0,26379,0,0,26382,26383,26385,0,0,26392,26406,0,0,0,0,26411,0,0,0,0,0, 26412,0,0,26420,0,0,26423,0,26424,26426,26432,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 26435,0,26436,0,0,0,0,0,26441,0,26444,0,0,0,26446,0,0,0,0,26447,0,0,0,0,26449,0, 26450,26452,0,26453,26454,0,0,0,26455,0,0,0,26456,0,0,26458,0,0,26460,0,26463,0, 0,0,0,0,0,0,0,26464,26470,0,0,0,0,0,0,0,0,0,26473,0,0,26474,0,0,0,0,0,0,0,26475, 0,0,0,0,0,0,0,26477,0,26485,0,0,26486,0,26487,0,0,26488,26493,26494,0,0,26495,0, 26497,26504,26506,0,0,0,0,0,26507,0,0,0,0,0,26509,0,0,26510,0,0,0,0,0,0,0,0,0,0, 0,0,0,26512,0,26513,26515,0,0,0,26518,0,0,0,26519,0,26524,26526,0,0,0,26527,0, 26532,0,26533,26537,26558,0,0,0,26559,0,0,0,26571,0,0,26573,0,26588,0,26593,0,0, 0,0,0,0,26603,0,26604,0,0,0,0,0,0,0,0,0,0,26606,0,0,0,0,0,0,0,26607,26609,26611, 26614,0,0,0,26616,26620,0,26621,0,0,0,0,0,26627,0,26629,0,0,26630,0,0,26632, 26643,0,0,0,26644,0,0,0,0,0,0,0,0,0,26646,26647,0,0,0,26650,0,0,26656,0,0,0,0, 26663,26670,26671,0,0,0,26685,26686,26687,0,26689,0,0,0,0,26744,0,26745,0,26747, 26748,0,26749,26750,26751,0,0,0,0,26752,26755,0,0,0,26756,26769,0,0,0,26774,0,0, 0,0,0,26775,0,26777,26778,0,26786,0,0,0,26787,0,0,0,0,0,0,0,0,0,0,0,0,0,26788,0, 0,26789,0,0,0,0,0,26791,0,26792,26793,0,0,0,26794,0,26797,26798,0,0,0,26800,0,0, 26803,0,26804,0,0,0,0,0,0,0,0,0,26805,0,0,26808,0,0,26809,0,0,0,0,0,0,0,26812,0, 26825,0,0,0,0,0,0,0,26826,0,0,26827,26829,26834,0,0,0,0,26835,0,0,26849,0,26851, 0,0,0,0,0,0,0,0,0,26852,0,26853,26857,0,26858,0,26859,0,0,0,0,0,0,0,26876,0, 26878,26882,26883,0,0,0,0,26890,26894,0,0,0,0,26895,26896,0,0,0,0,0,26900,0,0,0, 0,0,0,0,26911,26913,26914,26915,26916,26919,0,0,0,26921,26922,0,0,26925,0,0,0, 26928,0,0,26929,26930,0,0,0,26931,0,26932,0,0,0,0,0,26933,0,0,0,0,0,0,26937,0,0, 26943,0,0,26944,0,0,0,26946,0,0,0,0,0,0,0,26956,0,26958,0,0,26963,0,0,0,0,0,0,0, 26965,0,26969,26970,26972,0,0,0,0,0,26973,0,26974,0,26978,0,26980,0,0,0,0,0,0, 26982,0,26986,26987,0,26990,0,0,0,0,27003,27006,0,0,27007,27010,27012,27013,0,0, 0,0,0,0,0,0,27014,27015,27018,0,27019,0,0,0,0,0,27025,0,0,0,27026,0,0,0,0,27029, 27030,27031,27034,0,0,27036,27037,0,0,0,27038,27042,0,0,0,27044,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,27045,0,0,0,0,0,0,0,27046,0,0,0,0,0,0,0,27047,27049,0,27050,0,0,0, 27051,27052,0,27055,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27056,27058,27059,0, 27061,0,27064,0,0,0,0,0,27069,0,0,27070,0,0,0,0,0,0,0,27072,0,0,0,0,0,0,0,0, 27076,0,0,0,0,0,27078,0,27079,0,0,0,27081,0,0,0,0,0,0,27082,0,27083,27086,0,0,0, 0,27087,0,0,0,0,0,27088,27090,0,27094,0,0,27095,0,27099,27102,0,0,0,27103,0,0,0, 0,27105,0,0,0,27106,0,0,0,0,0,0,27107,0,0,0,0,27108,27117,0,0,0,0,27118,0,0, 27124,0,27126,0,0,27130,27131,0,0,0,0,0,0,27147,0,0,0,0,27148,27149,0,0,0,0, 27150,27151,0,27152,0,27159,0,0,0,27164,0,0,0,0,0,0,0,27175,0,27189,0,0,27191,0, 27193,0,27195,0,27198,0,0,0,0,0,27200,0,0,0,0,27202,0,0,0,0,27203,0,0,27204,0,0, 27206,0,27207,0,0,0,0,27209,0,0,0,27213,0,0,27216,27219,27220,27222,27223,0, 27224,0,27225,27226,0,0,27233,0,0,0,0,27235,0,27237,0,27238,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,27239,0,27242,27243,0,27250,0,0,0,27251,0,27253,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,27254,27255,27258,0,0,0,27259,0,0,0,0,0,0,27267,0,27276,27278, 0,0,0,0,0,0,0,0,0,27296,27297,27301,0,0,0,0,0,0,27302,0,0,0,0,0,0,27312,27313,0, 0,0,0,0,27318,0,27320,0,27329,0,27330,27331,0,27332,0,0,0,0,27340,0,0,0,27348,0, 0,0,0,0,0,27350,0,27351,0,0,0,0,27355,0,0,27358,27359,27361,0,0,0,27365,0,27367, 0,27376,27378,0,0,27379,0,0,0,0,0,0,27396,0,27397,27404,0,0,0,0,0,27408,0,0,0,0, 27453,0,0,0,27456,0,0,0,27458,0,0,0,0,0,0,0,27459,0,0,0,27460,0,0,27461,0,27465, 27467,0,0,27469,0,27470,0,27471,0,27477,27482,0,0,0,0,0,0,27484,0,0,0,0,0,0, 27485,0,0,0,0,0,27493,0,27494,27502,0,0,0,0,0,0,0,0,0,0,0,0,27511,27532,0,0,0, 27533,27545,0,0,0,27546,0,0,0,0,0,0,0,0,0,0,27547,0,0,27549,27550,0,27551,0,0,0, 0,0,0,0,27555,0,0,27571,0,27573,27574,27575,27577,0,27578,0,0,27579,27585,0,0,0, 0,0,27586,0,0,27588,27589,0,0,0,0,27596,0,0,27600,0,0,0,0,0,0,0,0,0,0,0,27608,0, 0,0,0,0,0,0,0,0,0,0,27610,0,0,0,27618,0,0,27620,0,0,0,27631,0,0,27632,27634,0, 27636,27638,0,0,0,27643,0,27644,27649,0,0,0,0,0,0,0,0,0,0,0,0,0,27651,27660,0, 27661,0,0,0,0,0,0,0,27662,0,0,27664,0,27665,0,0,0,27669,0,27671,0,0,0,27673, 27674,0,0,0,27682,0,0,0,27711,0,27712,27713,27719,27720,0,0,27728,0,27729,0,0,0, 0,0,0,0,0,0,27731,0,0,27732,0,27733,0,27738,0,0,0,27742,0,0,0,27743,27744,0,0,0, 0,0,0,27745,27746,0,0,0,27747,27748,27751,27752,0,0,0,27768,27770,0,0,0,27774, 27775,0,27776,27777,0,0,27781,0,27784,0,27786,0,0,27791,0,27792,27793,27804,0, 27812,27813,0,0,0,0,0,0,0,0,27814,0,27825,0,27827,0,0,0,0,27828,27861,27862,0,0, 0,27864,0,0,0,27865,27884,0,27889,0,0,0,0,0,27890,0,27891,0,0,0,27892,0,0,0,0,0, 27897,27898,0,0,27899,0,0,0,27901,27905,0,0,27920,0,0,27921,0,27922,0,0,0,27931, 27934,0,0,0,0,0,0,0,0,0,0,27941,0,27942,0,27945,0,27947,27954,0,0,0,0,27960, 27963,0,0,0,0,0,0,0,0,27964,27965,0,0,0,27967,0,27969,27975,0,27976,27977,0, 27981,0,27983,28051,28052,0,0,0,0,0,28056,0,0,0,0,0,0,28058,28059,0,0,28061,0,0, 0,0,0,0,0,28063,0,0,0,0,0,0,28066,0,0,0,0,0,0,28069,28070,28072,0,28073,0,0, 28074,0,0,0,0,28075,0,0,0,0,0,0,0,28078,0,0,0,0,28085,0,0,0,0,28086,0,0,0,0,0,0, 28088,0,0,0,0,0,0,0,0,28090,0,28097,28114,28115,0,0,0,0,0,0,0,28116,0,0,0,0,0, 28118,0,28129,0,28131,0,0,28135,0,0,0,28140,28141,0,0,0,28146,0,0,0,0,28152,0,0, 0,0,28155,28157,28161,0,0,0,0,28166,0,28167,0,0,0,0,0,0,0,0,0,0,0,28172,0,0,0,0, 0,0,28173,0,0,28175,0,0,0,0,0,0,0,0,0,28178,28188,0,28190,0,0,0,0,0,28191,0, 28193,28206,0,0,28207,28209,0,28211,0,28213,0,0,0,28215,28216,28217,0,28222,0, 28223,28225,0,0,0,28226,0,28227,28229,28232,0,0,0,0,0,0,0,0,0,28235,0,28241,0,0, 28242,0,0,0,0,28243,0,0,0,28245,0,0,0,28248,28250,0,28251,28252,0,0,0,0,0,0, 28253,0,0,28254,28255,0,0,28256,0,0,28258,0,0,0,0,0,28259,0,0,28260,0,0,28261,0, 0,0,0,28262,28263,0,0,28264,0,0,0,28266,0,28268,28269,0,28270,28272,28274,0, 28277,28278,0,0,0,28279,0,28280,28281,28283,0,28292,0,28294,0,28297,0,0,0,0, 28299,0,0,0,0,0,28300,0,0,0,0,0,0,0,28301,0,0,0,0,0,0,0,0,0,0,0,0,0,28302,28303, 0,0,0,0,28304,0,0,28305,0,28312,0,28313,28314,0,0,0,0,0,0,28315,0,0,0,28320, 28321,0,0,28328,0,0,0,28329,28338,0,28339,0,0,28344,0,0,0,0,0,0,0,0,28347,0,0,0, 0,0,0,0,0,28348,0,0,0,0,0,28411,0,28412,28413,0,28416,0,0,0,28420,0,0,0,0,0, 28421,0,0,0,0,28423,0,0,0,28424,0,0,28428,0,0,0,0,0,28429,0,0,0,28431,28434,0, 28458,0,0,0,0,0,0,0,0,0,0,0,28464,0,0,0,0,28465,0,28467,0,0,0,0,0,0,28471,0,0,0, 0,28474,0,28480,0,28481,0,0,28485,0,0,0,0,28486,28488,0,0,28489,0,0,0,0,28492,0, 0,0,28495,0,28497,0,28499,0,0,0,0,28500,0,0,28502,28503,0,0,0,28508,0,0,0,28510, 0,0,28512,28513,28514,28521,0,28526,0,28527,28528,0,0,0,0,28529,0,0,28532,0,0, 28537,28538,0,0,0,28539,0,28548,0,28553,28554,0,0,0,0,0,0,0,0,0,0,0,0,28560, 28563,0,0,28564,0,0,0,0,28565,0,0,0,0,0,0,0,28566,28568,0,0,0,0,0,0,28569,0,0,0, 28570,0,28572,28573,0,0,0,0,28575,0,0,0,0,28576,28581,28588,0,0,28589,0,0,0, 28590,28595,0,28598,0,0,28601,0,0,28605,0,0,0,0,28614,28615,28619,0,0,0,0,0,0, 28620,0,28626,0,0,28628,0,28631,0,28632,0,0,0,0,0,0,28635,0,0,0,28637,28638,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28639,0,28643,0,0,28652,0,0,0,28662,0, 28670,28671,0,0,0,0,0,0,0,0,0,28672,28673,28675,28676,0,0,0,0,0,0,0,28691,0,0,0, 28695,0,0,0,28696,0,28697,28698,0,28705,0,28707,28708,28710,0,0,0,0,0,0,0,28711, 28728,0,0,0,28736,0,0,0,28737,0,0,0,0,0,0,0,0,0,28738,0,28739,0,28741,0,0,28742, 0,0,0,0,0,0,0,0,0,0,0,28745,0,0,0,0,0,0,28749,28750,28752,28754,28756,0,28757,0, 0,0,0,28759,28760,0,0,0,0,0,0,28762,0,0,0,28764,0,0,0,0,0,0,28766,0,28767,28768, 0,0,0,0,28769,28770,0,0,0,0,0,0,0,0,0,0,0,0,0,28771,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,28772,0,28773,0,28782,0,0,0,0,0,0,28784,0,28785,0,28786,0,0,0,28787,0,0,0, 28797,0,0,0,0,0,0,28799,0,0,28801,0,0,0,0,28802,0,28805,0,0,28806,0,0,28807,0,0, 0,0,0,0,0,28808,0,0,0,0,0,28810,28812,0,0,28816,28819,0,0,28821,0,28826,0,0,0, 28842,28852,0,0,28853,0,28854,28855,0,0,0,28857,0,0,0,28858,0,28867,28868,28869, 0,0,0,28874,28880,28882,28890,28892,0,0,0,0,0,0,0,28895,0,0,0,28898,28899,0,0,0, 28900,0,0,28904,0,28906,0,0,0,0,28907,0,0,0,0,0,0,28908,0,0,0,28910,0,28914,0,0, 0,0,0,0,0,28915,28916,28919,0,0,28920,0,28921,0,0,0,0,0,0,0,0,28924,0,0,0,0, 28926,28929,0,0,0,28930,0,28936,0,28939,0,0,0,0,28942,0,0,0,0,0,0,28956,0,0,0, 28966,0,0,0,0,28967,0,0,0,0,0,0,0,0,0,28968,0,28971,0,28975,28976,0,28982,28983, 0,0,28984,28989,28996,28997,28998,0,0,0,0,0,0,28999,0,0,0,0,0,29000,0,29001,0,0, 0,29009,0,0,29011,0,0,29021,0,0,0,0,29024,0,29025,0,0,0,0,0,29026,0,0,0,29036,0, 0,0,29037,0,0,0,0,29038,0,29045,0,29047,0,0,0,0,0,0,0,0,0,29051,0,0,0,29054, 29056,29062,0,29070,29082,0,0,0,29083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29084,0,0, 0,0,29085,29088,0,0,0,0,0,0,0,29090,29097,0,0,0,29103,0,0,0,0,0,0,0,0,29105,0,0, 0,0,0,29107,0,29109,0,0,0,29115,0,0,29120,0,0,29138,29140,0,0,0,0,0,0,0,0,0, 29152,0,29160,29174,0,29176,0,0,29180,0,29181,0,0,0,0,0,0,0,0,29228,0,0,29229,0, 0,29230,0,0,0,0,0,0,0,0,0,0,29234,0,0,0,29241,0,29245,0,29248,0,29250,29256, 29280,0,29282,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29285,0,0,29286,29291,29292,0,0,0,0, 29294,0,29295,0,0,0,0,0,29296,29297,29298,29300,0,29302,0,0,29304,29307,0,29312, 0,0,0,29322,0,0,29323,0,0,29324,29326,29328,0,29335,0,0,0,0,0,0,0,29338,29339,0, 0,0,0,0,29341,29343,0,0,0,0,29344,0,0,0,0,0,29345,0,0,0,0,29346,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,29347,29348,29349,0,0,29354,0,0,29355,0,0,0,0,0,0,0,0,29357,0,0, 0,0,29364,0,29365,0,0,0,0,0,0,0,29366,0,0,29368,0,0,0,0,0,0,0,0,29378,0,29381,0, 0,0,0,0,0,0,0,29386,0,0,0,0,0,0,29389,0,0,0,29390,0,0,29391,29397,0,29398,29412, 29414,29418,29419,0,0,0,0,0,0,0,29420,0,0,0,0,0,0,0,29423,0,0,0,29435,0,0,0, 29437,0,0,29439,0,29441,0,0,0,0,29443,0,29446,29450,29452,0,0,0,0,0,29456,0,0,0, 0,0,29461,0,0,0,29464,0,0,0,0,0,0,0,0,29468,0,29473,0,0,0,29486,0,0,0,29490,0,0, 0,29491,29492,0,0,29497,0,0,0,29498,0,29499,0,29502,29505,0,29509,0,0,0,29510,0, 0,0,29512,0,0,0,29516,0,0,0,0,0,0,0,0,29518,0,29519,0,0,0,0,0,29520,29521,29529, 0,0,0,0,0,0,0,0,29530,0,0,29531,29538,0,29540,0,0,0,29542,0,29543,29544,29547,0, 0,29548,0,0,0,29549,0,0,0,29550,0,0,29552,0,0,0,0,29558,29561,0,29562,29564,0,0, 29565,0,0,29566,0,0,0,0,0,0,0,0,0,0,29578,29584,29586,29591,0,0,0,0,29593,29594, 0,0,29597,0,0,29613,0,29614,0,29615,0,0,0,0,29616,29617,0,0,29625,0,0,0,29632,0, 0,0,0,0,0,0,29633,0,0,0,0,0,29634,29635,29637,0,29638,0,29641,29643,0,0,0,0,0,0, 29644,0,29645,0,29649,0,0,0,29650,0,29653,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29656, 29659,0,0,29660,0,0,0,29661,0,0,0,0,0,29664,0,0,0,29671,29673,0,0,0,0,0,0,0, 29675,0,29677,29679,0,0,29684,0,0,0,0,0,29685,0,0,0,29687,0,0,0,29688,0,29689, 29690,29700,0,29701,0,0,0,29702,0,29706,0,0,0,0,0,0,0,29720,0,29721,0,29727,0, 29733,29734,0,29750,29761,0,29763,0,0,0,0,0,29764,0,0,29765,0,0,0,29771,0,0,0,0, 0,0,0,0,0,0,0,0,29772,0,0,0,29773,29774,29775,0,0,0,0,0,0,0,0,0,0,0,29822,0,0,0, 29824,0,29825,0,0,0,0,0,29827,0,0,0,0,0,0,0,0,29829,0,29832,29834,0,0,29835,0,0, 29837,29838,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29843,0,0,0,0,29844,29845,0,0,0, 0,0,0,0,0,0,29849,0,0,29869,29872,29890,29905,0,0,0,0,0,29907,29921,0,29922,0,0, 29923,29926,29944,29946,0,0,0,0,0,0,0,29947,29948,0,0,0,29951,0,0,0,0,0,29953,0, 0,29956,0,29957,0,0,29962,0,0,0,0,29971,0,0,0,29972,0,0,0,0,0,29978,0,29979, 29992,30007,30008,30010,0,0,0,30013,0,0,0,0,30014,30016,0,0,0,0,0,0,0,0,0,0,0, 30017,0,0,0,0,0,30023,30031,0,0,30033,0,0,0,0,0,0,0,0,0,0,30034,0,30038,0,30039, 0,30040,0,0,0,0,0,0,30067,30068,0,0,0,30069,0,30072,0,0,0,30073,0,0,0,0,30075,0, 0,0,0,0,0,30079,0,0,30080,0,0,0,0,0,30082,0,0,0,0,0,0,0,0,0,0,0,30084,30090,0,0, 30091,0,0,0,0,30098,30118,0,30119,0,30121,30130,0,0,0,0,0,0,0,0,0,0,0,0,0,30131, 30132,30133,0,0,0,0,0,0,30135,0,0,0,0,0,0,0,0,0,0,0,30136,0,0,30137,30138,0,0,0, 30139,30146,0,0,0,0,0,30147,0,0,30148,30151,0,0,0,30168,0,30172,30173,0,0,0,0,0, 0,0,0,30180,30181,0,30192,0,0,0,0,0,0,0,30194,30196,0,0,30199,0,0,30202,0,0,0,0, 30203,0,0,0,0,0,0,0,0,0,0,30213,0,0,0,30216,0,0,30217,0,0,0,30218,0,0,0,0,30219, 0,30220,0,30222,30227,0,0,0,0,0,30231,0,0,30233,30235,0,0,0,0,30238,0,30240, 30243,30245,0,30250,30252,0,0,0,30269,0,0,30271,30272,0,0,0,30278,30280,0,0, 30282,0,30284,0,30294,0,0,0,0,30295,30296,0,0,0,0,0,30298,30299,30302,30304, 30306,0,0,0,0,0,0,30316,30317,0,0,0,30318,0,0,0,30319,0,30320,30322,30326,0,0,0, 0,0,30327,0,30332,30348,30349,0,0,30356,0,0,0,0,0,0,0,0,30357,0,30358,0,30359, 30360,0,0,30365,30366,30378,0,0,0,0,30379,0,0,30381,0,30385,0,30388,30397,0,0,0, 30401,0,0,0,0,30403,0,0,0,0,0,30404,0,0,30405,0,30406,30408,0,30409,0,30410,0,0, 0,30417,0,0,30418,30419,0,30420,0,30424,0,0,0,30427,30430,30432,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,30433,0,0,0,0,0,0,0,30436,0,30437,30438,0,30441,30442,0,0, 0,30445,0,0,0,0,30452,30456,30457,0,0,0,30458,0,30464,0,0,0,0,0,0,30467,0,30469, 0,0,0,0,0,30477,0,0,30484,0,0,0,0,0,30485,0,0,0,0,0,30486,30487,30497,30498,0,0, 0,0,0,0,0,0,0,0,30505,0,30508,0,0,0,30509,30510,0,30514,30516,0,0,0,0,0,0,0,0,0, 0,0,30523,0,30524,0,30525,0,0,0,0,30537,0,0,30538,0,0,0,0,0,30553,0,0,30555, 30556,30558,30559,30560,0,0,30561,0,30562,0,0,0,0,0,0,0,0,30563,30570,30571,0, 30586,30587,0,0,30590,0,0,30594,0,0,0,0,30611,30612,30623,30634,0,0,30636,30640, 30655,30656,0,30657,0,0,30658,30669,0,30670,0,30676,30678,0,0,0,0,0,0,0,30679,0, 0,0,0,0,0,0,0,0,0,0,30695,0,0,30698,0,0,0,0,30700,0,0,0,0,30701,0,30702,30703,0, 0,0,0,30707,0,0,0,30709,0,0,30710,30719,30729,0,0,0,0,0,0,0,0,0,30731,0,0,30733, 0,0,0,30734,0,0,0,0,0,30736,30737,0,0,0,30740,0,0,0,30743,0,30746,0,30747,30748, 0,0,30751,30752,30753,0,0,0,30754,0,0,30760,0,0,0,0,0,0,0,30763,0,30764,0,0, 30766,0,30769,30770,30771,30774,30777,0,0,30779,30780,30781,0,0,0,0,30790,0,0,0, 30792,0,0,0,0,30810,0,0,0,0,0,0,0,30812,30819,0,0,30823,30824,0,30825,0,30827,0, 0,0,0,0,0,30828,0,0,30830,0,0,0,30834,0,30835,0,30837,30838,0,30845,0,0,0,0,0, 30846,30847,0,0,30849,0,30851,0,0,0,0,0,30852,30858,0,0,30859,0,30865,0,0,30866, 0,0,30868,0,0,30869,0,0,0,30881,30883,0,0,0,0,0,30889,0,30891,0,0,0,0,30894,0, 30895,0,30897,0,30898,0,0,0,30904,30906,0,30909,0,0,0,0,0,0,30910,0,0,0,30915, 30933,30942,0,0,0,0,30943,0,0,30945,0,0,0,0,0,0,30946,0,0,30947,0,0,30955,30956, 0,0,30960,0,0,30961,30962,30966,0,0,30969,30974,0,0,0,30976,0,0,30977,0,30978, 30982,0,0,0,0,0,0,0,30994,30995,30998,0,31000,0,0,31001,0,0,31003,31005,0,0, 31006,31011,0,0,31014,0,31016,0,0,0,0,31018,0,0,31020,31023,31024,31025,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,31027,31028,31029,0,0,0,0,0,0,31032,0,0,0,0,0,0,0,0,0,0,0, 31036,31037,31038,0,0,0,31041,31043,31045,0,31047,0,0,0,31048,0,31049,0,0,0, 31053,31054,31055,0,0,31063,0,0,0,0,0,31066,0,31068,31071,0,0,0,31072,31073,0,0, 0,0,31075,0,0,31076,0,0,0,31077,31079,0,31080,0,0,0,0,0,0,0,0,0,0,31087,0,31142, 0,31144,0,0,31145,31146,31147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31149,0,31151,31152,0, 0,0,0,0,0,0,31162,31171,31174,31175,0,0,0,31176,0,0,0,0,0,0,0,31179,0,0,0,31186, 0,0,0,31192,31195,0,0,31196,0,0,0,0,0,0,0,0,31198,0,0,0,0,0,31199,0,0,0,31205,0, 0,0,0,31211,31215,0,0,0,0,31231,0,31232,0,0,0,0,0,0,0,0,0,0,31233,31236,31253,0, 31254,0,0,0,0,0,0,31255,0,0,31257,0,0,0,0,0,0,0,0,0,31258,31259,0,0,31260,0, 31261,0,0,0,0,0,31262,31263,0,0,31264,0,31266,0,31267,0,0,0,0,0,31281,0,31282,0, 31284,0,0,31285,31287,31288,0,0,31290,0,0,0,31292,31295,0,31299,0,31300,0,0,0,0, 0,31302,0,0,0,0,31303,0,0,0,0,0,0,31304,0,0,0,0,0,31305,31308,31309,31315,0, 31317,0,0,0,0,0,31323,0,31324,0,0,0,0,0,31325,31327,0,0,31331,0,0,0,0,0,31333,0, 0,0,0,0,31336,0,0,31337,0,0,0,0,0,0,31338,0,0,0,0,0,0,0,0,0,0,0,0,31339,0,0,0,0, 0,0,0,31342,0,0,0,0,31345,0,0,0,0,0,0,0,0,31347,0,0,0,0,0,0,31348,0,0,31350, 31351,0,31352,0,0,31354,0,0,0,0,31355,0,0,31356,0,0,0,0,0,0,0,0,0,0,31363,0, 31372,0,0,31373,0,0,0,0,0,0,0,0,0,31376,0,31388,0,31389,0,31392,0,31401,0,31405, 31407,31408,0,31409,0,0,0,0,0,0,31413,31415,0,0,0,31416,31418,0,0,0,0,0,0,31422, 31423,0,0,31424,0,31425,31432,0,0,0,0,0,0,0,0,0,31433,0,0,0,0,0,0,0,0,31434,0,0, 0,0,0,0,31435,0,0,0,0,31438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31442,0,31444,0, 31448,0,0,31451,0,0,0,0,31452,0,31461,31465,0,0,31466,0,0,31467,0,0,31468,0,0,0, 31469,31473,0,31476,0,0,0,0,31489,31490,0,0,0,0,0,0,0,31492,31493,31494,0,0,0,0, 31501,31504,31505,0,0,0,0,0,0,0,0,0,31509,0,0,0,0,31510,0,0,31511,0,0,31513,0,0, 0,0,0,0,0,0,0,31514,0,31522,31536,31539,31540,0,31541,0,0,0,0,0,0,31546,31553, 31559,0,0,0,31560,31561,31562,0,0,31564,31567,0,31569,0,0,0,31570,0,0,0,0,31571, 0,0,0,0,0,0,31572,31574,31580,31581,0,0,31582,31584,31585,31586,31595,0,31596,0, 0,0,0,31597,0,31599,0,31600,31601,0,0,31603,31604,0,0,31608,31610,0,0,0,31611,0, 31615,0,0,0,0,31616,0,0,0,0,0,0,31617,0,0,0,0,0,31618,0,0,0,0,0,0,31621,0,0,0,0, 0,0,0,0,0,31622,31625,0,0,0,0,31627,0,31641,0,0,31642,0,0,31643,0,0,0,0,0,0,0,0, 0,31644,0,31646,0,0,0,0,31648,0,0,0,31652,0,0,0,31657,0,0,31676,0,0,0,0,0,0,0, 31689,31691,31692,0,31694,0,0,0,31696,0,31702,0,31703,0}; static const DictWord kStaticDictionaryWords[31705] = { {0,0,0},{8,0,1002},{136,0,1015},{4,0,683},{4,10,325},{138,10,125},{7,11,572},{9, 11,592},{11,11,680},{11,11,842},{11,11,924},{12,11,356},{12,11,550},{13,11,317}, {13,11,370},{13,11,469},{13,11,471},{14,11,397},{18,11,69},{146,11,145},{134,0, 1265},{136,11,534},{134,0,1431},{11,0,138},{140,0,40},{4,0,155},{7,0,1689},{4,10 ,718},{135,10,1216},{4,0,245},{5,0,151},{5,0,741},{6,0,1147},{7,0,498},{7,0,870} ,{7,0,1542},{12,0,213},{14,0,36},{14,0,391},{17,0,111},{18,0,6},{18,0,46},{18,0, 151},{19,0,36},{20,0,32},{20,0,56},{20,0,69},{20,0,102},{21,0,4},{22,0,8},{22,0, 10},{22,0,14},{150,0,31},{4,0,624},{135,0,1752},{5,10,124},{5,10,144},{6,10,548} ,{7,10,15},{7,10,153},{137,10,629},{6,0,503},{9,0,586},{13,0,468},{14,0,66},{16, 0,58},{7,10,1531},{8,10,416},{9,10,275},{10,10,100},{11,10,658},{11,10,979},{12, 10,86},{14,10,207},{15,10,20},{143,10,25},{5,0,603},{7,0,1212},{9,0,565},{14,0, 301},{5,10,915},{6,10,1783},{7,10,211},{7,10,1353},{9,10,83},{10,10,376},{10,10, 431},{11,10,543},{12,10,664},{13,10,280},{13,10,428},{14,10,128},{17,10,52},{145 ,10,81},{4,0,492},{133,0,451},{135,0,835},{141,0,70},{132,0,539},{7,11,748},{139 ,11,700},{7,11,1517},{11,11,597},{14,11,76},{14,11,335},{148,11,33},{6,0,113},{ 135,0,436},{4,10,338},{133,10,400},{136,0,718},{133,11,127},{133,11,418},{6,0, 1505},{7,0,520},{6,11,198},{11,10,892},{140,11,83},{4,10,221},{5,10,659},{5,10, 989},{7,10,697},{7,10,1211},{138,10,284},{135,0,1070},{5,11,276},{6,11,55},{135, 11,1369},{134,0,1515},{6,11,1752},{136,11,726},{138,10,507},{15,0,78},{4,10,188} ,{135,10,805},{5,10,884},{139,10,991},{133,11,764},{134,10,1653},{6,11,309},{7, 11,331},{138,11,550},{135,11,1861},{132,11,348},{135,11,986},{135,11,1573},{12,0 ,610},{13,0,431},{144,0,59},{9,11,799},{140,10,166},{134,0,1530},{132,0,750},{ 132,0,307},{133,0,964},{6,11,194},{7,11,133},{10,11,493},{10,11,570},{139,11,664 },{5,11,24},{5,11,569},{6,11,3},{6,11,119},{6,11,143},{6,11,440},{7,11,295},{7, 11,599},{7,11,1686},{7,11,1854},{8,11,424},{9,11,43},{9,11,584},{9,11,760},{10, 11,148},{10,11,328},{11,11,159},{11,11,253},{11,11,506},{12,11,487},{12,11,531}, {144,11,33},{136,10,760},{5,11,14},{5,11,892},{6,11,283},{7,11,234},{136,11,537} ,{135,11,1251},{4,11,126},{8,11,635},{147,11,34},{4,11,316},{135,11,1561},{6,0, 999},{6,0,1310},{137,11,861},{4,11,64},{5,11,352},{5,11,720},{6,11,368},{139,11, 359},{4,0,75},{5,0,180},{6,0,500},{7,0,58},{7,0,710},{10,0,645},{136,10,770},{ 133,0,649},{6,0,276},{7,0,282},{7,0,879},{7,0,924},{8,0,459},{9,0,599},{9,0,754} ,{11,0,574},{12,0,128},{12,0,494},{13,0,52},{13,0,301},{15,0,30},{143,0,132},{ 132,0,200},{4,10,89},{5,10,489},{6,10,315},{7,10,553},{7,10,1745},{138,10,243},{ 135,11,1050},{7,0,1621},{6,10,1658},{9,10,3},{10,10,154},{11,10,641},{13,10,85}, {13,10,201},{141,10,346},{6,11,175},{137,11,289},{5,11,432},{133,11,913},{6,0, 225},{137,0,211},{7,0,718},{8,0,687},{139,0,374},{4,10,166},{133,10,505},{9,0, 110},{134,10,1670},{8,0,58},{9,0,724},{11,0,809},{13,0,113},{145,0,72},{6,0,345} ,{7,0,1247},{144,11,82},{5,11,931},{134,11,1698},{8,0,767},{8,0,803},{9,0,301},{ 137,0,903},{139,0,203},{134,0,1154},{7,0,1949},{136,0,674},{134,0,259},{135,0, 1275},{5,11,774},{6,11,1637},{6,11,1686},{134,11,1751},{134,0,1231},{7,10,445},{ 8,10,307},{8,10,704},{10,10,41},{10,10,439},{11,10,237},{11,10,622},{140,10,201} ,{136,0,254},{6,11,260},{135,11,1484},{139,0,277},{135,10,1977},{4,10,189},{5,10 ,713},{6,11,573},{136,10,57},{138,10,371},{132,10,552},{134,11,344},{133,0,248}, {9,0,800},{10,0,693},{11,0,482},{11,0,734},{11,0,789},{134,11,240},{4,0,116},{5, 0,95},{5,0,445},{7,0,1688},{8,0,29},{9,0,272},{11,0,509},{11,0,915},{4,11,292},{ 4,11,736},{5,11,871},{6,11,171},{6,11,1689},{7,11,1324},{7,11,1944},{9,11,415},{ 9,11,580},{14,11,230},{146,11,68},{7,0,490},{13,0,100},{143,0,75},{135,0,1641},{ 133,0,543},{7,11,209},{8,11,661},{10,11,42},{11,11,58},{12,11,58},{12,11,118},{ 141,11,32},{5,0,181},{8,0,41},{6,11,63},{135,11,920},{133,0,657},{133,11,793},{ 138,0,709},{7,0,25},{8,0,202},{138,0,536},{5,11,665},{135,10,1788},{145,10,49},{ 9,0,423},{140,0,89},{5,11,67},{6,11,62},{6,11,374},{135,11,1391},{8,0,113},{9,0, 877},{10,0,554},{11,0,83},{12,0,136},{19,0,109},{9,11,790},{140,11,47},{138,10, 661},{4,0,963},{10,0,927},{14,0,442},{135,10,1945},{133,0,976},{132,0,206},{4,11 ,391},{135,11,1169},{134,0,2002},{6,0,696},{134,0,1008},{134,0,1170},{132,11,271 },{7,0,13},{8,0,226},{10,0,537},{11,0,570},{11,0,605},{11,0,799},{11,0,804},{12, 0,85},{12,0,516},{12,0,623},{13,0,112},{13,0,361},{14,0,77},{14,0,78},{17,0,28}, {19,0,110},{140,11,314},{132,0,769},{134,0,1544},{4,0,551},{137,0,678},{5,10,84} ,{134,10,163},{9,0,57},{9,0,459},{10,0,425},{11,0,119},{12,0,184},{12,0,371},{13 ,0,358},{145,0,51},{5,0,188},{5,0,814},{8,0,10},{9,0,421},{9,0,729},{10,0,609},{ 11,0,689},{4,11,253},{5,10,410},{5,11,544},{7,11,300},{137,11,340},{134,0,624},{ 138,11,321},{135,0,1941},{18,0,130},{5,10,322},{8,10,186},{9,10,262},{10,10,187} ,{142,10,208},{5,11,53},{5,11,541},{6,11,94},{6,11,499},{7,11,230},{139,11,321}, {133,10,227},{4,0,378},{4,11,920},{5,11,25},{5,11,790},{6,11,457},{135,11,853},{ 137,0,269},{132,0,528},{134,0,1146},{7,10,1395},{8,10,486},{9,10,236},{9,10,878} ,{10,10,218},{11,10,95},{19,10,17},{147,10,31},{7,10,2043},{8,10,672},{141,10, 448},{134,0,1105},{134,0,1616},{134,11,1765},{140,11,163},{5,10,412},{133,11,822 },{132,11,634},{6,0,656},{134,11,1730},{134,0,1940},{5,0,104},{6,0,173},{135,0, 1631},{136,10,562},{6,11,36},{7,11,658},{8,11,454},{147,11,86},{5,0,457},{134,10 ,1771},{7,0,810},{8,0,138},{8,0,342},{9,0,84},{10,0,193},{11,0,883},{140,0,359}, {9,0,620},{135,10,1190},{137,10,132},{7,11,975},{137,11,789},{6,0,95},{6,0,1934} ,{136,0,967},{141,11,335},{6,0,406},{10,0,409},{10,0,447},{11,0,44},{140,0,100}, {4,10,317},{135,10,1279},{132,0,477},{134,0,1268},{6,0,1941},{8,0,944},{5,10,63} ,{133,10,509},{132,0,629},{132,11,104},{4,0,246},{133,0,375},{6,0,1636},{132,10, 288},{135,11,1614},{9,0,49},{10,0,774},{8,10,89},{8,10,620},{11,10,628},{12,10, 322},{143,10,124},{4,0,282},{7,0,1034},{11,0,398},{11,0,634},{12,0,1},{12,0,79}, {12,0,544},{14,0,237},{17,0,10},{146,0,20},{132,0,824},{7,11,45},{9,11,542},{9, 11,566},{138,11,728},{5,0,118},{5,0,499},{6,0,476},{6,0,665},{6,0,1176},{6,0, 1196},{7,0,600},{7,0,888},{135,0,1096},{7,0,296},{7,0,596},{8,0,560},{8,0,586},{ 9,0,612},{11,0,304},{12,0,46},{13,0,89},{14,0,112},{145,0,122},{5,0,894},{6,0, 1772},{9,0,1009},{138,10,120},{5,11,533},{7,11,755},{138,11,780},{151,10,1},{6,0 ,1474},{7,11,87},{142,11,288},{139,0,366},{137,10,461},{7,11,988},{7,11,1939},{9 ,11,64},{9,11,502},{12,11,7},{12,11,34},{13,11,12},{13,11,234},{147,11,77},{7,0, 1599},{7,0,1723},{8,0,79},{8,0,106},{8,0,190},{8,0,302},{8,0,383},{8,0,713},{9,0 ,119},{9,0,233},{9,0,419},{9,0,471},{10,0,181},{10,0,406},{11,0,57},{11,0,85},{ 11,0,120},{11,0,177},{11,0,296},{11,0,382},{11,0,454},{11,0,758},{11,0,999},{12, 0,27},{12,0,98},{12,0,131},{12,0,245},{12,0,312},{12,0,446},{12,0,454},{13,0,25} ,{13,0,98},{13,0,426},{13,0,508},{14,0,70},{14,0,163},{14,0,272},{14,0,277},{14, 0,370},{15,0,95},{15,0,138},{15,0,167},{17,0,38},{148,0,96},{135,10,1346},{10,0, 200},{19,0,2},{151,0,22},{135,11,141},{134,10,85},{134,0,1759},{138,0,372},{145, 0,16},{8,0,943},{132,11,619},{139,11,88},{5,11,246},{8,11,189},{9,11,355},{9,11, 512},{10,11,124},{10,11,453},{11,11,143},{11,11,416},{11,11,859},{141,11,341},{5 ,0,258},{134,0,719},{6,0,1798},{6,0,1839},{8,0,900},{10,0,874},{10,0,886},{12,0, 698},{12,0,732},{12,0,770},{16,0,106},{18,0,163},{18,0,170},{18,0,171},{152,0,20 },{9,0,707},{11,0,326},{11,0,339},{12,0,423},{12,0,502},{20,0,62},{9,11,707},{11 ,11,326},{11,11,339},{12,11,423},{12,11,502},{148,11,62},{5,0,30},{7,0,495},{8,0 ,134},{9,0,788},{140,0,438},{133,11,678},{5,10,279},{6,10,235},{7,10,468},{8,10, 446},{9,10,637},{10,10,717},{11,10,738},{140,10,514},{5,11,35},{6,11,287},{7,11, 862},{7,11,1886},{138,11,179},{7,0,1948},{7,0,2004},{132,11,517},{5,10,17},{6,10 ,371},{137,10,528},{4,0,115},{5,0,669},{6,0,407},{8,0,311},{11,0,10},{141,0,5},{ 137,0,381},{5,0,50},{6,0,439},{7,0,780},{135,0,1040},{136,11,667},{11,11,403},{ 146,11,83},{5,0,1},{6,0,81},{138,0,520},{134,0,738},{5,0,482},{8,0,98},{9,0,172} ,{10,0,360},{10,0,700},{10,0,822},{11,0,302},{11,0,778},{12,0,50},{12,0,127},{12 ,0,396},{13,0,62},{13,0,328},{14,0,122},{147,0,72},{9,11,157},{10,11,131},{140, 11,72},{135,11,714},{135,11,539},{5,0,2},{6,0,512},{7,0,797},{7,0,1494},{8,0,253 },{8,0,589},{9,0,77},{10,0,1},{10,0,129},{10,0,225},{11,0,118},{11,0,226},{11,0, 251},{11,0,430},{11,0,701},{11,0,974},{11,0,982},{12,0,64},{12,0,260},{12,0,488} ,{140,0,690},{5,11,394},{7,11,367},{7,11,487},{7,11,857},{7,11,1713},{8,11,246}, {9,11,537},{10,11,165},{12,11,219},{140,11,561},{136,0,557},{5,10,779},{5,10,807 },{6,10,1655},{134,10,1676},{4,10,196},{5,10,558},{133,10,949},{11,11,827},{12, 11,56},{14,11,34},{143,11,148},{137,0,347},{133,0,572},{134,0,832},{4,0,12},{7,0 ,504},{7,0,522},{7,0,809},{8,0,797},{141,0,88},{4,10,752},{133,11,449},{7,11,86} ,{8,11,103},{145,11,69},{7,11,2028},{138,11,641},{5,0,528},{6,11,1},{142,11,2},{ 134,0,861},{10,0,294},{4,10,227},{5,10,159},{5,10,409},{7,10,80},{10,10,479},{12 ,10,418},{14,10,50},{14,10,249},{142,10,295},{7,10,1470},{8,10,66},{8,10,137},{8 ,10,761},{9,10,638},{11,10,80},{11,10,212},{11,10,368},{11,10,418},{12,10,8},{13 ,10,15},{16,10,61},{17,10,59},{19,10,28},{148,10,84},{20,0,109},{135,11,1148},{6 ,11,277},{7,11,1274},{7,11,1386},{7,11,1392},{12,11,129},{146,11,87},{6,11,187}, {7,11,39},{7,11,1203},{8,11,380},{8,11,542},{14,11,117},{149,11,28},{134,0,1187} ,{5,0,266},{9,0,290},{9,0,364},{10,0,293},{11,0,606},{142,0,45},{6,11,297},{7,11 ,793},{139,11,938},{4,0,50},{6,0,594},{9,0,121},{10,0,49},{10,0,412},{139,0,834} ,{136,0,748},{7,11,464},{8,11,438},{11,11,105},{11,11,363},{12,11,231},{14,11, 386},{15,11,102},{148,11,75},{132,0,466},{13,0,399},{14,0,337},{6,10,38},{7,10, 1220},{8,10,185},{8,10,256},{9,10,22},{9,10,331},{10,10,738},{11,10,205},{11,10, 540},{11,10,746},{13,10,465},{142,10,194},{9,0,378},{141,0,162},{137,0,519},{4, 10,159},{6,10,115},{7,10,252},{7,10,257},{7,10,1928},{8,10,69},{9,10,384},{10,10 ,91},{10,10,615},{12,10,375},{14,10,235},{18,10,117},{147,10,123},{5,11,604},{5, 10,911},{136,10,278},{132,0,667},{8,0,351},{9,0,322},{4,10,151},{135,10,1567},{ 134,0,902},{133,10,990},{12,0,180},{5,10,194},{7,10,1662},{137,10,90},{4,0,869}, {134,0,1996},{134,0,813},{133,10,425},{137,11,761},{132,0,260},{133,10,971},{5, 11,20},{6,11,298},{7,11,659},{7,11,1366},{137,11,219},{4,0,39},{5,0,36},{7,0, 1843},{8,0,407},{11,0,144},{140,0,523},{4,0,510},{10,0,587},{139,10,752},{7,0,29 },{7,0,66},{7,0,1980},{10,0,487},{138,0,809},{13,0,260},{14,0,82},{18,0,63},{137 ,10,662},{5,10,72},{6,10,264},{7,10,21},{7,10,46},{7,10,2013},{8,10,215},{8,10, 513},{10,10,266},{139,10,22},{134,0,570},{6,0,565},{7,0,1667},{4,11,439},{10,10, 95},{11,10,603},{12,11,242},{13,10,443},{14,10,160},{143,10,4},{134,0,1464},{134 ,10,431},{9,0,372},{15,0,2},{19,0,10},{19,0,18},{5,10,874},{6,10,1677},{143,10,0 },{132,0,787},{6,0,380},{12,0,399},{21,0,19},{7,10,939},{7,10,1172},{7,10,1671}, {9,10,540},{10,10,696},{11,10,265},{11,10,732},{11,10,928},{11,10,937},{141,10, 438},{137,0,200},{132,11,233},{132,0,516},{134,11,577},{132,0,844},{11,0,887},{ 14,0,365},{142,0,375},{132,11,482},{8,0,821},{140,0,44},{7,0,1655},{136,0,305},{ 5,10,682},{135,10,1887},{135,11,346},{132,10,696},{4,0,10},{7,0,917},{139,0,786} ,{5,11,795},{6,11,1741},{8,11,417},{137,11,782},{4,0,1016},{134,0,2031},{5,0,684 },{4,10,726},{133,10,630},{6,0,1021},{134,0,1480},{8,10,802},{136,10,838},{134,0 ,27},{134,0,395},{135,11,622},{7,11,625},{135,11,1750},{4,11,203},{135,11,1936}, {6,10,118},{7,10,215},{7,10,1521},{140,10,11},{132,0,813},{136,0,511},{7,10,615} ,{138,10,251},{135,10,1044},{145,0,56},{133,10,225},{6,0,342},{6,0,496},{8,0,275 },{137,0,206},{4,0,909},{133,0,940},{132,0,891},{7,11,311},{9,11,308},{140,11, 255},{4,10,370},{5,10,756},{135,10,1326},{4,0,687},{134,0,1596},{134,0,1342},{6, 10,1662},{7,10,48},{8,10,771},{10,10,116},{13,10,104},{14,10,105},{14,10,184},{ 15,10,168},{19,10,92},{148,10,68},{138,10,209},{4,11,400},{5,11,267},{135,11,232 },{151,11,12},{6,0,41},{141,0,160},{141,11,314},{134,0,1718},{136,0,778},{142,11 ,261},{134,0,1610},{133,0,115},{132,0,294},{14,0,314},{132,10,120},{132,0,983},{ 5,0,193},{140,0,178},{138,10,429},{5,10,820},{135,10,931},{6,0,994},{6,0,1051},{ 6,0,1439},{7,0,174},{133,11,732},{4,11,100},{7,11,679},{8,11,313},{138,10,199},{ 6,10,151},{6,10,1675},{7,10,383},{151,10,10},{6,0,1796},{8,0,848},{8,0,867},{8,0 ,907},{10,0,855},{140,0,703},{140,0,221},{4,0,122},{5,0,796},{5,0,952},{6,0,1660 },{6,0,1671},{8,0,567},{9,0,687},{9,0,742},{10,0,686},{11,0,682},{11,0,909},{140 ,0,281},{5,11,362},{5,11,443},{6,11,318},{7,11,1019},{139,11,623},{5,11,463},{ 136,11,296},{11,0,583},{13,0,262},{6,10,1624},{12,10,422},{142,10,360},{5,0,179} ,{7,0,1095},{135,0,1213},{4,10,43},{4,11,454},{5,10,344},{133,10,357},{4,0,66},{ 7,0,722},{135,0,904},{134,0,773},{7,0,352},{133,10,888},{5,11,48},{5,11,404},{6, 11,557},{7,11,458},{8,11,597},{10,11,455},{10,11,606},{11,11,49},{11,11,548},{12 ,11,476},{13,11,18},{141,11,450},{134,11,418},{132,10,711},{5,11,442},{135,11, 1984},{141,0,35},{137,0,152},{134,0,1197},{135,11,1093},{137,11,203},{137,10,440 },{10,0,592},{10,0,753},{12,0,317},{12,0,355},{12,0,465},{12,0,469},{12,0,560},{ 12,0,578},{141,0,243},{133,0,564},{134,0,797},{5,10,958},{133,10,987},{5,11,55}, {7,11,376},{140,11,161},{133,11,450},{134,0,556},{134,0,819},{11,10,276},{142,10 ,293},{7,0,544},{138,0,61},{8,0,719},{4,10,65},{5,10,479},{5,10,1004},{7,10,1913 },{8,10,317},{9,10,302},{10,10,612},{141,10,22},{4,0,5},{5,0,498},{8,0,637},{9,0 ,521},{4,11,213},{4,10,261},{7,11,223},{7,10,510},{136,11,80},{5,0,927},{7,0,101 },{4,10,291},{7,11,381},{7,11,806},{7,11,820},{8,11,354},{8,11,437},{8,11,787},{ 9,10,515},{9,11,657},{10,11,58},{10,11,339},{10,11,749},{11,11,914},{12,10,152}, {12,11,162},{12,10,443},{13,11,75},{13,10,392},{14,11,106},{14,11,198},{14,11, 320},{14,10,357},{14,11,413},{146,11,43},{6,0,1153},{7,0,1441},{136,11,747},{4,0 ,893},{5,0,780},{133,0,893},{138,11,654},{133,11,692},{133,0,238},{134,11,191},{ 4,10,130},{135,10,843},{6,0,1296},{5,10,42},{5,10,879},{7,10,245},{7,10,324},{7, 10,1532},{11,10,463},{11,10,472},{13,10,363},{144,10,52},{134,0,1729},{6,0,1999} ,{136,0,969},{4,10,134},{133,10,372},{4,0,60},{7,0,941},{7,0,1800},{8,0,314},{9, 0,700},{139,0,487},{134,0,1144},{6,11,162},{7,11,1960},{136,11,831},{132,11,706} ,{135,0,1147},{138,11,426},{138,11,89},{7,0,1853},{138,0,437},{136,0,419},{135, 10,1634},{133,0,828},{5,0,806},{7,0,176},{7,0,178},{7,0,1240},{7,0,1976},{132,10 ,644},{135,11,1877},{5,11,420},{135,11,1449},{4,0,51},{5,0,39},{6,0,4},{7,0,591} ,{7,0,849},{7,0,951},{7,0,1613},{7,0,1760},{7,0,1988},{9,0,434},{10,0,754},{11,0 ,25},{139,0,37},{10,11,57},{138,11,277},{135,10,540},{132,11,204},{135,0,159},{ 139,11,231},{133,0,902},{7,0,928},{7,11,366},{9,11,287},{12,11,199},{12,11,556}, {140,11,577},{6,10,623},{136,10,789},{4,10,908},{5,10,359},{5,10,508},{6,10,1723 },{7,10,343},{7,10,1996},{135,10,2026},{134,0,270},{4,10,341},{135,10,480},{5,11 ,356},{135,11,224},{11,11,588},{11,11,864},{11,11,968},{143,11,160},{132,0,556}, {137,0,801},{132,0,416},{142,0,372},{5,0,152},{5,0,197},{7,0,340},{7,0,867},{10, 0,548},{10,0,581},{11,0,6},{12,0,3},{12,0,19},{14,0,110},{142,0,289},{139,0,369} ,{7,11,630},{9,11,567},{11,11,150},{11,11,444},{141,11,119},{134,11,539},{7,10, 1995},{8,10,299},{11,10,890},{140,10,674},{7,0,34},{7,0,190},{8,0,28},{8,0,141}, {8,0,444},{8,0,811},{9,0,468},{11,0,334},{12,0,24},{12,0,386},{140,0,576},{133,0 ,757},{7,0,1553},{136,0,898},{133,0,721},{136,0,1012},{4,0,789},{5,0,647},{135,0 ,1102},{132,0,898},{10,0,183},{4,10,238},{5,10,503},{6,10,179},{7,10,2003},{8,10 ,381},{8,10,473},{9,10,149},{10,10,788},{15,10,45},{15,10,86},{20,10,110},{150, 10,57},{9,0,136},{19,0,107},{4,10,121},{5,10,156},{5,10,349},{10,10,605},{142,10 ,342},{4,11,235},{135,11,255},{4,11,194},{5,11,584},{6,11,384},{7,11,583},{10,11 ,761},{11,11,760},{139,11,851},{6,10,80},{6,10,1694},{7,10,173},{7,10,1974},{9, 10,547},{10,10,730},{14,10,18},{150,10,39},{4,10,923},{134,10,1711},{5,0,277},{ 141,0,247},{132,0,435},{133,11,562},{134,0,1311},{5,11,191},{137,11,271},{132,10 ,595},{7,11,1537},{14,11,96},{143,11,73},{5,0,437},{7,0,502},{7,0,519},{7,0,1122 },{7,0,1751},{14,0,211},{6,10,459},{7,10,1753},{7,10,1805},{8,10,658},{9,10,1},{ 11,10,959},{141,10,446},{6,0,814},{4,11,470},{5,11,473},{6,11,153},{7,11,1503},{ 7,11,1923},{10,11,701},{11,11,132},{11,11,168},{11,11,227},{11,11,320},{11,11, 436},{11,11,525},{11,11,855},{12,11,41},{12,11,286},{13,11,103},{13,11,284},{14, 11,255},{14,11,262},{15,11,117},{143,11,127},{5,0,265},{6,0,212},{135,0,28},{138 ,0,750},{133,11,327},{6,11,552},{7,11,1754},{137,11,604},{134,0,2012},{132,0,702 },{5,11,80},{6,11,405},{7,11,403},{7,11,1502},{7,11,1626},{8,11,456},{9,11,487}, {9,11,853},{9,11,889},{10,11,309},{11,11,721},{11,11,994},{12,11,430},{141,11, 165},{5,0,808},{135,0,2045},{5,0,166},{8,0,739},{140,0,511},{134,10,490},{4,11, 453},{5,11,887},{6,11,535},{8,11,6},{136,11,543},{4,0,119},{5,0,170},{5,0,447},{ 7,0,1708},{7,0,1889},{9,0,357},{9,0,719},{12,0,486},{140,0,596},{137,0,500},{7, 10,250},{136,10,507},{132,10,158},{6,0,809},{134,0,1500},{9,0,327},{11,0,350},{ 11,0,831},{13,0,352},{4,10,140},{7,10,362},{8,10,209},{9,10,10},{9,10,503},{9,10 ,614},{10,10,689},{11,10,327},{11,10,725},{12,10,252},{12,10,583},{13,10,192},{ 14,10,269},{14,10,356},{148,10,50},{135,11,741},{4,0,450},{7,0,1158},{19,10,1},{ 19,10,26},{150,10,9},{6,0,597},{135,0,1318},{134,0,1602},{6,10,228},{7,10,1341}, {9,10,408},{138,10,343},{7,0,1375},{7,0,1466},{138,0,331},{132,0,754},{132,10, 557},{5,11,101},{6,11,88},{6,11,543},{7,11,1677},{9,11,100},{10,11,677},{14,11, 169},{14,11,302},{14,11,313},{15,11,48},{143,11,84},{134,0,1368},{4,11,310},{9, 11,795},{10,11,733},{11,11,451},{12,11,249},{14,11,115},{14,11,286},{143,11,100} ,{132,10,548},{10,0,557},{7,10,197},{8,10,142},{8,10,325},{9,10,150},{9,10,596}, {10,10,353},{11,10,74},{11,10,315},{12,10,662},{12,10,681},{14,10,423},{143,10, 141},{133,11,587},{5,0,850},{136,0,799},{10,0,908},{12,0,701},{12,0,757},{142,0, 466},{4,0,62},{5,0,275},{18,0,19},{6,10,399},{6,10,579},{7,10,692},{7,10,846},{7 ,10,1015},{7,10,1799},{8,10,403},{9,10,394},{10,10,133},{12,10,4},{12,10,297},{ 12,10,452},{16,10,81},{18,10,25},{21,10,14},{22,10,12},{151,10,18},{12,0,459},{7 ,10,1546},{11,10,299},{142,10,407},{132,10,177},{132,11,498},{7,11,217},{8,11, 140},{138,11,610},{5,10,411},{135,10,653},{134,0,1802},{7,10,439},{10,10,727},{ 11,10,260},{139,10,684},{133,11,905},{11,11,580},{142,11,201},{134,0,1397},{5,10 ,208},{7,10,753},{135,10,1528},{7,0,238},{7,0,2033},{8,0,120},{8,0,188},{8,0,659 },{9,0,598},{10,0,466},{12,0,342},{12,0,588},{13,0,503},{14,0,246},{143,0,92},{ 135,11,1041},{4,11,456},{7,11,105},{7,11,358},{7,11,1637},{8,11,643},{139,11,483 },{6,0,1318},{134,0,1324},{4,0,201},{7,0,1744},{8,0,602},{11,0,247},{11,0,826},{ 17,0,65},{133,10,242},{8,0,164},{146,0,62},{133,10,953},{139,10,802},{133,0,615} ,{7,11,1566},{8,11,269},{9,11,212},{9,11,718},{14,11,15},{14,11,132},{142,11,227 },{133,10,290},{132,10,380},{5,10,52},{7,10,277},{9,10,368},{139,10,791},{135,0, 1243},{133,11,539},{11,11,919},{141,11,409},{136,0,968},{133,11,470},{134,0,882} ,{132,0,907},{5,0,100},{10,0,329},{12,0,416},{149,0,29},{10,10,138},{139,10,476} ,{5,10,725},{5,10,727},{6,11,91},{7,11,435},{135,10,1811},{4,11,16},{5,11,316},{ 5,11,842},{6,11,370},{6,11,1778},{8,11,166},{11,11,812},{12,11,206},{12,11,351}, {14,11,418},{16,11,15},{16,11,34},{18,11,3},{19,11,3},{19,11,7},{20,11,4},{149, 11,21},{132,0,176},{5,0,636},{5,0,998},{7,0,9},{7,0,1508},{8,0,26},{9,0,317},{9, 0,358},{10,0,210},{10,0,292},{10,0,533},{11,0,555},{12,0,526},{12,0,607},{13,0, 263},{13,0,459},{142,0,271},{6,0,256},{8,0,265},{4,10,38},{7,10,307},{7,10,999}, {7,10,1481},{7,10,1732},{7,10,1738},{9,10,414},{11,10,316},{12,10,52},{13,10,420 },{147,10,100},{135,10,1296},{4,11,611},{133,11,606},{4,0,643},{142,11,21},{133, 11,715},{133,10,723},{6,0,610},{135,11,597},{10,0,127},{141,0,27},{6,0,1995},{6, 0,2001},{8,0,119},{136,0,973},{4,11,149},{138,11,368},{12,0,522},{4,11,154},{5, 10,109},{6,10,1784},{7,11,1134},{7,10,1895},{8,11,105},{12,10,296},{140,10,302}, {4,11,31},{6,11,429},{7,11,962},{9,11,458},{139,11,691},{10,0,553},{11,0,876},{ 13,0,193},{13,0,423},{14,0,166},{19,0,84},{4,11,312},{5,10,216},{7,10,1879},{9, 10,141},{9,10,270},{9,10,679},{10,10,159},{11,10,197},{12,10,538},{12,10,559},{ 14,10,144},{14,10,167},{143,10,67},{134,0,1582},{7,0,1578},{135,11,1578},{137,10 ,81},{132,11,236},{134,10,391},{134,0,795},{7,10,322},{136,10,249},{5,11,836},{5 ,11,857},{6,11,1680},{7,11,59},{147,11,53},{135,0,432},{10,11,68},{139,11,494},{ 4,11,81},{139,11,867},{7,0,126},{136,0,84},{142,11,280},{5,11,282},{8,11,650},{9 ,11,295},{9,11,907},{138,11,443},{136,0,790},{5,10,632},{138,10,526},{6,0,64},{ 12,0,377},{13,0,309},{14,0,141},{14,0,429},{14,11,141},{142,11,429},{134,0,1529} ,{6,0,321},{7,0,1857},{9,0,530},{19,0,99},{7,10,948},{7,10,1042},{8,10,235},{8, 10,461},{9,10,453},{10,10,354},{145,10,77},{7,0,1104},{11,0,269},{11,0,539},{11, 0,627},{11,0,706},{11,0,975},{12,0,248},{12,0,434},{12,0,600},{12,0,622},{13,0, 297},{13,0,485},{14,0,69},{14,0,409},{143,0,108},{4,10,362},{7,10,52},{7,10,303} ,{10,11,70},{12,11,26},{14,11,17},{14,11,178},{15,11,34},{149,11,12},{11,0,977}, {141,0,507},{9,0,34},{139,0,484},{5,10,196},{6,10,486},{7,10,212},{8,10,309},{ 136,10,346},{6,0,1700},{7,0,26},{7,0,293},{7,0,382},{7,0,1026},{7,0,1087},{7,0, 2027},{8,0,24},{8,0,114},{8,0,252},{8,0,727},{8,0,729},{9,0,30},{9,0,199},{9,0, 231},{9,0,251},{9,0,334},{9,0,361},{9,0,712},{10,0,55},{10,0,60},{10,0,232},{10, 0,332},{10,0,384},{10,0,396},{10,0,504},{10,0,542},{10,0,652},{11,0,20},{11,0,48 },{11,0,207},{11,0,291},{11,0,298},{11,0,342},{11,0,365},{11,0,394},{11,0,620},{ 11,0,705},{11,0,1017},{12,0,123},{12,0,340},{12,0,406},{12,0,643},{13,0,61},{13, 0,269},{13,0,311},{13,0,319},{13,0,486},{14,0,234},{15,0,62},{15,0,85},{16,0,71} ,{18,0,119},{20,0,105},{135,10,1912},{4,11,71},{5,11,376},{7,11,119},{138,11,665 },{10,0,918},{10,0,926},{4,10,686},{136,11,55},{138,10,625},{136,10,706},{132,11 ,479},{4,10,30},{133,10,43},{6,0,379},{7,0,270},{8,0,176},{8,0,183},{9,0,432},{9 ,0,661},{12,0,247},{12,0,617},{18,0,125},{7,11,607},{8,11,99},{152,11,4},{5,0, 792},{133,0,900},{4,11,612},{133,11,561},{4,11,41},{4,10,220},{5,11,74},{7,10, 1535},{7,11,1627},{11,11,871},{140,11,619},{135,0,1920},{7,11,94},{11,11,329},{ 11,11,965},{12,11,241},{14,11,354},{15,11,22},{148,11,63},{9,11,209},{137,11,300 },{134,0,771},{135,0,1979},{4,0,901},{133,0,776},{142,0,254},{133,11,98},{9,11, 16},{141,11,386},{133,11,984},{4,11,182},{6,11,205},{135,11,220},{7,10,1725},{7, 10,1774},{138,10,393},{5,10,263},{134,10,414},{4,11,42},{9,11,205},{9,11,786},{ 138,11,659},{14,0,140},{148,0,41},{8,0,440},{10,0,359},{6,10,178},{6,11,289},{6, 10,1750},{7,11,1670},{9,10,690},{10,10,155},{10,10,373},{11,10,698},{12,11,57},{ 13,10,155},{20,10,93},{151,11,4},{4,0,37},{5,0,334},{7,0,1253},{151,11,25},{4,0, 508},{4,11,635},{5,10,97},{137,10,393},{139,11,533},{4,0,640},{133,0,513},{134, 10,1639},{132,11,371},{4,11,272},{7,11,836},{7,11,1651},{145,11,89},{5,11,825},{ 6,11,444},{6,11,1640},{136,11,308},{4,10,191},{7,10,934},{8,10,647},{145,10,97}, {12,0,246},{15,0,162},{19,0,64},{20,0,8},{20,0,95},{22,0,24},{152,0,17},{4,0,533 },{5,10,165},{9,10,346},{138,10,655},{5,11,737},{139,10,885},{133,10,877},{8,10, 128},{139,10,179},{137,11,307},{140,0,752},{133,0,920},{135,0,1048},{5,0,153},{6 ,0,580},{6,10,1663},{7,10,132},{7,10,1154},{7,10,1415},{7,10,1507},{12,10,493},{ 15,10,105},{151,10,15},{5,10,459},{7,10,1073},{8,10,241},{136,10,334},{138,0,391 },{135,0,1952},{133,11,525},{8,11,641},{11,11,388},{140,11,580},{142,0,126},{134 ,0,640},{132,0,483},{7,0,1616},{9,0,69},{6,10,324},{6,10,520},{7,10,338},{7,10, 1729},{8,10,228},{139,10,750},{5,11,493},{134,11,528},{135,0,734},{4,11,174},{ 135,11,911},{138,0,480},{9,0,495},{146,0,104},{135,10,705},{9,0,472},{4,10,73},{ 6,10,612},{7,10,927},{7,10,1330},{7,10,1822},{8,10,217},{9,10,765},{9,10,766},{ 10,10,408},{11,10,51},{11,10,793},{12,10,266},{15,10,158},{20,10,89},{150,10,32} ,{7,11,548},{137,11,58},{4,11,32},{5,11,215},{6,11,269},{7,11,1782},{7,11,1892}, {10,11,16},{11,11,822},{11,11,954},{141,11,481},{132,0,874},{9,0,229},{5,10,389} ,{136,10,636},{7,11,1749},{136,11,477},{134,0,948},{5,11,308},{135,11,1088},{4,0 ,748},{139,0,1009},{136,10,21},{6,0,555},{135,0,485},{5,11,126},{8,11,297},{9,11 ,366},{9,11,445},{12,11,53},{12,11,374},{141,11,492},{7,11,1551},{139,11,361},{ 136,0,193},{136,0,472},{8,0,653},{13,0,93},{147,0,14},{132,0,984},{132,11,175},{ 5,0,172},{6,0,1971},{132,11,685},{149,11,8},{133,11,797},{13,0,83},{5,10,189},{7 ,10,442},{7,10,443},{8,10,281},{12,10,174},{141,10,261},{134,0,1568},{133,11,565 },{139,0,384},{133,0,260},{7,0,758},{7,0,880},{7,0,1359},{9,0,164},{9,0,167},{10 ,0,156},{10,0,588},{12,0,101},{14,0,48},{15,0,70},{6,10,2},{7,10,1262},{7,10, 1737},{8,10,22},{8,10,270},{8,10,612},{9,10,312},{9,10,436},{10,10,311},{10,10, 623},{11,10,72},{11,10,330},{11,10,455},{12,10,321},{12,10,504},{12,10,530},{12, 10,543},{13,10,17},{13,10,156},{13,10,334},{17,10,60},{148,10,64},{4,11,252},{7, 11,1068},{10,11,434},{11,11,228},{11,11,426},{13,11,231},{18,11,106},{148,11,87} ,{7,10,354},{10,10,410},{139,10,815},{6,0,367},{7,10,670},{7,10,1327},{8,10,411} ,{8,10,435},{9,10,653},{9,10,740},{10,10,385},{11,10,222},{11,10,324},{11,10,829 },{140,10,611},{7,0,1174},{6,10,166},{135,10,374},{146,0,121},{132,0,828},{5,11, 231},{138,11,509},{7,11,601},{9,11,277},{9,11,674},{10,11,178},{10,11,257},{10, 11,418},{11,11,531},{11,11,544},{11,11,585},{12,11,113},{12,11,475},{13,11,99},{ 142,11,428},{134,0,1541},{135,11,1779},{5,0,343},{134,10,398},{135,10,50},{135, 11,1683},{4,0,440},{7,0,57},{8,0,167},{8,0,375},{9,0,82},{9,0,561},{9,0,744},{10 ,0,620},{137,11,744},{134,0,926},{6,10,517},{7,10,1159},{10,10,621},{139,10,192} ,{137,0,827},{8,0,194},{136,0,756},{10,10,223},{139,10,645},{7,10,64},{136,10, 245},{4,11,399},{5,11,119},{5,11,494},{7,11,751},{137,11,556},{132,0,808},{135,0 ,22},{7,10,1763},{140,10,310},{5,0,639},{7,0,1249},{11,0,896},{134,11,584},{134, 0,1614},{135,0,860},{135,11,1121},{5,10,129},{6,10,61},{135,10,947},{4,0,102},{7 ,0,815},{7,0,1699},{139,0,964},{13,10,505},{141,10,506},{139,10,1000},{132,11, 679},{132,0,899},{132,0,569},{5,11,694},{137,11,714},{136,0,795},{6,0,2045},{139 ,11,7},{6,0,52},{9,0,104},{9,0,559},{12,0,308},{147,0,87},{4,0,301},{132,0,604}, {133,10,637},{136,0,779},{5,11,143},{5,11,769},{6,11,1760},{7,11,682},{7,11,1992 },{136,11,736},{137,10,590},{147,0,32},{137,11,527},{5,10,280},{135,10,1226},{ 134,0,494},{6,0,677},{6,0,682},{134,0,1044},{133,10,281},{135,10,1064},{7,0,508} ,{133,11,860},{6,11,422},{7,11,0},{7,11,1544},{9,11,577},{11,11,990},{12,11,141} ,{12,11,453},{13,11,47},{141,11,266},{134,0,1014},{5,11,515},{137,11,131},{134,0 ,957},{132,11,646},{6,0,310},{7,0,1849},{8,0,72},{8,0,272},{8,0,431},{9,0,12},{9 ,0,376},{10,0,563},{10,0,630},{10,0,796},{10,0,810},{11,0,367},{11,0,599},{11,0, 686},{140,0,672},{7,0,570},{4,11,396},{7,10,120},{7,11,728},{8,10,489},{9,11,117 },{9,10,319},{10,10,820},{11,10,1004},{12,10,379},{12,10,679},{13,10,117},{13,11 ,202},{13,10,412},{14,10,25},{15,10,52},{15,10,161},{16,10,47},{20,11,51},{149, 10,2},{6,11,121},{6,11,124},{6,11,357},{7,11,1138},{7,11,1295},{8,11,162},{139, 11,655},{8,0,449},{4,10,937},{5,10,801},{136,11,449},{139,11,958},{6,0,181},{7,0 ,537},{8,0,64},{9,0,127},{10,0,496},{12,0,510},{141,0,384},{138,11,253},{4,0,244 },{135,0,233},{133,11,237},{132,10,365},{6,0,1650},{10,0,702},{139,0,245},{5,10, 7},{139,10,774},{13,0,463},{20,0,49},{13,11,463},{148,11,49},{4,10,734},{5,10, 662},{134,10,430},{4,10,746},{135,10,1090},{5,10,360},{136,10,237},{137,0,338},{ 143,11,10},{7,11,571},{138,11,366},{134,0,1279},{9,11,513},{10,11,22},{10,11,39} ,{12,11,122},{140,11,187},{133,0,896},{146,0,178},{134,0,695},{137,0,808},{134, 11,587},{7,11,107},{7,11,838},{8,11,550},{138,11,401},{7,0,1117},{136,0,539},{4, 10,277},{5,10,608},{6,10,493},{7,10,457},{140,10,384},{133,11,768},{12,0,257},{7 ,10,27},{135,10,316},{140,0,1003},{4,0,207},{5,0,586},{5,0,676},{6,0,448},{8,0, 244},{11,0,1},{13,0,3},{16,0,54},{17,0,4},{18,0,13},{133,10,552},{4,10,401},{137 ,10,264},{5,0,516},{7,0,1883},{135,11,1883},{12,0,960},{132,11,894},{5,0,4},{5,0 ,810},{6,0,13},{6,0,538},{6,0,1690},{6,0,1726},{7,0,499},{7,0,1819},{8,0,148},{8 ,0,696},{8,0,791},{12,0,125},{143,0,9},{135,0,1268},{11,0,30},{14,0,315},{9,10, 543},{10,10,524},{12,10,524},{16,10,18},{20,10,26},{148,10,65},{6,0,748},{4,10, 205},{5,10,623},{7,10,104},{136,10,519},{11,0,542},{139,0,852},{140,0,6},{132,0, 848},{7,0,1385},{11,0,582},{11,0,650},{11,0,901},{11,0,949},{12,0,232},{12,0,236 },{13,0,413},{13,0,501},{18,0,116},{7,10,579},{9,10,41},{9,10,244},{9,10,669},{ 10,10,5},{11,10,861},{11,10,951},{139,10,980},{4,0,945},{6,0,1811},{6,0,1845},{6 ,0,1853},{6,0,1858},{8,0,862},{12,0,782},{12,0,788},{18,0,160},{148,0,117},{132, 10,717},{4,0,925},{5,0,803},{8,0,698},{138,0,828},{134,0,1416},{132,0,610},{139, 0,992},{6,0,878},{134,0,1477},{135,0,1847},{138,11,531},{137,11,539},{134,11,272 },{133,0,383},{134,0,1404},{132,10,489},{4,11,9},{5,11,128},{7,11,368},{11,11, 480},{148,11,3},{136,0,986},{9,0,660},{138,0,347},{135,10,892},{136,11,682},{7,0 ,572},{9,0,592},{11,0,680},{12,0,356},{140,0,550},{7,0,1411},{138,11,527},{4,11, 2},{7,11,545},{135,11,894},{137,10,473},{11,0,64},{7,11,481},{7,10,819},{9,10,26 },{9,10,392},{9,11,792},{10,10,152},{10,10,226},{12,10,276},{12,10,426},{12,10, 589},{13,10,460},{15,10,97},{19,10,48},{148,10,104},{135,10,51},{136,11,445},{ 136,11,646},{135,0,606},{132,10,674},{6,0,1829},{134,0,1830},{132,10,770},{5,10, 79},{7,10,1027},{7,10,1477},{139,10,52},{5,11,530},{142,11,113},{134,10,1666},{7 ,0,748},{139,0,700},{134,10,195},{133,10,789},{9,0,87},{10,0,365},{4,10,251},{4, 10,688},{7,10,513},{135,10,1284},{136,11,111},{133,0,127},{6,0,198},{140,0,83},{ 133,11,556},{133,10,889},{4,10,160},{5,10,330},{7,10,1434},{136,10,174},{5,0,276 },{6,0,55},{7,0,1369},{138,0,864},{8,11,16},{140,11,568},{6,0,1752},{136,0,726}, {135,0,1066},{133,0,764},{6,11,186},{137,11,426},{11,0,683},{139,11,683},{6,0, 309},{7,0,331},{138,0,550},{133,10,374},{6,0,1212},{6,0,1852},{7,0,1062},{8,0, 874},{8,0,882},{138,0,936},{132,11,585},{134,0,1364},{7,0,986},{133,10,731},{6,0 ,723},{6,0,1408},{138,0,381},{135,0,1573},{134,0,1025},{4,10,626},{5,10,642},{6, 10,425},{10,10,202},{139,10,141},{4,11,93},{5,11,252},{6,11,229},{7,11,291},{9, 11,550},{139,11,644},{137,11,749},{137,11,162},{132,11,381},{135,0,1559},{6,0, 194},{7,0,133},{10,0,493},{10,0,570},{139,0,664},{5,0,24},{5,0,569},{6,0,3},{6,0 ,119},{6,0,143},{6,0,440},{7,0,295},{7,0,599},{7,0,1686},{7,0,1854},{8,0,424},{9 ,0,43},{9,0,584},{9,0,760},{10,0,148},{10,0,328},{11,0,159},{11,0,253},{11,0,506 },{12,0,487},{140,0,531},{6,0,661},{134,0,1517},{136,10,835},{151,10,17},{5,0,14 },{5,0,892},{6,0,283},{7,0,234},{136,0,537},{139,0,541},{4,0,126},{8,0,635},{147 ,0,34},{4,0,316},{4,0,495},{135,0,1561},{4,11,187},{5,11,184},{5,11,690},{7,11, 1869},{138,11,756},{139,11,783},{4,0,998},{137,0,861},{136,0,1009},{139,11,292}, {5,11,21},{6,11,77},{6,11,157},{7,11,974},{7,11,1301},{7,11,1339},{7,11,1490},{7 ,11,1873},{137,11,628},{7,11,1283},{9,11,227},{9,11,499},{10,11,341},{11,11,325} ,{11,11,408},{14,11,180},{15,11,144},{18,11,47},{147,11,49},{4,0,64},{5,0,352},{ 5,0,720},{6,0,368},{139,0,359},{5,10,384},{8,10,455},{140,10,48},{5,10,264},{134 ,10,184},{7,0,1577},{10,0,304},{10,0,549},{12,0,365},{13,0,220},{13,0,240},{142, 0,33},{134,0,1107},{134,0,929},{135,0,1142},{6,0,175},{137,0,289},{5,0,432},{133 ,0,913},{6,0,279},{7,0,219},{5,10,633},{135,10,1323},{7,0,785},{7,10,359},{8,10, 243},{140,10,175},{139,0,595},{132,10,105},{8,11,398},{9,11,681},{139,11,632},{ 140,0,80},{5,0,931},{134,0,1698},{142,11,241},{134,11,20},{134,0,1323},{11,0,526 },{11,0,939},{141,0,290},{5,0,774},{6,0,780},{6,0,1637},{6,0,1686},{6,0,1751},{8 ,0,559},{141,0,109},{141,0,127},{7,0,1167},{11,0,934},{13,0,391},{17,0,76},{135, 11,709},{135,0,963},{6,0,260},{135,0,1484},{134,0,573},{4,10,758},{139,11,941},{ 135,10,1649},{145,11,36},{4,0,292},{137,0,580},{4,0,736},{5,0,871},{6,0,1689},{ 135,0,1944},{7,11,945},{11,11,713},{139,11,744},{134,0,1164},{135,11,937},{6,0, 1922},{9,0,982},{15,0,173},{15,0,178},{15,0,200},{18,0,189},{18,0,207},{21,0,47} ,{135,11,1652},{7,0,1695},{139,10,128},{6,0,63},{135,0,920},{133,0,793},{143,11, 134},{133,10,918},{5,0,67},{6,0,62},{6,0,374},{135,0,1391},{9,0,790},{12,0,47},{ 4,11,579},{5,11,226},{5,11,323},{135,11,960},{10,11,784},{141,11,191},{4,0,391}, {135,0,1169},{137,0,443},{13,11,232},{146,11,35},{132,10,340},{132,0,271},{137, 11,313},{5,11,973},{137,11,659},{134,0,1140},{6,11,135},{135,11,1176},{4,0,253}, {5,0,544},{7,0,300},{137,0,340},{7,0,897},{5,10,985},{7,10,509},{145,10,96},{138 ,11,735},{135,10,1919},{138,0,890},{5,0,818},{134,0,1122},{5,0,53},{5,0,541},{6, 0,94},{6,0,499},{7,0,230},{139,0,321},{4,0,920},{5,0,25},{5,0,790},{6,0,457},{7, 0,853},{8,0,788},{142,11,31},{132,10,247},{135,11,314},{132,0,468},{7,0,243},{6, 10,337},{7,10,494},{8,10,27},{8,10,599},{138,10,153},{4,10,184},{5,10,390},{7,10 ,618},{7,10,1456},{139,10,710},{134,0,870},{134,0,1238},{134,0,1765},{10,0,853}, {10,0,943},{14,0,437},{14,0,439},{14,0,443},{14,0,446},{14,0,452},{14,0,469},{14 ,0,471},{14,0,473},{16,0,93},{16,0,102},{16,0,110},{148,0,121},{4,0,605},{7,0, 518},{7,0,1282},{7,0,1918},{10,0,180},{139,0,218},{133,0,822},{4,0,634},{11,0, 916},{142,0,419},{6,11,281},{7,11,6},{8,11,282},{8,11,480},{8,11,499},{9,11,198} ,{10,11,143},{10,11,169},{10,11,211},{10,11,417},{10,11,574},{11,11,147},{11,11, 395},{12,11,75},{12,11,407},{12,11,608},{13,11,500},{142,11,251},{134,0,898},{6, 0,36},{7,0,658},{8,0,454},{150,11,48},{133,11,674},{135,11,1776},{4,11,419},{10, 10,227},{11,10,497},{11,10,709},{140,10,415},{6,10,360},{7,10,1664},{136,10,478} ,{137,0,806},{12,11,508},{14,11,102},{14,11,226},{144,11,57},{135,11,1123},{4,11 ,138},{7,11,1012},{7,11,1280},{137,11,76},{5,11,29},{140,11,638},{136,10,699},{ 134,0,1326},{132,0,104},{135,11,735},{132,10,739},{134,0,1331},{7,0,260},{135,11 ,260},{135,11,1063},{7,0,45},{9,0,542},{9,0,566},{10,0,728},{137,10,869},{4,10, 67},{5,10,422},{7,10,1037},{7,10,1289},{7,10,1555},{9,10,741},{145,10,108},{139, 0,263},{134,0,1516},{14,0,146},{15,0,42},{16,0,23},{17,0,86},{146,0,17},{138,0, 468},{136,0,1005},{4,11,17},{5,11,23},{7,11,995},{11,11,383},{11,11,437},{12,11, 460},{140,11,532},{7,0,87},{142,0,288},{138,10,96},{135,11,626},{144,10,26},{7,0 ,988},{7,0,1939},{9,0,64},{9,0,502},{12,0,22},{12,0,34},{13,0,12},{13,0,234},{ 147,0,77},{13,0,133},{8,10,203},{11,10,823},{11,10,846},{12,10,482},{13,10,277}, {13,10,302},{13,10,464},{14,10,205},{142,10,221},{4,10,449},{133,10,718},{135,0, 141},{6,0,1842},{136,0,872},{8,11,70},{12,11,171},{141,11,272},{4,10,355},{6,10, 311},{9,10,256},{138,10,404},{132,0,619},{137,0,261},{10,11,233},{10,10,758},{ 139,11,76},{5,0,246},{8,0,189},{9,0,355},{9,0,512},{10,0,124},{10,0,453},{11,0, 143},{11,0,416},{11,0,859},{141,0,341},{134,11,442},{133,10,827},{5,10,64},{140, 10,581},{4,10,442},{7,10,1047},{7,10,1352},{135,10,1643},{134,11,1709},{5,0,678} ,{6,0,305},{7,0,775},{7,0,1065},{133,10,977},{11,11,69},{12,11,105},{12,11,117}, {13,11,213},{14,11,13},{14,11,62},{14,11,177},{14,11,421},{15,11,19},{146,11,141 },{137,11,309},{5,0,35},{7,0,862},{7,0,1886},{138,0,179},{136,0,285},{132,0,517} ,{7,11,976},{9,11,146},{10,11,206},{10,11,596},{13,11,218},{142,11,153},{132,10, 254},{6,0,214},{12,0,540},{4,10,275},{7,10,1219},{140,10,376},{8,0,667},{11,0, 403},{146,0,83},{12,0,74},{10,11,648},{11,11,671},{143,11,46},{135,0,125},{134, 10,1753},{133,0,761},{6,0,912},{4,11,518},{6,10,369},{6,10,502},{7,10,1036},{7, 11,1136},{8,10,348},{9,10,452},{10,10,26},{11,10,224},{11,10,387},{11,10,772},{ 12,10,95},{12,10,629},{13,10,195},{13,10,207},{13,10,241},{14,10,260},{14,10,270 },{143,10,140},{10,0,131},{140,0,72},{132,10,269},{5,10,480},{7,10,532},{7,10, 1197},{7,10,1358},{8,10,291},{11,10,349},{142,10,396},{8,11,689},{137,11,863},{8 ,0,333},{138,0,182},{4,11,18},{7,11,145},{7,11,444},{7,11,1278},{8,11,49},{8,11, 400},{9,11,71},{9,11,250},{10,11,459},{12,11,160},{144,11,24},{14,11,35},{142,11 ,191},{135,11,1864},{135,0,1338},{148,10,15},{14,0,94},{15,0,65},{16,0,4},{16,0, 77},{16,0,80},{145,0,5},{12,11,82},{143,11,36},{133,11,1010},{133,0,449},{133,0, 646},{7,0,86},{8,0,103},{135,10,657},{7,0,2028},{138,0,641},{136,10,533},{134,0, 1},{139,11,970},{5,11,87},{7,11,313},{7,11,1103},{10,11,112},{10,11,582},{11,11, 389},{11,11,813},{12,11,385},{13,11,286},{14,11,124},{146,11,108},{6,0,869},{132 ,11,267},{6,0,277},{7,0,1274},{7,0,1386},{146,0,87},{6,0,187},{7,0,39},{7,0,1203 },{8,0,380},{14,0,117},{149,0,28},{4,10,211},{4,10,332},{5,10,335},{6,10,238},{7 ,10,269},{7,10,811},{7,10,1797},{8,10,836},{9,10,507},{141,10,242},{4,0,785},{5, 0,368},{6,0,297},{7,0,793},{139,0,938},{7,0,464},{8,0,558},{11,0,105},{12,0,231} ,{14,0,386},{15,0,102},{148,0,75},{133,10,1009},{8,0,877},{140,0,731},{139,11, 289},{10,11,249},{139,11,209},{132,11,561},{134,0,1608},{132,11,760},{134,0,1429 },{9,11,154},{140,11,485},{5,10,228},{6,10,203},{7,10,156},{8,10,347},{137,10, 265},{7,0,1010},{11,0,733},{11,0,759},{13,0,34},{14,0,427},{146,0,45},{7,10,1131 },{135,10,1468},{136,11,255},{7,0,1656},{9,0,369},{10,0,338},{10,0,490},{11,0, 154},{11,0,545},{11,0,775},{13,0,77},{141,0,274},{133,11,621},{134,0,1038},{4,11 ,368},{135,11,641},{6,0,2010},{8,0,979},{8,0,985},{10,0,951},{138,0,1011},{134,0 ,1005},{19,0,121},{5,10,291},{5,10,318},{7,10,765},{9,10,389},{140,10,548},{5,0, 20},{6,0,298},{7,0,659},{137,0,219},{7,0,1440},{11,0,854},{11,0,872},{11,0,921}, {12,0,551},{13,0,472},{142,0,367},{5,0,490},{6,0,615},{6,0,620},{135,0,683},{6,0 ,1070},{134,0,1597},{139,0,522},{132,0,439},{136,0,669},{6,0,766},{6,0,1143},{6, 0,1245},{10,10,525},{139,10,82},{9,11,92},{147,11,91},{6,0,668},{134,0,1218},{6, 11,525},{9,11,876},{140,11,284},{132,0,233},{136,0,547},{132,10,422},{5,10,355}, {145,10,0},{6,11,300},{135,11,1515},{4,0,482},{137,10,905},{4,0,886},{7,0,346},{ 133,11,594},{133,10,865},{5,10,914},{134,10,1625},{135,0,334},{5,0,795},{6,0, 1741},{133,10,234},{135,10,1383},{6,11,1641},{136,11,820},{135,0,371},{7,11,1313 },{138,11,660},{135,10,1312},{135,0,622},{7,0,625},{135,0,1750},{135,0,339},{4,0 ,203},{135,0,1936},{15,0,29},{16,0,38},{15,11,29},{144,11,38},{5,0,338},{135,0, 1256},{135,10,1493},{10,0,130},{6,10,421},{7,10,61},{7,10,1540},{138,10,501},{6, 11,389},{7,11,149},{9,11,142},{138,11,94},{137,10,341},{11,0,678},{12,0,307},{ 142,10,98},{6,11,8},{7,11,1881},{136,11,91},{135,0,2044},{6,0,770},{6,0,802},{6, 0,812},{7,0,311},{9,0,308},{12,0,255},{6,10,102},{7,10,72},{15,10,142},{147,10, 67},{151,10,30},{135,10,823},{135,0,1266},{135,11,1746},{135,10,1870},{4,0,400}, {5,0,267},{135,0,232},{7,11,24},{11,11,542},{139,11,852},{135,11,1739},{4,11,503 },{135,11,1661},{5,11,130},{7,11,1314},{9,11,610},{10,11,718},{11,11,601},{11,11 ,819},{11,11,946},{140,11,536},{10,11,149},{11,11,280},{142,11,336},{7,0,739},{ 11,0,690},{7,11,1946},{8,10,48},{8,10,88},{8,10,582},{8,10,681},{9,10,373},{9,10 ,864},{11,10,157},{11,10,843},{148,10,27},{134,0,990},{4,10,88},{5,10,137},{5,10 ,174},{5,10,777},{6,10,1664},{6,10,1725},{7,10,77},{7,10,426},{7,10,1317},{7,10, 1355},{8,10,126},{8,10,563},{9,10,523},{9,10,750},{10,10,310},{10,10,836},{11,10 ,42},{11,10,318},{11,10,731},{12,10,68},{12,10,92},{12,10,507},{12,10,692},{13, 10,81},{13,10,238},{13,10,374},{14,10,436},{18,10,138},{19,10,78},{19,10,111},{ 20,10,55},{20,10,77},{148,10,92},{141,10,418},{7,0,1831},{132,10,938},{6,0,776}, {134,0,915},{138,10,351},{5,11,348},{6,11,522},{6,10,1668},{7,10,1499},{8,10,117 },{9,10,314},{138,10,174},{135,10,707},{132,0,613},{133,10,403},{132,11,392},{5, 11,433},{9,11,633},{139,11,629},{133,0,763},{132,0,878},{132,0,977},{132,0,100}, {6,0,463},{4,10,44},{5,10,311},{7,10,639},{7,10,762},{7,10,1827},{9,10,8},{9,10, 462},{148,10,83},{134,11,234},{4,10,346},{7,10,115},{9,10,180},{9,10,456},{138, 10,363},{5,0,362},{5,0,443},{6,0,318},{7,0,1019},{139,0,623},{5,0,463},{8,0,296} ,{7,11,140},{7,11,1950},{8,11,680},{11,11,817},{147,11,88},{7,11,1222},{138,11, 386},{142,0,137},{132,0,454},{7,0,1914},{6,11,5},{7,10,1051},{9,10,545},{11,11, 249},{12,11,313},{16,11,66},{145,11,26},{135,0,1527},{145,0,58},{148,11,59},{5,0 ,48},{5,0,404},{6,0,557},{7,0,458},{8,0,597},{10,0,455},{10,0,606},{11,0,49},{11 ,0,548},{12,0,476},{13,0,18},{141,0,450},{5,11,963},{134,11,1773},{133,0,729},{ 138,11,586},{5,0,442},{135,0,1984},{134,0,449},{144,0,40},{4,0,853},{7,11,180},{ 8,11,509},{136,11,792},{6,10,185},{7,10,1899},{9,10,875},{139,10,673},{134,11, 524},{12,0,227},{4,10,327},{5,10,478},{7,10,1332},{136,10,753},{6,0,1491},{5,10, 1020},{133,10,1022},{4,10,103},{133,10,401},{132,11,931},{4,10,499},{135,10,1421 },{5,0,55},{7,0,376},{140,0,161},{133,0,450},{6,0,1174},{134,0,1562},{10,0,62},{ 13,0,400},{135,11,1837},{140,0,207},{135,0,869},{4,11,773},{5,11,618},{137,11, 756},{132,10,96},{4,0,213},{7,0,223},{8,0,80},{135,10,968},{4,11,90},{5,11,337}, {5,11,545},{7,11,754},{9,11,186},{10,11,72},{10,11,782},{11,11,513},{11,11,577}, {11,11,610},{11,11,889},{11,11,961},{12,11,354},{12,11,362},{12,11,461},{12,11, 595},{13,11,79},{143,11,121},{7,0,381},{7,0,806},{7,0,820},{8,0,354},{8,0,437},{ 8,0,787},{9,0,657},{10,0,58},{10,0,339},{10,0,749},{11,0,914},{12,0,162},{13,0, 75},{14,0,106},{14,0,198},{14,0,320},{14,0,413},{146,0,43},{136,0,747},{136,0, 954},{134,0,1073},{135,0,556},{7,11,151},{9,11,329},{139,11,254},{5,0,692},{134, 0,1395},{6,10,563},{137,10,224},{134,0,191},{132,0,804},{9,11,187},{10,11,36},{ 17,11,44},{146,11,64},{7,11,165},{7,11,919},{136,11,517},{4,11,506},{5,11,295},{ 7,11,1680},{15,11,14},{144,11,5},{4,0,706},{6,0,162},{7,0,1960},{136,0,831},{135 ,11,1376},{7,11,987},{9,11,688},{10,11,522},{11,11,788},{140,11,566},{150,0,35}, {138,0,426},{135,0,1235},{135,11,1741},{7,11,389},{7,11,700},{7,11,940},{8,11, 514},{9,11,116},{9,11,535},{10,11,118},{11,11,107},{11,11,148},{11,11,922},{12, 11,254},{12,11,421},{142,11,238},{134,0,1234},{132,11,743},{4,10,910},{5,10,832} ,{135,11,1335},{141,0,96},{135,11,185},{146,0,149},{4,0,204},{137,0,902},{4,11, 784},{133,11,745},{136,0,833},{136,0,949},{7,0,366},{9,0,287},{12,0,199},{12,0, 556},{12,0,577},{5,11,81},{7,11,146},{7,11,1342},{7,11,1446},{8,11,53},{8,11,561 },{8,11,694},{8,11,754},{9,11,97},{9,11,115},{9,11,894},{10,11,462},{10,11,813}, {11,11,230},{11,11,657},{11,11,699},{11,11,748},{12,11,119},{12,11,200},{12,11, 283},{14,11,273},{145,11,15},{5,11,408},{137,11,747},{9,11,498},{140,11,181},{6, 0,2020},{136,0,992},{5,0,356},{135,0,224},{134,0,784},{7,0,630},{9,0,567},{11,0, 150},{11,0,444},{13,0,119},{8,10,528},{137,10,348},{134,0,539},{4,10,20},{133,10 ,616},{142,0,27},{7,11,30},{8,11,86},{8,11,315},{8,11,700},{9,11,576},{9,11,858} ,{11,11,310},{11,11,888},{11,11,904},{12,11,361},{141,11,248},{138,11,839},{134, 0,755},{134,0,1063},{7,10,1091},{135,10,1765},{134,11,428},{7,11,524},{8,11,169} ,{8,11,234},{9,11,480},{138,11,646},{139,0,814},{7,11,1462},{139,11,659},{4,10, 26},{5,10,429},{6,10,245},{7,10,704},{7,10,1379},{135,10,1474},{7,11,1205},{138, 11,637},{139,11,803},{132,10,621},{136,0,987},{4,11,266},{8,11,4},{9,11,39},{10, 11,166},{11,11,918},{12,11,635},{20,11,10},{22,11,27},{150,11,43},{4,0,235},{135 ,0,255},{4,0,194},{5,0,584},{6,0,384},{7,0,583},{10,0,761},{11,0,760},{139,0,851 },{133,10,542},{134,0,1086},{133,10,868},{8,0,1016},{136,0,1018},{7,0,1396},{7, 11,1396},{136,10,433},{135,10,1495},{138,10,215},{141,10,124},{7,11,157},{8,11, 279},{9,11,759},{16,11,31},{16,11,39},{16,11,75},{18,11,24},{20,11,42},{152,11,1 },{5,0,562},{134,11,604},{134,0,913},{5,0,191},{137,0,271},{4,0,470},{6,0,153},{ 7,0,1503},{7,0,1923},{10,0,701},{11,0,132},{11,0,227},{11,0,320},{11,0,436},{11, 0,525},{11,0,855},{11,0,873},{12,0,41},{12,0,286},{13,0,103},{13,0,284},{14,0, 255},{14,0,262},{15,0,117},{143,0,127},{7,0,475},{12,0,45},{147,10,112},{132,11, 567},{137,11,859},{6,0,713},{6,0,969},{6,0,1290},{134,0,1551},{133,0,327},{6,0, 552},{6,0,1292},{7,0,1754},{137,0,604},{4,0,223},{6,0,359},{11,0,3},{13,0,108},{ 14,0,89},{16,0,22},{5,11,762},{7,11,1880},{9,11,680},{139,11,798},{5,0,80},{6,0, 405},{7,0,403},{7,0,1502},{8,0,456},{9,0,487},{9,0,853},{9,0,889},{10,0,309},{11 ,0,721},{11,0,994},{12,0,430},{141,0,165},{133,11,298},{132,10,647},{134,0,2016} ,{18,10,10},{146,11,10},{4,0,453},{5,0,887},{6,0,535},{8,0,6},{8,0,543},{136,0, 826},{136,0,975},{10,0,961},{138,0,962},{138,10,220},{6,0,1891},{6,0,1893},{9,0, 916},{9,0,965},{9,0,972},{12,0,801},{12,0,859},{12,0,883},{15,0,226},{149,0,51}, {132,10,109},{135,11,267},{7,11,92},{7,11,182},{8,11,453},{9,11,204},{11,11,950} ,{12,11,94},{12,11,644},{16,11,20},{16,11,70},{16,11,90},{147,11,55},{134,10, 1746},{6,11,71},{7,11,845},{7,11,1308},{8,11,160},{137,11,318},{5,0,101},{6,0,88 },{7,0,263},{7,0,628},{7,0,1677},{8,0,349},{9,0,100},{10,0,677},{14,0,169},{14,0 ,302},{14,0,313},{15,0,48},{15,0,84},{7,11,237},{8,11,664},{9,11,42},{9,11,266}, {9,11,380},{9,11,645},{10,11,177},{138,11,276},{138,11,69},{4,0,310},{7,0,708},{ 7,0,996},{9,0,795},{10,0,390},{10,0,733},{11,0,451},{12,0,249},{14,0,115},{14,0, 286},{143,0,100},{5,0,587},{4,10,40},{10,10,67},{11,10,117},{11,10,768},{139,10, 935},{6,0,1942},{7,0,512},{136,0,983},{7,10,992},{8,10,301},{9,10,722},{12,10,63 },{13,10,29},{14,10,161},{143,10,18},{136,11,76},{139,10,923},{134,0,645},{134,0 ,851},{4,0,498},{132,11,293},{7,0,217},{8,0,140},{10,0,610},{14,11,352},{17,11, 53},{18,11,146},{18,11,152},{19,11,11},{150,11,54},{134,0,1448},{138,11,841},{ 133,0,905},{4,11,605},{7,11,518},{7,11,1282},{7,11,1918},{10,11,180},{139,11,218 },{139,11,917},{135,10,825},{140,10,328},{4,0,456},{7,0,105},{7,0,358},{7,0,1637 },{8,0,643},{139,0,483},{134,0,792},{6,11,96},{135,11,1426},{137,11,691},{4,11, 651},{133,11,289},{7,11,688},{8,11,35},{9,11,511},{10,11,767},{147,11,118},{150, 0,56},{5,0,243},{5,0,535},{6,10,204},{10,10,320},{10,10,583},{13,10,502},{14,10, 72},{14,10,274},{14,10,312},{14,10,344},{15,10,159},{16,10,62},{16,10,69},{17,10 ,30},{18,10,42},{18,10,53},{18,10,84},{18,10,140},{19,10,68},{19,10,85},{20,10,5 },{20,10,45},{20,10,101},{22,10,7},{150,10,20},{4,10,558},{6,10,390},{7,10,162}, {7,10,689},{9,10,360},{138,10,653},{146,11,23},{135,0,1748},{5,10,856},{6,10, 1672},{6,10,1757},{134,10,1781},{5,0,539},{5,0,754},{6,0,876},{132,11,704},{135, 11,1078},{5,10,92},{10,10,736},{140,10,102},{17,0,91},{5,10,590},{137,10,213},{ 134,0,1565},{6,0,91},{135,0,435},{4,0,939},{140,0,792},{134,0,1399},{4,0,16},{5, 0,316},{5,0,842},{6,0,370},{6,0,1778},{8,0,166},{11,0,812},{12,0,206},{12,0,351} ,{14,0,418},{16,0,15},{16,0,34},{18,0,3},{19,0,3},{19,0,7},{20,0,4},{21,0,21},{4 ,11,720},{133,11,306},{144,0,95},{133,11,431},{132,11,234},{135,0,551},{4,0,999} ,{6,0,1966},{134,0,2042},{7,0,619},{10,0,547},{11,0,122},{12,0,601},{15,0,7},{ 148,0,20},{5,11,464},{6,11,236},{7,11,276},{7,11,696},{7,11,914},{7,11,1108},{7, 11,1448},{9,11,15},{9,11,564},{10,11,14},{12,11,565},{13,11,449},{14,11,53},{15, 11,13},{16,11,64},{145,11,41},{6,0,884},{6,0,1019},{134,0,1150},{6,11,1767},{12, 11,194},{145,11,107},{136,10,503},{133,11,840},{7,0,671},{134,10,466},{132,0,888 },{4,0,149},{138,0,368},{4,0,154},{7,0,1134},{136,0,105},{135,0,983},{9,11,642}, {11,11,236},{142,11,193},{4,0,31},{6,0,429},{7,0,962},{9,0,458},{139,0,691},{6,0 ,643},{134,0,1102},{132,0,312},{4,11,68},{5,11,634},{6,11,386},{7,11,794},{8,11, 273},{9,11,563},{10,11,105},{10,11,171},{11,11,94},{139,11,354},{133,0,740},{135 ,0,1642},{4,11,95},{7,11,416},{8,11,211},{139,11,830},{132,0,236},{138,10,241},{ 7,11,731},{13,11,20},{143,11,11},{5,0,836},{5,0,857},{6,0,1680},{135,0,59},{10,0 ,68},{11,0,494},{152,11,6},{4,0,81},{139,0,867},{135,0,795},{133,11,689},{4,0, 1001},{5,0,282},{6,0,1932},{6,0,1977},{6,0,1987},{6,0,1992},{8,0,650},{8,0,919}, {8,0,920},{8,0,923},{8,0,926},{8,0,927},{8,0,931},{8,0,939},{8,0,947},{8,0,956}, {8,0,997},{9,0,907},{10,0,950},{10,0,953},{10,0,954},{10,0,956},{10,0,958},{10,0 ,959},{10,0,964},{10,0,970},{10,0,972},{10,0,973},{10,0,975},{10,0,976},{10,0, 980},{10,0,981},{10,0,984},{10,0,988},{10,0,990},{10,0,995},{10,0,999},{10,0, 1002},{10,0,1003},{10,0,1005},{10,0,1006},{10,0,1008},{10,0,1009},{10,0,1012},{ 10,0,1014},{10,0,1015},{10,0,1019},{10,0,1020},{10,0,1022},{12,0,959},{12,0,961} ,{12,0,962},{12,0,963},{12,0,964},{12,0,965},{12,0,967},{12,0,968},{12,0,969},{ 12,0,970},{12,0,971},{12,0,972},{12,0,973},{12,0,974},{12,0,975},{12,0,976},{12, 0,977},{12,0,979},{12,0,981},{12,0,982},{12,0,983},{12,0,984},{12,0,985},{12,0, 986},{12,0,987},{12,0,989},{12,0,990},{12,0,992},{12,0,993},{12,0,995},{12,0,998 },{12,0,999},{12,0,1000},{12,0,1001},{12,0,1002},{12,0,1004},{12,0,1005},{12,0, 1006},{12,0,1007},{12,0,1008},{12,0,1009},{12,0,1010},{12,0,1011},{12,0,1012},{ 12,0,1014},{12,0,1015},{12,0,1016},{12,0,1017},{12,0,1018},{12,0,1019},{12,0, 1022},{12,0,1023},{14,0,475},{14,0,477},{14,0,478},{14,0,479},{14,0,480},{14,0, 482},{14,0,483},{14,0,484},{14,0,485},{14,0,486},{14,0,487},{14,0,488},{14,0,489 },{14,0,490},{14,0,491},{14,0,492},{14,0,493},{14,0,494},{14,0,495},{14,0,496},{ 14,0,497},{14,0,498},{14,0,499},{14,0,500},{14,0,501},{14,0,502},{14,0,503},{14, 0,504},{14,0,506},{14,0,507},{14,0,508},{14,0,509},{14,0,510},{14,0,511},{16,0, 113},{16,0,114},{16,0,115},{16,0,117},{16,0,118},{16,0,119},{16,0,121},{16,0,122 },{16,0,123},{16,0,124},{16,0,125},{16,0,126},{16,0,127},{18,0,242},{18,0,243},{ 18,0,244},{18,0,245},{18,0,248},{18,0,249},{18,0,250},{18,0,251},{18,0,252},{18, 0,253},{18,0,254},{18,0,255},{20,0,125},{20,0,126},{148,0,127},{7,11,1717},{7,11 ,1769},{138,11,546},{7,11,1127},{7,11,1572},{10,11,297},{10,11,422},{11,11,764}, {11,11,810},{12,11,264},{13,11,102},{13,11,300},{13,11,484},{14,11,147},{14,11, 229},{17,11,71},{18,11,118},{147,11,120},{6,0,1148},{134,0,1586},{132,0,775},{ 135,10,954},{133,11,864},{133,11,928},{138,11,189},{135,10,1958},{6,10,549},{8, 10,34},{8,10,283},{9,10,165},{138,10,475},{5,10,652},{5,10,701},{135,10,449},{ 135,11,695},{4,10,655},{7,10,850},{17,10,75},{146,10,137},{140,11,682},{133,11, 523},{8,0,970},{136,10,670},{136,11,555},{7,11,76},{8,11,44},{9,11,884},{10,11, 580},{11,11,399},{11,11,894},{15,11,122},{18,11,144},{147,11,61},{6,10,159},{6, 10,364},{7,10,516},{7,10,1439},{137,10,518},{4,0,71},{5,0,376},{7,0,119},{138,0, 665},{141,10,151},{11,0,827},{14,0,34},{143,0,148},{133,11,518},{4,0,479},{135, 11,1787},{135,11,1852},{135,10,993},{7,0,607},{136,0,99},{134,0,1960},{132,0,793 },{4,0,41},{5,0,74},{7,0,1627},{11,0,871},{140,0,619},{7,0,94},{11,0,329},{11,0, 965},{12,0,241},{14,0,354},{15,0,22},{148,0,63},{7,10,501},{9,10,111},{10,10,141 },{11,10,332},{13,10,43},{13,10,429},{14,10,130},{14,10,415},{145,10,102},{9,0, 209},{137,0,300},{134,0,1497},{138,11,255},{4,11,934},{5,11,138},{136,11,610},{ 133,0,98},{6,0,1316},{10,11,804},{138,11,832},{8,11,96},{9,11,36},{10,11,607},{ 11,11,423},{11,11,442},{12,11,309},{14,11,199},{15,11,90},{145,11,110},{132,0, 463},{5,10,149},{136,10,233},{133,10,935},{4,11,652},{8,11,320},{9,11,13},{9,11, 398},{9,11,727},{10,11,75},{10,11,184},{10,11,230},{10,11,564},{10,11,569},{11, 11,973},{12,11,70},{12,11,189},{13,11,57},{13,11,257},{22,11,6},{150,11,16},{142 ,0,291},{12,10,582},{146,10,131},{136,10,801},{133,0,984},{145,11,116},{4,11,692 },{133,11,321},{4,0,182},{6,0,205},{135,0,220},{4,0,42},{9,0,205},{9,0,786},{138 ,0,659},{6,0,801},{11,11,130},{140,11,609},{132,0,635},{5,11,345},{135,11,1016}, {139,0,533},{132,0,371},{4,0,272},{135,0,836},{6,0,1282},{135,11,1100},{5,0,825} ,{134,0,1640},{135,11,1325},{133,11,673},{4,11,287},{133,11,1018},{135,0,357},{6 ,0,467},{137,0,879},{7,0,317},{135,0,569},{6,0,924},{134,0,1588},{5,11,34},{5,10 ,406},{10,11,724},{12,11,444},{13,11,354},{18,11,32},{23,11,24},{23,11,31},{152, 11,5},{6,0,1795},{6,0,1835},{6,0,1836},{6,0,1856},{8,0,844},{8,0,849},{8,0,854}, {8,0,870},{8,0,887},{10,0,852},{138,0,942},{6,10,69},{135,10,117},{137,0,307},{4 ,0,944},{6,0,1799},{6,0,1825},{10,0,848},{10,0,875},{10,0,895},{10,0,899},{10,0, 902},{140,0,773},{11,0,43},{13,0,72},{141,0,142},{135,10,1830},{134,11,382},{4, 10,432},{135,10,824},{132,11,329},{7,0,1820},{139,11,124},{133,10,826},{133,0, 525},{132,11,906},{7,11,1940},{136,11,366},{138,11,10},{4,11,123},{4,11,649},{5, 11,605},{7,11,1509},{136,11,36},{6,0,110},{135,0,1681},{133,0,493},{133,11,767}, {4,0,174},{135,0,911},{138,11,786},{8,0,417},{137,0,782},{133,10,1000},{7,0,733} ,{137,0,583},{4,10,297},{6,10,529},{7,10,152},{7,10,713},{7,10,1845},{8,10,710}, {8,10,717},{12,10,639},{140,10,685},{4,0,32},{5,0,215},{6,0,269},{7,0,1782},{7,0 ,1892},{10,0,16},{11,0,822},{11,0,954},{141,0,481},{4,11,273},{5,11,658},{133,11 ,995},{136,0,477},{134,11,72},{135,11,1345},{5,0,308},{7,0,1088},{4,10,520},{135 ,10,575},{133,11,589},{5,0,126},{8,0,297},{9,0,366},{140,0,374},{7,0,1551},{139, 0,361},{5,11,117},{6,11,514},{6,11,541},{7,11,1164},{7,11,1436},{8,11,220},{8,11 ,648},{10,11,688},{139,11,560},{133,11,686},{4,0,946},{6,0,1807},{8,0,871},{10,0 ,854},{10,0,870},{10,0,888},{10,0,897},{10,0,920},{12,0,722},{12,0,761},{12,0, 763},{12,0,764},{14,0,454},{14,0,465},{16,0,107},{18,0,167},{18,0,168},{146,0, 172},{132,0,175},{135,0,1307},{132,0,685},{135,11,1834},{133,0,797},{6,0,745},{6 ,0,858},{134,0,963},{133,0,565},{5,10,397},{6,10,154},{7,11,196},{7,10,676},{8, 10,443},{8,10,609},{9,10,24},{9,10,325},{10,10,35},{10,11,765},{11,11,347},{11, 10,535},{11,11,552},{11,11,576},{11,10,672},{11,11,790},{11,10,1018},{12,11,263} ,{12,10,637},{13,11,246},{13,11,270},{13,11,395},{14,11,74},{14,11,176},{14,11, 190},{14,11,398},{14,11,412},{15,11,32},{15,11,63},{16,10,30},{16,11,88},{147,11 ,105},{13,11,84},{141,11,122},{4,0,252},{7,0,1068},{10,0,434},{11,0,228},{11,0, 426},{13,0,231},{18,0,106},{148,0,87},{137,0,826},{4,11,589},{139,11,282},{5,11, 381},{135,11,1792},{132,0,791},{5,0,231},{10,0,509},{133,10,981},{7,0,601},{9,0, 277},{9,0,674},{10,0,178},{10,0,418},{10,0,571},{11,0,531},{12,0,113},{12,0,475} ,{13,0,99},{142,0,428},{4,10,56},{7,11,616},{7,10,1791},{8,10,607},{8,10,651},{ 10,11,413},{11,10,465},{11,10,835},{12,10,337},{141,10,480},{7,0,1591},{144,0,43 },{9,10,158},{138,10,411},{135,0,1683},{8,0,289},{11,0,45},{12,0,278},{140,0,537 },{6,11,120},{7,11,1188},{7,11,1710},{8,11,286},{9,11,667},{11,11,592},{139,11, 730},{136,10,617},{135,0,1120},{135,11,1146},{139,10,563},{4,11,352},{4,10,369}, {135,11,687},{143,11,38},{4,0,399},{5,0,119},{5,0,494},{7,0,751},{9,0,556},{14, 11,179},{15,11,151},{150,11,11},{4,11,192},{5,11,49},{6,11,200},{6,11,293},{6,11 ,1696},{135,11,488},{4,0,398},{133,0,660},{7,0,1030},{134,10,622},{135,11,595},{ 141,0,168},{132,11,147},{7,0,973},{10,10,624},{142,10,279},{132,10,363},{132,0, 642},{133,11,934},{134,0,1615},{7,11,505},{135,11,523},{7,0,594},{7,0,851},{7,0, 1858},{9,0,411},{9,0,574},{9,0,666},{9,0,737},{10,0,346},{10,0,712},{11,0,246},{ 11,0,432},{11,0,517},{11,0,647},{11,0,679},{11,0,727},{12,0,304},{12,0,305},{12, 0,323},{12,0,483},{12,0,572},{12,0,593},{12,0,602},{13,0,95},{13,0,101},{13,0, 171},{13,0,315},{13,0,378},{13,0,425},{13,0,475},{14,0,63},{14,0,380},{14,0,384} ,{15,0,133},{18,0,112},{148,0,72},{135,0,1093},{132,0,679},{8,0,913},{10,0,903}, {10,0,915},{12,0,648},{12,0,649},{14,0,455},{16,0,112},{138,11,438},{137,0,203}, {134,10,292},{134,0,1492},{7,0,1374},{8,0,540},{5,10,177},{6,10,616},{7,10,827}, {9,10,525},{138,10,656},{135,0,1486},{9,0,714},{138,10,31},{136,0,825},{134,0, 1511},{132,11,637},{134,0,952},{4,10,161},{133,10,631},{5,0,143},{5,0,769},{6,0, 1760},{7,0,682},{7,0,1992},{136,0,736},{132,0,700},{134,0,1540},{132,11,777},{9, 11,867},{138,11,837},{7,0,1557},{135,10,1684},{133,0,860},{6,0,422},{7,0,0},{7,0 ,1544},{9,0,605},{11,0,990},{12,0,235},{12,0,453},{13,0,47},{13,0,266},{9,10,469 },{9,10,709},{12,10,512},{14,10,65},{145,10,12},{11,0,807},{10,10,229},{11,10,73 },{139,10,376},{6,11,170},{7,11,1080},{8,11,395},{8,11,487},{11,11,125},{141,11, 147},{5,0,515},{137,0,131},{7,0,1605},{11,0,962},{146,0,139},{132,0,646},{4,0, 396},{7,0,728},{9,0,117},{13,0,202},{148,0,51},{6,0,121},{6,0,124},{6,0,357},{7, 0,1138},{7,0,1295},{8,0,162},{8,0,508},{11,0,655},{4,11,535},{6,10,558},{7,10, 651},{8,11,618},{9,10,0},{10,10,34},{139,10,1008},{135,11,1245},{138,0,357},{150 ,11,23},{133,0,237},{135,0,1784},{7,10,1832},{138,10,374},{132,0,713},{132,11,46 },{6,0,1536},{10,0,348},{5,11,811},{6,11,1679},{6,11,1714},{135,11,2032},{11,11, 182},{142,11,195},{6,0,523},{7,0,738},{7,10,771},{7,10,1731},{9,10,405},{138,10, 421},{7,11,1458},{9,11,407},{139,11,15},{6,11,34},{7,11,69},{7,11,640},{7,11, 1089},{8,11,708},{8,11,721},{9,11,363},{9,11,643},{10,11,628},{148,11,98},{133,0 ,434},{135,0,1877},{7,0,571},{138,0,366},{5,10,881},{133,10,885},{9,0,513},{10,0 ,25},{10,0,39},{12,0,122},{140,0,187},{132,0,580},{5,10,142},{134,10,546},{132, 11,462},{137,0,873},{5,10,466},{11,10,571},{12,10,198},{13,10,283},{14,10,186},{ 15,10,21},{143,10,103},{7,0,171},{4,10,185},{5,10,257},{5,10,839},{5,10,936},{9, 10,399},{10,10,258},{10,10,395},{10,10,734},{11,10,1014},{12,10,23},{13,10,350}, {14,10,150},{147,10,6},{134,0,625},{7,0,107},{7,0,838},{8,0,550},{138,0,401},{5, 11,73},{6,11,23},{134,11,338},{4,0,943},{6,0,1850},{12,0,713},{142,0,434},{11,0, 588},{11,0,864},{11,0,936},{11,0,968},{12,0,73},{12,0,343},{12,0,394},{13,0,275} ,{14,0,257},{15,0,160},{7,10,404},{7,10,1377},{7,10,1430},{7,10,2017},{8,10,149} ,{8,10,239},{8,10,512},{8,10,793},{8,10,818},{9,10,474},{9,10,595},{10,10,122},{ 10,10,565},{10,10,649},{10,10,783},{11,10,239},{11,10,295},{11,10,447},{11,10, 528},{11,10,639},{11,10,800},{12,10,25},{12,10,157},{12,10,316},{12,10,390},{12, 10,391},{12,10,395},{12,10,478},{12,10,503},{12,10,592},{12,10,680},{13,10,50},{ 13,10,53},{13,10,132},{13,10,198},{13,10,322},{13,10,415},{13,10,511},{14,10,71} ,{14,10,395},{15,10,71},{15,10,136},{17,10,123},{18,10,93},{147,10,58},{133,0, 768},{11,0,103},{142,0,0},{136,10,712},{132,0,799},{132,0,894},{7,11,725},{8,11, 498},{139,11,268},{135,11,1798},{135,11,773},{141,11,360},{4,10,377},{152,10,13} ,{135,0,1673},{132,11,583},{134,0,1052},{133,11,220},{140,11,69},{132,11,544},{4 ,10,180},{135,10,1906},{134,0,272},{4,0,441},{134,0,1421},{4,0,9},{5,0,128},{7,0 ,368},{11,0,480},{148,0,3},{5,11,176},{6,11,437},{6,11,564},{11,11,181},{141,11, 183},{132,10,491},{7,0,1182},{141,11,67},{6,0,1346},{4,10,171},{138,10,234},{4, 10,586},{7,10,1186},{138,10,631},{136,0,682},{134,0,1004},{15,0,24},{143,11,24}, {134,0,968},{4,0,2},{6,0,742},{6,0,793},{7,0,545},{7,0,894},{9,10,931},{10,10, 334},{148,10,71},{136,11,600},{133,10,765},{9,0,769},{140,0,185},{4,11,790},{5, 11,273},{134,11,394},{7,0,474},{137,0,578},{4,11,135},{6,11,127},{7,11,1185},{7, 11,1511},{8,11,613},{11,11,5},{12,11,133},{12,11,495},{12,11,586},{14,11,385},{ 15,11,118},{17,11,20},{146,11,98},{133,10,424},{5,0,530},{142,0,113},{6,11,230}, {7,11,961},{7,11,1085},{136,11,462},{7,11,1954},{137,11,636},{136,10,714},{149, 11,6},{135,10,685},{9,10,420},{10,10,269},{10,10,285},{10,10,576},{11,10,397},{ 13,10,175},{145,10,90},{132,10,429},{5,0,556},{5,11,162},{136,11,68},{132,11,654 },{4,11,156},{7,11,998},{7,11,1045},{7,11,1860},{9,11,48},{9,11,692},{11,11,419} ,{139,11,602},{6,0,1317},{8,0,16},{9,0,825},{12,0,568},{7,11,1276},{8,11,474},{ 137,11,652},{18,0,97},{7,10,18},{7,10,699},{7,10,1966},{8,10,752},{9,10,273},{9, 10,412},{9,10,703},{10,10,71},{10,10,427},{138,10,508},{10,0,703},{7,11,1454},{ 138,11,703},{4,10,53},{5,10,186},{135,10,752},{134,0,892},{134,0,1571},{8,10,575 },{10,10,289},{139,10,319},{6,0,186},{137,0,426},{134,0,1101},{132,10,675},{132, 0,585},{6,0,1870},{137,0,937},{152,11,10},{9,11,197},{10,11,300},{12,11,473},{13 ,11,90},{141,11,405},{4,0,93},{5,0,252},{6,0,229},{7,0,291},{9,0,550},{139,0,644 },{137,0,749},{9,0,162},{6,10,209},{8,10,468},{9,10,210},{11,10,36},{12,10,28},{ 12,10,630},{13,10,21},{13,10,349},{14,10,7},{145,10,13},{132,0,381},{132,11,606} ,{4,10,342},{135,10,1179},{7,11,1587},{7,11,1707},{10,11,528},{139,11,504},{12, 11,39},{13,11,265},{141,11,439},{4,10,928},{133,10,910},{7,10,1838},{7,11,1978}, {136,11,676},{6,0,762},{6,0,796},{134,0,956},{4,10,318},{4,10,496},{7,10,856},{ 139,10,654},{137,11,242},{4,11,361},{133,11,315},{132,11,461},{132,11,472},{132, 0,857},{5,0,21},{6,0,77},{6,0,157},{7,0,974},{7,0,1301},{7,0,1339},{7,0,1490},{7 ,0,1873},{9,0,628},{7,10,915},{8,10,247},{147,10,0},{4,10,202},{5,10,382},{6,10, 454},{7,10,936},{7,10,1803},{8,10,758},{9,10,375},{9,10,895},{10,10,743},{10,10, 792},{11,10,978},{11,10,1012},{142,10,109},{7,11,617},{10,11,498},{11,11,501},{ 12,11,16},{140,11,150},{7,10,1150},{7,10,1425},{7,10,1453},{10,11,747},{140,10, 513},{133,11,155},{11,0,919},{141,0,409},{138,10,791},{10,0,633},{139,11,729},{7 ,11,163},{8,11,319},{9,11,402},{10,11,24},{10,11,681},{11,11,200},{11,11,567},{ 12,11,253},{12,11,410},{142,11,219},{5,11,475},{7,11,1780},{9,11,230},{11,11,297 },{11,11,558},{14,11,322},{147,11,76},{7,0,332},{6,10,445},{137,10,909},{135,11, 1956},{136,11,274},{134,10,578},{135,0,1489},{135,11,1848},{5,11,944},{134,11, 1769},{132,11,144},{136,10,766},{4,0,832},{135,10,541},{8,0,398},{9,0,681},{139, 0,632},{136,0,645},{9,0,791},{10,0,93},{16,0,13},{17,0,23},{18,0,135},{19,0,12}, {20,0,1},{20,0,12},{148,0,14},{6,11,247},{137,11,555},{134,0,20},{132,0,800},{ 135,0,1841},{139,10,983},{137,10,768},{132,10,584},{141,11,51},{6,0,1993},{4,11, 620},{138,11,280},{136,0,769},{11,0,290},{11,0,665},{7,11,1810},{11,11,866},{12, 11,103},{13,11,495},{17,11,67},{147,11,74},{134,0,1426},{139,0,60},{4,10,326},{ 135,10,1770},{7,0,1874},{9,0,641},{132,10,226},{6,0,644},{5,10,426},{8,10,30},{9 ,10,2},{11,10,549},{147,10,122},{5,11,428},{138,11,442},{135,11,1871},{135,0, 1757},{147,10,117},{135,0,937},{135,0,1652},{6,0,654},{134,0,1476},{133,11,99},{ 135,0,527},{132,10,345},{4,10,385},{4,11,397},{7,10,265},{135,10,587},{4,0,579}, {5,0,226},{5,0,323},{135,0,960},{134,0,1486},{8,11,502},{144,11,9},{4,10,347},{5 ,10,423},{5,10,996},{135,10,1329},{7,11,727},{146,11,73},{4,11,485},{7,11,353},{ 7,10,1259},{7,11,1523},{9,10,125},{139,10,65},{6,0,325},{5,10,136},{6,11,366},{7 ,11,1384},{7,11,1601},{136,10,644},{138,11,160},{6,0,1345},{137,11,282},{18,0,91 },{147,0,70},{136,0,404},{4,11,157},{133,11,471},{133,0,973},{6,0,135},{135,0, 1176},{8,11,116},{11,11,551},{142,11,159},{4,0,549},{4,10,433},{133,10,719},{136 ,0,976},{5,11,160},{7,11,363},{7,11,589},{10,11,170},{141,11,55},{144,0,21},{144 ,0,51},{135,0,314},{135,10,1363},{4,11,108},{7,11,405},{10,11,491},{139,11,498}, {146,0,4},{4,10,555},{8,10,536},{10,10,288},{139,10,1005},{135,11,1005},{6,0,281 },{7,0,6},{8,0,282},{8,0,480},{8,0,499},{9,0,198},{10,0,143},{10,0,169},{10,0, 211},{10,0,417},{10,0,574},{11,0,147},{11,0,395},{12,0,75},{12,0,407},{12,0,608} ,{13,0,500},{142,0,251},{6,0,1093},{6,0,1405},{9,10,370},{138,10,90},{4,11,926}, {133,11,983},{135,0,1776},{134,0,1528},{132,0,419},{132,11,538},{6,11,294},{7,11 ,1267},{136,11,624},{135,11,1772},{138,11,301},{4,10,257},{135,10,2031},{4,0,138 },{7,0,1012},{7,0,1280},{9,0,76},{135,10,1768},{132,11,757},{5,0,29},{140,0,638} ,{7,11,655},{135,11,1844},{7,0,1418},{6,11,257},{135,11,1522},{8,11,469},{138,11 ,47},{142,11,278},{6,10,83},{6,10,1733},{135,10,1389},{11,11,204},{11,11,243},{ 140,11,293},{135,11,1875},{6,0,1710},{135,0,2038},{137,11,299},{4,0,17},{5,0,23} ,{7,0,995},{11,0,383},{11,0,437},{12,0,460},{140,0,532},{133,0,862},{137,10,696} ,{6,0,592},{138,0,946},{138,11,599},{7,10,1718},{9,10,95},{9,10,274},{10,10,279} ,{10,10,317},{10,10,420},{11,10,303},{11,10,808},{12,10,134},{12,10,367},{13,10, 149},{13,10,347},{14,10,349},{14,10,406},{18,10,22},{18,10,89},{18,10,122},{147, 10,47},{8,0,70},{12,0,171},{141,0,272},{133,10,26},{132,10,550},{137,0,812},{10, 0,233},{139,0,76},{134,0,988},{134,0,442},{136,10,822},{7,0,896},{4,10,902},{5, 10,809},{134,10,122},{5,11,150},{7,11,106},{8,11,603},{9,11,593},{9,11,634},{10, 11,44},{10,11,173},{11,11,462},{11,11,515},{13,11,216},{13,11,288},{142,11,400}, {136,0,483},{135,10,262},{6,0,1709},{133,10,620},{4,10,34},{5,10,574},{7,10,279} ,{7,10,1624},{136,10,601},{137,10,170},{147,0,119},{12,11,108},{141,11,291},{11, 0,69},{12,0,105},{12,0,117},{13,0,213},{14,0,13},{14,0,62},{14,0,177},{14,0,421} ,{15,0,19},{146,0,141},{137,0,309},{11,11,278},{142,11,73},{7,0,608},{7,0,976},{ 9,0,146},{10,0,206},{10,0,596},{13,0,218},{142,0,153},{133,10,332},{6,10,261},{8 ,10,182},{139,10,943},{4,11,493},{144,11,55},{134,10,1721},{132,0,768},{4,10,933 },{133,10,880},{7,11,555},{7,11,1316},{7,11,1412},{7,11,1839},{9,11,192},{9,11, 589},{11,11,241},{11,11,676},{11,11,811},{11,11,891},{12,11,140},{12,11,346},{12 ,11,479},{13,11,30},{13,11,49},{13,11,381},{14,11,188},{15,11,150},{16,11,76},{ 18,11,30},{148,11,52},{4,0,518},{135,0,1136},{6,11,568},{7,11,112},{7,11,1804},{ 8,11,362},{8,11,410},{8,11,830},{9,11,514},{11,11,649},{142,11,157},{135,11,673} ,{8,0,689},{137,0,863},{4,0,18},{7,0,145},{7,0,444},{7,0,1278},{8,0,49},{8,0,400 },{9,0,71},{9,0,250},{10,0,459},{12,0,160},{16,0,24},{132,11,625},{140,0,1020},{ 4,0,997},{6,0,1946},{6,0,1984},{134,0,1998},{6,11,16},{6,11,158},{7,11,43},{7,11 ,129},{7,11,181},{8,11,276},{8,11,377},{10,11,523},{11,11,816},{12,11,455},{13, 11,303},{142,11,135},{133,10,812},{134,0,658},{4,11,1},{7,11,1143},{7,11,1463},{ 8,11,61},{9,11,207},{9,11,390},{9,11,467},{139,11,836},{150,11,26},{140,0,106},{ 6,0,1827},{10,0,931},{18,0,166},{20,0,114},{4,10,137},{7,10,1178},{7,11,1319},{ 135,10,1520},{133,0,1010},{4,11,723},{5,11,895},{7,11,1031},{8,11,199},{8,11,340 },{9,11,153},{9,11,215},{10,11,21},{10,11,59},{10,11,80},{10,11,224},{11,11,229} ,{11,11,652},{12,11,192},{13,11,146},{142,11,91},{132,11,295},{6,11,619},{7,11, 898},{7,11,1092},{8,11,485},{18,11,28},{147,11,116},{137,11,51},{6,10,1661},{7, 10,1975},{7,10,2009},{135,10,2011},{5,11,309},{140,11,211},{5,0,87},{7,0,313},{7 ,0,1103},{10,0,208},{10,0,582},{11,0,389},{11,0,813},{12,0,385},{13,0,286},{14,0 ,124},{146,0,108},{5,11,125},{8,11,77},{138,11,15},{132,0,267},{133,0,703},{137, 11,155},{133,11,439},{11,11,164},{140,11,76},{9,0,496},{5,10,89},{7,10,1915},{9, 10,185},{9,10,235},{10,10,64},{10,10,270},{10,10,403},{10,10,469},{10,10,529},{ 10,10,590},{11,10,140},{11,10,860},{13,10,1},{13,10,422},{14,10,341},{14,10,364} ,{17,10,93},{18,10,113},{19,10,97},{147,10,113},{133,10,695},{135,0,1121},{5,10, 6},{6,10,183},{7,10,680},{7,10,978},{7,10,1013},{7,10,1055},{12,10,230},{13,10, 172},{146,10,29},{4,11,8},{7,11,1152},{7,11,1153},{7,11,1715},{9,11,374},{10,11, 478},{139,11,648},{135,11,1099},{6,10,29},{139,10,63},{4,0,561},{10,0,249},{139, 0,209},{132,0,760},{7,11,799},{138,11,511},{136,11,87},{9,0,154},{140,0,485},{ 136,0,255},{132,0,323},{140,0,419},{132,10,311},{134,10,1740},{4,0,368},{135,0, 641},{7,10,170},{8,10,90},{8,10,177},{8,10,415},{11,10,714},{142,10,281},{4,11, 69},{5,11,122},{9,11,656},{138,11,464},{5,11,849},{134,11,1633},{8,0,522},{142,0 ,328},{11,10,91},{13,10,129},{15,10,101},{145,10,125},{7,0,562},{8,0,551},{4,10, 494},{6,10,74},{7,10,44},{11,11,499},{12,10,17},{15,10,5},{148,10,11},{4,10,276} ,{133,10,296},{9,0,92},{147,0,91},{4,10,7},{5,10,90},{5,10,158},{6,10,542},{7,10 ,221},{7,10,1574},{9,10,490},{10,10,540},{11,10,443},{139,10,757},{6,0,525},{6,0 ,1976},{8,0,806},{9,0,876},{140,0,284},{5,11,859},{7,10,588},{7,11,1160},{8,11, 107},{9,10,175},{9,11,291},{9,11,439},{10,10,530},{10,11,663},{11,11,609},{140, 11,197},{7,11,168},{13,11,196},{141,11,237},{139,0,958},{133,0,594},{135,10,580} ,{7,10,88},{136,10,627},{6,0,479},{6,0,562},{7,0,1060},{13,0,6},{5,10,872},{6,10 ,57},{7,10,471},{9,10,447},{137,10,454},{136,11,413},{145,11,19},{4,11,117},{6, 11,372},{7,11,1905},{142,11,323},{4,11,722},{139,11,471},{17,0,61},{5,10,31},{ 134,10,614},{8,10,330},{140,10,477},{7,10,1200},{138,10,460},{6,10,424},{135,10, 1866},{6,0,1641},{136,0,820},{6,0,1556},{134,0,1618},{9,11,5},{12,11,216},{12,11 ,294},{12,11,298},{12,11,400},{12,11,518},{13,11,229},{143,11,139},{15,11,155},{ 144,11,79},{4,0,302},{135,0,1766},{5,10,13},{134,10,142},{6,0,148},{7,0,1313},{7 ,10,116},{8,10,322},{8,10,755},{9,10,548},{10,10,714},{11,10,884},{141,10,324},{ 137,0,676},{9,11,88},{139,11,270},{5,11,12},{7,11,375},{137,11,438},{134,0,1674} ,{7,10,1472},{135,10,1554},{11,0,178},{7,10,1071},{7,10,1541},{7,10,1767},{7,10, 1806},{11,10,162},{11,10,242},{12,10,605},{15,10,26},{144,10,44},{6,0,389},{7,0, 149},{9,0,142},{138,0,94},{140,11,71},{145,10,115},{6,0,8},{7,0,1881},{8,0,91},{ 11,11,966},{12,11,287},{13,11,342},{13,11,402},{15,11,110},{143,11,163},{4,11, 258},{136,11,639},{6,11,22},{7,11,903},{138,11,577},{133,11,681},{135,10,1111},{ 135,11,1286},{9,0,112},{8,10,1},{138,10,326},{5,10,488},{6,10,527},{7,10,489},{7 ,10,1636},{8,10,121},{8,10,144},{8,10,359},{9,10,193},{9,10,241},{9,10,336},{9, 10,882},{11,10,266},{11,10,372},{11,10,944},{12,10,401},{140,10,641},{4,11,664}, {133,11,804},{6,0,747},{134,0,1015},{135,0,1746},{9,10,31},{10,10,244},{10,10, 699},{12,10,149},{141,10,497},{133,10,377},{135,0,24},{6,0,1352},{5,11,32},{145, 10,101},{7,0,1530},{10,0,158},{13,0,13},{13,0,137},{13,0,258},{14,0,111},{14,0, 225},{14,0,253},{14,0,304},{14,0,339},{14,0,417},{146,0,33},{4,0,503},{135,0, 1661},{5,0,130},{6,0,845},{7,0,1314},{9,0,610},{10,0,718},{11,0,601},{11,0,819}, {11,0,946},{140,0,536},{10,0,149},{11,0,280},{142,0,336},{134,0,1401},{135,0, 1946},{8,0,663},{144,0,8},{134,0,1607},{135,10,2023},{4,11,289},{7,11,629},{7,11 ,1698},{7,11,1711},{140,11,215},{6,11,450},{136,11,109},{10,0,882},{10,0,883},{ 10,0,914},{138,0,928},{133,10,843},{136,11,705},{132,10,554},{133,10,536},{5,0, 417},{9,10,79},{11,10,625},{145,10,7},{7,11,1238},{142,11,37},{4,0,392},{135,0, 1597},{5,0,433},{9,0,633},{11,0,629},{132,10,424},{7,10,336},{136,10,785},{134, 11,355},{6,0,234},{7,0,769},{9,0,18},{138,0,358},{4,10,896},{134,10,1777},{138, 11,323},{7,0,140},{7,0,1950},{8,0,680},{11,0,817},{147,0,88},{7,0,1222},{138,0, 386},{139,11,908},{11,0,249},{12,0,313},{16,0,66},{145,0,26},{134,0,5},{7,10,750 },{9,10,223},{11,10,27},{11,10,466},{12,10,624},{14,10,265},{146,10,61},{134,11, 26},{134,0,1216},{5,0,963},{134,0,1773},{4,11,414},{5,11,467},{9,11,654},{10,11, 451},{12,11,59},{141,11,375},{135,11,17},{4,10,603},{133,10,661},{4,10,11},{6,10 ,128},{7,10,231},{7,10,1533},{138,10,725},{135,11,955},{7,0,180},{8,0,509},{136, 0,792},{132,10,476},{132,0,1002},{133,11,538},{135,10,1807},{132,0,931},{7,0,943 },{11,0,614},{140,0,747},{135,0,1837},{9,10,20},{10,10,324},{10,10,807},{139,10, 488},{134,0,641},{6,11,280},{10,11,502},{11,11,344},{140,11,38},{5,11,45},{7,11, 1161},{11,11,448},{11,11,880},{13,11,139},{13,11,407},{15,11,16},{17,11,95},{18, 11,66},{18,11,88},{18,11,123},{149,11,7},{9,0,280},{138,0,134},{22,0,22},{23,0,5 },{151,0,29},{136,11,777},{4,0,90},{5,0,545},{7,0,754},{9,0,186},{10,0,72},{10,0 ,782},{11,0,577},{11,0,610},{11,0,960},{12,0,354},{12,0,362},{12,0,595},{4,11, 410},{135,11,521},{135,11,1778},{5,10,112},{6,10,103},{134,10,150},{138,10,356}, {132,0,742},{7,0,151},{9,0,329},{139,0,254},{8,0,853},{8,0,881},{8,0,911},{8,0, 912},{10,0,872},{12,0,741},{12,0,742},{152,0,18},{4,11,573},{136,11,655},{6,0, 921},{134,0,934},{9,0,187},{10,0,36},{11,0,1016},{17,0,44},{146,0,64},{7,0,833}, {136,0,517},{4,0,506},{5,0,295},{135,0,1680},{4,10,708},{8,10,15},{9,10,50},{9, 10,386},{11,10,18},{11,10,529},{140,10,228},{7,0,251},{7,0,1701},{8,0,436},{4,10 ,563},{7,10,592},{7,10,637},{7,10,770},{8,10,463},{9,10,60},{9,10,335},{9,10,904 },{10,10,73},{11,10,434},{12,10,585},{13,10,331},{18,10,110},{148,10,60},{132,10 ,502},{136,0,584},{6,10,347},{138,10,161},{7,0,987},{9,0,688},{10,0,522},{11,0, 788},{12,0,137},{12,0,566},{14,0,9},{14,0,24},{14,0,64},{7,11,899},{142,11,325}, {4,0,214},{5,0,500},{5,10,102},{6,10,284},{7,10,1079},{7,10,1423},{7,10,1702},{8 ,10,470},{9,10,554},{9,10,723},{139,10,333},{7,10,246},{135,10,840},{6,10,10},{8 ,10,571},{9,10,739},{143,10,91},{133,10,626},{146,0,195},{134,0,1775},{7,0,389}, {7,0,700},{7,0,940},{8,0,514},{9,0,116},{9,0,535},{10,0,118},{11,0,107},{11,0, 148},{11,0,922},{12,0,254},{12,0,421},{142,0,238},{5,10,18},{6,10,526},{13,10,24 },{13,10,110},{19,10,5},{147,10,44},{132,0,743},{11,0,292},{4,10,309},{5,10,462} ,{7,10,970},{135,10,1097},{22,10,30},{150,10,33},{139,11,338},{135,11,1598},{7,0 ,1283},{9,0,227},{11,0,325},{11,0,408},{14,0,180},{146,0,47},{4,0,953},{6,0,1805 },{6,0,1814},{6,0,1862},{140,0,774},{6,11,611},{135,11,1733},{135,11,1464},{5,0, 81},{7,0,146},{7,0,1342},{8,0,53},{8,0,561},{8,0,694},{8,0,754},{9,0,115},{9,0, 179},{9,0,894},{10,0,462},{10,0,813},{11,0,230},{11,0,657},{11,0,699},{11,0,748} ,{12,0,119},{12,0,200},{12,0,283},{142,0,273},{5,0,408},{6,0,789},{6,0,877},{6,0 ,1253},{6,0,1413},{137,0,747},{134,10,1704},{135,11,663},{6,0,1910},{6,0,1915},{ 6,0,1923},{9,0,913},{9,0,928},{9,0,950},{9,0,954},{9,0,978},{9,0,993},{12,0,812} ,{12,0,819},{12,0,831},{12,0,833},{12,0,838},{12,0,909},{12,0,928},{12,0,931},{ 12,0,950},{15,0,186},{15,0,187},{15,0,195},{15,0,196},{15,0,209},{15,0,215},{15, 0,236},{15,0,241},{15,0,249},{15,0,253},{18,0,180},{18,0,221},{18,0,224},{18,0, 227},{18,0,229},{149,0,60},{7,0,1826},{135,0,1938},{11,0,490},{18,0,143},{5,10, 86},{7,10,743},{9,10,85},{10,10,281},{10,10,432},{12,10,251},{13,10,118},{142,10 ,378},{5,10,524},{133,10,744},{141,11,442},{10,10,107},{140,10,436},{135,11,503} ,{134,0,1162},{132,10,927},{7,0,30},{8,0,86},{8,0,315},{8,0,700},{9,0,576},{9,0, 858},{10,0,414},{11,0,310},{11,0,888},{11,0,904},{12,0,361},{13,0,248},{13,0,371 },{14,0,142},{12,10,670},{146,10,94},{134,0,721},{4,11,113},{5,11,163},{5,11,735 },{7,11,1009},{7,10,1149},{9,11,9},{9,10,156},{9,11,771},{12,11,90},{13,11,138}, {13,11,410},{143,11,128},{138,0,839},{133,10,778},{137,0,617},{133,10,502},{8,10 ,196},{10,10,283},{139,10,406},{6,0,428},{7,0,524},{8,0,169},{8,0,234},{9,0,480} ,{138,0,646},{133,10,855},{134,0,1648},{7,0,1205},{138,0,637},{7,0,1596},{4,11, 935},{133,11,823},{5,11,269},{7,11,434},{7,11,891},{8,11,339},{9,11,702},{11,11, 594},{11,11,718},{145,11,100},{7,11,878},{9,11,485},{141,11,264},{4,0,266},{8,0, 4},{9,0,39},{10,0,166},{11,0,918},{12,0,635},{20,0,10},{22,0,27},{22,0,43},{22,0 ,52},{134,11,1713},{7,10,1400},{9,10,446},{138,10,45},{135,11,900},{132,0,862},{ 134,0,1554},{135,11,1033},{19,0,16},{147,11,16},{135,11,1208},{7,0,157},{136,0, 279},{6,0,604},{136,0,391},{13,10,455},{15,10,99},{15,10,129},{144,10,68},{135, 10,172},{7,0,945},{11,0,713},{139,0,744},{4,0,973},{10,0,877},{10,0,937},{10,0, 938},{140,0,711},{139,0,1022},{132,10,568},{142,11,143},{4,0,567},{9,0,859},{132 ,10,732},{7,0,1846},{136,0,628},{136,10,733},{133,0,762},{4,10,428},{135,10,1789 },{10,0,784},{13,0,191},{7,10,2015},{140,10,665},{133,0,298},{7,0,633},{7,0,905} ,{7,0,909},{7,0,1538},{9,0,767},{140,0,636},{138,10,806},{132,0,795},{139,0,301} ,{135,0,1970},{5,11,625},{135,11,1617},{135,11,275},{7,11,37},{8,11,425},{8,11, 693},{9,11,720},{10,11,380},{10,11,638},{11,11,273},{11,11,307},{11,11,473},{12, 11,61},{143,11,43},{135,11,198},{134,0,1236},{7,0,369},{12,0,644},{12,0,645},{ 144,0,90},{19,0,15},{149,0,27},{6,0,71},{7,0,845},{8,0,160},{9,0,318},{6,10,1623 },{134,10,1681},{134,0,1447},{134,0,1255},{138,0,735},{8,0,76},{132,11,168},{6, 10,1748},{8,10,715},{9,10,802},{10,10,46},{10,10,819},{13,10,308},{14,10,351},{ 14,10,363},{146,10,67},{135,11,91},{6,0,474},{4,10,63},{133,10,347},{133,10,749} ,{138,0,841},{133,10,366},{6,0,836},{132,11,225},{135,0,1622},{135,10,89},{140,0 ,735},{134,0,1601},{138,11,145},{6,0,1390},{137,0,804},{142,0,394},{6,11,15},{7, 11,70},{10,11,240},{147,11,93},{6,0,96},{135,0,1426},{4,0,651},{133,0,289},{7,11 ,956},{7,10,977},{7,11,1157},{7,11,1506},{7,11,1606},{7,11,1615},{7,11,1619},{7, 11,1736},{7,11,1775},{8,11,590},{9,11,324},{9,11,736},{9,11,774},{9,11,776},{9, 11,784},{10,11,567},{10,11,708},{11,11,518},{11,11,613},{11,11,695},{11,11,716}, {11,11,739},{11,11,770},{11,11,771},{11,11,848},{11,11,857},{11,11,931},{11,11, 947},{12,11,326},{12,11,387},{12,11,484},{12,11,528},{12,11,552},{12,11,613},{13 ,11,189},{13,11,256},{13,11,340},{13,11,432},{13,11,436},{13,11,440},{13,11,454} ,{14,11,174},{14,11,220},{14,11,284},{14,11,390},{145,11,121},{7,0,688},{8,0,35} ,{9,0,511},{10,0,767},{147,0,118},{134,0,667},{4,0,513},{5,10,824},{133,10,941}, {7,10,440},{8,10,230},{139,10,106},{134,0,2034},{135,11,1399},{143,11,66},{135, 11,1529},{4,11,145},{6,11,176},{7,11,395},{9,11,562},{144,11,28},{132,11,501},{ 132,0,704},{134,0,1524},{7,0,1078},{134,11,464},{6,11,509},{10,11,82},{20,11,91} ,{151,11,13},{4,0,720},{133,0,306},{133,0,431},{7,0,1196},{4,10,914},{5,10,800}, {133,10,852},{135,11,1189},{10,0,54},{141,10,115},{7,10,564},{142,10,168},{5,0, 464},{6,0,236},{7,0,696},{7,0,914},{7,0,1108},{7,0,1448},{9,0,15},{9,0,564},{10, 0,14},{12,0,565},{13,0,449},{14,0,53},{15,0,13},{16,0,64},{17,0,41},{4,10,918},{ 133,10,876},{6,0,1418},{134,10,1764},{4,10,92},{133,10,274},{134,0,907},{4,11, 114},{8,10,501},{9,11,492},{13,11,462},{142,11,215},{4,11,77},{5,11,361},{6,11, 139},{6,11,401},{6,11,404},{7,11,413},{7,11,715},{7,11,1716},{11,11,279},{12,11, 179},{12,11,258},{13,11,244},{142,11,358},{6,0,1767},{12,0,194},{145,0,107},{134 ,11,1717},{5,10,743},{142,11,329},{4,10,49},{7,10,280},{135,10,1633},{5,0,840},{ 7,11,1061},{8,11,82},{11,11,250},{12,11,420},{141,11,184},{135,11,724},{134,0, 900},{136,10,47},{134,0,1436},{144,11,0},{6,0,675},{7,0,1008},{7,0,1560},{9,0, 642},{11,0,236},{14,0,193},{5,10,272},{5,10,908},{5,10,942},{8,10,197},{9,10,47} ,{11,10,538},{139,10,742},{4,0,68},{5,0,628},{5,0,634},{6,0,386},{7,0,794},{8,0, 273},{9,0,563},{10,0,105},{10,0,171},{11,0,94},{139,0,354},{135,10,1911},{137,10 ,891},{4,0,95},{6,0,1297},{6,0,1604},{7,0,416},{139,0,830},{6,11,513},{135,11, 1052},{7,0,731},{13,0,20},{143,0,11},{137,11,899},{10,0,850},{140,0,697},{4,0, 662},{7,11,1417},{12,11,382},{17,11,48},{152,11,12},{133,0,736},{132,0,861},{4, 10,407},{132,10,560},{141,10,490},{6,11,545},{7,11,565},{7,11,1669},{10,11,114}, {11,11,642},{140,11,618},{6,0,871},{134,0,1000},{5,0,864},{10,0,648},{11,0,671}, {15,0,46},{133,11,5},{133,0,928},{11,0,90},{13,0,7},{4,10,475},{11,10,35},{13,10 ,71},{13,10,177},{142,10,422},{136,0,332},{135,11,192},{134,0,1055},{136,11,763} ,{11,0,986},{140,0,682},{7,0,76},{8,0,44},{9,0,884},{10,0,580},{11,0,399},{11,0, 894},{143,0,122},{135,11,1237},{135,10,636},{11,0,300},{6,10,222},{7,10,1620},{8 ,10,409},{137,10,693},{4,11,87},{5,11,250},{10,11,601},{13,11,298},{13,11,353},{ 141,11,376},{5,0,518},{10,0,340},{11,0,175},{149,0,16},{140,0,771},{6,0,1108},{ 137,0,831},{132,0,836},{135,0,1852},{4,0,957},{6,0,1804},{8,0,842},{8,0,843},{8, 0,851},{8,0,855},{140,0,767},{135,11,814},{4,11,57},{7,11,1195},{7,11,1438},{7, 11,1548},{7,11,1835},{7,11,1904},{9,11,757},{10,11,604},{139,11,519},{133,10,882 },{138,0,246},{4,0,934},{5,0,202},{8,0,610},{7,11,1897},{12,11,290},{13,11,80},{ 13,11,437},{145,11,74},{8,0,96},{9,0,36},{10,0,607},{10,0,804},{10,0,832},{11,0, 423},{11,0,442},{12,0,309},{14,0,199},{15,0,90},{145,0,110},{132,10,426},{7,0, 654},{8,0,240},{6,10,58},{7,10,745},{7,10,1969},{8,10,675},{9,10,479},{9,10,731} ,{10,10,330},{10,10,593},{10,10,817},{11,10,32},{11,10,133},{11,10,221},{145,10, 68},{9,0,13},{9,0,398},{9,0,727},{10,0,75},{10,0,184},{10,0,230},{10,0,564},{10, 0,569},{11,0,973},{12,0,70},{12,0,189},{13,0,57},{141,0,257},{4,11,209},{135,11, 902},{7,0,391},{137,10,538},{134,0,403},{6,11,303},{7,11,335},{7,11,1437},{7,11, 1668},{8,11,553},{8,11,652},{8,11,656},{9,11,558},{11,11,743},{149,11,18},{132, 11,559},{11,0,75},{142,0,267},{6,0,815},{141,11,2},{141,0,366},{137,0,631},{133, 11,1017},{5,0,345},{135,0,1016},{133,11,709},{134,11,1745},{133,10,566},{7,0,952 },{6,10,48},{9,10,139},{10,10,399},{11,10,469},{12,10,634},{141,10,223},{133,0, 673},{9,0,850},{7,11,8},{136,11,206},{6,0,662},{149,0,35},{4,0,287},{133,0,1018} ,{6,10,114},{7,10,1224},{7,10,1556},{136,10,3},{8,10,576},{137,10,267},{4,0,884} ,{5,0,34},{10,0,724},{12,0,444},{13,0,354},{18,0,32},{23,0,24},{23,0,31},{152,0, 5},{133,10,933},{132,11,776},{138,0,151},{136,0,427},{134,0,382},{132,0,329},{9, 0,846},{10,0,827},{138,11,33},{9,0,279},{10,0,407},{14,0,84},{22,0,18},{135,11, 1297},{136,11,406},{132,0,906},{136,0,366},{134,0,843},{134,0,1443},{135,0,1372} ,{138,0,992},{4,0,123},{5,0,605},{7,0,1509},{136,0,36},{132,0,649},{8,11,175},{ 10,11,168},{138,11,573},{133,0,767},{134,0,1018},{135,11,1305},{12,10,30},{13,10 ,148},{14,10,87},{14,10,182},{16,10,42},{148,10,70},{134,11,607},{4,0,273},{5,0, 658},{133,0,995},{6,0,72},{139,11,174},{10,0,483},{12,0,368},{7,10,56},{7,10, 1989},{8,10,337},{8,10,738},{9,10,600},{13,10,447},{142,10,92},{5,11,784},{138, 10,666},{135,0,1345},{139,11,882},{134,0,1293},{133,0,589},{134,0,1988},{5,0,117 },{6,0,514},{6,0,541},{7,0,1164},{7,0,1436},{8,0,220},{8,0,648},{10,0,688},{139, 0,560},{136,0,379},{5,0,686},{7,10,866},{135,10,1163},{132,10,328},{9,11,14},{9, 11,441},{10,11,306},{139,11,9},{4,10,101},{135,10,1171},{5,10,833},{136,10,744}, {5,11,161},{7,11,839},{135,11,887},{7,0,196},{10,0,765},{11,0,347},{11,0,552},{ 11,0,790},{12,0,263},{13,0,246},{13,0,270},{13,0,395},{14,0,176},{14,0,190},{14, 0,398},{14,0,412},{15,0,32},{15,0,63},{16,0,88},{147,0,105},{6,10,9},{6,10,397}, {7,10,53},{7,10,1742},{10,10,632},{11,10,828},{140,10,146},{5,0,381},{135,0,1792 },{134,0,1452},{135,11,429},{8,0,367},{10,0,760},{14,0,79},{20,0,17},{152,0,0},{ 7,0,616},{138,0,413},{11,10,417},{12,10,223},{140,10,265},{7,11,1611},{13,11,14} ,{15,11,44},{19,11,13},{148,11,76},{135,0,1229},{6,0,120},{7,0,1188},{7,0,1710}, {8,0,286},{9,0,667},{11,0,592},{139,0,730},{135,11,1814},{135,0,1146},{4,10,186} ,{5,10,157},{8,10,168},{138,10,6},{4,0,352},{135,0,687},{4,0,192},{5,0,49},{6,0, 200},{6,0,293},{6,0,1696},{135,0,1151},{133,10,875},{5,10,773},{5,10,991},{6,10, 1635},{134,10,1788},{7,10,111},{136,10,581},{6,0,935},{134,0,1151},{134,0,1050}, {132,0,650},{132,0,147},{11,0,194},{12,0,62},{12,0,88},{11,11,194},{12,11,62},{ 140,11,88},{6,0,339},{135,0,923},{134,10,1747},{7,11,643},{136,11,236},{133,0, 934},{7,10,1364},{7,10,1907},{141,10,158},{132,10,659},{4,10,404},{135,10,675},{ 7,11,581},{9,11,644},{137,11,699},{13,0,211},{14,0,133},{14,0,204},{15,0,64},{15 ,0,69},{15,0,114},{16,0,10},{19,0,23},{19,0,35},{19,0,39},{19,0,51},{19,0,71},{ 19,0,75},{152,0,15},{133,10,391},{5,11,54},{135,11,1513},{7,0,222},{8,0,341},{5, 10,540},{134,10,1697},{134,10,78},{132,11,744},{136,0,293},{137,11,701},{7,11, 930},{10,11,402},{10,11,476},{13,11,452},{18,11,55},{147,11,104},{132,0,637},{ 133,10,460},{8,11,50},{137,11,624},{132,11,572},{134,0,1159},{4,10,199},{139,10, 34},{134,0,847},{134,10,388},{6,11,43},{7,11,38},{8,11,248},{9,11,504},{138,11, 513},{9,0,683},{4,10,511},{6,10,608},{9,10,333},{10,10,602},{11,10,441},{11,10, 723},{11,10,976},{140,10,357},{9,0,867},{138,0,837},{6,0,944},{135,11,326},{135, 0,1809},{5,10,938},{7,11,783},{136,10,707},{133,11,766},{133,11,363},{6,0,170},{ 7,0,1080},{8,0,395},{8,0,487},{141,0,147},{6,11,258},{140,11,409},{4,0,535},{8,0 ,618},{5,11,249},{148,11,82},{6,0,1379},{149,11,15},{135,0,1625},{150,0,23},{5, 11,393},{6,11,378},{7,11,1981},{9,11,32},{9,11,591},{10,11,685},{10,11,741},{142 ,11,382},{133,11,788},{7,11,1968},{10,11,19},{139,11,911},{7,11,1401},{135,11, 1476},{4,11,61},{5,11,58},{5,11,171},{5,11,635},{5,11,683},{5,11,700},{6,11,291} ,{6,11,566},{7,11,1650},{11,11,523},{12,11,273},{12,11,303},{15,11,39},{143,11, 111},{6,10,469},{7,10,1709},{138,10,515},{4,0,778},{134,11,589},{132,0,46},{5,0, 811},{6,0,1679},{6,0,1714},{135,0,2032},{7,0,1458},{9,0,407},{11,0,15},{12,0,651 },{149,0,37},{7,0,938},{132,10,500},{6,0,34},{7,0,69},{7,0,1089},{7,0,1281},{8,0 ,708},{8,0,721},{9,0,363},{148,0,98},{10,11,231},{147,11,124},{7,11,726},{152,11 ,9},{5,10,68},{134,10,383},{136,11,583},{4,11,917},{133,11,1005},{11,10,216},{ 139,10,340},{135,11,1675},{8,0,441},{10,0,314},{143,0,3},{132,11,919},{4,10,337} ,{6,10,353},{7,10,1934},{8,10,488},{137,10,429},{7,0,889},{7,10,1795},{8,10,259} ,{9,10,135},{9,10,177},{9,10,860},{10,10,825},{11,10,115},{11,10,370},{11,10,405 },{11,10,604},{12,10,10},{12,10,667},{12,10,669},{13,10,76},{14,10,310},{15,10, 76},{15,10,147},{148,10,23},{4,10,15},{4,11,255},{5,10,22},{5,11,302},{6,11,132} ,{6,10,244},{7,10,40},{7,11,128},{7,10,200},{7,11,283},{7,10,906},{7,10,1199},{7 ,11,1299},{9,10,616},{10,11,52},{10,11,514},{10,10,716},{11,10,635},{11,10,801}, {11,11,925},{12,10,458},{13,11,92},{142,11,309},{132,0,462},{137,11,173},{135,10 ,1735},{8,0,525},{5,10,598},{7,10,791},{8,10,108},{137,10,123},{5,0,73},{6,0,23} ,{134,0,338},{132,0,676},{132,10,683},{7,0,725},{8,0,498},{139,0,268},{12,0,21}, {151,0,7},{135,0,773},{4,10,155},{135,10,1689},{4,0,164},{5,0,730},{5,10,151},{5 ,10,741},{6,11,210},{7,10,498},{7,10,870},{7,10,1542},{12,10,213},{14,10,36},{14 ,10,391},{17,10,111},{18,10,6},{18,10,46},{18,10,151},{19,10,36},{20,10,32},{20, 10,56},{20,10,69},{20,10,102},{21,10,4},{22,10,8},{22,10,10},{22,10,14},{150,10, 31},{4,10,624},{135,10,1752},{4,0,583},{9,0,936},{15,0,214},{18,0,199},{24,0,26} ,{134,11,588},{7,0,1462},{11,0,659},{4,11,284},{134,11,223},{133,0,220},{139,0, 803},{132,0,544},{4,10,492},{133,10,451},{16,0,98},{148,0,119},{4,11,218},{7,11, 526},{143,11,137},{135,10,835},{4,11,270},{5,11,192},{6,11,332},{7,11,1322},{13, 11,9},{13,10,70},{14,11,104},{142,11,311},{132,10,539},{140,11,661},{5,0,176},{6 ,0,437},{6,0,564},{11,0,181},{141,0,183},{135,0,1192},{6,10,113},{135,10,436},{ 136,10,718},{135,10,520},{135,0,1878},{140,11,196},{7,11,379},{8,11,481},{137,11 ,377},{5,11,1003},{6,11,149},{137,11,746},{8,11,262},{9,11,627},{10,11,18},{11, 11,214},{11,11,404},{11,11,457},{11,11,780},{11,11,849},{11,11,913},{13,11,330}, {13,11,401},{142,11,200},{149,0,26},{136,11,304},{132,11,142},{135,0,944},{4,0, 790},{5,0,273},{134,0,394},{134,0,855},{4,0,135},{6,0,127},{7,0,1185},{7,0,1511} ,{8,0,613},{11,0,5},{12,0,336},{12,0,495},{12,0,586},{12,0,660},{12,0,668},{14,0 ,385},{15,0,118},{17,0,20},{146,0,98},{6,0,230},{9,0,752},{18,0,109},{12,10,610} ,{13,10,431},{144,10,59},{7,0,1954},{135,11,925},{4,11,471},{5,11,51},{6,11,602} ,{8,11,484},{10,11,195},{140,11,159},{132,10,307},{136,11,688},{132,11,697},{7, 11,812},{7,11,1261},{7,11,1360},{9,11,632},{140,11,352},{5,0,162},{8,0,68},{133, 10,964},{4,0,654},{136,11,212},{4,0,156},{7,0,998},{7,0,1045},{7,0,1860},{9,0,48 },{9,0,692},{11,0,419},{139,0,602},{133,11,221},{4,11,373},{5,11,283},{6,11,480} ,{135,11,609},{142,11,216},{132,0,240},{6,11,192},{9,11,793},{145,11,55},{4,10, 75},{5,10,180},{6,10,500},{7,10,58},{7,10,710},{138,10,645},{4,11,132},{5,11,69} ,{5,10,649},{135,11,1242},{6,10,276},{7,10,282},{7,10,879},{7,10,924},{8,10,459} ,{9,10,599},{9,10,754},{11,10,574},{12,10,128},{12,10,494},{13,10,52},{13,10,301 },{15,10,30},{143,10,132},{132,10,200},{4,11,111},{135,11,302},{9,0,197},{10,0, 300},{12,0,473},{13,0,90},{141,0,405},{132,11,767},{6,11,42},{7,11,1416},{7,11, 1590},{7,11,2005},{8,11,131},{8,11,466},{9,11,672},{13,11,252},{148,11,103},{8,0 ,958},{8,0,999},{10,0,963},{138,0,1001},{135,10,1621},{135,0,858},{4,0,606},{137 ,11,444},{6,11,44},{136,11,368},{139,11,172},{4,11,570},{133,11,120},{139,11,624 },{7,0,1978},{8,0,676},{6,10,225},{137,10,211},{7,0,972},{11,0,102},{136,10,687} ,{6,11,227},{135,11,1589},{8,10,58},{9,10,724},{11,10,809},{13,10,113},{145,10, 72},{4,0,361},{133,0,315},{132,0,461},{6,10,345},{135,10,1247},{132,0,472},{8,10 ,767},{8,10,803},{9,10,301},{137,10,903},{135,11,1333},{135,11,477},{7,10,1949}, {136,10,674},{6,0,905},{138,0,747},{133,0,155},{134,10,259},{7,0,163},{8,0,319}, {9,0,402},{10,0,24},{10,0,681},{11,0,200},{12,0,253},{12,0,410},{142,0,219},{5,0 ,475},{7,0,1780},{9,0,230},{11,0,297},{11,0,558},{14,0,322},{19,0,76},{6,11,1667 },{7,11,2036},{138,11,600},{136,10,254},{6,0,848},{135,0,1956},{6,11,511},{140, 11,132},{5,11,568},{6,11,138},{135,11,1293},{6,0,631},{137,0,838},{149,0,36},{4, 11,565},{8,11,23},{136,11,827},{5,0,944},{134,0,1769},{4,0,144},{6,0,842},{6,0, 1400},{4,11,922},{133,11,1023},{133,10,248},{9,10,800},{10,10,693},{11,10,482},{ 11,10,734},{139,10,789},{7,11,1002},{139,11,145},{4,10,116},{5,10,95},{5,10,445} ,{7,10,1688},{8,10,29},{9,10,272},{11,10,509},{139,10,915},{14,0,369},{146,0,72} ,{135,10,1641},{132,11,740},{133,10,543},{140,11,116},{6,0,247},{9,0,555},{5,10, 181},{136,10,41},{133,10,657},{136,0,996},{138,10,709},{7,0,189},{8,10,202},{138 ,10,536},{136,11,402},{4,11,716},{141,11,31},{10,0,280},{138,0,797},{9,10,423},{ 140,10,89},{8,10,113},{9,10,877},{10,10,554},{11,10,83},{12,10,136},{147,10,109} ,{133,10,976},{7,0,746},{132,10,206},{136,0,526},{139,0,345},{136,0,1017},{8,11, 152},{9,11,53},{9,11,268},{9,11,901},{10,11,518},{10,11,829},{11,11,188},{13,11, 74},{14,11,46},{15,11,17},{15,11,33},{17,11,40},{18,11,36},{19,11,20},{22,11,1}, {152,11,2},{133,11,736},{136,11,532},{5,0,428},{138,0,651},{135,11,681},{135,0, 1162},{7,0,327},{13,0,230},{17,0,113},{8,10,226},{10,10,537},{11,10,570},{11,10, 605},{11,10,799},{11,10,804},{12,10,85},{12,10,516},{12,10,623},{12,11,677},{13, 10,361},{14,10,77},{14,10,78},{147,10,110},{4,0,792},{7,0,1717},{10,0,546},{132, 10,769},{4,11,684},{136,11,384},{132,10,551},{134,0,1203},{9,10,57},{9,10,459},{ 10,10,425},{11,10,119},{12,10,184},{12,10,371},{13,10,358},{145,10,51},{5,0,672} ,{5,10,814},{8,10,10},{9,10,421},{9,10,729},{10,10,609},{139,10,689},{138,0,189} ,{134,10,624},{7,11,110},{7,11,188},{8,11,290},{8,11,591},{9,11,382},{9,11,649}, {11,11,71},{11,11,155},{11,11,313},{12,11,5},{13,11,325},{142,11,287},{133,0,99} ,{6,0,1053},{135,0,298},{7,11,360},{7,11,425},{9,11,66},{9,11,278},{138,11,644}, {4,0,397},{136,0,555},{137,10,269},{132,10,528},{4,11,900},{133,11,861},{6,0, 1157},{5,11,254},{7,11,985},{136,11,73},{7,11,1959},{136,11,683},{12,0,398},{20, 0,39},{21,0,11},{150,0,41},{4,0,485},{7,0,353},{135,0,1523},{6,0,366},{7,0,1384} ,{135,0,1601},{138,0,787},{137,0,282},{5,10,104},{6,10,173},{135,10,1631},{139, 11,146},{4,0,157},{133,0,471},{134,0,941},{132,11,725},{7,0,1336},{8,10,138},{8, 10,342},{9,10,84},{10,10,193},{11,10,883},{140,10,359},{134,11,196},{136,0,116}, {133,11,831},{134,0,787},{134,10,95},{6,10,406},{10,10,409},{10,10,447},{11,10, 44},{140,10,100},{5,0,160},{7,0,363},{7,0,589},{10,0,170},{141,0,55},{134,0,1815 },{132,0,866},{6,0,889},{6,0,1067},{6,0,1183},{4,11,321},{134,11,569},{5,11,848} ,{134,11,66},{4,11,36},{6,10,1636},{7,11,1387},{10,11,205},{11,11,755},{141,11, 271},{132,0,689},{9,0,820},{4,10,282},{7,10,1034},{11,10,398},{11,10,634},{12,10 ,1},{12,10,79},{12,10,544},{14,10,237},{17,10,10},{146,10,20},{4,0,108},{7,0,804 },{139,0,498},{132,11,887},{6,0,1119},{135,11,620},{6,11,165},{138,11,388},{5,0, 244},{5,10,499},{6,10,476},{7,10,600},{7,10,888},{135,10,1096},{140,0,609},{135, 0,1005},{4,0,412},{133,0,581},{4,11,719},{135,11,155},{7,10,296},{7,10,596},{8, 10,560},{8,10,586},{9,10,612},{11,10,304},{12,10,46},{13,10,89},{14,10,112},{145 ,10,122},{4,0,895},{133,0,772},{142,11,307},{135,0,1898},{4,0,926},{133,0,983},{ 4,11,353},{6,11,146},{6,11,1789},{7,11,288},{7,11,990},{7,11,1348},{9,11,665},{9 ,11,898},{11,11,893},{142,11,212},{132,0,538},{133,11,532},{6,0,294},{7,0,1267}, {8,0,624},{141,0,496},{7,0,1325},{4,11,45},{135,11,1257},{138,0,301},{9,0,298},{ 12,0,291},{13,0,276},{14,0,6},{17,0,18},{21,0,32},{7,10,1599},{7,10,1723},{8,10, 79},{8,10,106},{8,10,190},{8,10,302},{8,10,383},{8,10,713},{9,10,119},{9,10,233} ,{9,10,419},{9,10,471},{10,10,181},{10,10,406},{11,10,57},{11,10,85},{11,10,120} ,{11,10,177},{11,10,296},{11,10,382},{11,10,454},{11,10,758},{11,10,999},{12,10, 27},{12,10,131},{12,10,245},{12,10,312},{12,10,446},{12,10,454},{13,10,98},{13, 10,426},{13,10,508},{14,10,163},{14,10,272},{14,10,277},{14,10,370},{15,10,95},{ 15,10,138},{15,10,167},{17,10,38},{148,10,96},{132,0,757},{134,0,1263},{4,0,820} ,{134,10,1759},{133,0,722},{136,11,816},{138,10,372},{145,10,16},{134,0,1039},{4 ,0,991},{134,0,2028},{133,10,258},{7,0,1875},{139,0,124},{6,11,559},{6,11,1691}, {135,11,586},{5,0,324},{7,0,881},{8,10,134},{9,10,788},{140,10,438},{7,11,1823}, {139,11,693},{6,0,1348},{134,0,1545},{134,0,911},{132,0,954},{8,0,329},{8,0,414} ,{7,10,1948},{135,10,2004},{5,0,517},{6,10,439},{7,10,780},{135,10,1040},{132,0, 816},{5,10,1},{6,10,81},{138,10,520},{9,0,713},{10,0,222},{5,10,482},{8,10,98},{ 10,10,700},{10,10,822},{11,10,302},{11,10,778},{12,10,50},{12,10,127},{12,10,396 },{13,10,62},{13,10,328},{14,10,122},{147,10,72},{137,0,33},{5,10,2},{7,10,1494} ,{136,10,589},{6,10,512},{7,10,797},{8,10,253},{9,10,77},{10,10,1},{10,11,108},{ 10,10,129},{10,10,225},{11,11,116},{11,10,118},{11,10,226},{11,10,251},{11,10, 430},{11,10,701},{11,10,974},{11,10,982},{12,10,64},{12,10,260},{12,10,488},{140 ,10,690},{134,11,456},{133,11,925},{5,0,150},{7,0,106},{7,0,774},{8,0,603},{9,0, 593},{9,0,634},{10,0,44},{10,0,173},{11,0,462},{11,0,515},{13,0,216},{13,0,288}, {142,0,400},{137,10,347},{5,0,748},{134,0,553},{12,0,108},{141,0,291},{7,0,420}, {4,10,12},{7,10,522},{7,10,809},{8,10,797},{141,10,88},{6,11,193},{7,11,240},{7, 11,1682},{10,11,51},{10,11,640},{11,11,410},{13,11,82},{14,11,247},{14,11,331},{ 142,11,377},{133,10,528},{135,0,1777},{4,0,493},{144,0,55},{136,11,633},{139,0, 81},{6,0,980},{136,0,321},{148,10,109},{5,10,266},{9,10,290},{9,10,364},{10,10, 293},{11,10,606},{142,10,45},{6,0,568},{7,0,112},{7,0,1804},{8,0,362},{8,0,410}, {8,0,830},{9,0,514},{11,0,649},{142,0,157},{4,0,74},{6,0,510},{6,10,594},{9,10, 121},{10,10,49},{10,10,412},{139,10,834},{134,0,838},{136,10,748},{132,10,466},{ 132,0,625},{135,11,1443},{4,11,237},{135,11,514},{9,10,378},{141,10,162},{6,0,16 },{6,0,158},{7,0,43},{7,0,129},{7,0,181},{8,0,276},{8,0,377},{10,0,523},{11,0, 816},{12,0,455},{13,0,303},{142,0,135},{135,0,281},{4,0,1},{7,0,1143},{7,0,1463} ,{8,0,61},{9,0,207},{9,0,390},{9,0,467},{139,0,836},{6,11,392},{7,11,65},{135,11 ,2019},{132,10,667},{4,0,723},{5,0,895},{7,0,1031},{8,0,199},{8,0,340},{9,0,153} ,{9,0,215},{10,0,21},{10,0,59},{10,0,80},{10,0,224},{10,0,838},{11,0,229},{11,0, 652},{12,0,192},{13,0,146},{142,0,91},{132,0,295},{137,0,51},{9,11,222},{10,11, 43},{139,11,900},{5,0,309},{140,0,211},{5,0,125},{8,0,77},{138,0,15},{136,11,604 },{138,0,789},{5,0,173},{4,10,39},{7,10,1843},{8,10,407},{11,10,144},{140,10,523 },{138,11,265},{133,0,439},{132,10,510},{7,0,648},{7,0,874},{11,0,164},{12,0,76} ,{18,0,9},{7,10,1980},{10,10,487},{138,10,809},{12,0,111},{14,0,294},{19,0,45},{ 13,10,260},{146,10,63},{133,11,549},{134,10,570},{4,0,8},{7,0,1152},{7,0,1153},{ 7,0,1715},{9,0,374},{10,0,478},{139,0,648},{135,0,1099},{5,0,575},{6,0,354},{135 ,0,701},{7,11,36},{8,11,201},{136,11,605},{4,10,787},{136,11,156},{6,0,518},{149 ,11,13},{140,11,224},{134,0,702},{132,10,516},{5,11,724},{10,11,305},{11,11,151} ,{12,11,33},{12,11,121},{12,11,381},{17,11,3},{17,11,27},{17,11,78},{18,11,18},{ 19,11,54},{149,11,5},{8,0,87},{4,11,523},{5,11,638},{11,10,887},{14,10,365},{142 ,10,375},{138,0,438},{136,10,821},{135,11,1908},{6,11,242},{7,11,227},{7,11,1581 },{8,11,104},{9,11,113},{9,11,220},{9,11,427},{10,11,74},{10,11,239},{11,11,579} ,{11,11,1023},{13,11,4},{13,11,204},{13,11,316},{18,11,95},{148,11,86},{4,0,69}, {5,0,122},{5,0,849},{6,0,1633},{9,0,656},{138,0,464},{7,0,1802},{4,10,10},{139, 10,786},{135,11,861},{139,0,499},{7,0,476},{7,0,1592},{138,0,87},{133,10,684},{4 ,0,840},{134,10,27},{142,0,283},{6,0,1620},{7,11,1328},{136,11,494},{5,0,859},{7 ,0,1160},{8,0,107},{9,0,291},{9,0,439},{10,0,663},{11,0,609},{140,0,197},{7,11, 1306},{8,11,505},{9,11,482},{10,11,126},{11,11,225},{12,11,347},{12,11,449},{13, 11,19},{142,11,218},{5,11,268},{10,11,764},{12,11,120},{13,11,39},{145,11,127},{ 145,10,56},{7,11,1672},{10,11,472},{11,11,189},{143,11,51},{6,10,342},{6,10,496} ,{8,10,275},{137,10,206},{133,0,600},{4,0,117},{6,0,372},{7,0,1905},{142,0,323}, {4,10,909},{5,10,940},{135,11,1471},{132,10,891},{4,0,722},{139,0,471},{4,11,384 },{135,11,1022},{132,10,687},{9,0,5},{12,0,216},{12,0,294},{12,0,298},{12,0,400} ,{12,0,518},{13,0,229},{143,0,139},{135,11,1703},{7,11,1602},{10,11,698},{12,11, 212},{141,11,307},{6,10,41},{141,10,160},{135,11,1077},{9,11,159},{11,11,28},{ 140,11,603},{4,0,514},{7,0,1304},{138,0,477},{134,0,1774},{9,0,88},{139,0,270},{ 5,0,12},{7,0,375},{9,0,438},{134,10,1718},{132,11,515},{136,10,778},{8,11,632},{ 8,11,697},{137,11,854},{6,0,362},{6,0,997},{146,0,51},{7,0,816},{7,0,1241},{9,0, 283},{9,0,520},{10,0,213},{10,0,307},{10,0,463},{10,0,671},{10,0,746},{11,0,401} ,{11,0,794},{12,0,517},{18,0,107},{147,0,115},{133,10,115},{150,11,28},{4,11,136 },{133,11,551},{142,10,314},{132,0,258},{6,0,22},{7,0,903},{7,0,1963},{8,0,639}, {138,0,577},{5,0,681},{8,0,782},{13,0,130},{17,0,84},{5,10,193},{140,10,178},{9, 11,17},{138,11,291},{7,11,1287},{9,11,44},{10,11,552},{10,11,642},{11,11,839},{ 12,11,274},{12,11,275},{12,11,372},{13,11,91},{142,11,125},{135,10,174},{4,0,664 },{5,0,804},{139,0,1013},{134,0,942},{6,0,1349},{6,0,1353},{6,0,1450},{7,11,1518 },{139,11,694},{11,0,356},{4,10,122},{5,10,796},{5,10,952},{6,10,1660},{6,10, 1671},{8,10,567},{9,10,687},{9,10,742},{10,10,686},{11,10,682},{140,10,281},{5,0 ,32},{6,11,147},{7,11,886},{9,11,753},{138,11,268},{5,10,179},{7,10,1095},{135, 10,1213},{4,10,66},{7,10,722},{135,10,904},{135,10,352},{9,11,245},{138,11,137}, {4,0,289},{7,0,629},{7,0,1698},{7,0,1711},{12,0,215},{133,11,414},{6,0,1975},{ 135,11,1762},{6,0,450},{136,0,109},{141,10,35},{134,11,599},{136,0,705},{133,0, 664},{134,11,1749},{11,11,402},{12,11,109},{12,11,431},{13,11,179},{13,11,206},{ 14,11,175},{14,11,217},{16,11,3},{148,11,53},{135,0,1238},{134,11,1627},{132,11, 488},{13,0,318},{10,10,592},{10,10,753},{12,10,317},{12,10,355},{12,10,465},{12, 10,469},{12,10,560},{140,10,578},{133,10,564},{132,11,83},{140,11,676},{6,0,1872 },{6,0,1906},{6,0,1907},{9,0,934},{9,0,956},{9,0,960},{9,0,996},{12,0,794},{12,0 ,876},{12,0,880},{12,0,918},{15,0,230},{18,0,234},{18,0,238},{21,0,38},{149,0,62 },{134,10,556},{134,11,278},{137,0,103},{7,10,544},{8,10,719},{138,10,61},{4,10, 5},{5,10,498},{8,10,637},{137,10,521},{7,0,777},{12,0,229},{12,0,239},{15,0,12}, {12,11,229},{12,11,239},{143,11,12},{6,0,26},{7,11,388},{7,11,644},{139,11,781}, {7,11,229},{8,11,59},{9,11,190},{9,11,257},{10,11,378},{140,11,191},{133,10,927} ,{135,10,1441},{4,10,893},{5,10,780},{133,10,893},{4,0,414},{5,0,467},{9,0,654}, {10,0,451},{12,0,59},{141,0,375},{142,0,173},{135,0,17},{7,0,1350},{133,10,238}, {135,0,955},{4,0,960},{10,0,887},{12,0,753},{18,0,161},{18,0,162},{152,0,19},{ 136,11,344},{6,10,1729},{137,11,288},{132,11,660},{4,0,217},{5,0,710},{7,0,760}, {7,0,1926},{9,0,428},{9,0,708},{10,0,254},{10,0,296},{10,0,720},{11,0,109},{11,0 ,255},{12,0,165},{12,0,315},{13,0,107},{13,0,203},{14,0,54},{14,0,99},{14,0,114} ,{14,0,388},{16,0,85},{17,0,9},{17,0,33},{20,0,25},{20,0,28},{20,0,29},{21,0,9}, {21,0,10},{21,0,34},{22,0,17},{4,10,60},{7,10,1800},{8,10,314},{9,10,700},{139, 10,487},{7,11,1035},{138,11,737},{7,11,690},{9,11,217},{9,11,587},{140,11,521},{ 6,0,919},{7,11,706},{7,11,1058},{138,11,538},{7,10,1853},{138,10,437},{136,10, 419},{6,0,280},{10,0,502},{11,0,344},{140,0,38},{5,0,45},{7,0,1161},{11,0,448},{ 11,0,880},{13,0,139},{13,0,407},{15,0,16},{17,0,95},{18,0,66},{18,0,88},{18,0, 123},{149,0,7},{11,11,92},{11,11,196},{11,11,409},{11,11,450},{11,11,666},{11,11 ,777},{12,11,262},{13,11,385},{13,11,393},{15,11,115},{16,11,45},{145,11,82},{ 136,0,777},{134,11,1744},{4,0,410},{7,0,521},{133,10,828},{134,0,673},{7,0,1110} ,{7,0,1778},{7,10,176},{135,10,178},{5,10,806},{7,11,268},{7,10,1976},{136,11, 569},{4,11,733},{9,11,194},{10,11,92},{11,11,198},{12,11,84},{12,11,87},{13,11, 128},{144,11,74},{5,0,341},{7,0,1129},{11,0,414},{4,10,51},{6,10,4},{7,10,591},{ 7,10,849},{7,10,951},{7,10,1613},{7,10,1760},{7,10,1988},{9,10,434},{10,10,754}, {11,10,25},{139,10,37},{133,10,902},{135,10,928},{135,0,787},{132,0,436},{134,10 ,270},{7,0,1587},{135,0,1707},{6,0,377},{7,0,1025},{9,0,613},{145,0,104},{7,11, 982},{7,11,1361},{10,11,32},{143,11,56},{139,0,96},{132,0,451},{132,10,416},{142 ,10,372},{5,10,152},{5,10,197},{7,11,306},{7,10,340},{7,10,867},{10,10,548},{10, 10,581},{11,10,6},{12,10,3},{12,10,19},{14,10,110},{142,10,289},{134,0,680},{134 ,11,609},{7,0,483},{7,10,190},{8,10,28},{8,10,141},{8,10,444},{8,10,811},{9,10, 468},{11,10,334},{12,10,24},{12,10,386},{140,10,576},{10,0,916},{133,10,757},{5, 10,721},{135,10,1553},{133,11,178},{134,0,937},{132,10,898},{133,0,739},{147,0, 82},{135,0,663},{146,0,128},{5,10,277},{141,10,247},{134,0,1087},{132,10,435},{6 ,11,381},{7,11,645},{7,11,694},{136,11,546},{7,0,503},{135,0,1885},{6,0,1965},{8 ,0,925},{138,0,955},{4,0,113},{5,0,163},{5,0,735},{7,0,1009},{9,0,9},{9,0,771},{ 12,0,90},{13,0,138},{13,0,410},{143,0,128},{4,0,324},{138,0,104},{7,0,460},{5,10 ,265},{134,10,212},{133,11,105},{7,11,261},{7,11,1107},{7,11,1115},{7,11,1354},{ 7,11,1588},{7,11,1705},{7,11,1902},{9,11,465},{10,11,248},{10,11,349},{10,11,647 },{11,11,527},{11,11,660},{11,11,669},{12,11,529},{141,11,305},{5,11,438},{9,11, 694},{12,11,627},{141,11,210},{152,11,11},{4,0,935},{133,0,823},{132,10,702},{5, 0,269},{7,0,434},{7,0,891},{8,0,339},{9,0,702},{11,0,594},{11,0,718},{17,0,100}, {5,10,808},{135,10,2045},{7,0,1014},{9,0,485},{141,0,264},{134,0,1713},{7,0,1810 },{11,0,866},{12,0,103},{13,0,495},{140,11,233},{4,0,423},{10,0,949},{138,0,1013 },{135,0,900},{8,11,25},{138,11,826},{5,10,166},{8,10,739},{140,10,511},{134,0, 2018},{7,11,1270},{139,11,612},{4,10,119},{5,10,170},{5,10,447},{7,10,1708},{7, 10,1889},{9,10,357},{9,10,719},{12,10,486},{140,10,596},{12,0,574},{140,11,574}, {132,11,308},{6,0,964},{6,0,1206},{134,0,1302},{4,10,450},{135,10,1158},{135,11, 150},{136,11,649},{14,0,213},{148,0,38},{9,11,45},{9,11,311},{141,11,42},{134,11 ,521},{7,10,1375},{7,10,1466},{138,10,331},{132,10,754},{5,11,339},{7,11,1442},{ 14,11,3},{15,11,41},{147,11,66},{136,11,378},{134,0,1022},{5,10,850},{136,10,799 },{142,0,143},{135,0,2029},{134,11,1628},{8,0,523},{150,0,34},{5,0,625},{135,0, 1617},{7,0,275},{7,10,238},{7,10,2033},{8,10,120},{8,10,188},{8,10,659},{9,10, 598},{10,10,466},{12,10,342},{12,10,588},{13,10,503},{14,10,246},{143,10,92},{7, 0,37},{8,0,425},{8,0,693},{9,0,720},{10,0,380},{10,0,638},{11,0,273},{11,0,473}, {12,0,61},{143,0,43},{135,11,829},{135,0,1943},{132,0,765},{5,11,486},{135,11, 1349},{7,11,1635},{8,11,17},{10,11,217},{138,11,295},{4,10,201},{7,10,1744},{8, 10,602},{11,10,247},{11,10,826},{145,10,65},{138,11,558},{11,0,551},{142,0,159}, {8,10,164},{146,10,62},{139,11,176},{132,0,168},{136,0,1010},{134,0,1994},{135,0 ,91},{138,0,532},{135,10,1243},{135,0,1884},{132,10,907},{5,10,100},{10,10,329}, {12,10,416},{149,10,29},{134,11,447},{132,10,176},{5,10,636},{5,10,998},{7,10,9} ,{7,10,1508},{8,10,26},{9,10,317},{9,10,358},{10,10,210},{10,10,292},{10,10,533} ,{11,10,555},{12,10,526},{12,10,607},{13,10,263},{13,10,459},{142,10,271},{4,11, 609},{135,11,756},{6,0,15},{7,0,70},{10,0,240},{147,0,93},{4,11,930},{133,11,947 },{134,0,1227},{134,0,1534},{133,11,939},{133,11,962},{5,11,651},{8,11,170},{9, 11,61},{9,11,63},{10,11,23},{10,11,37},{10,11,834},{11,11,4},{11,11,187},{11,11, 281},{11,11,503},{11,11,677},{12,11,96},{12,11,130},{12,11,244},{14,11,5},{14,11 ,40},{14,11,162},{14,11,202},{146,11,133},{4,11,406},{5,11,579},{12,11,492},{150 ,11,15},{139,0,392},{6,10,610},{10,10,127},{141,10,27},{7,0,655},{7,0,1844},{136 ,10,119},{4,0,145},{6,0,176},{7,0,395},{137,0,562},{132,0,501},{140,11,145},{136 ,0,1019},{134,0,509},{139,0,267},{6,11,17},{7,11,16},{7,11,1001},{7,11,1982},{9, 11,886},{10,11,489},{10,11,800},{11,11,782},{12,11,320},{13,11,467},{14,11,145}, {14,11,387},{143,11,119},{145,11,17},{6,0,1099},{133,11,458},{7,11,1983},{8,11,0 },{8,11,171},{9,11,120},{9,11,732},{10,11,473},{11,11,656},{11,11,998},{18,11,0} ,{18,11,2},{147,11,21},{12,11,427},{146,11,38},{10,0,948},{138,0,968},{7,10,126} ,{136,10,84},{136,10,790},{4,0,114},{9,0,492},{13,0,462},{142,0,215},{6,10,64},{ 12,10,377},{141,10,309},{4,0,77},{5,0,361},{6,0,139},{6,0,401},{6,0,404},{7,0, 413},{7,0,715},{7,0,1716},{11,0,279},{12,0,179},{12,0,258},{13,0,244},{142,0,358 },{134,0,1717},{7,0,772},{7,0,1061},{7,0,1647},{8,0,82},{11,0,250},{11,0,607},{ 12,0,311},{12,0,420},{13,0,184},{13,0,367},{7,10,1104},{11,10,269},{11,10,539},{ 11,10,627},{11,10,706},{11,10,975},{12,10,248},{12,10,434},{12,10,600},{12,10, 622},{13,10,297},{13,10,485},{14,10,69},{14,10,409},{143,10,108},{135,0,724},{4, 11,512},{4,11,519},{133,11,342},{134,0,1133},{145,11,29},{11,10,977},{141,10,507 },{6,0,841},{6,0,1042},{6,0,1194},{10,0,993},{140,0,1021},{6,11,31},{7,11,491},{ 7,11,530},{8,11,592},{9,10,34},{11,11,53},{11,10,484},{11,11,779},{12,11,167},{ 12,11,411},{14,11,14},{14,11,136},{15,11,72},{16,11,17},{144,11,72},{4,0,1021},{ 6,0,2037},{133,11,907},{7,0,373},{8,0,335},{8,0,596},{9,0,488},{6,10,1700},{7,10 ,293},{7,10,382},{7,10,1026},{7,10,1087},{7,10,2027},{8,10,252},{8,10,727},{8,10 ,729},{9,10,30},{9,10,199},{9,10,231},{9,10,251},{9,10,334},{9,10,361},{9,10,712 },{10,10,55},{10,10,60},{10,10,232},{10,10,332},{10,10,384},{10,10,396},{10,10, 504},{10,10,542},{10,10,652},{11,10,20},{11,10,48},{11,10,207},{11,10,291},{11, 10,298},{11,10,342},{11,10,365},{11,10,394},{11,10,620},{11,10,705},{11,10,1017} ,{12,10,123},{12,10,340},{12,10,406},{12,10,643},{13,10,61},{13,10,269},{13,10, 311},{13,10,319},{13,10,486},{14,10,234},{15,10,62},{15,10,85},{16,10,71},{18,10 ,119},{148,10,105},{150,0,37},{4,11,208},{5,11,106},{6,11,531},{8,11,408},{9,11, 188},{138,11,572},{132,0,564},{6,0,513},{135,0,1052},{132,0,825},{9,0,899},{140, 11,441},{134,0,778},{133,11,379},{7,0,1417},{12,0,382},{17,0,48},{152,0,12},{132 ,11,241},{7,0,1116},{6,10,379},{7,10,270},{8,10,176},{8,10,183},{9,10,432},{9,10 ,661},{12,10,247},{12,10,617},{146,10,125},{5,10,792},{133,10,900},{6,0,545},{7, 0,565},{7,0,1669},{10,0,114},{11,0,642},{140,0,618},{133,0,5},{138,11,7},{132,11 ,259},{135,0,192},{134,0,701},{136,0,763},{135,10,1979},{4,10,901},{133,10,776}, {10,0,755},{147,0,29},{133,0,759},{4,11,173},{5,11,312},{5,11,512},{135,11,1285} ,{7,11,1603},{7,11,1691},{9,11,464},{11,11,195},{12,11,279},{12,11,448},{14,11, 11},{147,11,102},{7,0,370},{7,0,1007},{7,0,1177},{135,0,1565},{135,0,1237},{4,0, 87},{5,0,250},{141,0,298},{4,11,452},{5,11,583},{5,11,817},{6,11,433},{7,11,593} ,{7,11,720},{7,11,1378},{8,11,161},{9,11,284},{10,11,313},{139,11,886},{4,11,547 },{135,11,1409},{136,11,722},{4,10,37},{5,10,334},{135,10,1253},{132,10,508},{12 ,0,107},{146,0,31},{8,11,420},{139,11,193},{135,0,814},{135,11,409},{140,0,991}, {4,0,57},{7,0,1195},{7,0,1438},{7,0,1548},{7,0,1835},{7,0,1904},{9,0,757},{10,0, 604},{139,0,519},{132,0,540},{138,11,308},{132,10,533},{136,0,608},{144,11,65},{ 4,0,1014},{134,0,2029},{4,0,209},{7,0,902},{5,11,1002},{136,11,745},{134,0,2030} ,{6,0,303},{7,0,335},{7,0,1437},{7,0,1668},{8,0,553},{8,0,652},{8,0,656},{9,0, 558},{11,0,743},{149,0,18},{5,11,575},{6,11,354},{135,11,701},{4,11,239},{6,11, 477},{7,11,1607},{11,11,68},{139,11,617},{132,0,559},{8,0,527},{18,0,60},{147,0, 24},{133,10,920},{138,0,511},{133,0,1017},{133,0,675},{138,10,391},{11,0,156},{ 135,10,1952},{138,11,369},{132,11,367},{133,0,709},{6,0,698},{134,0,887},{142,10 ,126},{134,0,1745},{132,10,483},{13,11,299},{142,11,75},{133,0,714},{7,0,8},{136 ,0,206},{138,10,480},{4,11,694},{9,10,495},{146,10,104},{7,11,1248},{11,11,621}, {139,11,702},{140,11,687},{132,0,776},{139,10,1009},{135,0,1272},{134,0,1059},{8 ,10,653},{13,10,93},{147,10,14},{135,11,213},{136,0,406},{133,10,172},{132,0,947 },{8,0,175},{10,0,168},{138,0,573},{132,0,870},{6,0,1567},{151,11,28},{134,11, 472},{5,10,260},{136,11,132},{4,11,751},{11,11,390},{140,11,32},{4,11,409},{133, 11,78},{12,0,554},{6,11,473},{145,11,105},{133,0,784},{8,0,908},{136,11,306},{ 139,0,882},{6,0,358},{7,0,1393},{8,0,396},{10,0,263},{14,0,154},{16,0,48},{17,0, 8},{7,11,1759},{8,11,396},{10,11,263},{14,11,154},{16,11,48},{145,11,8},{13,11, 163},{13,11,180},{18,11,78},{148,11,35},{14,0,32},{18,0,85},{20,0,2},{152,0,16}, {7,0,228},{10,0,770},{8,10,167},{8,10,375},{9,10,82},{9,10,561},{138,10,620},{ 132,0,845},{9,0,14},{9,0,441},{10,0,306},{139,0,9},{11,0,966},{12,0,287},{13,0, 342},{13,0,402},{15,0,110},{15,0,163},{8,10,194},{136,10,756},{134,0,1578},{4,0, 967},{6,0,1820},{6,0,1847},{140,0,716},{136,0,594},{7,0,1428},{7,0,1640},{7,0, 1867},{9,0,169},{9,0,182},{9,0,367},{9,0,478},{9,0,506},{9,0,551},{9,0,557},{9,0 ,648},{9,0,697},{9,0,705},{9,0,725},{9,0,787},{9,0,794},{10,0,198},{10,0,214},{ 10,0,267},{10,0,275},{10,0,456},{10,0,551},{10,0,561},{10,0,613},{10,0,627},{10, 0,668},{10,0,675},{10,0,691},{10,0,695},{10,0,707},{10,0,715},{11,0,183},{11,0, 201},{11,0,244},{11,0,262},{11,0,352},{11,0,439},{11,0,493},{11,0,572},{11,0,591 },{11,0,608},{11,0,611},{11,0,646},{11,0,674},{11,0,711},{11,0,751},{11,0,761},{ 11,0,776},{11,0,785},{11,0,850},{11,0,853},{11,0,862},{11,0,865},{11,0,868},{11, 0,875},{11,0,898},{11,0,902},{11,0,903},{11,0,910},{11,0,932},{11,0,942},{11,0, 957},{11,0,967},{11,0,972},{12,0,148},{12,0,195},{12,0,220},{12,0,237},{12,0,318 },{12,0,339},{12,0,393},{12,0,445},{12,0,450},{12,0,474},{12,0,505},{12,0,509},{ 12,0,533},{12,0,591},{12,0,594},{12,0,597},{12,0,621},{12,0,633},{12,0,642},{13, 0,59},{13,0,60},{13,0,145},{13,0,239},{13,0,250},{13,0,329},{13,0,344},{13,0,365 },{13,0,372},{13,0,387},{13,0,403},{13,0,414},{13,0,456},{13,0,470},{13,0,478},{ 13,0,483},{13,0,489},{14,0,55},{14,0,57},{14,0,81},{14,0,90},{14,0,148},{14,0, 239},{14,0,266},{14,0,321},{14,0,326},{14,0,327},{14,0,330},{14,0,347},{14,0,355 },{14,0,401},{14,0,404},{14,0,411},{14,0,414},{14,0,416},{14,0,420},{15,0,61},{ 15,0,74},{15,0,87},{15,0,88},{15,0,94},{15,0,96},{15,0,116},{15,0,149},{15,0,154 },{16,0,50},{16,0,63},{16,0,73},{17,0,2},{17,0,66},{17,0,92},{17,0,103},{17,0, 112},{17,0,120},{18,0,50},{18,0,54},{18,0,82},{18,0,86},{18,0,90},{18,0,111},{18 ,0,115},{18,0,156},{19,0,40},{19,0,79},{20,0,78},{21,0,22},{135,11,883},{5,0,161 },{135,0,839},{4,0,782},{13,11,293},{142,11,56},{133,11,617},{139,11,50},{135,10 ,22},{145,0,64},{5,10,639},{7,10,1249},{139,10,896},{138,0,998},{135,11,2042},{4 ,11,546},{142,11,233},{6,0,1043},{134,0,1574},{134,0,1496},{4,10,102},{7,10,815} ,{7,10,1699},{139,10,964},{12,0,781},{142,0,461},{4,11,313},{133,11,577},{6,0, 639},{6,0,1114},{137,0,817},{8,11,184},{141,11,433},{7,0,1814},{135,11,935},{10, 0,997},{140,0,958},{4,0,812},{137,11,625},{132,10,899},{136,10,795},{5,11,886},{ 6,11,46},{6,11,1790},{7,11,14},{7,11,732},{7,11,1654},{8,11,95},{8,11,327},{8,11 ,616},{10,11,598},{10,11,769},{11,11,134},{11,11,747},{12,11,378},{142,11,97},{ 136,0,139},{6,10,52},{9,10,104},{9,10,559},{12,10,308},{147,10,87},{133,11,1021} ,{132,10,604},{132,10,301},{136,10,779},{7,0,643},{136,0,236},{132,11,153},{134, 0,1172},{147,10,32},{133,11,798},{6,0,1338},{132,11,587},{6,11,598},{7,11,42},{8 ,11,695},{10,11,212},{11,11,158},{14,11,196},{145,11,85},{135,10,508},{5,11,957} ,{5,11,1008},{135,11,249},{4,11,129},{135,11,465},{5,0,54},{7,11,470},{7,11,1057 },{7,11,1201},{9,11,755},{11,11,906},{140,11,527},{7,11,908},{146,11,7},{5,11, 148},{136,11,450},{144,11,1},{4,0,256},{135,0,1488},{9,0,351},{6,10,310},{7,10, 1849},{8,10,72},{8,10,272},{8,10,431},{9,10,12},{10,10,563},{10,10,630},{10,10, 796},{10,10,810},{11,10,367},{11,10,599},{11,10,686},{140,10,672},{6,0,1885},{6, 0,1898},{6,0,1899},{140,0,955},{4,0,714},{133,0,469},{6,0,1270},{134,0,1456},{ 132,0,744},{6,0,313},{7,10,537},{8,10,64},{9,10,127},{10,10,496},{12,10,510},{ 141,10,384},{4,11,217},{4,10,244},{5,11,710},{7,10,233},{7,11,1926},{9,11,428},{ 9,11,708},{10,11,254},{10,11,296},{10,11,720},{11,11,109},{11,11,255},{12,11,165 },{12,11,315},{13,11,107},{13,11,203},{14,11,54},{14,11,99},{14,11,114},{14,11, 388},{16,11,85},{17,11,9},{17,11,33},{20,11,25},{20,11,28},{20,11,29},{21,11,9}, {21,11,10},{21,11,34},{150,11,17},{138,0,402},{7,0,969},{146,0,55},{8,0,50},{137 ,0,624},{134,0,1355},{132,0,572},{134,10,1650},{10,10,702},{139,10,245},{10,0, 847},{142,0,445},{6,0,43},{7,0,38},{8,0,248},{138,0,513},{133,0,369},{137,10,338 },{133,0,766},{133,0,363},{133,10,896},{8,11,392},{11,11,54},{13,11,173},{13,11, 294},{148,11,7},{134,0,678},{7,11,1230},{136,11,531},{6,0,258},{140,0,409},{5,0, 249},{148,0,82},{7,10,1117},{136,10,539},{5,0,393},{6,0,378},{7,0,1981},{9,0,32} ,{9,0,591},{10,0,685},{10,0,741},{142,0,382},{133,0,788},{134,0,1281},{134,0, 1295},{7,0,1968},{141,0,509},{4,0,61},{5,0,58},{5,0,171},{5,0,683},{6,0,291},{6, 0,566},{7,0,1650},{11,0,523},{12,0,273},{12,0,303},{15,0,39},{143,0,111},{6,0, 706},{134,0,1283},{134,0,589},{135,11,1433},{133,11,435},{7,0,1059},{13,0,54},{5 ,10,4},{5,10,810},{6,10,13},{6,10,538},{6,10,1690},{6,10,1726},{7,10,1819},{8,10 ,148},{8,10,696},{8,10,791},{12,10,125},{143,10,9},{135,10,1268},{5,11,85},{6,11 ,419},{7,11,134},{7,11,305},{7,11,361},{7,11,1337},{8,11,71},{140,11,519},{137,0 ,824},{140,11,688},{5,11,691},{7,11,345},{7,10,1385},{9,11,94},{11,10,582},{11, 10,650},{11,10,901},{11,10,949},{12,11,169},{12,10,232},{12,10,236},{13,10,413}, {13,10,501},{146,10,116},{4,0,917},{133,0,1005},{7,0,1598},{5,11,183},{6,11,582} ,{9,11,344},{10,11,679},{140,11,435},{4,10,925},{5,10,803},{8,10,698},{138,10, 828},{132,0,919},{135,11,511},{139,10,992},{4,0,255},{5,0,302},{6,0,132},{7,0, 128},{7,0,283},{7,0,1299},{10,0,52},{10,0,514},{11,0,925},{13,0,92},{142,0,309}, {134,0,1369},{135,10,1847},{134,0,328},{7,11,1993},{136,11,684},{133,10,383},{ 137,0,173},{134,11,583},{134,0,1411},{19,0,65},{5,11,704},{8,11,357},{10,11,745} ,{14,11,426},{17,11,94},{147,11,57},{9,10,660},{138,10,347},{4,11,179},{5,11,198 },{133,11,697},{7,11,347},{7,11,971},{8,11,181},{138,11,711},{141,0,442},{11,0, 842},{11,0,924},{13,0,317},{13,0,370},{13,0,469},{13,0,471},{14,0,397},{18,0,69} ,{18,0,145},{7,10,572},{9,10,592},{11,10,680},{12,10,356},{140,10,550},{14,11,19 },{14,11,28},{144,11,29},{136,0,534},{4,11,243},{5,11,203},{7,11,19},{7,11,71},{ 7,11,113},{10,11,405},{11,11,357},{142,11,240},{6,0,210},{10,0,845},{138,0,862}, {7,11,1351},{9,11,581},{10,11,639},{11,11,453},{140,11,584},{7,11,1450},{139,11, 99},{10,0,892},{12,0,719},{144,0,105},{4,0,284},{6,0,223},{134,11,492},{5,11,134 },{6,11,408},{6,11,495},{135,11,1593},{136,0,529},{137,0,807},{4,0,218},{7,0,526 },{143,0,137},{6,0,1444},{142,11,4},{132,11,665},{4,0,270},{5,0,192},{6,0,332},{ 7,0,1322},{4,11,248},{7,11,137},{137,11,349},{140,0,661},{7,0,1517},{11,0,597},{ 14,0,76},{14,0,335},{20,0,33},{7,10,748},{139,10,700},{5,11,371},{135,11,563},{ 146,11,57},{133,10,127},{133,0,418},{4,11,374},{7,11,547},{7,11,1700},{7,11,1833 },{139,11,858},{6,10,198},{140,10,83},{7,11,1812},{13,11,259},{13,11,356},{14,11 ,242},{147,11,114},{7,0,379},{8,0,481},{9,0,377},{5,10,276},{6,10,55},{135,10, 1369},{138,11,286},{5,0,1003},{6,0,149},{6,10,1752},{136,10,726},{8,0,262},{9,0, 627},{10,0,18},{11,0,214},{11,0,404},{11,0,457},{11,0,780},{11,0,913},{13,0,401} ,{14,0,200},{6,11,1647},{7,11,1552},{7,11,2010},{9,11,494},{137,11,509},{135,0, 742},{136,0,304},{132,0,142},{133,10,764},{6,10,309},{7,10,331},{138,10,550},{ 135,10,1062},{6,11,123},{7,11,214},{7,10,986},{9,11,728},{10,11,157},{11,11,346} ,{11,11,662},{143,11,106},{135,10,1573},{7,0,925},{137,0,799},{4,0,471},{5,0,51} ,{6,0,602},{8,0,484},{138,0,195},{136,0,688},{132,0,697},{6,0,1169},{6,0,1241},{ 6,10,194},{7,10,133},{10,10,493},{10,10,570},{139,10,664},{140,0,751},{7,0,929}, {10,0,452},{11,0,878},{16,0,33},{5,10,24},{5,10,569},{6,10,3},{6,10,119},{6,10, 143},{6,10,440},{7,10,599},{7,10,1686},{7,10,1854},{8,10,424},{9,10,43},{9,10, 584},{9,10,760},{10,10,328},{11,10,159},{11,10,253},{12,10,487},{140,10,531},{4, 11,707},{13,11,106},{18,11,49},{147,11,41},{5,0,221},{5,11,588},{134,11,393},{ 134,0,1437},{6,11,211},{7,11,1690},{11,11,486},{140,11,369},{5,10,14},{5,10,892} ,{6,10,283},{7,10,234},{136,10,537},{4,0,988},{136,0,955},{135,0,1251},{4,10,126 },{8,10,635},{147,10,34},{4,10,316},{135,10,1561},{137,10,861},{4,10,64},{5,10, 352},{5,10,720},{6,10,368},{139,10,359},{134,0,192},{4,0,132},{5,0,69},{135,0, 1242},{7,10,1577},{10,10,304},{10,10,549},{12,10,365},{13,10,220},{13,10,240},{ 142,10,33},{4,0,111},{7,0,865},{134,11,219},{5,11,582},{6,11,1646},{7,11,99},{7, 11,1962},{7,11,1986},{8,11,515},{8,11,773},{9,11,23},{9,11,491},{12,11,620},{14, 11,52},{145,11,50},{132,0,767},{7,11,568},{148,11,21},{6,0,42},{7,0,1416},{7,0, 2005},{8,0,131},{8,0,466},{9,0,672},{13,0,252},{20,0,103},{133,11,851},{135,0, 1050},{6,10,175},{137,10,289},{5,10,432},{133,10,913},{6,0,44},{136,0,368},{135, 11,784},{132,0,570},{133,0,120},{139,10,595},{140,0,29},{6,0,227},{135,0,1589},{ 4,11,98},{7,11,1365},{9,11,422},{9,11,670},{10,11,775},{11,11,210},{13,11,26},{ 13,11,457},{141,11,476},{140,10,80},{5,10,931},{134,10,1698},{133,0,522},{134,0, 1120},{135,0,1529},{12,0,739},{14,0,448},{142,0,467},{11,10,526},{11,10,939},{ 141,10,290},{5,10,774},{6,10,1637},{6,10,1686},{134,10,1751},{6,0,1667},{135,0, 2036},{7,10,1167},{11,10,934},{13,10,391},{145,10,76},{137,11,147},{6,10,260},{7 ,10,1484},{11,11,821},{12,11,110},{12,11,153},{18,11,41},{150,11,19},{6,0,511},{ 12,0,132},{134,10,573},{5,0,568},{6,0,138},{135,0,1293},{132,0,1020},{8,0,258},{ 9,0,208},{137,0,359},{4,0,565},{8,0,23},{136,0,827},{134,0,344},{4,0,922},{5,0, 1023},{13,11,477},{14,11,120},{148,11,61},{134,0,240},{5,11,209},{6,11,30},{11, 11,56},{139,11,305},{6,0,171},{7,0,1002},{7,0,1324},{9,0,415},{14,0,230},{18,0, 68},{4,10,292},{4,10,736},{5,10,871},{6,10,1689},{7,10,1944},{137,10,580},{9,11, 635},{139,11,559},{4,11,150},{5,11,303},{134,11,327},{6,10,63},{135,10,920},{133 ,10,793},{8,11,192},{10,11,78},{10,11,555},{11,11,308},{13,11,359},{147,11,95},{ 135,11,786},{135,11,1712},{136,0,402},{6,0,754},{6,11,1638},{7,11,79},{7,11,496} ,{9,11,138},{10,11,336},{11,11,12},{12,11,412},{12,11,440},{142,11,305},{4,0,716 },{141,0,31},{133,0,982},{8,0,691},{8,0,731},{5,10,67},{6,10,62},{6,10,374},{135 ,10,1391},{9,10,790},{140,10,47},{139,11,556},{151,11,1},{7,11,204},{7,11,415},{ 8,11,42},{10,11,85},{11,11,33},{11,11,564},{12,11,571},{149,11,1},{8,0,888},{7, 11,610},{135,11,1501},{4,10,391},{135,10,1169},{5,0,847},{9,0,840},{138,0,803},{ 137,0,823},{134,0,785},{8,0,152},{9,0,53},{9,0,268},{9,0,901},{10,0,518},{10,0, 829},{11,0,188},{13,0,74},{14,0,46},{15,0,17},{15,0,33},{17,0,40},{18,0,36},{19, 0,20},{22,0,1},{152,0,2},{4,11,3},{5,11,247},{5,11,644},{7,11,744},{7,11,1207},{ 7,11,1225},{7,11,1909},{146,11,147},{136,0,532},{135,0,681},{132,10,271},{140,0, 314},{140,0,677},{4,0,684},{136,0,384},{5,11,285},{9,11,67},{13,11,473},{143,11, 82},{4,10,253},{5,10,544},{7,10,300},{137,10,340},{7,0,110},{7,0,447},{8,0,290}, {8,0,591},{9,0,382},{9,0,649},{11,0,71},{11,0,155},{11,0,313},{12,0,5},{13,0,325 },{142,0,287},{134,0,1818},{136,0,1007},{138,0,321},{7,0,360},{7,0,425},{9,0,66} ,{9,0,278},{138,0,644},{133,10,818},{5,0,385},{5,10,541},{6,10,94},{6,10,499},{7 ,10,230},{139,10,321},{4,10,920},{5,10,25},{5,10,790},{6,10,457},{7,10,853},{136 ,10,788},{4,0,900},{133,0,861},{5,0,254},{7,0,985},{136,0,73},{7,0,1959},{136,0, 683},{134,10,1765},{133,10,822},{132,10,634},{4,11,29},{6,11,532},{7,11,1628},{7 ,11,1648},{9,11,303},{9,11,350},{10,11,433},{11,11,97},{11,11,557},{11,11,745},{ 12,11,289},{12,11,335},{12,11,348},{12,11,606},{13,11,116},{13,11,233},{13,11, 466},{14,11,181},{14,11,209},{14,11,232},{14,11,236},{14,11,300},{16,11,41},{148 ,11,97},{19,0,86},{6,10,36},{7,10,658},{136,10,454},{135,11,1692},{132,0,725},{5 ,11,501},{7,11,1704},{9,11,553},{11,11,520},{12,11,557},{141,11,249},{134,0,196} ,{133,0,831},{136,0,723},{7,0,1897},{13,0,80},{13,0,437},{145,0,74},{4,0,992},{6 ,0,627},{136,0,994},{135,11,1294},{132,10,104},{5,0,848},{6,0,66},{136,0,764},{4 ,0,36},{7,0,1387},{10,0,205},{139,0,755},{6,0,1046},{134,0,1485},{134,0,950},{ 132,0,887},{14,0,450},{148,0,111},{7,0,620},{7,0,831},{9,10,542},{9,10,566},{138 ,10,728},{6,0,165},{138,0,388},{139,10,263},{4,0,719},{135,0,155},{138,10,468},{ 6,11,453},{144,11,36},{134,11,129},{5,0,533},{7,0,755},{138,0,780},{134,0,1465}, {4,0,353},{6,0,146},{6,0,1789},{7,0,427},{7,0,990},{7,0,1348},{9,0,665},{9,0,898 },{11,0,893},{142,0,212},{7,10,87},{142,10,288},{4,0,45},{135,0,1257},{12,0,7},{ 7,10,988},{7,10,1939},{9,10,64},{9,10,502},{12,10,34},{13,10,12},{13,10,234},{ 147,10,77},{4,0,607},{5,11,60},{6,11,504},{7,11,614},{7,11,1155},{140,11,0},{135 ,10,141},{8,11,198},{11,11,29},{140,11,534},{140,0,65},{136,0,816},{132,10,619}, {139,0,88},{5,10,246},{8,10,189},{9,10,355},{9,10,512},{10,10,124},{10,10,453},{ 11,10,143},{11,10,416},{11,10,859},{141,10,341},{4,11,379},{135,11,1397},{4,0, 600},{137,0,621},{133,0,367},{134,0,561},{6,0,559},{134,0,1691},{6,0,585},{134, 11,585},{135,11,1228},{4,11,118},{5,10,678},{6,11,274},{6,11,361},{7,11,75},{141 ,11,441},{135,11,1818},{137,11,841},{5,0,573},{6,0,287},{7,10,862},{7,10,1886},{ 138,10,179},{132,10,517},{140,11,693},{5,11,314},{6,11,221},{7,11,419},{10,11, 650},{11,11,396},{12,11,156},{13,11,369},{14,11,333},{145,11,47},{140,10,540},{ 136,10,667},{11,10,403},{146,10,83},{6,0,672},{133,10,761},{9,0,157},{10,10,131} ,{140,10,72},{7,0,714},{134,11,460},{134,0,456},{133,0,925},{5,11,682},{135,11, 1887},{136,11,510},{136,11,475},{133,11,1016},{9,0,19},{7,11,602},{8,11,179},{10 ,11,781},{140,11,126},{6,11,329},{138,11,111},{6,0,822},{134,0,1473},{144,11,86} ,{11,0,113},{139,11,113},{5,11,821},{134,11,1687},{133,10,449},{7,0,463},{17,0, 69},{136,10,103},{7,10,2028},{138,10,641},{6,0,193},{7,0,240},{7,0,1682},{10,0, 51},{10,0,640},{11,0,410},{13,0,82},{14,0,247},{14,0,331},{142,0,377},{6,0,471}, {11,0,411},{142,0,2},{5,11,71},{7,11,1407},{9,11,388},{9,11,704},{10,11,261},{10 ,11,619},{11,11,547},{11,11,619},{143,11,157},{136,0,633},{135,0,1148},{6,0,554} ,{7,0,1392},{12,0,129},{7,10,1274},{7,10,1386},{7,11,2008},{9,11,337},{10,11,517 },{146,10,87},{7,0,803},{8,0,542},{6,10,187},{7,10,1203},{8,10,380},{14,10,117}, {149,10,28},{6,10,297},{7,10,793},{139,10,938},{8,0,438},{11,0,363},{7,10,464},{ 11,10,105},{12,10,231},{14,10,386},{15,10,102},{148,10,75},{5,11,16},{6,11,86},{ 6,11,603},{7,11,292},{7,11,561},{8,11,257},{8,11,382},{9,11,721},{9,11,778},{11, 11,581},{140,11,466},{6,0,717},{4,11,486},{133,11,491},{132,0,875},{132,11,72},{ 6,11,265},{135,11,847},{4,0,237},{135,0,514},{6,0,392},{7,0,65},{135,0,2019},{ 140,11,261},{135,11,922},{137,11,404},{12,0,563},{14,0,101},{18,0,129},{7,10, 1010},{11,10,733},{11,10,759},{13,10,34},{146,10,45},{7,10,1656},{9,10,369},{10, 10,338},{10,10,490},{11,10,154},{11,10,545},{11,10,775},{13,10,77},{141,10,274}, {4,0,444},{10,0,146},{140,0,9},{139,11,163},{7,0,1260},{135,0,1790},{9,0,222},{ 10,0,43},{139,0,900},{137,11,234},{138,0,971},{137,0,761},{134,0,699},{136,11, 434},{6,0,1116},{7,0,1366},{5,10,20},{6,11,197},{6,10,298},{7,10,659},{8,11,205} ,{137,10,219},{132,11,490},{11,11,820},{150,11,51},{7,10,1440},{11,10,854},{11, 10,872},{11,10,921},{12,10,551},{13,10,472},{142,10,367},{140,11,13},{132,0,829} ,{12,0,242},{132,10,439},{136,10,669},{6,0,593},{6,11,452},{7,11,312},{138,11, 219},{4,11,333},{9,11,176},{12,11,353},{141,11,187},{7,0,36},{8,0,201},{136,0, 605},{140,0,224},{132,10,233},{134,0,1430},{134,0,1806},{4,0,523},{133,0,638},{6 ,0,1889},{9,0,958},{9,0,971},{9,0,976},{12,0,796},{12,0,799},{12,0,808},{12,0, 835},{12,0,836},{12,0,914},{12,0,946},{15,0,216},{15,0,232},{18,0,183},{18,0,187 },{18,0,194},{18,0,212},{18,0,232},{149,0,49},{132,10,482},{6,0,827},{134,0,1434 },{135,10,346},{134,0,2043},{6,0,242},{7,0,227},{7,0,1581},{8,0,104},{9,0,113},{ 9,0,220},{9,0,427},{10,0,136},{10,0,239},{11,0,579},{11,0,1023},{13,0,4},{13,0, 204},{13,0,316},{148,0,86},{134,11,1685},{7,0,148},{8,0,284},{141,0,63},{142,0, 10},{135,11,584},{134,0,1249},{7,0,861},{135,10,334},{5,10,795},{6,10,1741},{137 ,11,70},{132,0,807},{7,11,135},{8,11,7},{8,11,62},{9,11,243},{10,11,658},{10,11, 697},{11,11,456},{139,11,756},{9,11,395},{138,11,79},{137,11,108},{147,0,94},{ 136,0,494},{135,11,631},{135,10,622},{7,0,1510},{135,10,1750},{4,10,203},{135,10 ,1936},{7,11,406},{7,11,459},{8,11,606},{139,11,726},{7,0,1306},{8,0,505},{9,0, 482},{10,0,126},{11,0,225},{12,0,347},{12,0,449},{13,0,19},{14,0,218},{142,0,435 },{5,0,268},{10,0,764},{12,0,120},{13,0,39},{145,0,127},{142,11,68},{11,10,678}, {140,10,307},{12,11,268},{12,11,640},{142,11,119},{135,10,2044},{133,11,612},{4, 11,372},{7,11,482},{8,11,158},{9,11,602},{9,11,615},{10,11,245},{10,11,678},{10, 11,744},{11,11,248},{139,11,806},{7,10,311},{9,10,308},{140,10,255},{4,0,384},{ 135,0,1022},{5,11,854},{135,11,1991},{135,10,1266},{4,10,400},{5,10,267},{135,10 ,232},{135,0,1703},{9,0,159},{11,0,661},{140,0,603},{4,0,964},{14,0,438},{14,0, 444},{14,0,456},{22,0,60},{22,0,63},{9,11,106},{9,11,163},{9,11,296},{10,11,167} ,{10,11,172},{10,11,777},{139,11,16},{136,0,583},{132,0,515},{8,0,632},{8,0,697} ,{137,0,854},{5,11,195},{135,11,1685},{6,0,1123},{134,0,1365},{134,11,328},{7,11 ,1997},{8,11,730},{139,11,1006},{4,0,136},{133,0,551},{134,0,1782},{7,0,1287},{9 ,0,44},{10,0,552},{10,0,642},{11,0,839},{12,0,274},{12,0,275},{12,0,372},{13,0, 91},{142,0,125},{5,11,751},{11,11,797},{140,11,203},{133,0,732},{7,0,679},{8,0, 313},{4,10,100},{135,11,821},{10,0,361},{142,0,316},{134,0,595},{6,0,147},{7,0, 886},{9,0,753},{138,0,268},{5,10,362},{5,10,443},{6,10,318},{7,10,1019},{139,10, 623},{5,10,463},{136,10,296},{4,10,454},{5,11,950},{5,11,994},{134,11,351},{138, 0,137},{5,10,48},{5,10,404},{6,10,557},{7,10,458},{8,10,597},{10,10,455},{10,10, 606},{11,10,49},{11,10,548},{12,10,476},{13,10,18},{141,10,450},{133,0,414},{135 ,0,1762},{5,11,421},{135,11,47},{5,10,442},{135,10,1984},{134,0,599},{134,0,1749 },{134,0,1627},{4,0,488},{132,11,350},{137,11,751},{132,0,83},{140,0,676},{133, 11,967},{7,0,1639},{5,10,55},{140,10,161},{4,11,473},{7,11,623},{8,11,808},{9,11 ,871},{9,11,893},{11,11,38},{11,11,431},{12,11,112},{12,11,217},{12,11,243},{12, 11,562},{12,11,683},{13,11,141},{13,11,197},{13,11,227},{13,11,406},{13,11,487}, {14,11,156},{14,11,203},{14,11,224},{14,11,256},{18,11,58},{150,11,0},{133,10, 450},{7,11,736},{139,11,264},{134,0,278},{4,11,222},{7,11,286},{136,11,629},{135 ,10,869},{140,0,97},{144,0,14},{134,0,1085},{4,10,213},{7,10,223},{136,10,80},{7 ,0,388},{7,0,644},{139,0,781},{132,0,849},{7,0,229},{8,0,59},{9,0,190},{10,0,378 },{140,0,191},{7,10,381},{7,10,806},{7,10,820},{8,10,354},{8,10,437},{8,10,787}, {9,10,657},{10,10,58},{10,10,339},{10,10,749},{11,10,914},{12,10,162},{13,10,75} ,{14,10,106},{14,10,198},{14,10,320},{14,10,413},{146,10,43},{141,11,306},{136, 10,747},{134,0,1115},{16,0,94},{16,0,108},{136,11,146},{6,0,700},{6,0,817},{134, 0,1002},{133,10,692},{4,11,465},{135,11,1663},{134,10,191},{6,0,1414},{135,11, 913},{132,0,660},{7,0,1035},{138,0,737},{6,10,162},{7,10,1960},{136,10,831},{132 ,10,706},{7,0,690},{9,0,217},{9,0,587},{140,0,521},{138,10,426},{135,10,1235},{6 ,11,82},{7,11,138},{7,11,517},{9,11,673},{139,11,238},{138,0,272},{5,11,495},{7, 11,834},{9,11,733},{139,11,378},{134,0,1744},{132,0,1011},{7,11,828},{142,11,116 },{4,0,733},{9,0,194},{10,0,92},{11,0,198},{12,0,84},{13,0,128},{133,11,559},{10 ,0,57},{10,0,277},{6,11,21},{6,11,1737},{7,11,1444},{136,11,224},{4,10,204},{137 ,10,902},{136,10,833},{11,0,348},{12,0,99},{18,0,1},{18,0,11},{19,0,4},{7,10,366 },{9,10,287},{12,10,199},{12,10,556},{140,10,577},{6,0,1981},{136,0,936},{21,0, 33},{150,0,40},{5,11,519},{138,11,204},{5,10,356},{135,10,224},{134,0,775},{135, 0,306},{7,10,630},{9,10,567},{11,10,150},{11,10,444},{141,10,119},{5,0,979},{134 ,10,539},{133,0,611},{4,11,402},{135,11,1679},{5,0,178},{7,11,2},{8,11,323},{136 ,11,479},{5,11,59},{135,11,672},{4,0,1010},{6,0,1969},{138,11,237},{133,11,412}, {146,11,34},{7,11,1740},{146,11,48},{134,0,664},{139,10,814},{4,11,85},{135,11, 549},{133,11,94},{133,11,457},{132,0,390},{134,0,1510},{4,10,235},{135,10,255},{ 4,10,194},{5,10,584},{6,11,11},{6,10,384},{7,11,187},{7,10,583},{10,10,761},{11, 10,760},{139,10,851},{4,11,522},{139,11,802},{135,0,493},{10,11,776},{13,11,345} ,{142,11,425},{146,0,37},{4,11,52},{135,11,661},{134,0,724},{134,0,829},{133,11, 520},{133,10,562},{4,11,281},{5,11,38},{7,11,194},{7,11,668},{7,11,1893},{137,11 ,397},{5,10,191},{137,10,271},{7,0,1537},{14,0,96},{143,0,73},{5,0,473},{11,0, 168},{4,10,470},{6,10,153},{7,10,1503},{7,10,1923},{10,10,701},{11,10,132},{11, 10,227},{11,10,320},{11,10,436},{11,10,525},{11,10,855},{12,10,41},{12,10,286},{ 13,10,103},{13,10,284},{14,10,255},{14,10,262},{15,10,117},{143,10,127},{133,0, 105},{5,0,438},{9,0,694},{12,0,627},{141,0,210},{133,10,327},{6,10,552},{7,10, 1754},{137,10,604},{134,0,1256},{152,0,11},{5,11,448},{11,11,98},{139,11,524},{7 ,0,1626},{5,10,80},{6,10,405},{7,10,403},{7,10,1502},{8,10,456},{9,10,487},{9,10 ,853},{9,10,889},{10,10,309},{11,10,721},{11,10,994},{12,10,430},{13,10,165},{14 ,11,16},{146,11,44},{132,0,779},{8,0,25},{138,0,826},{4,10,453},{5,10,887},{6,10 ,535},{8,10,6},{8,10,543},{136,10,826},{137,11,461},{140,11,632},{132,0,308},{ 135,0,741},{132,0,671},{7,0,150},{8,0,649},{136,0,1020},{9,0,99},{6,11,336},{8, 11,552},{9,11,285},{10,11,99},{139,11,568},{134,0,521},{5,0,339},{14,0,3},{15,0, 41},{15,0,166},{147,0,66},{6,11,423},{7,11,665},{7,11,1210},{9,11,218},{141,11, 222},{6,0,543},{5,10,101},{5,11,256},{6,10,88},{7,10,1677},{9,10,100},{10,10,677 },{14,10,169},{14,10,302},{14,10,313},{15,10,48},{143,10,84},{4,10,310},{7,10, 708},{7,10,996},{9,10,795},{10,10,390},{10,10,733},{11,10,451},{12,10,249},{14, 10,115},{14,10,286},{143,10,100},{133,10,587},{13,11,417},{14,11,129},{143,11,15 },{134,0,1358},{136,11,554},{132,10,498},{7,10,217},{8,10,140},{138,10,610},{135 ,11,989},{135,11,634},{6,0,155},{140,0,234},{135,11,462},{132,11,618},{134,0, 1628},{132,0,766},{4,11,339},{5,10,905},{135,11,259},{135,0,829},{4,11,759},{141 ,11,169},{7,0,1445},{4,10,456},{7,10,358},{7,10,1637},{8,10,643},{139,10,483},{5 ,0,486},{135,0,1349},{5,11,688},{135,11,712},{7,0,1635},{8,0,17},{10,0,217},{10, 0,295},{12,0,2},{140,11,2},{138,0,558},{150,10,56},{4,11,278},{5,11,465},{135,11 ,1367},{136,11,482},{133,10,535},{6,0,1362},{6,0,1461},{10,11,274},{10,11,625},{ 139,11,530},{5,0,599},{5,11,336},{6,11,341},{6,11,478},{6,11,1763},{136,11,386}, {7,10,1748},{137,11,151},{134,0,1376},{133,10,539},{135,11,73},{135,11,1971},{ 139,11,283},{9,0,93},{139,0,474},{6,10,91},{135,10,435},{6,0,447},{5,11,396},{ 134,11,501},{4,10,16},{5,10,316},{5,10,842},{6,10,370},{6,10,1778},{8,10,166},{ 11,10,812},{12,10,206},{12,10,351},{14,10,418},{16,10,15},{16,10,34},{18,10,3},{ 19,10,3},{19,10,7},{20,10,4},{149,10,21},{7,0,577},{7,0,1432},{9,0,475},{9,0,505 },{9,0,526},{9,0,609},{9,0,689},{9,0,726},{9,0,735},{9,0,738},{10,0,556},{10,0, 674},{10,0,684},{11,0,89},{11,0,202},{11,0,272},{11,0,380},{11,0,415},{11,0,505} ,{11,0,537},{11,0,550},{11,0,562},{11,0,640},{11,0,667},{11,0,688},{11,0,847},{ 11,0,927},{11,0,930},{11,0,940},{12,0,144},{12,0,325},{12,0,329},{12,0,389},{12, 0,403},{12,0,451},{12,0,515},{12,0,604},{12,0,616},{12,0,626},{13,0,66},{13,0, 131},{13,0,167},{13,0,236},{13,0,368},{13,0,411},{13,0,434},{13,0,453},{13,0,461 },{13,0,474},{14,0,59},{14,0,60},{14,0,139},{14,0,152},{14,0,276},{14,0,353},{14 ,0,402},{15,0,28},{15,0,81},{15,0,123},{15,0,152},{18,0,136},{148,0,88},{4,11, 929},{133,11,799},{136,11,46},{142,0,307},{4,0,609},{7,0,756},{9,0,544},{11,0, 413},{144,0,25},{10,0,687},{7,10,619},{10,10,547},{11,10,122},{140,10,601},{4,0, 930},{133,0,947},{133,0,939},{142,0,21},{4,11,892},{133,11,770},{133,0,962},{5,0 ,651},{8,0,170},{9,0,61},{9,0,63},{10,0,23},{10,0,37},{10,0,834},{11,0,4},{11,0, 187},{11,0,281},{11,0,503},{11,0,677},{12,0,96},{12,0,130},{12,0,244},{14,0,5},{ 14,0,40},{14,0,162},{14,0,202},{146,0,133},{4,0,406},{5,0,579},{12,0,492},{150,0 ,15},{135,11,158},{135,0,597},{132,0,981},{132,10,888},{4,10,149},{138,10,368},{ 132,0,545},{4,10,154},{7,10,1134},{136,10,105},{135,11,2001},{134,0,1558},{4,10, 31},{6,10,429},{7,10,962},{9,10,458},{139,10,691},{132,10,312},{135,10,1642},{6, 0,17},{6,0,1304},{7,0,16},{7,0,1001},{9,0,886},{10,0,489},{10,0,800},{11,0,782}, {12,0,320},{13,0,467},{14,0,145},{14,0,387},{143,0,119},{135,0,1982},{17,0,17},{ 7,11,1461},{140,11,91},{4,10,236},{132,11,602},{138,0,907},{136,0,110},{7,0,272} ,{19,0,53},{5,10,836},{5,10,857},{134,10,1680},{5,0,458},{7,11,1218},{136,11,303 },{7,0,1983},{8,0,0},{8,0,171},{9,0,120},{9,0,732},{10,0,473},{11,0,656},{11,0, 998},{18,0,0},{18,0,2},{19,0,21},{10,10,68},{139,10,494},{137,11,662},{4,11,13}, {5,11,567},{7,11,1498},{9,11,124},{11,11,521},{140,11,405},{4,10,81},{139,10,867 },{135,11,1006},{7,11,800},{7,11,1783},{138,11,12},{9,0,295},{10,0,443},{5,10, 282},{8,10,650},{137,10,907},{132,11,735},{4,11,170},{4,10,775},{135,11,323},{6, 0,1844},{10,0,924},{11,11,844},{12,11,104},{140,11,625},{5,11,304},{7,11,1403},{ 140,11,498},{134,0,1232},{4,0,519},{10,0,70},{12,0,26},{14,0,17},{14,0,178},{15, 0,34},{149,0,12},{132,0,993},{4,11,148},{133,11,742},{6,0,31},{7,0,491},{7,0,530 },{8,0,592},{11,0,53},{11,0,779},{12,0,167},{12,0,411},{14,0,14},{14,0,136},{15, 0,72},{16,0,17},{144,0,72},{133,0,907},{134,0,733},{133,11,111},{4,10,71},{5,10, 376},{7,10,119},{138,10,665},{136,0,55},{8,0,430},{136,11,430},{4,0,208},{5,0, 106},{6,0,531},{8,0,408},{9,0,188},{138,0,572},{12,0,56},{11,10,827},{14,10,34}, {143,10,148},{134,0,1693},{133,11,444},{132,10,479},{140,0,441},{9,0,449},{10,0, 192},{138,0,740},{134,0,928},{4,0,241},{7,10,607},{136,10,99},{8,11,123},{15,11, 6},{144,11,7},{6,11,285},{8,11,654},{11,11,749},{12,11,190},{12,11,327},{13,11, 120},{13,11,121},{13,11,327},{15,11,47},{146,11,40},{4,10,41},{5,10,74},{7,10, 1627},{11,10,871},{140,10,619},{7,0,1525},{11,10,329},{11,10,965},{12,10,241},{ 14,10,354},{15,10,22},{148,10,63},{132,0,259},{135,11,183},{9,10,209},{137,10, 300},{5,11,937},{135,11,100},{133,10,98},{4,0,173},{5,0,312},{5,0,512},{135,0, 1285},{141,0,185},{7,0,1603},{7,0,1691},{9,0,464},{11,0,195},{12,0,279},{12,0, 448},{14,0,11},{147,0,102},{135,0,1113},{133,10,984},{4,0,452},{5,0,583},{135,0, 720},{4,0,547},{5,0,817},{6,0,433},{7,0,593},{7,0,1378},{8,0,161},{9,0,284},{10, 0,313},{139,0,886},{8,0,722},{4,10,182},{6,10,205},{135,10,220},{150,0,13},{4,10 ,42},{9,10,205},{9,10,786},{138,10,659},{6,0,289},{7,0,1670},{12,0,57},{151,0,4} ,{132,10,635},{14,0,43},{146,0,21},{139,10,533},{135,0,1694},{8,0,420},{139,0, 193},{135,0,409},{132,10,371},{4,10,272},{135,10,836},{5,10,825},{134,10,1640},{ 5,11,251},{5,11,956},{8,11,268},{9,11,214},{146,11,142},{138,0,308},{6,0,1863},{ 141,11,37},{137,10,879},{7,10,317},{135,10,569},{132,11,294},{134,0,790},{5,0, 1002},{136,0,745},{5,11,346},{5,11,711},{136,11,390},{135,0,289},{5,0,504},{11,0 ,68},{137,10,307},{4,0,239},{6,0,477},{7,0,1607},{139,0,617},{149,0,13},{133,0, 609},{133,11,624},{5,11,783},{7,11,1998},{135,11,2047},{133,10,525},{132,0,367}, {132,11,594},{6,0,528},{133,10,493},{4,10,174},{135,10,911},{8,10,417},{137,10, 782},{132,0,694},{7,0,548},{137,0,58},{4,10,32},{5,10,215},{6,10,269},{7,10,1782 },{7,10,1892},{10,10,16},{11,10,822},{11,10,954},{141,10,481},{140,0,687},{7,0, 1749},{136,10,477},{132,11,569},{133,10,308},{135,10,1088},{4,0,661},{138,0,1004 },{5,11,37},{6,11,39},{6,11,451},{7,11,218},{7,11,667},{7,11,1166},{7,11,1687},{ 8,11,662},{144,11,2},{9,0,445},{12,0,53},{13,0,492},{5,10,126},{8,10,297},{9,10, 366},{140,10,374},{7,10,1551},{139,10,361},{148,0,74},{134,11,508},{135,0,213},{ 132,10,175},{132,10,685},{6,0,760},{6,0,834},{134,0,1248},{7,11,453},{7,11,635}, {7,11,796},{8,11,331},{9,11,328},{9,11,330},{9,11,865},{10,11,119},{10,11,235},{ 11,11,111},{11,11,129},{11,11,240},{12,11,31},{12,11,66},{12,11,222},{12,11,269} ,{12,11,599},{12,11,689},{13,11,186},{13,11,364},{142,11,345},{7,0,1672},{139,0, 189},{133,10,797},{133,10,565},{6,0,1548},{6,11,98},{7,11,585},{135,11,702},{9,0 ,968},{15,0,192},{149,0,56},{4,10,252},{6,11,37},{7,11,299},{7,10,1068},{7,11, 1666},{8,11,195},{8,11,316},{9,11,178},{9,11,276},{9,11,339},{9,11,536},{10,11, 102},{10,11,362},{10,10,434},{10,11,785},{11,11,55},{11,11,149},{11,10,228},{11, 10,426},{11,11,773},{13,10,231},{13,11,416},{13,11,419},{14,11,38},{14,11,41},{ 14,11,210},{18,10,106},{148,10,87},{4,0,751},{11,0,390},{140,0,32},{4,0,409},{ 133,0,78},{11,11,458},{12,11,15},{140,11,432},{7,0,1602},{10,0,257},{10,0,698},{ 11,0,544},{11,0,585},{12,0,212},{13,0,307},{5,10,231},{7,10,601},{9,10,277},{9, 10,674},{10,10,178},{10,10,418},{10,10,509},{11,10,531},{12,10,113},{12,10,475}, {13,10,99},{142,10,428},{6,0,473},{145,0,105},{6,0,1949},{15,0,156},{133,11,645} ,{7,10,1591},{144,10,43},{135,0,1779},{135,10,1683},{4,11,290},{135,11,1356},{ 134,0,763},{6,11,70},{7,11,1292},{10,11,762},{139,11,288},{142,0,29},{140,11,428 },{7,0,883},{7,11,131},{7,11,422},{8,11,210},{140,11,573},{134,0,488},{4,10,399} ,{5,10,119},{5,10,494},{7,10,751},{137,10,556},{133,0,617},{132,11,936},{139,0, 50},{7,0,1518},{139,0,694},{137,0,785},{4,0,546},{135,0,2042},{7,11,716},{13,11, 97},{141,11,251},{132,11,653},{145,0,22},{134,0,1016},{4,0,313},{133,0,577},{136 ,11,657},{8,0,184},{141,0,433},{135,0,935},{6,0,720},{9,0,114},{146,11,80},{12,0 ,186},{12,0,292},{14,0,100},{18,0,70},{7,10,594},{7,10,851},{7,10,1858},{9,10, 411},{9,10,574},{9,10,666},{9,10,737},{10,10,346},{10,10,712},{11,10,246},{11,10 ,432},{11,10,517},{11,10,647},{11,10,679},{11,10,727},{12,10,304},{12,10,305},{ 12,10,323},{12,10,483},{12,10,572},{12,10,593},{12,10,602},{13,10,95},{13,10,101 },{13,10,171},{13,10,315},{13,10,378},{13,10,425},{13,10,475},{14,10,63},{14,10, 380},{14,10,384},{15,10,133},{18,10,112},{148,10,72},{135,10,1093},{135,11,1836} ,{132,10,679},{137,10,203},{11,0,402},{12,0,109},{12,0,431},{13,0,179},{13,0,206 },{14,0,217},{16,0,3},{148,0,53},{7,11,1368},{8,11,232},{8,11,361},{10,11,682},{ 138,11,742},{137,10,714},{5,0,886},{6,0,46},{6,0,1790},{7,0,14},{7,0,732},{7,0, 1654},{8,0,95},{8,0,327},{8,0,616},{9,0,892},{10,0,598},{10,0,769},{11,0,134},{ 11,0,747},{12,0,378},{14,0,97},{137,11,534},{4,0,969},{136,10,825},{137,11,27},{ 6,0,727},{142,11,12},{133,0,1021},{134,0,1190},{134,11,1657},{5,10,143},{5,10, 769},{6,10,1760},{7,10,682},{7,10,1992},{136,10,736},{132,0,153},{135,11,127},{ 133,0,798},{132,0,587},{6,0,598},{7,0,42},{8,0,695},{10,0,212},{11,0,158},{14,0, 196},{145,0,85},{133,10,860},{6,0,1929},{134,0,1933},{5,0,957},{5,0,1008},{9,0, 577},{12,0,141},{6,10,422},{7,10,0},{7,10,1544},{8,11,364},{11,10,990},{12,10, 453},{13,10,47},{141,10,266},{134,0,1319},{4,0,129},{135,0,465},{7,0,470},{7,0, 1057},{7,0,1201},{9,0,755},{11,0,906},{140,0,527},{7,0,908},{146,0,7},{5,0,148}, {136,0,450},{5,10,515},{137,10,131},{7,10,1605},{11,10,962},{146,10,139},{132,10 ,646},{134,0,1166},{4,10,396},{7,10,728},{9,10,117},{13,10,202},{148,10,51},{6, 10,121},{6,10,124},{6,10,357},{7,10,1138},{7,10,1295},{8,10,162},{139,10,655},{ 14,0,374},{142,11,374},{138,0,253},{139,0,1003},{5,11,909},{9,11,849},{138,11, 805},{133,10,237},{7,11,525},{7,11,1579},{8,11,497},{136,11,573},{137,0,46},{132 ,0,879},{134,0,806},{135,0,1868},{6,0,1837},{134,0,1846},{6,0,730},{134,0,881},{ 7,0,965},{7,0,1460},{7,0,1604},{7,11,193},{7,11,397},{7,11,1105},{8,11,124},{8, 11,619},{9,11,305},{10,11,264},{11,11,40},{12,11,349},{13,11,134},{13,11,295},{ 14,11,155},{15,11,120},{146,11,105},{136,0,506},{143,0,10},{4,11,262},{7,11,342} ,{7,10,571},{7,10,1877},{10,10,366},{141,11,23},{133,11,641},{10,0,22},{9,10,513 },{10,10,39},{12,10,122},{140,10,187},{135,11,1431},{150,11,49},{4,11,99},{6,11, 250},{6,11,346},{8,11,127},{138,11,81},{6,0,2014},{8,0,928},{10,0,960},{10,0,979 },{140,0,996},{134,0,296},{132,11,915},{5,11,75},{9,11,517},{10,11,470},{12,11, 155},{141,11,224},{137,10,873},{4,0,854},{140,11,18},{134,0,587},{7,10,107},{7, 10,838},{8,10,550},{138,10,401},{11,0,636},{15,0,145},{17,0,34},{19,0,50},{23,0, 20},{11,10,588},{11,10,864},{11,10,968},{143,10,160},{135,11,216},{7,0,982},{10, 0,32},{143,0,56},{133,10,768},{133,11,954},{6,11,304},{7,11,1114},{8,11,418},{10 ,11,345},{11,11,341},{11,11,675},{141,11,40},{9,11,410},{139,11,425},{136,0,941} ,{5,0,435},{132,10,894},{5,0,85},{6,0,419},{7,0,134},{7,0,305},{7,0,361},{7,0, 1337},{8,0,71},{140,0,519},{140,0,688},{135,0,740},{5,0,691},{7,0,345},{9,0,94}, {140,0,169},{5,0,183},{6,0,582},{10,0,679},{140,0,435},{134,11,14},{6,0,945},{ 135,0,511},{134,11,1708},{5,11,113},{6,11,243},{7,11,1865},{11,11,161},{16,11,37 },{145,11,99},{132,11,274},{137,0,539},{7,0,1993},{8,0,684},{134,10,272},{6,0, 659},{134,0,982},{4,10,9},{5,10,128},{7,10,368},{11,10,480},{148,10,3},{134,0, 583},{132,0,803},{133,0,704},{4,0,179},{5,0,198},{133,0,697},{7,0,347},{7,0,971} ,{8,0,181},{10,0,711},{135,11,166},{136,10,682},{4,10,2},{7,10,545},{7,10,894},{ 136,11,521},{135,0,481},{132,0,243},{5,0,203},{7,0,19},{7,0,71},{7,0,113},{10,0, 405},{11,0,357},{142,0,240},{5,11,725},{5,11,727},{135,11,1811},{6,0,826},{137, 11,304},{7,0,1450},{139,0,99},{133,11,654},{134,0,492},{5,0,134},{6,0,408},{6,0, 495},{7,0,1593},{6,11,273},{10,11,188},{13,11,377},{146,11,77},{9,10,769},{140, 10,185},{135,11,410},{142,0,4},{4,0,665},{134,11,1785},{4,0,248},{7,0,137},{137, 0,349},{5,10,530},{142,10,113},{7,0,1270},{139,0,612},{132,11,780},{5,0,371},{ 135,0,563},{135,0,826},{6,0,1535},{23,0,21},{151,0,23},{4,0,374},{7,0,547},{7,0, 1700},{7,0,1833},{139,0,858},{133,10,556},{7,11,612},{8,11,545},{8,11,568},{8,11 ,642},{9,11,717},{10,11,541},{10,11,763},{11,11,449},{12,11,489},{13,11,153},{13 ,11,296},{14,11,138},{14,11,392},{15,11,50},{16,11,6},{16,11,12},{148,11,9},{9,0 ,311},{141,0,42},{8,10,16},{140,10,568},{6,0,1968},{6,0,2027},{138,0,991},{6,0, 1647},{7,0,1552},{7,0,2010},{9,0,494},{137,0,509},{133,11,948},{6,10,186},{137, 10,426},{134,0,769},{134,0,642},{132,10,585},{6,0,123},{7,0,214},{9,0,728},{10,0 ,157},{11,0,346},{11,0,662},{143,0,106},{142,11,381},{135,0,1435},{4,11,532},{5, 11,706},{135,11,662},{5,11,837},{134,11,1651},{4,10,93},{5,10,252},{6,10,229},{7 ,10,291},{9,10,550},{139,10,644},{148,0,79},{137,10,749},{134,0,1425},{137,10, 162},{4,11,362},{7,11,52},{7,11,303},{140,11,166},{132,10,381},{4,11,330},{7,11, 933},{7,11,2012},{136,11,292},{135,11,767},{4,0,707},{5,0,588},{6,0,393},{13,0, 106},{18,0,49},{147,0,41},{6,0,211},{7,0,1690},{11,0,486},{140,0,369},{137,11, 883},{4,11,703},{135,11,207},{4,0,187},{5,0,184},{5,0,690},{7,0,1869},{10,0,756} ,{139,0,783},{132,11,571},{134,0,1382},{5,0,175},{6,10,77},{6,10,157},{7,10,974} ,{7,10,1301},{7,10,1339},{7,10,1490},{7,10,1873},{137,10,628},{134,0,1493},{5,11 ,873},{133,11,960},{134,0,1007},{12,11,93},{12,11,501},{13,11,362},{14,11,151},{ 15,11,40},{15,11,59},{16,11,46},{17,11,25},{18,11,14},{18,11,134},{19,11,25},{19 ,11,69},{20,11,16},{20,11,19},{20,11,66},{21,11,23},{21,11,25},{150,11,42},{11, 10,919},{141,10,409},{134,0,219},{5,0,582},{6,0,1646},{7,0,99},{7,0,1962},{7,0, 1986},{8,0,515},{8,0,773},{9,0,23},{9,0,491},{12,0,620},{142,0,93},{133,0,851},{ 5,11,33},{134,11,470},{135,11,1291},{134,0,1278},{135,11,1882},{135,10,1489},{ 132,0,1000},{138,0,982},{8,0,762},{8,0,812},{137,0,910},{6,11,47},{7,11,90},{7, 11,664},{7,11,830},{7,11,1380},{7,11,2025},{8,11,448},{136,11,828},{4,0,98},{4,0 ,940},{6,0,1819},{6,0,1834},{6,0,1841},{7,0,1365},{8,0,859},{8,0,897},{8,0,918}, {9,0,422},{9,0,670},{10,0,775},{10,0,894},{10,0,909},{10,0,910},{10,0,935},{11,0 ,210},{12,0,750},{12,0,755},{13,0,26},{13,0,457},{13,0,476},{16,0,100},{16,0,109 },{18,0,173},{18,0,175},{8,10,398},{9,10,681},{139,10,632},{9,11,417},{137,11, 493},{136,10,645},{138,0,906},{134,0,1730},{134,10,20},{133,11,1019},{134,0,1185 },{10,0,40},{136,10,769},{9,0,147},{134,11,208},{140,0,650},{5,0,209},{6,0,30},{ 11,0,56},{139,0,305},{132,0,553},{138,11,344},{6,11,68},{7,11,398},{7,11,448},{7 ,11,1629},{7,11,1813},{8,11,387},{8,11,442},{9,11,710},{10,11,282},{138,11,722}, {5,0,597},{14,0,20},{142,11,20},{135,0,1614},{135,10,1757},{4,0,150},{5,0,303},{ 6,0,327},{135,10,937},{16,0,49},{7,10,1652},{144,11,49},{8,0,192},{10,0,78},{141 ,0,359},{135,0,786},{143,0,134},{6,0,1638},{7,0,79},{7,0,496},{9,0,138},{10,0, 336},{11,0,12},{12,0,412},{12,0,440},{142,0,305},{136,11,491},{4,10,579},{5,10, 226},{5,10,323},{135,10,960},{7,0,204},{7,0,415},{8,0,42},{10,0,85},{139,0,564}, {132,0,614},{4,11,403},{5,11,441},{7,11,450},{11,11,101},{12,11,193},{141,11,430 },{135,11,1927},{135,11,1330},{4,0,3},{5,0,247},{5,0,644},{7,0,744},{7,0,1207},{ 7,0,1225},{7,0,1909},{146,0,147},{136,0,942},{4,0,1019},{134,0,2023},{5,11,679}, {133,10,973},{5,0,285},{9,0,67},{13,0,473},{143,0,82},{7,11,328},{137,11,326},{ 151,0,8},{6,10,135},{135,10,1176},{135,11,1128},{134,0,1309},{135,11,1796},{135, 10,314},{4,11,574},{7,11,350},{7,11,1024},{8,11,338},{9,11,677},{10,11,808},{139 ,11,508},{7,11,818},{17,11,14},{17,11,45},{18,11,75},{148,11,18},{146,10,4},{135 ,11,1081},{4,0,29},{6,0,532},{7,0,1628},{7,0,1648},{9,0,350},{10,0,433},{11,0,97 },{11,0,557},{11,0,745},{12,0,289},{12,0,335},{12,0,348},{12,0,606},{13,0,116},{ 13,0,233},{13,0,466},{14,0,181},{14,0,209},{14,0,232},{14,0,236},{14,0,300},{16, 0,41},{148,0,97},{7,0,318},{6,10,281},{8,10,282},{8,10,480},{8,10,499},{9,10,198 },{10,10,143},{10,10,169},{10,10,211},{10,10,417},{10,10,574},{11,10,147},{11,10 ,395},{12,10,75},{12,10,407},{12,10,608},{13,10,500},{142,10,251},{135,11,1676}, {135,11,2037},{135,0,1692},{5,0,501},{7,0,1704},{9,0,553},{11,0,520},{12,0,557}, {141,0,249},{6,0,1527},{14,0,324},{15,0,55},{15,0,80},{14,11,324},{15,11,55},{ 143,11,80},{135,10,1776},{8,0,988},{137,11,297},{132,10,419},{142,0,223},{139,11 ,234},{7,0,1123},{12,0,508},{14,0,102},{14,0,226},{144,0,57},{4,10,138},{7,10, 1012},{7,10,1280},{137,10,76},{7,0,1764},{5,10,29},{140,10,638},{134,0,2015},{ 134,0,1599},{138,11,56},{6,11,306},{7,11,1140},{7,11,1340},{8,11,133},{138,11, 449},{139,11,1011},{6,10,1710},{135,10,2038},{7,11,1763},{140,11,310},{6,0,129}, {4,10,17},{5,10,23},{7,10,995},{11,10,383},{11,10,437},{12,10,460},{140,10,532}, {5,11,329},{136,11,260},{133,10,862},{132,0,534},{6,0,811},{135,0,626},{132,11, 657},{4,0,25},{5,0,60},{6,0,504},{7,0,614},{7,0,1155},{12,0,0},{152,11,7},{7,0, 1248},{11,0,621},{139,0,702},{137,0,321},{8,10,70},{12,10,171},{141,10,272},{10, 10,233},{139,10,76},{4,0,379},{7,0,1397},{134,10,442},{5,11,66},{7,11,1896},{136 ,11,288},{134,11,1643},{134,10,1709},{4,11,21},{5,11,91},{5,11,570},{5,11,648},{ 5,11,750},{5,11,781},{6,11,54},{6,11,112},{6,11,402},{6,11,1732},{7,11,315},{7, 11,749},{7,11,1347},{7,11,1900},{9,11,78},{9,11,508},{10,11,611},{11,11,510},{11 ,11,728},{13,11,36},{14,11,39},{16,11,83},{17,11,124},{148,11,30},{4,0,118},{6,0 ,274},{6,0,361},{7,0,75},{141,0,441},{10,11,322},{10,11,719},{139,11,407},{147, 10,119},{12,11,549},{14,11,67},{147,11,60},{11,10,69},{12,10,105},{12,10,117},{ 13,10,213},{14,10,13},{14,10,62},{14,10,177},{14,10,421},{15,10,19},{146,10,141} ,{9,0,841},{137,10,309},{7,10,608},{7,10,976},{8,11,125},{8,11,369},{8,11,524},{ 9,10,146},{10,10,206},{10,11,486},{10,10,596},{11,11,13},{11,11,381},{11,11,736} ,{11,11,766},{11,11,845},{13,11,114},{13,10,218},{13,11,292},{14,11,47},{142,10, 153},{12,0,693},{135,11,759},{5,0,314},{6,0,221},{7,0,419},{10,0,650},{11,0,396} ,{12,0,156},{13,0,369},{14,0,333},{145,0,47},{6,11,1684},{6,11,1731},{7,11,356}, {7,11,1932},{8,11,54},{8,11,221},{9,11,225},{9,11,356},{10,11,77},{10,11,446},{ 10,11,731},{12,11,404},{141,11,491},{132,11,375},{4,10,518},{135,10,1136},{4,0, 913},{4,11,411},{11,11,643},{140,11,115},{4,11,80},{133,11,44},{8,10,689},{137, 10,863},{138,0,880},{4,10,18},{7,10,145},{7,10,444},{7,10,1278},{8,10,49},{8,10, 400},{9,10,71},{9,10,250},{10,10,459},{12,10,160},{144,10,24},{136,0,475},{5,0, 1016},{5,11,299},{135,11,1083},{7,0,602},{8,0,179},{10,0,781},{140,0,126},{6,0, 329},{138,0,111},{135,0,1864},{4,11,219},{7,11,1761},{137,11,86},{6,0,1888},{6,0 ,1892},{6,0,1901},{6,0,1904},{9,0,953},{9,0,985},{9,0,991},{9,0,1001},{12,0,818} ,{12,0,846},{12,0,847},{12,0,861},{12,0,862},{12,0,873},{12,0,875},{12,0,877},{ 12,0,879},{12,0,881},{12,0,884},{12,0,903},{12,0,915},{12,0,926},{12,0,939},{15, 0,182},{15,0,219},{15,0,255},{18,0,191},{18,0,209},{18,0,211},{149,0,41},{5,11, 328},{135,11,918},{137,0,780},{12,0,82},{143,0,36},{133,10,1010},{5,0,821},{134, 0,1687},{133,11,514},{132,0,956},{134,0,1180},{10,0,112},{5,10,87},{7,10,313},{7 ,10,1103},{10,10,582},{11,10,389},{11,10,813},{12,10,385},{13,10,286},{14,10,124 },{146,10,108},{5,0,71},{7,0,1407},{9,0,704},{10,0,261},{10,0,619},{11,0,547},{ 11,0,619},{143,0,157},{4,0,531},{5,0,455},{5,11,301},{6,11,571},{14,11,49},{146, 11,102},{132,10,267},{6,0,385},{7,0,2008},{9,0,337},{138,0,517},{133,11,726},{ 133,11,364},{4,11,76},{7,11,1550},{9,11,306},{9,11,430},{9,11,663},{10,11,683},{ 11,11,427},{11,11,753},{12,11,334},{12,11,442},{14,11,258},{14,11,366},{143,11, 131},{6,0,1865},{6,0,1879},{6,0,1881},{6,0,1894},{6,0,1908},{9,0,915},{9,0,926}, {9,0,940},{9,0,943},{9,0,966},{9,0,980},{9,0,989},{9,0,1005},{9,0,1010},{12,0, 813},{12,0,817},{12,0,840},{12,0,843},{12,0,855},{12,0,864},{12,0,871},{12,0,872 },{12,0,899},{12,0,905},{12,0,924},{15,0,171},{15,0,181},{15,0,224},{15,0,235},{ 15,0,251},{146,0,184},{137,11,52},{5,0,16},{6,0,86},{6,0,603},{7,0,292},{7,0,561 },{8,0,257},{8,0,382},{9,0,721},{9,0,778},{11,0,581},{140,0,466},{4,0,486},{5,0, 491},{135,10,1121},{4,0,72},{6,0,265},{135,0,1300},{135,11,1183},{10,10,249},{ 139,10,209},{132,10,561},{137,11,519},{4,11,656},{4,10,760},{135,11,779},{9,10, 154},{140,10,485},{135,11,1793},{135,11,144},{136,10,255},{133,0,621},{4,10,368} ,{135,10,641},{135,11,1373},{7,11,554},{7,11,605},{141,11,10},{137,0,234},{5,0, 815},{6,0,1688},{134,0,1755},{5,11,838},{5,11,841},{134,11,1649},{7,0,1987},{7,0 ,2040},{136,0,743},{133,11,1012},{6,0,197},{136,0,205},{6,0,314},{134,11,314},{ 144,11,53},{6,11,251},{7,11,365},{7,11,1357},{7,11,1497},{8,11,154},{141,11,281} ,{133,11,340},{6,0,452},{7,0,312},{138,0,219},{138,0,589},{4,0,333},{9,0,176},{ 12,0,353},{141,0,187},{9,10,92},{147,10,91},{134,0,1110},{11,0,47},{139,11,495}, {6,10,525},{8,10,806},{9,10,876},{140,10,284},{8,11,261},{9,11,144},{9,11,466},{ 10,11,370},{12,11,470},{13,11,144},{142,11,348},{137,11,897},{8,0,863},{8,0,864} ,{8,0,868},{8,0,884},{10,0,866},{10,0,868},{10,0,873},{10,0,911},{10,0,912},{10, 0,944},{12,0,727},{6,11,248},{9,11,546},{10,11,535},{11,11,681},{141,11,135},{6, 0,300},{135,0,1515},{134,0,1237},{139,10,958},{133,10,594},{140,11,250},{134,0, 1685},{134,11,567},{7,0,135},{8,0,7},{8,0,62},{9,0,243},{10,0,658},{10,0,697},{ 11,0,456},{139,0,756},{9,0,395},{138,0,79},{6,10,1641},{136,10,820},{4,10,302},{ 135,10,1766},{134,11,174},{135,10,1313},{135,0,631},{134,10,1674},{134,11,395},{ 138,0,835},{7,0,406},{7,0,459},{8,0,606},{139,0,726},{134,11,617},{134,0,979},{6 ,10,389},{7,10,149},{9,10,142},{138,10,94},{5,11,878},{133,11,972},{6,10,8},{7, 10,1881},{8,10,91},{136,11,511},{133,0,612},{132,11,351},{4,0,372},{7,0,482},{8, 0,158},{9,0,602},{9,0,615},{10,0,245},{10,0,678},{10,0,744},{11,0,248},{139,0, 806},{5,0,854},{135,0,1991},{132,11,286},{135,11,344},{7,11,438},{7,11,627},{7, 11,1516},{8,11,40},{9,11,56},{9,11,294},{10,11,30},{10,11,259},{11,11,969},{146, 11,148},{135,0,1492},{5,11,259},{7,11,414},{7,11,854},{142,11,107},{135,10,1746} ,{6,0,833},{134,0,998},{135,10,24},{6,0,750},{135,0,1739},{4,10,503},{135,10, 1661},{5,10,130},{7,10,1314},{9,10,610},{10,10,718},{11,10,601},{11,10,819},{11, 10,946},{140,10,536},{10,10,149},{11,10,280},{142,10,336},{132,11,738},{135,10, 1946},{5,0,195},{135,0,1685},{7,0,1997},{8,0,730},{139,0,1006},{151,11,17},{133, 11,866},{14,0,463},{14,0,470},{150,0,61},{5,0,751},{8,0,266},{11,0,578},{4,10, 392},{135,10,1597},{5,10,433},{9,10,633},{139,10,629},{135,0,821},{6,0,715},{134 ,0,1325},{133,11,116},{6,0,868},{132,11,457},{134,0,959},{6,10,234},{138,11,199} ,{7,0,1053},{7,10,1950},{8,10,680},{11,10,817},{147,10,88},{7,10,1222},{138,10, 386},{5,0,950},{5,0,994},{6,0,351},{134,0,1124},{134,0,1081},{7,0,1595},{6,10,5} ,{11,10,249},{12,10,313},{16,10,66},{145,10,26},{148,0,59},{5,11,527},{6,11,189} ,{135,11,859},{5,10,963},{6,10,1773},{11,11,104},{11,11,554},{15,11,60},{143,11, 125},{135,0,47},{137,0,684},{134,11,116},{134,0,1606},{134,0,777},{7,0,1020},{8, 10,509},{136,10,792},{135,0,1094},{132,0,350},{133,11,487},{4,11,86},{5,11,667}, {5,11,753},{6,11,316},{6,11,455},{135,11,946},{7,0,1812},{13,0,259},{13,0,356},{ 14,0,242},{147,0,114},{132,10,931},{133,0,967},{4,0,473},{7,0,623},{8,0,808},{9, 0,871},{9,0,893},{11,0,38},{11,0,431},{12,0,112},{12,0,217},{12,0,243},{12,0,562 },{12,0,663},{12,0,683},{13,0,141},{13,0,197},{13,0,227},{13,0,406},{13,0,487},{ 14,0,156},{14,0,203},{14,0,224},{14,0,256},{18,0,58},{150,0,0},{138,0,286},{7,10 ,943},{139,10,614},{135,10,1837},{150,11,45},{132,0,798},{4,0,222},{7,0,286},{ 136,0,629},{4,11,79},{7,11,1773},{10,11,450},{11,11,589},{13,11,332},{13,11,493} ,{14,11,183},{14,11,334},{14,11,362},{14,11,368},{14,11,376},{14,11,379},{19,11, 90},{19,11,103},{19,11,127},{148,11,90},{5,0,337},{11,0,513},{11,0,889},{11,0, 961},{12,0,461},{13,0,79},{15,0,121},{4,10,90},{5,10,545},{7,10,754},{9,10,186}, {10,10,72},{10,10,782},{11,10,577},{11,10,610},{12,10,354},{12,10,362},{140,10, 595},{141,0,306},{136,0,146},{7,0,1646},{9,10,329},{11,10,254},{141,11,124},{4,0 ,465},{135,0,1663},{132,0,525},{133,11,663},{10,0,299},{18,0,74},{9,10,187},{11, 10,1016},{145,10,44},{7,0,165},{7,0,919},{4,10,506},{136,10,517},{5,10,295},{135 ,10,1680},{133,11,846},{134,0,1064},{5,11,378},{7,11,1402},{7,11,1414},{8,11,465 },{9,11,286},{10,11,185},{10,11,562},{10,11,635},{11,11,31},{11,11,393},{12,11, 456},{13,11,312},{18,11,65},{18,11,96},{147,11,89},{132,0,596},{7,10,987},{9,10, 688},{10,10,522},{11,10,788},{140,10,566},{6,0,82},{7,0,138},{7,0,517},{7,0,1741 },{11,0,238},{4,11,648},{134,10,1775},{7,0,1233},{7,10,700},{7,10,940},{8,10,514 },{9,10,116},{9,10,535},{10,10,118},{11,10,107},{11,10,148},{11,10,922},{12,10, 254},{12,10,421},{142,10,238},{4,0,962},{6,0,1824},{8,0,894},{12,0,708},{12,0, 725},{14,0,451},{20,0,94},{22,0,59},{150,0,62},{5,11,945},{6,11,1656},{6,11,1787 },{7,11,167},{8,11,824},{9,11,391},{10,11,375},{139,11,185},{5,0,495},{7,0,834}, {9,0,733},{139,0,378},{4,10,743},{135,11,1273},{6,0,1204},{7,11,1645},{8,11,352} ,{137,11,249},{139,10,292},{133,0,559},{132,11,152},{9,0,499},{10,0,341},{15,0, 144},{19,0,49},{7,10,1283},{9,10,227},{11,10,325},{11,10,408},{14,10,180},{146, 10,47},{6,0,21},{6,0,1737},{7,0,1444},{136,0,224},{133,11,1006},{7,0,1446},{9,0, 97},{17,0,15},{5,10,81},{7,10,146},{7,10,1342},{8,10,53},{8,10,561},{8,10,694},{ 8,10,754},{9,10,115},{9,10,894},{10,10,462},{10,10,813},{11,10,230},{11,10,657}, {11,10,699},{11,10,748},{12,10,119},{12,10,200},{12,10,283},{142,10,273},{5,10, 408},{137,10,747},{135,11,431},{135,11,832},{6,0,729},{134,0,953},{4,0,727},{8,0 ,565},{5,11,351},{7,11,264},{136,11,565},{134,0,1948},{5,0,519},{5,11,40},{7,11, 598},{7,11,1638},{8,11,78},{9,11,166},{9,11,640},{9,11,685},{9,11,773},{11,11, 215},{13,11,65},{14,11,172},{14,11,317},{145,11,6},{8,11,60},{9,11,343},{139,11, 769},{137,11,455},{134,0,1193},{140,0,790},{7,11,1951},{8,11,765},{8,11,772},{ 140,11,671},{7,11,108},{8,11,219},{8,11,388},{9,11,639},{9,11,775},{11,11,275},{ 140,11,464},{132,11,468},{7,10,30},{8,10,86},{8,10,315},{8,10,700},{9,10,576},{9 ,10,858},{11,10,310},{11,10,888},{11,10,904},{12,10,361},{141,10,248},{5,11,15}, {6,11,56},{7,11,1758},{8,11,500},{9,11,730},{11,11,331},{13,11,150},{142,11,282} ,{4,0,402},{7,0,2},{8,0,323},{136,0,479},{138,10,839},{11,0,580},{142,0,201},{5, 0,59},{135,0,672},{137,10,617},{146,0,34},{134,11,1886},{4,0,961},{136,0,896},{6 ,0,1285},{5,11,205},{6,11,438},{137,11,711},{134,10,428},{7,10,524},{8,10,169},{ 8,10,234},{9,10,480},{138,10,646},{148,0,46},{141,0,479},{133,11,534},{6,0,2019} ,{134,10,1648},{4,0,85},{7,0,549},{7,10,1205},{138,10,637},{4,0,663},{5,0,94},{7 ,11,235},{7,11,1475},{15,11,68},{146,11,120},{6,11,443},{9,11,237},{9,11,571},{9 ,11,695},{10,11,139},{11,11,715},{12,11,417},{141,11,421},{132,0,783},{4,0,682}, {8,0,65},{9,10,39},{10,10,166},{11,10,918},{12,10,635},{20,10,10},{22,10,27},{22 ,10,43},{150,10,52},{6,0,11},{135,0,187},{132,0,522},{4,0,52},{135,0,661},{4,0, 383},{133,0,520},{135,11,546},{11,0,343},{142,0,127},{4,11,578},{7,10,157},{7,11 ,624},{7,11,916},{8,10,279},{10,11,256},{11,11,87},{139,11,703},{134,10,604},{4, 0,281},{5,0,38},{7,0,194},{7,0,668},{7,0,1893},{137,0,397},{7,10,945},{11,10,713 },{139,10,744},{139,10,1022},{9,0,635},{139,0,559},{5,11,923},{7,11,490},{12,11, 553},{13,11,100},{14,11,118},{143,11,75},{132,0,975},{132,10,567},{137,10,859},{ 7,10,1846},{7,11,1846},{8,10,628},{136,11,628},{148,0,116},{138,11,750},{14,0,51 },{14,11,51},{15,11,7},{148,11,20},{132,0,858},{134,0,1075},{4,11,924},{133,10, 762},{136,0,535},{133,0,448},{10,10,784},{141,10,191},{133,10,298},{7,0,610},{ 135,0,1501},{7,10,633},{7,10,905},{7,10,909},{7,10,1538},{9,10,767},{140,10,636} ,{4,11,265},{7,11,807},{135,11,950},{5,11,93},{12,11,267},{144,11,26},{136,0,191 },{139,10,301},{135,10,1970},{135,0,267},{4,0,319},{5,0,699},{138,0,673},{6,0, 336},{7,0,92},{7,0,182},{8,0,453},{8,0,552},{9,0,204},{9,0,285},{10,0,99},{11,0, 568},{11,0,950},{12,0,94},{16,0,20},{16,0,70},{19,0,55},{12,10,644},{144,10,90}, {6,0,551},{7,0,1308},{7,10,845},{7,11,994},{8,10,160},{137,10,318},{19,11,1},{19 ,11,26},{150,11,9},{7,0,1406},{9,0,218},{141,0,222},{5,0,256},{138,0,69},{5,11, 233},{5,11,320},{6,11,140},{7,11,330},{136,11,295},{6,0,1980},{136,0,952},{4,0, 833},{137,11,678},{133,11,978},{4,11,905},{6,11,1701},{137,11,843},{138,10,735}, {136,10,76},{17,0,39},{148,0,36},{18,0,81},{146,11,81},{14,0,352},{17,0,53},{18, 0,146},{18,0,152},{19,0,11},{150,0,54},{135,0,634},{138,10,841},{132,0,618},{4,0 ,339},{7,0,259},{17,0,73},{4,11,275},{140,11,376},{132,11,509},{7,11,273},{139, 11,377},{4,0,759},{13,0,169},{137,10,804},{6,10,96},{135,10,1426},{4,10,651},{ 133,10,289},{7,0,1075},{8,10,35},{9,10,511},{10,10,767},{147,10,118},{6,0,649},{ 6,0,670},{136,0,482},{5,0,336},{6,0,341},{6,0,478},{6,0,1763},{136,0,386},{5,11, 802},{7,11,2021},{8,11,805},{14,11,94},{15,11,65},{16,11,4},{16,11,77},{16,11,80 },{145,11,5},{6,0,1035},{5,11,167},{5,11,899},{6,11,410},{137,11,777},{134,11, 1705},{5,0,924},{133,0,969},{132,10,704},{135,0,73},{135,11,10},{135,10,1078},{5 ,11,11},{6,11,117},{6,11,485},{7,11,1133},{9,11,582},{9,11,594},{11,11,21},{11, 11,818},{12,11,535},{141,11,86},{135,0,1971},{4,11,264},{7,11,1067},{8,11,204},{ 8,11,385},{139,11,953},{6,0,1458},{135,0,1344},{5,0,396},{134,0,501},{4,10,720}, {133,10,306},{4,0,929},{5,0,799},{8,0,46},{8,0,740},{133,10,431},{7,11,646},{7, 11,1730},{11,11,446},{141,11,178},{7,0,276},{5,10,464},{6,10,236},{7,10,696},{7, 10,914},{7,10,1108},{7,10,1448},{9,10,15},{9,10,564},{10,10,14},{12,10,565},{13, 10,449},{14,10,53},{15,10,13},{16,10,64},{145,10,41},{4,0,892},{133,0,770},{6,10 ,1767},{12,10,194},{145,10,107},{135,0,158},{5,10,840},{138,11,608},{134,0,1432} ,{138,11,250},{8,11,794},{9,11,400},{10,11,298},{142,11,228},{151,0,25},{7,11, 1131},{135,11,1468},{135,0,2001},{9,10,642},{11,10,236},{142,10,193},{4,10,68},{ 5,10,634},{6,10,386},{7,10,794},{8,10,273},{9,10,563},{10,10,105},{10,10,171},{ 11,10,94},{139,10,354},{136,11,724},{132,0,478},{11,11,512},{13,11,205},{19,11, 30},{22,11,36},{151,11,19},{7,0,1461},{140,0,91},{6,11,190},{7,11,768},{135,11, 1170},{4,0,602},{8,0,211},{4,10,95},{7,10,416},{139,10,830},{7,10,731},{13,10,20 },{143,10,11},{6,0,1068},{135,0,1872},{4,0,13},{5,0,567},{7,0,1498},{9,0,124},{ 11,0,521},{12,0,405},{135,11,1023},{135,0,1006},{132,0,735},{138,0,812},{4,0,170 },{135,0,323},{6,11,137},{9,11,75},{9,11,253},{10,11,194},{138,11,444},{5,0,304} ,{7,0,1403},{5,10,864},{10,10,648},{11,10,671},{143,10,46},{135,11,1180},{133,10 ,928},{4,0,148},{133,0,742},{11,10,986},{140,10,682},{133,0,523},{135,11,1743},{ 7,0,730},{18,0,144},{19,0,61},{8,10,44},{9,10,884},{10,10,580},{11,10,399},{11, 10,894},{143,10,122},{5,11,760},{7,11,542},{8,11,135},{136,11,496},{136,0,981},{ 133,0,111},{10,0,132},{11,0,191},{11,0,358},{139,0,460},{7,11,319},{7,11,355},{7 ,11,763},{10,11,389},{145,11,43},{134,0,890},{134,0,1420},{136,11,557},{133,10, 518},{133,0,444},{135,0,1787},{135,10,1852},{8,0,123},{15,0,6},{144,0,7},{6,0, 2041},{10,11,38},{139,11,784},{136,0,932},{5,0,937},{135,0,100},{6,0,995},{4,11, 58},{5,11,286},{6,11,319},{7,11,402},{7,11,1254},{7,11,1903},{8,11,356},{140,11, 408},{4,11,389},{9,11,181},{9,11,255},{10,11,8},{10,11,29},{10,11,816},{11,11, 311},{11,11,561},{12,11,67},{141,11,181},{138,0,255},{5,0,138},{4,10,934},{136, 10,610},{4,0,965},{10,0,863},{138,0,898},{10,10,804},{138,10,832},{12,0,631},{8, 10,96},{9,10,36},{10,10,607},{11,10,423},{11,10,442},{12,10,309},{14,10,199},{15 ,10,90},{145,10,110},{134,0,1394},{4,0,652},{8,0,320},{22,0,6},{22,0,16},{9,10, 13},{9,10,398},{9,10,727},{10,10,75},{10,10,184},{10,10,230},{10,10,564},{10,10, 569},{11,10,973},{12,10,70},{12,10,189},{13,10,57},{141,10,257},{6,0,897},{134,0 ,1333},{4,0,692},{133,0,321},{133,11,373},{135,0,922},{5,0,619},{133,0,698},{137 ,10,631},{5,10,345},{135,10,1016},{9,0,957},{9,0,1018},{12,0,828},{12,0,844},{12 ,0,897},{12,0,901},{12,0,943},{15,0,180},{18,0,197},{18,0,200},{18,0,213},{18,0, 214},{146,0,226},{5,0,917},{134,0,1659},{135,0,1100},{134,0,1173},{134,0,1930},{ 5,0,251},{5,0,956},{8,0,268},{9,0,214},{146,0,142},{133,10,673},{137,10,850},{4, 10,287},{133,10,1018},{132,11,672},{5,0,346},{5,0,711},{8,0,390},{11,11,752},{ 139,11,885},{5,10,34},{10,10,724},{12,10,444},{13,10,354},{18,10,32},{23,10,24}, {23,10,31},{152,10,5},{4,11,710},{134,11,606},{134,0,744},{134,10,382},{133,11, 145},{4,10,329},{7,11,884},{140,11,124},{4,11,467},{5,11,405},{134,11,544},{9,10 ,846},{138,10,827},{133,0,624},{9,11,372},{15,11,2},{19,11,10},{147,11,18},{4,11 ,387},{135,11,1288},{5,0,783},{7,0,1998},{135,0,2047},{132,10,906},{136,10,366}, {135,11,550},{4,10,123},{4,10,649},{5,10,605},{7,10,1509},{136,10,36},{134,0, 1125},{132,0,594},{133,10,767},{135,11,1227},{136,11,467},{4,11,576},{135,11, 1263},{4,0,268},{7,0,1534},{135,11,1534},{4,10,273},{5,10,658},{5,11,919},{5,10, 995},{134,11,1673},{133,0,563},{134,10,72},{135,10,1345},{4,11,82},{5,11,333},{5 ,11,904},{6,11,207},{7,11,325},{7,11,1726},{8,11,101},{10,11,778},{139,11,220},{ 5,0,37},{6,0,39},{6,0,451},{7,0,218},{7,0,667},{7,0,1166},{7,0,1687},{8,0,662},{ 16,0,2},{133,10,589},{134,0,1332},{133,11,903},{134,0,508},{5,10,117},{6,10,514} ,{6,10,541},{7,10,1164},{7,10,1436},{8,10,220},{8,10,648},{10,10,688},{11,10,560 },{140,11,147},{6,11,555},{135,11,485},{133,10,686},{7,0,453},{7,0,635},{7,0,796 },{8,0,331},{9,0,330},{9,0,865},{10,0,119},{10,0,235},{11,0,111},{11,0,129},{11, 0,240},{12,0,31},{12,0,66},{12,0,222},{12,0,269},{12,0,599},{12,0,684},{12,0,689 },{12,0,691},{142,0,345},{135,0,1834},{4,11,705},{7,11,615},{138,11,251},{136,11 ,345},{137,0,527},{6,0,98},{7,0,702},{135,0,991},{11,0,576},{14,0,74},{7,10,196} ,{10,10,765},{11,10,347},{11,10,552},{11,10,790},{12,10,263},{13,10,246},{13,10, 270},{13,10,395},{14,10,176},{14,10,190},{14,10,398},{14,10,412},{15,10,32},{15, 10,63},{16,10,88},{147,10,105},{134,11,90},{13,0,84},{141,0,122},{6,0,37},{7,0, 299},{7,0,1666},{8,0,195},{8,0,316},{9,0,178},{9,0,276},{9,0,339},{9,0,536},{10, 0,102},{10,0,362},{10,0,785},{11,0,55},{11,0,149},{11,0,773},{13,0,416},{13,0, 419},{14,0,38},{14,0,41},{142,0,210},{5,10,381},{135,10,1792},{7,11,813},{12,11, 497},{141,11,56},{7,10,616},{138,10,413},{133,0,645},{6,11,125},{135,11,1277},{ 132,0,290},{6,0,70},{7,0,1292},{10,0,762},{139,0,288},{6,10,120},{7,10,1188},{7, 10,1710},{8,10,286},{9,10,667},{11,10,592},{139,10,730},{135,11,1784},{7,0,1315} ,{135,11,1315},{134,0,1955},{135,10,1146},{7,0,131},{7,0,422},{8,0,210},{140,0, 573},{4,10,352},{135,10,687},{139,0,797},{143,0,38},{14,0,179},{15,0,151},{150,0 ,11},{7,0,488},{4,10,192},{5,10,49},{6,10,200},{6,10,293},{134,10,1696},{132,0, 936},{135,11,703},{6,11,160},{7,11,1106},{9,11,770},{10,11,618},{11,11,112},{140 ,11,413},{5,0,453},{134,0,441},{135,0,595},{132,10,650},{132,10,147},{6,0,991},{ 6,0,1182},{12,11,271},{145,11,109},{133,10,934},{140,11,221},{132,0,653},{7,0, 505},{135,0,523},{134,0,903},{135,11,479},{7,11,304},{9,11,646},{9,11,862},{10, 11,262},{11,11,696},{12,11,208},{15,11,79},{147,11,108},{146,0,80},{135,11,981}, {142,0,432},{132,0,314},{137,11,152},{7,0,1368},{8,0,232},{8,0,361},{10,0,682},{ 138,0,742},{135,11,1586},{9,0,534},{4,11,434},{11,11,663},{12,11,210},{13,11,166 },{13,11,310},{14,11,373},{147,11,43},{7,11,1091},{135,11,1765},{6,11,550},{135, 11,652},{137,0,27},{142,0,12},{4,10,637},{5,11,553},{7,11,766},{138,11,824},{7, 11,737},{8,11,298},{136,11,452},{7,0,736},{139,0,264},{134,0,1657},{133,11,292}, {138,11,135},{6,0,844},{134,0,1117},{135,0,127},{9,10,867},{138,10,837},{6,0, 1184},{134,0,1208},{134,0,1294},{136,0,364},{6,0,1415},{7,0,1334},{11,0,125},{6, 10,170},{7,11,393},{8,10,395},{8,10,487},{10,11,603},{11,11,206},{141,10,147},{ 137,11,748},{4,11,912},{137,11,232},{4,10,535},{136,10,618},{137,0,792},{7,11, 1973},{136,11,716},{135,11,98},{5,0,909},{9,0,849},{138,0,805},{4,0,630},{132,0, 699},{5,11,733},{14,11,103},{150,10,23},{12,11,158},{18,11,8},{19,11,62},{20,11, 6},{22,11,4},{23,11,2},{151,11,9},{132,0,968},{132,10,778},{132,10,46},{5,10,811 },{6,10,1679},{6,10,1714},{135,10,2032},{6,0,1446},{7,10,1458},{9,10,407},{139, 10,15},{7,0,206},{7,0,397},{7,0,621},{7,0,640},{8,0,124},{8,0,619},{9,0,305},{9, 0,643},{10,0,264},{10,0,628},{11,0,40},{12,0,349},{13,0,134},{13,0,295},{14,0, 155},{15,0,120},{18,0,105},{6,10,34},{7,10,1089},{8,10,708},{8,10,721},{9,10,363 },{148,10,98},{4,0,262},{5,0,641},{135,0,342},{137,11,72},{4,0,99},{6,0,250},{6, 0,346},{8,0,127},{138,0,81},{132,0,915},{5,0,75},{9,0,517},{10,0,470},{12,0,155} ,{141,0,224},{132,10,462},{11,11,600},{11,11,670},{141,11,245},{142,0,83},{5,10, 73},{6,10,23},{134,10,338},{6,0,1031},{139,11,923},{7,11,164},{7,11,1571},{9,11, 107},{140,11,225},{134,0,1470},{133,0,954},{6,0,304},{8,0,418},{10,0,345},{11,0, 341},{139,0,675},{9,0,410},{139,0,425},{4,11,27},{5,11,484},{5,11,510},{6,11,434 },{7,11,1000},{7,11,1098},{8,11,2},{136,11,200},{134,0,734},{140,11,257},{7,10, 725},{8,10,498},{139,10,268},{134,0,1822},{135,0,1798},{135,10,773},{132,11,460} ,{4,11,932},{133,11,891},{134,0,14},{132,10,583},{7,10,1462},{8,11,625},{139,10, 659},{5,0,113},{6,0,243},{6,0,1708},{7,0,1865},{11,0,161},{16,0,37},{17,0,99},{ 133,10,220},{134,11,76},{5,11,461},{135,11,1925},{140,0,69},{8,11,92},{137,11, 221},{139,10,803},{132,10,544},{4,0,274},{134,0,922},{132,0,541},{5,0,627},{6,10 ,437},{6,10,564},{11,10,181},{141,10,183},{135,10,1192},{7,0,166},{132,11,763},{ 133,11,253},{134,0,849},{9,11,73},{10,11,110},{14,11,185},{145,11,119},{5,11,212 },{12,11,35},{141,11,382},{133,0,717},{137,0,304},{136,0,600},{133,0,654},{6,0, 273},{10,0,188},{13,0,377},{146,0,77},{4,10,790},{5,10,273},{134,10,394},{132,0, 543},{135,0,410},{11,0,98},{11,0,524},{141,0,87},{132,0,941},{135,11,1175},{4,0, 250},{7,0,1612},{11,0,186},{12,0,133},{6,10,127},{7,10,1511},{8,10,613},{12,10, 495},{12,10,586},{12,10,660},{12,10,668},{14,10,385},{15,10,118},{17,10,20},{146 ,10,98},{6,0,1785},{133,11,816},{134,0,1339},{7,0,961},{7,0,1085},{7,0,1727},{8, 0,462},{6,10,230},{135,11,1727},{9,0,636},{135,10,1954},{132,0,780},{5,11,869},{ 5,11,968},{6,11,1626},{8,11,734},{136,11,784},{4,11,542},{6,11,1716},{6,11,1727} ,{7,11,1082},{7,11,1545},{8,11,56},{8,11,118},{8,11,412},{8,11,564},{9,11,888},{ 9,11,908},{10,11,50},{10,11,423},{11,11,685},{11,11,697},{11,11,933},{12,11,299} ,{13,11,126},{13,11,136},{13,11,170},{141,11,190},{134,11,226},{4,11,232},{9,11, 202},{10,11,474},{140,11,433},{137,11,500},{5,0,529},{136,10,68},{132,10,654},{4 ,10,156},{7,10,998},{7,10,1045},{7,10,1860},{9,10,48},{9,10,692},{11,10,419},{ 139,10,602},{7,0,1276},{8,0,474},{9,0,652},{6,11,108},{7,11,1003},{7,11,1181},{ 136,11,343},{7,11,1264},{7,11,1678},{11,11,945},{12,11,341},{12,11,471},{140,11, 569},{134,11,1712},{5,0,948},{12,0,468},{19,0,96},{148,0,24},{4,11,133},{7,11, 711},{7,11,1298},{7,11,1585},{135,11,1929},{6,0,753},{140,0,657},{139,0,941},{6, 11,99},{7,11,1808},{145,11,57},{6,11,574},{7,11,428},{7,11,1250},{10,11,669},{11 ,11,485},{11,11,840},{12,11,300},{142,11,250},{4,0,532},{5,0,706},{135,0,662},{5 ,0,837},{6,0,1651},{139,0,985},{7,0,1861},{9,10,197},{10,10,300},{12,10,473},{13 ,10,90},{141,10,405},{137,11,252},{6,11,323},{135,11,1564},{4,0,330},{4,0,863},{ 7,0,933},{7,0,2012},{8,0,292},{7,11,461},{8,11,775},{138,11,435},{132,10,606},{4 ,11,655},{7,11,850},{17,11,75},{146,11,137},{135,0,767},{7,10,1978},{136,10,676} ,{132,0,641},{135,11,1559},{134,0,1233},{137,0,242},{17,0,114},{4,10,361},{133, 10,315},{137,0,883},{132,10,461},{138,0,274},{134,0,2008},{134,0,1794},{4,0,703} ,{135,0,207},{12,0,285},{132,10,472},{132,0,571},{5,0,873},{5,0,960},{8,0,823},{ 9,0,881},{136,11,577},{7,0,617},{10,0,498},{11,0,501},{12,0,16},{140,0,150},{138 ,10,747},{132,0,431},{133,10,155},{11,0,283},{11,0,567},{7,10,163},{8,10,319},{9 ,10,402},{10,10,24},{10,10,681},{11,10,200},{12,10,253},{12,10,410},{142,10,219} ,{4,11,413},{5,11,677},{8,11,432},{140,11,280},{9,0,401},{5,10,475},{7,10,1780}, {11,10,297},{11,10,558},{14,10,322},{147,10,76},{6,0,781},{9,0,134},{10,0,2},{10 ,0,27},{10,0,333},{11,0,722},{143,0,1},{5,0,33},{6,0,470},{139,0,424},{135,0, 2006},{12,0,783},{135,10,1956},{136,0,274},{135,0,1882},{132,0,794},{135,0,1848} ,{5,10,944},{134,10,1769},{6,0,47},{7,0,90},{7,0,664},{7,0,830},{7,0,1380},{7,0, 2025},{8,0,448},{136,0,828},{132,10,144},{134,0,1199},{4,11,395},{139,11,762},{ 135,11,1504},{9,0,417},{137,0,493},{9,11,174},{10,11,164},{11,11,440},{11,11,841 },{143,11,98},{134,11,426},{139,11,1002},{134,0,295},{134,0,816},{6,10,247},{137 ,10,555},{133,0,1019},{4,0,620},{5,11,476},{10,10,280},{138,10,797},{139,0,464}, {5,11,76},{6,11,458},{6,11,497},{7,11,764},{7,11,868},{9,11,658},{10,11,594},{11 ,11,173},{11,11,566},{12,11,20},{12,11,338},{141,11,200},{134,0,208},{4,11,526}, {7,11,1029},{135,11,1054},{132,11,636},{6,11,233},{7,11,660},{7,11,1124},{17,11, 31},{19,11,22},{151,11,14},{10,0,442},{133,10,428},{10,0,930},{140,0,778},{6,0, 68},{7,0,448},{7,0,1629},{7,0,1769},{7,0,1813},{8,0,442},{8,0,516},{9,0,710},{10 ,0,282},{10,0,722},{7,10,1717},{138,10,546},{134,0,1128},{11,0,844},{12,0,104},{ 140,0,625},{4,11,432},{135,11,824},{138,10,189},{133,0,787},{133,10,99},{4,11, 279},{7,11,301},{137,11,362},{8,0,491},{4,10,397},{136,10,555},{4,11,178},{133, 11,399},{134,0,711},{144,0,9},{4,0,403},{5,0,441},{7,0,450},{10,0,840},{11,0,101 },{12,0,193},{141,0,430},{135,11,1246},{12,10,398},{20,10,39},{21,10,11},{150,10 ,41},{4,10,485},{7,10,353},{135,10,1523},{6,10,366},{7,10,1384},{7,10,1601},{135 ,11,1912},{7,0,396},{10,0,160},{135,11,396},{137,10,282},{134,11,1692},{4,10,157 },{5,10,471},{6,11,202},{10,11,448},{11,11,208},{12,11,360},{17,11,117},{17,11, 118},{18,11,27},{148,11,67},{133,0,679},{137,0,326},{136,10,116},{7,11,872},{10, 11,516},{139,11,167},{132,11,224},{5,11,546},{7,11,35},{8,11,11},{8,11,12},{9,11 ,315},{9,11,533},{10,11,802},{11,11,166},{12,11,525},{142,11,243},{7,0,1128},{ 135,11,1920},{5,11,241},{8,11,242},{9,11,451},{10,11,667},{11,11,598},{140,11, 429},{6,0,737},{5,10,160},{7,10,363},{7,10,589},{10,10,170},{141,10,55},{135,0, 1796},{142,11,254},{4,0,574},{7,0,350},{7,0,1024},{8,0,338},{9,0,677},{138,0,808 },{134,0,1096},{137,11,516},{7,0,405},{10,0,491},{4,10,108},{4,11,366},{139,10, 498},{11,11,337},{142,11,303},{134,11,1736},{7,0,1081},{140,11,364},{7,10,1005}, {140,10,609},{7,0,1676},{4,10,895},{133,10,772},{135,0,2037},{6,0,1207},{11,11, 916},{142,11,419},{14,11,140},{148,11,41},{6,11,331},{136,11,623},{9,0,944},{9,0 ,969},{9,0,1022},{12,0,913},{12,0,936},{15,0,177},{15,0,193},{4,10,926},{133,10, 983},{5,0,354},{135,11,506},{8,0,598},{9,0,664},{138,0,441},{4,11,640},{133,11, 513},{137,0,297},{132,10,538},{6,10,294},{7,10,1267},{136,10,624},{7,0,1772},{7, 11,1888},{8,11,289},{11,11,45},{12,11,278},{140,11,537},{135,10,1325},{138,0,751 },{141,0,37},{134,0,1828},{132,10,757},{132,11,394},{6,0,257},{135,0,1522},{4,0, 582},{9,0,191},{135,11,1931},{7,11,574},{7,11,1719},{137,11,145},{132,11,658},{ 10,0,790},{132,11,369},{9,11,781},{10,11,144},{11,11,385},{13,11,161},{13,11,228 },{13,11,268},{148,11,107},{8,0,469},{10,0,47},{136,11,374},{6,0,306},{7,0,1140} ,{7,0,1340},{8,0,133},{138,0,449},{139,0,1011},{7,10,1875},{139,10,124},{4,11, 344},{6,11,498},{139,11,323},{137,0,299},{132,0,837},{133,11,906},{5,0,329},{8,0 ,260},{138,0,10},{134,0,1320},{4,0,657},{146,0,158},{135,0,1191},{152,0,7},{6,0, 1939},{8,0,974},{138,0,996},{135,0,1665},{11,11,126},{139,11,287},{143,0,8},{14, 11,149},{14,11,399},{143,11,57},{5,0,66},{7,0,1896},{136,0,288},{7,0,175},{10,0, 494},{5,10,150},{8,10,603},{9,10,593},{9,10,634},{10,10,173},{11,10,462},{11,10, 515},{13,10,216},{13,10,288},{142,10,400},{134,0,1643},{136,11,21},{4,0,21},{5,0 ,91},{5,0,648},{5,0,750},{5,0,781},{6,0,54},{6,0,112},{6,0,402},{6,0,1732},{7,0, 315},{7,0,749},{7,0,1427},{7,0,1900},{9,0,78},{9,0,508},{10,0,611},{10,0,811},{ 11,0,510},{11,0,728},{13,0,36},{14,0,39},{16,0,83},{17,0,124},{148,0,30},{4,0, 668},{136,0,570},{10,0,322},{10,0,719},{139,0,407},{135,11,1381},{136,11,193},{ 12,10,108},{141,10,291},{132,11,616},{136,11,692},{8,0,125},{8,0,369},{8,0,524}, {10,0,486},{11,0,13},{11,0,381},{11,0,736},{11,0,766},{11,0,845},{13,0,114},{13, 0,292},{142,0,47},{134,0,1247},{6,0,1684},{6,0,1731},{7,0,356},{8,0,54},{8,0,221 },{9,0,225},{9,0,356},{10,0,77},{10,0,446},{10,0,731},{12,0,404},{141,0,491},{ 135,10,1777},{4,11,305},{4,10,493},{144,10,55},{4,0,951},{6,0,1809},{6,0,1849},{ 8,0,846},{8,0,866},{8,0,899},{10,0,896},{12,0,694},{142,0,468},{5,11,214},{7,11, 603},{8,11,611},{9,11,686},{10,11,88},{11,11,459},{11,11,496},{12,11,463},{12,11 ,590},{13,11,0},{142,11,214},{132,0,411},{4,0,80},{133,0,44},{140,11,74},{143,0, 31},{7,0,669},{6,10,568},{7,10,1804},{8,10,362},{8,10,410},{8,10,830},{9,10,514} ,{11,10,649},{142,10,157},{7,0,673},{134,11,1703},{132,10,625},{134,0,1303},{5,0 ,299},{135,0,1083},{138,0,704},{6,0,275},{7,0,408},{6,10,158},{7,10,129},{7,10, 181},{8,10,276},{8,10,377},{10,10,523},{11,10,816},{12,10,455},{13,10,303},{142, 10,135},{4,0,219},{7,0,367},{7,0,1713},{7,0,1761},{9,0,86},{9,0,537},{10,0,165}, {12,0,219},{140,0,561},{8,0,216},{4,10,1},{4,11,737},{6,11,317},{7,10,1143},{7, 10,1463},{9,10,207},{9,10,390},{9,10,467},{10,11,98},{11,11,294},{11,10,836},{12 ,11,60},{12,11,437},{13,11,64},{13,11,380},{142,11,430},{6,11,1758},{8,11,520},{ 9,11,345},{9,11,403},{142,11,350},{5,11,47},{10,11,242},{138,11,579},{5,11,139}, {7,11,1168},{138,11,539},{135,0,1319},{4,10,295},{4,10,723},{5,10,895},{7,10, 1031},{8,10,199},{8,10,340},{9,10,153},{9,10,215},{10,10,21},{10,10,59},{10,10, 80},{10,10,224},{10,10,838},{11,10,229},{11,10,652},{12,10,192},{13,10,146},{142 ,10,91},{140,0,428},{137,10,51},{133,0,514},{5,10,309},{140,10,211},{6,0,1010},{ 5,10,125},{8,10,77},{138,10,15},{4,0,55},{5,0,301},{6,0,571},{142,0,49},{146,0, 102},{136,11,370},{4,11,107},{7,11,613},{8,11,358},{8,11,439},{8,11,504},{9,11, 501},{10,11,383},{139,11,477},{132,11,229},{133,0,364},{133,10,439},{4,11,903},{ 135,11,1816},{11,0,379},{140,10,76},{4,0,76},{4,0,971},{7,0,1550},{9,0,306},{9,0 ,430},{9,0,663},{10,0,683},{10,0,921},{11,0,427},{11,0,753},{12,0,334},{12,0,442 },{14,0,258},{14,0,366},{143,0,131},{137,0,52},{4,11,47},{6,11,373},{7,11,452},{ 7,11,543},{7,11,1714},{7,11,1856},{9,11,6},{11,11,257},{139,11,391},{4,10,8},{7, 10,1152},{7,10,1153},{7,10,1715},{9,10,374},{10,10,478},{139,10,648},{4,11,785}, {133,11,368},{135,10,1099},{135,11,860},{5,11,980},{134,11,1754},{134,0,1258},{6 ,0,1058},{6,0,1359},{7,11,536},{7,11,1331},{136,11,143},{4,0,656},{135,0,779},{ 136,10,87},{5,11,19},{6,11,533},{146,11,126},{7,0,144},{138,10,438},{5,11,395},{ 5,11,951},{134,11,1776},{135,0,1373},{7,0,554},{7,0,605},{141,0,10},{4,10,69},{5 ,10,122},{9,10,656},{138,10,464},{5,10,849},{134,10,1633},{5,0,838},{5,0,841},{ 134,0,1649},{133,0,1012},{139,10,499},{7,10,476},{7,10,1592},{138,10,87},{6,0, 251},{7,0,365},{7,0,1357},{7,0,1497},{8,0,154},{141,0,281},{132,11,441},{132,11, 695},{7,11,497},{9,11,387},{147,11,81},{133,0,340},{14,10,283},{142,11,283},{134 ,0,810},{135,11,1894},{139,0,495},{5,11,284},{6,11,49},{6,11,350},{7,11,1},{7,11 ,377},{7,11,1693},{8,11,18},{8,11,678},{9,11,161},{9,11,585},{9,11,671},{9,11, 839},{11,11,912},{141,11,427},{5,10,859},{7,10,1160},{8,10,107},{9,10,291},{9,10 ,439},{10,10,663},{11,10,609},{140,10,197},{8,0,261},{9,0,144},{9,0,466},{10,0, 370},{12,0,470},{13,0,144},{142,0,348},{137,0,897},{6,0,248},{9,0,546},{10,0,535 },{11,0,681},{141,0,135},{4,0,358},{135,0,1496},{134,0,567},{136,0,445},{4,10, 117},{6,10,372},{7,10,1905},{142,10,323},{4,10,722},{139,10,471},{6,0,697},{134, 0,996},{7,11,2007},{9,11,101},{9,11,450},{10,11,66},{10,11,842},{11,11,536},{140 ,11,587},{132,0,577},{134,0,1336},{9,10,5},{12,10,216},{12,10,294},{12,10,298},{ 12,10,400},{12,10,518},{13,10,229},{143,10,139},{6,0,174},{138,0,917},{134,10, 1774},{5,10,12},{7,10,375},{9,10,88},{9,10,438},{11,11,62},{139,10,270},{134,11, 1766},{6,11,0},{7,11,84},{7,10,816},{7,10,1241},{9,10,283},{9,10,520},{10,10,213 },{10,10,307},{10,10,463},{10,10,671},{10,10,746},{11,10,401},{11,10,794},{11,11 ,895},{12,10,517},{17,11,11},{18,10,107},{147,10,115},{5,0,878},{133,0,972},{6, 11,1665},{7,11,256},{7,11,1388},{138,11,499},{4,10,258},{136,10,639},{4,11,22},{ 5,11,10},{6,10,22},{7,11,848},{7,10,903},{7,10,1963},{8,11,97},{138,10,577},{5, 10,681},{136,10,782},{133,11,481},{132,0,351},{4,10,664},{5,10,804},{139,10,1013 },{6,11,134},{7,11,437},{7,11,959},{9,11,37},{14,11,285},{14,11,371},{144,11,60} ,{7,11,486},{8,11,155},{11,11,93},{140,11,164},{132,0,286},{7,0,438},{7,0,627},{ 7,0,1516},{8,0,40},{9,0,56},{9,0,294},{10,0,30},{11,0,969},{11,0,995},{146,0,148 },{5,11,591},{135,11,337},{134,0,1950},{133,10,32},{138,11,500},{5,11,380},{5,11 ,650},{136,11,310},{4,11,364},{7,11,1156},{7,11,1187},{137,11,409},{4,0,738},{ 134,11,482},{4,11,781},{6,11,487},{7,11,926},{8,11,263},{139,11,500},{135,11,418 },{6,0,2047},{10,0,969},{4,10,289},{7,10,629},{7,10,1698},{7,10,1711},{140,10, 215},{6,10,450},{136,10,109},{134,0,818},{136,10,705},{133,0,866},{4,11,94},{135 ,11,1265},{132,11,417},{134,0,1467},{135,10,1238},{4,0,972},{6,0,1851},{134,0, 1857},{134,0,355},{133,0,116},{132,0,457},{135,11,1411},{4,11,408},{4,11,741},{ 135,11,500},{134,10,26},{142,11,137},{5,0,527},{6,0,189},{7,0,859},{136,0,267},{ 11,0,104},{11,0,554},{15,0,60},{143,0,125},{134,0,1613},{4,10,414},{5,10,467},{9 ,10,654},{10,10,451},{12,10,59},{141,10,375},{135,10,17},{134,0,116},{135,11,541 },{135,10,955},{6,11,73},{135,11,177},{133,11,576},{134,0,886},{133,0,487},{4,0, 86},{5,0,667},{5,0,753},{6,0,316},{6,0,455},{135,0,946},{142,11,231},{150,0,45}, {134,0,863},{134,0,1953},{6,10,280},{10,10,502},{11,10,344},{140,10,38},{4,0,79} ,{7,0,1773},{10,0,450},{11,0,589},{13,0,332},{13,0,493},{14,0,183},{14,0,334},{ 14,0,362},{14,0,368},{14,0,376},{14,0,379},{19,0,90},{19,0,103},{19,0,127},{148, 0,90},{5,10,45},{7,10,1161},{11,10,448},{11,10,880},{13,10,139},{13,10,407},{15, 10,16},{17,10,95},{18,10,66},{18,10,88},{18,10,123},{149,10,7},{136,10,777},{4, 10,410},{135,10,521},{135,10,1778},{135,11,538},{142,0,381},{133,11,413},{134,0, 1142},{6,0,1189},{136,11,495},{5,0,663},{6,0,1962},{134,0,2003},{7,11,54},{8,11, 312},{10,11,191},{10,11,614},{140,11,567},{132,10,436},{133,0,846},{10,0,528},{ 11,0,504},{7,10,1587},{135,10,1707},{5,0,378},{8,0,465},{9,0,286},{10,0,185},{10 ,0,562},{10,0,635},{11,0,31},{11,0,393},{13,0,312},{18,0,65},{18,0,96},{147,0,89 },{7,0,899},{14,0,325},{6,11,468},{7,11,567},{7,11,1478},{8,11,530},{142,11,290} ,{7,0,1880},{9,0,680},{139,0,798},{134,0,1770},{132,0,648},{150,11,35},{5,0,945} ,{6,0,1656},{6,0,1787},{7,0,167},{8,0,824},{9,0,391},{10,0,375},{139,0,185},{6, 11,484},{135,11,822},{134,0,2046},{7,0,1645},{8,0,352},{137,0,249},{132,0,152},{ 6,0,611},{135,0,1733},{6,11,1724},{135,11,2022},{133,0,1006},{141,11,96},{5,0, 420},{135,0,1449},{146,11,149},{135,0,832},{135,10,663},{133,0,351},{5,0,40},{7, 0,598},{7,0,1638},{8,0,78},{9,0,166},{9,0,640},{9,0,685},{9,0,773},{11,0,215},{ 13,0,65},{14,0,172},{14,0,317},{145,0,6},{8,0,60},{9,0,343},{139,0,769},{134,0, 1354},{132,0,724},{137,0,745},{132,11,474},{7,0,1951},{8,0,765},{8,0,772},{140,0 ,671},{7,0,108},{8,0,219},{8,0,388},{9,0,775},{11,0,275},{140,0,464},{137,0,639} ,{135,10,503},{133,11,366},{5,0,15},{6,0,56},{7,0,1758},{8,0,500},{9,0,730},{11, 0,331},{13,0,150},{14,0,282},{5,11,305},{9,11,560},{141,11,208},{4,10,113},{5,10 ,163},{5,10,735},{7,10,1009},{9,10,9},{9,10,771},{12,10,90},{13,10,138},{13,10, 410},{143,10,128},{4,10,324},{138,10,104},{135,11,466},{142,11,27},{134,0,1886}, {5,0,205},{6,0,438},{9,0,711},{4,11,480},{6,11,167},{6,11,302},{6,11,1642},{7,11 ,130},{7,11,656},{7,11,837},{7,11,1547},{7,11,1657},{8,11,429},{9,11,228},{10,11 ,643},{13,11,289},{13,11,343},{147,11,101},{134,0,865},{6,0,2025},{136,0,965},{7 ,11,278},{10,11,739},{11,11,708},{141,11,348},{133,0,534},{135,11,1922},{137,0, 691},{4,10,935},{133,10,823},{6,0,443},{9,0,237},{9,0,571},{9,0,695},{10,0,139}, {11,0,715},{12,0,417},{141,0,421},{5,10,269},{7,10,434},{7,10,891},{8,10,339},{9 ,10,702},{11,10,594},{11,10,718},{145,10,100},{6,0,1555},{7,0,878},{9,10,485},{ 141,10,264},{134,10,1713},{7,10,1810},{11,10,866},{12,10,103},{141,10,495},{135, 10,900},{6,0,1410},{9,11,316},{139,11,256},{4,0,995},{135,0,1033},{132,0,578},{ 10,0,881},{12,0,740},{12,0,743},{140,0,759},{132,0,822},{133,0,923},{142,10,143} ,{135,11,1696},{6,11,363},{7,11,1955},{136,11,725},{132,0,924},{133,0,665},{135, 10,2029},{135,0,1901},{4,0,265},{6,0,1092},{6,0,1417},{7,0,807},{135,0,950},{5,0 ,93},{12,0,267},{141,0,498},{135,0,1451},{5,11,813},{135,11,2046},{5,10,625},{ 135,10,1617},{135,0,747},{6,0,788},{137,0,828},{7,0,184},{11,0,307},{11,0,400},{ 15,0,130},{5,11,712},{7,11,1855},{8,10,425},{8,10,693},{9,10,720},{10,10,380},{ 10,10,638},{11,11,17},{11,10,473},{12,10,61},{13,11,321},{144,11,67},{135,0,198} ,{6,11,320},{7,11,781},{7,11,1921},{9,11,55},{10,11,186},{10,11,273},{10,11,664} ,{10,11,801},{11,11,996},{11,11,997},{13,11,157},{142,11,170},{136,11,271},{135, 0,994},{7,11,103},{7,11,863},{11,11,184},{14,11,299},{145,11,62},{11,10,551},{ 142,10,159},{5,0,233},{5,0,320},{6,0,140},{8,0,295},{8,0,615},{136,11,615},{133, 0,978},{4,0,905},{6,0,1701},{137,0,843},{132,10,168},{4,0,974},{8,0,850},{12,0, 709},{12,0,768},{140,0,786},{135,10,91},{152,0,6},{138,10,532},{135,10,1884},{ 132,0,509},{6,0,1307},{135,0,273},{5,11,77},{7,11,1455},{10,11,843},{19,11,73},{ 150,11,5},{132,11,458},{135,11,1420},{6,11,109},{138,11,382},{6,0,201},{6,11,330 },{7,10,70},{7,11,1084},{10,10,240},{11,11,142},{147,10,93},{7,0,1041},{140,11, 328},{133,11,354},{134,0,1040},{133,0,693},{134,0,774},{139,0,234},{132,0,336},{ 7,0,1399},{139,10,392},{20,0,22},{148,11,22},{5,0,802},{7,0,2021},{136,0,805},{5 ,0,167},{5,0,899},{6,0,410},{137,0,777},{137,0,789},{134,0,1705},{7,10,655},{135 ,10,1844},{4,10,145},{6,10,176},{7,10,395},{137,10,562},{132,10,501},{135,0,10}, {5,0,11},{6,0,117},{6,0,485},{7,0,1133},{9,0,582},{9,0,594},{10,0,82},{11,0,21}, {11,0,818},{12,0,535},{13,0,86},{20,0,91},{23,0,13},{134,10,509},{4,0,264},{7,0, 1067},{8,0,204},{8,0,385},{139,0,953},{139,11,737},{138,0,56},{134,0,1917},{133, 0,470},{10,11,657},{14,11,297},{142,11,361},{135,11,412},{7,0,1198},{7,11,1198}, {8,11,556},{14,11,123},{14,11,192},{143,11,27},{7,11,1985},{14,11,146},{15,11,42 },{16,11,23},{17,11,86},{146,11,17},{11,0,1015},{136,11,122},{4,10,114},{9,10, 492},{13,10,462},{142,10,215},{4,10,77},{5,10,361},{6,10,139},{6,10,401},{6,10, 404},{7,10,413},{7,10,715},{7,10,1716},{11,10,279},{12,10,179},{12,10,258},{13, 10,244},{142,10,358},{134,10,1717},{7,10,1061},{8,10,82},{11,10,250},{12,10,420} ,{141,10,184},{133,0,715},{135,10,724},{9,0,919},{9,0,922},{9,0,927},{9,0,933},{ 9,0,962},{9,0,1000},{9,0,1002},{9,0,1021},{12,0,890},{12,0,907},{12,0,930},{15,0 ,207},{15,0,228},{15,0,238},{149,0,61},{8,0,794},{9,0,400},{10,0,298},{142,0,228 },{5,11,430},{5,11,932},{6,11,131},{7,11,417},{9,11,522},{11,11,314},{141,11,390 },{132,0,867},{8,0,724},{132,11,507},{137,11,261},{4,11,343},{133,11,511},{6,0, 190},{7,0,768},{135,0,1170},{6,10,513},{135,10,1052},{7,11,455},{138,11,591},{ 134,0,1066},{137,10,899},{14,0,67},{147,0,60},{4,0,948},{18,0,174},{146,0,176},{ 135,0,1023},{7,10,1417},{12,10,382},{17,10,48},{152,10,12},{134,11,575},{132,0, 764},{6,10,545},{7,10,565},{7,10,1669},{10,10,114},{11,10,642},{140,10,618},{6,0 ,137},{9,0,75},{9,0,253},{10,0,194},{138,0,444},{4,0,756},{133,10,5},{8,0,1008}, {135,10,192},{132,0,842},{11,0,643},{12,0,115},{136,10,763},{139,0,67},{133,10, 759},{4,0,821},{5,0,760},{7,0,542},{8,0,135},{8,0,496},{135,11,580},{7,10,370},{ 7,10,1007},{7,10,1177},{135,10,1565},{135,10,1237},{140,0,736},{7,0,319},{7,0, 355},{7,0,763},{10,0,389},{145,0,43},{8,11,333},{138,11,182},{4,10,87},{5,10,250 },{141,10,298},{138,0,786},{134,0,2044},{8,11,330},{140,11,477},{135,11,1338},{ 132,11,125},{134,0,1030},{134,0,1083},{132,11,721},{135,10,814},{7,11,776},{8,11 ,145},{147,11,56},{134,0,1226},{4,10,57},{7,10,1195},{7,10,1438},{7,10,1548},{7, 10,1835},{7,10,1904},{9,10,757},{10,10,604},{139,10,519},{7,11,792},{8,11,147},{ 10,11,821},{139,11,1021},{137,11,797},{4,0,58},{5,0,286},{6,0,319},{7,0,402},{7, 0,1254},{7,0,1903},{8,0,356},{140,0,408},{4,0,389},{4,0,815},{9,0,181},{9,0,255} ,{10,0,8},{10,0,29},{10,0,816},{11,0,311},{11,0,561},{12,0,67},{141,0,181},{7,11 ,1472},{135,11,1554},{7,11,1071},{7,11,1541},{7,11,1767},{7,11,1806},{7,11,1999} ,{9,11,248},{10,11,400},{11,11,162},{11,11,178},{11,11,242},{12,11,605},{15,11, 26},{144,11,44},{5,11,168},{5,11,930},{8,11,74},{9,11,623},{12,11,500},{12,11, 579},{13,11,41},{143,11,93},{6,11,220},{7,11,1101},{141,11,105},{5,0,474},{7,0, 507},{4,10,209},{7,11,507},{135,10,902},{132,0,427},{6,0,413},{7,10,335},{7,10, 1437},{7,10,1668},{8,10,553},{8,10,652},{8,10,656},{9,10,558},{11,10,743},{149, 10,18},{132,0,730},{6,11,19},{7,11,1413},{139,11,428},{133,0,373},{132,10,559},{ 7,11,96},{8,11,401},{137,11,896},{7,0,799},{7,0,1972},{5,10,1017},{138,10,511},{ 135,0,1793},{7,11,1961},{7,11,1965},{8,11,702},{136,11,750},{8,11,150},{8,11,737 },{140,11,366},{132,0,322},{133,10,709},{8,11,800},{9,11,148},{9,11,872},{9,11, 890},{11,11,309},{11,11,1001},{13,11,267},{141,11,323},{134,10,1745},{7,0,290},{ 136,10,206},{7,0,1651},{145,0,89},{139,0,2},{132,0,672},{6,0,1860},{8,0,905},{10 ,0,844},{10,0,846},{10,0,858},{12,0,699},{12,0,746},{140,0,772},{135,11,424},{ 133,11,547},{133,0,737},{5,11,490},{6,11,615},{6,11,620},{135,11,683},{6,0,746}, {134,0,1612},{132,10,776},{9,11,385},{149,11,17},{133,0,145},{135,10,1272},{7,0, 884},{140,0,124},{4,0,387},{135,0,1288},{5,11,133},{136,10,406},{136,11,187},{6, 0,679},{8,11,8},{138,11,0},{135,0,550},{135,11,798},{136,11,685},{7,11,1086},{ 145,11,46},{8,10,175},{10,10,168},{138,10,573},{135,0,1305},{4,0,576},{135,0, 1263},{6,0,686},{134,0,1563},{134,0,607},{5,0,919},{134,0,1673},{148,0,37},{8,11 ,774},{10,11,670},{140,11,51},{133,10,784},{139,10,882},{4,0,82},{5,0,333},{5,0, 904},{6,0,207},{7,0,325},{7,0,1726},{8,0,101},{10,0,778},{139,0,220},{135,11,371 },{132,0,958},{133,0,903},{4,11,127},{5,11,350},{6,11,356},{8,11,426},{9,11,572} ,{10,11,247},{139,11,312},{140,0,147},{6,11,59},{7,11,885},{9,11,603},{141,11, 397},{10,0,367},{9,10,14},{9,10,441},{139,10,9},{11,10,966},{12,10,287},{13,10, 342},{13,10,402},{15,10,110},{143,10,163},{134,0,690},{132,0,705},{9,0,651},{11, 0,971},{13,0,273},{7,10,1428},{7,10,1640},{7,10,1867},{9,10,169},{9,10,182},{9, 10,367},{9,10,478},{9,10,506},{9,10,551},{9,10,557},{9,10,648},{9,10,697},{9,10, 705},{9,10,725},{9,10,787},{9,10,794},{10,10,198},{10,10,214},{10,10,267},{10,10 ,275},{10,10,456},{10,10,551},{10,10,561},{10,10,613},{10,10,627},{10,10,668},{ 10,10,675},{10,10,691},{10,10,695},{10,10,707},{10,10,715},{11,10,183},{11,10, 201},{11,10,262},{11,10,352},{11,10,439},{11,10,493},{11,10,572},{11,10,591},{11 ,10,608},{11,10,611},{11,10,646},{11,10,674},{11,10,711},{11,10,751},{11,10,761} ,{11,10,776},{11,10,785},{11,10,850},{11,10,853},{11,10,862},{11,10,865},{11,10, 868},{11,10,875},{11,10,898},{11,10,902},{11,10,903},{11,10,910},{11,10,932},{11 ,10,942},{11,10,957},{11,10,967},{11,10,972},{12,10,148},{12,10,195},{12,10,220} ,{12,10,237},{12,10,318},{12,10,339},{12,10,393},{12,10,445},{12,10,450},{12,10, 474},{12,10,505},{12,10,509},{12,10,533},{12,10,591},{12,10,594},{12,10,597},{12 ,10,621},{12,10,633},{12,10,642},{13,10,59},{13,10,60},{13,10,145},{13,10,239},{ 13,10,250},{13,10,329},{13,10,344},{13,10,365},{13,10,372},{13,10,387},{13,10, 403},{13,10,414},{13,10,456},{13,10,470},{13,10,478},{13,10,483},{13,10,489},{14 ,10,55},{14,10,57},{14,10,81},{14,10,90},{14,10,148},{14,10,239},{14,10,266},{14 ,10,321},{14,10,326},{14,10,327},{14,10,330},{14,10,347},{14,10,355},{14,10,401} ,{14,10,404},{14,10,411},{14,10,414},{14,10,416},{14,10,420},{15,10,61},{15,10, 74},{15,10,87},{15,10,88},{15,10,94},{15,10,96},{15,10,116},{15,10,149},{15,10, 154},{16,10,50},{16,10,63},{16,10,73},{17,10,2},{17,10,66},{17,10,92},{17,10,103 },{17,10,112},{17,10,120},{18,10,50},{18,10,54},{18,10,82},{18,10,86},{18,10,90} ,{18,10,111},{18,10,115},{18,10,156},{19,10,40},{19,10,79},{20,10,78},{149,10,22 },{7,0,887},{5,10,161},{135,10,839},{142,11,98},{134,0,90},{138,11,356},{135,11, 441},{6,11,111},{7,11,4},{8,11,163},{8,11,776},{138,11,566},{134,0,908},{134,0, 1261},{7,0,813},{12,0,497},{141,0,56},{134,0,1235},{135,0,429},{135,11,1994},{ 138,0,904},{6,0,125},{7,0,1277},{137,0,772},{151,0,12},{4,0,841},{5,0,386},{133, 11,386},{5,11,297},{135,11,1038},{6,0,860},{6,0,1069},{135,11,309},{136,0,946},{ 135,10,1814},{141,11,418},{136,11,363},{10,0,768},{139,0,787},{22,11,30},{150,11 ,33},{6,0,160},{7,0,1106},{9,0,770},{11,0,112},{140,0,413},{11,11,216},{139,11, 340},{136,10,139},{135,11,1390},{135,11,808},{132,11,280},{12,0,271},{17,0,109}, {7,10,643},{136,10,236},{140,11,54},{4,11,421},{133,11,548},{11,0,719},{12,0,36} ,{141,0,337},{7,0,581},{9,0,644},{137,0,699},{11,11,511},{13,11,394},{14,11,298} ,{14,11,318},{146,11,103},{7,0,304},{9,0,646},{9,0,862},{11,0,696},{12,0,208},{ 15,0,79},{147,0,108},{4,0,631},{7,0,1126},{135,0,1536},{135,11,1527},{8,0,880},{ 10,0,869},{138,0,913},{7,0,1513},{5,10,54},{6,11,254},{9,11,109},{138,11,103},{ 135,0,981},{133,11,729},{132,10,744},{132,0,434},{134,0,550},{7,0,930},{10,0,476 },{13,0,452},{19,0,104},{6,11,1630},{10,10,402},{146,10,55},{5,0,553},{138,0,824 },{136,0,452},{8,0,151},{137,10,624},{132,10,572},{132,0,772},{133,11,671},{133, 0,292},{138,0,135},{132,11,889},{140,11,207},{9,0,504},{6,10,43},{7,10,38},{8,10 ,248},{138,10,513},{6,0,1089},{135,11,1910},{4,11,627},{133,11,775},{135,0,783}, {133,10,766},{133,10,363},{7,0,387},{135,11,387},{7,0,393},{10,0,603},{11,0,206} ,{7,11,202},{11,11,362},{11,11,948},{140,11,388},{6,11,507},{7,11,451},{8,11,389 },{12,11,490},{13,11,16},{13,11,215},{13,11,351},{18,11,132},{147,11,125},{4,0, 912},{9,0,232},{135,11,841},{6,10,258},{140,10,409},{5,10,249},{148,10,82},{136, 11,566},{6,0,977},{135,11,1214},{7,0,1973},{136,0,716},{135,0,98},{133,0,733},{5 ,11,912},{134,11,1695},{5,10,393},{6,10,378},{7,10,1981},{9,10,32},{9,10,591},{ 10,10,685},{10,10,741},{142,10,382},{133,10,788},{10,0,19},{11,0,911},{7,10,1968 },{141,10,509},{5,0,668},{5,11,236},{6,11,572},{8,11,492},{11,11,618},{144,11,56 },{135,11,1789},{4,0,360},{5,0,635},{5,0,700},{5,10,58},{5,10,171},{5,10,683},{6 ,10,291},{6,10,566},{7,10,1650},{11,10,523},{12,10,273},{12,10,303},{15,10,39},{ 143,10,111},{133,0,901},{134,10,589},{5,11,190},{136,11,318},{140,0,656},{7,0, 726},{152,0,9},{4,10,917},{133,10,1005},{135,10,1598},{134,11,491},{4,10,919},{ 133,11,434},{137,0,72},{6,0,1269},{6,0,1566},{134,0,1621},{9,0,463},{10,0,595},{ 4,10,255},{5,10,302},{6,10,132},{7,10,128},{7,10,283},{7,10,1299},{10,10,52},{10 ,10,514},{11,10,925},{13,10,92},{142,10,309},{135,0,1454},{134,0,1287},{11,0,600 },{13,0,245},{137,10,173},{136,0,989},{7,0,164},{7,0,1571},{9,0,107},{140,0,225} ,{6,0,1061},{141,10,442},{4,0,27},{5,0,484},{5,0,510},{6,0,434},{7,0,1000},{7,0, 1098},{136,0,2},{7,11,85},{7,11,247},{8,11,585},{10,11,163},{138,11,316},{11,11, 103},{142,11,0},{134,0,1127},{4,0,460},{134,0,852},{134,10,210},{4,0,932},{133,0 ,891},{6,0,588},{147,11,83},{8,0,625},{4,10,284},{134,10,223},{134,0,76},{8,0,92 },{137,0,221},{4,11,124},{10,11,457},{11,11,121},{11,11,169},{11,11,422},{11,11, 870},{12,11,214},{13,11,389},{14,11,187},{143,11,77},{9,11,618},{138,11,482},{4, 10,218},{7,10,526},{143,10,137},{13,0,9},{14,0,104},{14,0,311},{4,10,270},{5,10, 192},{6,10,332},{135,10,1322},{140,10,661},{135,11,1193},{6,11,107},{7,11,638},{ 7,11,1632},{137,11,396},{132,0,763},{4,0,622},{5,11,370},{134,11,1756},{133,0, 253},{135,0,546},{9,0,73},{10,0,110},{14,0,185},{17,0,119},{133,11,204},{7,0,624 },{7,0,916},{10,0,256},{139,0,87},{7,10,379},{8,10,481},{137,10,377},{5,0,212},{ 12,0,35},{13,0,382},{5,11,970},{134,11,1706},{9,0,746},{5,10,1003},{134,10,149}, {10,0,150},{11,0,849},{13,0,330},{8,10,262},{9,10,627},{11,10,214},{11,10,404},{ 11,10,457},{11,10,780},{11,10,913},{13,10,401},{142,10,200},{134,0,1466},{135,11 ,3},{6,0,1299},{4,11,35},{5,11,121},{5,11,483},{5,11,685},{6,11,489},{7,11,1204} ,{136,11,394},{135,10,742},{4,10,142},{136,10,304},{4,11,921},{133,11,1007},{134 ,0,1518},{6,0,1229},{135,0,1175},{133,0,816},{12,0,159},{4,10,471},{4,11,712},{5 ,10,51},{6,10,602},{7,10,925},{8,10,484},{138,10,195},{134,11,1629},{5,0,869},{5 ,0,968},{6,0,1626},{8,0,734},{136,0,784},{4,0,542},{6,0,1716},{6,0,1727},{7,0, 1082},{7,0,1545},{8,0,56},{8,0,118},{8,0,412},{8,0,564},{9,0,888},{9,0,908},{10, 0,50},{10,0,423},{11,0,685},{11,0,697},{11,0,933},{12,0,299},{13,0,126},{13,0, 136},{13,0,170},{13,0,190},{136,10,688},{132,10,697},{4,0,232},{9,0,202},{10,0, 474},{140,0,433},{136,0,212},{6,0,108},{7,0,1003},{7,0,1181},{8,0,111},{136,0, 343},{5,10,221},{135,11,1255},{133,11,485},{134,0,1712},{142,0,216},{5,0,643},{6 ,0,516},{4,11,285},{5,11,317},{6,11,301},{7,11,7},{8,11,153},{10,11,766},{11,11, 468},{12,11,467},{141,11,143},{4,0,133},{7,0,711},{7,0,1298},{135,0,1585},{134,0 ,650},{135,11,512},{6,0,99},{7,0,1808},{145,0,57},{6,0,246},{6,0,574},{7,0,428}, {9,0,793},{10,0,669},{11,0,485},{11,0,840},{12,0,300},{14,0,250},{145,0,55},{4, 10,132},{5,10,69},{135,10,1242},{136,0,1023},{7,0,302},{132,10,111},{135,0,1871} ,{132,0,728},{9,0,252},{132,10,767},{6,0,461},{7,0,1590},{7,10,1416},{7,10,2005} ,{8,10,131},{8,10,466},{9,10,672},{13,10,252},{148,10,103},{6,0,323},{135,0,1564 },{7,0,461},{136,0,775},{6,10,44},{136,10,368},{139,0,172},{132,0,464},{4,10,570 },{133,10,120},{137,11,269},{6,10,227},{135,10,1589},{6,11,1719},{6,11,1735},{7, 11,2016},{7,11,2020},{8,11,837},{137,11,852},{7,0,727},{146,0,73},{132,0,1023},{ 135,11,852},{135,10,1529},{136,0,577},{138,11,568},{134,0,1037},{8,11,67},{138, 11,419},{4,0,413},{5,0,677},{8,0,432},{140,0,280},{10,0,600},{6,10,1667},{7,11, 967},{7,10,2036},{141,11,11},{6,10,511},{140,10,132},{6,0,799},{5,10,568},{6,10, 138},{135,10,1293},{8,0,159},{4,10,565},{136,10,827},{7,0,646},{7,0,1730},{11,0, 446},{141,0,178},{4,10,922},{133,10,1023},{135,11,11},{132,0,395},{11,0,145},{ 135,10,1002},{9,0,174},{10,0,164},{11,0,440},{11,0,514},{11,0,841},{15,0,98},{ 149,0,20},{134,0,426},{10,0,608},{139,0,1002},{7,11,320},{8,11,51},{12,11,481},{ 12,11,570},{148,11,106},{9,0,977},{9,0,983},{132,11,445},{138,0,250},{139,0,100} ,{6,0,1982},{136,10,402},{133,11,239},{4,10,716},{141,10,31},{5,0,476},{7,11,83} ,{7,11,1990},{8,11,130},{139,11,720},{8,10,691},{136,10,731},{5,11,123},{6,11, 530},{7,11,348},{135,11,1419},{5,0,76},{6,0,458},{6,0,497},{7,0,868},{9,0,658},{ 10,0,594},{11,0,173},{11,0,566},{12,0,20},{12,0,338},{141,0,200},{9,11,139},{10, 11,399},{11,11,469},{12,11,634},{141,11,223},{9,10,840},{138,10,803},{133,10,847 },{11,11,223},{140,11,168},{132,11,210},{8,0,447},{9,10,53},{9,10,268},{9,10,901 },{10,10,518},{10,10,829},{11,10,188},{13,10,74},{14,10,46},{15,10,17},{15,10,33 },{17,10,40},{18,10,36},{19,10,20},{22,10,1},{152,10,2},{4,0,526},{7,0,1029},{ 135,0,1054},{19,11,59},{150,11,2},{4,0,636},{6,0,1875},{6,0,1920},{9,0,999},{12, 0,807},{12,0,825},{15,0,179},{15,0,190},{18,0,182},{136,10,532},{6,0,1699},{7,0, 660},{7,0,1124},{17,0,31},{19,0,22},{151,0,14},{135,10,681},{132,11,430},{140,10 ,677},{4,10,684},{136,10,384},{132,11,756},{133,11,213},{7,0,188},{7,10,110},{8, 10,290},{8,10,591},{9,10,382},{9,10,649},{11,10,71},{11,10,155},{11,10,313},{12, 10,5},{13,10,325},{142,10,287},{7,10,360},{7,10,425},{9,10,66},{9,10,278},{138, 10,644},{142,11,164},{4,0,279},{7,0,301},{137,0,362},{134,11,586},{135,0,1743},{ 4,0,178},{133,0,399},{4,10,900},{133,10,861},{5,10,254},{7,10,985},{136,10,73},{ 133,11,108},{7,10,1959},{136,10,683},{133,11,219},{4,11,193},{5,11,916},{7,11, 364},{10,11,398},{10,11,726},{11,11,317},{11,11,626},{12,11,142},{12,11,288},{12 ,11,678},{13,11,313},{15,11,113},{18,11,114},{21,11,30},{150,11,53},{6,11,241},{ 7,11,907},{8,11,832},{9,11,342},{10,11,729},{11,11,284},{11,11,445},{11,11,651}, {11,11,863},{13,11,398},{146,11,99},{132,0,872},{134,0,831},{134,0,1692},{6,0, 202},{6,0,1006},{9,0,832},{10,0,636},{11,0,208},{12,0,360},{17,0,118},{18,0,27}, {20,0,67},{137,11,734},{132,10,725},{7,11,993},{138,11,666},{134,0,1954},{134,10 ,196},{7,0,872},{10,0,516},{139,0,167},{133,10,831},{4,11,562},{9,11,254},{139, 11,879},{137,0,313},{4,0,224},{132,11,786},{11,0,24},{12,0,170},{136,10,723},{5, 0,546},{7,0,35},{8,0,11},{8,0,12},{9,0,315},{9,0,533},{10,0,802},{11,0,166},{12, 0,525},{142,0,243},{7,0,1937},{13,10,80},{13,10,437},{145,10,74},{5,0,241},{8,0, 242},{9,0,451},{10,0,667},{11,0,598},{140,0,429},{150,0,46},{6,0,1273},{137,0, 830},{5,10,848},{6,10,66},{136,10,764},{6,0,825},{134,0,993},{4,0,1006},{10,0, 327},{13,0,271},{4,10,36},{7,10,1387},{139,10,755},{134,0,1023},{135,0,1580},{4, 0,366},{137,0,516},{132,10,887},{6,0,1736},{135,0,1891},{6,11,216},{7,11,901},{7 ,11,1343},{136,11,493},{6,10,165},{138,10,388},{7,11,341},{139,11,219},{4,10,719 },{135,10,155},{134,0,1935},{132,0,826},{6,0,331},{6,0,1605},{8,0,623},{11,0,139 },{139,0,171},{135,11,1734},{10,11,115},{11,11,420},{12,11,154},{13,11,404},{14, 11,346},{15,11,54},{143,11,112},{7,0,288},{4,10,353},{6,10,146},{6,10,1789},{7, 10,990},{7,10,1348},{9,10,665},{9,10,898},{11,10,893},{142,10,212},{6,0,916},{ 134,0,1592},{7,0,1888},{4,10,45},{135,10,1257},{5,11,1011},{136,11,701},{139,11, 596},{4,11,54},{5,11,666},{7,11,1039},{7,11,1130},{9,11,195},{138,11,302},{134,0 ,1471},{134,0,1570},{132,0,394},{140,10,65},{136,10,816},{135,0,1931},{7,0,574}, {135,0,1719},{134,11,467},{132,0,658},{9,0,781},{10,0,144},{11,0,385},{13,0,161} ,{13,0,228},{13,0,268},{20,0,107},{134,11,1669},{136,0,374},{135,0,735},{4,0,344 },{6,0,498},{139,0,323},{7,0,586},{7,0,1063},{6,10,559},{134,10,1691},{137,0,155 },{133,0,906},{7,11,122},{9,11,259},{10,11,84},{11,11,470},{12,11,541},{141,11, 379},{134,0,1139},{10,0,108},{139,0,116},{134,10,456},{133,10,925},{5,11,82},{5, 11,131},{7,11,1755},{8,11,31},{9,11,168},{9,11,764},{139,11,869},{134,11,605},{5 ,11,278},{137,11,68},{4,11,163},{5,11,201},{5,11,307},{5,11,310},{6,11,335},{7, 11,284},{136,11,165},{135,11,1660},{6,11,33},{135,11,1244},{4,0,616},{136,11,483 },{8,0,857},{8,0,902},{8,0,910},{10,0,879},{12,0,726},{4,11,199},{139,11,34},{ 136,0,692},{6,10,193},{7,10,240},{7,10,1682},{10,10,51},{10,10,640},{11,10,410}, {13,10,82},{14,10,247},{14,10,331},{142,10,377},{6,0,823},{134,0,983},{139,10, 411},{132,0,305},{136,10,633},{138,11,203},{134,0,681},{6,11,326},{7,11,677},{ 137,11,425},{5,0,214},{7,0,603},{8,0,611},{9,0,686},{10,0,88},{11,0,459},{11,0, 496},{12,0,463},{12,0,590},{141,0,0},{136,0,1004},{142,0,23},{134,0,1703},{147, 11,8},{145,11,56},{135,0,1443},{4,10,237},{135,10,514},{6,0,714},{145,0,19},{5, 11,358},{7,11,473},{7,11,1184},{10,11,662},{13,11,212},{13,11,304},{13,11,333},{ 145,11,98},{4,0,737},{10,0,98},{11,0,294},{12,0,60},{12,0,437},{13,0,64},{13,0, 380},{142,0,430},{6,10,392},{7,10,65},{135,10,2019},{6,0,1758},{8,0,520},{9,0, 345},{9,0,403},{142,0,350},{5,0,47},{10,0,242},{138,0,579},{5,0,139},{7,0,1168}, {138,0,539},{134,0,1459},{13,0,388},{141,11,388},{134,0,253},{7,10,1260},{135,10 ,1790},{10,0,252},{9,10,222},{139,10,900},{140,0,745},{133,11,946},{4,0,107},{7, 0,613},{8,0,439},{8,0,504},{9,0,501},{10,0,383},{139,0,477},{135,11,1485},{132,0 ,871},{7,11,411},{7,11,590},{8,11,631},{9,11,323},{10,11,355},{11,11,491},{12,11 ,143},{12,11,402},{13,11,73},{14,11,408},{15,11,107},{146,11,71},{132,0,229},{ 132,0,903},{140,0,71},{133,0,549},{4,0,47},{6,0,373},{7,0,452},{7,0,543},{7,0, 1828},{7,0,1856},{9,0,6},{11,0,257},{139,0,391},{7,11,1467},{8,11,328},{10,11, 544},{11,11,955},{13,11,320},{145,11,83},{5,0,980},{134,0,1754},{136,0,865},{5,0 ,705},{137,0,606},{7,0,161},{8,10,201},{136,10,605},{143,11,35},{5,11,835},{6,11 ,483},{140,10,224},{7,0,536},{7,0,1331},{136,0,143},{134,0,1388},{5,0,724},{10,0 ,305},{11,0,151},{12,0,33},{12,0,121},{12,0,381},{17,0,3},{17,0,27},{17,0,78},{ 18,0,18},{19,0,54},{149,0,5},{4,10,523},{133,10,638},{5,0,19},{134,0,533},{5,0, 395},{5,0,951},{134,0,1776},{135,0,1908},{132,0,846},{10,0,74},{11,0,663},{12,0, 210},{13,0,166},{13,0,310},{14,0,373},{18,0,95},{19,0,43},{6,10,242},{7,10,227}, {7,10,1581},{8,10,104},{9,10,113},{9,10,220},{9,10,427},{10,10,239},{11,10,579}, {11,10,1023},{13,10,4},{13,10,204},{13,10,316},{148,10,86},{9,11,716},{11,11,108 },{13,11,123},{14,11,252},{19,11,38},{21,11,3},{151,11,11},{8,0,372},{9,0,122},{ 138,0,175},{132,11,677},{7,11,1374},{136,11,540},{135,10,861},{132,0,695},{7,0, 497},{9,0,387},{147,0,81},{136,0,937},{134,0,718},{7,0,1328},{136,10,494},{132, 11,331},{6,0,1581},{133,11,747},{5,0,284},{6,0,49},{6,0,350},{7,0,1},{7,0,377},{ 7,0,1693},{8,0,18},{8,0,678},{9,0,161},{9,0,585},{9,0,671},{9,0,839},{11,0,912}, {141,0,427},{7,10,1306},{8,10,505},{9,10,482},{10,10,126},{11,10,225},{12,10,347 },{12,10,449},{13,10,19},{14,10,218},{142,10,435},{10,10,764},{12,10,120},{13,10 ,39},{145,10,127},{4,0,597},{133,10,268},{134,0,1094},{4,0,1008},{134,0,1973},{ 132,0,811},{139,0,908},{135,0,1471},{133,11,326},{4,10,384},{135,10,1022},{7,0, 1935},{8,0,324},{12,0,42},{4,11,691},{7,11,1935},{8,11,324},{9,11,35},{10,11,680 },{11,11,364},{12,11,42},{13,11,357},{146,11,16},{135,0,2014},{7,0,2007},{9,0, 101},{9,0,450},{10,0,66},{10,0,842},{11,0,536},{12,0,587},{6,11,32},{7,11,385},{ 7,11,757},{7,11,1916},{8,11,37},{8,11,94},{8,11,711},{9,11,541},{10,11,162},{10, 11,795},{11,11,989},{11,11,1010},{12,11,14},{142,11,308},{139,0,586},{135,10, 1703},{7,0,1077},{11,0,28},{9,10,159},{140,10,603},{6,0,1221},{136,10,583},{6,11 ,152},{6,11,349},{6,11,1682},{7,11,1252},{8,11,112},{9,11,435},{9,11,668},{10,11 ,290},{10,11,319},{10,11,815},{11,11,180},{11,11,837},{12,11,240},{13,11,152},{ 13,11,219},{142,11,158},{139,0,62},{132,10,515},{8,10,632},{8,10,697},{137,10, 854},{134,0,1766},{132,11,581},{6,11,126},{7,11,573},{8,11,397},{142,11,44},{150 ,0,28},{11,0,670},{22,0,25},{4,10,136},{133,10,551},{6,0,1665},{7,0,256},{7,0, 1388},{138,0,499},{4,0,22},{5,0,10},{7,0,1576},{136,0,97},{134,10,1782},{5,0,481 },{7,10,1287},{9,10,44},{10,10,552},{10,10,642},{11,10,839},{12,10,274},{12,10, 275},{12,10,372},{13,10,91},{142,10,125},{133,11,926},{7,11,1232},{137,11,531},{ 6,0,134},{7,0,437},{7,0,1824},{9,0,37},{14,0,285},{142,0,371},{7,0,486},{8,0,155 },{11,0,93},{140,0,164},{6,0,1391},{134,0,1442},{133,11,670},{133,0,591},{6,10, 147},{7,10,886},{7,11,1957},{9,10,753},{138,10,268},{5,0,380},{5,0,650},{7,0, 1173},{136,0,310},{4,0,364},{7,0,1156},{7,0,1187},{137,0,409},{135,11,1621},{134 ,0,482},{133,11,506},{4,0,781},{6,0,487},{7,0,926},{8,0,263},{139,0,500},{138,10 ,137},{135,11,242},{139,11,96},{133,10,414},{135,10,1762},{134,0,804},{5,11,834} ,{7,11,1202},{8,11,14},{9,11,481},{137,11,880},{134,10,599},{4,0,94},{135,0,1265 },{4,0,415},{132,0,417},{5,0,348},{6,0,522},{6,10,1749},{7,11,1526},{138,11,465} ,{134,10,1627},{132,0,1012},{132,10,488},{4,11,357},{6,11,172},{7,11,143},{137, 11,413},{4,10,83},{4,11,590},{146,11,76},{140,10,676},{7,11,287},{8,11,355},{9, 11,293},{137,11,743},{134,10,278},{6,0,1803},{18,0,165},{24,0,21},{5,11,169},{7, 11,333},{136,11,45},{12,10,97},{140,11,97},{4,0,408},{4,0,741},{135,0,500},{132, 11,198},{7,10,388},{7,10,644},{139,10,781},{4,11,24},{5,11,140},{5,11,185},{7,11 ,1500},{11,11,565},{139,11,838},{6,0,1321},{9,0,257},{7,10,229},{8,10,59},{9,10, 190},{10,10,378},{140,10,191},{4,11,334},{133,11,593},{135,11,1885},{134,0,1138} ,{4,0,249},{6,0,73},{135,0,177},{133,0,576},{142,0,231},{137,0,288},{132,10,660} ,{7,10,1035},{138,10,737},{135,0,1487},{6,0,989},{9,0,433},{7,10,690},{9,10,587} ,{140,10,521},{7,0,1264},{7,0,1678},{11,0,945},{12,0,341},{12,0,471},{140,0,569} ,{132,11,709},{133,11,897},{5,11,224},{13,11,174},{146,11,52},{135,11,1840},{134 ,10,1744},{12,0,87},{16,0,74},{4,10,733},{9,10,194},{10,10,92},{11,10,198},{12, 10,84},{141,10,128},{140,0,779},{135,0,538},{4,11,608},{133,11,497},{133,0,413}, {7,11,1375},{7,11,1466},{138,11,331},{136,0,495},{6,11,540},{136,11,136},{7,0,54 },{8,0,312},{10,0,191},{10,0,614},{140,0,567},{6,0,468},{7,0,567},{7,0,1478},{8, 0,530},{14,0,290},{133,11,999},{4,11,299},{7,10,306},{135,11,1004},{142,11,296}, {134,0,1484},{133,10,979},{6,0,609},{9,0,815},{12,11,137},{14,11,9},{14,11,24},{ 142,11,64},{133,11,456},{6,0,484},{135,0,822},{133,10,178},{136,11,180},{132,11, 755},{137,0,900},{135,0,1335},{6,0,1724},{135,0,2022},{135,11,1139},{5,0,640},{ 132,10,390},{6,0,1831},{138,11,633},{135,11,566},{4,11,890},{5,11,805},{5,11,819 },{5,11,961},{6,11,396},{6,11,1631},{6,11,1678},{7,11,1967},{7,11,2041},{9,11, 630},{11,11,8},{11,11,1019},{12,11,176},{13,11,225},{14,11,292},{149,11,24},{132 ,0,474},{134,0,1103},{135,0,1504},{134,0,1576},{6,0,961},{6,0,1034},{140,0,655}, {11,11,514},{149,11,20},{5,0,305},{135,11,1815},{7,11,1505},{10,11,190},{10,11, 634},{11,11,792},{12,11,358},{140,11,447},{5,11,0},{6,11,536},{7,11,604},{13,11, 445},{145,11,126},{7,0,1236},{133,10,105},{4,0,480},{6,0,217},{6,0,302},{6,0, 1642},{7,0,130},{7,0,837},{7,0,1321},{7,0,1547},{7,0,1657},{8,0,429},{9,0,228},{ 13,0,289},{13,0,343},{19,0,101},{6,11,232},{6,11,412},{7,11,1074},{8,11,9},{8,11 ,157},{8,11,786},{9,11,196},{9,11,352},{9,11,457},{10,11,337},{11,11,232},{11,11 ,877},{12,11,480},{140,11,546},{5,10,438},{7,11,958},{9,10,694},{12,10,627},{13, 11,38},{141,10,210},{4,11,382},{136,11,579},{7,0,278},{10,0,739},{11,0,708},{141 ,0,348},{4,11,212},{135,11,1206},{135,11,1898},{6,0,708},{6,0,1344},{152,10,11}, {137,11,768},{134,0,1840},{140,0,233},{8,10,25},{138,10,826},{6,0,2017},{133,11, 655},{6,0,1488},{139,11,290},{132,10,308},{134,0,1590},{134,0,1800},{134,0,1259} ,{16,0,28},{6,11,231},{7,11,95},{136,11,423},{133,11,300},{135,10,150},{136,10, 649},{7,11,1874},{137,11,641},{6,11,237},{7,11,611},{8,11,100},{9,11,416},{11,11 ,335},{12,11,173},{146,11,101},{137,0,45},{134,10,521},{17,0,36},{14,11,26},{146 ,11,150},{7,0,1442},{14,0,22},{5,10,339},{15,10,41},{15,10,166},{147,10,66},{8,0 ,378},{6,11,581},{135,11,1119},{134,0,1507},{147,11,117},{139,0,39},{134,0,1054} ,{6,0,363},{7,0,1955},{136,0,725},{134,0,2036},{133,11,199},{6,0,1871},{9,0,935} ,{9,0,961},{9,0,1004},{9,0,1016},{12,0,805},{12,0,852},{12,0,853},{12,0,869},{12 ,0,882},{12,0,896},{12,0,906},{12,0,917},{12,0,940},{15,0,170},{15,0,176},{15,0, 188},{15,0,201},{15,0,205},{15,0,212},{15,0,234},{15,0,244},{18,0,181},{18,0,193 },{18,0,196},{18,0,201},{18,0,202},{18,0,210},{18,0,217},{18,0,235},{18,0,236},{ 18,0,237},{21,0,54},{21,0,55},{21,0,58},{21,0,59},{152,0,22},{134,10,1628},{137, 0,805},{5,0,813},{135,0,2046},{142,11,42},{5,0,712},{6,0,1240},{11,0,17},{13,0, 321},{144,0,67},{132,0,617},{135,10,829},{6,0,320},{7,0,781},{7,0,1921},{9,0,55} ,{10,0,186},{10,0,273},{10,0,664},{10,0,801},{11,0,996},{11,0,997},{13,0,157},{ 142,0,170},{136,0,271},{5,10,486},{135,10,1349},{18,11,91},{147,11,70},{10,0,445 },{7,10,1635},{8,10,17},{138,10,295},{136,11,404},{7,0,103},{7,0,863},{11,0,184} ,{145,0,62},{138,10,558},{137,0,659},{6,11,312},{6,11,1715},{10,11,584},{11,11, 546},{11,11,692},{12,11,259},{12,11,295},{13,11,46},{141,11,154},{134,0,676},{ 132,11,588},{4,11,231},{5,11,61},{6,11,104},{7,11,729},{7,11,964},{7,11,1658},{ 140,11,414},{6,11,263},{138,11,757},{11,0,337},{142,0,303},{135,11,1363},{132,11 ,320},{140,0,506},{134,10,447},{5,0,77},{7,0,1455},{10,0,843},{147,0,73},{7,10, 577},{7,10,1432},{9,10,475},{9,10,505},{9,10,526},{9,10,609},{9,10,689},{9,10, 726},{9,10,735},{9,10,738},{10,10,556},{10,10,674},{10,10,684},{11,10,89},{11,10 ,202},{11,10,272},{11,10,380},{11,10,415},{11,10,505},{11,10,537},{11,10,550},{ 11,10,562},{11,10,640},{11,10,667},{11,10,688},{11,10,847},{11,10,927},{11,10, 930},{11,10,940},{12,10,144},{12,10,325},{12,10,329},{12,10,389},{12,10,403},{12 ,10,451},{12,10,515},{12,10,604},{12,10,616},{12,10,626},{13,10,66},{13,10,131}, {13,10,167},{13,10,236},{13,10,368},{13,10,411},{13,10,434},{13,10,453},{13,10, 461},{13,10,474},{14,10,59},{14,10,60},{14,10,139},{14,10,152},{14,10,276},{14, 10,353},{14,10,402},{15,10,28},{15,10,81},{15,10,123},{15,10,152},{18,10,136},{ 148,10,88},{132,0,458},{135,0,1420},{6,0,109},{10,0,382},{4,11,405},{4,10,609},{ 7,10,756},{7,11,817},{9,10,544},{11,10,413},{14,11,58},{14,10,307},{16,10,25},{ 17,11,37},{146,11,124},{6,0,330},{7,0,1084},{11,0,142},{133,11,974},{4,10,930},{ 133,10,947},{5,10,939},{142,11,394},{16,0,91},{145,0,87},{5,11,235},{5,10,962},{ 7,11,1239},{11,11,131},{140,11,370},{11,0,492},{5,10,651},{8,10,170},{9,10,61},{ 9,10,63},{10,10,23},{10,10,37},{10,10,834},{11,10,4},{11,10,281},{11,10,503},{11 ,10,677},{12,10,96},{12,10,130},{12,10,244},{14,10,5},{14,10,40},{14,10,162},{14 ,10,202},{146,10,133},{4,10,406},{5,10,579},{12,10,492},{150,10,15},{9,11,137},{ 138,11,221},{134,0,1239},{11,0,211},{140,0,145},{7,11,390},{138,11,140},{135,11, 1418},{135,11,1144},{134,0,1049},{7,0,321},{6,10,17},{7,10,1001},{7,10,1982},{9, 10,886},{10,10,489},{10,10,800},{11,10,782},{12,10,320},{13,10,467},{14,10,145}, {14,10,387},{143,10,119},{145,10,17},{5,11,407},{11,11,489},{19,11,37},{20,11,73 },{150,11,38},{133,10,458},{135,0,1985},{7,10,1983},{8,10,0},{8,10,171},{9,10, 120},{9,10,732},{10,10,473},{11,10,656},{11,10,998},{18,10,0},{18,10,2},{147,10, 21},{5,11,325},{7,11,1483},{8,11,5},{8,11,227},{9,11,105},{10,11,585},{140,11, 614},{136,0,122},{132,0,234},{135,11,1196},{6,0,976},{6,0,1098},{134,0,1441},{7, 0,253},{136,0,549},{6,11,621},{13,11,504},{144,11,19},{132,10,519},{5,0,430},{5, 0,932},{6,0,131},{7,0,417},{9,0,522},{11,0,314},{141,0,390},{14,0,149},{14,0,399 },{143,0,57},{5,10,907},{6,10,31},{6,11,218},{7,10,491},{7,10,530},{8,10,592},{ 11,10,53},{11,10,779},{12,10,167},{12,10,411},{14,10,14},{14,10,136},{15,10,72}, {16,10,17},{144,10,72},{140,11,330},{7,11,454},{7,11,782},{136,11,768},{132,0, 507},{10,11,676},{140,11,462},{6,0,630},{9,0,811},{4,10,208},{5,10,106},{6,10, 531},{8,10,408},{9,10,188},{138,10,572},{4,0,343},{5,0,511},{134,10,1693},{134, 11,164},{132,0,448},{7,0,455},{138,0,591},{135,0,1381},{12,10,441},{150,11,50},{ 9,10,449},{10,10,192},{138,10,740},{6,0,575},{132,10,241},{134,0,1175},{134,0, 653},{134,0,1761},{134,0,1198},{132,10,259},{6,11,343},{7,11,195},{9,11,226},{10 ,11,197},{10,11,575},{11,11,502},{139,11,899},{7,0,1127},{7,0,1572},{10,0,297},{ 10,0,422},{11,0,764},{11,0,810},{12,0,264},{13,0,102},{13,0,300},{13,0,484},{14, 0,147},{14,0,229},{17,0,71},{18,0,118},{147,0,120},{135,11,666},{132,0,678},{4, 10,173},{5,10,312},{5,10,512},{135,10,1285},{7,10,1603},{7,10,1691},{9,10,464},{ 11,10,195},{12,10,279},{12,10,448},{14,10,11},{147,10,102},{16,0,99},{146,0,164} ,{7,11,1125},{9,11,143},{11,11,61},{14,11,405},{150,11,21},{137,11,260},{4,10, 452},{5,10,583},{5,10,817},{6,10,433},{7,10,593},{7,10,720},{7,10,1378},{8,10, 161},{9,10,284},{10,10,313},{139,10,886},{132,10,547},{136,10,722},{14,0,35},{ 142,0,191},{141,0,45},{138,0,121},{132,0,125},{134,0,1622},{133,11,959},{8,10, 420},{139,10,193},{132,0,721},{135,10,409},{136,0,145},{7,0,792},{8,0,147},{10,0 ,821},{11,0,970},{11,0,1021},{136,11,173},{134,11,266},{132,0,715},{7,0,1999},{ 138,10,308},{133,0,531},{5,0,168},{5,0,930},{8,0,74},{9,0,623},{12,0,500},{140,0 ,579},{144,0,65},{138,11,246},{6,0,220},{7,0,1101},{13,0,105},{142,11,314},{5,10 ,1002},{136,10,745},{134,0,960},{20,0,0},{148,11,0},{4,0,1005},{4,10,239},{6,10, 477},{7,10,1607},{11,10,68},{139,10,617},{6,0,19},{7,0,1413},{139,0,428},{149,10 ,13},{7,0,96},{8,0,401},{8,0,703},{9,0,896},{136,11,300},{134,0,1595},{145,0,116 },{136,0,1021},{7,0,1961},{7,0,1965},{7,0,2030},{8,0,150},{8,0,702},{8,0,737},{8 ,0,750},{140,0,366},{11,11,75},{142,11,267},{132,10,367},{8,0,800},{9,0,148},{9, 0,872},{9,0,890},{11,0,309},{11,0,1001},{13,0,267},{13,0,323},{5,11,427},{5,11, 734},{7,11,478},{136,11,52},{7,11,239},{11,11,217},{142,11,165},{132,11,323},{ 140,11,419},{13,0,299},{142,0,75},{6,11,87},{6,11,1734},{7,11,20},{7,11,1056},{8 ,11,732},{9,11,406},{9,11,911},{138,11,694},{134,0,1383},{132,10,694},{133,11, 613},{137,0,779},{4,0,598},{140,10,687},{6,0,970},{135,0,424},{133,0,547},{7,11, 32},{7,11,984},{8,11,85},{8,11,709},{9,11,579},{9,11,847},{9,11,856},{10,11,799} ,{11,11,258},{11,11,1007},{12,11,331},{12,11,615},{13,11,188},{13,11,435},{14,11 ,8},{15,11,165},{16,11,27},{148,11,40},{6,0,1222},{134,0,1385},{132,0,876},{138, 11,151},{135,10,213},{4,11,167},{135,11,82},{133,0,133},{6,11,24},{7,11,74},{7, 11,678},{137,11,258},{5,11,62},{6,11,534},{7,11,684},{7,11,1043},{7,11,1072},{8, 11,280},{8,11,541},{8,11,686},{10,11,519},{11,11,252},{140,11,282},{136,0,187},{ 8,0,8},{10,0,0},{10,0,818},{139,0,988},{132,11,359},{11,0,429},{15,0,51},{135,10 ,1672},{136,0,685},{5,11,211},{7,11,88},{136,11,627},{134,0,472},{136,0,132},{6, 11,145},{141,11,336},{4,10,751},{11,10,390},{140,10,32},{6,0,938},{6,0,1060},{4, 11,263},{4,10,409},{133,10,78},{137,0,874},{8,0,774},{10,0,670},{12,0,51},{4,11, 916},{6,10,473},{7,10,1602},{10,10,698},{12,10,212},{13,10,307},{145,10,105},{ 146,0,92},{143,10,156},{132,0,830},{137,0,701},{4,11,599},{6,11,1634},{7,11,5},{ 7,11,55},{7,11,67},{7,11,97},{7,11,691},{7,11,979},{7,11,1697},{8,11,207},{8,11, 214},{8,11,231},{8,11,294},{8,11,336},{8,11,428},{8,11,451},{8,11,460},{8,11,471 },{8,11,622},{8,11,626},{8,11,679},{8,11,759},{8,11,829},{9,11,11},{9,11,246},{9 ,11,484},{9,11,573},{9,11,706},{9,11,762},{9,11,798},{9,11,855},{9,11,870},{9,11 ,912},{10,11,303},{10,11,335},{10,11,424},{10,11,461},{10,11,543},{10,11,759},{ 10,11,814},{11,11,59},{11,11,199},{11,11,235},{11,11,475},{11,11,590},{11,11,929 },{11,11,963},{12,11,114},{12,11,182},{12,11,226},{12,11,332},{12,11,439},{12,11 ,575},{12,11,598},{13,11,8},{13,11,125},{13,11,194},{13,11,287},{14,11,197},{14, 11,383},{15,11,53},{17,11,63},{19,11,46},{19,11,98},{19,11,106},{148,11,85},{4,0 ,127},{5,0,350},{6,0,356},{8,0,426},{9,0,572},{10,0,247},{139,0,312},{134,0,1215 },{6,0,59},{9,0,603},{13,0,397},{7,11,1853},{138,11,437},{134,0,1762},{147,11, 126},{135,10,883},{13,0,293},{142,0,56},{133,10,617},{139,10,50},{5,11,187},{7, 10,1518},{139,10,694},{135,0,441},{6,0,111},{7,0,4},{8,0,163},{8,0,776},{138,0, 566},{132,0,806},{4,11,215},{9,11,38},{10,11,3},{11,11,23},{11,11,127},{139,11, 796},{14,0,233},{4,10,546},{135,10,2042},{135,0,1994},{134,0,1739},{135,11,1530} ,{136,0,393},{5,0,297},{7,0,1038},{14,0,359},{19,0,52},{148,0,47},{135,0,309},{4 ,10,313},{133,10,577},{8,10,184},{141,10,433},{135,10,935},{12,10,186},{12,10, 292},{14,10,100},{146,10,70},{136,0,363},{14,0,175},{11,10,402},{12,10,109},{12, 10,431},{13,10,179},{13,10,206},{14,10,217},{16,10,3},{148,10,53},{5,10,886},{6, 10,46},{6,10,1790},{7,10,14},{7,10,732},{7,10,1654},{8,10,95},{8,10,327},{8,10, 616},{9,10,892},{10,10,598},{10,10,769},{11,10,134},{11,10,747},{12,10,378},{142 ,10,97},{136,0,666},{135,0,1675},{6,0,655},{134,0,1600},{135,0,808},{133,10,1021 },{4,11,28},{5,11,440},{7,11,248},{11,11,833},{140,11,344},{134,11,1654},{132,0, 280},{140,0,54},{4,0,421},{133,0,548},{132,10,153},{6,11,339},{135,11,923},{133, 11,853},{133,10,798},{132,10,587},{6,11,249},{7,11,1234},{139,11,573},{6,10,598} ,{7,10,42},{8,10,695},{10,10,212},{11,10,158},{14,10,196},{145,10,85},{7,0,249}, {5,10,957},{133,10,1008},{4,10,129},{135,10,465},{6,0,254},{7,0,842},{7,0,1659}, {9,0,109},{10,0,103},{7,10,908},{7,10,1201},{9,10,755},{11,10,906},{12,10,527},{ 146,10,7},{5,0,262},{136,10,450},{144,0,1},{10,11,201},{142,11,319},{7,11,49},{7 ,11,392},{8,11,20},{8,11,172},{8,11,690},{9,11,383},{9,11,845},{10,11,48},{11,11 ,293},{11,11,832},{11,11,920},{141,11,221},{5,11,858},{133,11,992},{134,0,805},{ 139,10,1003},{6,0,1630},{134,11,307},{7,11,1512},{135,11,1794},{6,11,268},{137, 11,62},{135,10,1868},{133,0,671},{4,0,989},{8,0,972},{136,0,998},{132,11,423},{ 132,0,889},{135,0,1382},{135,0,1910},{7,10,965},{7,10,1460},{135,10,1604},{4,0, 627},{5,0,775},{138,11,106},{134,11,348},{7,0,202},{11,0,362},{11,0,948},{140,0, 388},{138,11,771},{6,11,613},{136,11,223},{6,0,560},{7,0,451},{8,0,389},{12,0, 490},{13,0,16},{13,0,215},{13,0,351},{18,0,132},{147,0,125},{135,0,841},{136,0, 566},{136,0,938},{132,11,670},{5,0,912},{6,0,1695},{140,11,55},{9,11,40},{139,11 ,136},{7,0,1361},{7,10,982},{10,10,32},{143,10,56},{11,11,259},{140,11,270},{5,0 ,236},{6,0,572},{8,0,492},{11,0,618},{144,0,56},{8,11,572},{9,11,310},{9,11,682} ,{137,11,698},{134,0,1854},{5,0,190},{136,0,318},{133,10,435},{135,0,1376},{4,11 ,296},{6,11,352},{7,11,401},{7,11,1410},{7,11,1594},{7,11,1674},{8,11,63},{8,11, 660},{137,11,74},{7,0,349},{5,10,85},{6,10,419},{7,10,305},{7,10,361},{7,10,1337 },{8,10,71},{140,10,519},{4,11,139},{4,11,388},{140,11,188},{6,0,1972},{6,0,2013 },{8,0,951},{10,0,947},{10,0,974},{10,0,1018},{142,0,476},{140,10,688},{135,10, 740},{5,10,691},{7,10,345},{9,10,94},{140,10,169},{9,0,344},{5,10,183},{6,10,582 },{10,10,679},{140,10,435},{135,10,511},{132,0,850},{8,11,441},{10,11,314},{143, 11,3},{7,10,1993},{136,10,684},{4,11,747},{6,11,290},{6,10,583},{7,11,649},{7,11 ,1479},{135,11,1583},{133,11,232},{133,10,704},{134,0,910},{4,10,179},{5,10,198} ,{133,10,697},{7,10,347},{7,10,971},{8,10,181},{138,10,711},{136,11,525},{14,0, 19},{14,0,28},{144,0,29},{7,0,85},{7,0,247},{8,0,585},{138,0,163},{4,0,487},{7, 11,472},{7,11,1801},{10,11,748},{141,11,458},{4,10,243},{5,10,203},{7,10,19},{7, 10,71},{7,10,113},{10,10,405},{11,10,357},{142,10,240},{7,10,1450},{139,10,99},{ 132,11,425},{138,0,145},{147,0,83},{6,10,492},{137,11,247},{4,0,1013},{134,0, 2033},{5,10,134},{6,10,408},{6,10,495},{135,10,1593},{135,0,1922},{134,11,1768}, {4,0,124},{10,0,457},{11,0,121},{11,0,169},{11,0,870},{11,0,874},{12,0,214},{14, 0,187},{143,0,77},{5,0,557},{135,0,1457},{139,0,66},{5,11,943},{6,11,1779},{142, 10,4},{4,10,248},{4,10,665},{7,10,137},{137,10,349},{7,0,1193},{5,11,245},{6,11, 576},{7,11,582},{136,11,225},{144,0,82},{7,10,1270},{139,10,612},{5,0,454},{10,0 ,352},{138,11,352},{18,0,57},{5,10,371},{135,10,563},{135,0,1333},{6,0,107},{7,0 ,638},{7,0,1632},{9,0,396},{134,11,610},{5,0,370},{134,0,1756},{4,10,374},{7,10, 547},{7,10,1700},{7,10,1833},{139,10,858},{133,0,204},{6,0,1305},{9,10,311},{141 ,10,42},{5,0,970},{134,0,1706},{6,10,1647},{7,10,1552},{7,10,2010},{9,10,494},{ 137,10,509},{13,11,455},{15,11,99},{15,11,129},{144,11,68},{135,0,3},{4,0,35},{5 ,0,121},{5,0,483},{5,0,685},{6,0,489},{6,0,782},{6,0,1032},{7,0,1204},{136,0,394 },{4,0,921},{133,0,1007},{8,11,360},{138,11,63},{135,0,1696},{134,0,1519},{132, 11,443},{135,11,944},{6,10,123},{7,10,214},{9,10,728},{10,10,157},{11,10,346},{ 11,10,662},{143,10,106},{137,0,981},{135,10,1435},{134,0,1072},{132,0,712},{134, 0,1629},{134,0,728},{4,11,298},{137,11,483},{6,0,1177},{6,0,1271},{5,11,164},{7, 11,121},{142,11,189},{7,0,1608},{4,10,707},{5,10,588},{6,10,393},{13,10,106},{18 ,10,49},{147,10,41},{23,0,16},{151,11,16},{6,10,211},{7,10,1690},{11,10,486},{ 140,10,369},{133,0,485},{19,11,15},{149,11,27},{4,11,172},{9,11,611},{10,11,436} ,{12,11,673},{141,11,255},{5,11,844},{10,11,484},{11,11,754},{12,11,457},{14,11, 171},{14,11,389},{146,11,153},{4,0,285},{5,0,27},{5,0,317},{6,0,301},{7,0,7},{8, 0,153},{10,0,766},{11,0,468},{12,0,467},{141,0,143},{134,0,1462},{9,11,263},{10, 11,147},{138,11,492},{133,11,537},{6,0,1945},{6,0,1986},{6,0,1991},{134,0,2038}, {134,10,219},{137,11,842},{14,0,52},{17,0,50},{5,10,582},{6,10,1646},{7,10,99},{ 7,10,1962},{7,10,1986},{8,10,515},{8,10,773},{9,10,23},{9,10,491},{12,10,620},{ 142,10,93},{138,11,97},{20,0,21},{20,0,44},{133,10,851},{136,0,819},{139,0,917}, {5,11,230},{5,11,392},{6,11,420},{8,10,762},{8,10,812},{9,11,568},{9,10,910},{ 140,11,612},{135,0,784},{15,0,135},{143,11,135},{10,0,454},{140,0,324},{4,11,0}, {5,11,41},{7,11,1459},{7,11,1469},{7,11,1618},{7,11,1859},{9,11,549},{139,11,905 },{4,10,98},{7,10,1365},{9,10,422},{9,10,670},{10,10,775},{11,10,210},{13,10,26} ,{13,10,457},{141,10,476},{6,0,1719},{6,0,1735},{7,0,2016},{7,0,2020},{8,0,837}, {137,0,852},{133,11,696},{135,0,852},{132,0,952},{134,10,1730},{132,11,771},{138 ,0,568},{137,0,448},{139,0,146},{8,0,67},{138,0,419},{133,11,921},{137,10,147},{ 134,0,1826},{10,0,657},{14,0,297},{142,0,361},{6,0,666},{6,0,767},{134,0,1542},{ 139,0,729},{6,11,180},{7,11,1137},{8,11,751},{139,11,805},{4,11,183},{7,11,271}, {11,11,824},{11,11,952},{13,11,278},{13,11,339},{13,11,482},{14,11,424},{148,11, 99},{4,0,669},{5,11,477},{5,11,596},{6,11,505},{7,11,1221},{11,11,907},{12,11, 209},{141,11,214},{135,11,1215},{5,0,402},{6,10,30},{11,10,56},{139,10,305},{7, 11,564},{142,11,168},{139,0,152},{7,0,912},{135,10,1614},{4,10,150},{5,10,303},{ 134,10,327},{7,0,320},{8,0,51},{9,0,868},{10,0,833},{12,0,481},{12,0,570},{148,0 ,106},{132,0,445},{7,11,274},{11,11,263},{11,11,479},{11,11,507},{140,11,277},{ 10,0,555},{11,0,308},{19,0,95},{6,11,1645},{8,10,192},{10,10,78},{141,10,359},{ 135,10,786},{6,11,92},{6,11,188},{7,11,1269},{7,11,1524},{7,11,1876},{10,11,228} ,{139,11,1020},{4,11,459},{133,11,966},{11,0,386},{6,10,1638},{7,10,79},{7,10, 496},{9,10,138},{10,10,336},{12,10,412},{12,10,440},{142,10,305},{133,0,239},{7, 0,83},{7,0,1990},{8,0,130},{139,0,720},{138,11,709},{4,0,143},{5,0,550},{133,0, 752},{5,0,123},{6,0,530},{7,0,348},{135,0,1419},{135,0,2024},{6,11,18},{7,11,179 },{7,11,721},{7,11,932},{8,11,548},{8,11,757},{9,11,54},{9,11,65},{9,11,532},{9, 11,844},{10,11,113},{10,11,117},{10,11,236},{10,11,315},{10,11,430},{10,11,798}, {11,11,153},{11,11,351},{11,11,375},{12,11,78},{12,11,151},{12,11,392},{14,11, 248},{143,11,23},{7,10,204},{7,10,415},{8,10,42},{10,10,85},{139,10,564},{134,0, 958},{133,11,965},{132,0,210},{135,11,1429},{138,11,480},{134,11,182},{139,11, 345},{10,11,65},{10,11,488},{138,11,497},{4,10,3},{5,10,247},{5,10,644},{7,10, 744},{7,10,1207},{7,10,1225},{7,10,1909},{146,10,147},{132,0,430},{5,10,285},{9, 10,67},{13,10,473},{143,10,82},{144,11,16},{7,11,1162},{9,11,588},{10,11,260},{ 151,10,8},{133,0,213},{138,0,7},{135,0,801},{134,11,1786},{135,11,308},{6,0,936} ,{134,0,1289},{133,0,108},{132,0,885},{133,0,219},{139,0,587},{4,0,193},{5,0,916 },{6,0,1041},{7,0,364},{10,0,398},{10,0,726},{11,0,317},{11,0,626},{12,0,142},{ 12,0,288},{12,0,678},{13,0,313},{15,0,113},{146,0,114},{135,0,1165},{6,0,241},{9 ,0,342},{10,0,729},{11,0,284},{11,0,445},{11,0,651},{11,0,863},{13,0,398},{146,0 ,99},{7,0,907},{136,0,832},{9,0,303},{4,10,29},{6,10,532},{7,10,1628},{7,10,1648 },{9,10,350},{10,10,433},{11,10,97},{11,10,557},{11,10,745},{12,10,289},{12,10, 335},{12,10,348},{12,10,606},{13,10,116},{13,10,233},{13,10,466},{14,10,181},{14 ,10,209},{14,10,232},{14,10,236},{14,10,300},{16,10,41},{148,10,97},{7,11,423},{ 7,10,1692},{136,11,588},{6,0,931},{134,0,1454},{5,10,501},{7,10,1704},{9,10,553} ,{11,10,520},{12,10,557},{141,10,249},{136,11,287},{4,0,562},{9,0,254},{139,0, 879},{132,0,786},{14,11,32},{18,11,85},{20,11,2},{152,11,16},{135,0,1294},{7,11, 723},{135,11,1135},{6,0,216},{7,0,901},{7,0,1343},{8,0,493},{134,11,403},{7,11, 719},{8,11,809},{136,11,834},{5,11,210},{6,11,213},{7,11,60},{10,11,364},{139,11 ,135},{7,0,341},{11,0,219},{5,11,607},{8,11,326},{136,11,490},{4,11,701},{5,11, 472},{5,11,639},{7,11,1249},{9,11,758},{139,11,896},{135,11,380},{135,11,1947},{ 139,0,130},{135,0,1734},{10,0,115},{11,0,420},{12,0,154},{13,0,404},{14,0,346},{ 143,0,54},{134,10,129},{4,11,386},{7,11,41},{8,11,405},{9,11,497},{11,11,110},{ 11,11,360},{15,11,37},{144,11,84},{141,11,282},{5,11,46},{7,11,1452},{7,11,1480} ,{8,11,634},{140,11,472},{4,11,524},{136,11,810},{10,11,238},{141,11,33},{133,0, 604},{5,0,1011},{136,0,701},{8,0,856},{8,0,858},{8,0,879},{12,0,702},{142,0,447} ,{4,0,54},{5,0,666},{7,0,1039},{7,0,1130},{9,0,195},{138,0,302},{4,10,25},{5,10, 60},{6,10,504},{7,10,614},{7,10,1155},{140,10,0},{7,10,1248},{11,10,621},{139,10 ,702},{133,11,997},{137,10,321},{134,0,1669},{134,0,1791},{4,10,379},{135,10, 1397},{138,11,372},{5,11,782},{5,11,829},{134,11,1738},{135,0,1228},{4,10,118},{ 6,10,274},{6,10,361},{7,10,75},{141,10,441},{132,0,623},{9,11,279},{10,11,407},{ 14,11,84},{150,11,18},{137,10,841},{135,0,798},{140,10,693},{5,10,314},{6,10,221 },{7,10,419},{10,10,650},{11,10,396},{12,10,156},{13,10,369},{14,10,333},{145,10 ,47},{135,11,1372},{7,0,122},{9,0,259},{10,0,84},{11,0,470},{12,0,541},{141,0, 379},{134,0,837},{8,0,1013},{4,11,78},{5,11,96},{5,11,182},{7,11,1724},{7,11, 1825},{10,11,394},{10,11,471},{11,11,532},{14,11,340},{145,11,88},{134,0,577},{ 135,11,1964},{132,10,913},{134,0,460},{8,0,891},{10,0,901},{10,0,919},{10,0,932} ,{12,0,715},{12,0,728},{12,0,777},{14,0,457},{144,0,103},{5,0,82},{5,0,131},{7,0 ,1755},{8,0,31},{9,0,168},{9,0,764},{139,0,869},{136,10,475},{6,0,605},{5,10, 1016},{9,11,601},{9,11,619},{10,11,505},{10,11,732},{11,11,355},{140,11,139},{7, 10,602},{8,10,179},{10,10,781},{140,10,126},{134,0,1246},{6,10,329},{138,10,111} ,{6,11,215},{7,11,1028},{7,11,1473},{7,11,1721},{9,11,424},{138,11,779},{5,0,278 },{137,0,68},{6,0,932},{6,0,1084},{144,0,86},{4,0,163},{5,0,201},{5,0,307},{5,0, 310},{6,0,335},{7,0,284},{7,0,1660},{136,0,165},{136,0,781},{134,0,707},{6,0,33} ,{135,0,1244},{5,10,821},{6,11,67},{6,10,1687},{7,11,258},{7,11,1630},{9,11,354} ,{9,11,675},{10,11,830},{14,11,80},{145,11,80},{6,11,141},{7,11,225},{9,11,59},{ 9,11,607},{10,11,312},{11,11,687},{12,11,555},{13,11,373},{13,11,494},{148,11,58 },{134,0,1113},{9,0,388},{5,10,71},{7,10,1407},{9,10,704},{10,10,261},{10,10,619 },{11,10,547},{11,10,619},{143,10,157},{7,0,1953},{136,0,720},{138,0,203},{7,10, 2008},{9,10,337},{138,10,517},{6,0,326},{7,0,677},{137,0,425},{139,11,81},{7,0, 1316},{7,0,1412},{7,0,1839},{9,0,589},{11,0,241},{11,0,676},{11,0,811},{11,0,891 },{12,0,140},{12,0,346},{12,0,479},{13,0,140},{13,0,381},{14,0,188},{18,0,30},{ 148,0,108},{5,0,416},{6,10,86},{6,10,603},{7,10,292},{7,10,561},{8,10,257},{8,10 ,382},{9,10,721},{9,10,778},{11,10,581},{140,10,466},{4,10,486},{133,10,491},{ 134,0,1300},{132,10,72},{7,0,847},{6,10,265},{7,11,430},{139,11,46},{5,11,602},{ 6,11,106},{7,11,1786},{7,11,1821},{7,11,2018},{9,11,418},{137,11,763},{5,0,358}, {7,0,535},{7,0,1184},{10,0,662},{13,0,212},{13,0,304},{13,0,333},{145,0,98},{5, 11,65},{6,11,416},{7,11,1720},{7,11,1924},{8,11,677},{10,11,109},{11,11,14},{11, 11,70},{11,11,569},{11,11,735},{15,11,153},{148,11,80},{6,0,1823},{8,0,839},{8,0 ,852},{8,0,903},{10,0,940},{12,0,707},{140,0,775},{135,11,1229},{6,0,1522},{140, 0,654},{136,11,595},{139,0,163},{141,0,314},{132,0,978},{4,0,601},{6,0,2035},{ 137,10,234},{5,10,815},{6,10,1688},{134,10,1755},{133,0,946},{136,0,434},{6,10, 197},{136,10,205},{7,0,411},{7,0,590},{8,0,631},{9,0,323},{10,0,355},{11,0,491}, {12,0,143},{12,0,402},{13,0,73},{14,0,408},{15,0,107},{146,0,71},{7,0,1467},{8,0 ,328},{10,0,544},{11,0,955},{12,0,13},{13,0,320},{145,0,83},{142,0,410},{11,0, 511},{13,0,394},{14,0,298},{14,0,318},{146,0,103},{6,10,452},{7,10,312},{138,10, 219},{138,10,589},{4,10,333},{9,10,176},{12,10,353},{141,10,187},{135,11,329},{ 132,11,469},{5,0,835},{134,0,483},{134,11,1743},{5,11,929},{6,11,340},{8,11,376} ,{136,11,807},{134,10,1685},{132,0,677},{5,11,218},{7,11,1610},{138,11,83},{5,11 ,571},{135,11,1842},{132,11,455},{137,0,70},{135,0,1405},{7,10,135},{8,10,7},{8, 10,62},{9,10,243},{10,10,658},{10,10,697},{11,10,456},{139,10,756},{9,10,395},{ 138,10,79},{137,0,108},{6,11,161},{7,11,372},{137,11,597},{132,11,349},{132,0, 777},{132,0,331},{135,10,631},{133,0,747},{6,11,432},{6,11,608},{139,11,322},{ 138,10,835},{5,11,468},{7,11,1809},{10,11,325},{11,11,856},{12,11,345},{143,11, 104},{133,11,223},{7,10,406},{7,10,459},{8,10,606},{139,10,726},{132,11,566},{ 142,0,68},{4,11,59},{135,11,1394},{6,11,436},{139,11,481},{4,11,48},{5,11,271},{ 135,11,953},{139,11,170},{5,11,610},{136,11,457},{133,11,755},{135,11,1217},{133 ,10,612},{132,11,197},{132,0,505},{4,10,372},{7,10,482},{8,10,158},{9,10,602},{9 ,10,615},{10,10,245},{10,10,678},{10,10,744},{11,10,248},{139,10,806},{133,0,326 },{5,10,854},{135,10,1991},{4,0,691},{146,0,16},{6,0,628},{9,0,35},{10,0,680},{ 10,0,793},{11,0,364},{13,0,357},{143,0,164},{138,0,654},{6,0,32},{7,0,385},{7,0, 757},{7,0,1916},{8,0,37},{8,0,94},{8,0,711},{9,0,541},{10,0,162},{10,0,795},{11, 0,989},{11,0,1010},{12,0,14},{142,0,308},{133,11,217},{6,0,152},{6,0,349},{6,0, 1682},{7,0,1252},{8,0,112},{9,0,435},{9,0,668},{10,0,290},{10,0,319},{10,0,815}, {11,0,180},{11,0,837},{12,0,240},{13,0,152},{13,0,219},{142,0,158},{4,0,581},{ 134,0,726},{5,10,195},{135,10,1685},{6,0,126},{7,0,573},{8,0,397},{142,0,44},{ 138,0,89},{7,10,1997},{8,10,730},{139,10,1006},{134,0,1531},{134,0,1167},{5,0, 926},{12,0,203},{133,10,751},{4,11,165},{7,11,1398},{135,11,1829},{7,0,1232},{ 137,0,531},{135,10,821},{134,0,943},{133,0,670},{4,0,880},{139,0,231},{134,0, 1617},{135,0,1957},{5,11,9},{7,11,297},{7,11,966},{140,11,306},{6,0,975},{134,0, 985},{5,10,950},{5,10,994},{134,10,351},{12,11,21},{151,11,7},{5,11,146},{6,11, 411},{138,11,721},{7,0,242},{135,0,1942},{6,11,177},{135,11,467},{5,0,421},{7,10 ,47},{137,10,684},{5,0,834},{7,0,1202},{8,0,14},{9,0,481},{137,0,880},{138,0,465 },{6,0,688},{9,0,834},{132,10,350},{132,0,855},{4,0,357},{6,0,172},{7,0,143},{ 137,0,413},{133,11,200},{132,0,590},{7,10,1812},{13,10,259},{13,10,356},{14,10, 242},{147,10,114},{133,10,967},{11,0,114},{4,10,473},{7,10,623},{8,10,808},{9,10 ,871},{9,10,893},{11,10,431},{12,10,112},{12,10,217},{12,10,243},{12,10,562},{12 ,10,663},{12,10,683},{13,10,141},{13,10,197},{13,10,227},{13,10,406},{13,10,487} ,{14,10,156},{14,10,203},{14,10,224},{14,10,256},{18,10,58},{150,10,0},{138,10, 286},{4,10,222},{7,10,286},{136,10,629},{5,0,169},{7,0,333},{136,0,45},{134,11, 481},{132,0,198},{4,0,24},{5,0,140},{5,0,185},{7,0,1500},{11,0,565},{11,0,838},{ 4,11,84},{7,11,1482},{10,11,76},{138,11,142},{133,0,585},{141,10,306},{133,11, 1015},{4,11,315},{5,11,507},{135,11,1370},{136,10,146},{6,0,691},{134,0,1503},{4 ,0,334},{133,0,593},{4,10,465},{135,10,1663},{142,11,173},{135,0,913},{12,0,116} ,{134,11,1722},{134,0,1360},{132,0,802},{8,11,222},{8,11,476},{9,11,238},{11,11, 516},{11,11,575},{15,11,109},{146,11,100},{6,0,308},{9,0,673},{7,10,138},{7,10, 517},{139,10,238},{132,0,709},{6,0,1876},{6,0,1895},{9,0,994},{9,0,1006},{12,0, 829},{12,0,888},{12,0,891},{146,0,185},{148,10,94},{4,0,228},{133,0,897},{7,0, 1840},{5,10,495},{7,10,834},{9,10,733},{139,10,378},{133,10,559},{6,10,21},{6,10 ,1737},{7,10,1444},{136,10,224},{4,0,608},{133,0,497},{6,11,40},{135,11,1781},{ 134,0,1573},{135,0,2039},{6,0,540},{136,0,136},{4,0,897},{5,0,786},{133,10,519}, {6,0,1878},{6,0,1884},{9,0,938},{9,0,948},{9,0,955},{9,0,973},{9,0,1012},{12,0, 895},{12,0,927},{143,0,254},{134,0,1469},{133,0,999},{4,0,299},{135,0,1004},{4,0 ,745},{133,0,578},{136,11,574},{133,0,456},{134,0,1457},{7,0,1679},{132,10,402}, {7,0,693},{8,0,180},{12,0,163},{8,10,323},{136,10,479},{11,10,580},{142,10,201}, {5,10,59},{135,10,672},{132,11,354},{146,10,34},{4,0,755},{135,11,1558},{7,0, 1740},{146,0,48},{4,10,85},{135,10,549},{139,0,338},{133,10,94},{134,0,1091},{ 135,11,469},{12,0,695},{12,0,704},{20,0,113},{5,11,830},{14,11,338},{148,11,81}, {135,0,1464},{6,10,11},{135,10,187},{135,0,975},{13,0,335},{132,10,522},{134,0, 1979},{5,11,496},{135,11,203},{4,10,52},{135,10,661},{7,0,1566},{8,0,269},{9,0, 212},{9,0,718},{14,0,15},{14,0,132},{142,0,227},{4,0,890},{5,0,805},{5,0,819},{5 ,0,961},{6,0,396},{6,0,1631},{6,0,1678},{7,0,1967},{7,0,2041},{9,0,630},{11,0,8} ,{11,0,1019},{12,0,176},{13,0,225},{14,0,292},{21,0,24},{4,10,383},{133,10,520}, {134,11,547},{135,11,1748},{5,11,88},{137,11,239},{146,11,128},{7,11,650},{135, 11,1310},{4,10,281},{5,10,38},{7,10,194},{7,10,668},{7,10,1893},{137,10,397},{ 135,0,1815},{9,10,635},{139,10,559},{7,0,1505},{10,0,190},{10,0,634},{11,0,792}, {12,0,358},{140,0,447},{5,0,0},{6,0,536},{7,0,604},{13,0,445},{145,0,126},{7,11, 1076},{9,11,80},{11,11,78},{11,11,421},{11,11,534},{140,11,545},{8,0,966},{10,0, 1023},{14,11,369},{146,11,72},{135,11,1641},{6,0,232},{6,0,412},{7,0,1074},{8,0, 9},{8,0,157},{8,0,786},{9,0,196},{9,0,352},{9,0,457},{10,0,337},{11,0,232},{11,0 ,877},{12,0,480},{140,0,546},{135,0,958},{4,0,382},{136,0,579},{4,0,212},{135,0, 1206},{4,11,497},{5,11,657},{135,11,1584},{132,0,681},{8,0,971},{138,0,965},{5, 10,448},{136,10,535},{14,0,16},{146,0,44},{11,0,584},{11,0,616},{14,0,275},{11, 11,584},{11,11,616},{142,11,275},{136,11,13},{7,10,610},{135,10,1501},{7,11,642} ,{8,11,250},{11,11,123},{11,11,137},{13,11,48},{142,11,95},{133,0,655},{17,0,67} ,{147,0,74},{134,0,751},{134,0,1967},{6,0,231},{136,0,423},{5,0,300},{138,0,1016 },{4,10,319},{5,10,699},{138,10,673},{6,0,237},{7,0,611},{8,0,100},{9,0,416},{11 ,0,335},{12,0,173},{18,0,101},{6,10,336},{8,10,552},{9,10,285},{10,10,99},{139, 10,568},{134,0,1370},{7,10,1406},{9,10,218},{141,10,222},{133,10,256},{135,0, 1208},{14,11,213},{148,11,38},{6,0,1219},{135,11,1642},{13,0,417},{14,0,129},{ 143,0,15},{10,11,545},{140,11,301},{17,10,39},{148,10,36},{133,0,199},{4,11,904} ,{133,11,794},{12,0,427},{146,0,38},{134,0,949},{8,0,665},{135,10,634},{132,10, 618},{135,10,259},{132,10,339},{133,11,761},{141,10,169},{132,10,759},{5,0,688}, {7,0,539},{135,0,712},{7,11,386},{138,11,713},{134,0,1186},{6,11,7},{6,11,35},{7 ,11,147},{7,11,1069},{7,11,1568},{7,11,1575},{7,11,1917},{8,11,43},{8,11,208},{9 ,11,128},{9,11,866},{10,11,20},{11,11,981},{147,11,33},{7,11,893},{8,10,482},{ 141,11,424},{6,0,312},{6,0,1715},{10,0,584},{11,0,546},{11,0,692},{12,0,259},{12 ,0,295},{13,0,46},{141,0,154},{5,10,336},{6,10,341},{6,10,478},{6,10,1763},{136, 10,386},{137,0,151},{132,0,588},{152,0,4},{6,11,322},{9,11,552},{11,11,274},{13, 11,209},{13,11,499},{14,11,85},{15,11,126},{145,11,70},{135,10,73},{4,0,231},{5, 0,61},{6,0,104},{7,0,729},{7,0,964},{7,0,1658},{140,0,414},{6,0,263},{138,0,757} ,{135,10,1971},{4,0,612},{133,0,561},{132,0,320},{135,10,1344},{8,11,83},{8,11, 817},{9,11,28},{9,11,29},{9,11,885},{10,11,387},{11,11,633},{11,11,740},{13,11, 235},{13,11,254},{15,11,143},{143,11,146},{5,10,396},{134,10,501},{140,11,49},{ 132,0,225},{4,10,929},{5,10,799},{8,10,46},{136,10,740},{4,0,405},{7,0,817},{14, 0,58},{17,0,37},{146,0,124},{133,0,974},{4,11,412},{133,11,581},{4,10,892},{133, 10,770},{4,0,996},{134,0,2026},{4,0,527},{5,0,235},{7,0,1239},{11,0,131},{140,0, 370},{9,0,16},{13,0,386},{135,11,421},{7,0,956},{7,0,1157},{7,0,1506},{7,0,1606} ,{7,0,1615},{7,0,1619},{7,0,1736},{7,0,1775},{8,0,590},{9,0,324},{9,0,736},{9,0, 774},{9,0,776},{9,0,784},{10,0,567},{10,0,708},{11,0,518},{11,0,613},{11,0,695}, {11,0,716},{11,0,739},{11,0,770},{11,0,771},{11,0,848},{11,0,857},{11,0,931},{11 ,0,947},{12,0,326},{12,0,387},{12,0,484},{12,0,528},{12,0,552},{12,0,613},{13,0, 189},{13,0,256},{13,0,340},{13,0,432},{13,0,436},{13,0,440},{13,0,454},{14,0,174 },{14,0,220},{14,0,284},{14,0,390},{145,0,121},{135,10,158},{9,0,137},{138,0,221 },{4,11,110},{10,11,415},{10,11,597},{142,11,206},{141,11,496},{135,11,205},{151 ,10,25},{135,11,778},{7,11,1656},{7,10,2001},{9,11,369},{10,11,338},{10,11,490}, {11,11,154},{11,11,545},{11,11,775},{13,11,77},{141,11,274},{4,11,444},{10,11, 146},{140,11,9},{7,0,390},{138,0,140},{135,0,1144},{134,0,464},{7,10,1461},{140, 10,91},{132,10,602},{4,11,283},{135,11,1194},{5,0,407},{11,0,204},{11,0,243},{11 ,0,489},{12,0,293},{19,0,37},{20,0,73},{150,0,38},{7,0,1218},{136,0,303},{5,0, 325},{8,0,5},{8,0,227},{9,0,105},{10,0,585},{12,0,614},{4,10,13},{5,10,567},{7, 10,1498},{9,10,124},{11,10,521},{140,10,405},{135,10,1006},{7,0,800},{10,0,12},{ 134,11,1720},{135,0,1783},{132,10,735},{138,10,812},{4,10,170},{135,10,323},{6,0 ,621},{13,0,504},{144,0,89},{5,10,304},{135,10,1403},{137,11,216},{6,0,920},{6,0 ,1104},{9,11,183},{139,11,286},{4,0,376},{133,10,742},{134,0,218},{8,0,641},{11, 0,388},{140,0,580},{7,0,454},{7,0,782},{8,0,768},{140,0,686},{137,11,33},{133,10 ,111},{144,0,0},{10,0,676},{140,0,462},{6,0,164},{136,11,735},{133,10,444},{150, 0,50},{7,11,1862},{12,11,491},{12,11,520},{13,11,383},{14,11,244},{146,11,12},{5 ,11,132},{9,11,486},{9,11,715},{10,11,458},{11,11,373},{11,11,668},{11,11,795},{ 11,11,897},{12,11,272},{12,11,424},{12,11,539},{12,11,558},{14,11,245},{14,11, 263},{14,11,264},{14,11,393},{142,11,403},{8,10,123},{15,10,6},{144,10,7},{6,0, 285},{8,0,654},{11,0,749},{12,0,190},{12,0,327},{13,0,120},{13,0,121},{13,0,327} ,{15,0,47},{146,0,40},{5,11,8},{6,11,89},{6,11,400},{7,11,1569},{7,11,1623},{7, 11,1850},{8,11,218},{8,11,422},{9,11,570},{138,11,626},{6,11,387},{7,11,882},{ 141,11,111},{6,0,343},{7,0,195},{9,0,226},{10,0,197},{10,0,575},{11,0,502},{11,0 ,899},{6,11,224},{7,11,877},{137,11,647},{5,10,937},{135,10,100},{135,11,790},{ 150,0,29},{147,0,8},{134,0,1812},{149,0,8},{135,11,394},{7,0,1125},{9,0,143},{11 ,0,61},{14,0,405},{150,0,21},{10,11,755},{147,11,29},{9,11,378},{141,11,162},{ 135,10,922},{5,10,619},{133,10,698},{134,0,1327},{6,0,1598},{137,0,575},{9,11, 569},{12,11,12},{12,11,81},{12,11,319},{13,11,69},{14,11,259},{16,11,87},{17,11, 1},{17,11,21},{17,11,24},{18,11,15},{18,11,56},{18,11,59},{18,11,127},{18,11,154 },{19,11,19},{148,11,31},{6,0,895},{135,11,1231},{5,0,959},{7,11,124},{136,11,38 },{5,11,261},{7,11,78},{7,11,199},{8,11,815},{9,11,126},{138,11,342},{5,10,917}, {134,10,1659},{7,0,1759},{5,11,595},{135,11,1863},{136,0,173},{134,0,266},{142,0 ,261},{132,11,628},{5,10,251},{5,10,956},{8,10,268},{9,10,214},{146,10,142},{7, 11,266},{136,11,804},{135,11,208},{6,11,79},{7,11,1021},{135,11,1519},{11,11,704 },{141,11,396},{5,10,346},{5,10,711},{136,10,390},{136,11,741},{134,11,376},{134 ,0,1427},{6,0,1033},{6,0,1217},{136,0,300},{133,10,624},{6,11,100},{7,11,244},{7 ,11,632},{7,11,1609},{8,11,178},{8,11,638},{141,11,58},{6,0,584},{5,10,783},{7, 10,1998},{135,10,2047},{5,0,427},{5,0,734},{7,0,478},{136,0,52},{7,0,239},{11,0, 217},{142,0,165},{134,0,1129},{6,0,168},{6,0,1734},{7,0,20},{7,0,1056},{8,0,732} ,{9,0,406},{9,0,911},{138,0,694},{132,10,594},{133,11,791},{7,11,686},{8,11,33}, {8,11,238},{10,11,616},{11,11,467},{11,11,881},{13,11,217},{13,11,253},{142,11, 268},{137,11,476},{134,0,418},{133,0,613},{132,0,632},{132,11,447},{7,0,32},{7,0 ,984},{8,0,85},{8,0,709},{9,0,579},{9,0,847},{9,0,856},{10,0,799},{11,0,258},{11 ,0,1007},{12,0,331},{12,0,615},{13,0,188},{13,0,435},{14,0,8},{15,0,165},{16,0, 27},{20,0,40},{144,11,35},{4,11,128},{5,11,415},{6,11,462},{7,11,294},{7,11,578} ,{10,11,710},{139,11,86},{5,0,694},{136,0,909},{7,0,1109},{11,0,7},{5,10,37},{6, 10,39},{6,10,451},{7,10,218},{7,10,1166},{7,10,1687},{8,10,662},{144,10,2},{136, 11,587},{6,11,427},{7,11,1018},{138,11,692},{4,11,195},{6,10,508},{135,11,802},{ 4,0,167},{135,0,82},{5,0,62},{6,0,24},{6,0,534},{7,0,74},{7,0,678},{7,0,684},{7, 0,1043},{7,0,1072},{8,0,280},{8,0,541},{8,0,686},{9,0,258},{10,0,519},{11,0,252} ,{140,0,282},{138,0,33},{4,0,359},{133,11,738},{7,0,980},{9,0,328},{13,0,186},{ 13,0,364},{7,10,635},{7,10,796},{8,10,331},{9,10,330},{9,10,865},{10,10,119},{10 ,10,235},{11,10,111},{11,10,129},{11,10,240},{12,10,31},{12,10,66},{12,10,222},{ 12,10,269},{12,10,599},{12,10,684},{12,10,689},{12,10,691},{142,10,345},{137,10, 527},{6,0,596},{7,0,585},{135,10,702},{134,11,1683},{133,0,211},{6,0,145},{141,0 ,336},{134,0,1130},{7,0,873},{6,10,37},{7,10,1666},{8,10,195},{8,10,316},{9,10, 178},{9,10,276},{9,10,339},{9,10,536},{10,10,102},{10,10,362},{10,10,785},{11,10 ,55},{11,10,149},{11,10,773},{13,10,416},{13,10,419},{14,10,38},{14,10,41},{142, 10,210},{8,0,840},{136,0,841},{132,0,263},{5,11,3},{8,11,578},{9,11,118},{10,11, 705},{12,11,383},{141,11,279},{132,0,916},{133,11,229},{133,10,645},{15,0,155},{ 16,0,79},{8,11,102},{10,11,578},{10,11,672},{12,11,496},{13,11,408},{14,11,121}, {145,11,106},{4,0,599},{5,0,592},{6,0,1634},{7,0,5},{7,0,55},{7,0,67},{7,0,97},{ 7,0,691},{7,0,979},{7,0,1600},{7,0,1697},{8,0,207},{8,0,214},{8,0,231},{8,0,294} ,{8,0,336},{8,0,428},{8,0,471},{8,0,622},{8,0,626},{8,0,679},{8,0,759},{8,0,829} ,{9,0,11},{9,0,246},{9,0,484},{9,0,573},{9,0,706},{9,0,762},{9,0,798},{9,0,855}, {9,0,870},{9,0,912},{10,0,303},{10,0,335},{10,0,424},{10,0,461},{10,0,543},{10,0 ,759},{10,0,814},{11,0,59},{11,0,199},{11,0,235},{11,0,590},{11,0,631},{11,0,929 },{11,0,963},{11,0,987},{12,0,114},{12,0,182},{12,0,226},{12,0,332},{12,0,439},{ 12,0,575},{12,0,598},{12,0,675},{13,0,8},{13,0,125},{13,0,194},{13,0,287},{14,0, 197},{14,0,383},{15,0,53},{17,0,63},{19,0,46},{19,0,98},{19,0,106},{148,0,85},{7 ,0,1356},{132,10,290},{6,10,70},{7,10,1292},{10,10,762},{139,10,288},{150,11,55} ,{4,0,593},{8,11,115},{8,11,350},{9,11,489},{10,11,128},{11,11,306},{12,11,373}, {14,11,30},{17,11,79},{147,11,80},{135,11,1235},{134,0,1392},{4,11,230},{133,11, 702},{147,0,126},{7,10,131},{7,10,422},{8,10,210},{140,10,573},{134,0,1179},{139 ,11,435},{139,10,797},{134,11,1728},{4,0,162},{18,11,26},{19,11,42},{20,11,43},{ 21,11,0},{23,11,27},{152,11,14},{132,10,936},{6,0,765},{5,10,453},{134,10,441},{ 133,0,187},{135,0,1286},{6,0,635},{6,0,904},{6,0,1210},{134,0,1489},{4,0,215},{8 ,0,890},{9,0,38},{10,0,923},{11,0,23},{11,0,127},{139,0,796},{6,0,1165},{134,0, 1306},{7,0,716},{13,0,97},{141,0,251},{132,10,653},{136,0,657},{146,10,80},{5,11 ,622},{7,11,1032},{11,11,26},{11,11,213},{11,11,707},{12,11,380},{13,11,226},{ 141,11,355},{6,0,299},{5,11,70},{6,11,334},{9,11,171},{11,11,637},{12,11,202},{ 14,11,222},{145,11,42},{142,0,134},{4,11,23},{5,11,313},{5,11,1014},{6,11,50},{6 ,11,51},{7,11,142},{7,11,384},{9,11,783},{139,11,741},{4,11,141},{7,11,559},{8, 11,640},{9,11,460},{12,11,183},{141,11,488},{136,11,614},{7,10,1368},{8,10,232}, {8,10,361},{10,10,682},{138,10,742},{137,10,534},{6,0,1082},{140,0,658},{137,10, 27},{135,0,2002},{142,10,12},{4,0,28},{5,0,440},{7,0,248},{11,0,833},{140,0,344} ,{7,10,736},{139,10,264},{134,10,1657},{134,0,1654},{138,0,531},{5,11,222},{9,11 ,140},{138,11,534},{6,0,634},{6,0,798},{134,0,840},{138,11,503},{135,10,127},{ 133,0,853},{5,11,154},{7,11,1491},{10,11,379},{138,11,485},{6,0,249},{7,0,1234}, {139,0,573},{133,11,716},{7,11,1570},{140,11,542},{136,10,364},{138,0,527},{4,11 ,91},{5,11,388},{5,11,845},{6,11,206},{6,11,252},{6,11,365},{7,11,136},{7,11,531 },{8,11,264},{136,11,621},{134,0,1419},{135,11,1441},{7,0,49},{7,0,392},{8,0,20} ,{8,0,172},{8,0,690},{9,0,383},{9,0,845},{10,0,48},{11,0,293},{11,0,832},{11,0, 920},{11,0,984},{141,0,221},{5,0,858},{133,0,992},{5,0,728},{137,10,792},{5,10, 909},{9,10,849},{138,10,805},{7,0,525},{7,0,1579},{8,0,497},{136,0,573},{6,0,268 },{137,0,62},{135,11,576},{134,0,1201},{5,11,771},{5,11,863},{5,11,898},{6,11, 1632},{6,11,1644},{134,11,1780},{133,11,331},{7,0,193},{7,0,1105},{10,0,495},{7, 10,397},{8,10,124},{8,10,619},{9,10,305},{11,10,40},{12,10,349},{13,10,134},{13, 10,295},{14,10,155},{15,10,120},{146,10,105},{138,0,106},{6,0,859},{5,11,107},{7 ,11,201},{136,11,518},{6,11,446},{135,11,1817},{13,0,23},{4,10,262},{135,10,342} ,{133,10,641},{137,11,851},{6,0,925},{137,0,813},{132,11,504},{6,0,613},{136,0, 223},{4,10,99},{6,10,250},{6,10,346},{8,10,127},{138,10,81},{136,0,953},{132,10, 915},{139,11,892},{5,10,75},{9,10,517},{10,10,470},{12,10,155},{141,10,224},{4,0 ,666},{7,0,1017},{7,11,996},{138,11,390},{5,11,883},{133,11,975},{14,10,83},{142 ,11,83},{4,0,670},{5,11,922},{134,11,1707},{135,0,216},{9,0,40},{11,0,136},{135, 11,787},{5,10,954},{5,11,993},{7,11,515},{137,11,91},{139,0,259},{7,0,1114},{9,0 ,310},{9,0,682},{10,0,440},{13,0,40},{6,10,304},{8,10,418},{11,10,341},{139,10, 675},{14,0,296},{9,10,410},{139,10,425},{10,11,377},{12,11,363},{13,11,68},{13, 11,94},{14,11,108},{142,11,306},{7,0,1401},{135,0,1476},{4,0,296},{6,0,475},{7,0 ,401},{7,0,1410},{7,0,1594},{7,0,1674},{8,0,63},{8,0,660},{137,0,74},{4,0,139},{ 4,0,388},{140,0,188},{132,0,797},{132,11,766},{5,11,103},{7,11,921},{8,11,580},{ 8,11,593},{8,11,630},{138,11,28},{4,11,911},{5,11,867},{133,11,1013},{134,10,14} ,{134,0,1572},{134,10,1708},{21,0,39},{5,10,113},{6,10,243},{7,10,1865},{11,10, 161},{16,10,37},{145,10,99},{7,11,1563},{141,11,182},{5,11,135},{6,11,519},{7,11 ,1722},{10,11,271},{11,11,261},{145,11,54},{132,10,274},{134,0,1594},{4,11,300}, {5,11,436},{135,11,484},{4,0,747},{6,0,290},{7,0,649},{7,0,1479},{135,0,1583},{ 133,11,535},{147,11,82},{133,0,232},{137,0,887},{135,10,166},{136,0,521},{4,0,14 },{7,0,472},{7,0,1801},{10,0,748},{141,0,458},{134,0,741},{134,0,992},{16,0,111} ,{137,10,304},{4,0,425},{5,11,387},{7,11,557},{12,11,547},{142,11,86},{135,11, 1747},{5,10,654},{135,11,1489},{7,0,789},{4,11,6},{5,11,708},{136,11,75},{6,10, 273},{10,10,188},{13,10,377},{146,10,77},{6,0,1593},{4,11,303},{7,11,619},{10,11 ,547},{10,11,687},{11,11,122},{140,11,601},{134,0,1768},{135,10,410},{138,11,772 },{11,0,233},{139,10,524},{5,0,943},{134,0,1779},{134,10,1785},{136,11,529},{132 ,0,955},{5,0,245},{6,0,576},{7,0,582},{136,0,225},{132,10,780},{142,0,241},{134, 0,1943},{4,11,106},{7,11,310},{7,11,1785},{10,11,690},{139,11,717},{134,0,1284}, {5,11,890},{133,11,988},{6,11,626},{142,11,431},{10,11,706},{145,11,32},{137,11, 332},{132,11,698},{135,0,709},{5,10,948},{138,11,17},{136,0,554},{134,0,1564},{ 139,10,941},{132,0,443},{134,0,909},{134,11,84},{142,0,280},{4,10,532},{5,10,706 },{135,10,662},{132,0,729},{5,10,837},{6,10,1651},{139,10,985},{135,10,1861},{4, 0,348},{152,11,3},{5,11,986},{6,11,130},{7,11,1582},{8,11,458},{10,11,101},{10, 11,318},{138,11,823},{134,0,758},{4,0,298},{137,0,848},{4,10,330},{7,10,933},{7, 10,2012},{136,10,292},{7,11,1644},{137,11,129},{6,0,1422},{9,0,829},{135,10,767} ,{5,0,164},{7,0,121},{142,0,189},{7,0,812},{7,0,1261},{7,0,1360},{9,0,632},{140, 0,352},{135,11,1788},{139,0,556},{135,11,997},{145,10,114},{4,0,172},{9,0,611},{ 10,0,436},{12,0,673},{13,0,255},{137,10,883},{11,0,530},{138,10,274},{133,0,844} ,{134,0,984},{13,0,232},{18,0,35},{4,10,703},{135,10,207},{132,10,571},{9,0,263} ,{10,0,147},{138,0,492},{7,11,1756},{137,11,98},{5,10,873},{5,10,960},{8,10,823} ,{137,10,881},{133,0,537},{132,0,859},{7,11,1046},{139,11,160},{137,0,842},{139, 10,283},{5,10,33},{6,10,470},{139,10,424},{6,11,45},{7,11,433},{8,11,129},{9,11, 21},{10,11,392},{11,11,79},{12,11,499},{13,11,199},{141,11,451},{135,0,1291},{ 135,10,1882},{7,11,558},{136,11,353},{134,0,1482},{5,0,230},{5,0,392},{6,0,420}, {9,0,568},{140,0,612},{6,0,262},{7,10,90},{7,10,664},{7,10,830},{7,10,1380},{7, 10,2025},{8,11,81},{8,10,448},{8,10,828},{9,11,189},{9,11,201},{11,11,478},{11, 11,712},{141,11,338},{142,0,31},{5,11,353},{151,11,26},{132,0,753},{4,0,0},{5,0, 41},{7,0,1459},{7,0,1469},{7,0,1859},{9,0,549},{139,0,905},{9,10,417},{137,10, 493},{135,11,1113},{133,0,696},{141,11,448},{134,10,295},{132,0,834},{4,0,771},{ 5,10,1019},{6,11,25},{7,11,855},{7,11,1258},{144,11,32},{134,0,1076},{133,0,921} ,{133,0,674},{4,11,4},{7,11,1118},{7,11,1320},{7,11,1706},{8,11,277},{9,11,622}, {10,11,9},{11,11,724},{12,11,350},{12,11,397},{13,11,28},{13,11,159},{15,11,89}, {18,11,5},{19,11,9},{20,11,34},{150,11,47},{134,10,208},{6,0,444},{136,0,308},{6 ,0,180},{7,0,1137},{8,0,751},{139,0,805},{4,0,183},{7,0,271},{11,0,824},{11,0, 952},{13,0,278},{13,0,339},{13,0,482},{14,0,424},{148,0,99},{7,11,317},{135,11, 569},{4,0,19},{5,0,477},{5,0,596},{6,0,505},{7,0,1221},{11,0,907},{12,0,209},{ 141,0,214},{135,0,1215},{6,0,271},{7,0,398},{8,0,387},{10,0,344},{7,10,448},{7, 10,1629},{7,10,1813},{8,10,442},{9,10,710},{10,10,282},{138,10,722},{11,10,844}, {12,10,104},{140,10,625},{134,11,255},{133,10,787},{134,0,1645},{11,11,956},{151 ,11,3},{6,0,92},{6,0,188},{7,0,209},{7,0,1269},{7,0,1524},{7,0,1876},{8,0,661},{ 10,0,42},{10,0,228},{11,0,58},{11,0,1020},{12,0,58},{12,0,118},{141,0,32},{4,0, 459},{133,0,966},{4,11,536},{7,11,1141},{10,11,723},{139,11,371},{140,0,330},{ 134,0,1557},{7,11,285},{135,11,876},{136,10,491},{135,11,560},{6,0,18},{7,0,179} ,{7,0,932},{8,0,548},{8,0,757},{9,0,54},{9,0,65},{9,0,532},{9,0,844},{10,0,113}, {10,0,117},{10,0,315},{10,0,560},{10,0,622},{10,0,798},{11,0,153},{11,0,351},{11 ,0,375},{12,0,78},{12,0,151},{12,0,392},{12,0,666},{14,0,248},{143,0,23},{6,0, 1742},{132,11,690},{4,10,403},{5,10,441},{7,10,450},{10,10,840},{11,10,101},{12, 10,193},{141,10,430},{133,0,965},{134,0,182},{10,0,65},{10,0,488},{138,0,497},{ 135,11,1346},{6,0,973},{6,0,1158},{10,11,200},{19,11,2},{151,11,22},{4,11,190},{ 133,11,554},{133,10,679},{7,0,328},{137,10,326},{133,11,1001},{9,0,588},{138,0, 260},{133,11,446},{135,10,1128},{135,10,1796},{147,11,119},{134,0,1786},{6,0, 1328},{6,0,1985},{8,0,962},{138,0,1017},{135,0,308},{11,0,508},{4,10,574},{7,10, 350},{7,10,1024},{8,10,338},{9,10,677},{138,10,808},{138,11,752},{135,10,1081},{ 137,11,96},{7,10,1676},{135,10,2037},{136,0,588},{132,11,304},{133,0,614},{140,0 ,793},{136,0,287},{137,10,297},{141,10,37},{6,11,53},{6,11,199},{7,11,1408},{8, 11,32},{8,11,93},{9,11,437},{10,11,397},{10,11,629},{11,11,593},{11,11,763},{13, 11,326},{145,11,35},{134,11,105},{9,11,320},{10,11,506},{138,11,794},{5,11,114}, {5,11,255},{141,11,285},{140,0,290},{7,11,2035},{8,11,19},{9,11,89},{138,11,831} ,{134,0,1136},{7,0,719},{8,0,796},{8,0,809},{8,0,834},{6,10,306},{7,10,1140},{7, 10,1340},{8,10,133},{138,10,449},{139,10,1011},{5,0,210},{6,0,213},{7,0,60},{10, 0,364},{139,0,135},{5,0,607},{8,0,326},{136,0,490},{138,11,176},{132,0,701},{5,0 ,472},{7,0,380},{137,0,758},{135,0,1947},{6,0,1079},{138,0,278},{138,11,391},{5, 10,329},{8,10,260},{139,11,156},{4,0,386},{7,0,41},{8,0,405},{8,0,728},{9,0,497} ,{11,0,110},{11,0,360},{15,0,37},{144,0,84},{5,0,46},{7,0,1452},{7,0,1480},{8,0, 634},{140,0,472},{136,0,961},{4,0,524},{136,0,810},{10,0,238},{141,0,33},{132,10 ,657},{152,10,7},{133,0,532},{5,0,997},{135,10,1665},{7,11,594},{7,11,851},{7,11 ,1858},{9,11,411},{9,11,574},{9,11,666},{9,11,737},{10,11,346},{10,11,712},{11, 11,246},{11,11,432},{11,11,517},{11,11,647},{11,11,679},{11,11,727},{12,11,304}, {12,11,305},{12,11,323},{12,11,483},{12,11,572},{12,11,593},{12,11,602},{13,11, 95},{13,11,101},{13,11,171},{13,11,315},{13,11,378},{13,11,425},{13,11,475},{14, 11,63},{14,11,380},{14,11,384},{15,11,133},{18,11,112},{148,11,72},{5,11,955},{ 136,11,814},{134,0,1301},{5,10,66},{7,10,1896},{136,10,288},{133,11,56},{134,10, 1643},{6,0,1298},{148,11,100},{5,0,782},{5,0,829},{6,0,671},{6,0,1156},{6,0,1738 },{137,11,621},{4,0,306},{5,0,570},{7,0,1347},{5,10,91},{5,10,648},{5,10,750},{5 ,10,781},{6,10,54},{6,10,112},{6,10,402},{6,10,1732},{7,10,315},{7,10,749},{7,10 ,1900},{9,10,78},{9,10,508},{10,10,611},{10,10,811},{11,10,510},{11,10,728},{13, 10,36},{14,10,39},{16,10,83},{17,10,124},{148,10,30},{8,10,570},{9,11,477},{141, 11,78},{4,11,639},{10,11,4},{10,10,322},{10,10,719},{11,10,407},{11,11,638},{12, 11,177},{148,11,57},{7,0,1823},{139,0,693},{7,0,759},{5,11,758},{8,10,125},{8,10 ,369},{8,10,524},{10,10,486},{11,10,13},{11,10,381},{11,10,736},{11,10,766},{11, 10,845},{13,10,114},{13,10,292},{142,10,47},{7,0,1932},{6,10,1684},{6,10,1731},{ 7,10,356},{8,10,54},{8,10,221},{9,10,225},{9,10,356},{10,10,77},{10,10,446},{10, 10,731},{12,10,404},{141,10,491},{135,11,552},{135,11,1112},{4,0,78},{5,0,96},{5 ,0,182},{6,0,1257},{7,0,1724},{7,0,1825},{10,0,394},{10,0,471},{11,0,532},{14,0, 340},{145,0,88},{139,11,328},{135,0,1964},{132,10,411},{4,10,80},{5,10,44},{137, 11,133},{5,11,110},{6,11,169},{6,11,1702},{7,11,400},{8,11,538},{9,11,184},{9,11 ,524},{140,11,218},{4,0,521},{5,10,299},{7,10,1083},{140,11,554},{6,11,133},{9, 11,353},{12,11,628},{146,11,79},{6,0,215},{7,0,584},{7,0,1028},{7,0,1473},{7,0, 1721},{9,0,424},{138,0,779},{7,0,857},{7,0,1209},{7,10,1713},{9,10,537},{10,10, 165},{12,10,219},{140,10,561},{4,10,219},{6,11,93},{7,11,1422},{7,10,1761},{7,11 ,1851},{8,11,673},{9,10,86},{9,11,529},{140,11,43},{137,11,371},{136,0,671},{5,0 ,328},{135,0,918},{132,0,529},{9,11,25},{10,11,467},{138,11,559},{4,11,335},{135 ,11,942},{134,0,716},{134,0,1509},{6,0,67},{7,0,258},{7,0,1630},{9,0,354},{9,0, 675},{10,0,830},{14,0,80},{17,0,80},{140,10,428},{134,0,1112},{6,0,141},{7,0,225 },{9,0,59},{9,0,607},{10,0,312},{11,0,687},{12,0,555},{13,0,373},{13,0,494},{148 ,0,58},{133,10,514},{8,11,39},{10,11,773},{11,11,84},{12,11,205},{142,11,1},{8,0 ,783},{5,11,601},{133,11,870},{136,11,594},{4,10,55},{5,10,301},{6,10,571},{14, 10,49},{146,10,102},{132,11,181},{134,11,1652},{133,10,364},{4,11,97},{5,11,147} ,{6,11,286},{7,11,1362},{141,11,176},{4,10,76},{7,10,1550},{9,10,306},{9,10,430} ,{9,10,663},{10,10,683},{11,10,427},{11,10,753},{12,10,334},{12,10,442},{14,10, 258},{14,10,366},{143,10,131},{137,10,52},{6,0,955},{134,0,1498},{6,11,375},{7, 11,169},{7,11,254},{136,11,780},{7,0,430},{11,0,46},{14,0,343},{142,11,343},{135 ,0,1183},{5,0,602},{7,0,2018},{9,0,418},{9,0,803},{135,11,1447},{8,0,677},{135, 11,1044},{139,11,285},{4,10,656},{135,10,779},{135,10,144},{5,11,629},{135,11, 1549},{135,10,1373},{138,11,209},{7,10,554},{7,10,605},{141,10,10},{5,10,838},{5 ,10,841},{134,10,1649},{133,10,1012},{6,0,1357},{134,0,1380},{144,0,53},{6,0,590 },{7,10,365},{7,10,1357},{7,10,1497},{8,10,154},{141,10,281},{133,10,340},{132, 11,420},{135,0,329},{147,11,32},{4,0,469},{10,11,429},{139,10,495},{8,10,261},{9 ,10,144},{9,10,466},{10,10,370},{12,10,470},{13,10,144},{142,10,348},{142,0,460} ,{4,11,325},{9,10,897},{138,11,125},{6,0,1743},{6,10,248},{9,10,546},{10,10,535} ,{11,10,681},{141,10,135},{4,0,990},{5,0,929},{6,0,340},{8,0,376},{8,0,807},{8,0 ,963},{8,0,980},{138,0,1007},{134,0,1603},{140,0,250},{4,11,714},{133,11,469},{ 134,10,567},{136,10,445},{5,0,218},{7,0,1610},{8,0,646},{10,0,83},{11,11,138},{ 140,11,40},{7,0,1512},{135,0,1794},{135,11,1216},{11,0,0},{16,0,78},{132,11,718} ,{133,0,571},{132,0,455},{134,0,1012},{5,11,124},{5,11,144},{6,11,548},{7,11,15} ,{7,11,153},{137,11,629},{142,11,10},{6,11,75},{7,11,1531},{8,11,416},{9,11,240} ,{9,11,275},{10,11,100},{11,11,658},{11,11,979},{12,11,86},{13,11,468},{14,11,66 },{14,11,207},{15,11,20},{15,11,25},{144,11,58},{132,10,577},{5,11,141},{5,11, 915},{6,11,1783},{7,11,211},{7,11,698},{7,11,1353},{9,11,83},{9,11,281},{10,11, 376},{10,11,431},{11,11,543},{12,11,664},{13,11,280},{13,11,428},{14,11,61},{14, 11,128},{17,11,52},{145,11,81},{6,0,161},{7,0,372},{137,0,597},{132,0,349},{10, 11,702},{139,11,245},{134,0,524},{134,10,174},{6,0,432},{9,0,751},{139,0,322},{ 147,11,94},{4,11,338},{133,11,400},{5,0,468},{10,0,325},{11,0,856},{12,0,345},{ 143,0,104},{133,0,223},{132,0,566},{4,11,221},{5,11,659},{5,11,989},{7,11,697},{ 7,11,1211},{138,11,284},{135,11,1070},{4,0,59},{135,0,1394},{6,0,436},{11,0,481} ,{5,10,878},{133,10,972},{4,0,48},{5,0,271},{135,0,953},{5,0,610},{136,0,457},{4 ,0,773},{5,0,618},{137,0,756},{133,0,755},{135,0,1217},{138,11,507},{132,10,351} ,{132,0,197},{143,11,78},{4,11,188},{7,11,805},{11,11,276},{142,11,293},{5,11, 884},{139,11,991},{132,10,286},{10,0,259},{10,0,428},{7,10,438},{7,10,627},{7,10 ,1516},{8,10,40},{9,10,56},{9,10,294},{11,10,969},{11,10,995},{146,10,148},{4,0, 356},{5,0,217},{5,0,492},{5,0,656},{8,0,544},{136,11,544},{5,0,259},{6,0,1230},{ 7,0,414},{7,0,854},{142,0,107},{132,0,1007},{15,0,14},{144,0,5},{6,0,1580},{132, 10,738},{132,11,596},{132,0,673},{133,10,866},{6,0,1843},{135,11,1847},{4,0,165} ,{7,0,1398},{135,0,1829},{135,11,1634},{147,11,65},{6,0,885},{6,0,1009},{137,0, 809},{133,10,116},{132,10,457},{136,11,770},{9,0,498},{12,0,181},{10,11,361},{ 142,11,316},{134,11,595},{5,0,9},{7,0,297},{7,0,966},{140,0,306},{4,11,89},{5,11 ,489},{6,11,315},{7,11,553},{7,11,1745},{138,11,243},{134,0,1487},{132,0,437},{5 ,0,146},{6,0,411},{138,0,721},{5,10,527},{6,10,189},{135,10,859},{11,10,104},{11 ,10,554},{15,10,60},{143,10,125},{6,11,1658},{9,11,3},{10,11,154},{11,11,641},{ 13,11,85},{13,11,201},{141,11,346},{6,0,177},{135,0,467},{134,0,1377},{134,10, 116},{136,11,645},{4,11,166},{5,11,505},{6,11,1670},{137,11,110},{133,10,487},{4 ,10,86},{5,10,667},{5,10,753},{6,10,316},{6,10,455},{135,10,946},{133,0,200},{ 132,0,959},{6,0,1928},{134,0,1957},{139,11,203},{150,10,45},{4,10,79},{7,10,1773 },{10,10,450},{11,10,589},{13,10,332},{13,10,493},{14,10,183},{14,10,334},{14,10 ,362},{14,10,368},{14,10,376},{14,10,379},{19,10,90},{19,10,103},{19,10,127},{ 148,10,90},{6,0,1435},{135,11,1275},{134,0,481},{7,11,445},{8,11,307},{8,11,704} ,{10,11,41},{10,11,439},{11,11,237},{11,11,622},{140,11,201},{135,11,869},{4,0, 84},{7,0,1482},{10,0,76},{138,0,142},{11,11,277},{144,11,14},{135,11,1977},{4,11 ,189},{5,11,713},{136,11,57},{133,0,1015},{138,11,371},{4,0,315},{5,0,507},{135, 0,1370},{4,11,552},{142,10,381},{9,0,759},{16,0,31},{16,0,39},{16,0,75},{18,0,24 },{20,0,42},{152,0,1},{134,0,712},{134,0,1722},{133,10,663},{133,10,846},{8,0, 222},{8,0,476},{9,0,238},{11,0,516},{11,0,575},{15,0,109},{146,0,100},{7,0,1402} ,{7,0,1414},{12,0,456},{5,10,378},{8,10,465},{9,10,286},{10,10,185},{10,10,562}, {10,10,635},{11,10,31},{11,10,393},{13,10,312},{18,10,65},{18,10,96},{147,10,89} ,{4,0,986},{6,0,1958},{6,0,2032},{8,0,934},{138,0,985},{7,10,1880},{9,10,680},{ 139,10,798},{134,10,1770},{145,11,49},{132,11,614},{132,10,648},{5,10,945},{6,10 ,1656},{6,10,1787},{7,10,167},{8,10,824},{9,10,391},{10,10,375},{139,10,185},{ 138,11,661},{7,0,1273},{135,11,1945},{7,0,706},{7,0,1058},{138,0,538},{7,10,1645 },{8,10,352},{137,10,249},{132,10,152},{11,0,92},{11,0,196},{11,0,409},{11,0,450 },{11,0,666},{11,0,777},{12,0,262},{13,0,385},{13,0,393},{15,0,115},{16,0,45},{ 145,0,82},{133,10,1006},{6,0,40},{135,0,1781},{9,11,614},{139,11,327},{5,10,420} ,{135,10,1449},{135,0,431},{10,0,97},{135,10,832},{6,0,423},{7,0,665},{135,0, 1210},{7,0,237},{8,0,664},{9,0,42},{9,0,266},{9,0,380},{9,0,645},{10,0,177},{138 ,0,276},{7,0,264},{133,10,351},{8,0,213},{5,10,40},{7,10,598},{7,10,1638},{9,10, 166},{9,10,640},{9,10,685},{9,10,773},{11,10,215},{13,10,65},{14,10,172},{14,10, 317},{145,10,6},{5,11,84},{134,11,163},{8,10,60},{9,10,343},{139,10,769},{137,0, 455},{133,11,410},{8,0,906},{12,0,700},{12,0,706},{140,0,729},{21,11,33},{150,11 ,40},{7,10,1951},{8,10,765},{8,10,772},{140,10,671},{7,10,108},{8,10,219},{8,10, 388},{9,10,639},{9,10,775},{11,10,275},{140,10,464},{5,11,322},{7,11,1941},{8,11 ,186},{9,11,262},{10,11,187},{14,11,208},{146,11,130},{139,0,624},{8,0,574},{5, 11,227},{140,11,29},{7,11,1546},{11,11,299},{142,11,407},{5,10,15},{6,10,56},{7, 10,1758},{8,10,500},{9,10,730},{11,10,331},{13,10,150},{142,10,282},{7,11,1395}, {8,11,486},{9,11,236},{9,11,878},{10,11,218},{11,11,95},{19,11,17},{147,11,31},{ 135,11,2043},{4,0,354},{146,11,4},{140,11,80},{135,0,1558},{134,10,1886},{5,10, 205},{6,10,438},{137,10,711},{133,11,522},{133,10,534},{7,0,235},{7,0,1475},{15, 0,68},{146,0,120},{137,10,691},{4,0,942},{6,0,1813},{8,0,917},{10,0,884},{12,0, 696},{12,0,717},{12,0,723},{12,0,738},{12,0,749},{12,0,780},{16,0,97},{146,0,169 },{6,10,443},{8,11,562},{9,10,237},{9,10,571},{9,10,695},{10,10,139},{11,10,715} ,{12,10,417},{141,10,421},{135,0,957},{133,0,830},{134,11,1771},{146,0,23},{5,0, 496},{6,0,694},{7,0,203},{7,11,1190},{137,11,620},{137,11,132},{6,0,547},{134,0, 1549},{8,11,258},{9,11,208},{137,11,359},{4,0,864},{5,0,88},{137,0,239},{135,11, 493},{4,11,317},{135,11,1279},{132,11,477},{4,10,578},{5,11,63},{133,11,509},{7, 0,650},{135,0,1310},{7,0,1076},{9,0,80},{11,0,78},{11,0,421},{11,0,534},{140,0, 545},{132,11,288},{12,0,553},{14,0,118},{133,10,923},{7,0,274},{11,0,479},{139,0 ,507},{8,11,89},{8,11,620},{9,11,49},{10,11,774},{11,11,628},{12,11,322},{143,11 ,124},{4,0,497},{135,0,1584},{7,0,261},{7,0,1115},{7,0,1354},{7,0,1404},{7,0, 1588},{7,0,1705},{7,0,1902},{9,0,465},{10,0,248},{10,0,349},{10,0,647},{11,0,527 },{11,0,660},{11,0,669},{12,0,529},{13,0,305},{132,10,924},{133,10,665},{136,0, 13},{6,0,791},{138,11,120},{7,0,642},{8,0,250},{11,0,123},{11,0,137},{13,0,48},{ 142,0,95},{4,10,265},{7,10,807},{135,10,950},{5,10,93},{140,10,267},{135,0,1429} ,{4,0,949},{10,0,885},{10,0,891},{10,0,900},{10,0,939},{12,0,760},{142,0,449},{ 139,11,366},{132,0,818},{134,11,85},{135,10,994},{7,0,330},{5,10,233},{5,10,320} ,{6,10,140},{136,10,295},{4,0,1004},{8,0,982},{136,0,993},{133,10,978},{4,10,905 },{6,10,1701},{137,10,843},{10,0,545},{140,0,301},{6,0,947},{134,0,1062},{134,0, 1188},{4,0,904},{5,0,794},{152,10,6},{134,0,1372},{135,11,608},{5,11,279},{6,11, 235},{7,11,468},{8,11,446},{9,11,637},{10,11,717},{11,11,738},{140,11,514},{132, 10,509},{5,11,17},{6,11,371},{137,11,528},{132,0,693},{4,11,115},{5,11,669},{6, 11,407},{8,11,311},{11,11,10},{141,11,5},{11,0,377},{7,10,273},{137,11,381},{135 ,0,695},{7,0,386},{138,0,713},{135,10,1041},{134,0,1291},{6,0,7},{6,0,35},{7,0, 147},{7,0,1069},{7,0,1568},{7,0,1575},{7,0,1917},{8,0,43},{8,0,208},{9,0,128},{9 ,0,866},{10,0,20},{11,0,981},{147,0,33},{7,0,893},{141,0,424},{139,10,234},{150, 11,56},{5,11,779},{5,11,807},{6,11,1655},{134,11,1676},{5,10,802},{7,10,2021},{ 136,10,805},{4,11,196},{5,10,167},{5,11,558},{5,10,899},{5,11,949},{6,10,410},{ 137,10,777},{137,10,789},{134,10,1705},{8,0,904},{140,0,787},{6,0,322},{9,0,552} ,{11,0,274},{13,0,209},{13,0,499},{14,0,85},{15,0,126},{145,0,70},{135,10,10},{5 ,10,11},{6,10,117},{6,10,485},{7,10,1133},{9,10,582},{9,10,594},{11,10,21},{11, 10,818},{12,10,535},{141,10,86},{4,10,264},{7,10,1067},{8,10,204},{8,10,385},{ 139,10,953},{132,11,752},{138,10,56},{133,10,470},{6,0,1808},{8,0,83},{8,0,742}, {8,0,817},{9,0,28},{9,0,29},{9,0,885},{10,0,387},{11,0,633},{11,0,740},{13,0,235 },{13,0,254},{15,0,143},{143,0,146},{140,0,49},{134,0,1832},{4,11,227},{5,11,159 },{5,11,409},{7,11,80},{10,11,294},{10,11,479},{12,11,418},{14,11,50},{14,11,249 },{142,11,295},{7,11,1470},{8,11,66},{8,11,137},{8,11,761},{9,11,638},{11,11,80} ,{11,11,212},{11,11,368},{11,11,418},{12,11,8},{13,11,15},{16,11,61},{17,11,59}, {19,11,28},{148,11,84},{139,10,1015},{138,11,468},{135,0,421},{6,0,415},{7,0, 1049},{137,0,442},{6,11,38},{7,11,1220},{8,11,185},{8,11,256},{9,11,22},{9,11, 331},{10,11,738},{11,11,205},{11,11,540},{11,11,746},{13,11,399},{13,11,465},{14 ,11,88},{142,11,194},{139,0,289},{133,10,715},{4,0,110},{10,0,415},{10,0,597},{ 142,0,206},{4,11,159},{6,11,115},{7,11,252},{7,11,257},{7,11,1928},{8,11,69},{9, 11,384},{10,11,91},{10,11,615},{12,11,375},{14,11,235},{18,11,117},{147,11,123}, {5,11,911},{136,11,278},{7,0,205},{7,0,2000},{8,10,794},{9,10,400},{10,10,298},{ 142,10,228},{135,11,1774},{4,11,151},{7,11,1567},{8,11,351},{137,11,322},{136,10 ,724},{133,11,990},{7,0,1539},{11,0,512},{13,0,205},{19,0,30},{22,0,36},{23,0,19 },{135,11,1539},{5,11,194},{7,11,1662},{9,11,90},{140,11,180},{6,10,190},{7,10, 768},{135,10,1170},{134,0,1340},{4,0,283},{135,0,1194},{133,11,425},{133,11,971} ,{12,0,549},{14,10,67},{147,10,60},{135,10,1023},{134,0,1720},{138,11,587},{5,11 ,72},{6,11,264},{7,11,21},{7,11,46},{7,11,2013},{8,11,215},{8,11,513},{10,11,266 },{139,11,22},{5,0,319},{135,0,534},{6,10,137},{9,10,75},{9,10,253},{10,10,194}, {138,10,444},{7,0,1180},{20,0,112},{6,11,239},{7,11,118},{10,11,95},{11,11,603}, {13,11,443},{14,11,160},{143,11,4},{134,11,431},{5,11,874},{6,11,1677},{11,10, 643},{12,10,115},{143,11,0},{134,0,967},{6,11,65},{7,11,939},{7,11,1172},{7,11, 1671},{9,11,540},{10,11,696},{11,11,265},{11,11,732},{11,11,928},{11,11,937},{12 ,11,399},{13,11,438},{149,11,19},{137,11,200},{135,0,1940},{5,10,760},{7,10,542} ,{8,10,135},{136,10,496},{140,11,44},{7,11,1655},{136,11,305},{7,10,319},{7,10, 355},{7,10,763},{10,10,389},{145,10,43},{136,0,735},{138,10,786},{137,11,19},{ 132,11,696},{5,0,132},{9,0,486},{9,0,715},{10,0,458},{11,0,373},{11,0,668},{11,0 ,795},{11,0,897},{12,0,272},{12,0,424},{12,0,539},{12,0,558},{14,0,245},{14,0, 263},{14,0,264},{14,0,393},{142,0,403},{10,0,38},{139,0,784},{132,0,838},{4,11, 302},{135,11,1766},{133,0,379},{5,0,8},{6,0,89},{6,0,400},{7,0,1569},{7,0,1623}, {7,0,1850},{8,0,218},{8,0,422},{9,0,570},{10,0,626},{4,11,726},{133,11,630},{4,0 ,1017},{138,0,660},{6,0,387},{7,0,882},{141,0,111},{6,0,224},{7,0,877},{137,0, 647},{4,10,58},{5,10,286},{6,10,319},{7,10,402},{7,10,1254},{7,10,1903},{8,10, 356},{140,10,408},{135,0,790},{9,0,510},{10,0,53},{4,10,389},{9,10,181},{10,10, 29},{10,10,816},{11,10,311},{11,10,561},{12,10,67},{141,10,181},{142,0,458},{6, 11,118},{7,11,215},{7,11,1521},{140,11,11},{134,0,954},{135,0,394},{134,0,1367}, {5,11,225},{133,10,373},{132,0,882},{7,0,1409},{135,10,1972},{135,10,1793},{4,11 ,370},{5,11,756},{135,11,1326},{150,11,13},{7,11,354},{10,11,410},{139,11,815},{ 6,11,1662},{7,11,48},{8,11,771},{10,11,116},{13,11,104},{14,11,105},{14,11,184}, {15,11,168},{19,11,92},{148,11,68},{7,0,124},{136,0,38},{5,0,261},{7,0,78},{7,0, 199},{8,0,815},{9,0,126},{10,0,342},{140,0,647},{4,0,628},{140,0,724},{7,0,266}, {8,0,804},{7,10,1651},{145,10,89},{135,0,208},{134,0,1178},{6,0,79},{135,0,1519} ,{132,10,672},{133,10,737},{136,0,741},{132,11,120},{4,0,710},{6,0,376},{134,0, 606},{134,0,1347},{134,0,1494},{6,0,850},{6,0,1553},{137,0,821},{5,10,145},{134, 11,593},{7,0,1311},{140,0,135},{4,0,467},{5,0,405},{134,0,544},{5,11,820},{135, 11,931},{6,0,100},{7,0,244},{7,0,632},{7,0,1609},{8,0,178},{8,0,638},{141,0,58}, {4,10,387},{135,10,1288},{6,11,151},{6,11,1675},{7,11,383},{151,11,10},{132,0, 481},{135,10,550},{134,0,1378},{6,11,1624},{11,11,11},{12,11,422},{13,11,262},{ 142,11,360},{133,0,791},{4,11,43},{5,11,344},{133,11,357},{7,0,1227},{140,0,978} ,{7,0,686},{8,0,33},{8,0,238},{10,0,616},{11,0,467},{11,0,881},{13,0,217},{13,0, 253},{142,0,268},{137,0,857},{8,0,467},{8,0,1006},{7,11,148},{8,11,284},{141,11, 63},{4,10,576},{135,10,1263},{133,11,888},{5,10,919},{134,10,1673},{20,10,37},{ 148,11,37},{132,0,447},{132,11,711},{4,0,128},{5,0,415},{6,0,462},{7,0,294},{7,0 ,578},{10,0,710},{139,0,86},{4,10,82},{5,10,333},{5,10,904},{6,10,207},{7,10,325 },{7,10,1726},{8,10,101},{10,10,778},{139,10,220},{136,0,587},{137,11,440},{133, 10,903},{6,0,427},{7,0,1018},{138,0,692},{4,0,195},{135,0,802},{140,10,147},{134 ,0,1546},{134,0,684},{132,10,705},{136,0,345},{11,11,678},{140,11,307},{133,0, 365},{134,0,1683},{4,11,65},{5,11,479},{5,11,1004},{7,11,1913},{8,11,317},{9,11, 302},{10,11,612},{141,11,22},{138,0,472},{4,11,261},{135,11,510},{134,10,90},{ 142,0,433},{151,0,28},{4,11,291},{7,11,101},{9,11,515},{12,11,152},{12,11,443},{ 13,11,392},{142,11,357},{140,0,997},{5,0,3},{8,0,578},{9,0,118},{10,0,705},{141, 0,279},{135,11,1266},{7,10,813},{12,10,497},{141,10,56},{133,0,229},{6,10,125},{ 135,10,1277},{8,0,102},{10,0,578},{10,0,672},{12,0,496},{13,0,408},{14,0,121},{ 17,0,106},{151,10,12},{6,0,866},{134,0,1080},{136,0,1022},{4,11,130},{135,11,843 },{5,11,42},{5,11,879},{7,11,245},{7,11,324},{7,11,1532},{11,11,463},{11,11,472} ,{13,11,363},{144,11,52},{150,0,55},{8,0,115},{8,0,350},{9,0,489},{10,0,128},{11 ,0,306},{12,0,373},{14,0,30},{17,0,79},{19,0,80},{4,11,134},{133,11,372},{134,0, 657},{134,0,933},{135,11,1147},{4,0,230},{133,0,702},{134,0,1728},{4,0,484},{18, 0,26},{19,0,42},{20,0,43},{21,0,0},{23,0,27},{152,0,14},{7,0,185},{135,0,703},{6 ,0,417},{10,0,618},{7,10,1106},{9,10,770},{11,10,112},{140,10,413},{134,0,803},{ 132,11,644},{134,0,1262},{7,11,540},{12,10,271},{145,10,109},{135,11,123},{132,0 ,633},{134,11,623},{4,11,908},{5,11,359},{5,11,508},{6,11,1723},{7,11,343},{7,11 ,1996},{135,11,2026},{135,0,479},{10,0,262},{7,10,304},{9,10,646},{9,10,862},{11 ,10,696},{12,10,208},{15,10,79},{147,10,108},{4,11,341},{135,11,480},{134,0,830} ,{5,0,70},{5,0,622},{6,0,334},{7,0,1032},{9,0,171},{11,0,26},{11,0,213},{11,0, 637},{11,0,707},{12,0,202},{12,0,380},{13,0,226},{13,0,355},{14,0,222},{145,0,42 },{135,10,981},{143,0,217},{137,11,114},{4,0,23},{4,0,141},{5,0,313},{5,0,1014}, {6,0,50},{6,0,51},{7,0,142},{7,0,384},{7,0,559},{8,0,640},{9,0,460},{9,0,783},{ 11,0,741},{12,0,183},{141,0,488},{141,0,360},{7,0,1586},{7,11,1995},{8,11,299},{ 11,11,890},{140,11,674},{132,10,434},{7,0,652},{134,10,550},{7,0,766},{5,10,553} ,{138,10,824},{7,0,737},{8,0,298},{136,10,452},{4,11,238},{5,11,503},{6,11,179}, {7,11,2003},{8,11,381},{8,11,473},{9,11,149},{10,11,183},{15,11,45},{143,11,86}, {133,10,292},{5,0,222},{9,0,655},{138,0,534},{138,10,135},{4,11,121},{5,11,156}, {5,11,349},{9,11,136},{10,11,605},{14,11,342},{147,11,107},{137,0,906},{6,0,1013 },{134,0,1250},{6,0,1956},{6,0,2009},{8,0,991},{144,0,120},{135,11,1192},{138,0, 503},{5,0,154},{7,0,1491},{10,0,379},{138,0,485},{6,0,1867},{6,0,1914},{6,0,1925 },{9,0,917},{9,0,925},{9,0,932},{9,0,951},{9,0,1007},{9,0,1013},{12,0,806},{12,0 ,810},{12,0,814},{12,0,816},{12,0,824},{12,0,832},{12,0,837},{12,0,863},{12,0, 868},{12,0,870},{12,0,889},{12,0,892},{12,0,900},{12,0,902},{12,0,908},{12,0,933 },{12,0,942},{12,0,949},{12,0,954},{15,0,175},{15,0,203},{15,0,213},{15,0,218},{ 15,0,225},{15,0,231},{15,0,239},{15,0,248},{15,0,252},{18,0,190},{18,0,204},{18, 0,215},{18,0,216},{18,0,222},{18,0,225},{18,0,230},{18,0,239},{18,0,241},{21,0, 42},{21,0,43},{21,0,44},{21,0,45},{21,0,46},{21,0,53},{24,0,27},{152,0,31},{133, 0,716},{135,0,844},{4,0,91},{5,0,388},{5,0,845},{6,0,206},{6,0,252},{6,0,365},{7 ,0,136},{7,0,531},{136,0,621},{7,10,393},{10,10,603},{139,10,206},{6,11,80},{6, 11,1694},{7,11,173},{7,11,1974},{9,11,547},{10,11,730},{14,11,18},{150,11,39},{ 137,0,748},{4,11,923},{134,11,1711},{4,10,912},{137,10,232},{7,10,98},{7,10,1973 },{136,10,716},{14,0,103},{133,10,733},{132,11,595},{12,0,158},{18,0,8},{19,0,62 },{20,0,6},{22,0,4},{23,0,2},{23,0,9},{5,11,240},{6,11,459},{7,11,12},{7,11,114} ,{7,11,502},{7,11,1751},{7,11,1753},{7,11,1805},{8,11,658},{9,11,1},{11,11,959}, {13,11,446},{142,11,211},{135,0,576},{5,0,771},{5,0,863},{5,0,898},{6,0,648},{6, 0,1632},{6,0,1644},{134,0,1780},{133,0,331},{7,11,633},{7,11,905},{7,11,909},{7, 11,1538},{9,11,767},{140,11,636},{140,0,632},{5,0,107},{7,0,201},{136,0,518},{6, 0,446},{7,0,1817},{134,11,490},{9,0,851},{141,0,510},{7,11,250},{8,11,506},{136, 11,507},{4,0,504},{137,10,72},{132,11,158},{4,11,140},{7,11,362},{8,11,209},{9, 11,10},{9,11,160},{9,11,503},{10,11,689},{11,11,350},{11,11,553},{11,11,725},{12 ,11,252},{12,11,583},{13,11,192},{13,11,352},{14,11,269},{14,11,356},{148,11,50} ,{6,11,597},{135,11,1318},{135,10,1454},{5,0,883},{5,0,975},{8,0,392},{148,0,7}, {6,11,228},{7,11,1341},{9,11,408},{138,11,343},{11,11,348},{11,10,600},{12,11,99 },{13,10,245},{18,11,1},{18,11,11},{147,11,4},{134,11,296},{5,0,922},{134,0,1707 },{132,11,557},{4,11,548},{7,10,164},{7,10,1571},{9,10,107},{140,10,225},{7,11, 197},{8,11,142},{8,11,325},{9,11,150},{9,11,596},{10,11,350},{10,11,353},{11,11, 74},{11,11,315},{14,11,423},{143,11,141},{5,0,993},{7,0,515},{137,0,91},{4,0,131 },{8,0,200},{5,10,484},{5,10,510},{6,10,434},{7,10,1000},{7,10,1098},{136,10,2}, {152,0,10},{4,11,62},{5,11,83},{6,11,399},{6,11,579},{7,11,692},{7,11,846},{7,11 ,1015},{7,11,1799},{8,11,403},{9,11,394},{10,11,133},{12,11,4},{12,11,297},{12, 11,452},{16,11,81},{18,11,19},{18,11,25},{21,11,14},{22,11,12},{151,11,18},{140, 11,459},{132,11,177},{7,0,1433},{9,0,365},{137,11,365},{132,10,460},{5,0,103},{6 ,0,2004},{7,0,921},{8,0,580},{8,0,593},{8,0,630},{10,0,28},{5,11,411},{135,11, 653},{4,10,932},{133,10,891},{4,0,911},{5,0,867},{5,0,1013},{7,0,2034},{8,0,798} ,{136,0,813},{7,11,439},{10,11,727},{11,11,260},{139,11,684},{136,10,625},{5,11, 208},{7,11,753},{135,11,1528},{5,0,461},{7,0,1925},{12,0,39},{13,0,265},{13,0, 439},{134,10,76},{6,0,853},{8,10,92},{137,10,221},{5,0,135},{6,0,519},{7,0,1722} ,{10,0,271},{11,0,261},{145,0,54},{139,11,814},{14,0,338},{148,0,81},{4,0,300},{ 133,0,436},{5,0,419},{5,0,687},{7,0,864},{9,0,470},{135,11,864},{9,0,836},{133, 11,242},{134,0,1937},{4,10,763},{133,11,953},{132,10,622},{132,0,393},{133,10, 253},{8,0,357},{10,0,745},{14,0,426},{17,0,94},{19,0,57},{135,10,546},{5,11,615} ,{146,11,37},{9,10,73},{10,10,110},{14,10,185},{145,10,119},{11,0,703},{7,10,624 },{7,10,916},{10,10,256},{139,10,87},{133,11,290},{5,10,212},{12,10,35},{141,10, 382},{132,11,380},{5,11,52},{7,11,277},{9,11,368},{139,11,791},{133,0,387},{10, 11,138},{139,11,476},{4,0,6},{5,0,708},{136,0,75},{7,0,1351},{9,0,581},{10,0,639 },{11,0,453},{140,0,584},{132,0,303},{138,0,772},{135,10,1175},{4,0,749},{5,10, 816},{6,11,256},{7,11,307},{7,11,999},{7,11,1481},{7,11,1732},{7,11,1738},{8,11, 265},{9,11,414},{11,11,316},{12,11,52},{13,11,420},{147,11,100},{135,11,1296},{6 ,0,1065},{5,10,869},{5,10,968},{6,10,1626},{8,10,734},{136,10,784},{4,10,542},{6 ,10,1716},{6,10,1727},{7,10,1082},{7,10,1545},{8,10,56},{8,10,118},{8,10,412},{8 ,10,564},{9,10,888},{9,10,908},{10,10,50},{10,10,423},{11,10,685},{11,10,697},{ 11,10,933},{12,10,299},{13,10,126},{13,10,136},{13,10,170},{141,10,190},{134,0, 226},{4,0,106},{7,0,310},{11,0,717},{133,11,723},{5,0,890},{5,0,988},{4,10,232}, {9,10,202},{10,10,474},{140,10,433},{6,0,626},{142,0,431},{10,0,706},{150,0,44}, {13,0,51},{6,10,108},{7,10,1003},{7,10,1181},{8,10,111},{136,10,343},{132,0,698} ,{5,11,109},{6,11,1784},{7,11,1895},{12,11,296},{140,11,302},{134,0,828},{134,10 ,1712},{138,0,17},{7,0,1929},{4,10,133},{5,11,216},{7,10,711},{7,10,1298},{7,10, 1585},{7,11,1879},{9,11,141},{9,11,270},{9,11,679},{10,11,159},{10,11,553},{11, 11,197},{11,11,438},{12,11,538},{12,11,559},{13,11,193},{13,11,423},{14,11,144}, {14,11,166},{14,11,167},{15,11,67},{147,11,84},{141,11,127},{7,11,1872},{137,11, 81},{6,10,99},{7,10,1808},{145,10,57},{134,11,391},{5,0,689},{6,0,84},{7,0,1250} ,{6,10,574},{7,10,428},{10,10,669},{11,10,485},{11,10,840},{12,10,300},{142,10, 250},{7,11,322},{136,11,249},{7,11,432},{135,11,1649},{135,10,1871},{137,10,252} ,{6,11,155},{140,11,234},{7,0,871},{19,0,27},{147,11,27},{140,0,498},{5,0,986},{ 6,0,130},{138,0,823},{6,0,1793},{7,0,1582},{8,0,458},{10,0,101},{10,0,318},{10,0 ,945},{12,0,734},{16,0,104},{18,0,177},{6,10,323},{135,10,1564},{5,11,632},{138, 11,526},{10,0,435},{7,10,461},{136,10,775},{6,11,144},{7,11,948},{7,11,1042},{7, 11,1857},{8,11,235},{8,11,461},{9,11,453},{9,11,530},{10,11,354},{17,11,77},{19, 11,99},{148,11,79},{138,0,966},{7,0,1644},{137,0,129},{135,0,997},{136,0,502},{5 ,11,196},{6,11,486},{7,11,212},{8,11,309},{136,11,346},{7,10,727},{146,10,73},{ 132,0,823},{132,11,686},{135,0,1927},{4,0,762},{7,0,1756},{137,0,98},{136,10,577 },{24,0,8},{4,11,30},{5,11,43},{152,11,8},{7,0,1046},{139,0,160},{7,0,492},{4,10 ,413},{5,10,677},{7,11,492},{8,10,432},{140,10,280},{6,0,45},{7,0,433},{8,0,129} ,{9,0,21},{10,0,392},{11,0,79},{12,0,499},{13,0,199},{141,0,451},{7,0,558},{136, 0,353},{4,11,220},{7,11,1535},{9,11,93},{139,11,474},{7,10,646},{7,10,1730},{11, 10,446},{141,10,178},{133,0,785},{134,0,1145},{8,0,81},{9,0,189},{9,0,201},{11,0 ,478},{11,0,712},{141,0,338},{5,0,353},{151,0,26},{11,0,762},{132,10,395},{134,0 ,2024},{4,0,611},{133,0,606},{9,10,174},{10,10,164},{11,10,440},{11,10,841},{143 ,10,98},{134,10,426},{10,10,608},{139,10,1002},{138,10,250},{6,0,25},{7,0,855},{ 7,0,1258},{144,0,32},{7,11,1725},{138,11,393},{5,11,263},{134,11,414},{6,0,2011} ,{133,10,476},{4,0,4},{7,0,1118},{7,0,1320},{7,0,1706},{8,0,277},{9,0,622},{10,0 ,9},{11,0,724},{12,0,350},{12,0,397},{13,0,28},{13,0,159},{15,0,89},{18,0,5},{19 ,0,9},{20,0,34},{22,0,47},{6,11,178},{6,11,1750},{8,11,251},{9,11,690},{10,11, 155},{10,11,196},{10,11,373},{11,11,698},{13,11,155},{148,11,93},{5,11,97},{137, 11,393},{7,0,764},{11,0,461},{12,0,172},{5,10,76},{6,10,458},{6,10,497},{7,10, 868},{9,10,658},{10,10,594},{11,10,566},{12,10,338},{141,10,200},{134,0,1449},{ 138,11,40},{134,11,1639},{134,0,1445},{6,0,1168},{4,10,526},{7,10,1029},{135,10, 1054},{4,11,191},{7,11,934},{8,11,647},{145,11,97},{132,10,636},{6,0,233},{7,10, 660},{7,10,1124},{17,10,31},{19,10,22},{151,10,14},{6,10,1699},{136,11,110},{12, 11,246},{15,11,162},{19,11,64},{20,11,8},{20,11,95},{22,11,24},{152,11,17},{5,11 ,165},{9,11,346},{138,11,655},{5,11,319},{135,11,534},{134,0,255},{9,0,216},{8, 11,128},{139,11,179},{9,0,183},{139,0,286},{11,0,956},{151,0,3},{4,0,536},{7,0, 1141},{10,0,723},{139,0,371},{4,10,279},{7,10,301},{137,10,362},{7,0,285},{5,11, 57},{6,11,101},{6,11,1663},{7,11,132},{7,11,1048},{7,11,1154},{7,11,1415},{7,11, 1507},{12,11,493},{15,11,105},{151,11,15},{5,11,459},{7,11,1073},{7,10,1743},{8, 11,241},{136,11,334},{4,10,178},{133,10,399},{135,0,560},{132,0,690},{135,0,1246 },{18,0,157},{147,0,63},{10,0,599},{11,0,33},{12,0,571},{149,0,1},{6,11,324},{6, 11,520},{7,11,338},{7,11,1616},{7,11,1729},{8,11,228},{9,11,69},{139,11,750},{7, 0,1862},{12,0,491},{12,0,520},{13,0,383},{142,0,244},{135,11,734},{134,10,1692}, {10,0,448},{11,0,630},{17,0,117},{6,10,202},{7,11,705},{12,10,360},{17,10,118},{ 18,10,27},{148,10,67},{4,11,73},{6,11,612},{7,11,927},{7,11,1822},{8,11,217},{9, 11,472},{9,11,765},{9,11,766},{10,11,408},{11,11,51},{11,11,793},{12,11,266},{15 ,11,158},{20,11,89},{150,11,32},{4,0,190},{133,0,554},{133,0,1001},{5,11,389},{8 ,11,636},{137,11,229},{5,0,446},{7,10,872},{10,10,516},{139,10,167},{137,10,313} ,{132,10,224},{134,0,1313},{5,10,546},{7,10,35},{8,10,11},{8,10,12},{9,10,315},{ 9,10,533},{10,10,802},{11,10,166},{12,10,525},{142,10,243},{6,0,636},{137,0,837} ,{5,10,241},{8,10,242},{9,10,451},{10,10,667},{11,10,598},{140,10,429},{22,10,46 },{150,11,46},{136,11,472},{11,0,278},{142,0,73},{141,11,185},{132,0,868},{134,0 ,972},{4,10,366},{137,10,516},{138,0,1010},{5,11,189},{6,10,1736},{7,11,442},{7, 11,443},{8,11,281},{12,11,174},{13,11,83},{141,11,261},{139,11,384},{6,11,2},{7, 11,191},{7,11,446},{7,11,758},{7,11,1262},{7,11,1737},{8,11,22},{8,11,270},{8,11 ,612},{9,11,4},{9,11,167},{9,11,312},{9,11,436},{10,11,156},{10,11,216},{10,11, 311},{10,11,623},{11,11,72},{11,11,330},{11,11,455},{12,11,101},{12,11,321},{12, 11,504},{12,11,530},{12,11,543},{13,11,17},{13,11,156},{13,11,334},{14,11,48},{ 15,11,70},{17,11,60},{148,11,64},{6,10,331},{136,10,623},{135,0,1231},{132,0,304 },{6,11,60},{7,11,670},{7,11,1327},{8,11,411},{8,11,435},{9,11,653},{9,11,740},{ 10,11,385},{11,11,222},{11,11,324},{11,11,829},{140,11,611},{7,0,506},{6,11,166} ,{7,11,374},{135,11,1174},{14,11,43},{146,11,21},{135,11,1694},{135,10,1888},{5, 11,206},{134,11,398},{135,11,50},{150,0,26},{6,0,53},{6,0,199},{7,0,1408},{8,0, 32},{8,0,93},{10,0,397},{10,0,629},{11,0,593},{11,0,763},{13,0,326},{145,0,35},{ 134,0,105},{132,10,394},{4,0,843},{138,0,794},{11,0,704},{141,0,396},{5,0,114},{ 5,0,255},{141,0,285},{6,0,619},{7,0,898},{7,0,1092},{8,0,485},{18,0,28},{19,0, 116},{135,10,1931},{9,0,145},{7,10,574},{135,10,1719},{7,0,2035},{8,0,19},{9,0, 89},{138,0,831},{132,10,658},{6,11,517},{7,11,1159},{10,11,621},{139,11,192},{7, 0,1933},{7,11,1933},{9,10,781},{10,10,144},{11,10,385},{13,10,161},{13,10,228},{ 13,10,268},{148,10,107},{136,10,374},{10,11,223},{139,11,645},{135,0,1728},{7,11 ,64},{7,11,289},{136,11,245},{4,10,344},{6,10,498},{139,10,323},{136,0,746},{135 ,10,1063},{137,10,155},{4,0,987},{6,0,1964},{6,0,1974},{6,0,1990},{136,0,995},{ 133,11,609},{133,10,906},{134,0,1550},{134,0,874},{5,11,129},{6,11,61},{135,11, 947},{4,0,1018},{6,0,1938},{6,0,2021},{134,0,2039},{132,0,814},{11,0,126},{139,0 ,287},{134,0,1264},{5,0,955},{136,0,814},{141,11,506},{132,11,314},{6,0,981},{ 139,11,1000},{5,0,56},{8,0,892},{8,0,915},{140,0,776},{148,0,100},{10,0,4},{10,0 ,13},{11,0,638},{148,0,57},{148,11,74},{5,0,738},{132,10,616},{133,11,637},{136, 10,692},{133,0,758},{132,10,305},{137,11,590},{5,11,280},{135,11,1226},{134,11, 494},{135,0,1112},{133,11,281},{13,0,44},{14,0,214},{5,10,214},{7,10,603},{8,10, 611},{9,10,686},{10,10,88},{11,10,459},{11,10,496},{12,10,463},{140,10,590},{139 ,0,328},{135,11,1064},{137,0,133},{7,0,168},{13,0,196},{141,0,237},{134,10,1703} ,{134,0,1152},{135,0,1245},{5,0,110},{6,0,169},{6,0,1702},{7,0,400},{8,0,538},{9 ,0,184},{9,0,524},{140,0,218},{6,0,1816},{10,0,871},{12,0,769},{140,0,785},{132, 11,630},{7,11,33},{7,11,120},{8,11,489},{9,11,319},{10,11,820},{11,11,1004},{12, 11,379},{13,11,117},{13,11,412},{14,11,25},{15,11,52},{15,11,161},{16,11,47},{ 149,11,2},{6,0,133},{8,0,413},{9,0,353},{139,0,993},{145,10,19},{4,11,937},{133, 11,801},{134,0,978},{6,0,93},{6,0,1508},{7,0,1422},{7,0,1851},{8,0,673},{9,0,529 },{140,0,43},{6,0,317},{10,0,512},{4,10,737},{11,10,294},{12,10,60},{12,10,437}, {13,10,64},{13,10,380},{142,10,430},{9,0,371},{7,11,1591},{144,11,43},{6,10,1758 },{8,10,520},{9,10,345},{9,10,403},{142,10,350},{5,0,526},{10,10,242},{138,10, 579},{9,0,25},{10,0,467},{138,0,559},{5,10,139},{7,10,1168},{138,10,539},{4,0, 335},{135,0,942},{140,0,754},{132,11,365},{11,0,182},{142,0,195},{142,11,29},{5, 11,7},{139,11,774},{4,11,746},{135,11,1090},{8,0,39},{10,0,773},{11,0,84},{12,0, 205},{142,0,1},{5,0,601},{5,0,870},{5,11,360},{136,11,237},{132,0,181},{136,0, 370},{134,0,1652},{8,0,358},{4,10,107},{7,10,613},{8,10,439},{8,10,504},{9,10, 501},{10,10,383},{139,10,477},{132,10,229},{137,11,785},{4,0,97},{5,0,147},{6,0, 286},{7,0,1362},{141,0,176},{6,0,537},{7,0,788},{7,0,1816},{132,10,903},{140,10, 71},{6,0,743},{134,0,1223},{6,0,375},{7,0,169},{7,0,254},{8,0,780},{135,11,1493} ,{7,0,1714},{4,10,47},{6,10,373},{7,10,452},{7,10,543},{7,10,1856},{9,10,6},{11, 10,257},{139,10,391},{6,0,896},{136,0,1003},{135,0,1447},{137,11,341},{5,10,980} ,{134,10,1754},{145,11,22},{4,11,277},{5,11,608},{6,11,493},{7,11,457},{140,11, 384},{7,10,536},{7,10,1331},{136,10,143},{140,0,744},{7,11,27},{135,11,316},{18, 0,126},{5,10,19},{134,10,533},{4,0,788},{11,0,41},{5,11,552},{5,11,586},{5,11, 676},{6,11,448},{8,11,244},{11,11,1},{11,11,41},{13,11,3},{16,11,54},{17,11,4},{ 146,11,13},{4,0,985},{6,0,1801},{4,11,401},{137,11,264},{5,10,395},{5,10,951},{ 134,10,1776},{5,0,629},{135,0,1549},{11,10,663},{12,10,210},{13,10,166},{13,10, 310},{14,10,373},{147,10,43},{9,11,543},{10,11,524},{11,11,30},{12,11,524},{14, 11,315},{16,11,18},{20,11,26},{148,11,65},{4,11,205},{5,11,623},{7,11,104},{136, 11,519},{5,0,293},{134,0,601},{7,11,579},{9,11,41},{9,11,244},{9,11,669},{10,11, 5},{11,11,861},{11,11,951},{139,11,980},{132,11,717},{132,10,695},{7,10,497},{9, 10,387},{147,10,81},{132,0,420},{142,0,37},{6,0,1134},{6,0,1900},{12,0,830},{12, 0,878},{12,0,894},{15,0,221},{143,0,245},{132,11,489},{7,0,1570},{140,0,542},{8, 0,933},{136,0,957},{6,0,1371},{7,0,31},{8,0,373},{5,10,284},{6,10,49},{6,10,350} ,{7,10,377},{7,10,1693},{8,10,678},{9,10,161},{9,10,585},{9,10,671},{9,10,839},{ 11,10,912},{141,10,427},{135,11,892},{4,0,325},{138,0,125},{139,11,47},{132,10, 597},{138,0,323},{6,0,1547},{7,11,1605},{9,11,473},{11,11,962},{146,11,139},{139 ,10,908},{7,11,819},{9,11,26},{9,11,392},{10,11,152},{10,11,226},{11,11,19},{12, 11,276},{12,11,426},{12,11,589},{13,11,460},{15,11,97},{19,11,48},{148,11,104},{ 135,11,51},{4,0,718},{135,0,1216},{6,0,1896},{6,0,1905},{6,0,1912},{9,0,947},{9, 0,974},{12,0,809},{12,0,850},{12,0,858},{12,0,874},{12,0,887},{12,0,904},{12,0, 929},{12,0,948},{12,0,952},{15,0,198},{15,0,206},{15,0,220},{15,0,227},{15,0,247 },{18,0,188},{21,0,48},{21,0,50},{24,0,25},{24,0,29},{7,11,761},{7,11,1051},{137 ,11,545},{5,0,124},{5,0,144},{6,0,548},{7,0,15},{7,0,153},{137,0,629},{135,11, 606},{135,10,2014},{7,10,2007},{9,11,46},{9,10,101},{9,10,450},{10,10,66},{10,10 ,842},{11,10,536},{140,10,587},{6,0,75},{7,0,1531},{8,0,416},{9,0,240},{9,0,275} ,{10,0,100},{11,0,658},{11,0,979},{12,0,86},{14,0,207},{15,0,20},{143,0,25},{5,0 ,141},{5,0,915},{6,0,1783},{7,0,211},{7,0,698},{7,0,1353},{9,0,83},{9,0,281},{10 ,0,376},{10,0,431},{11,0,543},{12,0,664},{13,0,280},{13,0,428},{14,0,61},{14,0, 128},{17,0,52},{145,0,81},{132,11,674},{135,0,533},{149,0,6},{132,11,770},{133,0 ,538},{5,11,79},{7,11,1027},{7,11,1477},{139,11,52},{139,10,62},{4,0,338},{133,0 ,400},{5,11,789},{134,11,195},{4,11,251},{4,11,688},{7,11,513},{7,11,1284},{9,11 ,87},{138,11,365},{134,10,1766},{6,0,0},{7,0,84},{11,0,895},{145,0,11},{139,0, 892},{4,0,221},{5,0,659},{7,0,697},{7,0,1211},{138,0,284},{133,0,989},{133,11, 889},{4,11,160},{5,11,330},{7,11,1434},{136,11,174},{6,10,1665},{7,10,256},{7,10 ,1388},{10,10,499},{139,10,670},{7,0,848},{4,10,22},{5,10,10},{136,10,97},{138,0 ,507},{133,10,481},{4,0,188},{135,0,805},{5,0,884},{6,0,732},{139,0,991},{135,11 ,968},{11,11,636},{15,11,145},{17,11,34},{19,11,50},{151,11,20},{7,0,959},{16,0, 60},{6,10,134},{7,10,437},{9,10,37},{14,10,285},{142,10,371},{7,10,486},{8,10, 155},{11,10,93},{140,10,164},{134,0,1653},{7,0,337},{133,10,591},{6,0,1989},{8,0 ,922},{8,0,978},{133,11,374},{132,0,638},{138,0,500},{133,11,731},{5,10,380},{5, 10,650},{136,10,310},{138,11,381},{4,10,364},{7,10,1156},{7,10,1187},{137,10,409 },{137,11,224},{140,0,166},{134,10,482},{4,11,626},{5,11,642},{6,11,425},{10,11, 202},{139,11,141},{4,10,781},{6,10,487},{7,10,926},{8,10,263},{139,10,500},{135, 0,418},{4,10,94},{135,10,1265},{136,0,760},{132,10,417},{136,11,835},{5,10,348}, {134,10,522},{6,0,1277},{134,0,1538},{139,11,541},{135,11,1597},{5,11,384},{8,11 ,455},{140,11,48},{136,0,770},{5,11,264},{134,11,184},{4,0,89},{5,0,489},{6,0, 315},{7,0,553},{7,0,1745},{138,0,243},{4,10,408},{4,10,741},{135,10,500},{134,0, 1396},{133,0,560},{6,0,1658},{9,0,3},{10,0,154},{11,0,641},{13,0,85},{13,0,201}, {141,0,346},{135,11,1595},{5,11,633},{6,11,28},{7,11,219},{135,11,1323},{9,11, 769},{140,11,185},{135,11,785},{7,11,359},{8,11,243},{140,11,175},{138,0,586},{7 ,0,1271},{134,10,73},{132,11,105},{4,0,166},{5,0,505},{134,0,1670},{133,10,576}, {4,11,324},{138,11,104},{142,10,231},{6,0,637},{7,10,1264},{7,10,1678},{11,10, 945},{12,10,341},{12,10,471},{12,10,569},{23,11,21},{151,11,23},{8,11,559},{141, 11,109},{134,0,1947},{7,0,445},{8,0,307},{8,0,704},{10,0,41},{10,0,439},{11,0, 237},{11,0,622},{140,0,201},{135,11,963},{135,0,1977},{4,0,189},{5,0,713},{136,0 ,57},{138,0,371},{135,10,538},{132,0,552},{6,0,883},{133,10,413},{6,0,923},{132, 11,758},{138,11,215},{136,10,495},{7,10,54},{8,10,312},{10,10,191},{10,10,614},{ 140,10,567},{7,11,351},{139,11,128},{7,0,875},{6,10,468},{7,10,1478},{8,10,530}, {142,10,290},{135,0,1788},{17,0,49},{133,11,918},{12,11,398},{20,11,39},{21,11, 11},{150,11,41},{10,0,661},{6,10,484},{135,10,822},{135,0,1945},{134,0,794},{137 ,10,900},{135,10,1335},{6,10,1724},{135,10,2022},{132,11,340},{134,0,1135},{4,0, 784},{133,0,745},{5,0,84},{134,0,163},{133,0,410},{4,0,976},{5,11,985},{7,11,509 },{7,11,529},{145,11,96},{132,10,474},{134,0,703},{135,11,1919},{5,0,322},{8,0, 186},{9,0,262},{10,0,187},{142,0,208},{135,10,1504},{133,0,227},{9,0,560},{13,0, 208},{133,10,305},{132,11,247},{7,0,1395},{8,0,486},{9,0,236},{9,0,878},{10,0, 218},{11,0,95},{19,0,17},{147,0,31},{7,0,2043},{8,0,672},{141,0,448},{4,11,184}, {5,11,390},{6,11,337},{7,11,23},{7,11,494},{7,11,618},{7,11,1456},{8,11,27},{8, 11,599},{10,11,153},{139,11,710},{135,0,466},{135,10,1236},{6,0,167},{7,0,186},{ 7,0,656},{10,0,643},{4,10,480},{6,10,302},{6,10,1642},{7,10,837},{7,10,1547},{7, 10,1657},{8,10,429},{9,10,228},{13,10,289},{13,10,343},{147,10,101},{134,0,1428} ,{134,0,1440},{5,0,412},{7,10,278},{10,10,739},{11,10,708},{141,10,348},{134,0, 1118},{136,0,562},{148,11,46},{9,0,316},{139,0,256},{134,0,1771},{135,0,1190},{ 137,0,132},{10,11,227},{11,11,497},{11,11,709},{140,11,415},{143,0,66},{6,11,360 },{7,11,1664},{136,11,478},{144,10,28},{4,0,317},{135,0,1279},{5,0,63},{133,0, 509},{136,11,699},{145,10,36},{134,0,1475},{11,11,343},{142,11,127},{132,11,739} ,{132,0,288},{135,11,1757},{8,0,89},{8,0,620},{9,0,608},{11,0,628},{12,0,322},{ 143,0,124},{134,0,1225},{7,0,1189},{4,11,67},{5,11,422},{6,10,363},{7,11,1037},{ 7,11,1289},{7,11,1555},{7,10,1955},{8,10,725},{9,11,741},{145,11,108},{134,0, 1468},{6,0,689},{134,0,1451},{138,0,120},{151,0,1},{137,10,805},{142,0,329},{5, 10,813},{135,10,2046},{135,0,226},{138,11,96},{7,0,1855},{5,10,712},{11,10,17},{ 13,10,321},{144,10,67},{9,0,461},{6,10,320},{7,10,781},{7,10,1921},{9,10,55},{10 ,10,186},{10,10,273},{10,10,664},{10,10,801},{11,10,996},{11,10,997},{13,10,157} ,{142,10,170},{8,11,203},{8,10,271},{11,11,823},{11,11,846},{12,11,482},{13,11, 133},{13,11,277},{13,11,302},{13,11,464},{14,11,205},{142,11,221},{135,0,1346},{ 4,11,449},{133,11,718},{134,0,85},{14,0,299},{7,10,103},{7,10,863},{11,10,184},{ 145,10,62},{4,11,355},{6,11,311},{9,11,256},{138,11,404},{137,10,659},{138,11, 758},{133,11,827},{5,11,64},{140,11,581},{134,0,1171},{4,11,442},{7,11,1047},{7, 11,1352},{135,11,1643},{132,0,980},{5,11,977},{6,11,288},{7,11,528},{135,11,1065 },{5,0,279},{6,0,235},{7,0,468},{8,0,446},{9,0,637},{10,0,717},{11,0,738},{140,0 ,514},{132,0,293},{11,10,337},{142,10,303},{136,11,285},{5,0,17},{6,0,371},{9,0, 528},{12,0,364},{132,11,254},{5,10,77},{7,10,1455},{10,10,843},{147,10,73},{150, 0,5},{132,10,458},{6,11,12},{7,11,1219},{145,11,73},{135,10,1420},{6,10,109},{ 138,10,382},{135,11,125},{6,10,330},{7,10,1084},{139,10,142},{6,11,369},{6,11, 502},{7,11,1036},{8,11,348},{9,11,452},{10,11,26},{11,11,224},{11,11,387},{11,11 ,772},{12,11,95},{12,11,629},{13,11,195},{13,11,207},{13,11,241},{14,11,260},{14 ,11,270},{143,11,140},{132,11,269},{5,11,480},{7,11,532},{7,11,1197},{7,11,1358} ,{8,11,291},{11,11,349},{142,11,396},{150,0,48},{10,0,601},{13,0,353},{141,0,376 },{5,0,779},{5,0,807},{6,0,1655},{134,0,1676},{142,11,223},{4,0,196},{5,0,558},{ 133,0,949},{148,11,15},{135,11,1764},{134,0,1322},{132,0,752},{139,0,737},{135, 11,657},{136,11,533},{135,0,412},{4,0,227},{5,0,159},{5,0,409},{7,0,80},{8,0,556 },{10,0,479},{12,0,418},{14,0,50},{14,0,123},{14,0,192},{14,0,249},{14,0,295},{ 143,0,27},{7,0,1470},{8,0,66},{8,0,137},{8,0,761},{9,0,638},{11,0,80},{11,0,212} ,{11,0,368},{11,0,418},{12,0,8},{13,0,15},{16,0,61},{17,0,59},{19,0,28},{148,0, 84},{135,10,1985},{4,11,211},{4,11,332},{5,11,335},{6,11,238},{7,11,269},{7,11, 811},{7,11,1797},{8,10,122},{8,11,836},{9,11,507},{141,11,242},{6,0,683},{134,0, 1252},{4,0,873},{132,10,234},{134,0,835},{6,0,38},{7,0,1220},{8,0,185},{8,0,256} ,{9,0,22},{9,0,331},{10,0,738},{11,0,205},{11,0,540},{11,0,746},{13,0,465},{14,0 ,88},{142,0,194},{138,0,986},{5,11,1009},{12,11,582},{146,11,131},{4,0,159},{6,0 ,115},{7,0,252},{7,0,257},{7,0,1928},{8,0,69},{9,0,384},{10,0,91},{10,0,615},{12 ,0,375},{14,0,235},{18,0,117},{147,0,123},{133,0,911},{136,0,278},{5,10,430},{5, 10,932},{6,10,131},{7,10,417},{9,10,522},{11,10,314},{141,10,390},{14,10,149},{ 14,10,399},{143,10,57},{4,0,151},{7,0,1567},{136,0,749},{5,11,228},{6,11,203},{7 ,11,156},{8,11,347},{137,11,265},{132,10,507},{10,0,989},{140,0,956},{133,0,990} ,{5,0,194},{6,0,927},{7,0,1662},{9,0,90},{140,0,564},{4,10,343},{133,10,511},{ 133,0,425},{7,10,455},{138,10,591},{4,0,774},{7,11,476},{7,11,1592},{138,11,87}, {5,0,971},{135,10,1381},{5,11,318},{147,11,121},{5,11,291},{7,11,765},{9,11,389} ,{140,11,548},{134,10,575},{4,0,827},{12,0,646},{12,0,705},{12,0,712},{140,0,714 },{139,0,752},{137,0,662},{5,0,72},{6,0,264},{7,0,21},{7,0,46},{7,0,2013},{8,0, 215},{8,0,513},{10,0,266},{139,0,22},{139,11,522},{6,0,239},{7,0,118},{10,0,95}, {11,0,603},{13,0,443},{14,0,160},{143,0,4},{6,0,431},{134,0,669},{7,10,1127},{7, 10,1572},{10,10,297},{10,10,422},{11,10,764},{11,10,810},{12,10,264},{13,10,102} ,{13,10,300},{13,10,484},{14,10,147},{14,10,229},{17,10,71},{18,10,118},{147,10, 120},{5,0,874},{6,0,1677},{15,0,0},{10,11,525},{139,11,82},{6,0,65},{7,0,939},{7 ,0,1172},{7,0,1671},{9,0,540},{10,0,696},{11,0,265},{11,0,732},{11,0,928},{11,0, 937},{141,0,438},{134,0,1350},{136,11,547},{132,11,422},{5,11,355},{145,11,0},{ 137,11,905},{5,0,682},{135,0,1887},{132,0,809},{4,0,696},{133,11,865},{6,0,1074} ,{6,0,1472},{14,10,35},{142,10,191},{5,11,914},{134,11,1625},{133,11,234},{135, 11,1383},{137,11,780},{132,10,125},{4,0,726},{133,0,630},{8,0,802},{136,0,838},{ 132,10,721},{6,0,1337},{7,0,776},{19,0,56},{136,10,145},{132,0,970},{7,10,792},{ 8,10,147},{10,10,821},{139,10,1021},{139,10,970},{8,0,940},{137,0,797},{135,11, 1312},{9,0,248},{10,0,400},{7,11,816},{7,11,1241},{7,10,1999},{9,11,283},{9,11, 520},{10,11,213},{10,11,307},{10,11,463},{10,11,671},{10,11,746},{11,11,401},{11 ,11,794},{12,11,517},{18,11,107},{147,11,115},{6,0,1951},{134,0,2040},{135,11, 339},{13,0,41},{15,0,93},{5,10,168},{5,10,930},{8,10,74},{9,10,623},{12,10,500}, {140,10,579},{6,0,118},{7,0,215},{7,0,1521},{140,0,11},{6,10,220},{7,10,1101},{ 141,10,105},{6,11,421},{7,11,61},{7,11,1540},{10,11,11},{138,11,501},{7,0,615},{ 138,0,251},{140,11,631},{135,0,1044},{6,10,19},{7,10,1413},{139,10,428},{133,0, 225},{7,10,96},{8,10,401},{8,10,703},{137,10,896},{145,10,116},{6,11,102},{7,11, 72},{15,11,142},{147,11,67},{7,10,1961},{7,10,1965},{8,10,702},{136,10,750},{7, 10,2030},{8,10,150},{8,10,737},{12,10,366},{151,11,30},{4,0,370},{5,0,756},{7,0, 1326},{135,11,823},{8,10,800},{9,10,148},{9,10,872},{9,10,890},{11,10,309},{11, 10,1001},{13,10,267},{141,10,323},{6,0,1662},{7,0,48},{8,0,771},{10,0,116},{13,0 ,104},{14,0,105},{14,0,184},{15,0,168},{19,0,92},{148,0,68},{10,0,209},{135,11, 1870},{7,11,68},{8,11,48},{8,11,88},{8,11,582},{8,11,681},{9,11,373},{9,11,864}, {11,11,157},{11,11,336},{11,11,843},{148,11,27},{134,0,930},{4,11,88},{5,11,137} ,{5,11,174},{5,11,777},{6,11,1664},{6,11,1725},{7,11,77},{7,11,426},{7,11,1317}, {7,11,1355},{8,11,126},{8,11,563},{9,11,523},{9,11,750},{10,11,310},{10,11,836}, {11,11,42},{11,11,318},{11,11,731},{12,11,68},{12,11,92},{12,11,507},{12,11,692} ,{13,11,81},{13,11,238},{13,11,374},{18,11,138},{19,11,78},{19,11,111},{20,11,55 },{20,11,77},{148,11,92},{4,11,938},{135,11,1831},{5,10,547},{7,10,424},{8,11, 617},{138,11,351},{6,0,1286},{6,11,1668},{7,11,1499},{8,11,117},{9,11,314},{138, 11,174},{6,0,759},{6,0,894},{7,11,707},{139,11,563},{4,0,120},{135,0,1894},{9,0, 385},{149,0,17},{138,0,429},{133,11,403},{5,0,820},{135,0,931},{10,0,199},{133, 10,133},{6,0,151},{6,0,1675},{7,0,383},{151,0,10},{6,0,761},{136,10,187},{8,0, 365},{10,10,0},{10,10,818},{139,10,988},{4,11,44},{5,11,311},{6,11,156},{7,11, 639},{7,11,762},{7,11,1827},{9,11,8},{9,11,462},{148,11,83},{4,11,346},{7,11,115 },{9,11,180},{9,11,456},{138,11,363},{136,10,685},{7,0,1086},{145,0,46},{6,0, 1624},{11,0,11},{12,0,422},{13,0,444},{142,0,360},{6,0,1020},{6,0,1260},{134,0, 1589},{4,0,43},{5,0,344},{5,0,357},{14,0,472},{150,0,58},{6,0,1864},{6,0,1866},{ 6,0,1868},{6,0,1869},{6,0,1874},{6,0,1877},{6,0,1903},{6,0,1911},{9,0,920},{9,0, 921},{9,0,924},{9,0,946},{9,0,959},{9,0,963},{9,0,970},{9,0,997},{9,0,1008},{9,0 ,1017},{12,0,795},{12,0,797},{12,0,798},{12,0,800},{12,0,803},{12,0,811},{12,0, 820},{12,0,821},{12,0,839},{12,0,841},{12,0,848},{12,0,911},{12,0,921},{12,0,922 },{12,0,925},{12,0,937},{12,0,944},{12,0,945},{12,0,953},{15,0,184},{15,0,191},{ 15,0,199},{15,0,237},{15,0,240},{15,0,243},{15,0,246},{18,0,203},{21,0,40},{21,0 ,52},{21,0,57},{24,0,23},{24,0,28},{152,0,30},{134,0,725},{145,11,58},{133,0,888 },{137,10,874},{4,0,711},{8,10,774},{10,10,670},{140,10,51},{144,11,40},{6,11, 185},{7,11,1899},{139,11,673},{137,10,701},{137,0,440},{4,11,327},{5,11,478},{7, 11,1332},{8,11,753},{140,11,227},{4,10,127},{5,10,350},{6,10,356},{8,10,426},{9, 10,572},{10,10,247},{139,10,312},{5,11,1020},{133,11,1022},{4,11,103},{133,11, 401},{6,0,1913},{6,0,1926},{6,0,1959},{9,0,914},{9,0,939},{9,0,952},{9,0,979},{9 ,0,990},{9,0,998},{9,0,1003},{9,0,1023},{12,0,827},{12,0,834},{12,0,845},{12,0, 912},{12,0,935},{12,0,951},{15,0,172},{15,0,174},{18,0,198},{149,0,63},{5,0,958} ,{5,0,987},{4,11,499},{135,11,1421},{7,0,885},{6,10,59},{6,10,1762},{9,10,603},{ 141,10,397},{10,11,62},{141,11,164},{4,0,847},{135,0,326},{11,0,276},{142,0,293} ,{4,0,65},{5,0,479},{5,0,1004},{7,0,1913},{8,0,317},{9,0,302},{10,0,612},{13,0, 22},{132,11,96},{4,0,261},{135,0,510},{135,0,1514},{6,10,111},{7,10,4},{8,10,163 },{8,10,776},{138,10,566},{4,0,291},{9,0,515},{12,0,152},{12,0,443},{13,0,392},{ 142,0,357},{7,11,399},{135,11,1492},{4,0,589},{139,0,282},{6,11,563},{135,10, 1994},{5,10,297},{135,10,1038},{4,0,130},{7,0,843},{135,0,1562},{5,0,42},{5,0, 879},{7,0,245},{7,0,324},{7,0,1532},{11,0,463},{11,0,472},{13,0,363},{144,0,52}, {4,0,134},{133,0,372},{133,0,680},{136,10,363},{6,0,1997},{8,0,935},{136,0,977}, {4,0,810},{135,0,1634},{135,10,1675},{7,0,1390},{4,11,910},{133,11,832},{7,10, 808},{8,11,266},{139,11,578},{132,0,644},{4,0,982},{138,0,867},{132,10,280},{135 ,0,540},{140,10,54},{135,0,123},{134,0,1978},{4,10,421},{133,10,548},{6,0,623},{ 136,0,789},{4,0,908},{5,0,359},{5,0,508},{6,0,1723},{7,0,343},{7,0,1996},{135,0, 2026},{134,0,1220},{4,0,341},{135,0,480},{6,10,254},{9,10,109},{138,10,103},{134 ,0,888},{8,11,528},{137,11,348},{7,0,1995},{8,0,299},{11,0,890},{12,0,674},{4,11 ,20},{133,11,616},{135,11,1094},{134,10,1630},{4,0,238},{5,0,503},{6,0,179},{7,0 ,2003},{8,0,381},{8,0,473},{9,0,149},{10,0,788},{15,0,45},{15,0,86},{20,0,110},{ 150,0,57},{133,10,671},{4,11,26},{5,11,429},{6,11,245},{7,11,704},{7,11,1379},{ 135,11,1474},{4,0,121},{5,0,156},{5,0,349},{9,0,431},{10,0,605},{142,0,342},{7, 11,943},{139,11,614},{132,10,889},{132,11,621},{7,10,1382},{7,11,1382},{135,10, 1910},{132,10,627},{133,10,775},{133,11,542},{133,11,868},{136,11,433},{6,0,1373 },{7,0,1011},{11,10,362},{11,10,948},{140,10,388},{6,0,80},{7,0,173},{9,0,547},{ 10,0,730},{14,0,18},{22,0,39},{135,11,1495},{6,0,1694},{135,0,1974},{140,0,196}, {4,0,923},{6,0,507},{6,0,1711},{7,10,451},{8,10,389},{12,10,490},{13,10,16},{13, 10,215},{13,10,351},{18,10,132},{147,10,125},{6,0,646},{134,0,1047},{135,10,841} ,{136,10,566},{6,0,1611},{135,0,1214},{139,0,926},{132,11,525},{132,0,595},{5,0, 240},{6,0,459},{7,0,12},{7,0,114},{7,0,949},{7,0,1753},{7,0,1805},{8,0,658},{9,0 ,1},{11,0,959},{141,0,446},{5,10,912},{134,10,1695},{132,0,446},{7,11,62},{12,11 ,45},{147,11,112},{5,10,236},{6,10,572},{8,10,492},{11,10,618},{144,10,56},{5,10 ,190},{136,10,318},{135,10,1376},{4,11,223},{6,11,359},{11,11,3},{13,11,108},{14 ,11,89},{144,11,22},{132,11,647},{134,0,490},{134,0,491},{134,0,1584},{135,11, 685},{138,11,220},{7,0,250},{136,0,507},{132,0,158},{4,0,140},{7,0,362},{8,0,209 },{9,0,10},{9,0,160},{9,0,503},{9,0,614},{10,0,689},{11,0,327},{11,0,553},{11,0, 725},{11,0,767},{12,0,252},{12,0,583},{13,0,192},{14,0,269},{14,0,356},{148,0,50 },{19,0,1},{19,0,26},{150,0,9},{132,11,109},{6,0,228},{7,0,1341},{9,0,408},{138, 0,343},{4,0,373},{5,0,283},{6,0,480},{7,0,609},{10,0,860},{138,0,878},{6,0,779}, {134,0,1209},{4,0,557},{7,11,263},{7,11,628},{136,11,349},{132,0,548},{7,0,197}, {8,0,142},{8,0,325},{9,0,150},{9,0,596},{10,0,350},{10,0,353},{11,0,74},{11,0, 315},{12,0,662},{12,0,681},{14,0,423},{143,0,141},{4,11,40},{10,11,67},{11,11, 117},{11,11,768},{139,11,935},{7,11,992},{8,11,301},{9,11,722},{12,11,63},{13,11 ,29},{14,11,161},{143,11,18},{6,0,1490},{138,11,532},{5,0,580},{7,0,378},{7,0, 674},{7,0,1424},{15,0,83},{16,0,11},{15,11,83},{144,11,11},{6,0,1057},{6,0,1335} ,{10,0,316},{7,10,85},{7,10,247},{8,10,585},{138,10,163},{4,0,169},{5,0,83},{6,0 ,399},{6,0,579},{6,0,1513},{7,0,692},{7,0,846},{7,0,1015},{7,0,1799},{8,0,403},{ 9,0,394},{10,0,133},{12,0,4},{12,0,297},{12,0,452},{16,0,81},{18,0,25},{21,0,14} ,{22,0,12},{151,0,18},{134,0,1106},{7,0,1546},{11,0,299},{142,0,407},{134,0,1192 },{132,0,177},{5,0,411},{135,0,653},{7,0,439},{10,0,727},{11,0,260},{139,0,684}, {138,10,145},{147,10,83},{5,0,208},{7,0,753},{135,0,1528},{137,11,617},{135,10, 1922},{135,11,825},{11,0,422},{13,0,389},{4,10,124},{10,10,457},{11,10,121},{11, 10,169},{11,10,870},{12,10,214},{14,10,187},{143,10,77},{11,0,615},{15,0,58},{11 ,11,615},{143,11,58},{9,0,618},{138,0,482},{6,0,1952},{6,0,1970},{142,0,505},{7, 10,1193},{135,11,1838},{133,0,242},{135,10,1333},{6,10,107},{7,10,638},{7,10, 1632},{137,10,396},{133,0,953},{5,10,370},{134,10,1756},{5,11,28},{6,11,204},{10 ,11,320},{10,11,583},{13,11,502},{14,11,72},{14,11,274},{14,11,312},{14,11,344}, {15,11,159},{16,11,62},{16,11,69},{17,11,30},{18,11,42},{18,11,53},{18,11,84},{ 18,11,140},{19,11,68},{19,11,85},{20,11,5},{20,11,45},{20,11,101},{22,11,7},{150 ,11,20},{4,11,558},{6,11,390},{7,11,162},{7,11,689},{9,11,360},{138,11,653},{11, 0,802},{141,0,67},{133,10,204},{133,0,290},{5,10,970},{134,10,1706},{132,0,380}, {5,0,52},{7,0,277},{9,0,368},{139,0,791},{5,11,856},{6,11,1672},{6,11,1757},{6, 11,1781},{7,11,1150},{7,11,1425},{7,11,1453},{140,11,513},{5,11,92},{7,10,3},{10 ,11,736},{140,11,102},{4,0,112},{5,0,653},{5,10,483},{5,10,685},{6,10,489},{7,10 ,1204},{136,10,394},{132,10,921},{6,0,1028},{133,10,1007},{5,11,590},{9,11,213}, {145,11,91},{135,10,1696},{10,0,138},{139,0,476},{5,0,725},{5,0,727},{135,0,1811 },{4,0,979},{6,0,1821},{6,0,1838},{8,0,876},{8,0,883},{8,0,889},{8,0,893},{8,0, 895},{10,0,934},{12,0,720},{14,0,459},{148,0,123},{135,11,551},{4,0,38},{6,0,435 },{7,0,307},{7,0,999},{7,0,1481},{7,0,1732},{7,0,1738},{8,0,371},{9,0,414},{11,0 ,316},{12,0,52},{13,0,420},{147,0,100},{135,0,1296},{132,10,712},{134,10,1629},{ 133,0,723},{134,0,651},{136,11,191},{9,11,791},{10,11,93},{11,11,301},{16,11,13} ,{17,11,23},{18,11,135},{19,11,12},{20,11,1},{20,11,12},{148,11,14},{136,11,503} ,{6,11,466},{135,11,671},{6,0,1200},{134,0,1330},{135,0,1255},{134,0,986},{5,0, 109},{6,0,1784},{7,0,1895},{12,0,296},{140,0,302},{135,11,983},{133,10,485},{134 ,0,660},{134,0,800},{5,0,216},{5,0,294},{6,0,591},{7,0,1879},{9,0,141},{9,0,270} ,{9,0,679},{10,0,159},{11,0,197},{11,0,438},{12,0,538},{12,0,559},{14,0,144},{14 ,0,167},{15,0,67},{4,10,285},{5,10,317},{6,10,301},{7,10,7},{8,10,153},{10,10, 766},{11,10,468},{12,10,467},{141,10,143},{136,0,945},{134,0,1090},{137,0,81},{ 12,11,468},{19,11,96},{148,11,24},{134,0,391},{138,11,241},{7,0,322},{136,0,249} ,{134,0,1412},{135,11,795},{5,0,632},{138,0,526},{136,10,819},{6,0,144},{7,0,948 },{7,0,1042},{8,0,235},{8,0,461},{9,0,453},{9,0,796},{10,0,354},{17,0,77},{135, 11,954},{139,10,917},{6,0,940},{134,0,1228},{4,0,362},{7,0,52},{135,0,303},{6,11 ,549},{8,11,34},{8,11,283},{9,11,165},{138,11,475},{7,11,370},{7,11,1007},{7,11, 1177},{135,11,1565},{5,11,652},{5,11,701},{135,11,449},{5,0,196},{6,0,486},{7,0, 212},{8,0,309},{136,0,346},{6,10,1719},{6,10,1735},{7,10,2016},{7,10,2020},{8,10 ,837},{137,10,852},{6,11,159},{6,11,364},{7,11,516},{7,11,1439},{137,11,518},{ 135,0,1912},{135,0,1290},{132,0,686},{141,11,151},{138,0,625},{136,0,706},{138, 10,568},{139,0,412},{4,0,30},{133,0,43},{8,10,67},{138,10,419},{7,0,967},{141,0, 11},{12,0,758},{14,0,441},{142,0,462},{10,10,657},{14,10,297},{142,10,361},{139, 10,729},{4,0,220},{135,0,1535},{7,11,501},{9,11,111},{10,11,141},{11,11,332},{13 ,11,43},{13,11,429},{14,11,130},{14,11,415},{145,11,102},{4,0,950},{6,0,1859},{7 ,0,11},{8,0,873},{12,0,710},{12,0,718},{12,0,748},{12,0,765},{148,0,124},{5,11, 149},{5,11,935},{136,11,233},{142,11,291},{134,0,1579},{7,0,890},{8,10,51},{9,10 ,868},{10,10,833},{12,10,481},{12,10,570},{148,10,106},{141,0,2},{132,10,445},{ 136,11,801},{135,0,1774},{7,0,1725},{138,0,393},{5,0,263},{134,0,414},{132,11, 322},{133,10,239},{7,0,456},{7,10,1990},{8,10,130},{139,10,720},{137,0,818},{5, 10,123},{6,10,530},{7,10,348},{135,10,1419},{135,10,2024},{6,0,178},{6,0,1750},{ 8,0,251},{9,0,690},{10,0,155},{10,0,196},{10,0,373},{11,0,698},{13,0,155},{148,0 ,93},{5,0,97},{137,0,393},{134,0,674},{11,0,223},{140,0,168},{132,10,210},{139, 11,464},{6,0,1639},{146,0,159},{139,11,2},{7,0,934},{8,0,647},{17,0,97},{19,0,59 },{150,0,2},{132,0,191},{5,0,165},{9,0,346},{10,0,655},{11,0,885},{4,10,430},{ 135,11,357},{133,0,877},{5,10,213},{133,11,406},{8,0,128},{139,0,179},{6,11,69}, {135,11,117},{135,0,1297},{11,11,43},{13,11,72},{141,11,142},{135,11,1830},{142, 0,164},{5,0,57},{6,0,101},{6,0,586},{6,0,1663},{7,0,132},{7,0,1154},{7,0,1415},{ 7,0,1507},{12,0,493},{15,0,105},{151,0,15},{5,0,459},{7,0,1073},{8,0,241},{136,0 ,334},{133,11,826},{133,10,108},{5,10,219},{10,11,132},{11,11,191},{11,11,358},{ 139,11,460},{6,0,324},{6,0,520},{7,0,338},{7,0,1729},{8,0,228},{139,0,750},{21,0 ,30},{22,0,53},{4,10,193},{5,10,916},{7,10,364},{10,10,398},{10,10,726},{11,10, 317},{11,10,626},{12,10,142},{12,10,288},{12,10,678},{13,10,313},{15,10,113},{ 146,10,114},{6,11,110},{135,11,1681},{135,0,910},{6,10,241},{7,10,907},{8,10,832 },{9,10,342},{10,10,729},{11,10,284},{11,10,445},{11,10,651},{11,10,863},{13,10, 398},{146,10,99},{7,0,705},{9,0,734},{5,11,1000},{7,11,733},{137,11,583},{4,0,73 },{6,0,612},{7,0,927},{7,0,1822},{8,0,217},{9,0,765},{9,0,766},{10,0,408},{11,0, 51},{11,0,793},{12,0,266},{15,0,158},{20,0,89},{150,0,32},{7,0,1330},{4,11,297}, {6,11,529},{7,11,152},{7,11,713},{7,11,1845},{8,11,710},{8,11,717},{140,11,639}, {5,0,389},{136,0,636},{134,0,1409},{4,10,562},{9,10,254},{139,10,879},{134,0,893 },{132,10,786},{4,11,520},{135,11,575},{136,0,21},{140,0,721},{136,0,959},{7,11, 1428},{7,11,1640},{9,11,169},{9,11,182},{9,11,367},{9,11,478},{9,11,506},{9,11, 551},{9,11,648},{9,11,651},{9,11,697},{9,11,705},{9,11,725},{9,11,787},{9,11,794 },{10,11,198},{10,11,214},{10,11,267},{10,11,275},{10,11,456},{10,11,551},{10,11 ,561},{10,11,613},{10,11,627},{10,11,668},{10,11,675},{10,11,691},{10,11,695},{ 10,11,707},{10,11,715},{11,11,183},{11,11,201},{11,11,244},{11,11,262},{11,11, 352},{11,11,439},{11,11,493},{11,11,572},{11,11,591},{11,11,608},{11,11,611},{11 ,11,646},{11,11,674},{11,11,711},{11,11,751},{11,11,761},{11,11,776},{11,11,785} ,{11,11,850},{11,11,853},{11,11,862},{11,11,865},{11,11,868},{11,11,898},{11,11, 902},{11,11,903},{11,11,910},{11,11,932},{11,11,942},{11,11,957},{11,11,967},{11 ,11,972},{12,11,148},{12,11,195},{12,11,220},{12,11,237},{12,11,318},{12,11,339} ,{12,11,393},{12,11,445},{12,11,450},{12,11,474},{12,11,509},{12,11,533},{12,11, 591},{12,11,594},{12,11,597},{12,11,621},{12,11,633},{12,11,642},{13,11,59},{13, 11,60},{13,11,145},{13,11,239},{13,11,250},{13,11,273},{13,11,329},{13,11,344},{ 13,11,365},{13,11,372},{13,11,387},{13,11,403},{13,11,414},{13,11,456},{13,11, 478},{13,11,483},{13,11,489},{14,11,55},{14,11,57},{14,11,81},{14,11,90},{14,11, 148},{14,11,239},{14,11,266},{14,11,321},{14,11,326},{14,11,327},{14,11,330},{14 ,11,347},{14,11,355},{14,11,401},{14,11,411},{14,11,414},{14,11,416},{14,11,420} ,{15,11,61},{15,11,74},{15,11,87},{15,11,88},{15,11,94},{15,11,96},{15,11,116},{ 15,11,149},{15,11,154},{16,11,50},{16,11,63},{16,11,73},{17,11,2},{17,11,66},{17 ,11,92},{17,11,103},{17,11,112},{18,11,50},{18,11,54},{18,11,82},{18,11,86},{18, 11,90},{18,11,111},{18,11,115},{18,11,156},{19,11,40},{19,11,79},{20,11,78},{149 ,11,22},{137,11,170},{134,0,1433},{135,11,1307},{139,11,411},{5,0,189},{7,0,442} ,{7,0,443},{8,0,281},{12,0,174},{141,0,261},{6,10,216},{7,10,901},{7,10,1343},{ 136,10,493},{5,11,397},{6,11,154},{7,10,341},{7,11,676},{8,11,443},{8,11,609},{9 ,11,24},{9,11,325},{10,11,35},{11,10,219},{11,11,535},{11,11,672},{11,11,1018},{ 12,11,637},{144,11,30},{6,0,2},{7,0,191},{7,0,446},{7,0,1262},{7,0,1737},{8,0,22 },{8,0,270},{8,0,612},{9,0,4},{9,0,312},{9,0,436},{9,0,626},{10,0,216},{10,0,311 },{10,0,521},{10,0,623},{11,0,72},{11,0,330},{11,0,455},{12,0,321},{12,0,504},{ 12,0,530},{12,0,543},{13,0,17},{13,0,156},{13,0,334},{14,0,131},{17,0,60},{148,0 ,64},{7,0,354},{10,0,410},{139,0,815},{139,10,130},{7,10,1734},{137,11,631},{12, 0,425},{15,0,112},{10,10,115},{11,10,420},{13,10,404},{14,10,346},{143,10,54},{6 ,0,60},{6,0,166},{7,0,374},{7,0,670},{7,0,1327},{8,0,411},{8,0,435},{9,0,653},{9 ,0,740},{10,0,385},{11,0,222},{11,0,324},{11,0,829},{140,0,611},{7,0,1611},{13,0 ,14},{15,0,44},{19,0,13},{148,0,76},{133,11,981},{4,11,56},{7,11,1791},{8,11,607 },{8,11,651},{11,11,465},{11,11,835},{12,11,337},{141,11,480},{6,0,1478},{5,10, 1011},{136,10,701},{139,0,596},{5,0,206},{134,0,398},{4,10,54},{5,10,666},{7,10, 1039},{7,10,1130},{9,10,195},{138,10,302},{7,0,50},{9,11,158},{138,11,411},{135, 11,1120},{6,0,517},{7,0,1159},{10,0,621},{11,0,192},{134,10,1669},{4,0,592},{6,0 ,600},{135,0,1653},{10,0,223},{139,0,645},{136,11,139},{7,0,64},{136,0,245},{142 ,0,278},{6,11,622},{135,11,1030},{136,0,604},{134,0,1502},{138,0,265},{141,11, 168},{7,0,1763},{140,0,310},{7,10,798},{139,11,719},{7,11,160},{10,11,624},{142, 11,279},{132,11,363},{7,10,122},{9,10,259},{10,10,84},{11,10,470},{12,10,541},{ 141,10,379},{5,0,129},{6,0,61},{135,0,947},{134,0,1356},{135,11,1191},{13,0,505} ,{141,0,506},{11,0,1000},{5,10,82},{5,10,131},{7,10,1755},{8,10,31},{9,10,168},{ 9,10,764},{139,10,869},{134,0,966},{134,10,605},{134,11,292},{5,11,177},{6,11, 616},{7,11,827},{9,11,525},{138,11,656},{135,11,1486},{138,11,31},{5,10,278},{ 137,10,68},{4,10,163},{5,10,201},{5,10,307},{5,10,310},{6,10,335},{7,10,284},{ 136,10,165},{6,0,839},{135,10,1660},{136,10,781},{6,10,33},{135,10,1244},{133,0, 637},{4,11,161},{133,11,631},{137,0,590},{7,10,1953},{136,10,720},{5,0,280},{7,0 ,1226},{138,10,203},{134,0,1386},{5,0,281},{6,0,1026},{6,10,326},{7,10,677},{137 ,10,425},{7,11,1557},{135,11,1684},{135,0,1064},{9,11,469},{9,11,709},{12,11,512 },{14,11,65},{145,11,12},{134,0,917},{10,11,229},{11,11,73},{11,11,376},{139,11, 433},{7,0,555},{9,0,192},{13,0,30},{13,0,49},{15,0,150},{16,0,76},{20,0,52},{7, 10,1316},{7,10,1412},{7,10,1839},{9,10,589},{11,10,241},{11,10,676},{11,10,811}, {11,10,891},{12,10,140},{12,10,346},{12,10,479},{13,10,381},{14,10,188},{146,10, 30},{149,0,15},{6,0,1882},{6,0,1883},{6,0,1897},{9,0,945},{9,0,1014},{9,0,1020}, {12,0,823},{12,0,842},{12,0,866},{12,0,934},{15,0,242},{146,0,208},{6,0,965},{ 134,0,1499},{7,0,33},{7,0,120},{8,0,489},{9,0,319},{10,0,820},{11,0,1004},{12,0, 379},{12,0,679},{13,0,117},{13,0,412},{14,0,25},{15,0,52},{15,0,161},{16,0,47},{ 149,0,2},{6,11,558},{7,11,651},{8,11,421},{9,11,0},{138,11,34},{4,0,937},{5,0, 801},{7,0,473},{5,10,358},{7,10,1184},{10,10,662},{13,10,212},{13,10,304},{13,10 ,333},{145,10,98},{132,0,877},{6,0,693},{134,0,824},{132,0,365},{7,11,1832},{138 ,11,374},{5,0,7},{139,0,774},{4,0,734},{5,0,662},{134,0,430},{4,0,746},{135,0, 1090},{5,0,360},{8,0,237},{10,0,231},{147,0,124},{138,11,348},{6,11,6},{7,11,81} ,{7,11,771},{7,11,1731},{9,11,405},{138,11,421},{6,0,740},{137,0,822},{133,10, 946},{7,0,1485},{136,0,929},{7,10,411},{8,10,631},{9,10,323},{10,10,355},{11,10, 491},{12,10,143},{12,10,402},{13,10,73},{14,10,408},{15,10,107},{146,10,71},{135 ,10,590},{5,11,881},{133,11,885},{150,11,25},{4,0,852},{5,11,142},{134,11,546},{ 7,10,1467},{8,10,328},{10,10,544},{11,10,955},{13,10,320},{145,10,83},{9,0,17},{ 10,0,291},{11,10,511},{13,10,394},{14,10,298},{14,10,318},{146,10,103},{5,11,466 },{11,11,571},{12,11,198},{13,11,283},{14,11,186},{15,11,21},{143,11,103},{134,0 ,1001},{4,11,185},{5,11,257},{5,11,839},{5,11,936},{7,11,171},{9,11,399},{10,11, 258},{10,11,395},{10,11,734},{11,11,1014},{12,11,23},{13,11,350},{14,11,150},{ 147,11,6},{143,0,35},{132,0,831},{5,10,835},{134,10,483},{4,0,277},{5,0,608},{6, 0,493},{7,0,457},{12,0,384},{7,11,404},{7,11,1377},{7,11,1430},{7,11,2017},{8,11 ,149},{8,11,239},{8,11,512},{8,11,793},{8,11,818},{9,11,474},{9,11,595},{10,11, 122},{10,11,565},{10,11,649},{10,11,783},{11,11,239},{11,11,295},{11,11,447},{11 ,11,528},{11,11,639},{11,11,800},{11,11,936},{12,11,25},{12,11,73},{12,11,77},{ 12,11,157},{12,11,316},{12,11,390},{12,11,391},{12,11,394},{12,11,395},{12,11, 478},{12,11,503},{12,11,592},{12,11,680},{13,11,50},{13,11,53},{13,11,132},{13, 11,198},{13,11,275},{13,11,322},{13,11,415},{14,11,71},{14,11,257},{14,11,395},{ 15,11,71},{15,11,136},{17,11,123},{18,11,93},{147,11,58},{134,0,1351},{7,0,27},{ 135,0,316},{136,11,712},{136,0,984},{133,0,552},{137,0,264},{132,0,401},{6,0,710 },{6,0,1111},{134,0,1343},{134,0,1211},{9,0,543},{10,0,524},{11,0,108},{11,0,653 },{12,0,524},{13,0,123},{14,0,252},{16,0,18},{19,0,38},{20,0,26},{20,0,65},{21,0 ,3},{151,0,11},{4,0,205},{5,0,623},{7,0,104},{8,0,519},{137,0,716},{132,10,677}, {4,11,377},{152,11,13},{135,11,1673},{7,0,579},{9,0,41},{9,0,244},{9,0,669},{10, 0,5},{11,0,861},{11,0,951},{139,0,980},{132,0,717},{136,0,1011},{132,0,805},{4, 11,180},{135,11,1906},{132,10,777},{132,10,331},{132,0,489},{6,0,1024},{4,11,491 },{133,10,747},{135,11,1182},{4,11,171},{138,11,234},{4,11,586},{7,11,1186},{138 ,11,631},{135,0,892},{135,11,336},{9,11,931},{10,11,334},{148,11,71},{137,0,473} ,{6,0,864},{12,0,659},{139,11,926},{7,0,819},{9,0,26},{9,0,392},{10,0,152},{10,0 ,226},{11,0,19},{12,0,276},{12,0,426},{12,0,589},{13,0,460},{15,0,97},{19,0,48}, {148,0,104},{135,0,51},{133,10,326},{4,10,691},{146,10,16},{9,0,130},{11,0,765}, {10,10,680},{10,10,793},{141,10,357},{133,11,765},{8,0,229},{6,10,32},{7,10,385} ,{7,10,757},{7,10,1916},{8,10,94},{8,10,711},{9,10,541},{10,10,162},{10,10,795}, {11,10,989},{11,10,1010},{12,10,14},{142,10,308},{7,11,474},{137,11,578},{132,0, 674},{132,0,770},{5,0,79},{7,0,1027},{7,0,1477},{139,0,52},{133,11,424},{134,0, 1666},{6,0,409},{6,10,349},{6,10,1682},{7,10,1252},{8,10,112},{8,11,714},{9,10, 435},{9,10,668},{10,10,290},{10,10,319},{10,10,815},{11,10,180},{11,10,837},{12, 10,240},{13,10,152},{13,10,219},{142,10,158},{5,0,789},{134,0,195},{4,0,251},{4, 0,688},{7,0,513},{135,0,1284},{132,10,581},{9,11,420},{10,11,269},{10,11,285},{ 10,11,576},{11,11,397},{13,11,175},{145,11,90},{6,10,126},{7,10,573},{8,10,397}, {142,10,44},{132,11,429},{133,0,889},{4,0,160},{5,0,330},{7,0,1434},{136,0,174}, {7,11,18},{7,11,699},{7,11,1966},{8,11,752},{9,11,273},{9,11,412},{9,11,703},{10 ,11,71},{10,11,427},{10,11,508},{146,11,97},{6,0,872},{134,0,899},{133,10,926},{ 134,0,1126},{134,0,918},{4,11,53},{5,11,186},{135,11,752},{7,0,268},{136,0,569}, {134,0,1224},{6,0,1361},{7,10,1232},{137,10,531},{8,11,575},{10,11,289},{139,11, 319},{133,10,670},{132,11,675},{133,0,374},{135,10,1957},{133,0,731},{11,0,190}, {15,0,49},{11,11,190},{143,11,49},{4,0,626},{5,0,506},{5,0,642},{6,0,425},{10,0, 202},{139,0,141},{137,0,444},{7,10,242},{135,10,1942},{6,11,209},{8,11,468},{9, 11,210},{11,11,36},{12,11,28},{12,11,630},{13,11,21},{13,11,349},{14,11,7},{145, 11,13},{4,11,342},{135,11,1179},{5,10,834},{7,10,1202},{8,10,14},{9,10,481},{137 ,10,880},{4,11,928},{133,11,910},{4,11,318},{4,11,496},{7,11,856},{139,11,654},{ 136,0,835},{7,0,1526},{138,10,465},{151,0,17},{135,0,477},{4,10,357},{6,10,172}, {7,10,143},{137,10,413},{6,0,1374},{138,0,994},{18,0,76},{132,10,590},{7,0,287}, {8,0,355},{9,0,293},{137,0,743},{134,0,1389},{7,11,915},{8,11,247},{147,11,0},{4 ,11,202},{5,11,382},{6,11,454},{7,11,936},{7,11,1803},{8,11,758},{9,11,375},{9, 11,895},{10,11,743},{10,11,792},{11,11,978},{11,11,1012},{142,11,109},{5,0,384}, {8,0,455},{140,0,48},{132,11,390},{5,10,169},{7,10,333},{136,10,45},{5,0,264},{ 134,0,184},{138,11,791},{133,11,717},{132,10,198},{6,11,445},{7,11,332},{137,11, 909},{136,0,1001},{4,10,24},{5,10,140},{5,10,185},{7,10,1500},{11,10,565},{139, 10,838},{134,11,578},{5,0,633},{6,0,28},{135,0,1323},{132,0,851},{136,11,267},{7 ,0,359},{8,0,243},{140,0,175},{4,10,334},{133,10,593},{141,11,87},{136,11,766},{ 10,0,287},{12,0,138},{10,11,287},{140,11,138},{4,0,105},{132,0,740},{140,10,116} ,{134,0,857},{135,11,1841},{6,0,1402},{137,0,819},{132,11,584},{132,10,709},{133 ,10,897},{5,0,224},{13,0,174},{146,0,52},{135,10,1840},{4,10,608},{133,10,497},{ 139,11,60},{4,0,758},{135,0,1649},{4,11,226},{4,11,326},{135,11,1770},{5,11,426} ,{8,11,30},{9,11,2},{11,11,549},{147,11,122},{135,10,2039},{6,10,540},{136,10, 136},{4,0,573},{8,0,655},{4,10,897},{133,10,786},{7,0,351},{139,0,128},{133,10, 999},{4,10,299},{135,10,1004},{133,0,918},{132,11,345},{4,11,385},{7,11,265},{ 135,11,587},{133,10,456},{136,10,180},{6,0,687},{134,0,1537},{4,11,347},{5,11, 423},{5,11,996},{135,11,1329},{132,10,755},{7,11,1259},{9,11,125},{11,11,65},{ 140,11,285},{5,11,136},{6,11,136},{136,11,644},{134,0,1525},{4,0,1009},{135,0, 1139},{139,10,338},{132,0,340},{135,10,1464},{8,0,847},{10,0,861},{10,0,876},{10 ,0,889},{10,0,922},{10,0,929},{10,0,933},{12,0,784},{140,0,791},{139,0,176},{9, 11,134},{10,11,2},{10,11,27},{10,11,333},{11,11,722},{143,11,1},{4,11,433},{133, 11,719},{5,0,985},{7,0,509},{7,0,529},{145,0,96},{132,0,615},{4,10,890},{5,10, 805},{5,10,819},{5,10,961},{6,10,396},{6,10,1631},{6,10,1678},{7,10,1967},{7,10, 2041},{9,10,630},{11,10,8},{11,10,1019},{12,10,176},{13,10,225},{14,10,292},{149 ,10,24},{135,0,1919},{134,0,1131},{144,11,21},{144,11,51},{135,10,1815},{4,0,247 },{7,10,1505},{10,10,190},{10,10,634},{11,10,792},{12,10,358},{140,10,447},{5,10 ,0},{6,10,536},{7,10,604},{13,10,445},{145,10,126},{4,0,184},{5,0,390},{6,0,337} ,{7,0,23},{7,0,494},{7,0,618},{7,0,1456},{8,0,27},{8,0,599},{10,0,153},{139,0, 710},{6,10,232},{6,10,412},{7,10,1074},{8,10,9},{8,10,157},{8,10,786},{9,10,196} ,{9,10,352},{9,10,457},{10,10,337},{11,10,232},{11,10,877},{12,10,480},{140,10, 546},{13,0,38},{135,10,958},{4,10,382},{136,10,579},{4,10,212},{135,10,1206},{4, 11,555},{8,11,536},{138,11,288},{11,11,139},{139,11,171},{9,11,370},{138,11,90}, {132,0,1015},{134,0,1088},{5,10,655},{135,11,977},{134,0,1585},{17,10,67},{147, 10,74},{10,0,227},{11,0,497},{11,0,709},{140,0,415},{6,0,360},{7,0,1664},{136,0, 478},{7,0,95},{6,10,231},{136,10,423},{140,11,65},{4,11,257},{135,11,2031},{135, 11,1768},{133,10,300},{139,11,211},{136,0,699},{6,10,237},{7,10,611},{8,10,100}, {9,10,416},{11,10,335},{12,10,173},{146,10,101},{14,0,26},{146,0,150},{6,0,581}, {135,0,1119},{135,10,1208},{132,0,739},{6,11,83},{6,11,1733},{135,11,1389},{137, 0,869},{4,0,67},{5,0,422},{7,0,1037},{7,0,1289},{7,0,1555},{9,0,741},{145,0,108} ,{133,10,199},{12,10,427},{146,10,38},{136,0,464},{142,0,42},{10,0,96},{8,11,501 },{137,11,696},{134,11,592},{4,0,512},{4,0,966},{5,0,342},{6,0,1855},{8,0,869},{ 8,0,875},{8,0,901},{144,0,26},{8,0,203},{11,0,823},{11,0,846},{12,0,482},{13,0, 277},{13,0,302},{13,0,464},{14,0,205},{142,0,221},{4,0,449},{133,0,718},{7,11, 1718},{9,11,95},{9,11,274},{10,11,279},{10,11,317},{10,11,420},{11,11,303},{11, 11,808},{12,11,134},{12,11,367},{13,11,149},{13,11,347},{14,11,349},{14,11,406}, {18,11,22},{18,11,89},{18,11,122},{147,11,47},{133,11,26},{4,0,355},{6,0,311},{9 ,0,256},{138,0,404},{132,11,550},{10,0,758},{6,10,312},{6,10,1715},{10,10,584},{ 11,10,546},{11,10,692},{12,10,259},{12,10,295},{13,10,46},{141,10,154},{136,11, 822},{5,0,827},{4,11,902},{5,11,809},{6,11,122},{135,11,896},{5,0,64},{140,0,581 },{4,0,442},{6,0,739},{7,0,1047},{7,0,1352},{7,0,1643},{7,11,1911},{9,11,449},{ 10,11,192},{138,11,740},{135,11,262},{132,10,588},{133,11,620},{5,0,977},{6,0, 288},{7,0,528},{4,11,34},{5,11,574},{7,11,279},{7,11,1624},{136,11,601},{6,0, 1375},{4,10,231},{5,10,61},{6,10,104},{7,10,729},{7,10,964},{7,10,1658},{140,10, 414},{6,10,263},{138,10,757},{132,10,320},{4,0,254},{7,0,1309},{5,11,332},{135, 11,1309},{6,11,261},{8,11,182},{139,11,943},{132,10,225},{6,0,12},{135,0,1219},{ 4,0,275},{12,0,376},{6,11,1721},{141,11,490},{4,11,933},{133,11,880},{6,0,951},{ 6,0,1109},{6,0,1181},{7,0,154},{4,10,405},{7,10,817},{14,10,58},{17,10,37},{146, 10,124},{6,0,1520},{133,10,974},{134,0,1753},{6,0,369},{6,0,502},{7,0,1036},{8,0 ,348},{9,0,452},{10,0,26},{11,0,224},{11,0,387},{11,0,772},{12,0,95},{12,0,629}, {13,0,195},{13,0,207},{13,0,241},{14,0,260},{14,0,270},{143,0,140},{132,0,269},{ 5,0,480},{7,0,532},{7,0,1197},{7,0,1358},{8,0,291},{11,0,349},{142,0,396},{5,10, 235},{7,10,1239},{11,10,131},{140,10,370},{7,10,956},{7,10,1157},{7,10,1506},{7, 10,1606},{7,10,1615},{7,10,1619},{7,10,1736},{7,10,1775},{8,10,590},{9,10,324},{ 9,10,736},{9,10,774},{9,10,776},{9,10,784},{10,10,567},{10,10,708},{11,10,518},{ 11,10,613},{11,10,695},{11,10,716},{11,10,739},{11,10,770},{11,10,771},{11,10, 848},{11,10,857},{11,10,931},{11,10,947},{12,10,326},{12,10,387},{12,10,484},{12 ,10,528},{12,10,552},{12,10,613},{13,10,189},{13,10,256},{13,10,340},{13,10,432} ,{13,10,436},{13,10,440},{13,10,454},{14,10,174},{14,10,220},{14,10,284},{14,10, 390},{145,10,121},{8,11,598},{9,11,664},{138,11,441},{9,10,137},{138,10,221},{ 133,11,812},{148,0,15},{134,0,1341},{6,0,1017},{4,11,137},{7,11,1178},{135,11, 1520},{7,10,390},{138,10,140},{7,11,1260},{135,11,1790},{137,11,191},{135,10, 1144},{6,0,1810},{7,0,657},{8,0,886},{10,0,857},{14,0,440},{144,0,96},{8,0,533}, {6,11,1661},{7,11,1975},{7,11,2009},{135,11,2011},{6,0,1453},{134,10,464},{132, 11,715},{5,10,407},{11,10,204},{11,10,243},{11,10,489},{12,10,293},{19,10,37},{ 20,10,73},{150,10,38},{133,11,703},{4,0,211},{7,0,1483},{5,10,325},{8,10,5},{8, 10,227},{9,10,105},{10,10,585},{140,10,614},{4,0,332},{5,0,335},{6,0,238},{7,0, 269},{7,0,811},{7,0,1797},{8,0,836},{9,0,507},{141,0,242},{5,11,89},{7,11,1915}, {9,11,185},{9,11,235},{9,11,496},{10,11,64},{10,11,270},{10,11,403},{10,11,469}, {10,11,529},{10,11,590},{11,11,140},{11,11,860},{13,11,1},{13,11,422},{14,11,341 },{14,11,364},{17,11,93},{18,11,113},{19,11,97},{147,11,113},{133,11,695},{16,0, 19},{5,11,6},{6,11,183},{6,10,621},{7,11,680},{7,11,978},{7,11,1013},{7,11,1055} ,{12,11,230},{13,11,172},{13,10,504},{146,11,29},{136,0,156},{133,0,1009},{6,11, 29},{139,11,63},{134,0,820},{134,10,218},{7,10,454},{7,10,782},{8,10,768},{140, 10,686},{5,0,228},{6,0,203},{7,0,156},{8,0,347},{9,0,265},{18,0,39},{20,0,54},{ 21,0,31},{22,0,3},{23,0,0},{15,11,8},{18,11,39},{20,11,54},{21,11,31},{22,11,3}, {151,11,0},{7,0,1131},{135,0,1468},{144,10,0},{134,0,1276},{10,10,676},{140,10, 462},{132,11,311},{134,11,1740},{7,11,170},{8,11,90},{8,11,177},{8,11,415},{11, 11,714},{142,11,281},{134,10,164},{6,0,1792},{138,0,849},{150,10,50},{5,0,291},{ 5,0,318},{7,0,765},{9,0,389},{12,0,548},{8,11,522},{142,11,328},{11,11,91},{13, 11,129},{15,11,101},{145,11,125},{4,11,494},{6,11,74},{7,11,44},{7,11,407},{8,11 ,551},{12,11,17},{15,11,5},{148,11,11},{4,11,276},{133,11,296},{6,10,343},{7,10, 195},{7,11,1777},{9,10,226},{10,10,197},{10,10,575},{11,10,502},{139,10,899},{10 ,0,525},{139,0,82},{14,0,453},{4,11,7},{5,11,90},{5,11,158},{6,11,542},{7,11,221 },{7,11,1574},{9,11,490},{10,11,540},{11,11,443},{139,11,757},{135,0,666},{22,10 ,29},{150,11,29},{4,0,422},{147,10,8},{5,0,355},{145,0,0},{6,0,1873},{9,0,918},{ 7,11,588},{9,11,175},{138,11,530},{143,11,31},{11,0,165},{7,10,1125},{9,10,143}, {14,10,405},{150,10,21},{9,0,260},{137,0,905},{5,11,872},{6,11,57},{6,11,479},{6 ,11,562},{7,11,471},{7,11,1060},{9,11,447},{9,11,454},{141,11,6},{138,11,704},{ 133,0,865},{5,0,914},{134,0,1625},{133,0,234},{7,0,1383},{5,11,31},{6,11,614},{ 145,11,61},{7,11,1200},{138,11,460},{6,11,424},{135,11,1866},{136,0,306},{5,10, 959},{12,11,30},{13,11,148},{14,11,87},{14,11,182},{16,11,42},{18,11,92},{148,11 ,70},{6,0,1919},{6,0,1921},{9,0,923},{9,0,930},{9,0,941},{9,0,949},{9,0,987},{9, 0,988},{9,0,992},{12,0,802},{12,0,815},{12,0,856},{12,0,885},{12,0,893},{12,0, 898},{12,0,919},{12,0,920},{12,0,941},{12,0,947},{15,0,183},{15,0,185},{15,0,189 },{15,0,197},{15,0,202},{15,0,233},{18,0,218},{18,0,219},{18,0,233},{143,11,156} ,{135,10,1759},{136,10,173},{13,0,163},{13,0,180},{18,0,78},{20,0,35},{5,11,13}, {134,11,142},{134,10,266},{6,11,97},{7,11,116},{8,11,322},{8,11,755},{9,11,548}, {10,11,714},{11,11,884},{141,11,324},{135,0,1312},{9,0,814},{137,11,676},{133,0, 707},{135,0,1493},{6,0,421},{7,0,61},{7,0,1540},{10,0,11},{138,0,501},{12,0,733} ,{12,0,766},{7,11,866},{135,11,1163},{137,0,341},{142,0,98},{145,11,115},{135,11 ,1111},{136,10,300},{136,0,1014},{8,11,1},{9,11,112},{138,11,326},{132,11,730},{ 5,11,488},{6,11,527},{7,11,489},{7,11,1636},{8,11,121},{8,11,144},{8,11,359},{9, 11,193},{9,11,241},{9,11,336},{9,11,882},{11,11,266},{11,11,372},{11,11,944},{12 ,11,401},{140,11,641},{6,0,971},{134,0,1121},{6,0,102},{7,0,72},{15,0,142},{147, 0,67},{151,0,30},{135,0,823},{134,0,1045},{5,10,427},{5,10,734},{7,10,478},{136, 10,52},{7,0,1930},{11,10,217},{142,10,165},{6,0,1512},{135,0,1870},{9,11,31},{10 ,11,244},{10,11,699},{12,11,149},{141,11,497},{133,11,377},{145,11,101},{10,11, 158},{13,11,13},{13,11,137},{13,11,258},{14,11,111},{14,11,225},{14,11,253},{14, 11,304},{14,11,339},{14,11,417},{146,11,33},{6,0,87},{6,10,1734},{7,10,20},{7,10 ,1056},{8,10,732},{9,10,406},{9,10,911},{138,10,694},{134,0,1243},{137,0,245},{7 ,0,68},{8,0,48},{8,0,88},{8,0,582},{8,0,681},{9,0,373},{9,0,864},{11,0,157},{11, 0,336},{11,0,843},{148,0,27},{8,11,663},{144,11,8},{133,10,613},{4,0,88},{5,0, 137},{5,0,174},{5,0,777},{6,0,1664},{6,0,1725},{7,0,77},{7,0,426},{7,0,1317},{7, 0,1355},{8,0,126},{8,0,563},{9,0,523},{9,0,750},{10,0,310},{10,0,836},{11,0,42}, {11,0,318},{11,0,731},{12,0,68},{12,0,92},{12,0,507},{12,0,692},{13,0,81},{13,0, 238},{13,0,374},{14,0,436},{18,0,138},{19,0,78},{19,0,111},{20,0,55},{20,0,77},{ 148,0,92},{141,0,418},{4,0,938},{137,0,625},{138,0,351},{5,11,843},{7,10,32},{7, 10,984},{8,10,85},{8,10,709},{9,10,579},{9,10,847},{9,10,856},{10,10,799},{11,10 ,258},{11,10,1007},{12,10,331},{12,10,615},{13,10,188},{13,10,435},{14,10,8},{15 ,10,165},{16,10,27},{148,10,40},{6,0,1668},{7,0,1499},{8,0,117},{9,0,314},{138,0 ,174},{135,0,707},{132,11,554},{133,11,536},{5,0,403},{5,11,207},{9,11,79},{11, 11,625},{145,11,7},{132,11,424},{136,11,785},{4,10,167},{135,10,82},{9,0,7},{23, 0,6},{9,11,7},{151,11,6},{6,0,282},{5,10,62},{6,10,534},{7,10,74},{7,10,678},{7, 10,684},{7,10,1043},{7,10,1072},{8,10,280},{8,10,541},{8,10,686},{9,10,258},{10, 10,519},{11,10,252},{140,10,282},{138,10,33},{132,10,359},{4,0,44},{5,0,311},{6, 0,156},{7,0,639},{7,0,762},{7,0,1827},{9,0,8},{9,0,462},{148,0,83},{7,11,769},{9 ,11,18},{138,11,358},{4,0,346},{7,0,115},{9,0,180},{9,0,456},{10,0,363},{4,11, 896},{134,11,1777},{133,10,211},{7,0,761},{7,0,1051},{137,0,545},{6,10,145},{141 ,10,336},{7,11,750},{9,11,223},{11,11,27},{11,11,466},{12,11,624},{14,11,265},{ 146,11,61},{6,0,752},{6,0,768},{6,0,1195},{6,0,1254},{6,0,1619},{137,0,835},{6,0 ,1936},{8,0,930},{136,0,960},{132,10,263},{132,11,249},{12,0,653},{132,10,916},{ 4,11,603},{133,11,661},{8,0,344},{4,11,11},{6,11,128},{7,11,231},{7,11,1533},{ 138,11,725},{134,0,1483},{134,0,875},{6,0,185},{7,0,1899},{9,0,875},{139,0,673}, {15,10,155},{144,10,79},{7,0,93},{7,0,210},{7,0,1223},{8,0,451},{8,0,460},{11,0, 353},{11,0,475},{4,10,599},{6,10,1634},{7,10,67},{7,10,691},{7,10,979},{7,10, 1697},{8,10,207},{8,10,214},{8,10,231},{8,10,294},{8,10,336},{8,10,428},{8,10, 471},{8,10,622},{8,10,626},{8,10,679},{8,10,759},{8,10,829},{9,10,11},{9,10,246} ,{9,10,484},{9,10,573},{9,10,706},{9,10,762},{9,10,798},{9,10,855},{9,10,870},{9 ,10,912},{10,10,303},{10,10,335},{10,10,424},{10,10,461},{10,10,543},{10,10,759} ,{10,10,814},{11,10,59},{11,10,235},{11,10,590},{11,10,929},{11,10,963},{11,10, 987},{12,10,114},{12,10,182},{12,10,226},{12,10,332},{12,10,439},{12,10,575},{12 ,10,598},{12,10,675},{13,10,8},{13,10,125},{13,10,194},{13,10,287},{14,10,197},{ 14,10,383},{15,10,53},{17,10,63},{19,10,46},{19,10,98},{19,10,106},{148,10,85},{ 132,11,476},{4,0,327},{5,0,478},{7,0,1332},{136,0,753},{5,0,1020},{133,0,1022},{ 135,11,1807},{4,0,103},{133,0,401},{4,0,499},{135,0,1421},{10,0,207},{13,0,164}, {147,10,126},{9,11,20},{10,11,324},{139,11,488},{132,0,96},{9,11,280},{138,11, 134},{135,0,968},{133,10,187},{135,10,1286},{5,11,112},{6,11,103},{134,11,150},{ 8,0,914},{10,0,3},{4,10,215},{9,10,38},{11,10,23},{11,10,127},{139,10,796},{135, 0,399},{6,0,563},{137,0,224},{6,0,704},{134,0,1214},{4,11,708},{8,11,15},{9,11, 50},{9,11,386},{11,11,18},{11,11,529},{140,11,228},{4,11,563},{7,11,109},{7,11, 592},{7,11,637},{7,11,770},{7,11,1701},{8,11,436},{8,11,463},{9,11,60},{9,11,335 },{9,11,904},{10,11,73},{11,11,434},{12,11,585},{13,11,331},{18,11,110},{148,11, 60},{134,0,1559},{132,11,502},{6,11,347},{138,11,161},{4,11,33},{5,11,102},{5,11 ,500},{6,11,284},{7,11,1079},{7,11,1423},{7,11,1702},{8,11,470},{9,11,554},{9,11 ,723},{139,11,333},{7,11,246},{135,11,840},{6,11,10},{8,11,571},{9,11,739},{143, 11,91},{8,0,861},{10,0,905},{12,0,730},{12,0,789},{133,11,626},{134,0,946},{5,0, 746},{12,0,333},{14,0,332},{12,11,333},{142,11,332},{5,11,18},{6,11,526},{13,11, 24},{13,11,110},{19,11,5},{147,11,44},{4,0,910},{5,0,832},{135,10,2002},{10,11, 768},{139,11,787},{4,11,309},{5,11,462},{7,11,970},{135,11,1097},{4,10,28},{5,10 ,440},{7,10,248},{11,10,833},{140,10,344},{134,10,1654},{6,0,632},{6,0,652},{6,0 ,1272},{6,0,1384},{134,0,1560},{134,11,1704},{6,0,1393},{133,10,853},{6,10,249}, {7,10,1234},{139,10,573},{5,11,86},{7,11,743},{9,11,85},{10,11,281},{10,11,432}, {11,11,490},{12,11,251},{13,11,118},{14,11,378},{146,11,143},{5,11,524},{133,11, 744},{134,0,1514},{10,0,201},{142,0,319},{7,0,717},{10,0,510},{7,10,392},{8,10, 20},{8,10,172},{8,10,690},{9,10,383},{9,10,845},{11,10,293},{11,10,832},{11,10, 920},{11,10,984},{141,10,221},{134,0,1381},{5,10,858},{133,10,992},{8,0,528},{ 137,0,348},{10,11,107},{140,11,436},{4,0,20},{133,0,616},{134,0,1251},{132,11, 927},{10,11,123},{12,11,670},{13,11,371},{14,11,142},{146,11,94},{134,0,1163},{7 ,11,1149},{137,11,156},{134,0,307},{133,11,778},{7,0,1091},{135,0,1765},{5,11, 502},{6,10,268},{137,10,62},{8,11,196},{10,11,283},{139,11,406},{4,0,26},{5,0, 429},{6,0,245},{7,0,704},{7,0,1379},{135,0,1474},{133,11,855},{132,0,881},{4,0, 621},{135,11,1596},{7,11,1400},{9,11,446},{138,11,45},{6,0,736},{138,10,106},{ 133,0,542},{134,0,348},{133,0,868},{136,0,433},{135,0,1495},{138,0,771},{6,10, 613},{136,10,223},{138,0,215},{141,0,124},{136,11,391},{135,11,172},{132,10,670} ,{140,0,55},{9,10,40},{139,10,136},{7,0,62},{147,0,112},{132,0,856},{132,11,568} ,{12,0,270},{139,10,259},{8,0,572},{137,0,698},{4,11,732},{9,10,310},{137,10,682 },{142,10,296},{134,0,939},{136,11,733},{135,11,1435},{7,10,1401},{135,10,1476}, {6,0,352},{4,10,296},{7,10,401},{7,10,1410},{7,10,1594},{7,10,1674},{8,10,63},{8 ,10,660},{137,10,74},{4,11,428},{133,11,668},{4,10,139},{4,10,388},{140,10,188}, {7,11,2015},{140,11,665},{132,0,647},{146,0,10},{138,0,220},{142,0,464},{132,0, 109},{134,0,1746},{6,0,515},{4,10,747},{6,11,1623},{6,11,1681},{7,10,649},{7,10, 1479},{135,10,1583},{133,10,232},{135,0,566},{137,10,887},{4,0,40},{10,0,67},{11 ,0,117},{11,0,768},{139,0,935},{132,0,801},{7,0,992},{8,0,301},{9,0,722},{12,0, 63},{13,0,29},{14,0,161},{143,0,18},{139,0,923},{6,11,1748},{8,11,715},{9,11,802 },{10,11,46},{10,11,819},{13,11,308},{14,11,351},{14,11,363},{146,11,67},{137,11 ,745},{7,0,1145},{4,10,14},{7,10,1801},{10,10,748},{141,10,458},{4,11,63},{5,11, 347},{134,11,474},{135,0,568},{4,10,425},{7,11,577},{7,11,1432},{9,11,475},{9,11 ,505},{9,11,526},{9,11,609},{9,11,689},{9,11,726},{9,11,735},{9,11,738},{10,11, 556},{10,11,674},{10,11,684},{11,11,89},{11,11,202},{11,11,272},{11,11,380},{11, 11,415},{11,11,505},{11,11,537},{11,11,550},{11,11,562},{11,11,640},{11,11,667}, {11,11,688},{11,11,847},{11,11,927},{11,11,930},{11,11,940},{12,11,144},{12,11, 325},{12,11,329},{12,11,389},{12,11,403},{12,11,451},{12,11,515},{12,11,604},{12 ,11,616},{12,11,626},{13,11,66},{13,11,131},{13,11,167},{13,11,236},{13,11,368}, {13,11,411},{13,11,434},{13,11,453},{13,11,461},{13,11,474},{14,11,59},{14,11,60 },{14,11,139},{14,11,152},{14,11,276},{14,11,353},{14,11,402},{15,11,28},{15,11, 81},{15,11,123},{15,11,152},{18,11,136},{148,11,88},{137,0,247},{135,11,1622},{9 ,11,544},{11,11,413},{144,11,25},{4,0,645},{7,0,825},{6,10,1768},{135,11,89},{ 140,0,328},{5,10,943},{134,10,1779},{134,0,1363},{5,10,245},{6,10,576},{7,10,582 },{136,10,225},{134,0,1280},{5,11,824},{133,11,941},{7,11,440},{8,11,230},{139, 11,106},{5,0,28},{6,0,204},{10,0,320},{10,0,583},{13,0,502},{14,0,72},{14,0,274} ,{14,0,312},{14,0,344},{15,0,159},{16,0,62},{16,0,69},{17,0,30},{18,0,42},{18,0, 53},{18,0,84},{18,0,140},{19,0,68},{19,0,85},{20,0,5},{20,0,45},{20,0,101},{22,0 ,7},{150,0,20},{4,0,558},{6,0,390},{7,0,162},{7,0,689},{9,0,360},{138,0,653},{ 134,0,764},{6,0,862},{137,0,833},{5,0,856},{6,0,1672},{6,0,1757},{134,0,1781},{5 ,0,92},{10,0,736},{140,0,102},{6,0,1927},{6,0,1944},{8,0,924},{8,0,948},{10,0, 967},{138,0,978},{134,0,1479},{5,0,590},{8,0,360},{9,0,213},{138,0,63},{134,0, 1521},{6,0,709},{134,0,891},{132,10,443},{13,0,477},{14,0,120},{148,0,61},{4,11, 914},{5,11,800},{133,11,852},{10,11,54},{141,11,115},{4,11,918},{133,11,876},{ 139,11,152},{4,11,92},{133,11,274},{135,11,1901},{9,11,800},{10,11,693},{11,11, 482},{11,11,734},{139,11,789},{9,0,483},{132,10,298},{6,0,1213},{141,11,498},{ 135,11,1451},{133,11,743},{4,0,1022},{10,0,1000},{12,0,957},{12,0,980},{12,0, 1013},{14,0,481},{144,0,116},{8,0,503},{17,0,29},{4,11,49},{7,11,280},{135,11, 1633},{135,0,1712},{134,0,466},{136,11,47},{5,10,164},{7,10,121},{142,10,189},{7 ,10,812},{7,10,1261},{7,10,1360},{9,10,632},{140,10,352},{139,10,556},{132,0,731 },{5,11,272},{5,11,908},{5,11,942},{7,11,1008},{7,11,1560},{8,11,197},{9,11,47}, {11,11,538},{139,11,742},{4,10,172},{9,10,611},{10,10,436},{12,10,673},{141,10, 255},{133,10,844},{10,0,484},{11,0,754},{12,0,457},{14,0,171},{14,0,389},{146,0, 153},{9,10,263},{10,10,147},{138,10,492},{137,11,891},{138,0,241},{133,10,537},{ 6,0,2005},{136,0,964},{137,10,842},{151,11,8},{4,11,407},{132,11,560},{135,11, 1884},{6,0,1100},{134,0,1242},{135,0,954},{5,10,230},{5,10,392},{6,10,420},{9,10 ,568},{140,10,612},{4,11,475},{11,11,35},{11,11,90},{13,11,7},{13,11,71},{13,11, 177},{142,11,422},{136,11,332},{135,0,1958},{6,0,549},{8,0,34},{8,0,283},{9,0, 165},{138,0,475},{10,0,952},{12,0,966},{140,0,994},{5,0,652},{5,0,701},{135,0, 449},{4,0,655},{7,0,850},{17,0,75},{146,0,137},{4,0,146},{7,0,1618},{8,0,670},{5 ,10,41},{7,10,1459},{7,10,1469},{7,10,1859},{9,10,549},{139,10,905},{133,10,696} ,{6,0,159},{6,0,364},{7,0,516},{137,0,518},{135,0,1439},{6,11,222},{7,11,636},{7 ,11,1620},{8,11,409},{9,11,693},{139,11,77},{13,0,151},{141,11,45},{6,0,1027},{4 ,11,336},{132,10,771},{139,11,392},{10,11,121},{11,11,175},{149,11,16},{8,0,950} ,{138,0,983},{133,10,921},{135,0,993},{6,10,180},{7,10,1137},{8,10,751},{139,10, 805},{7,0,501},{9,0,111},{10,0,141},{11,0,332},{13,0,43},{13,0,429},{14,0,130},{ 14,0,415},{145,0,102},{4,10,183},{5,11,882},{7,10,271},{11,10,824},{11,10,952},{ 13,10,278},{13,10,339},{13,10,482},{14,10,424},{148,10,99},{4,10,19},{5,10,477}, {5,10,596},{6,10,505},{7,10,1221},{11,10,907},{12,10,209},{141,10,214},{135,10, 1215},{133,0,452},{132,11,426},{5,0,149},{136,0,233},{133,0,935},{6,11,58},{7,11 ,654},{7,11,745},{7,11,1969},{8,11,240},{8,11,675},{9,11,479},{9,11,731},{10,11, 330},{10,11,593},{10,11,817},{11,11,32},{11,11,133},{11,11,221},{145,11,68},{12, 0,582},{18,0,131},{7,11,102},{137,11,538},{136,0,801},{134,10,1645},{132,0,70},{ 6,10,92},{6,10,188},{7,10,1269},{7,10,1524},{7,10,1876},{10,10,228},{139,10,1020 },{4,10,459},{133,10,966},{138,0,369},{16,0,36},{140,10,330},{141,11,366},{7,0, 721},{10,0,236},{12,0,204},{6,10,18},{7,10,932},{8,10,757},{9,10,54},{9,10,65},{ 9,10,844},{10,10,113},{10,10,315},{10,10,798},{11,10,153},{12,10,151},{12,10,392 },{12,10,666},{142,10,248},{7,0,241},{10,0,430},{8,10,548},{9,10,532},{10,10,117 },{11,10,351},{11,10,375},{143,10,23},{134,10,1742},{133,10,965},{133,11,566},{6 ,11,48},{135,11,63},{134,10,182},{10,10,65},{10,10,488},{138,10,497},{6,11,114}, {7,11,1224},{7,11,1556},{136,11,3},{134,0,1817},{8,11,576},{137,11,267},{6,0, 1078},{144,0,16},{9,10,588},{138,10,260},{138,0,1021},{5,0,406},{134,0,2022},{ 133,11,933},{6,0,69},{135,0,117},{7,0,1830},{136,11,427},{4,0,432},{135,0,824},{ 134,10,1786},{133,0,826},{139,11,67},{133,11,759},{135,10,308},{137,0,816},{133, 0,1000},{4,0,297},{6,0,529},{7,0,152},{7,0,713},{7,0,1845},{8,0,710},{8,0,717},{ 12,0,639},{140,0,685},{7,0,423},{136,10,588},{136,10,287},{136,0,510},{134,0, 1048},{6,0,618},{7,11,56},{7,11,1989},{8,11,337},{8,11,738},{9,11,600},{10,11, 483},{12,11,37},{13,11,447},{142,11,92},{4,0,520},{135,0,575},{8,0,990},{138,0, 977},{135,11,774},{9,11,347},{11,11,24},{140,11,170},{136,11,379},{140,10,290},{ 132,11,328},{4,0,321},{134,0,569},{4,11,101},{135,11,1171},{7,0,723},{7,0,1135}, {5,11,833},{136,11,744},{7,10,719},{8,10,809},{136,10,834},{8,0,921},{136,10,796 },{5,10,210},{6,10,213},{7,10,60},{10,10,364},{139,10,135},{5,0,397},{6,0,154},{ 7,0,676},{8,0,443},{8,0,609},{9,0,24},{9,0,325},{10,0,35},{11,0,535},{11,0,672}, {11,0,1018},{12,0,637},{16,0,30},{5,10,607},{8,10,326},{136,10,490},{4,10,701},{ 5,10,472},{6,11,9},{6,11,397},{7,11,53},{7,11,1742},{9,10,758},{10,11,632},{11, 11,828},{140,11,146},{135,10,380},{135,10,1947},{148,11,109},{10,10,278},{138,11 ,278},{134,0,856},{7,0,139},{4,10,386},{8,10,405},{8,10,728},{9,10,497},{11,10, 110},{11,10,360},{15,10,37},{144,10,84},{141,0,282},{133,0,981},{5,0,288},{7,10, 1452},{7,10,1480},{8,10,634},{140,10,472},{7,0,1890},{8,11,367},{10,11,760},{14, 11,79},{20,11,17},{152,11,0},{4,10,524},{136,10,810},{4,0,56},{7,0,1791},{8,0, 607},{8,0,651},{11,0,465},{11,0,835},{12,0,337},{141,0,480},{10,10,238},{141,10, 33},{11,11,417},{12,11,223},{140,11,265},{9,0,158},{10,0,411},{140,0,261},{133, 10,532},{133,10,997},{12,11,186},{12,11,292},{14,11,100},{146,11,70},{6,0,1403}, {136,0,617},{134,0,1205},{139,0,563},{4,0,242},{134,0,333},{4,11,186},{5,11,157} ,{8,11,168},{138,11,6},{132,0,369},{133,11,875},{5,10,782},{5,10,829},{134,10, 1738},{134,0,622},{135,11,1272},{6,0,1407},{7,11,111},{136,11,581},{7,10,1823},{ 139,10,693},{7,0,160},{10,0,624},{142,0,279},{132,0,363},{10,11,589},{12,11,111} ,{13,11,260},{14,11,82},{18,11,63},{147,11,45},{7,11,1364},{7,11,1907},{141,11, 158},{4,11,404},{4,11,659},{135,11,675},{13,11,211},{14,11,133},{14,11,204},{15, 11,64},{15,11,69},{15,11,114},{16,11,10},{19,11,23},{19,11,35},{19,11,39},{19,11 ,51},{19,11,71},{19,11,75},{152,11,15},{4,10,78},{5,10,96},{5,10,182},{7,10,1724 },{7,10,1825},{10,10,394},{10,10,471},{11,10,532},{14,10,340},{145,10,88},{135, 10,1964},{133,11,391},{11,11,887},{14,11,365},{142,11,375},{5,11,540},{6,11,1697 },{7,11,222},{136,11,341},{134,11,78},{9,0,601},{9,0,619},{10,0,505},{10,0,732}, {11,0,355},{140,0,139},{134,0,292},{139,0,174},{5,0,177},{6,0,616},{7,0,827},{9, 0,525},{138,0,656},{10,0,31},{6,10,215},{7,10,1028},{7,10,1473},{7,10,1721},{9, 10,424},{138,10,779},{135,10,584},{136,11,293},{134,0,685},{135,11,1868},{133,11 ,460},{7,0,647},{6,10,67},{7,10,1630},{9,10,354},{9,10,675},{10,10,830},{14,10, 80},{145,10,80},{4,0,161},{133,0,631},{6,10,141},{7,10,225},{9,10,59},{9,10,607} ,{10,10,312},{11,10,687},{12,10,555},{13,10,373},{13,10,494},{148,10,58},{7,11, 965},{7,11,1460},{135,11,1604},{136,10,783},{134,11,388},{6,0,722},{6,0,1267},{4 ,11,511},{9,11,333},{9,11,379},{10,11,602},{11,11,441},{11,11,723},{11,11,976},{ 140,11,357},{134,0,1797},{135,0,1684},{9,0,469},{9,0,709},{12,0,512},{14,0,65},{ 17,0,12},{5,11,938},{136,11,707},{7,0,1230},{136,0,531},{10,0,229},{11,0,73},{11 ,0,376},{139,0,433},{12,0,268},{12,0,640},{142,0,119},{7,10,430},{139,10,46},{6, 0,558},{7,0,651},{8,0,421},{9,0,0},{10,0,34},{139,0,1008},{6,0,106},{7,0,1786},{ 7,0,1821},{9,0,102},{9,0,763},{5,10,602},{7,10,2018},{137,10,418},{5,0,65},{6,0, 416},{7,0,1720},{7,0,1924},{10,0,109},{11,0,14},{11,0,70},{11,0,569},{11,0,735}, {15,0,153},{20,0,80},{136,10,677},{135,11,1625},{137,11,772},{136,0,595},{6,11, 469},{7,11,1709},{138,11,515},{7,0,1832},{138,0,374},{9,0,106},{9,0,163},{9,0, 296},{10,0,167},{10,0,172},{10,0,777},{139,0,16},{6,0,6},{7,0,81},{7,0,771},{7,0 ,1731},{9,0,405},{138,0,421},{4,11,500},{135,11,938},{5,11,68},{134,11,383},{5,0 ,881},{133,0,885},{6,0,854},{6,0,1132},{6,0,1495},{6,0,1526},{6,0,1533},{134,0, 1577},{4,11,337},{6,11,353},{7,11,1934},{8,11,488},{137,11,429},{7,11,236},{7,11 ,1795},{8,11,259},{9,11,135},{9,11,177},{10,11,825},{11,11,115},{11,11,370},{11, 11,405},{11,11,604},{12,11,10},{12,11,667},{12,11,669},{13,11,76},{14,11,310},{ 15,11,76},{15,11,147},{148,11,23},{5,0,142},{134,0,546},{4,11,15},{5,11,22},{6, 11,244},{7,11,40},{7,11,200},{7,11,906},{7,11,1199},{9,11,616},{10,11,716},{11, 11,635},{11,11,801},{140,11,458},{5,0,466},{11,0,571},{12,0,198},{13,0,283},{14, 0,186},{15,0,21},{15,0,103},{135,10,329},{4,0,185},{5,0,257},{5,0,839},{5,0,936} ,{9,0,399},{10,0,258},{10,0,395},{10,0,734},{11,0,1014},{12,0,23},{13,0,350},{14 ,0,150},{19,0,6},{135,11,1735},{12,11,36},{141,11,337},{5,11,598},{7,11,791},{8, 11,108},{137,11,123},{132,10,469},{7,0,404},{7,0,1377},{7,0,1430},{7,0,2017},{8, 0,149},{8,0,239},{8,0,512},{8,0,793},{8,0,818},{9,0,474},{9,0,595},{10,0,122},{ 10,0,565},{10,0,649},{10,0,783},{11,0,239},{11,0,295},{11,0,447},{11,0,528},{11, 0,639},{11,0,800},{12,0,25},{12,0,77},{12,0,157},{12,0,256},{12,0,316},{12,0,390 },{12,0,391},{12,0,395},{12,0,478},{12,0,503},{12,0,592},{12,0,680},{13,0,50},{ 13,0,53},{13,0,132},{13,0,198},{13,0,322},{13,0,415},{13,0,511},{14,0,71},{14,0, 395},{15,0,71},{15,0,136},{17,0,123},{18,0,93},{147,0,58},{136,0,712},{134,10, 1743},{5,10,929},{6,10,340},{8,10,376},{136,10,807},{6,0,1848},{8,0,860},{10,0, 856},{10,0,859},{10,0,925},{10,0,941},{140,0,762},{6,0,629},{6,0,906},{9,0,810}, {140,0,652},{5,10,218},{7,10,1610},{138,10,83},{7,10,1512},{135,10,1794},{4,0, 377},{24,0,13},{4,11,155},{7,11,1689},{11,10,0},{144,10,78},{4,11,164},{5,11,151 },{5,11,730},{5,11,741},{7,11,498},{7,11,870},{7,11,1542},{12,11,213},{14,11,36} ,{14,11,391},{17,11,111},{18,11,6},{18,11,46},{18,11,151},{19,11,36},{20,11,32}, {20,11,56},{20,11,69},{20,11,102},{21,11,4},{22,11,8},{22,11,10},{22,11,14},{150 ,11,31},{7,0,1842},{133,10,571},{4,10,455},{4,11,624},{135,11,1752},{134,0,1501} ,{4,11,492},{5,11,451},{6,10,161},{7,10,372},{137,10,597},{132,10,349},{4,0,180} ,{135,0,1906},{135,11,835},{141,11,70},{132,0,491},{137,10,751},{6,10,432},{139, 10,322},{4,0,171},{138,0,234},{6,11,113},{135,11,436},{4,0,586},{7,0,1186},{138, 0,631},{5,10,468},{10,10,325},{11,10,856},{12,10,345},{143,10,104},{5,10,223},{ 10,11,592},{10,11,753},{12,11,317},{12,11,355},{12,11,465},{12,11,469},{12,11, 560},{12,11,578},{141,11,243},{132,10,566},{135,11,520},{4,10,59},{135,10,1394}, {6,10,436},{139,10,481},{9,0,931},{10,0,334},{20,0,71},{4,10,48},{5,10,271},{7, 10,953},{135,11,1878},{11,0,170},{5,10,610},{136,10,457},{133,10,755},{6,0,1587} ,{135,10,1217},{4,10,197},{149,11,26},{133,11,585},{137,11,521},{133,0,765},{133 ,10,217},{139,11,586},{133,0,424},{9,11,752},{12,11,610},{13,11,431},{16,11,59}, {146,11,109},{136,0,714},{7,0,685},{132,11,307},{9,0,420},{10,0,269},{10,0,285}, {10,0,576},{11,0,397},{13,0,175},{145,0,90},{132,0,429},{133,11,964},{9,11,463}, {138,11,595},{7,0,18},{7,0,699},{7,0,1966},{8,0,752},{9,0,273},{9,0,412},{9,0, 703},{10,0,71},{10,0,427},{138,0,508},{4,10,165},{7,10,1398},{135,10,1829},{4,0, 53},{5,0,186},{7,0,752},{7,0,828},{142,0,116},{8,0,575},{10,0,289},{139,0,319},{ 132,0,675},{134,0,1424},{4,11,75},{5,11,180},{6,11,500},{7,11,58},{7,11,710},{ 138,11,645},{133,11,649},{6,11,276},{7,11,282},{7,11,879},{7,11,924},{8,11,459}, {9,11,599},{9,11,754},{11,11,574},{12,11,128},{12,11,494},{13,11,52},{13,11,301} ,{15,11,30},{143,11,132},{6,0,647},{134,0,1095},{5,10,9},{7,10,297},{7,10,966},{ 140,10,306},{132,11,200},{134,0,1334},{5,10,146},{6,10,411},{138,10,721},{6,0, 209},{6,0,1141},{6,0,1288},{8,0,468},{9,0,210},{11,0,36},{12,0,28},{12,0,630},{ 13,0,21},{13,0,349},{14,0,7},{145,0,13},{6,10,177},{135,10,467},{4,0,342},{135,0 ,1179},{10,11,454},{140,11,324},{4,0,928},{133,0,910},{7,0,1838},{6,11,225},{137 ,11,211},{16,0,101},{20,0,115},{20,0,118},{148,0,122},{4,0,496},{135,0,856},{4,0 ,318},{11,0,654},{7,11,718},{139,11,102},{8,11,58},{9,11,724},{11,11,809},{13,11 ,113},{145,11,72},{5,10,200},{6,11,345},{135,11,1247},{8,11,767},{8,11,803},{9, 11,301},{137,11,903},{7,0,915},{8,0,247},{19,0,0},{7,11,1949},{136,11,674},{4,0, 202},{5,0,382},{6,0,454},{7,0,936},{7,0,1803},{8,0,758},{9,0,375},{9,0,895},{10, 0,743},{10,0,792},{11,0,978},{11,0,1012},{142,0,109},{7,0,1150},{7,0,1425},{7,0, 1453},{140,0,513},{134,11,259},{138,0,791},{11,0,821},{12,0,110},{12,0,153},{18, 0,41},{150,0,19},{134,10,481},{132,0,796},{6,0,445},{9,0,909},{136,11,254},{10,0 ,776},{13,0,345},{142,0,425},{4,10,84},{7,10,1482},{10,10,76},{138,10,142},{135, 11,742},{6,0,578},{133,10,1015},{6,0,1387},{4,10,315},{5,10,507},{135,10,1370},{ 4,0,438},{133,0,555},{136,0,766},{133,11,248},{134,10,1722},{4,11,116},{5,11,95} ,{5,11,445},{7,11,1688},{8,11,29},{9,11,272},{11,11,509},{139,11,915},{135,0,541 },{133,11,543},{8,10,222},{8,10,476},{9,10,238},{11,10,516},{11,10,575},{15,10, 109},{146,10,100},{6,0,880},{134,0,1191},{5,11,181},{136,11,41},{134,0,1506},{ 132,11,681},{7,11,25},{8,11,202},{138,11,536},{139,0,983},{137,0,768},{132,0,584 },{9,11,423},{140,11,89},{8,11,113},{9,11,877},{10,11,554},{11,11,83},{12,11,136 },{147,11,109},{7,10,706},{7,10,1058},{138,10,538},{133,11,976},{4,11,206},{135, 11,746},{136,11,526},{140,0,737},{11,10,92},{11,10,196},{11,10,409},{11,10,450}, {11,10,666},{11,10,777},{12,10,262},{13,10,385},{13,10,393},{15,10,115},{16,10, 45},{145,10,82},{4,0,226},{4,0,326},{7,0,1770},{4,11,319},{5,11,699},{138,11,673 },{6,10,40},{135,10,1781},{5,0,426},{8,0,30},{9,0,2},{11,0,549},{147,0,122},{6,0 ,1161},{134,0,1329},{138,10,97},{6,10,423},{7,10,665},{135,10,1210},{7,11,13},{8 ,11,226},{10,11,537},{11,11,570},{11,11,605},{11,11,799},{11,11,804},{12,11,85}, {12,11,516},{12,11,623},{13,11,112},{13,11,361},{14,11,77},{14,11,78},{17,11,28} ,{147,11,110},{132,11,769},{132,11,551},{132,11,728},{147,0,117},{9,11,57},{9,11 ,459},{10,11,425},{11,11,119},{12,11,184},{12,11,371},{13,11,358},{145,11,51},{5 ,11,188},{5,11,814},{8,11,10},{9,11,421},{9,11,729},{10,11,609},{139,11,689},{ 134,11,624},{135,11,298},{135,0,462},{4,0,345},{139,10,624},{136,10,574},{4,0, 385},{7,0,265},{135,0,587},{6,0,808},{132,11,528},{133,0,398},{132,10,354},{4,0, 347},{5,0,423},{5,0,996},{135,0,1329},{135,10,1558},{7,0,1259},{9,0,125},{139,0, 65},{5,0,136},{6,0,136},{136,0,644},{5,11,104},{6,11,173},{135,11,1631},{135,0, 469},{133,10,830},{4,0,278},{5,0,465},{135,0,1367},{7,11,810},{8,11,138},{8,11, 342},{9,11,84},{10,11,193},{11,11,883},{140,11,359},{5,10,496},{135,10,203},{4,0 ,433},{133,0,719},{6,11,95},{134,10,547},{5,10,88},{137,10,239},{6,11,406},{10, 11,409},{10,11,447},{11,11,44},{140,11,100},{134,0,1423},{7,10,650},{135,10,1310 },{134,0,749},{135,11,1243},{135,0,1363},{6,0,381},{7,0,645},{7,0,694},{8,0,546} ,{7,10,1076},{9,10,80},{11,10,78},{11,10,421},{11,10,534},{140,10,545},{134,11, 1636},{135,11,1344},{12,0,277},{7,10,274},{11,10,479},{139,10,507},{6,0,705},{6, 0,783},{6,0,1275},{6,0,1481},{4,11,282},{7,11,1034},{11,11,398},{11,11,634},{12, 11,1},{12,11,79},{12,11,544},{14,11,237},{17,11,10},{146,11,20},{134,0,453},{4,0 ,555},{8,0,536},{10,0,288},{11,0,1005},{4,10,497},{135,10,1584},{5,11,118},{5,11 ,499},{6,11,476},{7,11,600},{7,11,888},{135,11,1096},{138,0,987},{7,0,1107},{7, 10,261},{7,10,1115},{7,10,1354},{7,10,1588},{7,10,1705},{7,10,1902},{9,10,465},{ 10,10,248},{10,10,349},{10,10,647},{11,10,527},{11,10,660},{11,10,669},{12,10, 529},{141,10,305},{7,11,296},{7,11,596},{8,11,560},{8,11,586},{9,11,612},{11,11, 100},{11,11,304},{12,11,46},{13,11,89},{14,11,112},{145,11,122},{9,0,370},{138,0 ,90},{136,10,13},{132,0,860},{7,10,642},{8,10,250},{11,10,123},{11,10,137},{13, 10,48},{142,10,95},{135,10,1429},{137,11,321},{132,0,257},{135,0,2031},{7,0,1768 },{7,11,1599},{7,11,1723},{8,11,79},{8,11,106},{8,11,190},{8,11,302},{8,11,383}, {9,11,119},{9,11,233},{9,11,298},{9,11,419},{9,11,471},{10,11,181},{10,11,406},{ 11,11,57},{11,11,85},{11,11,120},{11,11,177},{11,11,296},{11,11,382},{11,11,454} ,{11,11,758},{11,11,999},{12,11,27},{12,11,98},{12,11,131},{12,11,245},{12,11, 312},{12,11,446},{12,11,454},{13,11,25},{13,11,98},{13,11,426},{13,11,508},{14, 11,6},{14,11,163},{14,11,272},{14,11,277},{14,11,370},{15,11,95},{15,11,138},{15 ,11,167},{17,11,18},{17,11,38},{20,11,96},{149,11,32},{5,11,722},{134,11,1759},{ 145,11,16},{6,0,1071},{134,0,1561},{10,10,545},{140,10,301},{6,0,83},{6,0,1733}, {135,0,1389},{4,0,835},{135,0,1818},{133,11,258},{4,10,904},{133,10,794},{134,0, 2006},{5,11,30},{7,11,495},{8,11,134},{9,11,788},{140,11,438},{135,11,2004},{137 ,0,696},{5,11,50},{6,11,439},{7,11,780},{135,11,1040},{7,11,772},{7,11,1104},{7, 11,1647},{11,11,269},{11,11,539},{11,11,607},{11,11,627},{11,11,706},{11,11,975} ,{12,11,248},{12,11,311},{12,11,434},{12,11,600},{12,11,622},{13,11,297},{13,11, 367},{13,11,485},{14,11,69},{14,11,409},{143,11,108},{5,11,1},{6,11,81},{138,11, 520},{7,0,1718},{9,0,95},{9,0,274},{10,0,279},{10,0,317},{10,0,420},{11,0,303},{ 11,0,808},{12,0,134},{12,0,367},{13,0,149},{13,0,347},{14,0,349},{14,0,406},{18, 0,22},{18,0,89},{18,0,122},{147,0,47},{5,11,482},{8,11,98},{9,11,172},{10,11,222 },{10,11,700},{10,11,822},{11,11,302},{11,11,778},{12,11,50},{12,11,127},{12,11, 396},{13,11,62},{13,11,328},{14,11,122},{147,11,72},{7,10,386},{138,10,713},{6, 10,7},{6,10,35},{7,10,147},{7,10,1069},{7,10,1568},{7,10,1575},{7,10,1917},{8,10 ,43},{8,10,208},{9,10,128},{9,10,866},{10,10,20},{11,10,981},{147,10,33},{133,0, 26},{132,0,550},{5,11,2},{7,11,1494},{136,11,589},{6,11,512},{7,11,797},{8,11, 253},{9,11,77},{10,11,1},{10,11,129},{10,11,225},{11,11,118},{11,11,226},{11,11, 251},{11,11,430},{11,11,701},{11,11,974},{11,11,982},{12,11,64},{12,11,260},{12, 11,488},{140,11,690},{7,10,893},{141,10,424},{134,0,901},{136,0,822},{4,0,902},{ 5,0,809},{134,0,122},{6,0,807},{134,0,1366},{7,0,262},{5,11,748},{134,11,553},{ 133,0,620},{4,0,34},{5,0,574},{7,0,279},{7,0,1624},{136,0,601},{9,0,170},{6,10, 322},{9,10,552},{11,10,274},{13,10,209},{13,10,499},{14,10,85},{15,10,126},{145, 10,70},{132,0,537},{4,11,12},{7,11,420},{7,11,522},{7,11,809},{8,11,797},{141,11 ,88},{133,0,332},{8,10,83},{8,10,742},{8,10,817},{9,10,28},{9,10,29},{9,10,885}, {10,10,387},{11,10,633},{11,10,740},{13,10,235},{13,10,254},{15,10,143},{143,10, 146},{6,0,1909},{9,0,964},{12,0,822},{12,0,854},{12,0,865},{12,0,910},{12,0,938} ,{15,0,169},{15,0,208},{15,0,211},{18,0,205},{18,0,206},{18,0,220},{18,0,223},{ 152,0,24},{140,10,49},{5,11,528},{135,11,1580},{6,0,261},{8,0,182},{139,0,943},{ 134,0,1721},{4,0,933},{133,0,880},{136,11,321},{5,11,266},{9,11,290},{9,11,364}, {10,11,293},{11,11,606},{142,11,45},{6,0,1609},{4,11,50},{6,11,510},{6,11,594},{ 9,11,121},{10,11,49},{10,11,412},{139,11,834},{7,0,895},{136,11,748},{132,11,466 },{4,10,110},{10,10,415},{10,10,597},{142,10,206},{133,0,812},{135,11,281},{6,0, 1890},{6,0,1902},{6,0,1916},{9,0,929},{9,0,942},{9,0,975},{9,0,984},{9,0,986},{9 ,0,1011},{9,0,1019},{12,0,804},{12,0,851},{12,0,867},{12,0,916},{12,0,923},{15,0 ,194},{15,0,204},{15,0,210},{15,0,222},{15,0,223},{15,0,229},{15,0,250},{18,0, 179},{18,0,186},{18,0,192},{7,10,205},{135,10,2000},{132,11,667},{135,0,778},{4, 0,137},{7,0,1178},{135,0,1520},{134,0,1314},{4,11,242},{134,11,333},{6,0,1661},{ 7,0,1975},{7,0,2009},{135,0,2011},{134,0,1591},{4,10,283},{135,10,1194},{11,0, 820},{150,0,51},{4,11,39},{5,11,36},{7,11,1843},{8,11,407},{11,11,144},{140,11, 523},{134,10,1720},{4,11,510},{7,11,29},{7,11,66},{7,11,1980},{10,11,487},{10,11 ,809},{146,11,9},{5,0,89},{7,0,1915},{9,0,185},{9,0,235},{10,0,64},{10,0,270},{ 10,0,403},{10,0,469},{10,0,529},{10,0,590},{11,0,140},{11,0,860},{13,0,1},{13,0, 422},{14,0,341},{14,0,364},{17,0,93},{18,0,113},{19,0,97},{147,0,113},{133,0,695 },{6,0,987},{134,0,1160},{5,0,6},{6,0,183},{7,0,680},{7,0,978},{7,0,1013},{7,0, 1055},{12,0,230},{13,0,172},{146,0,29},{134,11,570},{132,11,787},{134,11,518},{6 ,0,29},{139,0,63},{132,11,516},{136,11,821},{132,0,311},{134,0,1740},{7,0,170},{ 8,0,90},{8,0,177},{8,0,415},{11,0,714},{14,0,281},{136,10,735},{134,0,1961},{135 ,11,1405},{4,11,10},{7,11,917},{139,11,786},{5,10,132},{9,10,486},{9,10,715},{10 ,10,458},{11,10,373},{11,10,668},{11,10,795},{11,10,897},{12,10,272},{12,10,424} ,{12,10,539},{12,10,558},{14,10,245},{14,10,263},{14,10,264},{14,10,393},{142,10 ,403},{11,0,91},{13,0,129},{15,0,101},{145,0,125},{135,0,1132},{4,0,494},{6,0,74 },{7,0,44},{7,0,407},{12,0,17},{15,0,5},{148,0,11},{133,10,379},{5,0,270},{5,11, 684},{6,10,89},{6,10,400},{7,10,1569},{7,10,1623},{7,10,1850},{8,10,218},{8,10, 422},{9,10,570},{138,10,626},{4,0,276},{133,0,296},{6,0,1523},{134,11,27},{6,10, 387},{7,10,882},{141,10,111},{6,10,224},{7,10,877},{137,10,647},{135,10,790},{4, 0,7},{5,0,90},{5,0,158},{6,0,542},{7,0,221},{7,0,1574},{9,0,490},{10,0,540},{11, 0,443},{139,0,757},{7,0,588},{9,0,175},{138,0,530},{135,10,394},{142,11,23},{134 ,0,786},{135,0,580},{7,0,88},{136,0,627},{5,0,872},{6,0,57},{7,0,471},{9,0,447}, {137,0,454},{6,11,342},{6,11,496},{8,11,275},{137,11,206},{4,11,909},{133,11,940 },{6,0,735},{132,11,891},{8,0,845},{8,0,916},{135,10,1409},{5,0,31},{134,0,614}, {11,0,458},{12,0,15},{140,0,432},{8,0,330},{140,0,477},{4,0,530},{5,0,521},{7,0, 1200},{10,0,460},{132,11,687},{6,0,424},{135,0,1866},{9,0,569},{12,0,12},{12,0, 81},{12,0,319},{13,0,69},{14,0,259},{16,0,87},{17,0,1},{17,0,21},{17,0,24},{18,0 ,15},{18,0,56},{18,0,59},{18,0,127},{18,0,154},{19,0,19},{148,0,31},{7,0,1302},{ 136,10,38},{134,11,253},{5,10,261},{7,10,78},{7,10,199},{8,10,815},{9,10,126},{ 138,10,342},{5,0,595},{135,0,1863},{6,11,41},{141,11,160},{5,0,13},{134,0,142},{ 6,0,97},{7,0,116},{8,0,322},{8,0,755},{9,0,548},{10,0,714},{11,0,884},{13,0,324} ,{7,11,1304},{138,11,477},{132,10,628},{134,11,1718},{7,10,266},{136,10,804},{ 135,10,208},{7,0,1021},{6,10,79},{135,10,1519},{7,0,1472},{135,0,1554},{6,11,362 },{146,11,51},{7,0,1071},{7,0,1541},{7,0,1767},{7,0,1806},{11,0,162},{11,0,242}, {11,0,452},{12,0,605},{15,0,26},{144,0,44},{136,10,741},{133,11,115},{145,0,115} ,{134,10,376},{6,0,1406},{134,0,1543},{5,11,193},{12,11,178},{13,11,130},{145,11 ,84},{135,0,1111},{8,0,1},{9,0,650},{10,0,326},{5,11,705},{137,11,606},{5,0,488} ,{6,0,527},{7,0,489},{7,0,1636},{8,0,121},{8,0,144},{8,0,359},{9,0,193},{9,0,241 },{9,0,336},{9,0,882},{11,0,266},{11,0,372},{11,0,944},{12,0,401},{140,0,641},{ 135,11,174},{6,0,267},{7,10,244},{7,10,632},{7,10,1609},{8,10,178},{8,10,638},{ 141,10,58},{134,0,1983},{134,0,1155},{134,0,1575},{134,0,1438},{9,0,31},{10,0, 244},{10,0,699},{12,0,149},{141,0,497},{133,0,377},{4,11,122},{5,11,796},{5,11, 952},{6,11,1660},{6,11,1671},{8,11,567},{9,11,687},{9,11,742},{10,11,686},{11,11 ,356},{11,11,682},{140,11,281},{145,0,101},{11,11,0},{144,11,78},{5,11,179},{5, 10,791},{7,11,1095},{135,11,1213},{8,11,372},{9,11,122},{138,11,175},{7,10,686}, {8,10,33},{8,10,238},{10,10,616},{11,10,467},{11,10,881},{13,10,217},{13,10,253} ,{142,10,268},{9,0,476},{4,11,66},{7,11,722},{135,11,904},{7,11,352},{137,11,684 },{135,0,2023},{135,0,1836},{132,10,447},{5,0,843},{144,0,35},{137,11,779},{141, 11,35},{4,10,128},{5,10,415},{6,10,462},{7,10,294},{7,10,578},{10,10,710},{139, 10,86},{132,0,554},{133,0,536},{136,10,587},{5,0,207},{9,0,79},{11,0,625},{145,0 ,7},{7,0,1371},{6,10,427},{138,10,692},{4,0,424},{4,10,195},{135,10,802},{8,0, 785},{133,11,564},{135,0,336},{4,0,896},{6,0,1777},{134,11,556},{137,11,103},{ 134,10,1683},{7,11,544},{8,11,719},{138,11,61},{138,10,472},{4,11,5},{5,11,498}, {136,11,637},{7,0,750},{9,0,223},{11,0,27},{11,0,466},{12,0,624},{14,0,265},{146 ,0,61},{12,0,238},{18,0,155},{12,11,238},{146,11,155},{151,10,28},{133,11,927},{ 12,0,383},{5,10,3},{8,10,578},{9,10,118},{10,10,705},{141,10,279},{4,11,893},{5, 11,780},{133,11,893},{4,0,603},{133,0,661},{4,0,11},{6,0,128},{7,0,231},{7,0, 1533},{10,0,725},{5,10,229},{5,11,238},{135,11,1350},{8,10,102},{10,10,578},{10, 10,672},{12,10,496},{13,10,408},{14,10,121},{145,10,106},{132,0,476},{134,0,1552 },{134,11,1729},{8,10,115},{8,10,350},{9,10,489},{10,10,128},{11,10,306},{12,10, 373},{14,10,30},{17,10,79},{19,10,80},{150,10,55},{135,0,1807},{4,0,680},{4,11, 60},{7,11,760},{7,11,1800},{8,11,314},{9,11,700},{139,11,487},{4,10,230},{5,10, 702},{148,11,94},{132,11,228},{139,0,435},{9,0,20},{10,0,324},{10,0,807},{139,0, 488},{6,10,1728},{136,11,419},{4,10,484},{18,10,26},{19,10,42},{20,10,43},{21,10 ,0},{23,10,27},{152,10,14},{135,0,1431},{133,11,828},{5,0,112},{6,0,103},{6,0, 150},{7,0,1303},{9,0,292},{10,0,481},{20,0,13},{7,11,176},{7,11,178},{7,11,1110} ,{10,11,481},{148,11,13},{138,0,356},{4,11,51},{5,11,39},{6,11,4},{7,11,591},{7, 11,849},{7,11,951},{7,11,1129},{7,11,1613},{7,11,1760},{7,11,1988},{9,11,434},{ 10,11,754},{11,11,25},{11,11,37},{139,11,414},{6,0,1963},{134,0,2000},{132,10, 633},{6,0,1244},{133,11,902},{135,11,928},{140,0,18},{138,0,204},{135,11,1173},{ 134,0,867},{4,0,708},{8,0,15},{9,0,50},{9,0,386},{11,0,18},{11,0,529},{140,0,228 },{134,11,270},{4,0,563},{7,0,109},{7,0,592},{7,0,637},{7,0,770},{8,0,463},{9,0, 60},{9,0,335},{9,0,904},{10,0,73},{11,0,434},{12,0,585},{13,0,331},{18,0,110},{ 148,0,60},{132,0,502},{14,11,359},{19,11,52},{148,11,47},{6,11,377},{7,11,1025}, {9,11,613},{145,11,104},{6,0,347},{10,0,161},{5,10,70},{5,10,622},{6,10,334},{7, 10,1032},{9,10,171},{11,10,26},{11,10,213},{11,10,637},{11,10,707},{12,10,202},{ 12,10,380},{13,10,226},{13,10,355},{14,10,222},{145,10,42},{132,11,416},{4,0,33} ,{5,0,102},{6,0,284},{7,0,1079},{7,0,1423},{7,0,1702},{8,0,470},{9,0,554},{9,0, 723},{11,0,333},{142,11,372},{5,11,152},{5,11,197},{7,11,340},{7,11,867},{10,11, 548},{10,11,581},{11,11,6},{12,11,3},{12,11,19},{14,11,110},{142,11,289},{7,0, 246},{135,0,840},{6,0,10},{8,0,571},{9,0,739},{143,0,91},{6,0,465},{7,0,1465},{4 ,10,23},{4,10,141},{5,10,313},{5,10,1014},{6,10,50},{7,10,142},{7,10,559},{8,10, 640},{9,10,460},{9,10,783},{11,10,741},{12,10,183},{141,10,488},{133,0,626},{136 ,0,614},{138,0,237},{7,11,34},{7,11,190},{8,11,28},{8,11,141},{8,11,444},{8,11, 811},{9,11,468},{11,11,334},{12,11,24},{12,11,386},{140,11,576},{133,11,757},{5, 0,18},{6,0,526},{13,0,24},{13,0,110},{19,0,5},{147,0,44},{6,0,506},{134,11,506}, {135,11,1553},{4,0,309},{5,0,462},{7,0,970},{7,0,1097},{22,0,30},{22,0,33},{7,11 ,1385},{11,11,582},{11,11,650},{11,11,901},{11,11,949},{12,11,232},{12,11,236},{ 13,11,413},{13,11,501},{146,11,116},{9,0,140},{5,10,222},{138,10,534},{6,0,1056} ,{137,10,906},{134,0,1704},{138,10,503},{134,0,1036},{5,10,154},{7,10,1491},{10, 10,379},{138,10,485},{4,11,383},{133,10,716},{134,0,1315},{5,0,86},{7,0,743},{9, 0,85},{10,0,281},{10,0,432},{11,0,825},{12,0,251},{13,0,118},{142,0,378},{8,0, 264},{4,10,91},{5,10,388},{5,10,845},{6,10,206},{6,10,252},{6,10,365},{7,10,136} ,{7,10,531},{136,10,621},{5,0,524},{133,0,744},{5,11,277},{141,11,247},{132,11, 435},{10,0,107},{140,0,436},{132,0,927},{10,0,123},{12,0,670},{146,0,94},{7,0, 1149},{9,0,156},{138,0,957},{5,11,265},{6,11,212},{135,11,28},{133,0,778},{133,0 ,502},{8,0,196},{10,0,283},{139,0,406},{135,10,576},{136,11,535},{134,0,1312},{5 ,10,771},{5,10,863},{5,10,898},{6,10,1632},{6,10,1644},{134,10,1780},{5,0,855},{ 5,10,331},{135,11,1487},{132,11,702},{5,11,808},{135,11,2045},{7,0,1400},{9,0, 446},{138,0,45},{140,10,632},{132,0,1003},{5,11,166},{8,11,739},{140,11,511},{5, 10,107},{7,10,201},{136,10,518},{6,10,446},{135,10,1817},{134,0,1532},{134,0, 1097},{4,11,119},{5,11,170},{5,11,447},{7,11,1708},{7,11,1889},{9,11,357},{9,11, 719},{12,11,486},{140,11,596},{9,10,851},{141,10,510},{7,0,612},{8,0,545},{8,0, 568},{8,0,642},{9,0,717},{10,0,541},{10,0,763},{11,0,449},{12,0,489},{13,0,153}, {13,0,296},{14,0,138},{14,0,392},{15,0,50},{16,0,6},{16,0,12},{20,0,9},{132,10, 504},{4,11,450},{135,11,1158},{11,0,54},{13,0,173},{13,0,294},{5,10,883},{5,10, 975},{8,10,392},{148,10,7},{13,0,455},{15,0,99},{15,0,129},{144,0,68},{135,0,172 },{132,11,754},{5,10,922},{134,10,1707},{134,0,1029},{17,11,39},{148,11,36},{4,0 ,568},{5,10,993},{7,10,515},{137,10,91},{132,0,732},{10,0,617},{138,11,617},{134 ,0,974},{7,0,989},{10,0,377},{12,0,363},{13,0,68},{13,0,94},{14,0,108},{142,0, 306},{136,0,733},{132,0,428},{7,0,1789},{135,11,1062},{7,0,2015},{140,0,665},{ 135,10,1433},{5,0,287},{7,10,921},{8,10,580},{8,10,593},{8,10,630},{138,10,28},{ 138,0,806},{4,10,911},{5,10,867},{5,10,1013},{7,10,2034},{8,10,798},{136,10,813} ,{134,0,1539},{8,11,523},{150,11,34},{135,11,740},{7,11,238},{7,11,2033},{8,11, 120},{8,11,188},{8,11,659},{9,11,598},{10,11,466},{12,11,342},{12,11,588},{13,11 ,503},{14,11,246},{143,11,92},{7,0,1563},{141,0,182},{5,10,135},{6,10,519},{7,10 ,1722},{10,10,271},{11,10,261},{145,10,54},{14,10,338},{148,10,81},{7,0,484},{4, 10,300},{133,10,436},{145,11,114},{6,0,1623},{134,0,1681},{133,11,640},{4,11,201 },{7,11,1744},{8,11,602},{11,11,247},{11,11,826},{145,11,65},{8,11,164},{146,11, 62},{6,0,1833},{6,0,1861},{136,0,878},{134,0,1569},{8,10,357},{10,10,745},{14,10 ,426},{17,10,94},{147,10,57},{12,0,93},{12,0,501},{13,0,362},{14,0,151},{15,0,40 },{15,0,59},{16,0,46},{17,0,25},{18,0,14},{18,0,134},{19,0,25},{19,0,69},{20,0, 16},{20,0,19},{20,0,66},{21,0,23},{21,0,25},{150,0,42},{6,0,1748},{8,0,715},{9,0 ,802},{10,0,46},{10,0,819},{13,0,308},{14,0,351},{14,0,363},{146,0,67},{132,0, 994},{4,0,63},{133,0,347},{132,0,591},{133,0,749},{7,11,1577},{10,11,304},{10,11 ,549},{11,11,424},{12,11,365},{13,11,220},{13,11,240},{142,11,33},{133,0,366},{7 ,0,557},{12,0,547},{14,0,86},{133,10,387},{135,0,1747},{132,11,907},{5,11,100},{ 10,11,329},{12,11,416},{149,11,29},{4,10,6},{5,10,708},{136,10,75},{7,10,1351},{ 9,10,581},{10,10,639},{11,10,453},{140,10,584},{7,0,89},{132,10,303},{138,10,772 },{132,11,176},{5,11,636},{5,11,998},{8,11,26},{137,11,358},{7,11,9},{7,11,1508} ,{9,11,317},{10,11,210},{10,11,292},{10,11,533},{11,11,555},{12,11,526},{12,11, 607},{13,11,263},{13,11,459},{142,11,271},{134,0,1463},{6,0,772},{6,0,1137},{139 ,11,595},{7,0,977},{139,11,66},{138,0,893},{20,0,48},{148,11,48},{5,0,824},{133, 0,941},{134,11,295},{7,0,1543},{7,0,1785},{10,0,690},{4,10,106},{139,10,717},{7, 0,440},{8,0,230},{139,0,106},{5,10,890},{133,10,988},{6,10,626},{142,10,431},{10 ,11,127},{141,11,27},{17,0,32},{10,10,706},{150,10,44},{132,0,216},{137,0,332},{ 4,10,698},{136,11,119},{139,11,267},{138,10,17},{11,11,526},{11,11,939},{141,11, 290},{7,11,1167},{11,11,934},{13,11,391},{145,11,76},{139,11,39},{134,10,84},{4, 0,914},{5,0,800},{133,0,852},{10,0,416},{141,0,115},{7,0,564},{142,0,168},{4,0, 918},{133,0,876},{134,0,1764},{152,0,3},{4,0,92},{5,0,274},{7,11,126},{136,11,84 },{140,10,498},{136,11,790},{8,0,501},{5,10,986},{6,10,130},{7,10,1582},{8,10, 458},{10,10,101},{10,10,318},{138,10,823},{6,11,64},{12,11,377},{141,11,309},{5, 0,743},{138,0,851},{4,0,49},{7,0,280},{135,0,1633},{134,0,879},{136,0,47},{7,10, 1644},{137,10,129},{132,0,865},{134,0,1202},{9,11,34},{139,11,484},{135,10,997}, {5,0,272},{5,0,908},{5,0,942},{8,0,197},{9,0,47},{11,0,538},{139,0,742},{6,11, 1700},{7,11,26},{7,11,293},{7,11,382},{7,11,1026},{7,11,1087},{7,11,2027},{8,11, 24},{8,11,114},{8,11,252},{8,11,727},{8,11,729},{9,11,30},{9,11,199},{9,11,231}, {9,11,251},{9,11,334},{9,11,361},{9,11,488},{9,11,712},{10,11,55},{10,11,60},{10 ,11,232},{10,11,332},{10,11,384},{10,11,396},{10,11,504},{10,11,542},{10,11,652} ,{11,11,20},{11,11,48},{11,11,207},{11,11,291},{11,11,298},{11,11,342},{11,11, 365},{11,11,394},{11,11,620},{11,11,705},{11,11,1017},{12,11,123},{12,11,340},{ 12,11,406},{12,11,643},{13,11,61},{13,11,269},{13,11,311},{13,11,319},{13,11,486 },{14,11,234},{15,11,62},{15,11,85},{16,11,71},{18,11,119},{148,11,105},{6,0, 1455},{150,11,37},{135,10,1927},{135,0,1911},{137,0,891},{7,10,1756},{137,10,98} ,{7,10,1046},{139,10,160},{132,0,761},{6,11,379},{7,11,270},{7,11,1116},{8,11, 176},{8,11,183},{9,11,432},{9,11,661},{12,11,247},{12,11,617},{146,11,125},{6,10 ,45},{7,10,433},{8,10,129},{9,10,21},{10,10,392},{11,10,79},{12,10,499},{13,10, 199},{141,10,451},{4,0,407},{5,11,792},{133,11,900},{132,0,560},{135,0,183},{13, 0,490},{7,10,558},{136,10,353},{4,0,475},{6,0,731},{11,0,35},{13,0,71},{13,0,177 },{14,0,422},{133,10,785},{8,10,81},{9,10,189},{9,10,201},{11,10,478},{11,10,712 },{141,10,338},{4,0,418},{4,0,819},{133,10,353},{151,10,26},{4,11,901},{133,11, 776},{132,0,575},{7,0,818},{16,0,92},{17,0,14},{17,0,45},{18,0,75},{148,0,18},{6 ,0,222},{7,0,636},{7,0,1620},{8,0,409},{9,0,693},{139,0,77},{6,10,25},{7,10,855} ,{7,10,1258},{144,10,32},{6,0,1880},{6,0,1887},{6,0,1918},{6,0,1924},{9,0,967},{ 9,0,995},{9,0,1015},{12,0,826},{12,0,849},{12,0,857},{12,0,860},{12,0,886},{12,0 ,932},{18,0,228},{18,0,231},{146,0,240},{134,0,633},{134,0,1308},{4,11,37},{5,11 ,334},{135,11,1253},{10,0,86},{4,10,4},{7,10,1118},{7,10,1320},{7,10,1706},{8,10 ,277},{9,10,622},{11,10,724},{12,10,350},{12,10,397},{13,10,28},{13,10,159},{15, 10,89},{18,10,5},{19,10,9},{20,10,34},{150,10,47},{132,11,508},{137,11,448},{12, 11,107},{146,11,31},{132,0,817},{134,0,663},{133,0,882},{134,0,914},{132,11,540} ,{132,11,533},{136,11,608},{8,0,885},{138,0,865},{132,0,426},{6,0,58},{7,0,745}, {7,0,1969},{8,0,399},{8,0,675},{9,0,479},{9,0,731},{10,0,330},{10,0,593},{10,0, 817},{11,0,32},{11,0,133},{11,0,221},{145,0,68},{134,10,255},{7,0,102},{137,0, 538},{137,10,216},{7,11,253},{136,11,549},{135,11,912},{9,10,183},{139,10,286},{ 11,10,956},{151,10,3},{8,11,527},{18,11,60},{147,11,24},{4,10,536},{7,10,1141},{ 10,10,723},{139,10,371},{133,11,920},{7,0,876},{135,10,285},{135,10,560},{132,10 ,690},{142,11,126},{11,10,33},{12,10,571},{149,10,1},{133,0,566},{9,0,139},{10,0 ,399},{11,0,469},{12,0,634},{13,0,223},{132,11,483},{6,0,48},{135,0,63},{18,0,12 },{7,10,1862},{12,10,491},{12,10,520},{13,10,383},{142,10,244},{135,11,1665},{ 132,11,448},{9,11,495},{146,11,104},{6,0,114},{7,0,1224},{7,0,1556},{136,0,3},{4 ,10,190},{133,10,554},{8,0,576},{9,0,267},{133,10,1001},{133,10,446},{133,0,933} ,{139,11,1009},{8,11,653},{13,11,93},{147,11,14},{6,0,692},{6,0,821},{134,0,1077 },{5,11,172},{135,11,801},{138,0,752},{4,0,375},{134,0,638},{134,0,1011},{140,11 ,540},{9,0,96},{133,11,260},{139,11,587},{135,10,1231},{12,0,30},{13,0,148},{14, 0,87},{14,0,182},{16,0,42},{20,0,70},{132,10,304},{6,0,1398},{7,0,56},{7,0,1989} ,{8,0,337},{8,0,738},{9,0,600},{12,0,37},{13,0,447},{142,0,92},{138,0,666},{5,0, 394},{7,0,487},{136,0,246},{9,0,437},{6,10,53},{6,10,199},{7,10,1408},{8,10,32}, {8,10,93},{10,10,397},{10,10,629},{11,10,593},{11,10,763},{13,10,326},{145,10,35 },{134,10,105},{9,0,320},{10,0,506},{138,10,794},{7,11,57},{8,11,167},{8,11,375} ,{9,11,82},{9,11,561},{10,11,620},{10,11,770},{11,10,704},{141,10,396},{6,0,1003 },{5,10,114},{5,10,255},{141,10,285},{7,0,866},{135,0,1163},{133,11,531},{132,0, 328},{7,10,2035},{8,10,19},{9,10,89},{138,10,831},{8,11,194},{136,11,756},{136,0 ,1000},{5,11,453},{134,11,441},{4,0,101},{5,0,833},{7,0,1171},{136,0,744},{133,0 ,726},{136,10,746},{138,0,176},{6,0,9},{6,0,397},{7,0,53},{7,0,1742},{10,0,632}, {11,0,828},{140,0,146},{135,11,22},{145,11,64},{132,0,839},{11,0,417},{12,0,223} ,{140,0,265},{4,11,102},{7,11,815},{7,11,1699},{139,11,964},{5,10,955},{136,10, 814},{6,0,1931},{6,0,2007},{18,0,246},{146,0,247},{8,0,198},{11,0,29},{140,0,534 },{135,0,1771},{6,0,846},{7,11,1010},{11,11,733},{11,11,759},{12,11,563},{13,11, 34},{14,11,101},{18,11,45},{146,11,129},{4,0,186},{5,0,157},{8,0,168},{138,0,6}, {132,11,899},{133,10,56},{148,10,100},{133,0,875},{5,0,773},{5,0,991},{6,0,1635} ,{134,0,1788},{6,0,1274},{9,0,477},{141,0,78},{4,0,639},{7,0,111},{8,0,581},{12, 0,177},{6,11,52},{9,11,104},{9,11,559},{10,10,4},{10,10,13},{11,10,638},{12,11, 308},{19,11,87},{148,10,57},{132,11,604},{4,11,301},{133,10,738},{133,10,758},{ 134,0,1747},{7,11,1440},{11,11,854},{11,11,872},{11,11,921},{12,11,551},{13,11, 472},{142,11,367},{7,0,1364},{7,0,1907},{141,0,158},{134,0,873},{4,0,404},{4,0, 659},{7,0,552},{135,0,675},{135,10,1112},{139,10,328},{7,11,508},{137,10,133},{ 133,0,391},{5,10,110},{6,10,169},{6,10,1702},{7,10,400},{8,10,538},{9,10,184},{9 ,10,524},{140,10,218},{6,11,310},{7,11,1849},{8,11,72},{8,11,272},{8,11,431},{9, 11,12},{9,11,351},{10,11,563},{10,11,630},{10,11,810},{11,11,367},{11,11,599},{ 11,11,686},{140,11,672},{5,0,540},{6,0,1697},{136,0,668},{132,0,883},{134,0,78}, {12,0,628},{18,0,79},{6,10,133},{9,10,353},{139,10,993},{6,11,181},{7,11,537},{8 ,11,64},{9,11,127},{10,11,496},{12,11,510},{141,11,384},{6,10,93},{7,10,1422},{7 ,10,1851},{8,10,673},{9,10,529},{140,10,43},{137,10,371},{134,0,1460},{134,0,962 },{4,11,244},{135,11,233},{9,10,25},{10,10,467},{138,10,559},{4,10,335},{135,10, 942},{133,0,460},{135,11,334},{134,11,1650},{4,0,199},{139,0,34},{5,10,601},{8, 10,39},{10,10,773},{11,10,84},{12,10,205},{142,10,1},{133,10,870},{134,0,388},{ 14,0,474},{148,0,120},{133,11,369},{139,0,271},{4,0,511},{9,0,333},{9,0,379},{10 ,0,602},{11,0,441},{11,0,723},{11,0,976},{12,0,357},{132,10,181},{134,0,608},{ 134,10,1652},{22,0,49},{137,11,338},{140,0,988},{134,0,617},{5,0,938},{136,0,707 },{132,10,97},{5,10,147},{6,10,286},{7,10,1362},{141,10,176},{6,0,756},{134,0, 1149},{133,11,896},{6,10,375},{7,10,169},{7,10,254},{136,10,780},{134,0,1583},{ 135,10,1447},{139,0,285},{7,11,1117},{8,11,393},{136,11,539},{135,0,344},{6,0, 469},{7,0,1709},{138,0,515},{5,10,629},{135,10,1549},{5,11,4},{5,11,810},{6,11, 13},{6,11,538},{6,11,1690},{6,11,1726},{7,11,499},{7,11,1819},{8,11,148},{8,11, 696},{8,11,791},{12,11,125},{13,11,54},{143,11,9},{135,11,1268},{137,0,404},{132 ,0,500},{5,0,68},{134,0,383},{11,0,216},{139,0,340},{4,11,925},{5,11,803},{8,11, 698},{138,11,828},{4,0,337},{6,0,353},{7,0,1934},{8,0,488},{137,0,429},{7,0,236} ,{7,0,1795},{8,0,259},{9,0,135},{9,0,177},{9,0,860},{10,0,825},{11,0,115},{11,0, 370},{11,0,405},{11,0,604},{12,0,10},{12,0,667},{12,0,669},{13,0,76},{14,0,310}, {15,0,76},{15,0,147},{148,0,23},{4,0,15},{4,0,490},{5,0,22},{6,0,244},{7,0,40},{ 7,0,200},{7,0,906},{7,0,1199},{9,0,616},{10,0,716},{11,0,635},{11,0,801},{140,0, 458},{12,0,756},{132,10,420},{134,0,1504},{6,0,757},{133,11,383},{6,0,1266},{135 ,0,1735},{5,0,598},{7,0,791},{8,0,108},{9,0,123},{7,10,1570},{140,10,542},{142, 11,410},{9,11,660},{138,11,347} }; /* GENERATED CODE END */ #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_STATIC_DICT_LUT_H_ */ dvisvgm-3.5/libs/brotli/enc/utf8_util.c000066400000000000000000000043351501401750600201240ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Heuristics for deciding about the UTF8-ness of strings. */ #include "utf8_util.h" #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static size_t BrotliParseAsUTF8( int* symbol, const uint8_t* input, size_t size) { /* ASCII */ if ((input[0] & 0x80) == 0) { *symbol = input[0]; if (*symbol > 0) { return 1; } } /* 2-byte UTF8 */ if (size > 1u && (input[0] & 0xE0) == 0xC0 && (input[1] & 0xC0) == 0x80) { *symbol = (((input[0] & 0x1F) << 6) | (input[1] & 0x3F)); if (*symbol > 0x7F) { return 2; } } /* 3-byte UFT8 */ if (size > 2u && (input[0] & 0xF0) == 0xE0 && (input[1] & 0xC0) == 0x80 && (input[2] & 0xC0) == 0x80) { *symbol = (((input[0] & 0x0F) << 12) | ((input[1] & 0x3F) << 6) | (input[2] & 0x3F)); if (*symbol > 0x7FF) { return 3; } } /* 4-byte UFT8 */ if (size > 3u && (input[0] & 0xF8) == 0xF0 && (input[1] & 0xC0) == 0x80 && (input[2] & 0xC0) == 0x80 && (input[3] & 0xC0) == 0x80) { *symbol = (((input[0] & 0x07) << 18) | ((input[1] & 0x3F) << 12) | ((input[2] & 0x3F) << 6) | (input[3] & 0x3F)); if (*symbol > 0xFFFF && *symbol <= 0x10FFFF) { return 4; } } /* Not UTF8, emit a special symbol above the UTF8-code space */ *symbol = 0x110000 | input[0]; return 1; } /* Returns 1 if at least min_fraction of the data is UTF8-encoded.*/ BROTLI_BOOL BrotliIsMostlyUTF8( const uint8_t* data, const size_t pos, const size_t mask, const size_t length, const double min_fraction) { size_t size_utf8 = 0; size_t i = 0; while (i < length) { int symbol; size_t bytes_read = BrotliParseAsUTF8(&symbol, &data[(pos + i) & mask], length - i); i += bytes_read; if (symbol < 0x110000) size_utf8 += bytes_read; } return TO_BROTLI_BOOL((double)size_utf8 > min_fraction * (double)length); } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif dvisvgm-3.5/libs/brotli/enc/utf8_util.h000066400000000000000000000016111501401750600201230ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Heuristics for deciding about the UTF8-ness of strings. */ #ifndef BROTLI_ENC_UTF8_UTIL_H_ #define BROTLI_ENC_UTF8_UTIL_H_ #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif static const double kMinUTF8Ratio = 0.75; /* Returns 1 if at least min_fraction of the bytes between pos and pos + length in the (data, mask) ring-buffer is UTF8-encoded, otherwise returns 0. */ BROTLI_INTERNAL BROTLI_BOOL BrotliIsMostlyUTF8( const uint8_t* data, const size_t pos, const size_t mask, const size_t length, const double min_fraction); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_UTF8_UTIL_H_ */ dvisvgm-3.5/libs/brotli/enc/write_bits.h000066400000000000000000000054561501401750600203660ustar00rootroot00000000000000/* Copyright 2010 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Write bits into a byte array. */ #ifndef BROTLI_ENC_WRITE_BITS_H_ #define BROTLI_ENC_WRITE_BITS_H_ #include #include "../common/platform.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /* This function writes bits into bytes in increasing addresses, and within a byte least-significant-bit first. The function can write up to 56 bits in one go with WriteBits Example: let's assume that 3 bits (Rs below) have been written already: BYTE-0 BYTE+1 BYTE+2 0000 0RRR 0000 0000 0000 0000 Now, we could write 5 or less bits in MSB by just shifting by 3 and OR'ing to BYTE-0. For n bits, we take the last 5 bits, OR that with high bits in BYTE-0, and locate the rest in BYTE+1, BYTE+2, etc. */ static BROTLI_INLINE void BrotliWriteBits(size_t n_bits, uint64_t bits, size_t* BROTLI_RESTRICT pos, uint8_t* BROTLI_RESTRICT array) { BROTLI_LOG(("WriteBits %2d 0x%08x%08x %10d\n", (int)n_bits, (uint32_t)(bits >> 32), (uint32_t)(bits & 0xFFFFFFFF), (int)*pos)); BROTLI_DCHECK((bits >> n_bits) == 0); BROTLI_DCHECK(n_bits <= 56); #if defined(BROTLI_LITTLE_ENDIAN) /* This branch of the code can write up to 56 bits at a time, 7 bits are lost by being perhaps already in *p and at least 1 bit is needed to initialize the bit-stream ahead (i.e. if 7 bits are in *p and we write 57 bits, then the next write will access a byte that was never initialized). */ { uint8_t* p = &array[*pos >> 3]; uint64_t v = (uint64_t)(*p); /* Zero-extend 8 to 64 bits. */ v |= bits << (*pos & 7); BROTLI_UNALIGNED_STORE64LE(p, v); /* Set some bits. */ *pos += n_bits; } #else /* implicit & 0xFF is assumed for uint8_t arithmetics */ { uint8_t* array_pos = &array[*pos >> 3]; const size_t bits_reserved_in_first_byte = (*pos & 7); size_t bits_left_to_write; bits <<= bits_reserved_in_first_byte; *array_pos++ |= (uint8_t)bits; for (bits_left_to_write = n_bits + bits_reserved_in_first_byte; bits_left_to_write >= 9; bits_left_to_write -= 8) { bits >>= 8; *array_pos++ = (uint8_t)bits; } *array_pos = 0; *pos += n_bits; } #endif } static BROTLI_INLINE void BrotliWriteBitsPrepareStorage( size_t pos, uint8_t* array) { BROTLI_LOG(("WriteBitsPrepareStorage %10d\n", (int)pos)); BROTLI_DCHECK((pos & 7) == 0); array[pos >> 3] = 0; } #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_WRITE_BITS_H_ */ dvisvgm-3.5/libs/brotli/include/000077500000000000000000000000001501401750600167065ustar00rootroot00000000000000dvisvgm-3.5/libs/brotli/include/brotli/000077500000000000000000000000001501401750600202015ustar00rootroot00000000000000dvisvgm-3.5/libs/brotli/include/brotli/decode.h000066400000000000000000000407661501401750600216120ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /** * @file * API for Brotli decompression. */ #ifndef BROTLI_DEC_DECODE_H_ #define BROTLI_DEC_DECODE_H_ #include #include #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /** * Opaque structure that holds decoder state. * * Allocated and initialized with ::BrotliDecoderCreateInstance. * Cleaned up and deallocated with ::BrotliDecoderDestroyInstance. */ typedef struct BrotliDecoderStateStruct BrotliDecoderState; /** * Result type for ::BrotliDecoderDecompress and * ::BrotliDecoderDecompressStream functions. */ typedef enum { /** Decoding error, e.g. corrupted input or memory allocation problem. */ BROTLI_DECODER_RESULT_ERROR = 0, /** Decoding successfully completed. */ BROTLI_DECODER_RESULT_SUCCESS = 1, /** Partially done; should be called again with more input. */ BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2, /** Partially done; should be called again with more output. */ BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3 } BrotliDecoderResult; /** * Template that evaluates items of ::BrotliDecoderErrorCode. * * Example: @code {.cpp} * // Log Brotli error code. * switch (brotliDecoderErrorCode) { * #define CASE_(PREFIX, NAME, CODE) \ * case BROTLI_DECODER ## PREFIX ## NAME: \ * LOG(INFO) << "error code:" << #NAME; \ * break; * #define NEWLINE_ * BROTLI_DECODER_ERROR_CODES_LIST(CASE_, NEWLINE_) * #undef CASE_ * #undef NEWLINE_ * default: LOG(FATAL) << "unknown brotli error code"; * } * @endcode */ #define BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE, SEPARATOR) \ BROTLI_ERROR_CODE(_, NO_ERROR, 0) SEPARATOR \ /* Same as BrotliDecoderResult values */ \ BROTLI_ERROR_CODE(_, SUCCESS, 1) SEPARATOR \ BROTLI_ERROR_CODE(_, NEEDS_MORE_INPUT, 2) SEPARATOR \ BROTLI_ERROR_CODE(_, NEEDS_MORE_OUTPUT, 3) SEPARATOR \ \ /* Errors caused by invalid input */ \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_NIBBLE, -1) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, RESERVED, -2) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_META_NIBBLE, -3) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_ALPHABET, -4) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_SAME, -5) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, CL_SPACE, -6) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, HUFFMAN_SPACE, -7) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, CONTEXT_MAP_REPEAT, -8) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_1, -9) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_2, -10) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, TRANSFORM, -11) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, DICTIONARY, -12) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, WINDOW_BITS, -13) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR \ \ /* -17 code is reserved */ \ \ BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR \ \ /* Memory allocation problems */ \ BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MODES, -21) SEPARATOR \ /* Literal, insert and distance trees together */ \ BROTLI_ERROR_CODE(_ERROR_ALLOC_, TREE_GROUPS, -22) SEPARATOR \ /* -23..-24 codes are reserved for distinct tree groups */ \ BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MAP, -25) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_1, -26) SEPARATOR \ BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_2, -27) SEPARATOR \ /* -28..-29 codes are reserved for dynamic ring-buffer allocation */ \ BROTLI_ERROR_CODE(_ERROR_ALLOC_, BLOCK_TYPE_TREES, -30) SEPARATOR \ \ /* "Impossible" states */ \ BROTLI_ERROR_CODE(_ERROR_, UNREACHABLE, -31) /** * Error code for detailed logging / production debugging. * * See ::BrotliDecoderGetErrorCode and ::BROTLI_LAST_ERROR_CODE. */ typedef enum { #define BROTLI_COMMA_ , #define BROTLI_ERROR_CODE_ENUM_ITEM_(PREFIX, NAME, CODE) \ BROTLI_DECODER ## PREFIX ## NAME = CODE BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_ENUM_ITEM_, BROTLI_COMMA_) } BrotliDecoderErrorCode; #undef BROTLI_ERROR_CODE_ENUM_ITEM_ #undef BROTLI_COMMA_ /** * The value of the last error code, negative integer. * * All other error code values are in the range from ::BROTLI_LAST_ERROR_CODE * to @c -1. There are also 4 other possible non-error codes @c 0 .. @c 3 in * ::BrotliDecoderErrorCode enumeration. */ #define BROTLI_LAST_ERROR_CODE BROTLI_DECODER_ERROR_UNREACHABLE /** Options to be used with ::BrotliDecoderSetParameter. */ typedef enum BrotliDecoderParameter { /** * Disable "canny" ring buffer allocation strategy. * * Ring buffer is allocated according to window size, despite the real size of * the content. */ BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION = 0, /** * Flag that determines if "Large Window Brotli" is used. */ BROTLI_DECODER_PARAM_LARGE_WINDOW = 1 } BrotliDecoderParameter; /** * Sets the specified parameter to the given decoder instance. * * @param state decoder instance * @param param parameter to set * @param value new parameter value * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid * @returns ::BROTLI_TRUE if value is accepted */ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter( BrotliDecoderState* state, BrotliDecoderParameter param, uint32_t value); /** * Adds LZ77 prefix dictionary, adds or replaces built-in static dictionary and * transforms. * * Attached dictionary ownership is not transferred. * Data provided to this method should be kept accessible until * decoding is finished and decoder instance is destroyed. * * @note Dictionaries can NOT be attached after actual decoding is started. * * @param state decoder instance * @param type dictionary data format * @param data_size length of memory region pointed by @p data * @param data dictionary data in format corresponding to @p type * @returns ::BROTLI_FALSE if dictionary is corrupted, * or dictionary count limit is reached * @returns ::BROTLI_TRUE if dictionary is accepted / attached */ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderAttachDictionary( BrotliDecoderState* state, BrotliSharedDictionaryType type, size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]); /** * Creates an instance of ::BrotliDecoderState and initializes it. * * The instance can be used once for decoding and should then be destroyed with * ::BrotliDecoderDestroyInstance, it cannot be reused for a new decoding * session. * * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the * case they are both zero, default memory allocators are used. @p opaque is * passed to @p alloc_func and @p free_func when they are called. @p free_func * has to return without doing anything when asked to free a NULL pointer. * * @param alloc_func custom memory allocation function * @param free_func custom memory free function * @param opaque custom memory manager handle * @returns @c 0 if instance can not be allocated or initialized * @returns pointer to initialized ::BrotliDecoderState otherwise */ BROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); /** * Deinitializes and frees ::BrotliDecoderState instance. * * @param state decoder instance to be cleaned up and deallocated */ BROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state); /** * Performs one-shot memory-to-memory decompression. * * Decompresses the data in @p encoded_buffer into @p decoded_buffer, and sets * @p *decoded_size to the decompressed length. * * @param encoded_size size of @p encoded_buffer * @param encoded_buffer compressed data buffer with at least @p encoded_size * addressable bytes * @param[in, out] decoded_size @b in: size of @p decoded_buffer; \n * @b out: length of decompressed data written to * @p decoded_buffer * @param decoded_buffer decompressed data destination buffer * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory * allocation failed, or @p decoded_buffer is not large enough; * @returns ::BROTLI_DECODER_RESULT_SUCCESS otherwise */ BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress( size_t encoded_size, const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)], size_t* decoded_size, uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]); /** * Decompresses the input stream to the output stream. * * The values @p *available_in and @p *available_out must specify the number of * bytes addressable at @p *next_in and @p *next_out respectively. * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL. * * After each call, @p *available_in will be decremented by the amount of input * bytes consumed, and the @p *next_in pointer will be incremented by that * amount. Similarly, @p *available_out will be decremented by the amount of * output bytes written, and the @p *next_out pointer will be incremented by * that amount. * * @p total_out, if it is not a null-pointer, will be set to the number * of bytes decompressed since the last @p state initialization. * * @note Input is never overconsumed, so @p next_in and @p available_in could be * passed to the next consumer after decoding is complete. * * @param state decoder instance * @param[in, out] available_in @b in: amount of available input; \n * @b out: amount of unused input * @param[in, out] next_in pointer to the next compressed byte * @param[in, out] available_out @b in: length of output buffer; \n * @b out: remaining size of output buffer * @param[in, out] next_out output buffer cursor; * can be @c NULL if @p available_out is @c 0 * @param[out] total_out number of bytes decompressed so far; can be @c NULL * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory * allocation failed, arguments were invalid, etc.; * use ::BrotliDecoderGetErrorCode to get detailed error code * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT decoding is blocked until * more input data is provided * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT decoding is blocked until * more output space is provided * @returns ::BROTLI_DECODER_RESULT_SUCCESS decoding is finished, no more * input might be consumed and no more output will be produced */ BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompressStream( BrotliDecoderState* state, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out); /** * Checks if decoder has more output. * * @param state decoder instance * @returns ::BROTLI_TRUE, if decoder has some unconsumed output * @returns ::BROTLI_FALSE otherwise */ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderHasMoreOutput( const BrotliDecoderState* state); /** * Acquires pointer to internal output buffer. * * This method is used to make language bindings easier and more efficient: * -# push data to ::BrotliDecoderDecompressStream, * until ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT is reported * -# use ::BrotliDecoderTakeOutput to peek bytes and copy to language-specific * entity * * Also this could be useful if there is an output stream that is able to * consume all the provided data (e.g. when data is saved to file system). * * @attention After every call to ::BrotliDecoderTakeOutput @p *size bytes of * output are considered consumed for all consecutive calls to the * instance methods; returned pointer becomes invalidated as well. * * @note Decoder output is not guaranteed to be contiguous. This means that * after the size-unrestricted call to ::BrotliDecoderTakeOutput, * immediate next call to ::BrotliDecoderTakeOutput may return more data. * * @param state decoder instance * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if * any amount could be handled; \n * @b out: amount of data pointed by returned pointer and * considered consumed; \n * out value is never greater than in value, unless it is @c 0 * @returns pointer to output data */ BROTLI_DEC_API const uint8_t* BrotliDecoderTakeOutput( BrotliDecoderState* state, size_t* size); /** * Checks if instance has already consumed input. * * Instance that returns ::BROTLI_FALSE is considered "fresh" and could be * reused. * * @param state decoder instance * @returns ::BROTLI_TRUE if decoder has already used some input bytes * @returns ::BROTLI_FALSE otherwise */ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* state); /** * Checks if decoder instance reached the final state. * * @param state decoder instance * @returns ::BROTLI_TRUE if decoder is in a state where it reached the end of * the input and produced all of the output * @returns ::BROTLI_FALSE otherwise */ BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsFinished( const BrotliDecoderState* state); /** * Acquires a detailed error code. * * Should be used only after ::BrotliDecoderDecompressStream returns * ::BROTLI_DECODER_RESULT_ERROR. * * See also ::BrotliDecoderErrorString * * @param state decoder instance * @returns last saved error code */ BROTLI_DEC_API BrotliDecoderErrorCode BrotliDecoderGetErrorCode( const BrotliDecoderState* state); /** * Converts error code to a c-string. */ BROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c); /** * Gets a decoder library version. * * Look at BROTLI_MAKE_HEX_VERSION for more information. */ BROTLI_DEC_API uint32_t BrotliDecoderVersion(void); /** * Callback to fire on metadata block start. * * After this callback is fired, if @p size is not @c 0, it is followed by * ::brotli_decoder_metadata_chunk_func as more metadata block contents become * accessible. * * @param opaque callback handle * @param size size of metadata block */ typedef void (*brotli_decoder_metadata_start_func)(void* opaque, size_t size); /** * Callback to fire on metadata block chunk becomes available. * * This function can be invoked multiple times per metadata block; block should * be considered finished when sum of @p size matches the announced metadata * block size. Chunks contents pointed by @p data are transient and shouln not * be accessed after leaving the callback. * * @param opaque callback handle * @param data pointer to metadata contents * @param size size of metadata block chunk, at least @c 1 */ typedef void (*brotli_decoder_metadata_chunk_func)(void* opaque, const uint8_t* data, size_t size); /** * Sets callback for receiving metadata blocks. * * @param state decoder instance * @param start_func callback on metadata block start * @param chunk_func callback on metadata block chunk * @param opaque callback handle */ BROTLI_DEC_API void BrotliDecoderSetMetadataCallbacks( BrotliDecoderState* state, brotli_decoder_metadata_start_func start_func, brotli_decoder_metadata_chunk_func chunk_func, void* opaque); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_DEC_DECODE_H_ */ dvisvgm-3.5/libs/brotli/include/brotli/encode.h000066400000000000000000000466011501401750600216160ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /** * @file * API for Brotli compression. */ #ifndef BROTLI_ENC_ENCODE_H_ #define BROTLI_ENC_ENCODE_H_ #include #include #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif /** Minimal value for ::BROTLI_PARAM_LGWIN parameter. */ #define BROTLI_MIN_WINDOW_BITS 10 /** * Maximal value for ::BROTLI_PARAM_LGWIN parameter. * * @note equal to @c BROTLI_MAX_DISTANCE_BITS constant. */ #define BROTLI_MAX_WINDOW_BITS 24 /** * Maximal value for ::BROTLI_PARAM_LGWIN parameter * in "Large Window Brotli" (32-bit). */ #define BROTLI_LARGE_MAX_WINDOW_BITS 30 /** Minimal value for ::BROTLI_PARAM_LGBLOCK parameter. */ #define BROTLI_MIN_INPUT_BLOCK_BITS 16 /** Maximal value for ::BROTLI_PARAM_LGBLOCK parameter. */ #define BROTLI_MAX_INPUT_BLOCK_BITS 24 /** Minimal value for ::BROTLI_PARAM_QUALITY parameter. */ #define BROTLI_MIN_QUALITY 0 /** Maximal value for ::BROTLI_PARAM_QUALITY parameter. */ #define BROTLI_MAX_QUALITY 11 /** Options for ::BROTLI_PARAM_MODE parameter. */ typedef enum BrotliEncoderMode { /** * Default compression mode. * * In this mode compressor does not know anything in advance about the * properties of the input. */ BROTLI_MODE_GENERIC = 0, /** Compression mode for UTF-8 formatted text input. */ BROTLI_MODE_TEXT = 1, /** Compression mode used in WOFF 2.0. */ BROTLI_MODE_FONT = 2 } BrotliEncoderMode; /** Default value for ::BROTLI_PARAM_QUALITY parameter. */ #define BROTLI_DEFAULT_QUALITY 11 /** Default value for ::BROTLI_PARAM_LGWIN parameter. */ #define BROTLI_DEFAULT_WINDOW 22 /** Default value for ::BROTLI_PARAM_MODE parameter. */ #define BROTLI_DEFAULT_MODE BROTLI_MODE_GENERIC /** Operations that can be performed by streaming encoder. */ typedef enum BrotliEncoderOperation { /** * Process input. * * Encoder may postpone producing output, until it has processed enough input. */ BROTLI_OPERATION_PROCESS = 0, /** * Produce output for all processed input. * * Actual flush is performed when input stream is depleted and there is enough * space in output stream. This means that client should repeat * ::BROTLI_OPERATION_FLUSH operation until @p available_in becomes @c 0, and * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired * via ::BrotliEncoderTakeOutput, then operation should be repeated after * output buffer is drained. * * @warning Until flush is complete, client @b SHOULD @b NOT swap, * reduce or extend input stream. * * When flush is complete, output data will be sufficient for decoder to * reproduce all the given input. */ BROTLI_OPERATION_FLUSH = 1, /** * Finalize the stream. * * Actual finalization is performed when input stream is depleted and there is * enough space in output stream. This means that client should repeat * ::BROTLI_OPERATION_FINISH operation until @p available_in becomes @c 0, and * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired * via ::BrotliEncoderTakeOutput, then operation should be repeated after * output buffer is drained. * * @warning Until finalization is complete, client @b SHOULD @b NOT swap, * reduce or extend input stream. * * Helper function ::BrotliEncoderIsFinished checks if stream is finalized and * output fully dumped. * * Adding more input data to finalized stream is impossible. */ BROTLI_OPERATION_FINISH = 2, /** * Emit metadata block to stream. * * Metadata is opaque to Brotli: neither encoder, nor decoder processes this * data or relies on it. It may be used to pass some extra information from * encoder client to decoder client without interfering with main data stream. * * @note Encoder may emit empty metadata blocks internally, to pad encoded * stream to byte boundary. * * @warning Until emitting metadata is complete client @b SHOULD @b NOT swap, * reduce or extend input stream. * * @warning The whole content of input buffer is considered to be the content * of metadata block. Do @b NOT @e append metadata to input stream, * before it is depleted with other operations. * * Stream is soft-flushed before metadata block is emitted. Metadata block * @b MUST be no longer than than 16MiB. */ BROTLI_OPERATION_EMIT_METADATA = 3 } BrotliEncoderOperation; /** Options to be used with ::BrotliEncoderSetParameter. */ typedef enum BrotliEncoderParameter { /** * Tune encoder for specific input. * * ::BrotliEncoderMode enumerates all available values. */ BROTLI_PARAM_MODE = 0, /** * The main compression speed-density lever. * * The higher the quality, the slower the compression. Range is * from ::BROTLI_MIN_QUALITY to ::BROTLI_MAX_QUALITY. */ BROTLI_PARAM_QUALITY = 1, /** * Recommended sliding LZ77 window size. * * Encoder may reduce this value, e.g. if input is much smaller than * window size. * * Window size is `(1 << value) - 16`. * * Range is from ::BROTLI_MIN_WINDOW_BITS to ::BROTLI_MAX_WINDOW_BITS. */ BROTLI_PARAM_LGWIN = 2, /** * Recommended input block size. * * Encoder may reduce this value, e.g. if input is much smaller than input * block size. * * Range is from ::BROTLI_MIN_INPUT_BLOCK_BITS to * ::BROTLI_MAX_INPUT_BLOCK_BITS. * * @note Bigger input block size allows better compression, but consumes more * memory. \n The rough formula of memory used for temporary input * storage is `3 << lgBlock`. */ BROTLI_PARAM_LGBLOCK = 3, /** * Flag that affects usage of "literal context modeling" format feature. * * This flag is a "decoding-speed vs compression ratio" trade-off. */ BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING = 4, /** * Estimated total input size for all ::BrotliEncoderCompressStream calls. * * The default value is 0, which means that the total input size is unknown. */ BROTLI_PARAM_SIZE_HINT = 5, /** * Flag that determines if "Large Window Brotli" is used. */ BROTLI_PARAM_LARGE_WINDOW = 6, /** * Recommended number of postfix bits (NPOSTFIX). * * Encoder may change this value. * * Range is from 0 to ::BROTLI_MAX_NPOSTFIX. */ BROTLI_PARAM_NPOSTFIX = 7, /** * Recommended number of direct distance codes (NDIRECT). * * Encoder may change this value. * * Range is from 0 to (15 << NPOSTFIX) in steps of (1 << NPOSTFIX). */ BROTLI_PARAM_NDIRECT = 8, /** * Number of bytes of input stream already processed by a different instance. * * @note It is important to configure all the encoder instances with same * parameters (except this one) in order to allow all the encoded parts * obey the same restrictions implied by header. * * If offset is not 0, then stream header is omitted. * In any case output start is byte aligned, so for proper streams stitching * "predecessor" stream must be flushed. * * Range is not artificially limited, but all the values greater or equal to * maximal window size have the same effect. Values greater than 2**30 are not * allowed. */ BROTLI_PARAM_STREAM_OFFSET = 9 } BrotliEncoderParameter; /** * Opaque structure that holds encoder state. * * Allocated and initialized with ::BrotliEncoderCreateInstance. * Cleaned up and deallocated with ::BrotliEncoderDestroyInstance. */ typedef struct BrotliEncoderStateStruct BrotliEncoderState; /** * Sets the specified parameter to the given encoder instance. * * @param state encoder instance * @param param parameter to set * @param value new parameter value * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid * @returns ::BROTLI_FALSE if value of parameter can not be changed at current * encoder state (e.g. when encoding is started, window size might be * already encoded and therefore it is impossible to change it) * @returns ::BROTLI_TRUE if value is accepted * @warning invalid values might be accepted in case they would not break * encoding process. */ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter( BrotliEncoderState* state, BrotliEncoderParameter param, uint32_t value); /** * Creates an instance of ::BrotliEncoderState and initializes it. * * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the * case they are both zero, default memory allocators are used. @p opaque is * passed to @p alloc_func and @p free_func when they are called. @p free_func * has to return without doing anything when asked to free a NULL pointer. * * @param alloc_func custom memory allocation function * @param free_func custom memory free function * @param opaque custom memory manager handle * @returns @c 0 if instance can not be allocated or initialized * @returns pointer to initialized ::BrotliEncoderState otherwise */ BROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); /** * Deinitializes and frees ::BrotliEncoderState instance. * * @param state decoder instance to be cleaned up and deallocated */ BROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState* state); /* Opaque type for pointer to different possible internal structures containing dictionary prepared for the encoder */ typedef struct BrotliEncoderPreparedDictionaryStruct BrotliEncoderPreparedDictionary; /** * Prepares a shared dictionary from the given file format for the encoder. * * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the * case they are both zero, default memory allocators are used. @p opaque is * passed to @p alloc_func and @p free_func when they are called. @p free_func * has to return without doing anything when asked to free a NULL pointer. * * @param type type of dictionary stored in data * @param data_size size of @p data buffer * @param data pointer to the dictionary data * @param quality the maximum Brotli quality to prepare the dictionary for, * use BROTLI_MAX_QUALITY by default * @param alloc_func custom memory allocation function * @param free_func custom memory free function * @param opaque custom memory manager handle */ BROTLI_ENC_API BrotliEncoderPreparedDictionary* BrotliEncoderPrepareDictionary(BrotliSharedDictionaryType type, size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)], int quality, brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); BROTLI_ENC_API void BrotliEncoderDestroyPreparedDictionary( BrotliEncoderPreparedDictionary* dictionary); /** * Attaches a prepared dictionary of any type to the encoder. Can be used * multiple times to attach multiple dictionaries. The dictionary type was * determined by BrotliEncoderPrepareDictionary. Multiple raw prefix * dictionaries and/or max 1 serialized dictionary with custom words can be * attached. * * @returns ::BROTLI_FALSE in case of error * @returns ::BROTLI_TRUE otherwise */ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderAttachPreparedDictionary( BrotliEncoderState* state, const BrotliEncoderPreparedDictionary* dictionary); /** * Calculates the output size bound for the given @p input_size. * * @warning Result is only valid if quality is at least @c 2 and, in * case ::BrotliEncoderCompressStream was used, no flushes * (::BROTLI_OPERATION_FLUSH) were performed. * * @param input_size size of projected input * @returns @c 0 if result does not fit @c size_t */ BROTLI_ENC_API size_t BrotliEncoderMaxCompressedSize(size_t input_size); /** * Performs one-shot memory-to-memory compression. * * Compresses the data in @p input_buffer into @p encoded_buffer, and sets * @p *encoded_size to the compressed length. * * @note If ::BrotliEncoderMaxCompressedSize(@p input_size) returns non-zero * value, then output is guaranteed to be no longer than that. * * @note If @p lgwin is greater than ::BROTLI_MAX_WINDOW_BITS then resulting * stream might be incompatible with RFC 7932; to decode such streams, * decoder should be configured with * ::BROTLI_DECODER_PARAM_LARGE_WINDOW = @c 1 * * @param quality quality parameter value, e.g. ::BROTLI_DEFAULT_QUALITY * @param lgwin lgwin parameter value, e.g. ::BROTLI_DEFAULT_WINDOW * @param mode mode parameter value, e.g. ::BROTLI_DEFAULT_MODE * @param input_size size of @p input_buffer * @param input_buffer input data buffer with at least @p input_size * addressable bytes * @param[in, out] encoded_size @b in: size of @p encoded_buffer; \n * @b out: length of compressed data written to * @p encoded_buffer, or @c 0 if compression fails * @param encoded_buffer compressed data destination buffer * @returns ::BROTLI_FALSE in case of compression error * @returns ::BROTLI_FALSE if output buffer is too small * @returns ::BROTLI_TRUE otherwise */ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress( int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)], size_t* encoded_size, uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]); /** * Compresses input stream to output stream. * * The values @p *available_in and @p *available_out must specify the number of * bytes addressable at @p *next_in and @p *next_out respectively. * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL. * * After each call, @p *available_in will be decremented by the amount of input * bytes consumed, and the @p *next_in pointer will be incremented by that * amount. Similarly, @p *available_out will be decremented by the amount of * output bytes written, and the @p *next_out pointer will be incremented by * that amount. * * @p total_out, if it is not a null-pointer, will be set to the number * of bytes compressed since the last @p state initialization. * * * * Internally workflow consists of 3 tasks: * -# (optionally) copy input data to internal buffer * -# actually compress data and (optionally) store it to internal buffer * -# (optionally) copy compressed bytes from internal buffer to output stream * * Whenever all 3 tasks can't move forward anymore, or error occurs, this * method returns the control flow to caller. * * @p op is used to perform flush, finish the stream, or inject metadata block. * See ::BrotliEncoderOperation for more information. * * Flushing the stream means forcing encoding of all input passed to encoder and * completing the current output block, so it could be fully decoded by stream * decoder. To perform flush set @p op to ::BROTLI_OPERATION_FLUSH. * Under some circumstances (e.g. lack of output stream capacity) this operation * would require several calls to ::BrotliEncoderCompressStream. The method must * be called again until both input stream is depleted and encoder has no more * output (see ::BrotliEncoderHasMoreOutput) after the method is called. * * Finishing the stream means encoding of all input passed to encoder and * adding specific "final" marks, so stream decoder could determine that stream * is complete. To perform finish set @p op to ::BROTLI_OPERATION_FINISH. * Under some circumstances (e.g. lack of output stream capacity) this operation * would require several calls to ::BrotliEncoderCompressStream. The method must * be called again until both input stream is depleted and encoder has no more * output (see ::BrotliEncoderHasMoreOutput) after the method is called. * * @warning When flushing and finishing, @p op should not change until operation * is complete; input stream should not be swapped, reduced or * extended as well. * * @param state encoder instance * @param op requested operation * @param[in, out] available_in @b in: amount of available input; \n * @b out: amount of unused input * @param[in, out] next_in pointer to the next input byte * @param[in, out] available_out @b in: length of output buffer; \n * @b out: remaining size of output buffer * @param[in, out] next_out compressed output buffer cursor; * can be @c NULL if @p available_out is @c 0 * @param[out] total_out number of bytes produced so far; can be @c NULL * @returns ::BROTLI_FALSE if there was an error * @returns ::BROTLI_TRUE otherwise */ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompressStream( BrotliEncoderState* state, BrotliEncoderOperation op, size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out); /** * Checks if encoder instance reached the final state. * * @param state encoder instance * @returns ::BROTLI_TRUE if encoder is in a state where it reached the end of * the input and produced all of the output * @returns ::BROTLI_FALSE otherwise */ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* state); /** * Checks if encoder has more output. * * @param state encoder instance * @returns ::BROTLI_TRUE, if encoder has some unconsumed output * @returns ::BROTLI_FALSE otherwise */ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput( BrotliEncoderState* state); /** * Acquires pointer to internal output buffer. * * This method is used to make language bindings easier and more efficient: * -# push data to ::BrotliEncoderCompressStream, * until ::BrotliEncoderHasMoreOutput returns BROTLI_TRUE * -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific * entity * * Also this could be useful if there is an output stream that is able to * consume all the provided data (e.g. when data is saved to file system). * * @attention After every call to ::BrotliEncoderTakeOutput @p *size bytes of * output are considered consumed for all consecutive calls to the * instance methods; returned pointer becomes invalidated as well. * * @note Encoder output is not guaranteed to be contiguous. This means that * after the size-unrestricted call to ::BrotliEncoderTakeOutput, * immediate next call to ::BrotliEncoderTakeOutput may return more data. * * @param state encoder instance * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if * any amount could be handled; \n * @b out: amount of data pointed by returned pointer and * considered consumed; \n * out value is never greater than in value, unless it is @c 0 * @returns pointer to output data */ BROTLI_ENC_API const uint8_t* BrotliEncoderTakeOutput( BrotliEncoderState* state, size_t* size); /* Returns the estimated peak memory usage (in bytes) of the BrotliCompress() function, not counting the memory needed for the input and output. */ BROTLI_ENC_EXTRA_API size_t BrotliEncoderEstimatePeakMemoryUsage( int quality, int lgwin, size_t input_size); /* Returns 0 if dictionary is not valid; otherwise returns allocation size. */ BROTLI_ENC_EXTRA_API size_t BrotliEncoderGetPreparedDictionarySize( const BrotliEncoderPreparedDictionary* dictionary); /** * Gets an encoder library version. * * Look at BROTLI_MAKE_HEX_VERSION for more information. */ BROTLI_ENC_API uint32_t BrotliEncoderVersion(void); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_ENC_ENCODE_H_ */ dvisvgm-3.5/libs/brotli/include/brotli/port.h000066400000000000000000000262571501401750600213520ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Macros for compiler / platform specific API declarations. */ #ifndef BROTLI_COMMON_PORT_H_ #define BROTLI_COMMON_PORT_H_ /* The following macros were borrowed from https://github.com/nemequ/hedley * with permission of original author - Evan Nemerson */ /* >>> >>> >>> hedley macros */ #define BROTLI_MAKE_VERSION(major, minor, revision) \ (((major) * 1000000) + ((minor) * 1000) + (revision)) #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) #define BROTLI_GNUC_VERSION \ BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #elif defined(__GNUC__) #define BROTLI_GNUC_VERSION BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, 0) #endif #if defined(BROTLI_GNUC_VERSION) #define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) \ (BROTLI_GNUC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) #define BROTLI_MSVC_VERSION \ BROTLI_MAKE_VERSION((_MSC_FULL_VER / 10000000), \ (_MSC_FULL_VER % 10000000) / 100000, \ (_MSC_FULL_VER % 100000) / 100) #elif defined(_MSC_FULL_VER) #define BROTLI_MSVC_VERSION \ BROTLI_MAKE_VERSION((_MSC_FULL_VER / 1000000), \ (_MSC_FULL_VER % 1000000) / 10000, \ (_MSC_FULL_VER % 10000) / 10) #elif defined(_MSC_VER) #define BROTLI_MSVC_VERSION \ BROTLI_MAKE_VERSION(_MSC_VER / 100, _MSC_VER % 100, 0) #endif #if !defined(_MSC_VER) #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) (0) #elif defined(_MSC_VER) && (_MSC_VER >= 1400) #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) #elif defined(_MSC_VER) && (_MSC_VER >= 1200) #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) #else #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ (_MSC_VER >= ((major * 100) + (minor))) #endif #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) #define BROTLI_INTEL_VERSION \ BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, \ __INTEL_COMPILER % 100, \ __INTEL_COMPILER_UPDATE) #elif defined(__INTEL_COMPILER) #define BROTLI_INTEL_VERSION \ BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) #endif #if defined(BROTLI_INTEL_VERSION) #define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) \ (BROTLI_INTEL_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__PGI) && \ defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) #define BROTLI_PGI_VERSION \ BROTLI_MAKE_VERSION(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) #endif #if defined(BROTLI_PGI_VERSION) #define BROTLI_PGI_VERSION_CHECK(major, minor, patch) \ (BROTLI_PGI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_PGI_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) #define BROTLI_SUNPRO_VERSION \ BROTLI_MAKE_VERSION( \ (((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \ (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), \ (__SUNPRO_C & 0xf) * 10) #elif defined(__SUNPRO_C) #define BROTLI_SUNPRO_VERSION \ BROTLI_MAKE_VERSION((__SUNPRO_C >> 8) & 0xf, \ (__SUNPRO_C >> 4) & 0xf, \ (__SUNPRO_C) & 0xf) #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) #define BROTLI_SUNPRO_VERSION \ BROTLI_MAKE_VERSION( \ (((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \ (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), \ (__SUNPRO_CC & 0xf) * 10) #elif defined(__SUNPRO_CC) #define BROTLI_SUNPRO_VERSION \ BROTLI_MAKE_VERSION((__SUNPRO_CC >> 8) & 0xf, \ (__SUNPRO_CC >> 4) & 0xf, \ (__SUNPRO_CC) & 0xf) #endif #if defined(BROTLI_SUNPRO_VERSION) #define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) \ (BROTLI_SUNPRO_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) #define BROTLI_ARM_VERSION \ BROTLI_MAKE_VERSION((__ARMCOMPILER_VERSION / 1000000), \ (__ARMCOMPILER_VERSION % 1000000) / 10000, \ (__ARMCOMPILER_VERSION % 10000) / 100) #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) #define BROTLI_ARM_VERSION \ BROTLI_MAKE_VERSION((__ARMCC_VERSION / 1000000), \ (__ARMCC_VERSION % 1000000) / 10000, \ (__ARMCC_VERSION % 10000) / 100) #endif #if defined(BROTLI_ARM_VERSION) #define BROTLI_ARM_VERSION_CHECK(major, minor, patch) \ (BROTLI_ARM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_ARM_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__ibmxl__) #define BROTLI_IBM_VERSION \ BROTLI_MAKE_VERSION(__ibmxl_version__, \ __ibmxl_release__, \ __ibmxl_modification__) #elif defined(__xlC__) && defined(__xlC_ver__) #define BROTLI_IBM_VERSION \ BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) #elif defined(__xlC__) #define BROTLI_IBM_VERSION BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, 0) #endif #if defined(BROTLI_IBM_VERSION) #define BROTLI_IBM_VERSION_CHECK(major, minor, patch) \ (BROTLI_IBM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_IBM_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__TI_COMPILER_VERSION__) #define BROTLI_TI_VERSION \ BROTLI_MAKE_VERSION((__TI_COMPILER_VERSION__ / 1000000), \ (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(BROTLI_TI_VERSION) #define BROTLI_TI_VERSION_CHECK(major, minor, patch) \ (BROTLI_TI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_TI_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__IAR_SYSTEMS_ICC__) #if __VER__ > 1000 #define BROTLI_IAR_VERSION \ BROTLI_MAKE_VERSION((__VER__ / 1000000), \ (__VER__ / 1000) % 1000, \ (__VER__ % 1000)) #else #define BROTLI_IAR_VERSION BROTLI_MAKE_VERSION(VER / 100, __VER__ % 100, 0) #endif #endif #if defined(BROTLI_IAR_VERSION) #define BROTLI_IAR_VERSION_CHECK(major, minor, patch) \ (BROTLI_IAR_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_IAR_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__TINYC__) #define BROTLI_TINYC_VERSION \ BROTLI_MAKE_VERSION(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) #endif #if defined(BROTLI_TINYC_VERSION) #define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) \ (BROTLI_TINYC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) #else #define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(__has_attribute) #define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ __has_attribute(attribute) #else #define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ BROTLI_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(__has_builtin) #define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ __has_builtin(builtin) #else #define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ BROTLI_GNUC_VERSION_CHECK(major, minor, patch) #endif #if defined(__has_feature) #define BROTLI_HAS_FEATURE(feature) __has_feature(feature) #else #define BROTLI_HAS_FEATURE(feature) (0) #endif #if defined(_WIN32) || defined(__CYGWIN__) #define BROTLI_PUBLIC #elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && \ defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__)) #define BROTLI_PUBLIC __attribute__ ((visibility ("default"))) #else #define BROTLI_PUBLIC #endif /* BROTLI_INTERNAL could be defined to override visibility, e.g. for tests. */ #if !defined(BROTLI_INTERNAL) #if defined(_WIN32) || defined(__CYGWIN__) #define BROTLI_INTERNAL #elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && \ defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__)) #define BROTLI_INTERNAL __attribute__ ((visibility ("hidden"))) #else #define BROTLI_INTERNAL #endif #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ !defined(__STDC_NO_VLA__) && !defined(__cplusplus) && \ !defined(__PGI) && !defined(__PGIC__) && !defined(__TINYC__) && \ !defined(__clang__) #define BROTLI_ARRAY_PARAM(name) (name) #else #define BROTLI_ARRAY_PARAM(name) #endif /* <<< <<< <<< end of hedley macros. */ #if defined(BROTLI_SHARED_COMPILATION) #if defined(_WIN32) #if defined(BROTLICOMMON_SHARED_COMPILATION) #define BROTLI_COMMON_API __declspec(dllexport) #else #define BROTLI_COMMON_API __declspec(dllimport) #endif /* BROTLICOMMON_SHARED_COMPILATION */ #if defined(BROTLIDEC_SHARED_COMPILATION) #define BROTLI_DEC_API __declspec(dllexport) #else #define BROTLI_DEC_API __declspec(dllimport) #endif /* BROTLIDEC_SHARED_COMPILATION */ #if defined(BROTLIENC_SHARED_COMPILATION) #define BROTLI_ENC_API __declspec(dllexport) #else #define BROTLI_ENC_API __declspec(dllimport) #endif /* BROTLIENC_SHARED_COMPILATION */ #else /* _WIN32 */ #define BROTLI_COMMON_API BROTLI_PUBLIC #define BROTLI_DEC_API BROTLI_PUBLIC #define BROTLI_ENC_API BROTLI_PUBLIC #endif /* _WIN32 */ #else /* BROTLI_SHARED_COMPILATION */ #define BROTLI_COMMON_API #define BROTLI_DEC_API #define BROTLI_ENC_API #endif #if defined(BROTLI_BUILD_ENC_EXTRA_API) #define BROTLI_ENC_EXTRA_API BROTLI_ENC_API #else #define BROTLI_ENC_EXTRA_API BROTLI_INTERNAL #endif #endif /* BROTLI_COMMON_PORT_H_ */ dvisvgm-3.5/libs/brotli/include/brotli/shared_dictionary.h000066400000000000000000000067171501401750600240600ustar00rootroot00000000000000/* Copyright 2017 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* (Opaque) Shared Dictionary definition and utilities. */ #ifndef BROTLI_COMMON_SHARED_DICTIONARY_H_ #define BROTLI_COMMON_SHARED_DICTIONARY_H_ #include #include #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH 4 #define SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH 31 #define SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS 64 #define SHARED_BROTLI_MAX_COMPOUND_DICTS 15 /** * Opaque structure that holds shared dictionary data. * * Allocated and initialized with ::BrotliSharedDictionaryCreateInstance. * Cleaned up and deallocated with ::BrotliSharedDictionaryDestroyInstance. */ typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionary; /** * Input data type for ::BrotliSharedDictionaryAttach. */ typedef enum BrotliSharedDictionaryType { /** Raw LZ77 prefix dictionary. */ BROTLI_SHARED_DICTIONARY_RAW = 0, /** Serialized shared dictionary. * * DO NOT USE: methods accepting this value will fail. */ BROTLI_SHARED_DICTIONARY_SERIALIZED = 1 } BrotliSharedDictionaryType; /** * Creates an instance of ::BrotliSharedDictionary. * * Fresh instance has default word dictionary and transforms * and no LZ77 prefix dictionary. * * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the * case they are both zero, default memory allocators are used. @p opaque is * passed to @p alloc_func and @p free_func when they are called. @p free_func * has to return without doing anything when asked to free a NULL pointer. * * @param alloc_func custom memory allocation function * @param free_func custom memory free function * @param opaque custom memory manager handle * @returns @c 0 if instance can not be allocated or initialized * @returns pointer to initialized ::BrotliSharedDictionary otherwise */ BROTLI_COMMON_API BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance( brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); /** * Deinitializes and frees ::BrotliSharedDictionary instance. * * @param dict shared dictionary instance to be cleaned up and deallocated */ BROTLI_COMMON_API void BrotliSharedDictionaryDestroyInstance( BrotliSharedDictionary* dict); /** * Attaches dictionary to a given instance of ::BrotliSharedDictionary. * * Dictionary to be attached is represented in a serialized format as a region * of memory. * * Provided data it partially referenced by a resulting (compound) dictionary, * and should be kept untouched, while at least one compound dictionary uses it. * This way memory overhead is kept minimal by the cost of additional resource * management. * * @param dict dictionary to extend * @param type type of dictionary to attach * @param data_size size of @p data * @param data serialized dictionary of type @p type, with at least @p data_size * addressable bytes * @returns ::BROTLI_TRUE if provided dictionary is successfully attached * @returns ::BROTLI_FALSE otherwise */ BROTLI_COMMON_API BROTLI_BOOL BrotliSharedDictionaryAttach( BrotliSharedDictionary* dict, BrotliSharedDictionaryType type, size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif #endif /* BROTLI_COMMON_SHARED_DICTIONARY_H_ */ dvisvgm-3.5/libs/brotli/include/brotli/types.h000066400000000000000000000050671501401750600215260ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /** * @file * Common types used in decoder and encoder API. */ #ifndef BROTLI_COMMON_TYPES_H_ #define BROTLI_COMMON_TYPES_H_ #include /* for size_t */ #if defined(_MSC_VER) && (_MSC_VER < 1600) typedef __int8 int8_t; typedef unsigned __int8 uint8_t; typedef __int16 int16_t; typedef unsigned __int16 uint16_t; typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int64 int64_t; #else #include #endif /* defined(_MSC_VER) && (_MSC_VER < 1600) */ /** * A portable @c bool replacement. * * ::BROTLI_BOOL is a "documentation" type: actually it is @c int, but in API it * denotes a type, whose only values are ::BROTLI_TRUE and ::BROTLI_FALSE. * * ::BROTLI_BOOL values passed to Brotli should either be ::BROTLI_TRUE or * ::BROTLI_FALSE, or be a result of ::TO_BROTLI_BOOL macros. * * ::BROTLI_BOOL values returned by Brotli should not be tested for equality * with @c true, @c false, ::BROTLI_TRUE, ::BROTLI_FALSE, but rather should be * evaluated, for example: @code{.cpp} * if (SomeBrotliFunction(encoder, BROTLI_TRUE) && * !OtherBrotliFunction(decoder, BROTLI_FALSE)) { * bool x = !!YetAnotherBrotliFunction(encoder, TO_BROLTI_BOOL(2 * 2 == 4)); * DoSomething(x); * } * @endcode */ #define BROTLI_BOOL int /** Portable @c true replacement. */ #define BROTLI_TRUE 1 /** Portable @c false replacement. */ #define BROTLI_FALSE 0 /** @c bool to ::BROTLI_BOOL conversion macros. */ #define TO_BROTLI_BOOL(X) (!!(X) ? BROTLI_TRUE : BROTLI_FALSE) #define BROTLI_MAKE_UINT64_T(high, low) ((((uint64_t)(high)) << 32) | low) #define BROTLI_UINT32_MAX (~((uint32_t)0)) #define BROTLI_SIZE_MAX (~((size_t)0)) /** * Allocating function pointer type. * * @param opaque custom memory manager handle provided by client * @param size requested memory region size; can not be @c 0 * @returns @c 0 in the case of failure * @returns a valid pointer to a memory region of at least @p size bytes * long otherwise */ typedef void* (*brotli_alloc_func)(void* opaque, size_t size); /** * Deallocating function pointer type. * * This function @b SHOULD do nothing if @p address is @c 0. * * @param opaque custom memory manager handle provided by client * @param address memory region pointer returned by ::brotli_alloc_func, or @c 0 */ typedef void (*brotli_free_func)(void* opaque, void* address); #endif /* BROTLI_COMMON_TYPES_H_ */ dvisvgm-3.5/libs/clipper/000077500000000000000000000000001501401750600154265ustar00rootroot00000000000000dvisvgm-3.5/libs/clipper/License.txt000066400000000000000000000025361501401750600175570ustar00rootroot00000000000000Boost Software License - Version 1.0 - August 17th, 2003 http://www.boost.org/LICENSE_1_0.txt Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.dvisvgm-3.5/libs/clipper/Makefile.am000066400000000000000000000002631501401750600174630ustar00rootroot00000000000000noinst_LIBRARIES = libclipper.a libclipper_a_SOURCES = clipper.cpp clipper.hpp EXTRA_DIST = License.txt AM_CXXFLAGS = -Wall clipper.cpp: clipper.hpp CLEANFILES = *.gcda *.gcno dvisvgm-3.5/libs/clipper/clipper.cpp000066400000000000000000004022131501401750600175720ustar00rootroot00000000000000/******************************************************************************* * * * Author : Angus Johnson * * Version : 6.2.1 * * Date : 31 October 2014 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2014 * * * * License: * * Use, modification & distribution is subject to Boost Software License Ver 1. * * http://www.boost.org/LICENSE_1_0.txt * * * * Attributions: * * The code in this library is an extension of Bala Vatti's clipping algorithm: * * "A generic solution to polygon clipping" * * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * * http://portal.acm.org/citation.cfm?id=129906 * * * * Computer graphics and geometric modeling: implementation and algorithms * * By Max K. Agoston * * Springer; 1 edition (January 4, 2005) * * http://books.google.com/books?q=vatti+clipping+agoston * * * * See also: * * "Polygon Offsetting by Computing Winding Numbers" * * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * * September 24-28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ /******************************************************************************* * * * This is a translation of the Delphi Clipper library and the naming style * * used has retained a Delphi flavour. * * * *******************************************************************************/ #include "clipper.hpp" #include #include #include #include #include #include #include #include namespace ClipperLib { static double const pi = 3.141592653589793238; static double const two_pi = pi *2; static double const def_arc_tolerance = 0.25; enum Direction { dRightToLeft, dLeftToRight }; static int const Unassigned = -1; //edge not currently 'owning' a solution static int const Skip = -2; //edge that would otherwise close a path #define HORIZONTAL (-1.0E+40) #define TOLERANCE (1.0e-20) #define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) struct TEdge { IntPoint Bot; IntPoint Curr; IntPoint Top; IntPoint Delta; double Dx = 0.0; PolyType PolyTyp = ptSubject; EdgeSide Side = esLeft; int WindDelta = 0; //1 or -1 depending on winding direction int WindCnt = 0; int WindCnt2 = 0; //winding count of the opposite polytype int OutIdx = 0; TEdge *Next = nullptr; TEdge *Prev = nullptr; TEdge *NextInLML = nullptr; TEdge *NextInAEL = nullptr; TEdge *PrevInAEL = nullptr; TEdge *NextInSEL = nullptr; TEdge *PrevInSEL = nullptr; }; struct IntersectNode { TEdge *Edge1; TEdge *Edge2; IntPoint Pt; }; struct LocalMinimum { cInt Y; TEdge *LeftBound; TEdge *RightBound; }; struct OutPt; struct OutRec { int Idx; bool IsHole; bool IsOpen; OutRec *FirstLeft; //see comments in clipper.pas PolyNode *PolyNd; OutPt *Pts; OutPt *BottomPt; }; struct OutPt { int Idx; IntPoint Pt; OutPt *Next; OutPt *Prev; }; struct Join { OutPt *OutPt1; OutPt *OutPt2; IntPoint OffPt; }; struct LocMinSorter { inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2) { return locMin2.Y < locMin1.Y; } }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline cInt Round(double val) { if ((val < 0)) return static_cast(val - 0.5); else return static_cast(val + 0.5); } //------------------------------------------------------------------------------ inline cInt Abs(cInt val) { return val < 0 ? -val : val; } //------------------------------------------------------------------------------ // PolyTree methods ... //------------------------------------------------------------------------------ void PolyTree::Clear() { for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i) delete AllNodes[i]; AllNodes.resize(0); Childs.resize(0); } //------------------------------------------------------------------------------ PolyNode* PolyTree::GetFirst() const { if (!Childs.empty()) return Childs[0]; else return 0; } //------------------------------------------------------------------------------ int PolyTree::Total() const { int result = (int)AllNodes.size(); //with negative offsets, ignore the hidden outer polygon ... if (result > 0 && Childs[0] != AllNodes[0]) result--; return result; } //------------------------------------------------------------------------------ // PolyNode methods ... //------------------------------------------------------------------------------ PolyNode::PolyNode(): Childs(), Parent(0), Index(0), m_IsOpen(false) { } //------------------------------------------------------------------------------ int PolyNode::ChildCount() const { return (int)Childs.size(); } //------------------------------------------------------------------------------ void PolyNode::AddChild(PolyNode& child) { unsigned cnt = (unsigned)Childs.size(); Childs.push_back(&child); child.Parent = this; child.Index = cnt; } //------------------------------------------------------------------------------ PolyNode* PolyNode::GetNext() const { if (!Childs.empty()) return Childs[0]; else return GetNextSiblingUp(); } //------------------------------------------------------------------------------ PolyNode* PolyNode::GetNextSiblingUp() const { if (!Parent) //protects against PolyTree.GetNextSiblingUp() return 0; else if (Index == Parent->Childs.size() - 1) return Parent->GetNextSiblingUp(); else return Parent->Childs[Index + 1]; } //------------------------------------------------------------------------------ bool PolyNode::IsHole() const { bool result = true; PolyNode* node = Parent; while (node) { result = !result; node = node->Parent; } return result; } //------------------------------------------------------------------------------ bool PolyNode::IsOpen() const { return m_IsOpen; } //------------------------------------------------------------------------------ #ifndef use_int32 //------------------------------------------------------------------------------ // Int128 class (enables safe math on signed 64bit integers) // eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 // Int128 val2((long64)9223372036854775807); // Int128 val3 = val1 * val2; // val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) //------------------------------------------------------------------------------ class Int128 { public: ulong64 lo; long64 hi; Int128(long64 _lo = 0) { lo = (ulong64)_lo; if (_lo < 0) hi = -1; else hi = 0; } Int128(const Int128 &val): lo(val.lo), hi(val.hi){} Int128(const long64& _hi, const ulong64& _lo): lo(_lo), hi(_hi){} Int128& operator = (const long64 &val) { lo = (ulong64)val; if (val < 0) hi = -1; else hi = 0; return *this; } bool operator == (const Int128 &val) const {return (hi == val.hi && lo == val.lo);} bool operator != (const Int128 &val) const { return !(*this == val);} bool operator > (const Int128 &val) const { if (hi != val.hi) return hi > val.hi; else return lo > val.lo; } bool operator < (const Int128 &val) const { if (hi != val.hi) return hi < val.hi; else return lo < val.lo; } bool operator >= (const Int128 &val) const { return !(*this < val);} bool operator <= (const Int128 &val) const { return !(*this > val);} Int128& operator += (const Int128 &rhs) { hi += rhs.hi; lo += rhs.lo; if (lo < rhs.lo) hi++; return *this; } Int128 operator + (const Int128 &rhs) const { Int128 result(*this); result+= rhs; return result; } Int128& operator -= (const Int128 &rhs) { *this += -rhs; return *this; } Int128 operator - (const Int128 &rhs) const { Int128 result(*this); result -= rhs; return result; } Int128 operator-() const //unary negation { if (lo == 0) return Int128(-hi, 0); else return Int128(~hi, ~lo + 1); } operator double() const { const double shift64 = 18446744073709551616.0; //2^64 if (hi < 0) { if (lo == 0) return (double)hi * shift64; else return -(double)(~lo + ~hi * shift64); } else return (double)(lo + hi * shift64); } }; //------------------------------------------------------------------------------ Int128 Int128Mul (long64 lhs, long64 rhs) { bool negate = (lhs < 0) != (rhs < 0); if (lhs < 0) lhs = -lhs; ulong64 int1Hi = ulong64(lhs) >> 32; ulong64 int1Lo = ulong64(lhs & 0xFFFFFFFF); if (rhs < 0) rhs = -rhs; ulong64 int2Hi = ulong64(rhs) >> 32; ulong64 int2Lo = ulong64(rhs & 0xFFFFFFFF); //nb: see comments in clipper.pas ulong64 a = int1Hi * int2Hi; ulong64 b = int1Lo * int2Lo; ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; Int128 tmp; tmp.hi = long64(a + (c >> 32)); tmp.lo = long64(c << 32); tmp.lo += long64(b); if (tmp.lo < b) tmp.hi++; if (negate) tmp = -tmp; return tmp; }; #endif //------------------------------------------------------------------------------ // Miscellaneous global functions //------------------------------------------------------------------------------ bool Orientation(const Path &poly) { return Area(poly) >= 0; } //------------------------------------------------------------------------------ double Area(const Path &poly) { int size = (int)poly.size(); if (size < 3) return 0; double a = 0; for (int i = 0, j = size -1; i < size; ++i) { a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); j = i; } return -a * 0.5; } //------------------------------------------------------------------------------ double Area(const OutRec &outRec) { OutPt *op = outRec.Pts; if (!op) return 0; double a = 0; do { a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y); op = op->Next; } while (op != outRec.Pts); return a * 0.5; } //------------------------------------------------------------------------------ bool PointIsVertex(const IntPoint &Pt, OutPt *pp) { OutPt *pp2 = pp; do { if (pp2->Pt == Pt) return true; pp2 = pp2->Next; } while (pp2 != pp); return false; } //------------------------------------------------------------------------------ int PointInPolygon (const IntPoint &pt, const Path &path) { //returns 0 if false, +1 if true, -1 if pt ON polygon boundary //See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf int result = 0; size_t cnt = path.size(); if (cnt < 3) return 0; IntPoint ip = path[0]; for(size_t i = 1; i <= cnt; ++i) { IntPoint ipNext = (i == cnt ? path[0] : path[i]); if (ipNext.Y == pt.Y) { if ((ipNext.X == pt.X) || (ip.Y == pt.Y && ((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1; } if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) { if (ip.X >= pt.X) { if (ipNext.X > pt.X) result = 1 - result; else { double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); if (!d) return -1; if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; } } else { if (ipNext.X > pt.X) { double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); if (!d) return -1; if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; } } } ip = ipNext; } return result; } //------------------------------------------------------------------------------ int PointInPolygon (const IntPoint &pt, OutPt *op) { //returns 0 if false, +1 if true, -1 if pt ON polygon boundary int result = 0; OutPt* startOp = op; for(;;) { if (op->Next->Pt.Y == pt.Y) { if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y && ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1; } if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) { if (op->Pt.X >= pt.X) { if (op->Next->Pt.X > pt.X) result = 1 - result; else { double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); if (!d) return -1; if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; } } else { if (op->Next->Pt.X > pt.X) { double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); if (!d) return -1; if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; } } } op = op->Next; if (startOp == op) break; } return result; } //------------------------------------------------------------------------------ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) { OutPt* op = OutPt1; do { //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon int res = PointInPolygon(op->Pt, OutPt2); if (res >= 0) return res > 0; op = op->Next; } while (op != OutPt1); return true; } //---------------------------------------------------------------------- bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) { #ifndef use_int32 if (UseFullInt64Range) return Int128Mul(e1.Delta.Y, e2.Delta.X) == Int128Mul(e1.Delta.X, e2.Delta.Y); else #endif return e1.Delta.Y * e2.Delta.X == e1.Delta.X * e2.Delta.Y; } //------------------------------------------------------------------------------ bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3, bool UseFullInt64Range) { #ifndef use_int32 if (UseFullInt64Range) return Int128Mul(pt1.Y-pt2.Y, pt2.X-pt3.X) == Int128Mul(pt1.X-pt2.X, pt2.Y-pt3.Y); else #endif return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); } //------------------------------------------------------------------------------ bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) { #ifndef use_int32 if (UseFullInt64Range) return Int128Mul(pt1.Y-pt2.Y, pt3.X-pt4.X) == Int128Mul(pt1.X-pt2.X, pt3.Y-pt4.Y); else #endif return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); } //------------------------------------------------------------------------------ inline bool IsHorizontal(TEdge &e) { return e.Delta.Y == 0; } //------------------------------------------------------------------------------ inline double GetDx(const IntPoint pt1, const IntPoint pt2) { return (pt1.Y == pt2.Y) ? HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); } //--------------------------------------------------------------------------- inline void SetDx(TEdge &e) { e.Delta.X = (e.Top.X - e.Bot.X); e.Delta.Y = (e.Top.Y - e.Bot.Y); if (e.Delta.Y == 0) e.Dx = HORIZONTAL; else e.Dx = (double)(e.Delta.X) / e.Delta.Y; } //--------------------------------------------------------------------------- inline void SwapSides(TEdge &Edge1, TEdge &Edge2) { EdgeSide Side = Edge1.Side; Edge1.Side = Edge2.Side; Edge2.Side = Side; } //------------------------------------------------------------------------------ inline void SwapPolyIndexes(TEdge &Edge1, TEdge &Edge2) { int OutIdx = Edge1.OutIdx; Edge1.OutIdx = Edge2.OutIdx; Edge2.OutIdx = OutIdx; } //------------------------------------------------------------------------------ inline cInt TopX(TEdge &edge, const cInt currentY) { return ( currentY == edge.Top.Y ) ? edge.Top.X : edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y)); } //------------------------------------------------------------------------------ void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip) { #ifdef use_xyz ip.Z = 0; #endif double b1, b2; if (Edge1.Dx == Edge2.Dx) { ip.Y = Edge1.Curr.Y; ip.X = TopX(Edge1, ip.Y); return; } else if (Edge1.Delta.X == 0) { ip.X = Edge1.Bot.X; if (IsHorizontal(Edge2)) ip.Y = Edge2.Bot.Y; else { b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); ip.Y = Round(ip.X / Edge2.Dx + b2); } } else if (Edge2.Delta.X == 0) { ip.X = Edge2.Bot.X; if (IsHorizontal(Edge1)) ip.Y = Edge1.Bot.Y; else { b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); ip.Y = Round(ip.X / Edge1.Dx + b1); } } else { b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; double q = (b2-b1) / (Edge1.Dx - Edge2.Dx); ip.Y = Round(q); if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) ip.X = Round(Edge1.Dx * q + b1); else ip.X = Round(Edge2.Dx * q + b2); } if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) { if (Edge1.Top.Y > Edge2.Top.Y) ip.Y = Edge1.Top.Y; else ip.Y = Edge2.Top.Y; if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) ip.X = TopX(Edge1, ip.Y); else ip.X = TopX(Edge2, ip.Y); } //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... if (ip.Y > Edge1.Curr.Y) { ip.Y = Edge1.Curr.Y; //use the more vertical edge to derive X ... if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx)) ip.X = TopX(Edge2, ip.Y); else ip.X = TopX(Edge1, ip.Y); } } //------------------------------------------------------------------------------ void ReversePolyPtLinks(OutPt *pp) { if (!pp) return; OutPt *pp1, *pp2; pp1 = pp; do { pp2 = pp1->Next; pp1->Next = pp1->Prev; pp1->Prev = pp2; pp1 = pp2; } while( pp1 != pp ); } //------------------------------------------------------------------------------ void DisposeOutPts(OutPt*& pp) { if (pp == 0) return; pp->Prev->Next = 0; while( pp ) { OutPt *tmpPp = pp; pp = pp->Next; delete tmpPp; } } //------------------------------------------------------------------------------ inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt) { *e = TEdge(); e->Next = eNext; e->Prev = ePrev; e->Curr = Pt; e->OutIdx = Unassigned; } //------------------------------------------------------------------------------ void InitEdge2(TEdge& e, PolyType Pt) { if (e.Curr.Y >= e.Next->Curr.Y) { e.Bot = e.Curr; e.Top = e.Next->Curr; } else { e.Top = e.Curr; e.Bot = e.Next->Curr; } SetDx(e); e.PolyTyp = Pt; } //------------------------------------------------------------------------------ TEdge* RemoveEdge(TEdge* e) { //removes e from double_linked_list (but without removing from memory) e->Prev->Next = e->Next; e->Next->Prev = e->Prev; TEdge* result = e->Next; e->Prev = 0; //flag as removed (see ClipperBase.Clear) return result; } //------------------------------------------------------------------------------ inline void ReverseHorizontal(TEdge &e) { //swap horizontal edges' Top and Bottom x's so they follow the natural //progression of the bounds - ie so their xbots will align with the //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] std::swap(e.Top.X, e.Bot.X); #ifdef use_xyz std::swap(e.Top.Z, e.Bot.Z); #endif } //------------------------------------------------------------------------------ void SwapPoints(IntPoint &pt1, IntPoint &pt2) { IntPoint tmp = pt1; pt1 = pt2; pt2 = tmp; } //------------------------------------------------------------------------------ bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) { //precondition: segments are Collinear. if (Abs(pt1a.X - pt1b.X) > Abs(pt1a.Y - pt1b.Y)) { if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; return pt1.X < pt2.X; } else { if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; return pt1.Y > pt2.Y; } } //------------------------------------------------------------------------------ bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) { OutPt *p = btmPt1->Prev; while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Prev; double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); p = btmPt1->Next; while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Next; double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); p = btmPt2->Prev; while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Prev; double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); p = btmPt2->Next; while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Next; double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); } //------------------------------------------------------------------------------ OutPt* GetBottomPt(OutPt *pp) { OutPt* dups = 0; OutPt* p = pp->Next; while (p != pp) { if (p->Pt.Y > pp->Pt.Y) { pp = p; dups = 0; } else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) { if (p->Pt.X < pp->Pt.X) { dups = 0; pp = p; } else { if (p->Next != pp && p->Prev != pp) dups = p; } } p = p->Next; } if (dups) { //there appears to be at least 2 vertices at BottomPt so ... while (dups != p) { if (!FirstIsBottomPt(p, dups)) pp = dups; dups = dups->Next; while (dups->Pt != pp->Pt) dups = dups->Next; } } return pp; } //------------------------------------------------------------------------------ bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3) { if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) return false; else if (pt1.X != pt3.X) return (pt2.X > pt1.X) == (pt2.X < pt3.X); else return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); } //------------------------------------------------------------------------------ bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) { if (seg1a > seg1b) std::swap(seg1a, seg1b); if (seg2a > seg2b) std::swap(seg2a, seg2b); return (seg1a < seg2b) && (seg2a < seg1b); } //------------------------------------------------------------------------------ // ClipperBase class methods ... //------------------------------------------------------------------------------ ClipperBase::ClipperBase() //constructor { m_CurrentLM = m_MinimaList.begin(); //begin() == end() here m_UseFullRange = false; } //------------------------------------------------------------------------------ ClipperBase::~ClipperBase() //destructor { Clear(); } //------------------------------------------------------------------------------ void RangeTest(const IntPoint& Pt, bool& useFullRange) { if (useFullRange) { if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) throw "Coordinate outside allowed range"; } else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) { useFullRange = true; RangeTest(Pt, useFullRange); } } //------------------------------------------------------------------------------ TEdge* FindNextLocMin(TEdge* E) { for (;;) { while (E->Bot != E->Prev->Bot || E->Curr == E->Top) E = E->Next; if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) break; while (IsHorizontal(*E->Prev)) E = E->Prev; TEdge* E2 = E; while (IsHorizontal(*E)) E = E->Next; if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz. if (E2->Prev->Bot.X < E->Bot.X) E = E2; break; } return E; } //------------------------------------------------------------------------------ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) { TEdge *Result = E; TEdge *Horz = 0; if (E->OutIdx == Skip) { //if edges still remain in the current bound beyond the skip edge then //create another LocMin and call ProcessBound once more if (NextIsForward) { while (E->Top.Y == E->Next->Bot.Y) E = E->Next; //don't include top horizontals when parsing a bound a second time, //they will be contained in the opposite bound ... while (E != Result && IsHorizontal(*E)) E = E->Prev; } else { while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev; while (E != Result && IsHorizontal(*E)) E = E->Next; } if (E == Result) { if (NextIsForward) Result = E->Next; else Result = E->Prev; } else { //there are more edges in the bound beyond result starting with E if (NextIsForward) E = Result->Next; else E = Result->Prev; MinimaList::value_type locMin; locMin.Y = E->Bot.Y; locMin.LeftBound = 0; locMin.RightBound = E; E->WindDelta = 0; Result = ProcessBound(E, NextIsForward); m_MinimaList.push_back(locMin); } return Result; } TEdge *EStart; if (IsHorizontal(*E)) { //We need to be careful with open paths because this may not be a //true local minima (ie E may be following a skip edge). //Also, consecutive horz. edges may start heading left before going right. if (NextIsForward) EStart = E->Prev; else EStart = E->Next; if (EStart->OutIdx != Skip) { if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge { if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) ReverseHorizontal(*E); } else if (EStart->Bot.X != E->Bot.X) ReverseHorizontal(*E); } } EStart = E; if (NextIsForward) { while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) Result = Result->Next; if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) { //nb: at the top of a bound, horizontals are added to the bound //only when the preceding edge attaches to the horizontal's left vertex //unless a Skip edge is encountered when that becomes the top divide Horz = Result; while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; if (Horz->Prev->Top.X == Result->Next->Top.X) { if (!NextIsForward) Result = Horz->Prev; } else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; } while (E != Result) { E->NextInLML = E->Next; if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); E = E->Next; } if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); Result = Result->Next; //move to the edge just beyond current bound } else { while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) Result = Result->Prev; if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) { Horz = Result; while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; if (Horz->Next->Top.X == Result->Prev->Top.X) { if (!NextIsForward) Result = Horz->Next; } else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; } while (E != Result) { E->NextInLML = E->Prev; if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) ReverseHorizontal(*E); E = E->Prev; } if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) ReverseHorizontal(*E); Result = Result->Prev; //move to the edge just beyond current bound } return Result; } //------------------------------------------------------------------------------ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) { #ifdef use_lines if (!Closed && PolyTyp == ptClip) throw clipperException("AddPath: Open paths must be subject."); #else if (!Closed) throw clipperException("AddPath: Open paths have been disabled."); #endif int highI = (int)pg.size() -1; if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI; while (highI > 0 && (pg[highI] == pg[highI -1])) --highI; if ((Closed && highI < 2) || (!Closed && highI < 1)) return false; //create a new edge array ... TEdge *edges = new TEdge [highI +1]; bool IsFlat = true; //1. Basic (first) edge initialization ... try { edges[1].Curr = pg[1]; RangeTest(pg[0], m_UseFullRange); RangeTest(pg[highI], m_UseFullRange); InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]); for (int i = highI - 1; i >= 1; --i) { RangeTest(pg[i], m_UseFullRange); InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]); } } catch(...) { delete [] edges; throw; //range test fails } TEdge *eStart = &edges[0]; //2. Remove duplicate vertices, and (when closed) collinear edges ... TEdge *E = eStart, *eLoopStop = eStart; for (;;) { //nb: allows matching start and end points when not Closed ... if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart)) { if (E == E->Next) break; if (E == eStart) eStart = E->Next; E = RemoveEdge(E); eLoopStop = E; continue; } if (E->Prev == E->Next) break; //only two vertices else if (Closed && SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) && (!m_PreserveCollinear || !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) { //Collinear edges are allowed for open paths but in closed paths //the default is to merge adjacent collinear edges into a single edge. //However, if the PreserveCollinear property is enabled, only overlapping //collinear edges (ie spikes) will be removed from closed paths. if (E == eStart) eStart = E->Next; E = RemoveEdge(E); E = E->Prev; eLoopStop = E; continue; } E = E->Next; if ((E == eLoopStop) || (!Closed && E->Next == eStart)) break; } if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) { delete [] edges; return false; } if (!Closed) { m_HasOpenPaths = true; eStart->Prev->OutIdx = Skip; } //3. Do second stage of edge initialization ... E = eStart; do { InitEdge2(*E, PolyTyp); E = E->Next; if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false; } while (E != eStart); //4. Finally, add edge bounds to LocalMinima list ... //Totally flat paths must be handled differently when adding them //to LocalMinima list to avoid endless loops etc ... if (IsFlat) { if (Closed) { delete [] edges; return false; } E->Prev->OutIdx = Skip; if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev); MinimaList::value_type locMin; locMin.Y = E->Bot.Y; locMin.LeftBound = 0; locMin.RightBound = E; locMin.RightBound->Side = esRight; locMin.RightBound->WindDelta = 0; while (E->Next->OutIdx != Skip) { E->NextInLML = E->Next; if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); E = E->Next; } m_MinimaList.push_back(locMin); m_edges.push_back(edges); return true; } m_edges.push_back(edges); bool leftBoundIsForward; TEdge* EMin = 0; //workaround to avoid an endless loop in the while loop below when //open paths have matching start and end points ... if (E->Prev->Bot == E->Prev->Top) E = E->Next; for (;;) { E = FindNextLocMin(E); if (E == EMin) break; else if (!EMin) EMin = E; //E and E.Prev now share a local minima (left aligned if horizontal). //Compare their slopes to find which starts which bound ... MinimaList::value_type locMin; locMin.Y = E->Bot.Y; if (E->Dx < E->Prev->Dx) { locMin.LeftBound = E->Prev; locMin.RightBound = E; leftBoundIsForward = false; //Q.nextInLML = Q.prev } else { locMin.LeftBound = E; locMin.RightBound = E->Prev; leftBoundIsForward = true; //Q.nextInLML = Q.next } locMin.LeftBound->Side = esLeft; locMin.RightBound->Side = esRight; if (!Closed) locMin.LeftBound->WindDelta = 0; else if (locMin.LeftBound->Next == locMin.RightBound) locMin.LeftBound->WindDelta = -1; else locMin.LeftBound->WindDelta = 1; locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta; E = ProcessBound(locMin.LeftBound, leftBoundIsForward); if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward); TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward); if (locMin.LeftBound->OutIdx == Skip) locMin.LeftBound = 0; else if (locMin.RightBound->OutIdx == Skip) locMin.RightBound = 0; m_MinimaList.push_back(locMin); if (!leftBoundIsForward) E = E2; } return true; } //------------------------------------------------------------------------------ bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) { bool result = false; for (Paths::size_type i = 0; i < ppg.size(); ++i) if (AddPath(ppg[i], PolyTyp, Closed)) result = true; return result; } //------------------------------------------------------------------------------ void ClipperBase::Clear() { DisposeLocalMinimaList(); for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) { //for each edge array in turn, find the first used edge and //check for and remove any hiddenPts in each edge in the array. TEdge* edges = m_edges[i]; delete [] edges; } m_edges.clear(); m_UseFullRange = false; m_HasOpenPaths = false; } //------------------------------------------------------------------------------ void ClipperBase::Reset() { m_CurrentLM = m_MinimaList.begin(); if (m_CurrentLM == m_MinimaList.end()) return; //ie nothing to process std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter()); //reset all edges ... for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm) { TEdge* e = lm->LeftBound; if (e) { e->Curr = e->Bot; e->Side = esLeft; e->OutIdx = Unassigned; } e = lm->RightBound; if (e) { e->Curr = e->Bot; e->Side = esRight; e->OutIdx = Unassigned; } } } //------------------------------------------------------------------------------ void ClipperBase::DisposeLocalMinimaList() { m_MinimaList.clear(); m_CurrentLM = m_MinimaList.begin(); } //------------------------------------------------------------------------------ void ClipperBase::PopLocalMinima() { if (m_CurrentLM == m_MinimaList.end()) return; ++m_CurrentLM; } //------------------------------------------------------------------------------ IntRect ClipperBase::GetBounds() { IntRect result; MinimaList::iterator lm = m_MinimaList.begin(); if (lm == m_MinimaList.end()) { result.left = result.top = result.right = result.bottom = 0; return result; } result.left = lm->LeftBound->Bot.X; result.top = lm->LeftBound->Bot.Y; result.right = lm->LeftBound->Bot.X; result.bottom = lm->LeftBound->Bot.Y; while (lm != m_MinimaList.end()) { result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y); TEdge* e = lm->LeftBound; for (;;) { TEdge* bottomE = e; while (e->NextInLML) { if (e->Bot.X < result.left) result.left = e->Bot.X; if (e->Bot.X > result.right) result.right = e->Bot.X; e = e->NextInLML; } result.left = std::min(result.left, e->Bot.X); result.right = std::max(result.right, e->Bot.X); result.left = std::min(result.left, e->Top.X); result.right = std::max(result.right, e->Top.X); result.top = std::min(result.top, e->Top.Y); if (bottomE == lm->LeftBound) e = lm->RightBound; else break; } ++lm; } return result; } //------------------------------------------------------------------------------ // TClipper methods ... //------------------------------------------------------------------------------ Clipper::Clipper(int initOptions) : ClipperBase() //constructor { m_ActiveEdges = 0; m_SortedEdges = 0; m_ExecuteLocked = false; m_UseFullRange = false; m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); m_HasOpenPaths = false; #ifdef use_xyz m_ZFill = 0; #endif } //------------------------------------------------------------------------------ Clipper::~Clipper() //destructor { Clear(); } //------------------------------------------------------------------------------ #ifdef use_xyz void Clipper::ZFillFunction(ZFillCallback zFillFunc) { m_ZFill = zFillFunc; } //------------------------------------------------------------------------------ #endif void Clipper::Reset() { ClipperBase::Reset(); m_Scanbeam = ScanbeamList(); m_ActiveEdges = 0; m_SortedEdges = 0; for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm) InsertScanbeam(lm->Y); } //------------------------------------------------------------------------------ bool Clipper::Execute(ClipType clipType, Paths &solution, PolyFillType subjFillType, PolyFillType clipFillType) { if( m_ExecuteLocked ) return false; if (m_HasOpenPaths) throw clipperException("Error: PolyTree struct is need for open path clipping."); m_ExecuteLocked = true; solution.resize(0); m_SubjFillType = subjFillType; m_ClipFillType = clipFillType; m_ClipType = clipType; m_UsingPolyTree = false; bool succeeded = ExecuteInternal(); if (succeeded) BuildResult(solution); DisposeAllOutRecs(); m_ExecuteLocked = false; return succeeded; } //------------------------------------------------------------------------------ bool Clipper::Execute(ClipType clipType, PolyTree& polytree, PolyFillType subjFillType, PolyFillType clipFillType) { if( m_ExecuteLocked ) return false; m_ExecuteLocked = true; m_SubjFillType = subjFillType; m_ClipFillType = clipFillType; m_ClipType = clipType; m_UsingPolyTree = true; bool succeeded = ExecuteInternal(); if (succeeded) BuildResult2(polytree); DisposeAllOutRecs(); m_ExecuteLocked = false; return succeeded; } //------------------------------------------------------------------------------ void Clipper::FixHoleLinkage(OutRec &outrec) { //skip OutRecs that (a) contain outermost polygons or //(b) already have the correct owner/child linkage ... if (!outrec.FirstLeft || (outrec.IsHole != outrec.FirstLeft->IsHole && outrec.FirstLeft->Pts)) return; OutRec* orfl = outrec.FirstLeft; while (orfl && ((orfl->IsHole == outrec.IsHole) || !orfl->Pts)) orfl = orfl->FirstLeft; outrec.FirstLeft = orfl; } //------------------------------------------------------------------------------ bool Clipper::ExecuteInternal() { bool succeeded = true; try { Reset(); if (m_CurrentLM == m_MinimaList.end()) return true; cInt botY = PopScanbeam(); do { InsertLocalMinimaIntoAEL(botY); ClearGhostJoins(); ProcessHorizontals(false); if (m_Scanbeam.empty()) break; cInt topY = PopScanbeam(); succeeded = ProcessIntersections(topY); if (!succeeded) break; ProcessEdgesAtTopOfScanbeam(topY); botY = topY; } while (!m_Scanbeam.empty() || m_CurrentLM != m_MinimaList.end()); } catch(...) { succeeded = false; } if (succeeded) { //fix orientations ... for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { OutRec *outRec = m_PolyOuts[i]; if (!outRec->Pts || outRec->IsOpen) continue; if ((outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) ReversePolyPtLinks(outRec->Pts); } if (!m_Joins.empty()) JoinCommonEdges(); //unfortunately FixupOutPolygon() must be done after JoinCommonEdges() for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { OutRec *outRec = m_PolyOuts[i]; if (outRec->Pts && !outRec->IsOpen) FixupOutPolygon(*outRec); } if (m_StrictSimple) DoSimplePolygons(); } ClearJoins(); ClearGhostJoins(); return succeeded; } //------------------------------------------------------------------------------ void Clipper::InsertScanbeam(const cInt Y) { //if (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) return;// avoid duplicates. m_Scanbeam.push(Y); } //------------------------------------------------------------------------------ cInt Clipper::PopScanbeam() { const cInt Y = m_Scanbeam.top(); m_Scanbeam.pop(); while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates. return Y; } //------------------------------------------------------------------------------ void Clipper::DisposeAllOutRecs(){ for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) DisposeOutRec(i); m_PolyOuts.clear(); } //------------------------------------------------------------------------------ void Clipper::DisposeOutRec(PolyOutList::size_type index) { OutRec *outRec = m_PolyOuts[index]; if (outRec->Pts) DisposeOutPts(outRec->Pts); delete outRec; m_PolyOuts[index] = 0; } //------------------------------------------------------------------------------ void Clipper::SetWindingCount(TEdge &edge) { TEdge *e = edge.PrevInAEL; //find the edge of the same polytype that immediately preceeds 'edge' in AEL while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) e = e->PrevInAEL; if (!e) { edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); edge.WindCnt2 = 0; e = m_ActiveEdges; //ie get ready to calc WindCnt2 } else if (edge.WindDelta == 0 && m_ClipType != ctUnion) { edge.WindCnt = 1; edge.WindCnt2 = e->WindCnt2; e = e->NextInAEL; //ie get ready to calc WindCnt2 } else if (IsEvenOddFillType(edge)) { //EvenOdd filling ... if (edge.WindDelta == 0) { //are we inside a subj polygon ... bool Inside = true; TEdge *e2 = e->PrevInAEL; while (e2) { if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) Inside = !Inside; e2 = e2->PrevInAEL; } edge.WindCnt = (Inside ? 0 : 1); } else { edge.WindCnt = edge.WindDelta; } edge.WindCnt2 = e->WindCnt2; e = e->NextInAEL; //ie get ready to calc WindCnt2 } else { //nonZero, Positive or Negative filling ... if (e->WindCnt * e->WindDelta < 0) { //prev edge is 'decreasing' WindCount (WC) toward zero //so we're outside the previous polygon ... if (Abs(e->WindCnt) > 1) { //outside prev poly but still inside another. //when reversing direction of prev poly use the same WC if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; //otherwise continue to 'decrease' WC ... else edge.WindCnt = e->WindCnt + edge.WindDelta; } else //now outside all polys of same polytype so set own WC ... edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); } else { //prev edge is 'increasing' WindCount (WC) away from zero //so we're inside the previous polygon ... if (edge.WindDelta == 0) edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); //if wind direction is reversing prev then use same WC else if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; //otherwise add to WC ... else edge.WindCnt = e->WindCnt + edge.WindDelta; } edge.WindCnt2 = e->WindCnt2; e = e->NextInAEL; //ie get ready to calc WindCnt2 } //update WindCnt2 ... if (IsEvenOddAltFillType(edge)) { //EvenOdd filling ... while (e != &edge) { if (e->WindDelta != 0) edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); e = e->NextInAEL; } } else { //nonZero, Positive or Negative filling ... while ( e != &edge ) { edge.WindCnt2 += e->WindDelta; e = e->NextInAEL; } } } //------------------------------------------------------------------------------ bool Clipper::IsEvenOddFillType(const TEdge& edge) const { if (edge.PolyTyp == ptSubject) return m_SubjFillType == pftEvenOdd; else return m_ClipFillType == pftEvenOdd; } //------------------------------------------------------------------------------ bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const { if (edge.PolyTyp == ptSubject) return m_ClipFillType == pftEvenOdd; else return m_SubjFillType == pftEvenOdd; } //------------------------------------------------------------------------------ bool Clipper::IsContributing(const TEdge& edge) const { PolyFillType pft, pft2; if (edge.PolyTyp == ptSubject) { pft = m_SubjFillType; pft2 = m_ClipFillType; } else { pft = m_ClipFillType; pft2 = m_SubjFillType; } switch(pft) { case pftEvenOdd: //return false if a subj line has been flagged as inside a subj polygon if (edge.WindDelta == 0 && edge.WindCnt != 1) return false; break; case pftNonZero: if (Abs(edge.WindCnt) != 1) return false; break; case pftPositive: if (edge.WindCnt != 1) return false; break; default: //pftNegative if (edge.WindCnt != -1) return false; } switch(m_ClipType) { case ctIntersection: switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.WindCnt2 != 0); case pftPositive: return (edge.WindCnt2 > 0); default: return (edge.WindCnt2 < 0); } break; case ctUnion: switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.WindCnt2 == 0); case pftPositive: return (edge.WindCnt2 <= 0); default: return (edge.WindCnt2 >= 0); } break; case ctDifference: if (edge.PolyTyp == ptSubject) switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.WindCnt2 == 0); case pftPositive: return (edge.WindCnt2 <= 0); default: return (edge.WindCnt2 >= 0); } else switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.WindCnt2 != 0); case pftPositive: return (edge.WindCnt2 > 0); default: return (edge.WindCnt2 < 0); } break; case ctXor: if (edge.WindDelta == 0) //XOr always contributing unless open switch(pft2) { case pftEvenOdd: case pftNonZero: return (edge.WindCnt2 == 0); case pftPositive: return (edge.WindCnt2 <= 0); default: return (edge.WindCnt2 >= 0); } else return true; break; default: return true; } } //------------------------------------------------------------------------------ OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) { OutPt* result; TEdge *e, *prevE; if (IsHorizontal(*e2) || ( e1->Dx > e2->Dx )) { result = AddOutPt(e1, Pt); e2->OutIdx = e1->OutIdx; e1->Side = esLeft; e2->Side = esRight; e = e1; if (e->PrevInAEL == e2) prevE = e2->PrevInAEL; else prevE = e->PrevInAEL; } else { result = AddOutPt(e2, Pt); e1->OutIdx = e2->OutIdx; e1->Side = esRight; e2->Side = esLeft; e = e2; if (e->PrevInAEL == e1) prevE = e1->PrevInAEL; else prevE = e->PrevInAEL; } if (prevE && prevE->OutIdx >= 0 && (TopX(*prevE, Pt.Y) == TopX(*e, Pt.Y)) && SlopesEqual(*e, *prevE, m_UseFullRange) && (e->WindDelta != 0) && (prevE->WindDelta != 0)) { OutPt* outPt = AddOutPt(prevE, Pt); AddJoin(result, outPt, e->Top); } return result; } //------------------------------------------------------------------------------ void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) { AddOutPt( e1, Pt ); if (e2->WindDelta == 0) AddOutPt(e2, Pt); if( e1->OutIdx == e2->OutIdx ) { e1->OutIdx = Unassigned; e2->OutIdx = Unassigned; } else if (e1->OutIdx < e2->OutIdx) AppendPolygon(e1, e2); else AppendPolygon(e2, e1); } //------------------------------------------------------------------------------ void Clipper::AddEdgeToSEL(TEdge *edge) { //SEL pointers in PEdge are reused to build a list of horizontal edges. //However, we don't need to worry about order with horizontal edge processing. if( !m_SortedEdges ) { m_SortedEdges = edge; edge->PrevInSEL = 0; edge->NextInSEL = 0; } else { edge->NextInSEL = m_SortedEdges; edge->PrevInSEL = 0; m_SortedEdges->PrevInSEL = edge; m_SortedEdges = edge; } } //------------------------------------------------------------------------------ void Clipper::CopyAELToSEL() { TEdge* e = m_ActiveEdges; m_SortedEdges = e; while ( e ) { e->PrevInSEL = e->PrevInAEL; e->NextInSEL = e->NextInAEL; e = e->NextInAEL; } } //------------------------------------------------------------------------------ void Clipper::AddJoin(OutPt *op1, OutPt *op2, const IntPoint OffPt) { Join* j = new Join; j->OutPt1 = op1; j->OutPt2 = op2; j->OffPt = OffPt; m_Joins.push_back(j); } //------------------------------------------------------------------------------ void Clipper::ClearJoins() { for (JoinList::size_type i = 0; i < m_Joins.size(); i++) delete m_Joins[i]; m_Joins.resize(0); } //------------------------------------------------------------------------------ void Clipper::ClearGhostJoins() { for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++) delete m_GhostJoins[i]; m_GhostJoins.resize(0); } //------------------------------------------------------------------------------ void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt) { Join* j = new Join; j->OutPt1 = op; j->OutPt2 = 0; j->OffPt = OffPt; m_GhostJoins.push_back(j); } //------------------------------------------------------------------------------ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) { while (m_CurrentLM != m_MinimaList.end() && (m_CurrentLM->Y == botY)) { TEdge* lb = m_CurrentLM->LeftBound; TEdge* rb = m_CurrentLM->RightBound; PopLocalMinima(); OutPt *Op1 = 0; if (!lb) { //nb: don't insert LB into either AEL or SEL InsertEdgeIntoAEL(rb, 0); SetWindingCount(*rb); if (IsContributing(*rb)) Op1 = AddOutPt(rb, rb->Bot); } else if (!rb) { InsertEdgeIntoAEL(lb, 0); SetWindingCount(*lb); if (IsContributing(*lb)) Op1 = AddOutPt(lb, lb->Bot); InsertScanbeam(lb->Top.Y); } else { InsertEdgeIntoAEL(lb, 0); InsertEdgeIntoAEL(rb, lb); SetWindingCount( *lb ); rb->WindCnt = lb->WindCnt; rb->WindCnt2 = lb->WindCnt2; if (IsContributing(*lb)) Op1 = AddLocalMinPoly(lb, rb, lb->Bot); InsertScanbeam(lb->Top.Y); } if (rb) { if(IsHorizontal(*rb)) AddEdgeToSEL(rb); else InsertScanbeam( rb->Top.Y ); } if (!lb || !rb) continue; //if any output polygons share an edge, they'll need joining later ... if (Op1 && IsHorizontal(*rb) && m_GhostJoins.size() > 0 && (rb->WindDelta != 0)) { for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i) { Join* jr = m_GhostJoins[i]; //if the horizontal Rb and a 'ghost' horizontal overlap, then convert //the 'ghost' join to a real join ready for later ... if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, rb->Top.X)) AddJoin(jr->OutPt1, Op1, jr->OffPt); } } if (lb->OutIdx >= 0 && lb->PrevInAEL && lb->PrevInAEL->Curr.X == lb->Bot.X && lb->PrevInAEL->OutIdx >= 0 && SlopesEqual(*lb->PrevInAEL, *lb, m_UseFullRange) && (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) { OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); AddJoin(Op1, Op2, lb->Top); } if(lb->NextInAEL != rb) { if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 && SlopesEqual(*rb->PrevInAEL, *rb, m_UseFullRange) && (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0)) { OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); AddJoin(Op1, Op2, rb->Top); } TEdge* e = lb->NextInAEL; if (e) { while( e != rb ) { //nb: For calculating winding counts etc, IntersectEdges() assumes //that param1 will be to the Right of param2 ABOVE the intersection ... IntersectEdges(rb , e , lb->Curr); //order important here e = e->NextInAEL; } } } } } //------------------------------------------------------------------------------ void Clipper::DeleteFromAEL(TEdge *e) { TEdge* AelPrev = e->PrevInAEL; TEdge* AelNext = e->NextInAEL; if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted if( AelPrev ) AelPrev->NextInAEL = AelNext; else m_ActiveEdges = AelNext; if( AelNext ) AelNext->PrevInAEL = AelPrev; e->NextInAEL = 0; e->PrevInAEL = 0; } //------------------------------------------------------------------------------ void Clipper::DeleteFromSEL(TEdge *e) { TEdge* SelPrev = e->PrevInSEL; TEdge* SelNext = e->NextInSEL; if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted if( SelPrev ) SelPrev->NextInSEL = SelNext; else m_SortedEdges = SelNext; if( SelNext ) SelNext->PrevInSEL = SelPrev; e->NextInSEL = 0; e->PrevInSEL = 0; } //------------------------------------------------------------------------------ #ifdef use_xyz void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2) { if (pt.Z != 0 || !m_ZFill) return; else if (pt == e1.Bot) pt.Z = e1.Bot.Z; else if (pt == e1.Top) pt.Z = e1.Top.Z; else if (pt == e2.Bot) pt.Z = e2.Bot.Z; else if (pt == e2.Top) pt.Z = e2.Top.Z; else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt); } //------------------------------------------------------------------------------ #endif void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt) { bool e1Contributing = ( e1->OutIdx >= 0 ); bool e2Contributing = ( e2->OutIdx >= 0 ); #ifdef use_xyz SetZ(Pt, *e1, *e2); #endif #ifdef use_lines //if either edge is on an OPEN path ... if (e1->WindDelta == 0 || e2->WindDelta == 0) { //ignore subject-subject open path intersections UNLESS they //are both open paths, AND they are both 'contributing maximas' ... if (e1->WindDelta == 0 && e2->WindDelta == 0) return; //if intersecting a subj line with a subj poly ... else if (e1->PolyTyp == e2->PolyTyp && e1->WindDelta != e2->WindDelta && m_ClipType == ctUnion) { if (e1->WindDelta == 0) { if (e2Contributing) { AddOutPt(e1, Pt); if (e1Contributing) e1->OutIdx = Unassigned; } } else { if (e1Contributing) { AddOutPt(e2, Pt); if (e2Contributing) e2->OutIdx = Unassigned; } } } else if (e1->PolyTyp != e2->PolyTyp) { //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 && (m_ClipType != ctUnion || e2->WindCnt2 == 0)) { AddOutPt(e1, Pt); if (e1Contributing) e1->OutIdx = Unassigned; } else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) && (m_ClipType != ctUnion || e1->WindCnt2 == 0)) { AddOutPt(e2, Pt); if (e2Contributing) e2->OutIdx = Unassigned; } } return; } #endif //update winding counts... //assumes that e1 will be to the Right of e2 ABOVE the intersection if ( e1->PolyTyp == e2->PolyTyp ) { if ( IsEvenOddFillType( *e1) ) { int oldE1WindCnt = e1->WindCnt; e1->WindCnt = e2->WindCnt; e2->WindCnt = oldE1WindCnt; } else { if (e1->WindCnt + e2->WindDelta == 0 ) e1->WindCnt = -e1->WindCnt; else e1->WindCnt += e2->WindDelta; if ( e2->WindCnt - e1->WindDelta == 0 ) e2->WindCnt = -e2->WindCnt; else e2->WindCnt -= e1->WindDelta; } } else { if (!IsEvenOddFillType(*e2)) e1->WindCnt2 += e2->WindDelta; else e1->WindCnt2 = ( e1->WindCnt2 == 0 ) ? 1 : 0; if (!IsEvenOddFillType(*e1)) e2->WindCnt2 -= e1->WindDelta; else e2->WindCnt2 = ( e2->WindCnt2 == 0 ) ? 1 : 0; } PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; if (e1->PolyTyp == ptSubject) { e1FillType = m_SubjFillType; e1FillType2 = m_ClipFillType; } else { e1FillType = m_ClipFillType; e1FillType2 = m_SubjFillType; } if (e2->PolyTyp == ptSubject) { e2FillType = m_SubjFillType; e2FillType2 = m_ClipFillType; } else { e2FillType = m_ClipFillType; e2FillType2 = m_SubjFillType; } cInt e1Wc, e2Wc; switch (e1FillType) { case pftPositive: e1Wc = e1->WindCnt; break; case pftNegative: e1Wc = -e1->WindCnt; break; default: e1Wc = Abs(e1->WindCnt); } switch(e2FillType) { case pftPositive: e2Wc = e2->WindCnt; break; case pftNegative: e2Wc = -e2->WindCnt; break; default: e2Wc = Abs(e2->WindCnt); } if ( e1Contributing && e2Contributing ) { if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) ) { AddLocalMaxPoly(e1, e2, Pt); } else { AddOutPt(e1, Pt); AddOutPt(e2, Pt); SwapSides( *e1 , *e2 ); SwapPolyIndexes( *e1 , *e2 ); } } else if ( e1Contributing ) { if (e2Wc == 0 || e2Wc == 1) { AddOutPt(e1, Pt); SwapSides(*e1, *e2); SwapPolyIndexes(*e1, *e2); } } else if ( e2Contributing ) { if (e1Wc == 0 || e1Wc == 1) { AddOutPt(e2, Pt); SwapSides(*e1, *e2); SwapPolyIndexes(*e1, *e2); } } else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) { //neither edge is currently contributing ... cInt e1Wc2, e2Wc2; switch (e1FillType2) { case pftPositive: e1Wc2 = e1->WindCnt2; break; case pftNegative : e1Wc2 = -e1->WindCnt2; break; default: e1Wc2 = Abs(e1->WindCnt2); } switch (e2FillType2) { case pftPositive: e2Wc2 = e2->WindCnt2; break; case pftNegative: e2Wc2 = -e2->WindCnt2; break; default: e2Wc2 = Abs(e2->WindCnt2); } if (e1->PolyTyp != e2->PolyTyp) { AddLocalMinPoly(e1, e2, Pt); } else if (e1Wc == 1 && e2Wc == 1) switch( m_ClipType ) { case ctIntersection: if (e1Wc2 > 0 && e2Wc2 > 0) AddLocalMinPoly(e1, e2, Pt); break; case ctUnion: if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) AddLocalMinPoly(e1, e2, Pt); break; case ctDifference: if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) AddLocalMinPoly(e1, e2, Pt); break; case ctXor: AddLocalMinPoly(e1, e2, Pt); } else SwapSides( *e1, *e2 ); } } //------------------------------------------------------------------------------ void Clipper::SetHoleState(TEdge *e, OutRec *outrec) { bool IsHole = false; TEdge *e2 = e->PrevInAEL; while (e2) { if (e2->OutIdx >= 0 && e2->WindDelta != 0) { IsHole = !IsHole; if (! outrec->FirstLeft) outrec->FirstLeft = m_PolyOuts[e2->OutIdx]; } e2 = e2->PrevInAEL; } if (IsHole) outrec->IsHole = true; } //------------------------------------------------------------------------------ OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) { //work out which polygon fragment has the correct hole state ... if (!outRec1->BottomPt) outRec1->BottomPt = GetBottomPt(outRec1->Pts); if (!outRec2->BottomPt) outRec2->BottomPt = GetBottomPt(outRec2->Pts); OutPt *OutPt1 = outRec1->BottomPt; OutPt *OutPt2 = outRec2->BottomPt; if (OutPt1->Pt.Y > OutPt2->Pt.Y) return outRec1; else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2; else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1; else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2; else if (OutPt1->Next == OutPt1) return outRec2; else if (OutPt2->Next == OutPt2) return outRec1; else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1; else return outRec2; } //------------------------------------------------------------------------------ bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) { do { outRec1 = outRec1->FirstLeft; if (outRec1 == outRec2) return true; } while (outRec1); return false; } //------------------------------------------------------------------------------ OutRec* Clipper::GetOutRec(int Idx) { OutRec* outrec = m_PolyOuts[Idx]; while (outrec != m_PolyOuts[outrec->Idx]) outrec = m_PolyOuts[outrec->Idx]; return outrec; } //------------------------------------------------------------------------------ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) { //get the start and ends of both output polygons ... OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; OutRec *holeStateRec; if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; else holeStateRec = GetLowermostRec(outRec1, outRec2); //get the start and ends of both output polygons and //join e2 poly onto e1 poly and delete pointers to e2 ... OutPt* p1_lft = outRec1->Pts; OutPt* p1_rt = p1_lft->Prev; OutPt* p2_lft = outRec2->Pts; OutPt* p2_rt = p2_lft->Prev; EdgeSide Side; //join e2 poly onto e1 poly and delete pointers to e2 ... if( e1->Side == esLeft ) { if( e2->Side == esLeft ) { //z y x a b c ReversePolyPtLinks(p2_lft); p2_lft->Next = p1_lft; p1_lft->Prev = p2_lft; p1_rt->Next = p2_rt; p2_rt->Prev = p1_rt; outRec1->Pts = p2_rt; } else { //x y z a b c p2_rt->Next = p1_lft; p1_lft->Prev = p2_rt; p2_lft->Prev = p1_rt; p1_rt->Next = p2_lft; outRec1->Pts = p2_lft; } Side = esLeft; } else { if( e2->Side == esRight ) { //a b c z y x ReversePolyPtLinks(p2_lft); p1_rt->Next = p2_rt; p2_rt->Prev = p1_rt; p2_lft->Next = p1_lft; p1_lft->Prev = p2_lft; } else { //a b c x y z p1_rt->Next = p2_lft; p2_lft->Prev = p1_rt; p1_lft->Prev = p2_rt; p2_rt->Next = p1_lft; } Side = esRight; } outRec1->BottomPt = 0; if (holeStateRec == outRec2) { if (outRec2->FirstLeft != outRec1) outRec1->FirstLeft = outRec2->FirstLeft; outRec1->IsHole = outRec2->IsHole; } outRec2->Pts = 0; outRec2->BottomPt = 0; outRec2->FirstLeft = outRec1; int OKIdx = e1->OutIdx; int ObsoleteIdx = e2->OutIdx; e1->OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly e2->OutIdx = Unassigned; TEdge* e = m_ActiveEdges; while( e ) { if( e->OutIdx == ObsoleteIdx ) { e->OutIdx = OKIdx; e->Side = Side; break; } e = e->NextInAEL; } outRec2->Idx = outRec1->Idx; } //------------------------------------------------------------------------------ OutRec* Clipper::CreateOutRec() { OutRec* result = new OutRec; result->IsHole = false; result->IsOpen = false; result->FirstLeft = 0; result->Pts = 0; result->BottomPt = 0; result->PolyNd = 0; m_PolyOuts.push_back(result); result->Idx = (int)m_PolyOuts.size()-1; return result; } //------------------------------------------------------------------------------ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) { bool ToFront = (e->Side == esLeft); if( e->OutIdx < 0 ) { OutRec *outRec = CreateOutRec(); outRec->IsOpen = (e->WindDelta == 0); OutPt* newOp = new OutPt; outRec->Pts = newOp; newOp->Idx = outRec->Idx; newOp->Pt = pt; newOp->Next = newOp; newOp->Prev = newOp; if (!outRec->IsOpen) SetHoleState(e, outRec); e->OutIdx = outRec->Idx; return newOp; } else { OutRec *outRec = m_PolyOuts[e->OutIdx]; //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' OutPt* op = outRec->Pts; if (ToFront && (pt == op->Pt)) return op; else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev; OutPt* newOp = new OutPt; newOp->Idx = outRec->Idx; newOp->Pt = pt; newOp->Next = op; newOp->Prev = op->Prev; newOp->Prev->Next = newOp; op->Prev = newOp; if (ToFront) outRec->Pts = newOp; return newOp; } } //------------------------------------------------------------------------------ void Clipper::ProcessHorizontals(bool IsTopOfScanbeam) { TEdge* horzEdge = m_SortedEdges; while(horzEdge) { DeleteFromSEL(horzEdge); ProcessHorizontal(horzEdge, IsTopOfScanbeam); horzEdge = m_SortedEdges; } } //------------------------------------------------------------------------------ inline bool IsMinima(TEdge *e) { return e && (e->Prev->NextInLML != e) && (e->Next->NextInLML != e); } //------------------------------------------------------------------------------ inline bool IsMaxima(TEdge *e, const cInt Y) { return e && e->Top.Y == Y && !e->NextInLML; } //------------------------------------------------------------------------------ inline bool IsIntermediate(TEdge *e, const cInt Y) { return e->Top.Y == Y && e->NextInLML; } //------------------------------------------------------------------------------ TEdge *GetMaximaPair(TEdge *e) { TEdge* result = 0; if ((e->Next->Top == e->Top) && !e->Next->NextInLML) result = e->Next; else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) result = e->Prev; if (result && (result->OutIdx == Skip || //result is false if both NextInAEL & PrevInAEL are nil & not horizontal ... (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) return 0; return result; } //------------------------------------------------------------------------------ void Clipper::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) { //check that one or other edge hasn't already been removed from AEL ... if (Edge1->NextInAEL == Edge1->PrevInAEL || Edge2->NextInAEL == Edge2->PrevInAEL) return; if( Edge1->NextInAEL == Edge2 ) { TEdge* Next = Edge2->NextInAEL; if( Next ) Next->PrevInAEL = Edge1; TEdge* Prev = Edge1->PrevInAEL; if( Prev ) Prev->NextInAEL = Edge2; Edge2->PrevInAEL = Prev; Edge2->NextInAEL = Edge1; Edge1->PrevInAEL = Edge2; Edge1->NextInAEL = Next; } else if( Edge2->NextInAEL == Edge1 ) { TEdge* Next = Edge1->NextInAEL; if( Next ) Next->PrevInAEL = Edge2; TEdge* Prev = Edge2->PrevInAEL; if( Prev ) Prev->NextInAEL = Edge1; Edge1->PrevInAEL = Prev; Edge1->NextInAEL = Edge2; Edge2->PrevInAEL = Edge1; Edge2->NextInAEL = Next; } else { TEdge* Next = Edge1->NextInAEL; TEdge* Prev = Edge1->PrevInAEL; Edge1->NextInAEL = Edge2->NextInAEL; if( Edge1->NextInAEL ) Edge1->NextInAEL->PrevInAEL = Edge1; Edge1->PrevInAEL = Edge2->PrevInAEL; if( Edge1->PrevInAEL ) Edge1->PrevInAEL->NextInAEL = Edge1; Edge2->NextInAEL = Next; if( Edge2->NextInAEL ) Edge2->NextInAEL->PrevInAEL = Edge2; Edge2->PrevInAEL = Prev; if( Edge2->PrevInAEL ) Edge2->PrevInAEL->NextInAEL = Edge2; } if( !Edge1->PrevInAEL ) m_ActiveEdges = Edge1; else if( !Edge2->PrevInAEL ) m_ActiveEdges = Edge2; } //------------------------------------------------------------------------------ void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2) { if( !( Edge1->NextInSEL ) && !( Edge1->PrevInSEL ) ) return; if( !( Edge2->NextInSEL ) && !( Edge2->PrevInSEL ) ) return; if( Edge1->NextInSEL == Edge2 ) { TEdge* Next = Edge2->NextInSEL; if( Next ) Next->PrevInSEL = Edge1; TEdge* Prev = Edge1->PrevInSEL; if( Prev ) Prev->NextInSEL = Edge2; Edge2->PrevInSEL = Prev; Edge2->NextInSEL = Edge1; Edge1->PrevInSEL = Edge2; Edge1->NextInSEL = Next; } else if( Edge2->NextInSEL == Edge1 ) { TEdge* Next = Edge1->NextInSEL; if( Next ) Next->PrevInSEL = Edge2; TEdge* Prev = Edge2->PrevInSEL; if( Prev ) Prev->NextInSEL = Edge1; Edge1->PrevInSEL = Prev; Edge1->NextInSEL = Edge2; Edge2->PrevInSEL = Edge1; Edge2->NextInSEL = Next; } else { TEdge* Next = Edge1->NextInSEL; TEdge* Prev = Edge1->PrevInSEL; Edge1->NextInSEL = Edge2->NextInSEL; if( Edge1->NextInSEL ) Edge1->NextInSEL->PrevInSEL = Edge1; Edge1->PrevInSEL = Edge2->PrevInSEL; if( Edge1->PrevInSEL ) Edge1->PrevInSEL->NextInSEL = Edge1; Edge2->NextInSEL = Next; if( Edge2->NextInSEL ) Edge2->NextInSEL->PrevInSEL = Edge2; Edge2->PrevInSEL = Prev; if( Edge2->PrevInSEL ) Edge2->PrevInSEL->NextInSEL = Edge2; } if( !Edge1->PrevInSEL ) m_SortedEdges = Edge1; else if( !Edge2->PrevInSEL ) m_SortedEdges = Edge2; } //------------------------------------------------------------------------------ TEdge* GetNextInAEL(TEdge *e, Direction dir) { return dir == dLeftToRight ? e->NextInAEL : e->PrevInAEL; } //------------------------------------------------------------------------------ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) { if (HorzEdge.Bot.X < HorzEdge.Top.X) { Left = HorzEdge.Bot.X; Right = HorzEdge.Top.X; Dir = dLeftToRight; } else { Left = HorzEdge.Top.X; Right = HorzEdge.Bot.X; Dir = dRightToLeft; } } //------------------------------------------------------------------------ /******************************************************************************* * Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * * Bottom of a scanbeam) are processed as if layered. The order in which HEs * * are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * * (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * * and with other non-horizontal edges [*]. Once these intersections are * * processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * * the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * *******************************************************************************/ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam) { Direction dir; cInt horzLeft, horzRight; GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); TEdge* eLastHorz = horzEdge, *eMaxPair = 0; while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) eLastHorz = eLastHorz->NextInLML; if (!eLastHorz->NextInLML) eMaxPair = GetMaximaPair(eLastHorz); for (;;) { bool IsLastHorz = (horzEdge == eLastHorz); TEdge* e = GetNextInAEL(horzEdge, dir); while(e) { //Break if we've got to the end of an intermediate horizontal edge ... //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML && e->Dx < horzEdge->NextInLML->Dx) break; TEdge* eNext = GetNextInAEL(e, dir); //saves eNext for later if ((dir == dLeftToRight && e->Curr.X <= horzRight) || (dir == dRightToLeft && e->Curr.X >= horzLeft)) { //so far we're still in range of the horizontal Edge but make sure //we're at the last of consec. horizontals when matching with eMaxPair if(e == eMaxPair && IsLastHorz) { if (horzEdge->OutIdx >= 0) { OutPt* op1 = AddOutPt(horzEdge, horzEdge->Top); TEdge* eNextHorz = m_SortedEdges; while (eNextHorz) { if (eNextHorz->OutIdx >= 0 && HorzSegmentsOverlap(horzEdge->Bot.X, horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) { OutPt* op2 = AddOutPt(eNextHorz, eNextHorz->Bot); AddJoin(op2, op1, eNextHorz->Top); } eNextHorz = eNextHorz->NextInSEL; } AddGhostJoin(op1, horzEdge->Bot); AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top); } DeleteFromAEL(horzEdge); DeleteFromAEL(eMaxPair); return; } else if(dir == dLeftToRight) { IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); IntersectEdges(horzEdge, e, Pt); } else { IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); IntersectEdges( e, horzEdge, Pt); } SwapPositionsInAEL( horzEdge, e ); } else if( (dir == dLeftToRight && e->Curr.X >= horzRight) || (dir == dRightToLeft && e->Curr.X <= horzLeft) ) break; e = eNext; } //end while if (horzEdge->NextInLML && IsHorizontal(*horzEdge->NextInLML)) { UpdateEdgeIntoAEL(horzEdge); if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot); GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); } else break; } //end for (;;) if(horzEdge->NextInLML) { if(horzEdge->OutIdx >= 0) { OutPt* op1 = AddOutPt( horzEdge, horzEdge->Top); if (isTopOfScanbeam) AddGhostJoin(op1, horzEdge->Bot); UpdateEdgeIntoAEL(horzEdge); if (horzEdge->WindDelta == 0) return; //nb: HorzEdge is no longer horizontal here TEdge* ePrev = horzEdge->PrevInAEL; TEdge* eNext = horzEdge->NextInAEL; if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 && (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) { OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot); AddJoin(op1, op2, horzEdge->Top); } else if (eNext && eNext->Curr.X == horzEdge->Bot.X && eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 && eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) { OutPt* op2 = AddOutPt(eNext, horzEdge->Bot); AddJoin(op1, op2, horzEdge->Top); } } else UpdateEdgeIntoAEL(horzEdge); } else { if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top); DeleteFromAEL(horzEdge); } } //------------------------------------------------------------------------------ void Clipper::UpdateEdgeIntoAEL(TEdge *&e) { if( !e->NextInLML ) throw clipperException("UpdateEdgeIntoAEL: invalid call"); e->NextInLML->OutIdx = e->OutIdx; TEdge* AelPrev = e->PrevInAEL; TEdge* AelNext = e->NextInAEL; if (AelPrev) AelPrev->NextInAEL = e->NextInLML; else m_ActiveEdges = e->NextInLML; if (AelNext) AelNext->PrevInAEL = e->NextInLML; e->NextInLML->Side = e->Side; e->NextInLML->WindDelta = e->WindDelta; e->NextInLML->WindCnt = e->WindCnt; e->NextInLML->WindCnt2 = e->WindCnt2; e = e->NextInLML; e->Curr = e->Bot; e->PrevInAEL = AelPrev; e->NextInAEL = AelNext; if (!IsHorizontal(*e)) InsertScanbeam(e->Top.Y); } //------------------------------------------------------------------------------ bool Clipper::ProcessIntersections(const cInt topY) { if( !m_ActiveEdges ) return true; try { BuildIntersectList(topY); size_t IlSize = m_IntersectList.size(); if (IlSize == 0) return true; if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList(); else return false; } catch(...) { m_SortedEdges = 0; DisposeIntersectNodes(); throw clipperException("ProcessIntersections error"); } m_SortedEdges = 0; return true; } //------------------------------------------------------------------------------ void Clipper::DisposeIntersectNodes() { for (size_t i = 0; i < m_IntersectList.size(); ++i ) delete m_IntersectList[i]; m_IntersectList.clear(); } //------------------------------------------------------------------------------ void Clipper::BuildIntersectList(const cInt topY) { if ( !m_ActiveEdges ) return; //prepare for sorting ... TEdge* e = m_ActiveEdges; m_SortedEdges = e; while( e ) { e->PrevInSEL = e->PrevInAEL; e->NextInSEL = e->NextInAEL; e->Curr.X = TopX( *e, topY ); e = e->NextInAEL; } //bubblesort ... bool isModified; do { isModified = false; e = m_SortedEdges; while( e->NextInSEL ) { TEdge *eNext = e->NextInSEL; IntPoint Pt; if(e->Curr.X > eNext->Curr.X) { IntersectPoint(*e, *eNext, Pt); IntersectNode * newNode = new IntersectNode; newNode->Edge1 = e; newNode->Edge2 = eNext; newNode->Pt = Pt; m_IntersectList.push_back(newNode); SwapPositionsInSEL(e, eNext); isModified = true; } else e = eNext; } if( e->PrevInSEL ) e->PrevInSEL->NextInSEL = 0; else break; } while ( isModified ); m_SortedEdges = 0; //important } //------------------------------------------------------------------------------ void Clipper::ProcessIntersectList() { for (size_t i = 0; i < m_IntersectList.size(); ++i) { IntersectNode* iNode = m_IntersectList[i]; { IntersectEdges( iNode->Edge1, iNode->Edge2, iNode->Pt); SwapPositionsInAEL( iNode->Edge1 , iNode->Edge2 ); } delete iNode; } m_IntersectList.clear(); } //------------------------------------------------------------------------------ bool IntersectListSort(IntersectNode* node1, IntersectNode* node2) { return node2->Pt.Y < node1->Pt.Y; } //------------------------------------------------------------------------------ inline bool EdgesAdjacent(const IntersectNode &inode) { return (inode.Edge1->NextInSEL == inode.Edge2) || (inode.Edge1->PrevInSEL == inode.Edge2); } //------------------------------------------------------------------------------ bool Clipper::FixupIntersectionOrder() { //pre-condition: intersections are sorted Bottom-most first. //Now it's crucial that intersections are made only between adjacent edges, //so to ensure this the order of intersections may need adjusting ... CopyAELToSEL(); std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort); size_t cnt = m_IntersectList.size(); for (size_t i = 0; i < cnt; ++i) { if (!EdgesAdjacent(*m_IntersectList[i])) { size_t j = i + 1; while (j < cnt && !EdgesAdjacent(*m_IntersectList[j])) j++; if (j == cnt) return false; std::swap(m_IntersectList[i], m_IntersectList[j]); } SwapPositionsInSEL(m_IntersectList[i]->Edge1, m_IntersectList[i]->Edge2); } return true; } //------------------------------------------------------------------------------ void Clipper::DoMaxima(TEdge *e) { TEdge* eMaxPair = GetMaximaPair(e); if (!eMaxPair) { if (e->OutIdx >= 0) AddOutPt(e, e->Top); DeleteFromAEL(e); return; } TEdge* eNext = e->NextInAEL; while(eNext && eNext != eMaxPair) { IntersectEdges(e, eNext, e->Top); SwapPositionsInAEL(e, eNext); eNext = e->NextInAEL; } if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) { DeleteFromAEL(e); DeleteFromAEL(eMaxPair); } else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 ) { if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top); DeleteFromAEL(e); DeleteFromAEL(eMaxPair); } #ifdef use_lines else if (e->WindDelta == 0) { if (e->OutIdx >= 0) { AddOutPt(e, e->Top); e->OutIdx = Unassigned; } DeleteFromAEL(e); if (eMaxPair->OutIdx >= 0) { AddOutPt(eMaxPair, e->Top); eMaxPair->OutIdx = Unassigned; } DeleteFromAEL(eMaxPair); } #endif else throw clipperException("DoMaxima error"); } //------------------------------------------------------------------------------ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) { TEdge* e = m_ActiveEdges; while( e ) { //1. process maxima, treating them as if they're 'bent' horizontal edges, // but exclude maxima with horizontal edges. nb: e can't be a horizontal. bool IsMaximaEdge = IsMaxima(e, topY); if(IsMaximaEdge) { TEdge* eMaxPair = GetMaximaPair(e); IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); } if(IsMaximaEdge) { TEdge* ePrev = e->PrevInAEL; DoMaxima(e); if( !ePrev ) e = m_ActiveEdges; else e = ePrev->NextInAEL; } else { //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) { UpdateEdgeIntoAEL(e); if (e->OutIdx >= 0) AddOutPt(e, e->Bot); AddEdgeToSEL(e); } else { e->Curr.X = TopX( *e, topY ); e->Curr.Y = topY; } if (m_StrictSimple) { TEdge* ePrev = e->PrevInAEL; if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) && (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) { IntPoint pt = e->Curr; #ifdef use_xyz SetZ(pt, *ePrev, *e); #endif OutPt* op = AddOutPt(ePrev, pt); OutPt* op2 = AddOutPt(e, pt); AddJoin(op, op2, pt); //StrictlySimple (type-3) join } } e = e->NextInAEL; } } //3. Process horizontals at the Top of the scanbeam ... ProcessHorizontals(true); //4. Promote intermediate vertices ... e = m_ActiveEdges; while(e) { if(IsIntermediate(e, topY)) { OutPt* op = 0; if( e->OutIdx >= 0 ) op = AddOutPt(e, e->Top); UpdateEdgeIntoAEL(e); //if output polygons share an edge, they'll need joining later ... TEdge* ePrev = e->PrevInAEL; TEdge* eNext = e->NextInAEL; if (ePrev && ePrev->Curr.X == e->Bot.X && ePrev->Curr.Y == e->Bot.Y && op && ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && SlopesEqual(*e, *ePrev, m_UseFullRange) && (e->WindDelta != 0) && (ePrev->WindDelta != 0)) { OutPt* op2 = AddOutPt(ePrev, e->Bot); AddJoin(op, op2, e->Top); } else if (eNext && eNext->Curr.X == e->Bot.X && eNext->Curr.Y == e->Bot.Y && op && eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && SlopesEqual(*e, *eNext, m_UseFullRange) && (e->WindDelta != 0) && (eNext->WindDelta != 0)) { OutPt* op2 = AddOutPt(eNext, e->Bot); AddJoin(op, op2, e->Top); } } e = e->NextInAEL; } } //------------------------------------------------------------------------------ void Clipper::FixupOutPolygon(OutRec &outrec) { //FixupOutPolygon() - removes duplicate points and simplifies consecutive //parallel edges by removing the middle vertex. OutPt *lastOK = 0; outrec.BottomPt = 0; OutPt *pp = outrec.Pts; for (;;) { if (pp->Prev == pp || pp->Prev == pp->Next ) { DisposeOutPts(pp); outrec.Pts = 0; return; } //test for duplicate points and collinear edges ... if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) || (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) && (!m_PreserveCollinear || !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) { lastOK = 0; OutPt *tmp = pp; pp->Prev->Next = pp->Next; pp->Next->Prev = pp->Prev; pp = pp->Prev; delete tmp; } else if (pp == lastOK) break; else { if (!lastOK) lastOK = pp; pp = pp->Next; } } outrec.Pts = pp; } //------------------------------------------------------------------------------ int PointCount(OutPt *Pts) { if (!Pts) return 0; int result = 0; OutPt* p = Pts; do { result++; p = p->Next; } while (p != Pts); return result; } //------------------------------------------------------------------------------ void Clipper::BuildResult(Paths &polys) { polys.reserve(m_PolyOuts.size()); for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { if (!m_PolyOuts[i]->Pts) continue; Path pg; OutPt* p = m_PolyOuts[i]->Pts->Prev; int cnt = PointCount(p); if (cnt < 2) continue; pg.reserve(cnt); for (int i = 0; i < cnt; ++i) { pg.push_back(p->Pt); p = p->Prev; } polys.push_back(pg); } } //------------------------------------------------------------------------------ void Clipper::BuildResult2(PolyTree& polytree) { polytree.Clear(); polytree.AllNodes.reserve(m_PolyOuts.size()); //add each output polygon/contour to polytree ... for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) { OutRec* outRec = m_PolyOuts[i]; int cnt = PointCount(outRec->Pts); if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) continue; FixHoleLinkage(*outRec); PolyNode* pn = new PolyNode(); //nb: polytree takes ownership of all the PolyNodes polytree.AllNodes.push_back(pn); outRec->PolyNd = pn; pn->Parent = 0; pn->Index = 0; pn->Contour.reserve(cnt); OutPt *op = outRec->Pts->Prev; for (int j = 0; j < cnt; j++) { pn->Contour.push_back(op->Pt); op = op->Prev; } } //fixup PolyNode links etc ... polytree.Childs.reserve(m_PolyOuts.size()); for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) { OutRec* outRec = m_PolyOuts[i]; if (!outRec->PolyNd) continue; if (outRec->IsOpen) { outRec->PolyNd->m_IsOpen = true; polytree.AddChild(*outRec->PolyNd); } else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); else polytree.AddChild(*outRec->PolyNd); } } //------------------------------------------------------------------------------ void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) { //just swap the contents (because fIntersectNodes is a single-linked-list) IntersectNode inode = int1; //gets a copy of Int1 int1.Edge1 = int2.Edge1; int1.Edge2 = int2.Edge2; int1.Pt = int2.Pt; int2.Edge1 = inode.Edge1; int2.Edge2 = inode.Edge2; int2.Pt = inode.Pt; } //------------------------------------------------------------------------------ inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) { if (e2.Curr.X == e1.Curr.X) { if (e2.Top.Y > e1.Top.Y) return e2.Top.X < TopX(e1, e2.Top.Y); else return e1.Top.X > TopX(e2, e1.Top.Y); } else return e2.Curr.X < e1.Curr.X; } //------------------------------------------------------------------------------ bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, cInt& Left, cInt& Right) { if (a1 < a2) { if (b1 < b2) {Left = std::max(a1,b1); Right = std::min(a2,b2);} else {Left = std::max(a1,b2); Right = std::min(a2,b1);} } else { if (b1 < b2) {Left = std::max(a2,b1); Right = std::min(a1,b2);} else {Left = std::max(a2,b2); Right = std::min(a1,b1);} } return Left < Right; } //------------------------------------------------------------------------------ inline void UpdateOutPtIdxs(OutRec& outrec) { OutPt* op = outrec.Pts; do { op->Idx = outrec.Idx; op = op->Prev; } while(op != outrec.Pts); } //------------------------------------------------------------------------------ void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge) { if(!m_ActiveEdges) { edge->PrevInAEL = 0; edge->NextInAEL = 0; m_ActiveEdges = edge; } else if(!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) { edge->PrevInAEL = 0; edge->NextInAEL = m_ActiveEdges; m_ActiveEdges->PrevInAEL = edge; m_ActiveEdges = edge; } else { if(!startEdge) startEdge = m_ActiveEdges; while(startEdge->NextInAEL && !E2InsertsBeforeE1(*startEdge->NextInAEL , *edge)) startEdge = startEdge->NextInAEL; edge->NextInAEL = startEdge->NextInAEL; if(startEdge->NextInAEL) startEdge->NextInAEL->PrevInAEL = edge; edge->PrevInAEL = startEdge; startEdge->NextInAEL = edge; } } //---------------------------------------------------------------------- OutPt* DupOutPt(OutPt* outPt, bool InsertAfter) { OutPt* result = new OutPt; result->Pt = outPt->Pt; result->Idx = outPt->Idx; if (InsertAfter) { result->Next = outPt->Next; result->Prev = outPt; outPt->Next->Prev = result; outPt->Next = result; } else { result->Prev = outPt->Prev; result->Next = outPt; outPt->Prev->Next = result; outPt->Prev = result; } return result; } //------------------------------------------------------------------------------ bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, const IntPoint Pt, bool DiscardLeft) { Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); if (Dir1 == Dir2) return false; //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we //want Op1b to be on the Right. (And likewise with Op2 and Op2b.) //So, to facilitate this while inserting Op1b and Op2b ... //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) if (Dir1 == dLeftToRight) { while (op1->Next->Pt.X <= Pt.X && op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) op1 = op1->Next; if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; op1b = DupOutPt(op1, !DiscardLeft); if (op1b->Pt != Pt) { op1 = op1b; op1->Pt = Pt; op1b = DupOutPt(op1, !DiscardLeft); } } else { while (op1->Next->Pt.X >= Pt.X && op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) op1 = op1->Next; if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; op1b = DupOutPt(op1, DiscardLeft); if (op1b->Pt != Pt) { op1 = op1b; op1->Pt = Pt; op1b = DupOutPt(op1, DiscardLeft); } } if (Dir2 == dLeftToRight) { while (op2->Next->Pt.X <= Pt.X && op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) op2 = op2->Next; if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; op2b = DupOutPt(op2, !DiscardLeft); if (op2b->Pt != Pt) { op2 = op2b; op2->Pt = Pt; op2b = DupOutPt(op2, !DiscardLeft); }; } else { while (op2->Next->Pt.X >= Pt.X && op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) op2 = op2->Next; if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; op2b = DupOutPt(op2, DiscardLeft); if (op2b->Pt != Pt) { op2 = op2b; op2->Pt = Pt; op2b = DupOutPt(op2, DiscardLeft); }; }; if ((Dir1 == dLeftToRight) == DiscardLeft) { op1->Prev = op2; op2->Next = op1; op1b->Next = op2b; op2b->Prev = op1b; } else { op1->Next = op2; op2->Prev = op1; op1b->Prev = op2b; op2b->Next = op1b; } return true; } //------------------------------------------------------------------------------ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) { OutPt *op1 = j->OutPt1, *op1b; OutPt *op2 = j->OutPt2, *op2b; //There are 3 kinds of joins for output polygons ... //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a vertices anywhere //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal). //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same //location at the Bottom of the overlapping segment (& Join.OffPt is above). //3. StrictSimple joins where edges touch but are not collinear and where //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && (j->OffPt == j->OutPt2->Pt)) { //Strictly Simple join ... if (outRec1 != outRec2) return false; op1b = j->OutPt1->Next; while (op1b != op1 && (op1b->Pt == j->OffPt)) op1b = op1b->Next; bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); op2b = j->OutPt2->Next; while (op2b != op2 && (op2b->Pt == j->OffPt)) op2b = op2b->Next; bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); if (reverse1 == reverse2) return false; if (reverse1) { op1b = DupOutPt(op1, false); op2b = DupOutPt(op2, true); op1->Prev = op2; op2->Next = op1; op1b->Next = op2b; op2b->Prev = op1b; j->OutPt1 = op1; j->OutPt2 = op1b; return true; } else { op1b = DupOutPt(op1, true); op2b = DupOutPt(op2, false); op1->Next = op2; op2->Prev = op1; op1b->Prev = op2b; op2b->Next = op1b; j->OutPt1 = op1; j->OutPt2 = op1b; return true; } } else if (isHorizontal) { //treat horizontal joins differently to non-horizontal joins since with //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt //may be anywhere along the horizontal edge. op1b = op1; while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2) op1 = op1->Prev; while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2) op1b = op1b->Next; if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon' op2b = op2; while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b) op2 = op2->Prev; while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1) op2b = op2b->Next; if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon' cInt Left, Right; //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) return false; //DiscardLeftSide: when overlapping edges are joined, a spike will created //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up //on the discard Side as either may still be needed for other joins ... IntPoint Pt; bool DiscardLeftSide; if (op1->Pt.X >= Left && op1->Pt.X <= Right) { Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); } else if (op2->Pt.X >= Left&& op2->Pt.X <= Right) { Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); } else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) { Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X; } else { Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); } j->OutPt1 = op1; j->OutPt2 = op2; return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); } else { //nb: For non-horizontal joins ... // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y // 2. Jr.OutPt1.Pt > Jr.OffPt.Y //make sure the polygons are correctly oriented ... op1b = op1->Next; while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next; bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) || !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); if (Reverse1) { op1b = op1->Prev; while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev; if ((op1b->Pt.Y > op1->Pt.Y) || !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false; }; op2b = op2->Next; while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next; bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) || !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); if (Reverse2) { op2b = op2->Prev; while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev; if ((op2b->Pt.Y > op2->Pt.Y) || !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false; } if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false; if (Reverse1) { op1b = DupOutPt(op1, false); op2b = DupOutPt(op2, true); op1->Prev = op2; op2->Next = op1; op1b->Next = op2b; op2b->Prev = op1b; j->OutPt1 = op1; j->OutPt2 = op1b; return true; } else { op1b = DupOutPt(op1, true); op2b = DupOutPt(op2, false); op1->Next = op2; op2->Prev = op1; op1b->Prev = op2b; op2b->Next = op1b; j->OutPt1 = op1; j->OutPt2 = op1b; return true; } } } //---------------------------------------------------------------------- static OutRec* ParseFirstLeft(OutRec* FirstLeft) { while (FirstLeft && !FirstLeft->Pts) FirstLeft = FirstLeft->FirstLeft; return FirstLeft; } //------------------------------------------------------------------------------ void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) { //tests if NewOutRec contains the polygon before reassigning FirstLeft for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { OutRec* outRec = m_PolyOuts[i]; if (!outRec->Pts || !outRec->FirstLeft) continue; OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft); if (firstLeft == OldOutRec) { if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) outRec->FirstLeft = NewOutRec; } } } //---------------------------------------------------------------------- void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) { //reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { OutRec* outRec = m_PolyOuts[i]; if (outRec->FirstLeft == OldOutRec) outRec->FirstLeft = NewOutRec; } } //---------------------------------------------------------------------- void Clipper::JoinCommonEdges() { for (JoinList::size_type i = 0; i < m_Joins.size(); i++) { Join* join = m_Joins[i]; OutRec *outRec1 = GetOutRec(join->OutPt1->Idx); OutRec *outRec2 = GetOutRec(join->OutPt2->Idx); if (!outRec1->Pts || !outRec2->Pts) continue; //get the polygon fragment with the correct hole state (FirstLeft) //before calling JoinPoints() ... OutRec *holeStateRec; if (outRec1 == outRec2) holeStateRec = outRec1; else if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; else holeStateRec = GetLowermostRec(outRec1, outRec2); if (!JoinPoints(join, outRec1, outRec2)) continue; if (outRec1 == outRec2) { //instead of joining two polygons, we've just created a new one by //splitting one polygon into two. outRec1->Pts = join->OutPt1; outRec1->BottomPt = 0; outRec2 = CreateOutRec(); outRec2->Pts = join->OutPt2; //update all OutRec2.Pts Idx's ... UpdateOutPtIdxs(*outRec2); //We now need to check every OutRec.FirstLeft pointer. If it points //to OutRec1 it may need to point to OutRec2 instead ... if (m_UsingPolyTree) for (PolyOutList::size_type j = 0; j < m_PolyOuts.size() - 1; j++) { OutRec* oRec = m_PolyOuts[j]; if (!oRec->Pts || ParseFirstLeft(oRec->FirstLeft) != outRec1 || oRec->IsHole == outRec1->IsHole) continue; if (Poly2ContainsPoly1(oRec->Pts, join->OutPt2)) oRec->FirstLeft = outRec2; } if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) { //outRec2 is contained by outRec1 ... outRec2->IsHole = !outRec1->IsHole; outRec2->FirstLeft = outRec1; //fixup FirstLeft pointers that may need reassigning to OutRec1 if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) ReversePolyPtLinks(outRec2->Pts); } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) { //outRec1 is contained by outRec2 ... outRec2->IsHole = outRec1->IsHole; outRec1->IsHole = !outRec2->IsHole; outRec2->FirstLeft = outRec1->FirstLeft; outRec1->FirstLeft = outRec2; //fixup FirstLeft pointers that may need reassigning to OutRec1 if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2); if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) ReversePolyPtLinks(outRec1->Pts); } else { //the 2 polygons are completely separate ... outRec2->IsHole = outRec1->IsHole; outRec2->FirstLeft = outRec1->FirstLeft; //fixup FirstLeft pointers that may need reassigning to OutRec2 if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2); } } else { //joined 2 polygons together ... outRec2->Pts = 0; outRec2->BottomPt = 0; outRec2->Idx = outRec1->Idx; outRec1->IsHole = holeStateRec->IsHole; if (holeStateRec == outRec2) outRec1->FirstLeft = outRec2->FirstLeft; outRec2->FirstLeft = outRec1; //fixup FirstLeft pointers that may need reassigning to OutRec1 if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); } } } //------------------------------------------------------------------------------ // ClipperOffset support functions ... //------------------------------------------------------------------------------ DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) { if(pt2.X == pt1.X && pt2.Y == pt1.Y) return DoublePoint(0, 0); double Dx = (double)(pt2.X - pt1.X); double dy = (double)(pt2.Y - pt1.Y); double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy ); Dx *= f; dy *= f; return DoublePoint(dy, -Dx); } //------------------------------------------------------------------------------ // ClipperOffset class //------------------------------------------------------------------------------ ClipperOffset::ClipperOffset(double miterLimit, double arcTolerance) { this->MiterLimit = miterLimit; this->ArcTolerance = arcTolerance; m_lowest.X = -1; } //------------------------------------------------------------------------------ ClipperOffset::~ClipperOffset() { Clear(); } //------------------------------------------------------------------------------ void ClipperOffset::Clear() { for (int i = 0; i < m_polyNodes.ChildCount(); ++i) delete m_polyNodes.Childs[i]; m_polyNodes.Childs.clear(); m_lowest.X = -1; } //------------------------------------------------------------------------------ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType) { int highI = (int)path.size() - 1; if (highI < 0) return; PolyNode* newNode = new PolyNode(); newNode->m_jointype = joinType; newNode->m_endtype = endType; //strip duplicate points from path and also get index to the lowest point ... if (endType == etClosedLine || endType == etClosedPolygon) while (highI > 0 && path[0] == path[highI]) highI--; newNode->Contour.reserve(highI + 1); newNode->Contour.push_back(path[0]); int j = 0, k = 0; for (int i = 1; i <= highI; i++) if (newNode->Contour[j] != path[i]) { j++; newNode->Contour.push_back(path[i]); if (path[i].Y > newNode->Contour[k].Y || (path[i].Y == newNode->Contour[k].Y && path[i].X < newNode->Contour[k].X)) k = j; } if (endType == etClosedPolygon && j < 2) { delete newNode; return; } m_polyNodes.AddChild(*newNode); //if this path's lowest pt is lower than all the others then update m_lowest if (endType != etClosedPolygon) return; if (m_lowest.X < 0) m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); else { IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; if (newNode->Contour[k].Y > ip.Y || (newNode->Contour[k].Y == ip.Y && newNode->Contour[k].X < ip.X)) m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); } } //------------------------------------------------------------------------------ void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType) { for (Paths::size_type i = 0; i < paths.size(); ++i) AddPath(paths[i], joinType, endType); } //------------------------------------------------------------------------------ void ClipperOffset::FixOrientations() { //fixup orientations of all closed paths if the orientation of the //closed path with the lowermost vertex is wrong ... if (m_lowest.X >= 0 && !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) { for (int i = 0; i < m_polyNodes.ChildCount(); ++i) { PolyNode& node = *m_polyNodes.Childs[i]; if (node.m_endtype == etClosedPolygon || (node.m_endtype == etClosedLine && Orientation(node.Contour))) ReversePath(node.Contour); } } else { for (int i = 0; i < m_polyNodes.ChildCount(); ++i) { PolyNode& node = *m_polyNodes.Childs[i]; if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) ReversePath(node.Contour); } } } //------------------------------------------------------------------------------ void ClipperOffset::Execute(Paths& solution, double delta) { solution.clear(); FixOrientations(); DoOffset(delta); //now clean up 'corners' ... Clipper clpr; clpr.AddPaths(m_destPolys, ptSubject, true); if (delta > 0) { clpr.Execute(ctUnion, solution, pftPositive, pftPositive); } else { IntRect r = clpr.GetBounds(); Path outer(4); outer[0] = IntPoint(r.left - 10, r.bottom + 10); outer[1] = IntPoint(r.right + 10, r.bottom + 10); outer[2] = IntPoint(r.right + 10, r.top - 10); outer[3] = IntPoint(r.left - 10, r.top - 10); clpr.AddPath(outer, ptSubject, true); clpr.ReverseSolution(true); clpr.Execute(ctUnion, solution, pftNegative, pftNegative); if (solution.size() > 0) solution.erase(solution.begin()); } } //------------------------------------------------------------------------------ void ClipperOffset::Execute(PolyTree& solution, double delta) { solution.Clear(); FixOrientations(); DoOffset(delta); //now clean up 'corners' ... Clipper clpr; clpr.AddPaths(m_destPolys, ptSubject, true); if (delta > 0) { clpr.Execute(ctUnion, solution, pftPositive, pftPositive); } else { IntRect r = clpr.GetBounds(); Path outer(4); outer[0] = IntPoint(r.left - 10, r.bottom + 10); outer[1] = IntPoint(r.right + 10, r.bottom + 10); outer[2] = IntPoint(r.right + 10, r.top - 10); outer[3] = IntPoint(r.left - 10, r.top - 10); clpr.AddPath(outer, ptSubject, true); clpr.ReverseSolution(true); clpr.Execute(ctUnion, solution, pftNegative, pftNegative); //remove the outer PolyNode rectangle ... if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) { PolyNode* outerNode = solution.Childs[0]; solution.Childs.reserve(outerNode->ChildCount()); solution.Childs[0] = outerNode->Childs[0]; solution.Childs[0]->Parent = outerNode->Parent; for (int i = 1; i < outerNode->ChildCount(); ++i) solution.AddChild(*outerNode->Childs[i]); } else solution.Clear(); } } //------------------------------------------------------------------------------ void ClipperOffset::DoOffset(double delta) { m_destPolys.clear(); m_delta = delta; //if Zero offset, just copy any CLOSED polygons to m_p and return ... if (NEAR_ZERO(delta)) { m_destPolys.reserve(m_polyNodes.ChildCount()); for (int i = 0; i < m_polyNodes.ChildCount(); i++) { PolyNode& node = *m_polyNodes.Childs[i]; if (node.m_endtype == etClosedPolygon) m_destPolys.push_back(node.Contour); } return; } //see offset_triginometry3.svg in the documentation folder ... if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit); else m_miterLim = 0.5; double y; if (ArcTolerance <= 0.0) y = def_arc_tolerance; else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) y = std::fabs(delta) * def_arc_tolerance; else y = ArcTolerance; //see offset_triginometry2.svg in the documentation folder ... double steps = pi / std::acos(1 - y / std::fabs(delta)); if (steps > std::fabs(delta) * pi) steps = std::fabs(delta) * pi; //ie excessive precision check m_sin = std::sin(two_pi / steps); m_cos = std::cos(two_pi / steps); m_StepsPerRad = steps / two_pi; if (delta < 0.0) m_sin = -m_sin; m_destPolys.reserve(m_polyNodes.ChildCount() * 2); for (int i = 0; i < m_polyNodes.ChildCount(); i++) { PolyNode& node = *m_polyNodes.Childs[i]; m_srcPoly = node.Contour; int len = (int)m_srcPoly.size(); if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) continue; m_destPoly.clear(); if (len == 1) { if (node.m_jointype == jtRound) { double X = 1.0, Y = 0.0; for (cInt j = 1; j <= steps; j++) { m_destPoly.push_back(IntPoint( Round(m_srcPoly[0].X + X * delta), Round(m_srcPoly[0].Y + Y * delta))); double X2 = X; X = X * m_cos - m_sin * Y; Y = X2 * m_sin + Y * m_cos; } } else { double X = -1.0, Y = -1.0; for (int j = 0; j < 4; ++j) { m_destPoly.push_back(IntPoint( Round(m_srcPoly[0].X + X * delta), Round(m_srcPoly[0].Y + Y * delta))); if (X < 0) X = 1; else if (Y < 0) Y = 1; else X = -1; } } m_destPolys.push_back(m_destPoly); continue; } //build m_normals ... m_normals.clear(); m_normals.reserve(len); for (int j = 0; j < len - 1; ++j) m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); else m_normals.push_back(DoublePoint(m_normals[len - 2])); if (node.m_endtype == etClosedPolygon) { int k = len - 1; for (int j = 0; j < len; ++j) OffsetPoint(j, k, node.m_jointype); m_destPolys.push_back(m_destPoly); } else if (node.m_endtype == etClosedLine) { int k = len - 1; for (int j = 0; j < len; ++j) OffsetPoint(j, k, node.m_jointype); m_destPolys.push_back(m_destPoly); m_destPoly.clear(); //re-build m_normals ... DoublePoint n = m_normals[len -1]; for (int j = len - 1; j > 0; j--) m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); m_normals[0] = DoublePoint(-n.X, -n.Y); k = 0; for (int j = len - 1; j >= 0; j--) OffsetPoint(j, k, node.m_jointype); m_destPolys.push_back(m_destPoly); } else { int k = 0; for (int j = 1; j < len - 1; ++j) OffsetPoint(j, k, node.m_jointype); IntPoint pt1; if (node.m_endtype == etOpenButt) { int j = len - 1; pt1 = IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X * delta), (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); m_destPoly.push_back(pt1); pt1 = IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X * delta), (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); m_destPoly.push_back(pt1); } else { int j = len - 1; k = len - 2; m_sinA = 0; m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); if (node.m_endtype == etOpenSquare) DoSquare(j, k); else DoRound(j, k); } //re-build m_normals ... for (int j = len - 1; j > 0; j--) m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); k = len - 1; for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype); if (node.m_endtype == etOpenButt) { pt1 = IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta), (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); m_destPoly.push_back(pt1); pt1 = IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta), (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); m_destPoly.push_back(pt1); } else { k = 1; m_sinA = 0; if (node.m_endtype == etOpenSquare) DoSquare(0, 1); else DoRound(0, 1); } m_destPolys.push_back(m_destPoly); } } } //------------------------------------------------------------------------------ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype) { //cross product ... m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); if (std::fabs(m_sinA * m_delta) < 1.0) { //dot product ... double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y ); if (cosA > 0) // angle => 0 degrees { m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); return; } //else angle => 180 degrees } else if (m_sinA > 1.0) m_sinA = 1.0; else if (m_sinA < -1.0) m_sinA = -1.0; if (m_sinA * m_delta < 0) { m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); m_destPoly.push_back(m_srcPoly[j]); m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); } else switch (jointype) { case jtMiter: { double r = 1 + (m_normals[j].X * m_normals[k].X + m_normals[j].Y * m_normals[k].Y); if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k); break; } case jtSquare: DoSquare(j, k); break; case jtRound: DoRound(j, k); break; } k = j; } //------------------------------------------------------------------------------ void ClipperOffset::DoSquare(int j, int k) { double dx = std::tan(std::atan2(m_sinA, m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); m_destPoly.push_back(IntPoint( Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); m_destPoly.push_back(IntPoint( Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); } //------------------------------------------------------------------------------ void ClipperOffset::DoMiter(int j, int k, double r) { double q = m_delta / r; m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); } //------------------------------------------------------------------------------ void ClipperOffset::DoRound(int j, int k) { double a = std::atan2(m_sinA, m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1); double X = m_normals[k].X, Y = m_normals[k].Y, X2; for (int i = 0; i < steps; ++i) { m_destPoly.push_back(IntPoint( Round(m_srcPoly[j].X + X * m_delta), Round(m_srcPoly[j].Y + Y * m_delta))); X2 = X; X = X * m_cos - m_sin * Y; Y = X2 * m_sin + Y * m_cos; } m_destPoly.push_back(IntPoint( Round(m_srcPoly[j].X + m_normals[j].X * m_delta), Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); } //------------------------------------------------------------------------------ // Miscellaneous public functions //------------------------------------------------------------------------------ void Clipper::DoSimplePolygons() { PolyOutList::size_type i = 0; while (i < m_PolyOuts.size()) { OutRec* outrec = m_PolyOuts[i++]; OutPt* op = outrec->Pts; if (!op || outrec->IsOpen) continue; do //for each Pt in Polygon until duplicate found do ... { OutPt* op2 = op->Next; while (op2 != outrec->Pts) { if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) { //split the polygon into two ... OutPt* op3 = op->Prev; OutPt* op4 = op2->Prev; op->Prev = op4; op4->Next = op; op2->Prev = op3; op3->Next = op2; outrec->Pts = op; OutRec* outrec2 = CreateOutRec(); outrec2->Pts = op2; UpdateOutPtIdxs(*outrec2); if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) { //OutRec2 is contained by OutRec1 ... outrec2->IsHole = !outrec->IsHole; outrec2->FirstLeft = outrec; if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec); } else if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) { //OutRec1 is contained by OutRec2 ... outrec2->IsHole = outrec->IsHole; outrec->IsHole = !outrec2->IsHole; outrec2->FirstLeft = outrec->FirstLeft; outrec->FirstLeft = outrec2; if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2); } else { //the 2 polygons are separate ... outrec2->IsHole = outrec->IsHole; outrec2->FirstLeft = outrec->FirstLeft; if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2); } op2 = op; //ie get ready for the Next iteration } op2 = op2->Next; } op = op->Next; } while (op != outrec->Pts); } } //------------------------------------------------------------------------------ void ReversePath(Path& p) { std::reverse(p.begin(), p.end()); } //------------------------------------------------------------------------------ void ReversePaths(Paths& p) { for (Paths::size_type i = 0; i < p.size(); ++i) ReversePath(p[i]); } //------------------------------------------------------------------------------ void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType) { Clipper c; c.StrictlySimple(true); c.AddPath(in_poly, ptSubject, true); c.Execute(ctUnion, out_polys, fillType, fillType); } //------------------------------------------------------------------------------ void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType) { Clipper c; c.StrictlySimple(true); c.AddPaths(in_polys, ptSubject, true); c.Execute(ctUnion, out_polys, fillType, fillType); } //------------------------------------------------------------------------------ void SimplifyPolygons(Paths &polys, PolyFillType fillType) { SimplifyPolygons(polys, polys, fillType); } //------------------------------------------------------------------------------ inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) { double Dx = ((double)pt1.X - pt2.X); double dy = ((double)pt1.Y - pt2.Y); return (Dx*Dx + dy*dy); } //------------------------------------------------------------------------------ double DistanceFromLineSqrd( const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) { //The equation of a line in general form (Ax + By + C = 0) //given 2 points (x,y) & (x,y) is ... //(y - y)x + (x - x)y + (y - y)x - (x - x)y = 0 //A = (y - y); B = (x - x); C = (y - y)x - (x - x)y //perpendicular distance of point (x,y) = (Ax + By + C)/Sqrt(A + B) //see http://en.wikipedia.org/wiki/Perpendicular_distance double A = double(ln1.Y - ln2.Y); double B = double(ln2.X - ln1.X); double C = A * ln1.X + B * ln1.Y; C = A * pt.X + B * pt.Y - C; return (C * C) / (A * A + B * B); } //--------------------------------------------------------------------------- bool SlopesNearCollinear(const IntPoint& pt1, const IntPoint& pt2, const IntPoint& pt3, double distSqrd) { //this function is more accurate when the point that's geometrically //between the other 2 points is the one that's tested for distance. //ie makes it more likely to pick up 'spikes' ... if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y)) { if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; else return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; } else { if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; else return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; } } //------------------------------------------------------------------------------ bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) { double Dx = (double)pt1.X - pt2.X; double dy = (double)pt1.Y - pt2.Y; return ((Dx * Dx) + (dy * dy) <= distSqrd); } //------------------------------------------------------------------------------ OutPt* ExcludeOp(OutPt* op) { OutPt* result = op->Prev; result->Next = op->Next; op->Next->Prev = result; result->Idx = 0; return result; } //------------------------------------------------------------------------------ void CleanPolygon(const Path& in_poly, Path& out_poly, double distance) { //distance = proximity in units/pixels below which vertices //will be stripped. Default ~= sqrt(2). size_t size = in_poly.size(); if (size == 0) { out_poly.clear(); return; } OutPt* outPts = new OutPt[size]; for (size_t i = 0; i < size; ++i) { outPts[i].Pt = in_poly[i]; outPts[i].Next = &outPts[(i + 1) % size]; outPts[i].Next->Prev = &outPts[i]; outPts[i].Idx = 0; } double distSqrd = distance * distance; OutPt* op = &outPts[0]; while (op->Idx == 0 && op->Next != op->Prev) { if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) { op = ExcludeOp(op); size--; } else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) { ExcludeOp(op->Next); op = ExcludeOp(op); size -= 2; } else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd)) { op = ExcludeOp(op); size--; } else { op->Idx = 1; op = op->Next; } } if (size < 3) size = 0; out_poly.resize(size); for (size_t i = 0; i < size; ++i) { out_poly[i] = op->Pt; op = op->Next; } delete [] outPts; } //------------------------------------------------------------------------------ void CleanPolygon(Path& poly, double distance) { CleanPolygon(poly, poly, distance); } //------------------------------------------------------------------------------ void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance) { for (Paths::size_type i = 0; i < in_polys.size(); ++i) CleanPolygon(in_polys[i], out_polys[i], distance); } //------------------------------------------------------------------------------ void CleanPolygons(Paths& polys, double distance) { CleanPolygons(polys, polys, distance); } //------------------------------------------------------------------------------ void Minkowski(const Path& poly, const Path& path, Paths& solution, bool isSum, bool isClosed) { int delta = (isClosed ? 1 : 0); size_t polyCnt = poly.size(); size_t pathCnt = path.size(); Paths pp; pp.reserve(pathCnt); if (isSum) for (size_t i = 0; i < pathCnt; ++i) { Path p; p.reserve(polyCnt); for (size_t j = 0; j < poly.size(); ++j) p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); pp.push_back(p); } else for (size_t i = 0; i < pathCnt; ++i) { Path p; p.reserve(polyCnt); for (size_t j = 0; j < poly.size(); ++j) p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); pp.push_back(p); } solution.clear(); solution.reserve((pathCnt + delta) * (polyCnt + 1)); for (size_t i = 0; i < pathCnt - 1 + delta; ++i) for (size_t j = 0; j < polyCnt; ++j) { Path quad; quad.reserve(4); quad.push_back(pp[i % pathCnt][j % polyCnt]); quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); if (!Orientation(quad)) ReversePath(quad); solution.push_back(quad); } } //------------------------------------------------------------------------------ void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed) { Minkowski(pattern, path, solution, true, pathIsClosed); Clipper c; c.AddPaths(solution, ptSubject, true); c.Execute(ctUnion, solution, pftNonZero, pftNonZero); } //------------------------------------------------------------------------------ void TranslatePath(const Path& input, Path& output, IntPoint delta) { //precondition: input != output output.resize(input.size()); for (size_t i = 0; i < input.size(); ++i) output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y); } //------------------------------------------------------------------------------ void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed) { Clipper c; for (size_t i = 0; i < paths.size(); ++i) { Paths tmp; Minkowski(pattern, paths[i], tmp, true, pathIsClosed); c.AddPaths(tmp, ptSubject, true); if (pathIsClosed) { Path tmp2; TranslatePath(paths[i], tmp2, pattern[0]); c.AddPath(tmp2, ptClip, true); } } c.Execute(ctUnion, solution, pftNonZero, pftNonZero); } //------------------------------------------------------------------------------ void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution) { Minkowski(poly1, poly2, solution, false, true); Clipper c; c.AddPaths(solution, ptSubject, true); c.Execute(ctUnion, solution, pftNonZero, pftNonZero); } //------------------------------------------------------------------------------ enum NodeType {ntAny, ntOpen, ntClosed}; void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths) { bool match = true; if (nodetype == ntClosed) match = !polynode.IsOpen(); else if (nodetype == ntOpen) return; if (!polynode.Contour.empty() && match) paths.push_back(polynode.Contour); for (int i = 0; i < polynode.ChildCount(); ++i) AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); } //------------------------------------------------------------------------------ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths) { paths.resize(0); paths.reserve(polytree.Total()); AddPolyNodeToPaths(polytree, ntAny, paths); } //------------------------------------------------------------------------------ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths) { paths.resize(0); paths.reserve(polytree.Total()); AddPolyNodeToPaths(polytree, ntClosed, paths); } //------------------------------------------------------------------------------ void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths) { paths.resize(0); paths.reserve(polytree.Total()); //Open paths are top level only, so ... for (int i = 0; i < polytree.ChildCount(); ++i) if (polytree.Childs[i]->IsOpen()) paths.push_back(polytree.Childs[i]->Contour); } //------------------------------------------------------------------------------ std::ostream& operator <<(std::ostream &s, const IntPoint &p) { s << "(" << p.X << "," << p.Y << ")"; return s; } //------------------------------------------------------------------------------ std::ostream& operator <<(std::ostream &s, const Path &p) { if (p.empty()) return s; Path::size_type last = p.size() -1; for (Path::size_type i = 0; i < last; i++) s << "(" << p[i].X << "," << p[i].Y << "), "; s << "(" << p[last].X << "," << p[last].Y << ")\n"; return s; } //------------------------------------------------------------------------------ std::ostream& operator <<(std::ostream &s, const Paths &p) { for (Paths::size_type i = 0; i < p.size(); i++) s << p[i]; s << "\n"; return s; } //------------------------------------------------------------------------------ } //ClipperLib namespace dvisvgm-3.5/libs/clipper/clipper.hpp000066400000000000000000000370071501401750600176040ustar00rootroot00000000000000/******************************************************************************* * * * Author : Angus Johnson * * Version : 6.2.1 * * Date : 31 October 2014 * * Website : http://www.angusj.com * * Copyright : Angus Johnson 2010-2014 * * * * License: * * Use, modification & distribution is subject to Boost Software License Ver 1. * * http://www.boost.org/LICENSE_1_0.txt * * * * Attributions: * * The code in this library is an extension of Bala Vatti's clipping algorithm: * * "A generic solution to polygon clipping" * * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * * http://portal.acm.org/citation.cfm?id=129906 * * * * Computer graphics and geometric modeling: implementation and algorithms * * By Max K. Agoston * * Springer; 1 edition (January 4, 2005) * * http://books.google.com/books?q=vatti+clipping+agoston * * * * See also: * * "Polygon Offsetting by Computing Winding Numbers" * * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * * September 24-28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ #ifndef clipper_hpp #define clipper_hpp #define CLIPPER_VERSION "6.2.1" //use_int32: When enabled 32bit ints are used instead of 64bit ints. This //improve performance but coordinate values are limited to the range +/- 46340 //#define use_int32 //use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance. #define use_xyz //use_lines: Enables line clipping. Adds a very minor cost to performance. #define use_lines //use_deprecated: Enables temporary support for the obsolete functions //#define use_deprecated #include #include #include #include #include #include #include #include #include namespace ClipperLib { enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; enum PolyType { ptSubject, ptClip }; //By far the most widely used winding rules for polygon filling are //EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) //Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) //see http://glprogramming.com/red/chapter11.html enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; struct ZLabel { ZLabel () : id(0), t(0) {} ZLabel (int32_t ii) : id(ii), t(0) {} ZLabel (int32_t ii, double tt) : id(ii), t(tt) {} bool operator == (const ZLabel &l) const {return id == l.id;} int32_t id; double t; }; inline std::ostream& operator << (std::ostream &os, const ZLabel &l) { return os << l.id << ':' << l.t; } struct ZType { ZType (uint64_t v) : label1(v >> 32), label2(v & 0xffffffff) {} ZType (int32_t id1, int32_t id2) : label1(id1), label2(id2) {} ZType (const ZLabel &l1, const ZLabel &l2) : label1(l1), label2(l2) {} const ZLabel& minLabel () const {return (label1.id < label2.id) ? label1 : label2;} const ZLabel& maxLabel () const {return (label1.id > label2.id) ? label1 : label2;} const ZLabel& otherLabel (const ZLabel &l) const { return (l.id == label1.id && l.t == label1.t) ? label2 : label1; } bool operator == (const ZType &p) const {return minLabel() == p.minLabel() && maxLabel() == p.maxLabel();} operator uint64_t () const {return (uint64_t(label1.id) << 32) & label2.id;} ZLabel label1, label2; }; inline std::ostream& operator << (std::ostream &os, const ZType &z) { return os << '[' << z.label1 << '|' << z.label2 << ']'; } #ifdef use_int32 typedef int cInt; static cInt const loRange = 0x7FFF; static cInt const hiRange = 0x7FFF; #else typedef signed long long cInt; static cInt const loRange = 0x3FFFFFFF; static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; typedef signed long long long64; //used by Int128 class typedef unsigned long long ulong64; #endif struct IntPoint { cInt X; cInt Y; #ifdef use_xyz ZType Z; IntPoint(cInt x = 0, cInt y = 0, ZType z = 0): X(x), Y(y), Z(z) {}; #else IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {}; #endif friend inline bool operator== (const IntPoint& a, const IntPoint& b) { return a.X == b.X && a.Y == b.Y; } friend inline bool operator!= (const IntPoint& a, const IntPoint& b) { return a.X != b.X || a.Y != b.Y; } }; //------------------------------------------------------------------------------ typedef std::vector< IntPoint > Path; typedef std::vector< Path > Paths; inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} std::ostream& operator <<(std::ostream &s, const IntPoint &p); std::ostream& operator <<(std::ostream &s, const Path &p); std::ostream& operator <<(std::ostream &s, const Paths &p); struct DoublePoint { double X; double Y; DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {} }; //------------------------------------------------------------------------------ #ifdef use_xyz typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt); #endif enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4}; enum JoinType {jtSquare, jtRound, jtMiter}; enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; class PolyNode; typedef std::vector< PolyNode* > PolyNodes; class PolyNode { public: PolyNode(); virtual ~PolyNode(){}; Path Contour; PolyNodes Childs; PolyNode* Parent; PolyNode* GetNext() const; bool IsHole() const; bool IsOpen() const; int ChildCount() const; private: unsigned Index; //node index in Parent.Childs bool m_IsOpen; JoinType m_jointype; EndType m_endtype; PolyNode* GetNextSiblingUp() const; void AddChild(PolyNode& child); friend class Clipper; //to access Index friend class ClipperOffset; }; class PolyTree: public PolyNode { public: ~PolyTree(){Clear();}; PolyNode* GetFirst() const; void Clear(); int Total() const; private: PolyNodes AllNodes; friend class Clipper; //to access AllNodes }; bool Orientation(const Path &poly); double Area(const Path &poly); int PointInPolygon(const IntPoint &pt, const Path &path); void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415); void CleanPolygon(Path& poly, double distance = 1.415); void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415); void CleanPolygons(Paths& polys, double distance = 1.415); void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed); void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed); void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution); void PolyTreeToPaths(const PolyTree& polytree, Paths& paths); void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths); void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths); void ReversePath(Path& p); void ReversePaths(Paths& p); struct IntRect { cInt left; cInt top; cInt right; cInt bottom; }; //enums that are used internally ... enum EdgeSide { esLeft = 1, esRight = 2}; //forward declarations (for stuff used internally) ... struct TEdge; struct IntersectNode; struct LocalMinimum; struct Scanbeam; struct OutPt; struct OutRec; struct Join; typedef std::vector < OutRec* > PolyOutList; typedef std::vector < TEdge* > EdgeList; typedef std::vector < Join* > JoinList; typedef std::vector < IntersectNode* > IntersectList; //------------------------------------------------------------------------------ //ClipperBase is the ancestor to the Clipper class. It should not be //instantiated directly. This class simply abstracts the conversion of sets of //polygon coordinates into edge objects that are stored in a LocalMinima list. class ClipperBase { public: ClipperBase(); virtual ~ClipperBase(); bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); virtual void Clear(); IntRect GetBounds(); bool PreserveCollinear() {return m_PreserveCollinear;}; void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; protected: void DisposeLocalMinimaList(); TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); void PopLocalMinima(); virtual void Reset(); TEdge* ProcessBound(TEdge* E, bool IsClockwise); void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed); TEdge* DescendToMin(TEdge *&E); void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); typedef std::vector MinimaList; MinimaList::iterator m_CurrentLM; MinimaList m_MinimaList; bool m_UseFullRange; EdgeList m_edges; bool m_PreserveCollinear; bool m_HasOpenPaths; }; //------------------------------------------------------------------------------ class Clipper : public virtual ClipperBase { public: Clipper(int initOptions = 0); ~Clipper(); bool Execute(ClipType clipType, Paths &solution, PolyFillType subjFillType = pftEvenOdd, PolyFillType clipFillType = pftEvenOdd); bool Execute(ClipType clipType, PolyTree &polytree, PolyFillType subjFillType = pftEvenOdd, PolyFillType clipFillType = pftEvenOdd); bool ReverseSolution() {return m_ReverseOutput;}; void ReverseSolution(bool value) {m_ReverseOutput = value;}; bool StrictlySimple() {return m_StrictSimple;}; void StrictlySimple(bool value) {m_StrictSimple = value;}; //set the callback function for z value filling on intersections (otherwise Z is 0) #ifdef use_xyz void ZFillFunction(ZFillCallback zFillFunc); #endif protected: void Reset() override; virtual bool ExecuteInternal(); private: PolyOutList m_PolyOuts; JoinList m_Joins; JoinList m_GhostJoins; IntersectList m_IntersectList; ClipType m_ClipType; typedef std::priority_queue ScanbeamList; ScanbeamList m_Scanbeam; TEdge *m_ActiveEdges; TEdge *m_SortedEdges; bool m_ExecuteLocked; PolyFillType m_ClipFillType; PolyFillType m_SubjFillType; bool m_ReverseOutput; bool m_UsingPolyTree; bool m_StrictSimple; #ifdef use_xyz ZFillCallback m_ZFill; //custom callback #endif void SetWindingCount(TEdge& edge); bool IsEvenOddFillType(const TEdge& edge) const; bool IsEvenOddAltFillType(const TEdge& edge) const; void InsertScanbeam(const cInt Y); cInt PopScanbeam(); void InsertLocalMinimaIntoAEL(const cInt botY); void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge); void AddEdgeToSEL(TEdge *edge); void CopyAELToSEL(); void DeleteFromSEL(TEdge *e); void DeleteFromAEL(TEdge *e); void UpdateEdgeIntoAEL(TEdge *&e); void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); bool IsContributing(const TEdge& edge) const; bool IsTopHorz(const cInt XPos); void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); void DoMaxima(TEdge *e); void ProcessHorizontals(bool IsTopOfScanbeam); void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam); void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); OutRec* GetOutRec(int idx); void AppendPolygon(TEdge *e1, TEdge *e2); void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt); OutRec* CreateOutRec(); OutPt* AddOutPt(TEdge *e, const IntPoint &pt); void DisposeAllOutRecs(); void DisposeOutRec(PolyOutList::size_type index); bool ProcessIntersections(const cInt topY); void BuildIntersectList(const cInt topY); void ProcessIntersectList(); void ProcessEdgesAtTopOfScanbeam(const cInt topY); void BuildResult(Paths& polys); void BuildResult2(PolyTree& polytree); void SetHoleState(TEdge *e, OutRec *outrec); void DisposeIntersectNodes(); bool FixupIntersectionOrder(); void FixupOutPolygon(OutRec &outrec); bool IsHole(TEdge *e); bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl); void FixHoleLinkage(OutRec &outrec); void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt); void ClearJoins(); void ClearGhostJoins(); void AddGhostJoin(OutPt *op, const IntPoint offPt); bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2); void JoinCommonEdges(); void DoSimplePolygons(); void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec); #ifdef use_xyz void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2); #endif }; //------------------------------------------------------------------------------ class ClipperOffset { public: ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25); ~ClipperOffset(); void AddPath(const Path& path, JoinType joinType, EndType endType); void AddPaths(const Paths& paths, JoinType joinType, EndType endType); void Execute(Paths& solution, double delta); void Execute(PolyTree& solution, double delta); void Clear(); double MiterLimit; double ArcTolerance; private: Paths m_destPolys; Path m_srcPoly; Path m_destPoly; std::vector m_normals; double m_delta, m_sinA, m_sin, m_cos; double m_miterLim, m_StepsPerRad; IntPoint m_lowest; PolyNode m_polyNodes; void FixOrientations(); void DoOffset(double delta); void OffsetPoint(int j, int& k, JoinType jointype); void DoSquare(int j, int k); void DoMiter(int j, int k, double r); void DoRound(int j, int k); }; //------------------------------------------------------------------------------ class clipperException : public std::exception { public: clipperException(const char* description): m_descr(description) {} virtual ~clipperException() throw() {} virtual const char* what() const throw() override {return m_descr.c_str();} private: std::string m_descr; }; //------------------------------------------------------------------------------ } //ClipperLib namespace #endif //clipper_hpp dvisvgm-3.5/libs/defs.am000066400000000000000000000012301501401750600152240ustar00rootroot00000000000000## This file is part of dvisvgm ## Copyright (C) 2005-2025 Martin Gieseking if !HAVE_BROTLI BROTLI_CFLAGS += -I$(dvisvgm_srcdir)/libs/brotli/include BROTLI_LIBS += ../libs/brotli/libbrotli.a endif if TEXLIVE_BUILD POTRACE_CFLAGS = $(POTRACE_INCLUDES) else if !HAVE_POTRACE POTRACE_CFLAGS = -I$(dvisvgm_srcdir)/libs/potrace POTRACE_LIBS = ../libs/potrace/libpotrace.a endif !HAVE_POTRACE endif !TEXLIVE_BUILD if !HAVE_WOFF2 WOFF2_CFLAGS += -I$(dvisvgm_srcdir)/libs/woff2/include WOFF2_LIBS += ../libs/woff2/libwoff2.a endif if !HAVE_XXHASH XXHASH_CFLAGS = -I$(dvisvgm_srcdir)/libs/xxHash XXHASH_LIBS = ../libs/xxHash/libxxhash.a endif dvisvgm-3.5/libs/md5/000077500000000000000000000000001501401750600144555ustar00rootroot00000000000000dvisvgm-3.5/libs/md5/Makefile.am000066400000000000000000000001731501401750600165120ustar00rootroot00000000000000noinst_LIBRARIES = libmd5.a libmd5_a_SOURCES = md5.c md5.h AM_CXXFLAGS = -Wall md5.c: md5.h CLEANFILES = *.gcda *.gcno dvisvgm-3.5/libs/md5/md5.c000066400000000000000000000210471501401750600153120ustar00rootroot00000000000000/* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * (This is a heavily cut-down "BSD license".) * * This differs from Colin Plumb's older public domain implementation in that * no exactly 32-bit integer data type is required (any 32-bit or wider * unsigned integer data type will do), there's no compile-time endianness * configuration, and the function prototypes match OpenSSL's. No code from * Colin Plumb's implementation has been reused; this comment merely compares * the properties of the two independent implementations. * * The primary goals of this implementation are portability and ease of use. * It is meant to be fast, but not as fast as possible. Some known * optimizations are not included to reduce source code size and avoid * compile-time configuration. */ #ifndef HAVE_OPENSSL #include #include "md5.h" /* * The basic MD5 functions. * * F and G are optimized compared to their RFC 1321 definitions for * architectures that lack an AND-NOT instruction, just like in Colin Plumb's * implementation. */ #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) #define H(x, y, z) (((x) ^ (y)) ^ (z)) #define H2(x, y, z) ((x) ^ ((y) ^ (z))) #define I(x, y, z) ((y) ^ ((x) | ~(z))) /* * The MD5 transformation for all four rounds. */ #define STEP(f, a, b, c, d, x, t, s) \ (a) += f((b), (c), (d)) + (x) + (t); \ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ (a) += (b); /* * SET reads 4 input bytes in little-endian byte order and stores them in a * properly aligned word in host byte order. * * The check for little-endian architectures that tolerate unaligned memory * accesses is just an optimization. Nothing will break if it fails to detect * a suitable architecture. * * Unfortunately, this optimization may be a C strict aliasing rules violation * if the caller's data buffer has effective type that cannot be aliased by * MD5_u32plus. In practice, this problem may occur if these MD5 routines are * inlined into a calling function, or with future and dangerously advanced * link-time optimizations. For the time being, keeping these MD5 routines in * their own translation unit avoids the problem. */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) #define SET(n) \ (*(MD5_u32plus *)&ptr[(n) * 4]) #define GET(n) \ SET(n) #else #define SET(n) \ (ctx->block[(n)] = \ (MD5_u32plus)ptr[(n) * 4] | \ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) #define GET(n) \ (ctx->block[(n)]) #endif /* * This processes one or more 64-byte data blocks, but does NOT update the bit * counters. There are no alignment requirements. */ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) { const unsigned char *ptr; MD5_u32plus a, b, c, d; MD5_u32plus saved_a, saved_b, saved_c, saved_d; ptr = (const unsigned char *)data; a = ctx->a; b = ctx->b; c = ctx->c; d = ctx->d; do { saved_a = a; saved_b = b; saved_c = c; saved_d = d; /* Round 1 */ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) STEP(F, c, d, a, b, SET(2), 0x242070db, 17) STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) /* Round 2 */ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) STEP(G, d, a, b, c, GET(10), 0x02441453, 9) STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) /* Round 3 */ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) /* Round 4 */ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) a += saved_a; b += saved_b; c += saved_c; d += saved_d; ptr += 64; } while (size -= 64); ctx->a = a; ctx->b = b; ctx->c = c; ctx->d = d; return ptr; } void MD5_Init(MD5_CTX *ctx) { ctx->a = 0x67452301; ctx->b = 0xefcdab89; ctx->c = 0x98badcfe; ctx->d = 0x10325476; ctx->lo = 0; ctx->hi = 0; } void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) { MD5_u32plus saved_lo; unsigned long used, available; saved_lo = ctx->lo; if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) ctx->hi++; ctx->hi += size >> 29; used = saved_lo & 0x3f; if (used) { available = 64 - used; if (size < available) { memcpy(&ctx->buffer[used], data, size); return; } memcpy(&ctx->buffer[used], data, available); data = (const unsigned char *)data + available; size -= available; body(ctx, ctx->buffer, 64); } if (size >= 64) { data = body(ctx, data, size & ~(unsigned long)0x3f); size &= 0x3f; } memcpy(ctx->buffer, data, size); } #define OUT(dst, src) \ (dst)[0] = (unsigned char)(src); \ (dst)[1] = (unsigned char)((src) >> 8); \ (dst)[2] = (unsigned char)((src) >> 16); \ (dst)[3] = (unsigned char)((src) >> 24); void MD5_Final(unsigned char *result, MD5_CTX *ctx) { unsigned long used, available; used = ctx->lo & 0x3f; ctx->buffer[used++] = 0x80; available = 64 - used; if (available < 8) { memset(&ctx->buffer[used], 0, available); body(ctx, ctx->buffer, 64); used = 0; available = 64; } memset(&ctx->buffer[used], 0, available - 8); ctx->lo <<= 3; OUT(&ctx->buffer[56], ctx->lo) OUT(&ctx->buffer[60], ctx->hi) body(ctx, ctx->buffer, 64); OUT(&result[0], ctx->a) OUT(&result[4], ctx->b) OUT(&result[8], ctx->c) OUT(&result[12], ctx->d) memset(ctx, 0, sizeof(*ctx)); } #endif dvisvgm-3.5/libs/md5/md5.h000066400000000000000000000026221501401750600153150ustar00rootroot00000000000000/* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * See md5.c for more information. */ #ifndef _MD5_H #define _MD5_H #ifdef __cplusplus extern "C" { #endif /* Any 32-bit or wider unsigned integer data type will do */ typedef unsigned int MD5_u32plus; typedef struct { MD5_u32plus lo, hi; MD5_u32plus a, b, c, d; unsigned char buffer[64]; MD5_u32plus block[16]; } MD5_CTX; extern void MD5_Init(MD5_CTX *ctx); extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); #ifdef __cplusplus } #endif #endif dvisvgm-3.5/libs/potrace/000077500000000000000000000000001501401750600154255ustar00rootroot00000000000000dvisvgm-3.5/libs/potrace/Makefile.am000066400000000000000000000004641501401750600174650ustar00rootroot00000000000000if !HAVE_POTRACE noinst_LIBRARIES = libpotrace.a libpotrace_a_SOURCES = \ auxiliary.h \ bitmap.h \ config.h \ curve.c \ curve.h \ decompose.c \ decompose.h \ lists.h \ potracelib.c \ potracelib.h \ progress.h \ trace.c \ trace.h AM_CFLAGS = -Wall -I$(srcdir) endif CLEANFILES = *.gcda *.gcno dvisvgm-3.5/libs/potrace/auxiliary.h000066400000000000000000000041421501401750600176060ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ /* This header file collects some general-purpose macros (and static inline functions) that are used in various places. */ #ifndef AUXILIARY_H #define AUXILIARY_H #ifdef HAVE_CONFIG_H #include #endif #include /* ---------------------------------------------------------------------- */ /* point arithmetic */ #include "potracelib.h" struct point_s { long x; long y; }; typedef struct point_s point_t; typedef potrace_dpoint_t dpoint_t; /* convert point_t to dpoint_t */ static inline dpoint_t dpoint(point_t p) { dpoint_t res; res.x = p.x; res.y = p.y; return res; } /* range over the straight line segment [a,b] when lambda ranges over [0,1] */ static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) { dpoint_t res; res.x = a.x + lambda * (b.x - a.x); res.y = a.y + lambda * (b.y - a.y); return res; } /* ---------------------------------------------------------------------- */ /* some useful macros. Note: the "mod" macro works correctly for negative a. Also note that the test for a>=n, while redundant, speeds up the mod function by 70% in the average case (significant since the program spends about 16% of its time here - or 40% without the test). The "floordiv" macro returns the largest integer <= a/n, and again this works correctly for negative a, as long as a,n are integers and n>0. */ /* integer arithmetic */ static inline int mod(int a, int n) { return a>=n ? a%n : a>=0 ? a : n-1-(-1-a)%n; } static inline int floordiv(int a, int n) { return a>=0 ? a/n : -1-(-1-a)/n; } /* Note: the following work for integers and other numeric types. */ #undef sign #undef abs #undef min #undef max #undef sq #undef cu #define sign(x) ((x)>0 ? 1 : (x)<0 ? -1 : 0) #define abs(a) ((a)>0 ? (a) : -(a)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define max(a,b) ((a)>(b) ? (a) : (b)) #define sq(a) ((a)*(a)) #define cu(a) ((a)*(a)*(a)) #endif /* AUXILIARY_H */ dvisvgm-3.5/libs/potrace/bitmap.h000066400000000000000000000144621501401750600170610ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifndef BITMAP_H #define BITMAP_H #include #include #include #include /* The bitmap type is defined in potracelib.h */ #include "potracelib.h" /* The present file defines some convenient macros and static inline functions for accessing bitmaps. Since they only produce inline code, they can be conveniently shared by the library and frontends, if desired */ /* ---------------------------------------------------------------------- */ /* some measurements */ #define BM_WORDSIZE ((int)sizeof(potrace_word)) #define BM_WORDBITS (8*BM_WORDSIZE) #define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1)) #define BM_ALLBITS (~(potrace_word)0) /* macros for accessing pixel at index (x,y). U* macros omit the bounds check. */ #define bm_scanline(bm, y) ((bm)->map + (ptrdiff_t)(y)*(ptrdiff_t)(bm)->dy) #define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS]) #define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1))) #define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a)) #define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h)) #define BM_UGET(bm, x, y) ((*bm_index(bm, x, y) & bm_mask(x)) != 0) #define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x)) #define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x)) #define BM_UINV(bm, x, y) (*bm_index(bm, x, y) ^= bm_mask(x)) #define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y)) #define BM_GET(bm, x, y) (bm_safe(bm, x, y) ? BM_UGET(bm, x, y) : 0) #define BM_SET(bm, x, y) (bm_safe(bm, x, y) ? BM_USET(bm, x, y) : 0) #define BM_CLR(bm, x, y) (bm_safe(bm, x, y) ? BM_UCLR(bm, x, y) : 0) #define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0) #define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0) /* calculate the size, in bytes, required for the data area of a bitmap of the given dy and h. Assume h >= 0. Return -1 if the size does not fit into the ptrdiff_t type. */ static inline ptrdiff_t getsize(int dy, int h) { ptrdiff_t size; if (dy < 0) { dy = -dy; } size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)BM_WORDSIZE; /* check for overflow error */ if (size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE)) { return -1; } return size; } /* return the size, in bytes, of the data area of the bitmap. Return -1 if the size does not fit into the ptrdiff_t type; however, this cannot happen if the bitmap is well-formed, i.e., if created with bm_new or bm_dup. */ static inline ptrdiff_t bm_size(const potrace_bitmap_t *bm) { return getsize(bm->dy, bm->h); } /* calculate the base address of the bitmap data. Assume that the bitmap is well-formed, i.e., its size fits into the ptrdiff_t type. This is the case if created with bm_new or bm_dup. The base address may differ from bm->map if dy is negative */ static inline potrace_word *bm_base(const potrace_bitmap_t *bm) { int dy = bm->dy; if (dy >= 0 || bm->h == 0) { return bm->map; } else { return bm_scanline(bm, bm->h - 1); } } /* free the given bitmap. Leaves errno untouched. */ static inline void bm_free(potrace_bitmap_t *bm) { if (bm && bm->map) { free(bm_base(bm)); } free(bm); } /* return new bitmap initialized to 0. NULL with errno on error. Assumes w, h >= 0. */ static inline potrace_bitmap_t *bm_new(int w, int h) { potrace_bitmap_t *bm; int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1; ptrdiff_t size; size = getsize(dy, h); if (size < 0) { errno = ENOMEM; return NULL; } if (size == 0) { size = BM_WORDSIZE; /* make sure calloc() doesn't return NULL */ } bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t)); if (!bm) { return NULL; } bm->w = w; bm->h = h; bm->dy = dy; bm->map = (potrace_word *) calloc(1, size); if (!bm->map) { free(bm); return NULL; } return bm; } /* clear the given bitmap. Set all bits to c. Assumes a well-formed bitmap. */ static inline void bm_clear(potrace_bitmap_t *bm, int c) { /* Note: if the bitmap was created with bm_new, then it is guaranteed that size will fit into the ptrdiff_t type. */ ptrdiff_t size = bm_size(bm); memset(bm_base(bm), c ? -1 : 0, size); } /* duplicate the given bitmap. Return NULL on error with errno set. Assumes a well-formed bitmap. */ static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) { potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h); int y; if (!bm1) { return NULL; } for (y=0; y < bm->h; y++) { memcpy(bm_scanline(bm1, y), bm_scanline(bm, y), (size_t)bm1->dy * (size_t)BM_WORDSIZE); } return bm1; } /* invert the given bitmap. */ static inline void bm_invert(potrace_bitmap_t *bm) { int dy = bm->dy; int y; int i; potrace_word *p; if (dy < 0) { dy = -dy; } for (y=0; y < bm->h; y++) { p = bm_scanline(bm, y); for (i=0; i < dy; i++) { p[i] ^= BM_ALLBITS; } } } /* turn the given bitmap upside down. This does not move the bitmap data or change the bm_base() address. */ static inline void bm_flip(potrace_bitmap_t *bm) { int dy = bm->dy; if (bm->h == 0 || bm->h == 1) { return; } bm->map = bm_scanline(bm, bm->h - 1); bm->dy = -dy; } /* resize the bitmap to the given new height. The bitmap data remains bottom-aligned (truncated at the top) when dy >= 0 and top-aligned (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on error with errno set. If the new height is <= the old one, no error should occur. If the new height is larger, the additional bitmap data is *not* initialized. */ static inline int bm_resize(potrace_bitmap_t *bm, int h) { int dy = bm->dy; ptrdiff_t newsize; potrace_word *newmap; if (dy < 0) { bm_flip(bm); } newsize = getsize(dy, h); if (newsize < 0) { errno = ENOMEM; goto error; } if (newsize == 0) { newsize = BM_WORDSIZE; /* make sure realloc() doesn't return NULL */ } newmap = (potrace_word *)realloc(bm->map, newsize); if (newmap == NULL) { goto error; } bm->map = newmap; bm->h = h; if (dy < 0) { bm_flip(bm); } return 0; error: if (dy < 0) { bm_flip(bm); } return 1; } #endif /* BITMAP_H */ dvisvgm-3.5/libs/potrace/config.h000066400000000000000000000001321501401750600170370ustar00rootroot00000000000000#ifndef CONFIG_H #define CONFIG_H #define VERSION "1.16" #define HAVE_INTTYPES_H 1 #endif dvisvgm-3.5/libs/potrace/curve.c000066400000000000000000000052051501401750600167170ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ /* private part of the path and curve data structures */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "potracelib.h" #include "lists.h" #include "curve.h" #define SAFE_CALLOC(var, n, typ) \ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error /* ---------------------------------------------------------------------- */ /* allocate and free path objects */ path_t *path_new(void) { path_t *p = NULL; privpath_t *priv = NULL; SAFE_CALLOC(p, 1, path_t); memset(p, 0, sizeof(path_t)); SAFE_CALLOC(priv, 1, privpath_t); memset(priv, 0, sizeof(privpath_t)); p->priv = priv; return p; calloc_error: free(p); free(priv); return NULL; } /* free the members of the given curve structure. Leave errno unchanged. */ static void privcurve_free_members(privcurve_t *curve) { free(curve->tag); free(curve->c); free(curve->vertex); free(curve->alpha); free(curve->alpha0); free(curve->beta); } /* free a path. Leave errno untouched. */ void path_free(path_t *p) { if (p) { if (p->priv) { free(p->priv->pt); free(p->priv->lon); free(p->priv->sums); free(p->priv->po); privcurve_free_members(&p->priv->curve); privcurve_free_members(&p->priv->ocurve); } free(p->priv); /* do not free p->fcurve ! */ } free(p); } /* free a pathlist, leaving errno untouched. */ void pathlist_free(path_t *plist) { path_t *p; list_forall_unlink(p, plist) { path_free(p); } } /* ---------------------------------------------------------------------- */ /* initialize and finalize curve structures */ typedef dpoint_t dpoint3_t[3]; /* initialize the members of the given curve structure to size m. Return 0 on success, 1 on error with errno set. */ int privcurve_init(privcurve_t *curve, int n) { memset(curve, 0, sizeof(privcurve_t)); curve->n = n; SAFE_CALLOC(curve->tag, n, int); SAFE_CALLOC(curve->c, n, dpoint3_t); SAFE_CALLOC(curve->vertex, n, dpoint_t); SAFE_CALLOC(curve->alpha, n, double); SAFE_CALLOC(curve->alpha0, n, double); SAFE_CALLOC(curve->beta, n, double); return 0; calloc_error: free(curve->tag); free(curve->c); free(curve->vertex); free(curve->alpha); free(curve->alpha0); free(curve->beta); return 1; } /* copy private to public curve structure */ void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c) { c->n = pc->n; c->tag = pc->tag; c->c = pc->c; } dvisvgm-3.5/libs/potrace/curve.h000066400000000000000000000053361501401750600167310ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifndef CURVE_H #define CURVE_H #include "auxiliary.h" /* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only defined for tag=POTRACE_CURVETO and is the alpha parameter of the curve: .c[-1][2]..c[0] = alpha*(.c[-1][2]..vertex), and c[2]..c[1] = alpha*(c[2]..vertex). Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2]. */ struct privcurve_s { int n; /* number of segments */ int *tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */ dpoint_t (*c)[3]; /* c[n][i]: control points. c[n][0] is unused for tag[n]=POTRACE_CORNER */ /* the remainder of this structure is special to privcurve, and is used in EPS debug output and special EPS "short coding". These fields are valid only if "alphacurve" is set. */ int alphacurve; /* have the following fields been initialized? */ dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */ double *alpha; /* only for POTRACE_CURVETO */ double *alpha0; /* "uncropped" alpha parameter - for debug output only */ double *beta; }; typedef struct privcurve_s privcurve_t; struct sums_s { double x; double y; double x2; double xy; double y2; }; typedef struct sums_s sums_t; /* the path structure is filled in with information about a given path as it is accumulated and passed through the different stages of the Potrace algorithm. Backends only need to read the fcurve and fm fields of this data structure, but debugging backends may read other fields. */ struct potrace_privpath_s { int len; point_t *pt; /* pt[len]: path as extracted from bitmap */ int *lon; /* lon[len]: (i,lon[i]) = longest straight line from i */ int x0, y0; /* origin for sums */ sums_t *sums; /* sums[len+1]: cache for fast summing */ int m; /* length of optimal polygon */ int *po; /* po[m]: optimal polygon */ privcurve_t curve; /* curve[m]: array of curve elements */ privcurve_t ocurve; /* ocurve[om]: array of curve elements */ privcurve_t *fcurve; /* final curve: this points to either curve or ocurve. Do not free this separately. */ }; typedef struct potrace_privpath_s potrace_privpath_t; /* shorter names */ typedef potrace_privpath_t privpath_t; typedef potrace_path_t path_t; path_t *path_new(void); void path_free(path_t *p); void pathlist_free(path_t *plist); int privcurve_init(privcurve_t *curve, int n); void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c); #endif /* CURVE_H */ dvisvgm-3.5/libs/potrace/decompose.c000066400000000000000000000344151501401750600175560ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef HAVE_INTTYPES_H #include #endif #include "potracelib.h" #include "curve.h" #include "lists.h" #include "bitmap.h" #include "decompose.h" #include "progress.h" /* ---------------------------------------------------------------------- */ /* deterministically and efficiently hash (x,y) into a pseudo-random bit */ static inline int detrand(int x, int y) { unsigned int z; static const unsigned char t[256] = { /* non-linear sequence: constant term of inverse in GF(8), mod x^8+x^4+x^3+x+1 */ 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, }; /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible 5-bit sequence */ z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93; z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff]; return z; } /* ---------------------------------------------------------------------- */ /* auxiliary bitmap manipulations */ /* set the excess padding to 0 */ static void bm_clearexcess(potrace_bitmap_t *bm) { potrace_word mask; int y; if (bm->w % BM_WORDBITS != 0) { mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS)); for (y=0; yh; y++) { *bm_index(bm, bm->w, y) &= mask; } } } struct bbox_s { int x0, x1, y0, y1; /* bounding box */ }; typedef struct bbox_s bbox_t; /* clear the bm, assuming the bounding box is set correctly (faster than clearing the whole bitmap) */ static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) { int imin = (bbox->x0 / BM_WORDBITS); int imax = ((bbox->x1 + BM_WORDBITS-1) / BM_WORDBITS); int i, y; for (y=bbox->y0; yy1; y++) { for (i=imin; i0) { return 1; } else if (ct<0) { return 0; } } return 0; } /* ---------------------------------------------------------------------- */ /* decompose image into paths */ /* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa must be a multiple of BM_WORDBITS. */ static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) { int xhi = x & -BM_WORDBITS; int xlo = x & (BM_WORDBITS-1); /* = x % BM_WORDBITS */ int i; if (xhipriv->len <= 0) { /* a path of length 0 is silly, but legal */ return; } y1 = p->priv->pt[p->priv->len-1].y; xa = p->priv->pt[0].x & -BM_WORDBITS; for (k=0; kpriv->len; k++) { x = p->priv->pt[k].x; y = p->priv->pt[k].y; if (y != y1) { /* efficiently invert the rectangle [x,xa] x [y,y1] */ xor_to_ref(bm, x, min(y,y1), xa); y1 = y; } } } /* Find the bounding box of a given path. Path is assumed to be of non-zero length. */ static void setbbox_path(bbox_t *bbox, path_t *p) { int x, y; int k; bbox->y0 = INT_MAX; bbox->y1 = 0; bbox->x0 = INT_MAX; bbox->x1 = 0; for (k=0; kpriv->len; k++) { x = p->priv->pt[k].x; y = p->priv->pt[k].y; if (x < bbox->x0) { bbox->x0 = x; } if (x > bbox->x1) { bbox->x1 = x; } if (y < bbox->y0) { bbox->y0 = y; } if (y > bbox->y1) { bbox->y1 = y; } } } /* compute a path in the given pixmap, separating black from white. Start path at the point (x0,x1), which must be an upper left corner of the path. Also compute the area enclosed by the path. Return a new path_t object, or NULL on error (note that a legitimate path cannot have length 0). Sign is required for correct interpretation of turnpolicies. */ static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turnpolicy) { int x, y, dirx, diry, len, size; uint64_t area; int c, d, tmp; point_t *pt, *pt1; path_t *p = NULL; x = x0; y = y0; dirx = 0; diry = -1; len = size = 0; pt = NULL; area = 0; while (1) { /* add point to path */ if (len>=size) { size += 100; size = (int)(1.3 * size); pt1 = (point_t *)realloc(pt, size * sizeof(point_t)); if (!pt1) { goto error; } pt = pt1; } pt[len].x = x; pt[len].y = y; len++; /* move to next point */ x += dirx; y += diry; area += x*diry; /* path complete? */ if (x==x0 && y==y0) { break; } /* determine next direction */ c = BM_GET(bm, x + (dirx+diry-1)/2, y + (diry-dirx-1)/2); d = BM_GET(bm, x + (dirx-diry-1)/2, y + (diry+dirx-1)/2); if (c && !d) { /* ambiguous turn */ if (turnpolicy == POTRACE_TURNPOLICY_RIGHT || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+') || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-') || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x,y)) || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y)) || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) { tmp = dirx; /* right turn */ dirx = diry; diry = -tmp; } else { tmp = dirx; /* left turn */ dirx = -diry; diry = tmp; } } else if (c) { /* right turn */ tmp = dirx; dirx = diry; diry = -tmp; } else if (!d) { /* left turn */ tmp = dirx; dirx = -diry; diry = tmp; } } /* while this path */ /* allocate new path object */ p = path_new(); if (!p) { goto error; } p->priv->pt = pt; p->priv->len = len; p->area = area <= INT_MAX ? area : INT_MAX; /* avoid overflow */ p->sign = sign; return p; error: free(pt); return NULL; } /* Give a tree structure to the given path list, based on "insideness" testing. I.e., path A is considered "below" path B if it is inside path B. The input pathlist is assumed to be ordered so that "outer" paths occur before "inner" paths. The tree structure is stored in the "childlist" and "sibling" components of the path_t structure. The linked list structure is also changed so that negative path components are listed immediately after their positive parent. Note: some backends may ignore the tree structure, others may use it e.g. to group path components. We assume that in the input, point 0 of each path is an "upper left" corner of the path, as returned by bm_to_pathlist. This makes it easy to find an "interior" point. The bm argument should be a bitmap of the correct size (large enough to hold all the paths), and will be used as scratch space. Return 0 on success or -1 on error with errno set. */ static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) { path_t *p, *p1; path_t *heap, *heap1; path_t *cur; path_t *head; path_t **plist_hook; /* for fast appending to linked list */ path_t **hook_in, **hook_out; /* for fast appending to linked list */ bbox_t bbox; bm_clear(bm, 0); /* save original "next" pointers */ list_forall(p, plist) { p->sibling = p->next; p->childlist = NULL; } heap = plist; /* the heap holds a list of lists of paths. Use "childlist" field for outer list, "next" field for inner list. Each of the sublists is to be turned into a tree. This code is messy, but it is actually fast. Each path is rendered exactly once. We use the heap to get a tail recursive algorithm: the heap holds a list of pathlists which still need to be transformed. */ while (heap) { /* unlink first sublist */ cur = heap; heap = heap->childlist; cur->childlist = NULL; /* unlink first path */ head = cur; cur = cur->next; head->next = NULL; /* render path */ xor_path(bm, head); setbbox_path(&bbox, head); /* now do insideness test for each element of cur; append it to head->childlist if it's inside head, else append it to head->next. */ hook_in=&head->childlist; hook_out=&head->next; list_forall_unlink(p, cur) { if (p->priv->pt[0].y <= bbox.y0) { list_insert_beforehook(p, hook_out); /* append the remainder of the list to hook_out */ *hook_out = cur; break; } if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y-1)) { list_insert_beforehook(p, hook_in); } else { list_insert_beforehook(p, hook_out); } } /* clear bm */ clear_bm_with_bbox(bm, &bbox); /* now schedule head->childlist and head->next for further processing */ if (head->next) { head->next->childlist = heap; heap = head->next; } if (head->childlist) { head->childlist->childlist = heap; heap = head->childlist; } } /* copy sibling structure from "next" to "sibling" component */ p = plist; while (p) { p1 = p->sibling; p->sibling = p->next; p = p1; } /* reconstruct a new linked list ("next") structure from tree ("childlist", "sibling") structure. This code is slightly messy, because we use a heap to make it tail recursive: the heap contains a list of childlists which still need to be processed. */ heap = plist; if (heap) { heap->next = NULL; /* heap is a linked list of childlists */ } plist = NULL; plist_hook = &plist; while (heap) { heap1 = heap->next; for (p=heap; p; p=p->sibling) { /* p is a positive path */ /* append to linked list */ list_insert_beforehook(p, plist_hook); /* go through its children */ for (p1=p->childlist; p1; p1=p1->sibling) { /* append to linked list */ list_insert_beforehook(p1, plist_hook); /* append its childlist to heap, if non-empty */ if (p1->childlist) { list_append(path_t, heap1, p1->childlist); } } } heap = heap1; } return; } /* find the next set pixel in a row <= y. Pixels are searched first left-to-right, then top-down. In other words, (x,y)<(x',y') if y>y' or y=y' and x=0; y--) { for (x=x0; xw && x>=0; x+=(unsigned)BM_WORDBITS) { if (*bm_index(bm, x, y)) { while (!BM_GET(bm, x, y)) { x++; } /* found */ *xp = x; *yp = y; return 0; } } x0 = 0; } /* not found */ return 1; } /* Decompose the given bitmap into paths. Returns a linked list of path_t objects with the fields len, pt, area, sign filled in. Returns 0 on success with plistp set, or -1 on error with errno set. */ int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress) { int x; int y; path_t *p; path_t *plist = NULL; /* linked list of path objects */ path_t **plist_hook = &plist; /* used to speed up appending to linked list */ potrace_bitmap_t *bm1 = NULL; int sign; bm1 = bm_dup(bm); if (!bm1) { goto error; } /* be sure the byte padding on the right is set to 0, as the fast pixel search below relies on it */ bm_clearexcess(bm1); /* iterate through components */ x = 0; y = bm1->h - 1; while (findnext(bm1, &x, &y) == 0) { /* calculate the sign by looking at the original */ sign = BM_GET(bm, x, y) ? '+' : '-'; /* calculate the path */ p = findpath(bm1, x, y+1, sign, param->turnpolicy); if (p==NULL) { goto error; } /* update buffered image */ xor_path(bm1, p); /* if it's a turd, eliminate it, else append it to the list */ if (p->area <= param->turdsize) { path_free(p); } else { list_insert_beforehook(p, plist_hook); } if (bm1->h > 0) { /* to be sure */ progress_update(1-y/(double)bm1->h, progress); } } pathlist_to_tree(plist, bm1); bm_free(bm1); *plistp = plist; progress_update(1.0, progress); return 0; error: bm_free(bm1); list_forall_unlink(p, plist) { path_free(p); } return -1; } dvisvgm-3.5/libs/potrace/decompose.h000066400000000000000000000006721501401750600175610ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifndef DECOMPOSE_H #define DECOMPOSE_H #include "potracelib.h" #include "progress.h" #include "curve.h" int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress); #endif /* DECOMPOSE_H */ dvisvgm-3.5/libs/potrace/lists.h000066400000000000000000000255561501401750600167510ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifndef _PS_LISTS_H #define _PS_LISTS_H /* here we define some general list macros. Because they are macros, they should work on any datatype with a "->next" component. Some of them use a "hook". If elt and list are of type t* then hook is of type t**. A hook stands for an insertion point in the list, i.e., either before the first element, or between two elements, or after the last element. If an operation "sets the hook" for an element, then the hook is set to just before the element. One can insert something at a hook. One can also unlink at a hook: this means, unlink the element just after the hook. By "to unlink", we mean the element is removed from the list, but not deleted. Thus, it and its components still need to be freed. */ /* Note: these macros are somewhat experimental. Only the ones that are actually *used* have been tested. So be careful to test any that you use. Looking at the output of the preprocessor, "gcc -E" (possibly piped though "indent"), might help too. Also: these macros define some internal (local) variables that start with "_". */ /* we enclose macro definitions whose body consists of more than one statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'. The reason is that we want to be able to use the macro in a context such as "if (...) macro(...); else ...". If we didn't use this obscure trick, we'd have to omit the ";" in such cases. */ #define MACRO_BEGIN do { #define MACRO_END } while (0) /* ---------------------------------------------------------------------- */ /* macros for singly-linked lists */ /* traverse list. At the end, elt is set to NULL. */ #define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next) /* set elt to the first element of list satisfying boolean condition c, or NULL if not found */ #define list_find(elt, list, c) \ MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END /* like forall, except also set hook for elt. */ #define list_forall2(elt, list, hook) \ for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next) /* same as list_find, except also set hook for elt. */ #define list_find2(elt, list, c, hook) \ MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END /* same, except only use hook. */ #define _list_forall_hook(list, hook) \ for (hook=&list; *hook!=NULL; hook=&(*hook)->next) /* same, except only use hook. Note: c may only refer to *hook, not elt. */ #define _list_find_hook(list, c, hook) \ MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END /* insert element after hook */ #define list_insert_athook(elt, hook) \ MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END /* insert element before hook */ #define list_insert_beforehook(elt, hook) \ MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END /* unlink element after hook, let elt be unlinked element, or NULL. hook remains. */ #define list_unlink_athook(list, elt, hook) \ MACRO_BEGIN \ elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\ MACRO_END /* unlink the specific element, if it is in the list. Otherwise, set elt to NULL */ #define list_unlink(listtype, list, elt) \ MACRO_BEGIN \ listtype **_hook; \ _list_find_hook(list, *_hook==elt, _hook); \ list_unlink_athook(list, elt, _hook); \ MACRO_END /* prepend elt to list */ #define list_prepend(list, elt) \ MACRO_BEGIN elt->next = list; list = elt; MACRO_END /* append elt to list. */ #define list_append(listtype, list, elt) \ MACRO_BEGIN \ listtype **_hook; \ _list_forall_hook(list, _hook) {} \ list_insert_athook(elt, _hook); \ MACRO_END /* unlink the first element that satisfies the condition. */ #define list_unlink_cond(listtype, list, elt, c) \ MACRO_BEGIN \ listtype **_hook; \ list_find2(elt, list, c, _hook); \ list_unlink_athook(list, elt, _hook); \ MACRO_END /* let elt be the nth element of the list, starting to count from 0. Return NULL if out of bounds. */ #define list_nth(elt, list, n) \ MACRO_BEGIN \ int _x; /* only evaluate n once */ \ for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \ MACRO_END /* let elt be the nth element of the list, starting to count from 0. Return NULL if out of bounds. */ #define list_nth_hook(elt, list, n, hook) \ MACRO_BEGIN \ int _x; /* only evaluate n once */ \ for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \ MACRO_END /* set n to the length of the list */ #define list_length(listtype, list, n) \ MACRO_BEGIN \ listtype *_elt; \ n=0; \ list_forall(_elt, list) \ n++; \ MACRO_END /* set n to the index of the first element satisfying cond, or -1 if none found. Also set elt to the element, or NULL if none found. */ #define list_index(list, n, elt, c) \ MACRO_BEGIN \ n=0; \ list_forall(elt, list) { \ if (c) break; \ n++; \ } \ if (!elt) \ n=-1; \ MACRO_END /* set n to the number of elements in the list that satisfy condition c */ #define list_count(list, n, elt, c) \ MACRO_BEGIN \ n=0; \ list_forall(elt, list) { \ if (c) n++; \ } \ MACRO_END /* let elt be each element of the list, unlinked. At the end, set list=NULL. */ #define list_forall_unlink(elt, list) \ for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list) /* reverse a list (efficient) */ #define list_reverse(listtype, list) \ MACRO_BEGIN \ listtype *_list1=NULL, *elt; \ list_forall_unlink(elt, list) \ list_prepend(_list1, elt); \ list = _list1; \ MACRO_END /* insert the element ELT just before the first element TMP of the list for which COND holds. Here COND must be a condition of ELT and TMP. Typical usage is to insert an element into an ordered list: for instance, list_insert_ordered(listtype, list, elt, tmp, elt->size <= tmp->size). Note: if we give a "less than or equal" condition, the new element will be inserted just before a sequence of equal elements. If we give a "less than" condition, the new element will be inserted just after a list of equal elements. Note: it is much more efficient to construct a list with list_prepend and then order it with list_merge_sort, than to construct it with list_insert_ordered. */ #define list_insert_ordered(listtype, list, elt, tmp, cond) \ MACRO_BEGIN \ listtype **_hook; \ _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \ list_insert_athook(elt, _hook); \ MACRO_END /* sort the given list, according to the comparison condition. Typical usage is list_sort(listtype, list, a, b, a->size < b->size). Note: if we give "less than or equal" condition, each segment of equal elements will be reversed in order. If we give a "less than" condition, each segment of equal elements will retain the original order. The latter is slower but sometimes prettier. Average running time: n*n/2. */ #define list_sort(listtype, list, a, b, cond) \ MACRO_BEGIN \ listtype *_newlist=NULL; \ list_forall_unlink(a, list) \ list_insert_ordered(listtype, _newlist, a, b, cond); \ list = _newlist; \ MACRO_END /* a much faster sort algorithm (merge sort, n log n worst case). It is required that the list type has an additional, unused next1 component. Note there is no curious reversal of order of equal elements as for list_sort. */ #define list_mergesort(listtype, list, a, b, cond) \ MACRO_BEGIN \ listtype *_elt, **_hook1; \ \ for (_elt=list; _elt; _elt=_elt->next1) { \ _elt->next1 = _elt->next; \ _elt->next = NULL; \ } \ do { \ _hook1 = &(list); \ while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \ _elt = b->next1; \ _list_merge_cond(listtype, a, b, cond, *_hook1); \ _hook1 = &((*_hook1)->next1); \ *_hook1 = _elt; \ } \ } while (_hook1 != &(list)); \ MACRO_END /* merge two sorted lists. Store result at &result */ #define _list_merge_cond(listtype, a, b, cond, result) \ MACRO_BEGIN \ listtype **_hook; \ _hook = &(result); \ while (1) { \ if (a==NULL) { \ *_hook = b; \ break; \ } else if (b==NULL) { \ *_hook = a; \ break; \ } else if (cond) { \ *_hook = a; \ _hook = &(a->next); \ a = a->next; \ } else { \ *_hook = b; \ _hook = &(b->next); \ b = b->next; \ } \ } \ MACRO_END /* ---------------------------------------------------------------------- */ /* macros for doubly-linked lists */ #define dlist_append(head, end, elt) \ MACRO_BEGIN \ elt->prev = end; \ elt->next = NULL; \ if (end) { \ end->next = elt; \ } else { \ head = elt; \ } \ end = elt; \ MACRO_END /* let elt be each element of the list, unlinked. At the end, set list=NULL. */ #define dlist_forall_unlink(elt, head, end) \ for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head) /* unlink the first element of the list */ #define dlist_unlink_first(head, end, elt) \ MACRO_BEGIN \ elt = head; \ if (head) { \ head = head->next; \ if (head) { \ head->prev = NULL; \ } else { \ end = NULL; \ } \ elt->prev = NULL; \ elt->next = NULL; \ } \ MACRO_END #endif /* _PS_LISTS_H */ dvisvgm-3.5/libs/potrace/potracelib.c000066400000000000000000000060621501401750600177210ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "potracelib.h" #include "curve.h" #include "decompose.h" #include "trace.h" #include "progress.h" /* default parameters */ static const potrace_param_t param_default = { 2, /* turdsize */ POTRACE_TURNPOLICY_MINORITY, /* turnpolicy */ 1.0, /* alphamax */ 1, /* opticurve */ 0.2, /* opttolerance */ { NULL, /* callback function */ NULL, /* callback data */ 0.0, 1.0, /* progress range */ 0.0, /* granularity */ }, }; /* Return a fresh copy of the set of default parameters, or NULL on failure with errno set. */ potrace_param_t *potrace_param_default(void) { potrace_param_t *p; p = (potrace_param_t *) malloc(sizeof(potrace_param_t)); if (!p) { return NULL; } memcpy(p, ¶m_default, sizeof(potrace_param_t)); return p; } /* On success, returns a Potrace state st with st->status == POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state could be created (with errno set), or returns an incomplete Potrace state (with st->status == POTRACE_STATUS_INCOMPLETE, and with errno set). Complete or incomplete Potrace state can be freed with potrace_state_free(). */ potrace_state_t *potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm) { int r; path_t *plist = NULL; potrace_state_t *st; progress_t prog; progress_t subprog; /* prepare private progress bar state */ prog.callback = param->progress.callback; prog.data = param->progress.data; prog.min = param->progress.min; prog.max = param->progress.max; prog.epsilon = param->progress.epsilon; prog.d_prev = param->progress.min; /* allocate state object */ st = (potrace_state_t *)malloc(sizeof(potrace_state_t)); if (!st) { return NULL; } progress_subrange_start(0.0, 0.1, &prog, &subprog); /* process the image */ r = bm_to_pathlist(bm, &plist, param, &subprog); if (r) { free(st); return NULL; } st->status = POTRACE_STATUS_OK; st->plist = plist; st->priv = NULL; /* private state currently unused */ progress_subrange_end(&prog, &subprog); progress_subrange_start(0.1, 1.0, &prog, &subprog); /* partial success. */ r = process_path(plist, param, &subprog); if (r) { st->status = POTRACE_STATUS_INCOMPLETE; } progress_subrange_end(&prog, &subprog); return st; } /* free a Potrace state, without disturbing errno. */ void potrace_state_free(potrace_state_t *st) { pathlist_free(st->plist); free(st); } /* free a parameter list, without disturbing errno. */ void potrace_param_free(potrace_param_t *p) { free(p); } const char *potrace_version(void) { return "potracelib " VERSION ""; } dvisvgm-3.5/libs/potrace/potracelib.h000066400000000000000000000107351501401750600177300ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifndef POTRACELIB_H #define POTRACELIB_H /* this file defines the API for the core Potrace library. For a more detailed description of the API, see potracelib.pdf */ #ifdef __cplusplus extern "C" { #endif /* ---------------------------------------------------------------------- */ /* tracing parameters */ /* turn policies */ #define POTRACE_TURNPOLICY_BLACK 0 #define POTRACE_TURNPOLICY_WHITE 1 #define POTRACE_TURNPOLICY_LEFT 2 #define POTRACE_TURNPOLICY_RIGHT 3 #define POTRACE_TURNPOLICY_MINORITY 4 #define POTRACE_TURNPOLICY_MAJORITY 5 #define POTRACE_TURNPOLICY_RANDOM 6 /* structure to hold progress bar callback data */ struct potrace_progress_s { void (*callback)(double progress, void *privdata); /* callback fn */ void *data; /* callback function's private data */ double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */ double epsilon; /* granularity: can skip smaller increments */ }; typedef struct potrace_progress_s potrace_progress_t; /* structure to hold tracing parameters */ struct potrace_param_s { int turdsize; /* area of largest path to be ignored */ int turnpolicy; /* resolves ambiguous turns in path decomposition */ double alphamax; /* corner threshold */ int opticurve; /* use curve optimization? */ double opttolerance; /* curve optimization tolerance */ potrace_progress_t progress; /* progress callback function */ }; typedef struct potrace_param_s potrace_param_t; /* ---------------------------------------------------------------------- */ /* bitmaps */ /* native word size */ typedef unsigned long potrace_word; /* Internal bitmap format. The n-th scanline starts at scanline(n) = (map + n*dy). Raster data is stored as a sequence of potrace_words (NOT bytes). The leftmost bit of scanline n is the most significant bit of scanline(n)[0]. */ struct potrace_bitmap_s { int w, h; /* width and height, in pixels */ int dy; /* words per scanline (not bytes) */ potrace_word *map; /* raw data, dy*h words */ }; typedef struct potrace_bitmap_s potrace_bitmap_t; /* ---------------------------------------------------------------------- */ /* curves */ /* point */ struct potrace_dpoint_s { double x, y; }; typedef struct potrace_dpoint_s potrace_dpoint_t; /* segment tags */ #define POTRACE_CURVETO 1 #define POTRACE_CORNER 2 /* closed curve segment */ struct potrace_curve_s { int n; /* number of segments */ int *tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */ potrace_dpoint_t (*c)[3]; /* c[n][3]: control points. c[n][0] is unused for tag[n]=POTRACE_CORNER */ }; typedef struct potrace_curve_s potrace_curve_t; /* Linked list of signed curve segments. Also carries a tree structure. */ struct potrace_path_s { int area; /* area of the bitmap path */ int sign; /* '+' or '-', depending on orientation */ potrace_curve_t curve; /* this path's vector data */ struct potrace_path_s *next; /* linked list structure */ struct potrace_path_s *childlist; /* tree structure */ struct potrace_path_s *sibling; /* tree structure */ struct potrace_privpath_s *priv; /* private state */ }; typedef struct potrace_path_s potrace_path_t; /* ---------------------------------------------------------------------- */ /* Potrace state */ #define POTRACE_STATUS_OK 0 #define POTRACE_STATUS_INCOMPLETE 1 struct potrace_state_s { int status; potrace_path_t *plist; /* vector data */ struct potrace_privstate_s *priv; /* private state */ }; typedef struct potrace_state_s potrace_state_t; /* ---------------------------------------------------------------------- */ /* API functions */ /* get default parameters */ potrace_param_t *potrace_param_default(void); /* free parameter set */ void potrace_param_free(potrace_param_t *p); /* trace a bitmap */ potrace_state_t *potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm); /* free a Potrace state */ void potrace_state_free(potrace_state_t *st); /* return a static plain text version string identifying this version of potracelib */ const char *potrace_version(void); #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* POTRACELIB_H */ dvisvgm-3.5/libs/potrace/progress.h000066400000000000000000000051361501401750600174470ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ /* operations on potrace_progress_t objects, which are defined in potracelib.h. Note: the code attempts to minimize runtime overhead when no progress monitoring was requested. It also tries to minimize excessive progress calculations beneath the "epsilon" threshold. */ #ifndef PROGRESS_H #define PROGRESS_H /* structure to hold progress bar callback data */ struct progress_s { void (*callback)(double progress, void *privdata); /* callback fn */ void *data; /* callback function's private data */ double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */ double epsilon; /* granularity: can skip smaller increments */ double b; /* upper limit of subrange in superrange units */ double d_prev; /* previous value of d */ }; typedef struct progress_s progress_t; /* notify given progress object of current progress. Note that d is given in the 0.0-1.0 range, which will be scaled and translated to the progress object's range. */ static inline void progress_update(double d, progress_t *prog) { double d_scaled; if (prog != NULL && prog->callback != NULL) { d_scaled = prog->min * (1-d) + prog->max * d; if (d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon) { prog->callback(prog->min * (1-d) + prog->max * d, prog->data); prog->d_prev = d_scaled; } } } /* start a subrange of the given progress object. The range is narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range is below granularity threshold, disable further subdivisions. */ static inline void progress_subrange_start(double a, double b, const progress_t *prog, progress_t *sub) { double min, max; if (prog == NULL || prog->callback == NULL) { sub->callback = NULL; return; } min = prog->min * (1-a) + prog->max * a; max = prog->min * (1-b) + prog->max * b; if (max - min < prog->epsilon) { sub->callback = NULL; /* no further progress info in subrange */ sub->b = b; return; } sub->callback = prog->callback; sub->data = prog->data; sub->epsilon = prog->epsilon; sub->min = min; sub->max = max; sub->d_prev = prog->d_prev; return; } static inline void progress_subrange_end(progress_t *prog, progress_t *sub) { if (prog != NULL && prog->callback != NULL) { if (sub->callback == NULL) { progress_update(sub->b, prog); } else { prog->d_prev = sub->d_prev; } } } #endif /* PROGRESS_H */ dvisvgm-3.5/libs/potrace/trace.c000066400000000000000000000772101501401750600166760ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ /* transform jaggy paths into smooth curves */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "potracelib.h" #include "curve.h" #include "lists.h" #include "auxiliary.h" #include "trace.h" #include "progress.h" #define INFTY 10000000 /* it suffices that this is longer than any path; it need not be really infinite */ #define COS179 -0.999847695156 /* the cosine of 179 degrees */ /* ---------------------------------------------------------------------- */ #define SAFE_CALLOC(var, n, typ) \ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error /* ---------------------------------------------------------------------- */ /* auxiliary functions */ /* return a direction that is 90 degrees counterclockwise from p2-p0, but then restricted to one of the major wind directions (n, nw, w, etc) */ static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) { point_t r; r.y = sign(p2.x-p0.x); r.x = -sign(p2.y-p0.y); return r; } /* return (p1-p0)x(p2-p0), the area of the parallelogram */ static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) { double x1, y1, x2, y2; x1 = p1.x-p0.x; y1 = p1.y-p0.y; x2 = p2.x-p0.x; y2 = p2.y-p0.y; return x1*y2 - x2*y1; } /* ddenom/dpara have the property that the square of radius 1 centered at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */ static inline double ddenom(dpoint_t p0, dpoint_t p2) { point_t r = dorth_infty(p0, p2); return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y); } /* return 1 if a <= b < c < a, in a cyclic sense (mod n) */ static inline int cyclic(int a, int b, int c) { if (a<=c) { return (a<=b && blen; sums_t *sums = pp->sums; double x, y, x2, xy, y2; double k; double a, b, c, lambda2, l; int r=0; /* rotations from i to j */ while (j>=n) { j-=n; r+=1; } while (i>=n) { i-=n; r-=1; } while (j<0) { j+=n; r-=1; } while (i<0) { i+=n; r+=1; } x = sums[j+1].x-sums[i].x+r*sums[n].x; y = sums[j+1].y-sums[i].y+r*sums[n].y; x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2; xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy; y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2; k = j+1-i+r*n; ctr->x = x/k; ctr->y = y/k; a = (x2-(double)x*x/k)/k; b = (xy-(double)x*y/k)/k; c = (y2-(double)y*y/k)/k; lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */ /* now find e.vector for lambda2 */ a -= lambda2; c -= lambda2; if (fabs(a) >= fabs(c)) { l = sqrt(a*a+b*b); if (l!=0) { dir->x = -b/l; dir->y = a/l; } } else { l = sqrt(c*c+b*b); if (l!=0) { dir->x = -c/l; dir->y = b/l; } } if (l==0) { dir->x = dir->y = 0; /* sometimes this can happen when k=4: the two eigenvalues coincide */ } } /* the type of (affine) quadratic forms, represented as symmetric 3x3 matrices. The value of the quadratic form at a vector (x,y) is v^t Q v, where v = (x,y,1)^t. */ typedef double quadform_t[3][3]; /* Apply quadratic form Q to vector w = (w.x,w.y) */ static inline double quadform(quadform_t Q, dpoint_t w) { double v[3]; int i, j; double sum; v[0] = w.x; v[1] = w.y; v[2] = 1; sum = 0.0; for (i=0; i<3; i++) { for (j=0; j<3; j++) { sum += v[i] * Q[i][j] * v[j]; } } return sum; } /* calculate p1 x p2 */ static inline int xprod(point_t p1, point_t p2) { return p1.x*p2.y - p1.y*p2.x; } /* calculate (p1-p0)x(p3-p2) */ static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) { double x1, y1, x2, y2; x1 = p1.x - p0.x; y1 = p1.y - p0.y; x2 = p3.x - p2.x; y2 = p3.y - p2.y; return x1*y2 - x2*y1; } /* calculate (p1-p0)*(p2-p0) */ static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) { double x1, y1, x2, y2; x1 = p1.x - p0.x; y1 = p1.y - p0.y; x2 = p2.x - p0.x; y2 = p2.y - p0.y; return x1*x2 + y1*y2; } /* calculate (p1-p0)*(p3-p2) */ static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) { double x1, y1, x2, y2; x1 = p1.x - p0.x; y1 = p1.y - p0.y; x2 = p3.x - p2.x; y2 = p3.y - p2.y; return x1*x2 + y1*y2; } /* calculate distance between two points */ static inline double ddist(dpoint_t p, dpoint_t q) { return sqrt(sq(p.x-q.x)+sq(p.y-q.y)); } /* calculate point of a bezier curve */ static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) { double s = 1-t; dpoint_t res; /* Note: a good optimizing compiler (such as gcc-3) reduces the following to 16 multiplications, using common subexpression elimination. */ res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x; res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y; return res; } /* calculate the point t in [0..1] on the (convex) bezier curve (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no solution in [0..1]. */ static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) { double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */ double a, b, c; /* a t^2 + b t + c = 0 */ double d, s, r1, r2; A = cprod(p0, p1, q0, q1); B = cprod(p1, p2, q0, q1); C = cprod(p2, p3, q0, q1); a = A - 2*B + C; b = -2*A + 2*B; c = A; d = b*b - 4*a*c; if (a==0 || d<0) { return -1.0; } s = sqrt(d); r1 = (-b + s) / (2 * a); r2 = (-b - s) / (2 * a); if (r1 >= 0 && r1 <= 1) { return r1; } else if (r2 >= 0 && r2 <= 1) { return r2; } else { return -1.0; } } /* ---------------------------------------------------------------------- */ /* Preparation: fill in the sum* fields of a path (used for later rapid summing). Return 0 on success, 1 with errno set on failure. */ static int calc_sums(privpath_t *pp) { int i, x, y; int n = pp->len; SAFE_CALLOC(pp->sums, pp->len+1, sums_t); /* origin */ pp->x0 = pp->pt[0].x; pp->y0 = pp->pt[0].y; /* preparatory computation for later fast summing */ pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0; for (i=0; ipt[i].x - pp->x0; y = pp->pt[i].y - pp->y0; pp->sums[i+1].x = pp->sums[i].x + x; pp->sums[i+1].y = pp->sums[i].y + y; pp->sums[i+1].x2 = pp->sums[i].x2 + (double)x*x; pp->sums[i+1].xy = pp->sums[i].xy + (double)x*y; pp->sums[i+1].y2 = pp->sums[i].y2 + (double)y*y; } return 0; calloc_error: return 1; } /* ---------------------------------------------------------------------- */ /* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the "lon" component of a path object (based on pt/len). For each i, lon[i] is the furthest index such that a straight line can be drawn from i to lon[i]. Return 1 on error with errno set, else 0. */ /* this algorithm depends on the fact that the existence of straight subpaths is a triplewise property. I.e., there exists a straight line through squares i0,...,in iff there exists a straight line through i,j,k, for all i0<=i= 0 and xprod(constraint[1], cur) <= 0. */ /* Remark for Potrace 1.1: the current implementation of calc_lon is more complex than the implementation found in Potrace 1.0, but it is considerably faster. The introduction of the "nc" data structure means that we only have to test the constraints for "corner" points. On a typical input file, this speeds up the calc_lon function by a factor of 31.2, thereby decreasing its time share within the overall Potrace algorithm from 72.6% to 7.82%, and speeding up the overall algorithm by a factor of 3.36. On another input file, calc_lon was sped up by a factor of 6.7, decreasing its time share from 51.4% to 13.61%, and speeding up the overall algorithm by a factor of 1.78. In any case, the savings are substantial. */ /* returns 0 on success, 1 on error with errno set */ static int calc_lon(privpath_t *pp) { point_t *pt = pp->pt; int n = pp->len; int i, j, k, k1; int ct[4], dir; point_t constraint[2]; point_t cur; point_t off; int *pivk = NULL; /* pivk[n] */ int *nc = NULL; /* nc[n]: next corner */ point_t dk; /* direction of k-k1 */ int a, b, c, d; SAFE_CALLOC(pivk, n, int); SAFE_CALLOC(nc, n, int); /* initialize the nc data structure. Point from each point to the furthest future point to which it is connected by a vertical or horizontal segment. We take advantage of the fact that there is always a direction change at 0 (due to the path decomposition algorithm). But even if this were not so, there is no harm, as in practice, correctness does not depend on the word "furthest" above. */ k = 0; for (i=n-1; i>=0; i--) { if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) { k = i+1; /* necessarily ilon, n, int); /* determine pivot points: for each i, let pivk[i] be the furthest k such that all j with i=0; i--) { ct[0] = ct[1] = ct[2] = ct[3] = 0; /* keep track of "directions" that have occurred */ dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2; ct[dir]++; constraint[0].x = 0; constraint[0].y = 0; constraint[1].x = 0; constraint[1].y = 0; /* find the next k such that no straight line from i to k */ k = nc[i]; k1 = i; while (1) { dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2; ct[dir]++; /* if all four "directions" have occurred, cut this path */ if (ct[0] && ct[1] && ct[2] && ct[3]) { pivk[i] = k1; goto foundk; } cur.x = pt[k].x - pt[i].x; cur.y = pt[k].y - pt[i].y; /* see if current constraint is violated */ if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) { goto constraint_viol; } /* else, update constraint */ if (abs(cur.x) <= 1 && abs(cur.y) <= 1) { /* no constraint */ } else { off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1); off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1); if (xprod(constraint[0], off) >= 0) { constraint[0] = off; } off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1); off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1); if (xprod(constraint[1], off) <= 0) { constraint[1] = off; } } k1 = k; k = nc[k1]; if (!cyclic(k,i,k1)) { break; } } constraint_viol: /* k1 was the last "corner" satisfying the current constraint, and k is the first one violating it. We now need to find the last point along k1..k which satisfied the constraint. */ dk.x = sign(pt[k].x-pt[k1].x); dk.y = sign(pt[k].y-pt[k1].y); cur.x = pt[k1].x - pt[i].x; cur.y = pt[k1].y - pt[i].y; /* find largest integer j such that xprod(constraint[0], cur+j*dk) >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity of xprod. */ a = xprod(constraint[0], cur); b = xprod(constraint[0], dk); c = xprod(constraint[1], cur); d = xprod(constraint[1], dk); /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This can be solved with integer arithmetic. */ j = INFTY; if (b<0) { j = floordiv(a,-b); } if (d>0) { j = min(j, floordiv(-c,d)); } pivk[i] = mod(k1+j,n); foundk: ; } /* for i */ /* clean up: for each i, let lon[i] be the largest k such that for all i' with i<=i'lon[n-1]=j; for (i=n-2; i>=0; i--) { if (cyclic(i+1,pivk[i],j)) { j=pivk[i]; } pp->lon[i]=j; } for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) { pp->lon[i] = j; } free(pivk); free(nc); return 0; calloc_error: free(pivk); free(nc); return 1; } /* ---------------------------------------------------------------------- */ /* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */ /* Auxiliary function: calculate the penalty of an edge from i to j in the given path. This needs the "lon" and "sum*" data. */ static double penalty3(privpath_t *pp, int i, int j) { int n = pp->len; point_t *pt = pp->pt; sums_t *sums = pp->sums; /* assume 0<=i=n) { j -= n; r = 1; } /* critical inner loop: the "if" gives a 4.6 percent speedup */ if (r == 0) { x = sums[j+1].x - sums[i].x; y = sums[j+1].y - sums[i].y; x2 = sums[j+1].x2 - sums[i].x2; xy = sums[j+1].xy - sums[i].xy; y2 = sums[j+1].y2 - sums[i].y2; k = j+1 - i; } else { x = sums[j+1].x - sums[i].x + sums[n].x; y = sums[j+1].y - sums[i].y + sums[n].y; x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2; xy = sums[j+1].xy - sums[i].xy + sums[n].xy; y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2; k = j+1 - i + n; } px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x; py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y; ey = (pt[j].x - pt[i].x); ex = -(pt[j].y - pt[i].y); a = ((x2 - 2*x*px) / k + px*px); b = ((xy - x*py - y*px) / k + px*py); c = ((y2 - 2*y*py) / k + py*py); s = ex*ex*a + 2*ex*ey*b + ey*ey*c; return sqrt(s); } /* find the optimal polygon. Fill in the m and po components. Return 1 on failure with errno set, else 0. Non-cyclic version: assumes i=0 is in the polygon. Fixme: implement cyclic version. */ static int bestpolygon(privpath_t *pp) { int i, j, m, k; int n = pp->len; double *pen = NULL; /* pen[n+1]: penalty vector */ int *prev = NULL; /* prev[n+1]: best path pointer vector */ int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */ int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */ int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */ int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */ double thispen; double best; int c; SAFE_CALLOC(pen, n+1, double); SAFE_CALLOC(prev, n+1, int); SAFE_CALLOC(clip0, n, int); SAFE_CALLOC(clip1, n+1, int); SAFE_CALLOC(seg0, n+1, int); SAFE_CALLOC(seg1, n+1, int); /* calculate clipped paths */ for (i=0; ilon[mod(i-1,n)]-1,n); if (c == i) { c = mod(i+1,n); } if (c < i) { clip0[i] = n; } else { clip0[i] = c; } } /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff clip1[j] <= i, for i,j=0..n. */ j = 1; for (i=0; i0; j--) { seg1[j] = i; i = clip1[i]; } seg1[0] = 0; /* now find the shortest path with m segments, based on penalty3 */ /* note: the outer 2 loops jointly have at most n iterations, thus the worst-case behavior here is quadratic. In practice, it is close to linear since the inner loop tends to be short. */ pen[0]=0; for (j=1; j<=m; j++) { for (i=seg1[j]; i<=seg0[j]; i++) { best = -1; for (k=seg0[j-1]; k>=clip1[i]; k--) { thispen = penalty3(pp, k, i) + pen[k]; if (best < 0 || thispen < best) { prev[i] = k; best = thispen; } } pen[i] = best; } } pp->m = m; SAFE_CALLOC(pp->po, m, int); /* read off shortest path */ for (i=n, j=m-1; i>0; j--) { i = prev[i]; pp->po[j] = i; } free(pen); free(prev); free(clip0); free(clip1); free(seg0); free(seg1); return 0; calloc_error: free(pen); free(prev); free(clip0); free(clip1); free(seg0); free(seg1); return 1; } /* ---------------------------------------------------------------------- */ /* Stage 3: vertex adjustment (Sec. 2.3.1). */ /* Adjust vertices of optimal polygon: calculate the intersection of the two "optimal" line segments, then move it into the unit square if it lies outside. Return 1 with errno set on error; 0 on success. */ static int adjust_vertices(privpath_t *pp) { int m = pp->m; int *po = pp->po; int n = pp->len; point_t *pt = pp->pt; int x0 = pp->x0; int y0 = pp->y0; dpoint_t *ctr = NULL; /* ctr[m] */ dpoint_t *dir = NULL; /* dir[m] */ quadform_t *q = NULL; /* q[m] */ double v[3]; double d; int i, j, k, l; dpoint_t s; int r; SAFE_CALLOC(ctr, m, dpoint_t); SAFE_CALLOC(dir, m, dpoint_t); SAFE_CALLOC(q, m, quadform_t); r = privcurve_init(&pp->curve, m); if (r) { goto calloc_error; } /* calculate "optimal" point-slope representation for each line segment */ for (i=0; iQ[1][1]) { v[0] = -Q[0][1]; v[1] = Q[0][0]; } else if (Q[1][1]) { v[0] = -Q[1][1]; v[1] = Q[1][0]; } else { v[0] = 1; v[1] = 0; } d = sq(v[0]) + sq(v[1]); v[2] = - v[1] * s.y - v[0] * s.x; for (l=0; l<3; l++) { for (k=0; k<3; k++) { Q[l][k] += v[l] * v[k] / d; } } } dx = fabs(w.x-s.x); dy = fabs(w.y-s.y); if (dx <= .5 && dy <= .5) { pp->curve.vertex[i].x = w.x+x0; pp->curve.vertex[i].y = w.y+y0; continue; } /* the minimum was not in the unit square; now minimize quadratic on boundary of square */ min = quadform(Q, s); xmin = s.x; ymin = s.y; if (Q[0][0] == 0.0) { goto fixx; } for (z=0; z<2; z++) { /* value of the y-coordinate */ w.y = s.y-0.5+z; w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0]; dx = fabs(w.x-s.x); cand = quadform(Q, w); if (dx <= .5 && cand < min) { min = cand; xmin = w.x; ymin = w.y; } } fixx: if (Q[1][1] == 0.0) { goto corners; } for (z=0; z<2; z++) { /* value of the x-coordinate */ w.x = s.x-0.5+z; w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1]; dy = fabs(w.y-s.y); cand = quadform(Q, w); if (dy <= .5 && cand < min) { min = cand; xmin = w.x; ymin = w.y; } } corners: /* check four corners */ for (l=0; l<2; l++) { for (k=0; k<2; k++) { w.x = s.x-0.5+l; w.y = s.y-0.5+k; cand = quadform(Q, w); if (cand < min) { min = cand; xmin = w.x; ymin = w.y; } } } pp->curve.vertex[i].x = xmin + x0; pp->curve.vertex[i].y = ymin + y0; continue; } free(ctr); free(dir); free(q); return 0; calloc_error: free(ctr); free(dir); free(q); return 1; } /* ---------------------------------------------------------------------- */ /* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */ /* reverse orientation of a path */ static void reverse(privcurve_t *curve) { int m = curve->n; int i, j; dpoint_t tmp; for (i=0, j=m-1; ivertex[i]; curve->vertex[i] = curve->vertex[j]; curve->vertex[j] = tmp; } } /* Always succeeds */ static void smooth(privcurve_t *curve, double alphamax) { int m = curve->n; int i, j, k; double dd, denom, alpha; dpoint_t p2, p3, p4; /* examine each vertex and find its best fit */ for (i=0; ivertex[k], curve->vertex[j]); denom = ddenom(curve->vertex[i], curve->vertex[k]); if (denom != 0.0) { dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom; dd = fabs(dd); alpha = dd>1 ? (1 - 1.0/dd) : 0; alpha = alpha / 0.75; } else { alpha = 4/3.0; } curve->alpha0[j] = alpha; /* remember "original" value of alpha */ if (alpha >= alphamax) { /* pointed corner */ curve->tag[j] = POTRACE_CORNER; curve->c[j][1] = curve->vertex[j]; curve->c[j][2] = p4; } else { if (alpha < 0.55) { alpha = 0.55; } else if (alpha > 1) { alpha = 1; } p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]); p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]); curve->tag[j] = POTRACE_CURVETO; curve->c[j][0] = p2; curve->c[j][1] = p3; curve->c[j][2] = p4; } curve->alpha[j] = alpha; /* store the "cropped" value of alpha */ curve->beta[j] = 0.5; } curve->alphacurve = 1; return; } /* ---------------------------------------------------------------------- */ /* Stage 5: Curve optimization (Sec. 2.4) */ /* a private type for the result of opti_penalty */ struct opti_s { double pen; /* penalty */ dpoint_t c[2]; /* curve parameters */ double t, s; /* curve parameters */ double alpha; /* curve parameter */ }; typedef struct opti_s opti_t; /* calculate best fit from i+.5 to j+.5. Assume icurve.n; int k, k1, k2, conv, i1; double area, alpha, d, d1, d2; dpoint_t p0, p1, p2, p3, pt; double A, R, A1, A2, A3, A4; double s, t; /* check convexity, corner-freeness, and maximum bend < 179 degrees */ if (i==j) { /* sanity - a full loop can never be an opticurve */ return 1; } k = i; i1 = mod(i+1, m); k1 = mod(k+1, m); conv = convc[k1]; if (conv == 0) { return 1; } d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]); for (k=k1; k!=j; k=k1) { k1 = mod(k+1, m); k2 = mod(k+2, m); if (convc[k1] != conv) { return 1; } if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) { return 1; } if (iprod1(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2]) < d * ddist(pp->curve.vertex[k1], pp->curve.vertex[k2]) * COS179) { return 1; } } /* the curve we're working in: */ p0 = pp->curve.c[mod(i,m)][2]; p1 = pp->curve.vertex[mod(i+1,m)]; p2 = pp->curve.vertex[mod(j,m)]; p3 = pp->curve.c[mod(j,m)][2]; /* determine its area */ area = areac[j] - areac[i]; area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2; if (i>=j) { area += areac[m]; } /* find intersection o of p0p1 and p2p3. Let t,s such that o = interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the triangle (p0,o,p3). */ A1 = dpara(p0, p1, p2); A2 = dpara(p0, p1, p3); A3 = dpara(p0, p2, p3); /* A4 = dpara(p1, p2, p3); */ A4 = A1+A3-A2; if (A2 == A1) { /* this should never happen */ return 1; } t = A3/(A3-A4); s = A2/(A2-A1); A = A2 * t / 2.0; if (A == 0.0) { /* this should never happen */ return 1; } R = area / A; /* relative area */ alpha = 2 - sqrt(4 - R / 0.3); /* overall alpha for p0-o-p3 curve */ res->c[0] = interval(t * alpha, p0, p1); res->c[1] = interval(s * alpha, p3, p2); res->alpha = alpha; res->t = t; res->s = s; p1 = res->c[0]; p2 = res->c[1]; /* the proposed curve is now (p0,p1,p2,p3) */ res->pen = 0; /* calculate penalty */ /* check tangency with edges */ for (k=mod(i+1,m); k!=j; k=k1) { k1 = mod(k+1,m); t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]); if (t<-.5) { return 1; } pt = bezier(t, p0, p1, p2, p3); d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]); if (d == 0.0) { /* this should never happen */ return 1; } d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d; if (fabs(d1) > opttolerance) { return 1; } if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) { return 1; } res->pen += sq(d1); } /* check corners */ for (k=i; k!=j; k=k1) { k1 = mod(k+1,m); t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]); if (t<-.5) { return 1; } pt = bezier(t, p0, p1, p2, p3); d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]); if (d == 0.0) { /* this should never happen */ return 1; } d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d; d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d; d2 *= 0.75 * pp->curve.alpha[k1]; if (d2 < 0) { d1 = -d1; d2 = -d2; } if (d1 < d2 - opttolerance) { return 1; } if (d1 < d2) { res->pen += sq(d1 - d2); } } return 0; } /* optimize the path p, replacing sequences of Bezier segments by a single segment when possible. Return 0 on success, 1 with errno set on failure. */ static int opticurve(privpath_t *pp, double opttolerance) { int m = pp->curve.n; int *pt = NULL; /* pt[m+1] */ double *pen = NULL; /* pen[m+1] */ int *len = NULL; /* len[m+1] */ opti_t *opt = NULL; /* opt[m+1] */ int om; int i,j,r; opti_t o; dpoint_t p0; int i1; double area; double alpha; double *s = NULL; double *t = NULL; int *convc = NULL; /* conv[m]: pre-computed convexities */ double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */ SAFE_CALLOC(pt, m+1, int); SAFE_CALLOC(pen, m+1, double); SAFE_CALLOC(len, m+1, int); SAFE_CALLOC(opt, m+1, opti_t); SAFE_CALLOC(convc, m, int); SAFE_CALLOC(areac, m+1, double); /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */ for (i=0; icurve.tag[i] == POTRACE_CURVETO) { convc[i] = sign(dpara(pp->curve.vertex[mod(i-1,m)], pp->curve.vertex[i], pp->curve.vertex[mod(i+1,m)])); } else { convc[i] = 0; } } /* pre-calculate areas */ area = 0.0; areac[0] = 0.0; p0 = pp->curve.vertex[0]; for (i=0; icurve.tag[i1] == POTRACE_CURVETO) { alpha = pp->curve.alpha[i1]; area += 0.3*alpha*(4-alpha)*dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2])/2; area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2])/2; } areac[i+1] = area; } pt[0] = -1; pen[0] = 0; len[0] = 0; /* Fixme: we always start from a fixed point -- should find the best curve cyclically */ for (j=1; j<=m; j++) { /* calculate best path from 0 to j */ pt[j] = j-1; pen[j] = pen[j-1]; len[j] = len[j-1]+1; for (i=j-2; i>=0; i--) { r = opti_penalty(pp, i, mod(j,m), &o, opttolerance, convc, areac); if (r) { break; } if (len[j] > len[i]+1 || (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) { pt[j] = i; pen[j] = pen[i] + o.pen; len[j] = len[i] + 1; opt[j] = o; } } } om = len[m]; r = privcurve_init(&pp->ocurve, om); if (r) { goto calloc_error; } SAFE_CALLOC(s, om, double); SAFE_CALLOC(t, om, double); j = m; for (i=om-1; i>=0; i--) { if (pt[j]==j-1) { pp->ocurve.tag[i] = pp->curve.tag[mod(j,m)]; pp->ocurve.c[i][0] = pp->curve.c[mod(j,m)][0]; pp->ocurve.c[i][1] = pp->curve.c[mod(j,m)][1]; pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2]; pp->ocurve.vertex[i] = pp->curve.vertex[mod(j,m)]; pp->ocurve.alpha[i] = pp->curve.alpha[mod(j,m)]; pp->ocurve.alpha0[i] = pp->curve.alpha0[mod(j,m)]; pp->ocurve.beta[i] = pp->curve.beta[mod(j,m)]; s[i] = t[i] = 1.0; } else { pp->ocurve.tag[i] = POTRACE_CURVETO; pp->ocurve.c[i][0] = opt[j].c[0]; pp->ocurve.c[i][1] = opt[j].c[1]; pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2]; pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j,m)][2], pp->curve.vertex[mod(j,m)]); pp->ocurve.alpha[i] = opt[j].alpha; pp->ocurve.alpha0[i] = opt[j].alpha; s[i] = opt[j].s; t[i] = opt[j].t; } j = pt[j]; } /* calculate beta parameters */ for (i=0; iocurve.beta[i] = s[i] / (s[i] + t[i1]); } pp->ocurve.alphacurve = 1; free(pt); free(pen); free(len); free(opt); free(s); free(t); free(convc); free(areac); return 0; calloc_error: free(pt); free(pen); free(len); free(opt); free(s); free(t); free(convc); free(areac); return 1; } /* ---------------------------------------------------------------------- */ #define TRY(x) if (x) goto try_error /* return 0 on success, 1 on error with errno set. */ int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress) { path_t *p; double nn = 0, cn = 0; if (progress->callback) { /* precompute task size for progress estimates */ nn = 0; list_forall (p, plist) { nn += p->priv->len; } cn = 0; } /* call downstream function with each path */ list_forall (p, plist) { TRY(calc_sums(p->priv)); TRY(calc_lon(p->priv)); TRY(bestpolygon(p->priv)); TRY(adjust_vertices(p->priv)); if (p->sign == '-') { /* reverse orientation of negative paths */ reverse(&p->priv->curve); } smooth(&p->priv->curve, param->alphamax); if (param->opticurve) { TRY(opticurve(p->priv, param->opttolerance)); p->priv->fcurve = &p->priv->ocurve; } else { p->priv->fcurve = &p->priv->curve; } privcurve_to_curve(p->priv->fcurve, &p->curve); if (progress->callback) { cn += p->priv->len; progress_update(cn/nn, progress); } } progress_update(1.0, progress); return 0; try_error: return 1; } dvisvgm-3.5/libs/potrace/trace.h000066400000000000000000000006151501401750600166760ustar00rootroot00000000000000/* Copyright (C) 2001-2019 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ #ifndef TRACE_H #define TRACE_H #include "potracelib.h" #include "progress.h" #include "curve.h" int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress); #endif /* TRACE_H */ dvisvgm-3.5/libs/variant/000077500000000000000000000000001501401750600154345ustar00rootroot00000000000000dvisvgm-3.5/libs/variant/LICENSE.md000066400000000000000000000024721501401750600170450ustar00rootroot00000000000000Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. dvisvgm-3.5/libs/variant/Makefile.am000066400000000000000000000001071501401750600174660ustar00rootroot00000000000000noinst_HEADERS = \ include/mpark/variant.hpp EXTRA_DIST = LICENSE.md dvisvgm-3.5/libs/variant/include/000077500000000000000000000000001501401750600170575ustar00rootroot00000000000000dvisvgm-3.5/libs/variant/include/mpark/000077500000000000000000000000001501401750600201715ustar00rootroot00000000000000dvisvgm-3.5/libs/variant/include/mpark/variant.hpp000066400000000000000000003102661501401750600223560ustar00rootroot00000000000000// MPark.Variant // // Copyright Michael Park, 2015-2017 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #ifndef MPARK_VARIANT_HPP #define MPARK_VARIANT_HPP /* variant synopsis namespace std { // 20.7.2, class template variant template class variant { public: // 20.7.2.1, constructors constexpr variant() noexcept(see below); variant(const variant&); variant(variant&&) noexcept(see below); template constexpr variant(T&&) noexcept(see below); template constexpr explicit variant(in_place_type_t, Args&&...); template constexpr explicit variant( in_place_type_t, initializer_list, Args&&...); template constexpr explicit variant(in_place_index_t, Args&&...); template constexpr explicit variant( in_place_index_t, initializer_list, Args&&...); // 20.7.2.2, destructor ~variant(); // 20.7.2.3, assignment variant& operator=(const variant&); variant& operator=(variant&&) noexcept(see below); template variant& operator=(T&&) noexcept(see below); // 20.7.2.4, modifiers template T& emplace(Args&&...); template T& emplace(initializer_list, Args&&...); template variant_alternative& emplace(Args&&...); template variant_alternative& emplace(initializer_list, Args&&...); // 20.7.2.5, value status constexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // 20.7.2.6, swap void swap(variant&) noexcept(see below); }; // 20.7.3, variant helper classes template struct variant_size; // undefined template constexpr size_t variant_size_v = variant_size::value; template struct variant_size; template struct variant_size; template struct variant_size; template struct variant_size>; template struct variant_alternative; // undefined template using variant_alternative_t = typename variant_alternative::type; template struct variant_alternative; template struct variant_alternative; template struct variant_alternative; template struct variant_alternative>; constexpr size_t variant_npos = -1; // 20.7.4, value access template constexpr bool holds_alternative(const variant&) noexcept; template constexpr variant_alternative_t>& get(variant&); template constexpr variant_alternative_t>&& get(variant&&); template constexpr variant_alternative_t> const& get(const variant&); template constexpr variant_alternative_t> const&& get(const variant&&); template constexpr T& get(variant&); template constexpr T&& get(variant&&); template constexpr const T& get(const variant&); template constexpr const T&& get(const variant&&); template constexpr add_pointer_t>> get_if(variant*) noexcept; template constexpr add_pointer_t>> get_if(const variant*) noexcept; template constexpr add_pointer_t get_if(variant*) noexcept; template constexpr add_pointer_t get_if(const variant*) noexcept; // 20.7.5, relational operators template constexpr bool operator==(const variant&, const variant&); template constexpr bool operator!=(const variant&, const variant&); template constexpr bool operator<(const variant&, const variant&); template constexpr bool operator>(const variant&, const variant&); template constexpr bool operator<=(const variant&, const variant&); template constexpr bool operator>=(const variant&, const variant&); // 20.7.6, visitation template constexpr see below visit(Visitor&&, Variants&&...); // 20.7.7, class monostate struct monostate; // 20.7.8, monostate relational operators constexpr bool operator<(monostate, monostate) noexcept; constexpr bool operator>(monostate, monostate) noexcept; constexpr bool operator<=(monostate, monostate) noexcept; constexpr bool operator>=(monostate, monostate) noexcept; constexpr bool operator==(monostate, monostate) noexcept; constexpr bool operator!=(monostate, monostate) noexcept; // 20.7.9, specialized algorithms template void swap(variant&, variant&) noexcept(see below); // 20.7.10, class bad_variant_access class bad_variant_access; // 20.7.11, hash support template struct hash; template struct hash>; template <> struct hash; } // namespace std */ #include #include #include #include #include #include #include // MPark.Variant // // Copyright Michael Park, 2015-2017 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #ifndef MPARK_CONFIG_HPP #define MPARK_CONFIG_HPP // MSVC 2015 Update 3. #if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210) #error "MPark.Variant requires C++11 support." #endif #ifndef __has_attribute #define __has_attribute(x) 0 #endif #ifndef __has_builtin #define __has_builtin(x) 0 #endif #ifndef __has_include #define __has_include(x) 0 #endif #ifndef __has_feature #define __has_feature(x) 0 #endif #if __has_attribute(always_inline) || defined(__GNUC__) #define MPARK_ALWAYS_INLINE __attribute__((__always_inline__)) inline #elif defined(_MSC_VER) #define MPARK_ALWAYS_INLINE __forceinline #else #define MPARK_ALWAYS_INLINE inline #endif #if __has_builtin(__builtin_addressof) || \ (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) #define MPARK_BUILTIN_ADDRESSOF #endif #if __has_builtin(__builtin_unreachable) || defined(__GNUC__) #define MPARK_BUILTIN_UNREACHABLE __builtin_unreachable() #elif defined(_MSC_VER) #define MPARK_BUILTIN_UNREACHABLE __assume(false) #else #define MPARK_BUILTIN_UNREACHABLE #endif #if __has_builtin(__type_pack_element) #define MPARK_TYPE_PACK_ELEMENT #endif #if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \ !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9) #define MPARK_CPP11_CONSTEXPR #endif #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 #define MPARK_CPP14_CONSTEXPR #endif #if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ (defined(_MSC_VER) && defined(_CPPUNWIND)) #define MPARK_EXCEPTIONS #endif #if defined(__cpp_generic_lambdas) || defined(_MSC_VER) #define MPARK_GENERIC_LAMBDAS #endif #if defined(__cpp_lib_integer_sequence) #define MPARK_INTEGER_SEQUENCE #endif #if defined(__cpp_return_type_deduction) || defined(_MSC_VER) #define MPARK_RETURN_TYPE_DEDUCTION #endif #if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER) #define MPARK_TRANSPARENT_OPERATORS #endif #if defined(__cpp_variable_templates) || defined(_MSC_VER) #define MPARK_VARIABLE_TEMPLATES #endif #if !defined(__GLIBCXX__) || __has_include() // >= libstdc++-5 #define MPARK_TRIVIALITY_TYPE_TRAITS #define MPARK_INCOMPLETE_TYPE_TRAITS #endif #endif // MPARK_CONFIG_HPP // MPark.Variant // // Copyright Michael Park, 2015-2017 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #ifndef MPARK_IN_PLACE_HPP #define MPARK_IN_PLACE_HPP #include namespace mpark { struct in_place_t { explicit in_place_t() = default; }; template struct in_place_index_t { explicit in_place_index_t() = default; }; template struct in_place_type_t { explicit in_place_type_t() = default; }; #ifdef MPARK_VARIABLE_TEMPLATES constexpr in_place_t in_place{}; template constexpr in_place_index_t in_place_index{}; template constexpr in_place_type_t in_place_type{}; #endif } // namespace mpark #endif // MPARK_IN_PLACE_HPP // MPark.Variant // // Copyright Michael Park, 2015-2017 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #ifndef MPARK_LIB_HPP #define MPARK_LIB_HPP #include #include #include #include #define MPARK_RETURN(...) \ noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } namespace mpark { namespace lib { template struct identity { using type = T; }; inline namespace cpp14 { template struct array { constexpr const T &operator[](std::size_t index) const { return data[index]; } T data[N == 0 ? 1 : N]; }; template using add_pointer_t = typename std::add_pointer::type; template using common_type_t = typename std::common_type::type; template using decay_t = typename std::decay::type; template using enable_if_t = typename std::enable_if::type; template using remove_const_t = typename std::remove_const::type; template using remove_reference_t = typename std::remove_reference::type; template inline constexpr T &&forward(remove_reference_t &t) noexcept { return static_cast(t); } template inline constexpr T &&forward(remove_reference_t &&t) noexcept { static_assert(!std::is_lvalue_reference::value, "can not forward an rvalue as an lvalue"); return static_cast(t); } template inline constexpr remove_reference_t &&move(T &&t) noexcept { return static_cast &&>(t); } #ifdef MPARK_INTEGER_SEQUENCE using std::integer_sequence; using std::index_sequence; using std::make_index_sequence; using std::index_sequence_for; #else template struct integer_sequence { using value_type = T; static constexpr std::size_t size() noexcept { return sizeof...(Is); } }; template using index_sequence = integer_sequence; template struct make_index_sequence_concat; template struct make_index_sequence_concat, index_sequence> : identity> {}; template struct make_index_sequence_impl; template using make_index_sequence = typename make_index_sequence_impl::type; template struct make_index_sequence_impl : make_index_sequence_concat, make_index_sequence> {}; template <> struct make_index_sequence_impl<0> : identity> {}; template <> struct make_index_sequence_impl<1> : identity> {}; template using index_sequence_for = make_index_sequence; #endif // #ifdef MPARK_TRANSPARENT_OPERATORS using equal_to = std::equal_to<>; #else struct equal_to { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) == lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using not_equal_to = std::not_equal_to<>; #else struct not_equal_to { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) != lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using less = std::less<>; #else struct less { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) < lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using greater = std::greater<>; #else struct greater { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) > lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using less_equal = std::less_equal<>; #else struct less_equal { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) <= lib::forward(rhs)) }; #endif #ifdef MPARK_TRANSPARENT_OPERATORS using greater_equal = std::greater_equal<>; #else struct greater_equal { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const MPARK_RETURN(lib::forward(lhs) >= lib::forward(rhs)) }; #endif } // namespace cpp14 inline namespace cpp17 { // template using bool_constant = std::integral_constant; template struct voider : identity {}; template using void_t = typename voider::type; namespace detail { namespace swappable { using std::swap; template struct is_swappable { private: template (), std::declval()))> inline static std::true_type test(int); template inline static std::false_type test(...); public: static constexpr bool value = decltype(test(0))::value; }; template struct is_nothrow_swappable { static constexpr bool value = noexcept(swap(std::declval(), std::declval())); }; template struct is_nothrow_swappable : std::false_type {}; } // namespace swappable } // namespace detail using detail::swappable::is_swappable; template using is_nothrow_swappable = detail::swappable::is_nothrow_swappable::value, T>; // namespace detail { template struct is_reference_wrapper : std::false_type {}; template struct is_reference_wrapper> : std::true_type {}; template struct Invoke; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) MPARK_RETURN((lib::forward(arg).*pmf)(lib::forward(args)...)) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) MPARK_RETURN((lib::forward(arg).get().*pmf)(lib::forward(args)...)) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) MPARK_RETURN(((*lib::forward(arg)).*pmf)(lib::forward(args)...)) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) MPARK_RETURN(lib::forward(arg).*pmo) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) MPARK_RETURN(lib::forward(arg).get().*pmo) }; template <> struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) MPARK_RETURN((*lib::forward(arg)).*pmo) }; template inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) MPARK_RETURN( Invoke::value, (std::is_base_of>::value ? 0 : is_reference_wrapper>::value ? 1 : 2)>::invoke(f, lib::forward(arg), lib::forward(args)...)) #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) #endif template inline constexpr auto invoke(F &&f, Args &&... args) MPARK_RETURN(lib::forward(f)(lib::forward(args)...)) #ifdef _MSC_VER #pragma warning(pop) #endif } // namespace detail template inline constexpr auto invoke(F &&f, Args &&... args) MPARK_RETURN(detail::invoke(lib::forward(f), lib::forward(args)...)) namespace detail { template struct invoke_result {}; template struct invoke_result(), std::declval()...))>, F, Args...> : identity(), std::declval()...))> {}; } // namespace detail template using invoke_result = detail::invoke_result; template using invoke_result_t = typename invoke_result::type; namespace detail { template struct is_invocable : std::false_type {}; template struct is_invocable>, F, Args...> : std::true_type {}; template struct is_invocable_r : std::false_type {}; template struct is_invocable_r>, R, F, Args...> : std::is_convertible, R> {}; } // namespace detail template using is_invocable = detail::is_invocable; template using is_invocable_r = detail::is_invocable_r; namespace detail { template struct is_nothrow_invocable { static constexpr bool value = noexcept(lib::invoke(std::declval(), std::declval()...)); }; template struct is_nothrow_invocable : std::false_type {}; template struct is_nothrow_invocable_r { private: inline static R impl() { return lib::invoke(std::declval(), std::declval()...); } public: static constexpr bool value = noexcept(impl()); }; template struct is_nothrow_invocable_r : std::false_type {}; } // namespace detail template using is_nothrow_invocable = detail:: is_nothrow_invocable::value, F, Args...>; template using is_nothrow_invocable_r = detail::is_nothrow_invocable_r::value, R, F, Args...>; // #ifdef MPARK_BUILTIN_ADDRESSOF template inline constexpr T *addressof(T &arg) noexcept { return __builtin_addressof(arg); } #else namespace detail { namespace has_addressof_impl { struct fail; template inline fail operator&(T &&); template inline static constexpr bool impl() { return (std::is_class::value || std::is_union::value) && !std::is_same()), fail>::value; } } // namespace has_addressof_impl template using has_addressof = bool_constant()>; template inline constexpr T *addressof(T &arg, std::true_type) noexcept { return std::addressof(arg); } template inline constexpr T *addressof(T &arg, std::false_type) noexcept { return &arg; } } // namespace detail template inline constexpr T *addressof(T &arg) noexcept { return detail::addressof(arg, detail::has_addressof{}); } #endif template inline constexpr T *addressof(const T &&) = delete; } // namespace cpp17 template struct remove_all_extents : identity {}; template struct remove_all_extents> : remove_all_extents {}; template using remove_all_extents_t = typename remove_all_extents::type; template using size_constant = std::integral_constant; template struct indexed_type : size_constant { using type = T; }; template using all = std::is_same, integer_sequence>; #ifdef MPARK_TYPE_PACK_ELEMENT template using type_pack_element_t = __type_pack_element; #else template struct type_pack_element_impl { private: template struct set; template struct set> : indexed_type... {}; template inline static std::enable_if impl(indexed_type); inline static std::enable_if impl(...); public: using type = decltype(impl(set>{})); }; template using type_pack_element = typename type_pack_element_impl::type; template using type_pack_element_t = typename type_pack_element::type; #endif #ifdef MPARK_TRIVIALITY_TYPE_TRAITS using std::is_trivially_copy_constructible; using std::is_trivially_move_constructible; using std::is_trivially_copy_assignable; using std::is_trivially_move_assignable; #else template struct is_trivially_copy_constructible : bool_constant< std::is_copy_constructible::value && __has_trivial_copy(T)> {}; template struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; template struct is_trivially_copy_assignable : bool_constant< std::is_copy_assignable::value && __has_trivial_assign(T)> {}; template struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; #endif template struct dependent_type : T {}; template struct push_back; template using push_back_t = typename push_back::type; template struct push_back, J> { using type = index_sequence; }; } // namespace lib } // namespace mpark #undef MPARK_RETURN #endif // MPARK_LIB_HPP namespace mpark { #ifdef MPARK_RETURN_TYPE_DEDUCTION #define AUTO auto #define AUTO_RETURN(...) { return __VA_ARGS__; } #define AUTO_REFREF auto && #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; } #define DECLTYPE_AUTO decltype(auto) #define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; } #else #define AUTO auto #define AUTO_RETURN(...) \ -> lib::decay_t { return __VA_ARGS__; } #define AUTO_REFREF auto #define AUTO_REFREF_RETURN(...) \ -> decltype((__VA_ARGS__)) { \ static_assert(std::is_reference::value, ""); \ return __VA_ARGS__; \ } #define DECLTYPE_AUTO auto #define DECLTYPE_AUTO_RETURN(...) \ -> decltype(__VA_ARGS__) { return __VA_ARGS__; } #endif class bad_variant_access : public std::exception { public: virtual const char *what() const noexcept override { return "bad_variant_access"; } }; [[noreturn]] inline void throw_bad_variant_access() { #ifdef MPARK_EXCEPTIONS throw bad_variant_access{}; #else std::terminate(); MPARK_BUILTIN_UNREACHABLE; #endif } template class variant; template struct variant_size; #ifdef MPARK_VARIABLE_TEMPLATES template constexpr std::size_t variant_size_v = variant_size::value; #endif template struct variant_size : variant_size {}; template struct variant_size : variant_size {}; template struct variant_size : variant_size {}; template struct variant_size> : lib::size_constant {}; template struct variant_alternative; template using variant_alternative_t = typename variant_alternative::type; template struct variant_alternative : std::add_const> {}; template struct variant_alternative : std::add_volatile> {}; template struct variant_alternative : std::add_cv> {}; template struct variant_alternative> { static_assert(I < sizeof...(Ts), "index out of bounds in `std::variant_alternative<>`"); using type = lib::type_pack_element_t; }; constexpr std::size_t variant_npos = static_cast(-1); namespace detail { constexpr std::size_t not_found = static_cast(-1); constexpr std::size_t ambiguous = static_cast(-2); #ifdef MPARK_CPP14_CONSTEXPR template inline constexpr std::size_t find_index() { constexpr lib::array matches = { {std::is_same::value...} }; std::size_t result = not_found; for (std::size_t i = 0; i < sizeof...(Ts); ++i) { if (matches[i]) { if (result != not_found) { return ambiguous; } result = i; } } return result; } #else inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t) { return result; } template inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t idx, bool b, Bs... bs) { return b ? (result != not_found ? ambiguous : find_index_impl(idx, idx + 1, bs...)) : find_index_impl(result, idx + 1, bs...); } template inline constexpr std::size_t find_index() { return find_index_impl(not_found, 0, std::is_same::value...); } #endif template using find_index_sfinae_impl = lib::enable_if_t>; template using find_index_sfinae = find_index_sfinae_impl()>; template struct find_index_checked_impl : lib::size_constant { static_assert(I != not_found, "the specified type is not found."); static_assert(I != ambiguous, "the specified type is ambiguous."); }; template using find_index_checked = find_index_checked_impl()>; struct valueless_t {}; enum class Trait { TriviallyAvailable, Available, Unavailable }; template class IsTriviallyAvailable, template class IsAvailable> inline constexpr Trait trait() { return IsTriviallyAvailable::value ? Trait::TriviallyAvailable : IsAvailable::value ? Trait::Available : Trait::Unavailable; } #ifdef MPARK_CPP14_CONSTEXPR template inline constexpr Trait common_trait(Traits... traits_) { Trait result = Trait::TriviallyAvailable; lib::array traits = {{traits_...}}; for (std::size_t i = 0; i < sizeof...(Traits); ++i) { Trait t = traits[i]; if (static_cast(t) > static_cast(result)) { result = t; } } return result; } #else inline constexpr Trait common_trait_impl(Trait result) { return result; } template inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts) { return static_cast(t) > static_cast(result) ? common_trait_impl(t, ts...) : common_trait_impl(result, ts...); } template inline constexpr Trait common_trait(Traits... ts) { return common_trait_impl(Trait::TriviallyAvailable, ts...); } #endif template struct traits { static constexpr Trait copy_constructible_trait = common_trait(trait()...); static constexpr Trait move_constructible_trait = common_trait(trait()...); static constexpr Trait copy_assignable_trait = common_trait(copy_constructible_trait, trait()...); static constexpr Trait move_assignable_trait = common_trait(move_constructible_trait, trait()...); static constexpr Trait destructible_trait = common_trait(trait()...); }; namespace access { struct recursive_union { #ifdef MPARK_RETURN_TYPE_DEDUCTION template inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) { return lib::forward(v).head_; } template inline static constexpr auto &&get_alt(V &&v, in_place_index_t) { return get_alt(lib::forward(v).tail_, in_place_index_t{}); } #else template struct get_alt_impl { template inline constexpr AUTO_REFREF operator()(V &&v) const AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v).tail_)) }; template struct get_alt_impl<0, Dummy> { template inline constexpr AUTO_REFREF operator()(V &&v) const AUTO_REFREF_RETURN(lib::forward(v).head_) }; template inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) #endif }; struct base { template inline static constexpr AUTO_REFREF get_alt(V &&v) #ifdef _MSC_VER AUTO_REFREF_RETURN(recursive_union::get_alt( lib::forward(v).data_, in_place_index_t{})) #else AUTO_REFREF_RETURN(recursive_union::get_alt( data(lib::forward(v)), in_place_index_t{})) #endif }; struct variant { template inline static constexpr AUTO_REFREF get_alt(V &&v) AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) }; } // namespace access namespace visitation { #if defined(MPARK_CPP14_CONSTEXPR) && !defined(_MSC_VER) #define MPARK_VARIANT_SWITCH_VISIT #endif struct base { template using dispatch_result_t = decltype( lib::invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); template struct expected { template inline static constexpr bool but_got() { return std::is_same::value; } }; template struct visit_return_type_check { static_assert( expected::template but_got(), "`visit` requires the visitor to have a single return type"); template inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Alts &&... alts) DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), lib::forward(alts)...)) }; #ifdef MPARK_VARIANT_SWITCH_VISIT template struct dispatcher; template struct dispatcher { template MPARK_ALWAYS_INLINE static constexpr R dispatch( F &&, typename ITs::type &&..., Vs &&...) { MPARK_BUILTIN_UNREACHABLE; } template MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) { MPARK_BUILTIN_UNREACHABLE; } template MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t, F &&, Vs &&...) { MPARK_BUILTIN_UNREACHABLE; } }; template struct dispatcher { template MPARK_ALWAYS_INLINE static constexpr R dispatch( F &&f, typename ITs::type &&... visited_vs) { using Expected = R; using Actual = decltype(lib::invoke( lib::forward(f), access::base::get_alt( lib::forward(visited_vs))...)); return visit_return_type_check::invoke( lib::forward(f), access::base::get_alt( lib::forward(visited_vs))...); } template MPARK_ALWAYS_INLINE static constexpr R dispatch( F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) { #define MPARK_DISPATCH(I) \ dispatcher<(I < lib::decay_t::size()), \ R, \ ITs..., \ lib::indexed_type>:: \ template dispatch<0>(lib::forward(f), \ lib::forward(visited_vs)..., \ lib::forward(v), \ lib::forward(vs)...) #define MPARK_DEFAULT(I) \ dispatcher<(I < lib::decay_t::size()), R, ITs...>::template dispatch( \ lib::forward(f), \ lib::forward(visited_vs)..., \ lib::forward(v), \ lib::forward(vs)...) switch (v.index()) { case B + 0: return MPARK_DISPATCH(B + 0); case B + 1: return MPARK_DISPATCH(B + 1); case B + 2: return MPARK_DISPATCH(B + 2); case B + 3: return MPARK_DISPATCH(B + 3); case B + 4: return MPARK_DISPATCH(B + 4); case B + 5: return MPARK_DISPATCH(B + 5); case B + 6: return MPARK_DISPATCH(B + 6); case B + 7: return MPARK_DISPATCH(B + 7); case B + 8: return MPARK_DISPATCH(B + 8); case B + 9: return MPARK_DISPATCH(B + 9); case B + 10: return MPARK_DISPATCH(B + 10); case B + 11: return MPARK_DISPATCH(B + 11); case B + 12: return MPARK_DISPATCH(B + 12); case B + 13: return MPARK_DISPATCH(B + 13); case B + 14: return MPARK_DISPATCH(B + 14); case B + 15: return MPARK_DISPATCH(B + 15); case B + 16: return MPARK_DISPATCH(B + 16); case B + 17: return MPARK_DISPATCH(B + 17); case B + 18: return MPARK_DISPATCH(B + 18); case B + 19: return MPARK_DISPATCH(B + 19); case B + 20: return MPARK_DISPATCH(B + 20); case B + 21: return MPARK_DISPATCH(B + 21); case B + 22: return MPARK_DISPATCH(B + 22); case B + 23: return MPARK_DISPATCH(B + 23); case B + 24: return MPARK_DISPATCH(B + 24); case B + 25: return MPARK_DISPATCH(B + 25); case B + 26: return MPARK_DISPATCH(B + 26); case B + 27: return MPARK_DISPATCH(B + 27); case B + 28: return MPARK_DISPATCH(B + 28); case B + 29: return MPARK_DISPATCH(B + 29); case B + 30: return MPARK_DISPATCH(B + 30); case B + 31: return MPARK_DISPATCH(B + 31); default: return MPARK_DEFAULT(B + 32); } #undef MPARK_DEFAULT #undef MPARK_DISPATCH } template MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&f, Vs &&... vs) { using Expected = R; using Actual = decltype( lib::invoke(lib::forward(f), access::base::get_alt(lib::forward(vs))...)); return visit_return_type_check::invoke( lib::forward(f), access::base::get_alt(lib::forward(vs))...); } template MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index, F &&f, V &&v, Vs &&... vs) { static_assert(lib::all<(lib::decay_t::size() == lib::decay_t::size())...>::value, "all of the variants must be the same size."); #define MPARK_DISPATCH_AT(I) \ dispatcher<(I < lib::decay_t::size()), R>::template dispatch_case( \ lib::forward(f), lib::forward(v), lib::forward(vs)...) #define MPARK_DEFAULT(I) \ dispatcher<(I < lib::decay_t::size()), R>::template dispatch_at( \ index, lib::forward(f), lib::forward(v), lib::forward(vs)...) switch (index) { case B + 0: return MPARK_DISPATCH_AT(B + 0); case B + 1: return MPARK_DISPATCH_AT(B + 1); case B + 2: return MPARK_DISPATCH_AT(B + 2); case B + 3: return MPARK_DISPATCH_AT(B + 3); case B + 4: return MPARK_DISPATCH_AT(B + 4); case B + 5: return MPARK_DISPATCH_AT(B + 5); case B + 6: return MPARK_DISPATCH_AT(B + 6); case B + 7: return MPARK_DISPATCH_AT(B + 7); case B + 8: return MPARK_DISPATCH_AT(B + 8); case B + 9: return MPARK_DISPATCH_AT(B + 9); case B + 10: return MPARK_DISPATCH_AT(B + 10); case B + 11: return MPARK_DISPATCH_AT(B + 11); case B + 12: return MPARK_DISPATCH_AT(B + 12); case B + 13: return MPARK_DISPATCH_AT(B + 13); case B + 14: return MPARK_DISPATCH_AT(B + 14); case B + 15: return MPARK_DISPATCH_AT(B + 15); case B + 16: return MPARK_DISPATCH_AT(B + 16); case B + 17: return MPARK_DISPATCH_AT(B + 17); case B + 18: return MPARK_DISPATCH_AT(B + 18); case B + 19: return MPARK_DISPATCH_AT(B + 19); case B + 20: return MPARK_DISPATCH_AT(B + 20); case B + 21: return MPARK_DISPATCH_AT(B + 21); case B + 22: return MPARK_DISPATCH_AT(B + 22); case B + 23: return MPARK_DISPATCH_AT(B + 23); case B + 24: return MPARK_DISPATCH_AT(B + 24); case B + 25: return MPARK_DISPATCH_AT(B + 25); case B + 26: return MPARK_DISPATCH_AT(B + 26); case B + 27: return MPARK_DISPATCH_AT(B + 27); case B + 28: return MPARK_DISPATCH_AT(B + 28); case B + 29: return MPARK_DISPATCH_AT(B + 29); case B + 30: return MPARK_DISPATCH_AT(B + 30); case B + 31: return MPARK_DISPATCH_AT(B + 31); default: return MPARK_DEFAULT(B + 32); } #undef MPARK_DEFAULT #undef MPARK_DISPATCH_AT } }; #else template inline static constexpr const T &at(const T &elem) noexcept { return elem; } template inline static constexpr const lib::remove_all_extents_t &at( const lib::array &elems, std::size_t i, Is... is) noexcept { return at(elems[i], is...); } template inline static constexpr lib::array, sizeof...(Fs) + 1> make_farray(F &&f, Fs &&... fs) { return {{lib::forward(f), lib::forward(fs)...}}; } template struct make_fmatrix_impl { template inline static constexpr dispatch_result_t dispatch( F &&f, Vs &&... vs) { using Expected = dispatch_result_t; using Actual = decltype(lib::invoke( lib::forward(f), access::base::get_alt(lib::forward(vs))...)); return visit_return_type_check::invoke( lib::forward(f), access::base::get_alt(lib::forward(vs))...); } #ifdef MPARK_RETURN_TYPE_DEDUCTION template inline static constexpr auto impl(lib::index_sequence) { return &dispatch; } template inline static constexpr auto impl(Is, lib::index_sequence, Ls... ls) { return make_farray(impl(lib::push_back_t{}, ls...)...); } #else template struct impl; template struct impl> { inline constexpr AUTO operator()() const AUTO_RETURN(&dispatch) }; template struct impl, Ls...> { inline constexpr AUTO operator()() const AUTO_RETURN( make_farray(impl, Ls...>{}()...)) }; #endif }; #ifdef MPARK_RETURN_TYPE_DEDUCTION template inline static constexpr auto make_fmatrix() { return make_fmatrix_impl::impl( lib::index_sequence<>{}, lib::make_index_sequence::size()>{}...); } #else template inline static constexpr AUTO make_fmatrix() AUTO_RETURN( typename make_fmatrix_impl::template impl< lib::index_sequence<>, lib::make_index_sequence::size()>...>{}()) #endif template struct make_fdiagonal_impl { template inline static constexpr dispatch_result_t dispatch( F &&f, Vs &&... vs) { using Expected = dispatch_result_t; using Actual = decltype( lib::invoke(lib::forward(f), access::base::get_alt(lib::forward(vs))...)); return visit_return_type_check::invoke( lib::forward(f), access::base::get_alt(lib::forward(vs))...); } template inline static constexpr AUTO impl(lib::index_sequence) AUTO_RETURN(make_farray(&dispatch...)) }; template inline static constexpr auto make_fdiagonal() -> decltype(make_fdiagonal_impl::impl( lib::make_index_sequence::size()>{})) { static_assert(lib::all<(lib::decay_t::size() == lib::decay_t::size())...>::value, "all of the variants must be the same size."); return make_fdiagonal_impl::impl( lib::make_index_sequence::size()>{}); } #endif }; #if !defined(MPARK_VARIANT_SWITCH_VISIT) && \ (!defined(_MSC_VER) || _MSC_VER >= 1910) template using fmatrix_t = decltype(base::make_fmatrix()); template struct fmatrix { static constexpr fmatrix_t value = base::make_fmatrix(); }; template constexpr fmatrix_t fmatrix::value; template using fdiagonal_t = decltype(base::make_fdiagonal()); template struct fdiagonal { static constexpr fdiagonal_t value = base::make_fdiagonal(); }; template constexpr fdiagonal_t fdiagonal::value; #endif struct alt { template inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, Vs &&... vs) #ifdef MPARK_VARIANT_SWITCH_VISIT DECLTYPE_AUTO_RETURN( base::dispatcher< true, base::dispatch_result_t(vs)))...>>:: template dispatch<0>(lib::forward(visitor), as_base(lib::forward(vs))...)) #elif !defined(_MSC_VER) || _MSC_VER >= 1910 DECLTYPE_AUTO_RETURN(base::at( fmatrix(vs)))...>::value, vs.index()...)(lib::forward(visitor), as_base(lib::forward(vs))...)) #else DECLTYPE_AUTO_RETURN(base::at( base::make_fmatrix(vs)))...>(), vs.index()...)(lib::forward(visitor), as_base(lib::forward(vs))...)) #endif template inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) #ifdef MPARK_VARIANT_SWITCH_VISIT DECLTYPE_AUTO_RETURN( base::dispatcher< true, base::dispatch_result_t(vs)))...>>:: template dispatch_at<0>(index, lib::forward(visitor), as_base(lib::forward(vs))...)) #elif !defined(_MSC_VER) || _MSC_VER >= 1910 DECLTYPE_AUTO_RETURN(base::at( fdiagonal(vs)))...>::value, index)(lib::forward(visitor), as_base(lib::forward(vs))...)) #else DECLTYPE_AUTO_RETURN(base::at( base::make_fdiagonal(vs)))...>(), index)(lib::forward(visitor), as_base(lib::forward(vs))...)) #endif }; struct variant { private: template struct visitor { template inline static constexpr bool does_not_handle() { return lib::is_invocable::value; } }; template struct visit_exhaustiveness_check { static_assert(visitor::template does_not_handle(), "`visit` requires the visitor to be exhaustive."); inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Values &&... values) DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), lib::forward(values)...)) }; template struct value_visitor { Visitor &&visitor_; template inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const DECLTYPE_AUTO_RETURN( visit_exhaustiveness_check< Visitor, decltype((lib::forward(alts).value))...>:: invoke(lib::forward(visitor_), lib::forward(alts).value...)) }; template inline static constexpr AUTO make_value_visitor(Visitor &&visitor) AUTO_RETURN(value_visitor{lib::forward(visitor)}) public: template inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), lib::forward(vs).impl_...)) template inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( alt::visit_alt_at(index, lib::forward(visitor), lib::forward(vs).impl_...)) template inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( visit_alt(make_value_visitor(lib::forward(visitor)), lib::forward(vs)...)) template inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index, Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( visit_alt_at(index, make_value_visitor(lib::forward(visitor)), lib::forward(vs)...)) }; } // namespace visitation template struct alt { using value_type = T; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4244) #endif template inline explicit constexpr alt(in_place_t, Args &&... args) : value(lib::forward(args)...) {} #ifdef _MSC_VER #pragma warning(pop) #endif T value; }; template union recursive_union; template union recursive_union {}; #define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ template \ union recursive_union { \ public: \ inline explicit constexpr recursive_union(valueless_t) noexcept \ : dummy_{} {} \ \ template \ inline explicit constexpr recursive_union(in_place_index_t<0>, \ Args &&... args) \ : head_(in_place_t{}, lib::forward(args)...) {} \ \ template \ inline explicit constexpr recursive_union(in_place_index_t, \ Args &&... args) \ : tail_(in_place_index_t{}, lib::forward(args)...) {} \ \ recursive_union(const recursive_union &) = default; \ recursive_union(recursive_union &&) = default; \ \ destructor \ \ recursive_union &operator=(const recursive_union &) = default; \ recursive_union &operator=(recursive_union &&) = default; \ \ private: \ char dummy_; \ alt head_; \ recursive_union tail_; \ \ friend struct access::recursive_union; \ } MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, ~recursive_union() = default;); MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, ~recursive_union() {}); MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, ~recursive_union() = delete;); #undef MPARK_VARIANT_RECURSIVE_UNION using index_t = unsigned int; template class base { public: inline explicit constexpr base(valueless_t tag) noexcept : data_(tag), index_(static_cast(-1)) {} template inline explicit constexpr base(in_place_index_t, Args &&... args) : data_(in_place_index_t{}, lib::forward(args)...), index_(I) {} inline constexpr bool valueless_by_exception() const noexcept { return index_ == static_cast(-1); } inline constexpr std::size_t index() const noexcept { return valueless_by_exception() ? variant_npos : index_; } protected: using data_t = recursive_union; friend inline constexpr base &as_base(base &b) { return b; } friend inline constexpr const base &as_base(const base &b) { return b; } friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); } friend inline constexpr data_t &data(base &b) { return b.data_; } friend inline constexpr const data_t &data(const base &b) { return b.data_; } friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; } friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; } inline static constexpr std::size_t size() { return sizeof...(Ts); } data_t data_; index_t index_; friend struct access::base; friend struct visitation::base; }; struct dtor { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) #endif template inline void operator()(Alt &alt) const noexcept { alt.~Alt(); } #ifdef _MSC_VER #pragma warning(pop) #endif }; #if !defined(_MSC_VER) || _MSC_VER >= 1910 #define MPARK_INHERITING_CTOR(type, base) using base::base; #else #define MPARK_INHERITING_CTOR(type, base) \ template \ inline explicit constexpr type(Args &&... args) \ : base(lib::forward(args)...) {} #endif template class destructor; #define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ template \ class destructor, destructible_trait> \ : public base { \ using super = base; \ \ public: \ MPARK_INHERITING_CTOR(destructor, super) \ using super::operator=; \ \ destructor(const destructor &) = default; \ destructor(destructor &&) = default; \ definition \ destructor &operator=(const destructor &) = default; \ destructor &operator=(destructor &&) = default; \ \ protected: \ destroy \ } MPARK_VARIANT_DESTRUCTOR( Trait::TriviallyAvailable, ~destructor() = default;, inline void destroy() noexcept { this->index_ = static_cast(-1); }); MPARK_VARIANT_DESTRUCTOR( Trait::Available, ~destructor() { destroy(); }, inline void destroy() noexcept { if (!this->valueless_by_exception()) { visitation::alt::visit_alt(dtor{}, *this); } this->index_ = static_cast(-1); }); MPARK_VARIANT_DESTRUCTOR( Trait::Unavailable, ~destructor() = delete;, inline void destroy() noexcept = delete;); #undef MPARK_VARIANT_DESTRUCTOR template class constructor : public destructor { using super = destructor; public: MPARK_INHERITING_CTOR(constructor, super) using super::operator=; protected: #ifndef MPARK_GENERIC_LAMBDAS struct ctor { template inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { constructor::construct_alt(lhs_alt, lib::forward(rhs_alt).value); } }; #endif template inline static T &construct_alt(alt &a, Args &&... args) { auto *result = ::new (static_cast(lib::addressof(a))) alt(in_place_t{}, lib::forward(args)...); return result->value; } template inline static void generic_construct(constructor &lhs, Rhs &&rhs) { lhs.destroy(); if (!rhs.valueless_by_exception()) { visitation::alt::visit_alt_at( rhs.index(), #ifdef MPARK_GENERIC_LAMBDAS [](auto &lhs_alt, auto &&rhs_alt) { constructor::construct_alt( lhs_alt, lib::forward(rhs_alt).value); } #else ctor{} #endif , lhs, lib::forward(rhs)); lhs.index_ = rhs.index_; } } }; template class move_constructor; #define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ template \ class move_constructor, move_constructible_trait> \ : public constructor> { \ using super = constructor>; \ \ public: \ MPARK_INHERITING_CTOR(move_constructor, super) \ using super::operator=; \ \ move_constructor(const move_constructor &) = default; \ definition \ ~move_constructor() = default; \ move_constructor &operator=(const move_constructor &) = default; \ move_constructor &operator=(move_constructor &&) = default; \ } MPARK_VARIANT_MOVE_CONSTRUCTOR( Trait::TriviallyAvailable, move_constructor(move_constructor &&that) = default;); MPARK_VARIANT_MOVE_CONSTRUCTOR( Trait::Available, move_constructor(move_constructor &&that) noexcept( lib::all::value...>::value) : move_constructor(valueless_t{}) { this->generic_construct(*this, lib::move(that)); }); MPARK_VARIANT_MOVE_CONSTRUCTOR( Trait::Unavailable, move_constructor(move_constructor &&) = delete;); #undef MPARK_VARIANT_MOVE_CONSTRUCTOR template class copy_constructor; #define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ template \ class copy_constructor, copy_constructible_trait> \ : public move_constructor> { \ using super = move_constructor>; \ \ public: \ MPARK_INHERITING_CTOR(copy_constructor, super) \ using super::operator=; \ \ definition \ copy_constructor(copy_constructor &&) = default; \ ~copy_constructor() = default; \ copy_constructor &operator=(const copy_constructor &) = default; \ copy_constructor &operator=(copy_constructor &&) = default; \ } MPARK_VARIANT_COPY_CONSTRUCTOR( Trait::TriviallyAvailable, copy_constructor(const copy_constructor &that) = default;); MPARK_VARIANT_COPY_CONSTRUCTOR( Trait::Available, copy_constructor(const copy_constructor &that) : copy_constructor(valueless_t{}) { this->generic_construct(*this, that); }); MPARK_VARIANT_COPY_CONSTRUCTOR( Trait::Unavailable, copy_constructor(const copy_constructor &) = delete;); #undef MPARK_VARIANT_COPY_CONSTRUCTOR template class assignment : public copy_constructor { using super = copy_constructor; public: MPARK_INHERITING_CTOR(assignment, super) using super::operator=; template inline /* auto & */ auto emplace(Args &&... args) -> decltype(this->construct_alt(access::base::get_alt(*this), lib::forward(args)...)) { this->destroy(); auto &result = this->construct_alt(access::base::get_alt(*this), lib::forward(args)...); this->index_ = I; return result; } protected: #ifndef MPARK_GENERIC_LAMBDAS template struct assigner { template inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { self->assign_alt(this_alt, lib::forward(that_alt).value); } assignment *self; }; #endif template inline void assign_alt(alt &a, Arg &&arg) { if (this->index() == I) { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4244) #endif a.value = lib::forward(arg); #ifdef _MSC_VER #pragma warning(pop) #endif } else { struct { void operator()(std::true_type) const { this_->emplace(lib::forward(arg_)); } void operator()(std::false_type) const { this_->emplace(T(lib::forward(arg_))); } assignment *this_; Arg &&arg_; } impl{this, lib::forward(arg)}; impl(lib::bool_constant< std::is_nothrow_constructible::value || !std::is_nothrow_move_constructible::value>{}); } } template inline void generic_assign(That &&that) { if (this->valueless_by_exception() && that.valueless_by_exception()) { // do nothing. } else if (that.valueless_by_exception()) { this->destroy(); } else { visitation::alt::visit_alt_at( that.index(), #ifdef MPARK_GENERIC_LAMBDAS [this](auto &this_alt, auto &&that_alt) { this->assign_alt( this_alt, lib::forward(that_alt).value); } #else assigner{this} #endif , *this, lib::forward(that)); } } }; template class move_assignment; #define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ template \ class move_assignment, move_assignable_trait> \ : public assignment> { \ using super = assignment>; \ \ public: \ MPARK_INHERITING_CTOR(move_assignment, super) \ using super::operator=; \ \ move_assignment(const move_assignment &) = default; \ move_assignment(move_assignment &&) = default; \ ~move_assignment() = default; \ move_assignment &operator=(const move_assignment &) = default; \ definition \ } MPARK_VARIANT_MOVE_ASSIGNMENT( Trait::TriviallyAvailable, move_assignment &operator=(move_assignment &&that) = default;); MPARK_VARIANT_MOVE_ASSIGNMENT( Trait::Available, move_assignment & operator=(move_assignment &&that) noexcept( lib::all<(std::is_nothrow_move_constructible::value && std::is_nothrow_move_assignable::value)...>::value) { this->generic_assign(lib::move(that)); return *this; }); MPARK_VARIANT_MOVE_ASSIGNMENT( Trait::Unavailable, move_assignment &operator=(move_assignment &&) = delete;); #undef MPARK_VARIANT_MOVE_ASSIGNMENT template class copy_assignment; #define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ template \ class copy_assignment, copy_assignable_trait> \ : public move_assignment> { \ using super = move_assignment>; \ \ public: \ MPARK_INHERITING_CTOR(copy_assignment, super) \ using super::operator=; \ \ copy_assignment(const copy_assignment &) = default; \ copy_assignment(copy_assignment &&) = default; \ ~copy_assignment() = default; \ definition \ copy_assignment &operator=(copy_assignment &&) = default; \ } MPARK_VARIANT_COPY_ASSIGNMENT( Trait::TriviallyAvailable, copy_assignment &operator=(const copy_assignment &that) = default;); MPARK_VARIANT_COPY_ASSIGNMENT( Trait::Available, copy_assignment &operator=(const copy_assignment &that) { this->generic_assign(that); return *this; }); MPARK_VARIANT_COPY_ASSIGNMENT( Trait::Unavailable, copy_assignment &operator=(const copy_assignment &) = delete;); #undef MPARK_VARIANT_COPY_ASSIGNMENT template class impl : public copy_assignment> { using super = copy_assignment>; public: MPARK_INHERITING_CTOR(impl, super) using super::operator=; template inline void assign(Arg &&arg) { this->assign_alt(access::base::get_alt(*this), lib::forward(arg)); } inline void swap(impl &that) { if (this->valueless_by_exception() && that.valueless_by_exception()) { // do nothing. } else if (this->index() == that.index()) { visitation::alt::visit_alt_at(this->index(), #ifdef MPARK_GENERIC_LAMBDAS [](auto &this_alt, auto &that_alt) { using std::swap; swap(this_alt.value, that_alt.value); } #else swapper{} #endif , *this, that); } else { impl *lhs = this; impl *rhs = lib::addressof(that); if (lhs->move_nothrow() && !rhs->move_nothrow()) { std::swap(lhs, rhs); } impl tmp(lib::move(*rhs)); #ifdef MPARK_EXCEPTIONS // EXTENSION: When the move construction of `lhs` into `rhs` throws // and `tmp` is nothrow move constructible then we move `tmp` back // into `rhs` and provide the strong exception safety guarantee. try { this->generic_construct(*rhs, lib::move(*lhs)); } catch (...) { if (tmp.move_nothrow()) { this->generic_construct(*rhs, lib::move(tmp)); } throw; } #else this->generic_construct(*rhs, lib::move(*lhs)); #endif this->generic_construct(*lhs, lib::move(tmp)); } } private: #ifndef MPARK_GENERIC_LAMBDAS struct swapper { template inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { using std::swap; swap(this_alt.value, that_alt.value); } }; #endif inline constexpr bool move_nothrow() const { return this->valueless_by_exception() || lib::array{ {std::is_nothrow_move_constructible::value...} }[this->index()]; } }; #undef MPARK_INHERITING_CTOR template struct overload_leaf { using F = lib::size_constant (*)(T); operator F() const { return nullptr; } }; template struct overload_impl { private: template struct impl; template struct impl> : overload_leaf... {}; public: using type = impl>; }; template using overload = typename overload_impl::type; template using best_match = lib::invoke_result_t, T &&>; template struct is_in_place_index : std::false_type {}; template struct is_in_place_index> : std::true_type {}; template struct is_in_place_type : std::false_type {}; template struct is_in_place_type> : std::true_type {}; } // detail template class variant { static_assert(0 < sizeof...(Ts), "variant must consist of at least one alternative."); static_assert(lib::all::value...>::value, "variant can not have an array type as an alternative."); static_assert(lib::all::value...>::value, "variant can not have a reference type as an alternative."); static_assert(lib::all::value...>::value, "variant can not have a void type as an alternative."); public: template < typename Front = lib::type_pack_element_t<0, Ts...>, lib::enable_if_t::value, int> = 0> inline constexpr variant() noexcept( std::is_nothrow_default_constructible::value) : impl_(in_place_index_t<0>{}) {} variant(const variant &) = default; variant(variant &&) = default; template < typename Arg, typename Decayed = lib::decay_t, lib::enable_if_t::value, int> = 0, lib::enable_if_t::value, int> = 0, lib::enable_if_t::value, int> = 0, std::size_t I = detail::best_match::value, typename T = lib::type_pack_element_t, lib::enable_if_t::value, int> = 0> inline constexpr variant(Arg &&arg) noexcept( std::is_nothrow_constructible::value) : impl_(in_place_index_t{}, lib::forward(arg)) {} template < std::size_t I, typename... Args, typename T = lib::type_pack_element_t, lib::enable_if_t::value, int> = 0> inline explicit constexpr variant( in_place_index_t, Args &&... args) noexcept(std::is_nothrow_constructible::value) : impl_(in_place_index_t{}, lib::forward(args)...) {} template < std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, lib::enable_if_t &, Args...>::value, int> = 0> inline explicit constexpr variant( in_place_index_t, std::initializer_list il, Args &&... args) noexcept(std:: is_nothrow_constructible< T, std::initializer_list &, Args...>::value) : impl_(in_place_index_t{}, il, lib::forward(args)...) {} template < typename T, typename... Args, std::size_t I = detail::find_index_sfinae::value, lib::enable_if_t::value, int> = 0> inline explicit constexpr variant( in_place_type_t, Args &&... args) noexcept(std::is_nothrow_constructible::value) : impl_(in_place_index_t{}, lib::forward(args)...) {} template < typename T, typename Up, typename... Args, std::size_t I = detail::find_index_sfinae::value, lib::enable_if_t &, Args...>::value, int> = 0> inline explicit constexpr variant( in_place_type_t, std::initializer_list il, Args &&... args) noexcept(std:: is_nothrow_constructible< T, std::initializer_list &, Args...>::value) : impl_(in_place_index_t{}, il, lib::forward(args)...) {} ~variant() = default; variant &operator=(const variant &) = default; variant &operator=(variant &&) = default; template , variant>::value, int> = 0, std::size_t I = detail::best_match::value, typename T = lib::type_pack_element_t, lib::enable_if_t<(std::is_assignable::value && std::is_constructible::value), int> = 0> inline variant &operator=(Arg &&arg) noexcept( (std::is_nothrow_assignable::value && std::is_nothrow_constructible::value)) { impl_.template assign(lib::forward(arg)); return *this; } template < std::size_t I, typename... Args, typename T = lib::type_pack_element_t, lib::enable_if_t::value, int> = 0> inline T &emplace(Args &&... args) { return impl_.template emplace(lib::forward(args)...); } template < std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, lib::enable_if_t &, Args...>::value, int> = 0> inline T &emplace(std::initializer_list il, Args &&... args) { return impl_.template emplace(il, lib::forward(args)...); } template < typename T, typename... Args, std::size_t I = detail::find_index_sfinae::value, lib::enable_if_t::value, int> = 0> inline T &emplace(Args &&... args) { return impl_.template emplace(lib::forward(args)...); } template < typename T, typename Up, typename... Args, std::size_t I = detail::find_index_sfinae::value, lib::enable_if_t &, Args...>::value, int> = 0> inline T &emplace(std::initializer_list il, Args &&... args) { return impl_.template emplace(il, lib::forward(args)...); } inline constexpr bool valueless_by_exception() const noexcept { return impl_.valueless_by_exception(); } inline constexpr std::size_t index() const noexcept { return impl_.index(); } template , Dummy>::value && lib::dependent_type, Dummy>::value)...>::value, int> = 0> inline void swap(variant &that) noexcept( lib::all<(std::is_nothrow_move_constructible::value && lib::is_nothrow_swappable::value)...>::value) { impl_.swap(that.impl_); } private: detail::impl impl_; friend struct detail::access::variant; friend struct detail::visitation::variant; }; template inline constexpr bool holds_alternative(const variant &v) noexcept { return v.index() == I; } template inline constexpr bool holds_alternative(const variant &v) noexcept { return holds_alternative::value>(v); } namespace detail { template struct generic_get_impl { constexpr generic_get_impl(int) noexcept {} constexpr AUTO_REFREF operator()(V &&v) const AUTO_REFREF_RETURN( access::variant::get_alt(lib::forward(v)).value) }; template inline constexpr AUTO_REFREF generic_get(V &&v) AUTO_REFREF_RETURN(generic_get_impl( holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))( lib::forward(v))) } // namespace detail template inline constexpr variant_alternative_t> &get( variant &v) { return detail::generic_get(v); } template inline constexpr variant_alternative_t> &&get( variant &&v) { return detail::generic_get(lib::move(v)); } template inline constexpr const variant_alternative_t> &get( const variant &v) { return detail::generic_get(v); } template inline constexpr const variant_alternative_t> &&get( const variant &&v) { return detail::generic_get(lib::move(v)); } template inline constexpr T &get(variant &v) { return get::value>(v); } template inline constexpr T &&get(variant &&v) { return get::value>(lib::move(v)); } template inline constexpr const T &get(const variant &v) { return get::value>(v); } template inline constexpr const T &&get(const variant &&v) { return get::value>(lib::move(v)); } namespace detail { template inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept AUTO_RETURN(v && holds_alternative(*v) ? lib::addressof(access::variant::get_alt(*v).value) : nullptr) } // namespace detail template inline constexpr lib::add_pointer_t>> get_if(variant *v) noexcept { return detail::generic_get_if(v); } template inline constexpr lib::add_pointer_t< const variant_alternative_t>> get_if(const variant *v) noexcept { return detail::generic_get_if(v); } template inline constexpr lib::add_pointer_t get_if(variant *v) noexcept { return get_if::value>(v); } template inline constexpr lib::add_pointer_t get_if(const variant *v) noexcept { return get_if::value>(v); } namespace detail { template struct convert_to_bool { template inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const { static_assert(std::is_convertible, bool>::value, "relational operators must return a type" " implicitly convertible to bool"); return lib::invoke( RelOp{}, lib::forward(lhs), lib::forward(rhs)); } }; } // namespace detail template inline constexpr bool operator==(const variant &lhs, const variant &rhs) { using detail::visitation::variant; using equal_to = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR if (lhs.index() != rhs.index()) return false; if (lhs.valueless_by_exception()) return true; return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs); #else return lhs.index() == rhs.index() && (lhs.valueless_by_exception() || variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); #endif } template inline constexpr bool operator!=(const variant &lhs, const variant &rhs) { using detail::visitation::variant; using not_equal_to = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR if (lhs.index() != rhs.index()) return true; if (lhs.valueless_by_exception()) return false; return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs); #else return lhs.index() != rhs.index() || (!lhs.valueless_by_exception() && variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); #endif } template inline constexpr bool operator<(const variant &lhs, const variant &rhs) { using detail::visitation::variant; using less = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR if (rhs.valueless_by_exception()) return false; if (lhs.valueless_by_exception()) return true; if (lhs.index() < rhs.index()) return true; if (lhs.index() > rhs.index()) return false; return variant::visit_value_at(lhs.index(), less{}, lhs, rhs); #else return !rhs.valueless_by_exception() && (lhs.valueless_by_exception() || lhs.index() < rhs.index() || (lhs.index() == rhs.index() && variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); #endif } template inline constexpr bool operator>(const variant &lhs, const variant &rhs) { using detail::visitation::variant; using greater = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR if (lhs.valueless_by_exception()) return false; if (rhs.valueless_by_exception()) return true; if (lhs.index() > rhs.index()) return true; if (lhs.index() < rhs.index()) return false; return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs); #else return !lhs.valueless_by_exception() && (rhs.valueless_by_exception() || lhs.index() > rhs.index() || (lhs.index() == rhs.index() && variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); #endif } template inline constexpr bool operator<=(const variant &lhs, const variant &rhs) { using detail::visitation::variant; using less_equal = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR if (lhs.valueless_by_exception()) return true; if (rhs.valueless_by_exception()) return false; if (lhs.index() < rhs.index()) return true; if (lhs.index() > rhs.index()) return false; return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs); #else return lhs.valueless_by_exception() || (!rhs.valueless_by_exception() && (lhs.index() < rhs.index() || (lhs.index() == rhs.index() && variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); #endif } template inline constexpr bool operator>=(const variant &lhs, const variant &rhs) { using detail::visitation::variant; using greater_equal = detail::convert_to_bool; #ifdef MPARK_CPP14_CONSTEXPR if (rhs.valueless_by_exception()) return true; if (lhs.valueless_by_exception()) return false; if (lhs.index() > rhs.index()) return true; if (lhs.index() < rhs.index()) return false; return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs); #else return rhs.valueless_by_exception() || (!lhs.valueless_by_exception() && (lhs.index() > rhs.index() || (lhs.index() == rhs.index() && variant::visit_value_at( lhs.index(), greater_equal{}, lhs, rhs)))); #endif } struct monostate {}; inline constexpr bool operator<(monostate, monostate) noexcept { return false; } inline constexpr bool operator>(monostate, monostate) noexcept { return false; } inline constexpr bool operator<=(monostate, monostate) noexcept { return true; } inline constexpr bool operator>=(monostate, monostate) noexcept { return true; } inline constexpr bool operator==(monostate, monostate) noexcept { return true; } inline constexpr bool operator!=(monostate, monostate) noexcept { return false; } #ifdef MPARK_CPP14_CONSTEXPR namespace detail { inline constexpr bool all(std::initializer_list bs) { for (bool b : bs) { if (!b) { return false; } } return true; } } // namespace detail template inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) { return (detail::all({!vs.valueless_by_exception()...}) ? (void)0 : throw_bad_variant_access()), detail::visitation::variant::visit_value( lib::forward(visitor), lib::forward(vs)...); } #else namespace detail { template inline constexpr bool all_impl(const lib::array &bs, std::size_t idx) { return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); } template inline constexpr bool all(const lib::array &bs) { return all_impl(bs, 0); } } // namespace detail template inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( (detail::all( lib::array{{!vs.valueless_by_exception()...}}) ? (void)0 : throw_bad_variant_access()), detail::visitation::variant::visit_value(lib::forward(visitor), lib::forward(vs)...)) #endif template inline auto swap(variant &lhs, variant &rhs) noexcept(noexcept(lhs.swap(rhs))) -> decltype(lhs.swap(rhs)) { lhs.swap(rhs); } namespace detail { template using enabled_type = T; namespace hash { template constexpr bool meets_requirements() noexcept { return std::is_copy_constructible::value && std::is_move_constructible::value && lib::is_invocable_r::value; } template constexpr bool is_enabled() noexcept { using H = std::hash; return meets_requirements() && std::is_default_constructible::value && std::is_copy_assignable::value && std::is_move_assignable::value; } } // namespace hash } // namespace detail #undef AUTO #undef AUTO_RETURN #undef AUTO_REFREF #undef AUTO_REFREF_RETURN #undef DECLTYPE_AUTO #undef DECLTYPE_AUTO_RETURN } // namespace mpark namespace std { template struct hash, mpark::lib::enable_if_t>()...>::value>>> { using argument_type = mpark::variant; using result_type = std::size_t; inline result_type operator()(const argument_type &v) const { using mpark::detail::visitation::variant; std::size_t result = v.valueless_by_exception() ? 299792458 // Random value chosen by the universe upon creation : variant::visit_alt( #ifdef MPARK_GENERIC_LAMBDAS [](const auto &alt) { using alt_type = mpark::lib::decay_t; using value_type = mpark::lib::remove_const_t< typename alt_type::value_type>; return hash{}(alt.value); } #else hasher{} #endif , v); return hash_combine(result, hash{}(v.index())); } private: #ifndef MPARK_GENERIC_LAMBDAS struct hasher { template inline std::size_t operator()(const Alt &alt) const { using alt_type = mpark::lib::decay_t; using value_type = mpark::lib::remove_const_t; return hash{}(alt.value); } }; #endif static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); } }; template <> struct hash { using argument_type = mpark::monostate; using result_type = std::size_t; inline result_type operator()(const argument_type &) const noexcept { return 66740831; // return a fundamentally attractive random value. } }; } // namespace std #endif // MPARK_VARIANT_HPP dvisvgm-3.5/libs/woff2/000077500000000000000000000000001501401750600150135ustar00rootroot00000000000000dvisvgm-3.5/libs/woff2/LICENSE000066400000000000000000000261361501401750600160300ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. dvisvgm-3.5/libs/woff2/Makefile.am000066400000000000000000000012471501401750600170530ustar00rootroot00000000000000if !HAVE_WOFF2 noinst_LIBRARIES = libwoff2.a libwoff2_a_SOURCES = \ include/woff2/decode.h \ include/woff2/encode.h \ include/woff2/output.h \ include/woff2/version.h \ src/buffer.h \ src/font.cc \ src/font.h \ src/glyph.cc \ src/glyph.h \ src/normalize.cc \ src/normalize.h \ src/port.h \ src/round.h \ src/store_bytes.h \ src/table_tags.cc \ src/table_tags.h \ src/transform.cc \ src/transform.h \ src/variable_length.cc \ src/variable_length.h \ src/woff2_common.cc \ src/woff2_common.h \ src/woff2_enc.cc \ src/woff2_out.cc AM_CXXFLAGS = -Wall -I$(srcdir)/include -I$(srcdir)/../brotli/include endif EXTRA_DIST = LICENSE CLEANFILES = *.gcda *.gcno dvisvgm-3.5/libs/woff2/include/000077500000000000000000000000001501401750600164365ustar00rootroot00000000000000dvisvgm-3.5/libs/woff2/include/woff2/000077500000000000000000000000001501401750600174615ustar00rootroot00000000000000dvisvgm-3.5/libs/woff2/include/woff2/decode.h000066400000000000000000000022231501401750600210540ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Library for converting WOFF2 format font files to their TTF versions. */ #ifndef WOFF2_WOFF2_DEC_H_ #define WOFF2_WOFF2_DEC_H_ #include #include #include namespace woff2 { // Compute the size of the final uncompressed font, or 0 on error. size_t ComputeWOFF2FinalSize(const uint8_t *data, size_t length); // Decompresses the font into the target buffer. The result_length should // be the same as determined by ComputeFinalSize(). Returns true on successful // decompression. // DEPRECATED; please prefer the version that takes a WOFF2Out* bool ConvertWOFF2ToTTF(uint8_t *result, size_t result_length, const uint8_t *data, size_t length); // Decompresses the font into out. Returns true on success. // Works even if WOFF2Header totalSfntSize is wrong. // Please prefer this API. bool ConvertWOFF2ToTTF(const uint8_t *data, size_t length, WOFF2Out* out); } // namespace woff2 #endif // WOFF2_WOFF2_DEC_H_ dvisvgm-3.5/libs/woff2/include/woff2/encode.h000066400000000000000000000026321501401750600210720ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Library for converting WOFF2 format font files to their TTF versions. */ #ifndef WOFF2_WOFF2_ENC_H_ #define WOFF2_WOFF2_ENC_H_ #include #include #include namespace woff2 { struct WOFF2Params { WOFF2Params() : extended_metadata(""), brotli_quality(11), allow_transforms(true) {} std::string extended_metadata; int brotli_quality; bool allow_transforms; }; // Returns an upper bound on the size of the compressed file. size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length); size_t MaxWOFF2CompressedSize(const uint8_t *data, size_t length, const std::string &extended_metadata); // Compresses the font into the target buffer. *result_length should be at least // the value returned by MaxWOFF2CompressedSize(), upon return, it is set to the // actual compressed size. Returns true on successful compression. bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, uint8_t *result, size_t *result_length); bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, uint8_t *result, size_t *result_length, const WOFF2Params& params); } // namespace woff2 #endif // WOFF2_WOFF2_ENC_H_ dvisvgm-3.5/libs/woff2/include/woff2/output.h000066400000000000000000000044231501401750600211750ustar00rootroot00000000000000/* Copyright 2016 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Output buffer for WOFF2 decompression. */ #ifndef WOFF2_WOFF2_OUT_H_ #define WOFF2_WOFF2_OUT_H_ #include #include #include #include #include namespace woff2 { // Suggested max size for output. const size_t kDefaultMaxSize = 30 * 1024 * 1024; /** * Output interface for the woff2 decoding. * * Writes to arbitrary offsets are supported to facilitate updating offset * table and checksums after tables are ready. Reading the current size is * supported so a 'loca' table can be built up while writing glyphs. * * By default limits size to kDefaultMaxSize. */ class WOFF2Out { public: virtual ~WOFF2Out(void) {} // Append n bytes of data from buf. // Return true if all written, false otherwise. virtual bool Write(const void *buf, size_t n) = 0; // Write n bytes of data from buf at offset. // Return true if all written, false otherwise. virtual bool Write(const void *buf, size_t offset, size_t n) = 0; virtual size_t Size() = 0; }; /** * Expanding memory block for woff2 out. By default limited to kDefaultMaxSize. */ class WOFF2StringOut : public WOFF2Out { public: // Create a writer that writes its data to buf. // buf->size() will grow to at most max_size // buf may be sized (e.g. using EstimateWOFF2FinalSize) or empty. explicit WOFF2StringOut(std::string *buf); bool Write(const void *buf, size_t n) override; bool Write(const void *buf, size_t offset, size_t n) override; size_t Size() override { return offset_; } size_t MaxSize() { return max_size_; } void SetMaxSize(size_t max_size); private: std::string *buf_; size_t max_size_; size_t offset_; }; /** * Fixed memory block for woff2 out. */ class WOFF2MemoryOut : public WOFF2Out { public: // Create a writer that writes its data to buf. WOFF2MemoryOut(uint8_t* buf, size_t buf_size); bool Write(const void *buf, size_t n) override; bool Write(const void *buf, size_t offset, size_t n) override; size_t Size() override { return offset_; } private: uint8_t* buf_; size_t buf_size_; size_t offset_; }; } // namespace woff2 #endif // WOFF2_WOFF2_OUT_H_ dvisvgm-3.5/libs/woff2/include/woff2/version.h000066400000000000000000000002031501401750600213120ustar00rootroot00000000000000#ifndef WOFF2_WOFF2_VERSION_H_ #define WOFF2_WOFF2_VERSION_H_ namespace woff2 { constexpr const int version = 0x010002; } #endif dvisvgm-3.5/libs/woff2/src/000077500000000000000000000000001501401750600156025ustar00rootroot00000000000000dvisvgm-3.5/libs/woff2/src/buffer.h000066400000000000000000000101311501401750600172200ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* The parts of ots.h & opentype-sanitiser.h that we need, taken from the https://code.google.com/p/ots/ project. */ #ifndef WOFF2_BUFFER_H_ #define WOFF2_BUFFER_H_ #if defined(_WIN32) #include typedef signed char int8_t; typedef unsigned char uint8_t; typedef short int16_t; typedef unsigned short uint16_t; typedef int int32_t; typedef unsigned int uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #define ntohl(x) _byteswap_ulong (x) #define ntohs(x) _byteswap_ushort (x) #define htonl(x) _byteswap_ulong (x) #define htons(x) _byteswap_ushort (x) #else #include #include #endif #include #include #include #include namespace woff2 { #if defined(_MSC_VER) || !defined(FONT_COMPRESSION_DEBUG) #define FONT_COMPRESSION_FAILURE() false #else #define FONT_COMPRESSION_FAILURE() \ woff2::Failure(__FILE__, __LINE__, __PRETTY_FUNCTION__) inline bool Failure(const char *f, int l, const char *fn) { fprintf(stderr, "ERROR at %s:%d (%s)\n", f, l, fn); fflush(stderr); return false; } #endif // ----------------------------------------------------------------------------- // Buffer helper class // // This class perform some trival buffer operations while checking for // out-of-bounds errors. As a family they return false if anything is amiss, // updating the current offset otherwise. // ----------------------------------------------------------------------------- class Buffer { public: Buffer(const uint8_t *data, size_t len) : buffer_(data), length_(len), offset_(0) { } bool Skip(size_t n_bytes) { return Read(NULL, n_bytes); } bool Read(uint8_t *data, size_t n_bytes) { if (n_bytes > 1024 * 1024 * 1024) { return FONT_COMPRESSION_FAILURE(); } if ((offset_ + n_bytes > length_) || (offset_ > length_ - n_bytes)) { return FONT_COMPRESSION_FAILURE(); } if (data) { std::memcpy(data, buffer_ + offset_, n_bytes); } offset_ += n_bytes; return true; } inline bool ReadU8(uint8_t *value) { if (offset_ + 1 > length_) { return FONT_COMPRESSION_FAILURE(); } *value = buffer_[offset_]; ++offset_; return true; } bool ReadU16(uint16_t *value) { if (offset_ + 2 > length_) { return FONT_COMPRESSION_FAILURE(); } std::memcpy(value, buffer_ + offset_, sizeof(uint16_t)); *value = ntohs(*value); offset_ += 2; return true; } bool ReadS16(int16_t *value) { return ReadU16(reinterpret_cast(value)); } bool ReadU24(uint32_t *value) { if (offset_ + 3 > length_) { return FONT_COMPRESSION_FAILURE(); } *value = static_cast(buffer_[offset_]) << 16 | static_cast(buffer_[offset_ + 1]) << 8 | static_cast(buffer_[offset_ + 2]); offset_ += 3; return true; } bool ReadU32(uint32_t *value) { if (offset_ + 4 > length_) { return FONT_COMPRESSION_FAILURE(); } std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); *value = ntohl(*value); offset_ += 4; return true; } bool ReadS32(int32_t *value) { return ReadU32(reinterpret_cast(value)); } bool ReadTag(uint32_t *value) { if (offset_ + 4 > length_) { return FONT_COMPRESSION_FAILURE(); } std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); offset_ += 4; return true; } bool ReadR64(uint64_t *value) { if (offset_ + 8 > length_) { return FONT_COMPRESSION_FAILURE(); } std::memcpy(value, buffer_ + offset_, sizeof(uint64_t)); offset_ += 8; return true; } const uint8_t *buffer() const { return buffer_; } size_t offset() const { return offset_; } size_t length() const { return length_; } void set_offset(size_t newoffset) { offset_ = newoffset; } private: const uint8_t * const buffer_; const size_t length_; size_t offset_; }; } // namespace woff2 #endif // WOFF2_BUFFER_H_ dvisvgm-3.5/libs/woff2/src/font.cc000066400000000000000000000275731501401750600170750ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Font management utilities */ #include "./font.h" #include #include "./buffer.h" #include "./port.h" #include "./store_bytes.h" #include "./table_tags.h" #include "./woff2_common.h" namespace woff2 { Font::Table* Font::FindTable(uint32_t tag) { std::map::iterator it = tables.find(tag); return it == tables.end() ? 0 : &it->second; } const Font::Table* Font::FindTable(uint32_t tag) const { std::map::const_iterator it = tables.find(tag); return it == tables.end() ? 0 : &it->second; } std::vector Font::OutputOrderedTags() const { std::vector output_order; for (const auto& i : tables) { const Font::Table& table = i.second; // This is a transformed table, we will write it together with the // original version. if (table.tag & 0x80808080) { continue; } output_order.push_back(table.tag); } // Alphabetize then put loca immediately after glyf auto glyf_loc = std::find(output_order.begin(), output_order.end(), kGlyfTableTag); auto loca_loc = std::find(output_order.begin(), output_order.end(), kLocaTableTag); if (glyf_loc != output_order.end() && loca_loc != output_order.end()) { output_order.erase(loca_loc); output_order.insert(std::find(output_order.begin(), output_order.end(), kGlyfTableTag) + 1, kLocaTableTag); } return output_order; } bool ReadTrueTypeFont(Buffer* file, const uint8_t* data, size_t len, Font* font) { // We don't care about the search_range, entry_selector and range_shift // fields, they will always be computed upon writing the font. if (!file->ReadU16(&font->num_tables) || !file->Skip(6)) { return FONT_COMPRESSION_FAILURE(); } std::map intervals; for (uint16_t i = 0; i < font->num_tables; ++i) { Font::Table table; table.flag_byte = 0; table.reuse_of = NULL; if (!file->ReadU32(&table.tag) || !file->ReadU32(&table.checksum) || !file->ReadU32(&table.offset) || !file->ReadU32(&table.length)) { return FONT_COMPRESSION_FAILURE(); } if ((table.offset & 3) != 0 || table.length > len || len - table.length < table.offset) { return FONT_COMPRESSION_FAILURE(); } intervals[table.offset] = table.length; table.data = data + table.offset; if (font->tables.find(table.tag) != font->tables.end()) { return FONT_COMPRESSION_FAILURE(); } font->tables[table.tag] = table; } // Check that tables are non-overlapping. uint32_t last_offset = 12UL + 16UL * font->num_tables; for (const auto& i : intervals) { if (i.first < last_offset || i.first + i.second < i.first) { return FONT_COMPRESSION_FAILURE(); } last_offset = i.first + i.second; } // Sanity check key tables const Font::Table* head_table = font->FindTable(kHeadTableTag); if (head_table != NULL && head_table->length < 52) { return FONT_COMPRESSION_FAILURE(); } return true; } bool ReadCollectionFont(Buffer* file, const uint8_t* data, size_t len, Font* font, std::map* all_tables) { if (!file->ReadU32(&font->flavor)) { return FONT_COMPRESSION_FAILURE(); } if (!ReadTrueTypeFont(file, data, len, font)) { return FONT_COMPRESSION_FAILURE(); } for (auto& entry : font->tables) { Font::Table& table = entry.second; if (all_tables->find(table.offset) == all_tables->end()) { (*all_tables)[table.offset] = font->FindTable(table.tag); } else { table.reuse_of = (*all_tables)[table.offset]; if (table.tag != table.reuse_of->tag) { return FONT_COMPRESSION_FAILURE(); } } } return true; } bool ReadTrueTypeCollection(Buffer* file, const uint8_t* data, size_t len, FontCollection* font_collection) { uint32_t num_fonts; if (!file->ReadU32(&font_collection->header_version) || !file->ReadU32(&num_fonts)) { return FONT_COMPRESSION_FAILURE(); } std::vector offsets; for (size_t i = 0; i < num_fonts; i++) { uint32_t offset; if (!file->ReadU32(&offset)) { return FONT_COMPRESSION_FAILURE(); } offsets.push_back(offset); } font_collection->fonts.resize(offsets.size()); std::vector::iterator font_it = font_collection->fonts.begin(); std::map all_tables; for (const auto offset : offsets) { file->set_offset(offset); Font& font = *font_it++; if (!ReadCollectionFont(file, data, len, &font, &all_tables)) { return FONT_COMPRESSION_FAILURE(); } } return true; } bool ReadFont(const uint8_t* data, size_t len, Font* font) { Buffer file(data, len); if (!file.ReadU32(&font->flavor)) { return FONT_COMPRESSION_FAILURE(); } if (font->flavor == kTtcFontFlavor) { return FONT_COMPRESSION_FAILURE(); } return ReadTrueTypeFont(&file, data, len, font); } bool ReadFontCollection(const uint8_t* data, size_t len, FontCollection* font_collection) { Buffer file(data, len); if (!file.ReadU32(&font_collection->flavor)) { return FONT_COMPRESSION_FAILURE(); } if (font_collection->flavor != kTtcFontFlavor) { font_collection->fonts.resize(1); Font& font = font_collection->fonts[0]; font.flavor = font_collection->flavor; return ReadTrueTypeFont(&file, data, len, &font); } return ReadTrueTypeCollection(&file, data, len, font_collection); } size_t FontFileSize(const Font& font) { size_t max_offset = 12ULL + 16ULL * font.num_tables; for (const auto& i : font.tables) { const Font::Table& table = i.second; size_t padding_size = (4 - (table.length & 3)) & 3; size_t end_offset = (padding_size + table.offset) + table.length; max_offset = std::max(max_offset, end_offset); } return max_offset; } size_t FontCollectionFileSize(const FontCollection& font_collection) { size_t max_offset = 0; for (auto& font : font_collection.fonts) { // font file size actually just finds max offset max_offset = std::max(max_offset, FontFileSize(font)); } return max_offset; } bool WriteFont(const Font& font, uint8_t* dst, size_t dst_size) { size_t offset = 0; return WriteFont(font, &offset, dst, dst_size); } bool WriteTableRecord(const Font::Table* table, size_t* offset, uint8_t* dst, size_t dst_size) { if (dst_size < *offset + kSfntEntrySize) { return FONT_COMPRESSION_FAILURE(); } if (table->IsReused()) { table = table->reuse_of; } StoreU32(table->tag, offset, dst); StoreU32(table->checksum, offset, dst); StoreU32(table->offset, offset, dst); StoreU32(table->length, offset, dst); return true; } bool WriteTable(const Font::Table& table, size_t* offset, uint8_t* dst, size_t dst_size) { if (!WriteTableRecord(&table, offset, dst, dst_size)) { return false; } // Write the actual table data if it's the first time we've seen it if (!table.IsReused()) { if (table.offset + table.length < table.offset || dst_size < table.offset + table.length) { return FONT_COMPRESSION_FAILURE(); } memcpy(dst + table.offset, table.data, table.length); size_t padding_size = (4 - (table.length & 3)) & 3; if (table.offset + table.length + padding_size < padding_size || dst_size < table.offset + table.length + padding_size) { return FONT_COMPRESSION_FAILURE(); } memset(dst + table.offset + table.length, 0, padding_size); } return true; } bool WriteFont(const Font& font, size_t* offset, uint8_t* dst, size_t dst_size) { if (dst_size < 12ULL + 16ULL * font.num_tables) { return FONT_COMPRESSION_FAILURE(); } StoreU32(font.flavor, offset, dst); Store16(font.num_tables, offset, dst); uint16_t max_pow2 = font.num_tables ? Log2Floor(font.num_tables) : 0; uint16_t search_range = max_pow2 ? 1 << (max_pow2 + 4) : 0; uint16_t range_shift = (font.num_tables << 4) - search_range; Store16(search_range, offset, dst); Store16(max_pow2, offset, dst); Store16(range_shift, offset, dst); for (const auto& i : font.tables) { if (!WriteTable(i.second, offset, dst, dst_size)) { return false; } } return true; } bool WriteFontCollection(const FontCollection& font_collection, uint8_t* dst, size_t dst_size) { size_t offset = 0; // It's simpler if this just a simple sfnt if (font_collection.flavor != kTtcFontFlavor) { return WriteFont(font_collection.fonts[0], &offset, dst, dst_size); } // Write TTC header StoreU32(kTtcFontFlavor, &offset, dst); StoreU32(font_collection.header_version, &offset, dst); StoreU32(font_collection.fonts.size(), &offset, dst); // Offset Table, zeroed for now size_t offset_table = offset; // where to write offsets later for (size_t i = 0; i < font_collection.fonts.size(); i++) { StoreU32(0, &offset, dst); } if (font_collection.header_version == 0x00020000) { StoreU32(0, &offset, dst); // ulDsigTag StoreU32(0, &offset, dst); // ulDsigLength StoreU32(0, &offset, dst); // ulDsigOffset } // Write fonts and their offsets. for (size_t i = 0; i < font_collection.fonts.size(); i++) { const auto& font = font_collection.fonts[i]; StoreU32(offset, &offset_table, dst); if (!WriteFont(font, &offset, dst, dst_size)) { return false; } } return true; } int NumGlyphs(const Font& font) { const Font::Table* head_table = font.FindTable(kHeadTableTag); const Font::Table* loca_table = font.FindTable(kLocaTableTag); if (head_table == NULL || loca_table == NULL || head_table->length < 52) { return 0; } int index_fmt = IndexFormat(font); uint32_t loca_record_size = (index_fmt == 0 ? 2 : 4); if (loca_table->length < loca_record_size) { return 0; } return (loca_table->length / loca_record_size) - 1; } int IndexFormat(const Font& font) { const Font::Table* head_table = font.FindTable(kHeadTableTag); if (head_table == NULL) { return 0; } return head_table->data[51]; } bool Font::Table::IsReused() const { return this->reuse_of != NULL; } bool GetGlyphData(const Font& font, int glyph_index, const uint8_t** glyph_data, size_t* glyph_size) { if (glyph_index < 0) { return FONT_COMPRESSION_FAILURE(); } const Font::Table* head_table = font.FindTable(kHeadTableTag); const Font::Table* loca_table = font.FindTable(kLocaTableTag); const Font::Table* glyf_table = font.FindTable(kGlyfTableTag); if (head_table == NULL || loca_table == NULL || glyf_table == NULL || head_table->length < 52) { return FONT_COMPRESSION_FAILURE(); } int index_fmt = IndexFormat(font); Buffer loca_buf(loca_table->data, loca_table->length); if (index_fmt == 0) { uint16_t offset1, offset2; if (!loca_buf.Skip(2 * glyph_index) || !loca_buf.ReadU16(&offset1) || !loca_buf.ReadU16(&offset2) || offset2 < offset1 || 2 * offset2 > glyf_table->length) { return FONT_COMPRESSION_FAILURE(); } *glyph_data = glyf_table->data + 2 * offset1; *glyph_size = 2 * (offset2 - offset1); } else { uint32_t offset1, offset2; if (!loca_buf.Skip(4 * glyph_index) || !loca_buf.ReadU32(&offset1) || !loca_buf.ReadU32(&offset2) || offset2 < offset1 || offset2 > glyf_table->length) { return FONT_COMPRESSION_FAILURE(); } *glyph_data = glyf_table->data + offset1; *glyph_size = offset2 - offset1; } return true; } bool RemoveDigitalSignature(Font* font) { std::map::iterator it = font->tables.find(kDsigTableTag); if (it != font->tables.end()) { font->tables.erase(it); font->num_tables = font->tables.size(); } return true; } } // namespace woff2 dvisvgm-3.5/libs/woff2/src/font.h000066400000000000000000000066651501401750600167360ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Data model for a font file in sfnt format, reading and writing functions and accessors for the glyph data. */ #ifndef WOFF2_FONT_H_ #define WOFF2_FONT_H_ #include #include #include #include namespace woff2 { // Represents an sfnt font file. Only the table directory is parsed, for the // table data we only store a raw pointer, therefore a font object is valid only // as long the data from which it was parsed is around. struct Font { uint32_t flavor; uint16_t num_tables; struct Table { uint32_t tag; uint32_t checksum; uint32_t offset; uint32_t length; const uint8_t* data; // Buffer used to mutate the data before writing out. std::vector buffer; // If we've seen this tag/offset before, pointer to the first time we saw it // If this is the first time we've seen this table, NULL // Intended use is to bypass re-processing tables Font::Table* reuse_of; uint8_t flag_byte; // Is this table reused by a TTC bool IsReused() const; }; std::map tables; std::vector OutputOrderedTags() const; Table* FindTable(uint32_t tag); const Table* FindTable(uint32_t tag) const; }; // Accomodates both singular (OTF, TTF) and collection (TTC) fonts struct FontCollection { uint32_t flavor; uint32_t header_version; // (offset, first use of table*) pairs std::map tables; std::vector fonts; }; // Parses the font from the given data. Returns false on parsing failure or // buffer overflow. The font is valid only so long the input data pointer is // valid. Does NOT support collections. bool ReadFont(const uint8_t* data, size_t len, Font* font); // Parses the font from the given data. Returns false on parsing failure or // buffer overflow. The font is valid only so long the input data pointer is // valid. Supports collections. bool ReadFontCollection(const uint8_t* data, size_t len, FontCollection* fonts); // Returns the file size of the font. size_t FontFileSize(const Font& font); size_t FontCollectionFileSize(const FontCollection& font); // Writes the font into the specified dst buffer. The dst_size should be the // same as returned by FontFileSize(). Returns false upon buffer overflow (which // should not happen if dst_size was computed by FontFileSize()). bool WriteFont(const Font& font, uint8_t* dst, size_t dst_size); // Write the font at a specific offset bool WriteFont(const Font& font, size_t* offset, uint8_t* dst, size_t dst_size); bool WriteFontCollection(const FontCollection& font_collection, uint8_t* dst, size_t dst_size); // Returns the number of glyphs in the font. // NOTE: Currently this works only for TrueType-flavored fonts, will return // zero for CFF-flavored fonts. int NumGlyphs(const Font& font); // Returns the index format of the font int IndexFormat(const Font& font); // Sets *glyph_data and *glyph_size to point to the location of the glyph data // with the given index. Returns false if the glyph is not found. bool GetGlyphData(const Font& font, int glyph_index, const uint8_t** glyph_data, size_t* glyph_size); // Removes the digital signature (DSIG) table bool RemoveDigitalSignature(Font* font); } // namespace woff2 #endif // WOFF2_FONT_H_ dvisvgm-3.5/libs/woff2/src/glyph.cc000066400000000000000000000265721501401750600172500ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Glyph manipulation */ #include "./glyph.h" #include #include #include "./buffer.h" #include "./store_bytes.h" namespace woff2 { static const int32_t kFLAG_ONCURVE = 1; static const int32_t kFLAG_XSHORT = 1 << 1; static const int32_t kFLAG_YSHORT = 1 << 2; static const int32_t kFLAG_REPEAT = 1 << 3; static const int32_t kFLAG_XREPEATSIGN = 1 << 4; static const int32_t kFLAG_YREPEATSIGN = 1 << 5; static const int32_t kFLAG_OVERLAP_SIMPLE = 1 << 6; static const int32_t kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; static const int32_t kFLAG_WE_HAVE_A_SCALE = 1 << 3; static const int32_t kFLAG_MORE_COMPONENTS = 1 << 5; static const int32_t kFLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; static const int32_t kFLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7; static const int32_t kFLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; bool ReadCompositeGlyphData(Buffer* buffer, Glyph* glyph) { glyph->have_instructions = false; glyph->composite_data = buffer->buffer() + buffer->offset(); size_t start_offset = buffer->offset(); uint16_t flags = kFLAG_MORE_COMPONENTS; while (flags & kFLAG_MORE_COMPONENTS) { if (!buffer->ReadU16(&flags)) { return FONT_COMPRESSION_FAILURE(); } glyph->have_instructions |= (flags & kFLAG_WE_HAVE_INSTRUCTIONS) != 0; size_t arg_size = 2; // glyph index if (flags & kFLAG_ARG_1_AND_2_ARE_WORDS) { arg_size += 4; } else { arg_size += 2; } if (flags & kFLAG_WE_HAVE_A_SCALE) { arg_size += 2; } else if (flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) { arg_size += 4; } else if (flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) { arg_size += 8; } if (!buffer->Skip(arg_size)) { return FONT_COMPRESSION_FAILURE(); } } if (buffer->offset() - start_offset > std::numeric_limits::max()) { return FONT_COMPRESSION_FAILURE(); } glyph->composite_data_size = buffer->offset() - start_offset; return true; } bool ReadGlyph(const uint8_t* data, size_t len, Glyph* glyph) { Buffer buffer(data, len); int16_t num_contours; if (!buffer.ReadS16(&num_contours)) { return FONT_COMPRESSION_FAILURE(); } // Read the bounding box. if (!buffer.ReadS16(&glyph->x_min) || !buffer.ReadS16(&glyph->y_min) || !buffer.ReadS16(&glyph->x_max) || !buffer.ReadS16(&glyph->y_max)) { return FONT_COMPRESSION_FAILURE(); } if (num_contours == 0) { // Empty glyph. return true; } if (num_contours > 0) { // Simple glyph. glyph->contours.resize(num_contours); // Read the number of points per contour. uint16_t last_point_index = 0; for (int i = 0; i < num_contours; ++i) { uint16_t point_index; if (!buffer.ReadU16(&point_index)) { return FONT_COMPRESSION_FAILURE(); } uint16_t num_points = point_index - last_point_index + (i == 0 ? 1 : 0); glyph->contours[i].resize(num_points); last_point_index = point_index; } // Read the instructions. if (!buffer.ReadU16(&glyph->instructions_size)) { return FONT_COMPRESSION_FAILURE(); } glyph->instructions_data = data + buffer.offset(); if (!buffer.Skip(glyph->instructions_size)) { return FONT_COMPRESSION_FAILURE(); } // Read the run-length coded flags. std::vector > flags(num_contours); { uint8_t flag = 0; uint8_t flag_repeat = 0; for (int i = 0; i < num_contours; ++i) { flags[i].resize(glyph->contours[i].size()); for (size_t j = 0; j < glyph->contours[i].size(); ++j) { if (flag_repeat == 0) { if (!buffer.ReadU8(&flag)) { return FONT_COMPRESSION_FAILURE(); } if (flag & kFLAG_REPEAT) { if (!buffer.ReadU8(&flag_repeat)) { return FONT_COMPRESSION_FAILURE(); } } } else { flag_repeat--; } flags[i][j] = flag; glyph->contours[i][j].on_curve = flag & kFLAG_ONCURVE; } } } if (!flags.empty() && !flags[0].empty()) { glyph->overlap_simple_flag_set = (flags[0][0] & kFLAG_OVERLAP_SIMPLE); } // Read the x coordinates. int prev_x = 0; for (int i = 0; i < num_contours; ++i) { for (size_t j = 0; j < glyph->contours[i].size(); ++j) { uint8_t flag = flags[i][j]; if (flag & kFLAG_XSHORT) { // single byte x-delta coord value uint8_t x_delta; if (!buffer.ReadU8(&x_delta)) { return FONT_COMPRESSION_FAILURE(); } int sign = (flag & kFLAG_XREPEATSIGN) ? 1 : -1; glyph->contours[i][j].x = prev_x + sign * x_delta; } else { // double byte x-delta coord value int16_t x_delta = 0; if (!(flag & kFLAG_XREPEATSIGN)) { if (!buffer.ReadS16(&x_delta)) { return FONT_COMPRESSION_FAILURE(); } } glyph->contours[i][j].x = prev_x + x_delta; } prev_x = glyph->contours[i][j].x; } } // Read the y coordinates. int prev_y = 0; for (int i = 0; i < num_contours; ++i) { for (size_t j = 0; j < glyph->contours[i].size(); ++j) { uint8_t flag = flags[i][j]; if (flag & kFLAG_YSHORT) { // single byte y-delta coord value uint8_t y_delta; if (!buffer.ReadU8(&y_delta)) { return FONT_COMPRESSION_FAILURE(); } int sign = (flag & kFLAG_YREPEATSIGN) ? 1 : -1; glyph->contours[i][j].y = prev_y + sign * y_delta; } else { // double byte y-delta coord value int16_t y_delta = 0; if (!(flag & kFLAG_YREPEATSIGN)) { if (!buffer.ReadS16(&y_delta)) { return FONT_COMPRESSION_FAILURE(); } } glyph->contours[i][j].y = prev_y + y_delta; } prev_y = glyph->contours[i][j].y; } } } else if (num_contours == -1) { // Composite glyph. if (!ReadCompositeGlyphData(&buffer, glyph)) { return FONT_COMPRESSION_FAILURE(); } // Read the instructions. if (glyph->have_instructions) { if (!buffer.ReadU16(&glyph->instructions_size)) { return FONT_COMPRESSION_FAILURE(); } glyph->instructions_data = data + buffer.offset(); if (!buffer.Skip(glyph->instructions_size)) { return FONT_COMPRESSION_FAILURE(); } } else { glyph->instructions_size = 0; } } else { return FONT_COMPRESSION_FAILURE(); } return true; } namespace { void StoreBbox(const Glyph& glyph, size_t* offset, uint8_t* dst) { Store16(glyph.x_min, offset, dst); Store16(glyph.y_min, offset, dst); Store16(glyph.x_max, offset, dst); Store16(glyph.y_max, offset, dst); } void StoreInstructions(const Glyph& glyph, size_t* offset, uint8_t* dst) { Store16(glyph.instructions_size, offset, dst); StoreBytes(glyph.instructions_data, glyph.instructions_size, offset, dst); } bool StoreEndPtsOfContours(const Glyph& glyph, size_t* offset, uint8_t* dst) { int end_point = -1; for (const auto& contour : glyph.contours) { end_point += contour.size(); if (contour.size() > std::numeric_limits::max() || end_point > std::numeric_limits::max()) { return FONT_COMPRESSION_FAILURE(); } Store16(end_point, offset, dst); } return true; } bool StorePoints(const Glyph& glyph, size_t* offset, uint8_t* dst, size_t dst_size) { int previous_flag = -1; int repeat_count = 0; int last_x = 0; int last_y = 0; size_t x_bytes = 0; size_t y_bytes = 0; // Store the flags and calculate the total size of the x and y coordinates. for (const auto& contour : glyph.contours) { for (const auto& point : contour) { int flag = point.on_curve ? kFLAG_ONCURVE : 0; if (previous_flag == -1 && glyph.overlap_simple_flag_set) { // First flag needs to have overlap simple bit set. flag = flag | kFLAG_OVERLAP_SIMPLE; } int dx = point.x - last_x; int dy = point.y - last_y; if (dx == 0) { flag |= kFLAG_XREPEATSIGN; } else if (dx > -256 && dx < 256) { flag |= kFLAG_XSHORT | (dx > 0 ? kFLAG_XREPEATSIGN : 0); x_bytes += 1; } else { x_bytes += 2; } if (dy == 0) { flag |= kFLAG_YREPEATSIGN; } else if (dy > -256 && dy < 256) { flag |= kFLAG_YSHORT | (dy > 0 ? kFLAG_YREPEATSIGN : 0); y_bytes += 1; } else { y_bytes += 2; } if (flag == previous_flag && repeat_count != 255) { dst[*offset - 1] |= kFLAG_REPEAT; repeat_count++; } else { if (repeat_count != 0) { if (*offset >= dst_size) { return FONT_COMPRESSION_FAILURE(); } dst[(*offset)++] = repeat_count; } if (*offset >= dst_size) { return FONT_COMPRESSION_FAILURE(); } dst[(*offset)++] = flag; repeat_count = 0; } last_x = point.x; last_y = point.y; previous_flag = flag; } } if (repeat_count != 0) { if (*offset >= dst_size) { return FONT_COMPRESSION_FAILURE(); } dst[(*offset)++] = repeat_count; } if (*offset + x_bytes + y_bytes > dst_size) { return FONT_COMPRESSION_FAILURE(); } // Store the x and y coordinates. size_t x_offset = *offset; size_t y_offset = *offset + x_bytes; last_x = 0; last_y = 0; for (const auto& contour : glyph.contours) { for (const auto& point : contour) { int dx = point.x - last_x; int dy = point.y - last_y; if (dx == 0) { // pass } else if (dx > -256 && dx < 256) { dst[x_offset++] = std::abs(dx); } else { Store16(dx, &x_offset, dst); } if (dy == 0) { // pass } else if (dy > -256 && dy < 256) { dst[y_offset++] = std::abs(dy); } else { Store16(dy, &y_offset, dst); } last_x += dx; last_y += dy; } } *offset = y_offset; return true; } } // namespace bool StoreGlyph(const Glyph& glyph, uint8_t* dst, size_t* dst_size) { size_t offset = 0; if (glyph.composite_data_size > 0) { // Composite glyph. if (*dst_size < ((10ULL + glyph.composite_data_size) + ((glyph.have_instructions ? 2ULL : 0) + glyph.instructions_size))) { return FONT_COMPRESSION_FAILURE(); } Store16(-1, &offset, dst); StoreBbox(glyph, &offset, dst); StoreBytes(glyph.composite_data, glyph.composite_data_size, &offset, dst); if (glyph.have_instructions) { StoreInstructions(glyph, &offset, dst); } } else if (glyph.contours.size() > 0) { // Simple glyph. if (glyph.contours.size() > std::numeric_limits::max()) { return FONT_COMPRESSION_FAILURE(); } if (*dst_size < ((12ULL + 2 * glyph.contours.size()) + glyph.instructions_size)) { return FONT_COMPRESSION_FAILURE(); } Store16(glyph.contours.size(), &offset, dst); StoreBbox(glyph, &offset, dst); if (!StoreEndPtsOfContours(glyph, &offset, dst)) { return FONT_COMPRESSION_FAILURE(); } StoreInstructions(glyph, &offset, dst); if (!StorePoints(glyph, &offset, dst, *dst_size)) { return FONT_COMPRESSION_FAILURE(); } } *dst_size = offset; return true; } } // namespace woff2 dvisvgm-3.5/libs/woff2/src/glyph.h000066400000000000000000000035231501401750600171010ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Data model and I/O for glyph data within sfnt format files for the purpose of performing the preprocessing step of the WOFF 2.0 conversion. */ #ifndef WOFF2_GLYPH_H_ #define WOFF2_GLYPH_H_ #include #include #include #include namespace woff2 { // Represents a parsed simple or composite glyph. The composite glyph data and // instructions are un-parsed and we keep only pointers to the raw data, // therefore the glyph is valid only so long the data from which it was parsed // is around. class Glyph { public: Glyph() : instructions_size(0), overlap_simple_flag_set(false), composite_data_size(0) {} // Bounding box. int16_t x_min; int16_t x_max; int16_t y_min; int16_t y_max; // Instructions. uint16_t instructions_size; const uint8_t* instructions_data; // Flags. bool overlap_simple_flag_set; // Data model for simple glyphs. struct Point { int x; int y; bool on_curve; }; std::vector > contours; // Data for composite glyphs. const uint8_t* composite_data; uint32_t composite_data_size; bool have_instructions; }; // Parses the glyph from the given data. Returns false on parsing failure or // buffer overflow. The glyph is valid only so long the input data pointer is // valid. bool ReadGlyph(const uint8_t* data, size_t len, Glyph* glyph); // Stores the glyph into the specified dst buffer. The *dst_size is the buffer // size on entry and is set to the actual (unpadded) stored size on exit. // Returns false on buffer overflow. bool StoreGlyph(const Glyph& glyph, uint8_t* dst, size_t* dst_size); } // namespace woff2 #endif // WOFF2_GLYPH_H_ dvisvgm-3.5/libs/woff2/src/normalize.cc000066400000000000000000000214541501401750600201170ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Glyph normalization */ #include "./normalize.h" #include #include #include "./buffer.h" #include "./port.h" #include "./font.h" #include "./glyph.h" #include "./round.h" #include "./store_bytes.h" #include "./table_tags.h" #include "./woff2_common.h" namespace woff2 { namespace { void StoreLoca(int index_fmt, uint32_t value, size_t* offset, uint8_t* dst) { if (index_fmt == 0) { Store16(value >> 1, offset, dst); } else { StoreU32(value, offset, dst); } } } // namespace namespace { bool WriteNormalizedLoca(int index_fmt, int num_glyphs, Font* font) { Font::Table* glyf_table = font->FindTable(kGlyfTableTag); Font::Table* loca_table = font->FindTable(kLocaTableTag); int glyph_sz = index_fmt == 0 ? 2 : 4; loca_table->buffer.resize(Round4(num_glyphs + 1) * glyph_sz); loca_table->length = (num_glyphs + 1) * glyph_sz; uint8_t* glyf_dst = num_glyphs ? &glyf_table->buffer[0] : NULL; uint8_t* loca_dst = &loca_table->buffer[0]; uint32_t glyf_offset = 0; size_t loca_offset = 0; for (int i = 0; i < num_glyphs; ++i) { StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst); Glyph glyph; const uint8_t* glyph_data; size_t glyph_size; if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) || (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) { return FONT_COMPRESSION_FAILURE(); } size_t glyf_dst_size = glyf_table->buffer.size() - glyf_offset; if (!StoreGlyph(glyph, glyf_dst + glyf_offset, &glyf_dst_size)) { return FONT_COMPRESSION_FAILURE(); } glyf_dst_size = Round4(glyf_dst_size); if (glyf_dst_size > std::numeric_limits::max() || glyf_offset + static_cast(glyf_dst_size) < glyf_offset || (index_fmt == 0 && glyf_offset + glyf_dst_size >= (1UL << 17))) { return FONT_COMPRESSION_FAILURE(); } glyf_offset += glyf_dst_size; } StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst); glyf_table->buffer.resize(glyf_offset); glyf_table->data = glyf_offset ? &glyf_table->buffer[0] : NULL; glyf_table->length = glyf_offset; loca_table->data = loca_offset ? &loca_table->buffer[0] : NULL; return true; } } // namespace namespace { bool MakeEditableBuffer(Font* font, int tableTag) { Font::Table* table = font->FindTable(tableTag); if (table == NULL) { return FONT_COMPRESSION_FAILURE(); } if (table->IsReused()) { return true; } unsigned sz = Round4(table->length); table->buffer.resize(sz); uint8_t* buf = &table->buffer[0]; memcpy(buf, table->data, table->length); if (PREDICT_FALSE(sz > table->length)) { memset(buf + table->length, 0, sz - table->length); } table->data = buf; return true; } } // namespace bool NormalizeGlyphs(Font* font) { Font::Table* head_table = font->FindTable(kHeadTableTag); Font::Table* glyf_table = font->FindTable(kGlyfTableTag); Font::Table* loca_table = font->FindTable(kLocaTableTag); if (head_table == NULL) { return FONT_COMPRESSION_FAILURE(); } // If you don't have glyf/loca this transform isn't very interesting if (loca_table == NULL && glyf_table == NULL) { return true; } // It would be best if you didn't have just one of glyf/loca if ((glyf_table == NULL) != (loca_table == NULL)) { return FONT_COMPRESSION_FAILURE(); } // Must share neither or both loca & glyf if (loca_table->IsReused() != glyf_table->IsReused()) { return FONT_COMPRESSION_FAILURE(); } if (loca_table->IsReused()) { return true; } int index_fmt = head_table->data[51]; int num_glyphs = NumGlyphs(*font); // We need to allocate a bit more than its original length for the normalized // glyf table, since it can happen that the glyphs in the original table are // 2-byte aligned, while in the normalized table they are 4-byte aligned. // That gives a maximum of 2 bytes increase per glyph. However, there is no // theoretical guarantee that the total size of the flags plus the coordinates // is the smallest possible in the normalized version, so we have to allow // some general overhead. // TODO(user) Figure out some more precise upper bound on the size of // the overhead. size_t max_normalized_glyf_size = 1.1 * glyf_table->length + 2 * num_glyphs; glyf_table->buffer.resize(max_normalized_glyf_size); // if we can't write a loca using short's (index_fmt 0) // try again using longs (index_fmt 1) if (!WriteNormalizedLoca(index_fmt, num_glyphs, font)) { if (index_fmt != 0) { return FONT_COMPRESSION_FAILURE(); } // Rewrite loca with 4-byte entries & update head to match index_fmt = 1; if (!WriteNormalizedLoca(index_fmt, num_glyphs, font)) { return FONT_COMPRESSION_FAILURE(); } head_table->buffer[51] = 1; } return true; } bool NormalizeOffsets(Font* font) { uint32_t offset = 12 + 16 * font->num_tables; for (auto tag : font->OutputOrderedTags()) { auto& table = font->tables[tag]; table.offset = offset; offset += Round4(table.length); } return true; } namespace { uint32_t ComputeHeaderChecksum(const Font& font) { uint32_t checksum = font.flavor; uint16_t max_pow2 = font.num_tables ? Log2Floor(font.num_tables) : 0; uint16_t search_range = max_pow2 ? 1 << (max_pow2 + 4) : 0; uint16_t range_shift = (font.num_tables << 4) - search_range; checksum += (font.num_tables << 16 | search_range); checksum += (max_pow2 << 16 | range_shift); for (const auto& i : font.tables) { const Font::Table* table = &i.second; if (table->IsReused()) { table = table->reuse_of; } checksum += table->tag; checksum += table->checksum; checksum += table->offset; checksum += table->length; } return checksum; } } // namespace bool FixChecksums(Font* font) { Font::Table* head_table = font->FindTable(kHeadTableTag); if (head_table == NULL) { return FONT_COMPRESSION_FAILURE(); } if (head_table->reuse_of != NULL) { head_table = head_table->reuse_of; } if (head_table->length < 12) { return FONT_COMPRESSION_FAILURE(); } uint8_t* head_buf = &head_table->buffer[0]; size_t offset = 8; StoreU32(0, &offset, head_buf); uint32_t file_checksum = 0; for (auto& i : font->tables) { Font::Table* table = &i.second; if (table->IsReused()) { table = table->reuse_of; } table->checksum = ComputeULongSum(table->data, table->length); file_checksum += table->checksum; } file_checksum += ComputeHeaderChecksum(*font); offset = 8; StoreU32(0xb1b0afba - file_checksum, &offset, head_buf); return true; } namespace { bool MarkTransformed(Font* font) { Font::Table* head_table = font->FindTable(kHeadTableTag); if (head_table == NULL) { return FONT_COMPRESSION_FAILURE(); } if (head_table->reuse_of != NULL) { head_table = head_table->reuse_of; } if (head_table->length < 17) { return FONT_COMPRESSION_FAILURE(); } // set bit 11 of head table 'flags' to indicate that font has undergone // lossless modifying transform int head_flags = head_table->data[16]; head_table->buffer[16] = head_flags | 0x08; return true; } } // namespace bool NormalizeWithoutFixingChecksums(Font* font) { return (MakeEditableBuffer(font, kHeadTableTag) && RemoveDigitalSignature(font) && MarkTransformed(font) && NormalizeGlyphs(font) && NormalizeOffsets(font)); } bool NormalizeFont(Font* font) { return (NormalizeWithoutFixingChecksums(font) && FixChecksums(font)); } bool NormalizeFontCollection(FontCollection* font_collection) { if (font_collection->fonts.size() == 1) { return NormalizeFont(&font_collection->fonts[0]); } uint32_t offset = CollectionHeaderSize(font_collection->header_version, font_collection->fonts.size()); for (auto& font : font_collection->fonts) { if (!NormalizeWithoutFixingChecksums(&font)) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Font normalization failed.\n"); #endif return FONT_COMPRESSION_FAILURE(); } offset += kSfntHeaderSize + kSfntEntrySize * font.num_tables; } // Start table offsets after TTC Header and Sfnt Headers for (auto& font : font_collection->fonts) { for (auto tag : font.OutputOrderedTags()) { Font::Table& table = font.tables[tag]; if (table.IsReused()) { table.offset = table.reuse_of->offset; } else { table.offset = offset; offset += Round4(table.length); } } } // Now we can fix the checksums for (auto& font : font_collection->fonts) { if (!FixChecksums(&font)) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Failed to fix checksums\n"); #endif return FONT_COMPRESSION_FAILURE(); } } return true; } } // namespace woff2 dvisvgm-3.5/libs/woff2/src/normalize.h000066400000000000000000000024251501401750600177560ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Functions for normalizing fonts. Since the WOFF 2.0 decoder creates font files in normalized form, the WOFF 2.0 conversion is guaranteed to be lossless (in a bitwise sense) only for normalized font files. */ #ifndef WOFF2_NORMALIZE_H_ #define WOFF2_NORMALIZE_H_ namespace woff2 { struct Font; struct FontCollection; // Changes the offset fields of the table headers so that the data for the // tables will be written in order of increasing tag values, without any gaps // other than the 4-byte padding. bool NormalizeOffsets(Font* font); // Changes the checksum fields of the table headers and the checksum field of // the head table so that it matches the current data. bool FixChecksums(Font* font); // Parses each of the glyphs in the font and writes them again to the glyf // table in normalized form, as defined by the StoreGlyph() function. Changes // the loca table accordigly. bool NormalizeGlyphs(Font* font); // Performs all of the normalization steps above. bool NormalizeFont(Font* font); bool NormalizeFontCollection(FontCollection* font_collection); } // namespace woff2 #endif // WOFF2_NORMALIZE_H_ dvisvgm-3.5/libs/woff2/src/port.h000066400000000000000000000032121501401750600167350ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Helper function for bit twiddling and macros for branch prediction. */ #ifndef WOFF2_PORT_H_ #define WOFF2_PORT_H_ #include namespace woff2 { typedef unsigned int uint32; inline int Log2Floor(uint32 n) { #if defined(__GNUC__) return n == 0 ? -1 : 31 ^ __builtin_clz(n); #else if (n == 0) return -1; int log = 0; uint32 value = n; for (int i = 4; i >= 0; --i) { int shift = (1 << i); uint32 x = value >> shift; if (x != 0) { value = x; log += shift; } } assert(value == 1); return log; #endif } } // namespace woff2 /* Compatibility with non-clang compilers. */ #ifndef __has_builtin #define __has_builtin(x) 0 #endif #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \ (defined(__llvm__) && __has_builtin(__builtin_expect)) #define PREDICT_FALSE(x) (__builtin_expect(x, 0)) #define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) #else #define PREDICT_FALSE(x) (x) #define PREDICT_TRUE(x) (x) #endif #if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \ (defined(M_ARM) && (M_ARM == 7)) || \ defined(__aarch64__) || defined(__ARM64_ARCH_8__) || defined(__i386) || \ defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #define WOFF_LITTLE_ENDIAN #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #define WOFF_BIG_ENDIAN #endif /* endianness */ #endif /* CPU whitelist */ #endif // WOFF2_PORT_H_ dvisvgm-3.5/libs/woff2/src/round.h000066400000000000000000000011131501401750600170760ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Helper for rounding */ #ifndef WOFF2_ROUND_H_ #define WOFF2_ROUND_H_ #include namespace woff2 { // Round a value up to the nearest multiple of 4. Don't round the value in the // case that rounding up overflows. template T Round4(T value) { if (std::numeric_limits::max() - value < 3) { return value; } return (value + 3) & ~3; } } // namespace woff2 #endif // WOFF2_ROUND_H_ dvisvgm-3.5/libs/woff2/src/store_bytes.h000066400000000000000000000024721501401750600203220ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Helper functions for storing integer values into byte streams. No bounds checking is performed, that is the responsibility of the caller. */ #ifndef WOFF2_STORE_BYTES_H_ #define WOFF2_STORE_BYTES_H_ #include #include #include #include "./port.h" namespace woff2 { inline size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) { dst[offset] = x >> 24; dst[offset + 1] = x >> 16; dst[offset + 2] = x >> 8; dst[offset + 3] = x; return offset + 4; } inline size_t Store16(uint8_t* dst, size_t offset, int x) { dst[offset] = x >> 8; dst[offset + 1] = x; return offset + 2; } inline void StoreU32(uint32_t val, size_t* offset, uint8_t* dst) { dst[(*offset)++] = val >> 24; dst[(*offset)++] = val >> 16; dst[(*offset)++] = val >> 8; dst[(*offset)++] = val; } inline void Store16(int val, size_t* offset, uint8_t* dst) { dst[(*offset)++] = val >> 8; dst[(*offset)++] = val; } inline void StoreBytes(const uint8_t* data, size_t len, size_t* offset, uint8_t* dst) { memcpy(&dst[*offset], data, len); *offset += len; } } // namespace woff2 #endif // WOFF2_STORE_BYTES_H_ dvisvgm-3.5/libs/woff2/src/table_tags.cc000066400000000000000000000047761501401750600202340ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Font table tags */ #include "./table_tags.h" namespace woff2 { // Note that the byte order is big-endian, not the same as ots.cc #define TAG(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) const uint32_t kKnownTags[63] = { TAG('c', 'm', 'a', 'p'), // 0 TAG('h', 'e', 'a', 'd'), // 1 TAG('h', 'h', 'e', 'a'), // 2 TAG('h', 'm', 't', 'x'), // 3 TAG('m', 'a', 'x', 'p'), // 4 TAG('n', 'a', 'm', 'e'), // 5 TAG('O', 'S', '/', '2'), // 6 TAG('p', 'o', 's', 't'), // 7 TAG('c', 'v', 't', ' '), // 8 TAG('f', 'p', 'g', 'm'), // 9 TAG('g', 'l', 'y', 'f'), // 10 TAG('l', 'o', 'c', 'a'), // 11 TAG('p', 'r', 'e', 'p'), // 12 TAG('C', 'F', 'F', ' '), // 13 TAG('V', 'O', 'R', 'G'), // 14 TAG('E', 'B', 'D', 'T'), // 15 TAG('E', 'B', 'L', 'C'), // 16 TAG('g', 'a', 's', 'p'), // 17 TAG('h', 'd', 'm', 'x'), // 18 TAG('k', 'e', 'r', 'n'), // 19 TAG('L', 'T', 'S', 'H'), // 20 TAG('P', 'C', 'L', 'T'), // 21 TAG('V', 'D', 'M', 'X'), // 22 TAG('v', 'h', 'e', 'a'), // 23 TAG('v', 'm', 't', 'x'), // 24 TAG('B', 'A', 'S', 'E'), // 25 TAG('G', 'D', 'E', 'F'), // 26 TAG('G', 'P', 'O', 'S'), // 27 TAG('G', 'S', 'U', 'B'), // 28 TAG('E', 'B', 'S', 'C'), // 29 TAG('J', 'S', 'T', 'F'), // 30 TAG('M', 'A', 'T', 'H'), // 31 TAG('C', 'B', 'D', 'T'), // 32 TAG('C', 'B', 'L', 'C'), // 33 TAG('C', 'O', 'L', 'R'), // 34 TAG('C', 'P', 'A', 'L'), // 35 TAG('S', 'V', 'G', ' '), // 36 TAG('s', 'b', 'i', 'x'), // 37 TAG('a', 'c', 'n', 't'), // 38 TAG('a', 'v', 'a', 'r'), // 39 TAG('b', 'd', 'a', 't'), // 40 TAG('b', 'l', 'o', 'c'), // 41 TAG('b', 's', 'l', 'n'), // 42 TAG('c', 'v', 'a', 'r'), // 43 TAG('f', 'd', 's', 'c'), // 44 TAG('f', 'e', 'a', 't'), // 45 TAG('f', 'm', 't', 'x'), // 46 TAG('f', 'v', 'a', 'r'), // 47 TAG('g', 'v', 'a', 'r'), // 48 TAG('h', 's', 't', 'y'), // 49 TAG('j', 'u', 's', 't'), // 50 TAG('l', 'c', 'a', 'r'), // 51 TAG('m', 'o', 'r', 't'), // 52 TAG('m', 'o', 'r', 'x'), // 53 TAG('o', 'p', 'b', 'd'), // 54 TAG('p', 'r', 'o', 'p'), // 55 TAG('t', 'r', 'a', 'k'), // 56 TAG('Z', 'a', 'p', 'f'), // 57 TAG('S', 'i', 'l', 'f'), // 58 TAG('G', 'l', 'a', 't'), // 59 TAG('G', 'l', 'o', 'c'), // 60 TAG('F', 'e', 'a', 't'), // 61 TAG('S', 'i', 'l', 'l'), // 62 }; } // namespace woff2 dvisvgm-3.5/libs/woff2/src/table_tags.h000066400000000000000000000014471501401750600200660ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Font table tags */ #ifndef WOFF2_TABLE_TAGS_H_ #define WOFF2_TABLE_TAGS_H_ #include namespace woff2 { // Tags of popular tables. static const uint32_t kGlyfTableTag = 0x676c7966; static const uint32_t kHeadTableTag = 0x68656164; static const uint32_t kLocaTableTag = 0x6c6f6361; static const uint32_t kDsigTableTag = 0x44534947; static const uint32_t kCffTableTag = 0x43464620; static const uint32_t kHmtxTableTag = 0x686d7478; static const uint32_t kHheaTableTag = 0x68686561; static const uint32_t kMaxpTableTag = 0x6d617870; extern const uint32_t kKnownTags[]; } // namespace woff2 #endif // WOFF2_TABLE_TAGS_H_ dvisvgm-3.5/libs/woff2/src/transform.cc000066400000000000000000000326001501401750600201250ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Library for preprocessing fonts as part of the WOFF 2.0 conversion. */ #include "./transform.h" #include // for std::abs #include "./buffer.h" #include "./font.h" #include "./glyph.h" #include "./table_tags.h" #include "./variable_length.h" namespace woff2 { namespace { const int FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; const int FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; const int FLAG_OVERLAP_SIMPLE_BITMAP = 1 << 0; void WriteBytes(std::vector* out, const uint8_t* data, size_t len) { if (len == 0) return; size_t offset = out->size(); out->resize(offset + len); memcpy(&(*out)[offset], data, len); } void WriteBytes(std::vector* out, const std::vector& in) { for (size_t i = 0; i < in.size(); ++i) { out->push_back(in[i]); } } void WriteUShort(std::vector* out, int value) { out->push_back(value >> 8); out->push_back(value & 255); } void WriteLong(std::vector* out, int value) { out->push_back((value >> 24) & 255); out->push_back((value >> 16) & 255); out->push_back((value >> 8) & 255); out->push_back(value & 255); } // Glyf table preprocessing, based on // GlyfEncoder.java class GlyfEncoder { public: explicit GlyfEncoder(int num_glyphs) : n_glyphs_(num_glyphs) { bbox_bitmap_.resize(((num_glyphs + 31) >> 5) << 2); } bool Encode(int glyph_id, const Glyph& glyph) { if (glyph.composite_data_size > 0) { WriteCompositeGlyph(glyph_id, glyph); } else if (glyph.contours.size() > 0) { WriteSimpleGlyph(glyph_id, glyph); } else { WriteUShort(&n_contour_stream_, 0); } return true; } void GetTransformedGlyfBytes(std::vector* result) { WriteUShort(result, 0); // Version WriteUShort(result, overlap_bitmap_.empty() ? 0x00 : FLAG_OVERLAP_SIMPLE_BITMAP); // Flags WriteUShort(result, n_glyphs_); WriteUShort(result, 0); // index_format, will be set later WriteLong(result, n_contour_stream_.size()); WriteLong(result, n_points_stream_.size()); WriteLong(result, flag_byte_stream_.size()); WriteLong(result, glyph_stream_.size()); WriteLong(result, composite_stream_.size()); WriteLong(result, bbox_bitmap_.size() + bbox_stream_.size()); WriteLong(result, instruction_stream_.size()); WriteBytes(result, n_contour_stream_); WriteBytes(result, n_points_stream_); WriteBytes(result, flag_byte_stream_); WriteBytes(result, glyph_stream_); WriteBytes(result, composite_stream_); WriteBytes(result, bbox_bitmap_); WriteBytes(result, bbox_stream_); WriteBytes(result, instruction_stream_); if (!overlap_bitmap_.empty()) { WriteBytes(result, overlap_bitmap_); } } private: void WriteInstructions(const Glyph& glyph) { Write255UShort(&glyph_stream_, glyph.instructions_size); WriteBytes(&instruction_stream_, glyph.instructions_data, glyph.instructions_size); } bool ShouldWriteSimpleGlyphBbox(const Glyph& glyph) { if (glyph.contours.empty() || glyph.contours[0].empty()) { return glyph.x_min || glyph.y_min || glyph.x_max || glyph.y_max; } int16_t x_min = glyph.contours[0][0].x; int16_t y_min = glyph.contours[0][0].y; int16_t x_max = x_min; int16_t y_max = y_min; for (const auto& contour : glyph.contours) { for (const auto& point : contour) { if (point.x < x_min) x_min = point.x; if (point.x > x_max) x_max = point.x; if (point.y < y_min) y_min = point.y; if (point.y > y_max) y_max = point.y; } } if (glyph.x_min != x_min) return true; if (glyph.y_min != y_min) return true; if (glyph.x_max != x_max) return true; if (glyph.y_max != y_max) return true; return false; } void WriteSimpleGlyph(int glyph_id, const Glyph& glyph) { if (glyph.overlap_simple_flag_set) { EnsureOverlapBitmap(); overlap_bitmap_[glyph_id >> 3] |= 0x80 >> (glyph_id & 7); } int num_contours = glyph.contours.size(); WriteUShort(&n_contour_stream_, num_contours); if (ShouldWriteSimpleGlyphBbox(glyph)) { WriteBbox(glyph_id, glyph); } for (int i = 0; i < num_contours; i++) { Write255UShort(&n_points_stream_, glyph.contours[i].size()); } int lastX = 0; int lastY = 0; for (int i = 0; i < num_contours; i++) { int num_points = glyph.contours[i].size(); for (int j = 0; j < num_points; j++) { int x = glyph.contours[i][j].x; int y = glyph.contours[i][j].y; int dx = x - lastX; int dy = y - lastY; WriteTriplet(glyph.contours[i][j].on_curve, dx, dy); lastX = x; lastY = y; } } if (num_contours > 0) { WriteInstructions(glyph); } } void WriteCompositeGlyph(int glyph_id, const Glyph& glyph) { WriteUShort(&n_contour_stream_, -1); WriteBbox(glyph_id, glyph); WriteBytes(&composite_stream_, glyph.composite_data, glyph.composite_data_size); if (glyph.have_instructions) { WriteInstructions(glyph); } } void WriteBbox(int glyph_id, const Glyph& glyph) { bbox_bitmap_[glyph_id >> 3] |= 0x80 >> (glyph_id & 7); WriteUShort(&bbox_stream_, glyph.x_min); WriteUShort(&bbox_stream_, glyph.y_min); WriteUShort(&bbox_stream_, glyph.x_max); WriteUShort(&bbox_stream_, glyph.y_max); } void WriteTriplet(bool on_curve, int x, int y) { int abs_x = std::abs(x); int abs_y = std::abs(y); int on_curve_bit = on_curve ? 0 : 128; int x_sign_bit = (x < 0) ? 0 : 1; int y_sign_bit = (y < 0) ? 0 : 1; int xy_sign_bits = x_sign_bit + 2 * y_sign_bit; if (x == 0 && abs_y < 1280) { flag_byte_stream_.push_back(on_curve_bit + ((abs_y & 0xf00) >> 7) + y_sign_bit); glyph_stream_.push_back(abs_y & 0xff); } else if (y == 0 && abs_x < 1280) { flag_byte_stream_.push_back(on_curve_bit + 10 + ((abs_x & 0xf00) >> 7) + x_sign_bit); glyph_stream_.push_back(abs_x & 0xff); } else if (abs_x < 65 && abs_y < 65) { flag_byte_stream_.push_back(on_curve_bit + 20 + ((abs_x - 1) & 0x30) + (((abs_y - 1) & 0x30) >> 2) + xy_sign_bits); glyph_stream_.push_back((((abs_x - 1) & 0xf) << 4) | ((abs_y - 1) & 0xf)); } else if (abs_x < 769 && abs_y < 769) { flag_byte_stream_.push_back(on_curve_bit + 84 + 12 * (((abs_x - 1) & 0x300) >> 8) + (((abs_y - 1) & 0x300) >> 6) + xy_sign_bits); glyph_stream_.push_back((abs_x - 1) & 0xff); glyph_stream_.push_back((abs_y - 1) & 0xff); } else if (abs_x < 4096 && abs_y < 4096) { flag_byte_stream_.push_back(on_curve_bit + 120 + xy_sign_bits); glyph_stream_.push_back(abs_x >> 4); glyph_stream_.push_back(((abs_x & 0xf) << 4) | (abs_y >> 8)); glyph_stream_.push_back(abs_y & 0xff); } else { flag_byte_stream_.push_back(on_curve_bit + 124 + xy_sign_bits); glyph_stream_.push_back(abs_x >> 8); glyph_stream_.push_back(abs_x & 0xff); glyph_stream_.push_back(abs_y >> 8); glyph_stream_.push_back(abs_y & 0xff); } } void EnsureOverlapBitmap() { if (overlap_bitmap_.empty()) { overlap_bitmap_.resize((n_glyphs_ + 7) >> 3); } } std::vector n_contour_stream_; std::vector n_points_stream_; std::vector flag_byte_stream_; std::vector composite_stream_; std::vector bbox_bitmap_; std::vector bbox_stream_; std::vector glyph_stream_; std::vector instruction_stream_; std::vector overlap_bitmap_; int n_glyphs_; }; } // namespace bool TransformGlyfAndLocaTables(Font* font) { // no transform for CFF const Font::Table* glyf_table = font->FindTable(kGlyfTableTag); const Font::Table* loca_table = font->FindTable(kLocaTableTag); // If you don't have glyf/loca this transform isn't very interesting if (loca_table == NULL && glyf_table == NULL) { return true; } // It would be best if you didn't have just one of glyf/loca if ((glyf_table == NULL) != (loca_table == NULL)) { return FONT_COMPRESSION_FAILURE(); } // Must share neither or both loca & glyf if (loca_table->IsReused() != glyf_table->IsReused()) { return FONT_COMPRESSION_FAILURE(); } if (loca_table->IsReused()) { return true; } Font::Table* transformed_glyf = &font->tables[kGlyfTableTag ^ 0x80808080]; Font::Table* transformed_loca = &font->tables[kLocaTableTag ^ 0x80808080]; int num_glyphs = NumGlyphs(*font); GlyfEncoder encoder(num_glyphs); for (int i = 0; i < num_glyphs; ++i) { Glyph glyph; const uint8_t* glyph_data; size_t glyph_size; if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) || (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) { return FONT_COMPRESSION_FAILURE(); } encoder.Encode(i, glyph); } encoder.GetTransformedGlyfBytes(&transformed_glyf->buffer); const Font::Table* head_table = font->FindTable(kHeadTableTag); if (head_table == NULL || head_table->length < 52) { return FONT_COMPRESSION_FAILURE(); } transformed_glyf->buffer[7] = head_table->data[51]; // index_format transformed_glyf->tag = kGlyfTableTag ^ 0x80808080; transformed_glyf->length = transformed_glyf->buffer.size(); transformed_glyf->data = transformed_glyf->buffer.data(); transformed_loca->tag = kLocaTableTag ^ 0x80808080; transformed_loca->length = 0; transformed_loca->data = NULL; return true; } // See https://www.microsoft.com/typography/otspec/hmtx.htm // See WOFF2 spec, 5.4. Transformed hmtx table format bool TransformHmtxTable(Font* font) { const Font::Table* glyf_table = font->FindTable(kGlyfTableTag); const Font::Table* hmtx_table = font->FindTable(kHmtxTableTag); const Font::Table* hhea_table = font->FindTable(kHheaTableTag); // If you don't have hmtx or a glyf not much is going to happen here if (hmtx_table == NULL || glyf_table == NULL) { return true; } // hmtx without hhea doesn't make sense if (hhea_table == NULL) { return FONT_COMPRESSION_FAILURE(); } // Skip 34 to reach 'hhea' numberOfHMetrics Buffer hhea_buf(hhea_table->data, hhea_table->length); uint16_t num_hmetrics; if (!hhea_buf.Skip(34) || !hhea_buf.ReadU16(&num_hmetrics)) { return FONT_COMPRESSION_FAILURE(); } // Must have at least one hMetric if (num_hmetrics < 1) { return FONT_COMPRESSION_FAILURE(); } int num_glyphs = NumGlyphs(*font); // Most fonts can be transformed; assume it's a go until proven otherwise std::vector advance_widths; std::vector proportional_lsbs; std::vector monospace_lsbs; bool remove_proportional_lsb = true; bool remove_monospace_lsb = (num_glyphs - num_hmetrics) > 0; Buffer hmtx_buf(hmtx_table->data, hmtx_table->length); for (int i = 0; i < num_glyphs; i++) { Glyph glyph; const uint8_t* glyph_data; size_t glyph_size; if (!GetGlyphData(*font, i, &glyph_data, &glyph_size) || (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) { return FONT_COMPRESSION_FAILURE(); } uint16_t advance_width = 0; int16_t lsb = 0; if (i < num_hmetrics) { // [0, num_hmetrics) are proportional hMetrics if (!hmtx_buf.ReadU16(&advance_width)) { return FONT_COMPRESSION_FAILURE(); } if (!hmtx_buf.ReadS16(&lsb)) { return FONT_COMPRESSION_FAILURE(); } if (glyph_size > 0 && glyph.x_min != lsb) { remove_proportional_lsb = false; } advance_widths.push_back(advance_width); proportional_lsbs.push_back(lsb); } else { // [num_hmetrics, num_glyphs) are monospace leftSideBearing's if (!hmtx_buf.ReadS16(&lsb)) { return FONT_COMPRESSION_FAILURE(); } if (glyph_size > 0 && glyph.x_min != lsb) { remove_monospace_lsb = false; } monospace_lsbs.push_back(lsb); } // If we know we can't optimize, bail out completely if (!remove_proportional_lsb && !remove_monospace_lsb) { return true; } } Font::Table* transformed_hmtx = &font->tables[kHmtxTableTag ^ 0x80808080]; uint8_t flags = 0; size_t transformed_size = 1 + 2 * advance_widths.size(); if (remove_proportional_lsb) { flags |= 1; } else { transformed_size += 2 * proportional_lsbs.size(); } if (remove_monospace_lsb) { flags |= 1 << 1; } else { transformed_size += 2 * monospace_lsbs.size(); } transformed_hmtx->buffer.reserve(transformed_size); std::vector* out = &transformed_hmtx->buffer; WriteBytes(out, &flags, 1); for (uint16_t advance_width : advance_widths) { WriteUShort(out, advance_width); } if (!remove_proportional_lsb) { for (int16_t lsb : proportional_lsbs) { WriteUShort(out, lsb); } } if (!remove_monospace_lsb) { for (int16_t lsb : monospace_lsbs) { WriteUShort(out, lsb); } } transformed_hmtx->tag = kHmtxTableTag ^ 0x80808080; transformed_hmtx->flag_byte = 1 << 6; transformed_hmtx->length = transformed_hmtx->buffer.size(); transformed_hmtx->data = transformed_hmtx->buffer.data(); return true; } } // namespace woff2 dvisvgm-3.5/libs/woff2/src/transform.h000066400000000000000000000014001501401750600177610ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Library for preprocessing fonts as part of the WOFF 2.0 conversion. */ #ifndef WOFF2_TRANSFORM_H_ #define WOFF2_TRANSFORM_H_ #include "./font.h" namespace woff2 { // Adds the transformed versions of the glyf and loca tables to the font. The // transformed loca table has zero length. The tag of the transformed tables is // derived from the original tag by flipping the MSBs of every byte. bool TransformGlyfAndLocaTables(Font* font); // Apply transformation to hmtx table if applicable for this font. bool TransformHmtxTable(Font* font); } // namespace woff2 #endif // WOFF2_TRANSFORM_H_ dvisvgm-3.5/libs/woff2/src/variable_length.cc000066400000000000000000000061501501401750600212410ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Helper functions for woff2 variable length types: 255UInt16 and UIntBase128 */ #include "./variable_length.h" namespace woff2 { size_t Size255UShort(uint16_t value) { size_t result = 3; if (value < 253) { result = 1; } else if (value < 762) { result = 2; } else { result = 3; } return result; } void Write255UShort(std::vector* out, int value) { if (value < 253) { out->push_back(value); } else if (value < 506) { out->push_back(255); out->push_back(value - 253); } else if (value < 762) { out->push_back(254); out->push_back(value - 506); } else { out->push_back(253); out->push_back(value >> 8); out->push_back(value & 0xff); } } void Store255UShort(int val, size_t* offset, uint8_t* dst) { std::vector packed; Write255UShort(&packed, val); for (uint8_t packed_byte : packed) { dst[(*offset)++] = packed_byte; } } // Based on section 6.1.1 of MicroType Express draft spec bool Read255UShort(Buffer* buf, unsigned int* value) { static const int kWordCode = 253; static const int kOneMoreByteCode2 = 254; static const int kOneMoreByteCode1 = 255; static const int kLowestUCode = 253; uint8_t code = 0; if (!buf->ReadU8(&code)) { return FONT_COMPRESSION_FAILURE(); } if (code == kWordCode) { uint16_t result = 0; if (!buf->ReadU16(&result)) { return FONT_COMPRESSION_FAILURE(); } *value = result; return true; } else if (code == kOneMoreByteCode1) { uint8_t result = 0; if (!buf->ReadU8(&result)) { return FONT_COMPRESSION_FAILURE(); } *value = result + kLowestUCode; return true; } else if (code == kOneMoreByteCode2) { uint8_t result = 0; if (!buf->ReadU8(&result)) { return FONT_COMPRESSION_FAILURE(); } *value = result + kLowestUCode * 2; return true; } else { *value = code; return true; } } bool ReadBase128(Buffer* buf, uint32_t* value) { uint32_t result = 0; for (size_t i = 0; i < 5; ++i) { uint8_t code = 0; if (!buf->ReadU8(&code)) { return FONT_COMPRESSION_FAILURE(); } // Leading zeros are invalid. if (i == 0 && code == 0x80) { return FONT_COMPRESSION_FAILURE(); } // If any of the top seven bits are set then we're about to overflow. if (result & 0xfe000000) { return FONT_COMPRESSION_FAILURE(); } result = (result << 7) | (code & 0x7f); if ((code & 0x80) == 0) { *value = result; return true; } } // Make sure not to exceed the size bound return FONT_COMPRESSION_FAILURE(); } size_t Base128Size(size_t n) { size_t size = 1; for (; n >= 128; n >>= 7) ++size; return size; } void StoreBase128(size_t len, size_t* offset, uint8_t* dst) { size_t size = Base128Size(len); for (size_t i = 0; i < size; ++i) { int b = static_cast((len >> (7 * (size - i - 1))) & 0x7f); if (i < size - 1) { b |= 0x80; } dst[(*offset)++] = b; } } } // namespace woff2 dvisvgm-3.5/libs/woff2/src/variable_length.h000066400000000000000000000014531501401750600211040ustar00rootroot00000000000000/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Helper functions for woff2 variable length types: 255UInt16 and UIntBase128 */ #ifndef WOFF2_VARIABLE_LENGTH_H_ #define WOFF2_VARIABLE_LENGTH_H_ #include #include #include "./buffer.h" namespace woff2 { size_t Size255UShort(uint16_t value); bool Read255UShort(Buffer* buf, unsigned int* value); void Write255UShort(std::vector* out, int value); void Store255UShort(int val, size_t* offset, uint8_t* dst); size_t Base128Size(size_t n); bool ReadBase128(Buffer* buf, uint32_t* value); void StoreBase128(size_t len, size_t* offset, uint8_t* dst); } // namespace woff2 #endif // WOFF2_VARIABLE_LENGTH_H_ dvisvgm-3.5/libs/woff2/src/woff2_common.cc000066400000000000000000000023211501401750600205020ustar00rootroot00000000000000/* Copyright 2013 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Helpers common across multiple parts of woff2 */ #include #include "./woff2_common.h" #include "./port.h" namespace woff2 { uint32_t ComputeULongSum(const uint8_t* buf, size_t size) { uint32_t checksum = 0; size_t aligned_size = size & ~3; for (size_t i = 0; i < aligned_size; i += 4) { checksum += (buf[i] << 24) | (buf[i + 1] << 16) | (buf[i + 2] << 8) | buf[i + 3]; } // treat size not aligned on 4 as if it were padded to 4 with 0's if (size != aligned_size) { uint32_t v = 0; for (size_t i = aligned_size; i < size; ++i) { v |= buf[i] << (24 - 8 * (i & 3)); } checksum += v; } return checksum; } size_t CollectionHeaderSize(uint32_t header_version, uint32_t num_fonts) { size_t size = 0; if (header_version == 0x00020000) { size += 12; // ulDsig{Tag,Length,Offset} } if (header_version == 0x00010000 || header_version == 0x00020000) { size += 12 // TTCTag, Version, numFonts + 4 * num_fonts; // OffsetTable[numFonts] } return size; } } // namespace woff2 dvisvgm-3.5/libs/woff2/src/woff2_common.h000066400000000000000000000026371501401750600203560ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Common definition for WOFF2 encoding/decoding */ #ifndef WOFF2_WOFF2_COMMON_H_ #define WOFF2_WOFF2_COMMON_H_ #include #include #include namespace woff2 { static const uint32_t kWoff2Signature = 0x774f4632; // "wOF2" // Leave the first byte open to store flag_byte const unsigned int kWoff2FlagsTransform = 1 << 8; // TrueType Collection ID string: 'ttcf' static const uint32_t kTtcFontFlavor = 0x74746366; static const size_t kSfntHeaderSize = 12; static const size_t kSfntEntrySize = 16; struct Point { int x; int y; bool on_curve; }; struct Table { uint32_t tag; uint32_t flags; uint32_t src_offset; uint32_t src_length; uint32_t transform_length; uint32_t dst_offset; uint32_t dst_length; const uint8_t* dst_data; bool operator<(const Table& other) const { return tag < other.tag; } }; // Size of the collection header. 0 if version indicates this isn't a // collection. Ref http://www.microsoft.com/typography/otspec/otff.htm, // True Type Collections size_t CollectionHeaderSize(uint32_t header_version, uint32_t num_fonts); // Compute checksum over size bytes of buf uint32_t ComputeULongSum(const uint8_t* buf, size_t size); } // namespace woff2 #endif // WOFF2_WOFF2_COMMON_H_ dvisvgm-3.5/libs/woff2/src/woff2_enc.cc000066400000000000000000000360661501401750600177740ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Library for converting TTF format font files to their WOFF2 versions. */ #include #include #include #include #include #include #include #include #include "./buffer.h" #include "./font.h" #include "./normalize.h" #include "./round.h" #include "./store_bytes.h" #include "./table_tags.h" #include "./transform.h" #include "./variable_length.h" #include "./woff2_common.h" namespace woff2 { namespace { const size_t kWoff2HeaderSize = 48; const size_t kWoff2EntrySize = 20; bool Compress(const uint8_t* data, const size_t len, uint8_t* result, uint32_t* result_len, BrotliEncoderMode mode, int quality) { size_t compressed_len = *result_len; if (BrotliEncoderCompress(quality, BROTLI_DEFAULT_WINDOW, mode, len, data, &compressed_len, result) == 0) { return false; } *result_len = compressed_len; return true; } bool Woff2Compress(const uint8_t* data, const size_t len, uint8_t* result, uint32_t* result_len, int quality) { return Compress(data, len, result, result_len, BROTLI_MODE_FONT, quality); } bool TextCompress(const uint8_t* data, const size_t len, uint8_t* result, uint32_t* result_len, int quality) { return Compress(data, len, result, result_len, BROTLI_MODE_TEXT, quality); } int KnownTableIndex(uint32_t tag) { for (int i = 0; i < 63; ++i) { if (tag == kKnownTags[i]) return i; } return 63; } void StoreTableEntry(const Table& table, size_t* offset, uint8_t* dst) { uint8_t flag_byte = (table.flags & 0xC0) | KnownTableIndex(table.tag); dst[(*offset)++] = flag_byte; // The index here is treated as a set of flag bytes because // bits 6 and 7 of the byte are reserved for future use as flags. // 0x3f or 63 means an arbitrary table tag. if ((flag_byte & 0x3f) == 0x3f) { StoreU32(table.tag, offset, dst); } StoreBase128(table.src_length, offset, dst); if ((table.flags & kWoff2FlagsTransform) != 0) { StoreBase128(table.transform_length, offset, dst); } } size_t TableEntrySize(const Table& table) { uint8_t flag_byte = KnownTableIndex(table.tag); size_t size = ((flag_byte & 0x3f) != 0x3f) ? 1 : 5; size += Base128Size(table.src_length); if ((table.flags & kWoff2FlagsTransform) != 0) { size += Base128Size(table.transform_length); } return size; } size_t ComputeWoff2Length(const FontCollection& font_collection, const std::vector& tables, std::map, uint16_t> index_by_tag_offset, size_t compressed_data_length, size_t extended_metadata_length) { size_t size = kWoff2HeaderSize; for (const auto& table : tables) { size += TableEntrySize(table); } // for collections only, collection tables if (font_collection.flavor == kTtcFontFlavor) { size += 4; // UInt32 Version of TTC Header size += Size255UShort(font_collection.fonts.size()); // 255UInt16 numFonts size += 4 * font_collection.fonts.size(); // UInt32 flavor for each for (const auto& font : font_collection.fonts) { size += Size255UShort(font.tables.size()); // 255UInt16 numTables for (const auto& entry : font.tables) { const Font::Table& table = entry.second; // no collection entry for xform table if (table.tag & 0x80808080) continue; std::pair tag_offset(table.tag, table.offset); uint16_t table_index = index_by_tag_offset[tag_offset]; size += Size255UShort(table_index); // 255UInt16 index entry } } } // compressed data size += compressed_data_length; size = Round4(size); size += extended_metadata_length; return size; } size_t ComputeUncompressedLength(const Font& font) { // sfnt header + offset table size_t size = 12 + 16 * font.num_tables; for (const auto& entry : font.tables) { const Font::Table& table = entry.second; if (table.tag & 0x80808080) continue; // xform tables don't stay if (table.IsReused()) continue; // don't have to pay twice size += Round4(table.length); } return size; } size_t ComputeUncompressedLength(const FontCollection& font_collection) { if (font_collection.flavor != kTtcFontFlavor) { return ComputeUncompressedLength(font_collection.fonts[0]); } size_t size = CollectionHeaderSize(font_collection.header_version, font_collection.fonts.size()); for (const auto& font : font_collection.fonts) { size += ComputeUncompressedLength(font); } return size; } size_t ComputeTotalTransformLength(const Font& font) { size_t total = 0; for (const auto& i : font.tables) { const Font::Table& table = i.second; if (table.IsReused()) { continue; } if (table.tag & 0x80808080 || !font.FindTable(table.tag ^ 0x80808080)) { // Count transformed tables and non-transformed tables that do not have // transformed versions. total += table.length; } } return total; } } // namespace size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length) { return MaxWOFF2CompressedSize(data, length, ""); } size_t MaxWOFF2CompressedSize(const uint8_t* data, size_t length, const std::string& extended_metadata) { // Except for the header size, which is 32 bytes larger in woff2 format, // all other parts should be smaller (table header in short format, // transformations and compression). Just to be sure, we will give some // headroom anyway. return length + 1024 + extended_metadata.length(); } uint32_t CompressedBufferSize(uint32_t original_size) { return 1.2 * original_size + 10240; } bool TransformFontCollection(FontCollection* font_collection) { for (auto& font : font_collection->fonts) { if (!TransformGlyfAndLocaTables(&font)) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "glyf/loca transformation failed.\n"); #endif return FONT_COMPRESSION_FAILURE(); } } return true; } bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, uint8_t *result, size_t *result_length) { WOFF2Params params; return ConvertTTFToWOFF2(data, length, result, result_length, params); } bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, uint8_t *result, size_t *result_length, const WOFF2Params& params) { FontCollection font_collection; if (!ReadFontCollection(data, length, &font_collection)) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Parsing of the input font failed.\n"); #endif return FONT_COMPRESSION_FAILURE(); } if (!NormalizeFontCollection(&font_collection)) { return FONT_COMPRESSION_FAILURE(); } if (params.allow_transforms && !TransformFontCollection(&font_collection)) { return FONT_COMPRESSION_FAILURE(); } else { // glyf/loca use 11 to flag "not transformed" for (auto& font : font_collection.fonts) { Font::Table* glyf_table = font.FindTable(kGlyfTableTag); Font::Table* loca_table = font.FindTable(kLocaTableTag); if (glyf_table) { glyf_table->flag_byte |= 0xc0; } if (loca_table) { loca_table->flag_byte |= 0xc0; } } } // Although the compressed size of each table in the final woff2 file won't // be larger than its transform_length, we have to allocate a large enough // buffer for the compressor, since the compressor can potentially increase // the size. If the compressor overflows this, it should return false and // then this function will also return false. size_t total_transform_length = 0; for (const auto& font : font_collection.fonts) { total_transform_length += ComputeTotalTransformLength(font); } size_t compression_buffer_size = CompressedBufferSize(total_transform_length); std::vector compression_buf(compression_buffer_size); uint32_t total_compressed_length = compression_buffer_size; // Collect all transformed data into one place in output order. std::vector transform_buf(total_transform_length); size_t transform_offset = 0; for (const auto& font : font_collection.fonts) { for (const auto tag : font.OutputOrderedTags()) { const Font::Table& original = font.tables.at(tag); if (original.IsReused()) continue; if (tag & 0x80808080) continue; const Font::Table* table_to_store = font.FindTable(tag ^ 0x80808080); if (table_to_store == NULL) table_to_store = &original; StoreBytes(table_to_store->data, table_to_store->length, &transform_offset, &transform_buf[0]); } } // Compress all transformed data in one stream. if (!Woff2Compress(transform_buf.data(), total_transform_length, &compression_buf[0], &total_compressed_length, params.brotli_quality)) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Compression of combined table failed.\n"); #endif return FONT_COMPRESSION_FAILURE(); } #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Compressed %zu to %u.\n", total_transform_length, total_compressed_length); #endif // Compress the extended metadata // TODO(user): how does this apply to collections uint32_t compressed_metadata_buf_length = CompressedBufferSize(params.extended_metadata.length()); std::vector compressed_metadata_buf(compressed_metadata_buf_length); if (params.extended_metadata.length() > 0) { if (!TextCompress((const uint8_t*)params.extended_metadata.data(), params.extended_metadata.length(), compressed_metadata_buf.data(), &compressed_metadata_buf_length, params.brotli_quality)) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Compression of extended metadata failed.\n"); #endif return FONT_COMPRESSION_FAILURE(); } } else { compressed_metadata_buf_length = 0; } std::vector
tables; std::map, uint16_t> index_by_tag_offset; for (const auto& font : font_collection.fonts) { for (const auto tag : font.OutputOrderedTags()) { const Font::Table& src_table = font.tables.at(tag); if (src_table.IsReused()) { continue; } std::pair tag_offset(src_table.tag, src_table.offset); if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) { index_by_tag_offset[tag_offset] = tables.size(); } else { return false; } Table table; table.tag = src_table.tag; table.flags = src_table.flag_byte; table.src_length = src_table.length; table.transform_length = src_table.length; const Font::Table* transformed_table = font.FindTable(src_table.tag ^ 0x80808080); if (transformed_table != NULL) { table.flags = transformed_table->flag_byte; table.flags |= kWoff2FlagsTransform; table.transform_length = transformed_table->length; } tables.push_back(table); } } size_t woff2_length = ComputeWoff2Length(font_collection, tables, index_by_tag_offset, total_compressed_length, compressed_metadata_buf_length); if (woff2_length > *result_length) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Result allocation was too small (%zd vs %zd bytes).\n", *result_length, woff2_length); #endif return FONT_COMPRESSION_FAILURE(); } *result_length = woff2_length; size_t offset = 0; // start of woff2 header (http://www.w3.org/TR/WOFF2/#woff20Header) StoreU32(kWoff2Signature, &offset, result); if (font_collection.flavor != kTtcFontFlavor) { StoreU32(font_collection.fonts[0].flavor, &offset, result); } else { StoreU32(kTtcFontFlavor, &offset, result); } StoreU32(woff2_length, &offset, result); Store16(tables.size(), &offset, result); Store16(0, &offset, result); // reserved // totalSfntSize StoreU32(ComputeUncompressedLength(font_collection), &offset, result); StoreU32(total_compressed_length, &offset, result); // totalCompressedSize // Let's just all be v1.0 Store16(1, &offset, result); // majorVersion Store16(0, &offset, result); // minorVersion if (compressed_metadata_buf_length > 0) { StoreU32(woff2_length - compressed_metadata_buf_length, &offset, result); // metaOffset StoreU32(compressed_metadata_buf_length, &offset, result); // metaLength StoreU32(params.extended_metadata.length(), &offset, result); // metaOrigLength } else { StoreU32(0, &offset, result); // metaOffset StoreU32(0, &offset, result); // metaLength StoreU32(0, &offset, result); // metaOrigLength } StoreU32(0, &offset, result); // privOffset StoreU32(0, &offset, result); // privLength // end of woff2 header // table directory (http://www.w3.org/TR/WOFF2/#table_dir_format) for (const auto& table : tables) { StoreTableEntry(table, &offset, result); } // for collections only, collection table directory if (font_collection.flavor == kTtcFontFlavor) { StoreU32(font_collection.header_version, &offset, result); Store255UShort(font_collection.fonts.size(), &offset, result); for (const Font& font : font_collection.fonts) { uint16_t num_tables = 0; for (const auto& entry : font.tables) { const Font::Table& table = entry.second; if (table.tag & 0x80808080) continue; // don't write xform tables num_tables++; } Store255UShort(num_tables, &offset, result); StoreU32(font.flavor, &offset, result); for (const auto& entry : font.tables) { const Font::Table& table = entry.second; if (table.tag & 0x80808080) continue; // don't write xform tables // for reused tables, only the original has an updated offset uint32_t table_offset = table.IsReused() ? table.reuse_of->offset : table.offset; std::pair tag_offset(table.tag, table_offset); if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Missing table index for offset 0x%08x\n", table_offset); #endif return FONT_COMPRESSION_FAILURE(); } uint16_t index = index_by_tag_offset[tag_offset]; Store255UShort(index, &offset, result); } } } // compressed data format (http://www.w3.org/TR/WOFF2/#table_format) StoreBytes(&compression_buf[0], total_compressed_length, &offset, result); offset = Round4(offset); StoreBytes(compressed_metadata_buf.data(), compressed_metadata_buf_length, &offset, result); if (*result_length != offset) { #ifdef FONT_COMPRESSION_BIN fprintf(stderr, "Mismatch between computed and actual length " "(%zd vs %zd)\n", *result_length, offset); #endif return FONT_COMPRESSION_FAILURE(); } return true; } } // namespace woff2 dvisvgm-3.5/libs/woff2/src/woff2_out.cc000066400000000000000000000030071501401750600200230ustar00rootroot00000000000000/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Output buffer for WOFF2 decompression. */ #include namespace woff2 { WOFF2StringOut::WOFF2StringOut(std::string *buf) : buf_(buf), max_size_(kDefaultMaxSize), offset_(0) {} bool WOFF2StringOut::Write(const void *buf, size_t n) { return Write(buf, offset_, n); } bool WOFF2StringOut::Write(const void *buf, size_t offset, size_t n) { if (offset > max_size_ || n > max_size_ - offset) { return false; } if (offset == buf_->size()) { buf_->append(static_cast(buf), n); } else { if (offset + n > buf_->size()) { buf_->append(offset + n - buf_->size(), 0); } buf_->replace(offset, n, static_cast(buf), n); } offset_ = std::max(offset_, offset + n); return true; } void WOFF2StringOut::SetMaxSize(size_t max_size) { max_size_ = max_size; if (offset_ > max_size_) { offset_ = max_size_; } } WOFF2MemoryOut::WOFF2MemoryOut(uint8_t* buf, size_t buf_size) : buf_(buf), buf_size_(buf_size), offset_(0) {} bool WOFF2MemoryOut::Write(const void *buf, size_t n) { return Write(buf, offset_, n); } bool WOFF2MemoryOut::Write(const void *buf, size_t offset, size_t n) { if (offset > buf_size_ || n > buf_size_ - offset) { return false; } std::memcpy(buf_ + offset, buf, n); offset_ = std::max(offset_, offset + n); return true; } } // namespace woff2 dvisvgm-3.5/libs/xxHash/000077500000000000000000000000001501401750600152335ustar00rootroot00000000000000dvisvgm-3.5/libs/xxHash/LICENSE000066400000000000000000000024421501401750600162420ustar00rootroot00000000000000xxHash Library Copyright (c) 2012-2014, Yann Collet All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dvisvgm-3.5/libs/xxHash/Makefile.am000066400000000000000000000002621501401750600172670ustar00rootroot00000000000000if !HAVE_XXHASH noinst_LIBRARIES = libxxhash.a libxxhash_a_SOURCES = xxhash.c xxhash.h xxh3.h AM_CXXFLAGS = -Wall xxhash.c: xxhash.h xxh3.h endif CLEANFILES = *.gcda *.gcno dvisvgm-3.5/libs/xxHash/xxh3.h000066400000000000000000000045321501401750600163020ustar00rootroot00000000000000/* * xxHash - Extremely Fast Hash algorithm * Development source file for `xxh3` * Copyright (C) 2019-2021 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ /* * Note: This file used to host the source code of XXH3_* variants. * during the development period. * The source code is now properly integrated within xxhash.h. * * xxh3.h is no longer useful, * but it is still provided for compatibility with source code * which used to include it directly. * * Programs are now highly discouraged to include xxh3.h. * Include `xxhash.h` instead, which is the officially supported interface. * * In the future, xxh3.h will start to generate warnings, then errors, * then it will be removed from source package and from include directory. */ /* Simulate the same impact as including the old xxh3.h source file */ #define XXH_INLINE_ALL #include "xxhash.h" dvisvgm-3.5/libs/xxHash/xxhash.c000066400000000000000000000034771501401750600167150ustar00rootroot00000000000000/* * xxHash - Extremely Fast Hash algorithm * Copyright (C) 2012-2023 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ /* * xxhash.c instantiates functions defined in xxhash.h */ #define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ #define XXH_IMPLEMENTATION /* access definitions */ #include "xxhash.h" dvisvgm-3.5/libs/xxHash/xxhash.h000066400000000000000000010140371501401750600167150ustar00rootroot00000000000000/* * xxHash - Extremely Fast Hash algorithm * Header File * Copyright (C) 2012-2023 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ /*! * @mainpage xxHash * * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed * limits. * * It is proposed in four flavors, in three families: * 1. @ref XXH32_family * - Classic 32-bit hash function. Simple, compact, and runs on almost all * 32-bit and 64-bit systems. * 2. @ref XXH64_family * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most * 64-bit systems (but _not_ 32-bit systems). * 3. @ref XXH3_family * - Modern 64-bit and 128-bit hash function family which features improved * strength and performance across the board, especially on smaller data. * It benefits greatly from SIMD and 64-bit without requiring it. * * Benchmarks * --- * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04. * The open source benchmark program is compiled with clang v10.0 using -O3 flag. * * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity | * | -------------------- | ------- | ----: | ---------------: | ------------------: | * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 | * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 | * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 | * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 | * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 | * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 | * | RAM sequential read | | N/A | 28.0 GB/s | N/A | * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 | * | City64 | | 64 | 22.0 GB/s | 76.6 | * | T1ha2 | | 64 | 22.0 GB/s | 99.0 | * | City128 | | 128 | 21.7 GB/s | 57.7 | * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 | * | XXH64() | | 64 | 19.4 GB/s | 71.0 | * | SpookyHash | | 64 | 19.3 GB/s | 53.2 | * | Mum | | 64 | 18.0 GB/s | 67.0 | * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 | * | XXH32() | | 32 | 9.7 GB/s | 71.9 | * | City32 | | 32 | 9.1 GB/s | 66.0 | * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 | * | Murmur3 | | 32 | 3.9 GB/s | 56.1 | * | SipHash* | | 64 | 3.0 GB/s | 43.2 | * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 | * | HighwayHash | | 64 | 1.4 GB/s | 6.0 | * | FNV64 | | 64 | 1.2 GB/s | 62.7 | * | Blake2* | | 256 | 1.1 GB/s | 5.1 | * | SHA1* | | 160 | 0.8 GB/s | 5.6 | * | MD5* | | 128 | 0.6 GB/s | 7.8 | * @note * - Hashes which require a specific ISA extension are noted. SSE2 is also noted, * even though it is mandatory on x64. * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic * by modern standards. * - Small data velocity is a rough average of algorithm's efficiency for small * data. For more accurate information, see the wiki. * - More benchmarks and strength tests are found on the wiki: * https://github.com/Cyan4973/xxHash/wiki * * Usage * ------ * All xxHash variants use a similar API. Changing the algorithm is a trivial * substitution. * * @pre * For functions which take an input and length parameter, the following * requirements are assumed: * - The range from [`input`, `input + length`) is valid, readable memory. * - The only exception is if the `length` is `0`, `input` may be `NULL`. * - For C++, the objects must have the *TriviallyCopyable* property, as the * functions access bytes directly as if it was an array of `unsigned char`. * * @anchor single_shot_example * **Single Shot** * * These functions are stateless functions which hash a contiguous block of memory, * immediately returning the result. They are the easiest and usually the fastest * option. * * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits() * * @code{.c} * #include * #include "xxhash.h" * * // Example for a function which hashes a null terminated string with XXH32(). * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed) * { * // NULL pointers are only valid if the length is zero * size_t length = (string == NULL) ? 0 : strlen(string); * return XXH32(string, length, seed); * } * @endcode * * * @anchor streaming_example * **Streaming** * * These groups of functions allow incremental hashing of unknown size, even * more than what would fit in a size_t. * * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset() * * @code{.c} * #include * #include * #include "xxhash.h" * // Example for a function which hashes a FILE incrementally with XXH3_64bits(). * XXH64_hash_t hashFile(FILE* f) * { * // Allocate a state struct. Do not just use malloc() or new. * XXH3_state_t* state = XXH3_createState(); * assert(state != NULL && "Out of memory!"); * // Reset the state to start a new hashing session. * XXH3_64bits_reset(state); * char buffer[4096]; * size_t count; * // Read the file in chunks * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) { * // Run update() as many times as necessary to process the data * XXH3_64bits_update(state, buffer, count); * } * // Retrieve the finalized hash. This will not change the state. * XXH64_hash_t result = XXH3_64bits_digest(state); * // Free the state. Do not use free(). * XXH3_freeState(state); * return result; * } * @endcode * * Streaming functions generate the xxHash value from an incremental input. * This method is slower than single-call functions, due to state management. * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. * * An XXH state must first be allocated using `XXH*_createState()`. * * Start a new hash by initializing the state with a seed using `XXH*_reset()`. * * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. * * The function returns an error code, with 0 meaning OK, and any other value * meaning there is an error. * * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. * This function returns the nn-bits hash as an int or long long. * * It's still possible to continue inserting input into the hash state after a * digest, and generate new hash values later on by invoking `XXH*_digest()`. * * When done, release the state using `XXH*_freeState()`. * * * @anchor canonical_representation_example * **Canonical Representation** * * The default return values from XXH functions are unsigned 32, 64 and 128 bit * integers. * This the simplest and fastest format for further post-processing. * * However, this leaves open the question of what is the order on the byte level, * since little and big endian conventions will store the same number differently. * * The canonical representation settles this issue by mandating big-endian * convention, the same convention as human-readable numbers (large digits first). * * When writing hash values to storage, sending them over a network, or printing * them, it's highly recommended to use the canonical representation to ensure * portability across a wider range of systems, present and future. * * The following functions allow transformation of hash values to and from * canonical format. * * XXH32_canonicalFromHash(), XXH32_hashFromCanonical(), * XXH64_canonicalFromHash(), XXH64_hashFromCanonical(), * XXH128_canonicalFromHash(), XXH128_hashFromCanonical(), * * @code{.c} * #include * #include "xxhash.h" * * // Example for a function which prints XXH32_hash_t in human readable format * void printXxh32(XXH32_hash_t hash) * { * XXH32_canonical_t cano; * XXH32_canonicalFromHash(&cano, hash); * size_t i; * for(i = 0; i < sizeof(cano.digest); ++i) { * printf("%02x", cano.digest[i]); * } * printf("\n"); * } * * // Example for a function which converts XXH32_canonical_t to XXH32_hash_t * XXH32_hash_t convertCanonicalToXxh32(XXH32_canonical_t cano) * { * XXH32_hash_t hash = XXH32_hashFromCanonical(&cano); * return hash; * } * @endcode * * * @file xxhash.h * xxHash prototypes and implementation */ #if defined (__cplusplus) extern "C" { #endif /* **************************** * INLINE mode ******************************/ /*! * @defgroup public Public API * Contains details on the public xxHash functions. * @{ */ #ifdef XXH_DOXYGEN /*! * @brief Gives access to internal state declaration, required for static allocation. * * Incompatible with dynamic linking, due to risks of ABI changes. * * Usage: * @code{.c} * #define XXH_STATIC_LINKING_ONLY * #include "xxhash.h" * @endcode */ # define XXH_STATIC_LINKING_ONLY /* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */ /*! * @brief Gives access to internal definitions. * * Usage: * @code{.c} * #define XXH_STATIC_LINKING_ONLY * #define XXH_IMPLEMENTATION * #include "xxhash.h" * @endcode */ # define XXH_IMPLEMENTATION /* Do not undef XXH_IMPLEMENTATION for Doxygen */ /*! * @brief Exposes the implementation and marks all functions as `inline`. * * Use these build macros to inline xxhash into the target unit. * Inlining improves performance on small inputs, especially when the length is * expressed as a compile-time constant: * * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html * * It also keeps xxHash symbols private to the unit, so they are not exported. * * Usage: * @code{.c} * #define XXH_INLINE_ALL * #include "xxhash.h" * @endcode * Do not compile and link xxhash.o as a separate object, as it is not useful. */ # define XXH_INLINE_ALL # undef XXH_INLINE_ALL /*! * @brief Exposes the implementation without marking functions as inline. */ # define XXH_PRIVATE_API # undef XXH_PRIVATE_API /*! * @brief Emulate a namespace by transparently prefixing all symbols. * * If you want to include _and expose_ xxHash functions from within your own * library, but also want to avoid symbol collisions with other libraries which * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE * (therefore, avoid empty or numeric values). * * Note that no change is required within the calling program as long as it * includes `xxhash.h`: Regular symbol names will be automatically translated * by this header. */ # define XXH_NAMESPACE /* YOUR NAME HERE */ # undef XXH_NAMESPACE #endif #if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ && !defined(XXH_INLINE_ALL_31684351384) /* this section should be traversed only once */ # define XXH_INLINE_ALL_31684351384 /* give access to the advanced API, required to compile implementations */ # undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */ # define XXH_STATIC_LINKING_ONLY /* make all functions private */ # undef XXH_PUBLIC_API # if defined(__GNUC__) # define XXH_PUBLIC_API static __inline __attribute__((__unused__)) # elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # define XXH_PUBLIC_API static inline # elif defined(_MSC_VER) # define XXH_PUBLIC_API static __inline # else /* note: this version may generate warnings for unused static functions */ # define XXH_PUBLIC_API static # endif /* * This part deals with the special case where a unit wants to inline xxHash, * but "xxhash.h" has previously been included without XXH_INLINE_ALL, * such as part of some previously included *.h header file. * Without further action, the new include would just be ignored, * and functions would effectively _not_ be inlined (silent failure). * The following macros solve this situation by prefixing all inlined names, * avoiding naming collision with previous inclusions. */ /* Before that, we unconditionally #undef all symbols, * in case they were already defined with XXH_NAMESPACE. * They will then be redefined for XXH_INLINE_ALL */ # undef XXH_versionNumber /* XXH32 */ # undef XXH32 # undef XXH32_createState # undef XXH32_freeState # undef XXH32_reset # undef XXH32_update # undef XXH32_digest # undef XXH32_copyState # undef XXH32_canonicalFromHash # undef XXH32_hashFromCanonical /* XXH64 */ # undef XXH64 # undef XXH64_createState # undef XXH64_freeState # undef XXH64_reset # undef XXH64_update # undef XXH64_digest # undef XXH64_copyState # undef XXH64_canonicalFromHash # undef XXH64_hashFromCanonical /* XXH3_64bits */ # undef XXH3_64bits # undef XXH3_64bits_withSecret # undef XXH3_64bits_withSeed # undef XXH3_64bits_withSecretandSeed # undef XXH3_createState # undef XXH3_freeState # undef XXH3_copyState # undef XXH3_64bits_reset # undef XXH3_64bits_reset_withSeed # undef XXH3_64bits_reset_withSecret # undef XXH3_64bits_update # undef XXH3_64bits_digest # undef XXH3_generateSecret /* XXH3_128bits */ # undef XXH128 # undef XXH3_128bits # undef XXH3_128bits_withSeed # undef XXH3_128bits_withSecret # undef XXH3_128bits_reset # undef XXH3_128bits_reset_withSeed # undef XXH3_128bits_reset_withSecret # undef XXH3_128bits_reset_withSecretandSeed # undef XXH3_128bits_update # undef XXH3_128bits_digest # undef XXH128_isEqual # undef XXH128_cmp # undef XXH128_canonicalFromHash # undef XXH128_hashFromCanonical /* Finally, free the namespace itself */ # undef XXH_NAMESPACE /* employ the namespace for XXH_INLINE_ALL */ # define XXH_NAMESPACE XXH_INLINE_ /* * Some identifiers (enums, type names) are not symbols, * but they must nonetheless be renamed to avoid redeclaration. * Alternative solution: do not redeclare them. * However, this requires some #ifdefs, and has a more dispersed impact. * Meanwhile, renaming can be achieved in a single place. */ # define XXH_IPREF(Id) XXH_NAMESPACE ## Id # define XXH_OK XXH_IPREF(XXH_OK) # define XXH_ERROR XXH_IPREF(XXH_ERROR) # define XXH_errorcode XXH_IPREF(XXH_errorcode) # define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t) # define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t) # define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t) # define XXH32_state_s XXH_IPREF(XXH32_state_s) # define XXH32_state_t XXH_IPREF(XXH32_state_t) # define XXH64_state_s XXH_IPREF(XXH64_state_s) # define XXH64_state_t XXH_IPREF(XXH64_state_t) # define XXH3_state_s XXH_IPREF(XXH3_state_s) # define XXH3_state_t XXH_IPREF(XXH3_state_t) # define XXH128_hash_t XXH_IPREF(XXH128_hash_t) /* Ensure the header is parsed again, even if it was previously included */ # undef XXHASH_H_5627135585666179 # undef XXHASH_H_STATIC_13879238742 #endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ /* **************************************************************** * Stable API *****************************************************************/ #ifndef XXHASH_H_5627135585666179 #define XXHASH_H_5627135585666179 1 /*! @brief Marks a global symbol. */ #if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) # if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) # ifdef XXH_EXPORT # define XXH_PUBLIC_API __declspec(dllexport) # elif XXH_IMPORT # define XXH_PUBLIC_API __declspec(dllimport) # endif # else # define XXH_PUBLIC_API /* do nothing */ # endif #endif #ifdef XXH_NAMESPACE # define XXH_CAT(A,B) A##B # define XXH_NAME2(A,B) XXH_CAT(A,B) # define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) /* XXH32 */ # define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) # define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) # define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) # define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) # define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) # define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) # define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) # define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) # define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) /* XXH64 */ # define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) # define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) # define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) # define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) # define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) # define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) # define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) # define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) # define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) /* XXH3_64bits */ # define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits) # define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret) # define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed) # define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed) # define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState) # define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState) # define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState) # define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset) # define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed) # define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret) # define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed) # define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update) # define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest) # define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret) # define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed) /* XXH3_128bits */ # define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128) # define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits) # define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed) # define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret) # define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed) # define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset) # define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed) # define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret) # define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed) # define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update) # define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest) # define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual) # define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp) # define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash) # define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical) #endif /* ************************************* * Compiler specifics ***************************************/ /* specific declaration modes for Windows */ #if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) # if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) # ifdef XXH_EXPORT # define XXH_PUBLIC_API __declspec(dllexport) # elif XXH_IMPORT # define XXH_PUBLIC_API __declspec(dllimport) # endif # else # define XXH_PUBLIC_API /* do nothing */ # endif #endif #if defined (__GNUC__) # define XXH_CONSTF __attribute__((__const__)) # define XXH_PUREF __attribute__((__pure__)) # define XXH_MALLOCF __attribute__((__malloc__)) #else # define XXH_CONSTF /* disable */ # define XXH_PUREF # define XXH_MALLOCF #endif /* ************************************* * Version ***************************************/ #define XXH_VERSION_MAJOR 0 #define XXH_VERSION_MINOR 8 #define XXH_VERSION_RELEASE 3 /*! @brief Version number, encoded as two digits each */ #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) /*! * @brief Obtains the xxHash version. * * This is mostly useful when xxHash is compiled as a shared library, * since the returned value comes from the library, as opposed to header file. * * @return @ref XXH_VERSION_NUMBER of the invoked library. */ XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void); /* **************************** * Common basic types ******************************/ #include /* size_t */ /*! * @brief Exit code for the streaming API. */ typedef enum { XXH_OK = 0, /*!< OK */ XXH_ERROR /*!< Error */ } XXH_errorcode; /*-********************************************************************** * 32-bit hash ************************************************************************/ #if defined(XXH_DOXYGEN) /* Don't show include */ /*! * @brief An unsigned 32-bit integer. * * Not necessarily defined to `uint32_t` but functionally equivalent. */ typedef uint32_t XXH32_hash_t; #elif !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # ifdef _AIX # include # else # include # endif typedef uint32_t XXH32_hash_t; #else # include # if UINT_MAX == 0xFFFFFFFFUL typedef unsigned int XXH32_hash_t; # elif ULONG_MAX == 0xFFFFFFFFUL typedef unsigned long XXH32_hash_t; # else # error "unsupported platform: need a 32-bit type" # endif #endif /*! * @} * * @defgroup XXH32_family XXH32 family * @ingroup public * Contains functions used in the classic 32-bit xxHash algorithm. * * @note * XXH32 is useful for older platforms, with no or poor 64-bit performance. * Note that the @ref XXH3_family provides competitive speed for both 32-bit * and 64-bit systems, and offers true 64/128 bit hash results. * * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families * @see @ref XXH32_impl for implementation details * @{ */ /*! * @brief Calculates the 32-bit hash of @p input using xxHash32. * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 32-bit seed to alter the hash's output predictably. * * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return The calculated 32-bit xxHash32 value. * * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); #ifndef XXH_NO_STREAM /*! * @typedef struct XXH32_state_s XXH32_state_t * @brief The opaque state struct for the XXH32 streaming API. * * @see XXH32_state_s for details. * @see @ref streaming_example "Streaming Example" */ typedef struct XXH32_state_s XXH32_state_t; /*! * @brief Allocates an @ref XXH32_state_t. * * @return An allocated pointer of @ref XXH32_state_t on success. * @return `NULL` on failure. * * @note Must be freed with XXH32_freeState(). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); /*! * @brief Frees an @ref XXH32_state_t. * * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). * * @return @ref XXH_OK. * * @note @p statePtr must be allocated with XXH32_createState(). * * @see @ref streaming_example "Streaming Example" * */ XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); /*! * @brief Copies one @ref XXH32_state_t to another. * * @param dst_state The state to copy to. * @param src_state The state to copy from. * @pre * @p dst_state and @p src_state must not be `NULL` and must not overlap. */ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); /*! * @brief Resets an @ref XXH32_state_t to begin a new hash. * * @param statePtr The state struct to reset. * @param seed The 32-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note This function resets and seeds a state. Call it before @ref XXH32_update(). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); /*! * @brief Consumes a block of @p input to an @ref XXH32_state_t. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note Call this to incrementally consume blocks of data. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); /*! * @brief Returns the calculated hash value from an @ref XXH32_state_t. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated 32-bit xxHash32 value from that state. * * @note * Calling XXH32_digest() will not affect @p statePtr, so you can update, * digest, and update again. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! * @brief Canonical (big endian) representation of @ref XXH32_hash_t. */ typedef struct { unsigned char digest[4]; /*!< Hash bytes, big endian */ } XXH32_canonical_t; /*! * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. * * @param dst The @ref XXH32_canonical_t pointer to be stored to. * @param hash The @ref XXH32_hash_t to be converted. * * @pre * @p dst must not be `NULL`. * * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); /*! * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t. * * @param src The @ref XXH32_canonical_t to convert. * * @pre * @p src must not be `NULL`. * * @return The converted hash. * * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); /*! @cond Doxygen ignores this part */ #ifdef __has_attribute # define XXH_HAS_ATTRIBUTE(x) __has_attribute(x) #else # define XXH_HAS_ATTRIBUTE(x) 0 #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ /* * C23 __STDC_VERSION__ number hasn't been specified yet. For now * leave as `201711L` (C17 + 1). * TODO: Update to correct value when its been specified. */ #define XXH_C23_VN 201711L /*! @endcond */ /*! @cond Doxygen ignores this part */ /* C-language Attributes are added in C23. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute) # define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) #else # define XXH_HAS_C_ATTRIBUTE(x) 0 #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ #if defined(__cplusplus) && defined(__has_cpp_attribute) # define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else # define XXH_HAS_CPP_ATTRIBUTE(x) 0 #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ /* * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute * introduced in CPP17 and C23. * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough */ #if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough) # define XXH_FALLTHROUGH [[fallthrough]] #elif XXH_HAS_ATTRIBUTE(__fallthrough__) # define XXH_FALLTHROUGH __attribute__ ((__fallthrough__)) #else # define XXH_FALLTHROUGH /* fallthrough */ #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ /* * Define XXH_NOESCAPE for annotated pointers in public API. * https://clang.llvm.org/docs/AttributeReference.html#noescape * As of writing this, only supported by clang. */ #if XXH_HAS_ATTRIBUTE(noescape) # define XXH_NOESCAPE __attribute__((__noescape__)) #else # define XXH_NOESCAPE #endif /*! @endcond */ /*! * @} * @ingroup public * @{ */ #ifndef XXH_NO_LONG_LONG /*-********************************************************************** * 64-bit hash ************************************************************************/ #if defined(XXH_DOXYGEN) /* don't include */ /*! * @brief An unsigned 64-bit integer. * * Not necessarily defined to `uint64_t` but functionally equivalent. */ typedef uint64_t XXH64_hash_t; #elif !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # ifdef _AIX # include # else # include # endif typedef uint64_t XXH64_hash_t; #else # include # if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL /* LP64 ABI says uint64_t is unsigned long */ typedef unsigned long XXH64_hash_t; # else /* the following type must have a width of 64-bit */ typedef unsigned long long XXH64_hash_t; # endif #endif /*! * @} * * @defgroup XXH64_family XXH64 family * @ingroup public * @{ * Contains functions used in the classic 64-bit xxHash algorithm. * * @note * XXH3 provides competitive speed for both 32-bit and 64-bit systems, * and offers true 64/128 bit hash results. * It provides better speed for systems with vector processing capabilities. */ /*! * @brief Calculates the 64-bit hash of @p input using xxHash64. * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 64-bit seed to alter the hash's output predictably. * * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return The calculated 64-bit xxHash64 value. * * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); /******* Streaming *******/ #ifndef XXH_NO_STREAM /*! * @brief The opaque state struct for the XXH64 streaming API. * * @see XXH64_state_s for details. * @see @ref streaming_example "Streaming Example" */ typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ /*! * @brief Allocates an @ref XXH64_state_t. * * @return An allocated pointer of @ref XXH64_state_t on success. * @return `NULL` on failure. * * @note Must be freed with XXH64_freeState(). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); /*! * @brief Frees an @ref XXH64_state_t. * * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState(). * * @return @ref XXH_OK. * * @note @p statePtr must be allocated with XXH64_createState(). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); /*! * @brief Copies one @ref XXH64_state_t to another. * * @param dst_state The state to copy to. * @param src_state The state to copy from. * @pre * @p dst_state and @p src_state must not be `NULL` and must not overlap. */ XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state); /*! * @brief Resets an @ref XXH64_state_t to begin a new hash. * * @param statePtr The state struct to reset. * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note This function resets and seeds a state. Call it before @ref XXH64_update(). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed); /*! * @brief Consumes a block of @p input to an @ref XXH64_state_t. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note Call this to incrementally consume blocks of data. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated hash value from an @ref XXH64_state_t. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated 64-bit xxHash64 value from that state. * * @note * Calling XXH64_digest() will not affect @p statePtr, so you can update, * digest, and update again. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! * @brief Canonical (big endian) representation of @ref XXH64_hash_t. */ typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; /*! * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t. * * @param dst The @ref XXH64_canonical_t pointer to be stored to. * @param hash The @ref XXH64_hash_t to be converted. * * @pre * @p dst must not be `NULL`. * * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash); /*! * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t. * * @param src The @ref XXH64_canonical_t to convert. * * @pre * @p src must not be `NULL`. * * @return The converted hash. * * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src); #ifndef XXH_NO_XXH3 /*! * @} * ************************************************************************ * @defgroup XXH3_family XXH3 family * @ingroup public * @{ * * XXH3 is a more recent hash algorithm featuring: * - Improved speed for both small and large inputs * - True 64-bit and 128-bit outputs * - SIMD acceleration * - Improved 32-bit viability * * Speed analysis methodology is explained here: * * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html * * Compared to XXH64, expect XXH3 to run approximately * ~2x faster on large inputs and >3x faster on small ones, * exact differences vary depending on platform. * * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, * but does not require it. * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3 * at competitive speeds, even without vector support. Further details are * explained in the implementation. * * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD * implementations for many common platforms: * - AVX512 * - AVX2 * - SSE2 * - ARM NEON * - WebAssembly SIMD128 * - POWER8 VSX * - s390x ZVector * This can be controlled via the @ref XXH_VECTOR macro, but it automatically * selects the best version according to predefined macros. For the x86 family, an * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c. * * XXH3 implementation is portable: * it has a generic C90 formulation that can be compiled on any platform, * all implementations generate exactly the same hash value on all platforms. * Starting from v0.8.0, it's also labelled "stable", meaning that * any future version will also generate the same hash value. * * XXH3 offers 2 variants, _64bits and _128bits. * * When only 64 bits are needed, prefer invoking the _64bits variant, as it * reduces the amount of mixing, resulting in faster speed on small inputs. * It's also generally simpler to manipulate a scalar return type than a struct. * * The API supports one-shot hashing, streaming mode, and custom secrets. */ /*! * @ingroup tuning * @brief Possible values for @ref XXH_VECTOR. * * Unless set explicitly, determined automatically. */ # define XXH_SCALAR 0 /*!< Portable scalar version */ # define XXH_SSE2 1 /*!< SSE2 for Pentium 4, Opteron, all x86_64. */ # define XXH_AVX2 2 /*!< AVX2 for Haswell and Bulldozer */ # define XXH_AVX512 3 /*!< AVX512 for Skylake and Icelake */ # define XXH_NEON 4 /*!< NEON for most ARMv7-A, all AArch64, and WASM SIMD128 */ # define XXH_VSX 5 /*!< VSX and ZVector for POWER8/z13 (64-bit) */ # define XXH_SVE 6 /*!< SVE for some ARMv8-A and ARMv9-A */ # define XXH_LSX 7 /*!< LSX (128-bit SIMD) for LoongArch64 */ /*-********************************************************************** * XXH3 64-bit variant ************************************************************************/ /*! * @brief Calculates 64-bit unseeded variant of XXH3 hash of @p input. * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return The calculated 64-bit XXH3 hash value. * * @note * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of `0`, however * it may have slightly better performance due to constant propagation of the * defaults. * * @see * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length); /*! * @brief Calculates 64-bit seeded variant of XXH3 hash of @p input. * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return The calculated 64-bit XXH3 hash value. * * @note * seed == 0 produces the same results as @ref XXH3_64bits(). * * This variant generates a custom secret on the fly based on default secret * altered using the @p seed value. * * While this operation is decently fast, note that it's not completely free. * * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); /*! * The bare minimum size for a custom secret. * * @see * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(), * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret(). */ #define XXH3_SECRET_SIZE_MIN 136 /*! * @brief Calculates 64-bit variant of XXH3 with a custom "secret". * * @param data The block of data to be hashed, at least @p len bytes in size. * @param len The length of @p data, in bytes. * @param secret The secret data. * @param secretSize The length of @p secret, in bytes. * * @return The calculated 64-bit XXH3 hash value. * * @pre * The memory between @p data and @p data + @p len must be valid, * readable, contiguous memory. However, if @p length is `0`, @p data may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * It's possible to provide any blob of bytes as a "secret" to generate the hash. * This makes it more difficult for an external actor to prepare an intentional collision. * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). * However, the quality of the secret impacts the dispersion of the hash algorithm. * Therefore, the secret _must_ look like a bunch of random bytes. * Avoid "trivial" or structured data such as repeated sequences or a text document. * Whenever in doubt about the "randomness" of the blob of bytes, * consider employing @ref XXH3_generateSecret() instead (see below). * It will generate a proper high entropy secret derived from the blob of bytes. * Another advantage of using XXH3_generateSecret() is that * it guarantees that all bits within the initial blob of bytes * will impact every bit of the output. * This is not necessarily the case when using the blob of bytes directly * because, when hashing _small_ inputs, only a portion of the secret is employed. * * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); /******* Streaming *******/ #ifndef XXH_NO_STREAM /* * Streaming requires state maintenance. * This operation costs memory and CPU. * As a consequence, streaming is slower than one-shot hashing. * For better performance, prefer one-shot functions whenever applicable. */ /*! * @brief The opaque state struct for the XXH3 streaming API. * * @see XXH3_state_s for details. * @see @ref streaming_example "Streaming Example" */ typedef struct XXH3_state_s XXH3_state_t; XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); /*! * @brief Copies one @ref XXH3_state_t to another. * * @param dst_state The state to copy to. * @param src_state The state to copy from. * @pre * @p dst_state and @p src_state must not be `NULL` and must not overlap. */ XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state); /*! * @brief Resets an @ref XXH3_state_t to begin a new hash. * * @param statePtr The state struct to reset. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note * - This function resets `statePtr` and generate a secret with default parameters. * - Call this function before @ref XXH3_64bits_update(). * - Digest will be equivalent to `XXH3_64bits()`. * * @see @ref streaming_example "Streaming Example" * */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); /*! * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. * * @param statePtr The state struct to reset. * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note * - This function resets `statePtr` and generate a secret from `seed`. * - Call this function before @ref XXH3_64bits_update(). * - Digest will be equivalent to `XXH3_64bits_withSeed()`. * * @see @ref streaming_example "Streaming Example" * */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); /*! * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. * * @param statePtr The state struct to reset. * @param secret The secret data. * @param secretSize The length of @p secret, in bytes. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note * `secret` is referenced, it _must outlive_ the hash streaming session. * * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, * and the quality of produced hash values depends on secret's entropy * (secret's content should look like a bunch of random bytes). * When in doubt about the randomness of a candidate `secret`, * consider employing `XXH3_generateSecret()` instead (see below). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); /*! * @brief Consumes a block of @p input to an @ref XXH3_state_t. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note Call this to incrementally consume blocks of data. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated XXH3 64-bit hash value from that state. * * @note * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, * digest, and update again. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /* note : canonical representation of XXH3 is the same as XXH64 * since they both produce XXH64_hash_t values */ /*-********************************************************************** * XXH3 128-bit variant ************************************************************************/ /*! * @brief The return value from 128-bit hashes. * * Stored in little endian order, although the fields themselves are in native * endianness. */ typedef struct { XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */ XXH64_hash_t high64; /*!< `value >> 64` */ } XXH128_hash_t; /*! * @brief Calculates 128-bit unseeded variant of XXH3 of @p data. * * @param data The block of data to be hashed, at least @p length bytes in size. * @param len The length of @p data, in bytes. * * @return The calculated 128-bit variant of XXH3 value. * * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead * for shorter inputs. * * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of `0`, however * it may have slightly better performance due to constant propagation of the * defaults. * * @see XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len); /*! @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. * * @param data The block of data to be hashed, at least @p length bytes in size. * @param len The length of @p data, in bytes. * @param seed The 64-bit seed to alter the hash result predictably. * * @return The calculated 128-bit variant of XXH3 value. * * @note * seed == 0 produces the same results as @ref XXH3_64bits(). * * This variant generates a custom secret on the fly based on default secret * altered using the @p seed value. * * While this operation is decently fast, note that it's not completely free. * * @see XXH3_128bits(), XXH3_128bits_withSecret(): other seeding variants * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); /*! * @brief Calculates 128-bit variant of XXH3 with a custom "secret". * * @param data The block of data to be hashed, at least @p len bytes in size. * @param len The length of @p data, in bytes. * @param secret The secret data. * @param secretSize The length of @p secret, in bytes. * * @return The calculated 128-bit variant of XXH3 value. * * It's possible to provide any blob of bytes as a "secret" to generate the hash. * This makes it more difficult for an external actor to prepare an intentional collision. * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). * However, the quality of the secret impacts the dispersion of the hash algorithm. * Therefore, the secret _must_ look like a bunch of random bytes. * Avoid "trivial" or structured data such as repeated sequences or a text document. * Whenever in doubt about the "randomness" of the blob of bytes, * consider employing @ref XXH3_generateSecret() instead (see below). * It will generate a proper high entropy secret derived from the blob of bytes. * Another advantage of using XXH3_generateSecret() is that * it guarantees that all bits within the initial blob of bytes * will impact every bit of the output. * This is not necessarily the case when using the blob of bytes directly * because, when hashing _small_ inputs, only a portion of the secret is employed. * * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); /******* Streaming *******/ #ifndef XXH_NO_STREAM /* * Streaming requires state maintenance. * This operation costs memory and CPU. * As a consequence, streaming is slower than one-shot hashing. * For better performance, prefer one-shot functions whenever applicable. * * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits(). * Use already declared XXH3_createState() and XXH3_freeState(). * * All reset and streaming functions have same meaning as their 64-bit counterpart. */ /*! * @brief Resets an @ref XXH3_state_t to begin a new hash. * * @param statePtr The state struct to reset. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note * - This function resets `statePtr` and generate a secret with default parameters. * - Call it before @ref XXH3_128bits_update(). * - Digest will be equivalent to `XXH3_128bits()`. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); /*! * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. * * @param statePtr The state struct to reset. * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note * - This function resets `statePtr` and generate a secret from `seed`. * - Call it before @ref XXH3_128bits_update(). * - Digest will be equivalent to `XXH3_128bits_withSeed()`. * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); /*! * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. * * @param statePtr The state struct to reset. * @param secret The secret data. * @param secretSize The length of @p secret, in bytes. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * `secret` is referenced, it _must outlive_ the hash streaming session. * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, * and the quality of produced hash values depends on secret's entropy * (secret's content should look like a bunch of random bytes). * When in doubt about the randomness of a candidate `secret`, * consider employing `XXH3_generateSecret()` instead (see below). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); /*! * @brief Consumes a block of @p input to an @ref XXH3_state_t. * * Call this to incrementally consume blocks of data. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @note * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated XXH3 128-bit hash value from that state. * * @note * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, * digest, and update again. * */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /* Following helper functions make it possible to compare XXH128_hast_t values. * Since XXH128_hash_t is a structure, this capability is not offered by the language. * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ /*! * @brief Check equality of two XXH128_hash_t values * * @param h1 The 128-bit hash value. * @param h2 Another 128-bit hash value. * * @return `1` if `h1` and `h2` are equal. * @return `0` if they are not. */ XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); /*! * @brief Compares two @ref XXH128_hash_t * * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. * * @param h128_1 Left-hand side value * @param h128_2 Right-hand side value * * @return >0 if @p h128_1 > @p h128_2 * @return =0 if @p h128_1 == @p h128_2 * @return <0 if @p h128_1 < @p h128_2 */ XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2); /******* Canonical representation *******/ typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; /*! * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t. * * @param dst The @ref XXH128_canonical_t pointer to be stored to. * @param hash The @ref XXH128_hash_t to be converted. * * @pre * @p dst must not be `NULL`. * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash); /*! * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t. * * @param src The @ref XXH128_canonical_t to convert. * * @pre * @p src must not be `NULL`. * * @return The converted hash. * @see @ref canonical_representation_example "Canonical Representation Example" */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src); #endif /* !XXH_NO_XXH3 */ #endif /* XXH_NO_LONG_LONG */ /*! * @} */ #endif /* XXHASH_H_5627135585666179 */ #if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) #define XXHASH_H_STATIC_13879238742 /* **************************************************************************** * This section contains declarations which are not guaranteed to remain stable. * They may change in future versions, becoming incompatible with a different * version of the library. * These declarations should only be used with static linking. * Never use them in association with dynamic linking! ***************************************************************************** */ /* * These definitions are only present to allow static allocation * of XXH states, on stack or in a struct, for example. * Never **ever** access their members directly. */ /*! * @internal * @brief Structure for XXH32 streaming API. * * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is * an opaque type. This allows fields to safely be changed. * * Typedef'd to @ref XXH32_state_t. * Do not access the members of this struct directly. * @see XXH64_state_s, XXH3_state_s */ struct XXH32_state_s { XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ XXH32_hash_t acc[4]; /*!< Accumulator lanes */ unsigned char buffer[16]; /*!< Internal buffer for partial reads. */ XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */ XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ }; /* typedef'd to XXH32_state_t */ #ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */ /*! * @internal * @brief Structure for XXH64 streaming API. * * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is * an opaque type. This allows fields to safely be changed. * * Typedef'd to @ref XXH64_state_t. * Do not access the members of this struct directly. * @see XXH32_state_s, XXH3_state_s */ struct XXH64_state_s { XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ XXH64_hash_t acc[4]; /*!< Accumulator lanes */ unsigned char buffer[32]; /*!< Internal buffer for partial reads.. */ XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */ XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ }; /* typedef'd to XXH64_state_t */ #ifndef XXH_NO_XXH3 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ # define XXH_ALIGN(n) _Alignas(n) #elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ /* In C++ alignas() is a keyword */ # define XXH_ALIGN(n) alignas(n) #elif defined(__GNUC__) # define XXH_ALIGN(n) __attribute__ ((aligned(n))) #elif defined(_MSC_VER) # define XXH_ALIGN(n) __declspec(align(n)) #else # define XXH_ALIGN(n) /* disabled */ #endif /* Old GCC versions only accept the attribute after the type in structures. */ #if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \ && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \ && defined(__GNUC__) # define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align) #else # define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type #endif /*! * @brief The size of the internal XXH3 buffer. * * This is the optimal update size for incremental hashing. * * @see XXH3_64b_update(), XXH3_128b_update(). */ #define XXH3_INTERNALBUFFER_SIZE 256 /*! * @internal * @brief Default size of the secret buffer (and @ref XXH3_kSecret). * * This is the size used in @ref XXH3_kSecret and the seeded functions. * * Not to be confused with @ref XXH3_SECRET_SIZE_MIN. */ #define XXH3_SECRET_DEFAULT_SIZE 192 /*! * @internal * @brief Structure for XXH3 streaming API. * * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. * Otherwise it is an opaque type. * Never use this definition in combination with dynamic library. * This allows fields to safely be changed in the future. * * @note ** This structure has a strict alignment requirement of 64 bytes!! ** * Do not allocate this with `malloc()` or `new`, * it will not be sufficiently aligned. * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation. * * Typedef'd to @ref XXH3_state_t. * Do never access the members of this struct directly. * * @see XXH3_INITSTATE() for stack initialization. * @see XXH3_createState(), XXH3_freeState(). * @see XXH32_state_s, XXH64_state_s */ struct XXH3_state_s { XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */ XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); /*!< Used to store a custom secret generated from a seed. */ XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); /*!< The internal buffer. @see XXH32_state_s::mem32 */ XXH32_hash_t bufferedSize; /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */ XXH32_hash_t useSeed; /*!< Reserved field. Needed for padding on 64-bit. */ size_t nbStripesSoFar; /*!< Number or stripes processed. */ XXH64_hash_t totalLen; /*!< Total length hashed. 64-bit even on 32-bit targets. */ size_t nbStripesPerBlock; /*!< Number of stripes per block. */ size_t secretLimit; /*!< Size of @ref customSecret or @ref extSecret */ XXH64_hash_t seed; /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */ XXH64_hash_t reserved64; /*!< Reserved field. */ const unsigned char* extSecret; /*!< Reference to an external secret for the _withSecret variants, NULL * for other variants. */ /* note: there may be some padding at the end due to alignment on 64 bytes */ }; /* typedef'd to XXH3_state_t */ #undef XXH_ALIGN_MEMBER /*! * @brief Initializes a stack-allocated `XXH3_state_s`. * * When the @ref XXH3_state_t structure is merely emplaced on stack, * it should be initialized with XXH3_INITSTATE() or a memset() * in case its first reset uses XXH3_NNbits_reset_withSeed(). * This init can be omitted if the first reset uses default or _withSecret mode. * This operation isn't necessary when the state is created with XXH3_createState(). * Note that this doesn't prepare the state for a streaming operation, * it's still necessary to use XXH3_NNbits_reset*() afterwards. */ #define XXH3_INITSTATE(XXH3_state_ptr) \ do { \ XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \ tmp_xxh3_state_ptr->seed = 0; \ tmp_xxh3_state_ptr->extSecret = NULL; \ } while(0) /*! * @brief Calculates the 128-bit hash of @p data using XXH3. * * @param data The block of data to be hashed, at least @p len bytes in size. * @param len The length of @p data, in bytes. * @param seed The 64-bit seed to alter the hash's output predictably. * * @pre * The memory between @p data and @p data + @p len must be valid, * readable, contiguous memory. However, if @p len is `0`, @p data may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return The calculated 128-bit XXH3 value. * * @see @ref single_shot_example "Single Shot Example" for an example. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); /* === Experimental API === */ /* Symbols defined below must be considered tied to a specific library version. */ /*! * @brief Derive a high-entropy secret from any user-defined content, named customSeed. * * @param secretBuffer A writable buffer for derived high-entropy secret data. * @param secretSize Size of secretBuffer, in bytes. Must be >= XXH3_SECRET_SIZE_MIN. * @param customSeed A user-defined content. * @param customSeedSize Size of customSeed, in bytes. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * The generated secret can be used in combination with `*_withSecret()` functions. * The `_withSecret()` variants are useful to provide a higher level of protection * than 64-bit seed, as it becomes much more difficult for an external actor to * guess how to impact the calculation logic. * * The function accepts as input a custom seed of any length and any content, * and derives from it a high-entropy secret of length @p secretSize into an * already allocated buffer @p secretBuffer. * * The generated secret can then be used with any `*_withSecret()` variant. * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(), * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret() * are part of this list. They all accept a `secret` parameter * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN) * _and_ feature very high entropy (consist of random-looking bytes). * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can * be employed to ensure proper quality. * * @p customSeed can be anything. It can have any size, even small ones, * and its content can be anything, even "poor entropy" sources such as a bunch * of zeroes. The resulting `secret` will nonetheless provide all required qualities. * * @pre * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior. * * Example code: * @code{.c} * #include * #include * #include * #define XXH_STATIC_LINKING_ONLY // expose unstable API * #include "xxhash.h" * // Hashes argv[2] using the entropy from argv[1]. * int main(int argc, char* argv[]) * { * char secret[XXH3_SECRET_SIZE_MIN]; * if (argv != 3) { return 1; } * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1])); * XXH64_hash_t h = XXH3_64bits_withSecret( * argv[2], strlen(argv[2]), * secret, sizeof(secret) * ); * printf("%016llx\n", (unsigned long long) h); * } * @endcode */ XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize); /*! * @brief Generate the same secret as the _withSeed() variants. * * @param secretBuffer A writable buffer of @ref XXH3_SECRET_DEFAULT_SIZE bytes * @param seed The 64-bit seed to alter the hash result predictably. * * The generated secret can be used in combination with *`*_withSecret()` and `_withSecretandSeed()` variants. * * Example C++ `std::string` hash class: * @code{.cpp} * #include * #define XXH_STATIC_LINKING_ONLY // expose unstable API * #include "xxhash.h" * // Slow, seeds each time * class HashSlow { * XXH64_hash_t seed; * public: * HashSlow(XXH64_hash_t s) : seed{s} {} * size_t operator()(const std::string& x) const { * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)}; * } * }; * // Fast, caches the seeded secret for future uses. * class HashFast { * unsigned char secret[XXH3_SECRET_DEFAULT_SIZE]; * public: * HashFast(XXH64_hash_t s) { * XXH3_generateSecret_fromSeed(secret, seed); * } * size_t operator()(const std::string& x) const { * return size_t{ * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret)) * }; * } * }; * @endcode */ XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed); /*! * @brief Maximum size of "short" key in bytes. */ #define XXH3_MIDSIZE_MAX 240 /*! * @brief Calculates 64/128-bit seeded variant of XXH3 hash of @p data. * * @param data The block of data to be hashed, at least @p len bytes in size. * @param len The length of @p data, in bytes. * @param secret The secret data. * @param secretSize The length of @p secret, in bytes. * @param seed The 64-bit seed to alter the hash result predictably. * * These variants generate hash values using either: * - @p seed for "short" keys (< @ref XXH3_MIDSIZE_MAX = 240 bytes) * - @p secret for "large" keys (>= @ref XXH3_MIDSIZE_MAX). * * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. * `_withSeed()` has to generate the secret on the fly for "large" keys. * It's fast, but can be perceptible for "not so large" keys (< 1 KB). * `_withSecret()` has to generate the masks on the fly for "small" keys, * which requires more instructions than _withSeed() variants. * Therefore, _withSecretandSeed variant combines the best of both worlds. * * When @p secret has been generated by XXH3_generateSecret_fromSeed(), * this variant produces *exactly* the same results as `_withSeed()` variant, * hence offering only a pure speed benefit on "large" input, * by skipping the need to regenerate the secret for every large input. * * Another usage scenario is to hash the secret to a 64-bit hash value, * for example with XXH3_64bits(), which then becomes the seed, * and then employ both the seed and the secret in _withSecretandSeed(). * On top of speed, an added benefit is that each bit in the secret * has a 50% chance to swap each bit in the output, via its impact to the seed. * * This is not guaranteed when using the secret directly in "small data" scenarios, * because only portions of the secret are employed for small data. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed); /*! * @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. * * @param data The memory segment to be hashed, at least @p len bytes in size. * @param length The length of @p data, in bytes. * @param secret The secret used to alter hash result predictably. * @param secretSize The length of @p secret, in bytes (must be >= XXH3_SECRET_SIZE_MIN) * @param seed64 The 64-bit seed to alter the hash result predictably. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @see XXH3_64bits_withSecretandSeed(): contract is the same. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); #ifndef XXH_NO_STREAM /*! * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. * * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). * @param secret The secret data. * @param secretSize The length of @p secret, in bytes. * @param seed64 The 64-bit seed to alter the hash result predictably. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @see XXH3_64bits_withSecretandSeed(). Contract is identical. */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); /*! * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. * * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). * @param secret The secret data. * @param secretSize The length of @p secret, in bytes. * @param seed64 The 64-bit seed to alter the hash result predictably. * * @return @ref XXH_OK on success. * @return @ref XXH_ERROR on failure. * * @see XXH3_64bits_withSecretandSeed(). Contract is identical. * * Note: there was a bug in an earlier version of this function (<= v0.8.2) * that would make it generate an incorrect hash value * when @p seed == 0 and @p length < XXH3_MIDSIZE_MAX * and @p secret is different from XXH3_generateSecret_fromSeed(). * As stated in the contract, the correct hash result must be * the same as XXH3_128bits_withSeed() when @p length <= XXH3_MIDSIZE_MAX. * Results generated by this older version are wrong, hence not comparable. */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); #endif /* !XXH_NO_STREAM */ #endif /* !XXH_NO_XXH3 */ #endif /* XXH_NO_LONG_LONG */ #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) # define XXH_IMPLEMENTATION #endif #endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */ /* ======================================================================== */ /* ======================================================================== */ /* ======================================================================== */ /*-********************************************************************** * xxHash implementation *-********************************************************************** * xxHash's implementation used to be hosted inside xxhash.c. * * However, inlining requires implementation to be visible to the compiler, * hence be included alongside the header. * Previously, implementation was hosted inside xxhash.c, * which was then #included when inlining was activated. * This construction created issues with a few build and install systems, * as it required xxhash.c to be stored in /include directory. * * xxHash implementation is now directly integrated within xxhash.h. * As a consequence, xxhash.c is no longer needed in /include. * * xxhash.c is still available and is still useful. * In a "normal" setup, when xxhash is not inlined, * xxhash.h only exposes the prototypes and public symbols, * while xxhash.c can be built into an object file xxhash.o * which can then be linked into the final binary. ************************************************************************/ #if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \ || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387) # define XXH_IMPLEM_13a8737387 /* ************************************* * Tuning parameters ***************************************/ /*! * @defgroup tuning Tuning parameters * @{ * * Various macros to control xxHash's behavior. */ #ifdef XXH_DOXYGEN /*! * @brief Define this to disable 64-bit code. * * Useful if only using the @ref XXH32_family and you have a strict C90 compiler. */ # define XXH_NO_LONG_LONG # undef XXH_NO_LONG_LONG /* don't actually */ /*! * @brief Controls how unaligned memory is accessed. * * By default, access to unaligned memory is controlled by `memcpy()`, which is * safe and portable. * * Unfortunately, on some target/compiler combinations, the generated assembly * is sub-optimal. * * The below switch allow selection of a different access method * in the search for improved performance. * * @par Possible options: * * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy` * @par * Use `memcpy()`. Safe and portable. Note that most modern compilers will * eliminate the function call and treat it as an unaligned access. * * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))` * @par * Depends on compiler extensions and is therefore not portable. * This method is safe _if_ your compiler supports it, * and *generally* as fast or faster than `memcpy`. * * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast * @par * Casts directly and dereferences. This method doesn't depend on the * compiler, but it violates the C standard as it directly dereferences an * unaligned pointer. It can generate buggy code on targets which do not * support unaligned memory accesses, but in some circumstances, it's the * only known way to get the most performance. * * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift * @par * Also portable. This can generate the best code on old compilers which don't * inline small `memcpy()` calls, and it might also be faster on big-endian * systems which lack a native byteswap instruction. However, some compilers * will emit literal byteshifts even if the target supports unaligned access. * * * @warning * Methods 1 and 2 rely on implementation-defined behavior. Use these with * care, as what works on one compiler/platform/optimization level may cause * another to read garbage data or even crash. * * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. * * Prefer these methods in priority order (0 > 3 > 1 > 2) */ # define XXH_FORCE_MEMORY_ACCESS 0 /*! * @def XXH_SIZE_OPT * @brief Controls how much xxHash optimizes for size. * * xxHash, when compiled, tends to result in a rather large binary size. This * is mostly due to heavy usage to forced inlining and constant folding of the * @ref XXH3_family to increase performance. * * However, some developers prefer size over speed. This option can * significantly reduce the size of the generated code. When using the `-Os` * or `-Oz` options on GCC or Clang, this is defined to 1 by default, * otherwise it is defined to 0. * * Most of these size optimizations can be controlled manually. * * This is a number from 0-2. * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed * comes first. * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more * conservative and disables hacks that increase code size. It implies the * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0, * and @ref XXH3_NEON_LANES == 8 if they are not already defined. * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible. * Performance may cry. For example, the single shot functions just use the * streaming API. */ # define XXH_SIZE_OPT 0 /*! * @def XXH_FORCE_ALIGN_CHECK * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() * and XXH64() only). * * This is an important performance trick for architectures without decent * unaligned memory access performance. * * It checks for input alignment, and when conditions are met, uses a "fast * path" employing direct 32-bit/64-bit reads, resulting in _dramatically * faster_ read speed. * * The check costs one initial branch per hash, which is generally negligible, * but not zero. * * Moreover, it's not useful to generate an additional code path if memory * access uses the same instruction for both aligned and unaligned * addresses (e.g. x86 and aarch64). * * In these cases, the alignment check can be removed by setting this macro to 0. * Then the code will always use unaligned memory access. * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips * which are platforms known to offer good unaligned memory accesses performance. * * It is also disabled by default when @ref XXH_SIZE_OPT >= 1. * * This option does not affect XXH3 (only XXH32 and XXH64). */ # define XXH_FORCE_ALIGN_CHECK 0 /*! * @def XXH_NO_INLINE_HINTS * @brief When non-zero, sets all functions to `static`. * * By default, xxHash tries to force the compiler to inline almost all internal * functions. * * This can usually improve performance due to reduced jumping and improved * constant folding, but significantly increases the size of the binary which * might not be favorable. * * Additionally, sometimes the forced inlining can be detrimental to performance, * depending on the architecture. * * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the * compiler full control on whether to inline or not. * * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if * @ref XXH_SIZE_OPT >= 1, this will automatically be defined. */ # define XXH_NO_INLINE_HINTS 0 /*! * @def XXH3_INLINE_SECRET * @brief Determines whether to inline the XXH3 withSecret code. * * When the secret size is known, the compiler can improve the performance * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret(). * * However, if the secret size is not known, it doesn't have any benefit. This * happens when xxHash is compiled into a global symbol. Therefore, if * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0. * * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers * that are *sometimes* force inline on -Og, and it is impossible to automatically * detect this optimization level. */ # define XXH3_INLINE_SECRET 0 /*! * @def XXH32_ENDJMP * @brief Whether to use a jump for `XXH32_finalize`. * * For performance, `XXH32_finalize` uses multiple branches in the finalizer. * This is generally preferable for performance, * but depending on exact architecture, a jmp may be preferable. * * This setting is only possibly making a difference for very small inputs. */ # define XXH32_ENDJMP 0 /*! * @internal * @brief Redefines old internal names. * * For compatibility with code that uses xxHash's internals before the names * were changed to improve namespacing. There is no other reason to use this. */ # define XXH_OLD_NAMES # undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ /*! * @def XXH_NO_STREAM * @brief Disables the streaming API. * * When xxHash is not inlined and the streaming functions are not used, disabling * the streaming functions can improve code size significantly, especially with * the @ref XXH3_family which tends to make constant folded copies of itself. */ # define XXH_NO_STREAM # undef XXH_NO_STREAM /* don't actually */ #endif /* XXH_DOXYGEN */ /*! * @} */ #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ /* prefer __packed__ structures (method 1) for GCC * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy * which for some reason does unaligned loads. */ # if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED)) # define XXH_FORCE_MEMORY_ACCESS 1 # endif #endif #ifndef XXH_SIZE_OPT /* default to 1 for -Os or -Oz */ # if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__) # define XXH_SIZE_OPT 1 # else # define XXH_SIZE_OPT 0 # endif #endif #ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */ # if XXH_SIZE_OPT >= 1 || \ defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \ || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */ # define XXH_FORCE_ALIGN_CHECK 0 # else # define XXH_FORCE_ALIGN_CHECK 1 # endif #endif #ifndef XXH_NO_INLINE_HINTS # if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */ # define XXH_NO_INLINE_HINTS 1 # else # define XXH_NO_INLINE_HINTS 0 # endif #endif #ifndef XXH3_INLINE_SECRET # if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \ || !defined(XXH_INLINE_ALL) # define XXH3_INLINE_SECRET 0 # else # define XXH3_INLINE_SECRET 1 # endif #endif #ifndef XXH32_ENDJMP /* generally preferable for performance */ # define XXH32_ENDJMP 0 #endif /*! * @defgroup impl Implementation * @{ */ /* ************************************* * Includes & Memory related functions ***************************************/ #if defined(XXH_NO_STREAM) /* nothing */ #elif defined(XXH_NO_STDLIB) /* When requesting to disable any mention of stdlib, * the library loses the ability to invoked malloc / free. * In practice, it means that functions like `XXH*_createState()` * will always fail, and return NULL. * This flag is useful in situations where * xxhash.h is integrated into some kernel, embedded or limited environment * without access to dynamic allocation. */ static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; } static void XXH_free(void* p) { (void)p; } #else /* * Modify the local functions below should you wish to use * different memory routines for malloc() and free() */ #include /*! * @internal * @brief Modify this function to use a different routine than malloc(). */ static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); } /*! * @internal * @brief Modify this function to use a different routine than free(). */ static void XXH_free(void* p) { free(p); } #endif /* XXH_NO_STDLIB */ #include /*! * @internal * @brief Modify this function to use a different routine than memcpy(). */ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } #include /* ULLONG_MAX */ /* ************************************* * Compiler Specific Options ***************************************/ #ifdef _MSC_VER /* Visual Studio warning fix */ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ #endif #if XXH_NO_INLINE_HINTS /* disable inlining hints */ # if defined(__GNUC__) || defined(__clang__) # define XXH_FORCE_INLINE static __attribute__((__unused__)) # else # define XXH_FORCE_INLINE static # endif # define XXH_NO_INLINE static /* enable inlining hints */ #elif defined(__GNUC__) || defined(__clang__) # define XXH_FORCE_INLINE static __inline__ __attribute__((__always_inline__, __unused__)) # define XXH_NO_INLINE static __attribute__((__noinline__)) #elif defined(_MSC_VER) /* Visual Studio */ # define XXH_FORCE_INLINE static __forceinline # define XXH_NO_INLINE static __declspec(noinline) #elif defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */ # define XXH_FORCE_INLINE static inline # define XXH_NO_INLINE static #else # define XXH_FORCE_INLINE static # define XXH_NO_INLINE static #endif #if defined(XXH_INLINE_ALL) # define XXH_STATIC XXH_FORCE_INLINE #else # define XXH_STATIC static #endif #if XXH3_INLINE_SECRET # define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE #else # define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE #endif #if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ # define XXH_RESTRICT /* disable */ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ # define XXH_RESTRICT restrict #elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ || (defined (__clang__)) \ || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) /* * There are a LOT more compilers that recognize __restrict but this * covers the major ones. */ # define XXH_RESTRICT __restrict #else # define XXH_RESTRICT /* disable */ #endif /* ************************************* * Debug ***************************************/ /*! * @ingroup tuning * @def XXH_DEBUGLEVEL * @brief Sets the debugging level. * * XXH_DEBUGLEVEL is expected to be defined externally, typically via the * compiler's command line options. The value must be a number. */ #ifndef XXH_DEBUGLEVEL # ifdef DEBUGLEVEL /* backwards compat */ # define XXH_DEBUGLEVEL DEBUGLEVEL # else # define XXH_DEBUGLEVEL 0 # endif #endif #if (XXH_DEBUGLEVEL>=1) # include /* note: can still be disabled with NDEBUG */ # define XXH_ASSERT(c) assert(c) #else # if defined(__INTEL_COMPILER) # define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c)) # else # define XXH_ASSERT(c) XXH_ASSUME(c) # endif #endif /* note: use after variable declarations */ #ifndef XXH_STATIC_ASSERT # if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0) # elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0) # else # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0) # endif # define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c) #endif /*! * @internal * @def XXH_COMPILER_GUARD(var) * @brief Used to prevent unwanted optimizations for @p var. * * It uses an empty GCC inline assembly statement with a register constraint * which forces @p var into a general purpose register (eg eax, ebx, ecx * on x86) and marks it as modified. * * This is used in a few places to avoid unwanted autovectorization (e.g. * XXH32_round()). All vectorization we want is explicit via intrinsics, * and _usually_ isn't wanted elsewhere. * * We also use it to prevent unwanted constant folding for AArch64 in * XXH3_initCustomSecret_scalar(). */ #if defined(__GNUC__) || defined(__clang__) # define XXH_COMPILER_GUARD(var) __asm__("" : "+r" (var)) #else # define XXH_COMPILER_GUARD(var) ((void)0) #endif /* Specifically for NEON vectors which use the "w" constraint, on * Clang. */ #if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__) # define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var)) #else # define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0) #endif /* ************************************* * Basic Types ***************************************/ #if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # ifdef _AIX # include # else # include # endif typedef uint8_t xxh_u8; #else typedef unsigned char xxh_u8; #endif typedef XXH32_hash_t xxh_u32; #ifdef XXH_OLD_NAMES # warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly" # define BYTE xxh_u8 # define U8 xxh_u8 # define U32 xxh_u32 #endif /* *** Memory access *** */ /*! * @internal * @fn xxh_u32 XXH_read32(const void* ptr) * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * * @param ptr The pointer to read from. * @return The 32-bit native endian integer from the bytes at @p ptr. */ /*! * @internal * @fn xxh_u32 XXH_readLE32(const void* ptr) * @brief Reads an unaligned 32-bit little endian integer from @p ptr. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * * @param ptr The pointer to read from. * @return The 32-bit little endian integer from the bytes at @p ptr. */ /*! * @internal * @fn xxh_u32 XXH_readBE32(const void* ptr) * @brief Reads an unaligned 32-bit big endian integer from @p ptr. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * * @param ptr The pointer to read from. * @return The 32-bit big endian integer from the bytes at @p ptr. */ /*! * @internal * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) * @brief Like @ref XXH_readLE32(), but has an option for aligned reads. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is * always @ref XXH_alignment::XXH_unaligned. * * @param ptr The pointer to read from. * @param align Whether @p ptr is aligned. * @pre * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte * aligned. * @return The 32-bit little endian integer from the bytes at @p ptr. */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) /* * Manual byteshift. Best for old compilers which don't inline memcpy. * We actually directly use XXH_readLE32 and XXH_readBE32. */ #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) /* * Force direct memory access. Only works on CPU which support unaligned memory * access in hardware. */ static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; } #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* * __attribute__((aligned(1))) is supported by gcc and clang. Originally the * documentation claimed that it only increased the alignment, but actually it * can decrease it on gcc, clang, and icc: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES typedef union { xxh_u32 u32; } __attribute__((__packed__)) unalign; #endif static xxh_u32 XXH_read32(const void* ptr) { typedef __attribute__((__aligned__(1))) xxh_u32 xxh_unalign32; return *((const xxh_unalign32*)ptr); } #else /* * Portable and safe solution. Generally efficient. * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html */ static xxh_u32 XXH_read32(const void* memPtr) { xxh_u32 val; XXH_memcpy(&val, memPtr, sizeof(val)); return val; } #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ /* *** Endianness *** */ /*! * @ingroup tuning * @def XXH_CPU_LITTLE_ENDIAN * @brief Whether the target is little endian. * * Defined to 1 if the target is little endian, or 0 if it is big endian. * It can be defined externally, for example on the compiler command line. * * If it is not defined, * a runtime check (which is usually constant folded) is used instead. * * @note * This is not necessarily defined to an integer constant. * * @see XXH_isLittleEndian() for the runtime check. */ #ifndef XXH_CPU_LITTLE_ENDIAN /* * Try to detect endianness automatically, to avoid the nonstandard behavior * in `XXH_isLittleEndian()` */ # if defined(_WIN32) /* Windows is always little endian */ \ || defined(__LITTLE_ENDIAN__) \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) # define XXH_CPU_LITTLE_ENDIAN 1 # elif defined(__BIG_ENDIAN__) \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) # define XXH_CPU_LITTLE_ENDIAN 0 # else /*! * @internal * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN. * * Most compilers will constant fold this. */ static int XXH_isLittleEndian(void) { /* * Portable and well-defined behavior. * Don't use static: it is detrimental to performance. */ const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; return one.c[0]; } # define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() # endif #endif /* **************************************** * Compiler-specific Functions and Macros ******************************************/ #define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) #ifdef __has_builtin # define XXH_HAS_BUILTIN(x) __has_builtin(x) #else # define XXH_HAS_BUILTIN(x) 0 #endif /* * C23 and future versions have standard "unreachable()". * Once it has been implemented reliably we can add it as an * additional case: * * ``` * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) * # include * # ifdef unreachable * # define XXH_UNREACHABLE() unreachable() * # endif * #endif * ``` * * Note C++23 also has std::unreachable() which can be detected * as follows: * ``` * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L) * # include * # define XXH_UNREACHABLE() std::unreachable() * #endif * ``` * NB: `__cpp_lib_unreachable` is defined in the `` header. * We don't use that as including `` in `extern "C"` blocks * doesn't work on GCC12 */ #if XXH_HAS_BUILTIN(__builtin_unreachable) # define XXH_UNREACHABLE() __builtin_unreachable() #elif defined(_MSC_VER) # define XXH_UNREACHABLE() __assume(0) #else # define XXH_UNREACHABLE() #endif #if XXH_HAS_BUILTIN(__builtin_assume) # define XXH_ASSUME(c) __builtin_assume(c) #else # define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); } #endif /*! * @internal * @def XXH_rotl32(x,r) * @brief 32-bit rotate left. * * @param x The 32-bit integer to be rotated. * @param r The number of bits to rotate. * @pre * @p r > 0 && @p r < 32 * @note * @p x and @p r may be evaluated multiple times. * @return The rotated result. */ #if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \ && XXH_HAS_BUILTIN(__builtin_rotateleft64) # define XXH_rotl32 __builtin_rotateleft32 # define XXH_rotl64 __builtin_rotateleft64 #elif XXH_HAS_BUILTIN(__builtin_stdc_rotate_left) # define XXH_rotl32 __builtin_stdc_rotate_left # define XXH_rotl64 __builtin_stdc_rotate_left /* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ #elif defined(_MSC_VER) # define XXH_rotl32(x,r) _rotl(x,r) # define XXH_rotl64(x,r) _rotl64(x,r) #else # define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) # define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r)))) #endif /*! * @internal * @fn xxh_u32 XXH_swap32(xxh_u32 x) * @brief A 32-bit byteswap. * * @param x The 32-bit integer to byteswap. * @return @p x, byteswapped. */ #if defined(_MSC_VER) /* Visual Studio */ # define XXH_swap32 _byteswap_ulong #elif XXH_GCC_VERSION >= 403 # define XXH_swap32 __builtin_bswap32 #else static xxh_u32 XXH_swap32 (xxh_u32 x) { return ((x << 24) & 0xff000000 ) | ((x << 8) & 0x00ff0000 ) | ((x >> 8) & 0x0000ff00 ) | ((x >> 24) & 0x000000ff ); } #endif /* *************************** * Memory reads *****************************/ /*! * @internal * @brief Enum to indicate whether a pointer is aligned. */ typedef enum { XXH_aligned, /*!< Aligned */ XXH_unaligned /*!< Possibly unaligned */ } XXH_alignment; /* * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. * * This is ideal for older compilers which don't inline memcpy. */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[0] | ((xxh_u32)bytePtr[1] << 8) | ((xxh_u32)bytePtr[2] << 16) | ((xxh_u32)bytePtr[3] << 24); } XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[3] | ((xxh_u32)bytePtr[2] << 8) | ((xxh_u32)bytePtr[1] << 16) | ((xxh_u32)bytePtr[0] << 24); } #else XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); } static xxh_u32 XXH_readBE32(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); } #endif XXH_FORCE_INLINE xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) { if (align==XXH_unaligned) { return XXH_readLE32(ptr); } else { return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr); } } /* ************************************* * Misc ***************************************/ /*! @ingroup public */ XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } /* ******************************************************************* * 32-bit hash functions *********************************************************************/ /*! * @} * @defgroup XXH32_impl XXH32 implementation * @ingroup impl * * Details on the XXH32 implementation. * @{ */ /* #define instead of static const, to be used as initializers */ #define XXH_PRIME32_1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */ #define XXH_PRIME32_2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */ #define XXH_PRIME32_3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */ #define XXH_PRIME32_4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */ #define XXH_PRIME32_5 0x165667B1U /*!< 0b00010110010101100110011110110001 */ #ifdef XXH_OLD_NAMES # define PRIME32_1 XXH_PRIME32_1 # define PRIME32_2 XXH_PRIME32_2 # define PRIME32_3 XXH_PRIME32_3 # define PRIME32_4 XXH_PRIME32_4 # define PRIME32_5 XXH_PRIME32_5 #endif /*! * @internal * @brief Normal stripe processing routine. * * This shuffles the bits so that any bit from @p input impacts several bits in * @p acc. * * @param acc The accumulator lane. * @param input The stripe of input to mix. * @return The mixed accumulator lane. */ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) { acc += input * XXH_PRIME32_2; acc = XXH_rotl32(acc, 13); acc *= XXH_PRIME32_1; #if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) /* * UGLY HACK: * A compiler fence is used to prevent GCC and Clang from * autovectorizing the XXH32 loop (pragmas and attributes don't work for some * reason) without globally disabling SSE4.1. * * The reason we want to avoid vectorization is because despite working on * 4 integers at a time, there are multiple factors slowing XXH32 down on * SSE4: * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on * newer chips!) making it slightly slower to multiply four integers at * once compared to four integers independently. Even when pmulld was * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE * just to multiply unless doing a long operation. * * - Four instructions are required to rotate, * movqda tmp, v // not required with VEX encoding * pslld tmp, 13 // tmp <<= 13 * psrld v, 19 // x >>= 19 * por v, tmp // x |= tmp * compared to one for scalar: * roll v, 13 // reliably fast across the board * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason * * - Instruction level parallelism is actually more beneficial here because * the SIMD actually serializes this operation: While v1 is rotating, v2 * can load data, while v3 can multiply. SSE forces them to operate * together. * * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing * the loop. NEON is only faster on the A53, and with the newer cores, it is less * than half the speed. * * Additionally, this is used on WASM SIMD128 because it JITs to the same * SIMD instructions and has the same issue. */ XXH_COMPILER_GUARD(acc); #endif return acc; } /*! * @internal * @brief Mixes all bits to finalize the hash. * * The final mix ensures that all input bits have a chance to impact any bit in * the output digest, resulting in an unbiased distribution. * * @param hash The hash to avalanche. * @return The avalanched hash. */ static xxh_u32 XXH32_avalanche(xxh_u32 hash) { hash ^= hash >> 15; hash *= XXH_PRIME32_2; hash ^= hash >> 13; hash *= XXH_PRIME32_3; hash ^= hash >> 16; return hash; } #define XXH_get32bits(p) XXH_readLE32_align(p, align) /*! * @internal * @brief Sets up the initial accumulator state for XXH32(). */ XXH_FORCE_INLINE void XXH32_initAccs(xxh_u32 *acc, xxh_u32 seed) { XXH_ASSERT(acc != NULL); acc[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; acc[1] = seed + XXH_PRIME32_2; acc[2] = seed + 0; acc[3] = seed - XXH_PRIME32_1; } /*! * @internal * @brief Consumes a block of data for XXH32(). * * @return the end input pointer. */ XXH_FORCE_INLINE const xxh_u8 * XXH32_consumeLong( xxh_u32 *XXH_RESTRICT acc, xxh_u8 const *XXH_RESTRICT input, size_t len, XXH_alignment align ) { const xxh_u8* const bEnd = input + len; const xxh_u8* const limit = bEnd - 15; XXH_ASSERT(acc != NULL); XXH_ASSERT(input != NULL); XXH_ASSERT(len >= 16); do { acc[0] = XXH32_round(acc[0], XXH_get32bits(input)); input += 4; acc[1] = XXH32_round(acc[1], XXH_get32bits(input)); input += 4; acc[2] = XXH32_round(acc[2], XXH_get32bits(input)); input += 4; acc[3] = XXH32_round(acc[3], XXH_get32bits(input)); input += 4; } while (input < limit); return input; } /*! * @internal * @brief Merges the accumulator lanes together for XXH32() */ XXH_FORCE_INLINE XXH_PUREF xxh_u32 XXH32_mergeAccs(const xxh_u32 *acc) { XXH_ASSERT(acc != NULL); return XXH_rotl32(acc[0], 1) + XXH_rotl32(acc[1], 7) + XXH_rotl32(acc[2], 12) + XXH_rotl32(acc[3], 18); } /*! * @internal * @brief Processes the last 0-15 bytes of @p ptr. * * There may be up to 15 bytes remaining to consume from the input. * This final stage will digest them to ensure that all input bytes are present * in the final mix. * * @param hash The hash to finalize. * @param ptr The pointer to the remaining input. * @param len The remaining length, modulo 16. * @param align Whether @p ptr is aligned. * @return The finalized hash. * @see XXH64_finalize(). */ static XXH_PUREF xxh_u32 XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) { #define XXH_PROCESS1 do { \ hash += (*ptr++) * XXH_PRIME32_5; \ hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \ } while (0) #define XXH_PROCESS4 do { \ hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \ ptr += 4; \ hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \ } while (0) if (ptr==NULL) XXH_ASSERT(len == 0); /* Compact rerolled version; generally faster */ if (!XXH32_ENDJMP) { len &= 15; while (len >= 4) { XXH_PROCESS4; len -= 4; } while (len > 0) { XXH_PROCESS1; --len; } return XXH32_avalanche(hash); } else { switch(len&15) /* or switch(bEnd - p) */ { case 12: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 8: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 4: XXH_PROCESS4; return XXH32_avalanche(hash); case 13: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 9: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 5: XXH_PROCESS4; XXH_PROCESS1; return XXH32_avalanche(hash); case 14: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 10: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 6: XXH_PROCESS4; XXH_PROCESS1; XXH_PROCESS1; return XXH32_avalanche(hash); case 15: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 11: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 7: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 3: XXH_PROCESS1; XXH_FALLTHROUGH; /* fallthrough */ case 2: XXH_PROCESS1; XXH_FALLTHROUGH; /* fallthrough */ case 1: XXH_PROCESS1; XXH_FALLTHROUGH; /* fallthrough */ case 0: return XXH32_avalanche(hash); } XXH_ASSERT(0); return hash; /* reaching this point is deemed impossible */ } } #ifdef XXH_OLD_NAMES # define PROCESS1 XXH_PROCESS1 # define PROCESS4 XXH_PROCESS4 #else # undef XXH_PROCESS1 # undef XXH_PROCESS4 #endif /*! * @internal * @brief The implementation for @ref XXH32(). * * @param input , len , seed Directly passed from @ref XXH32(). * @param align Whether @p input is aligned. * @return The calculated hash. */ XXH_FORCE_INLINE XXH_PUREF xxh_u32 XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) { xxh_u32 h32; if (input==NULL) XXH_ASSERT(len == 0); if (len>=16) { xxh_u32 acc[4]; XXH32_initAccs(acc, seed); input = XXH32_consumeLong(acc, input, len, align); h32 = XXH32_mergeAccs(acc); } else { h32 = seed + XXH_PRIME32_5; } h32 += (xxh_u32)len; return XXH32_finalize(h32, input, len&15, align); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) { #if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ XXH32_state_t state; XXH32_reset(&state, seed); XXH32_update(&state, (const xxh_u8*)input, len); return XXH32_digest(&state); #else if (XXH_FORCE_ALIGN_CHECK) { if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); } } return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); #endif } /******* Hash streaming *******/ #ifndef XXH_NO_STREAM /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) { return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) { XXH_free(statePtr); return XXH_OK; } /*! @ingroup XXH32_family */ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) { XXH_memcpy(dstState, srcState, sizeof(*dstState)); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) { XXH_ASSERT(statePtr != NULL); memset(statePtr, 0, sizeof(*statePtr)); XXH32_initAccs(statePtr->acc, seed); return XXH_OK; } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t* state, const void* input, size_t len) { if (input==NULL) { XXH_ASSERT(len == 0); return XXH_OK; } state->total_len_32 += (XXH32_hash_t)len; state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); XXH_ASSERT(state->bufferedSize < sizeof(state->buffer)); if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */ XXH_memcpy(state->buffer + state->bufferedSize, input, len); state->bufferedSize += (XXH32_hash_t)len; return XXH_OK; } { const xxh_u8* xinput = (const xxh_u8*)input; const xxh_u8* const bEnd = xinput + len; if (state->bufferedSize) { /* non-empty buffer: complete first */ XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize); xinput += sizeof(state->buffer) - state->bufferedSize; /* then process one round */ (void)XXH32_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned); state->bufferedSize = 0; } XXH_ASSERT(xinput <= bEnd); if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) { /* Process the remaining data */ xinput = XXH32_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned); } if (xinput < bEnd) { /* Copy the leftover to the tmp buffer */ XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput)); state->bufferedSize = (unsigned)(bEnd-xinput); } } return XXH_OK; } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) { xxh_u32 h32; if (state->large_len) { h32 = XXH32_mergeAccs(state->acc); } else { h32 = state->acc[2] /* == seed */ + XXH_PRIME32_5; } h32 += state->total_len_32; return XXH32_finalize(h32, state->buffer, state->bufferedSize, XXH_aligned); } #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! @ingroup XXH32_family */ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); XXH_memcpy(dst, &hash, sizeof(*dst)); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) { return XXH_readBE32(src); } #ifndef XXH_NO_LONG_LONG /* ******************************************************************* * 64-bit hash functions *********************************************************************/ /*! * @} * @ingroup impl * @{ */ /******* Memory access *******/ typedef XXH64_hash_t xxh_u64; #ifdef XXH_OLD_NAMES # define U64 xxh_u64 #endif #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) /* * Manual byteshift. Best for old compilers which don't inline memcpy. * We actually directly use XXH_readLE64 and XXH_readBE64. */ #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ static xxh_u64 XXH_read64(const void* memPtr) { return *(const xxh_u64*) memPtr; } #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* * __attribute__((aligned(1))) is supported by gcc and clang. Originally the * documentation claimed that it only increased the alignment, but actually it * can decrease it on gcc, clang, and icc: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((__packed__)) unalign64; #endif static xxh_u64 XXH_read64(const void* ptr) { typedef __attribute__((__aligned__(1))) xxh_u64 xxh_unalign64; return *((const xxh_unalign64*)ptr); } #else /* * Portable and safe solution. Generally efficient. * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html */ static xxh_u64 XXH_read64(const void* memPtr) { xxh_u64 val; XXH_memcpy(&val, memPtr, sizeof(val)); return val; } #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ #if defined(_MSC_VER) /* Visual Studio */ # define XXH_swap64 _byteswap_uint64 #elif XXH_GCC_VERSION >= 403 # define XXH_swap64 __builtin_bswap64 #else static xxh_u64 XXH_swap64(xxh_u64 x) { return ((x << 56) & 0xff00000000000000ULL) | ((x << 40) & 0x00ff000000000000ULL) | ((x << 24) & 0x0000ff0000000000ULL) | ((x << 8) & 0x000000ff00000000ULL) | ((x >> 8) & 0x00000000ff000000ULL) | ((x >> 24) & 0x0000000000ff0000ULL) | ((x >> 40) & 0x000000000000ff00ULL) | ((x >> 56) & 0x00000000000000ffULL); } #endif /* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[0] | ((xxh_u64)bytePtr[1] << 8) | ((xxh_u64)bytePtr[2] << 16) | ((xxh_u64)bytePtr[3] << 24) | ((xxh_u64)bytePtr[4] << 32) | ((xxh_u64)bytePtr[5] << 40) | ((xxh_u64)bytePtr[6] << 48) | ((xxh_u64)bytePtr[7] << 56); } XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[7] | ((xxh_u64)bytePtr[6] << 8) | ((xxh_u64)bytePtr[5] << 16) | ((xxh_u64)bytePtr[4] << 24) | ((xxh_u64)bytePtr[3] << 32) | ((xxh_u64)bytePtr[2] << 40) | ((xxh_u64)bytePtr[1] << 48) | ((xxh_u64)bytePtr[0] << 56); } #else XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); } static xxh_u64 XXH_readBE64(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); } #endif XXH_FORCE_INLINE xxh_u64 XXH_readLE64_align(const void* ptr, XXH_alignment align) { if (align==XXH_unaligned) return XXH_readLE64(ptr); else return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr); } /******* xxh64 *******/ /*! * @} * @defgroup XXH64_impl XXH64 implementation * @ingroup impl * * Details on the XXH64 implementation. * @{ */ /* #define rather that static const, to be used as initializers */ #define XXH_PRIME64_1 0x9E3779B185EBCA87ULL /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */ #define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */ #define XXH_PRIME64_3 0x165667B19E3779F9ULL /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */ #define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */ #define XXH_PRIME64_5 0x27D4EB2F165667C5ULL /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */ #ifdef XXH_OLD_NAMES # define PRIME64_1 XXH_PRIME64_1 # define PRIME64_2 XXH_PRIME64_2 # define PRIME64_3 XXH_PRIME64_3 # define PRIME64_4 XXH_PRIME64_4 # define PRIME64_5 XXH_PRIME64_5 #endif /*! @copydoc XXH32_round */ static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) { acc += input * XXH_PRIME64_2; acc = XXH_rotl64(acc, 31); acc *= XXH_PRIME64_1; #if (defined(__AVX512F__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) /* * DISABLE AUTOVECTORIZATION: * A compiler fence is used to prevent GCC and Clang from * autovectorizing the XXH64 loop (pragmas and attributes don't work for some * reason) without globally disabling AVX512. * * Autovectorization of XXH64 tends to be detrimental, * though the exact outcome may change depending on exact cpu and compiler version. * For information, it has been reported as detrimental for Skylake-X, * but possibly beneficial for Zen4. * * The default is to disable auto-vectorization, * but you can select to enable it instead using `XXH_ENABLE_AUTOVECTORIZE` build variable. */ XXH_COMPILER_GUARD(acc); #endif return acc; } static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) { val = XXH64_round(0, val); acc ^= val; acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4; return acc; } /*! @copydoc XXH32_avalanche */ static xxh_u64 XXH64_avalanche(xxh_u64 hash) { hash ^= hash >> 33; hash *= XXH_PRIME64_2; hash ^= hash >> 29; hash *= XXH_PRIME64_3; hash ^= hash >> 32; return hash; } #define XXH_get64bits(p) XXH_readLE64_align(p, align) /*! * @internal * @brief Sets up the initial accumulator state for XXH64(). */ XXH_FORCE_INLINE void XXH64_initAccs(xxh_u64 *acc, xxh_u64 seed) { XXH_ASSERT(acc != NULL); acc[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; acc[1] = seed + XXH_PRIME64_2; acc[2] = seed + 0; acc[3] = seed - XXH_PRIME64_1; } /*! * @internal * @brief Consumes a block of data for XXH64(). * * @return the end input pointer. */ XXH_FORCE_INLINE const xxh_u8 * XXH64_consumeLong( xxh_u64 *XXH_RESTRICT acc, xxh_u8 const *XXH_RESTRICT input, size_t len, XXH_alignment align ) { const xxh_u8* const bEnd = input + len; const xxh_u8* const limit = bEnd - 31; XXH_ASSERT(acc != NULL); XXH_ASSERT(input != NULL); XXH_ASSERT(len >= 32); do { /* reroll on 32-bit */ if (sizeof(void *) < sizeof(xxh_u64)) { size_t i; for (i = 0; i < 4; i++) { acc[i] = XXH64_round(acc[i], XXH_get64bits(input)); input += 8; } } else { acc[0] = XXH64_round(acc[0], XXH_get64bits(input)); input += 8; acc[1] = XXH64_round(acc[1], XXH_get64bits(input)); input += 8; acc[2] = XXH64_round(acc[2], XXH_get64bits(input)); input += 8; acc[3] = XXH64_round(acc[3], XXH_get64bits(input)); input += 8; } } while (input < limit); return input; } /*! * @internal * @brief Merges the accumulator lanes together for XXH64() */ XXH_FORCE_INLINE XXH_PUREF xxh_u64 XXH64_mergeAccs(const xxh_u64 *acc) { XXH_ASSERT(acc != NULL); { xxh_u64 h64 = XXH_rotl64(acc[0], 1) + XXH_rotl64(acc[1], 7) + XXH_rotl64(acc[2], 12) + XXH_rotl64(acc[3], 18); /* reroll on 32-bit */ if (sizeof(void *) < sizeof(xxh_u64)) { size_t i; for (i = 0; i < 4; i++) { h64 = XXH64_mergeRound(h64, acc[i]); } } else { h64 = XXH64_mergeRound(h64, acc[0]); h64 = XXH64_mergeRound(h64, acc[1]); h64 = XXH64_mergeRound(h64, acc[2]); h64 = XXH64_mergeRound(h64, acc[3]); } return h64; } } /*! * @internal * @brief Processes the last 0-31 bytes of @p ptr. * * There may be up to 31 bytes remaining to consume from the input. * This final stage will digest them to ensure that all input bytes are present * in the final mix. * * @param hash The hash to finalize. * @param ptr The pointer to the remaining input. * @param len The remaining length, modulo 32. * @param align Whether @p ptr is aligned. * @return The finalized hash * @see XXH32_finalize(). */ XXH_STATIC XXH_PUREF xxh_u64 XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) { if (ptr==NULL) XXH_ASSERT(len == 0); len &= 31; while (len >= 8) { xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); ptr += 8; hash ^= k1; hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4; len -= 8; } if (len >= 4) { hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; ptr += 4; hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; len -= 4; } while (len > 0) { hash ^= (*ptr++) * XXH_PRIME64_5; hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1; --len; } return XXH64_avalanche(hash); } #ifdef XXH_OLD_NAMES # define PROCESS1_64 XXH_PROCESS1_64 # define PROCESS4_64 XXH_PROCESS4_64 # define PROCESS8_64 XXH_PROCESS8_64 #else # undef XXH_PROCESS1_64 # undef XXH_PROCESS4_64 # undef XXH_PROCESS8_64 #endif /*! * @internal * @brief The implementation for @ref XXH64(). * * @param input , len , seed Directly passed from @ref XXH64(). * @param align Whether @p input is aligned. * @return The calculated hash. */ XXH_FORCE_INLINE XXH_PUREF xxh_u64 XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) { xxh_u64 h64; if (input==NULL) XXH_ASSERT(len == 0); if (len>=32) { /* Process a large block of data */ xxh_u64 acc[4]; XXH64_initAccs(acc, seed); input = XXH64_consumeLong(acc, input, len, align); h64 = XXH64_mergeAccs(acc); } else { h64 = seed + XXH_PRIME64_5; } h64 += (xxh_u64) len; return XXH64_finalize(h64, input, len, align); } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH64_hash_t XXH64 (XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { #if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ XXH64_state_t state; XXH64_reset(&state, seed); XXH64_update(&state, (const xxh_u8*)input, len); return XXH64_digest(&state); #else if (XXH_FORCE_ALIGN_CHECK) { if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); } } return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); #endif } /******* Hash Streaming *******/ #ifndef XXH_NO_STREAM /*! @ingroup XXH64_family*/ XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) { return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) { XXH_free(statePtr); return XXH_OK; } /*! @ingroup XXH64_family */ XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState) { XXH_memcpy(dstState, srcState, sizeof(*dstState)); } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed) { XXH_ASSERT(statePtr != NULL); memset(statePtr, 0, sizeof(*statePtr)); XXH64_initAccs(statePtr->acc, seed); return XXH_OK; } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len) { if (input==NULL) { XXH_ASSERT(len == 0); return XXH_OK; } state->total_len += len; XXH_ASSERT(state->bufferedSize <= sizeof(state->buffer)); if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */ XXH_memcpy(state->buffer + state->bufferedSize, input, len); state->bufferedSize += (XXH32_hash_t)len; return XXH_OK; } { const xxh_u8* xinput = (const xxh_u8*)input; const xxh_u8* const bEnd = xinput + len; if (state->bufferedSize) { /* non-empty buffer => complete first */ XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize); xinput += sizeof(state->buffer) - state->bufferedSize; /* and process one round */ (void)XXH64_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned); state->bufferedSize = 0; } XXH_ASSERT(xinput <= bEnd); if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) { /* Process the remaining data */ xinput = XXH64_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned); } if (xinput < bEnd) { /* Copy the leftover to the tmp buffer */ XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput)); state->bufferedSize = (unsigned)(bEnd-xinput); } } return XXH_OK; } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state) { xxh_u64 h64; if (state->total_len >= 32) { h64 = XXH64_mergeAccs(state->acc); } else { h64 = state->acc[2] /*seed*/ + XXH_PRIME64_5; } h64 += (xxh_u64) state->total_len; return XXH64_finalize(h64, state->buffer, (size_t)state->total_len, XXH_aligned); } #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! @ingroup XXH64_family */ XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); XXH_memcpy(dst, &hash, sizeof(*dst)); } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src) { return XXH_readBE64(src); } #ifndef XXH_NO_XXH3 /* ********************************************************************* * XXH3 * New generation hash designed for speed on small keys and vectorization ************************************************************************ */ /*! * @} * @defgroup XXH3_impl XXH3 implementation * @ingroup impl * @{ */ /* === Compiler specifics === */ #if (defined(__GNUC__) && (__GNUC__ >= 3)) \ || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ || defined(__clang__) # define XXH_likely(x) __builtin_expect(x, 1) # define XXH_unlikely(x) __builtin_expect(x, 0) #else # define XXH_likely(x) (x) # define XXH_unlikely(x) (x) #endif #ifndef XXH_HAS_INCLUDE # ifdef __has_include /* * Not defined as XXH_HAS_INCLUDE(x) (function-like) because * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion) */ # define XXH_HAS_INCLUDE __has_include # else # define XXH_HAS_INCLUDE(x) 0 # endif #endif #if defined(__GNUC__) || defined(__clang__) # if defined(__ARM_FEATURE_SVE) # include # endif # if defined(__ARM_NEON__) || defined(__ARM_NEON) \ || (defined(_M_ARM) && _M_ARM >= 7) \ || defined(_M_ARM64) || defined(_M_ARM64EC) \ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* WASM SIMD128 via SIMDe */ # define inline __inline__ /* circumvent a clang bug */ # include # undef inline # elif defined(__AVX2__) # include # elif defined(__SSE2__) # include # elif defined(__loongarch_sx) # include # endif #endif #if defined(_MSC_VER) # include #endif /* * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while * remaining a true 64-bit/128-bit hash function. * * This is done by prioritizing a subset of 64-bit operations that can be * emulated without too many steps on the average 32-bit machine. * * For example, these two lines seem similar, and run equally fast on 64-bit: * * xxh_u64 x; * x ^= (x >> 47); // good * x ^= (x >> 13); // bad * * However, to a 32-bit machine, there is a major difference. * * x ^= (x >> 47) looks like this: * * x.lo ^= (x.hi >> (47 - 32)); * * while x ^= (x >> 13) looks like this: * * // note: funnel shifts are not usually cheap. * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13)); * x.hi ^= (x.hi >> 13); * * The first one is significantly faster than the second, simply because the * shift is larger than 32. This means: * - All the bits we need are in the upper 32 bits, so we can ignore the lower * 32 bits in the shift. * - The shift result will always fit in the lower 32 bits, and therefore, * we can ignore the upper 32 bits in the xor. * * Thanks to this optimization, XXH3 only requires these features to be efficient: * * - Usable unaligned access * - A 32-bit or 64-bit ALU * - If 32-bit, a decent ADC instruction * - A 32 or 64-bit multiply with a 64-bit result * - For the 128-bit variant, a decent byteswap helps short inputs. * * The first two are already required by XXH32, and almost all 32-bit and 64-bit * platforms which can run XXH32 can run XXH3 efficiently. * * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one * notable exception. * * First of all, Thumb-1 lacks support for the UMULL instruction which * performs the important long multiply. This means numerous __aeabi_lmul * calls. * * Second of all, the 8 functional registers are just not enough. * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need * Lo registers, and this shuffling results in thousands more MOVs than A32. * * A32 and T32 don't have this limitation. They can access all 14 registers, * do a 32->64 multiply with UMULL, and the flexible operand allowing free * shifts is helpful, too. * * Therefore, we do a quick sanity check. * * If compiling Thumb-1 for a target which supports ARM instructions, we will * emit a warning, as it is not a "sane" platform to compile for. * * Usually, if this happens, it is because of an accident and you probably need * to specify -march, as you likely meant to compile for a newer architecture. * * Credit: large sections of the vectorial and asm source code paths * have been contributed by @easyaspi314 */ #if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM) # warning "XXH3 is highly inefficient without ARM or Thumb-2." #endif /* ========================================== * Vectorization detection * ========================================== */ #ifdef XXH_DOXYGEN /*! * @ingroup tuning * @brief Overrides the vectorization implementation chosen for XXH3. * * Can be defined to 0 to disable SIMD or any of the values mentioned in * @ref XXH_VECTOR_TYPE. * * If this is not defined, it uses predefined macros to determine the best * implementation. */ # define XXH_VECTOR XXH_SCALAR /*! * @ingroup tuning * @brief Selects the minimum alignment for XXH3's accumulators. * * When using SIMD, this should match the alignment required for said vector * type, so, for example, 32 for AVX2. * * Default: Auto detected. */ # define XXH_ACC_ALIGN 8 #endif /* Actual definition */ #ifndef XXH_DOXYGEN #endif #ifndef XXH_VECTOR /* can be defined on command line */ # if defined(__ARM_FEATURE_SVE) # define XXH_VECTOR XXH_SVE # elif ( \ defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \ || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* wasm simd128 via SIMDe */ \ ) && ( \ defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ ) # define XXH_VECTOR XXH_NEON # elif defined(__AVX512F__) # define XXH_VECTOR XXH_AVX512 # elif defined(__AVX2__) # define XXH_VECTOR XXH_AVX2 # elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) # define XXH_VECTOR XXH_SSE2 # elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ || (defined(__s390x__) && defined(__VEC__)) \ && defined(__GNUC__) /* TODO: IBM XL */ # define XXH_VECTOR XXH_VSX # elif defined(__loongarch_sx) # define XXH_VECTOR XXH_LSX # else # define XXH_VECTOR XXH_SCALAR # endif #endif /* __ARM_FEATURE_SVE is only supported by GCC & Clang. */ #if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE) # ifdef _MSC_VER # pragma warning(once : 4606) # else # warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead." # endif # undef XXH_VECTOR # define XXH_VECTOR XXH_SCALAR #endif /* * Controls the alignment of the accumulator, * for compatibility with aligned vector loads, which are usually faster. */ #ifndef XXH_ACC_ALIGN # if defined(XXH_X86DISPATCH) # define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */ # elif XXH_VECTOR == XXH_SCALAR /* scalar */ # define XXH_ACC_ALIGN 8 # elif XXH_VECTOR == XXH_SSE2 /* sse2 */ # define XXH_ACC_ALIGN 16 # elif XXH_VECTOR == XXH_AVX2 /* avx2 */ # define XXH_ACC_ALIGN 32 # elif XXH_VECTOR == XXH_NEON /* neon */ # define XXH_ACC_ALIGN 16 # elif XXH_VECTOR == XXH_VSX /* vsx */ # define XXH_ACC_ALIGN 16 # elif XXH_VECTOR == XXH_AVX512 /* avx512 */ # define XXH_ACC_ALIGN 64 # elif XXH_VECTOR == XXH_SVE /* sve */ # define XXH_ACC_ALIGN 64 # elif XXH_VECTOR == XXH_LSX /* lsx */ # define XXH_ACC_ALIGN 64 # endif #endif #if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 # define XXH_SEC_ALIGN XXH_ACC_ALIGN #elif XXH_VECTOR == XXH_SVE # define XXH_SEC_ALIGN XXH_ACC_ALIGN #else # define XXH_SEC_ALIGN 8 #endif #if defined(__GNUC__) || defined(__clang__) # define XXH_ALIASING __attribute__((__may_alias__)) #else # define XXH_ALIASING /* nothing */ #endif /* * UGLY HACK: * GCC usually generates the best code with -O3 for xxHash. * * However, when targeting AVX2, it is overzealous in its unrolling resulting * in code roughly 3/4 the speed of Clang. * * There are other issues, such as GCC splitting _mm256_loadu_si256 into * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which * only applies to Sandy and Ivy Bridge... which don't even support AVX2. * * That is why when compiling the AVX2 version, it is recommended to use either * -O2 -mavx2 -march=haswell * or * -O2 -mavx2 -mno-avx256-split-unaligned-load * for decent performance, or to use Clang instead. * * Fortunately, we can control the first one with a pragma that forces GCC into * -O2, but the other one we can't control without "failed to inline always * inline function due to target mismatch" warnings. */ #if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ # pragma GCC push_options # pragma GCC optimize("-O2") #endif #if XXH_VECTOR == XXH_NEON /* * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3 * optimizes out the entire hashLong loop because of the aliasing violation. * * However, GCC is also inefficient at load-store optimization with vld1q/vst1q, * so the only option is to mark it as aliasing. */ typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING; /*! * @internal * @brief `vld1q_u64` but faster and alignment-safe. * * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86). * * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it * prohibits load-store optimizations. Therefore, a direct dereference is used. * * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe * unaligned load. */ #if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */ { return *(xxh_aliasing_uint64x2_t const *)ptr; } #else XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) { return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr)); } #endif /*! * @internal * @brief `vmlal_u32` on low and high halves of a vector. * * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32` * with `vmlal_u32`. */ #if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11 XXH_FORCE_INLINE uint64x2_t XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { /* Inline assembly is the only way */ __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs)); return acc; } XXH_FORCE_INLINE uint64x2_t XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { /* This intrinsic works as expected */ return vmlal_high_u32(acc, lhs, rhs); } #else /* Portable intrinsic versions */ XXH_FORCE_INLINE uint64x2_t XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs)); } /*! @copydoc XXH_vmlal_low_u32 * Assume the compiler converts this to vmlal_high_u32 on aarch64 */ XXH_FORCE_INLINE uint64x2_t XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs)); } #endif /*! * @ingroup tuning * @brief Controls the NEON to scalar ratio for XXH3 * * This can be set to 2, 4, 6, or 8. * * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used. * * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU * bandwidth. * * This is even more noticeable on the more advanced cores like the Cortex-A76 which * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once. * * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes * and 2 scalar lanes, which is chosen by default. * * This does not apply to Apple processors or 32-bit processors, which run better with * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes. * * This change benefits CPUs with large micro-op buffers without negatively affecting * most other CPUs: * * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. | * |:----------------------|:--------------------|----------:|-----------:|------:| * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% | * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% | * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% | * | Apple M1 | 4 NEON/8 micro-ops | 37.3 GB/s | 36.1 GB/s | ~-3% | * * It also seems to fix some bad codegen on GCC, making it almost as fast as clang. * * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning * it effectively becomes worse 4. * * @see XXH3_accumulate_512_neon() */ # ifndef XXH3_NEON_LANES # if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \ && !defined(__APPLE__) && XXH_SIZE_OPT <= 0 # define XXH3_NEON_LANES 6 # else # define XXH3_NEON_LANES XXH_ACC_NB # endif # endif #endif /* XXH_VECTOR == XXH_NEON */ /* * VSX and Z Vector helpers. * * This is very messy, and any pull requests to clean this up are welcome. * * There are a lot of problems with supporting VSX and s390x, due to * inconsistent intrinsics, spotty coverage, and multiple endiannesses. */ #if XXH_VECTOR == XXH_VSX /* Annoyingly, these headers _may_ define three macros: `bool`, `vector`, * and `pixel`. This is a problem for obvious reasons. * * These keywords are unnecessary; the spec literally says they are * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd * after including the header. * * We use pragma push_macro/pop_macro to keep the namespace clean. */ # pragma push_macro("bool") # pragma push_macro("vector") # pragma push_macro("pixel") /* silence potential macro redefined warnings */ # undef bool # undef vector # undef pixel # if defined(__s390x__) # include # else # include # endif /* Restore the original macro values, if applicable. */ # pragma pop_macro("pixel") # pragma pop_macro("vector") # pragma pop_macro("bool") typedef __vector unsigned long long xxh_u64x2; typedef __vector unsigned char xxh_u8x16; typedef __vector unsigned xxh_u32x4; /* * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue. */ typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING; # ifndef XXH_VSX_BE # if defined(__BIG_ENDIAN__) \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) # define XXH_VSX_BE 1 # elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__ # warning "-maltivec=be is not recommended. Please use native endianness." # define XXH_VSX_BE 1 # else # define XXH_VSX_BE 0 # endif # endif /* !defined(XXH_VSX_BE) */ # if XXH_VSX_BE # if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__)) # define XXH_vec_revb vec_revb # else /*! * A polyfill for POWER9's vec_revb(). */ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val) { xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; return vec_perm(val, val, vByteSwap); } # endif # endif /* XXH_VSX_BE */ /*! * Performs an unaligned vector load and byte swaps it on big endian. */ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) { xxh_u64x2 ret; XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2)); # if XXH_VSX_BE ret = XXH_vec_revb(ret); # endif return ret; } /* * vec_mulo and vec_mule are very problematic intrinsics on PowerPC * * These intrinsics weren't added until GCC 8, despite existing for a while, * and they are endian dependent. Also, their meaning swap depending on version. * */ # if defined(__s390x__) /* s390x is always big endian, no issue on this platform */ # define XXH_vec_mulo vec_mulo # define XXH_vec_mule vec_mule # elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__) /* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */ # define XXH_vec_mulo __builtin_altivec_vmulouw # define XXH_vec_mule __builtin_altivec_vmuleuw # else /* gcc needs inline assembly */ /* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b) { xxh_u64x2 result; __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); return result; } XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) { xxh_u64x2 result; __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); return result; } # endif /* XXH_vec_mulo, XXH_vec_mule */ #endif /* XXH_VECTOR == XXH_VSX */ #if XXH_VECTOR == XXH_SVE #define ACCRND(acc, offset) \ do { \ svuint64_t input_vec = svld1_u64(mask, xinput + offset); \ svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \ svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \ svuint64_t swapped = svtbl_u64(input_vec, kSwap); \ svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \ svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \ svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \ acc = svadd_u64_x(mask, acc, mul); \ } while (0) #endif /* XXH_VECTOR == XXH_SVE */ /* prefetch * can be disabled, by declaring XXH_NO_PREFETCH build macro */ #if defined(XXH_NO_PREFETCH) # define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ #else # if XXH_SIZE_OPT >= 1 # define XXH_PREFETCH(ptr) (void)(ptr) # elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ # include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) # define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) # else # define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ # endif #endif /* XXH_NO_PREFETCH */ /* ========================================== * XXH3 default settings * ========================================== */ #define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */ #if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN) # error "default keyset is not large enough" #endif /*! Pseudorandom secret taken directly from FARSH. */ XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, }; static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */ static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */ #ifdef XXH_OLD_NAMES # define kSecret XXH3_kSecret #endif #ifdef XXH_DOXYGEN /*! * @brief Calculates a 32-bit to 64-bit long multiply. * * Implemented as a macro. * * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't * need to (but it shouldn't need to anyways, it is about 7 instructions to do * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we * use that instead of the normal method. * * If you are compiling for platforms like Thumb-1 and don't have a better option, * you may also want to write your own long multiply routine here. * * @param x, y Numbers to be multiplied * @return 64-bit product of the low 32 bits of @p x and @p y. */ XXH_FORCE_INLINE xxh_u64 XXH_mult32to64(xxh_u64 x, xxh_u64 y) { return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); } #elif defined(_MSC_VER) && defined(_M_IX86) # define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) #else /* * Downcast + upcast is usually better than masking on older compilers like * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers. * * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands * and perform a full 64x64 multiply -- entirely redundant on 32-bit. */ # define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) #endif /*! * @brief Calculates a 64->128-bit long multiply. * * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar * version. * * @param lhs , rhs The 64-bit integers to be multiplied * @return The 128-bit result represented in an @ref XXH128_hash_t. */ static XXH128_hash_t XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) { /* * GCC/Clang __uint128_t method. * * On most 64-bit targets, GCC and Clang define a __uint128_t type. * This is usually the best way as it usually uses a native long 64-bit * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64. * * Usually. * * Despite being a 32-bit platform, Clang (and emscripten) define this type * despite not having the arithmetic for it. This results in a laggy * compiler builtin call which calculates a full 128-bit multiply. * In that case it is best to use the portable one. * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 */ #if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \ && defined(__SIZEOF_INT128__) \ || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs; XXH128_hash_t r128; r128.low64 = (xxh_u64)(product); r128.high64 = (xxh_u64)(product >> 64); return r128; /* * MSVC for x64's _umul128 method. * * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct); * * This compiles to single operand MUL on x64. */ #elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC) #ifndef _MSC_VER # pragma intrinsic(_umul128) #endif xxh_u64 product_high; xxh_u64 const product_low = _umul128(lhs, rhs, &product_high); XXH128_hash_t r128; r128.low64 = product_low; r128.high64 = product_high; return r128; /* * MSVC for ARM64's __umulh method. * * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method. */ #elif defined(_M_ARM64) || defined(_M_ARM64EC) #ifndef _MSC_VER # pragma intrinsic(__umulh) #endif XXH128_hash_t r128; r128.low64 = lhs * rhs; r128.high64 = __umulh(lhs, rhs); return r128; #else /* * Portable scalar method. Optimized for 32-bit and 64-bit ALUs. * * This is a fast and simple grade school multiply, which is shown below * with base 10 arithmetic instead of base 0x100000000. * * 9 3 // D2 lhs = 93 * x 7 5 // D2 rhs = 75 * ---------- * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15 * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45 * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21 * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63 * --------- * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27 * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67 * --------- * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975 * * The reasons for adding the products like this are: * 1. It avoids manual carry tracking. Just like how * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX. * This avoids a lot of complexity. * * 2. It hints for, and on Clang, compiles to, the powerful UMAAL * instruction available in ARM's Digital Signal Processing extension * in 32-bit ARMv6 and later, which is shown below: * * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm) * { * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm; * *RdLo = (xxh_u32)(product & 0xFFFFFFFF); * *RdHi = (xxh_u32)(product >> 32); * } * * This instruction was designed for efficient long multiplication, and * allows this to be calculated in only 4 instructions at speeds * comparable to some 64-bit ALUs. * * 3. It isn't terrible on other platforms. Usually this will be a couple * of 32-bit ADD/ADCs. */ /* First calculate all of the cross products. */ xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF); xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF); xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32); xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32); /* Now add the products together. These will never overflow. */ xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi; xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi; xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF); XXH128_hash_t r128; r128.low64 = lower; r128.high64 = upper; return r128; #endif } /*! * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it. * * The reason for the separate function is to prevent passing too many structs * around by value. This will hopefully inline the multiply, but we don't force it. * * @param lhs , rhs The 64-bit integers to multiply * @return The low 64 bits of the product XOR'd by the high 64 bits. * @see XXH_mult64to128() */ static xxh_u64 XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) { XXH128_hash_t product = XXH_mult64to128(lhs, rhs); return product.low64 ^ product.high64; } /*! Seems to produce slightly better code on GCC for some reason. */ XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) { XXH_ASSERT(0 <= shift && shift < 64); return v64 ^ (v64 >> shift); } /* * This is a fast avalanche stage, * suitable when input bits are already partially mixed */ static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) { h64 = XXH_xorshift64(h64, 37); h64 *= PRIME_MX1; h64 = XXH_xorshift64(h64, 32); return h64; } /* * This is a stronger avalanche, * inspired by Pelle Evensen's rrmxmx * preferable when input has not been previously mixed */ static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) { /* this mix is inspired by Pelle Evensen's rrmxmx */ h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); h64 *= PRIME_MX2; h64 ^= (h64 >> 35) + len ; h64 *= PRIME_MX2; return XXH_xorshift64(h64, 28); } /* ========================================== * Short keys * ========================================== * One of the shortcomings of XXH32 and XXH64 was that their performance was * sub-optimal on short lengths. It used an iterative algorithm which strongly * favored lengths that were a multiple of 4 or 8. * * Instead of iterating over individual inputs, we use a set of single shot * functions which piece together a range of lengths and operate in constant time. * * Additionally, the number of multiplies has been significantly reduced. This * reduces latency, especially when emulating 64-bit multiplies on 32-bit. * * Depending on the platform, this may or may not be faster than XXH32, but it * is almost guaranteed to be faster than XXH64. */ /* * At very short lengths, there isn't enough input to fully hide secrets, or use * the entire secret. * * There is also only a limited amount of mixing we can do before significantly * impacting performance. * * Therefore, we use different sections of the secret and always mix two secret * samples with an XOR. This should have no effect on performance on the * seedless or withSeed variants because everything _should_ be constant folded * by modern compilers. * * The XOR mixing hides individual parts of the secret and increases entropy. * * This adds an extra layer of strength for custom secrets. */ XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(1 <= len && len <= 3); XXH_ASSERT(secret != NULL); /* * len = 1: combined = { input[0], 0x01, input[0], input[0] } * len = 2: combined = { input[1], 0x02, input[0], input[1] } * len = 3: combined = { input[2], 0x03, input[0], input[1] } */ { xxh_u8 const c1 = input[0]; xxh_u8 const c2 = input[len >> 1]; xxh_u8 const c3 = input[len - 1]; xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24) | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; xxh_u64 const keyed = (xxh_u64)combined ^ bitflip; return XXH64_avalanche(keyed); } } XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(4 <= len && len <= 8); seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; { xxh_u32 const input1 = XXH_readLE32(input); xxh_u32 const input2 = XXH_readLE32(input + len - 4); xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed; xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32); xxh_u64 const keyed = input64 ^ bitflip; return XXH3_rrmxmx(keyed, len); } } XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(9 <= len && len <= 16); { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed; xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed; xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1; xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2; xxh_u64 const acc = len + XXH_swap64(input_lo) + input_hi + XXH3_mul128_fold64(input_lo, input_hi); return XXH3_avalanche(acc); } } XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(len <= 16); { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed); if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed); if (len) return XXH3_len_1to3_64b(input, len, secret, seed); return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64))); } } /* * DISCLAIMER: There are known *seed-dependent* multicollisions here due to * multiplication by zero, affecting hashes of lengths 17 to 240. * * However, they are very unlikely. * * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all * unseeded non-cryptographic hashes, it does not attempt to defend itself * against specially crafted inputs, only random inputs. * * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes * cancelling out the secret is taken an arbitrary number of times (addressed * in XXH3_accumulate_512), this collision is very unlikely with random inputs * and/or proper seeding: * * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a * function that is only called up to 16 times per hash with up to 240 bytes of * input. * * This is not too bad for a non-cryptographic hash function, especially with * only 64 bit outputs. * * The 128-bit variant (which trades some speed for strength) is NOT affected * by this, although it is always a good idea to use a proper seed if you care * about strength. */ XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64) { #if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */ /* * UGLY HACK: * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in * slower code. * * By forcing seed64 into a register, we disrupt the cost model and * cause it to scalarize. See `XXH32_round()` * * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600, * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on * GCC 9.2, despite both emitting scalar code. * * GCC generates much better scalar code than Clang for the rest of XXH3, * which is why finding a more optimal codepath is an interest. */ XXH_COMPILER_GUARD(seed64); #endif { xxh_u64 const input_lo = XXH_readLE64(input); xxh_u64 const input_hi = XXH_readLE64(input+8); return XXH3_mul128_fold64( input_lo ^ (XXH_readLE64(secret) + seed64), input_hi ^ (XXH_readLE64(secret+8) - seed64) ); } } /* For mid range keys, XXH3 uses a Mum-hash variant. */ XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(16 < len && len <= 128); { xxh_u64 acc = len * XXH_PRIME64_1; #if XXH_SIZE_OPT >= 1 /* Smaller and cleaner, but slightly slower. */ unsigned int i = (unsigned int)(len - 1) / 32; do { acc += XXH3_mix16B(input+16 * i, secret+32*i, seed); acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed); } while (i-- != 0); #else if (len > 32) { if (len > 64) { if (len > 96) { acc += XXH3_mix16B(input+48, secret+96, seed); acc += XXH3_mix16B(input+len-64, secret+112, seed); } acc += XXH3_mix16B(input+32, secret+64, seed); acc += XXH3_mix16B(input+len-48, secret+80, seed); } acc += XXH3_mix16B(input+16, secret+32, seed); acc += XXH3_mix16B(input+len-32, secret+48, seed); } acc += XXH3_mix16B(input+0, secret+0, seed); acc += XXH3_mix16B(input+len-16, secret+16, seed); #endif return XXH3_avalanche(acc); } } XXH_NO_INLINE XXH_PUREF XXH64_hash_t XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); #define XXH3_MIDSIZE_STARTOFFSET 3 #define XXH3_MIDSIZE_LASTOFFSET 17 { xxh_u64 acc = len * XXH_PRIME64_1; xxh_u64 acc_end; unsigned int const nbRounds = (unsigned int)len / 16; unsigned int i; XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); for (i=0; i<8; i++) { acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); } /* last bytes */ acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); XXH_ASSERT(nbRounds >= 8); acc = XXH3_avalanche(acc); #if defined(__clang__) /* Clang */ \ && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ /* * UGLY HACK: * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86. * In everywhere else, it uses scalar code. * * For 64->128-bit multiplies, even if the NEON was 100% optimal, it * would still be slower than UMAAL (see XXH_mult64to128). * * Unfortunately, Clang doesn't handle the long multiplies properly and * converts them to the nonexistent "vmulq_u64" intrinsic, which is then * scalarized into an ugly mess of VMOV.32 instructions. * * This mess is difficult to avoid without turning autovectorization * off completely, but they are usually relatively minor and/or not * worth it to fix. * * This loop is the easiest to fix, as unlike XXH32, this pragma * _actually works_ because it is a loop vectorization instead of an * SLP vectorization. */ #pragma clang loop vectorize(disable) #endif for (i=8 ; i < nbRounds; i++) { /* * Prevents clang for unrolling the acc loop and interleaving with this one. */ XXH_COMPILER_GUARD(acc); acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); } return XXH3_avalanche(acc + acc_end); } } /* ======= Long Keys ======= */ #define XXH_STRIPE_LEN 64 #define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */ #define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64)) #ifdef XXH_OLD_NAMES # define STRIPE_LEN XXH_STRIPE_LEN # define ACC_NB XXH_ACC_NB #endif #ifndef XXH_PREFETCH_DIST # ifdef __clang__ # define XXH_PREFETCH_DIST 320 # else # if (XXH_VECTOR == XXH_AVX512) # define XXH_PREFETCH_DIST 512 # else # define XXH_PREFETCH_DIST 384 # endif # endif /* __clang__ */ #endif /* XXH_PREFETCH_DIST */ /* * These macros are to generate an XXH3_accumulate() function. * The two arguments select the name suffix and target attribute. * * The name of this symbol is XXH3_accumulate_() and it calls * XXH3_accumulate_512_(). * * It may be useful to hand implement this function if the compiler fails to * optimize the inline function. */ #define XXH3_ACCUMULATE_TEMPLATE(name) \ void \ XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \ const xxh_u8* XXH_RESTRICT input, \ const xxh_u8* XXH_RESTRICT secret, \ size_t nbStripes) \ { \ size_t n; \ for (n = 0; n < nbStripes; n++ ) { \ const xxh_u8* const in = input + n*XXH_STRIPE_LEN; \ XXH_PREFETCH(in + XXH_PREFETCH_DIST); \ XXH3_accumulate_512_##name( \ acc, \ in, \ secret + n*XXH_SECRET_CONSUME_RATE); \ } \ } XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) { if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); XXH_memcpy(dst, &v64, sizeof(v64)); } /* Several intrinsic functions below are supposed to accept __int64 as argument, * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ . * However, several environments do not define __int64 type, * requiring a workaround. */ #if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) typedef int64_t xxh_i64; #else /* the following type must have a width of 64-bit */ typedef long long xxh_i64; #endif /* * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. * * It is a hardened version of UMAC, based off of FARSH's implementation. * * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD * implementations, and it is ridiculously fast. * * We harden it by mixing the original input to the accumulators as well as the product. * * This means that in the (relatively likely) case of a multiply by zero, the * original input is preserved. * * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve * cross-pollination, as otherwise the upper and lower halves would be * essentially independent. * * This doesn't matter on 64-bit hashes since they all get merged together in * the end, so we skip the extra step. * * Both XXH3_64bits and XXH3_128bits use this subroutine. */ #if (XXH_VECTOR == XXH_AVX512) \ || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0) #ifndef XXH_TARGET_AVX512 # define XXH_TARGET_AVX512 /* disable attribute target */ #endif XXH_FORCE_INLINE XXH_TARGET_AVX512 void XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { __m512i* const xacc = (__m512i *) acc; XXH_ASSERT((((size_t)acc) & 63) == 0); XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); { /* data_vec = input[0]; */ __m512i const data_vec = _mm512_loadu_si512 (input); /* key_vec = secret[0]; */ __m512i const key_vec = _mm512_loadu_si512 (secret); /* data_key = data_vec ^ key_vec; */ __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); /* xacc[0] += swap(data_vec); */ __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2)); __m512i const sum = _mm512_add_epi64(*xacc, data_swap); /* xacc[0] += product; */ *xacc = _mm512_add_epi64(product, sum); } } XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512) /* * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. * * Multiplication isn't perfect, as explained by Google in HighwayHash: * * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to * // varying degrees. In descending order of goodness, bytes * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32. * // As expected, the upper and lower bytes are much worse. * * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291 * * Since our algorithm uses a pseudorandom secret to add some variance into the * mix, we don't need to (or want to) mix as often or as much as HighwayHash does. * * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid * extraction. * * Both XXH3_64bits and XXH3_128bits use this subroutine. */ XXH_FORCE_INLINE XXH_TARGET_AVX512 void XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 63) == 0); XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); { __m512i* const xacc = (__m512i*) acc; const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1); /* xacc[0] ^= (xacc[0] >> 47) */ __m512i const acc_vec = *xacc; __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); /* xacc[0] ^= secret; */ __m512i const key_vec = _mm512_loadu_si512 (secret); __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */); /* xacc[0] *= XXH_PRIME32_1; */ __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32); __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); } } XXH_FORCE_INLINE XXH_TARGET_AVX512 void XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0); XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64); XXH_ASSERT(((size_t)customSecret & 63) == 0); (void)(&XXH_writeLE64); { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64); __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos); const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret); __m512i* const dest = ( __m512i*) customSecret; int i; XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */ XXH_ASSERT(((size_t)dest & 63) == 0); for (i=0; i < nbRounds; ++i) { dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed); } } } #endif #if (XXH_VECTOR == XXH_AVX2) \ || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0) #ifndef XXH_TARGET_AVX2 # define XXH_TARGET_AVX2 /* disable attribute target */ #endif XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 31) == 0); { __m256i* const xacc = (__m256i *) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ const __m256i* const xinput = (const __m256i *) input; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ const __m256i* const xsecret = (const __m256i *) secret; size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { /* data_vec = xinput[i]; */ __m256i const data_vec = _mm256_loadu_si256 (xinput+i); /* key_vec = xsecret[i]; */ __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); /* data_key = data_vec ^ key_vec; */ __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); /* xacc[i] += swap(data_vec); */ __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2)); __m256i const sum = _mm256_add_epi64(xacc[i], data_swap); /* xacc[i] += product; */ xacc[i] = _mm256_add_epi64(product, sum); } } } XXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2) XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 31) == 0); { __m256i* const xacc = (__m256i*) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ const __m256i* const xsecret = (const __m256i *) secret; const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1); size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { /* xacc[i] ^= (xacc[i] >> 47) */ __m256i const acc_vec = xacc[i]; __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47); __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted); /* xacc[i] ^= xsecret; */ __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1; */ __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32); __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); } } } XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0); XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6); XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64); (void)(&XXH_writeLE64); XXH_PREFETCH(customSecret); { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64); const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret); __m256i* dest = ( __m256i*) customSecret; # if defined(__GNUC__) || defined(__clang__) /* * On GCC & Clang, marking 'dest' as modified will cause the compiler: * - do not extract the secret from sse registers in the internal loop * - use less common registers, and avoid pushing these reg into stack */ XXH_COMPILER_GUARD(dest); # endif XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */ XXH_ASSERT(((size_t)dest & 31) == 0); /* GCC -O2 need unroll loop manually */ dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed); dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed); dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed); dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed); dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed); dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed); } } #endif /* x86dispatch always generates SSE2 */ #if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH) #ifndef XXH_TARGET_SSE2 # define XXH_TARGET_SSE2 /* disable attribute target */ #endif XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { /* SSE2 is just a half-scale version of the AVX2 version. */ XXH_ASSERT((((size_t)acc) & 15) == 0); { __m128i* const xacc = (__m128i *) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ const __m128i* const xinput = (const __m128i *) input; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ const __m128i* const xsecret = (const __m128i *) secret; size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { /* data_vec = xinput[i]; */ __m128i const data_vec = _mm_loadu_si128 (xinput+i); /* key_vec = xsecret[i]; */ __m128i const key_vec = _mm_loadu_si128 (xsecret+i); /* data_key = data_vec ^ key_vec; */ __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m128i const product = _mm_mul_epu32 (data_key, data_key_lo); /* xacc[i] += swap(data_vec); */ __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2)); __m128i const sum = _mm_add_epi64(xacc[i], data_swap); /* xacc[i] += product; */ xacc[i] = _mm_add_epi64(product, sum); } } } XXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2) XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { __m128i* const xacc = (__m128i*) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ const __m128i* const xsecret = (const __m128i *) secret; const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1); size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { /* xacc[i] ^= (xacc[i] >> 47) */ __m128i const acc_vec = xacc[i]; __m128i const shifted = _mm_srli_epi64 (acc_vec, 47); __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted); /* xacc[i] ^= xsecret[i]; */ __m128i const key_vec = _mm_loadu_si128 (xsecret+i); __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1; */ __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32); __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32); xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32)); } } } XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); (void)(&XXH_writeLE64); { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i); # if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900 /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */ XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) }; __m128i const seed = _mm_load_si128((__m128i const*)seed64x2); # else __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64); # endif int i; const void* const src16 = XXH3_kSecret; __m128i* dst16 = (__m128i*) customSecret; # if defined(__GNUC__) || defined(__clang__) /* * On GCC & Clang, marking 'dest' as modified will cause the compiler: * - do not extract the secret from sse registers in the internal loop * - use less common registers, and avoid pushing these reg into stack */ XXH_COMPILER_GUARD(dst16); # endif XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */ XXH_ASSERT(((size_t)dst16 & 15) == 0); for (i=0; i < nbRounds; ++i) { dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed); } } } #endif #if (XXH_VECTOR == XXH_NEON) /* forward declarations for the scalar routines */ XXH_FORCE_INLINE void XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, void const* XXH_RESTRICT secret, size_t lane); XXH_FORCE_INLINE void XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT secret, size_t lane); /*! * @internal * @brief The bulk processing loop for NEON and WASM SIMD128. * * The NEON code path is actually partially scalar when running on AArch64. This * is to optimize the pipelining and can have up to 15% speedup depending on the * CPU, and it also mitigates some GCC codegen issues. * * @see XXH3_NEON_LANES for configuring this and details about this optimization. * * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit * integers instead of the other platforms which mask full 64-bit vectors, * so the setup is more complicated than just shifting right. * * Additionally, there is an optimization for 4 lanes at once noted below. * * Since, as stated, the most optimal amount of lanes for Cortexes is 6, * there needs to be *three* versions of the accumulate operation used * for the remaining 2 lanes. * * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap * nearly perfectly. */ XXH_FORCE_INLINE void XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0); { /* GCC for darwin arm64 does not like aliasing here */ xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc; /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ uint8_t const* xinput = (const uint8_t *) input; uint8_t const* xsecret = (const uint8_t *) secret; size_t i; #ifdef __wasm_simd128__ /* * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret * is constant propagated, which results in it converting it to this * inside the loop: * * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0) * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0) * ... * * This requires a full 32-bit address immediate (and therefore a 6 byte * instruction) as well as an add for each offset. * * Putting an asm guard prevents it from folding (at the cost of losing * the alignment hint), and uses the free offset in `v128.load` instead * of adding secret_offset each time which overall reduces code size by * about a kilobyte and improves performance. */ XXH_COMPILER_GUARD(xsecret); #endif /* Scalar lanes use the normal scalarRound routine */ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { XXH3_scalarRound(acc, input, secret, i); } i = 0; /* 4 NEON lanes at a time. */ for (; i+1 < XXH3_NEON_LANES / 2; i+=2) { /* data_vec = xinput[i]; */ uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16)); uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16)); /* key_vec = xsecret[i]; */ uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16)); uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16)); /* data_swap = swap(data_vec) */ uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1); uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1); /* data_key = data_vec ^ key_vec; */ uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1); uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2); /* * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to * get one vector with the low 32 bits of each lane, and one vector * with the high 32 bits of each lane. * * The intrinsic returns a double vector because the original ARMv7-a * instruction modified both arguments in place. AArch64 and SIMD128 emit * two instructions from this intrinsic. * * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ] * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ] */ uint32x4x2_t unzipped = vuzpq_u32( vreinterpretq_u32_u64(data_key_1), vreinterpretq_u32_u64(data_key_2) ); /* data_key_lo = data_key & 0xFFFFFFFF */ uint32x4_t data_key_lo = unzipped.val[0]; /* data_key_hi = data_key >> 32 */ uint32x4_t data_key_hi = unzipped.val[1]; /* * Then, we can split the vectors horizontally and multiply which, as for most * widening intrinsics, have a variant that works on both high half vectors * for free on AArch64. A similar instruction is available on SIMD128. * * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi */ uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi); uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi); /* * Clang reorders * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s * c += a; // add acc.2d, acc.2d, swap.2d * to * c += a; // add acc.2d, acc.2d, swap.2d * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s * * While it would make sense in theory since the addition is faster, * for reasons likely related to umlal being limited to certain NEON * pipelines, this is worse. A compiler guard fixes this. */ XXH_COMPILER_GUARD_CLANG_NEON(sum_1); XXH_COMPILER_GUARD_CLANG_NEON(sum_2); /* xacc[i] = acc_vec + sum; */ xacc[i] = vaddq_u64(xacc[i], sum_1); xacc[i+1] = vaddq_u64(xacc[i+1], sum_2); } /* Operate on the remaining NEON lanes 2 at a time. */ for (; i < XXH3_NEON_LANES / 2; i++) { /* data_vec = xinput[i]; */ uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16)); /* key_vec = xsecret[i]; */ uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); /* acc_vec_2 = swap(data_vec) */ uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1); /* data_key = data_vec ^ key_vec; */ uint64x2_t data_key = veorq_u64(data_vec, key_vec); /* For two lanes, just use VMOVN and VSHRN. */ /* data_key_lo = data_key & 0xFFFFFFFF; */ uint32x2_t data_key_lo = vmovn_u64(data_key); /* data_key_hi = data_key >> 32; */ uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32); /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */ uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi); /* Same Clang workaround as before */ XXH_COMPILER_GUARD_CLANG_NEON(sum); /* xacc[i] = acc_vec + sum; */ xacc[i] = vaddq_u64 (xacc[i], sum); } } } XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon) XXH_FORCE_INLINE void XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc; uint8_t const* xsecret = (uint8_t const*) secret; size_t i; /* WASM uses operator overloads and doesn't need these. */ #ifndef __wasm_simd128__ /* { prime32_1, prime32_1 } */ uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1); /* { 0, prime32_1, 0, prime32_1 } */ uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32)); #endif /* AArch64 uses both scalar and neon at the same time */ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { XXH3_scalarScrambleRound(acc, secret, i); } for (i=0; i < XXH3_NEON_LANES / 2; i++) { /* xacc[i] ^= (xacc[i] >> 47); */ uint64x2_t acc_vec = xacc[i]; uint64x2_t shifted = vshrq_n_u64(acc_vec, 47); uint64x2_t data_vec = veorq_u64(acc_vec, shifted); /* xacc[i] ^= xsecret[i]; */ uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); uint64x2_t data_key = veorq_u64(data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1 */ #ifdef __wasm_simd128__ /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */ xacc[i] = data_key * XXH_PRIME32_1; #else /* * Expanded version with portable NEON intrinsics * * lo(x) * lo(y) + (hi(x) * lo(y) << 32) * * prod_hi = hi(data_key) * lo(prime) << 32 * * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits * and avoid the shift. */ uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi); /* Extract low bits for vmlal_u32 */ uint32x2_t data_key_lo = vmovn_u64(data_key); /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */ xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo); #endif } } } #endif #if (XXH_VECTOR == XXH_VSX) XXH_FORCE_INLINE void XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { /* presumed aligned */ xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */ xxh_u8 const* const xsecret = (xxh_u8 const*) secret; /* no alignment restriction */ xxh_u64x2 const v32 = { 32, 32 }; size_t i; for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { /* data_vec = xinput[i]; */ xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i); /* key_vec = xsecret[i]; */ xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); xxh_u64x2 const data_key = data_vec ^ key_vec; /* shuffled = (data_key << 32) | (data_key >> 32); */ xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); /* acc_vec = xacc[i]; */ xxh_u64x2 acc_vec = xacc[i]; acc_vec += product; /* swap high and low halves */ #ifdef __s390x__ acc_vec += vec_permi(data_vec, data_vec, 2); #else acc_vec += vec_xxpermdi(data_vec, data_vec, 2); #endif xacc[i] = acc_vec; } } XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx) XXH_FORCE_INLINE void XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; const xxh_u8* const xsecret = (const xxh_u8*) secret; /* constants */ xxh_u64x2 const v32 = { 32, 32 }; xxh_u64x2 const v47 = { 47, 47 }; xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 }; size_t i; for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { /* xacc[i] ^= (xacc[i] >> 47); */ xxh_u64x2 const acc_vec = xacc[i]; xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); /* xacc[i] ^= xsecret[i]; */ xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); xxh_u64x2 const data_key = data_vec ^ key_vec; /* xacc[i] *= XXH_PRIME32_1 */ /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */ xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime); /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */ xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime); xacc[i] = prod_odd + (prod_even << v32); } } } #endif #if (XXH_VECTOR == XXH_SVE) XXH_FORCE_INLINE void XXH3_accumulate_512_sve( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { uint64_t *xacc = (uint64_t *)acc; const uint64_t *xinput = (const uint64_t *)(const void *)input; const uint64_t *xsecret = (const uint64_t *)(const void *)secret; svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); uint64_t element_count = svcntd(); if (element_count >= 8) { svbool_t mask = svptrue_pat_b64(SV_VL8); svuint64_t vacc = svld1_u64(mask, xacc); ACCRND(vacc, 0); svst1_u64(mask, xacc, vacc); } else if (element_count == 2) { /* sve128 */ svbool_t mask = svptrue_pat_b64(SV_VL2); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 2); svuint64_t acc2 = svld1_u64(mask, xacc + 4); svuint64_t acc3 = svld1_u64(mask, xacc + 6); ACCRND(acc0, 0); ACCRND(acc1, 2); ACCRND(acc2, 4); ACCRND(acc3, 6); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 2, acc1); svst1_u64(mask, xacc + 4, acc2); svst1_u64(mask, xacc + 6, acc3); } else { svbool_t mask = svptrue_pat_b64(SV_VL4); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 4); ACCRND(acc0, 0); ACCRND(acc1, 4); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 4, acc1); } } XXH_FORCE_INLINE void XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT input, const xxh_u8* XXH_RESTRICT secret, size_t nbStripes) { if (nbStripes != 0) { uint64_t *xacc = (uint64_t *)acc; const uint64_t *xinput = (const uint64_t *)(const void *)input; const uint64_t *xsecret = (const uint64_t *)(const void *)secret; svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); uint64_t element_count = svcntd(); if (element_count >= 8) { svbool_t mask = svptrue_pat_b64(SV_VL8); svuint64_t vacc = svld1_u64(mask, xacc + 0); do { /* svprfd(svbool_t, void *, enum svfprop); */ svprfd(mask, xinput + 128, SV_PLDL1STRM); ACCRND(vacc, 0); xinput += 8; xsecret += 1; nbStripes--; } while (nbStripes != 0); svst1_u64(mask, xacc + 0, vacc); } else if (element_count == 2) { /* sve128 */ svbool_t mask = svptrue_pat_b64(SV_VL2); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 2); svuint64_t acc2 = svld1_u64(mask, xacc + 4); svuint64_t acc3 = svld1_u64(mask, xacc + 6); do { svprfd(mask, xinput + 128, SV_PLDL1STRM); ACCRND(acc0, 0); ACCRND(acc1, 2); ACCRND(acc2, 4); ACCRND(acc3, 6); xinput += 8; xsecret += 1; nbStripes--; } while (nbStripes != 0); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 2, acc1); svst1_u64(mask, xacc + 4, acc2); svst1_u64(mask, xacc + 6, acc3); } else { svbool_t mask = svptrue_pat_b64(SV_VL4); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 4); do { svprfd(mask, xinput + 128, SV_PLDL1STRM); ACCRND(acc0, 0); ACCRND(acc1, 4); xinput += 8; xsecret += 1; nbStripes--; } while (nbStripes != 0); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 4, acc1); } } } #endif #if (XXH_VECTOR == XXH_LSX) #define _LSX_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w)) XXH_FORCE_INLINE void XXH3_accumulate_512_lsx( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { __m128i* const xacc = (__m128i *) acc; const __m128i* const xinput = (const __m128i *) input; const __m128i* const xsecret = (const __m128i *) secret; for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) { /* data_vec = xinput[i]; */ __m128i const data_vec = __lsx_vld(xinput + i, 0); /* key_vec = xsecret[i]; */ __m128i const key_vec = __lsx_vld(xsecret + i, 0); /* data_key = data_vec ^ key_vec; */ __m128i const data_key = __lsx_vxor_v(data_vec, key_vec); /* data_key_lo = data_key >> 32; */ __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32); // __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m128i const product = __lsx_vmulwev_d_wu(data_key, data_key_lo); /* xacc[i] += swap(data_vec); */ __m128i const data_swap = __lsx_vshuf4i_w(data_vec, _LSX_SHUFFLE(1, 0, 3, 2)); __m128i const sum = __lsx_vadd_d(xacc[i], data_swap); /* xacc[i] += product; */ xacc[i] = __lsx_vadd_d(product, sum); } } } XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(lsx) XXH_FORCE_INLINE void XXH3_scrambleAcc_lsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { __m128i* const xacc = (__m128i*) acc; const __m128i* const xsecret = (const __m128i *) secret; const __m128i prime32 = __lsx_vreplgr2vr_w((int)XXH_PRIME32_1); for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) { /* xacc[i] ^= (xacc[i] >> 47) */ __m128i const acc_vec = xacc[i]; __m128i const shifted = __lsx_vsrli_d(acc_vec, 47); __m128i const data_vec = __lsx_vxor_v(acc_vec, shifted); /* xacc[i] ^= xsecret[i]; */ __m128i const key_vec = __lsx_vld(xsecret + i, 0); __m128i const data_key = __lsx_vxor_v(data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1; */ __m128i const data_key_hi = __lsx_vsrli_d(data_key, 32); __m128i const prod_lo = __lsx_vmulwev_d_wu(data_key, prime32); __m128i const prod_hi = __lsx_vmulwev_d_wu(data_key_hi, prime32); xacc[i] = __lsx_vadd_d(prod_lo, __lsx_vslli_d(prod_hi, 32)); } } } #endif /* scalar variants - universal */ #if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) /* * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they * emit an excess mask and a full 64-bit multiply-add (MADD X-form). * * While this might not seem like much, as AArch64 is a 64-bit architecture, only * big Cortex designs have a full 64-bit multiplier. * * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit * multiplies expand to 2-3 multiplies in microcode. This has a major penalty * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline. * * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does * not have this penalty and does the mask automatically. */ XXH_FORCE_INLINE xxh_u64 XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) { xxh_u64 ret; /* note: %x = 64-bit register, %w = 32-bit register */ __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc)); return ret; } #else XXH_FORCE_INLINE xxh_u64 XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) { return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc; } #endif /*! * @internal * @brief Scalar round for @ref XXH3_accumulate_512_scalar(). * * This is extracted to its own function because the NEON path uses a combination * of NEON and scalar. */ XXH_FORCE_INLINE void XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, void const* XXH_RESTRICT secret, size_t lane) { xxh_u64* xacc = (xxh_u64*) acc; xxh_u8 const* xinput = (xxh_u8 const*) input; xxh_u8 const* xsecret = (xxh_u8 const*) secret; XXH_ASSERT(lane < XXH_ACC_NB); XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); { xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8); xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8); xacc[lane ^ 1] += data_val; /* swap adjacent lanes */ xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]); } } /*! * @internal * @brief Processes a 64 byte block of data using the scalar path. */ XXH_FORCE_INLINE void XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { size_t i; /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */ #if defined(__GNUC__) && !defined(__clang__) \ && (defined(__arm__) || defined(__thumb2__)) \ && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \ && XXH_SIZE_OPT <= 0 # pragma GCC unroll 8 #endif for (i=0; i < XXH_ACC_NB; i++) { XXH3_scalarRound(acc, input, secret, i); } } XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar) /*! * @internal * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar(). * * This is extracted to its own function because the NEON path uses a combination * of NEON and scalar. */ XXH_FORCE_INLINE void XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT secret, size_t lane) { xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); XXH_ASSERT(lane < XXH_ACC_NB); { xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8); xxh_u64 acc64 = xacc[lane]; acc64 = XXH_xorshift64(acc64, 47); acc64 ^= key64; acc64 *= XXH_PRIME32_1; xacc[lane] = acc64; } } /*! * @internal * @brief Scrambles the accumulators after a large chunk has been read */ XXH_FORCE_INLINE void XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { size_t i; for (i=0; i < XXH_ACC_NB; i++) { XXH3_scalarScrambleRound(acc, secret, i); } } XXH_FORCE_INLINE void XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { /* * We need a separate pointer for the hack below, * which requires a non-const pointer. * Any decent compiler will optimize this out otherwise. */ const xxh_u8* kSecretPtr = XXH3_kSecret; XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); #if defined(__GNUC__) && defined(__aarch64__) /* * UGLY HACK: * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are * placed sequentially, in order, at the top of the unrolled loop. * * While MOVK is great for generating constants (2 cycles for a 64-bit * constant compared to 4 cycles for LDR), it fights for bandwidth with * the arithmetic instructions. * * I L S * MOVK * MOVK * MOVK * MOVK * ADD * SUB STR * STR * By forcing loads from memory (as the asm line causes the compiler to assume * that XXH3_kSecretPtr has been changed), the pipelines are used more * efficiently: * I L S * LDR * ADD LDR * SUB STR * STR * * See XXH3_NEON_LANES for details on the pipsline. * * XXH3_64bits_withSeed, len == 256, Snapdragon 835 * without hack: 2654.4 MB/s * with hack: 3202.9 MB/s */ XXH_COMPILER_GUARD(kSecretPtr); #endif { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; int i; for (i=0; i < nbRounds; i++) { /* * The asm hack causes the compiler to assume that kSecretPtr aliases with * customSecret, and on aarch64, this prevented LDP from merging two * loads together for free. Putting the loads together before the stores * properly generates LDP. */ xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64; xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64; XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo); XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi); } } } typedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t); typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); #if (XXH_VECTOR == XXH_AVX512) #define XXH3_accumulate_512 XXH3_accumulate_512_avx512 #define XXH3_accumulate XXH3_accumulate_avx512 #define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 #define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 #elif (XXH_VECTOR == XXH_AVX2) #define XXH3_accumulate_512 XXH3_accumulate_512_avx2 #define XXH3_accumulate XXH3_accumulate_avx2 #define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 #define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 #elif (XXH_VECTOR == XXH_SSE2) #define XXH3_accumulate_512 XXH3_accumulate_512_sse2 #define XXH3_accumulate XXH3_accumulate_sse2 #define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 #define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 #elif (XXH_VECTOR == XXH_NEON) #define XXH3_accumulate_512 XXH3_accumulate_512_neon #define XXH3_accumulate XXH3_accumulate_neon #define XXH3_scrambleAcc XXH3_scrambleAcc_neon #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #elif (XXH_VECTOR == XXH_VSX) #define XXH3_accumulate_512 XXH3_accumulate_512_vsx #define XXH3_accumulate XXH3_accumulate_vsx #define XXH3_scrambleAcc XXH3_scrambleAcc_vsx #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #elif (XXH_VECTOR == XXH_SVE) #define XXH3_accumulate_512 XXH3_accumulate_512_sve #define XXH3_accumulate XXH3_accumulate_sve #define XXH3_scrambleAcc XXH3_scrambleAcc_scalar #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #elif (XXH_VECTOR == XXH_LSX) #define XXH3_accumulate_512 XXH3_accumulate_512_lsx #define XXH3_accumulate XXH3_accumulate_lsx #define XXH3_scrambleAcc XXH3_scrambleAcc_lsx #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #else /* scalar */ #define XXH3_accumulate_512 XXH3_accumulate_512_scalar #define XXH3_accumulate XXH3_accumulate_scalar #define XXH3_scrambleAcc XXH3_scrambleAcc_scalar #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #endif #if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */ # undef XXH3_initCustomSecret # define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #endif XXH_FORCE_INLINE void XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock; size_t const nb_blocks = (len - 1) / block_len; size_t n; XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); for (n = 0; n < nb_blocks; n++) { f_acc(acc, input + n*block_len, secret, nbStripesPerBlock); f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); } /* last partial block */ XXH_ASSERT(len > XXH_STRIPE_LEN); { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); f_acc(acc, input + nb_blocks*block_len, secret, nbStripes); /* last stripe */ { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; #define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); } } } XXH_FORCE_INLINE xxh_u64 XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret) { return XXH3_mul128_fold64( acc[0] ^ XXH_readLE64(secret), acc[1] ^ XXH_readLE64(secret+8) ); } static XXH_PUREF XXH64_hash_t XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) { xxh_u64 result64 = start; size_t i = 0; for (i = 0; i < 4; i++) { result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i); #if defined(__clang__) /* Clang */ \ && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \ && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ /* * UGLY HACK: * Prevent autovectorization on Clang ARMv7-a. Exact same problem as * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b. * XXH3_64bits, len == 256, Snapdragon 835: * without hack: 2063.7 MB/s * with hack: 2560.7 MB/s */ XXH_COMPILER_GUARD(result64); #endif } return XXH3_avalanche(result64); } /* do not align on 8, so that the secret is different from the accumulator */ #define XXH_SECRET_MERGEACCS_START 11 static XXH_PUREF XXH64_hash_t XXH3_finalizeLong_64b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 len) { return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, len * XXH_PRIME64_1); } #define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, const void* XXH_RESTRICT secret, size_t secretSize, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble); /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); return XXH3_finalizeLong_64b(acc, (const xxh_u8*)secret, (xxh_u64)len); } /* * It's important for performance to transmit secret's size (when it's static) * so that the compiler can properly optimize the vectorized loop. * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set. * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE * breaks -Og, this is XXH_NO_INLINE. */ XXH3_WITH_SECRET_INLINE XXH64_hash_t XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); } /* * It's preferable for performance that XXH3_hashLong is not inlined, * as it results in a smaller function for small data, easier to the instruction cache. * Note that inside this no_inline function, we do inline the internal loop, * and provide a statically defined secret size to allow optimization of vector loop. */ XXH_NO_INLINE XXH_PUREF XXH64_hash_t XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); } /* * XXH3_hashLong_64b_withSeed(): * Generate a custom key based on alteration of default XXH3_kSecret with the seed, * and then use this key for long mode hashing. * * This operation is decently fast but nonetheless costs a little bit of time. * Try to avoid it whenever possible (typically when seed==0). * * It's important for performance that XXH3_hashLong is not inlined. Not sure * why (uop cache maybe?), but the difference is large and easily measurable. */ XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, XXH64_hash_t seed, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble, XXH3_f_initCustomSecret f_initSec) { #if XXH_SIZE_OPT <= 0 if (seed == 0) return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), f_acc, f_scramble); #endif { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; f_initSec(secret, seed); return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), f_acc, f_scramble); } } /* * It's important for performance that XXH3_hashLong is not inlined. */ XXH_NO_INLINE XXH64_hash_t XXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)secret; (void)secretLen; return XXH3_hashLong_64b_withSeed_internal(input, len, seed, XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); } typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t, XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t); XXH_FORCE_INLINE XXH64_hash_t XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, XXH3_hashLong64_f f_hashLong) { XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); /* * If an action is to be taken if `secretLen` condition is not respected, * it should be done here. * For now, it's a contract pre-condition. * Adding a check and a branch here would cost performance at every hash. * Also, note that function signature doesn't offer room to return an error. */ if (len <= 16) return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); if (len <= 128) return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); if (len <= XXH3_MIDSIZE_MAX) return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen); } /* === Public entry point === */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length) { return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed) { return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); } XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { if (length <= XXH3_MIDSIZE_MAX) return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize); } /* === XXH3 streaming === */ #ifndef XXH_NO_STREAM /* * Malloc's a pointer that is always aligned to @align. * * This must be freed with `XXH_alignedFree()`. * * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2 * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON. * * This underalignment previously caused a rather obvious crash which went * completely unnoticed due to XXH3_createState() not actually being tested. * Credit to RedSpah for noticing this bug. * * The alignment is done manually: Functions like posix_memalign or _mm_malloc * are avoided: To maintain portability, we would have to write a fallback * like this anyways, and besides, testing for the existence of library * functions without relying on external build tools is impossible. * * The method is simple: Overallocate, manually align, and store the offset * to the original behind the returned pointer. * * Align must be a power of 2 and 8 <= align <= 128. */ static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align) { XXH_ASSERT(align <= 128 && align >= 8); /* range check */ XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */ { /* Overallocate to make room for manual realignment and an offset byte */ xxh_u8* base = (xxh_u8*)XXH_malloc(s + align); if (base != NULL) { /* * Get the offset needed to align this pointer. * * Even if the returned pointer is aligned, there will always be * at least one byte to store the offset to the original pointer. */ size_t offset = align - ((size_t)base & (align - 1)); /* base % align */ /* Add the offset for the now-aligned pointer */ xxh_u8* ptr = base + offset; XXH_ASSERT((size_t)ptr % align == 0); /* Store the offset immediately before the returned pointer. */ ptr[-1] = (xxh_u8)offset; return ptr; } return NULL; } } /* * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout. */ static void XXH_alignedFree(void* p) { if (p != NULL) { xxh_u8* ptr = (xxh_u8*)p; /* Get the offset byte we added in XXH_malloc. */ xxh_u8 offset = ptr[-1]; /* Free the original malloc'd pointer */ xxh_u8* base = ptr - offset; XXH_free(base); } } /*! @ingroup XXH3_family */ /*! * @brief Allocate an @ref XXH3_state_t. * * @return An allocated pointer of @ref XXH3_state_t on success. * @return `NULL` on failure. * * @note Must be freed with XXH3_freeState(). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) { XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); if (state==NULL) return NULL; XXH3_INITSTATE(state); return state; } /*! @ingroup XXH3_family */ /*! * @brief Frees an @ref XXH3_state_t. * * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). * * @return @ref XXH_OK. * * @note Must be allocated with XXH3_createState(). * * @see @ref streaming_example "Streaming Example" */ XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) { XXH_alignedFree(statePtr); return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state) { XXH_memcpy(dst_state, src_state, sizeof(*dst_state)); } static void XXH3_reset_internal(XXH3_state_t* statePtr, XXH64_hash_t seed, const void* secret, size_t secretSize) { size_t const initStart = offsetof(XXH3_state_t, bufferedSize); size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart; XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart); XXH_ASSERT(statePtr != NULL); /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */ memset((char*)statePtr + initStart, 0, initLength); statePtr->acc[0] = XXH_PRIME32_3; statePtr->acc[1] = XXH_PRIME64_1; statePtr->acc[2] = XXH_PRIME64_2; statePtr->acc[3] = XXH_PRIME64_3; statePtr->acc[4] = XXH_PRIME64_4; statePtr->acc[5] = XXH_PRIME32_2; statePtr->acc[6] = XXH_PRIME64_5; statePtr->acc[7] = XXH_PRIME32_1; statePtr->seed = seed; statePtr->useSeed = (seed != 0); statePtr->extSecret = (const unsigned char*)secret; XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); statePtr->secretLimit = secretSize - XXH_STRIPE_LEN; statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) { if (statePtr == NULL) return XXH_ERROR; XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) { if (statePtr == NULL) return XXH_ERROR; XXH3_reset_internal(statePtr, 0, secret, secretSize); if (secret == NULL) return XXH_ERROR; if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) { if (statePtr == NULL) return XXH_ERROR; if (seed==0) return XXH3_64bits_reset(statePtr); if ((seed != statePtr->seed) || (statePtr->extSecret != NULL)) XXH3_initCustomSecret(statePtr->customSecret, seed); XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64) { if (statePtr == NULL) return XXH_ERROR; if (secret == NULL) return XXH_ERROR; if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; XXH3_reset_internal(statePtr, seed64, secret, secretSize); statePtr->useSeed = 1; /* always, even if seed64==0 */ return XXH_OK; } /*! * @internal * @brief Processes a large input for XXH3_update() and XXH3_digest_long(). * * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block. * * @param acc Pointer to the 8 accumulator lanes * @param nbStripesSoFarPtr In/out pointer to the number of leftover stripes in the block* * @param nbStripesPerBlock Number of stripes in a block * @param input Input pointer * @param nbStripes Number of stripes to process * @param secret Secret pointer * @param secretLimit Offset of the last block in @p secret * @param f_acc Pointer to an XXH3_accumulate implementation * @param f_scramble Pointer to an XXH3_scrambleAcc implementation * @return Pointer past the end of @p input after processing */ XXH_FORCE_INLINE const xxh_u8 * XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, const xxh_u8* XXH_RESTRICT input, size_t nbStripes, const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE; /* Process full blocks */ if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) { /* Process the initial partial block... */ size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr; do { /* Accumulate and scramble */ f_acc(acc, input, initialSecret, nbStripesThisIter); f_scramble(acc, secret + secretLimit); input += nbStripesThisIter * XXH_STRIPE_LEN; nbStripes -= nbStripesThisIter; /* Then continue the loop with the full block size */ nbStripesThisIter = nbStripesPerBlock; initialSecret = secret; } while (nbStripes >= nbStripesPerBlock); *nbStripesSoFarPtr = 0; } /* Process a partial block */ if (nbStripes > 0) { f_acc(acc, input, initialSecret, nbStripes); input += nbStripes * XXH_STRIPE_LEN; *nbStripesSoFarPtr += nbStripes; } /* Return end pointer */ return input; } #ifndef XXH3_STREAM_USE_STACK # if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */ # define XXH3_STREAM_USE_STACK 1 # endif #endif /* * Both XXH3_64bits_update and XXH3_128bits_update use this routine. */ XXH_FORCE_INLINE XXH_errorcode XXH3_update(XXH3_state_t* XXH_RESTRICT const state, const xxh_u8* XXH_RESTRICT input, size_t len, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { if (input==NULL) { XXH_ASSERT(len == 0); return XXH_OK; } XXH_ASSERT(state != NULL); { const xxh_u8* const bEnd = input + len; const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; #if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 /* For some reason, gcc and MSVC seem to suffer greatly * when operating accumulators directly into state. * Operating into stack space seems to enable proper optimization. * clang, on the other hand, doesn't seem to need this trick */ XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; XXH_memcpy(acc, state->acc, sizeof(acc)); #else xxh_u64* XXH_RESTRICT const acc = state->acc; #endif state->totalLen += len; XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); /* small input : just fill in tmp buffer */ if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) { XXH_memcpy(state->buffer + state->bufferedSize, input, len); state->bufferedSize += (XXH32_hash_t)len; return XXH_OK; } /* total input is now > XXH3_INTERNALBUFFER_SIZE */ #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN) XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */ /* * Internal buffer is partially filled (always, except at beginning) * Complete it, then consume it. */ if (state->bufferedSize) { size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize; XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize); input += loadSize; XXH3_consumeStripes(acc, &state->nbStripesSoFar, state->nbStripesPerBlock, state->buffer, XXH3_INTERNALBUFFER_STRIPES, secret, state->secretLimit, f_acc, f_scramble); state->bufferedSize = 0; } XXH_ASSERT(input < bEnd); if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN; input = XXH3_consumeStripes(acc, &state->nbStripesSoFar, state->nbStripesPerBlock, input, nbStripes, secret, state->secretLimit, f_acc, f_scramble); XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); } /* Some remaining input (always) : buffer it */ XXH_ASSERT(input < bEnd); XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE); XXH_ASSERT(state->bufferedSize == 0); XXH_memcpy(state->buffer, input, (size_t)(bEnd-input)); state->bufferedSize = (XXH32_hash_t)(bEnd-input); #if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 /* save stack accumulators into state */ XXH_memcpy(state->acc, acc, sizeof(acc)); #endif } return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { return XXH3_update(state, (const xxh_u8*)input, len, XXH3_accumulate, XXH3_scrambleAcc); } XXH_FORCE_INLINE void XXH3_digest_long (XXH64_hash_t* acc, const XXH3_state_t* state, const unsigned char* secret) { xxh_u8 lastStripe[XXH_STRIPE_LEN]; const xxh_u8* lastStripePtr; /* * Digest on a local copy. This way, the state remains unaltered, and it can * continue ingesting more input afterwards. */ XXH_memcpy(acc, state->acc, sizeof(state->acc)); if (state->bufferedSize >= XXH_STRIPE_LEN) { /* Consume remaining stripes then point to remaining data in buffer */ size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; size_t nbStripesSoFar = state->nbStripesSoFar; XXH3_consumeStripes(acc, &nbStripesSoFar, state->nbStripesPerBlock, state->buffer, nbStripes, secret, state->secretLimit, XXH3_accumulate, XXH3_scrambleAcc); lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN; } else { /* bufferedSize < XXH_STRIPE_LEN */ /* Copy to temp buffer */ size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); lastStripePtr = lastStripe; } /* Last stripe */ XXH3_accumulate_512(acc, lastStripePtr, secret + state->secretLimit - XXH_SECRET_LASTACC_START); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state) { const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; if (state->totalLen > XXH3_MIDSIZE_MAX) { XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; XXH3_digest_long(acc, state, secret); return XXH3_finalizeLong_64b(acc, secret, (xxh_u64)state->totalLen); } /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ if (state->useSeed) return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), secret, state->secretLimit + XXH_STRIPE_LEN); } #endif /* !XXH_NO_STREAM */ /* ========================================== * XXH3 128 bits (a.k.a XXH128) * ========================================== * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant, * even without counting the significantly larger output size. * * For example, extra steps are taken to avoid the seed-dependent collisions * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B). * * This strength naturally comes at the cost of some speed, especially on short * lengths. Note that longer hashes are about as fast as the 64-bit version * due to it using only a slight modification of the 64-bit loop. * * XXH128 is also more oriented towards 64-bit machines. It is still extremely * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). */ XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { /* A doubled version of 1to3_64b with different constants. */ XXH_ASSERT(input != NULL); XXH_ASSERT(1 <= len && len <= 3); XXH_ASSERT(secret != NULL); /* * len = 1: combinedl = { input[0], 0x01, input[0], input[0] } * len = 2: combinedl = { input[1], 0x02, input[0], input[1] } * len = 3: combinedl = { input[2], 0x03, input[0], input[1] } */ { xxh_u8 const c1 = input[0]; xxh_u8 const c2 = input[len >> 1]; xxh_u8 const c3 = input[len - 1]; xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24) | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13); xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed; xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl; xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph; XXH128_hash_t h128; h128.low64 = XXH64_avalanche(keyed_lo); h128.high64 = XXH64_avalanche(keyed_hi); return h128; } } XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(4 <= len && len <= 8); seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; { xxh_u32 const input_lo = XXH_readLE32(input); xxh_u32 const input_hi = XXH_readLE32(input + len - 4); xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32); xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed; xxh_u64 const keyed = input_64 ^ bitflip; /* Shift len to the left to ensure it is even, this avoids even multiplies. */ XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2)); m128.high64 += (m128.low64 << 1); m128.low64 ^= (m128.high64 >> 3); m128.low64 = XXH_xorshift64(m128.low64, 35); m128.low64 *= PRIME_MX2; m128.low64 = XXH_xorshift64(m128.low64, 28); m128.high64 = XXH3_avalanche(m128.high64); return m128; } } XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(9 <= len && len <= 16); { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed; xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed; xxh_u64 const input_lo = XXH_readLE64(input); xxh_u64 input_hi = XXH_readLE64(input + len - 8); XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1); /* * Put len in the middle of m128 to ensure that the length gets mixed to * both the low and high bits in the 128x64 multiply below. */ m128.low64 += (xxh_u64)(len - 1) << 54; input_hi ^= bitfliph; /* * Add the high 32 bits of input_hi to the high 32 bits of m128, then * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to * the high 64 bits of m128. * * The best approach to this operation is different on 32-bit and 64-bit. */ if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */ /* * 32-bit optimized version, which is more readable. * * On 32-bit, it removes an ADC and delays a dependency between the two * halves of m128.high64, but it generates an extra mask on 64-bit. */ m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2); } else { /* * 64-bit optimized (albeit more confusing) version. * * Uses some properties of addition and multiplication to remove the mask: * * Let: * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF) * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000) * c = XXH_PRIME32_2 * * a + (b * c) * Inverse Property: x + y - x == y * a + (b * (1 + c - 1)) * Distributive Property: x * (y + z) == (x * y) + (x * z) * a + (b * 1) + (b * (c - 1)) * Identity Property: x * 1 == x * a + b + (b * (c - 1)) * * Substitute a, b, and c: * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) * * Since input_hi.hi + input_hi.lo == input_hi, we get this: * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) */ m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1); } /* m128 ^= XXH_swap64(m128 >> 64); */ m128.low64 ^= XXH_swap64(m128.high64); { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */ XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2); h128.high64 += m128.high64 * XXH_PRIME64_2; h128.low64 = XXH3_avalanche(h128.low64); h128.high64 = XXH3_avalanche(h128.high64); return h128; } } } /* * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN */ XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(len <= 16); { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed); if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed); if (len) return XXH3_len_1to3_128b(input, len, secret, seed); { XXH128_hash_t h128; xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72); xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88); h128.low64 = XXH64_avalanche(seed ^ bitflipl); h128.high64 = XXH64_avalanche( seed ^ bitfliph); return h128; } } } /* * A bit slower than XXH3_mix16B, but handles multiply by zero better. */ XXH_FORCE_INLINE XXH128_hash_t XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, const xxh_u8* secret, XXH64_hash_t seed) { acc.low64 += XXH3_mix16B (input_1, secret+0, seed); acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8); acc.high64 += XXH3_mix16B (input_2, secret+16, seed); acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8); return acc; } XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(16 < len && len <= 128); { XXH128_hash_t acc; acc.low64 = len * XXH_PRIME64_1; acc.high64 = 0; #if XXH_SIZE_OPT >= 1 { /* Smaller, but slightly slower. */ unsigned int i = (unsigned int)(len - 1) / 32; do { acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed); } while (i-- != 0); } #else if (len > 32) { if (len > 64) { if (len > 96) { acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed); } acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed); } acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); } acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); #endif { XXH128_hash_t h128; h128.low64 = acc.low64 + acc.high64; h128.high64 = (acc.low64 * XXH_PRIME64_1) + (acc.high64 * XXH_PRIME64_4) + ((len - seed) * XXH_PRIME64_2); h128.low64 = XXH3_avalanche(h128.low64); h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); return h128; } } } XXH_NO_INLINE XXH_PUREF XXH128_hash_t XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); { XXH128_hash_t acc; unsigned i; acc.low64 = len * XXH_PRIME64_1; acc.high64 = 0; /* * We set as `i` as offset + 32. We do this so that unchanged * `len` can be used as upper bound. This reaches a sweet spot * where both x86 and aarch64 get simple agen and good codegen * for the loop. */ for (i = 32; i < 160; i += 32) { acc = XXH128_mix32B(acc, input + i - 32, input + i - 16, secret + i - 32, seed); } acc.low64 = XXH3_avalanche(acc.low64); acc.high64 = XXH3_avalanche(acc.high64); /* * NB: `i <= len` will duplicate the last 32-bytes if * len % 32 was zero. This is an unfortunate necessity to keep * the hash result stable. */ for (i=160; i <= len; i += 32) { acc = XXH128_mix32B(acc, input + i - 32, input + i - 16, secret + XXH3_MIDSIZE_STARTOFFSET + i - 160, seed); } /* last bytes */ acc = XXH128_mix32B(acc, input + len - 16, input + len - 32, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, (XXH64_hash_t)0 - seed); { XXH128_hash_t h128; h128.low64 = acc.low64 + acc.high64; h128.high64 = (acc.low64 * XXH_PRIME64_1) + (acc.high64 * XXH_PRIME64_4) + ((len - seed) * XXH_PRIME64_2); h128.low64 = XXH3_avalanche(h128.low64); h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); return h128; } } } static XXH_PUREF XXH128_hash_t XXH3_finalizeLong_128b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, xxh_u64 len) { XXH128_hash_t h128; h128.low64 = XXH3_finalizeLong_64b(acc, secret, len); h128.high64 = XXH3_mergeAccs(acc, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_MERGEACCS_START, ~(len * XXH_PRIME64_2)); return h128; } XXH_FORCE_INLINE XXH128_hash_t XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble); /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); return XXH3_finalizeLong_128b(acc, secret, secretSize, (xxh_u64)len); } /* * It's important for performance that XXH3_hashLong() is not inlined. */ XXH_NO_INLINE XXH_PUREF XXH128_hash_t XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); } /* * It's important for performance to pass @p secretLen (when it's static) * to the compiler, so that it can properly optimize the vectorized loop. * * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE * breaks -Og, this is XXH_NO_INLINE. */ XXH3_WITH_SECRET_INLINE XXH128_hash_t XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); } XXH_FORCE_INLINE XXH128_hash_t XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble, XXH3_f_initCustomSecret f_initSec) { if (seed64 == 0) return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), f_acc, f_scramble); { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; f_initSec(secret, seed64); return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), f_acc, f_scramble); } } /* * It's important for performance that XXH3_hashLong is not inlined. */ XXH_NO_INLINE XXH128_hash_t XXH3_hashLong_128b_withSeed(const void* input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) { (void)secret; (void)secretLen; return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); } typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, XXH64_hash_t, const void* XXH_RESTRICT, size_t); XXH_FORCE_INLINE XXH128_hash_t XXH3_128bits_internal(const void* input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, XXH3_hashLong128_f f_hl128) { XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); /* * If an action is to be taken if `secret` conditions are not respected, * it should be done here. * For now, it's a contract pre-condition. * Adding a check and a branch here would cost performance at every hash. */ if (len <= 16) return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); if (len <= 128) return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); if (len <= XXH3_MIDSIZE_MAX) return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); return f_hl128(input, len, seed64, secret, secretLen); } /* === Public XXH128 API === */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len) { return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_default); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_128bits_internal(input, len, 0, (const xxh_u8*)secret, secretSize, XXH3_hashLong_128b_withSecret); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { if (len <= XXH3_MIDSIZE_MAX) return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_128bits_withSeed(input, len, seed); } /* === XXH3 128-bit streaming === */ #ifndef XXH_NO_STREAM /* * All initialization and update functions are identical to 64-bit streaming variant. * The only difference is the finalization routine. */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) { return XXH3_64bits_reset(statePtr); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) { return XXH3_64bits_reset_withSeed(statePtr, seed); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { return XXH3_64bits_update(state, input, len); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state) { const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; if (state->totalLen > XXH3_MIDSIZE_MAX) { XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; XXH3_digest_long(acc, state, secret); XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); return XXH3_finalizeLong_128b(acc, secret, state->secretLimit + XXH_STRIPE_LEN, (xxh_u64)state->totalLen); } /* len <= XXH3_MIDSIZE_MAX : short code */ if (state->useSeed) return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), secret, state->secretLimit + XXH_STRIPE_LEN); } #endif /* !XXH_NO_STREAM */ /* 128-bit utility functions */ #include /* memcmp, memcpy */ /* return : 1 is equal, 0 if different */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) { /* note : XXH128_hash_t is compact, it has no padding byte */ return !(memcmp(&h1, &h2, sizeof(h1))); } /* This prototype is compatible with stdlib's qsort(). * @return : >0 if *h128_1 > *h128_2 * <0 if *h128_1 < *h128_2 * =0 if *h128_1 == *h128_2 */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2) { XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64); /* note : bets that, in most cases, hash values are different */ if (hcmp) return hcmp; return (h1.low64 > h2.low64) - (h2.low64 > h1.low64); } /*====== Canonical representation ======*/ /*! @ingroup XXH3_family */ XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) { hash.high64 = XXH_swap64(hash.high64); hash.low64 = XXH_swap64(hash.low64); } XXH_memcpy(dst, &hash.high64, sizeof(hash.high64)); XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src) { XXH128_hash_t h; h.high64 = XXH_readBE64(src); h.low64 = XXH_readBE64(src->digest + 8); return h; } /* ========================================== * Secret generators * ========================================== */ #define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128) { XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 ); XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 ); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize) { #if (XXH_DEBUGLEVEL >= 1) XXH_ASSERT(secretBuffer != NULL); XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); #else /* production mode, assert() are disabled */ if (secretBuffer == NULL) return XXH_ERROR; if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; #endif if (customSeedSize == 0) { customSeed = XXH3_kSecret; customSeedSize = XXH_SECRET_DEFAULT_SIZE; } #if (XXH_DEBUGLEVEL >= 1) XXH_ASSERT(customSeed != NULL); #else if (customSeed == NULL) return XXH_ERROR; #endif /* Fill secretBuffer with a copy of customSeed - repeat as needed */ { size_t pos = 0; while (pos < secretSize) { size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize); memcpy((char*)secretBuffer + pos, customSeed, toCopy); pos += toCopy; } } { size_t const nbSeg16 = secretSize / 16; size_t n; XXH128_canonical_t scrambler; XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0)); for (n=0; n # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 10 AC_DEFUN([AX_AC_APPEND_TO_FILE],[ AC_REQUIRE([AX_FILE_ESCAPES]) m4_esyscmd( AX_FILE_ESCAPES [ printf "%s" "$2" >> "$1" ]) ]) dvisvgm-3.5/m4/ax_ac_print_to_file.m4000066400000000000000000000016111501401750600176100ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_ac_print_to_file.html # =========================================================================== # # SYNOPSIS # # AX_AC_PRINT_TO_FILE([FILE],[DATA]) # # DESCRIPTION # # Writes the specified data to the specified file when Autoconf is run. If # you want to print to a file when configure is run use AX_PRINT_TO_FILE # instead. # # LICENSE # # Copyright (c) 2009 Allan Caffee # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 10 AC_DEFUN([AX_AC_PRINT_TO_FILE],[ m4_esyscmd( AC_REQUIRE([AX_FILE_ESCAPES]) [ printf "%s" "$2" > "$1" ]) ]) dvisvgm-3.5/m4/ax_add_am_macro_static.m4000066400000000000000000000015251501401750600202510ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_add_am_macro_static.html # =========================================================================== # # SYNOPSIS # # AX_ADD_AM_MACRO_STATIC([RULE]) # # DESCRIPTION # # Adds the specified rule to $AMINCLUDE. # # LICENSE # # Copyright (c) 2009 Tom Howard # Copyright (c) 2009 Allan Caffee # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AC_DEFUN([AX_ADD_AM_MACRO_STATIC],[ AC_REQUIRE([AX_AM_MACROS_STATIC]) AX_AC_APPEND_TO_FILE(AMINCLUDE_STATIC,[$1]) ]) dvisvgm-3.5/m4/ax_am_macros_static.m4000066400000000000000000000021251501401750600176210ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_am_macros_static.html # =========================================================================== # # SYNOPSIS # # AX_AM_MACROS_STATIC # # DESCRIPTION # # Adds support for macros that create Automake rules. You must manually # add the following line # # include $(top_srcdir)/aminclude_static.am # # to your Makefile.am files. # # LICENSE # # Copyright (c) 2009 Tom Howard # Copyright (c) 2009 Allan Caffee # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 11 AC_DEFUN([AMINCLUDE_STATIC],[aminclude_static.am]) AC_DEFUN([AX_AM_MACROS_STATIC], [ AX_AC_PRINT_TO_FILE(AMINCLUDE_STATIC,[ # ]AMINCLUDE_STATIC[ generated automatically by Autoconf # from AX_AM_MACROS_STATIC on ]m4_esyscmd([LC_ALL=C date])[ ]) ]) dvisvgm-3.5/m4/ax_check_compile_flag.m4000066400000000000000000000040701501401750600200700ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 6 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS dvisvgm-3.5/m4/ax_code_coverage.m4000066400000000000000000000276161501401750600171120ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_code_coverage.html # =========================================================================== # # SYNOPSIS # # AX_CODE_COVERAGE() # # DESCRIPTION # # Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS, # CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included # in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every # build target (program or library) which should be built with code # coverage support. Also add rules using AX_ADD_AM_MACRO_STATIC; and # $enable_code_coverage which can be used in subsequent configure output. # CODE_COVERAGE_ENABLED is defined and substituted, and corresponds to the # value of the --enable-code-coverage option, which defaults to being # disabled. # # Test also for gcov program and create GCOV variable that could be # substituted. # # Note that all optimization flags in CFLAGS must be disabled when code # coverage is enabled. # # Usage example: # # configure.ac: # # AX_CODE_COVERAGE # # Makefile.am: # # include $(top_srcdir)/aminclude_static.am # # my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ... # my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ... # my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ... # my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ... # # clean-local: code-coverage-clean # distclean-local: code-coverage-dist-clean # # This results in a "check-code-coverage" rule being added to any # Makefile.am which do "include $(top_srcdir)/aminclude_static.am" # (assuming the module has been configured with --enable-code-coverage). # Running `make check-code-coverage` in that directory will run the # module's test suite (`make check`) and build a code coverage report # detailing the code which was touched, then print the URI for the report. # # This code was derived from Makefile.decl in GLib, originally licensed # under LGPLv2.1+. # # LICENSE # # Copyright (c) 2012, 2016 Philip Withnall # Copyright (c) 2012 Xan Lopez # Copyright (c) 2012 Christian Persch # Copyright (c) 2012 Paolo Borelli # Copyright (c) 2012 Dan Winship # Copyright (c) 2015,2018 Bastien ROUCARIES # # This library 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 2.1 of the License, or (at # your option) any later version. # # This library 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 this program. If not, see . #serial 34 m4_define(_AX_CODE_COVERAGE_RULES,[ AX_ADD_AM_MACRO_STATIC([ # Code coverage # # Optional: # - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. # Multiple directories may be specified, separated by whitespace. # (Default: \$(top_builddir)) # - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated # by lcov for code coverage. (Default: # \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info) # - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage # reports to be created. (Default: # \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage) # - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, # set to 0 to disable it and leave empty to stay with the default. # (Default: empty) # - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov # instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) # - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov # instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) # - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov # - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the # collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) # - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov # instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) # - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering # lcov instance. (Default: empty) # - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov # instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) # - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the # genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE) # - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml # instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) # - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore # # The generated report will be titled using the \$(PACKAGE_NAME) and # \$(PACKAGE_VERSION). In order to add the current git hash to the title, # use the git-version-gen script, available online. # Optional variables # run only on top dir if CODE_COVERAGE_ENABLED ifeq (\$(abs_builddir), \$(abs_top_builddir)) CODE_COVERAGE_DIRECTORY ?= \$(top_builddir) CODE_COVERAGE_OUTPUT_FILE ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info CODE_COVERAGE_OUTPUT_DIRECTORY ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage CODE_COVERAGE_BRANCH_COVERAGE ?= CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= \$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\ --rc lcov_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)) CODE_COVERAGE_LCOV_SHOPTS ?= \$(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool \"\$(GCOV)\" CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= \$(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) CODE_COVERAGE_LCOV_OPTIONS ?= \$(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= CODE_COVERAGE_LCOV_RMOPTS ?= \$(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\ \$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\ --rc genhtml_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE)) CODE_COVERAGE_GENHTML_OPTIONS ?= \$(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) CODE_COVERAGE_IGNORE_PATTERN ?= GITIGNOREFILES := \$(GITIGNOREFILES) \$(CODE_COVERAGE_OUTPUT_FILE) \$(CODE_COVERAGE_OUTPUT_DIRECTORY) code_coverage_v_lcov_cap = \$(code_coverage_v_lcov_cap_\$(V)) code_coverage_v_lcov_cap_ = \$(code_coverage_v_lcov_cap_\$(AM_DEFAULT_VERBOSITY)) code_coverage_v_lcov_cap_0 = @echo \" LCOV --capture\" \$(CODE_COVERAGE_OUTPUT_FILE); code_coverage_v_lcov_ign = \$(code_coverage_v_lcov_ign_\$(V)) code_coverage_v_lcov_ign_ = \$(code_coverage_v_lcov_ign_\$(AM_DEFAULT_VERBOSITY)) code_coverage_v_lcov_ign_0 = @echo \" LCOV --remove /tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN); code_coverage_v_genhtml = \$(code_coverage_v_genhtml_\$(V)) code_coverage_v_genhtml_ = \$(code_coverage_v_genhtml_\$(AM_DEFAULT_VERBOSITY)) code_coverage_v_genhtml_0 = @echo \" GEN \" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\"; code_coverage_quiet = \$(code_coverage_quiet_\$(V)) code_coverage_quiet_ = \$(code_coverage_quiet_\$(AM_DEFAULT_VERBOSITY)) code_coverage_quiet_0 = --quiet # sanitizes the test-name: replaces with underscores: dashes and dots code_coverage_sanitize = \$(subst -,_,\$(subst .,_,\$(1))) # Use recursive makes in order to ignore errors during check check-code-coverage: -\$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) -k check \$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) code-coverage-capture # Capture code coverage data code-coverage-capture: code-coverage-capture-hook \$(code_coverage_v_lcov_cap)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --capture --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" --test-name \"\$(call code_coverage_sanitize,\$(PACKAGE_NAME)-\$(PACKAGE_VERSION))\" --no-checksum --compat-libtool \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_OPTIONS) \$(code_coverage_v_lcov_ign)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --remove \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"/tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN) --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_RMOPTS) -@rm -f \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \$(code_coverage_v_genhtml)LANG=C \$(GENHTML) \$(code_coverage_quiet) \$(addprefix --prefix ,\$(CODE_COVERAGE_DIRECTORY)) --output-directory \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" --title \"\$(PACKAGE_NAME)-\$(PACKAGE_VERSION) Code Coverage\" --legend --show-details \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_GENHTML_OPTIONS) @echo \"file://\$(abs_builddir)/\$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html\" code-coverage-clean: -\$(LCOV) --directory \$(top_builddir) -z -rm -rf \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" -find . \\( -name \"*.gcda\" -o -name \"*.gcno\" -o -name \"*.gcov\" \\) -delete code-coverage-dist-clean: A][M_DISTCHECK_CONFIGURE_FLAGS := \$(A][M_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage else # ifneq (\$(abs_builddir), \$(abs_top_builddir)) check-code-coverage: code-coverage-capture: code-coverage-capture-hook code-coverage-clean: code-coverage-dist-clean: endif # ifeq (\$(abs_builddir), \$(abs_top_builddir)) else #! CODE_COVERAGE_ENABLED # Use recursive makes in order to ignore errors during check check-code-coverage: @echo \"Need to reconfigure with --enable-code-coverage\" # Capture code coverage data code-coverage-capture: code-coverage-capture-hook @echo \"Need to reconfigure with --enable-code-coverage\" code-coverage-clean: code-coverage-dist-clean: endif #CODE_COVERAGE_ENABLED # Hook rule executed before code-coverage-capture, overridable by the user code-coverage-capture-hook: .PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook ]) ]) AC_DEFUN([_AX_CODE_COVERAGE_ENABLED],[ AX_CHECK_GNU_MAKE([],[AC_MSG_ERROR([not using GNU make that is needed for coverage])]) AC_REQUIRE([AX_ADD_AM_MACRO_STATIC]) # check for gcov AC_CHECK_TOOL([GCOV], [$_AX_CODE_COVERAGE_GCOV_PROG_WITH], [:]) AS_IF([test "X$GCOV" = "X:"], [AC_MSG_ERROR([gcov is needed to do coverage])]) AC_SUBST([GCOV]) dnl Check if gcc is being used AS_IF([ test "$GCC" = "no" ], [ AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage]) ]) AC_CHECK_PROG([LCOV], [lcov], [lcov]) AC_CHECK_PROG([GENHTML], [genhtml], [genhtml]) AS_IF([ test x"$LCOV" = x ], [ AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed]) ]) AS_IF([ test x"$GENHTML" = x ], [ AC_MSG_ERROR([Could not find genhtml from the lcov package]) ]) dnl Build the code coverage flags dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility CODE_COVERAGE_CPPFLAGS="-DNDEBUG" CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" CODE_COVERAGE_LIBS="-lgcov" AC_SUBST([CODE_COVERAGE_CPPFLAGS]) AC_SUBST([CODE_COVERAGE_CFLAGS]) AC_SUBST([CODE_COVERAGE_CXXFLAGS]) AC_SUBST([CODE_COVERAGE_LIBS]) ]) AC_DEFUN([AX_CODE_COVERAGE],[ dnl Check for --enable-code-coverage # allow to override gcov location AC_ARG_WITH([gcov], [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])], [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov], [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov]) AC_MSG_CHECKING([whether to build with code coverage support]) AC_ARG_ENABLE([code-coverage], AS_HELP_STRING([--enable-code-coverage], [Whether to enable code coverage support]),, enable_code_coverage=no) AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test "x$enable_code_coverage" = xyes]) AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage]) AC_MSG_RESULT($enable_code_coverage) AS_IF([ test "x$enable_code_coverage" = xyes ], [ _AX_CODE_COVERAGE_ENABLED ]) _AX_CODE_COVERAGE_RULES ]) dvisvgm-3.5/m4/ax_cxx_compile_stdcxx.m4000066400000000000000000000512061501401750600202240ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for # the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for no added switch, and then for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper # Copyright (c) 2020 Jason Merrill # Copyright (c) 2021 Jörn Heusipp # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 15 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [$1], [20], [ax_cxx_compile_alternatives="20"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no m4_if([$2], [], [dnl AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, ax_cv_cxx_compile_cxx$1, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [ax_cv_cxx_compile_cxx$1=yes], [ax_cv_cxx_compile_cxx$1=no])]) if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi]) m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) dnl Test body for checking C++17 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) dnl Test body for checking C++20 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" // MSVC always sets __cplusplus to 199711L in older versions; newer versions // only set it correctly if /Zc:__cplusplus is specified as well as a // /std:c++NN switch: // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ #elif __cplusplus < 201103L && !defined _MSC_VER #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L && !defined _MSC_VER #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) dnl Tests for new features in C++17 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L && !defined _MSC_VER #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L && !defined _MSC_VER ]]) dnl Tests for new features in C++20 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 202002L && !defined _MSC_VER #error "This is not a C++20 compiler" #else #include namespace cxx20 { // As C++20 supports feature test macros in the standard, there is no // immediate need to actually test for feature availability on the // Autoconf side. } // namespace cxx20 #endif // __cplusplus < 202002L && !defined _MSC_VER ]]) dvisvgm-3.5/m4/ax_file_escapes.m4000066400000000000000000000013731501401750600167370ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_file_escapes.html # =========================================================================== # # SYNOPSIS # # AX_FILE_ESCAPES # # DESCRIPTION # # Writes the specified data to the specified file. # # LICENSE # # Copyright (c) 2008 Tom Howard # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AC_DEFUN([AX_FILE_ESCAPES],[ AX_DOLLAR="\$" AX_SRB="\\135" AX_SLB="\\133" AX_BS="\\\\" AX_DQ="\"" ]) dvisvgm-3.5/m4/ax_gcc_builtin.m4000066400000000000000000000133461501401750600166020ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html # =========================================================================== # # SYNOPSIS # # AX_GCC_BUILTIN(BUILTIN) # # DESCRIPTION # # This macro checks if the compiler supports one of GCC's built-in # functions; many other compilers also provide those same built-ins. # # The BUILTIN parameter is the name of the built-in function. # # If BUILTIN is supported define HAVE_. Keep in mind that since # builtins usually start with two underscores they will be copied over # into the HAVE_ definition (e.g. HAVE___BUILTIN_EXPECT for # __builtin_expect()). # # The macro caches its result in the ax_cv_have_ variable (e.g. # ax_cv_have___builtin_expect). # # The macro currently supports the following built-in functions: # # __builtin_assume_aligned # __builtin_bswap16 # __builtin_bswap32 # __builtin_bswap64 # __builtin_choose_expr # __builtin___clear_cache # __builtin_clrsb # __builtin_clrsbl # __builtin_clrsbll # __builtin_clz # __builtin_clzl # __builtin_clzll # __builtin_complex # __builtin_constant_p # __builtin_ctz # __builtin_ctzl # __builtin_ctzll # __builtin_expect # __builtin_ffs # __builtin_ffsl # __builtin_ffsll # __builtin_fpclassify # __builtin_huge_val # __builtin_huge_valf # __builtin_huge_vall # __builtin_inf # __builtin_infd128 # __builtin_infd32 # __builtin_infd64 # __builtin_inff # __builtin_infl # __builtin_isinf_sign # __builtin_nan # __builtin_nand128 # __builtin_nand32 # __builtin_nand64 # __builtin_nanf # __builtin_nanl # __builtin_nans # __builtin_nansf # __builtin_nansl # __builtin_object_size # __builtin_parity # __builtin_parityl # __builtin_parityll # __builtin_popcount # __builtin_popcountl # __builtin_popcountll # __builtin_powi # __builtin_powif # __builtin_powil # __builtin_prefetch # __builtin_trap # __builtin_types_compatible_p # __builtin_unreachable # # Unsupported built-ins will be tested with an empty parameter set and the # result of the check might be wrong or meaningless so use with care. # # LICENSE # # Copyright (c) 2013 Gabriele Svelto # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 6 AC_DEFUN([AX_GCC_BUILTIN], [ AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1]) AC_CACHE_CHECK([for $1], [ac_var], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [ m4_case([$1], [__builtin_assume_aligned], [$1("", 0)], [__builtin_bswap16], [$1(0)], [__builtin_bswap32], [$1(0)], [__builtin_bswap64], [$1(0)], [__builtin_choose_expr], [$1(0, 0, 0)], [__builtin___clear_cache], [$1("", "")], [__builtin_clrsb], [$1(0)], [__builtin_clrsbl], [$1(0)], [__builtin_clrsbll], [$1(0)], [__builtin_clz], [$1(0)], [__builtin_clzl], [$1(0)], [__builtin_clzll], [$1(0)], [__builtin_complex], [$1(0.0, 0.0)], [__builtin_constant_p], [$1(0)], [__builtin_ctz], [$1(0)], [__builtin_ctzl], [$1(0)], [__builtin_ctzll], [$1(0)], [__builtin_expect], [$1(0, 0)], [__builtin_ffs], [$1(0)], [__builtin_ffsl], [$1(0)], [__builtin_ffsll], [$1(0)], [__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)], [__builtin_huge_val], [$1()], [__builtin_huge_valf], [$1()], [__builtin_huge_vall], [$1()], [__builtin_inf], [$1()], [__builtin_infd128], [$1()], [__builtin_infd32], [$1()], [__builtin_infd64], [$1()], [__builtin_inff], [$1()], [__builtin_infl], [$1()], [__builtin_isinf_sign], [$1(0.0)], [__builtin_nan], [$1("")], [__builtin_nand128], [$1("")], [__builtin_nand32], [$1("")], [__builtin_nand64], [$1("")], [__builtin_nanf], [$1("")], [__builtin_nanl], [$1("")], [__builtin_nans], [$1("")], [__builtin_nansf], [$1("")], [__builtin_nansl], [$1("")], [__builtin_object_size], [$1("", 0)], [__builtin_parity], [$1(0)], [__builtin_parityl], [$1(0)], [__builtin_parityll], [$1(0)], [__builtin_popcount], [$1(0)], [__builtin_popcountl], [$1(0)], [__builtin_popcountll], [$1(0)], [__builtin_powi], [$1(0, 0)], [__builtin_powif], [$1(0, 0)], [__builtin_powil], [$1(0, 0)], [__builtin_prefetch], [$1("")], [__builtin_trap], [$1()], [__builtin_types_compatible_p], [$1(int, int)], [__builtin_unreachable], [$1()], [m4_warn([syntax], [Unsupported built-in $1, the test may fail]) $1()] ) ])], [AS_VAR_SET([ac_var], [yes])], [AS_VAR_SET([ac_var], [no])]) ]) AS_IF([test yes = AS_VAR_GET([ac_var])], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1, [Define to 1 if the system has the `$1' built-in function])], []) AS_VAR_POPDEF([ac_var]) ]) dvisvgm-3.5/src/000077500000000000000000000000001501401750600136265ustar00rootroot00000000000000dvisvgm-3.5/src/AGLTable.hpp000066400000000000000000004657621501401750600157360ustar00rootroot00000000000000/************************************************************************* ** AGLTable.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ /* The following table provides a compact mapping from PostScript character names * to Unicode points. Instead of using the character names directly it maps the * hash values (xxhash32) of the names to the corresponding code points. * The character mapping is derived from the Adobe Glyph List (AGL): * https://github.com/adobe-type-tools/agl-aglfn * http://tug.ctan.org/macros/latex/contrib/pdfx/glyphtounicode-cmr.tex */ #include struct HashCodepointPair { uint32_t hash; uint32_t codepoint; }; std::array hash2unicode {{ {0x001cf4a9, 0x0118}, // Eogonek {0x003b11fb, 0x055f}, // abbreviationmarkarmenian {0x0050a316, 0x0444}, // afii10086 {0x0066ddfe, 0x03a5}, // Upsilon {0x0067a87d, 0x0026}, // ampersand {0x007399ea, 0x2118}, // weierstrass {0x009a8cbc, 0x30c8}, // tokatakana {0x00a8ecc1, 0xfb93}, // gaffinalarabic {0x00b0f8d6, 0x05b2}, // hatafpatahwidehebrew {0x00b1b890, 0x2486}, // nineteenparen {0x00b92975, 0x05a7}, // dargalefthebrew {0x00c458a3, 0x2154}, // twothirds {0x00e73988, 0x09b8}, // sabengali {0x00f475c4, 0x03ee}, // Deicoptic {0x00fa9974, 0x0303}, // tildecmb {0x01012c9a, 0x05b4}, // hiriq {0x0107d6e3, 0x0933}, // lladeva {0x01127238, 0x3237}, // ideographiccongratulationparen {0x011abc50, 0x0547}, // Shaarmenian {0x01297545, 0x25aa}, // H18543 {0x012d44bc, 0x05d6}, // afii57670 {0x013044fb, 0x2205}, // emptyset {0x01422ce1, 0x0486}, // psilipneumatacyrilliccmb {0x01571757, 0xfe6b}, // atsmall {0x01678eeb, 0x066b}, // decimalseparatorpersian {0x018643fe, 0x091a}, // cadeva {0x019e6772, 0x3148}, // cieuckorean {0x019fa822, 0x05de}, // mem {0x01cfa7b3, 0x0a3e}, // aamatragurmukhi {0x01d7c979, 0x3007}, // ideographiczero {0x020d70ad, 0x278b}, // twocircleinversesansserif {0x0239eab1, 0x3131}, // kiyeokkorean {0x023b0c79, 0xff87}, // nukatakanahalfwidth {0x023deac8, 0x3183}, // yesieungpansioskorean {0x02409db2, 0x1ed1}, // ocircumflexacute {0x02574652, 0x0e1b}, // poplathai {0x025b8acc, 0x0a47}, // eematragurmukhi {0x02610d57, 0x2668}, // hotsprings {0x0292f83b, 0x0e11}, // thonangmonthothai {0x0293c9db, 0xff49}, // imonospace {0x029e63cc, 0x21e7}, // arrowupwhite {0x02a32a9d, 0x0275}, // obarred {0x02a97908, 0x09f7}, // fournumeratorbengali {0x02abe0be, 0x2556}, // SF210000 {0x02acd87a, 0x2461}, // twocircle {0x02bb8927, 0x0154}, // Racute {0x02bd043f, 0x3392}, // mhzsquare {0x02bdc138, 0x304a}, // ohiragana {0x02c40de7, 0xffe6}, // wonmonospace {0x02dab625, 0x310c}, // lbopomofo {0x02df8edf, 0x30e7}, // yosmallkatakana {0x02e3dfc8, 0x3062}, // dihiragana {0x0306380d, 0xff35}, // Umonospace {0x03170204, 0x0495}, // ghemiddlehookcyrillic {0x03182c9f, 0x25b4}, // blackuppointingsmalltriangle {0x0319d343, 0x329e}, // ideographicprintcircle {0x031ad266, 0x331e}, // kooposquare {0x03274b72, 0x0018}, // controlCAN {0x0334c4d5, 0x0aa7}, // dhagujarati {0x03396436, 0x1ed0}, // Ocircumflexacute {0x033b64c4, 0x047f}, // otcyrillic {0x033e74dc, 0x1e44}, // Ndotaccent {0x034ec8b1, 0x30b0}, // gukatakana {0x037b5e30, 0x00b9}, // onesuperior {0x03993e60, 0xff57}, // wmonospace {0x03a136c3, 0x0e0b}, // sosothai {0x03b0103c, 0x2270}, // notlessnorequal {0x03c2a8d8, 0x1eb3}, // abrevehookabove {0x03d234c7, 0xfea7}, // khahinitialarabic {0x03f4da1a, 0x05b8}, // qamatsnarrowhebrew {0x0410b525, 0x0138}, // kgreenlandic {0x0433eb22, 0x014e}, // Obreve {0x043f3fc5, 0x040a}, // afii10059 {0x044589fe, 0x0646}, // afii57446 {0x044ba421, 0x0585}, // oharmenian {0x0454dddc, 0x0432}, // afii10067 {0x048b164e, 0x01c3}, // clickretroflex {0x048e8b97, 0x0161}, // scaron {0x0491732e, 0x3186}, // yeorinhieuhkorean {0x049c65ac, 0x2121}, // telephone {0x04a45907, 0x041a}, // afii10028 {0x04c4d94b, 0x05b5}, // tsere1e {0x04c8ee7d, 0x042d}, // Ereversedcyrillic {0x04de1db0, 0x0950}, // omdeva {0x04f4d676, 0x0027}, // quotesingle {0x0500f909, 0x0407}, // Yicyrillic {0x0503fcb5, 0x00b1}, // plusminus {0x05116c6a, 0x30fc}, // prolongedkana {0x05302abd, 0x2025}, // twodotleader {0x053ece0c, 0x3050}, // guhiragana {0x05574c05, 0x09a3}, // nnabengali {0x056bac6c, 0x30a3}, // ismallkatakana {0x058218bb, 0x0386}, // Alphatonos {0x058691a9, 0x33d2}, // squarelog {0x059c61cd, 0x0436}, // zhecyrillic {0x059eb4a3, 0x2085}, // fiveinferior {0x05a47299, 0x320d}, // hieuhparenkorean {0x05a53e96, 0x0282}, // shook {0x05b0f8c3, 0x02b5}, // rhookturnedsuperior {0x05cee53c, 0x201d}, // quotedblright {0x05de47fd, 0x1e7f}, // vdotbelow {0x05e340f3, 0x1e70}, // Tcircumflexbelow {0x05e8321d, 0x0325}, // ringbelowcmb {0x05ec5d36, 0x2471}, // eighteencircle {0x05f03fff, 0x0ae0}, // rrvocalicgujarati {0x060beb03, 0x0175}, // wcircumflex {0x061ad8fc, 0x24ca}, // Ucircle {0x0642035b, 0x0010}, // controlDLE {0x0646584a, 0x003d}, // equal {0x064874b1, 0x05d3}, // afii57667 {0x066433cf, 0x20a4}, // lira {0x06823c6b, 0xfb4d}, // kafrafehebrew {0x06894954, 0xff5e}, // asciitildemonospace {0x069a405d, 0x00e6}, // ae {0x06b00ffc, 0x0101}, // amacron {0x06b72f51, 0x27e8}, // angbracketleftbig {0x06be8647, 0x0442}, // afii10084 {0x06ec3366, 0xfe42}, // cornerbracketrightvertical {0x0700a693, 0x0475}, // izhitsacyrillic {0x07019244, 0xfb02}, // fl {0x07072da3, 0x2299}, // circleot {0x07099ef9, 0xfeae}, // rehfinalarabic {0x0710dd39, 0x02de}, // rhotichookmod {0x074aba74, 0x09af}, // yabengali {0x07562010, 0x09bc}, // nuktabengali {0x075a830a, 0x21e6}, // arrowleftwhite {0x076312db, 0x2497}, // sixteenperiod {0x0767cf10, 0x1ea8}, // Acircumflexhookabove {0x076c3b34, 0x1ec3}, // ecircumflexhookabove {0x076dbf41, 0x05b7}, // patah11 {0x07726745, 0x0e25}, // lolingthai {0x078184fa, 0x00f7}, // divide {0x0790751c, 0x2466}, // sevencircle {0x0793d50d, 0x30bb}, // sekatakana {0x07a1ce35, 0x0906}, // aadeva {0x07ab20a8, 0x0ab3}, // llagujarati {0x07e20c30, 0x017b}, // Zdot {0x07e38c67, 0x33bb}, // nwsquare {0x081dd122, 0x0a38}, // sagurmukhi {0x082543e5, 0x33a0}, // cmsquaredsquare {0x083d0b54, 0x3227}, // eightideographicparen {0x08429fa7, 0x2591}, // ltshade {0x084b888b, 0x311a}, // abopomofo {0x085499c4, 0x0925}, // thadeva {0x086a99d9, 0x01af}, // Uhorn {0x087038eb, 0xfb20}, // ayinaltonehebrew {0x089d739a, 0x005a}, // Z {0x08a131c8, 0x096d}, // sevendeva {0x08a6b099, 0x02a6}, // ts {0x08b5de5a, 0x038a}, // Iotatonos {0x08b78f6b, 0xff86}, // nikatakanahalfwidth {0x08d57b6a, 0x0019}, // controlEM {0x08ddb521, 0x3226}, // sevenideographicparen {0x092aa224, 0x0a90}, // aigujarati {0x092cd86d, 0x03d6}, // omega1 {0x09310ab8, 0x027f}, // rfishhookreversed {0x094ceadc, 0x0047}, // G {0x09751504, 0x038c}, // Omicrontonos {0x09790f28, 0x33be}, // kwsquare {0x09853aa3, 0x01c1}, // clicklateral {0x09a03740, 0xfe5b}, // braceleftsmall {0x09a4b050, 0x0ae8}, // twogujarati {0x09d4b5eb, 0x3388}, // calsquare {0x09f2217d, 0x00a9}, // copyright {0x09f9df24, 0x1e0c}, // Ddotbelow {0x0a040d76, 0x098a}, // uubengali {0x0a1d800c, 0x0291}, // zcurl {0x0a3b8eb5, 0x044b}, // yericyrillic {0x0a46f2f1, 0x0284}, // dotlessjstrokehook {0x0a5cb3b1, 0x30d6}, // bukatakana {0x0a5ff1a8, 0xff6b}, // osmallkatakanahalfwidth {0x0a67f8fb, 0x24b2}, // wparen {0x0a704676, 0xfccc}, // lammeeminitialarabic {0x0a8ba8e8, 0x0112}, // Emacron {0x0a9b47dd, 0x306f}, // hahiragana {0x0aa2156d, 0xfc0c}, // tehhahisolatedarabic {0x0abb4ec1, 0x0441}, // afii10083 {0x0adbba15, 0x21c0}, // harpoonrightbarbup {0x0ae79191, 0x01e1}, // adotmacron {0x0af77d49, 0x09ea}, // fourbengali {0x0b367d7a, 0x0421}, // Escyrillic {0x0b4b7082, 0xff62}, // cornerbracketlefthalfwidth {0x0b6abf22, 0x20aa}, // sheqel {0x0b7f2b2d, 0x0a5a}, // ghhagurmukhi {0x0b92d660, 0x32a6}, // ideographiclowcircle {0x0b9e2621, 0x2665}, // heartsuitblack {0x0ba5f00c, 0x03cc}, // omicrontonos {0x0bae12ff, 0xff2a}, // Jmonospace {0x0bd4abb3, 0x0254}, // oopen {0x0bd8d304, 0x3215}, // ieungaparenkorean {0x0bdad647, 0x0970}, // abbreviationsigndeva {0x0bdb550e, 0x0669}, // ninehackarabic {0x0be3cda3, 0x1e0b}, // ddotaccent {0x0bf8ed4a, 0x09f2}, // rupeemarkbengali {0x0bfa9d4e, 0x05b6}, // afii57795 {0x0c138c8e, 0x308f}, // wahiragana {0x0c17017e, 0x02a5}, // dzcurl {0x0c19fd92, 0x037a}, // ypogegrammeni {0x0c255ae5, 0x0553}, // Piwrarmenian {0x0c356707, 0x0625}, // afii57413 {0x0c678de3, 0x032a}, // bridgebelowcmb {0x0c810887, 0x0a88}, // iigujarati {0x0c83c594, 0x1e63}, // sdotbelow {0x0c8f5261, 0x0164}, // Tcaron {0x0cacee48, 0xfba8}, // hehinitialaltonearabic {0x0cbb507c, 0x3036}, // circlepostalmark {0x0cd99820, 0x05c0}, // paseqhebrew {0x0cdb81c4, 0x24a2}, // gparen {0x0ce8bb7e, 0x30d5}, // hukatakana {0x0cf04968, 0x02be}, // ringhalfright {0x0d0eb2f0, 0x315d}, // weokorean {0x0d21bb72, 0x2550}, // SF430000 {0x0d47308f, 0x05d4}, // he {0x0d747cfe, 0x04c3}, // Kahookcyrillic {0x0d932b5b, 0x30d2}, // hikatakana {0x0da4d862, 0x05b6}, // segol13 {0x0db7d6e4, 0x05d4}, // hehebrew {0x0dc03ecb, 0x0a9c}, // jagujarati {0x0dd6f75d, 0x09f6}, // threenumeratorbengali {0x0de664af, 0x01fa}, // Aringacute {0x0deddd7b, 0x017a}, // zacute {0x0df6966e, 0x1e4f}, // otildedieresis {0x0e0870a7, 0x2713}, // checkmark {0x0e0aefc5, 0x05af}, // masoracirclehebrew {0x0e15512a, 0xff43}, // cmonospace {0x0e157c7d, 0x0166}, // Tbar {0x0e34eac4, 0x06ba}, // afii57514 {0x0e359de3, 0x332b}, // paasentosquare {0x0e35e57d, 0x01f4}, // Gacute {0x0e6ec8aa, 0x0a40}, // iimatragurmukhi {0x0e8140cb, 0x2318}, // propellor {0x0e8e8ac7, 0x25aa}, // blacksmallsquare {0x0e8ed92c, 0x05b3}, // hatafqamatsquarterhebrew {0x0e9c1a93, 0x0149}, // quoterightn {0x0eb0ce00, 0xff30}, // Pmonospace {0x0ec7e019, 0xfc4b}, // noonjeemisolatedarabic {0x0ed8b040, 0x33b5}, // nvsquare {0x0edd0c59, 0x0e35}, // saraiithai {0x0ee06289, 0x05b0}, // shevaquarterhebrew {0x0efc1459, 0x09b6}, // shabengali {0x0f02712c, 0x00ea}, // ecircumflex {0x0f066e82, 0x33b3}, // mssquare {0x0f1a6991, 0x24c4}, // Ocircle {0x0f2768b1, 0x05b1}, // hatafsegolwidehebrew {0x0f332d5e, 0x002e}, // period {0x0f35dd15, 0x04b0}, // Ustraightstrokecyrillic {0x0f432338, 0x0020}, // space {0x0f433f21, 0xff7d}, // sukatakanahalfwidth {0x0f610d68, 0x1e53}, // omacronacute {0x0f61debf, 0x33b9}, // mvmegasquare {0x0f8de5e5, 0xff4b}, // kmonospace {0x0f984d6e, 0xfec0}, // dadmedialarabic {0x0fcfb12d, 0x016c}, // Ubreve {0x0fdfc487, 0x02a8}, // tccurl {0x0ff64b0b, 0x0665}, // fivehackarabic {0x1001b5d7, 0xfc48}, // meemmeemisolatedarabic {0x100f790a, 0x20ac}, // Euro {0x101477b7, 0x216a}, // Elevenroman {0x1030f103, 0x0918}, // ghadeva {0x103612b8, 0x2287}, // supersetorequal {0x10459048, 0x2217}, // asteriskmath {0x10529f46, 0x0e59}, // ninethai {0x10656b29, 0x042a}, // afii10044 {0x10659a4d, 0x0041}, // A {0x106ab99c, 0x0943}, // rvocalicvowelsigndeva {0x10827219, 0x01e4}, // Gstroke {0x1087cbb6, 0x318d}, // araeakorean {0x10c49213, 0x094d}, // viramadeva {0x10c6b04c, 0xfee8}, // noonmedialarabic {0x10e1204e, 0x224c}, // allequal {0x1112335e, 0x0e24}, // ruthai {0x1113e9a7, 0x0a87}, // igujarati {0x11140e23, 0xff50}, // pmonospace {0x112533be, 0x0446}, // tsecyrillic {0x1128968b, 0x03dc}, // Digammagreek {0x113f9725, 0x1ea1}, // adotbelow {0x11572f90, 0x3240}, // ideographicfestivalparen {0x1159e298, 0x2484}, // seventeenparen {0x115b5935, 0xff78}, // kukatakanahalfwidth {0x115c3cb2, 0x3179}, // kapyeounssangpieupkorean {0x11672a1e, 0x3051}, // kehiragana {0x1179ac42, 0x00a0}, // nbspace {0x1198b8ba, 0x05f1}, // vavyodhebrew {0x11adf5a7, 0x24a9}, // nparen {0x11aeb63a, 0x2272}, // lessorequivalent {0x11ba40f5, 0x05ea}, // tavhebrew {0x11c11092, 0x1e2c}, // Itildebelow {0x11c8e4b3, 0x2660}, // spadesuitblack {0x11d3eac3, 0x3060}, // dahiragana {0x11d67798, 0xfb33}, // daletdagesh {0x11e401c1, 0x05d6}, // zayin {0x1216fef8, 0x328e}, // ideographmetalcircle {0x1219f723, 0xff6e}, // yosmallkatakanahalfwidth {0x1224d569, 0xfee4}, // meemmedialarabic {0x1228548c, 0x05d0}, // alefhebrew {0x1233afe9, 0x30df}, // mikatakana {0x123a07fe, 0x05e6}, // tsadihebrew {0x1242de49, 0x042b}, // Yericyrillic {0x1246d709, 0x315f}, // wikorean {0x126c42a3, 0x21d0}, // arrowleftdbl {0x1278a8d5, 0x3087}, // yosmallhiragana {0x129b0140, 0x0445}, // afii10087 {0x12a29be8, 0x03c5}, // upsilon {0x12bdd9c7, 0x21a6}, // mapsto {0x12d3e8f7, 0x30c0}, // dakatakana {0x12def4bb, 0xfeba}, // sadfinalarabic {0x12e22bb8, 0x33c2}, // amsquare {0x1329e467, 0x0311}, // breveinvertedcmb {0x132b7bd0, 0x2a04}, // unionmultitext {0x132e0697, 0x01b3}, // Yhook {0x134d9c31, 0x304c}, // gahiragana {0x13597fb3, 0x04d9}, // afii10846 {0x135d6341, 0x33c8}, // dbsquare {0x13635045, 0x0300}, // gravecmb {0x1369554a, 0x207f}, // nsuperior {0x1376f153, 0x0403}, // afii10052 {0x1384d3da, 0x05b4}, // hiriqnarrowhebrew {0x13868087, 0x0636}, // afii57430 {0x138fca68, 0x0a30}, // ragurmukhi {0x13a69297, 0x0917}, // gadeva {0x13bcc567, 0x25d1}, // circlewithrighthalfblack {0x13ccaf5f, 0x3061}, // tihiragana {0x13dc1f9e, 0x05b1}, // hatafsegol {0x13e2dbb5, 0x1e3a}, // Llinebelow {0x140e7a7e, 0x0551}, // Coarmenian {0x14117f5a, 0x1e77}, // ucircumflexbelow {0x141d63ad, 0x1eda}, // Ohornacute {0x142c024d, 0x013a}, // lacute {0x143d707c, 0x05a6}, // merkhakefulalefthebrew {0x146c75cf, 0x3275}, // ieungacirclekorean {0x146f18bb, 0xfb36}, // zayindagesh {0x147a2240, 0x1e81}, // wgrave {0x1486cc9b, 0x054b}, // Jheharmenian {0x14ac715c, 0x2473}, // twentycircle {0x14b421a5, 0x0638}, // zaharabic {0x14c795cf, 0x0051}, // Q {0x14d1cd4b, 0x2284}, // notsubset {0x14d2cd8a, 0x012f}, // iogonek {0x14f2bc91, 0x1eab}, // acircumflextilde {0x15045632, 0x05d1}, // bet {0x1505dc02, 0x3083}, // yasmallhiragana {0x152785c0, 0x30a1}, // asmallkatakana {0x15642935, 0x23a9}, // braceleftbt {0x1564e3f1, 0x05b9}, // holam26 {0x15771621, 0x042c}, // Softsigncyrillic {0x159ac6ab, 0x0591}, // etnahtafoukhlefthebrew {0x159b9dc9, 0x24c6}, // Qcircle {0x15d1c25e, 0x04bf}, // chedescenderabkhasiancyrillic {0x15dd6b0c, 0x25d9}, // whitecircleinverse {0x15f64606, 0x33c5}, // cdsquare {0x15f8ec13, 0x037e}, // questiongreek {0x1602acd3, 0xff38}, // Xmonospace {0x1610c2ad, 0x3181}, // yesieungkorean {0x16393f6d, 0xfef6}, // lamalefmaddaabovefinalarabic {0x164a5cd1, 0x0058}, // X {0x165341dd, 0x02e0}, // gammasuperior {0x167b1fac, 0xfebc}, // sadmedialarabic {0x168b9d05, 0x04d5}, // aiecyrillic {0x169cceb3, 0x005b}, // bracketleft {0x16ad260d, 0x0253}, // bhook {0x16b23c67, 0x3135}, // nieuncieuckorean {0x16ba0a7a, 0x30a9}, // osmallkatakana {0x16d5ac91, 0x3018}, // whitetortoiseshellbracketleft {0x16f9045d, 0x0a16}, // khagurmukhi {0x17093caa, 0x01e3}, // aemacron {0x170fc75c, 0x306c}, // nuhiragana {0x171b516a, 0x0a39}, // hagurmukhi {0x17301afd, 0x3023}, // threehangzhou {0x173c8456, 0x338b}, // nfsquare {0x178d45ae, 0x337e}, // meizierasquare {0x17a9e49b, 0x322a}, // ideographicmoonparen {0x17ad5313, 0x09ab}, // phabengali {0x17da2afa, 0x0335}, // strokeshortoverlaycmb {0x17deda0e, 0x00ed}, // iacute {0x17e36acb, 0x05b8}, // qamats {0x17ef9c62, 0x0a05}, // agurmukhi {0x180419cd, 0xfc62}, // shaddakasraarabic {0x18120be8, 0x200b}, // zerowidthspace {0x18175789, 0x05b3}, // hatafqamatswidehebrew {0x181f5c91, 0x091f}, // ttadeva {0x182bd096, 0x0148}, // ncaron {0x183028bb, 0x04da}, // Schwadieresiscyrillic {0x1840ed9a, 0xfea0}, // jeemmedialarabic {0x18492236, 0x0e5a}, // angkhankhuthai {0x1855a5e3, 0xfe5f}, // numbersignsmall {0x185b816d, 0x0146}, // ncommaaccent {0x187ab455, 0x0e42}, // saraothai {0x1885706c, 0x3157}, // okorean {0x18923bff, 0x2135}, // aleph {0x18a5c10a, 0x2584}, // dnblock {0x18a72a69, 0xfb3a}, // finalkafdageshhebrew {0x18b82c53, 0x045c}, // afii10109 {0x18c46fec, 0x033c}, // seagullbelowcmb {0x18d47bfd, 0x3298}, // ideographiclaborcircle {0x18dbddd2, 0x0993}, // obengali {0x18df8652, 0x2286}, // subsetorequal {0x18ea53c7, 0x0663}, // afii57395 {0x18ec3f78, 0x05e8}, // afii57688 {0x18f0d507, 0xfe9f}, // jeeminitialarabic {0x190a56aa, 0xfe5a}, // parenrightsmall {0x1920c2c2, 0xff65}, // middledotkatakanahalfwidth {0x192c8826, 0x2283}, // superset {0x1940b4fd, 0x2251}, // geometricallyequal {0x19427103, 0x2a01}, // circleplustext {0x1946a31f, 0x05ae}, // zinorhebrew {0x194ec3dd, 0xfb38}, // tetdageshhebrew {0x195fdeed, 0x3013}, // getamark {0x197f461f, 0x1e03}, // bdotaccent {0x1994a487, 0x0481}, // koppacyrillic {0x19985117, 0x339a}, // nmsquare {0x19a1a98b, 0x00ad}, // sfthyphen {0x19ad4aac, 0xfef2}, // yehfinalarabic {0x19b22272, 0x3269}, // chieuchcirclekorean {0x19b344e4, 0x0123}, // gcedilla {0x19b3f208, 0x05b8}, // qamats27 {0x19d833fe, 0x02ba}, // dblprimemod {0x19dea593, 0x0428}, // afii10042 {0x19f7c320, 0x04d1}, // abrevecyrillic {0x19fa29b1, 0x327f}, // koreanstandardsymbol {0x1a00d3da, 0x032b}, // dblarchinvertedbelowcmb {0x1a260946, 0x0447}, // checyrillic {0x1a287ed9, 0x0922}, // ddhadeva {0x1a3b33cb, 0xfed7}, // qafinitialarabic {0x1a3bf649, 0x05b2}, // hatafpatahhebrew {0x1a4f3484, 0x0913}, // odeva {0x1a533d39, 0x0306}, // brevecmb {0x1ac76244, 0x0425}, // Khacyrillic {0x1ac90440, 0x010f}, // dcaron {0x1b240a74, 0x00d8}, // Oslash {0x1b2b4015, 0xfe65}, // greatersmall {0x1b33167a, 0xfe3e}, // dblanglebracketrightvertical {0x1b342691, 0x017c}, // zdot {0x1b39339b, 0x253c}, // SF050000 {0x1b3f9c21, 0x1e72}, // Udieresisbelow {0x1b4399b2, 0x04c7}, // Enhookcyrillic {0x1b5874ea, 0x091b}, // chadeva {0x1b8c8992, 0x2122}, // trademark {0x1ba72293, 0xff03}, // numbersignmonospace {0x1bbb8fb3, 0x0477}, // izhitsadblgravecyrillic {0x1bcb2bfd, 0x337d}, // taisyouerasquare {0x1be98812, 0x24d4}, // ecircle {0x1c079308, 0x09cc}, // auvowelsignbengali {0x1c16ebae, 0x0126}, // Hbar {0x1c2631dd, 0x3385}, // KBsquare {0x1c56e166, 0xfd3f}, // parenrightaltonearabic {0x1c94529b, 0x21b5}, // carriagereturn {0x1cb10674, 0x0a27}, // dhagurmukhi {0x1cb5367a, 0x0532}, // Benarmenian {0x1cdb3e05, 0x2514}, // SF020000 {0x1ce17c08, 0xfea6}, // khahfinalarabic {0x1ce29209, 0x02cc}, // verticallinelowmod {0x1ce40996, 0xff3b}, // bracketleftmonospace {0x1cf31612, 0x0598}, // zarqahebrew {0x1d2559c8, 0x03b9}, // iota {0x1d25e3ef, 0x043c}, // emcyrillic {0x1d420ccb, 0x0430}, // afii10065 {0x1d954d85, 0x09a4}, // tabengali {0x1da7ae8c, 0x00d7}, // multiply {0x1db92094, 0x053d}, // Xeharmenian {0x1dbbea92, 0x02e6}, // tonebarhighmod {0x1dbc2a14, 0x2245}, // congruent {0x1dbe86c5, 0x246d}, // fourteencircle {0x1dc0644e, 0x2012}, // figuredash {0x1ded853e, 0x01cc}, // nj {0x1df7638a, 0x00e4}, // adieresis {0x1dfc2837, 0x217a}, // elevenroman {0x1e0312fa, 0x0290}, // zretroflexhook {0x1e1332fd, 0x0287}, // tturned {0x1e25355a, 0x0461}, // omegacyrillic {0x1e38c8d8, 0x012a}, // Imacron {0x1e56afb4, 0xfc61}, // shaddadammaarabic {0x1e645fd0, 0x00b2}, // twosuperior {0x1e6cddcb, 0x0563}, // gimarmenian {0x1e7c9862, 0x338f}, // squarekg {0x1e82a7c3, 0x2302}, // house {0x1e860782, 0x0983}, // visargabengali {0x1e917582, 0x09a2}, // ddhabengali {0x1ea7d113, 0x031c}, // ringhalfleftbelowcmb {0x1eae034a, 0x3122}, // anbopomofo {0x1eae1716, 0x0434}, // afii10069 {0x1edf9913, 0x1e16}, // Emacronacute {0x1ef123d5, 0x0413}, // Gecyrillic {0x1f06ae25, 0xfb31}, // betdageshhebrew {0x1f1df6d1, 0x3381}, // nasquare {0x1f2383d4, 0x0004}, // controlEOT {0x1f2a4214, 0xfdfa}, // sallallahoualayhewasallamarabic {0x1f60dad4, 0x05e8}, // reshhebrew {0x1f686fbe, 0xff2c}, // Lmonospace {0x1f90aeb4, 0xff7b}, // sakatakanahalfwidth {0x1f93ce2b, 0xff33}, // Smonospace {0x1f9b52d4, 0x0323}, // dotbelowcmb {0x1faa2fdf, 0x203e}, // overline {0x1faf20cc, 0x02b9}, // primemod {0x1fba9d24, 0x1e4a}, // Ncircumflexbelow {0x1fc00e7e, 0x0050}, // P {0x1fc99492, 0x3126}, // erbopomofo {0x1feea4ab, 0x0623}, // afii57411 {0x20061138, 0x1e02}, // Bdotaccent {0x200e9513, 0x030f}, // dblgravecmb {0x201a6676, 0x2310}, // logicalnotreversed {0x201e3ee9, 0x0310}, // candrabinducmb {0x2024cfd1, 0x0475}, // afii10196 {0x2038e6d5, 0x307a}, // pehiragana {0x205d0ec7, 0x03a0}, // Pi {0x207bf81e, 0xff84}, // tokatakanahalfwidth {0x2086c569, 0x00d2}, // Ograve {0x208b3b40, 0xfed0}, // ghainmedialarabic {0x209bfca6, 0x24d5}, // fcircle {0x20a31ebd, 0x2489}, // twoperiod {0x20abefc1, 0x0385}, // dialytikatonos {0x20b8cfa5, 0x0443}, // afii10085 {0x20bc528f, 0x2042}, // asterism {0x20ca67b9, 0x09a1}, // ddabengali {0x20ce09b9, 0xfb7b}, // tchehfinalarabic {0x20dd36ea, 0x207e}, // parenrightsuperior {0x20e840a0, 0x30d4}, // pikatakana {0x2111e869, 0x092a}, // padeva {0x21185c0e, 0x028e}, // yturned {0x2130f98f, 0x0aa0}, // tthagujarati {0x215fc096, 0x000d}, // controlCR {0x21622652, 0x249e}, // cparen {0x21669982, 0x0181}, // Bhook {0x217143de, 0x05b3}, // hatafqamats34 {0x2173a28b, 0x0295}, // glottalstopreversed {0x218d5b62, 0x3232}, // ideographichaveparen {0x21b37808, 0x2477}, // fourparen {0x21bef9d7, 0x0e06}, // khorakhangthai {0x21c0f31f, 0x013b}, // Lcommaaccent {0x21ce0071, 0x2179}, // tenroman {0x21d28f9e, 0x05e9}, // shin {0x21f74f30, 0x043e}, // afii10080 {0x2203033d, 0x019d}, // Nhookleft {0x22037801, 0x044b}, // afii10093 {0x220f1331, 0x05db}, // kafhebrew {0x2221c36b, 0x06f6}, // sixpersian {0x22351581, 0x059f}, // qarneyparahebrew {0x223cb30f, 0xfc9f}, // behmeeminitialarabic {0x225099c3, 0x3149}, // ssangcieuckorean {0x22542ce4, 0x2207}, // nabla {0x22702420, 0x3153}, // eokorean {0x2274db8f, 0xff08}, // parenleftmonospace {0x2282e86d, 0x00fa}, // uacute {0x22a883d2, 0x25c7}, // whitediamond {0x22c93a2b, 0x338d}, // mugsquare {0x22e3ac9e, 0xff4c}, // lmonospace {0x2320c842, 0x0277}, // omegalatinclosed {0x2324e69c, 0x2665}, // heart {0x2351e945, 0x0a8a}, // uugujarati {0x2356706f, 0x0541}, // Jaarmenian {0x23679572, 0x1ef1}, // uhorndotbelow {0x236d79e4, 0x301e}, // quotedblprime {0x237979f3, 0xff73}, // ukatakanahalfwidth {0x23947e9f, 0x0266}, // hhook {0x23b6327c, 0x304f}, // kuhiragana {0x23b9408d, 0x2208}, // element {0x23d291f5, 0x0639}, // ainarabic {0x23d42e51, 0xff0b}, // plusmonospace {0x23e15f1c, 0xff90}, // mikatakanahalfwidth {0x23e70b3f, 0x0664}, // afii57396 {0x23e9f46b, 0xff80}, // takatakanahalfwidth {0x23ea33c4, 0x30f1}, // wekatakana {0x23f0f542, 0xff2f}, // Omonospace {0x2415f58f, 0x3069}, // dohiragana {0x2419b09a, 0x038f}, // Omegatonos {0x241b0583, 0x0a9e}, // nyagujarati {0x241f6494, 0x3105}, // bbopomofo {0x2459d6f7, 0x0aea}, // fourgujarati {0x24688db0, 0x02c1}, // glottalstopreversedmod {0x24776c38, 0x0343}, // koroniscmb {0x2479e0d2, 0x3021}, // onehangzhou {0x249dd6ee, 0x0665}, // afii57397 {0x24c0efcc, 0x316d}, // rieulyeorinhieuhkorean {0x24ccbd1b, 0x09e6}, // zerobengali {0x24d11d48, 0x02c2}, // arrowheadleftmod {0x24d6b19b, 0xfee7}, // nooninitialarabic {0x24deab24, 0x25a4}, // squarehorizontalfill {0x24e9b4e5, 0x21e4}, // arrowtableft {0x24f5be18, 0x0308}, // dieresiscmb {0x2527d2da, 0x300c}, // cornerbracketleft {0x252ef6ac, 0x01de}, // Adieresismacron {0x253f33be, 0x006e}, // n {0x2543ce81, 0x05c1}, // shindothebrew {0x254b8857, 0x0929}, // nnnadeva {0x25725d01, 0x0496}, // Zhedescendercyrillic {0x2592eb8c, 0x1e39}, // ldotbelowmacron {0x25a29a9e, 0x000a}, // controlLF {0x25bfabf1, 0x056c}, // liwnarmenian {0x25c22a8d, 0x0927}, // dhadeva {0x25c3f8ae, 0xff3e}, // asciicircummonospace {0x25ca4638, 0x0576}, // nowarmenian {0x25d83051, 0x0e19}, // nonuthai {0x25e64388, 0x1ee5}, // udotbelow {0x25eb8755, 0xff34}, // Tmonospace {0x25ef68be, 0x0103}, // abreve {0x25f0117e, 0x095f}, // yyadeva {0x2614c40e, 0x0aaf}, // yagujarati {0x262be20f, 0x0471}, // psicyrillic {0x2637caf5, 0x0932}, // ladeva {0x263e0b92, 0x09ac}, // babengali {0x2652690c, 0x3137}, // tikeutkorean {0x265be8ad, 0x01cf}, // Icaron {0x265fdad4, 0x05b8}, // qamatshebrew {0x26621b4d, 0x0072}, // r {0x2669a6cb, 0x211c}, // Rfraktur {0x26837556, 0x0048}, // H {0x26a72a71, 0x3188}, // yoyaekorean {0x26ab6d3a, 0x1ed9}, // ocircumflexdotbelow {0x26af8089, 0x304e}, // gihiragana {0x26b9c1d9, 0x0e30}, // saraathai {0x26c43ea8, 0x0911}, // ocandradeva {0x26caa803, 0x21d4}, // arrowdblboth {0x26cb382e, 0x23ab}, // bracerighttp {0x26f6f992, 0x04e4}, // Idieresiscyrillic {0x26fb496b, 0x3351}, // rittorusquare {0x27075678, 0x012e}, // Iogonek {0x2731451f, 0x0408}, // afii10057 {0x273977ae, 0x0435}, // afii10070 {0x27487450, 0x007e}, // asciitilde {0x275654ea, 0x099b}, // chabengali {0x275a3e46, 0x09a0}, // tthabengali {0x275a5b3b, 0x1ee1}, // ohorntilde {0x27607db6, 0x05b4}, // hiriq2d {0x27a2d18f, 0x05b9}, // holam32 {0x27b7bf17, 0x031f}, // plusbelowcmb {0x27b7cc70, 0xfb2d}, // shindageshsindothebrew {0x27d62d65, 0x200d}, // afii301 {0x27d8dd28, 0x00e8}, // egrave {0x27e6d9df, 0x0271}, // mhook {0x27f31ec3, 0x3271}, // rieulacirclekorean {0x283f3216, 0x2075}, // fivesuperior {0x28898020, 0x0281}, // Rsmallinverted {0x288edd59, 0x24cc}, // Wcircle {0x28d9fe2f, 0x0e41}, // saraaethai {0x28dd4931, 0x3234}, // ideographicnameparen {0x28e31924, 0x0a6c}, // sixgurmukhi {0x28e4057d, 0xfc58}, // yehmeemisolatedarabic {0x28f71acd, 0x0633}, // afii57427 {0x290ed42e, 0x1e18}, // Ecircumflexbelow {0x29287ce1, 0x03d2}, // Upsilon1 {0x29346ac3, 0x2021}, // daggerdbl {0x29371ded, 0x1e8f}, // ydotaccent {0x29734fd7, 0x092d}, // bhadeva {0x298e1b46, 0x01ea}, // Oogonek {0x29958ce9, 0x0005}, // controlENQ {0x29a8f130, 0x04d4}, // Aiecyrillic {0x29ab0eda, 0x0146}, // ncedilla {0x29c07bd0, 0x305e}, // zohiragana {0x29d0597d, 0x262f}, // yinyang {0x29d51dd2, 0x06d1}, // yehthreedotsbelowarabic {0x29d5f944, 0x03e4}, // Feicoptic {0x29e31b8f, 0x05b1}, // hatafsegolhebrew {0x29e6e487, 0x30cc}, // nukatakana {0x29e7f6bb, 0x0035}, // five {0x2a0fca4c, 0x3085}, // yusmallhiragana {0x2a239937, 0x0375}, // numeralsignlowergreek {0x2a28d54e, 0x30aa}, // okatakana {0x2a619f09, 0x2660}, // spade {0x2a645de3, 0x3091}, // wehiragana {0x2a64e363, 0x226e}, // notless {0x2a6a5dc5, 0x3088}, // yohiragana {0x2a72414c, 0x0e44}, // saraaimaimalaithai {0x2a8e7779, 0x0ad0}, // omgujarati {0x2ac0e180, 0x33a6}, // kmcubedsquare {0x2ac17d0f, 0x00f3}, // oacute {0x2ae749c7, 0x00e1}, // aacute {0x2ae8215f, 0x001d}, // controlGS {0x2ae8c5a6, 0x21c4}, // arrowrightoverleft {0x2aedcd2c, 0x09fa}, // issharbengali {0x2afb134c, 0xfb03}, // ffi {0x2b27655e, 0x261c}, // pointingindexleftwhite {0x2b3ff353, 0x2557}, // SF250000 {0x2b42ad49, 0xfe55}, // colonsmall {0x2b5ac1a6, 0x0045}, // E {0x2b84f841, 0x30a6}, // ukatakana {0x2b91651d, 0x0319}, // righttackbelowcmb {0x2b93dd53, 0x0661}, // afii57393 {0x2b9750e3, 0x2200}, // universal {0x2b9c968a, 0x0315}, // commaaboverightcmb {0x2bb5189c, 0x25e3}, // blacklowerlefttriangle {0x2bd253b1, 0x09bf}, // ivowelsignbengali {0x2be6415c, 0x05b3}, // hatafqamatshebrew {0x2beb7c62, 0x013c}, // lcommaaccent {0x2c0f9c0b, 0x0912}, // oshortdeva {0x2c15e9f4, 0x091c}, // jadeva {0x2c1b74f9, 0x2262}, // notidentical {0x2c4944e4, 0x0393}, // Gamma {0x2c91b61a, 0x0640}, // kashidaautonosidebearingarabic {0x2c964b66, 0x334a}, // miribaarusquare {0x2cb17e35, 0xfec6}, // zahfinalarabic {0x2cd9d9ec, 0xfc6d}, // behnoonfinalarabic {0x2cdfcd2a, 0x30cb}, // nikatakana {0x2cf9daf5, 0x3228}, // nineideographicparen {0x2d2e3883, 0x2190}, // arrowleft {0x2d329c65, 0xfb3c}, // lameddageshhebrew {0x2d39ea69, 0x019e}, // nlegrightlong {0x2d3b565d, 0x05ea}, // afii57690 {0x2d456f79, 0x25e2}, // blacklowerrighttriangle {0x2d52bd2b, 0x3326}, // dorusquare {0x2d84140a, 0x0293}, // ezhcurl {0x2d8d5b1d, 0x33d0}, // lmsquare {0x2d95d169, 0x3155}, // yeokorean {0x2d975eca, 0xfb04}, // ffl {0x2d9ae85a, 0x0661}, // onehackarabic {0x2d9b14ff, 0xfb6d}, // vehmedialarabic {0x2da2ea79, 0x313d}, // rieulsioskorean {0x2daa1b6f, 0x090a}, // uudeva {0x2e04353d, 0x1ea9}, // acircumflexhookabove {0x2e043b05, 0xff0a}, // asteriskmonospace {0x2e10a2b1, 0x0374}, // numeralsigngreek {0x2e1eaa7d, 0xfb49}, // shindagesh {0x2e2c25c0, 0x0392}, // Beta {0x2e356485, 0x09c2}, // uuvowelsignbengali {0x2e4224af, 0x05e4}, // afii57684 {0x2e5e0023, 0x0a20}, // tthagurmukhi {0x2e647759, 0x33d6}, // molsquare {0x2e7c6436, 0x3048}, // ehiragana {0x2e915a9d, 0xfe3b}, // blacklenticularbracketleftvertical {0x2e9e14a6, 0x0454}, // ecyrillic {0x2e9ef541, 0x0192}, // florin {0x2ea8b970, 0x327a}, // phieuphacirclekorean {0x2eb22aa1, 0x01dc}, // udieresisgrave {0x2eb3bdc7, 0x027e}, // rfishhook {0x2eb455b0, 0x25b6}, // blackrightpointingtriangle {0x2ec430ea, 0x0078}, // x {0x2ec8352a, 0x0143}, // Nacute {0x2eea1838, 0x0170}, // Uhungarumlaut {0x2efaa14d, 0x3015}, // tortoiseshellbracketright {0x2f06c380, 0x0a91}, // ocandragujarati {0x2f0e722f, 0x0021}, // exclam {0x2f14e4ad, 0x0183}, // btopbar {0x2f22b335, 0x305f}, // tahiragana {0x2f247a45, 0x00b5}, // mu {0x2f42e9c9, 0x0405}, // afii10054 {0x2f4b01e9, 0x03e0}, // Sampigreek {0x2f51a2a5, 0x0591}, // etnahtahebrew {0x2f5af1cc, 0xfec4}, // tahmedialarabic {0x2f5c74c9, 0x30a4}, // ikatakana {0x2f5e2692, 0x033f}, // dbloverlinecmb {0x2f7e3ce0, 0xfb35}, // vavdagesh65 {0x2f7fe7da, 0x04ea}, // Obarreddieresiscyrillic {0x2f8f84ed, 0x3019}, // whitetortoiseshellbracketright {0x2f9c7ff4, 0x221f}, // orthogonal {0x2fa13b0c, 0x0309}, // hookcmb {0x2fa6d960, 0x0e05}, // khokhonthai {0x2fb88e89, 0x0492}, // Ghestrokecyrillic {0x2fe066dc, 0x24c8}, // Scircle {0x2ff9eee3, 0x3231}, // ideographicstockparen {0x30132e73, 0x2474}, // oneparen {0x302d72c2, 0xfb2b}, // shinsindothebrew {0x3033e257, 0x0416}, // Zhecyrillic {0x3034a6d0, 0x0213}, // rinvertedbreve {0x3043436d, 0x0208}, // Idblgrave {0x3046485b, 0x0a41}, // umatragurmukhi {0x30585e10, 0x0631}, // reharabic {0x305b2089, 0x006d}, // m {0x305dc9d7, 0x2480}, // thirteenparen {0x3097f64c, 0x010c}, // Ccaron {0x30b4b18c, 0x0e28}, // sosalathai {0x30c0161e, 0x01d3}, // Ucaron {0x30c9bc6e, 0x0a1e}, // nyagurmukhi {0x30cd38cb, 0x33d8}, // pmsquare {0x30d25d42, 0x2089}, // nineinferior {0x30eada85, 0x2219}, // bulletoperator {0x30f64fef, 0x20aa}, // sheqelhebrew {0x310a4774, 0x337f}, // corporationsquare {0x31158bc3, 0x339f}, // mmsquaredsquare {0x3116a838, 0x0647}, // heharabic {0x312db4ff, 0x2040}, // tie {0x313237dd, 0xff32}, // Rmonospace {0x313f3c20, 0x09df}, // yyabengali {0x3154a912, 0x04ab}, // esdescendercyrillic {0x31f1489a, 0x0643}, // afii57443 {0x31f928de, 0x05df}, // finalnun {0x31fab77d, 0x1eea}, // Uhorngrave {0x3207407e, 0x046b}, // yusbigcyrillic {0x3238fa28, 0x3004}, // jis {0x323ea229, 0x33ac}, // gpasquare {0x324496b3, 0x33bf}, // mwmegasquare {0x3248fa12, 0xfe5e}, // tortoiseshellbracketrightsmall {0x324bc39e, 0x22da}, // lessequalorgreater {0x3266451e, 0x30f2}, // wokatakana {0x326ca1fd, 0x013f}, // Ldot {0x32930f95, 0x046f}, // ksicyrillic {0x329a975f, 0x0a0a}, // uugurmukhi {0x329ed55c, 0x04e1}, // dzeabkhasiancyrillic {0x32d855b8, 0x0ae9}, // threegujarati {0x32e77f07, 0x22c2}, // intersectiontext {0x32fd46a7, 0x041e}, // afii10032 {0x32fe41c6, 0x0667}, // afii57399 {0x330263f2, 0x3136}, // nieunhieuhkorean {0x3303dbcb, 0x04b2}, // Hadescendercyrillic {0x33042de7, 0x1e90}, // Zcircumflex {0x335e3259, 0x3022}, // twohangzhou {0x336106b8, 0x05d7}, // afii57671 {0x33821f87, 0x05e2}, // ayinhebrew {0x33849fcd, 0x304d}, // kihiragana {0x339cb29c, 0x03cb}, // upsilondieresis {0x339dfd30, 0x2200}, // forall {0x33a4598f, 0x0e10}, // thothanthai {0x33dd39ff, 0x0437}, // zecyrillic {0x33ea63c8, 0x24df}, // pcircle {0x33f59002, 0x0285}, // eshsquatreversed {0x340746a2, 0xff4a}, // jmonospace {0x3425ba3a, 0x056d}, // xeharmenian {0x342d52b5, 0x25cb}, // whitecircle {0x34399add, 0x0034}, // four {0x343b0ff5, 0x1e8b}, // xdotaccent {0x343f59f3, 0x0437}, // afii10073 {0x344b950b, 0x031d}, // uptackbelowcmb {0x34515ec0, 0x01ca}, // NJ {0x345791f2, 0x027c}, // rlongleg {0x346086da, 0x2286}, // reflexsubset {0x3463147c, 0x1e69}, // sdotbelowdotaccent {0x3490ad97, 0x047a}, // Omegaroundcyrillic {0x34a7b989, 0x006f}, // o {0x34a88183, 0x2640}, // female {0x34b5f401, 0x016a}, // Umacron {0x34bab99c, 0x24e0}, // qcircle {0x34c88fb4, 0x2312}, // arc {0x34c908a5, 0x1eb4}, // Abrevetilde {0x34df3d1c, 0x00a1}, // exclamdown {0x34e969fb, 0x05a0}, // telishagedolahebrew {0x34f9cd37, 0x010b}, // cdot {0x35188ac4, 0xfeac}, // thalfinalarabic {0x351bf85e, 0x0257}, // dhook {0x351e7136, 0x0482}, // thousandcyrillic {0x352bce90, 0x00a3}, // sterling {0x35378756, 0x2591}, // shadelight {0x35440d94, 0x040c}, // Kjecyrillic {0x354dad21, 0x0129}, // itilde {0x35514624, 0x00d6}, // Odieresis {0x3596098d, 0xfb9f}, // noonghunnafinalarabic {0x359e9c03, 0x0418}, // Iicyrillic {0x359f6846, 0x1ebc}, // Etilde {0x35a9ba78, 0x0a95}, // kagujarati {0x35b65af3, 0x33af}, // radoverssquaredsquare {0x35ce2a2d, 0x066a}, // afii57381 {0x35ddec6f, 0x00eb}, // edieresis {0x35e5fe3b, 0x3118}, // cbopomofo {0x3613bad2, 0x011b}, // ecaron {0x361cb4c9, 0xfb6b}, // vehfinalarabic {0x361e70b8, 0x0043}, // C {0x362459fb, 0xfe97}, // tehinitialarabic {0x362c9d3a, 0x02b0}, // hsuperior {0x36678fdf, 0x2326}, // deleteright {0x3676afc0, 0x0ac9}, // ocandravowelsigngujarati {0x368bf72e, 0x0038}, // eight {0x36aaad0e, 0x307b}, // hohiragana {0x36d3bc14, 0x0491}, // afii10098 {0x36d54fb7, 0x015a}, // Sacute {0x37117bac, 0x059b}, // tevirlefthebrew {0x372986de, 0x05f3}, // gereshhebrew {0x373e5e3f, 0xff27}, // Gmonospace {0x37866f5c, 0x00df}, // germandbls {0x37a73b5a, 0xfee0}, // lammedialarabic {0x37a77cc1, 0x030b}, // hungarumlautcmb {0x37b36429, 0xff68}, // ismallkatakanahalfwidth {0x37b7557e, 0x001c}, // controlFS {0x37c2175b, 0xfcca}, // lamhahinitialarabic {0x37c23820, 0x24c5}, // Pcircle {0x37d669b4, 0x090e}, // eshortdeva {0x37e460db, 0x308d}, // rohiragana {0x37e5061e, 0x04a3}, // endescendercyrillic {0x37f67ca7, 0x029a}, // eopenclosed {0x381040c4, 0x310d}, // gbopomofo {0x381640e0, 0xffe3}, // macronmonospace {0x381c7e4d, 0x1ece}, // Ohookabove {0x38201bde, 0x0961}, // llvocalicdeva {0x38291591, 0x0e2e}, // honokhukthai {0x3839681b, 0x3055}, // sahiragana {0x3863c9a6, 0x208e}, // parenrightinferior {0x386cda71, 0x01f0}, // jcaron {0x38746563, 0x01b0}, // uhorn {0x38880d1d, 0x0198}, // Khook {0x38885f68, 0x091d}, // jhadeva {0x388ccfdd, 0x30e3}, // yasmallkatakana {0x3896be1c, 0x0025}, // percent {0x38a80af1, 0x306d}, // nehiragana {0x38bcbef5, 0x05b7}, // afii57798 {0x38bebcf5, 0x2552}, // SF510000 {0x38ce8c39, 0x059a}, // yetivhebrew {0x38cea50a, 0x24d6}, // gcircle {0x38d9b559, 0x3003}, // dittomark {0x38de4662, 0x1e7c}, // Vtilde {0x38e73ed2, 0x01c0}, // clickdental {0x38efc9e4, 0x04a6}, // Pemiddlehookcyrillic {0x391e728b, 0x099a}, // cabengali {0x392c00af, 0x3305}, // intisquare {0x3934b5de, 0x0e43}, // saraaimaimuanthai {0x3946429a, 0x3010}, // blacklenticularbracketleft {0x396642a3, 0x322d}, // ideographicwoodparen {0x396b44dd, 0x0a3c}, // nuktagurmukhi {0x396d8b52, 0x0930}, // radeva {0x3989511a, 0xfc5e}, // shaddadammatanarabic {0x39918d40, 0x30b6}, // zakatakana {0x399ac15a, 0x0283}, // esh {0x39aa6d90, 0x0a83}, // visargagujarati {0x39b06752, 0x004a}, // J {0x39d0b19b, 0x00ae}, // registered {0x39d5a1b1, 0x019c}, // Mturned {0x39e226d5, 0x05e3}, // afii57683 {0x39f864d5, 0x2462}, // threecircle {0x39fd88e8, 0x05a8}, // qadmahebrew {0x3a029acd, 0x338e}, // squaremg {0x3a0e66b8, 0x1ee6}, // Uhookabove {0x3a1089b2, 0x0073}, // s {0x3a3b69ae, 0x317c}, // siostikeutkorean {0x3a3c0e00, 0xff9d}, // nkatakanahalfwidth {0x3a40856d, 0x25a0}, // blacksquare {0x3a7498f3, 0x05e2}, // ayin {0x3a777405, 0x0945}, // ecandravowelsigndeva {0x3a846086, 0xff9c}, // wakatakanahalfwidth {0x3aa3cfcb, 0x0960}, // rrvocalicdeva {0x3ab26d21, 0x062f}, // dalarabic {0x3ade6670, 0x0440}, // afii10082 {0x3afe4407, 0x25a9}, // squarediagonalcrosshatchfill {0x3b0367b4, 0x0a6b}, // fivegurmukhi {0x3b43910b, 0x0e36}, // sarauethai {0x3b4774fb, 0xfb35}, // vavdageshhebrew {0x3b6394a8, 0x30e0}, // mukatakana {0x3b722aff, 0x02bf}, // ringhalfleft {0x3b86faf7, 0x1e31}, // kacute {0x3b8c9510, 0x0926}, // dadeva {0x3b8f536a, 0x0564}, // daarmenian {0x3b919910, 0x02b4}, // rturnedsuperior {0x3b92b9ea, 0x1e4b}, // ncircumflexbelow {0x3b9a0136, 0x2468}, // ninecircle {0x3b9a26e8, 0x0637}, // taharabic {0x3bf4dcc7, 0xfea3}, // hahinitialarabic {0x3bf5a3f3, 0x301d}, // quotedblprimereversed {0x3c2679f3, 0x25c3}, // whiteleftpointingsmalltriangle {0x3c4101c7, 0x0a2b}, // phagurmukhi {0x3c47c401, 0x0196}, // Iotaafrican {0x3c5c7654, 0x0910}, // aideva {0x3c6261b4, 0x322e}, // ideographicmetalparen {0x3c6e58f4, 0x05d5}, // vavhebrew {0x3c89c6b7, 0x2192}, // arrowright {0x3c9425ca, 0x0666}, // sixhackarabic {0x3c9b6897, 0xff0e}, // periodmonospace {0x3ca31461, 0x01d1}, // Ocaron {0x3ca4227b, 0x0120}, // Gdot {0x3ca9c5ab, 0x0345}, // ypogegrammenigreekcmb {0x3cb5e1bf, 0x3146}, // ssangsioskorean {0x3cb6098f, 0x25b9}, // whiterightpointingsmalltriangle {0x3ccd3832, 0xfc60}, // shaddafathaarabic {0x3cfd6c60, 0x305a}, // zuhiragana {0x3cfe2d05, 0x018f}, // Schwa {0x3d0581a8, 0x313c}, // rieulpieupkorean {0x3d200141, 0x30c9}, // dokatakana {0x3d25bc32, 0x2116}, // numero {0x3d292466, 0x05b1}, // hatafsegol17 {0x3d30abad, 0x0279}, // rturned {0x3d3a35a3, 0x0252}, // ascriptturned {0x3d3c2f4b, 0x309d}, // iterationhiragana {0x3d44ad12, 0x3210}, // tikeutaparenkorean {0x3d4a2f11, 0x0187}, // Chook {0x3d50ceda, 0x21a8}, // arrowupdnbse {0x3d59a63c, 0x30e2}, // mokatakana {0x3d6d45f8, 0x0688}, // ddalarabic {0x3d794ead, 0x04c8}, // enhookcyrillic {0x3d888246, 0x300d}, // cornerbracketright {0x3d93ad95, 0x0171}, // uhungarumlaut {0x3d987773, 0x03c6}, // phi {0x3da1e076, 0xfb2a}, // shinshindot {0x3da24bf2, 0x004d}, // M {0x3da45134, 0xff3d}, // bracketrightmonospace {0x3dac6cb7, 0x212e}, // estimated {0x3db24f7f, 0x04eb}, // obarreddieresiscyrillic {0x3ddbfa17, 0xfe64}, // lesssmall {0x3de84dee, 0x3387}, // GBsquare {0x3de8cd4d, 0x02c9}, // firsttonechinese {0x3deb36dc, 0x0570}, // hoarmenian {0x3e08b864, 0x1e1c}, // Ecedillabreve {0x3e2966c3, 0x25a7}, // squareupperlefttolowerrightfill {0x3e2ad069, 0x0125}, // hcircumflex {0x3e2b18e7, 0x05d2}, // gimelhebrew {0x3e2ddf1a, 0x00fb}, // ucircumflex {0x3e4b0d7f, 0x2478}, // fiveparen {0x3e5c6b2e, 0x2086}, // sixinferior {0x3e78c213, 0x03f3}, // yotgreek {0x3e7bef16, 0x063a}, // ghainarabic {0x3e9c0cab, 0x0e0d}, // yoyingthai {0x3ea9e6c5, 0x044e}, // afii10096 {0x3ec30c4d, 0x0168}, // Utilde {0x3ed6d505, 0x3108}, // fbopomofo {0x3edc9801, 0x031e}, // downtackbelowcmb {0x3edf2653, 0x04ba}, // Shhacyrillic {0x3edfbd48, 0x0959}, // khhadeva {0x3ee5a28f, 0x0342}, // perispomenigreekcmb {0x3ef2c5ca, 0x05df}, // finalnunhebrew {0x3efcef55, 0x09a7}, // dhabengali {0x3f19d4d4, 0x30e5}, // yusmallkatakana {0x3f35ecb4, 0x0a0f}, // eegurmukhi {0x3f36dce9, 0x061b}, // afii57403 {0x3f5ead94, 0x0456}, // icyrillic {0x3f61f37a, 0x1ea3}, // ahookabove {0x3f76f3d1, 0x0214}, // Udblgrave {0x3f817391, 0x314b}, // khieukhkorean {0x3f8b0c34, 0x30c7}, // dekatakana {0x3fa4349b, 0x0e1d}, // fofathai {0x3fa5f151, 0x03de}, // Koppagreek {0x3fbf7ccb, 0x01ae}, // Tretroflexhook {0x3fddfa91, 0x22ce}, // curlyor {0x3fe060fb, 0x0147}, // Ncaron {0x3fe534eb, 0x0e12}, // thophuthaothai {0x4016947c, 0x246b}, // twelvecircle {0x401a74d3, 0x06f3}, // threepersian {0x40663d0c, 0xfeb2}, // seenfinalarabic {0x4069b3b1, 0x24ab}, // pparen {0x407a7b83, 0x0531}, // Aybarmenian {0x407de2ef, 0x06d5}, // afii57534 {0x40882350, 0x0305}, // overlinecmb {0x4096d7d2, 0x006a}, // j {0x409d1b5a, 0xff97}, // rakatakanahalfwidth {0x40b0365e, 0x092f}, // yadeva {0x40e21552, 0x30de}, // makatakana {0x40eb54f4, 0x046d}, // yusbigiotifiedcyrillic {0x413f6e7c, 0x05b4}, // hiriq21 {0x4144d56c, 0x016d}, // ubreve {0x414507c4, 0x05b9}, // holamnarrowhebrew {0x414a0074, 0x3336}, // hekutaarusquare {0x4156a20e, 0xfb06}, // s_t {0x4156eb7c, 0x3123}, // enbopomofo {0x415d9061, 0xff42}, // bmonospace {0x415fae27, 0x0398}, // Theta {0x4161c806, 0x09e1}, // llvocalicbengali {0x416a2ede, 0x0e04}, // khokhwaithai {0x4178dd24, 0x2243}, // asymptoticallyequal {0x41a22b2c, 0x007c}, // bar {0x41a40813, 0xff2d}, // Mmonospace {0x41a4780c, 0x0472}, // afii10147 {0x41c544c2, 0x1ee7}, // uhookabove {0x41c76cd5, 0x05d7}, // het {0x41cb5b30, 0x02db}, // ogonek {0x41da6e39, 0x098c}, // lvocalicbengali {0x41e154b7, 0x1edd}, // ohorngrave {0x41e44ef7, 0x0aaa}, // pagujarati {0x41efdfc2, 0x33c1}, // mohmsquare {0x42320627, 0x2495}, // fourteenperiod {0x4235d221, 0xfecf}, // ghaininitialarabic {0x423f9221, 0x05a7}, // dargahebrew {0x4247685c, 0x01ff}, // oslashacute {0x4252dd77, 0x02c7}, // caron {0x42716524, 0x0069}, // i {0x42737aaf, 0x3081}, // mehiragana {0x427d3f50, 0x04a9}, // haabkhasiancyrillic {0x42803db2, 0x0030}, // zero {0x42813ae4, 0x1e24}, // Hdotbelow {0x428fedda, 0xfb44}, // pedagesh {0x42bba9f5, 0x30f0}, // wikatakana {0x42bc1b07, 0x25c4}, // triaglf {0x42bed72c, 0x33c0}, // kohmsquare {0x42bf360e, 0x1e6e}, // Tlinebelow {0x42d74152, 0x0578}, // voarmenian {0x42e554b2, 0x013b}, // Lcedilla {0x42ed7ca6, 0x0698}, // jeharabic {0x42f02b62, 0xfb95}, // gafmedialarabic {0x42f35290, 0x0064}, // d {0x42fb2842, 0x3120}, // aubopomofo {0x42fc57be, 0x3110}, // jbopomofo {0x42fd43ba, 0x044c}, // afii10094 {0x42fdb31a, 0x0070}, // p {0x4305bc9e, 0x0920}, // tthadeva {0x4306eed3, 0x015d}, // scircumflex {0x430c20fb, 0x215e}, // seveneighths {0x430ddad4, 0xff20}, // atmonospace {0x431e0706, 0x00dc}, // Udieresis {0x43221a39, 0x1e91}, // zcircumflex {0x4328cb01, 0x339d}, // squarecm {0x432e75ab, 0x055d}, // commaarmenian {0x43399322, 0x026c}, // lbelt {0x434b10a7, 0x0a86}, // aagujarati {0x435f906e, 0xfb3e}, // memdageshhebrew {0x436008b6, 0x3064}, // tuhiragana {0x436f4b68, 0xfeaa}, // dalfinalarabic {0x439bf74d, 0xff8b}, // hikatakanahalfwidth {0x43a7e4d1, 0x0635}, // afii57429 {0x43d0d1da, 0x0627}, // afii57415 {0x43d651b4, 0x2663}, // clubsuitblack {0x43d755d6, 0x2212}, // minus {0x43dfb761, 0x0592}, // segoltahebrew {0x4405f04b, 0x05be}, // afii57645 {0x4425746a, 0x0a18}, // ghagurmukhi {0x44317cf4, 0x2662}, // diamondsuitwhite {0x443620cd, 0x00fe}, // thorn {0x444b0abf, 0x0467}, // yuslittlecyrillic {0x444f60e7, 0x007f}, // controlDEL {0x445a3b6e, 0x0447}, // afii10089 {0x4461957b, 0x041c}, // Emcyrillic {0x4464a19f, 0x0acb}, // ovowelsigngujarati {0x4483f355, 0x300f}, // whitecornerbracketright {0x4487c491, 0x3342}, // hoonsquare {0x4492e703, 0x0624}, // afii57412 {0x44979567, 0x0a25}, // thagurmukhi {0x449b4678, 0xfec3}, // tahinitialarabic {0x44a78c72, 0x1eef}, // uhorntilde {0x44b414b4, 0xff0c}, // commamonospace {0x44d687fa, 0x1e06}, // Blinebelow {0x45116064, 0x2592}, // shade {0x453aa0af, 0x09f0}, // ramiddlediagonalbengali {0x4546a724, 0x05d0}, // afii57664 {0x454cef44, 0x2642}, // mars {0x455bcfc1, 0x041d}, // afii10031 {0x457de97e, 0x3184}, // kapyeounphieuphkorean {0x457e9e97, 0x1ee8}, // Uhornacute {0x459f0c78, 0x23a7}, // bracelefttp {0x45b3d9fd, 0x0a22}, // ddhagurmukhi {0x45b6c88f, 0x029b}, // Gsmallhook {0x45b98e95, 0x2163}, // Fourroman {0x45c29649, 0x1ef4}, // Ydotbelow {0x45c5ae6b, 0x0165}, // tcaron {0x45d73e08, 0x0a09}, // ugurmukhi {0x45e50e5b, 0x0384}, // tonos {0x45f6e82c, 0x057f}, // tiwnarmenian {0x45f7d5e0, 0x2084}, // fourinferior {0x46038ece, 0x00b6}, // paragraph {0x460c35ae, 0x05b8}, // qamats10 {0x460ca9f0, 0x30e8}, // yokatakana {0x4611c6d0, 0x000b}, // controlVT {0x461bc854, 0x0194}, // Gammaafrican {0x46271982, 0x23ac}, // bracerightmid {0x4652be4f, 0x1e6d}, // tdotbelow {0x46541398, 0x0111}, // dmacron {0x465ea2f8, 0x3202}, // tikeutparenkorean {0x46611d40, 0x05bb}, // qubuts31 {0x466452b7, 0x321b}, // hieuhaparenkorean {0x467a9a55, 0x055b}, // emphasismarkarmenian {0x46ab407a, 0x322b}, // ideographicfireparen {0x46ab921d, 0x3076}, // buhiragana {0x46ba3911, 0x1e45}, // ndotaccent {0x46bce40e, 0xfb4f}, // aleflamedhebrew {0x46c4dd5b, 0x0433}, // afii10068 {0x46ca3a49, 0x2791}, // eightcircleinversesansserif {0x46e3006c, 0x055c}, // exclamarmenian {0x46f10ed2, 0x222a}, // union {0x46f3948a, 0x05d1}, // bethebrew {0x46f5f918, 0x05c3}, // afii57658 {0x46f9c8ca, 0x2195}, // arrowupdn {0x470d662e, 0x042e}, // IUcyrillic {0x470da4b8, 0x0453}, // gjecyrillic {0x471d219d, 0x00f4}, // ocircumflex {0x472c971d, 0x1e4d}, // otildeacute {0x47542f2d, 0x0107}, // cacute {0x47849b51, 0x05e5}, // finaltsadi {0x478eb915, 0x014f}, // obreve {0x47b12f1d, 0x3009}, // anglebracketright {0x47b78334, 0x09a5}, // thabengali {0x47ee62a0, 0x04f1}, // udieresiscyrillic {0x480265ce, 0x06f2}, // twopersian {0x48175191, 0x0130}, // Idotaccent {0x481e50de, 0xfb32}, // gimeldagesh {0x4825c60d, 0x02c3}, // arrowheadrightmod {0x482626d7, 0x09ee}, // eightbengali {0x4826d3e4, 0x3391}, // khzsquare {0x48270352, 0x1e42}, // Mdotbelow {0x4848966d, 0x05b2}, // hatafpatah {0x485d5052, 0x057d}, // seharmenian {0x48908e05, 0xff28}, // Hmonospace {0x48a3aad1, 0x1ec8}, // Ihookabove {0x48adcc47, 0x0160}, // Scaron {0x48b11825, 0x1e3f}, // macute {0x48b31eb3, 0x02a3}, // dzaltone {0x48bbab6b, 0x1e68}, // Sdotbelowdotaccent {0x48d0cd97, 0x0460}, // Omegacyrillic {0x48ed1289, 0x3180}, // ssangieungkorean {0x48f1ea86, 0x007c}, // verticalbar {0x49188fb6, 0x261d}, // pointingindexupwhite {0x491e8c30, 0x2562}, // SF200000 {0x4928f75b, 0x1e3d}, // lcircumflexbelow {0x49299271, 0x1eee}, // Uhorntilde {0x49314f7c, 0x1e96}, // hlinebelow {0x493c6957, 0x01ec}, // Oogonekmacron {0x497b2a29, 0x03c8}, // psi {0x49877605, 0x1ecf}, // ohookabove {0x49a6c904, 0x00d5}, // Otilde {0x49a8fbe4, 0x227a}, // precedes {0x49b28bf6, 0x011f}, // gbreve {0x49c941c8, 0x0630}, // thalarabic {0x49cf949f, 0x0011}, // controlDC1 {0x49d53679, 0x053e}, // Caarmenian {0x49e41b40, 0x0117}, // edotaccent {0x4a059748, 0x2329}, // angleleft {0x4a0a939e, 0x02dc}, // ilde {0x4a0dc7cd, 0x0273}, // nhookretroflex {0x4a1b8688, 0x0a8f}, // egujarati {0x4a67a4cd, 0x33c6}, // coverkgsquare {0x4a6dc3e0, 0x017c}, // zdotaccent {0x4a8f25d9, 0x0134}, // Jcircumflex {0x4a911686, 0x042a}, // Hardsigncyrillic {0x4aa9a643, 0x220c}, // notcontains {0x4ab871b2, 0x05a9}, // telishaqetanahebrew {0x4ad4b644, 0x066c}, // thousandsseparatorpersian {0x4adaae02, 0x30bc}, // zekatakana {0x4b13bfc7, 0x261f}, // pointingindexdownwhite {0x4b146e46, 0x0076}, // v {0x4b1cfc1b, 0x0052}, // R {0x4b69c8eb, 0x3200}, // kiyeokparenkorean {0x4b7a4380, 0x326b}, // thieuthcirclekorean {0x4b8cb1d3, 0x315a}, // oekorean {0x4b904ad7, 0x09ec}, // sixbengali {0x4bc3db0d, 0xfe8e}, // aleffinalarabic {0x4bcb1484, 0x0997}, // gabengali {0x4bf3941c, 0x04e7}, // odieresiscyrillic {0x4c1231bd, 0xfebe}, // dadfinalarabic {0x4c224e3d, 0x0216}, // Uinvertedbreve {0x4c31d446, 0x05b6}, // segolwidehebrew {0x4c330dc7, 0x2303}, // control {0x4c539c26, 0xff45}, // emonospace {0x4c550d84, 0x0286}, // eshcurl {0x4c63022b, 0x00ac}, // logicalnot {0x4c636f96, 0xfe4c}, // overlinedblwavy {0x4ca2293a, 0x0549}, // Chaarmenian {0x4ca721bb, 0x24d9}, // jcircle {0x4cbb6976, 0x054c}, // Raarmenian {0x4cc2766b, 0x0474}, // Izhitsacyrillic {0x4ccaa98f, 0x0292}, // ezh {0x4cda32dd, 0x2592}, // shademedium {0x4cf1d7c1, 0xfb2c}, // shindageshshindot {0x4d08f8de, 0x278c}, // threecircleinversesansserif {0x4d18f1c3, 0x01e5}, // gstroke {0x4d3fee14, 0x2207}, // gradient {0x4d5e2eea, 0x09c7}, // evowelsignbengali {0x4d66ad61, 0x0259}, // schwa {0x4d6f0f44, 0x03b6}, // zeta {0x4d76cbca, 0x0939}, // hadeva {0x4da2ea17, 0x30f7}, // vakatakana {0x4dad3b1f, 0xff47}, // gmonospace {0x4db4092d, 0x05b2}, // hatafpatahquarterhebrew {0x4dc635ef, 0x03c2}, // sigmafinal {0x4dd49001, 0x04ae}, // Ustraightcyrillic {0x4dd4e51e, 0x05e3}, // finalpe {0x4ddb0ff8, 0x3014}, // tortoiseshellbracketleft {0x4ddbe970, 0x0054}, // T {0x4ddd9ef4, 0x3296}, // ideographicfinancialcircle {0x4dedf33d, 0xff8d}, // hekatakanahalfwidth {0x4def9c7c, 0x2327}, // clear {0x4dfb4b2a, 0x247b}, // eightparen {0x4e03617a, 0x0ac1}, // uvowelsigngujarati {0x4e0fdced, 0x0a2d}, // bhagurmukhi {0x4e1cdd9c, 0x247d}, // tenparen {0x4e63a83b, 0x0642}, // qafarabic {0x4e7d8096, 0xff53}, // smonospace {0x4e8356bc, 0x0108}, // Ccircumflex {0x4eb853e7, 0x3384}, // kasquare {0x4ec3d2dc, 0xfccb}, // lamkhahinitialarabic {0x4ec752cf, 0x2022}, // bullet {0x4ef94777, 0x323b}, // ideographicstudyparen {0x4efcaf3c, 0x01ff}, // ostrokeacute {0x4f1d81af, 0x05bb}, // qubuts {0x4f1d9a74, 0x1e15}, // emacrongrave {0x4f1fbad2, 0x33b2}, // mussquare {0x4f238367, 0x0270}, // mlonglegturned {0x4f23d8fd, 0xfeda}, // kaffinalarabic {0x4f2d09de, 0x0662}, // twohackarabic {0x4f2efda5, 0xff07}, // quotesinglemonospace {0x4f30c414, 0x01c6}, // dzcaron {0x4f4be9c8, 0x3129}, // iubopomofo {0x4f6c2078, 0x00e5}, // aring {0x4f9b207b, 0x06c1}, // hehaltonearabic {0x4f9deafc, 0x03c4}, // tau {0x4fb92256, 0x216b}, // Twelveroman {0x4fdd1a2b, 0x300a}, // dblanglebracketleft {0x4feaecfe, 0x22c3}, // uniontext {0x5004c9ab, 0x09ed}, // sevenbengali {0x50166be8, 0x049a}, // Kadescendercyrillic {0x501dd48e, 0x2229}, // intersection {0x5024fa7b, 0x260f}, // whitetelephone {0x502bdceb, 0x3290}, // ideographsuncircle {0x503133b5, 0x0009}, // controlHT {0x507713d7, 0x2a02}, // circlemultiplytext {0x50794cf3, 0x255d}, // SF260000 {0x508090a0, 0xff82}, // tukatakanahalfwidth {0x50993bc3, 0x05dd}, // finalmemhebrew {0x509ec6af, 0x0490}, // Gheupturncyrillic {0x50a87245, 0x05b9}, // holamwidehebrew {0x50be3a5b, 0x3189}, // yoikorean {0x50cc5524, 0x00be}, // threequarters {0x50cc8cef, 0x24a3}, // hparen {0x50fb6106, 0x30c1}, // tikatakana {0x510f444c, 0x0662}, // afii57394 {0x511118c0, 0x05b8}, // qamatsqatanquarterhebrew {0x51250a43, 0x0ab9}, // hagujarati {0x5125d1fa, 0x25a1}, // whitesquare {0x513a52c9, 0x2510}, // SF030000 {0x51439af3, 0x064e}, // afii57454 {0x5147986a, 0xff5b}, // braceleftmonospace {0x514d7298, 0x3238}, // ideographiclaborparen {0x515692ea, 0x0414}, // Decyrillic {0x51616742, 0x328c}, // ideographwatercircle {0x51817d65, 0xfca1}, // tehjeeminitialarabic {0x51969939, 0x03ba}, // kappa {0x51ca7ab6, 0x00f6}, // odieresis {0x51cbc424, 0x014d}, // omacron {0x51d34569, 0x00e9}, // eacute {0x51e6847c, 0x05b2}, // hatafpatah16 {0x51ed3cb2, 0x00af}, // macron {0x51f006ea, 0x24af}, // tparen {0x51f3c5bb, 0x2082}, // twoinferior {0x51fee10e, 0x2210}, // coproducttext {0x52099e7d, 0x3267}, // ieungcirclekorean {0x5241ded3, 0x0428}, // Shacyrillic {0x5247cafc, 0x0691}, // afii57513 {0x524c924c, 0x02d6}, // plusmod {0x525a3324, 0x2606}, // whitestar {0x5282fafa, 0x0e09}, // chochingthai {0x528afecc, 0xfb89}, // ddalfinalarabic {0x52beac4f, 0x25bf}, // whitedownpointingsmalltriangle {0x52e15cc8, 0x24b6}, // Acircle {0x52f72574, 0x3322}, // sentisquare {0x530e1856, 0x05dd}, // finalmem {0x531472bf, 0x05bb}, // qubutswidehebrew {0x531963a3, 0x0a73}, // uragurmukhi {0x531c6e1f, 0x315b}, // yokorean {0x532f469f, 0x093d}, // avagrahadeva {0x533e9388, 0x02bc}, // afii57929 {0x537b0d36, 0x0466}, // Yuslittlecyrillic {0x53b3b784, 0xfb4a}, // tavdagesh {0x53ca8524, 0x099d}, // jhabengali {0x53d8dfb9, 0x3115}, // shbopomofo {0x53e66e1a, 0x0476}, // Izhitsadblgravecyrillic {0x53f49c2a, 0x066c}, // thousandsseparatorarabic {0x53f951b5, 0x056f}, // kenarmenian {0x540493c8, 0x03b1}, // alpha {0x540c5f40, 0x0552}, // Yiwnarmenian {0x542576f9, 0x0a07}, // igurmukhi {0x542f1e7a, 0x0151}, // ohungarumlaut {0x54761f15, 0x0631}, // afii57425 {0x54820079, 0x04df}, // zedieresiscyrillic {0x548a6dde, 0x0451}, // iocyrillic {0x5494ff15, 0x053c}, // Liwnarmenian {0x54cc0e6b, 0x0212}, // Rinvertedbreve {0x54dfda54, 0xfe44}, // whitecornerbracketrightvertical {0x54f8c0f2, 0x1e78}, // Utildeacute {0x55003750, 0x05b0}, // shevanarrowhebrew {0x55021a5a, 0x0644}, // lamarabic {0x550a9f23, 0x0452}, // djecyrillic {0x550d7456, 0x0061}, // a {0x5512ec97, 0x0067}, // g {0x552e72ea, 0x1e8d}, // xdieresis {0x5532b75e, 0x3044}, // ihiragana {0x554f67fa, 0x1e4e}, // Otildedieresis {0x556bcf7c, 0xff1f}, // questionmonospace {0x5575c7a8, 0x09a8}, // nabengali {0x557f8e27, 0x1ee0}, // Ohorntilde {0x558d2385, 0x0318}, // lefttackbelowcmb {0x55aa99d5, 0xfe3f}, // anglebracketleftvertical {0x55b44317, 0x1ef2}, // Ygrave {0x55c6e8cd, 0x0aac}, // bagujarati {0x55e74cbe, 0x23a6}, // bracketrightbt {0x55e81ebb, 0x3124}, // angbopomofo {0x56000715, 0x33b0}, // pssquare {0x560f90ad, 0x25e4}, // blackupperlefttriangle {0x56200891, 0x092b}, // phadeva {0x56217879, 0x0596}, // tipehalefthebrew {0x56362764, 0x24d0}, // acircle {0x565aa859, 0x30a8}, // ekatakana {0x565d95fc, 0x3109}, // dbopomofo {0x56a0101f, 0x04ac}, // Tedescendercyrillic {0x56d036b9, 0x000f}, // controlSI {0x56deae12, 0x0102}, // Abreve {0x57050efe, 0x0145}, // Ncommaaccent {0x5708e98e, 0x3154}, // ekorean {0x5713d355, 0x2790}, // sevencircleinversesansserif {0x575226bc, 0x239f}, // parenrightex {0x57687403, 0x0e08}, // chochanthai {0x576959da, 0x04b7}, // chedescendercyrillic {0x577fdcc5, 0x033a}, // bridgeinvertedbelowcmb {0x578594f4, 0x0e47}, // maitaikhuthai {0x579e8de2, 0x2074}, // foursuperior {0x57a10bfe, 0x0435}, // iecyrillic {0x57c4d153, 0xfb1f}, // yodyodpatahhebrew {0x57c8c90f, 0x313b}, // rieulmieumkorean {0x57cea503, 0xff17}, // sevenmonospace {0x57fc3d5e, 0x255b}, // SF280000 {0x58064efc, 0x0448}, // shacyrillic {0x580bc6b8, 0x2320}, // integraltop {0x580e0aa6, 0x005e}, // asciicircum {0x5817c838, 0x3141}, // mieumkorean {0x581d6ffc, 0x1ef8}, // Ytilde {0x58246165, 0x0152}, // OE {0x582e4f2f, 0x02a1}, // glottalstopstroke {0x58408a1e, 0x2321}, // integralbottom {0x584e8397, 0x263a}, // whitesmilingface {0x5855c496, 0x0465}, // eiotifiedcyrillic {0x587d22eb, 0x208d}, // parenleftinferior {0x58a61c85, 0x1e9a}, // arighthalfring {0x58ab0a67, 0x0544}, // Menarmenian {0x58ba15a9, 0x24c9}, // Tcircle {0x58c52193, 0x221a}, // radical {0x58df0572, 0x0301}, // acutecmb {0x58dfd388, 0x3187}, // yoyakorean {0x58e61a1f, 0x05e8}, // resh {0x58ea1dd9, 0x0650}, // afii57456 {0x593b3f38, 0x0aa1}, // ddagujarati {0x5951351c, 0x0109}, // ccircumflex {0x59664498, 0xff21}, // Amonospace {0x597231b2, 0x1e00}, // Aringbelow {0x598309ec, 0x1edc}, // Ohorngrave {0x598631c5, 0x24c1}, // Lcircle {0x59b5003e, 0x3274}, // siosacirclekorean {0x59b9b187, 0x0075}, // u {0x59be0f3a, 0xff7f}, // sokatakanahalfwidth {0x59c46f70, 0x3299}, // ideographicsecretcircle {0x59c80d40, 0x2482}, // fifteenparen {0x59d6d87b, 0xff74}, // ekatakanahalfwidth {0x59d7f689, 0x3393}, // ghzsquare {0x59eccfd0, 0x05a3}, // munahlefthebrew {0x5a1aca3c, 0xfe34}, // wavyunderscorevertical {0x5a24f67c, 0x03b4}, // delta {0x5a3b6461, 0xfeb8}, // sheenmedialarabic {0x5a532aa6, 0x0586}, // feharmenian {0x5a575dc4, 0x0582}, // yiwnarmenian {0x5a62c8e8, 0x005c}, // backslash {0x5a8d2a4a, 0x09c3}, // rvocalicvowelsignbengali {0x5a963c7c, 0x0e02}, // khokhaithai {0x5acd345c, 0x339c}, // squaremm {0x5af634c5, 0x059e}, // gershayimaccenthebrew {0x5b041347, 0x0581}, // coarmenian {0x5b0fd985, 0x0360}, // tildedoublecmb {0x5b1907c0, 0x30a5}, // usmallkatakana {0x5b1da33a, 0x2206}, // increment {0x5b1dbca0, 0x0aa6}, // dagujarati {0x5b426364, 0x30cf}, // hakatakana {0x5b426591, 0xfeb7}, // sheeninitialarabic {0x5b46f9e7, 0x2080}, // zeroinferior {0x5b54a5c3, 0x05e1}, // afii57681 {0x5b5f52e7, 0x0421}, // afii10035 {0x5b6ab184, 0x25ef}, // largecircle {0x5b6f6c30, 0x0003}, // controlETX {0x5b720455, 0x014c}, // Omacron {0x5b72ad21, 0x03d5}, // phi1 {0x5b785975, 0x02a7}, // tesh {0x5b7a64f2, 0x0597}, // reviahebrew {0x5bbfa15f, 0x25c4}, // blackleftpointingpointer {0x5bc1fa37, 0xfb47}, // qofdageshhebrew {0x5be94211, 0xff24}, // Dmonospace {0x5beb1e0f, 0x24cf}, // Zcircle {0x5bf0ba5d, 0xfb04}, // f_f_l {0x5c0e8b47, 0x0426}, // afii10040 {0x5c185e06, 0x0250}, // aturned {0x5c299659, 0x250c}, // SF010000 {0x5c337c81, 0xff8a}, // hakatakanahalfwidth {0x5c3478b9, 0xff3a}, // Zmonospace {0x5c349e9d, 0x30c5}, // dukatakana {0x5c352033, 0x092c}, // badeva {0x5c3b9279, 0x307e}, // mahiragana {0x5c3eecc5, 0x2561}, // SF190000 {0x5c4a060e, 0x0e29}, // sorusithai {0x5c6b0ced, 0x05b8}, // qamats33 {0x5c71c76c, 0x24b8}, // Ccircle {0x5c7f4966, 0x01b8}, // Ezhreversed {0x5c97be88, 0x0a2a}, // pagurmukhi {0x5c9a7487, 0x30ec}, // rekatakana {0x5ca0edc2, 0x01e7}, // gcaron {0x5cad2e17, 0x0679}, // tteharabic {0x5cb64e9e, 0x0150}, // Ohungarumlaut {0x5cb98a11, 0x05e9}, // afii57689 {0x5cc203b0, 0x09eb}, // fivebengali {0x5cde4fa9, 0xff39}, // Ymonospace {0x5ce216d6, 0x02bb}, // commaturnedmod {0x5ce89c18, 0x028c}, // vturned {0x5cee9de2, 0x333b}, // peezisquare {0x5d053ab9, 0x334d}, // meetorusquare {0x5d06b34a, 0x01f5}, // gacute {0x5d185c29, 0x0aec}, // sixgujarati {0x5d23e967, 0x019a}, // lbar {0x5d24fed7, 0x047d}, // omegatitlocyrillic {0x5d26ca2e, 0x0996}, // khabengali {0x5d32256c, 0x25c6}, // blackdiamond {0x5d333915, 0x2234}, // therefore {0x5d42ce05, 0x30c2}, // dikatakana {0x5d590cb1, 0x05bb}, // qubutsnarrowhebrew {0x5d71a05b, 0x0017}, // controlETB {0x5d85b369, 0x05b8}, // qamats29 {0x5d8c507f, 0xfb47}, // qofdagesh {0x5da58253, 0x30d0}, // bakatakana {0x5dba07ed, 0x22a5}, // perpendicular {0x5dbeec87, 0x01cd}, // Acaron {0x5de3b63c, 0x09cb}, // ovowelsignbengali {0x5e0aac56, 0x0200}, // Adblgrave {0x5e1c8dfa, 0x05b0}, // sheva2e {0x5e27fa57, 0xff6d}, // yusmallkatakanahalfwidth {0x5e36a670, 0xfe33}, // underscorevertical {0x5e483ddc, 0x3277}, // chieuchacirclekorean {0x5e4f2fbb, 0x1e65}, // sacutedotaccent {0x5ea7176f, 0x02d9}, // dotaccent {0x5edd1e19, 0xff25}, // Emonospace {0x5edd9086, 0x003a}, // colon {0x5eddf92b, 0x0044}, // D {0x5ee2af9c, 0x0e58}, // eightthai {0x5f03252d, 0x0136}, // Kcedilla {0x5f0ec9e9, 0x039a}, // Kappa {0x5f1bf33a, 0x1e17}, // emacronacute {0x5f4a5f07, 0x0abe}, // aavowelsigngujarati {0x5f5c5d5f, 0x041b}, // Elcyrillic {0x5f63748c, 0x03e6}, // Kheicoptic {0x5f7dc76d, 0x033b}, // squarebelowcmb {0x5f881d5c, 0x3160}, // yukorean {0x5f8f63e2, 0x24a0}, // eparen {0x5f99c0ac, 0x01ad}, // thook {0x5fa5f5cc, 0xfefa}, // lamalefhamzabelowfinalarabic {0x5fb56903, 0x095d}, // rhadeva {0x5fbeac33, 0x028b}, // vhook {0x5fe9065e, 0x042e}, // afii10048 {0x6037ae88, 0x1ef3}, // ygrave {0x603b5882, 0x2287}, // reflexsuperset {0x603b9d93, 0x00d3}, // Oacute {0x603ff393, 0x1e6c}, // Tdotbelow {0x60753fe5, 0x066d}, // afii63167 {0x607c93ed, 0x01b2}, // Vhook {0x60a46930, 0x0197}, // Istroke {0x60a4c80a, 0x30ee}, // wasmallkatakana {0x60ac2314, 0x25cc}, // dottedcircle {0x60ba7236, 0x000e}, // controlSO {0x60d57bed, 0x0aa4}, // tagujarati {0x60e1bf57, 0x1e0d}, // ddotbelow {0x60ebe651, 0x1ed8}, // Ocircumflexdotbelow {0x60f5a9fa, 0x03b7}, // eta {0x6106119c, 0xff37}, // Wmonospace {0x610b31e6, 0x01f1}, // DZ {0x6114c811, 0x1ef0}, // Uhorndotbelow {0x6121a3f6, 0x0e4d}, // nikhahitthai {0x61239a5a, 0x01c2}, // clickalveolar {0x6143b142, 0x1e67}, // scarondotaccent {0x61503571, 0x027b}, // rhookturned {0x6154bc05, 0x043b}, // afii10077 {0x617c687c, 0x01a2}, // Oi {0x6198a771, 0xfef3}, // alefmaksurainitialarabic {0x61a21109, 0x01c9}, // lj {0x61a2d0df, 0x258c}, // lfblock {0x61a6f1a4, 0x0264}, // ramshorn {0x61b4ed39, 0x25ba}, // triagrt {0x61b7afbf, 0x05b5}, // tserenarrowhebrew {0x61b9f022, 0x04c4}, // kahookcyrillic {0x61ce131a, 0x0647}, // afii57470 {0x61d46fc2, 0x1ed6}, // Ocircumflextilde {0x61d7bcdb, 0x1e57}, // pdotaccent {0x61e75298, 0x0417}, // afii10025 {0x61f36361, 0x06f8}, // eightpersian {0x61fe712f, 0x20a4}, // afii08941 {0x621057dd, 0x1ef5}, // ydotbelow {0x62127977, 0x266a}, // musicalnote {0x62161c15, 0x05da}, // finalkafhebrew {0x6229838d, 0x05d0}, // alef {0x62447ae3, 0x0314}, // commareversedabovecmb {0x6248b5e6, 0x33dd}, // wbsquare {0x625320aa, 0x30b2}, // gekatakana {0x6260c6fc, 0x0589}, // periodarmenian {0x6265e881, 0x2266}, // lessoverequal {0x626cbaa4, 0x01bf}, // wynn {0x62724d89, 0x09ad}, // bhabengali {0x62896f4a, 0x05f2}, // yodyodhebrew {0x628a5951, 0xff56}, // vmonospace {0x62a11b25, 0x1e87}, // wdotaccent {0x62accaf5, 0x239d}, // parenleftbt {0x62b2cd2d, 0x00c2}, // Acircumflex {0x62b6e7ac, 0x01a5}, // phook {0x62c361d5, 0x05e2}, // afii57682 {0x62c52689, 0x05d5}, // afii57669 {0x62ca59ed, 0x03aa}, // Iotadieresis {0x62cfccee, 0x017d}, // Zcaron {0x62d27ffc, 0x0567}, // eharmenian {0x62f7161d, 0x3020}, // postalmarkface {0x630680b1, 0x1e20}, // Gmacron {0x63070542, 0x0401}, // afii10023 {0x630758ff, 0x317e}, // sioscieuckorean {0x632ae410, 0x0acc}, // auvowelsigngujarati {0x634ac34b, 0x2297}, // timescircle {0x634e42e5, 0xff2b}, // Kmonospace {0x635a9554, 0x04e5}, // idieresiscyrillic {0x636fabd5, 0x093c}, // nuktadeva {0x637ae7ca, 0x0344}, // dialytikatonoscmb {0x637d3539, 0x00bc}, // onequarter {0x6389d9bb, 0x0641}, // afii57441 {0x63a82931, 0x0297}, // cstretched {0x63d84bb6, 0x2281}, // notsucceeds {0x63dfed74, 0x311f}, // eibopomofo {0x63e274d2, 0xfc0b}, // tehjeemisolatedarabic {0x63e60b13, 0x0149}, // napostrophe {0x63f6cd8f, 0x049d}, // kaverticalstrokecyrillic {0x642b78c5, 0x1ed5}, // ocircumflexhookabove {0x642e193e, 0x0469}, // yuslittleiotifiedcyrillic {0x6434f04a, 0xfd88}, // lammeemhahinitialarabic {0x64468e36, 0x0e18}, // thothongthai {0x64517fe8, 0x004b}, // K {0x6453c78e, 0x064e}, // fathalowarabic {0x6460d798, 0x3025}, // fivehangzhou {0x646b157e, 0x3242}, // ideographicselfparen {0x646c5c19, 0x0ab5}, // vagujarati {0x647eca4f, 0x09ae}, // mabengali {0x64a1b76b, 0x30fa}, // vokatakana {0x64d00b32, 0x0114}, // Ebreve {0x64d7a402, 0x0e40}, // saraethai {0x64d94f4a, 0x0e01}, // kokaithai {0x64e7dff2, 0x09c4}, // rrvocalicvowelsignbengali {0x64eb016b, 0x2245}, // approximatelyequal {0x64fd7a48, 0x2078}, // eightsuperior {0x650678be, 0x02cb}, // fourthtonechinese {0x65070663, 0x0459}, // ljecyrillic {0x6510d99a, 0x0938}, // sadeva {0x651d5722, 0x04c2}, // zhebrevecyrillic {0x6525cdb1, 0x00ad}, // softhyphen {0x6543f12c, 0x01d5}, // Udieresismacron {0x654d08a0, 0x0e3a}, // phinthuthai {0x657ffabd, 0x22ee}, // ellipsisvertical {0x6598fbfe, 0x3112}, // xbopomofo {0x65a5bd1b, 0x24e1}, // rcircle {0x65be15d1, 0x0a08}, // iigurmukhi {0x65c095c5, 0x200e}, // afii299 {0x65cc1f56, 0x0545}, // Yiarmenian {0x662a6586, 0x23a0}, // parenrightbt {0x662a831c, 0x1eeb}, // uhorngrave {0x663a2c1a, 0x3300}, // apaatosquare {0x6642f834, 0x0361}, // breveinverteddoublecmb {0x665bba62, 0x2017}, // dbllowline {0x665e930f, 0x3264}, // mieumcirclekorean {0x666ae75e, 0x0159}, // rcaron {0x666e8927, 0xfc4e}, // noonmeemisolatedarabic {0x666faf51, 0xfba5}, // hehhamzaabovefinalarabic {0x6689dbc7, 0x33cb}, // HPsquare {0x668e9764, 0x30a2}, // akatakana {0x66bb979c, 0x246c}, // thirteencircle {0x66c590a5, 0x2236}, // ratio {0x66e9c5c7, 0x3084}, // yahiragana {0x66ef8fdf, 0x040f}, // afii10145 {0x66fb9b49, 0x33c9}, // gysquare {0x67188e74, 0x0066}, // f {0x6740a4ac, 0x25cf}, // H18533 {0x67427e4a, 0x2079}, // ninesuperior {0x674a0210, 0x02b6}, // Rsmallinvertedsuperior {0x674c80b7, 0x03da}, // Stigmagreek {0x67569fa6, 0x05b5}, // tsere {0x6758c83c, 0x2588}, // block {0x6776a85a, 0x0ac7}, // evowelsigngujarati {0x6779be95, 0x3113}, // zhbopomofo {0x6785194b, 0x221f}, // rightangle {0x679d9205, 0x02c5}, // arrowheaddownmod {0x679dcadd, 0x0e54}, // fourthai {0x679ffc49, 0x2024}, // onedotenleader {0x67ea250f, 0x1e2d}, // itildebelow {0x67ebcea4, 0x3209}, // chieuchparenkorean {0x67f3db47, 0x3073}, // bihiragana {0x67f3ecac, 0xfb4b}, // afii57700 {0x67f7f220, 0x309c}, // semivoicedmarkkana {0x67fa1db6, 0x203a}, // guilsinglright {0x68070609, 0x0916}, // khadeva {0x6808ec86, 0x02d8}, // breve {0x6811e3e1, 0x0404}, // Ecyrillic {0x6814026d, 0x02c8}, // verticallinemod {0x682b08dd, 0x01ac}, // Thook {0x6853e235, 0x0652}, // sukunarabic {0x685932be, 0xfe36}, // parenrightvertical {0x68a76955, 0x00c7}, // Ccedilla {0x68b3215e, 0x0339}, // ringhalfrightbelowcmb {0x68b98a65, 0x0679}, // afii57511 {0x68ccd1d8, 0x3212}, // mieumaparenkorean {0x68eb418e, 0x3011}, // blacklenticularbracketright {0x690f8118, 0x320b}, // thieuthparenkorean {0x692bc1f7, 0x0a42}, // uumatragurmukhi {0x693ccd9c, 0x0432}, // vecyrillic {0x6962e430, 0x0322}, // hookretroflexbelowcmb {0x6977f4b7, 0xff05}, // percentmonospace {0x697925af, 0x05d2}, // gimel {0x697feb80, 0x030d}, // verticallineabovecmb {0x6991a62a, 0x0935}, // vadeva {0x699d525a, 0x0111}, // dcroat {0x69aabc4d, 0x06af}, // gafarabic {0x69d31152, 0x0e51}, // onethai {0x69faaae4, 0x33a7}, // moverssquare {0x6a104703, 0x2569}, // SF400000 {0x6a16e743, 0xfef0}, // alefmaksurafinalarabic {0x6a3d8bdc, 0x0a99}, // ngagujarati {0x6a511868, 0x03a7}, // Chi {0x6a5f0a3f, 0x334e}, // yaadosquare {0x6a721907, 0xfecc}, // ainmedialarabic {0x6a8d644d, 0x1ead}, // acircumflexdotbelow {0x6a972227, 0x0401}, // Iocyrillic {0x6a988d53, 0x2035}, // primereversed {0x6a9b2b92, 0x0414}, // afii10021 {0x6aa62850, 0x0662}, // twoarabic {0x6aa82ca6, 0x3218}, // khieukhaparenkorean {0x6abb1490, 0x005d}, // bracketright {0x6ad19d29, 0xfb1f}, // doubleyodpatahhebrew {0x6b214948, 0xff6f}, // tusmallkatakanahalfwidth {0x6b2d374c, 0xfcdd}, // yehmeeminitialarabic {0x6b3f02ab, 0x211e}, // prescription {0x6b58bab9, 0x0963}, // llvocalicvowelsigndeva {0x6b83db74, 0x2295}, // circleplus {0x6b85cd6e, 0x00a4}, // currency {0x6b8b924f, 0x30d8}, // hekatakana {0x6b908b1b, 0x09e7}, // onebengali {0x6b98f18c, 0x212b}, // angstrom {0x6b9adcc4, 0x25cf}, // blackcircle {0x6b9f4fbe, 0x0940}, // iivowelsigndeva {0x6baa5ba4, 0x03ce}, // omegatonos {0x6bbd76c8, 0x0936}, // shadeva {0x6bca6ff5, 0xfe4a}, // overlinecenterline {0x6bd59d12, 0x0915}, // kadeva {0x6bd609d3, 0x00f0}, // eth {0x6be13af7, 0x2199}, // arrowdownleft {0x6bf10a81, 0x2015}, // horizontalbar {0x6c0e37b1, 0x30ce}, // nokatakana {0x6c11086e, 0x0a1c}, // jagurmukhi {0x6c180b9f, 0x0462}, // Yatcyrillic {0x6c429460, 0xfb40}, // nundageshhebrew {0x6c5c9da6, 0x0457}, // yicyrillic {0x6c781e8a, 0x25bd}, // whitedownpointingtriangle {0x6c8584d5, 0x3065}, // duhiragana {0x6c95b865, 0x0941}, // uvowelsigndeva {0x6c98a67f, 0x0479}, // ukcyrillic {0x6cbb9b7a, 0xfe5d}, // tortoiseshellbracketleftsmall {0x6cce2d3d, 0x0aa5}, // thagujarati {0x6cce7f58, 0x043b}, // elcyrillic {0x6d02864a, 0x049c}, // Kaverticalstrokecyrillic {0x6d1b554b, 0x0982}, // anusvarabengali {0x6d3fc0d7, 0x040f}, // Dzhecyrillic {0x6d519305, 0x2169}, // Tenroman {0x6d63a915, 0x02bc}, // apostrophemod {0x6d6c6ece, 0x307f}, // mihiragana {0x6d794da3, 0x0057}, // W {0x6d7a8d87, 0x00fd}, // yacute {0x6d88930b, 0x044a}, // afii10092 {0x6d89653d, 0x24e8}, // ycircle {0x6d8f5cd4, 0xff95}, // yukatakanahalfwidth {0x6d931b7f, 0x255c}, // SF270000 {0x6d9b9c3e, 0x05dc}, // afii57676 {0x6dd186b9, 0x0575}, // yiarmenian {0x6ddcf118, 0x22a4}, // tackdown {0x6ddd69da, 0x05b1}, // hatafsegolquarterhebrew {0x6df68266, 0x0388}, // Epsilontonos {0x6df8e451, 0x2203}, // existential {0x6dfa6cea, 0x0a66}, // zerogurmukhi {0x6dff449c, 0xff79}, // kekatakanahalfwidth {0x6e002bb5, 0xfb05}, // longs_t {0x6e298b2c, 0x3380}, // paampssquare {0x6e2b4011, 0x2213}, // minusplus {0x6e2e0a97, 0xfe66}, // equalsmall {0x6e53b9b3, 0xfb00}, // ff {0x6e5f0868, 0x30ed}, // rokatakana {0x6e7cf223, 0x3071}, // pahiragana {0x6e81816d, 0x1e5d}, // rdotbelowmacron {0x6e897228, 0x0324}, // dieresisbelowcmb {0x6e8ccbbb, 0xfb48}, // reshdageshhebrew {0x6eb16a59, 0x2166}, // Sevenroman {0x6eb40b0d, 0x04db}, // schwadieresiscyrillic {0x6eba69ba, 0xfe9e}, // jeemfinalarabic {0x6ebb53ea, 0x2261}, // equivalence {0x6ecb4ba4, 0x0449}, // afii10091 {0x6ecc1f68, 0x25bc}, // triagdn {0x6ed918ed, 0xfcd1}, // meemmeeminitialarabic {0x6ee27b35, 0x0321}, // hookpalatalizedbelowcmb {0x6f028e08, 0x0571}, // jaarmenian {0x6f1f2583, 0x25ce}, // bullseye {0x6f2573bb, 0x30eb}, // rukatakana {0x6f4833d3, 0x0a5c}, // rragurmukhi {0x6f57587a, 0x227b}, // succeeds {0x6f64edc9, 0x054f}, // Tiwnarmenian {0x6f6b6e30, 0x0e0e}, // dochadathai {0x6f75692f, 0x0ac8}, // aivowelsigngujarati {0x6f7744aa, 0x2196}, // arrowupleft {0x6fae2151, 0x0aef}, // ninegujarati {0x6fbeef2a, 0x044d}, // ereversedcyrillic {0x6fc01d9f, 0x00f8}, // oslash {0x702ecc19, 0x3054}, // gohiragana {0x70534c83, 0x05a4}, // mahapakhlefthebrew {0x7061d5ad, 0x255a}, // SF380000 {0x707057b4, 0xfb2e}, // alefpatahhebrew {0x7070c1c4, 0x0333}, // dbllowlinecmb {0x7077f8df, 0x0163}, // tcommaaccent {0x708cf64a, 0x0944}, // rrvocalicvowelsigndeva {0x709b2bbe, 0x0056}, // V {0x70a0d365, 0xfeee}, // wawfinalarabic {0x70a7b34b, 0x05b5}, // tsere12 {0x70c1bcae, 0x1ede}, // Ohornhookabove {0x70d74f05, 0x04b1}, // ustraightstrokecyrillic {0x70d8442c, 0xff3c}, // backslashmonospace {0x70e9d43c, 0x2202}, // partialdiff {0x70f78dac, 0x24b5}, // zparen {0x70f8a40d, 0x05b8}, // afii57797 {0x71062567, 0xfeea}, // hehfinalalttwoarabic {0x710fbfc8, 0x0179}, // Zacute {0x712afb91, 0x310b}, // nbopomofo {0x7138408a, 0x04cc}, // chekhakassiancyrillic {0x71411a8f, 0x3156}, // yekorean {0x7154079a, 0x1e50}, // Omacrongrave {0x715a0e07, 0xfef4}, // alefmaksuramedialarabic {0x715aaa7e, 0x0122}, // Gcommaaccent {0x71693ad6, 0x0919}, // ngadeva {0x718d2f07, 0xff16}, // sixmonospace {0x71a4a95d, 0x1eaa}, // Acircumflextilde {0x71b12b2f, 0x01e0}, // Adotmacron {0x71b2c74d, 0x00b7}, // periodcentered {0x71b2e09c, 0x0e32}, // saraaathai {0x71e104c6, 0x3041}, // asmallhiragana {0x71ebf117, 0x0640}, // afii57440 {0x7222af0c, 0x25cb}, // circle {0x722d9aa3, 0x2153}, // onethird {0x72446324, 0x3164}, // hangulfiller {0x7256dcb9, 0x0ac2}, // uuvowelsigngujarati {0x725da2a5, 0x0548}, // Voarmenian {0x7274464b, 0x0e31}, // maihanakatthai {0x7276cdf0, 0x02d7}, // minusmod {0x7278753d, 0x04d7}, // iebrevecyrillic {0x728cf068, 0x020f}, // oinvertedbreve {0x728f761b, 0x3111}, // qbopomofo {0x72b3c6a8, 0x00b4}, // acute {0x72ba7ff6, 0x3093}, // nhiragana {0x72c6f1c4, 0xff5c}, // barmonospace {0x72c8f209, 0x0136}, // Kcommaaccent {0x72e33f41, 0x0419}, // afii10027 {0x72f1f5cf, 0x0438}, // iicyrillic {0x72fc7974, 0x2111}, // Ifraktur {0x72fd959a, 0x002a}, // asterisk {0x73032cb1, 0x3268}, // cieuccirclekorean {0x731be3b3, 0x3140}, // rieulhieuhkorean {0x73200dbd, 0x0e20}, // phosamphaothai {0x7322d42e, 0x24b9}, // Dcircle {0x73282fcd, 0x1ee3}, // ohorndotbelow {0x732cf2ca, 0x2485}, // eighteenparen {0x7338db3a, 0x066b}, // decimalseparatorarabic {0x73392eb6, 0x1ed4}, // Ocircumflexhookabove {0x733b0480, 0xfe94}, // tehmarbutafinalarabic {0x734f6c6b, 0x3090}, // wihiragana {0x7375cb46, 0x0686}, // tcheharabic {0x73843708, 0x0434}, // decyrillic {0x7387f092, 0x2088}, // eightinferior {0x73b2bbd4, 0xfe63}, // hyphensmall {0x73b70a88, 0x05d8}, // afii57672 {0x73b7c451, 0x095a}, // ghhadeva {0x73c5e60b, 0x004e}, // N {0x73ee6902, 0x0965}, // dbldanda {0x73f5578c, 0x093f}, // ivowelsigndeva {0x74030714, 0x311c}, // ebopomofo {0x7411ab47, 0x00ba}, // ordmasculine {0x74144417, 0x311e}, // aibopomofo {0x74157df0, 0x0667}, // sevenhackarabic {0x741e8130, 0x00cf}, // Idieresis {0x7435abfe, 0x057c}, // raarmenian {0x743d1e25, 0x0456}, // afii10103 {0x745c44bf, 0x02e3}, // xsuperior {0x746e784f, 0xff48}, // hmonospace {0x7476bb3d, 0x21d2}, // dblarrowright {0x74814589, 0x05b9}, // holam19 {0x748db30c, 0x33b1}, // nssquare {0x7495de6c, 0x0008}, // controlBS {0x74a2fb64, 0x2280}, // notprecedes {0x74abeab2, 0x05ac}, // iluyhebrew {0x74b1cbfb, 0x22c5}, // dotmath {0x74caf1a5, 0x01b4}, // yhook {0x74d74b92, 0x2209}, // notelement {0x74f1fca9, 0x01db}, // Udieresisgrave {0x7506e8c8, 0x24d1}, // bcircle {0x751253a5, 0x2168}, // Nineroman {0x7544678b, 0x307d}, // pohiragana {0x754982de, 0x06a4}, // veharabic {0x755a250b, 0x09dd}, // rhabengali {0x755f707c, 0x1ebf}, // ecircumflexacute {0x75841530, 0x2002}, // enspace {0x75907eb0, 0x322c}, // ideographicwaterparen {0x759ddc3d, 0x3068}, // tohiragana {0x759f9daf, 0x00c4}, // Adieresis {0x75aa325f, 0x3047}, // esmallhiragana {0x75b73269, 0x27e9}, // angbracketrightbig {0x75b9e64d, 0xff46}, // fmonospace {0x75bf74c1, 0x0a59}, // khhagurmukhi {0x75f4d85d, 0x0a2c}, // bagurmukhi {0x7603459c, 0x094c}, // auvowelsigndeva {0x760d83de, 0x222b}, // integral {0x7612320f, 0x3273}, // pieupacirclekorean {0x76186d8e, 0x01f3}, // dz {0x7619aedc, 0xfb4c}, // betrafehebrew {0x762dd6ce, 0x2260}, // notequal {0x763e1836, 0x30c4}, // tukatakana {0x7656c681, 0x01c4}, // DZcaron {0x767695a3, 0xfed4}, // fehmedialarabic {0x76811ae6, 0x0169}, // utilde {0x7681e1d4, 0xfe9b}, // thehinitialarabic {0x76a40aac, 0x001e}, // controlRS {0x76a57fc1, 0x0117}, // edot {0x76aa35a2, 0x1e27}, // hdieresis {0x76abdb93, 0xfb41}, // samekhdageshhebrew {0x76af2566, 0x05c1}, // afii57804 {0x76b279b9, 0x1e76}, // Ucircumflexbelow {0x76be5e67, 0x0389}, // Etatonos {0x76ec167e, 0x3128}, // ubopomofo {0x76ee8ef9, 0x326a}, // khieukhcirclekorean {0x76fa92ba, 0x2225}, // parallel {0x7722080a, 0x21e2}, // arrowdashright {0x772d6b37, 0x3294}, // ideographnamecircle {0x774eb078, 0x0328}, // ogonekcmb {0x774fe771, 0x064d}, // kasratanarabic {0x7752bcc4, 0x239e}, // parenrighttp {0x775a46a9, 0xffe0}, // centmonospace {0x77651620, 0x007b}, // braceleft {0x776629fd, 0x044a}, // hardsigncyrillic {0x7766a0eb, 0x041e}, // Ocyrillic {0x776cd4d6, 0x1e89}, // wdotbelow {0x77741a8d, 0x0473}, // fitacyrillic {0x7782c966, 0x1e46}, // Ndotbelow {0x7786e0a6, 0x246f}, // sixteencircle {0x779ce17f, 0x0390}, // iotadieresistonos {0x77a6f721, 0x2165}, // Sixroman {0x77aefb3f, 0x3027}, // sevenhangzhou {0x77b3e914, 0x3106}, // pbopomofo {0x77d27346, 0x0110}, // Dcroat {0x77e1d263, 0x0442}, // tecyrillic {0x77ee824a, 0xfba7}, // hehfinalaltonearabic {0x77f415ae, 0x03eb}, // gangiacoptic {0x77f608a5, 0x00ec}, // igrave {0x78151b28, 0x04f8}, // Yerudieresiscyrillic {0x781b1710, 0x3175}, // pieupsiostikeutkorean {0x782f5323, 0x2297}, // circlemultiply {0x783bb2b4, 0xfeea}, // hehfinalarabic {0x7849decd, 0x05f0}, // vavvavhebrew {0x7865471d, 0x30f8}, // vikatakana {0x7868522a, 0x0172}, // Uogonek {0x78728968, 0x0e3f}, // bahtthai {0x7877a9ea, 0x05d9}, // yodhebrew {0x7878b2f0, 0x323c}, // ideographicsuperviseparen {0x788e7d3e, 0x05b3}, // hatafqamats {0x78965447, 0x0593}, // shalshelethebrew {0x78d4db12, 0x032e}, // brevebelowcmb {0x78da6d23, 0x046e}, // Ksicyrillic {0x78f4df25, 0x04d9}, // schwacyrillic {0x79042ee6, 0x30e9}, // rakatakana {0x79116479, 0x0039}, // nine {0x7919f419, 0x0416}, // afii10024 {0x792d6db9, 0x0272}, // nhookleft {0x793801c3, 0x3158}, // wakorean {0x79577113, 0x2565}, // SF480000 {0x795917d1, 0x0583}, // piwrarmenian {0x79638654, 0x1ecd}, // odotbelow {0x796eb2f8, 0x3389}, // kcalsquare {0x796edb96, 0x0387}, // anoteleia {0x797aa124, 0x0445}, // khacyrillic {0x7980bc25, 0x00c5}, // Aring {0x7987b173, 0x03e8}, // Horicoptic {0x79961e28, 0x20a7}, // peseta {0x79c6a044, 0xfe3a}, // tortoiseshellbracketrightvertical {0x79d35b17, 0x3229}, // tenideographicparen {0x79dfa961, 0xfb2d}, // shindageshsindot {0x79e5e3c1, 0x0e2f}, // paiyannoithai {0x79fc5691, 0x24ce}, // Ycircle {0x7a196523, 0x0451}, // afii10071 {0x7a29214e, 0x006c}, // l {0x7a32a546, 0x202d}, // afii61574 {0x7a3f45e9, 0x0ab8}, // sagujarati {0x7a49bde9, 0xfca4}, // tehmeeminitialarabic {0x7a49dc21, 0xfee2}, // meemfinalarabic {0x7a56cace, 0x33a1}, // squaremsquared {0x7a6cfa6a, 0x0a3f}, // imatragurmukhi {0x7a75be4d, 0x2559}, // SF490000 {0x7a8736f8, 0x320c}, // phieuphparenkorean {0x7aa071da, 0x0217}, // uinvertedbreve {0x7aa95d24, 0xfb34}, // hedageshhebrew {0x7aac463a, 0x0669}, // afii57401 {0x7ab8ba14, 0x1ebe}, // Ecircumflexacute {0x7ad78099, 0x05b5}, // afii57794 {0x7b074f4f, 0x062c}, // jeemarabic {0x7b0aca00, 0x3315}, // kiroguramusquare {0x7b443626, 0x3331}, // birusquare {0x7b5e0418, 0xff10}, // zeromonospace {0x7b7b9d4d, 0x0424}, // afii10038 {0x7b80aee5, 0x05bb}, // qubutsquarterhebrew {0x7b8c3862, 0x02b8}, // ysuperior {0x7bac8f33, 0x0016}, // controlSYN {0x7bc269dd, 0x0040}, // at {0x7bd5ca88, 0x33ca}, // hasquare {0x7bd8b82b, 0x3005}, // ideographiciterationmark {0x7c301325, 0x0472}, // Fitacyrillic {0x7c3f4566, 0x00e7}, // ccedilla {0x7c4777ca, 0xfcc9}, // lamjeeminitialarabic {0x7c4f7ece, 0x0ab2}, // lagujarati {0x7c53c130, 0x0a13}, // oogurmukhi {0x7c613499, 0x2566}, // SF410000 {0x7c8ffdc8, 0x24e7}, // xcircle {0x7c903e9b, 0x1ec7}, // ecircumflexdotbelow {0x7cb539e8, 0x096e}, // eightdeva {0x7cc006ef, 0x222c}, // dblintegral {0x7cdf3e4a, 0x0a2f}, // yagurmukhi {0x7cf2e5f4, 0x0029}, // parenright {0x7cf2ebbd, 0xff96}, // yokatakanahalfwidth {0x7cf8ce2e, 0x3394}, // thzsquare {0x7d32ca29, 0x0127}, // hbar {0x7d44a576, 0x24b1}, // vparen {0x7d4ddd33, 0x2554}, // SF390000 {0x7d86a046, 0xff93}, // mokatakanahalfwidth {0x7d8bc7c0, 0x255f}, // SF370000 {0x7d981506, 0x0a9f}, // ttagujarati {0x7dc79678, 0x062a}, // afii57418 {0x7dc79708, 0x223c}, // tildeoperator {0x7dc7cd45, 0x33b6}, // muvsquare {0x7dcf75fb, 0x223c}, // similar {0x7dd21a95, 0x30b5}, // sakatakana {0x7dd63b6c, 0x1ec1}, // ecircumflexgrave {0x7de5edf4, 0x05b9}, // afii57806 {0x7df90cb9, 0x249c}, // aparen {0x7e46df3d, 0x30d7}, // pukatakana {0x7e4f805e, 0x3067}, // dehiragana {0x7e5c9fda, 0x042f}, // IAcyrillic {0x7e701b6d, 0xff0d}, // hyphenmonospace {0x7e739224, 0x3046}, // uhiragana {0x7ebf5260, 0x0031}, // one {0x7eddac19, 0x09f4}, // onenumeratorbengali {0x7f43cdd7, 0x0ab0}, // ragujarati {0x7f56c599, 0x0141}, // Lslash {0x7f5b3579, 0x1e74}, // Utildebelow {0x7f630a55, 0x1ef9}, // ytilde {0x7f7aa31e, 0x0648}, // afii57448 {0x7f82e2ff, 0x098f}, // ebengali {0x7f851974, 0x0568}, // etarmenian {0x7f92fe37, 0x066d}, // asteriskarabic {0x7f97f320, 0x301c}, // wavedash {0x7f99701f, 0xfb2a}, // shinshindothebrew {0x7fbd4335, 0x2309}, // ceilingrightbig {0x7ff2087d, 0x01df}, // adieresismacron {0x7ffdad4c, 0x326e}, // kiyeokacirclekorean {0x801f311e, 0x1ebb}, // ehookabove {0x8020003f, 0x05e9}, // shinhebrew {0x8027a085, 0x03d2}, // Upsilonhooksymbol {0x8029e67d, 0x049b}, // kadescendercyrillic {0x803a882f, 0x0a8b}, // rvocalicgujarati {0x80417827, 0x33a9}, // pasquare {0x8048e51c, 0x24e6}, // wcircle {0x80690312, 0x0155}, // racute {0x8076b638, 0xfedf}, // laminitialarabic {0x80792dfa, 0x0478}, // Ukcyrillic {0x8082c40e, 0x251c}, // SF080000 {0x8086d5c5, 0x0490}, // afii10050 {0x80890e42, 0x0316}, // gravebelowcmb {0x808de596, 0x2492}, // elevenperiod {0x808eef1b, 0x0068}, // h {0x80b21ab0, 0x00f5}, // otilde {0x80b54bce, 0x3170}, // mieumpansioskorean {0x80c36a57, 0x0480}, // Koppacyrillic {0x80f8e4b8, 0x017f}, // slong {0x80fb86d5, 0x00ff}, // ydieresis {0x810ea19f, 0x02bd}, // afii64937 {0x810f1d5a, 0x30c6}, // tekatakana {0x812767fa, 0x0555}, // Oharmenian {0x8140027d, 0x24d3}, // dcircle {0x815134d6, 0x00cd}, // Iacute {0x81589a47, 0x2220}, // angle {0x81658581, 0x0207}, // einvertedbreve {0x816871c9, 0x1ec2}, // Ecircumflexhookabove {0x8169da43, 0x0483}, // titlocyrilliccmb {0x8170d563, 0x256b}, // SF530000 {0x817f112a, 0x1e37}, // ldotbelow {0x817f9471, 0x1e92}, // Zdotbelow {0x81806da2, 0x328d}, // ideographwoodcircle {0x8184073f, 0x053b}, // Iniarmenian {0x818aac3d, 0x3165}, // ssangnieunkorean {0x81b94a51, 0x3233}, // ideographicsocietyparen {0x81e18c26, 0x30c3}, // tusmallkatakana {0x81eec5b0, 0x320e}, // kiyeokaparenkorean {0x8215ea5e, 0x02b2}, // jsuperior {0x82173176, 0x05d9}, // afii57673 {0x8218cc3e, 0x039c}, // Mu {0x822cf82c, 0x3070}, // bahiragana {0x8230e7a0, 0x32a7}, // ideographicleftcircle {0x823da9d2, 0x0413}, // afii10020 {0x825a2038, 0x3045}, // usmallhiragana {0x8260fa87, 0x1ea5}, // acircumflexacute {0x8272e0b5, 0x249b}, // twentyperiod {0x827d6960, 0xff40}, // gravemonospace {0x828072a0, 0x2666}, // diamond {0x8281c05a, 0x00b5}, // mu1 {0x8291bd7d, 0x248e}, // sevenperiod {0x82ab3b91, 0x03a3}, // Sigma {0x82b182a5, 0x057e}, // vewarmenian {0x82b58e6a, 0x1e94}, // Zlinebelow {0x82b5e1a0, 0x266b}, // eighthnotebeamed {0x82b5fc2f, 0x05bc}, // afii57807 {0x82c39f59, 0x1e62}, // Sdotbelow {0x82c3da09, 0x0a1a}, // cagurmukhi {0x82d03f46, 0x056e}, // caarmenian {0x82d4758a, 0x25e6}, // whitebullet {0x82db51c1, 0x05b6}, // segolnarrowhebrew {0x82dffbf3, 0xfe9c}, // thehmedialarabic {0x8322270c, 0x1e49}, // nlinebelow {0x832d9a03, 0x263b}, // invsmileface {0x83393d74, 0xfef7}, // lamalefhamzaaboveisolatedarabic {0x83589346, 0x1eb0}, // Abrevegrave {0x837601e2, 0x0ae7}, // onegujarati {0x8377c3f2, 0x026b}, // lmiddletilde {0x837a2830, 0x2113}, // lsquare {0x837c1552, 0x2172}, // threeroman {0x8388f2be, 0x00c9}, // Eacute {0x83a89a03, 0x045f}, // dzhecyrillic {0x83aeaef2, 0x1e23}, // hdotaccent {0x83c5c486, 0x05e7}, // afii57687 {0x83cd4320, 0x0565}, // echarmenian {0x83e3c3a4, 0x3075}, // huhiragana {0x83f86a79, 0x339e}, // squarekm {0x83fc4077, 0x0037}, // seven {0x83fe9093, 0x0441}, // escyrillic {0x840c8507, 0x0313}, // commaabovecmb {0x8411d0c3, 0x1e3e}, // Macute {0x84132896, 0x0140}, // ldot {0x841d72ff, 0x02e4}, // glottalstopreversedsuperior {0x841d9ceb, 0x0572}, // ghadarmenian {0x8424a64d, 0x05b5}, // tserewidehebrew {0x843c7aca, 0x323f}, // ideographicallianceparen {0x8445bb28, 0x0905}, // adeva {0x8459e5f4, 0x2248}, // approxequal {0x84776c26, 0x329d}, // ideographicexcellentcircle {0x847d9b8a, 0x1ec5}, // ecircumflextilde {0x847ed2d4, 0x0540}, // Hoarmenian {0x8487ed37, 0x0621}, // hamzaarabic {0x848baa07, 0xfc5f}, // shaddakasratanarabic {0x8494dfda, 0x05b1}, // hatafsegol24 {0x8498dbae, 0xfe86}, // wawhamzaabovefinalarabic {0x849b0297, 0x1e2e}, // Idieresisacute {0x84a67fee, 0x323a}, // ideographiccallparen {0x84b1d089, 0x0430}, // acyrillic {0x84de35f4, 0x0210}, // Rdblgrave {0x84e0b580, 0x04ef}, // umacroncyrillic {0x8501599a, 0x30f6}, // kesmallkatakana {0x85103d59, 0xfb39}, // yoddagesh {0x853a4f53, 0x217b}, // twelveroman {0x855c805d, 0xff1a}, // colonmonospace {0x856013c8, 0x248a}, // threeperiod {0x8567c154, 0x01bc}, // Tonefive {0x85a6c8bc, 0x310a}, // tbopomofo {0x85b41716, 0x201a}, // quotesinglbase {0x85b6b018, 0x2228}, // logicalor {0x85c83eb6, 0xff77}, // kikatakanahalfwidth {0x85ce16f4, 0x05da}, // afii57674 {0x85e92466, 0x2282}, // propersubset {0x85ee23d7, 0x311b}, // obopomofo {0x85f325ac, 0x064c}, // dammatanaltonearabic {0x85f47ad1, 0x0660}, // zerohackarabic {0x85f89b18, 0x3049}, // osmallhiragana {0x86129c18, 0x2209}, // notelementof {0x861e8048, 0xff54}, // tmonospace {0x861ef200, 0x1e75}, // utildebelow {0x8654695b, 0x0020}, // spacehackarabic {0x865c7659, 0x0312}, // commaturnedabovecmb {0x8665f7ab, 0x201b}, // quotereversed {0x8686768e, 0x093e}, // aavowelsigndeva {0x8694e2ae, 0x3132}, // ssangkiyeokkorean {0x8699e716, 0x09ef}, // ninebengali {0x869fef4c, 0x064b}, // afii57451 {0x86a662d1, 0x05e7}, // qofhebrew {0x86a80595, 0x0535}, // Echarmenian {0x86c2d4a4, 0x01ef}, // ezhcaron {0x86d0b880, 0x01c7}, // LJ {0x86d66230, 0x04ad}, // tedescendercyrillic {0x86e222a0, 0x05d9}, // yod {0x86eea6f9, 0x03a4}, // Tau {0x870315b6, 0x30e1}, // mekatakana {0x8713ac2f, 0xfb4b}, // vavholam {0x87634c8c, 0x05bd}, // siluqhebrew {0x877afbbb, 0xfb35}, // afii57723 {0x877f7c7a, 0xfeb4}, // seenmedialarabic {0x8787b92b, 0x02c0}, // glottalstopmod {0x87a041c7, 0x0446}, // afii10088 {0x87a4b30d, 0x263c}, // compass {0x87b6c8ba, 0x00c3}, // Atilde {0x87bb7ac5, 0x020b}, // iinvertedbreve {0x87e03b4f, 0x0642}, // afii57442 {0x87e97d46, 0x04dd}, // zhedieresiscyrillic {0x87ef58ab, 0xfe30}, // twodotleadervertical {0x87fc47e5, 0x24d2}, // ccircle {0x88044bf5, 0x2167}, // Eightroman {0x880a9911, 0x1e34}, // Klinebelow {0x881905a5, 0x0e22}, // yoyakthai {0x881a4ba0, 0x0931}, // rradeva {0x88264250, 0x1e71}, // tcircumflexbelow {0x8826a561, 0x03cd}, // upsilontonos {0x883bae04, 0x248c}, // fiveperiod {0x8841d986, 0x30b8}, // zikatakana {0x8853f322, 0x339b}, // mumsquare {0x885dcb80, 0x00a7}, // section {0x886c5d13, 0x0636}, // dadarabic {0x8876a700, 0x1e98}, // wring {0x888833ba, 0x02e7}, // tonebarmidmod {0x888e1142, 0x026d}, // lhookretroflex {0x88a12621, 0x05d4}, // afii57668 {0x88b6884b, 0x06f7}, // sevenpersian {0x88c2fc70, 0x0a6a}, // fourgurmukhi {0x88c96d26, 0xfb4a}, // tavdages {0x88cc32a3, 0x1ef6}, // Yhookabove {0x88da326f, 0x0546}, // Nowarmenian {0x88e4df33, 0x1e1b}, // etildebelow {0x88e6eee8, 0x3119}, // sbopomofo {0x88ea0124, 0x0949}, // ocandravowelsigndeva {0x88f38eed, 0x21d0}, // arrowdblleft {0x88f62270, 0x314f}, // akorean {0x88fdc1bb, 0x308e}, // wasmallhiragana {0x88fdcf2e, 0x039e}, // Xi {0x893a8f13, 0x09b9}, // habengali {0x89468742, 0x0e1f}, // fofanthai {0x897340ea, 0x3207}, // ieungparenkorean {0x897854cd, 0x060c}, // afii57388 {0x897adc4f, 0x0128}, // Itilde {0x89aa67b7, 0x2161}, // Tworoman {0x89ace505, 0xff06}, // ampersandmonospace {0x89d8daae, 0x25c9}, // fisheye {0x89e05206, 0x0022}, // quotedbl {0x89e2c74b, 0x062d}, // afii57421 {0x89ed1e17, 0x3171}, // kapyeounmieumkorean {0x89f4c981, 0x02dc}, // tilde {0x89f7042b, 0xfe38}, // bracerightvertical {0x89fc7dc4, 0x05bf}, // rafehebrew {0x8a1958e1, 0x03d1}, // theta1 {0x8a27f623, 0x030e}, // dblverticallineabovecmb {0x8a36e0e0, 0x0a89}, // ugujarati {0x8a64ee32, 0x23a2}, // bracketleftex {0x8a743e71, 0x3279}, // thieuthacirclekorean {0x8a7ff438, 0x0632}, // zainarabic {0x8ab11ede, 0x0907}, // ideva {0x8ab50af4, 0xfedb}, // kafinitialarabic {0x8ac9c3df, 0x00cb}, // Edieresis {0x8ae82e18, 0x05c2}, // sindothebrew {0x8aebef01, 0x064f}, // afii57455 {0x8af00e69, 0x3396}, // mlsquare {0x8af0299d, 0x2465}, // sixcircle {0x8af3a8ba, 0x1e55}, // pacute {0x8afdb385, 0x05b2}, // hatafpatahnarrowhebrew {0x8b04e879, 0x0573}, // cheharmenian {0x8b2ea84b, 0x045f}, // afii10193 {0x8b336b03, 0x33c3}, // bqsquare {0x8b3d9ff3, 0x313a}, // rieulkiyeokkorean {0x8b46ba2c, 0x1e10}, // Dcedilla {0x8b5fbe71, 0x0209}, // idblgrave {0x8b6e36e5, 0x0001}, // controlSTX {0x8b91eefb, 0x0135}, // jcircumflex {0x8ba07e30, 0x3236}, // ideographicfinancialparen {0x8ba61ca6, 0x0170}, // Udblacute {0x8bb0c7c5, 0x04a4}, // Enghecyrillic {0x8bb9fe95, 0x1e35}, // klinebelow {0x8bc6e552, 0x027a}, // rlonglegturned {0x8bd60707, 0x33ce}, // squarekmcapital {0x8bdd4dfa, 0x05a1}, // pazerhebrew {0x8be0aeeb, 0x1e28}, // Hcedilla {0x8bf3f9ec, 0x0aed}, // sevengujarati {0x8bfc7ed2, 0x02e9}, // tonebarextralowmod {0x8c09cf1f, 0x0251}, // ascript {0x8c169f16, 0x0a4c}, // aumatragurmukhi {0x8c1a91ec, 0x1ed2}, // Ocircumflexgrave {0x8c21575a, 0x2175}, // sixroman {0x8c3dc32f, 0x0632}, // afii57426 {0x8c5fd3c7, 0x05dd}, // afii57677 {0x8c7614fd, 0x0046}, // F {0x8c789c98, 0x0255}, // ccurl {0x8c7eba77, 0x3114}, // chbopomofo {0x8c941f03, 0x0639}, // afii57433 {0x8c9c3f66, 0x0e37}, // saraueethai {0x8cb6cb59, 0xfb6c}, // vehinitialarabic {0x8cbe2a76, 0x0951}, // udattadeva {0x8cc838c1, 0x099f}, // ttabengali {0x8ccab94e, 0x311d}, // ehbopomofo {0x8cd2ceac, 0x322f}, // ideographicearthparen {0x8cdd7a5e, 0xfefb}, // lamalefisolatedarabic {0x8cfeaaad, 0x04b4}, // Tetsecyrillic {0x8d0e3bcc, 0x0162}, // Tcommaaccent {0x8d15f0f9, 0x01d8}, // udieresisacute {0x8d17055f, 0xff23}, // Cmonospace {0x8d2183aa, 0x00ee}, // icircumflex {0x8d24b8c2, 0x0457}, // afii10104 {0x8d262f6a, 0x33ad}, // radsquare {0x8d3bc051, 0x1eb1}, // abrevegrave {0x8d430411, 0x0288}, // tretroflexhook {0x8d4c7b99, 0x0473}, // afii10195 {0x8d557bba, 0xfe98}, // tehmedialarabic {0x8d5ae6d4, 0x0440}, // ercyrillic {0x8d62c566, 0x21e0}, // arrowdashleft {0x8d7f2614, 0x2164}, // Fiveroman {0x8db3e76c, 0x1e97}, // tdieresis {0x8dbd6f57, 0xffe1}, // sterlingmonospace {0x8dc41abc, 0x1e33}, // kdotbelow {0x8de51633, 0x1ed7}, // ocircumflextilde {0x8df7afeb, 0x0968}, // twodeva {0x8e0d9fbd, 0x0337}, // solidusshortoverlaycmb {0x8e2538f6, 0x0420}, // Ercyrillic {0x8e325301, 0x0133}, // ij {0x8e3386c6, 0x0439}, // iishortcyrillic {0x8e360b54, 0x027d}, // rhook {0x8e40b292, 0x01fb}, // aringacute {0x8e467ab5, 0x1ecc}, // Odotbelow {0x8e474342, 0x1e2a}, // Hbrevebelow {0x8e5ae93f, 0x0909}, // udeva {0x8e5f575a, 0x0458}, // jecyrillic {0x8e5f7ac5, 0x01d2}, // ocaron {0x8e6f5aa1, 0x3074}, // pihiragana {0x8e757f60, 0x308a}, // rihiragana {0x8e7aa1b5, 0x207c}, // equalsuperior {0x8e8e0711, 0x042f}, // afii10049 {0x8e91af6c, 0x3000}, // ideographicspace {0x8ec9ea4f, 0xfb40}, // nundagesh {0x8eca9ee8, 0x045c}, // kjecyrillic {0x8ed1765d, 0xff36}, // Vmonospace {0x8ed539a2, 0x278a}, // onecircleinversesansserif {0x8f084bdd, 0x3204}, // mieumparenkorean {0x8f19bc84, 0x0e4a}, // maitrithai {0x8f289d06, 0x0444}, // efcyrillic {0x8f28eae1, 0x013f}, // Ldotaccent {0x8f4b9c51, 0x0404}, // afii10053 {0x8f505863, 0x04f2}, // Uhungarumlautcyrillic {0x8f52df2f, 0x0256}, // dtail {0x8f5e284f, 0xfed6}, // qaffinalarabic {0x8f760fbe, 0x25e5}, // blackupperrighttriangle {0x8f7f3f67, 0x0645}, // afii57445 {0x8f89b56f, 0x05b8}, // qamatsqatanhebrew {0x8fa69b6c, 0x0331}, // macronbelowcmb {0x8fbba331, 0x0205}, // edblgrave {0x8fc968d8, 0x01b9}, // ezhreversed {0x8fce94ba, 0x0395}, // Epsilon {0x8fd18473, 0x2593}, // shadedark {0x8fe2c390, 0x0e53}, // threethai {0x8fe329b9, 0x266c}, // beamedsixteenthnotes {0x8fe85541, 0x0637}, // afii57431 {0x8ff897b6, 0x0042}, // B {0x900e8281, 0x1e3b}, // llinebelow {0x900fb5c0, 0x0144}, // nacute {0x902443c2, 0xfe52}, // periodsmall {0x9024a760, 0x029d}, // jcrossedtail {0x90307534, 0x3059}, // suhiragana {0x9059f738, 0x00b7}, // middot {0x906746a4, 0xff75}, // okatakanahalfwidth {0x907d968c, 0x0a9b}, // chagujarati {0x90872973, 0x0538}, // Etarmenian {0x9098fbd4, 0x0002}, // controlSOT {0x90995fc1, 0x1e09}, // ccedillaacute {0x90a162b6, 0x05b4}, // hiriqwidehebrew {0x90b86ad8, 0x30dd}, // pokatakana {0x90b9c076, 0xff0f}, // slashmonospace {0x90c2be85, 0x0268}, // istroke {0x910a1b16, 0x03f1}, // rhosymbolgreek {0x9132f814, 0xff22}, // Bmonospace {0x9134ebbc, 0x01cb}, // Nj {0x913ff5ff, 0x3125}, // engbopomofo {0x9141d43c, 0x2126}, // Ohm {0x914ce494, 0x05e6}, // afii57686 {0x9166eec8, 0x33ba}, // pwsquare {0x916cdeb8, 0xfed2}, // fehfinalarabic {0x917f2f3f, 0x0438}, // afii10074 {0x9181b388, 0x01eb}, // oogonek {0x9184e24f, 0x30ab}, // kakatakana {0x919f5679, 0x00ca}, // Ecircumflex {0x91acc220, 0xff91}, // mukatakanahalfwidth {0x91accd4b, 0x0937}, // ssadeva {0x91c3e17e, 0x05f2}, // afii57718 {0x91d99037, 0x1eb9}, // edotbelow {0x91de3939, 0x064f}, // dammalowarabic {0x91e65480, 0x0abf}, // ivowelsigngujarati {0x91eaac20, 0x3214}, // siosaparenkorean {0x920dae79, 0x039f}, // Omicron {0x9215b042, 0x3147}, // ieungkorean {0x9220d7f0, 0xff69}, // usmallkatakanahalfwidth {0x923767e3, 0x3133}, // kiyeoksioskorean {0x9239e7fb, 0x062b}, // theharabic {0x923bf3d0, 0x0330}, // tildebelowcmb {0x926b691e, 0x0100}, // Amacron {0x92aa52d3, 0x30fb}, // dotkatakana {0x92e2ffd9, 0x21e8}, // arrowrightwhite {0x92f283dc, 0x25d8}, // bulletinverse {0x92f96dbe, 0x1e56}, // Pdotaccent {0x930724f6, 0x06ba}, // noonghunnaarabic {0x930c1a0b, 0x001b}, // controlESC {0x932512ee, 0x03ea}, // Gangiacoptic {0x9330a2fc, 0x0336}, // strokelongoverlaycmb {0x934b1595, 0x062d}, // haharabic {0x93959445, 0x263a}, // smileface {0x939a56c4, 0x03ad}, // epsilontonos {0x939b5eb8, 0xfe92}, // behmedialarabic {0x93bca3b6, 0x099e}, // nyabengali {0x93e00dc4, 0x2193}, // arrowdown {0x93eef318, 0x0263}, // gammalatinsmall {0x9404d5fc, 0x33d5}, // squaremil {0x941a6b5f, 0x0a23}, // nnagurmukhi {0x941b20fa, 0xfe4b}, // overlinewavy {0x942ad1c7, 0x09be}, // aavowelsignbengali {0x9453959c, 0x24bd}, // Hcircle {0x9464bc2e, 0x1e66}, // Scarondotaccent {0x94724b66, 0x21bc}, // harpoonleftbarbup {0x94803386, 0x09d7}, // aulengthmarkbengali {0x948a9ce4, 0x05de}, // afii57678 {0x949bc805, 0x01da}, // udieresiscaron {0x94ae0441, 0x0410}, // Acyrillic {0x94b7f6ea, 0x0463}, // yatcyrillic {0x94c36e74, 0x3261}, // nieuncirclekorean {0x94c9571f, 0x25ac}, // blackrectangle {0x94d13d1c, 0xfe39}, // tortoiseshellbracketleftvertical {0x94d74b96, 0x1e64}, // Sacutedotaccent {0x94e6f584, 0x3058}, // zihiragana {0x94ee5ae7, 0x2792}, // ninecircleinversesansserif {0x94f9a508, 0x3265}, // pieupcirclekorean {0x9518a20d, 0x30d9}, // bekatakana {0x951a0238, 0xfdf2}, // lamlamhehisolatedarabic {0x951ae869, 0x09dc}, // rrabengali {0x952cce64, 0x04ee}, // Umacroncyrillic {0x952ec009, 0x0988}, // iibengali {0x953a0a51, 0x2211}, // summation {0x954a8776, 0x03d1}, // thetasymbolgreek {0x95526ac8, 0x2500}, // SF100000 {0x9559e176, 0x05b7}, // patah2a {0x955dbbe7, 0x23aa}, // braceex {0x957765bc, 0xfe8a}, // yehhamzaabovefinalarabic {0x958830cb, 0x2669}, // quarternote {0x9588e4f1, 0xff99}, // rukatakanahalfwidth {0x959cf6c1, 0x203b}, // referencemark {0x95af6475, 0x05e3}, // finalpehebrew {0x95aff05f, 0x03ca}, // iotadieresis {0x95b3bc07, 0xfb46}, // tsadidagesh {0x95bed968, 0x0e15}, // totaothai {0x95cabf3f, 0x21cf}, // arrowrightdblstroke {0x95d7e2f4, 0x0032}, // two {0x95ed768c, 0x05e0}, // nun {0x960140f0, 0x2496}, // fifteenperiod {0x961b2e15, 0x1e6f}, // tlinebelow {0x96220dd7, 0x318a}, // yuyeokorean {0x962b0c72, 0x3323}, // sentosquare {0x9638605a, 0x0669}, // ninearabic {0x967b01ac, 0x05b9}, // holamhebrew {0x967d0326, 0x3134}, // nieunkorean {0x96a5e022, 0x25d9}, // invcircle {0x96b677d5, 0x0153}, // oe {0x96c05d98, 0x01f2}, // Dz {0x96c1ab16, 0x247f}, // twelveparen {0x96d9cc68, 0x0427}, // Checyrillic {0x96fd8ec6, 0x1e7a}, // Umacrondieresis {0x9711eb31, 0x21aa}, // arrowhookleft {0x9741ad45, 0x05bf}, // rafe {0x975dc1dc, 0x32a5}, // ideographiccentrecircle {0x9776a4ba, 0x0007}, // controlBEL {0x977737b3, 0x0265}, // hturned {0x9778a35b, 0x0562}, // benarmenian {0x977e0dfa, 0x25d0}, // circlewithlefthalfblack {0x97843a2e, 0x09f8}, // denominatorminusonenumeratorbengali {0x978c8c89, 0x03ac}, // alphatonos {0x97ae16ea, 0x23a1}, // bracketlefttp {0x97b3e7db, 0x24c3}, // Ncircle {0x97e45478, 0x05b6}, // segol2c {0x97ea0cb5, 0x04d8}, // Schwacyrillic {0x97ebb44e, 0x015f}, // scedilla {0x97f03f9c, 0x0419}, // Iishortcyrillic {0x97f6721e, 0x05bf}, // afii57841 {0x980e76a2, 0x1e32}, // Kdotbelow {0x98148d7b, 0xff14}, // fourmonospace {0x981fc90b, 0x0a1b}, // chagurmukhi {0x982585a7, 0x260e}, // telephoneblack {0x982718e0, 0x003c}, // less {0x982eb09a, 0x0e5b}, // khomutthai {0x9853033e, 0x04b5}, // tetsecyrillic {0x987e6d13, 0x0411}, // Becyrillic {0x9896e370, 0x0402}, // afii10051 {0x98b02dc0, 0x0a48}, // aimatragurmukhi {0x98d74b1c, 0x01c8}, // Lj {0x98d9aba5, 0x03ae}, // etatonos {0x98eba766, 0x018b}, // Dtopbar {0x98f4783f, 0x24ac}, // qparen {0x98f4b751, 0x0651}, // afii57457 {0x99104281, 0x02e5}, // tonebarextrahighmod {0x99235205, 0x05dc}, // lamedhebrew {0x994ebac3, 0x05c0}, // afii57842 {0x99725844, 0x0320}, // minusbelowcmb {0x9982855c, 0x0686}, // afii57507 {0x99830dc7, 0x062c}, // afii57420 {0x99863852, 0x03ed}, // shimacoptic {0x99997c4f, 0x3314}, // kirosquare {0x999c619c, 0x3078}, // hehiragana {0x999f4db4, 0x05b4}, // afii57793 {0x99cca883, 0xff04}, // dollarmonospace {0x99e63f81, 0x0962}, // lvocalicvowelsigndeva {0x9a069ea3, 0x2267}, // greateroverequal {0x9a098276, 0xfea2}, // hahfinalarabic {0x9a157ece, 0x246a}, // elevencircle {0x9a1c929d, 0x043c}, // afii10078 {0x9a310f17, 0xff51}, // qmonospace {0x9a3391f5, 0x0190}, // Eopen {0x9a464a33, 0x0174}, // Wcircumflex {0x9a50ec2e, 0x05b6}, // segolquarterhebrew {0x9a7aab21, 0x05c3}, // sofpasuqhebrew {0x9ac6c137, 0x0e0f}, // topatakthai {0x9aea680b, 0x3029}, // ninehangzhou {0x9af6d63b, 0x054a}, // Peharmenian {0x9b09b61d, 0x0a10}, // aigurmukhi {0x9b0db21d, 0x0402}, // Djecyrillic {0x9b100042, 0x0e21}, // momathai {0x9b29e68e, 0x0278}, // philatin {0x9b3ff954, 0x0e56}, // sixthai {0x9b5a3eb3, 0x0626}, // afii57414 {0x9b712e01, 0x1eba}, // Ehookabove {0x9b73811a, 0x2227}, // logicaland {0x9b76648b, 0x041f}, // afii10033 {0x9b7712b3, 0x1e5a}, // Rdotbelow {0x9b8591a5, 0x30ca}, // nakatakana {0x9b950b60, 0x095e}, // fadeva {0x9ba02025, 0x01e9}, // kcaron {0x9bca0720, 0x1e93}, // zdotbelow {0x9bcccde6, 0x0e4e}, // yamakkanthai {0x9bd59a36, 0x300e}, // whitecornerbracketleft {0x9bdb98a4, 0x1e5e}, // Rlinebelow {0x9be54046, 0x0e0a}, // chochangthai {0x9bfe067d, 0x0405}, // Dzecyrillic {0x9c14c866, 0x0484}, // palatalizationcyrilliccmb {0x9c1ff986, 0x05f1}, // afii57717 {0x9c30e64e, 0x0121}, // gdot {0x9c3d076c, 0x002d}, // hyphen {0x9c5df589, 0x03b2}, // beta {0x9c5e488c, 0x05d3}, // dalethebrew {0x9c743ddb, 0x3239}, // ideographicrepresentparen {0x9cc9b890, 0x2a00}, // circledottext {0x9cd2074a, 0x0a36}, // shagurmukhi {0x9ce0dacf, 0xfebb}, // sadinitialarabic {0x9ce3d2fe, 0x06d2}, // afii57519 {0x9ce9cdfc, 0x0408}, // Jecyrillic {0x9ce9f027, 0x0426}, // Tsecyrillic {0x9cf54095, 0x20aa}, // newsheqelsign {0x9d1b1141, 0x25d8}, // invbullet {0x9d1ed2c0, 0x0120}, // Gdotaccent {0x9d25f804, 0x0294}, // glottalstop {0x9d3a5187, 0x03bb}, // lambda {0x9d4507ca, 0x00a0}, // nonbreakingspace {0x9d4ea24d, 0x045a}, // njecyrillic {0x9d5ba323, 0x3145}, // sioskorean {0x9d5eb9a4, 0x001f}, // controlUS {0x9d662219, 0x332a}, // haitusquare {0x9d760ad7, 0x3318}, // guramusquare {0x9d770652, 0x1e2b}, // hbrevebelow {0x9db9ebc8, 0x30ba}, // zukatakana {0x9dee7277, 0x2015}, // afii00208 {0x9df531bb, 0x059b}, // tevirhebrew {0x9e021469, 0x22cf}, // curlyand {0x9e062707, 0x02a2}, // glottalstopstrokereversed {0x9e0bf218, 0x02b1}, // hhooksuperior {0x9e0d1458, 0x02c4}, // arrowheadupmod {0x9e1247f8, 0x0033}, // three {0x9e248728, 0x3053}, // kohiragana {0x9e2d5a68, 0x053f}, // Kenarmenian {0x9e5de325, 0x222e}, // contourintegral {0x9e65e800, 0x248b}, // fourperiod {0x9e98d52c, 0x2483}, // sixteenparen {0x9ea14168, 0x05b7}, // patahquarterhebrew {0x9ea23fe1, 0x00f1}, // ntilde {0x9eac193b, 0x00ef}, // idieresis {0x9eb5aea3, 0x3142}, // pieupkorean {0x9ebea1a0, 0x3150}, // aekorean {0x9ee7bbd1, 0x094b}, // ovowelsigndeva {0x9eedaba9, 0x0113}, // emacron {0x9f023815, 0x20ac}, // euro {0x9f30fc87, 0xfec2}, // tahfinalarabic {0x9f37894c, 0x040e}, // afii10062 {0x9f53036c, 0x0a19}, // ngagurmukhi {0x9f65cf71, 0x1e25}, // hdotbelow {0x9f69147e, 0x1e61}, // sdotaccent {0x9f6f9105, 0x0433}, // gecyrillic {0x9f739695, 0x04f9}, // yerudieresiscyrillic {0x9f79f6eb, 0xfb33}, // daletdageshhebrew {0x9f8cff14, 0x003e}, // greater {0x9f94b2e4, 0x04a1}, // kabashkircyrillic {0x9fa5f7ad, 0x0e49}, // maithothai {0x9fc7ffac, 0x05b4}, // hiriqhebrew {0x9fd406b1, 0xfed8}, // qafmedialarabic {0x9fd7c50e, 0x05bb}, // afii57796 {0x9fdfc7a1, 0x00b0}, // degree {0x9ffeaad9, 0x01ed}, // oogonekmacron {0xa0144bc6, 0xfc8d}, // noonnoonfinalarabic {0xa0166e3d, 0x3159}, // waekorean {0xa016fb2d, 0x016b}, // umacron {0xa0286aa8, 0x1e04}, // Bdotbelow {0xa03db58b, 0x02d2}, // ringhalfrightcentered {0xa05ccf71, 0x05e1}, // samekhhebrew {0xa069fd2d, 0x012b}, // imacron {0xa08ca5a7, 0x2491}, // tenperiod {0xa0a317f9, 0x0574}, // menarmenian {0xa0c2ffe3, 0x247a}, // sevenparen {0xa0e40fac, 0x337b}, // heiseierasquare {0xa0e487b8, 0x33cd}, // KKsquare {0xa0ee672b, 0x3143}, // ssangpieupkorean {0xa100bc11, 0x043e}, // ocyrillic {0xa10462a8, 0x0394}, // Deltagreek {0xa11f6f39, 0x0071}, // q {0xa12507ea, 0x2177}, // eightroman {0xa12d2230, 0x05b5}, // tsere2b {0xa134a191, 0xff11}, // onemonospace {0xa14f5367, 0x05b0}, // sheva15 {0xa157c7c6, 0x0643}, // kafarabic {0xa15811a3, 0x061f}, // questionarabic {0xa1697005, 0x0015}, // controlNAK {0xa16fa8a4, 0x22a3}, // tackleft {0xa1703e0a, 0x3219}, // thieuthaparenkorean {0xa1850262, 0x05c2}, // afii57803 {0xa1a14a63, 0x1eb8}, // Edotbelow {0xa1ed89db, 0x0202}, // Ainvertedbreve {0xa20cadbf, 0x0062}, // b {0xa20ea9da, 0x24aa}, // oparen {0xa212ed2d, 0x0e38}, // sarauthai {0xa2448aa1, 0x01e6}, // Gcaron {0xa2543878, 0x326f}, // nieunacirclekorean {0xa254ebdd, 0xfb3e}, // memdagesh {0xa259bfe7, 0xff19}, // ninemonospace {0xa262edc1, 0xfe49}, // overlinedashed {0xa26bc10f, 0x061b}, // semicolonarabic {0xa27876ee, 0xfe35}, // parenleftvertical {0xa28a5f58, 0xfec8}, // zahmedialarabic {0xa28ba8ac, 0x317d}, // siospieupkorean {0xa2972ad9, 0x2305}, // projective {0xa2be0dd9, 0x062b}, // afii57419 {0xa2c2120e, 0x0e52}, // twothai {0xa2d967e3, 0x2083}, // threeinferior {0xa2e1fb7a, 0x221e}, // infinity {0xa2f62d95, 0x306e}, // nohiragana {0xa3004c6f, 0x092e}, // madeva {0xa316ccc6, 0x2044}, // fraction {0xa32a4538, 0xfb1f}, // afii57705 {0xa334b2d1, 0x043d}, // afii10079 {0xa34b5d2f, 0x0e57}, // seventhai {0xa36dbdee, 0x30db}, // hokatakana {0xa386d6fe, 0x3327}, // tonsquare {0xa3903917, 0x3270}, // tikeutacirclekorean {0xa39b2570, 0xfefc}, // lamaleffinalarabic {0xa3b51a89, 0x0597}, // reviamugrashhebrew {0xa3cc74fa, 0x3056}, // zahiragana {0xa3d9a90d, 0x0499}, // zedescendercyrillic {0xa3e95215, 0xfef9}, // lamalefhamzabelowisolatedarabic {0xa3ec709c, 0x0569}, // toarmenian {0xa3fbf1d9, 0x0497}, // zhedescendercyrillic {0xa3fe88d1, 0x0104}, // Aogonek {0xa40369ed, 0x32a9}, // ideographicmedicinecircle {0xa4259ac9, 0xff76}, // kakatakanahalfwidth {0xa43cdc2e, 0xfb44}, // pedageshhebrew {0xa446d45f, 0x3224}, // fiveideographicparen {0xa450f946, 0x0454}, // afii10101 {0xa456f11e, 0x09e8}, // twobengali {0xa457c062, 0x30ad}, // kikatakana {0xa45b3183, 0x0aeb}, // fivegujarati {0xa45b7f21, 0x010e}, // Dcaron {0xa4627c0f, 0x0204}, // Edblgrave {0xa478f921, 0x09e0}, // rrvocalicbengali {0xa4863185, 0x30f4}, // vukatakana {0xa4922e7c, 0x0341}, // acutetonecmb {0xa4aa1092, 0x05b1}, // hatafsegol30 {0xa4aa8935, 0xff58}, // xmonospace {0xa4af8f73, 0x2282}, // subset {0xa4decb10, 0x0a72}, // irigurmukhi {0xa50a3a99, 0x0630}, // afii57424 {0xa50cf621, 0xff7e}, // sekatakanahalfwidth {0xa512e58d, 0xff83}, // tekatakanahalfwidth {0xa517b724, 0xfee6}, // noonfinalarabic {0xa52168e0, 0x2325}, // option {0xa54253fb, 0x05e7}, // qof {0xa545c2a6, 0xfb2a}, // afii57694 {0xa553cf3e, 0x003b}, // semicolon {0xa56dfce7, 0x0e03}, // khokhuatthai {0xa58382dd, 0x0137}, // kcedilla {0xa5b93826, 0x2555}, // SF220000 {0xa5ecbdaa, 0x03b5}, // epsilon {0xa6056425, 0x05b8}, // qamatswidehebrew {0xa60745ee, 0x2250}, // approaches {0xa6281f81, 0x0142}, // lslash {0xa62afc92, 0x0534}, // Daarmenian {0xa6454b66, 0x2498}, // seventeenperiod {0xa64723d6, 0x30af}, // kukatakana {0xa6522894, 0x24da}, // kcircle {0xa652cff2, 0x24a8}, // mparen {0xa65ca284, 0x314d}, // phieuphkorean {0xa65ea7b9, 0x00ab}, // guillemotleft {0xa6644796, 0xfc94}, // yehnoonfinalarabic {0xa66b3ab3, 0x00b8}, // cedilla {0xa675e0d6, 0x0156}, // Rcommaaccent {0xa683217b, 0x0ab7}, // ssagujarati {0xa6a017fd, 0x0415}, // Iecyrillic {0xa6ae34a8, 0x3028}, // eighthangzhou {0xa6b19efc, 0x0591}, // etnahtafoukhhebrew {0xa6b46028, 0xff72}, // ikatakanahalfwidth {0xa6bd2b95, 0x1e6b}, // tdotaccent {0xa6c10839, 0x0431}, // becyrillic {0xa6e68e9f, 0x0966}, // zerodeva {0xa6f16c03, 0x03c2}, // sigma1 {0xa6f2df0d, 0x0a32}, // lagurmukhi {0xa716a470, 0x2464}, // fivecircle {0xa71dfe13, 0x1ea2}, // Ahookabove {0xa73026ce, 0x007a}, // z {0xa73199c0, 0x05bb}, // qubutshebrew {0xa731e944, 0x0411}, // afii10018 {0xa7320cb3, 0x3139}, // rieulkorean {0xa74014fc, 0x003f}, // question {0xa745be27, 0x2308}, // ceilingleftbig {0xa74cd67a, 0x025f}, // jdotlessstroke {0xa756caf5, 0x04d2}, // Adieresiscyrillic {0xa7769b7a, 0x22c1}, // logicalortext {0xa7895d88, 0x252c}, // SF060000 {0xa796d5bb, 0x0267}, // henghook {0xa7bff3d5, 0x032c}, // caronbelowcmb {0xa7dcd836, 0xfb68}, // ttehinitialarabic {0xa7e01c26, 0x01a7}, // Tonetwo {0xa7e7d702, 0x05b8}, // qamats1a {0xa7edca33, 0x25b7}, // whiterightpointingtriangle {0xa7fb6ee6, 0x226f}, // notgreater {0xa7fe97d8, 0x3166}, // nieuntikeutkorean {0xa815fa8a, 0x309e}, // voicediterationhiragana {0xa819fe3e, 0x315e}, // wekorean {0xa81ee743, 0x0542}, // Ghadarmenian {0xa826b713, 0xfeb6}, // sheenfinalarabic {0xa842618b, 0x025b}, // eopen {0xa84fdde5, 0x0340}, // gravetonecmb {0xa851c76f, 0x05a5}, // merkhahebrew {0xa8547bdd, 0x0455}, // afii10102 {0xa8665e8d, 0x05b1}, // afii57801 {0xa877e561, 0x2642}, // male {0xa8982f3b, 0x09b2}, // labengali {0xa8a24959, 0x00d0}, // Eth {0xa8b6c7f5, 0x0a2e}, // magurmukhi {0xa8b7f35e, 0x06c1}, // haaltonearabic {0xa8bb13d5, 0x0a70}, // tippigurmukhi {0xa8ccc65c, 0x3316}, // kiromeetorusquare {0xa8db2b93, 0x017e}, // zcaron {0xa93204a5, 0x03a6}, // Phi {0xa9350b3f, 0x20a1}, // colonmonetary {0xa93a2a4f, 0x1e47}, // ndotbelow {0xa94e0303, 0x33ab}, // mpasquare {0xa94eeaee, 0x01aa}, // eshreversedloop {0xa95e2711, 0x1e21}, // gmacron {0xa96cef91, 0x3169}, // rieulkiyeoksioskorean {0xa981562d, 0x0668}, // eightarabic {0xa98e771c, 0x0634}, // sheenarabic {0xa9985803, 0x30dc}, // bokatakana {0xa99c94c2, 0x01be}, // glottalinvertedstroke {0xa9a0932f, 0x2077}, // sevensuperior {0xa9af18f2, 0x30b4}, // gokatakana {0xa9c0b182, 0x2264}, // lessequal {0xaa13efde, 0x007d}, // braceright {0xaa4e278b, 0x0967}, // onedeva {0xaa51d75f, 0x2476}, // threeparen {0xaa69d0f1, 0x256c}, // SF440000 {0xaa863ce3, 0x0629}, // tehmarbutaarabic {0xaa8c5eeb, 0x03e5}, // feicoptic {0xaa96b9dc, 0x0665}, // fivearabic {0xaaabcf5c, 0x04b9}, // cheverticalstrokecyrillic {0xaab6b9a5, 0x0211}, // rdblgrave {0xaabfed05, 0xff85}, // nakatakanahalfwidth {0xaac3a76a, 0x0559}, // ringhalfleftarmenian {0xaac3adf0, 0x3121}, // oubopomofo {0xaacaffc4, 0x2162}, // Threeroman {0xaad54f7c, 0x3002}, // ideographicperiod {0xaaf6eb21, 0x01ce}, // acaron {0xab0b499a, 0x099c}, // jabengali {0xab126f69, 0x5344}, // twentyhangzhou {0xab1f1bb7, 0x05df}, // afii57679 {0xab24577f, 0x0667}, // sevenarabic {0xab2b4200, 0x2105}, // careof {0xab3b4b27, 0x24e2}, // scircle {0xab808d1e, 0x2087}, // seveninferior {0xab8a6656, 0x01d0}, // icaron {0xaba55a59, 0xfb32}, // gimeldageshhebrew {0xabb7eb8f, 0x2081}, // oneinferior {0xabd373e8, 0x055e}, // questionarmenian {0xac05d874, 0x1e84}, // Wdieresis {0xac259f58, 0x0448}, // afii10090 {0xac2c323e, 0x0191}, // Fhook {0xac32a034, 0x316f}, // mieumsioskorean {0xac483cb3, 0x338c}, // mufsquare {0xac4f1094, 0x059c}, // gereshaccenthebrew {0xac50a082, 0x33a3}, // mmcubedsquare {0xac5faca7, 0x230b}, // floorrightbig {0xac67aca2, 0x045b}, // tshecyrillic {0xacb92bab, 0x0691}, // rreharabic {0xacd00f05, 0x21c6}, // arrowleftoverright {0xacd11e18, 0x2010}, // hyphentwo {0xace7d07a, 0x0921}, // ddadeva {0xacfcbdb9, 0x3042}, // ahiragana {0xad01f787, 0xff1d}, // equalmonospace {0xad1b58f9, 0x0595}, // zaqefgadolhebrew {0xad29738f, 0x05f4}, // gershayimhebrew {0xad33f4b3, 0x04c1}, // Zhebrevecyrillic {0xad37f8e0, 0x0a24}, // tagurmukhi {0xad38bc31, 0x2194}, // arrowboth {0xad5fe438, 0x0924}, // tadeva {0xad781e89, 0x200c}, // afii61664 {0xad8ff38a, 0x0a21}, // ddagurmukhi {0xadb1b19e, 0x0206}, // Einvertedbreve {0xadb53f6b, 0xfbaf}, // yehbarreefinalarabic {0xadbea3e4, 0x20aa}, // afii57636 {0xadc3ff5e, 0x0649}, // afii57449 {0xadf402a9, 0x0989}, // ubengali {0xadf4d422, 0x0625}, // alefhamzabelowarabic {0xae04e5ad, 0x0a15}, // kagurmukhi {0xae1f7b0a, 0x2076}, // sixsuperior {0xae23dd7b, 0x1eaf}, // abreveacute {0xae30147f, 0x0908}, // iideva {0xae56317c, 0x24ae}, // sparen {0xae6f7e74, 0x031b}, // horncmb {0xae7c975f, 0x249a}, // nineteenperiod {0xae8f4e4c, 0x0406}, // afii10055 {0xaeb06274, 0x0423}, // Ucyrillic {0xaec173e8, 0x03b8}, // theta {0xaee16fb6, 0xfe4f}, // underscorewavy {0xaef4b475, 0x1edf}, // ohornhookabove {0xaef8393d, 0x0664}, // fourarabic {0xaf01f370, 0x278e}, // fivecircleinversesansserif {0xaf2073fd, 0x2103}, // centigrade {0xaf3552ce, 0x3072}, // hihiragana {0xaf36c6b1, 0x30cd}, // nekatakana {0xaf4df0df, 0xfc0e}, // tehmeemisolatedarabic {0xaf5710c9, 0x00c0}, // Agrave {0xaf5b123d, 0x032d}, // circumflexbelowcmb {0xaf5ce08f, 0x00e0}, // agrave {0xaf788850, 0x00fc}, // udieresis {0xaf7abcb1, 0x05b9}, // holam {0xaf8a8524, 0x0455}, // dzecyrillic {0xafa14924, 0x33d3}, // lxsquare {0xafaa365c, 0x30be}, // zokatakana {0xafb28009, 0x03e2}, // Sheicoptic {0xafb8e89a, 0x0a68}, // twogurmukhi {0xafbbfcac, 0xff71}, // akatakanahalfwidth {0xafbd0738, 0x305d}, // sohiragana {0xafc9b657, 0x0e17}, // thothahanthai {0xb000150a, 0xfe96}, // tehfinalarabic {0xb01f8020, 0x0666}, // sixarabic {0xb026a3ef, 0x30b3}, // kokatakana {0xb0309f24, 0xfee3}, // meeminitialarabic {0xb032be97, 0x047b}, // omegaroundcyrillic {0xb033a837, 0x0079}, // y {0xb03640f2, 0x2252}, // approxequalorimage {0xb0522c01, 0x278f}, // sixcircleinversesansserif {0xb0791aaf, 0x09f3}, // rupeesignbengali {0xb0a20aff, 0x22db}, // greaterequalorless {0xb0c33454, 0x028a}, // upsilonlatin {0xb0efaba6, 0x0a97}, // gagujarati {0xb107bdf6, 0x304b}, // kahiragana {0xb1240d86, 0x0474}, // afii10148 {0xb145d406, 0x327b}, // hieuhacirclekorean {0xb169c9ac, 0x1eed}, // uhornhookabove {0xb1722e49, 0x3006}, // ideographicclose {0xb199f9f3, 0x314a}, // chieuchkorean {0xb1a83745, 0x246e}, // fifteencircle {0xb1a9eaa4, 0x1eb7}, // abrevedotbelow {0xb1b08c26, 0x2020}, // dagger {0xb1b2e578, 0xff13}, // threemonospace {0xb1c3eac2, 0x1e8c}, // Xdieresis {0xb1e18633, 0x0e2d}, // oangthai {0xb1eda93c, 0x09e2}, // lvocalicvowelsignbengali {0xb1fa6226, 0x0a9a}, // cagujarati {0xb225a8bc, 0x0947}, // evowelsigndeva {0xb243894e, 0x21d1}, // arrowdblup {0xb25639c1, 0x2534}, // SF070000 {0xb2566e08, 0x064d}, // afii57453 {0xb256786e, 0x03f2}, // sigmalunatesymbolgreek {0xb25b34dc, 0x0e1a}, // bobaimaithai {0xb26943db, 0x0420}, // afii10034 {0xb27e91f4, 0x01bb}, // twostroke {0xb27fe618, 0xfb03}, // f_f_i {0xb290d64a, 0xfe88}, // alefhamzabelowfinalarabic {0xb2bbd0d4, 0xfeb0}, // zainfinalarabic {0xb2cc02c2, 0x1e38}, // Ldotbelowmacron {0xb2d79f3e, 0x00f9}, // ugrave {0xb2d7f27b, 0x0652}, // afii57458 {0xb2d95c63, 0x2518}, // SF040000 {0xb2f3aff0, 0x0946}, // eshortvowelsigndeva {0xb3178333, 0x00da}, // Uacute {0xb321fe9c, 0x21e3}, // arrowdashdown {0xb3329e90, 0x313e}, // rieulthieuthkorean {0xb33c41bc, 0x018c}, // dtopbar {0xb340e2fe, 0x04a5}, // enghecyrillic {0xb341da2f, 0x1e36}, // Ldotbelow {0xb345c512, 0xfea4}, // hahmedialarabic {0xb369c9bd, 0x2423}, // blank {0xb36f3f4e, 0x054d}, // Seharmenian {0xb3880287, 0x05d6}, // zayinhebrew {0xb38b59bc, 0x0ac0}, // iivowelsigngujarati {0xb3a3592e, 0x21e5}, // arrowtabright {0xb3dbcf55, 0x323d}, // ideographicenterpriseparen {0xb3e6b497, 0x03c9}, // omega {0xb3ed41be, 0x328f}, // ideographearthcircle {0xb3f4ae6c, 0x1e9e}, // germandblS {0xb40169ac, 0x05b0}, // sheva22 {0xb405e3e3, 0x0439}, // afii10075 {0xb41baecc, 0x2487}, // twentyparen {0xb427632e, 0x05b3}, // hatafqamats1b {0xb4344c30, 0x090f}, // edeva {0xb43bb55a, 0x3263}, // rieulcirclekorean {0xb448d464, 0x0391}, // Alpha {0xb457e11d, 0xfb00}, // f_f {0xb45a5763, 0x201b}, // quoteleftreversed {0xb45ef9b7, 0x03c0}, // pi {0xb497903a, 0x01dd}, // eturned {0xb4a55071, 0x1e7d}, // vtilde {0xb4a6b289, 0x2235}, // because {0xb4a7f99d, 0x0954}, // acutedeva {0xb4a9d27d, 0x05d2}, // afii57666 {0xb4c0dc86, 0x0e48}, // maiekthai {0xb4c2484c, 0x05dc}, // lamed {0xb4c667bc, 0xff61}, // periodhalfwidth {0xb4c72b2a, 0x0215}, // udblgrave {0xb4e21f31, 0x2198}, // arrowdownright {0xb500deca, 0x1e41}, // mdotaccent {0xb510d684, 0x1e80}, // Wgrave {0xb526b685, 0x22bf}, // righttriangle {0xb52e7c1d, 0x091e}, // nyadeva {0xb53ca7e2, 0x326c}, // phieuphcirclekorean {0xb58e59d7, 0x24ad}, // rparen {0xb5af274f, 0x064a}, // afii57450 {0xb5b94593, 0x010d}, // ccaron {0xb5c458a3, 0x05b8}, // qamatsqatanwidehebrew {0xb5f24e31, 0xff5a}, // zmonospace {0xb600bed1, 0x3024}, // fourhangzhou {0xb6052cdb, 0x010b}, // cdotaccent {0xb61c54b4, 0x24e4}, // ucircle {0xb64312f2, 0x00a2}, // cent {0xb6443d26, 0x0622}, // afii57410 {0xb647ed9e, 0x01d7}, // Udieresisacute {0xb652184e, 0x0e4b}, // maichattawathai {0xb6588f1c, 0x247c}, // nineparen {0xb66bf9b9, 0x33dc}, // svsquare {0xb673fbb5, 0x038e}, // Upsilontonos {0xb67e35c8, 0x0121}, // gdotaccent {0xb6bb2a6b, 0x0116}, // Edot {0xb6d45c54, 0xff7a}, // kokatakanahalfwidth {0xb6f322b3, 0x05e5}, // afii57685 {0xb6f9554e, 0x3205}, // pieupparenkorean {0xb6f9c67c, 0x0464}, // Eiotifiedcyrillic {0xb6fea9e7, 0xff3f}, // underscoremonospace {0xb70f3f60, 0xff4e}, // nmonospace {0xb711b601, 0x039d}, // Nu {0xb719922a, 0x067e}, // afii57506 {0xb71d84e2, 0x3167}, // nieunsioskorean {0xb726c42e, 0xfb49}, // shindageshhebrew {0xb72e5846, 0x1edb}, // ohornacute {0xb73606f5, 0x0463}, // afii10194 {0xb7400632, 0x33aa}, // kpasquare {0xb747ebc8, 0x2310}, // revlogicalnot {0xb755a24e, 0x310e}, // kbopomofo {0xb7934eea, 0x01c5}, // Dzcaron {0xb7affc1f, 0x0418}, // afii10026 {0xb7b78fdd, 0x2463}, // fourcircle {0xb7bd89d3, 0x0491}, // gheupturncyrillic {0xb7d20c6c, 0x215c}, // threeeighths {0xb7e9bb2b, 0x30fe}, // voicediterationkatakana {0xb80991a9, 0x04d6}, // Iebrevecyrillic {0xb81d8e8c, 0xfb31}, // betdagesh {0xb855cda8, 0x3397}, // dlsquare {0xb85a6427, 0x0650}, // kasraarabic {0xb8632720, 0x0e07}, // ngonguthai {0xb879d78f, 0xfe32}, // endashvertical {0xb894f4d6, 0x01a0}, // Ohorn {0xb8972176, 0x04bb}, // shhacyrillic {0xb89948ac, 0x0a93}, // ogujarati {0xb8be7e03, 0x2039}, // guilsinglleft {0xb8fa96e6, 0x0110}, // Dslash {0xb8ff412c, 0xfef8}, // lamalefhamzaabovefinalarabic {0xb902d285, 0x053a}, // Zhearmenian {0xb90dcf8c, 0xff6a}, // esmallkatakanahalfwidth {0xb910864a, 0x2032}, // minute {0xb921c241, 0xfeca}, // ainfinalarabic {0xb92ccc5d, 0x2469}, // tencircle {0xb9305b2b, 0x3174}, // pieupsioskiyeokkorean {0xb96268cb, 0x00de}, // Thorn {0xb9808b18, 0x09c1}, // uvowelsignbengali {0xb9927e88, 0x3382}, // muasquare {0xb99f8f9e, 0xfeeb}, // hehinitialarabic {0xb9b2e314, 0x0498}, // Zedescendercyrillic {0xb9b4563d, 0x24b3}, // xparen {0xb9c5eece, 0x05bc}, // dageshhebrew {0xb9d8b5d9, 0xfba4}, // hehhamzaaboveisolatedarabic {0xb9dbedd2, 0x317b}, // siosnieunkorean {0xb9e5ea71, 0x314c}, // thieuthkorean {0xb9e8b13e, 0x25a0}, // filledbox {0xb9f42560, 0x0964}, // danda {0xb9f5b462, 0x0990}, // aibengali {0xba1bcecd, 0x0176}, // Ycircumflex {0xba1f80d6, 0x21e1}, // arrowdashup {0xba21ad27, 0xfb3a}, // finalkafdagesh {0xba4eb5f9, 0x0055}, // U {0xba544632, 0x05db}, // afii57675 {0xba5871eb, 0x033e}, // tildeverticalcmb {0xba60a3b8, 0x0902}, // anusvaradeva {0xba7e1049, 0x01d9}, // Udieresiscaron {0xba8d69d2, 0x232a}, // angleright {0xbaa24d97, 0x05e0}, // afii57680 {0xbaa7aa4c, 0xfedc}, // kafmedialarabic {0xbac7de75, 0x1ed3}, // ocircumflexgrave {0xbad44ddc, 0x004f}, // O {0xbad7d685, 0x04b8}, // Cheverticalstrokecyrillic {0xbad97612, 0x03af}, // iotatonos {0xbadf80e2, 0x06f5}, // fivepersian {0xbafeb301, 0x0422}, // Tecyrillic {0xbb28e2ea, 0x1eb2}, // Abrevehookabove {0xbb30f37e, 0x0218}, // Scommaaccent {0xbb6353b2, 0x0332}, // lowlinecmb {0xbb72d76e, 0x0139}, // Lacute {0xbb906e01, 0x3266}, // sioscirclekorean {0xbb970588, 0x266f}, // musicsharpsign {0xbba252f7, 0x0106}, // Cacute {0xbbae7b40, 0x3172}, // pieupkiyeokkorean {0xbbb9d0f4, 0x0934}, // llladeva {0xbbd8677b, 0x330d}, // karoriisquare {0xbbdbcb55, 0x0a6f}, // ninegurmukhi {0xbbdc86be, 0xfb2b}, // shinsindot {0xbc0d2781, 0x0a1f}, // ttagurmukhi {0xbc1b1166, 0x2558}, // SF500000 {0xbc280da2, 0x1e79}, // utildeacute {0xbc3510eb, 0x317f}, // pansioskorean {0xbc45cf9a, 0x02a4}, // dezh {0xbc75336c, 0x21a9}, // arrowhookright {0xbc78e14f, 0x24b0}, // uparen {0xbcd2c61b, 0x064c}, // dammatanarabic {0xbd0f6f71, 0x004c}, // L {0xbd1a9441, 0x3235}, // ideographicspecialparen {0xbd1abdb6, 0x0184}, // Tonesix {0xbd2d2e5f, 0x054e}, // Vewarmenian {0xbd30ce0c, 0x2641}, // earth {0xbd4d0860, 0x320a}, // khieukhparenkorean {0xbd54bd2d, 0x3208}, // cieucparenkorean {0xbd569183, 0x0182}, // Btopbar {0xbd5dbcc1, 0x0151}, // odblacute {0xbd5ee257, 0x01b7}, // Ezh {0xbd85b57b, 0x21a8}, // arrowupdownbase {0xbd8f8d24, 0x064b}, // fathatanarabic {0xbd906fab, 0x041f}, // Pecyrillic {0xbd98b80f, 0x25c8}, // whitediamondcontainingblacksmalldiamond {0xbdc1280a, 0x24be}, // Icircle {0xbdd372da, 0x318b}, // yuyekorean {0xbde8281d, 0x3276}, // cieucacirclekorean {0xbe3e45cf, 0xfb58}, // pehinitialarabic {0xbe663ca6, 0x2470}, // seventeencircle {0xbe7a58ae, 0x3203}, // rieulparenkorean {0xbea937fd, 0x25bc}, // blackdownpointingtriangle {0xbec6916e, 0x011c}, // Gcircumflex {0xbedd6640, 0x00d9}, // Ugrave {0xbf12496a, 0x0985}, // abengali {0xbf156070, 0x04e2}, // Imacroncyrillic {0xbf26dc61, 0x041d}, // Encyrillic {0xbf2dca30, 0x3082}, // mohiragana {0xbf3cff90, 0x0425}, // afii10039 {0xbf5cef43, 0x01ee}, // Ezhcaron {0xbf673175, 0x01fd}, // aeacute {0xbf87a284, 0x00bf}, // questiondown {0xbf897387, 0x2273}, // greaterorequivalent {0xbf8f3598, 0x25a6}, // squareorthogonalcrosshatchfill {0xbf934ed3, 0x04e0}, // Dzeabkhasiancyrillic {0xbf97194e, 0x010a}, // Cdot {0xbf9bc7bd, 0xfb59}, // pehmedialarabic {0xbf9c1926, 0x0627}, // alefarabic {0xbfc69ab7, 0xff18}, // eightmonospace {0xbfd3ede4, 0x0396}, // Zeta {0xbffa52a3, 0x33c7}, // cosquare {0xc006a810, 0x062a}, // teharabic {0xc008508a, 0xff1c}, // lessmonospace {0xc00a3b07, 0x24bc}, // Gcircle {0xc0126352, 0x0661}, // onearabic {0xc03e102c, 0x3012}, // postalmark {0xc059a094, 0x0626}, // yehhamzaabovearabic {0xc0668ba8, 0x202e}, // afii61575 {0xc07e7e42, 0x24a6}, // kparen {0xc084bd84, 0x1e29}, // hcedilla {0xc092fb91, 0x1e95}, // zlinebelow {0xc09823db, 0x016f}, // uring {0xc09889a1, 0x1e11}, // dcedilla {0xc0a2bc69, 0x2564}, // SF470000 {0xc0a93f4f, 0x0e2c}, // lochulathai {0xc0bd9f90, 0x094a}, // oshortvowelsigndeva {0xc0c043bd, 0x3008}, // anglebracketleft {0xc0c1496c, 0x029e}, // kturned {0xc0cbe66a, 0x33b7}, // mvsquare {0xc0d444a4, 0x3220}, // oneideographicparen {0xc0dcb90f, 0x062e}, // khaharabic {0xc0efe98c, 0x2191}, // arrowup {0xc0fb3832, 0x25ab}, // H18551 {0xc131664b, 0x30e4}, // yakatakana {0xc1425417, 0x317a}, // sioskiyeokkorean {0xc1641f79, 0xfe4d}, // lowlinedashed {0xc1835ca2, 0x02d3}, // ringhalfleftcentered {0xc191ae65, 0x0470}, // Psicyrillic {0xc1aa3399, 0x2a06}, // unionsqtext {0xc1c1cd87, 0xff2e}, // Nmonospace {0xc1d325d6, 0x05d8}, // tet {0xc1e02cdd, 0x0594}, // zaqefqatanhebrew {0xc1e3fd2d, 0x05d5}, // vav {0xc1e4c743, 0x3057}, // sihiragana {0xc1ec1451, 0x03c3}, // sigma {0xc1f9ede7, 0x05a3}, // munahhebrew {0xc2089a04, 0x05b7}, // patah1d {0xc21675c5, 0x0317}, // acutebelowcmb {0xc21e92b6, 0x2265}, // greaterequal {0xc2352e98, 0x0554}, // Keharmenian {0xc25217c2, 0xfeff}, // zerowidthjoiner {0xc25a58a0, 0x0a28}, // nagurmukhi {0xc25a7d39, 0x2663}, // club {0xc2658d7c, 0x3395}, // mulsquare {0xc26d6fce, 0x20a9}, // won {0xc283f2c3, 0x03bc}, // mugreek {0xc29c269a, 0x326d}, // hieuhcirclekorean {0xc2c391b3, 0x25b2}, // triagup {0xc2d0d165, 0x0137}, // kcommaaccent {0xc2db7e0f, 0x04a0}, // Kabashkircyrillic {0xc327f9ff, 0x239b}, // parenlefttp {0xc32ea721, 0x061f}, // afii57407 {0xc36634d0, 0x09f9}, // sixteencurrencydenominatorbengali {0xc3722d19, 0x23ad}, // bracerightbt {0xc3751bae, 0x25ab}, // whitesmallsquare {0xc375a046, 0x05b0}, // shevahebrew {0xc391e9a8, 0xfe50}, // commasmall {0xc3c94bba, 0x306a}, // nahiragana {0xc3d9dd70, 0xfe43}, // whitecornerbracketleftvertical {0xc3df4586, 0x0903}, // visargadeva {0xc3eb9abd, 0x02c6}, // circumflex {0xc3edb597, 0x24bb}, // Fcircle {0xc3f1c1ff, 0x00e3}, // atilde {0xc3f76044, 0xff7c}, // sikatakanahalfwidth {0xc3f8f5bb, 0x04e3}, // imacroncyrillic {0xc3fbb2ce, 0x025e}, // eopenreversedclosed {0xc4004762, 0x328a}, // ideographmooncircle {0xc4289b41, 0x25a5}, // squareverticalfill {0xc43e9d0c, 0x1e26}, // Hdieresis {0xc4494fb1, 0x098b}, // rvocalicbengali {0xc459127a, 0x2174}, // fiveroman {0xc460226d, 0xfb34}, // hedagesh {0xc4607843, 0x25ca}, // lozenge {0xc4991f6f, 0x03d0}, // betasymbolgreek {0xc49bedba, 0x1e22}, // Hdotaccent {0xc4bd396f, 0xff98}, // rikatakanahalfwidth {0xc4cf0400, 0x0ac3}, // rvocalicvowelsigngujarati {0xc4d48fb7, 0x0a06}, // aagurmukhi {0xc510ccfb, 0x0327}, // cedillacmb {0xc51e03d1, 0x0e2a}, // sosuathai {0xc5233a99, 0xff41}, // amonospace {0xc52d9608, 0x0409}, // afii10058 {0xc541abe3, 0x0409}, // Ljecyrillic {0xc560e83e, 0x1e4c}, // Otildeacute {0xc575fbd8, 0x3303}, // aarusquare {0xc577ce75, 0xff5d}, // bracerightmonospace {0xc579feb1, 0x03bf}, // omicron {0xc5904240, 0x1ee9}, // uhornacute {0xc594a84a, 0x0a85}, // agujarati {0xc5a57fbd, 0x0178}, // Ydieresis {0xc5b52809, 0x25ac}, // filledrect {0xc5c558c0, 0x2593}, // dkshade {0xc5df0b88, 0x0aae}, // magujarati {0xc5e2935b, 0x30bf}, // takatakana {0xc616ce34, 0x1e83}, // wacute {0xc618c356, 0x005f}, // underscore {0xc6231f67, 0x3117}, // zbopomofo {0xc62d494f, 0x042b}, // afii10045 {0xc65b9029, 0x0012}, // controlDC2 {0xc65e4473, 0x0300}, // gravecomb {0xc6649ea6, 0x263b}, // blacksmilingface {0xc6730a47, 0x3230}, // ideographicsunparen {0xc6a18663, 0x2173}, // fourroman {0xc6a33bcf, 0x23a4}, // bracketrighttp {0xc6bb9cde, 0x03c1}, // rho {0xc6c2ca67, 0x0537}, // Eharmenian {0xc6db1db1, 0x0a94}, // augujarati {0xc6ddc5a6, 0x0334}, // tildeoverlaycmb {0xc6e9fa39, 0x064a}, // yeharabic {0xc6fbfdac, 0x025a}, // schwahook {0xc703d8e7, 0x33b8}, // kvsquare {0xc71e49b3, 0x23a5}, // bracketrightex {0xc74688aa, 0x24dc}, // mcircle {0xc74a8cc7, 0x05b5}, // tserequarterhebrew {0xc74f4c99, 0x0298}, // bilabialclick {0xc7515b37, 0x0132}, // IJ {0xc755c80f, 0xff67}, // asmallkatakanahalfwidth {0xc75bc6a7, 0x01e8}, // Kcaron {0xc7618f62, 0x05b3}, // hatafqamats28 {0xc76816e4, 0x0566}, // zaarmenian {0xc76c439e, 0x0115}, // ebreve {0xc76ec8b2, 0x0e1c}, // phophungthai {0xc77c2828, 0x2206}, // Delta {0xc786ef31, 0x095b}, // zadeva {0xc78887c7, 0x1e08}, // Ccedillaacute {0xc78fe323, 0x0698}, // afii57508 {0xc798936b, 0xfc73}, // tehnoonfinalarabic {0xc7b3573a, 0x1e2f}, // idieresisacute {0xc7daee30, 0x09b7}, // ssabengali {0xc7e20869, 0x0aee}, // eightgujarati {0xc7ed01af, 0x33a5}, // mcubedsquare {0xc7f07bcf, 0x248f}, // eightperiod {0xc7f0b4c8, 0x0406}, // Icyrillic {0xc7fb5fe5, 0x05b2}, // afii57800 {0xc812d1b7, 0x041b}, // afii10029 {0xc82c0a32, 0x026f}, // mturned {0xc834804d, 0x2475}, // twoparen {0xc8488aa4, 0x05b0}, // shevawidehebrew {0xc84db89c, 0x2013}, // endash {0xc85fce80, 0x0901}, // candrabindudeva {0xc86d3a57, 0xff31}, // Qmonospace {0xc875e6fd, 0x040c}, // afii10061 {0xc88f7d57, 0x05b3}, // hatafqamatsnarrowhebrew {0xc89d4f1f, 0x0006}, // controlACK {0xc8ae6fb2, 0x0e26}, // luthai {0xc8b50d48, 0x21d4}, // dblarrowleft {0xc8c2c42c, 0x0162}, // Tcedilla {0xc8c687a4, 0xfb4b}, // vavholamhebrew {0xc8cf912e, 0xfe59}, // parenleftsmall {0xc8fcce82, 0x0424}, // Efcyrillic {0xc8fdfe4b, 0x0914}, // audeva {0xc9315b90, 0x0338}, // soliduslongoverlaycmb {0xc93304ec, 0x2176}, // sevenroman {0xc9366418, 0x1e7e}, // Vdotbelow {0xc948d9f2, 0x01fe}, // Oslashacute {0xc948dd49, 0x0417}, // Zecyrillic {0xc94ac55a, 0xfb4e}, // perafehebrew {0xc94ceb7c, 0x1eca}, // Idotbelow {0xc956ff7e, 0x1e7b}, // umacrondieresis {0xc997284d, 0x03d3}, // Upsilonacutehooksymbolgreek {0xc997d626, 0xfe3d}, // dblanglebracketleftvertical {0xc9d02325, 0x2283}, // propersuperset {0xc9d7e9b6, 0x064c}, // afii57452 {0xc9d96803, 0x3278}, // khieukhacirclekorean {0xc9e8cf5f, 0xfebf}, // dadinitialarabic {0xc9ea8b89, 0x305b}, // sehiragana {0xc9eb1227, 0x321c}, // cieucuparenkorean {0xca07e9ca, 0x02dd}, // hungarumlaut {0xca0b3331, 0x1e5f}, // rlinebelow {0xca2dd9fa, 0x2590}, // rtblock {0xca5ed753, 0x0269}, // iotalatin {0xca65e972, 0x0646}, // noonarabic {0xca9389a5, 0xa75b}, // roundr {0xcab40374, 0x1e1f}, // fdotaccent {0xcabe62a6, 0x0e16}, // thothungthai {0xcac3bcb6, 0x33a8}, // moverssquaredsquare {0xcac4b1a9, 0x32a8}, // ideographicrightcircle {0xcad1f345, 0x01bd}, // tonefive {0xcae44cee, 0x0013}, // controlDC3 {0xcaf66d1c, 0x33b4}, // pvsquare {0xcb1a38a0, 0x226b}, // muchgreater {0xcb1b6c03, 0x0a5e}, // fagurmukhi {0xcb1e3324, 0x042d}, // afii10047 {0xcb267db3, 0x3221}, // twoideographicparen {0xcb281438, 0x33ae}, // radoverssquare {0xcb2edf2d, 0x220f}, // product {0xcb4fc444, 0x03f0}, // kappasymbolgreek {0xcb56efb7, 0x015c}, // Scircumflex {0xcb5b537a, 0x0412}, // afii10019 {0xcb669b9c, 0x1ee2}, // Ohorndotbelow {0xcb72660a, 0xff1e}, // greatermonospace {0xcb75245d, 0x1e48}, // Nlinebelow {0xcb88e590, 0x013c}, // lcedilla {0xcb8bc7f1, 0x002b}, // plus {0xcbada403, 0x0429}, // Shchacyrillic {0xcc11d7b0, 0x000c}, // controlFF {0xcc261604, 0x04a2}, // Endescendercyrillic {0xcc3139de, 0x33d1}, // squareln {0xcc3accb9, 0x05d8}, // tethebrew {0xcc3b7b5c, 0x0649}, // alefmaksuraarabic {0xcc447b1d, 0x0296}, // glottalstopinverted {0xcc8c13e9, 0x25c0}, // blackleftpointingtriangle {0xcc993e5c, 0x025c}, // eopenreversed {0xcca8fd16, 0x09e3}, // llvocalicvowelsignbengali {0xccaa74e1, 0xfb7d}, // tchehmedialarabic {0xccac0ec6, 0x300b}, // dblanglebracketright {0xccc389ea, 0xfb30}, // alefdageshhebrew {0xccc85a27, 0x0a81}, // candrabindugujarati {0xcd07b41d, 0x05bc}, // dagesh {0xcd30953c, 0x203c}, // exclamdbl {0xcd37d58c, 0x24e3}, // tcircle {0xcd415c99, 0x0e55}, // fivethai {0xcd499038, 0x33a2}, // kmsquaredsquare {0xcd54eec2, 0x06f4}, // fourpersian {0xcd5fb77d, 0x0185}, // tonesix {0xcd64e087, 0x266b}, // musicalnotedbl {0xcd75d5eb, 0x2551}, // SF240000 {0xcd7ce3d0, 0x24a7}, // lparen {0xcd85d846, 0x1eec}, // Uhornhookabove {0xcd9d27ad, 0x24c7}, // Rcircle {0xcd9f5a2c, 0x0028}, // parenleft {0xcda0c667, 0x2018}, // quoteleft {0xcdae6ea2, 0xff59}, // ymonospace {0xcdbb64f4, 0x2105}, // afii61248 {0xcdd2cfab, 0x24b4}, // yparen {0xcdd44c7f, 0x33a4}, // cmcubedsquare {0xcde56fe0, 0x05b6}, // segol {0xcdea4ff0, 0x03d4}, // Upsilondieresishooksymbolgreek {0xcdf0bcd8, 0x0e1e}, // phophanthai {0xcdfd40ec, 0x0180}, // bstroke {0xce074882, 0x0668}, // afii57400 {0xce4d2d1e, 0x2563}, // SF230000 {0xce6d06c6, 0x0aab}, // phagujarati {0xce6f0d59, 0x3272}, // mieumacirclekorean {0xce79a056, 0x3339}, // herutusquare {0xce8dac39, 0x25a8}, // squareupperrighttolowerleftfill {0xce942ad9, 0x09a6}, // dabengali {0xcea39f20, 0x02d5}, // downtackmod {0xcedf2a68, 0x0157}, // rcedilla {0xcee9759d, 0x043a}, // afii10076 {0xcef01870, 0x0171}, // udblacute {0xcef10e83, 0x046a}, // Yusbigcyrillic {0xcef67881, 0x200c}, // zerowidthnonjoiner {0xcf235874, 0x030c}, // caroncmb {0xcf4c6b71, 0x02d4}, // uptackmod {0xcf6550b0, 0xfb4a}, // tavdageshhebrew {0xcf6a5e7c, 0x323e}, // ideographicresourceparen {0xcf738908, 0x011d}, // gcircumflex {0xcf848334, 0x0453}, // afii10100 {0xcf8cbf6b, 0x0195}, // hv {0xcf9b96b5, 0x03bd}, // nu {0xcfb1da5d, 0xff89}, // nokatakanahalfwidth {0xcfc386a6, 0x00db}, // Ucircumflex {0xcfc400d6, 0x06d2}, // yehbarreearabic {0xcfd8a703, 0xfe61}, // asterisksmall {0xcfe519cb, 0x309b}, // voicedmarkkana {0xcfe64e44, 0x0668}, // eighthackarabic {0xcff88b7d, 0x05b8}, // qamatsqatannarrowhebrew {0xd0096386, 0x25b3}, // whiteuppointingtriangle {0xd0227bd1, 0x0199}, // khook {0xd02a9cfe, 0x0105}, // aogonek {0xd031b297, 0x24e9}, // zcircle {0xd03ef2b0, 0x316b}, // rieulpieupsioskorean {0xd0417b9a, 0x0494}, // Ghemiddlehookcyrillic {0xd044dddd, 0x0a9d}, // jhagujarati {0xd04ad0f0, 0x263c}, // sun {0xd04cc01e, 0x0561}, // aybarmenian {0xd0511b87, 0x0e4c}, // thanthakhatthai {0xd056aca3, 0xff9a}, // rekatakanahalfwidth {0xd06b6bb7, 0x096a}, // fourdeva {0xd07a803b, 0x09aa}, // pabengali {0xd0847e20, 0x05c4}, // upperdothebrew {0xd087e60f, 0x0158}, // Rcaron {0xd0897bb6, 0x0579}, // chaarmenian {0xd0c5df61, 0x05b4}, // hiriq14 {0xd0ce4edc, 0x09e9}, // threebengali {0xd0d6e6c0, 0xff6c}, // yasmallkatakanahalfwidth {0xd0e3648a, 0xfd3e}, // parenleftaltonearabic {0xd133ff70, 0x01a1}, // ohorn {0xd1373ca2, 0x0648}, // wawarabic {0xd13d9bf5, 0xfe37}, // braceleftvertical {0xd13faec5, 0x05e1}, // samekh {0xd14fc185, 0x045b}, // afii10108 {0xd17987dd, 0x0543}, // Cheharmenian {0xd18447d8, 0x0663}, // threearabic {0xd18966b1, 0x0a82}, // anusvaragujarati {0xd18d83de, 0x0aa3}, // nnagujarati {0xd190d310, 0x0a35}, // vagurmukhi {0xd191827c, 0x0e39}, // sarauuthai {0xd1acdf44, 0xfb94}, // gafinitialarabic {0xd1d7231f, 0x04bc}, // Cheabkhasiancyrillic {0xd1d9da71, 0x30ea}, // rikatakana {0xd2337241, 0x05b6}, // segol1f {0xd247ef8b, 0x3243}, // ideographicreachparen {0xd254c368, 0x0443}, // ucyrillic {0xd2658bcb, 0x05b9}, // holamquarterhebrew {0xd26b0e16, 0x2321}, // integralbt {0xd26ef570, 0x310f}, // hbopomofo {0xd293868c, 0x019b}, // lambdastroke {0xd297cb79, 0x30b7}, // sikatakana {0xd2b4c516, 0x30da}, // pekatakana {0xd2c0e1bc, 0x0150}, // Odblacute {0xd2cbfc99, 0x05b7}, // patahhebrew {0xd2e2a716, 0x03ec}, // Shimacoptic {0xd2eaddf5, 0x0633}, // seenarabic {0xd2f253f5, 0xfe40}, // anglebracketrightvertical {0xd2f3cdf3, 0x1e0e}, // Dlinebelow {0xd304784a, 0x05d3}, // dalet {0xd308b167, 0x1e5b}, // rdotbelow {0xd310fcc1, 0x04e9}, // obarredcyrillic {0xd3145153, 0xfeec}, // hehmedialarabic {0xd326ec6d, 0x2237}, // proportion {0xd3342503, 0x30bd}, // sokatakana {0xd33cb244, 0x02cd}, // macronlowmod {0xd35ba6fb, 0x04be}, // Chedescenderabkhasiancyrillic {0xd3730282, 0xff64}, // ideographiccommaleft {0xd3797e0f, 0x24db}, // lcircle {0xd37b4bcb, 0x041c}, // afii10030 {0xd3a5ba29, 0x062e}, // afii57422 {0xd3c22da1, 0x01b5}, // Zstroke {0xd3c6a66e, 0x05e4}, // pe {0xd3cfef4c, 0x0427}, // afii10041 {0xd3e84c23, 0x201c}, // quotedblleft {0xd421361f, 0x067e}, // peharabic {0xd4273f62, 0x30fd}, // iterationkatakana {0xd44f2d4c, 0xff9b}, // rokatakanahalfwidth {0xd45c6c89, 0x3079}, // behiragana {0xd467b0a3, 0x0131}, // dotlessi {0xd48c064b, 0x0599}, // pashtahebrew {0xd48dad4d, 0x01e2}, // AEmacron {0xd4b2bb68, 0x0145}, // Ncedilla {0xd4d3eb56, 0x255e}, // SF360000 {0xd4e86e58, 0x1ef7}, // yhookabove {0xd4e92fa8, 0x0623}, // alefhamzaabovearabic {0xd514a0e0, 0x318c}, // yuikorean {0xd5189135, 0x1e73}, // udieresisbelow {0xd52f1d8f, 0x24cb}, // Vcircle {0xd54b71bd, 0x0a6e}, // eightgurmukhi {0xd574af4c, 0x318e}, // araeaekorean {0xd57a206a, 0x00f2}, // ograve {0xd58ee561, 0x04f3}, // uhungarumlautcyrillic {0xd5b6f4bf, 0x3163}, // ikorean {0xd5b7a706, 0x1e13}, // dcircumflexbelow {0xd5da03ab, 0x0123}, // gcommaaccent {0xd5dc1f0e, 0x24a5}, // jparen {0xd5e6a2b4, 0x200f}, // afii300 {0xd6067104, 0x05bd}, // siluqlefthebrew {0xd6180af1, 0x0023}, // numbersign {0xd6191adc, 0x02ce}, // gravelowmod {0xd6480a61, 0x0e46}, // maiyamokthai {0xd65815d1, 0x04f5}, // chedieresiscyrillic {0xd6674587, 0xfea8}, // khahmedialarabic {0xd66f3b98, 0x1ebd}, // etilde {0xd67d357f, 0x0e23}, // roruathai {0xd67dc19d, 0x1e05}, // bdotbelow {0xd682be7e, 0xfe54}, // semicolonsmall {0xd689f58d, 0x0024}, // dollar {0xd68be98a, 0xff8f}, // makatakanahalfwidth {0xd6a99b0e, 0x05aa}, // yerahbenyomolefthebrew {0xd6c4c66e, 0x3262}, // tikeutcirclekorean {0xd6c7e5a6, 0x03b0}, // upsilondieresistonos {0xd6df6252, 0xfef4}, // yehmedialarabic {0xd6e234de, 0x044d}, // afii10095 {0xd7151c8a, 0x040b}, // afii10060 {0xd71af0cf, 0x00af}, // overscore {0xd72c6112, 0x0036}, // six {0xd73b3901, 0x02da}, // ring {0xd7425de1, 0x0a1d}, // jhagurmukhi {0xd771b953, 0x3107}, // mbopomofo {0xd7a40cc3, 0x315c}, // ukorean {0xd7b7f8a3, 0x3094}, // vuhiragana {0xd7b8c7af, 0x05b8}, // qamatsquarterhebrew {0xd7bf0d2a, 0x308b}, // ruhiragana {0xd7cebade, 0x01b1}, // Upsilonafrican {0xd7d268b5, 0x314e}, // hieuhkorean {0xd7ece605, 0x2553}, // SF520000 {0xd813ab1a, 0x3176}, // pieupcieuckorean {0xd816387d, 0x2178}, // nineroman {0xd8171429, 0x013e}, // lcaron {0xd817c39d, 0x0664}, // fourhackarabic {0xd824acfb, 0x05de}, // memhebrew {0xd849e14d, 0x3052}, // gehiragana {0xd84afb0a, 0x00d1}, // Ntilde {0xd85534fc, 0x02ca}, // secondtonechinese {0xd8708805, 0x01ba}, // ezhtail {0xd890928b, 0x0053}, // S {0xd893adf8, 0x0580}, // reharmenian {0xd8964f73, 0x043d}, // encyrillic {0xd89879e8, 0x2116}, // afii61352 {0xd8a1ab6d, 0x03ab}, // Upsilondieresis {0xd8b1d2bf, 0x0177}, // ycircumflex {0xd8faed0d, 0x30ef}, // wakatakana {0xd9038cdb, 0x32a4}, // ideographichighcircle {0xd90a7039, 0x06af}, // afii57509 {0xd91584cd, 0xfe31}, // emdashvertical {0xd92072b9, 0x0493}, // ghestrokecyrillic {0xd92d9608, 0x0acd}, // viramagujarati {0xd9321a82, 0xfb01}, // f_i {0xd932c15c, 0x30ac}, // gakatakana {0xd93c2940, 0x33cf}, // ktsquare {0xd94d846e, 0x321a}, // phieuphaparenkorean {0xd94faf13, 0x0188}, // chook {0xd95c2f59, 0x04bd}, // cheabkhasiancyrillic {0xd9697a13, 0x328b}, // ideographfirecircle {0xd98cc91f, 0x0307}, // dotaccentcmb {0xd991004f, 0x0e4f}, // fongmanthai {0xd99e3976, 0x249f}, // dparen {0xd9ba695c, 0xff70}, // katahiraprolongmarkhalfwidth {0xd9d63664, 0x0189}, // Dafrican {0xd9e83df4, 0x096b}, // fivedeva {0xd9eba56d, 0x03b3}, // gamma {0xda15411c, 0x0304}, // macroncmb {0xda2037e1, 0x1e01}, // aringbelow {0xda3670ae, 0x3347}, // mansyonsquare {0xda39b9df, 0x013d}, // Lcaron {0xda48ff7e, 0x00bb}, // guillemotright {0xda4e1891, 0x228b}, // supersetnotequal {0xda55d0f3, 0x0a69}, // threegurmukhi {0xda620e6e, 0xfca2}, // tehhahinitialarabic {0xda734cc8, 0x232b}, // deleteleft {0xda85eaa3, 0x2070}, // zerosuperior {0xda94576a, 0x0999}, // ngabengali {0xda94a677, 0x0634}, // afii57428 {0xda99b3d7, 0x30d1}, // pakatakana {0xdab46527, 0x21e9}, // arrowdownwhite {0xdac4a95a, 0x002f}, // slash {0xdac8670b, 0x011e}, // Gbreve {0xdad5813e, 0x24bf}, // Jcircle {0xdaf9ae21, 0x03e7}, // kheicoptic {0xdb00acb2, 0x04dc}, // Zhedieresiscyrillic {0xdb07430c, 0x1eac}, // Acircumflexdotbelow {0xdb15243d, 0xfb38}, // tetdagesh {0xdb180684, 0x059d}, // gereshmuqdamhebrew {0xdb19f222, 0x1e30}, // Kacute {0xdb36c0cb, 0x00c1}, // Aacute {0xdb46a061, 0x044f}, // afii10097 {0xdb4843d8, 0x0140}, // ldotaccent {0xdb491e12, 0x3201}, // nieunparenkorean {0xdb4ecb82, 0x06a4}, // afii57505 {0xdb5fdfb2, 0x09cd}, // viramabengali {0xdb9c2f74, 0x3063}, // tusmallhiragana {0xdb9dda85, 0xfb3b}, // kafdageshhebrew {0xdba170e8, 0x0998}, // ghabengali {0xdbae2c8c, 0x2277}, // greaterorless {0xdbc3c473, 0x001a}, // controlSUB {0xdbc6ef9a, 0x05b2}, // hatafpatah23 {0xdbc71338, 0xff01}, // exclammonospace {0xdbcb0069, 0x338a}, // pfsquare {0xdbf12380, 0x2460}, // onecircle {0xdc0071a3, 0xfb46}, // tsadidageshhebrew {0xdc05ec50, 0x30f5}, // kasmallkatakana {0xdc0ad3ae, 0x012d}, // ibreve {0xdc0c240d, 0xff9e}, // voicedmarkkanahalfwidth {0xdc0c9e85, 0xff9f}, // semivoicedmarkkanahalfwidth {0xdc3d7ac8, 0x04a7}, // pemiddlehookcyrillic {0xdc41d3b3, 0x05ab}, // olehebrew {0xdc54447c, 0x307c}, // bohiragana {0xdc6ca9b3, 0x0584}, // keharmenian {0xdc7756d1, 0x0077}, // w {0xdc7d1de8, 0xfba9}, // hehmedialaltonearabic {0xdc7f6ca5, 0x0624}, // wawhamzaabovearabic {0xdcc5c006, 0x055a}, // apostrophearmenian {0xdce03f6b, 0x261e}, // pointingindexrightwhite {0xdcefaeeb, 0x228a}, // subsetnotequal {0xdd07775c, 0x3223}, // fourideographicparen {0xdd07a474, 0x00b3}, // threesuperior {0xdd21d4c1, 0x039b}, // Lambda {0xdd2fee63, 0x0aad}, // bhagujarati {0xdd4e62a4, 0x0a96}, // khagujarati {0xdd55f861, 0x2560}, // SF420000 {0xdd64bab7, 0x3080}, // muhiragana {0xdd68d3ef, 0x00a5}, // yen {0xdd8a8538, 0x0a26}, // dagurmukhi {0xdd9a009b, 0x2016}, // dblverticalbar {0xdda2fef7, 0x33db}, // srsquare {0xdda8f1e0, 0x33d4}, // mbsquare {0xddd89deb, 0xff4d}, // mmonospace {0xdde406ed, 0x23a8}, // braceleftmid {0xddfdd08a, 0x30a7}, // esmallkatakana {0xddfea657, 0x0049}, // I {0xddffcb32, 0x1e60}, // Sdotaccent {0xde111430, 0x2271}, // notgreaternorequal {0xde159412, 0x2605}, // blackstar {0xde3de1bb, 0xfede}, // lamfinalarabic {0xde4643cf, 0x0ac5}, // ecandravowelsigngujarati {0xde5450d1, 0xff88}, // nekatakanahalfwidth {0xde6c8dd1, 0x2223}, // divides {0xde91c7ac, 0xfb35}, // vavdagesh {0xdea63325, 0x0e0c}, // chochoethai {0xdea93241, 0x0385}, // dieresistonos {0xdeab4b8b, 0x05ad}, // dehihebrew {0xdebc4010, 0xfcd5}, // noonmeeminitialarabic {0xdebf0df4, 0x05f0}, // afii57716 {0xdecde878, 0x1e52}, // Omacronacute {0xdee80462, 0xffe5}, // yenmonospace {0xdee969b3, 0x3001}, // ideographiccomma {0xdef14eee, 0x020e}, // Oinvertedbreve {0xdef351c2, 0x020c}, // Odblgrave {0xdef92b6a, 0x3349}, // mirisquare {0xdf08e8b4, 0xff15}, // fivemonospace {0xdf09c757, 0x0186}, // Oopen {0xdf1ee74b, 0xff81}, // tikatakanahalfwidth {0xdf243dad, 0x044c}, // softsigncyrillic {0xdf46fba9, 0x01a4}, // Phook {0xdf80589a, 0x3217}, // chieuchaparenkorean {0xdf8c6402, 0x0e45}, // lakkhangyaothai {0xdf9eaf7a, 0x33bc}, // muwsquare {0xdfad5d93, 0x22c0}, // logicalandtext {0xdfaf476d, 0x0167}, // tbar {0xdfb9632c, 0x3144}, // pieupsioskorean {0xdff819d0, 0xfe8c}, // yehhamzaabovemedialarabic {0xdffe3761, 0x1e14}, // Emacrongrave {0xe0130535, 0x316c}, // rieulpansioskorean {0xe019189f, 0x0994}, // aubengali {0xe0197d92, 0x0a4b}, // oomatragurmukhi {0xe0343a59, 0x0323}, // dotbelowcomb {0xe03a2368, 0x019f}, // Ocenteredtilde {0xe0489c79, 0x017f}, // longs {0xe0560cdf, 0x1e19}, // ecircumflexbelow {0xe065671a, 0x1e0a}, // Ddotaccent {0xe07dfee5, 0x04f4}, // Chedieresiscyrillic {0xe0800244, 0xfb69}, // ttehmedialarabic {0xe0987417, 0x24dd}, // ncircle {0xe0ac4869, 0x3225}, // sixideographicparen {0xe0c42e1f, 0x3357}, // wattosquare {0xe0cf3aca, 0x1e1d}, // ecedillabreve {0xe0d114bf, 0x04b6}, // Chedescendercyrillic {0xe0dbd3b5, 0x2494}, // thirteenperiod {0xe0ec0106, 0x05a6}, // merkhakefulahebrew {0xe0ec7a9f, 0x01a6}, // yr {0xe0f957bb, 0x0644}, // afii57444 {0xe10a53c6, 0x0aa8}, // nagujarati {0xe13f2d93, 0x3026}, // sixhangzhou {0xe173c1f2, 0x1e12}, // Dcircumflexbelow {0xe180ca73, 0x1e43}, // mdotbelow {0xe1b37094, 0x0629}, // afii57417 {0xe1bbda55, 0x040e}, // Ushortcyrillic {0xe1bf1035, 0x0536}, // Zaarmenian {0xe20234a2, 0x012c}, // Ibreve {0xe20c937f, 0x041a}, // Kacyrillic {0xe20deadd, 0x047c}, // Omegatitlocyrillic {0xe2234dec, 0xff52}, // rmonospace {0xe22682ea, 0x3260}, // kiyeokcirclekorean {0xe22a6510, 0x1e8e}, // Ydotaccent {0xe23968a4, 0x04b3}, // hadescendercyrillic {0xe25773d9, 0x04d3}, // adieresiscyrillic {0xe259edda, 0x0628}, // afii57416 {0xe25f57e9, 0xfe9a}, // thehfinalarabic {0xe26168f6, 0x1e82}, // Wacute {0xe28a564c, 0x044f}, // iacyrillic {0xe28eea2e, 0x1e51}, // omacrongrave {0xe2924f7e, 0x0a67}, // onegurmukhi {0xe2a7b092, 0x3213}, // pieupaparenkorean {0xe2b99909, 0x0e14}, // dodekthai {0xe2cfeeb5, 0x0301}, // acutecomb {0xe2eccaa5, 0x0059}, // Y {0xe2ef1bbf, 0x2197}, // arrowupright {0xe2fc74df, 0x0533}, // Gimarmenian {0xe2ff3ec5, 0xfb8d}, // rrehfinalarabic {0xe2ffc4d4, 0x2661}, // heartsuitwhite {0xe3356dd7, 0x1e54}, // Pacute {0xe35f1369, 0xfe5c}, // bracerightsmall {0xe3708e14, 0xfed3}, // fehinitialarabic {0xe37c75f9, 0x03c7}, // chi {0xe38423f1, 0x01ab}, // tpalatalhook {0xe387ebf8, 0xff94}, // yakatakanahalfwidth {0xe39adf52, 0x05b7}, // patahnarrowhebrew {0xe39bb5ba, 0x0258}, // ereversed {0xe3a00fb0, 0x0aa2}, // ddhagujarati {0xe3a0394c, 0x05b3}, // afii57802 {0xe3bf40b5, 0x21c5}, // arrowupleftofdown {0xe3cbb73f, 0x0459}, // afii10106 {0xe3cddac1, 0x0621}, // hamzalowarabic {0xe3d5ad06, 0x1ec0}, // Ecircumflexgrave {0xe3dd99f7, 0x0596}, // tipehahebrew {0xe3fae787, 0x0587}, // echyiwnarmenian {0xe3fe00d6, 0x2170}, // oneroman {0xe401701f, 0x3016}, // whitelenticularbracketleft {0xe41d9109, 0x3089}, // rahiragana {0xe424f4cb, 0x0969}, // threedeva {0xe42a588e, 0x0e27}, // wowaenthai {0xe42a6647, 0x0a71}, // addakgurmukhi {0xe433c6bf, 0x042c}, // afii10046 {0xe44aea0b, 0x0219}, // scommaaccent {0xe44ed7aa, 0x2481}, // fourteenparen {0xe468e60e, 0x33bd}, // mwsquare {0xe47b4b2e, 0xfecb}, // aininitialarabic {0xe4896ee4, 0x09c0}, // iivowelsignbengali {0xe4924345, 0xff63}, // cornerbracketrighthalfwidth {0xe49ba568, 0x090c}, // lvocalicdeva {0xe4a8920f, 0x0014}, // controlDC4 {0xe4c6b94a, 0x0550}, // Reharmenian {0xe4c91eec, 0x1ea7}, // acircumflexgrave {0xe4d0a5c5, 0x2171}, // tworoman {0xe4de0824, 0x090b}, // rvocalicdeva {0xe4e78bbf, 0x0e33}, // saraamthai {0xe4e90251, 0xfb41}, // samekhdagesh {0xe4f1acea, 0x24d7}, // hcircle {0xe5034999, 0xff55}, // umonospace {0xe504c22f, 0x01a9}, // Esh {0xe506e1eb, 0x2493}, // twelveperiod {0xe5107e85, 0xff92}, // mekatakanahalfwidth {0xe5116fc8, 0x2472}, // nineteencircle {0xe514f37f, 0x03be}, // xi {0xe51bd3a3, 0x0163}, // tcedilla {0xe5287de7, 0x3173}, // pieuptikeutkorean {0xe5322bbf, 0x25b2}, // blackuppointingtriangle {0xe5431590, 0x2296}, // minuscircle {0xe54a2cdd, 0x201e}, // quotedblbase {0xe5694805, 0x3161}, // eukorean {0xe56f3e08, 0x1e9b}, // slongdotaccent {0xe5779de7, 0x0666}, // afii57398 {0xe578bf9d, 0x066d}, // asteriskaltonearabic {0xe5850206, 0x2226}, // notparallel {0xe59889e5, 0x014b}, // eng {0xe59f1c1d, 0x2664}, // spadesuitwhite {0xe59f1f71, 0x2203}, // thereexists {0xe5dca65a, 0x04aa}, // Esdescendercyrillic {0xe5e0ac19, 0x0a74}, // ekonkargurmukhi {0xe5eb1828, 0x25e6}, // openbullet {0xe5f403ac, 0x0981}, // candrabindubengali {0xe5f51e2d, 0x0156}, // Rcedilla {0xe61a323e, 0x21d2}, // arrowdblright {0xe61dad29, 0x017b}, // Zdotaccent {0xe62fb889, 0x2524}, // SF090000 {0xe6699f03, 0x025d}, // eopenreversedhook {0xe6743f55, 0x011a}, // Ecaron {0xe6861695, 0x018a}, // Dhook {0xe68d35b4, 0x0436}, // afii10072 {0xe68e2cfd, 0x306b}, // nihiragana {0xe6910141, 0x06f1}, // onepersian {0xe6936418, 0xfb2f}, // alefqamatshebrew {0xe6a0587d, 0x3222}, // threeideographicparen {0xe6a445c8, 0xfcd2}, // noonjeeminitialarabic {0xe6b00dbd, 0x060c}, // commaarabic {0xe6bd7d55, 0x04f0}, // Udieresiscyrillic {0xe6beeaab, 0x2667}, // clubsuitwhite {0xe6d26878, 0x0663}, // threehackarabic {0xe6eee43a, 0x031a}, // leftangleabovecmb {0xe70bdf5d, 0x1e85}, // wdieresis {0xe72762a6, 0x3127}, // ibopomofo {0xe74e8d5b, 0x02d0}, // colontriangularmod {0xe75de72d, 0x0a4d}, // halantgurmukhi {0xe796e6c1, 0x032f}, // breveinvertedbelowcmb {0xe7a9201c, 0x24e5}, // vcircle {0xe7abb869, 0x05b0}, // sheva115 {0xe7f3b395, 0x24d8}, // icircle {0xe80a2426, 0x3116}, // rbopomofo {0xe80eec90, 0x0942}, // uuvowelsigndeva {0xe832e25c, 0x03ef}, // deicoptic {0xe836846a, 0x20a1}, // colonsign {0xe8445eb9, 0x05e5}, // finaltsadihebrew {0xe84e29b1, 0xfef5}, // lamalefmaddaaboveisolatedarabic {0xe853fc35, 0x3177}, // pieupthieuthkorean {0xe871a9d4, 0x03e3}, // sheicoptic {0xe872f83d, 0x02a0}, // qhook {0xe87409fd, 0xfe8b}, // yehhamzaaboveinitialarabic {0xe885d69b, 0x1e58}, // Rdotaccent {0xe893423b, 0x202c}, // afii61573 {0xe894f25c, 0x03a1}, // Rho {0xe89d944f, 0x043a}, // kacyrillic {0xe8aff9ae, 0x24b7}, // Bcircle {0xe8d4db79, 0x2320}, // integraltp {0xe8d6bd29, 0x0621}, // afii57409 {0xe8ec3154, 0x2490}, // nineperiod {0xe8ef5782, 0x3092}, // wohiragana {0xe8f0c584, 0x05d1}, // afii57665 {0xe8f5ca9b, 0x05b1}, // hatafsegolnarrowhebrew {0xe8f7e9bf, 0x320f}, // nieunaparenkorean {0xe903bc23, 0xfb36}, // zayindageshhebrew {0xe90424fe, 0x2479}, // sixparen {0xe927829f, 0x0953}, // gravedeva {0xe92a9522, 0x0060}, // grave {0xe93b2c93, 0x09c8}, // aivowelsignbengali {0xe9598c36, 0x018e}, // Ereversed {0xe96c43a5, 0x00d4}, // Ocircumflex {0xe977a63b, 0x0591}, // etnahtalefthebrew {0xe9860674, 0x2467}, // eightcircle {0xe994ec07, 0x1e88}, // Wdotbelow {0xe9955c1b, 0x2109}, // fahrenheit {0xe997ce80, 0x03d6}, // pisymbolgreek {0xe9b8fb39, 0x256a}, // SF540000 {0xe9c5c9e3, 0x0928}, // nadeva {0xe9dc1b2b, 0x3162}, // yikorean {0xe9f5bb0b, 0x1e40}, // Mdotaccent {0xe9fd5bd7, 0x02d1}, // colontriangularhalfmod {0xe9fe0986, 0xfe91}, // behinitialarabic {0xea0e9b0d, 0x3077}, // puhiragana {0xea11b5f2, 0x05d7}, // hethebrew {0xea281c50, 0xfb3b}, // kafdagesh {0xea281f0f, 0xfb43}, // pefinaldageshhebrew {0xea4521ba, 0x1e99}, // yring {0xea469ad4, 0x0641}, // feharabic {0xea4bf6ca, 0x25b5}, // whiteuppointingsmalltriangle {0xea505c24, 0x006b}, // k {0xea723c32, 0x05b7}, // patahwidehebrew {0xea828d24, 0x0ac4}, // rrvocalicvowelsigngujarati {0xea8df8fe, 0xff09}, // parenrightmonospace {0xeaaa8586, 0x05b6}, // segolhebrew {0xeabb8dad, 0xfeb3}, // seeninitialarabic {0xeabdd2cd, 0xff02}, // quotedblmonospace {0xeacd0b4a, 0xfb1f}, // doubleyodpatah {0xeade9ba5, 0x2113}, // afii61289 {0xeb0445d5, 0x043f}, // afii10081 {0xeb095515, 0x0452}, // afii10099 {0xeb4a0523, 0x056a}, // zhearmenian {0xeb4fdea3, 0xfc08}, // behmeemisolatedarabic {0xeb576d94, 0x21de}, // pageup {0xeb701704, 0x2014}, // emdash {0xeb71d801, 0x30f3}, // nkatakana {0xebeccb02, 0x00dd}, // Yacute {0xec20a331, 0x096c}, // sixdeva {0xec450aad, 0x3211}, // rieulaparenkorean {0xec4fc0c5, 0x0173}, // uogonek {0xec78ec45, 0x05a4}, // mahapakhhebrew {0xec820a21, 0x05b4}, // hiriqquarterhebrew {0xec8ae366, 0x0987}, // ibengali {0xec967081, 0x040a}, // Njecyrillic {0xecad584f, 0x01a8}, // tonetwo {0xecc21039, 0x0a98}, // ghagujarati {0xecce5cae, 0x056b}, // iniarmenian {0xecd385c5, 0x03a8}, // Psi {0xecda4c6b, 0x0622}, // alefmaddaabovearabic {0xecddb27b, 0x23d0}, // vextendsingle {0xecddb519, 0x05db}, // kaf {0xecef01e0, 0x1e59}, // rdotaccent {0xed102125, 0x24c0}, // Kcircle {0xed1afc7c, 0x05b2}, // hatafpatah2f {0xed2b4a43, 0x00aa}, // ordfeminine {0xed4bb321, 0x313f}, // rieulphieuphkorean {0xed65e3bb, 0x057a}, // peharmenian {0xed729d82, 0x049e}, // Kastrokecyrillic {0xed796a9e, 0x0407}, // afii10056 {0xed8b66db, 0x040b}, // Tshecyrillic {0xed9bf511, 0x063a}, // afii57434 {0xedfaec74, 0xfe69}, // dollarsmall {0xee22e47f, 0x00bd}, // onehalf {0xee3352d3, 0x05b0}, // afii57799 {0xee339d2e, 0x2025}, // twodotenleader {0xee421e32, 0x0660}, // zeroarabic {0xee6c8858, 0x3168}, // nieunpansioskorean {0xee7a31f8, 0x220b}, // suchthat {0xee8d09d6, 0xff12}, // twomonospace {0xee900f0f, 0x0462}, // afii10146 {0xee9f1e99, 0x02b7}, // wsuperior {0xeeb00f1b, 0x0063}, // c {0xeeb5ef47, 0x24c2}, // Mcircle {0xeeda5b48, 0x00a6}, // brokenbar {0xeeeef128, 0x062f}, // afii57423 {0xeeef7f7c, 0x01b6}, // zstroke {0xef03e03f, 0x32a3}, // ideographiccorrectcircle {0xef22f61a, 0x06f0}, // zeropersian {0xef24cf3c, 0x00a8}, // dieresis {0xef2800a0, 0x00cc}, // Igrave {0xef33d78e, 0x25a1}, // H22073 {0xef3a179c, 0x020a}, // Iinvertedbreve {0xef636ee0, 0x05da}, // finalkaf {0xefa03eab, 0x00c6}, // AE {0xefc57067, 0x0260}, // ghook {0xefd65ddd, 0x2033}, // second {0xefd69119, 0x044e}, // iucyrillic {0xefd88572, 0x1ecb}, // idotbelow {0xefe0e3fd, 0xfb01}, // fi {0xeff59b38, 0x0397}, // Eta {0xeff843d0, 0x25a3}, // squarewhitewithsmallblack {0xf00181f3, 0x305c}, // zehiragana {0xf00455e8, 0x1e86}, // Wdotaccent {0xf0045976, 0x3178}, // kapyeounpieupkorean {0xf0213847, 0x3383}, // masquare {0xf0248bca, 0x0640}, // tatweelarabic {0xf029041c, 0x3017}, // whitelenticularbracketright {0xf0412bb8, 0x04d0}, // Abrevecyrillic {0xf04a093b, 0xff66}, // wokatakanahalfwidth {0xf04c3677, 0xfe62}, // plussmall {0xf04d9cf4, 0x308c}, // rehiragana {0xf064a013, 0x047e}, // Otcyrillic {0xf0673e49, 0x096f}, // ninedeva {0xf0757f39, 0x030a}, // ringcmb {0xf08a28a9, 0xfe4e}, // lowlinecenterline {0xf09092b0, 0x3185}, // ssanghieuhkorean {0xf091911a, 0x223d}, // reversedtilde {0xf098620b, 0x066a}, // percentarabic {0xf0a5507a, 0x03d5}, // phisymbolgreek {0xf0ac995b, 0x337c}, // syouwaerasquare {0xf0b806fd, 0xfb7c}, // tchehinitialarabic {0xf0c10455, 0x0645}, // meemarabic {0xf0d79471, 0x0201}, // adblgrave {0xf0e2f076, 0x04cb}, // Chekhakassiancyrillic {0xf0ec6a42, 0x0302}, // circumflexcmb {0xf0f2a82b, 0x1e8a}, // Xdotaccent {0xf0fcc511, 0x3398}, // klsquare {0xf1116d2e, 0xfe41}, // cornerbracketleftvertical {0xf1200f87, 0x05e6}, // tsadi {0xf13a2d0d, 0x0119}, // eogonek {0xf1410096, 0x1e1a}, // Etildebelow {0xf144c7a3, 0x249d}, // bparen {0xf15ab600, 0x05bb}, // qubuts18 {0xf16238a6, 0x04de}, // Zedieresiscyrillic {0xf1aad12e, 0x0638}, // afii57432 {0xf1b08e52, 0x20ab}, // dong {0xf1b0be56, 0x20a2}, // cruzeiro {0xf1b5f5d1, 0x05b5}, // tserehebrew {0xf1dd7830, 0x033d}, // xabovecmb {0xf1ddaa7d, 0x0995}, // kabengali {0xf1e94d64, 0x064e}, // fathaarabic {0xf1eb4f66, 0x0116}, // Edotaccent {0xf1f78ce7, 0x226a}, // muchless {0xf2118c6c, 0x0635}, // sadarabic {0xf232181a, 0x2640}, // venus {0xf237f0f1, 0xff29}, // Imonospace {0xf23a5b68, 0x0130}, // Idot {0xf24a3a6b, 0x05b8}, // qamats1c {0xf2558e7a, 0x230a}, // floorleftbig {0xf2620ee8, 0x1e07}, // blinebelow {0xf26e5910, 0x045e}, // ushortcyrillic {0xf2b4963c, 0x09b0}, // rabengali {0xf2b826ec, 0x0449}, // shchacyrillic {0xf2c1d44e, 0x05be}, // maqafhebrew {0xf2c69081, 0x016e}, // Uring {0xf2dd8deb, 0x248d}, // sixperiod {0xf2e23a0c, 0xfb57}, // pehfinalarabic {0xf2e7f536, 0x0329}, // verticallinebelowcmb {0xf2f52e6c, 0x00ce}, // Icircumflex {0xf2f6e905, 0x24cd}, // Xcircle {0xf3086f4b, 0x2030}, // perthousand {0xf311fe21, 0xfece}, // ghainfinalarabic {0xf315dbae, 0xfe3c}, // blacklenticularbracketrightvertical {0xf336d994, 0xfef3}, // yehinitialarabic {0xf3527249, 0xfb67}, // ttehfinalarabic {0xf3935843, 0xff26}, // Fmonospace {0xf399cd14, 0x0074}, // t {0xf3c08521, 0x0431}, // afii10066 {0xf3ce4ef0, 0x014a}, // Eng {0xf3cfe996, 0x05b8}, // qamatsde {0xf3ef0654, 0x2160}, // Oneroman {0xf41c3e87, 0x3182}, // yesieungsioskorean {0xf4266df0, 0x2253}, // imageorapproximatelyequal {0xf4584280, 0x05ea}, // tav {0xf4637345, 0x207a}, // plussuperior {0xf467a09a, 0x3066}, // tehiragana {0xf4728f62, 0x06f9}, // ninepersian {0xf47778a3, 0x0958}, // qadeva {0xf47c7f06, 0x05a5}, // merkhalefthebrew {0xf498c20b, 0xfb2c}, // shindageshshindothebrew {0xf4a2e6c9, 0xff8e}, // hokatakanahalfwidth {0xf4bd2095, 0xfb02}, // f_l {0xf4c721dd, 0x0415}, // afii10022 {0xf4d1afd1, 0x015b}, // sacute {0xf4d731e8, 0x0e2b}, // hohipthai {0xf4d7dcfe, 0x05b0}, // sheva {0xf4ea5918, 0x0423}, // afii10037 {0xf4f5b85f, 0x05bd}, // afii57839 {0xf4fec4c5, 0x2026}, // ellipsis {0xf4fecbee, 0x3152}, // yaekorean {0xf526b2bc, 0x09f5}, // twonumeratorbengali {0xf53d898f, 0x0122}, // Gcedilla {0xf54df907, 0x02e8}, // tonebarlowmod {0xf573def2, 0x25ba}, // blackrightpointingpointer {0xf573f1ec, 0x24a4}, // iparen {0xf59704d9, 0xff4f}, // omonospace {0xf59943f5, 0x01d4}, // ucaron {0xf59f95da, 0x0399}, // Iota {0xf5a6729d, 0x247e}, // elevenparen {0xf5ab4f6d, 0x0458}, // afii10105 {0xf5c2a87b, 0x0a14}, // augurmukhi {0xf5c40812, 0x2019}, // quoteright {0xf5cad972, 0x1ea6}, // Acircumflexgrave {0xf5e83826, 0x0986}, // aabengali {0xf5f606a8, 0x316e}, // mieumpieupkorean {0xf5f79af6, 0x23a3}, // bracketleftbt {0xf5fe99ee, 0x2017}, // underscoredbl {0xf61328eb, 0x2580}, // upblock {0xf61a2336, 0x0157}, // rcommaaccent {0xf6228c58, 0x20a3}, // franc {0xf6271ec7, 0x0429}, // afii10043 {0xf630815e, 0x0577}, // shaarmenian {0xf64f0a5d, 0x30f9}, // vekatakana {0xf64f6666, 0xff44}, // dmonospace {0xf6545660, 0x3333}, // huiitosquare {0xf655e1cb, 0x316a}, // rieultikeutkorean {0xf66aa028, 0x215d}, // fiveeighths {0xf67e1ed1, 0x01a3}, // oi {0xf6886180, 0x3216}, // cieucaparenkorean {0xf68c8679, 0x3043}, // ismallhiragana {0xf68fb68d, 0x215b}, // oneeighth {0xf6909b76, 0x24a1}, // fparen {0xf6b386e5, 0x1e3c}, // Lcircumflexbelow {0xf6c0ec85, 0x1e5c}, // Rdotbelowmacron {0xf6f2a8b6, 0x0289}, // ubar {0xf7114d7b, 0x2502}, // SF110000 {0xf7440454, 0x045e}, // afii10110 {0xf757213f, 0x01d6}, // udieresismacron {0xf779fd74, 0x1ea0}, // Adotbelow {0xf7887f64, 0x24ba}, // Ecircle {0xf7994ed0, 0x0a6d}, // sevengurmukhi {0xf7c65164, 0x266d}, // musicflatsign {0xf7d4f2e3, 0x1e1e}, // Fdotaccent {0xf7ddf3cd, 0x0a17}, // gagurmukhi {0xf7de3a36, 0x3086}, // yuhiragana {0xf7edf1a3, 0x0403}, // Gjecyrillic {0xf7fe7207, 0x279e}, // arrowrightheavy {0xf7fec616, 0x1ec4}, // Ecircumflextilde {0xf81e4626, 0x0a02}, // bindigurmukhi {0xf8245f14, 0x30e6}, // yukatakana {0xf82ad190, 0x05e4}, // pehebrew {0xf8376f18, 0x0410}, // afii10017 {0xf885c738, 0x30d3}, // bikatakana {0xf8868f94, 0xff8c}, // hukatakanahalfwidth {0xf8892150, 0x04a8}, // Haabkhasiancyrillic {0xf89be814, 0x0abc}, // nuktagujarati {0xf8e483f7, 0x1eb5}, // abrevetilde {0xf8ef289b, 0x21df}, // pagedown {0xf90377b2, 0x3151}, // yakorean {0xf90f516b, 0x0a5b}, // zagurmukhi {0xf9190810, 0x0203}, // ainvertedbreve {0xf929be43, 0x0ab6}, // shagujarati {0xf93a01ea, 0xfe6a}, // percentsmall {0xf952cde5, 0x1eae}, // Abreveacute {0xf95ad1c7, 0x0065}, // e {0xf95b34b0, 0x0660}, // afii57392 {0xf976011b, 0x3399}, // fmsquare {0xf99ebcf4, 0x25c1}, // whiteleftpointingtriangle {0xf9bdabb3, 0x00e2}, // acircumflex {0xf9d67642, 0x00c8}, // Egrave {0xf9e5170b, 0x1eb6}, // Abrevedotbelow {0xf9e8161d, 0x3206}, // siosparenkorean {0xf9eeaebc, 0x002c}, // comma {0xf9f4a348, 0x2279}, // notgreaternorless {0xf9f6f2fe, 0xfe84}, // alefhamzaabovefinalarabic {0xf9f909db, 0x09f1}, // ralowerdiagonalbengali {0xfa1f37f7, 0x207d}, // parenleftsuperior {0xfa3ebdeb, 0xfb8b}, // jehfinalarabic {0xfa46e08a, 0x010a}, // Cdotaccent {0xfa6e953f, 0x0e13}, // nonenthai {0xfa7aad8b, 0x0e34}, // saraithai {0xfa85b29d, 0x0ae6}, // zerogujarati {0xfa8f771c, 0xfe82}, // alefmaddaabovefinalarabic {0xfa932832, 0x1ec9}, // ihookabove {0xfa9cd43f, 0x2488}, // oneperiod {0xfa9f7510, 0x1e6a}, // Tdotaccent {0xfaa7f693, 0xff1b}, // semicolonmonospace {0xfab3dba6, 0x3138}, // ssangtikeutkorean {0xfac03db8, 0x015e}, // Scedilla {0xfac092ef, 0x24de}, // ocircle {0xfad44b21, 0x278d}, // fourcircleinversesansserif {0xfadde282, 0x0539}, // Toarmenian {0xfaf8abd4, 0x05bb}, // qubuts25 {0xfb0a35fb, 0xfb2b}, // afii57695 {0xfb0e1bad, 0x2567}, // SF450000 {0xfb1373b2, 0x30b9}, // sukatakana {0xfb161300, 0x049f}, // kastrokecyrillic {0xfb206015, 0x30b1}, // kekatakana {0xfb2465d5, 0x0468}, // Yuslittleiotifiedcyrillic {0xfb3e0b48, 0x01fc}, // AEacute {0xfb4678bc, 0xfe90}, // behfinalarabic {0xfb5bf4b4, 0x02cf}, // acutelowmod {0xfb5cfdc8, 0x095c}, // dddhadeva {0xfb764dd2, 0x21d3}, // arrowdbldown {0xfb7c1fd7, 0x0485}, // dasiapneumatacyrilliccmb {0xfbcf44c4, 0x018d}, // deltaturned {0xfbd1b93f, 0x33c4}, // squarecc {0xfbd50511, 0x04e8}, // Obarredcyrillic {0xfbf1fcde, 0x03e9}, // horicoptic {0xfc161b2f, 0x2499}, // eighteenperiod {0xfc18556b, 0x02bd}, // commareversedmod {0xfc1a2c97, 0x046c}, // Yusbigiotifiedcyrillic {0xfc2caf5c, 0x2285}, // notsuperset {0xfc3393bc, 0x0124}, // Hcircumflex {0xfc3a32c2, 0x0a8d}, // ecandragujarati {0xfc75d31c, 0x1ec6}, // Ecircumflexdotbelow {0xfc7e1ef8, 0x0952}, // anudattadeva {0xfc7ea01a, 0x04e6}, // Odieresiscyrillic {0xfc8020b6, 0xfb39}, // yoddageshhebrew {0xfc828b2d, 0x1ee4}, // Udotbelow {0xfc9cf271, 0x020d}, // odblgrave {0xfce47bc6, 0x05b7}, // patah {0xfce8ddc1, 0x1e0f}, // dlinebelow {0xfce9ddb5, 0x05aa}, // yerahbenyomohebrew {0xfcf6e2a9, 0x21ea}, // capslock {0xfd00e31a, 0x0303}, // tildecomb {0xfd0eac29, 0x0261}, // gscript {0xfd1397ce, 0x0412}, // Vecyrillic {0xfd166ead, 0x05e0}, // nunhebrew {0xfd2c8feb, 0x1ea4}, // Acircumflexacute {0xfd5ace9a, 0x057b}, // jheharmenian {0xfd6ac237, 0x221d}, // proportional {0xfd77296d, 0x04af}, // ustraightcyrillic {0xfd891a4c, 0x0948}, // aivowelsigndeva {0xfd8944f5, 0x0309}, // hookabovecomb {0xfd89977d, 0x0e50}, // zerothai {0xfd93a170, 0x239c}, // parenleftex {0xfd99bb06, 0xfb3c}, // lameddagesh {0xfdb6c57c, 0x2215}, // divisionslash {0xfdbbbec8, 0x090d}, // ecandradeva {0xfdc83f1f, 0x028d}, // wturned {0xfdd37935, 0x0422}, // afii10036 {0xfdec640d, 0x0640}, // kashidaautoarabic {0xfdf32442, 0x3390}, // Hzsquare {0xfdf4c83e, 0x026e}, // lezh {0xfe3d55df, 0x064f}, // dammaarabic {0xfe407199, 0x2276}, // lessorgreater {0xfe7515f3, 0x03a9}, // Omegagreek {0xfe779a6a, 0x045a}, // afii10107 {0xfea7088a, 0x0628}, // beharabic {0xfeb66fd9, 0xfec7}, // zahinitialarabic {0xfeb7f263, 0x0556}, // Feharmenian {0xfec7bc3b, 0x0651}, // shaddaarabic {0xfee2004d, 0x01fe}, // Ostrokeacute {0xfee5f25e, 0x2126}, // Omega {0xfee9d86c, 0x2295}, // pluscircle {0xfef651f8, 0x0688}, // afii57512 {0xff5dadf4, 0x0193}, // Ghook {0xff81c116, 0x21cd}, // arrowleftdblstroke {0xff8c00d8, 0x3386}, // MBsquare {0xff8f2931, 0x30ae}, // gikatakana {0xff90fc92, 0x0923}, // nnadeva {0xff94689d, 0x04c0}, // palochkacyrillic {0xffe38169, 0x043f}, // pecyrillic {0xfffadc30, 0x2568}, // SF460000 }}; dvisvgm-3.5/src/BasicDVIReader.cpp000066400000000000000000000371151501401750600170500ustar00rootroot00000000000000/************************************************************************* ** BasicDVIReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include "BasicDVIReader.hpp" using namespace std; BasicDVIReader::BasicDVIReader (std::istream &is) : StreamReader(is), _dviVersion(DVI_NONE) { } void BasicDVIReader::throwDVIException(const string &msg) const { throw DVIException(msg + " at position " + to_string(tellg())); } /** Evaluates the next DVI command, and computes the corresponding handler. * @param[out] handler handler for current DVI command * @param[out] param the handler must be called with this parameter * @return opcode of current DVI command */ int BasicDVIReader::evalCommand (CommandHandler &handler, int ¶m) { struct DVICommand { CommandHandler handler; int length; // number of parameter bytes }; /* Each cmdFOO command reads the necessary number of bytes from the stream, so executeCommand doesn't need to know the exact DVI command format. Some cmdFOO methods are used for multiple DVI commands because they only differ in length of their parameters. */ static const DVICommand commands[] = { {&BasicDVIReader::cmdSetChar, 1}, {&BasicDVIReader::cmdSetChar, 2}, // 128-129 {&BasicDVIReader::cmdSetChar, 3}, {&BasicDVIReader::cmdSetChar, 4}, // 130-131 {&BasicDVIReader::cmdSetRule, 8}, // 132 {&BasicDVIReader::cmdPutChar, 1}, {&BasicDVIReader::cmdPutChar, 2}, // 133-134 {&BasicDVIReader::cmdPutChar, 3}, {&BasicDVIReader::cmdPutChar, 4}, // 135-136 {&BasicDVIReader::cmdPutRule, 8}, // 137 {&BasicDVIReader::cmdNop, 0}, // 138 {&BasicDVIReader::cmdBop, 44}, {&BasicDVIReader::cmdEop, 0}, // 139-140 {&BasicDVIReader::cmdPush, 0}, {&BasicDVIReader::cmdPop, 0}, // 141-142 {&BasicDVIReader::cmdRight, 1}, {&BasicDVIReader::cmdRight, 2}, // 143-144 {&BasicDVIReader::cmdRight, 3}, {&BasicDVIReader::cmdRight, 4}, // 145-146 {&BasicDVIReader::cmdW0, 0}, // 147 {&BasicDVIReader::cmdW, 1}, {&BasicDVIReader::cmdW, 2}, // 148-149 {&BasicDVIReader::cmdW, 3}, {&BasicDVIReader::cmdW, 4}, // 150-151 {&BasicDVIReader::cmdX0, 0}, // 152 {&BasicDVIReader::cmdX, 1}, {&BasicDVIReader::cmdX, 2}, // 153-154 {&BasicDVIReader::cmdX, 3}, {&BasicDVIReader::cmdX, 4}, // 155-156 {&BasicDVIReader::cmdDown, 1}, {&BasicDVIReader::cmdDown, 2}, // 157-158 {&BasicDVIReader::cmdDown, 3}, {&BasicDVIReader::cmdDown, 4}, // 159-160 {&BasicDVIReader::cmdY0, 0}, // 161 {&BasicDVIReader::cmdY, 1}, {&BasicDVIReader::cmdY, 2}, // 162-163 {&BasicDVIReader::cmdY, 3}, {&BasicDVIReader::cmdY, 4}, // 164-165 {&BasicDVIReader::cmdZ0, 0}, // 166 {&BasicDVIReader::cmdZ, 1}, {&BasicDVIReader::cmdZ, 2}, // 167-168 {&BasicDVIReader::cmdZ, 3}, {&BasicDVIReader::cmdZ, 4}, // 169-170 {&BasicDVIReader::cmdFontNum, 1}, {&BasicDVIReader::cmdFontNum, 2}, // 235-236 {&BasicDVIReader::cmdFontNum, 3}, {&BasicDVIReader::cmdFontNum, 4}, // 237-238 {&BasicDVIReader::cmdXXX, 1}, {&BasicDVIReader::cmdXXX, 2}, // 239-240 {&BasicDVIReader::cmdXXX, 3}, {&BasicDVIReader::cmdXXX, 4}, // 241-242 {&BasicDVIReader::cmdFontDef, 1}, {&BasicDVIReader::cmdFontDef, 2}, // 243-244 {&BasicDVIReader::cmdFontDef, 3}, {&BasicDVIReader::cmdFontDef, 4}, // 245-246 {&BasicDVIReader::cmdPre, 0}, {&BasicDVIReader::cmdPost, 0}, // 247-248 {&BasicDVIReader::cmdPostPost, 0}, // 249 }; const int opcode = readByte(); if (!isStreamValid() || opcode < 0) // at end of file throw DVIPrematureEOFException(); int num_param_bytes = 0; param = -1; if (opcode >= OP_SETCHAR0 && opcode <= OP_SETCHAR127) { handler = &BasicDVIReader::cmdSetChar0; param = opcode; } else if (opcode >= OP_FNTNUM0 && opcode <= OP_FNTNUM63) { handler = &BasicDVIReader::cmdFontNum0; param = opcode-OP_FNTNUM0; } else if (evalXDVOpcode(opcode, handler)) num_param_bytes = 0; else if (_dviVersion == DVI_PTEX && opcode == OP_DIR) { // direction command set by pTeX? handler = &BasicDVIReader::cmdDir; num_param_bytes = 1; } else if (opcode > OP_POSTPOST) throwDVIException("undefined DVI command (opcode " + to_string(opcode) + ")"); else { const int offset = opcode < OP_FNTNUM0 ? OP_SET1 : (OP_FNTNUM63+1)-(OP_FNTNUM0-OP_SET1); handler = commands[opcode-offset].handler; num_param_bytes = commands[opcode-offset].length; } if (param < 0) param = num_param_bytes; return opcode; } /** Checks if a given opcode belongs to an XDV extension. * @param[in] op the opcode to check * @param[out] handler corresponding command handler if opcode is valid */ bool BasicDVIReader::evalXDVOpcode (int op, CommandHandler &handler) const { static const struct { int min, max; // minimal and maximal opcode in XDV section } xdvranges[] = { {251, 254}, // XDV5 {252, 253}, // XDV6 {252, 254}, // XDV7 }; int index = _dviVersion-DVI_XDV5; if (_dviVersion < DVI_XDV5 || _dviVersion > DVI_XDV7 || op < xdvranges[index].min || op > xdvranges[index].max) return false; static const CommandHandler handlers[] = { &BasicDVIReader::cmdXPic, // 251 (XDV5 only) &BasicDVIReader::cmdXFontDef, // 252 &BasicDVIReader::cmdXGlyphArray, // 253 &BasicDVIReader::cmdXTextAndGlyphs, // 254 (XDV7 only) &BasicDVIReader::cmdXGlyphString // 254 (XDV5 only) }; index = op-251; if (_dviVersion == DVI_XDV5 && op == 254) index++; handler = handlers[index]; return true; } /** Reads a single DVI command from the current position of the input stream and calls the * corresponding cmdFOO method. * @return opcode of the executed command */ int BasicDVIReader::executeCommand () { CommandHandler handler; int param; // parameter of handler int opcode = evalCommand(handler, param); (this->*handler)(param); return opcode; } void BasicDVIReader::executePreamble () { clearStream(); if (isStreamValid()) { seek(0); if (readByte() == OP_PRE) { cmdPre(0); return; } } throwDVIException("invalid DVI file (missing preamble)"); } /** Moves stream pointer to begin of postamble */ void BasicDVIReader::goToPostamble () { clearStream(); if (!isStreamValid()) throwDVIException("invalid DVI file (missing postamble)"); seek(-1, ios::end); // stream pointer to last byte int count=0; while (peek() == DVI_FILL) { // skip fill bytes seek(-1, ios::cur); count++; } if (count < 4) // the standard requires at least 4 trailing fill bytes throwDVIException("missing fill bytes at end of file"); seek(-4, ios::cur); // now at first byte of q (pointer to begin of postamble) uint32_t q = readUnsigned(4); // pointer to begin of postamble seek(q); // now at begin of postamble } /** Reads and executes the commands of the postamble. */ void BasicDVIReader::executePostamble () { goToPostamble(); while (executeCommand() != OP_POSTPOST); // executes all commands until post_post (= 249) is reached } void BasicDVIReader::executePostPost () { clearStream(); // reset all status bits if (!isStreamValid()) throwDVIException("invalid DVI file (missing postpost)"); seek(-1, ios::end); // stream pointer to last byte int count=0; while (peek() == DVI_FILL) { // count trailing fill bytes seek(-1, ios::cur); count++; } if (count < 4) // the standard requires at least 4 trailing fill bytes throwDVIException("missing fill bytes at end of file"); setDVIVersion((DVIVersion)readUnsigned(1)); } void BasicDVIReader::executeFontDefs () { goToPostamble(); seek(1+28, ios::cur); // now on first fontdef or postpost if (peek() != OP_POSTPOST) while (executeCommand() != OP_POSTPOST); } /** Collects and records the file offsets of all bop commands. */ vector BasicDVIReader::collectBopOffsets () { std::vector bopOffsets; goToPostamble(); bopOffsets.push_back(tell()); // also add offset of postamble readByte(); // skip post command uint32_t offset = readUnsigned(4); // offset of final bop while (int32_t(offset) != -1) { // not yet on first bop? bopOffsets.push_back(offset); // record offset seek(offset); // now on previous bop if (readByte() != OP_BOP) throwDVIException("bop offset at "+to_string(offset)+" doesn't point to bop command" ); seek(40, ios::cur); // skip the 10 \count values => now on offset of previous bop uint32_t prevOffset = readUnsigned(4); if ((prevOffset >= offset && int32_t(prevOffset) != -1)) throwDVIException("invalid bop offset at "+to_string(tell()-static_cast(4))); offset = prevOffset; } std::reverse(bopOffsets.begin(), bopOffsets.end()); return bopOffsets; } void BasicDVIReader::executeAllPages () { if (_dviVersion == DVI_NONE) executePostPost(); // get version ID from post_post seek(0); // go to preamble while (executeCommand() != OP_POST); // execute all commands until postamble is reached } void BasicDVIReader::setDVIVersion (DVIVersion version) { _dviVersion = max(_dviVersion, version); switch (_dviVersion) { case DVI_STANDARD: case DVI_PTEX: case DVI_XDV5: case DVI_XDV6: case DVI_XDV7: break; default: throwDVIException("DVI version " + to_string(_dviVersion) + " not supported"); } } ///////////////////////////////////// /** Executes preamble command. * Format: pre i[1] num[4] den[4] mag[4] k[1] x[k] */ void BasicDVIReader::cmdPre (int) { setDVIVersion((DVIVersion)readUnsigned(1)); // identification number seek(12, ios::cur); // skip numerator, denominator, and mag factor uint32_t k = readUnsigned(1); // length of following comment seek(k, ios::cur); // skip comment } /** Executes postamble command. * Format: post p[4] num[4] den[4] mag[4] l[4] u[4] s[2] t[2] */ void BasicDVIReader::cmdPost (int) { seek(28, ios::cur); } /** Executes postpost command. * Format: postpost q[4] i[1] 223's[>= 4] */ void BasicDVIReader::cmdPostPost (int) { seek(4, ios::cur); setDVIVersion((DVIVersion)readUnsigned(1)); // identification byte while (readUnsigned(1) == DVI_FILL); // skip fill bytes (223), eof bit should be set now } /** Executes bop (begin of page) command. * Format: bop c0[+4] ... c9[+4] p[+4] */ void BasicDVIReader::cmdBop (int) {seek(44, ios::cur);} void BasicDVIReader::cmdEop (int) {} void BasicDVIReader::cmdPush (int) {} void BasicDVIReader::cmdPop (int) {} void BasicDVIReader::cmdSetChar0 (int) {} void BasicDVIReader::cmdSetChar (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdPutChar (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdSetRule (int) {seek(8, ios::cur);} void BasicDVIReader::cmdPutRule (int) {seek(8, ios::cur);} void BasicDVIReader::cmdRight (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdDown (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdX0 (int) {} void BasicDVIReader::cmdY0 (int) {} void BasicDVIReader::cmdW0 (int) {} void BasicDVIReader::cmdZ0 (int) {} void BasicDVIReader::cmdX (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdY (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdW (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdZ (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdNop (int) {} void BasicDVIReader::cmdDir (int) {seek(1, ios::cur);} void BasicDVIReader::cmdFontNum0 (int) {} void BasicDVIReader::cmdFontNum (int len) {seek(len, ios::cur);} void BasicDVIReader::cmdXXX (int len) {seek(readUnsigned(len), ios::cur);} /** Executes fontdef command. * Format: fontdef k[len] c[4] s[4] d[4] a[1] l[1] n[a+l] * @param[in] len size of font number variable (in bytes) */ void BasicDVIReader::cmdFontDef (int len) { seek(len+12, ios::cur); // skip font number uint32_t pathlen = readUnsigned(1); // length of font path uint32_t namelen = readUnsigned(1); // length of font name seek(pathlen+namelen, ios::cur); } /** XDV extension: include image or pdf file. * parameters: box[1] matrix[4][6] p[2] len[2] path[l] */ void BasicDVIReader::cmdXPic (int) { seek(1+24+2, ios::cur); uint16_t len = readUnsigned(2); seek(len, ios::cur); } void BasicDVIReader::cmdXFontDef (int) { seek(4+4, ios::cur); uint16_t flags = readUnsigned(2); uint8_t len = readUnsigned(1); if (_dviVersion == DVI_XDV5) len += readUnsigned(1)+readUnsigned(1); seek(len, ios::cur); if (_dviVersion >= DVI_XDV6) seek(4, ios::cur); // skip subfont index if (flags & 0x0200) // colored? seek(4, ios::cur); if (flags & 0x1000) // extend? seek(4, ios::cur); if (flags & 0x2000) // slant? seek(4, ios::cur); if (flags & 0x4000) // embolden? seek(4, ios::cur); if ((flags & 0x0800) && (_dviVersion == DVI_XDV5)) { // variations? uint16_t num_variations = readSigned(2); seek(4*num_variations, ios::cur); } } /** XDV extension: prints an array of characters where each character * can take independent x and y coordinates. * parameters: w[4] n[2] xy[(4+4)n] g[2n] */ void BasicDVIReader::cmdXGlyphArray (int) { seek(4, ios::cur); uint16_t num_glyphs = readUnsigned(2); seek(10*num_glyphs, ios::cur); } /** XDV extension: prints an array/string of characters where each character * can take independent x coordinates whereas all share a single y coordinate. * parameters: w[4] n[2] x[4n] y[4] g[2n] */ void BasicDVIReader::cmdXGlyphString (int) { seek(4, ios::cur); uint16_t num_glyphs = readUnsigned(2); seek(6*num_glyphs, ios::cur); } /** XDV extension: Same as cmdXGlyphArray plus a leading array of UTF-16 characters * that specify the "actual text" represented by the glyphs to be printed. It usually * contains the text with special characters (like ligatures) expanded so that it * can be used for text search, plain text copy & paste etc. This XDV command was * introduced with XeTeX 0.99995 and can be triggered by \\XeTeXgenerateactualtext1. * parameters: l[2] t[2l] w[4] n[2] xy[8n] g[2n] */ void BasicDVIReader::cmdXTextAndGlyphs (int) { uint16_t l = readUnsigned(2); seek(2*l, ios::cur); cmdXGlyphArray(0); } dvisvgm-3.5/src/BasicDVIReader.hpp000066400000000000000000000123231501401750600170470ustar00rootroot00000000000000/************************************************************************* ** BasicDVIReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef BASICDVIREADER_HPP #define BASICDVIREADER_HPP #include #include "Matrix.hpp" #include "MessageException.hpp" #include "StreamReader.hpp" struct DVIException : public MessageException { explicit DVIException (const std::string &msg) : MessageException(msg) {} }; struct DVIPrematureEOFException : public DVIException { explicit DVIPrematureEOFException () : DVIException("premature end of DVI stream") {} }; /** This class provides the basic functionality to read a DVI file. * It just skips all DVI commands and apply any semantic to it. The latter must * be realized by deriving a separate class that implements the cmdXXX template * methods. These are low-level functions that represent the DVI commands and * require to read and evaluate the correct portion of data from the DVI stream. * Since the DVI commands are almost skipped by advancing the file pointer, * running through a DVI file is pretty fast. */ class BasicDVIReader : public StreamReader { protected: using CommandHandler = void (BasicDVIReader::*)(int); enum DVIVersion {DVI_NONE=0, DVI_STANDARD=2, DVI_PTEX=3, DVI_XDV5=5, DVI_XDV6=6, DVI_XDV7=7}; const uint8_t OP_SETCHAR0=0, OP_SETCHAR127=127, OP_SET1=128, OP_BOP=139, OP_EOP=140, OP_FNTNUM0=171, OP_FNTNUM63=234, OP_PRE=247, OP_POST=248, OP_POSTPOST=249, OP_DIR=255, DVI_FILL=223; public: explicit BasicDVIReader (std::istream &is); virtual void executeAllPages (); virtual void executeFontDefs (); virtual double getXPos () const {return 0;} virtual double getYPos () const {return 0;} virtual void finishLine () {} virtual void translateToX (double x) {} virtual void translateToY (double y) {} virtual int stackDepth () const {return 0;} virtual Matrix getPageTransformation () const {return Matrix(1);} virtual unsigned currentPageNumber () const {return 0;} protected: void throwDVIException (const std::string &msg) const; void setDVIVersion (DVIVersion version); DVIVersion getDVIVersion () const {return _dviVersion;} virtual int evalCommand (CommandHandler &handler, int ¶m); virtual int executeCommand (); void executePreamble (); void executePostamble (); void executePostPost (); void goToPostamble (); std::vector collectBopOffsets (); bool evalXDVOpcode (int op, CommandHandler &handler) const; // The following template methods represent the single DVI commands. They // must read the correct chunk of data from the input stream in order to // process the DVI file correctly. virtual void cmdSetChar0 (int c); virtual void cmdSetChar (int len); virtual void cmdPutChar (int len); virtual void cmdSetRule (int len); virtual void cmdPutRule (int len); virtual void cmdNop (int len); virtual void cmdBop (int len); virtual void cmdEop (int len); virtual void cmdPush (int len); virtual void cmdPop (int len); virtual void cmdDir (int len); virtual void cmdRight (int len); virtual void cmdDown (int len); virtual void cmdX0 (int len); virtual void cmdY0 (int len); virtual void cmdW0 (int len); virtual void cmdZ0 (int len); virtual void cmdX (int len); virtual void cmdY (int len); virtual void cmdW (int len); virtual void cmdZ (int len); virtual void cmdFontDef (int len); virtual void cmdFontNum0 (int n); virtual void cmdFontNum (int len); virtual void cmdXXX (int len); virtual void cmdPre (int len); virtual void cmdPost (int len); virtual void cmdPostPost (int len); virtual void cmdXFontDef (int len); // XDV only virtual void cmdXGlyphArray (int len); // XDV only virtual void cmdXGlyphString (int len); // XDV version 5 only virtual void cmdXPic (int len); // XDV version 5 only virtual void cmdXTextAndGlyphs (int len); // XDV version 7 only private: DVIVersion _dviVersion; ///< DVI version of file being processed }; #endif dvisvgm-3.5/src/Bezier.cpp000066400000000000000000000345031501401750600155570ustar00rootroot00000000000000/************************************************************************* ** Bezier.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include "algorithm.hpp" #include "Bezier.hpp" #include "Matrix.hpp" #include "utility.hpp" using namespace std; QuadBezier::QuadBezier () { _points[0] = _points[1] = _points[2] = DPair(0, 0); } QuadBezier::QuadBezier (const DPair &p0, const DPair &p1, const DPair &p2) { setPoints(p0, p1, p2); } void QuadBezier::setPoints(const DPair &p0, const DPair &p1, const DPair &p2) { _points[0] = p0; _points[1] = p1; _points[2] = p2; } /** Returns the value (curve point) at t. */ DPair QuadBezier::valueAt (double t) const { const double s = 1-t; return _points[0]*s*s + _points[1]*2.0*s*t + _points[2]*t*t; } /** Returns the value of the first derivative of the curve at t. */ DPair QuadBezier::derivativeAt (double t) const { return _points[0]*(2*t-2) + _points[1]*(2-4*t) + _points[2]*(2*t); } /** Returns the arc length of the curve from 0 to t. */ double QuadBezier::arclen (double t) const { return math::integral(0, t, 20, [this](double t) -> double { DPair deriv = derivativeAt(t); return sqrt(deriv.x()*deriv.x() + deriv.y()*deriv.y()); }); } //////////////////////////////////////////////////////////////////////////////// CubicBezier::CubicBezier () { _points[0] = _points[1] = _points[2] = _points[3] = DPair(0, 0); } CubicBezier::CubicBezier (const DPair &p0, const DPair &p1, const DPair &p2, const DPair &p3) { setPoints(p0, p1, p2, p3); } /** Creates a subcurve of a given Bézier curve. * @param[in] source original curve to be clipped * @param[in] t0 'time' parameter \f$\in[0,1]\f$ of source curve where the subcurve starts * @param[in] t1 'time' parameter \f$\in[0,1]\f$ of source curve where the subcurve ends */ CubicBezier::CubicBezier (const CubicBezier &source, double t0, double t1) { if (t0 == t1) _points[0] = _points[1] = _points[2] = _points[3] = source.valueAt(t0); else { if (t0 > t1) swap(t0, t1); if (t0 == 0) source.subdivide(t1, this, nullptr); else if (t1 == 1) source.subdivide(t0, nullptr, this); else { CubicBezier subcurve; source.subdivide(t0, nullptr, &subcurve); subcurve.subdivide((t1-t0)/(1-t0), this, nullptr); } } } /** Creates a cubic Bézier from a quadratic one. */ CubicBezier::CubicBezier (const QuadBezier &qbezier) { const DPair &p0 = qbezier.point(0); const DPair &p1 = qbezier.point(1); const DPair &p2 = qbezier.point(2); setPoints(p0, p0+(p1-p0)*2.0/3.0, p2+(p1-p2)*2.0/3.0, p2); } void CubicBezier::setPoints(const DPair &p0, const DPair &p1, const DPair &p2, const DPair &p3) { _points[0] = p0; _points[1] = p1; _points[2] = p2; _points[3] = p3; } void CubicBezier::reverse() { swap(_points[0], _points[3]); swap(_points[1], _points[2]); } DPair CubicBezier::valueAt (double t) const { const double s = 1-t; return _points[0]*s*s*s + _points[1]*3.0*s*s*t + _points[2]*3.0*s*t*t + _points[3]*t*t*t; } /** Returns a value of the Bézier curve's blossom representation. */ DPair CubicBezier::blossomValue (double u, double v, double w) const { const double uv = u*v; const double uw = u*w; const double vw = v*w; const double uvw = u*v*w; return _points[0]*(1.0-u-v-w+uv+uw+vw-uvw) +_points[1]*(u+v+w-2.0*(uv+uw+vw)+3.0*uvw) +_points[2]*(uv+uw+vw-3.0*uvw) +_points[3]*uvw; } /** Splits the curve at t into two sub-curves. */ void CubicBezier::subdivide (double t, CubicBezier *bezier1, CubicBezier *bezier2) const { const double s = 1-t; DPair p01 = _points[0]*s + _points[1]*t; DPair p12 = _points[1]*s + _points[2]*t; DPair p23 = _points[2]*s + _points[3]*t; DPair p012 = p01*s + p12*t; DPair p123 = p12*s + p23*t; DPair p0123 = p012*s + p123*t; if (bezier1) bezier1->setPoints(_points[0], p01, p012, p0123); if (bezier2) bezier2->setPoints(p0123, p123, p23, _points[3]); } /** Approximates the current Bézier curve by a sequence of line segments. * This is done by subdividing the curve several times using De Casteljau's algorithm. * If a sub-curve is almost flat, i.e. \f$\sum\limits_{k=0}^2 |p_{k+1}-p_k| - |p_3-p_0| < \delta\f$, * the curve is not further subdivided. * @param[in] delta threshold where to stop further subdivisions (see description above) * @param[out] p the resulting sequence of points defining the start/end points of the line segments * @param[out] t corresponding curve parameters of the approximated points p: \f$ b(t_i)=p_i \f$ * @return number of points in vector p */ int CubicBezier::approximate (double delta, std::vector &p, vector *t) const { p.push_back(_points[0]); if (t) t->push_back(0); return approximate(delta, 0, 1, p, t); } int CubicBezier::approximate (double delta, double t0, double t1, vector &p, vector *t) const { // compute distance of adjacent control points const double l01 = (_points[1]-_points[0]).length(); const double l12 = (_points[2]-_points[1]).length(); const double l23 = (_points[3]-_points[2]).length(); const double l03 = (_points[3]-_points[0]).length(); if (l01+l12+l23-l03 < delta) { // is curve flat enough? p.push_back(_points[3]); // => store endpoint if (t) t->push_back(t1); } else { // subdivide curve at b(0.5) and approximate the resulting parts separately CubicBezier b1, b2; subdivide(0.5, &b1, &b2); double tmid = (t0+t1)/2; b1.approximate(delta, t0, tmid, p, t); b2.approximate(delta, tmid, t1, p, t); } return static_cast(p.size()); } /** Returns the signed area of the triangle (p1, p2, p3). */ static inline double signed_area (const DPair &p1, const DPair &p2, const DPair &p3) { return ((p2.x()-p1.x())*(p3.y()-p1.y()) - (p3.x()-p1.x())*(p2.y()-p1.y()))/2.0; } static inline double dot_prod (const DPair &p1, const DPair &p2) { return p1.x()*p2.x() + p1.y()*p2.y(); } /** Returns true if p3 is located between p1 and p2, i.e. p3 lays almost on the line * between p1 and p2. */ static bool between (const DPair &p1, const DPair &p2, const DPair &p3, double delta) { double sqr_dist = dot_prod(p2-p1, p2-p1); double factor = sqr_dist == 0.0 ? 1.0 : sqr_dist; double area2 = abs(signed_area(p1, p2, p3)); return area2*area2/factor < delta // does p3 lay almost on the line through p1 and p2... && min(p1.x(), p2.x()) <= p3.x() // ...and on or inside the rectangle spanned by p1 and p2? && max(p1.x(), p2.x()) >= p3.x() && min(p1.y(), p2.y()) <= p3.y() && max(p1.y(), p2.y()) >= p3.y(); } static inline bool near (const DPair &p1, const DPair &p2, double delta) { DPair diff = p2-p1; return abs(diff.x()) < delta && abs(diff.y()) < delta; } /** Tries to reduce the degree of the Bézier curve. This only works if the number of * control points can be reduces without changing the shape of the curve significantly. * @param[in] delta deviation tolerance * @param[in] p control points of the reduced curve * @return degree of the reduced curve */ int CubicBezier::reduceDegree (double delta, vector &p) const { p.clear(); if (near(_points[0], _points[1], delta) && near(_points[0], _points[2], delta) && near(_points[0], _points[3], delta)) p.push_back(_points[0]); else if (between(_points[0], _points[3], _points[1], delta) && between(_points[0], _points[3], _points[2], delta)) { p.push_back(_points[0]); p.push_back(_points[3]); } else if (near((_points[1]-_points[0])*1.5+_points[0], (_points[2]-_points[3])*1.5+_points[3], delta)) { p.push_back(_points[0]); p.push_back((_points[1]-_points[0])*1.5 + _points[0]); p.push_back(_points[3]); } else { p.resize(4); for (int i=0; i < 4; i++) p[i] = _points[i]; } return static_cast(p.size()-1); } /** Approximates the cubic Bézier curve by a sequence of quadratic ones. * @param[in] precision specifies the precision of the approximation * @param[out] splitParams parameters t where the curve was split * @return map containing the split parameters t_n together with the qudratic curves */ vector CubicBezier::toQuadBeziers (double precision, vector *splitParams) const { vector qbeziers; toQuadBeziers(0, 1, precision, qbeziers, splitParams); return qbeziers; } /** Returns the "mid-point approximation" of this cubic Bézier. */ QuadBezier CubicBezier::midpointApproximation () const { DPair p0 = (_points[1]*3.0 - _points[0])/2.0; DPair p1 = (_points[2]*3.0 - _points[3])/2.0; return {_points[0], (p0+p1)/2.0, _points[3]}; } /** Approximates a segment of a cubic Bézier curve by a sequence of quadratic curves. * The quadratic segments are computed by adaptive subdivision of the cubic curve * as described at http://www.caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html * @param[in] t0 curve parameter of the segment's start point * @param[in] t1 curve parameter of the segment's end point * @param[in] precision maximum allowed distance between the curve points b(t) and the * corresponding approximated point c(t) on the quadratic curve * @param[out] qbeziers the resulting quadratic curves sorted in ascending order by their split points * @param[out] startParams the start parameters t[k] of the curves qbeziers[k] relative to *this. */ void CubicBezier::toQuadBeziers (double t0, double t1, double precision, vector &qbeziers, vector *startParams) const { // If -p0+3p1-3p2+p3 = 0, the degree of the curve is <= 2 and it's not necessary do any approximation. // In this case, the control point of the quadratic Bézier curve is (-p0+3p1)/2 = (3p2-p3)/2. // Otherwise, the distance d between q1:=(-p0+3p1)/2 and q2:=(3p2-p3)/2 is != 0. // Now we compute the quadratic Bézier with start point p0, end point p3, and control point (q1+q2)/2, // the "mid-point approximation" (MPA) of b. // The maximal distance between the points of the original curve b and the corresponding ones // on the MPA is d*sqrt(3)/18. The same computations can be done for the cubic curves we get // when subdividing b at a parameter t. The maximal distance of these curves to their MPA // is t^3*d*sqrt(3)/18. // Based on the formula for this distance we compute the split point tmax for a given precision // and check 3 cases: // * tmax >= 1: curve is quadratic, return MPA of b // * tmax >= 0.5: split b at t=0.5, return the MPAs of both segments // * tmax < 0.5: split b at tmax and 1-tmax, return the MPAs of the first and third segment, // recurse the algorithm for the middle segment DPair q1 = (_points[1]*3.0 - _points[0])/2.0; DPair q2 = (_points[2]*3.0 - _points[3])/2.0; double dist = (q2-q1).length(); double tmax3 = 18.0/sqrt(3.0)*precision/dist; // the cube of tmax if (tmax3 >= 1.0) { // curve is already quadratic, no subdivision necessary, return MPA qbeziers.emplace_back(_points[0], (q1+q2)/2.0, _points[3]); if (startParams) startParams->push_back(t0); } else if (tmax3 >= 0.125) { // tmax >= 0.5 // split the curve at t=0.5 and compute the MPA for both segments CubicBezier cbezier1, cbezier2; subdivide(0.5, &cbezier1, &cbezier2); qbeziers.emplace_back(cbezier1.midpointApproximation()); qbeziers.emplace_back(cbezier2.midpointApproximation()); if (startParams) { startParams->push_back(t0); startParams->push_back((t0+t1)/2); } } else { // tmax < 0.5 double tmax = cbrt(tmax3); double smax = 1.0-tmax; double dt = t1-t0; // first segment can be approximated by its MPA qbeziers.emplace_back(CubicBezier(*this, 0, tmax).midpointApproximation()); if (startParams) startParams->push_back(t0); // recurse for middle segment CubicBezier(*this, tmax, smax).toQuadBeziers(t0+tmax*dt, t0+smax*dt, precision, qbeziers, startParams); // third segment can be approximated by its MPA qbeziers.emplace_back(CubicBezier(*this, smax, 1).midpointApproximation()); if (startParams) startParams->push_back(smax); } } /** Try to solve the quadratic equation ax^2 + bx + c = 0. */ static bool solve_quadratic_equation (double a, double b, double c, double &x1, double &x2) { if (a == 0) { if (b == 0) return false; x1 = x2 = -c/b; } else { double discr = b*b - 4*a*c; if (discr < 0) return false; double p = -b/a/2; double r = sqrt(discr)/a/2; x1 = p+r; x2 = p-r; } return true; } /** Returns a tight bounding box parallel to the x- and y-axis. */ BoundingBox CubicBezier::getBBox () const { BoundingBox bbox; // coefficients of the derivative DPair pa = _points[3] - _points[2]*3.0 + _points[1]*3.0 - _points[0]; DPair pb = (_points[2]-_points[1]*2.0+_points[0])*2.0; DPair pc = _points[1]-_points[0]; // compute extrema for t > 0 and t < 1 double t1, t2; if (solve_quadratic_equation(pa.x(), pb.x(), pc.x(), t1, t2)) { if (t1 > 0.001 && t1 < 0.999) bbox.embed(valueAt(t1)); if (t1 != t2 && t2 > 0.001 && t2 < 0.999) bbox.embed(valueAt(t2)); } if (solve_quadratic_equation(pa.y(), pb.y(), pc.y(), t1, t2)) { if (t1 > 0.001 && t1 < 0.999) bbox.embed(valueAt(t1)); if (t1 != t2 && t2 > 0.001 && t2 < 0.999) bbox.embed(valueAt(t2)); } bbox.embed(_points[0]); bbox.embed(_points[3]); return bbox; } CubicBezier& CubicBezier::transform (const Matrix &matrix) { algo::transform(_points, begin(_points), [&matrix](const DPair &p) { return matrix * p; }); return *this; } dvisvgm-3.5/src/Bezier.hpp000066400000000000000000000064601501401750600155650ustar00rootroot00000000000000/************************************************************************* ** Bezier.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef BEZIER_HPP #define BEZIER_HPP #include #include "BoundingBox.hpp" #include "Pair.hpp" class Matrix; class QuadBezier { public: QuadBezier (); QuadBezier (const DPair &p0, const DPair &p1, const DPair &p2); void setPoints (const DPair &p0, const DPair &p1, const DPair &p2); const DPair& point (int i) const {return _points[i];} DPair valueAt (double t) const; DPair derivativeAt (double t) const; double arclen (double t=1.0) const; private: DPair _points[3]; }; class CubicBezier { public: CubicBezier (); //CubicBezier (const DPair &p0, const DPair &p1, const DPair &p2); CubicBezier (const DPair &p0, const DPair &p1, const DPair &p2, const DPair &p3); CubicBezier (double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3); CubicBezier (const CubicBezier &source, double t0, double t1); explicit CubicBezier (const QuadBezier &qbezier); void setPoints (const DPair &p0, const DPair &p1, const DPair &p2, const DPair &p3); void reverse (); DPair valueAt (double t) const; DPair blossomValue (double u, double v, double w) const; void subdivide (double t, CubicBezier *bezier1, CubicBezier *bezier2) const; CubicBezier& transform (const Matrix &matrix); int approximate (double delta, std::vector &p, std::vector *t=nullptr) const; const DPair& point (int i) const {return _points[i];} int reduceDegree (double delta, std::vector &p) const; std::vector toQuadBeziers (double delta, std::vector *startParams=nullptr) const; BoundingBox getBBox () const; protected: int approximate (double delta, double t0, double t1, std::vector &p, std::vector *t) const; void toQuadBeziers (double t0, double t1, double precision, std::vector &qbeziers, std::vector *startParams) const; QuadBezier midpointApproximation () const; private: DPair _points[4]; }; #endif dvisvgm-3.5/src/BgColorSpecialHandler.cpp000066400000000000000000000061141501401750600204620ustar00rootroot00000000000000/************************************************************************* ** BgColorSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include "algorithm.hpp" #include "BgColorSpecialHandler.hpp" #include "ColorSpecialHandler.hpp" #include "SpecialActions.hpp" using namespace std; /** Collect all background color changes while preprocessing the DVI file. * We need them in order to apply the correct background colors even if * not all but only selected DVI pages are converted. */ void BgColorSpecialHandler::preprocess (const string&, std::istream &is, SpecialActions &actions) { Color color = ColorSpecialHandler::readColor(is); if (_pageColors.empty() || _pageColors.back().second != color) { unsigned pageno = actions.getCurrentPageNumber(); if (!_pageColors.empty() && _pageColors.back().first == pageno) _pageColors.back().second = color; else _pageColors.emplace_back(pageno, color); } } bool BgColorSpecialHandler::process (const string&, istream&, SpecialActions&) { return true; } void BgColorSpecialHandler::dviBeginPage (unsigned pageno, SpecialActions &actions) { // Ensure that the background color of the preceding page is set as the // default background color of the current page because this special affects // the current and all subsequent pages until the next change. // See the documentation of the color package, section 3.5. if (_pageColors.empty()) return; // find number of page with bg color change not lower than the current one auto it = algo::lower_bound(_pageColors, PageColor(pageno, Color::BLACK)); if (it != _pageColors.end() && it->first == pageno) actions.setBgColor(it->second); else if (it != _pageColors.begin()) actions.setBgColor((--it)->second); } vector BgColorSpecialHandler::prefixes () const { vector pfx {"background"}; return pfx; } dvisvgm-3.5/src/BgColorSpecialHandler.hpp000066400000000000000000000043621501401750600204720ustar00rootroot00000000000000/************************************************************************* ** BgColorSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef BGCOLORSPECIALHANDLER_HPP #define BGCOLORSPECIALHANDLER_HPP #include #include "Color.hpp" #include "SpecialHandler.hpp" class BgColorSpecialHandler : public SpecialHandler { public: void preprocess (const std::string &prefix, std::istream &is, SpecialActions &actions) override; bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override; const char* info () const override {return "background color special";} const char* name () const override {return handlerName();} static const char* handlerName () {return "bgcolor";} std::vector prefixes () const override; protected: void dviBeginPage (unsigned pageno, SpecialActions &actions) override; private: using PageColor = std::pair; // page number and color std::vector _pageColors; }; #endif dvisvgm-3.5/src/Bitmap.cpp000066400000000000000000000114311501401750600155460ustar00rootroot00000000000000/************************************************************************* ** Bitmap.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include #include "Bitmap.hpp" using namespace std; /** Constructs a Bitmap */ Bitmap::Bitmap (int minx, int maxx, int miny , int maxy) { resize(minx, maxx, miny, maxy); } /** Resizes the bitmap and clears all pixels. * @param[in] minx index of leftmost pixel column * @param[in] maxx index of rightmost pixel column * @param[in] miny index of bottom row * @param[in] maxy index of top row */ void Bitmap::resize (int minx, int maxx, int miny , int maxy) { _rows = abs(maxy-miny)+1; _cols = abs(maxx-minx)+1; _xshift = minx; _yshift = miny; _bpr = _cols/8 + (_cols % 8 ? 1 : 0); // bytes per row _bytes.resize(_rows*_bpr); std::fill(_bytes.begin(), _bytes.end(), 0); } /** Sets n pixels of row r to 1 starting at pixel c. * @param[in] row number of row * @param[in] col number of column (pixel) * @param[in] n number of bits to be set */ void Bitmap::setBits (int row, int col, int n) { row -= _yshift; col -= _xshift; uint8_t *byte = &_bytes[row*_bpr + col/8]; if (byte < &_bytes[0]) return; const uint8_t *maxptr = &_bytes[0]+_bytes.size()-1; while (n > 0 && byte <= maxptr) { int b = 7 - col%8; // number of leftmost bit in current byte to be set int m = min(n, b+1); // number of bits to be set in current byte int bitseq = (1 << m)-1; // sequence of n set bits (bits 0..n-1 are set) bitseq <<= b-m+1; // move bit sequence so that bit b is the leftmost set bit *byte |= uint8_t(bitseq); // apply bit sequence to current byte byte++; n -= m; col += m; } } void Bitmap::forAllPixels (Callback &data) const { for (int row=0; row < _rows ; row++) { for (int col=0; col < _bpr; col++) { uint8_t byte = _bytes[row*_bpr+col]; int x; for (int b=7; (b >= 0) && ((x = 8*col+(7-b)) < _cols); b--) data.pixel(x, row, bool(byte & (1 << b)), *this); } } data.finish(); } class BBoxCallback : public Bitmap::Callback { public: int minx () const {return _minx;} int miny () const {return _miny;} int maxx () const {return _maxx;} int maxy () const {return _maxy;} bool empty () const {return !_changed;} void pixel (int x, int y, bool set, const Bitmap&) override { if (set) { _minx = min(_minx, x); _miny = min(_miny, y); _maxx = max(_maxx, x); _maxy = max(_maxy, y); _changed = true; } } void finish () override { if (empty()) _minx = _miny = 0; } private: bool _changed = false; int _minx = numeric_limits::max(), _miny=_minx; int _maxx = 0, _maxy = 0; }; /** Computes the bounding box that spans all set pixels. */ bool Bitmap::getBBox (int &minx, int &miny, int &maxx, int &maxy) const { BBoxCallback bboxCallback; forAllPixels(bboxCallback); minx = bboxCallback.minx(); miny = bboxCallback.miny(); maxx = bboxCallback.maxx(); maxy = bboxCallback.maxy(); return !bboxCallback.empty(); } /** Computes width and height of the bounding box that spans all set pixels. */ void Bitmap::getExtent (int &w, int &h) const { int minx, miny, maxx, maxy; if (getBBox(minx, miny, maxx, maxy)) { w = maxx-minx+1; h = maxy-miny+1; } else w = h = 0; } #if 0 ostream& Bitmap::write (ostream &os) const { for (int r=_rows-1; r >= 0 ; r--) { for (int c=0; c < _bpr; c++) { uint8_t byte = _bytes[r*_bpr+c]; for (int b=128; b; b>>=1) os << (byte & b ? '*' : '-'); os << ' '; } os << endl; } return os; } #endif dvisvgm-3.5/src/Bitmap.hpp000066400000000000000000000101311501401750600155470ustar00rootroot00000000000000/************************************************************************* ** Bitmap.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef BITMAP_HPP #define BITMAP_HPP #include #include #include class Bitmap { public: struct Callback { virtual ~Callback() =default; virtual void pixel (int x, int y, bool set, Bitmap &bm) {} virtual void pixel (int x, int y, bool set, const Bitmap &bm) {} virtual void finish () {} }; public: Bitmap () =default; Bitmap (int minx, int maxx, int miny , int maxy); void resize (int minx, int maxx, int miny , int maxy); void setBits(int row, int col, int n); const uint8_t* rowPtr (int row) const {return &_bytes[row*_bpr];} int height () const {return _rows;} int width () const {return _cols;} int xshift () const {return _xshift;} int yshift () const {return _yshift;} int bytesPerRow () const {return _bpr;} bool empty () const {return (!_rows && !_cols) || _bytes.empty();} bool getBBox (int &minx, int &miny, int &maxx, int &maxy) const; void getExtent (int &w, int &h) const; void forAllPixels (Callback &callback) const; template int copy (std::vector &target, bool vflip=false) const; // template // void write (std::ostream &os, const std::vector &v) const; // std::ostream& write (std::ostream &os) const; private: int _rows=0, _cols=0; ///< number of rows, columns int _xshift=0, _yshift=0; ///< horizontal/vertical shift int _bpr=0; ///< number of bytes per row std::vector _bytes; }; /** Copies the bitmap to a new target area and reorganizes the bits. * @tparam T component type of target vector * @param[out] target points to first T of new bitmap (must be deleted after usage) * @param[in] vflip true if the new bitmap should be flipped vertically * @return number of Ts per row */ template int Bitmap::copy (std::vector &target, bool vflip) const { const int s = sizeof(T); const int tpr = _bpr/s + (_bpr%s ? 1 : 0); // number of Ts per row target.resize(_rows*tpr); for (int r=0; r < _rows; r++) { int targetrow = vflip ? _rows-r-1 : r; for (int b=0; b < _bpr; b++) { T &t = target[targetrow*tpr + b/s]; T chunk = static_cast(_bytes[r*_bpr+b]) << (8*(s-1-b%s)); if (b % s == 0) t = chunk; else t |= chunk; } } return tpr; } /* template void Bitmap::write (std::ostream &os, const std::vector &v) const { const int s = sizeof(T); const int tpr = _bpr/s + (_bpr%s ? 1 : 0); // number of Ts per row for (int r=_rows-1; r >= 0; r--) { for (int t=0; t < tpr; t++) { for (T b=(T)1<<(8*s-1); b; b>>=1) os << ((v[r*tpr+t] & b) ? '*' : '-'); os << ' '; } os << std::endl; } }*/ #endif dvisvgm-3.5/src/BoundingBox.cpp000066400000000000000000000200211501401750600165430ustar00rootroot00000000000000/************************************************************************* ** BoundingBox.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include "algorithm.hpp" #include "BoundingBox.hpp" #include "Matrix.hpp" #include "utility.hpp" #include "SVGTree.hpp" #include "XMLNode.hpp" #include "XMLString.hpp" using namespace std; BoundingBox::BoundingBox () : _ulx(0), _uly(0), _lrx(0), _lry(0), _valid(false), _locked(false) { } BoundingBox::BoundingBox (double ulxx, double ulyy, double lrxx, double lryy) : _ulx(min(ulxx,lrxx)), _uly(min(ulyy,lryy)), _lrx(max(ulxx,lrxx)), _lry(max(ulyy,lryy)), _valid(true), _locked(false) { } BoundingBox::BoundingBox (const DPair &p1, const DPair &p2) : _ulx(min(p1.x(), p2.x())), _uly(min(p1.y(), p2.y())), _lrx(max(p1.x(), p2.x())), _lry(max(p1.y(), p2.y())), _valid(true), _locked(false) { } BoundingBox::BoundingBox (const Length &ulxx, const Length &ulyy, const Length &lrxx, const Length &lryy) : _ulx(min(ulxx.bp(),lrxx.bp())), _uly(min(ulyy.bp(),lryy.bp())), _lrx(max(ulxx.bp(),lrxx.bp())), _lry(max(ulyy.bp(),lryy.bp())), _valid(true), _locked(false) { } BoundingBox::BoundingBox (const string &boxstr) : _ulx(0), _uly(0), _lrx(0), _lry(0), _valid(false), _locked(false) { set(boxstr); } /** Extracts a sequence of length values from a string like "5cm, 2.4in, 0pt". * @param[in] boxstr whitespace and/or comma separated string of lengths. * @return the extracted lengths */ vector BoundingBox::extractLengths (string boxstr) { vector lengths; boxstr = util::replace(boxstr, ",", " "); boxstr = util::normalize_space(boxstr); vector lengthStrings = util::split(boxstr, " "); algo::copy_if(lengthStrings, back_inserter(lengths), std::not1(util::IsEmptyString())); return lengths; } /** Sets or modifies the bounding box. If 'boxstr' consists of 4 length values, * they denote the absolute position of two diagonal corners of the box. In case * of a single length value l the current box is enlarged by adding (-l,-l) the upper * left and (l,l) to the lower right corner. * @param[in] boxstr whitespace and/or comma separated string of lengths. */ void BoundingBox::set (const string &boxstr) { vector coord = extractLengths(boxstr); set(coord); } void BoundingBox::set (const std::vector &coord) { switch (coord.size()) { case 1: _ulx -= coord[0].bp(); _uly -= coord[0].bp(); _lrx += coord[0].bp(); _lry += coord[0].bp(); break; case 2: _ulx -= coord[0].bp(); _uly -= coord[1].bp(); _lrx += coord[0].bp(); _lry += coord[1].bp(); break; case 4: _ulx = min(coord[0].bp(), coord[2].bp()); _uly = min(coord[1].bp(), coord[3].bp()); _lrx = max(coord[0].bp(), coord[2].bp()); _lry = max(coord[1].bp(), coord[3].bp()); break; default: throw BoundingBoxException("1, 2 or 4 length parameters expected"); } _valid = true; } /** Enlarges the box so that point (x,y) is enclosed. */ void BoundingBox::embed (double x, double y) { if (!_locked) { if (_valid) { if (x < _ulx) _ulx = x; else if (x > _lrx) _lrx = x; if (y < _uly) _uly = y; else if (y > _lry) _lry = y; } else { _ulx = _lrx = x; _uly = _lry = y; _valid = true; } } } /** Enlarges the box so that the given bounding box is enclosed. */ void BoundingBox::embed (const BoundingBox &bbox) { if (!_locked && bbox._valid) { if (_valid) { embed(bbox._ulx, bbox._uly); embed(bbox._lrx, bbox._lry); } else { _ulx = bbox._ulx; _uly = bbox._uly; _lrx = bbox._lrx; _lry = bbox._lry; _valid = true; } } } /** Embeds a virtual circle into the box and enlarges it accordingly. * @param[in] c center of the circle * @param[in] r radius of the circle */ void BoundingBox::embed (const DPair &c, double r) { embed(BoundingBox(c.x()-r, c.y()-r, c.x()+r, c.y()+r)); } /** Expands the box in all four directions by a given value. */ void BoundingBox::expand (double m) { if (!_locked) { _ulx -= m; _uly -= m; _lrx += m; _lry += m; } } /** Intersects the current box with bbox and applies the result to *this. * If both boxes are disjoint, *this is not altered. * @param[in] bbox box to intersect with * @return false if *this is locked or both boxes are disjoint */ bool BoundingBox::intersect (const BoundingBox &bbox) { // check if the two boxes are disjoint if (_locked || _lrx < bbox._ulx || _lry < bbox._uly || _ulx > bbox._lrx || _uly > bbox._lry) return false; // not disjoint: compute the intersection _ulx = max(_ulx, bbox._ulx); _uly = max(_uly, bbox._uly); _lrx = min(_lrx, bbox._lrx); _lry = min(_lry, bbox._lry); return true; } void BoundingBox::operator += (const BoundingBox &bbox) { if (!_locked) { _ulx += bbox._ulx; _uly += bbox._uly; _lrx += bbox._lrx; _lry += bbox._lry; } } static inline bool almost_equal (double v1, double v2) { return abs(v1-v2) < 1e-10; } bool BoundingBox::operator == (const BoundingBox &bbox) const { return _valid && bbox._valid && almost_equal(_ulx, bbox._ulx) && almost_equal(_uly, bbox._uly) && almost_equal(_lrx, bbox._lrx) && almost_equal(_lry, bbox._lry); } void BoundingBox::scale (double sx, double sy) { if (!_locked) { _ulx *= sx; _lrx *= sx; if (sx < 0) swap(_ulx, _lrx); _uly *= sy; _lry *= sy; if (sy < 0) swap(_uly, _lry); } } void BoundingBox::transform (const Matrix &tm) { if (!_locked) { DPair ul = tm * DPair(_ulx, _uly); DPair lr = tm * DPair(_lrx, _lry); DPair ll = tm * DPair(_ulx, _lry); DPair ur = tm * DPair(_lrx, _uly); _ulx = min(min(ul.x(), lr.x()), min(ur.x(), ll.x())); _uly = min(min(ul.y(), lr.y()), min(ur.y(), ll.y())); _lrx = max(max(ul.x(), lr.x()), max(ur.x(), ll.x())); _lry = max(max(ul.y(), lr.y()), max(ur.y(), ll.y())); } } string BoundingBox::svgViewBoxString () const { ostringstream oss; oss << XMLString(_ulx) << ' ' << XMLString(_uly) << ' ' << XMLString(width()) << ' ' << XMLString(height()); return oss.str(); } ostream& BoundingBox::write (ostream &os) const { os << '(' << _ulx << ", " << _uly << ", " << _lrx << ", " << _lry << ')'; if (!_valid) os << " (invalid)"; else if (_locked) os << " (locked)"; return os; } unique_ptr BoundingBox::createSVGRect () const { auto rect = util::make_unique("rect"); rect->addAttribute("x", minX()); rect->addAttribute("y", minY()); rect->addAttribute("width", width()); rect->addAttribute("height", height()); rect->addAttribute("fill", "none"); return rect; } unique_ptr BoundingBox::createSVGPath () const { GraphicsPath path; path.rect(minX(), minY(), maxX(), maxY()); ostringstream oss; path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); auto pathElem = util::make_unique("path"); pathElem->addAttribute("d", oss.str()); return pathElem; } dvisvgm-3.5/src/BoundingBox.hpp000066400000000000000000000076021501401750600165620ustar00rootroot00000000000000/************************************************************************* ** BoundingBox.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef BOUNDINGBOX_HPP #define BOUNDINGBOX_HPP #include #include #include #include #include "Length.hpp" #include "MessageException.hpp" #include "Pair.hpp" class Matrix; class XMLElement; struct BoundingBoxException : MessageException { explicit BoundingBoxException (const std::string &msg) : MessageException(msg) {} }; class BoundingBox { public: BoundingBox (); BoundingBox (double ulxx, double ulyy, double lrxx, double lryy); BoundingBox (const DPair &p1, const DPair &p2); BoundingBox (const Length &ulxx, const Length &ulyy, const Length &lrxx, const Length &lryy); explicit BoundingBox (const std::string &boxstr); void set (const std::string &boxstr); void set (const std::vector &lengths); void embed (double x, double y); void embed (const BoundingBox &bb); void embed (const DPair &p) {embed(p.x(), p.y());} void embed (const DPair &c, double r); static std::vector extractLengths (std::string boxstr); template void embed (const Pair &p) {embed(p.x(), p.y());} void expand (double m); bool intersect (const BoundingBox &bbox); double minX () const {return _ulx;} double minY () const {return _uly;} double maxX () const {return _lrx;} double maxY () const {return _lry;} double width () const {return _lrx-_ulx;} double height () const {return _lry-_uly;} bool valid() const {return _valid;} bool locked() const {return _locked;} void lock () {_locked = true;} void unlock () {_locked = false;} void invalidate () {_valid = false;} void operator += (const BoundingBox &bbox); bool operator == (const BoundingBox &bbox) const; bool operator != (const BoundingBox &bbox) const {return !(*this == bbox);} void scale (double sx, double sy); void transform (const Matrix &tm); std::string svgViewBoxString () const; std::ostream& write (std::ostream &os) const; std::unique_ptr createSVGRect () const; std::unique_ptr createSVGPath () const; private: double _ulx, _uly; ///< coordinates of upper left vertex (in PS point units) double _lrx, _lry; ///< coordinates of lower right vertex (in PS point units) bool _valid : 1; ///< true if the box coordinates are properly set bool _locked : 1; ///< if true, the box data is read-only }; inline std::ostream& operator << (std::ostream &os, const BoundingBox &bbox) { return bbox.write(os); } #endif dvisvgm-3.5/src/CLCommandLine.cpp000066400000000000000000000201071501401750600167370ustar00rootroot00000000000000/************************************************************************* ** CLCommandLine.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include "algorithm.hpp" #include "CLCommandLine.hpp" #include "version.hpp" using namespace CL; using namespace std; CommandLine::CommandLine (const char *summary, const char *usage, const char *copyright) : _summary(summary), _usage(usage), _copyright(copyright) { } void CommandLine::parse (int argc, char **argv) { bool filesOnly = false; for (int i=1; i < argc; i++) { istringstream iss(argv[i]); if (filesOnly || iss.peek() != '-') _files.emplace_back(argv[i]); else { iss.get(); // skip dash if (iss.peek() < 0) _singleDashParsed = true; else if (iss.peek() != '-') parseShortOption(iss, argc, argv, i); else { iss.get(); // skip dash if (iss.peek() == EOF) // "--" only, no following option name? filesOnly = true; // treat all following options as filenames else parseLongOption(iss); } } } } static void error (const Option &option, bool shortname, const string &msg) { ostringstream oss; oss << "option "; if (shortname) oss << '-' << option.shortName(); else oss << "--" << option.longName(); oss << ": " << msg; throw CommandLineException(oss.str()); } static void type_error (const Option &option, bool shortname) { ostringstream oss; switch (option.argMode()) { case Option::ArgMode::NONE: error(option, shortname, "no argument expected"); break; case Option::ArgMode::OPTIONAL: oss << "optional argument "; if (!option.argName().empty()) oss << "'" << option.argName() << "' "; oss << "must be of "+option.typeString()+" type"; error(option, shortname, oss.str()); break; default: oss << option.typeString()+" argument "; if (!option.argName().empty()) oss << "'" << option.argName() << "' "; oss << "expected"; error(option, shortname, oss.str()); } } void CommandLine::parseShortOption (istringstream &iss, int argc, char **argv, int &argn) const { bool combined = false; do { char shortname = static_cast(iss.get()); if (!isalnum(shortname)) throw CommandLineException(string("syntax error: -")+shortname); if (Option *option = lookupOption(shortname)) { if (!combined || option->argMode() == Option::ArgMode::NONE) { if (option->argMode() == Option::ArgMode::REQUIRED && strlen(argv[argn]) == 2) { // required argument separated by whitespace? if (argn+1 < argc && argv[argn+1][0] != '-') { iss.clear(); // reset error flags iss.str(argv[++argn]); // continue parsing with next command-line field } } if (!option->parse(iss, false)) type_error(*option, true); if (option->argMode() == Option::ArgMode::NONE) combined = true; } else throw CommandLineException(string("option -")+ shortname + " must be given separately"); } else throw CommandLineException(string("unknown option -")+shortname); } while (combined && !iss.eof()); } void CommandLine::parseLongOption (istream &is) const { string optname; while (isalnum(is.peek()) || (!optname.empty() && is.peek() == '-')) optname += char(is.get()); if (optname.empty()) throw CommandLineException("unexpected character '" + string(1, is.peek()) + "' after '--'"); vector options = lookupOption(optname); if (options.empty()) throw CommandLineException("unknown option --"+optname); if (options.size() == 1) { if (!options[0]->parse(is, true)) type_error(*options[0], false); } else { // is partially given option ambiguous? algo::sort(options, [](const Option *opt1, const Option *opt2) { return opt1->longName() < opt2->longName(); }); string msg = "option --" + optname + " is ambiguous ("; msg = algo::accumulate(options, msg, [](const string &str, const Option *opt) { return str + opt->longName() + ", "; }); msg.pop_back(); msg.back() = ')'; throw CommandLineException(msg); } } /** Returns all options that match the given long name. */ vector CommandLine::lookupOption (const string &optname) const { vector matches; auto len = optname.length(); for (OptSectPair optsect : options()) { if (optsect.first->longName() == optname) { // exact match? matches.clear(); matches.push_back(optsect.first); break; } if (optsect.first->longName().substr(0, len) == optname) // partial match? matches.push_back(optsect.first); } return matches; } /** Returns the option that match the given short name. */ Option* CommandLine::lookupOption (char optchar) const { auto it = algo::find_if(options(), [&](const OptSectPair &optsect) { return optsect.first->shortName() == optchar; }); return (it != options().end()) ? it->first : nullptr; } /** Prints help text including summary of options. * @param[in] os output stream the help text is printed to * @param[in] mode output mode (0=section, 1=sorted by short options, 2=sorted by long options) */ void CommandLine::help (ostream &os, int mode) const { os << PROGRAM_NAME << ' '<< PROGRAM_VERSION << "\n\n"; os << _summary << "\n\n"; // print usage info string usage = _usage; int count=0; while (!usage.empty()) { auto pos = usage.find('\n'); os << (count++ == 0 ? "Usage: " : " ") << PROGRAM_NAME << ' ' << usage.substr(0, pos) << '\n'; if (pos != string::npos) usage = usage.substr(pos+1); else usage.clear(); } if (mode > 0) os << '\n'; // compute width of first column of help output unordered_map> linecols; size_t col1width=0; for (const OptSectPair &ospair : options()) { string::size_type pos; string line = ospair.first->helpline(); if ((pos = line.find('\t')) != string::npos) { linecols.emplace(ospair.first, pair(line.substr(0, pos), line.substr(pos+1))); col1width = max(col1width, pos); } } if (mode > 0) { auto isless = +[](const OptSectPair &p1, const OptSectPair &p2) { return p1.first->longName() < p2.first->longName(); }; if (mode == 1) { isless = [](const OptSectPair &p1, const OptSectPair &p2) { char c1 = p1.first->shortName(), c2 = p2.first->shortName(); if (c1 == c2) return p1.first->longName() < p2.first->longName(); if (tolower(c1) == tolower(c2)) return c1 > c2; // lower case before upper case letters return tolower(c1) < tolower(c2); }; } algo::sort(options(), isless); } // print summary of options col1width += 2; int sectno=-1; for (const OptSectPair &ospair : options()) { if (mode == 0 && ospair.second != sectno) { // first option in current section? sectno = ospair.second; if (section(sectno)) os << '\n' << section(sectno) << ":\n"; } Option *opt = ospair.first; os << " " << setw(col1width) << left << linecols[opt].first; os << setw(0) << linecols[opt].second << '\n'; } os << '\n' << _copyright << '\n'; } dvisvgm-3.5/src/CLCommandLine.hpp000066400000000000000000000055271501401750600167550ustar00rootroot00000000000000/************************************************************************* ** CLCommandLine.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CL_COMMANDLINE_HPP #define CL_COMMANDLINE_HPP #include #include #include #include #include #include "CLOption.hpp" #include "MessageException.hpp" namespace CL { class CommandLine { public: CommandLine (const char *summary, const char *usage, const char *copyright); virtual ~CommandLine () =default; void parse (int argc, char **argv); void help (std::ostream &os, int mode=0) const; void addFilename (const std::string &fname) {_files.emplace_back(fname);} bool singleDashGiven () const {return _singleDashParsed;} const std::vector& filenames () const {return _files;} protected: using OptSectPair = std::pair; void parseShortOption (std::istringstream &is, int argc, char **argv, int &argn) const; void parseLongOption (std::istream &is) const; virtual std::vector& options () const =0; virtual const char* section (size_t n) const {return nullptr;} Option* lookupOption (char optchar) const; std::vector lookupOption (const std::string &optname) const; private: const char *_summary; const char *_usage; const char *_copyright; bool _singleDashParsed=false; ///< true if a single '-' w/o a following char was parsed std::vector _files; }; struct CommandLineException : public MessageException { explicit CommandLineException (const std::string &msg) : MessageException(msg) {} }; } // namespace CL #endif dvisvgm-3.5/src/CLOption.hpp000066400000000000000000000146071501401750600160360ustar00rootroot00000000000000/************************************************************************* ** CLOption.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CL_OPTION_HPP #define CL_OPTION_HPP #include #include #include namespace CL { class Option { friend class CommandLine; public: enum class ArgMode {NONE, OPTIONAL, REQUIRED}; public: Option (const char *longname, char shortname, const char *summary) : _shortName(shortname), _longName(longname), _summary(summary), _given(false) {} virtual ~Option () = default; virtual std::string typeString () const {return "";} virtual ArgMode argMode () const {return ArgMode::NONE;} virtual bool given () const {return _given;} virtual char shortName () const {return _shortName;} virtual std::string longName () const {return _longName;} virtual std::string summary () const {return _summary;} virtual std::string argName () const {return "";} virtual std::string valueString () const {return "";} virtual std::string helpline () const { std::string line; if (_shortName != '\0') line = std::string("-") + _shortName + ", "; else line = " "; line += "--" + std::string(_longName); if (!argName().empty()) { if (argMode() == ArgMode::OPTIONAL) line += '['; line += '='; line += argName(); if (argMode() == ArgMode::OPTIONAL) line += ']'; } if (_summary) { line += '\t'; line += _summary; } if (argMode() != ArgMode::NONE && !valueString().empty()) line += std::string(" [") + valueString() + "]"; return line; } protected: virtual bool parse (std::istream &is, bool longopt) { if (is.eof()) return given(argMode() != ArgMode::REQUIRED); if (argMode() == ArgMode::OPTIONAL && is.peek() == ' ') return given(false); if (longopt && is.get() != '=') return given(false); return given(parseValue(is)); } virtual bool parseValue (std::istream &is) { return is.peek() == EOF || argMode() == ArgMode::NONE; } bool given (bool val) {return _given = val;} private: char _shortName; const char *_longName; const char*_summary; bool _given; }; template constexpr const char* typeString () {return "unknown";} template<> constexpr const char* typeString () {return "boolean";} template<> constexpr const char* typeString () {return "integer";} template<> constexpr const char* typeString () {return "non-negative integer";} template<> constexpr const char* typeString () {return "floating point";} template<> constexpr const char* typeString () {return "string";} template T parseValue (std::istream &is) { T value; is >> value; return value; } template<> inline std::string parseValue (std::istream &is) { is >> std::ws; std::string str; std::getline(is, str); return str; } template class TypedOption : public Option { public: TypedOption (const char *longName, char shortName, const char *argName, T val, const char *summary) : Option(longName, shortName, summary), _argName(argName), _value(std::move(val)) {} TypedOption (const char *longName, char shortName, const char *argName, const char *summary) : Option(longName, shortName, summary), _argName(argName), _value() {} T value () const {return _value;} std::string typeString () const override {return CL::typeString();} std::string argName() const override {return _argName ? _argName : "";} std::string valueString () const override { std::ostringstream oss; oss << _value; return oss.str(); } ArgMode argMode () const override {return mode;} protected: bool parseValue (std::istream &is) override { T value = CL::parseValue(is); if (!is.fail()) _value = std::move(value); return !is.fail() || (argMode() == ArgMode::OPTIONAL && is.eof()); } private: const char *_argName; T _value; }; template class TypedOption : public Option { public: TypedOption (const char *longName, char shortName, const char *argName, bool val, const char *summary) : Option(longName, shortName, summary), _argName(argName), _value(val) {} TypedOption (const char *longName, char shortName, const char *argName, const char *summary) : Option(longName, shortName, summary), _argName(argName), _value(false) {} bool value () const {return _value;} std::string valueString () const override {return _value ? "yes" : "no";} ArgMode argMode () const override {return mode;} std::string typeString () const override {return CL::typeString();} std::string argName() const override {return _argName ? _argName : "";} protected: bool parseValue (std::istream &is) override { std::string str; is >> str; if (is.fail()) return argMode() != ArgMode::REQUIRED; if (str == "yes" || str == "y" || str == "true" || str == "1") _value = true; else if (str == "no" || str == "n" || str == "false" || str == "0") _value = false; else return false; return true; } private: const char *_argName; bool _value; }; } // namespace CL #endif dvisvgm-3.5/src/CMap.cpp000066400000000000000000000067051501401750600151620ustar00rootroot00000000000000/************************************************************************* ** CMap.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include "algorithm.hpp" #include "CMap.hpp" #include "CMapManager.hpp" #include "FileFinder.hpp" #include "Unicode.hpp" using namespace std; const char* CMap::path () const { return FileFinder::instance().lookup(name(), "cmap", false); } const FontEncoding* CMap::findCompatibleBaseFontMap (const PhysicalFont *font, CharMapID &charmapID) const { return CMapManager::instance().findCompatibleBaseFontMap(font, this, charmapID); } ////////////////////////////////////////////////////////////////////// void SegmentedCMap::addCIDRange (uint32_t first, uint32_t last, uint32_t cid) { if (uint32_t cp = Unicode::fromSurrogate(first)) // is 'first' a surrogate? first = cp; if (uint32_t cp = Unicode::fromSurrogate(last)) // is 'last' a surrogate? last = cp; _cidranges.addRange(first, last, cid); } void SegmentedCMap::addBFRange (uint32_t first, uint32_t last, uint32_t chrcode) { if (uint32_t cp = Unicode::fromSurrogate(chrcode)) // is 'chrcode' a surrogate? chrcode = cp; _bfranges.addRange(first, last, chrcode); } /** Returns the RO (Registry-Ordering) string of the CMap. */ string SegmentedCMap::getROString() const { if (_registry.empty() || _ordering.empty()) return ""; return _registry + "-" + _ordering; } bool SegmentedCMap::mapsToUnicode () const { vector encstrings = {"UTF8", "UTF16", "UCS2", "UCS4", "UCS32"}; return algo::any_of(encstrings, [&](const string& s) { auto pos = _filename.find(s); return (pos != string::npos && (pos == 0 || _filename[pos-1] == '-')); }); } /** Returns the CID for a given character code. */ uint32_t SegmentedCMap::cid (uint32_t c) const { if (_cidranges.valueExists(c)) return _cidranges.valueAt(c); if (_basemap) return _basemap->cid(c); return 0; } /** Returns the character code of a base font for a given CID. */ uint32_t SegmentedCMap::bfcode (uint32_t cid) const { if (_bfranges.valueExists(cid)) return _bfranges.valueAt(cid); if (_basemap) return _basemap->bfcode(cid); return 0; } void SegmentedCMap::write (ostream &os) const { _cidranges.write(os); } dvisvgm-3.5/src/CMap.hpp000066400000000000000000000105711501401750600151630ustar00rootroot00000000000000/************************************************************************* ** CMap.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CMAP_HPP #define CMAP_HPP #include #include #include #include "FontEncoding.hpp" #include "RangeMap.hpp" struct CMap : public NamedFontEncoding { virtual bool vertical () const =0; virtual bool mapsToCID () const =0; virtual uint32_t cid (uint32_t c) const =0; virtual uint32_t bfcode (uint32_t cid) const =0; virtual std::string getROString () const =0; const char* path () const override; const FontEncoding* findCompatibleBaseFontMap (const PhysicalFont *font, CharMapID &charmapID) const override; bool mapsToCharIndex () const override {return mapsToCID();} Character decode (uint32_t c) const override { if (mapsToCID()) return Character(Character::INDEX, cid(c)); return Character(Character::CHRCODE, bfcode(c)); } }; struct IdentityCMap : public CMap { uint32_t cid (uint32_t c) const override {return c;} uint32_t bfcode (uint32_t cid) const override {return 0;} std::string getROString () const override {return "Adobe-Identity";} bool mapsToCID() const override {return true;} }; struct IdentityHCMap : public IdentityCMap { bool vertical () const override {return false;} const char* name () const override {return "Identity-H";} }; struct IdentityVCMap : public IdentityCMap { bool vertical () const override {return true;} const char* name () const override {return "Identity-V";} }; struct UnicodeCMap : public CMap { bool vertical () const override {return false;} const char* name () const override {return "unicode";} bool mapsToCID () const override {return false;} const char* path () const override {return nullptr;} uint32_t cid (uint32_t c) const override {return c;} uint32_t bfcode (uint32_t cid) const override {return cid;} std::string getROString () const override {return "";} bool mapsToUnicode () const override {return true;} }; class SegmentedCMap : public CMap { friend class CMapReader; public: explicit SegmentedCMap (std::string fname) : _filename(std::move(fname)) {} const char* name () const override {return _filename.c_str();} uint32_t cid (uint32_t c) const override; uint32_t bfcode (uint32_t cid) const override; void addCIDRange (uint32_t first, uint32_t last, uint32_t cid); void addBFRange (uint32_t first, uint32_t last, uint32_t chrcode); void write (std::ostream &os) const; bool vertical () const override {return _vertical;} bool mapsToCID () const override {return _mapsToCID;} size_t numCIDRanges () const {return _cidranges.numRanges();} size_t numBFRanges () const {return _bfranges.numRanges();} std::string getROString () const override; bool mapsToUnicode () const override; private: std::string _filename; std::string _registry; std::string _ordering; std::string _cmaptype; CMap *_basemap = nullptr; bool _vertical = false; bool _mapsToCID = true; // true: chrcode->CID, false: CID->charcode RangeMap _cidranges; RangeMap _bfranges; }; #endif dvisvgm-3.5/src/CMapManager.cpp000066400000000000000000000122631501401750600164510ustar00rootroot00000000000000/************************************************************************* ** CMapManager.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include "CMap.hpp" #include "CMapManager.hpp" #include "CMapReader.hpp" #include "FileFinder.hpp" #include "Font.hpp" #include "Message.hpp" using namespace std; CMapManager& CMapManager::instance () { static CMapManager cmm; return cmm; } /** Loads a cmap and returns the corresponding object. */ CMap* CMapManager::lookup (const string &name) { auto it = _cmaps.find(name); if (it != _cmaps.end()) return it->second.get(); if (_includedCMaps.find(name) != _includedCMaps.end()) { _level = 0; throw CMapReaderException("circular reference of CMap " + name); } unique_ptr cmap_ptr; if (name == "Identity-H") cmap_ptr = util::make_unique(); else if (name == "Identity-V") cmap_ptr = util::make_unique(); else if (name == "unicode") cmap_ptr = util::make_unique(); if (cmap_ptr) { CMap *ret = cmap_ptr.get(); _cmaps[name] = std::move(cmap_ptr); return ret; } // Load cmap data of file and also process all cmaps referenced by operator "usecmap". // This can lead to a sequence of further calls of lookup(). In order to prevent infinite loops // due to (disallowed) circular cmap inclusions, we keep track of all cmaps processed during // a sequence of inclusions. _includedCMaps.insert(name); // save name of current cmap being processed _level++; // increase nesting level CMap *ret=nullptr; try { CMapReader reader; if (!(cmap_ptr = reader.read(name))) { _level = 1; Message::wstream(true) << "CMap file '" << name << "' not found\n"; } ret = cmap_ptr.get(); _cmaps[name] = std::move(cmap_ptr); } catch (const CMapReaderException &e) { Message::estream(true) << "CMap file " << name << ": " << e.what() << "\n"; } if (--_level == 0) // back again at initial nesting level? _includedCMaps.clear(); // => names of included cmaps are no longer needed return ret; } /** Looks for a base font CMap and a compatible encoding table in a given font. The CMap describe * the mapping from CIDs to character codes where the latter are relative to the encoding table * identified by charmapID. * cmap:X->CID, bfmap:CID->Y, enctable:Y->CharCode * @param[in] font look for available encoding tables in this font * @param[in] cmap take the source registry-ordering pair from this CMap * @param[out] charmapID ID of the compatible character map found in the given font * @return base font CMap that maps from CIDs to character codes */ const CMap* CMapManager::findCompatibleBaseFontMap (const PhysicalFont *font, const CMap *cmap, CharMapID &charmapID) { if (!font || !cmap) return nullptr; struct CharMapIDToEncName { CharMapID id; const char *encname; }; const array encodings {{ {CharMapID::WIN_UCS4, "UCS4"}, {CharMapID::WIN_UCS2, "UCS2"}, {CharMapID::WIN_SHIFTJIS, "90ms-RKSJ"}, {CharMapID::WIN_PRC, "GBK-EUC"}, {CharMapID::WIN_BIG5, "ETen-B5"}, {CharMapID::WIN_WANSUNG, "KSCms-UHC"}, {CharMapID::MAC_JAPANESE, "90pv-RKSJ"}, {CharMapID::MAC_TRADCHINESE, "B5pc"}, {CharMapID::MAC_SIMPLCHINESE, "GBpc-EUC"}, {CharMapID::MAC_KOREAN, "KSCpc-EUC"} }}; // get IDs of all available charmaps in font vector charmapIDs; font->collectCharMapIDs(charmapIDs); // try to find a compatible encoding CMap const bool is_unicode_map = cmap->mapsToUnicode(); const string ro = cmap->getROString(); for (const CharMapIDToEncName &enc : encodings) { for (const CharMapID &id : charmapIDs) { if (enc.id == id) { string cmapname = ro+"-"+enc.encname; if (is_unicode_map || FileFinder::instance().lookup(cmapname, "cmap", false)) { charmapID = enc.id; return is_unicode_map ? cmap : lookup(cmapname); } } } } return nullptr; } dvisvgm-3.5/src/CMapManager.hpp000066400000000000000000000042551501401750600164600ustar00rootroot00000000000000/************************************************************************* ** CMapManager.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CMAPMANAGER_HPP #define CMAPMANAGER_HPP #include #include #include #include #include "CharMapID.hpp" struct CMap; struct FontEncoding; class FontEncodingPair; class PhysicalFont; class CMapManager { public: CMap* lookup (const std::string &name); const CMap* findCompatibleBaseFontMap (const PhysicalFont *font, const CMap *cmap, CharMapID &charmapID); static CMapManager& instance (); protected: CMapManager () : _level(0) {} private: std::unordered_map> _cmaps; ///< loaded cmaps std::unordered_set _includedCMaps; ///< names of cmaps loaded by "usecmap" int _level; ///< current inclusion depth; >0 if a cmap loaded by "usecmap" is being processed }; #endif dvisvgm-3.5/src/CMapReader.cpp000066400000000000000000000201511501401750600162740ustar00rootroot00000000000000/************************************************************************* ** CMapReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include #include "algorithm.hpp" #include "CMap.hpp" #include "CMapManager.hpp" #include "CMapReader.hpp" #include "FileFinder.hpp" #include "InputReader.hpp" #include "utility.hpp" using namespace std; /** Reads a cmap file and returns the corresponding CMap object. * @param fname[in] name/path of cmap file * @return CMap object representing the read data, or 0 if file could not be read */ unique_ptr CMapReader::read (const string &fname) { if (const char *path = FileFinder::instance().lookup(fname, "cmap", false)) { ifstream ifs(path); if (ifs) return read(ifs, fname); } _tokens.clear(); return {}; } /** Reads cmap data from a given stream and returns the corresponding CMap object. * @param[in] is cmap data input stream * @param[in] name name of CMap to be read * @return CMap object representing the read data, or 0 if file could not be read */ unique_ptr CMapReader::read (std::istream& is, const string &name) { _tokens.clear(); _cmap = util::make_unique(name); StreamInputReader ir(is); try { while (ir) { Token token(ir); if (token.type() == Token::Type::END) break; if (_inCMap) { if (token.type() == Token::Type::OPERATOR) executeOperator(token.strvalue(), ir); else _tokens.push_back(token); } else if (token.type() == Token::Type::OPERATOR && token.strvalue() == "begincmap") _inCMap = true; } } catch (CMapReaderException &) { _cmap.reset(); throw; } return std::move(_cmap); } /** Executes a PS operator from the CMap file. * @param[in] opname name of operator to execute * @param[in] ir reader object used to read the CMap stream */ void CMapReader::executeOperator (const string &opname, InputReader &ir) { struct Operator { const char *name; void (CMapReader::*handler)(InputReader&); }; constexpr array operators {{ {"beginbfchar", &CMapReader::op_beginbfchar}, {"beginbfrange", &CMapReader::op_beginbfrange}, {"begincidchar", &CMapReader::op_begincidchar}, {"begincidrange", &CMapReader::op_begincidrange}, {"def", &CMapReader::op_def}, {"endcmap", &CMapReader::op_endcmap}, {"usecmap", &CMapReader::op_usecmap}, }}; auto it = algo::find_if(operators, [&](const Operator &op) { return op.name == opname; }); if (it != operators.end()) (this->*it->handler)(ir); _tokens.clear(); } void CMapReader::op_def (InputReader&) { size_t size = _tokens.size(); if (size >= 2) { const string val = popToken().strvalue(); const string name = popToken().strvalue(); if (name == "WMode") { if (val == "0" || val == "1") _cmap->_vertical = (val == "1"); else throw CMapReaderException("invalid WMode (0 or 1 expected)"); } else if (name == "CMapType") _cmap->_cmaptype = val; else if (name == "Registry") _cmap->_registry = val; else if (name == "Ordering") _cmap->_ordering = val; } } void CMapReader::op_endcmap (InputReader &) { _inCMap = false; } void CMapReader::op_usecmap (InputReader &) { if (_tokens.empty()) throw CMapReaderException("stack underflow while processing usecmap"); else { const string name = popToken().strvalue(); if ((_cmap->_basemap = CMapManager::instance().lookup(name)) == nullptr) throw CMapReaderException("CMap file '"+name+"' not found"); } } static uint32_t parse_hexentry (InputReader &ir) { ir.skipSpace(); if (ir.get() != '<') throw CMapReaderException("invalid range entry ('<' expected)"); unsigned val; if (!ir.parseUInt(16, val)) throw CMapReaderException("invalid range entry (hexadecimal value expected)"); if (ir.get() != '>') throw CMapReaderException("invalid range entry ('>' expected)"); return uint32_t(val); } void CMapReader::parseCIDChars (InputReader &ir, bool isRange) { if (!_tokens.empty() && _tokens.back().type() == Token::Type::NUMBER) { ir.skipSpace(); int num_entries = static_cast(popToken().numvalue()); while (num_entries > 0 && ir.peek() == '<') { uint32_t first = parse_hexentry(ir); uint32_t last = first; if (isRange) last = parse_hexentry(ir); ir.skipSpace(); uint32_t cid; if (!ir.parseUInt(cid)) throw CMapReaderException("invalid char entry (decimal value expected)"); _cmap->addCIDRange(first, last, cid); ir.skipSpace(); } } } void CMapReader::op_begincidchar (InputReader &ir) { parseCIDChars(ir, false); } void CMapReader::op_begincidrange (InputReader &ir) { parseCIDChars(ir, true); } void CMapReader::op_beginbfrange (InputReader &ir) { if (!_tokens.empty() && _tokens.back().type() == Token::Type::NUMBER) { ir.skipSpace(); int num_entries = static_cast(popToken().numvalue()); while (num_entries > 0 && ir.peek() == '<') { uint32_t first = parse_hexentry(ir); uint32_t last = parse_hexentry(ir); uint32_t chrcode = parse_hexentry(ir); _cmap->addBFRange(first, last, chrcode); ir.skipSpace(); } _cmap->_mapsToCID = false; } } void CMapReader::op_beginbfchar (InputReader &ir) { if (!_tokens.empty() && _tokens.back().type() == Token::Type::NUMBER) { ir.skipSpace(); int num_entries = static_cast(popToken().numvalue()); while (num_entries > 0 && ir.peek() == '<') { uint32_t cid = parse_hexentry(ir); ir.skipSpace(); if (ir.peek() == '/') throw CMapReaderException("mapping of named characters is not supported"); uint32_t chrcode = parse_hexentry(ir); _cmap->addBFRange(cid, cid, chrcode); ir.skipSpace(); } _cmap->_mapsToCID = false; } } //////////////////////////////////////////////////////////////////////////////////// CMapReader::Token::Token (InputReader &ir) { scan(ir); } /** Reads the next characters from the input stream to create a token. */ void CMapReader::Token::scan (InputReader &ir) { ir.skipSpace(); while (ir.peek() == '%') { // comment? while (ir.peek() != '\n') // => skip until end of line ir.get(); ir.skipSpace(); } ir.skipSpace(); if (ir.eof()) _type = Type::END; else if (ir.peek() == '/') { // PS name? ir.get(); while (!strchr("[]{}<>", ir.peek()) && !isspace(ir.peek())) _value += ir.get(); _type = Type::NAME; } else if (ir.peek() == '(') { // string? ir.get(); int level=0; while (ir.peek() != ')' || level > 0) { if (ir.peek() == '(') level++; else if (ir.peek() == ')' && level > 0) level--; _value += ir.get(); } ir.get(); // skip ')' _type = Type::STRING; } else if (strchr("[]{}<>", ir.peek())) { // PS delimiter _value = ir.get(); _type = Type::DELIM; } else if (isdigit(ir.peek())) { // number? double val; if (ir.parseDouble(val)) { _value = util::to_string(val); _type = Type::NUMBER; } } else { while (!strchr("[]{}<>", ir.peek()) && !isspace(ir.peek())) _value += ir.get(); _type = Type::OPERATOR; } } dvisvgm-3.5/src/CMapReader.hpp000066400000000000000000000060101501401750600162770ustar00rootroot00000000000000/************************************************************************* ** CMapReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CMAPREADER_HPP #define CMAPREADER_HPP #include #include #include #include #include #include "MessageException.hpp" struct CMap; class InputReader; class CMapReader { class Token { public: enum class Type {UNKNOWN, END, DELIM, NUMBER, STRING, NAME, OPERATOR}; public: explicit Token (InputReader &ir); void scan (InputReader &ir); Type type () const {return _type;} const std::string& strvalue () const {return _value;} double numvalue () const {return std::atof(_value.c_str());} private: Type _type; std::string _value; }; public: std::unique_ptr read (const std::string &fname); std::unique_ptr read (std::istream &is, const std::string &name); protected: Token popToken () {Token t=_tokens.back(); _tokens.pop_back(); return t;} void executeOperator (const std::string &op, InputReader &ir); void parseCIDChars (InputReader &ir, bool isRange); void op_beginbfchar (InputReader &ir); void op_beginbfrange (InputReader &ir); void op_begincidchar (InputReader &ir); void op_begincidrange (InputReader &ir); void op_def (InputReader &ir); void op_endcmap (InputReader &ir); void op_usecmap (InputReader &ir); private: std::unique_ptr _cmap; ///< pointer to CMap being read std::vector _tokens; ///< stack of tokens to be processed bool _inCMap=false; ///< true if operator begincmap has been executed }; struct CMapReaderException : public MessageException { explicit CMapReaderException (const std::string &msg) : MessageException(msg) {} }; #endif dvisvgm-3.5/src/Calculator.cpp000066400000000000000000000151711501401750600164300ustar00rootroot00000000000000/************************************************************************* ** Calculator.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include #include "Calculator.hpp" using namespace std; /** Evaluates a given arithmetic expression and returns its value. * The evaluator is implemented as a recursive descent parser. * @param[in] is reads expression from this stream * @return expression value */ double Calculator::eval (istream &is) const { double ret = expr(is, false); try { // check if expression has been fully evaluated (next token is of type bool) mpark::get(lookAhead(is)); } catch (mpark::bad_variant_access &) { throw CalculatorException("expression syntax error"); } return ret; } /** Evaluates a given arithmetic expression and returns its value. * @param[in] expr expression to evaluate * @return expression value */ double Calculator::eval (const string &expr) const { istringstream iss; iss.str(expr); return eval(iss); } /** Evaluates the root rule of the expression grammar. */ double Calculator::expr (istream &is, bool skip) const { // expr: double left = term(is, skip); bool ready=false; while (!ready) { Token token = lookAhead(is); char *op = mpark::get_if(&token); if (!op) ready = true; else { switch (*op) { case '+': left += term(is, true); break; // term '+' term => $1 + $3 case '-': left -= term(is, true); break; // term '-' term => $1 - $3 default : ready = true; } } } return left; // term => $1 } double Calculator::term (istream &is, bool skip) const { // term: double left = prim(is, skip); bool ready=false; while (!ready) { Token token = lookAhead(is); char *op = mpark::get_if(&token); if (!op) ready = true; else { switch (*op) { case '*': left *= prim(is, true); break; // prim '*' prim => $1 * $3 case '(': left *= prim(is, false); break; // prim '(' prim => $1 * $3 case '/': { // prim '/' prim => $1 / $3 double denom = prim(is, true); if (denom == 0) throw CalculatorException("division by zero"); left /= denom; break; } case '%': { // prim '%' prim => $1 mod $3 double denom = prim(is, true); if (denom == 0) throw CalculatorException("division by zero"); left -= denom * floor(left / denom); break; } default: ready = true; } } } return left; } /** Evaluates a primary expression of the grammar which doesn't contain any binary operators. */ double Calculator::prim (istream &is, bool skip) const { // prim: if (skip) lex(is); Token token = lookAhead(is); if (mpark::get_if(&token)) { // NUMBER => $1 double ret = mpark::get(lex(is)); token = lookAhead(is); if (mpark::get_if(&token)) // NUMBER STRING => $1 * $2 ret *= getVariable(mpark::get(lex(is))); return ret; } if (mpark::get_if(&token)) // STRING => getVariable($1) return getVariable(mpark::get(lex(is))); if (char *op = mpark::get_if(&token)) { switch (*op) { case '-': // '-' prim => -$2 return -prim(is, true); case '(': { // '(' expr ')' => $2 double e = expr(is, true); try { if (mpark::get(lookAhead(is)) != ')') throw CalculatorException("')' expected"); } catch (mpark::bad_variant_access &) { throw CalculatorException("')' expected"); } is.get(); // skip processed char return e; } } } throw CalculatorException("primary expression expected"); } /** Returns the value of a previously defined variable. If there * is no variable of the given name, a CalculatorException is thrown. * @param[in] name name of variable * @return assigned value */ double Calculator::getVariable (const string &name) const { auto it = _variables.find(name); if (it == _variables.end()) throw CalculatorException("undefined variable '" + name + "'"); return it->second; } /** Determines the type of the next token without swallowing it. That means * the same token will be read again next time. The value of the returned token * object is only set for character tokens and should be considered undefined * for the other types. */ Calculator::Token Calculator::lookAhead (istream &is) { is >> ws; int c = is.peek(); if (is.eof()) return false; if (isdigit(c) || c == '.') return double(0); if (isalpha(c)) return string(); return char(c); } /** Reads and swallows the next token. The returned Token object is represented by * a variant and thus contains both its type and value. * @param[in] is next token is read from this stream * @return the read token */ Calculator::Token Calculator::lex (istream &is) { Token token = lookAhead(is); if (mpark::get_if(&token)) is.get(); // token already contains the value from look ahead else if (mpark::get_if(&token)) { string str; while (isdigit(is.peek()) || is.peek() == '.') str += char(is.get()); try { token.emplace(stod(str)); } catch (const exception&) { throw CalculatorException("invalid number: "+str); } } else if (mpark::get_if(&token)) { string name; while (isalpha(is.peek())) name += char(is.get()); token.emplace(name); } return token; } dvisvgm-3.5/src/Calculator.hpp000066400000000000000000000044751501401750600164420ustar00rootroot00000000000000/************************************************************************* ** Calculator.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CALCULATOR_HPP #define CALCULATOR_HPP #include #include #include #include #include "MessageException.hpp" struct CalculatorException : public MessageException { explicit CalculatorException (const std::string &msg) : MessageException(msg) {} }; class Calculator { public: double eval (std::istream &is) const; double eval (const std::string &expr) const; void setVariable (const std::string &name, double value) {_variables[name] = value;} double getVariable (const std::string &name) const; protected: double expr (std::istream &is, bool skip) const; double term (std::istream &is, bool skip) const; double prim (std::istream &is, bool skip) const; using Token = mpark::variant; static Token lex (std::istream &is); static Token lookAhead (std::istream &is); private: std::map _variables; }; #endif dvisvgm-3.5/src/CharMapID.cpp000066400000000000000000000037701501401750600160710ustar00rootroot00000000000000/************************************************************************* ** CharMapID.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include "CharMapID.hpp" const CharMapID CharMapID::NONE(0, 0); const CharMapID CharMapID::WIN_SYMBOL(3, 0); const CharMapID CharMapID::WIN_UCS2(3, 1); const CharMapID CharMapID::WIN_SHIFTJIS(3, 2); const CharMapID CharMapID::WIN_PRC(3, 3); const CharMapID CharMapID::WIN_BIG5(3, 4); const CharMapID CharMapID::WIN_WANSUNG(3, 5); const CharMapID CharMapID::WIN_JOHAB(3, 6); const CharMapID CharMapID::WIN_UCS4(3, 10); const CharMapID CharMapID::MAC_JAPANESE(1, 1); const CharMapID CharMapID::MAC_TRADCHINESE(1, 2); const CharMapID CharMapID::MAC_KOREAN(1, 3); const CharMapID CharMapID::MAC_SIMPLCHINESE(1, 25); dvisvgm-3.5/src/CharMapID.hpp000066400000000000000000000047551501401750600161020ustar00rootroot00000000000000/************************************************************************* ** CharMapID.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CHARMAPID_HPP #define CHARMAPID_HPP #include /** Represents a character map of a font. */ struct CharMapID { CharMapID () noexcept =default; CharMapID (uint8_t plf_id, uint8_t enc_id) noexcept : platform_id(plf_id), encoding_id(enc_id) {} bool operator == (const CharMapID &ids) const { return platform_id == ids.platform_id && encoding_id == ids.encoding_id; } bool operator != (const CharMapID &ids) const { return platform_id != ids.platform_id || encoding_id != ids.encoding_id; } bool valid () const {return platform_id != 0 && encoding_id != 0;} static const CharMapID NONE; static const CharMapID WIN_SYMBOL; static const CharMapID WIN_UCS2; static const CharMapID WIN_SHIFTJIS; static const CharMapID WIN_PRC; static const CharMapID WIN_BIG5; static const CharMapID WIN_WANSUNG; static const CharMapID WIN_JOHAB; static const CharMapID WIN_UCS4; static const CharMapID MAC_JAPANESE; static const CharMapID MAC_TRADCHINESE; static const CharMapID MAC_SIMPLCHINESE; static const CharMapID MAC_KOREAN; uint8_t platform_id=0; uint8_t encoding_id=0; }; #endif dvisvgm-3.5/src/Character.hpp000066400000000000000000000037431501401750600162420ustar00rootroot00000000000000/************************************************************************* ** Character.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef CHARACTER_HPP #define CHARACTER_HPP #include class Character { public: enum Type {CHRCODE, INDEX, NAME}; explicit Character (const char *name) : _type(NAME), _name(name) {} Character (Type type, uint32_t val) : _type(type), _number(val) {} Character (Type type, const Character &c) : _type(type), _number(c.type() != NAME ? c._number : 0) {} Type type () const {return _type;} const char* name () const {return _name;} uint32_t number () const {return _number;} private: Type _type; union { uint32_t _number; const char *_name; }; }; #endif dvisvgm-3.5/src/Color.cpp000066400000000000000000000766421501401750600154270ustar00rootroot00000000000000/************************************************************************* ** Color.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include #include #include #include #include #include "algorithm.hpp" #include "Color.hpp" #include "utility.hpp" using namespace std; bool Color::SUPPRESS_COLOR_NAMES = true; const Color Color::BLACK(uint32_t(0)); const Color Color::WHITE(uint8_t(255), uint8_t(255), uint8_t(255)); inline uint8_t double_to_byte (double v) { v = max(0.0, min(1.0, v)); return uint8_t(round(255.0*v)); } /** Reads n double values from input stream is. The values may be * separated by whitespace and/or commas. */ static valarray read_doubles (istream &is, int n) { valarray values(n); for (double &val : values) { is >> ws; if (!util::read_double(is, val)) val = 0; is >> ws; if (is.peek() == ',') { is.get(); is >> ws; } } return values; } /** Creates a color object from a string specifying the color. It can * either be a PS color name or one of the color functions rgb(r,g,b), * cmyk(c,m,y,k) where the parameters are numbers in the interval * from 0 to 1. */ Color::Color (const string &colorstr) { if (colorstr.substr(0, 4) == "rgb(") { istringstream iss(colorstr.substr(4)); setRGB(read_doubles(iss, 3)); } else if (colorstr.substr(0, 5) == "cmyk(") { istringstream iss(colorstr.substr(5)); setCMYK(read_doubles(iss, 4)); } else if (!setPSName(colorstr, false)) setGray(uint8_t(0)); } Color::Color (const valarray &values, ColorSpace cs) noexcept : _cspace(cs) { int n = numComponents(cs); int i=0; _value = 0; for (int shift=(n-1)*8; shift >= 0; shift-=8) _value |= double_to_byte(values[i++]) << shift; } void Color::setRGB (uint8_t r, uint8_t g, uint8_t b) { _value = (r << 16) | (g << 8) | b; _cspace = ColorSpace::RGB; } void Color::setRGB (double r, double g, double b) { setRGB(double_to_byte(r), double_to_byte(g), double_to_byte(b)); } /** Sets the color value according to a given hex RGB string of the * form "#123456" or "#123" where the latter is expanded to "#112233". * The leading '#' character is optional. * @param[in] hexString the RGB hex string * @return true if the color value was assigned successfully */ bool Color::setRGBHexString (string hexString) { if (!hexString.empty()) { if (hexString[0] == '#') hexString = hexString.substr(1); if (hexString.length() == 3) { // expand short form "123" to "112233" hexString.resize(6); hexString[5] = hexString[4] = hexString[2]; hexString[3] = hexString[2] = hexString[1]; hexString[1] = hexString[0]; } if (hexString.length() == 6) { try { _value = stoi(hexString, nullptr, 16); _cspace = ColorSpace::RGB; return true; } catch (...) { } } } return false; } /** Expects a PostScript color name and sets the color accordingly. * @param[in] name PS color name * @param[in] case_sensitive if true, upper/lower case spelling is significant * @return true if color name could be applied properly */ bool Color::setPSName (string name, bool case_sensitive) { _cspace = ColorSpace::RGB; if (name[0] == '#') { char *p=nullptr; _value = uint32_t(strtol(name.c_str()+1, &p, 16)); while (isspace(*p)) p++; return (*p == 0 && _value <= 0xFFFFFF); } struct ColorConstant { const char *name; const uint32_t rgb; }; // converted color constants from color.pro static constexpr array constants {{ {"Apricot", 0xFFAD7A}, {"Aquamarine", 0x2DFFB2}, {"Bittersweet", 0xC10200}, {"Black", 0x000000}, {"Blue", 0x0000FF}, {"BlueGreen", 0x26FFAA}, {"BlueViolet", 0x190CF4}, {"BrickRed", 0xB70000}, {"Brown", 0x660000}, {"BurntOrange", 0xFF7C00}, {"CadetBlue", 0x606DC4}, {"CarnationPink", 0xFF5EFF}, {"Cerulean", 0x0FE2FF}, {"CornflowerBlue", 0x59DDFF}, {"Cyan", 0x00FFFF}, {"Dandelion", 0xFFB528}, {"DarkOrchid", 0x9932CC}, {"Emerald", 0x00FF7F}, {"ForestGreen", 0x00E000}, {"Fuchsia", 0x7202EA}, {"Goldenrod", 0xFFE528}, {"Gray", 0x7F7F7F}, {"Green", 0x00FF00}, {"GreenYellow", 0xD8FF4F}, {"JungleGreen", 0x02FF7A}, {"Lavender", 0xFF84FF}, {"LimeGreen", 0x7FFF00}, {"Magenta", 0xFF00FF}, {"Mahogany", 0xA50000}, {"Maroon", 0xAD0000}, {"Melon", 0xFF897F}, {"MidnightBlue", 0x007091}, {"Mulberry", 0xA314F9}, {"NavyBlue", 0x0F75FF}, {"OliveGreen", 0x009900}, {"Orange", 0xFF6321}, {"OrangeRed", 0xFF007F}, {"Orchid", 0xAD5BFF}, {"Peach", 0xFF7F4C}, {"Periwinkle", 0x6D72FF}, {"PineGreen", 0x00BF28}, {"Plum", 0x7F00FF}, {"ProcessBlue", 0x0AFFFF}, {"Purple", 0x8C23FF}, {"RawSienna", 0x8C0000}, {"Red", 0xFF0000}, {"RedOrange", 0xFF3A21}, {"RedViolet", 0x9600A8}, {"Rhodamine", 0xFF2DFF}, {"RoyalBlue", 0x007FFF}, {"RoyalPurple", 0x3F19FF}, {"RubineRed", 0xFF00DD}, {"Salmon", 0xFF779E}, {"SeaGreen", 0x4FFF7F}, {"Sepia", 0x4C0000}, {"SkyBlue", 0x60FFE0}, {"SpringGreen", 0xBCFF3D}, {"Tan", 0xDB9370}, {"TealBlue", 0x1EF9A3}, {"Thistle", 0xE068FF}, {"Turquoise", 0x26FFCC}, {"Violet", 0x351EFF}, {"VioletRed", 0xFF30FF}, {"White", 0xFFFFFF}, {"WildStrawberry", 0xFF0A9B}, {"Yellow", 0xFFFF00}, {"YellowGreen", 0x8EFF42}, {"YellowOrange", 0xFF9300}, }}; if (case_sensitive) { const ColorConstant cmppair = {name.c_str(), 0}; auto it = algo::lower_bound(constants, cmppair, [](const ColorConstant &c1, const ColorConstant &c2) { return strcmp(c1.name, c2.name) < 0; }); if (it != constants.end() && it->name == name) { _value = it->rgb; return true; } } else { name = util::tolower(name); auto it = algo::find_if(constants, [&](const ColorConstant &cc) { return name == util::tolower(cc.name); }); if (it != constants.end()) { _value = it->rgb; return true; } } return false; } void Color::setHSB (double h, double s, double b) { valarray hsb(3), rgb(3); hsb[0] = h; hsb[1] = s; hsb[2] = b; HSB2RGB(hsb, rgb); setRGB(rgb); } void Color::setCMYK (uint8_t c, uint8_t m, uint8_t y, uint8_t k) { _value = (c << 24) | (m << 16) | (y << 8) | k; _cspace = ColorSpace::CMYK; } void Color::setCMYK (double c, double m, double y, double k) { setCMYK(double_to_byte(c), double_to_byte(m), double_to_byte(y), double_to_byte(k)); } void Color::setCMYK (const std::valarray &cmyk) { setCMYK(cmyk[0], cmyk[1], cmyk[2], cmyk[3]); } void Color::set (ColorSpace colorSpace, VectorIterator &it) { switch (colorSpace) { case ColorSpace::GRAY: setGray(*it++); break; case ColorSpace::RGB : setRGB(*it, *(it+1), *(it+2)); it+=3; break; case ColorSpace::LAB : setLab(*it, *(it+1), *(it+2)); it+=3; break; case ColorSpace::CMYK: setCMYK(*it, *(it+1), *(it+2), *(it+3)); it+=4; break; default: ; } } Color Color::operator *= (double c) { if (abs(c) < 0.001) _value &= 0xff000000; else if (abs(c-trunc(c)) < 0.999) { uint32_t value=0; for (int i=0; i < 4; i++) { value |= lround((_value & 0xff)*c) << (8*i); _value >>= 8; } _value = value; } return *this; } /** Returns an RGB string representing the color. Depending on the * color value, the string either consists of 3 or 6 hex digits * plus a leading '#' character. */ string Color::rgbString () const { uint32_t rgb = getRGBUInt32(); ostringstream oss; oss << '#'; for (int i=2; i >= 0; i--) { oss << setbase(16) << setfill('0') << setw(2) << (((rgb >> (8*i)) & 0xff)); } // check if RGB string can be reduced to a three digit hex value // #RRGGBB => #RGB, e.g. #112233 => #123 string hexstr = oss.str(); if (hexstr[1] == hexstr[2] && hexstr[3] == hexstr[4] && hexstr[5] == hexstr[6]) { hexstr[2] = hexstr[3]; hexstr[3] = hexstr[5]; hexstr.resize(4); } return hexstr; } /** Returns an SVG color string representing the current color. The result can * either be an SVG color name or an RGB string of the form #RRGGBB. The latter * will be returned if parameter rgbonly is true or if the SVG standard doesn't * define a name for the current color. */ string Color::svgColorString (bool rgbonly) const { if (!rgbonly) { struct ColorName { uint32_t rgb; const char *name; }; static constexpr array colornames {{ {0x000000, "black"}, {0x000080, "navy"}, {0x00008b, "darkblue"}, {0x0000cd, "mediumblue"}, {0x0000ff, "blue"}, {0x006400, "darkgreen"}, {0x008000, "green"}, {0x008080, "teal"}, {0x008b8b, "darkcyan"}, {0x00bfff, "deepskyblue"}, {0x00ced1, "darkturquoise"}, {0x00fa9a, "mediumspringgreen"}, {0x00ff00, "lime"}, {0x00ff7f, "springgreen"}, {0x00ffff, "cyan"}, {0x191970, "midnightblue"}, {0x1e90ff, "dodgerblue"}, {0x20b2aa, "lightseagreen"}, {0x228b22, "forestgreen"}, {0x2e8b57, "seagreen"}, {0x2f4f4f, "darkslategray"}, {0x32cd32, "limegreen"}, {0x3cb371, "mediumseagreen"}, {0x40e0d0, "turquoise"}, {0x4169e1, "royalblue"}, {0x4682b4, "steelblue"}, {0x483d8b, "darkslateblue"}, {0x48d1cc, "mediumturquoise"}, {0x4b0082, "indigo"}, {0x556b2f, "darkolivegreen"}, {0x5f9ea0, "cadetblue"}, {0x6495ed, "cornflowerblue"}, {0x66cdaa, "mediumaquamarine"}, {0x696969, "dimgray"}, {0x6a5acd, "slateblue"}, {0x6b8e23, "olivedrab"}, {0x708090, "slategray"}, {0x778899, "lightslategray"}, {0x7b68ee, "mediumslateblue"}, {0x7cfc00, "lawngreen"}, {0x7fff00, "chartreuse"}, {0x7fffd4, "aquamarine"}, {0x800000, "maroon"}, {0x800080, "purple"}, {0x808000, "olive"}, {0x808080, "gray"}, {0x87ceeb, "skyblue"}, {0x87cefa, "lightskyblue"}, {0x8a2be2, "blueviolet"}, {0x8b0000, "darkred"}, {0x8b008b, "darkmagenta"}, {0x8b4513, "saddlebrown"}, {0x8fbc8f, "darkseagreen"}, {0x90ee90, "lightgreen"}, {0x9370db, "mediumpurple"}, {0x9400d3, "darkviolet"}, {0x98fb98, "palegreen"}, {0x9932cc, "darkorchid"}, {0x9acd32, "yellowgreen"}, {0xa0522d, "sienna"}, {0xa52a2a, "brown"}, {0xa9a9a9, "darkgray"}, {0xadd8e6, "lightblue"}, {0xadff2f, "greenyellow"}, {0xafeeee, "paleturquoise"}, {0xb0c4de, "lightsteelblue"}, {0xb0e0e6, "powderblue"}, {0xb22222, "firebrick"}, {0xb8860b, "darkgoldenrod"}, {0xba55d3, "mediumorchid"}, {0xbc8f8f, "rosybrown"}, {0xbdb76b, "darkkhaki"}, {0xc0c0c0, "silver"}, {0xc71585, "mediumvioletred"}, {0xcd5c5c, "indianred"}, {0xcd853f, "peru"}, {0xd2691e, "chocolate"}, {0xd2b48c, "tan"}, {0xd3d3d3, "lightgray"}, {0xd8bfd8, "thistle"}, {0xda70d6, "orchid"}, {0xdaa520, "goldenrod"}, {0xdb7093, "palevioletred"}, {0xdc143c, "crimson"}, {0xdcdcdc, "gainsboro"}, {0xdda0dd, "plum"}, {0xdeb887, "burlywood"}, {0xe0ffff, "lightcyan"}, {0xe6e6fa, "lavender"}, {0xe9967a, "darksalmon"}, {0xee82ee, "violet"}, {0xeee8aa, "palegoldenrod"}, {0xf08080, "lightcoral"}, {0xf0e68c, "khaki"}, {0xf0f8ff, "aliceblue"}, {0xf0fff0, "honeydew"}, {0xf0ffff, "azure"}, {0xf4a460, "sandybrown"}, {0xf5deb3, "wheat"}, {0xf5f5dc, "beige"}, {0xf5f5f5, "whitesmoke"}, {0xf5fffa, "mintcream"}, {0xf8f8ff, "ghostwhite"}, {0xfa8072, "salmon"}, {0xfaebd7, "antiquewhite"}, {0xfaf0e6, "linen"}, {0xfafad2, "lightgoldenrodyellow"}, {0xfdf5e6, "oldlace"}, {0xff0000, "red"}, {0xff00ff, "magenta"}, {0xff1493, "deeppink"}, {0xff4500, "orangered"}, {0xff6347, "tomato"}, {0xff69b4, "hotpink"}, {0xff7f50, "coral"}, {0xff8c00, "darkorange"}, {0xffa07a, "lightsalmon"}, {0xffa500, "orange"}, {0xffb6c1, "lightpink"}, {0xffc0cb, "pink"}, {0xffd700, "gold"}, {0xffdab9, "peachpuff"}, {0xffdead, "navajowhite"}, {0xffe4b5, "moccasin"}, {0xffe4c4, "bisque"}, {0xffe4e1, "mistyrose"}, {0xffebcd, "blanchedalmond"}, {0xffefd5, "papayawhip"}, {0xfff0f5, "lavenderblush"}, {0xfff5ee, "seashell"}, {0xfff8dc, "cornsilk"}, {0xfffacd, "lemonchiffon"}, {0xfffaf0, "floralwhite"}, {0xfffafa, "snow"}, {0xffff00, "yellow"}, {0xffffe0, "lightyellow"}, {0xfffff0, "ivory"}, {0xffffff, "white"} }}; ColorName cmppair = {_value, nullptr}; auto it = algo::lower_bound(colornames, cmppair, [](const ColorName &c1, const ColorName &c2) { return c1.rgb < c2.rgb; }); if (it != colornames.end() && it->rgb == _value) return it->name; } return rgbString(); } valarray Color::getDoubleValues () const { int n = numComponents(_cspace); valarray values(n); int i=0; for (int shift= (n-1)*8; shift >= 0; shift-=8) values[i++] = ((_value >> shift) & 0xff)/255.0; return values; } static uint32_t interpolate_cmyk2rgb (const valarray &cmyk); /** Approximates a CMYK color by an RGB triple. The component values * are expected to be normalized, i.e. 0 <= cmyk[i],rgb[j] <= 1. * @param[in] cmyk color in CMYK space * @param[out] rgb RGB approximation */ void Color::CMYK2RGB (const valarray &cmyk, valarray &rgb) { #if 0 double cc = 1-cmyk[0]; double mc = 1-cmyk[1]; double yc = 1-cmyk[2]; double kc = 1-cmyk[3]; // https://graphicdesign.stackexchange.com/a/137902 rgb[0] = 0.3137+0.5882*cc-0.3529*mc-0.1373*yc+0.47175*cc*mc+0.1173*yc*cc; rgb[1] = 0.2588-0.1961*cc+0.2745*mc-0.0627*yc+0.54825*cc*mc+0.0204*yc*cc+0.1581*yc*mc; rgb[2] = 0.3373-0.3255*cc-0.1569*mc+0.1647*yc+0.1173*cc*mc+0.31365*yc*cc+0.54825*yc*mc; for (int i=0; i < 3; i++) rgb[i] = min(1.0, max(0.0, rgb[i]*kc)); #else uint32_t rgb32 = interpolate_cmyk2rgb(cmyk); rgb[0] = (rgb32 >> 16) / 255.0; rgb[1] = ((rgb32 >> 8) & 0xff) / 255.0; rgb[2] = (rgb32 & 0xff) / 255.0; #endif } /** Converts a color given in HSB coordinates to RGB. * @param[in] hsb color in HSB space * @param[out] rgb color in RGB space */ void Color::HSB2RGB (const valarray &hsb, valarray &rgb) { if (hsb[1] == 0) rgb[0] = rgb[1] = rgb[2] = hsb[2]; else { double h = hsb[0]-floor(hsb[0]); int i = int(6*h); double f = 6*h-i; double p = hsb[2]*(1-hsb[1]); double q = hsb[2]*(1-hsb[1]*f); double t = hsb[2]*(1-hsb[1]*(1-f)); switch (i) { case 0 : rgb[0]=hsb[2]; rgb[1]=t; rgb[2]=p; break; case 1 : rgb[0]=q; rgb[1]=hsb[2]; rgb[2]=p; break; case 2 : rgb[0]=p; rgb[1]=hsb[2]; rgb[2]=t; break; case 3 : rgb[0]=p; rgb[1]=q; rgb[2]=hsb[2]; break; case 4 : rgb[0]=t; rgb[1]=p; rgb[2]=hsb[2]; break; case 5 : rgb[0]=hsb[2]; rgb[1]=p; rgb[2]=q; break; default: ; // prevent compiler warning } } } double Color::getGray () const { double r, g, b; getRGB(r, g, b); return r*0.3 + g*0.59 + b*0.11; // gray value according to NTSC video standard } void Color::getGray (valarray &gray) const { gray.resize(1); gray[0] = getGray(); } valarray Color::getRGBDouble () const { valarray values = getDoubleValues(); valarray rgbValues; switch (_cspace) { case ColorSpace::RGB: rgbValues = std::move(values); break; case ColorSpace::CMYK: rgbValues.resize(3); CMYK2RGB(values, rgbValues); break; case ColorSpace::GRAY: rgbValues.resize(3); rgbValues[0] = rgbValues[1] = rgbValues[2] = values[0]; break; case ColorSpace::LAB: rgbValues.resize(3); Lab2XYZ(values, rgbValues); XYZ2RGB(rgbValues, values); rgbValues = std::move(values); break; default: ; } return rgbValues; } uint32_t Color::getRGBUInt32 () const { switch (_cspace) { case ColorSpace::GRAY: { uint32_t gray = _value & 0xff; return (gray << 16) | (gray << 8) | gray; } case ColorSpace::RGB: return _value; default: valarray rgb = getRGBDouble(); return (double_to_byte(rgb[0]) << 16) | (double_to_byte(rgb[1]) << 8) | (double_to_byte(rgb[2])); } } void Color::getRGB (double &r, double &g, double &b) const { valarray rgb = getRGBDouble(); r = rgb[0]; g = rgb[1]; b = rgb[2]; } void Color::getRGB (valarray &rgb) const { rgb = getRGBDouble(); } void Color::getXYZ (double &x, double &y, double &z) const { valarray rgb(3), xyz(3); getRGB(rgb); RGB2XYZ(std::move(rgb), xyz); x = xyz[0]; y = xyz[1]; z = xyz[2]; } void Color::setXYZ (double x, double y, double z) { valarray xyz(3), rgb(3); xyz[0] = x; xyz[1] = y; xyz[2] = z; XYZ2RGB(xyz, rgb); setRGB(rgb); _cspace = ColorSpace::RGB; } void Color::setXYZ (const valarray &xyz) { valarray rgb(3); XYZ2RGB(xyz, rgb); setRGB(rgb); _cspace = ColorSpace::RGB; } void Color::setLab (double l, double a, double b) { valarray lab(3), xyz(3); lab[0] = l; lab[1] = a; lab[2] = b; Lab2XYZ(lab, xyz); setXYZ(xyz); } void Color::setLab (const valarray &lab) { valarray xyz(3); Lab2XYZ(lab, xyz); setXYZ(xyz); } /** Get the color in CIELAB color space using the sRGB working space and reference white D65. */ void Color::getLab (double &l, double &a, double &b) const { valarray rgb(3), lab(3); getRGB(rgb); RGB2Lab(rgb, lab); l = lab[0]; a = lab[1]; b = lab[2]; } void Color::getLab (std::valarray &lab) const { lab.resize(3); valarray rgb(3); getRGB(rgb); RGB2Lab(rgb, lab); } inline double cube (double x) {return x*x*x;} void Color::Lab2XYZ (const valarray &lab, valarray &xyz) { xyz.resize(3); double wx=0.95047, wy=1.00, wz=1.08883; // reference white D65 double eps = 0.008856; double kappa = 903.3; double fy = (lab[0]+16)/116; double fx = lab[1]/500 + fy; double fz = fy - lab[2]/200; double xr = (cube(fx) > eps ? cube(fx) : (116*fx-16)/kappa); double yr = (lab[0] > kappa*eps ? cube((lab[0]+16)/116) : lab[0]/kappa); double zr = (cube(fz) > eps ? cube(fz) : (116*fz-16)/kappa); xyz[0] = xr*wx; xyz[1] = yr*wy; xyz[2] = zr*wz; } void Color::XYZ2RGB (const valarray &xyz, valarray &rgb) { rgb.resize(3); rgb[0] = 3.2404542*xyz[0] - 1.5371385*xyz[1] - 0.4985314*xyz[2]; rgb[1] = -0.9692660*xyz[0] + 1.8760108*xyz[1] + 0.0415560*xyz[2]; rgb[2] = 0.0556434*xyz[0] - 0.2040259*xyz[1] + 1.0572252*xyz[2]; for (int i=0; i < 3; i++) rgb[i] = (rgb[i] <= 0.0031308 ? 12.92*rgb[i] : 1.055*pow(rgb[i], 1/2.4)-0.055); } void Color::RGB2XYZ (valarray rgb, valarray &xyz) { xyz.resize(3); for (int i=0; i < 3; i++) rgb[i] = (rgb[i] <= 0.04045 ? rgb[i]/12.92 : pow((rgb[i]+0.055)/1.055, 2.4)); xyz[0] = 0.4124564*rgb[0] + 0.3575761*rgb[1] + 0.1804375*rgb[2]; xyz[1] = 0.2126729*rgb[0] + 0.7151522*rgb[1] + 0.0721750*rgb[2]; xyz[2] = 0.0193339*rgb[0] + 0.1191920*rgb[1] + 0.9503041*rgb[2]; } void Color::RGB2Lab (const valarray &rgb, valarray &lab) { double wx=0.95047, wy=1.00, wz=1.08883; // reference white D65 double eps = 0.008856; double kappa = 903.3; valarray xyz(3); RGB2XYZ(rgb, xyz); xyz[0] /= wx; xyz[1] /= wy; xyz[2] /= wz; double fx = (xyz[0] > eps ? pow(xyz[0], 1.0/3) : (kappa*xyz[0]+16)/116); double fy = (xyz[1] > eps ? pow(xyz[1], 1.0/3) : (kappa*xyz[1]+16)/116); double fz = (xyz[2] > eps ? pow(xyz[2], 1.0/3) : (kappa*xyz[2]+16)/116); lab[0] = 116*fy-16; lab[1] = 500*(fx-fy); lab[2] = 200*(fy-fz); } #if 0 /** Returns the Delta E difference (CIE 2000) between this and another color. */ double Color::deltaE (const Color &c) const { double l1, a1, b1; double l2, a2, b2; getLab(l1, a1, b1); c.getLab(l2, a2, b2); const double deltaL = l2-l1; const double lBar = (l1+l2)/2; const double c1 = hypot(a1, b1); const double c2 = hypot(a2, b2); const double cBar = (c1+c2)/2.0; const double g = (1.0-sqrt(pow(cBar, 7.0)/(pow(cBar, 7.0)+6103515625.0)))/2.0; const double aa1 = a1*(1.0+g); const double aa2 = a2*(1.0+g); const double cc1 = hypot(aa1, b1); const double cc2 = hypot(aa2, b2); const double ccBar = (cc1+cc2)/2.0; const double deltaCC = cc2-cc1; double hh1 = atan2(b1, aa1); if (hh1 < 0) hh1 += deg2rad(360); double hh2 = atan2(b2, aa2); if (hh2 < 0) hh2 += deg2rad(360); const double hhBar = (std::abs(hh1-hh2) > deg2rad(180) ? (hh1+hh2+deg2rad(360)) : (hh1+hh2))/2.0; const double t = 1.0 - 0.17*cos(hhBar-deg2rad(30.0)) + 0.24*cos(2.0*hhBar) + 0.32*cos(3.0*hhBar+deg2rad(6.0)) - 0.20*cos(4.0*hhBar-deg2rad(63.0)); double deltaHH = hh2-hh1; if (deltaHH < deg2rad(-180)) deltaHH += deg2rad(360); else if (deltaHH > deg2rad(180)) deltaHH -= deg2rad(360); const double deltaHHH = 2.0*sqrt(cc1*cc2)*sin(deltaHH/2.0); const double sl = 1.0 + 0.015*sqr(lBar-50.0)/sqrt(20.0+sqr(lBar-50.0)); const double sc = 1.0 + 0.045*ccBar; const double sh = 1.0 + 0.015*ccBar*t; const double deltaTheta = deg2rad(30)*exp(-sqr((hhBar-deg2rad(275))/deg2rad(25))); const double rc = 2.0*sqrt(pow(ccBar, 7)/(pow(ccBar, 7)+6103515625.0)); const double rt = -rc*sin(2.0*deltaTheta); const double deltaE = sqrt(sqr(deltaL/sl) + sqr(deltaCC/sc) + sqr(deltaHHH/sh) + rt*deltaCC/sc*deltaHHH/sh); return deltaE; } #endif int Color::numComponents (ColorSpace colorSpace) { switch (colorSpace) { case ColorSpace::GRAY: return 1; case ColorSpace::LAB: case ColorSpace::RGB: return 3; case ColorSpace::CMYK: return 4; default: ; } return 0; } struct Cmyk2RgbTable { using IntVec = vector; using DoubleVec = vector; static constexpr const int GRIDSIZE = 5; // number of grid points per CMYK component static array rgbvalues; static const array dimfactors; static double interpolate (const IntVec &gi0, const IntVec &gi1, const DoubleVec &t, int icmyk, int irgb, int idx); }; // For grid indices ci, mi, yi, ki, the corresponding table entry is located // at index ci + mi*GRIDSIZE + yi*GRIDSIZE^2 + ki*GRIDSIZE^3. const array Cmyk2RgbTable::dimfactors {{ 1, GRIDSIZE, GRIDSIZE*GRIDSIZE, GRIDSIZE*GRIDSIZE*GRIDSIZE }}; /** Compute RGB from CMYK by multivariate linear interpolation of sampled color values. * @param[in] cmyk CMYK color components (all values between 0 and 1) * @return 24-bit RGB color value (0x00RRGGBB) */ static uint32_t interpolate_cmyk2rgb (const valarray &cmyk) { vector gi0(4), gi1(4); // upper and lower grid indices enclosing the CMYK components vector t(4); // fractional parts of the grid indices where the CMYK components are located for (int i=0; i < 4; i++) { double gridpos = math::clip(cmyk[i], 0, 1)*(Cmyk2RgbTable::GRIDSIZE-1); double gi; t[i] = modf(gridpos, &gi); // distance of i-th CMYK component to nearest lower grid index (in [0,1)) gi0[i] = int(gi); // index of nearest grid value <= i-th CMYK component gi1[i] = ceil(gridpos); // index of nearest grid value >= i-th CMYK component } uint32_t rgb=0; for (int i=0; i < 3; i++) { double rgb_component = Cmyk2RgbTable::interpolate(gi0, gi1, t, 3, i, 0); rgb_component = round(math::clip(rgb_component, 0, 255)); rgb = (rgb << 8) | int(rgb_component); } return rgb; } inline uint32_t get_byte (uint32_t value, int n) { return (value >> n*8) & 0xff; } /** Computes an RGB color component for a CMYK color by multi-linear interpolation * using a 4-dimensional grid of pre-computed color values. * @param[in] gi0 indices of nearest grid values <= corresponding CMYK components * @param[in] gi1 indices of nearest grid values >= corresponding CMYK components * @param[in] t fractional parts of the grid indices where the components of the CMYK color are located * @param[in] icmyk index of CMYK component to process (0=C, 1=M, 2=Y, 3=K) * @param[in] irgb index of RGB component to interpolate (0=R, 1=G, 2=B) * @param[in] idx index of RGB value in lookup table (computed during recursion, final value reached when icmyk==0) * @return The interpolated RGB color component in the range from 0 to 255. */ double Cmyk2RgbTable::interpolate (const IntVec &gi0, const IntVec &gi1, const DoubleVec &t, int icmyk, int irgb, int idx) { int idx0 = gi0[icmyk]*dimfactors[icmyk]+idx; int idx1 = gi1[icmyk]*dimfactors[icmyk]+idx; double a, b; if (icmyk == 0) { a = get_byte(rgbvalues[idx0], 2-irgb); b = get_byte(rgbvalues[idx1], 2-irgb); } else { a = interpolate(gi0, gi1, t, icmyk-1, irgb, idx0); b = interpolate(gi0, gi1, t, icmyk-1, irgb, idx1); } return a + (b-a)*t[icmyk]; } /** RGB values for a 5x5x5x5 grid of CMYK values in [0,1]^4, i.e. the grid values of each dimension * are 0, 0.25, 0.5, 0.75, and 1. For grid coordinates (c,m,y,k), the corresponding RGB values are * located at index ci + 5*mi + 5*5*yi + 5*5*5*ki where ci=4*c, mi=4*m, yi=4*y, ki=4*k. * The RGB values were computed with Little CMS utility 'transicc' using options -t1 and -b * applied to Ghostscript's ICC profiles default_cmyk.icc and default_rgb.icc. */ array Cmyk2RgbTable::rgbvalues {{ 0xffffff,0xb9e5fa,0x6dcff6,0x00bdf2,0x00aeef,0xf9cbdf,0xbbb8dc,0x7da7d9,0x1c9ad6,0x008fd5,0xf49ac1,0xbc8cbf,0x8781bd,0x4978bc,0x0072bc,0xf067a6, 0xbd60a5,0x8e5ba5,0x5b57a6,0x0054a6,0xec008c,0xbd1a8d,0x92278f,0x662c91,0x2e3092,0xfffbcc,0xc0e2ca,0x7accc8,0x00bac6,0x00abc5,0xfbc8b4,0xc1b6b3, 0x86a6b2,0x3799b1,0x008eb0,0xf5989d,0xc08c9c,0x8d819c,0x51789c,0x00719c,0xf16687,0xc06188,0x915c89,0x5f588a,0x03558b,0xed0972,0xbf1e74,0x942977, 0x682f79,0x32327b,0xfff799,0xc4df9b,0x82ca9c,0x07b89d,0x00a99d,0xfdc689,0xc3b48b,0x8aa48c,0x43978d,0x008c8d,0xf69679,0xc28b7b,0x8f807d,0x56777e, 0x00707e,0xf1666a,0xc1616c,0x925c6e,0x625870,0x145571,0xed145a,0xbf235e,0x942c61,0x693163,0x343465,0xfff45f,0xc8dd69,0x88c86f,0x2bb673,0x00a775, 0xfec35a,0xc6b261,0x8ea366,0x4b9669,0x008b6b,0xf79552,0xc48a57,0x927f5c,0x5b775f,0x006f61,0xf26649,0xc2614e,0x945c53,0x645855,0x1c5557,0xed1941, 0xc02646,0x952e4a,0x6a324d,0x35354e,0xfff200,0xcbdb2a,0x8dc63f,0x39b54a,0x00a650,0xffc20d,0xc8b12f,0x91a23d,0x519546,0x008a4b,0xf7941d,0xc5892f, 0x947f3a,0x5e7641,0x006f45,0xf26522,0xc3602e,0x955c37,0x66583c,0x22543f,0xed1c24,0xc1272d,0x962e34,0x6b3337,0x363639,0xc7c8ca,0x92b6c7,0x57a5c4, 0x0097c1,0x008bbf,0xc3a0b2,0x9593b0,0x6486ae,0x177bac,0x0072aa,0xc0799a,0x967099,0x6c6798,0x3a6097,0x005a96,0xbd4f84,0x964b84,0x714784,0x484385, 0x004185,0xba006f,0x960470,0x741372,0x511b74,0x232176,0xcac6a3,0x97b3a2,0x60a3a0,0x00959f,0x008a9e,0xc59f90,0x98918f,0x6a858e,0x2a7a8e,0x00728d, 0xc1787d,0x986f7d,0x70677d,0x40607d,0x00597d,0xbd506c,0x984b6c,0x73486d,0x4b446e,0x00416f,0xbb005a,0x970e5c,0x75185e,0x531e60,0x262261,0xcbc37b, 0x9ab07c,0x65a07d,0x00937d,0x00887e,0xc69c6d,0x9a8f6f,0x6d836f,0x337970,0x007071,0xc17760,0x996e61,0x716663,0x435f63,0x005964,0xbe4f53,0x984b55, 0x744857,0x4c4458,0x0a4159,0xba0546,0x971549,0x751c4b,0x52214d,0x27244f,0xccc04d,0x9cae53,0x6a9f58,0x1c915c,0x00875e,0xc69a47,0x9b8e4c,0x6f824f, 0x397853,0x006f55,0xc1753f,0x9a6d43,0x736547,0x465e4a,0x00584c,0xbe4f38,0x994b3b,0x74483f,0x4e4442,0x124144,0xba0e31,0x971934,0x761f37,0x53233a, 0x28253c,0xccbe00,0x9dad20,0x6d9d30,0x28903a,0x008641,0xc7990b,0x9c8c21,0x71812d,0x3d7735,0x006f3b,0xc27514,0x9b6c21,0x74652a,0x485e30,0x005834, 0xbe4f17,0x994b20,0x754827,0x4f442c,0x17412f,0xba1319,0x981b1e,0x762123,0x542427,0x2a2529,0x939598,0x6c8896,0x3e7c94,0x007192,0x006991,0x917786, 0x6f6d84,0x496483,0x055b82,0x005581,0x8f5973,0x705273,0x504b72,0x274572,0x004071,0x8e3762,0x713363,0x543063,0x332d63,0x002b64,0x8c0052,0x710053, 0x570054,0x3b0256,0x140858,0x95937a,0x6f8679,0x447a78,0x007078,0x006877,0x92766b,0x716c6b,0x4c636a,0x175b6a,0x00546a,0x90585d,0x71515d,0x524b5d, 0x2b455d,0x00405d,0x8e384f,0x713450,0x553151,0x352e51,0x002c52,0x8c0041,0x710043,0x570144,0x3b0846,0x160d47,0x96915b,0x70845c,0x48785d,0x006e5e, 0x00665e,0x937450,0x716a51,0x4e6252,0x1e5a53,0x005454,0x905745,0x715047,0x524b48,0x2d4549,0x00404a,0x8d383a,0x71353c,0x55323e,0x362f40,0x002c41, 0x8b0030,0x700032,0x560835,0x3b0d37,0x161038,0x968f37,0x72823c,0x4a7740,0x006d43,0x006545,0x937231,0x726935,0x506039,0x23593b,0x00533e,0x90562a, 0x71502e,0x534a31,0x2f4534,0x004036,0x8d3823,0x713527,0x55322a,0x362f2d,0x002d2f,0x8b001d,0x700520,0x560c23,0x3b1026,0x161228,0x968d00,0x728012, 0x4c7520,0x0d6c28,0x00652e,0x937100,0x726812,0x51601c,0x265823,0x005228,0x905500,0x714f0f,0x534919,0x31441e,0x004022,0x8d3802,0x71350d,0x553215, 0x37301a,0x012d1d,0x8b0204,0x70090a,0x560f10,0x3b1215,0x171417,0x636466,0x465a65,0x225264,0x004b63,0x004563,0x624e59,0x494758,0x2c4058,0x003a57, 0x003557,0x61374c,0x4a324c,0x322d4c,0x0f284c,0x00244c,0x601b3f,0x4b1740,0x361441,0x1c1041,0x000d42,0x600032,0x4c0034,0x380035,0x220037,0x000038, 0x636250,0x475950,0x265150,0x004a50,0x004550,0x624d45,0x494646,0x2e4046,0x003a46,0x003546,0x61363a,0x4a323b,0x332d3c,0x12293c,0x00253c,0x601c30, 0x4b1931,0x361632,0x1c1333,0x001134,0x5f0024,0x4b0027,0x380029,0x22002a,0x00002b,0x64603a,0x48573b,0x28503c,0x00493d,0x00443d,0x624b31,0x4a4532, 0x2f3f33,0x003a34,0x003535,0x603628,0x4a312a,0x332d2b,0x14292c,0x00252d,0x5f1d1f,0x4b1a21,0x351823,0x1c1525,0x001226,0x5e0015,0x4b0018,0x37001b, 0x21001d,0x00001e,0x645f1e,0x495623,0x2a4f26,0x004928,0x00442a,0x624a18,0x4a441c,0x303e1f,0x043922,0x003524,0x603510,0x4a3115,0x332d18,0x15291b, 0x00261d,0x5f1d07,0x4a1b0d,0x351911,0x1c1714,0x001416,0x5e0000,0x4a0004,0x370008,0x21000c,0x00000e,0x635e00,0x495500,0x2b4e08,0x004811,0x004416, 0x624a00,0x4a4300,0x303e03,0x07390b,0x003510,0x603500,0x4a3100,0x332d00,0x162904,0x002608,0x5f1e00,0x4a1b00,0x351900,0x1c1700,0x001502,0x5e0000, 0x4a0000,0x360000,0x210000,0x000000,0x231f20,0x0c1a21,0x001522,0x001123,0x000e23,0x230d15,0x100617,0x000019,0x00001a,0x00001b,0x230008,0x13000d, 0x00000f,0x000011,0x000012,0x230000,0x150001,0x030005,0x000008,0x00000a,0x230000,0x160000,0x060000,0x000000,0x000001,0x201d12,0x081914,0x001515, 0x001216,0x001017,0x210c04,0x0e0608,0x00020a,0x00000c,0x00000d,0x220000,0x120000,0x000000,0x000002,0x000003,0x230000,0x140000,0x010000,0x000000, 0x000000,0x230000,0x150000,0x040000,0x000000,0x000000,0x1e1c00,0x061802,0x001504,0x001306,0x001107,0x200c00,0x0d0700,0x000300,0x000100,0x000000, 0x210000,0x110000,0x000000,0x000000,0x000000,0x220000,0x130000,0x000000,0x000000,0x000000,0x230000,0x150000,0x030000,0x000000,0x000000,0x1c1b00, 0x041800,0x001500,0x001300,0x001200,0x1f0b00,0x0b0700,0x000400,0x000200,0x000100,0x210000,0x100000,0x000000,0x000000,0x000000,0x220000,0x120000, 0x000000,0x000000,0x000000,0x230000,0x140000,0x020000,0x000000,0x000000,0x1b1a00,0x021700,0x001500,0x001400,0x001200,0x1e0b00,0x0a0700,0x000500, 0x000300,0x000200,0x200000,0x0f0000,0x000000,0x000000,0x000000,0x210000,0x120000,0x000000,0x000000,0x000000,0x220000,0x140000,0x010000,0x000000, 0x000000 }}; dvisvgm-3.5/src/Color.hpp000066400000000000000000000117321501401750600154210ustar00rootroot00000000000000/************************************************************************* ** Color.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef COLOR_HPP #define COLOR_HPP #include #include #include #include #include "VectorIterator.hpp" #ifdef TRANSPARENT #undef TRANSPARENT #endif class Color { public: static bool SUPPRESS_COLOR_NAMES; static const Color BLACK; static const Color WHITE; enum class ColorSpace {GRAY, RGB, CMYK, LAB, TRANSPARENT}; public: Color () noexcept =default; explicit Color (uint32_t rgb) noexcept : _value(rgb) {} Color (uint32_t value, ColorSpace cs) : _value(value), _cspace(cs) {} Color (uint8_t r, uint8_t g, uint8_t b) noexcept {setRGB(r,g,b);} Color (double r, double g, double b) noexcept {setRGB(r,g,b);} explicit Color (const std::valarray &rgb) noexcept {setRGB(rgb);} explicit Color (const std::valarray &rgb, ColorSpace cs) noexcept; explicit Color (const std::string &colorstr); explicit operator uint32_t () const {return _value;} bool operator == (const Color &c) const {return _value == c._value;} bool operator != (const Color &c) const {return _value != c._value;} bool operator < (const Color &c) const {return _value < c._value;} Color operator *= (double c); Color operator * (double c) const {return Color(*this) *= c;} bool isTransparent () const {return _cspace == ColorSpace::TRANSPARENT;} void setRGB (uint8_t r, uint8_t g, uint8_t b); void setRGB (double r, double g, double b); void setRGB (const std::valarray &rgb) {setRGB(rgb[0], rgb[1], rgb[2]);} bool setRGBHexString (std::string hexString); bool setPSName (std::string name, bool case_sensitive=true); void setGray (uint8_t g) {setRGB(g,g,g);} void setGray (double g) {setRGB(g,g,g);} void setGray (const std::valarray &gray) {setRGB(gray[0], gray[0], gray[0]);} void setHSB (double h, double s, double b); void setCMYK (uint8_t c, uint8_t m, uint8_t y, uint8_t k); void setCMYK (double c, double m, double y, double k); void setCMYK (const std::valarray &cmyk); void setXYZ (double x, double y, double z); void setXYZ (const std::valarray &xyz); void setLab (double l, double a, double b); void setLab (const std::valarray &lab); void set (ColorSpace colorSpace, VectorIterator &it); std::valarray getDoubleValues () const; double getGray () const; void getGray (std::valarray &gray) const; void getRGB (double &r, double &g, double &b) const; void getRGB (std::valarray &rgb) const; void getXYZ (double &x, double &y, double &z) const; void getLab (double &l, double &a, double &b) const; void getLab (std::valarray &lab) const; double deltaE (const Color &c) const; std::string rgbString () const; std::string svgColorString (bool rgbonly) const; std::string svgColorString () const {return svgColorString(SUPPRESS_COLOR_NAMES);} static void CMYK2RGB (const std::valarray &cmyk, std::valarray &rgb); static void HSB2RGB (const std::valarray &hsb, std::valarray &rgb); static void RGB2XYZ (std::valarray rgb, std::valarray &xyz); static void XYZ2RGB (const std::valarray &xyz, std::valarray &rgb); static void RGB2Lab (const std::valarray &rgb, std::valarray &lab); static void Lab2XYZ (const std::valarray &lab, std::valarray &xyz); static int numComponents (ColorSpace colorSpace); protected: uint32_t getRGBUInt32 () const; std::valarray getRGBDouble () const; private: uint32_t _value=0; ColorSpace _cspace=ColorSpace::RGB; }; #endif dvisvgm-3.5/src/ColorSpecialHandler.cpp000066400000000000000000000143231501401750600202120ustar00rootroot00000000000000/************************************************************************* ** ColorSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include #include "algorithm.hpp" #include "ColorSpecialHandler.hpp" #include "SpecialActions.hpp" using namespace std; static double read_double (istream &is) { is.clear(); double v; is >> v; if (is.fail()) throw SpecialException("number expected"); return v; } /** Reads multiple double values from a given stream. The number of * values read is determined by the size of the result vector. * @param[in] is stream to be read from * @param[out] vec the resulting values */ static void read_doubles (istream &is, vector &vec) { algo::generate(vec, [&is]() { return read_double(is); }); } /** Reads a color statement from an input stream and converts it to a color object. * A color statement has the following syntax: * _color model_ _component values_ * Currently, the following color models are supported: rgb, cmyk, hsb and gray. * Examples: rgb 1 0.5 0, gray 0.5 * @param[in] model the color model * @param[in] is stream to be read from * @return resulting Color object */ Color ColorSpecialHandler::readColor (const string &model, istream &is) { Color color; if (model == "rgb") { vector rgb(3); read_doubles(is, rgb); color.setRGB(rgb[0], rgb[1], rgb[2]); } else if (model == "cmyk") { vector cmyk(4); read_doubles(is, cmyk); color.setCMYK(cmyk[0], cmyk[1], cmyk[2], cmyk[3]); } else if (model == "hsb") { vector hsb(3); read_doubles(is, hsb); color.setHSB(hsb[0], hsb[1], hsb[2]); } else if (model == "gray") color.setGray(read_double(is)); else if (!color.setPSName(model, true)) throw SpecialException("unknown color statement"); return color; } /** Reads the color model (rgb, cmyk, hsb, or gray) and the corresponding color components * from a given input stream. * @param[in] is stream to be read from * @return resulting Color object */ Color ColorSpecialHandler::readColor (istream &is) { string model; is >> model; return readColor(model, is); } bool ColorSpecialHandler::process (const string&, istream &is, SpecialActions &actions) { char colortype=0; auto pos = is.tellg(); string cmd; is >> cmd; if (cmd == "push") // color push [fill|stroke] colortype = processPush(is); else if (cmd == "pop") { if (!_colorStack.empty()) // color pop _colorStack.pop_back(); } else if (cmd == "set") // color set [fill|stroke] colortype = processSet(is); else { // color [fill|stroke] while (!_colorStack.empty()) _colorStack.pop_back(); is.seekg(pos); colortype = processPush(is); } if (_colorStack.empty()) { if (colortype == 0 || colortype == 'f') actions.setFillColor(_defaultFillColor); if (colortype == 0 || colortype == 's') actions.setStrokeColor(_defaultStrokeColor); } else { if (colortype == 0 || colortype == 'f') actions.setFillColor(_colorStack.back().fillColor); if (colortype == 0 || colortype == 's') actions.setStrokeColor(_colorStack.back().strokeColor); } return true; } /** Parses [fill|stroke] . * @param[in] is stream to read from * @param[out] type specified type color type ('f'=fill, 's'=stroke, 0=none specified) * @return color object representing the specified color */ static Color read_color_and_type (istream &is, char &type) { string token; string model; is >> token; if (token == "fill" || token == "stroke") { is >> model; type = token[0]; } else { model = std::move(token); type = '\0'; } return ColorSpecialHandler::readColor(model, is); } /** Handles push [fill|stroke] which pushes a new color pair * onto the stack. If 'fill' or 'stroke' is specified, only that color value is set. * The other one is copied from the current corresponding value. * @return color type specified in the special command ('f'=fill, 's'=stroke, 0=none specified) */ char ColorSpecialHandler::processPush (istream &is) { _colorStack.emplace_back(ColorPair{}); return processSet(is); } /** Handles set [fill|stroke] which changes the current * color pair without pushing new ones. If the stack is empty, the default * color values (usually black) are changed. * @return color type specified in the special command ('f'=fill, 's'=stroke, 0=none specified) */ char ColorSpecialHandler::processSet (istream &is) { char type; Color color = read_color_and_type(is, type); Color &fillColor = _colorStack.empty() ? _defaultFillColor : _colorStack.back().fillColor; Color &strokeColor = _colorStack.empty() ? _defaultStrokeColor : _colorStack.back().strokeColor; if (type == 0 || type == 'f') fillColor = color; if (type == 0 || type == 's') strokeColor = color; return type; } vector ColorSpecialHandler::prefixes () const { vector pfx {"color"}; return pfx; } dvisvgm-3.5/src/ColorSpecialHandler.hpp000066400000000000000000000047011501401750600202160ustar00rootroot00000000000000/************************************************************************* ** ColorSpecialHandler.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef COLORSPECIALHANDLER_HPP #define COLORSPECIALHANDLER_HPP #include #include #include #include "Color.hpp" #include "SpecialHandler.hpp" class ColorSpecialHandler : public SpecialHandler { private: struct ColorPair { Color fillColor; Color strokeColor; }; public: bool process (const std::string &prefix, std::istream &is, SpecialActions &actions) override; static Color readColor (std::istream &is); static Color readColor (const std::string &model, std::istream &is); const char* name () const override {return handlerName();} static const char* handlerName () {return "color";} const char* info () const override {return "complete support of color specials";} std::vector prefixes () const override; size_t stackSize () const {return _colorStack.size();} protected: char processPush (std::istream &is); char processSet (std::istream &is); private: Color _defaultFillColor = Color::BLACK; Color _defaultStrokeColor = Color::BLACK; std::vector _colorStack; }; #endif dvisvgm-3.5/src/CommandLine.hpp000066400000000000000000000201071501401750600165250ustar00rootroot00000000000000// This file was automatically generated by opt2cpp. // It is part of the dvisvgm package and published under the terms // of the GNU General Public License version 3, or (at your option) any later version. // See file COPYING for further details. // Copyright (C) 2016-2025 Martin Gieseking #ifndef COMMANDLINE_HPP #define COMMANDLINE_HPP #include #include #include #include "CLCommandLine.hpp" using CL::Option; using CL::TypedOption; class CommandLine : public CL::CommandLine { public: CommandLine () : CL::CommandLine( "This program converts DVI files, as created by TeX/LaTeX, as well as\nEPS and PDF files to the XML-based scalable vector graphics format SVG.", "[options] dvifile\n--eps [options] epsfile\n--pdf [options] pdffile", "Copyright (C) 2005-2025 Martin Gieseking " ) {} CommandLine (int argc, char **argv) : CommandLine() { parse(argc, argv); } // option variables TypedOption bboxOpt {"bbox", 'b', "size", "min", "set size of bounding box"}; TypedOption bitmapFormatOpt {"bitmap-format", 'B', "fmt", "jpeg", "set format used to embed PS/EPS bitmaps"}; TypedOption cacheOpt {"cache", 'C', "dir", "set/print path of cache directory"}; Option clipjoinOpt {"clipjoin", 'j', "compute intersection of clipping paths"}; Option colorOpt {"color", '\0', "colorize messages"}; Option colornamesOpt {"colornames", '\0', "prefer color names to RGB values if possible"}; Option commentsOpt {"comments", '\0', "add comments with additional information"}; TypedOption currentcolorOpt {"currentcolor", '\0', "color", "#000", "replace given color with 'currentColor'"}; Option debugGlyphsOpt {"debug-glyphs", '\0', "create PS files for all glyphs converted to TTF"}; Option embedBitmapsOpt {"embed-bitmaps", '\0', "prevent references to external bitmap files"}; Option epsOpt {"eps", 'E', "convert EPS file to SVG"}; Option exactBboxOpt {"exact-bbox", 'e', "compute exact glyph bounding boxes"}; TypedOption fontFormatOpt {"font-format", 'f', "format", "svg", "set file format of embedded fonts"}; TypedOption fontmapOpt {"fontmap", 'm', "filenames", "evaluate (additional) font map files"}; Option gradOverlapOpt {"grad-overlap", '\0', "create overlapping color gradient segments"}; TypedOption gradSegmentsOpt {"grad-segments", '\0', "number", 20, "number of color gradient segments per row"}; TypedOption gradSimplifyOpt {"grad-simplify", '\0', "delta", 0.05, "reduce level of detail for small segments"}; TypedOption helpOpt {"help", 'h', "mode", 0, "print this summary of options and exit"}; Option keepOpt {"keep", '\0', "keep temporary files"}; TypedOption libgsOpt {"libgs", '\0', "filename", "set name of Ghostscript shared library"}; TypedOption linkmarkOpt {"linkmark", 'L', "style", "box", "select how to mark hyperlinked areas"}; Option listSpecialsOpt {"list-specials", 'l', "print supported special sets and exit"}; TypedOption magOpt {"mag", 'M', "factor", 4, "magnification of Metafont output"}; TypedOption messageOpt {"message", '\0', "text", "print message text after writing an SVG file"}; TypedOption noFontsOpt {"no-fonts", 'n', "variant", 0, "draw glyphs by using path elements"}; Option noMergeOpt {"no-merge", '\0', "don't merge adjacent text elements"}; Option noMktexmfOpt {"no-mktexmf", '\0', "don't try to create missing fonts"}; TypedOption noSpecialsOpt {"no-specials", 'S', "prefixes", "don't process [selected] specials"}; Option noStylesOpt {"no-styles", '\0', "don't use CSS styles to reference fonts"}; TypedOption optimizeOpt {"optimize", 'O', "modules", "all", "perform several SVG optimizations"}; TypedOption outputOpt {"output", 'o', "pattern", "set name pattern of output files"}; TypedOption pageOpt {"page", 'p', "ranges", "1", "choose page(s) to convert"}; TypedOption pageHashesOpt {"page-hashes", 'H', "params", "xxh64", "activate usage of page hashes"}; Option pdfOpt {"pdf", 'P', "convert PDF file to SVG"}; TypedOption precisionOpt {"precision", 'd', "number", 0, "set number of decimal points (0-6)"}; TypedOption progressOpt {"progress", '\0', "delay", 0.5, "enable progress indicator"}; Option relativeOpt {"relative", 'R', "create relative path commands"}; TypedOption rotateOpt {"rotate", 'r', "angle", "rotate page content clockwise"}; TypedOption scaleOpt {"scale", 'c', "sx[,sy]", "scale page content"}; Option stdinOpt {"stdin", '\0', "read input file from stdin"}; Option stdoutOpt {"stdout", 's', "write SVG output to stdout"}; TypedOption tmpdirOpt {"tmpdir", '\0', "path", "set/print the directory for temporary files"}; TypedOption traceAllOpt {"trace-all", 'a', "retrace", false, "trace all glyphs of bitmap fonts"}; TypedOption transformOpt {"transform", 'T', "commands", "transform page content"}; TypedOption translateOpt {"translate", 't', "tx[,ty]", "shift page content"}; TypedOption verbosityOpt {"verbosity", 'v', "level", 15, "set verbosity level (0-15)"}; TypedOption versionOpt {"version", 'V', "extended", false, "print version and exit"}; TypedOption zipOpt {"zip", 'z', "level", 9, "create compressed .svgz file"}; TypedOption zoomOpt {"zoom", 'Z', "factor", 1.0, "zoom page content"}; protected: std::vector& options () const override {return _options;} const char* section (size_t n) const override {return n < _sections.size() ? _sections[n] : nullptr;} private: std::array _sections {{ "Input options", "SVG output options", "SVG transformations", "Processing options", "Message options", }}; mutable std::vector _options = { {&pageOpt, 0}, {&fontmapOpt, 0}, #if !defined(DISABLE_GS) {&epsOpt, 0}, #endif #if !defined(DISABLE_GS) {&pdfOpt, 0}, #endif {&stdinOpt, 0}, {&bboxOpt, 1}, #if !defined(DISABLE_GS) {&bitmapFormatOpt, 1}, #endif #if !defined(DISABLE_GS) {&clipjoinOpt, 1}, #endif {&colornamesOpt, 1}, {&commentsOpt, 1}, {¤tcolorOpt, 1}, {&embedBitmapsOpt, 1}, #if !defined(DISABLE_WOFF) {&fontFormatOpt, 1}, #endif #if !defined(DISABLE_GS) {&gradOverlapOpt, 1}, #endif #if !defined(DISABLE_GS) {&gradSegmentsOpt, 1}, #endif #if !defined(DISABLE_GS) {&gradSimplifyOpt, 1}, #endif {&linkmarkOpt, 1}, {&optimizeOpt, 1}, {&outputOpt, 1}, {&precisionOpt, 1}, {&relativeOpt, 1}, {&stdoutOpt, 1}, {&tmpdirOpt, 1}, {&noFontsOpt, 1}, {&noMergeOpt, 1}, {&noStylesOpt, 1}, {&zipOpt, 1}, {&rotateOpt, 2}, {&scaleOpt, 2}, {&translateOpt, 2}, {&transformOpt, 2}, {&zoomOpt, 2}, {&cacheOpt, 3}, #if defined(TTFDEBUG) {&debugGlyphsOpt, 3}, #endif {&exactBboxOpt, 3}, {&keepOpt, 3}, #if !defined(HAVE_LIBGS) && !defined(DISABLE_GS) {&libgsOpt, 3}, #endif {&magOpt, 3}, {&noMktexmfOpt, 3}, {&noSpecialsOpt, 3}, {&pageHashesOpt, 3}, {&traceAllOpt, 3}, {&colorOpt, 4}, {&helpOpt, 4}, {&listSpecialsOpt, 4}, {&messageOpt, 4}, {&progressOpt, 4}, {&verbosityOpt, 4}, {&versionOpt, 4}, }; }; #endif dvisvgm-3.5/src/DLLoader.cpp000066400000000000000000000043621501401750600157650ustar00rootroot00000000000000/************************************************************************* ** DLLoader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include "DLLoader.hpp" using namespace std; /** Creates a new DLLoader object and tries to load the given dynamic/shared library. * @param[in] dlname name of library to load */ DLLoader::DLLoader (const string &dlname) : _handle(nullptr) { loadLibrary(dlname); } /** Releases the currently assigned dynamic/shared library and loads another one. * @param[in] dlname name of library to load */ bool DLLoader::loadLibrary (const string &dlname) { closeLibrary(); if (!dlname.empty()) { #ifdef _WIN32 _handle = LoadLibrary(dlname.c_str()); #else _handle = dlopen(dlname.c_str(), RTLD_LAZY); #endif } return _handle != nullptr; } /** Releases the library currently assigned to the DLLoader object. */ void DLLoader::closeLibrary () { if (_handle) { #ifdef _WIN32 FreeLibrary(_handle); #else dlclose(_handle); #endif _handle = nullptr; } } dvisvgm-3.5/src/DLLoader.hpp000066400000000000000000000047531501401750600157760ustar00rootroot00000000000000/************************************************************************* ** DLLoader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef DLLOADER_HPP #define DLLOADER_HPP #include #ifdef _WIN32 #include "windows.hpp" #else #include #endif class DLLoader { public: DLLoader () =delete; explicit DLLoader (const std::string &dlname); DLLoader (DLLoader &&loader) =default; virtual ~DLLoader () {closeLibrary();} bool loaded () const {return _handle != nullptr;} bool loadLibrary (const std::string &dlname); protected: template T loadSymbol (const char *name) const; void closeLibrary (); private: #ifdef _WIN32 HINSTANCE _handle; #else void *_handle; #endif }; /** Loads a function or variable from the dynamic/shared library. * @param[in] name name of function/variable to load * @return pointer to loaded symbol, or 0 if the symbol could not be loaded */ template T DLLoader::loadSymbol (const char *name) const { if (_handle) { #ifdef _WIN32 return reinterpret_cast(GetProcAddress(_handle, name)); #else return reinterpret_cast(dlsym(_handle, name)); #endif } return nullptr; } #define LOAD_SYMBOL(sym) loadSymbol(#sym) #endif dvisvgm-3.5/src/DVIActions.hpp000066400000000000000000000044611501401750600163070ustar00rootroot00000000000000/************************************************************************* ** DVIActions.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef DVIACTIONS_HPP #define DVIACTIONS_HPP #include #include #include class BoundingBox; class Font; struct DVIActions { virtual ~DVIActions () =default; virtual void reset () {} virtual void setChar (double x, double y, unsigned c, bool vertical, const Font &f) {} virtual void setRule (double x, double y, double height, double width) {} virtual void setTextOrientation (bool vertical) {} virtual void moveToX (double x, bool forceSVGMove) {} virtual void moveToY (double y, bool forceSVGMove) {} virtual void setFont (int num, const Font &font) {} virtual void special (const std::string &s, double dvi2bp, bool preprocessing=false) {} virtual void beginPage (unsigned pageno, const std::vector &c) {} virtual void endPage (unsigned pageno) {} virtual BoundingBox& bbox () =0; virtual void progress (size_t current, size_t total, const char *id=nullptr) {} }; #endif dvisvgm-3.5/src/DVIReader.cpp000066400000000000000000000633211501401750600161040ustar00rootroot00000000000000/************************************************************************* ** DVIReader.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include #include "algorithm.hpp" #include "Color.hpp" #include "DVIActions.hpp" #include "DVIReader.hpp" #include "Font.hpp" #include "FontManager.hpp" #include "HashFunction.hpp" #include "utility.hpp" using namespace std; DVIReader::DVIReader (istream &is) : BasicDVIReader(is) { executePreamble(); _bopOffsets = collectBopOffsets(); // read data from postamble but don't process font definitions goToPostamble(); executeCommand(); executePostPost(); } /** Executes all DVI commands read from the input stream. */ void DVIReader::executeAll () { int opcode = 0; while (!eof() && opcode >= 0) { try { opcode = executeCommand(); } catch (const DVIPrematureEOFException &) { // end of stream reached opcode = -1; } } } /** Reads and executes the commands of a single page. * This methods stops reading after the page's eop command has been executed. * @param[in] n number of page to be executed (1-based) * @returns true if page was read successfully */ bool DVIReader::executePage (unsigned n) { clearStream(); // reset all status bits if (!isStreamValid()) throwDVIException("invalid DVI file (page "+to_string(n)+" not found"); if (n < 1 || n > numberOfPages()) return false; seek(_bopOffsets[n-1]); // goto bop of n-th page _currPageNum = n; while (executeCommand() != OP_EOP); return true; } /** Computes a hash value for a given page. The hash algorithm is selected by * a HashFunction object which will also contain the resulting hash value if * this function returns true. * @param[in] pageno number of page to process (1-based) * @param[in,out] hashFunc hash function to use * @return true on success, hashFunc contains the resulting hash value */ bool DVIReader::computePageHash (size_t pageno, HashFunction &hashFunc) const { if (pageno == 0 || pageno > numberOfPages()) return false; hashFunc.reset(); clearStream(); seek(_bopOffsets[pageno-1]+45); // now on first command after bop of selected page size_t numBytes = numberOfPageBytes(pageno-1)-46; // number of bytes excluding bop and eop while (numBytes > 0) { constexpr size_t BUFSIZE = 4096; char buf[BUFSIZE]; getInputStream().read(buf, min(numBytes, BUFSIZE)); hashFunc.update(buf, getInputStream().gcount()); numBytes -= getInputStream().gcount(); } return true; } ///////////////////////////////////// /** Reads and executes DVI preamble command. * Format: pre ver[1] num[4] den[4] mag[4] cmtlen[1] cmt[cmtlen] */ void DVIReader::cmdPre (int) { uint8_t id = readUnsigned(1); setDVIVersion(DVIVersion(id)); // identification number uint32_t numer = readUnsigned(4); // numerator units of measurement uint32_t denom = readUnsigned(4); // denominator units of measurement if (denom == 0) throwDVIException("denominator of measurement unit is zero"); _mag = readUnsigned(4); // magnification uint32_t k = readUnsigned(1); // length of following comment string comment = readString(k); // 1 dviunit * num/den == multiples of 0.0000001m // 1 dviunit * _dvibp: length of 1 dviunit in PS points * _mag/1000 _dvi2bp = numer/254000.0*72.0/denom*_mag/1000.0; dviPre(id, numer, denom, _mag, comment); } /** Reads and executes DVI postamble command. * Format: post p[4] num[4] den[4] mag[4] ph[4] pw[4] sd[2] np[2] */ void DVIReader::cmdPost (int) { uint32_t prevBopOffset = readUnsigned(4); uint32_t numer = readUnsigned(4); uint32_t denom = readUnsigned(4); if (denom == 0) throwDVIException("denominator of measurement unit is zero"); _mag = readUnsigned(4); uint32_t pageHeight = readUnsigned(4); // height of tallest page in dvi units uint32_t pageWidth = readUnsigned(4); // width of widest page in dvi units uint16_t stackDepth = readUnsigned(2); // max. stack depth required uint16_t numPages = readUnsigned(2); if (numPages != (numberOfPages() & 0xffff)) throwDVIException("page count in postamble doesn't match actual number of pages"); // 1 dviunit * num/den == multiples of 0.0000001m // 1 dviunit * _dvi2bp: length of 1 dviunit in PS points * _mag/1000 _dvi2bp = numer/254000.0*72.0/denom*_mag/1000.0; dviPost(stackDepth, numPages, pageWidth*_dvi2bp, pageHeight*_dvi2bp, _mag, numer, denom, prevBopOffset); } /** Reads and executes DVI post_post command. * Format: post_post q[4] i[1] 223[>=4] */ void DVIReader::cmdPostPost (int) { uint32_t postOffset = readUnsigned(4); // pointer to begin of postamble uint8_t id = readUnsigned(1); setDVIVersion(DVIVersion(id)); // identification byte while (readUnsigned(1) == DVI_FILL); // skip fill bytes (223), eof bit should be set now dviPostPost(DVIVersion(id), postOffset); } /** Reads and executes Begin-Of-Page command. * Format: bop c0[+4] ... c9[+4] p[+4] */ void DVIReader::cmdBop (int) { vector c(10); for (int i=0; i < 10; i++) c[i] = readSigned(4); int32_t prevBopOffset = readSigned(4); // pointer to peceeding bop (-1 in case of first page) _dviState.reset(); // set all DVI registers to 0 while (!_stateStack.empty()) _stateStack.pop(); _currFontNum = 0; _inPage = true; dviBop(c, prevBopOffset); } /** Reads and executes End-Of-Page command. */ void DVIReader::cmdEop (int) { if (!_stateStack.empty()) throwDVIException("stack not empty at end of page"); _inPage = false; dviEop(); } /** Reads and executes push command. */ void DVIReader::cmdPush (int) { _stateStack.push(_dviState); dviPush(); } /** Reads and executes pop command (restores pushed position information). */ void DVIReader::cmdPop (int) { if (_stateStack.empty()) throwDVIException("stack empty at pop command"); _dviState = _stateStack.top(); _stateStack.pop(); dviPop(); } /** Helper function that handles characters from virtual fonts (VF). * It is called by the cmdSetChar and cmdPutChar methods. * @param[in] font current font (corresponding to _currFontNum) * @param[in] c character to typeset */ void DVIReader::putVFChar (Font *font, uint32_t c) { if (auto vf = font_cast(font)) { // is current font a virtual font? FontManager &fm = FontManager::instance(); const auto *dvi = vf->getDVI(c); // try to get DVI sequence that represents character c Font *firstFont = fm.vfFirstFont(vf); if (!dvi) { const FontMetrics *ffm = firstFont ? firstFont->getMetrics() : nullptr; if (!ffm || (!ffm->isJFM() && !ffm->isOFM())) return; } fm.enterVF(vf); // enter VF font number context int savedFontNum = _currFontNum; // save current font number setFont(fm.vfFirstFontNum(vf), SetFontMode::VF_ENTER); if (!dvi) // no definition present for current (Japanese) char? dviPutChar(c, firstFont); // fallback for JFM-based virtual fonts else { // DVI units in virtual fonts are multiples of 1^(-20) times the scaled size of the VF double savedScale = _dvi2bp; _dvi2bp = vf->scaledSize()/(1 << 20); DVIState savedState = _dviState; // save current cursor position _dviState.x = _dviState.y = _dviState.w = _dviState.z = 0; ivectorstream> vis(*dvi); auto &is = replaceStream(vis); try { executeAll(); // execute DVI fragment } catch (const DVIException &) { // Message::estream(true) << "invalid dvi in vf: " << e.getMessage() << endl; // @@ } replaceStream(is); // restore previous input stream _dviState = savedState; // restore previous cursor position _dvi2bp = savedScale; // restore previous scale factor } fm.leaveVF(); // restore previous font number context setFont(savedFontNum, SetFontMode::VF_LEAVE); // restore previous font number } } /** Reads and executes set_char_x command. Puts a character at the current * position and advances the cursor. * @param[in] c character to set * @throw DVIException if method is called outside a bop/eop pair */ void DVIReader::cmdSetChar0 (int c) { if (!_inPage) throwDVIException("setchar outside of page"); if (Font *font = FontManager::instance().getFont(_currFontNum)) { dviSetChar0(c, font); // template method that may trigger further actions putVFChar(font, c); // further character processing if current font is a virtual font moveRight(font->charWidth(c)*font->scaleFactor()*_mag/1000.0, MoveMode::SETCHAR); } else throwDVIException("no font selected prior to setchar"); } /** Reads and executes setx command. Puts a character at the current * position and advances the cursor. * @param[in] len number of parameter bytes (possible values: 1-4) * @throw DVIException if method is called outside a bop/eop pair */ void DVIReader::cmdSetChar (int len) { if (!_inPage) throwDVIException("setchar outside of page"); // According to the dvi specification all character codes are unsigned // except len == 4. At the moment all char codes are treated as unsigned... uint32_t c = readUnsigned(len); // if len == 4 c may be signed if (Font *font = FontManager::instance().getFont(_currFontNum)) { dviSetChar(c, font); // template method that may trigger further actions putVFChar(font, c); // further character processing if current font is a virtual font moveRight(font->charWidth(c)*font->scaleFactor()*_mag/1000.0, MoveMode::SETCHAR); } else throwDVIException("no font selected prior to setchar"); } /** Reads and executes putx command. Puts a character at the current * position but doesn't change the cursor position. * @param[in] len number of parameter bytes (possible values: 1-4) * @throw DVIException if method is called outside a bop/eop pair */ void DVIReader::cmdPutChar (int len) { if (!_inPage) throwDVIException("putchar outside of page"); // According to the dvi specification all character codes are unsigned // except len == 4. At the moment all char codes are treated as unsigned... int32_t c = readUnsigned(len); if (Font *font = FontManager::instance().getFont(_currFontNum)) { dviPutChar(c, font); putVFChar(font, c); } else throwDVIException("no font selected prior to putchar"); } /** Reads and executes set_rule command. Puts a solid rectangle at the current * position and updates the cursor position. * Format: set_rule h[+4] w[+4] * @throw DVIException if method is called outside a bop/eop pair */ void DVIReader::cmdSetRule (int) { if (!_inPage) throwDVIException("set_rule outside of page"); double height = _dvi2bp*readSigned(4); double width = _dvi2bp*readSigned(4); dviSetRule(height, width); moveRight(width, MoveMode::CHANGEPOS); } /** Reads and executes set_rule command. Puts a solid rectangle at the current * position but leaves the cursor position unchanged. * Format: put_rule h[+4] w[+4] * @throw DVIException if method is called outside a bop/eop pair */ void DVIReader::cmdPutRule (int) { if (!_inPage) throwDVIException("put_rule outside of page"); double height = _dvi2bp*readSigned(4); double width = _dvi2bp*readSigned(4); dviPutRule(height, width); } void DVIReader::moveRight (double dx, MoveMode) { switch (_dviState.d) { case WritingMode::LR: _dviState.h += dx; break; case WritingMode::TB: _dviState.v += dx; break; case WritingMode::BT: _dviState.v -= dx; break; } } void DVIReader::moveDown (double dy, MoveMode) { switch (_dviState.d) { case WritingMode::LR: _dviState.v += dy; break; case WritingMode::TB: _dviState.h -= dy; break; case WritingMode::BT: _dviState.h += dy; break; } } void DVIReader::cmdRight (int len) { double dx = _dvi2bp*readSigned(len); moveRight(dx, MoveMode::CHANGEPOS); dviRight(dx); } void DVIReader::cmdDown (int len) { double dy = _dvi2bp*readSigned(len); moveDown(dy, MoveMode::CHANGEPOS); dviDown(dy); } void DVIReader::cmdNop (int) {dviNop();} void DVIReader::cmdX0 (int) {moveRight(_dviState.x, MoveMode::CHANGEPOS); dviX0();} void DVIReader::cmdY0 (int) {moveDown(_dviState.y, MoveMode::CHANGEPOS); dviY0();} void DVIReader::cmdW0 (int) {moveRight(_dviState.w, MoveMode::CHANGEPOS); dviW0();} void DVIReader::cmdZ0 (int) {moveDown(_dviState.z, MoveMode::CHANGEPOS); dviZ0();} void DVIReader::cmdX (int len) { double dx = _dvi2bp*readSigned(len); _dviState.x = dx; moveRight(dx, MoveMode::CHANGEPOS); dviX(dx); } void DVIReader::cmdY (int len) { double dy = _dvi2bp*readSigned(len); _dviState.y = dy; moveDown(dy, MoveMode::CHANGEPOS); dviY(dy); } void DVIReader::cmdW (int len) { double dx = _dvi2bp*readSigned(len); _dviState.w = dx; moveRight(dx, MoveMode::CHANGEPOS); dviW(dx); } void DVIReader::cmdZ (int len) { double dy = _dvi2bp*readSigned(len); _dviState.z = dy; moveDown(dy, MoveMode::CHANGEPOS); dviZ(dy); } /** Sets the text orientation (horizontal, vertical). * This command is only available in DVI version 3 (created by pTeX) */ void DVIReader::cmdDir (int) { uint8_t wmode = readUnsigned(1); if (wmode == 4) // yoko mode (4) equals default LR mode (0) wmode = 0; if (wmode == 2 || wmode > 3) throwDVIException("invalid writing mode value " + std::to_string(wmode) + " (0, 1, 3, or 4 expected)"); _dviState.d = (WritingMode)wmode; dviDir(_dviState.d); } void DVIReader::cmdXXX (int len) { if (!_inPage) throwDVIException("special outside of page"); uint32_t numBytes = readUnsigned(len); string str = readString(numBytes); dviXXX(str); } /** Change the current font. * @param[in] fontnum local number of font to select * @param[in] mode info on command that triggered the font change * @throw DVIException if font number is undefined */ void DVIReader::setFont (int fontnum, SetFontMode mode) { if (const Font *font = FontManager::instance().getFont(fontnum)) { _currFontNum = fontnum; dviFontNum(uint32_t(fontnum), mode, font); } else throwDVIException("undefined font number " + std::to_string(fontnum)); } /** Selects a previously defined font by its number. * @param[in] fontnum font number * @throw DVIException if font number is undefined */ void DVIReader::cmdFontNum0 (int fontnum) { setFont(fontnum, SetFontMode::SF_SHORT); } /** Selects a previously defined font. * @param[in] len size of font number variable (in bytes) * @throw DVIException if font number is undefined */ void DVIReader::cmdFontNum (int len) { uint32_t fontnum = readUnsigned(len); setFont(fontnum, SetFontMode::SF_LONG); } /** Parses a sequence of font attributes given as key1=val1;key2=val2;...;keyn=valn */ static map parse_font_attribs (const string &str) { map attribs; if (!str.empty()) { for (const string &attr : util::split(str, ";")) { vector keyval = util::split(attr, "="); if (keyval.size() == 2) attribs[keyval[0]] = keyval[1]; } } return attribs; } /** Helper function to handle a font definition. * @param[in] fontnum local font number * @param[in] name font name (or file path if enclosed in square brackets) * @param[in] cs checksum to be compared with TFM checksum * @param[in] dsize design size of font in PS point units * @param[in] ssize scaled size of font in PS point units */ const Font* DVIReader::defineFont (uint32_t fontnum, const string &name, uint32_t cs, double dsize, double ssize) { FontManager &fm = FontManager::instance(); Font *font = fm.getFont(fontnum); if (!font && !name.empty()) { // font not registered yet? if (name[0] == '[') { // LuaTeX native font reference? auto last = name.rfind(']'); if (last != string::npos) { string path = name.substr(1, last-1); FontStyle style; int fontIndex=0; if (name.size() > last && name[last+1] == ':') { // look for font attributes? auto attribs = parse_font_attribs(name.substr(last+2)); auto it = attribs.begin(); if ((it = attribs.find("index")) != attribs.end()) fontIndex = stoi(it->second); if ((it = attribs.find("embolden")) != attribs.end()) style.bold = stoi(it->second)/65536.0; if ((it = attribs.find("extend")) != attribs.end()) style.extend = stoi(it->second)/65536.0; if ((it = attribs.find("slant")) != attribs.end()) style.slant = stoi(it->second)/65536.0; } int id = fm.registerFont(fontnum, path, fontIndex, ssize, style, Color::BLACK); font = fm.getFontById(id); } } else { // TFM-based font specified by name int id = fm.registerFont(fontnum, name, cs, dsize, ssize); font = fm.getFontById(id); if (auto vf = font_cast(font)) { // read vf file, register its font and character definitions fm.enterVF(vf); ifstream ifs(vf->path(), ios::binary); VFReader vfReader(ifs); vfReader.replaceActions(this); vfReader.executeAll(); fm.leaveVF(); } } } return font; } /** Defines a new font. * @param[in] len size of font number variable (in bytes) */ void DVIReader::cmdFontDef (int len) { uint32_t fontnum = readUnsigned(len); // font number uint32_t checksum = readUnsigned(4); // font checksum (to be compared with corresponding TFM checksum) uint32_t ssize = readUnsigned(4); // scaled size of font in DVI units uint32_t dsize = readUnsigned(4); // design size of font in DVI units uint32_t pathlen = readUnsigned(1); // length of font path uint32_t namelen = readUnsigned(1); // length of font name string path = readString(pathlen); // path to font file string fontname = readString(namelen); const Font *font = defineFont(fontnum, fontname, checksum, dsize*_dvi2bp, ssize*_dvi2bp); dviFontDef(fontnum, checksum, font); } /** This template method is called by the VFReader after reading a font definition from a VF file. * @param[in] fontnum local font number * @param[in] path path to font file * @param[in] name font name * @param[in] checksum checksum to be compared with TFM checksum * @param[in] dsize design size in PS point units * @param[in] ssize scaled size in PS point units */ void DVIReader::defineVFFont (uint32_t fontnum, const string &path, const string &name, uint32_t checksum, double dsize, double ssize) { if (const VirtualFont *vf = FontManager::instance().getVF()) defineFont(fontnum, name, checksum, dsize, ssize * vf->scaleFactor()); } /** This template method is called by the VFReader after reading a character definition from a VF file. * @param[in] c character number * @param[in] dvi DVI fragment describing the character */ void DVIReader::defineVFChar (uint32_t c, vector dvi) { FontManager::instance().assignVFChar(c, std::move(dvi)); } /** XDV extension: includes image or pdf file. * parameters: box[1] matrix[4][6] p[2] len[2] path[l] */ void DVIReader::cmdXPic (int) { uint8_t box = readUnsigned(1); // box vector matrix(6); for (int i=0; i < 6; i++) // matrix matrix[i] = readSigned(4); int16_t page = readSigned(2); // page number uint16_t len = readUnsigned(2); string path = readString(len); // path to image/pdf file dviXPic(box, matrix, page, path); } /** XDV extension: defines a native font */ void DVIReader::cmdXFontDef (int) { int32_t fontnum = readSigned(4); double ptsize = _dvi2bp*readUnsigned(4); uint16_t flags = readUnsigned(2); uint8_t psname_len = readUnsigned(1); uint8_t fmname_len = getDVIVersion() == DVI_XDV5 ? readUnsigned(1) : 0; // length of family name uint8_t stname_len = getDVIVersion() == DVI_XDV5 ? readUnsigned(1) : 0; // length of style name string fontname = readString(psname_len); uint32_t fontIndex=0; if (getDVIVersion() == DVI_XDV5) seek(fmname_len+stname_len, ios::cur); else fontIndex = readUnsigned(4); FontStyle style; Color color; if (flags & 0x0100) { // vertical? } if (flags & 0x0200) { // colored? // The font color must not interfere with color specials. If the font color is not black, // all color specials should be ignored, i.e. glyphs of a non-black fonts have a fixed color // that can't be changed by color specials. uint32_t rgba = readUnsigned(4); color.setRGB(uint8_t(rgba >> 24), uint8_t((rgba >> 16) & 0xff), uint8_t((rgba >> 8) & 0xff)); } if (flags & 0x1000) // extend? style.extend = _dvi2bp*readSigned(4); if (flags & 0x2000) // slant? style.slant = _dvi2bp*readSigned(4); if (flags & 0x4000) // embolden? style.bold = _dvi2bp*readSigned(4); if ((flags & 0x0800) && (getDVIVersion() == DVI_XDV5)) { // variations? uint16_t num_variations = readSigned(2); for (int i=0; i < num_variations; i++) readUnsigned(4); } const Font *font = FontManager::instance().getFont(fontnum); if (!font) { FontManager::instance().registerFont(fontnum, fontname, fontIndex, ptsize, style, color); font = FontManager::instance().getFont(fontnum); } dviXFontDef(fontnum, font_cast(font)); } /** Returns the width of a string typed with a given font. * @param[in] glyphs glyphs of the string * @param[in] font assigned font * @return width in bp units */ static double string_width (const vector &glyphs, const Font *font) { if (auto nfont = font_cast(font)) { return algo::accumulate(glyphs, 0.0, [&nfont](double w, uint16_t gid) { return w + nfont->hAdvance(Character(Character::INDEX, gid)); }); } return 0; } /** XDV extension: prints an array of characters where each character * can take independent x and y coordinates. * parameters: w[4] n[2] (dx,dy)[(4+4)n] glyphs[2n] */ void DVIReader::cmdXGlyphArray (int) { vector dx, dy; vector glyphs; double width = putGlyphArray(false, dx, dy, glyphs); Font *font = FontManager::instance().getFont(_currFontNum); if (!font) throwDVIException("missing setfont prior to xglypharray"); dviXGlyphArray(dx, dy, glyphs, *font); double diff = abs(string_width(glyphs, font) - width); // if the given width differs from the actual width of the string, // we must force a position change to prevent misalignments moveRight(width, diff < 0.2 ? MoveMode::SETCHAR : MoveMode::CHANGEPOS); } /** XDV extension: prints an array/string of characters where each character * can take independent x coordinates whereas all share a single y coordinate. * parameters: w[4] n[2] dx[4n] dy[4] glyphs[2n] */ void DVIReader::cmdXGlyphString (int) { vector dx, dy; vector glyphs; double width = putGlyphArray(true, dx, dy, glyphs); Font *font = FontManager::instance().getFont(_currFontNum); if (!font) throwDVIException("missing setfont prior to xglyphstring"); dviXGlyphString(dx, glyphs, *font); double diff = abs(string_width(glyphs, font) - width); // if the given width differs from the actual width of the string, // we must force a position change to prevent misalignments moveRight(width, diff < 0.2 ? MoveMode::SETCHAR : MoveMode::CHANGEPOS); } /** XDV extension: Same as cmdXGlyphArray plus a leading array of UTF-16 characters * that specify the "actual text" represented by the glyphs to be printed. It usually * contains the text with special characters (like ligatures) expanded so that it * can be used for text search, plain text copy & paste etc. This XDV command was * introduced with XeTeX 0.99995 and can be triggered by \\XeTeXgenerateactualtext1. * parameters: l[2] chars[2l] w[4] n[2] (dx,dy)[8n] glyphs[2n] */ void DVIReader::cmdXTextAndGlyphs (int) { uint16_t l = readUnsigned(2); // number of chars vector chars(l); for (int i=0; i < l; i++) chars[i] = readUnsigned(2); vector x, y; vector glyphs; double width = putGlyphArray(false, x, y, glyphs); Font *font = FontManager::instance().getFont(_currFontNum); if (!font) throwDVIException("missing setfont prior to xtextandglyphs"); dviXTextAndGlyphs(x, y, chars, glyphs, *font); double diff = abs(string_width(glyphs, font) - width); // if the given width differs from the actual width of the string, // we must force a position change to prevent misalignments moveRight(width, diff < 0.2 ? MoveMode::SETCHAR : MoveMode::CHANGEPOS); } /** Implements the common functionality of cmdXGlyphArray, cmdXGlyphString, and cmdXTextAndGlyphs. * @param[in] xonly indicates if the characters share a single y coordinate (xonly==true) * @param[out] dx relative horizontal positions of each glyph * @param[out] dy relative vertical positions of each glyph * @param[out] glyphs FreeType indices of the glyphs to typeset * @return total width of the glyph array */ double DVIReader::putGlyphArray (bool xonly, vector &dx, vector &dy, vector &glyphs) const { double strwidth = _dvi2bp*readSigned(4); uint16_t num_glyphs = readUnsigned(2); dx.resize(num_glyphs); dy.resize(num_glyphs); glyphs.resize(num_glyphs); for (int i=0; i < num_glyphs; i++) { dx[i] = readSigned(4)*_dvi2bp; dy[i] = xonly ? 0 : readSigned(4)*_dvi2bp; } for (int i=0; i < num_glyphs; i++) glyphs[i] = readUnsigned(2); return strwidth; } dvisvgm-3.5/src/DVIReader.hpp000066400000000000000000000177101501401750600161120ustar00rootroot00000000000000/************************************************************************* ** DVIReader.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef DVIREADER_HPP #define DVIREADER_HPP #include #include #include #include #include #include "BasicDVIReader.hpp" #include "Color.hpp" #include "VFActions.hpp" class Font; class FontStyle; class HashFunction; class NativeFont; class VirtualFont; class DVIReader : public BasicDVIReader, public VFActions { protected: enum class WritingMode {LR=0, TB=1, BT=3}; enum class SetFontMode {SF_SHORT, SF_LONG, VF_ENTER, VF_LEAVE}; enum class MoveMode {SETCHAR, CHANGEPOS}; struct DVIState { double h=0, v=0; ///< horizontal and vertical cursor position double x=0, w=0, y=0, z=0; ///< additional registers to store horizontal (x, w) and vertical (y, z) positions WritingMode d=WritingMode::LR; ///< direction: 0: horizontal, 1: vertical(top->bottom), 3: vertical (bottom->top) void reset () {h = v = x = w = y = z = 0.0; d=WritingMode::LR;} }; public: explicit DVIReader (std::istream &is); void executeAll (); bool executePage (unsigned n); double getXPos () const override {return _dviState.h;} double getYPos () const override {return _dviState.v;} int stackDepth () const override {return _stateStack.size();} unsigned currentPageNumber () const override {return _currPageNum;} unsigned numberOfPages () const {return _bopOffsets.empty() ? 0 : _bopOffsets.size()-1;} protected: size_t numberOfPageBytes (int n) const {return _bopOffsets.size() > 1 ? _bopOffsets[n+1]-_bopOffsets[n] : 0;} bool computePageHash (size_t pageno, HashFunction &hashFunc) const; virtual void moveRight (double dx, MoveMode mode); virtual void moveDown (double dy, MoveMode mode); void putVFChar (Font *font, uint32_t c); double putGlyphArray (bool xonly, std::vector &dx, std::vector &dy, std::vector &glyphs) const; const Font* defineFont (uint32_t fontnum, const std::string &name, uint32_t cs, double dsize, double ssize); void setFont (int num, SetFontMode mode); const DVIState& dviState() const {return _dviState;} double dvi2bp () const {return _dvi2bp;} bool inPage () const {return _inPage;} // VFAction methods void defineVFFont (uint32_t fontnum, const std::string &path, const std::string &name, uint32_t checksum, double dsize, double ssize) override; void defineVFChar (uint32_t c, std::vector dvi) override; // The following template methods provide higher-level access to the DVI commands. // In contrast to their cmdXXX pendants, they don't require any handling of the input stream. // All command arguments are delivered as function parameters. These methods are called after // the DVI registers have been updated, i.e. currState() represents the state after executing // the command. If the previous register state is required, prevState() can be used. virtual void dviPre (uint8_t id, uint32_t numer, uint32_t denom, uint32_t mag, const std::string &comment) {} virtual void dviPost (uint16_t stdepth, uint16_t pages, uint32_t pw, uint32_t ph, uint32_t mag, uint32_t num, uint32_t den, uint32_t lbopofs) {} virtual void dviPostPost (uint8_t id, uint32_t postOffset) {} virtual void dviBop (const std::vector &c, int32_t prevBopOffset) {} virtual void dviEop () {} virtual void dviSetChar0 (uint32_t c, const Font *font) {} virtual void dviSetChar (uint32_t c, const Font *font) {} virtual void dviPutChar (uint32_t c, const Font *font) {} virtual void dviSetRule (double h, double w) {} virtual void dviPutRule (double h, double w) {} virtual void dviNop () {} virtual void dviPush () {} virtual void dviPop () {} virtual void dviRight (double dx) {} virtual void dviDown (double dy) {} virtual void dviX0 () {} virtual void dviY0 () {} virtual void dviW0 () {} virtual void dviZ0 () {} virtual void dviX (double x) {} virtual void dviY (double y) {} virtual void dviW (double w) {} virtual void dviZ (double z) {} virtual void dviFontDef (uint32_t fontnum, uint32_t checksum, const Font *font) {} virtual void dviFontNum (uint32_t fontnum, SetFontMode mode, const Font *font) {} virtual void dviDir (WritingMode dir) {} virtual void dviXXX (const std::string &str) {} virtual void dviXPic (uint8_t box, const std::vector &matrix, int16_t page, const std::string &path) {} virtual void dviXFontDef (uint32_t fontnum, const NativeFont *font) {} virtual void dviXGlyphArray (std::vector &dx, std::vector &dy, std::vector &glyphs, const Font &font) {} virtual void dviXGlyphString (std::vector &dx, std::vector &glyphs, const Font &font) {} virtual void dviXTextAndGlyphs (std::vector &dx, std::vector &dy, std::vector &chars, std::vector &glyphs, const Font &font) {} private: // The following low-level methods evaluate the DVI commands read from // the input stream and call the corresponding dviXXX methods. void cmdSetChar0 (int c) override; void cmdSetChar (int len) override; void cmdPutChar (int len) override; void cmdSetRule (int len) override; void cmdPutRule (int len) override; void cmdNop (int len) override; void cmdBop (int len) override; void cmdEop (int len) override; void cmdPush (int len) override; void cmdPop (int len) override; void cmdDir (int len) override; void cmdRight (int len) override; void cmdDown (int len) override; void cmdX0 (int len) override; void cmdY0 (int len) override; void cmdW0 (int len) override; void cmdZ0 (int len) override; void cmdX (int len) override; void cmdY (int len) override; void cmdW (int len) override; void cmdZ (int len) override; void cmdFontDef (int len) override; void cmdFontNum0 (int n) override; void cmdFontNum (int len) override; void cmdXXX (int len) override; void cmdPre (int len) override; void cmdPost (int len) override; void cmdPostPost (int len) override; void cmdXPic (int len) override; void cmdXFontDef (int len) override; void cmdXGlyphArray (int len) override; void cmdXGlyphString (int len) override; void cmdXTextAndGlyphs (int len) override; private: bool _inPage=false; ///< true if stream pointer is between bop and eop unsigned _currPageNum=0; ///< current page number (1 is first page) int _currFontNum=0; ///< current font number double _dvi2bp=0.0; ///< factor to convert dvi units to PS points uint32_t _mag=1; ///< magnification factor * 1000 DVIState _dviState; ///< current state of the DVI registers std::stack _stateStack; std::vector _bopOffsets; }; #endif dvisvgm-3.5/src/DVIToSVG.cpp000066400000000000000000000513411501401750600156430ustar00rootroot00000000000000/************************************************************************* ** DVIToSVG.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include #include #include #include #include #include "Calculator.hpp" #include "DVIToSVG.hpp" #include "DVIToSVGActions.hpp" #include "FileSystem.hpp" #include "Font.hpp" #include "FontManager.hpp" #include "GlyphTracerMessages.hpp" #include "InputBuffer.hpp" #include "InputReader.hpp" #include "PageRanges.hpp" #include "PageSize.hpp" #include "PreScanDVIReader.hpp" #include "SignalHandler.hpp" #include "optimizer/SVGOptimizer.hpp" #include "SVGOutput.hpp" #include "utility.hpp" #include "version.hpp" #include "XXHashFunction.hpp" /////////////////////////////////// // special handlers #include "BgColorSpecialHandler.hpp" #include "ColorSpecialHandler.hpp" #include "DvisvgmSpecialHandler.hpp" #include "EmSpecialHandler.hpp" #include "HtmlSpecialHandler.hpp" #include "PapersizeSpecialHandler.hpp" #include "PdfSpecialHandler.hpp" #include "PsSpecialHandlerProxy.hpp" #include "TpicSpecialHandler.hpp" /////////////////////////////////// using namespace std; /** 'a': trace all glyphs even if some of them are already cached * 'm': trace missing glyphs, i.e. glyphs not yet cached * 0 : only trace actually required glyphs */ char DVIToSVG::TRACE_MODE = 0; bool DVIToSVG::COMPUTE_PROGRESS = false; DVIToSVG::HashSettings DVIToSVG::PAGE_HASH_SETTINGS; DVIToSVG::DVIToSVG (istream &is, SVGOutputBase &out) : DVIReader(is), _out(out), _prevWritingMode(WritingMode::LR) { _prevXPos = _prevYPos = numeric_limits::min(); _actions = util::make_unique(*this, _svg); } /** Starts the conversion process. * @param[in] first number of first page to convert * @param[in] last number of last page to convert * @param[in] hashFunc pointer to function to be used to compute page hashes */ void DVIToSVG::convert (unsigned first, unsigned last, HashFunction *hashFunc) { if (first > last) swap(first, last); if (first > numberOfPages()) { ostringstream oss; oss << "file contains only " << numberOfPages() << " page"; if (numberOfPages() > 1) oss << 's'; throw DVIException(oss.str()); } last = min(last, numberOfPages()); bool computeHashes = (hashFunc && !_out.ignoresHashes()); string shortenedOptHash = XXH32HashFunction(PAGE_HASH_SETTINGS.optionsHash()).digestString(); for (unsigned i=first; i <= last; ++i) { string dviHash, combinedHash; if (computeHashes) { computePageHash(i, *hashFunc); dviHash = hashFunc->digestString(); hashFunc->update(PAGE_HASH_SETTINGS.optionsHash()); combinedHash = hashFunc->digestString(); } const SVGOutput::HashTriple hashTriple(dviHash, shortenedOptHash, std::move(combinedHash)); FilePath path = _out.filepath(i, numberOfPages(), hashTriple); if (!dviHash.empty() && !PAGE_HASH_SETTINGS.isSet(HashSettings::P_REPLACE) && path.exists()) { Message::mstream(false, Message::MC_PAGE_NUMBER) << "skipping page " << i; Message::mstream().indent(1); Message::mstream(false, Message::MC_PAGE_WRITTEN) << "\nfile " << path.shorterAbsoluteOrRelative() << " exists\n"; Message::mstream().indent(0); } else { executePage(i); SVGOptimizer(_svg).execute(); embedFonts(); bool success = _svg.write(_out.getPageStream(currentPageNumber(), numberOfPages(), hashTriple)); _out.finish(); string fname = path.shorterAbsoluteOrRelative(); if (fname.empty()) fname = ""; if (!success) Message::wstream(true) << "failed to write output to " << fname << '\n'; else { Message::mstream(false, Message::MC_PAGE_WRITTEN) << "\noutput written to " << fname << '\n'; if (!_userMessage.empty()) { if (auto specialActions = dynamic_cast(_actions.get())) { string msg = specialActions->expandText(_userMessage); Message::ustream(true) << msg << "\n"; } } } _svg.reset(); _actions->reset(); } } } /** Creates a HashFunction object for a given algorithm name. * @param[in] algo name of hash algorithm * @return pointer to hash function * @throw MessageException if algorithm name is invalid or not supported */ static unique_ptr create_hash_function (const string &algo) { if (auto hashFunc = HashFunction::create(algo)) return hashFunc; string msg = "unknown hash algorithm '"+algo+"' (supported algorithms: "; for (const string &name : HashFunction::supportedAlgorithms()) msg += name + ", "; msg.pop_back(); msg.back() = ')'; throw MessageException(std::move(msg)); } /** Convert DVI pages specified by a page range string. * @param[in] rangestr string describing the pages to convert * @param[out] pageinfo (number of converted pages, number of total pages) */ void DVIToSVG::convert (const string &rangestr, pair *pageinfo) { PageRanges ranges; if (!ranges.parse(rangestr, numberOfPages())) throw MessageException("invalid page range format"); Message::mstream(false, Message::MC_PAGE_NUMBER) << "pre-processing DVI file (format version " << getDVIVersion() << ")\n"; if (auto actions = dynamic_cast(_actions.get())) { PreScanDVIReader prescan(getInputStream(), actions); actions->setDVIReader(prescan); prescan.executeAllPages(); actions->setDVIReader(*this); SpecialManager::instance().notifyPreprocessingFinished(); executeFontDefs(); } unique_ptr hashFunc; if (!PAGE_HASH_SETTINGS.algorithm().empty()) // name of hash algorithm present? hashFunc = create_hash_function(PAGE_HASH_SETTINGS.algorithm()); for (const auto &range : ranges) convert(range.first, range.second, hashFunc.get()); if (pageinfo) { pageinfo->first = ranges.numberOfPages(); pageinfo->second = numberOfPages(); } } /** Writes the hash values of a selected set of pages to an output stream. * @param[in] rangestr string describing the pages to convert * @param[in,out] os stream the output is written to */ void DVIToSVG::listHashes (const string &rangestr, std::ostream &os) { PageRanges ranges; if (!ranges.parse(rangestr, numberOfPages())) throw MessageException("invalid page range format"); XXH32HashFunction xxh32; auto hashFunc = create_hash_function(PAGE_HASH_SETTINGS.algorithm()); int width1 = util::ilog10(numberOfPages())+1; int width2 = hashFunc->digestSize()*2; int spaces1 = width1+2+(width2-3)/2; int spaces2 = width1+2+width2+2-spaces1-3+(width2-7)/2; string shortenedOptHash = XXH32HashFunction(PAGE_HASH_SETTINGS.optionsHash()).digestString(); os << string(spaces1, ' ') << "DVI" << string(spaces2, ' ') << "DVI+opt\n"; for (const auto &range : ranges) { for (int i=range.first; i <= range.second; i++) { computePageHash(i, *hashFunc); os << setw(width1) << i; os << ": " << hashFunc->digestString(); hashFunc->update(PAGE_HASH_SETTINGS.optionsHash()); os << ", " << hashFunc->digestString() << '\n'; } } os << "hash algorithm: " << PAGE_HASH_SETTINGS.algorithm() << ", options hash: " << shortenedOptHash << '\n'; } int DVIToSVG::executeCommand () { SignalHandler::instance().check(); const streampos cmdpos = tell(); int opcode = DVIReader::executeCommand(); if (dviState().v+_ty != _prevYPos) { _tx = _ty = 0; _prevYPos = dviState().v; } _prevXPos = dviState().h+_tx; _prevWritingMode = dviState().d; if (COMPUTE_PROGRESS && inPage() && _actions) { size_t pagelen = numberOfPageBytes(currentPageNumber()-1); _pageByte += tell()-cmdpos; _actions->progress(_pageByte, pagelen); } return opcode; } /** This template method is called by parent class DVIReader before * executing the BOP actions. * @param[in] pageno physical page number (1 = first page) * @param[in] c contains information about the page (page number etc.) */ void DVIToSVG::enterBeginPage (unsigned pageno, const vector &c) { if (dynamic_cast(_actions.get())) { Message::mstream().indent(0); Message::mstream(false, Message::MC_PAGE_NUMBER) << "processing page " << pageno; if (pageno != (unsigned)c[0]) // Does page number shown on page differ from physical page number? Message::mstream(false) << " [" << c[0] << ']'; Message::mstream().indent(1); _svg.appendToDoc(util::make_unique(" This file was generated by dvisvgm " + string(PROGRAM_VERSION) + " ")); } } /** This template method is called by DVIReader::cmdEop() after * executing the EOP actions. */ void DVIToSVG::leaveEndPage (unsigned) const { if (!dynamic_cast(_actions.get())) return; // set bounding box and apply page transformations BoundingBox bbox = _actions->bbox(); // bounding box derived from the DVI commands executed if (_bboxFormatString == "min" || _bboxFormatString == "preview" || _bboxFormatString == "papersize") { bbox.unlock(); bbox.transform(getPageTransformation()); } else if (_bboxFormatString == "dvi") { // center page content double dx = (_pageWidth-bbox.width())/2; double dy = (_pageHeight-bbox.height())/2; bbox += BoundingBox(-dx, -dy, dx, dy); } else if (_bboxFormatString != "none") { istringstream iss(_bboxFormatString); StreamInputReader ir(iss); ir.skipSpace(); if (isalpha(ir.peek())) { // set explicitly given page format PageSize size(_bboxFormatString); if (size.valid()) { // convention: DVI position (0,0) equals (1in, 1in) relative // to the upper left vertex of the page (see DVI specification) const double border = -72; bbox = BoundingBox(border, border, size.width().bp()+border, size.height().bp()+border); } } else { // set/modify bounding box by explicitly given values try { vector lengths = BoundingBox::extractLengths(_bboxFormatString); if (lengths.size() == 1 || lengths.size() == 2) { // relative box size? // apply the page transformation and adjust the bbox afterwards bbox.transform(getPageTransformation()); } bbox.set(lengths); } catch (const MessageException &) { } } } if (bbox.width() == 0) Message::wstream(false) << "\npage is empty\n"; if (_bboxFormatString != "none") { _svg.setBBox(bbox); const double bp2pt = (1_bp).pt(); Message::mstream(false) << '\n'; Message::mstream(false, Message::MC_PAGE_SIZE) << "graphic size: " << XMLString(bbox.width()*bp2pt) << "pt" " x " << XMLString(bbox.height()*bp2pt) << "pt" " (" << XMLString(bbox.width()) << "bp" " x " << XMLString(bbox.height()) << "bp)"; Message::mstream(false) << '\n'; } } Matrix DVIToSVG::getPageTransformation () const { Matrix matrix(1); // unity matrix if (!_transCmds.empty()) { Calculator calc; if (_actions) { const double bp2pt = (1_bp).pt(); BoundingBox &bbox = _actions->bbox(); calc.setVariable("ux", bbox.minX()*bp2pt); calc.setVariable("uy", bbox.minY()*bp2pt); calc.setVariable("w", bbox.width()*bp2pt); calc.setVariable("h", bbox.height()*bp2pt); } // add constants for length units to calculator for (const auto &unit : Length::getUnits()) calc.setVariable(unit.first, Length(1, unit.second).pt()); matrix.set(_transCmds, calc); } return matrix; } static void collect_chars (unordered_map> &fontmap) { unordered_map> insertedChars; for (const auto &entry : fontmap) { const Font *unique_font = entry.first->uniqueFont(); if (unique_font != entry.first) { for (int c : entry.second) insertedChars[unique_font].insert(c); } } for (const auto &entry : insertedChars) fontmap[entry.first].insert(entry.second.begin(), entry.second.end()); } /** Adds the font information to the SVG tree. */ void DVIToSVG::embedFonts () { if (!_actions) // no dvi actions => no chars written => no fonts to embed return; auto usedFonts = FontManager::instance().getUniqueFonts(); auto &usedCharsMap = FontManager::instance().getUsedChars(); collect_chars(usedCharsMap); GlyphTracerMessages messages; unordered_set tracedFonts; // collect unique fonts already traced for (auto font : usedFonts) { if (auto ph_font = font_cast(font)) { // Check if glyphs should be traced. Only trace the glyphs of unique fonts, i.e. // avoid retracing the same glyphs again if they are referenced in various sizes. if (TRACE_MODE != 0 && tracedFonts.find(ph_font->uniqueFont()) == tracedFonts.end()) { ph_font->traceAllGlyphs(TRACE_MODE == 'a', &messages); tracedFonts.insert(ph_font->uniqueFont()); } if (font->path()) { // does font file exist? auto it = usedCharsMap.find(font); if (it != usedCharsMap.end()) _svg.append(*ph_font, it->second, &messages); } else Message::wstream(true) << "can't embed font '" << font->name() << "'\n"; } else Message::wstream(true) << "can't embed font '" << font->name() << "'\n"; } _svg.appendFontStyles(FontManager::instance().getUsedFonts()); } static vector extract_prefixes (const string &ignorelist) { vector prefixes; if (!ignorelist.empty()) { auto left = ignorelist.begin(); while (left != ignorelist.end()) { left = std::find_if(left, ignorelist.end(), [](char c) { return isalnum(c); }); auto right = std::find_if(left, ignorelist.end(), [](char c) { return !isalnum(c); }); if (left != ignorelist.end()) prefixes.emplace_back(left-ignorelist.begin(), right-left); left = right; } } return prefixes; } /** Enables or disables processing of specials. If ignorelist == 0, all * supported special handlers are loaded. To disable selected sets of specials, * the corresponding prefixes can be given separated by non alpha-numeric characters, * e.g. "color, ps, em" or "color: ps em" etc. * A single "*" in the ignore list disables all specials. * @param[in] ignorelist list of handler names to ignore * @param[in] pswarning if true, shows warning about disabled PS support */ void DVIToSVG::setProcessSpecials (const string &ignorelist, bool pswarning) { if (ignorelist == "*") // ignore all specials? SpecialManager::instance().unregisterHandlers(); else { auto ignoredHandlerName = extract_prefixes(ignorelist); // add special handlers SpecialManager::registerHandler(ignoredHandlerName); // handles background color special SpecialManager::registerHandler(ignoredHandlerName); // handles color specials SpecialManager::registerHandler(ignoredHandlerName); // handles raw SVG embeddings SpecialManager::registerHandler(ignoredHandlerName); // handles emTeX specials SpecialManager::registerHandler(ignoredHandlerName); // handles hyperref specials SpecialManager::registerHandler(ignoredHandlerName); // handles papersize special SpecialManager::registerHandler(ignoredHandlerName); SpecialManager::registerHandler(ignoredHandlerName); // handles tpic specials SpecialManager::registerHandler(util::make_unique(pswarning), ignoredHandlerName); } } FilePath DVIToSVG::getSVGFilePath (unsigned pageno) const { return _out.filepath(pageno, numberOfPages()); } void DVIToSVG::moveRight (double dx, MoveMode mode) { DVIReader::moveRight(dx, mode); if (_actions) { if (dviState().d == WritingMode::LR) _actions->moveToX(dviState().h+_tx, mode == MoveMode::CHANGEPOS); else _actions->moveToY(dviState().v+_ty, mode == MoveMode::CHANGEPOS); } } void DVIToSVG::moveDown (double dy, MoveMode mode) { DVIReader::moveDown(dy, mode); if (_actions) { if (dviState().d == WritingMode::LR) _actions->moveToY(dviState().v+_ty, mode == MoveMode::CHANGEPOS); else _actions->moveToX(dviState().h+_tx, mode == MoveMode::CHANGEPOS); } } void DVIToSVG::dviPost (uint16_t, uint16_t pages, uint32_t pw, uint32_t ph, uint32_t, uint32_t, uint32_t, uint32_t) { _pageHeight = ph; // height of tallest page in dvi units _pageWidth = pw; // width of widest page in dvi units } void DVIToSVG::dviBop (const std::vector &c, int32_t) { _pageByte = 0; enterBeginPage(currentPageNumber(), c); if (_actions) { _actions->progress(0, 1); // ensure that progress is called at 0% _actions->beginPage(currentPageNumber(), c); } } void DVIToSVG::dviEop () { if (_actions) { _actions->endPage(currentPageNumber()); _pageByte = numberOfPageBytes(currentPageNumber()-1); _actions->progress(_pageByte, _pageByte); // ensure that progress is called at 100% } leaveEndPage(currentPageNumber()); } void DVIToSVG::dviSetChar0 (uint32_t c, const Font *font) { if (_actions && !font_cast(font)) _actions->setChar(dviState().h+_tx, dviState().v+_ty, c, dviState().d != WritingMode::LR, *font); } void DVIToSVG::dviSetChar (uint32_t c, const Font *font) { dviSetChar0(c, font); } void DVIToSVG::dviPutChar (uint32_t c, const Font *font) { dviSetChar0(c, font); } void DVIToSVG::dviSetRule (double height, double width) { if (_actions && height > 0 && width > 0) _actions->setRule(dviState().h+_tx, dviState().v+_ty, height, width); } void DVIToSVG::dviPutRule (double height, double width) { dviSetRule(height, width); } void DVIToSVG::dviPop () { if (_actions) { if (_prevXPos != dviState().h+_tx) _actions->moveToX(dviState().h + _tx, true); // force setting the SVG position if (_prevYPos != dviState().v+_ty) _actions->moveToY(dviState().v + _ty, true); // force setting the SVG position if (_prevWritingMode != dviState().d) _actions->setTextOrientation(dviState().d != WritingMode::LR); } } void DVIToSVG::dviFontNum (uint32_t fontnum, SetFontMode, const Font *font) { if (_actions && font && !font_cast(font)) _actions->setFont(FontManager::instance().fontID(fontnum), *font); // all fonts get a recomputed ID } void DVIToSVG::dviDir (WritingMode dir) { if (_actions) _actions->setTextOrientation(dir != WritingMode::LR); } void DVIToSVG::dviXXX (const std::string &str) { if (_actions) _actions->special(str, dvi2bp()); } void DVIToSVG::dviXGlyphArray (std::vector &dx, vector &dy, vector &glyphs, const Font &font) { if (_actions) { for (size_t i=0; i < glyphs.size(); i++) _actions->setChar(dviState().h+dx[i]+_tx, dviState().v+dy[i]+_ty, glyphs[i], false, font); } } void DVIToSVG::dviXGlyphString (vector &dx, vector &glyphs, const Font &font) { if (_actions) { for (size_t i=0; i < glyphs.size(); i++) _actions->setChar(dviState().h+dx[i]+_tx, dviState().v+_ty, glyphs[i], false, font); } } void DVIToSVG::dviXTextAndGlyphs (vector &dx, vector &dy, vector&, vector &glyphs, const Font &font) { dviXGlyphArray(dx, dy, glyphs, font); } /////////////////////////////////////////////////////////////// /** Parses a string consisting of comma-separated words, and assigns * the values to the hash settings. */ void DVIToSVG::HashSettings::setParameters (const string ¶mstr) { auto paramnames = util::split(paramstr, ","); map paramMap = { {"list", P_LIST}, {"replace", P_REPLACE} }; for (string &name : paramnames) { name = util::trim(name); auto it = paramMap.find(name); if (it != paramMap.end()) _params.insert(it->second); else if (_algo.empty()) { if (HashFunction::isSupportedAlgorithm(name)) _algo = name; else if (!name.empty()) { string msg = "invalid hash parameter '" + name + "' (supported algorithms: "; for (const string &str: HashFunction::supportedAlgorithms()) msg += str + ", "; msg.pop_back(); msg.back() = ')'; throw MessageException(std::move(msg)); } } } // set default hash algorithm if none is given if (_algo.empty()) _algo = "xxh64"; } dvisvgm-3.5/src/DVIToSVG.hpp000066400000000000000000000132501501401750600156450ustar00rootroot00000000000000/************************************************************************* ** DVIToSVG.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef DVITOSVG_HPP #define DVITOSVG_HPP #include #include #include #include "DVIReader.hpp" #include "FilePath.hpp" #include "SVGTree.hpp" struct DVIActions; struct SVGOutputBase; class HashFunction; class DVIToSVG : public DVIReader { public: class HashSettings { public: enum Parameter {P_LIST, P_REPLACE}; void setParameters (const std::string ¶mstr); void setOptionHash (const std::string &optHash) {_optHash = optHash;} const std::string& algorithm () const {return _algo;} const std::string& optionsHash () const {return _optHash;} bool isSet (Parameter param) {return _params.find(param) != _params.end();} private: std::string _algo; std::string _optHash; std::set _params; }; public: explicit DVIToSVG (std::istream &is, SVGOutputBase &out); DVIToSVG (const DVIToSVG&) =delete; void convert (const std::string &range, std::pair *pageinfo=nullptr); void setPageSize (const std::string &format) {_bboxFormatString = format;} void setPageTransformation (const std::string &cmds) {_transCmds = cmds;} void setUserMessage (const std::string &msg) {_userMessage = msg;} Matrix getPageTransformation () const override; void translateToX (double x) override {_tx = x-dviState().h-_tx;} void translateToY (double y) override {_ty = y-dviState().v-_ty;} double getXPos() const override {return dviState().h+_tx;} double getYPos() const override {return dviState().v+_ty;} void finishLine () override {_prevYPos = std::numeric_limits::min();} void listHashes (const std::string &rangestr, std::ostream &os); FilePath getSVGFilePath (unsigned pageno) const; const std::string& getUserBBoxString () const {return _bboxFormatString;} static void setProcessSpecials (const std::string &ignorelist="", bool pswarning=false); public: static bool COMPUTE_PROGRESS; ///< if true, an action to handle the progress ratio of a page is triggered static char TRACE_MODE; static HashSettings PAGE_HASH_SETTINGS; protected: void convert (unsigned firstPage, unsigned lastPage, HashFunction *hashFunc); int executeCommand () override; void enterBeginPage (unsigned pageno, const std::vector &c); void leaveEndPage (unsigned pageno) const; void embedFonts (); void moveRight (double dx, MoveMode mode) override; void moveDown (double dy, MoveMode mode) override; void dviPost (uint16_t stdepth, uint16_t pages, uint32_t pw, uint32_t ph, uint32_t mag, uint32_t num, uint32_t den, uint32_t lbopofs) override; void dviBop (const std::vector &c, int32_t prevBopOffset) override; void dviEop () override; void dviSetChar0 (uint32_t c, const Font *font) override; void dviSetChar (uint32_t c, const Font *font) override; void dviPutChar (uint32_t c, const Font *font) override; void dviSetRule (double h, double w) override; void dviPutRule (double h, double w) override; void dviPop () override; void dviFontNum (uint32_t fontnum, SetFontMode mode, const Font *font) override; void dviDir (WritingMode dir) override; void dviXXX (const std::string &str) override; void dviXGlyphArray (std::vector &dx, std::vector &dy, std::vector &glyphs, const Font &font) override; void dviXGlyphString (std::vector &dx, std::vector &glyphs, const Font &font) override; void dviXTextAndGlyphs (std::vector &dx, std::vector &dy, std::vector &chars, std::vector &glyphs, const Font &font) override; private: SVGTree _svg; SVGOutputBase &_out; std::unique_ptr _actions; std::string _bboxFormatString; ///< bounding box size/format set by the user std::string _transCmds; ///< page transformation commands set by the user std::string _userMessage; ///< message printed after conversion of a page double _pageHeight=0, _pageWidth=0; ///< global page height and width stored in the postamble double _tx=0, _ty=0; ///< translation of cursor position double _prevXPos, _prevYPos; ///< previous cursor position WritingMode _prevWritingMode; ///< previous writing mode std::streampos _pageByte=0; ///< position of the stream pointer relative to the preceding bop (in bytes) }; #endif dvisvgm-3.5/src/DVIToSVGActions.cpp000066400000000000000000000273441501401750600171720ustar00rootroot00000000000000/************************************************************************* ** DVIToSVGActions.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include #include #include "BoundingBox.hpp" #include "DVIToSVG.hpp" #include "DVIToSVGActions.hpp" #include "Font.hpp" #include "FontManager.hpp" #include "GlyphTracerMessages.hpp" #include "System.hpp" #include "utility.hpp" using namespace std; void DVIToSVGActions::reset () { FontManager::instance().resetUsedChars(); _bbox.invalidate(); _bgcolor = Color(0, Color::ColorSpace::TRANSPARENT); } /** Change current horizontal position. * @param[in] x new horizontal position * @param[in] forceSVGMove if true, creates an explicit position change in the SVG tree */ void DVIToSVGActions::moveToX (double x, bool forceSVGMove) { SpecialManager::instance().notifyPositionChange(getX(), getY(), *this); if (forceSVGMove) _svg.setX(x); } /** Change current vertical position. * @param[in] y new vertical position * @param[in] forceSVGMove if true, creates an explicit position change in the SVG tree */ void DVIToSVGActions::moveToY (double y, bool forceSVGMove) { SpecialManager::instance().notifyPositionChange(getX(), getY(), *this); if (forceSVGMove) _svg.setY(y); } FilePath DVIToSVGActions::getSVGFilePath (unsigned pageno) const { FilePath path; if (auto dvi2svg = dynamic_cast(_dvireader)) path = dvi2svg->getSVGFilePath(pageno); return path; } string DVIToSVGActions::getBBoxFormatString () const { string boxstr; if (auto dvi2svg = dynamic_cast(_dvireader)) boxstr = dvi2svg->getUserBBoxString(); return boxstr; } /** This method is called when a "set char" command was found in the DVI file. * It draws a character of the current font. * @param[in] x horizontal position of left bounding box edge * @param[in] y vertical position of the character's baseline * @param[in] c character code relative to the current font * @param[in] vertical true if we're in vertical mode * @param[in] font font to be used */ void DVIToSVGActions::setChar (double x, double y, unsigned c, bool vertical, const Font &font) { if (_outputLocked) return; // If we use SVG fonts there is no need to record all font name/char/size combinations // because the SVG font mechanism handles this automatically. It's sufficient to // record font names and chars. The various font sizes can be ignored here. // For a given font object, Font::uniqueFont() returns the same unique font object for // all fonts with the same name. FontManager::instance().addUsedChar(font, c); _svg.appendChar(c, x, y); static string fontname; GlyphTracerMessages callback(fontname != font.name(), false); fontname = font.name(); GlyphMetrics metrics; font.getGlyphMetrics(c, vertical, metrics); auto pf = font_cast(&font); if (PhysicalFont::EXACT_BBOX && pf) { GlyphMetrics exact_metrics; pf->getExactGlyphBox(c, exact_metrics, vertical, &callback); if (vertical) { // move top of bbox to upper margin of glyph (just an approximation yet) y += (metrics.d-exact_metrics.h-exact_metrics.d)/2; } metrics = exact_metrics; } BoundingBox bbox(x-metrics.wl, y-metrics.h, x+metrics.wr, y+metrics.d); // update bounding box if (!getMatrix().isIdentity()) bbox.transform(getMatrix()); embed(bbox); #if 0 auto rect = util::make_unique("rect"); rect->addAttribute("x", x-metrics.wl); rect->addAttribute("y", y-metrics.h); rect->addAttribute("width", metrics.wl+metrics.wr); rect->addAttribute("height", metrics.h+metrics.d); rect->addAttribute("fill", "none"); rect->addAttribute("stroke", "red"); rect->addAttribute("stroke-width", "0.5"); _svg.appendToPage(std::move(rect)); if (metrics.d > 0) { auto line = util::make_unique("line"); line->addAttribute("x1", x-metrics.wl); line->addAttribute("y1", y); line->addAttribute("x2", x+metrics.wr); line->addAttribute("y2", y); line->addAttribute("stroke", "blue"); line->addAttribute("stroke-width", "0.5"); _svg.appendToPage(std::move(line)); } if (metrics.wl > 0) { auto line = util::make_unique("line"); line->addAttribute("x1", x); line->addAttribute("y1", y-metrics.h); line->addAttribute("x2", x); line->addAttribute("y2", y+metrics.d); line->addAttribute("stroke", "blue"); line->addAttribute("stroke-width", "0.5"); _svg.appendToPage(std::move(line)); } #endif } /** This method is called when a "set rule" or "put rule" command was found in the * DVI file. It draws a solid unrotated rectangle. * @param[in] x horizontal position of left edge * @param[in] y vertical position of bottom(!) edge * @param[in] height length of the vertical edges * @param[in] width length of the horizontal edges */ void DVIToSVGActions::setRule (double x, double y, double height, double width) { if (_outputLocked) return; // (x,y) is the lower left corner of the rectangle auto rect = util::make_unique("rect"); rect->addAttribute("x", x); rect->addAttribute("y", y-height); rect->addAttribute("height", height); rect->addAttribute("width", width); rect->setTransform(getMatrix()); rect->setFillColor(_svg.getFillColor()); _svg.appendToPage(std::move(rect)); // update bounding box BoundingBox bb(x, y-height, x+width, y); if (!getMatrix().isIdentity()) bb.transform(getMatrix()); embed(bb); } /** This method is called when a "set font" command was found in the DVI file. The * font must be previously defined. * @param[in] num unique number of the font in the DVI file (not necessarily equal to the DVI font number) * @param[in] font pointer to the font object (always represents a physical font and never a virtual font) */ void DVIToSVGActions::setFont (int num, const Font &font) { _svg.setFont(num, font); } /** This method is called when a "special" command was found in the DVI file. * @param[in] spc the special expression * @param[in] dvi2bp factor to scale DVI units to PS points * @param[in] preprocessing if true, the DVI file is being pre-processed */ void DVIToSVGActions::special (const string &spc, double dvi2bp, bool preprocessing) { try { if (preprocessing) SpecialManager::instance().preprocess(spc, *this); else SpecialManager::instance().process(spc, dvi2bp, *this); // @@ output message in case of unsupported specials? } catch (const SpecialException &e) { Message::estream(true) << "error in special: " << e.what() << '\n'; } } /** This method is called when a "begin of page (bop)" command was found in the DVI file. * @param[in] pageno physical page number */ void DVIToSVGActions::beginPage (unsigned pageno, const vector&) { _svg.newPage(++_pageCount); _bbox = BoundingBox(); // clear bounding box _boxes.clear(); setMatrix(Matrix(1)); SpecialManager::instance().notifyBeginPage(pageno, *this); } /** This method is called when an "end of page (eop)" command was found in the DVI file. */ void DVIToSVGActions::endPage (unsigned pageno) { try { SpecialManager::instance().notifyEndPage(pageno, *this); } catch (const SpecialException &e) { Message::estream(true) << "error in special: " << e.what() << '\n'; } Matrix matrix = _dvireader->getPageTransformation(); _svg.transformPage(matrix); if (!_bgcolor.isTransparent()) { // create a rectangle filled with the background color auto rect = util::make_unique("rect"); rect->addAttribute("x", _bbox.minX()); rect->addAttribute("y", _bbox.minY()); rect->addAttribute("width", _bbox.width()); rect->addAttribute("height", _bbox.height()); rect->setFillColor(_bgcolor); _svg.prependToPage(std::move(rect)); } } void DVIToSVGActions::setBgColor (const Color &color) { _bgcolor = color; } void DVIToSVGActions::embed (const BoundingBox &bbox) { _bbox.embed(bbox); for (auto &strboxpair : _boxes) strboxpair.second.embed(bbox); } void DVIToSVGActions::embed (const DPair& p, double r) { if (r == 0) _bbox.embed(p); else _bbox.embed(p, r); for (auto &strboxpair : _boxes) strboxpair.second.embed(p, r); } BoundingBox& DVIToSVGActions::bbox (const string& name, bool reset) { BoundingBox &box = _boxes[name]; if (reset) box = BoundingBox(); return box; } /** This method is called by subprocesses like the PS handler when * a computation step has finished. Since the total number of steps * can't be determined in advance, we don't show a percent value but * a rotating dash. */ void DVIToSVGActions::progress (const char *id) { if (PROGRESSBAR_DELAY < 1000) { static double time=System::time(); // slow down updating the progress indicator to prevent flickering if (System::time() - time > 0.1) { progress(0, 0, id); time = System::time(); } } } /** Returns the number of digits of a given integer. */ static int digits (int n) { if (n == 0) return 1; if (n > 0) return util::ilog10(n)+1; return util::ilog10(-n)+2; } /** Draws a simple progress indicator. * @param[in] current current iteration step (of 'total' steps) * @param[in] total total number of iteration steps * @param[in] id ID of the subprocess providing the information */ void DVIToSVGActions::progress (size_t current, size_t total, const char *id) { static double time=0; static bool draw=false; // show progress indicator? static const char *prev_id=nullptr; if (current == 0 && total > 0) { time = System::time(); draw = false; Message::mstream() << '\n'; } // don't show the progress indicator before the given time has elapsed if (!draw && System::time()-time > PROGRESSBAR_DELAY) { draw = true; Terminal::cursor(false); } if (draw && (System::time() - time > 0.1 || (total > 0 && current == total) || prev_id != id)) { static int step = -1; // >=0: rotating dash static size_t prev_current=0, prev_total=1; const char *tips = "-\\|/"; if (total == 0) { current = prev_current; total = prev_total; step = (step+1) % 4; } else { prev_current = current; prev_total = total; step = -1; } // adapt length of progress indicator to terminal width int cols = Terminal::columns(); int width = (cols == 0 || cols > 60) ? 50 : 49-60+cols; double factor = double(current)/double(total); int length = int(width*factor); Message::mstream(false, Message::MC_PROGRESS) << '[' << string(length, '=') << (factor < 1.0 ? (step < 0 ? ' ' : tips[step]) : '=') << string(width-length, ' ') << "] " << string(3-digits(int(100*factor)), ' ') << int(100*factor) << "%\r"; // overprint indicator when finished if (factor == 1.0) { Message::estream().clearline(); Terminal::cursor(true); } time = System::time(); prev_id = id; } } dvisvgm-3.5/src/DVIToSVGActions.hpp000066400000000000000000000115641501401750600171740ustar00rootroot00000000000000/************************************************************************* ** DVIToSVGActions.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef DVITOSVGACTIONS_HPP #define DVITOSVGACTIONS_HPP #include #include #include "BoundingBox.hpp" #include "DVIActions.hpp" #include "Matrix.hpp" #include "SpecialActions.hpp" #include "SpecialManager.hpp" #include "SVGTree.hpp" class DVIToSVG; class FileFinder; class Font; class XMLNode; class DVIToSVGActions : public DVIActions, public SpecialActions { using BoxMap = std::unordered_map; public: DVIToSVGActions (DVIToSVG &dvisvg, SVGTree &svg) : _svg(svg), _dvireader(&dvisvg) {} void reset () override; void setChar (double x, double y, unsigned c, bool vertical, const Font &f) override; void setRule (double x, double y, double height, double width) override; void setBgColor (const Color &color) override; void setFillColor (const Color &color) override {_svg.setFillColor(color);} void setStrokeColor (const Color &color) override {_svg.setStrokeColor(color);} void setMatrix (const Matrix &m) override {_svg.setMatrix(m);} void setOpacity (const Opacity &opacity) override {_svg.setOpacity(opacity);} const Opacity& getOpacity () const override {return _svg.getOpacity();} const Matrix& getMatrix () const override {return _svg.getMatrix();} Matrix getPageTransformation () const override {return _dvireader->getPageTransformation();} Color getFillColor () const override {return _svg.getFillColor();} Color getStrokeColor () const override {return _svg.getStrokeColor();} int getDVIStackDepth () const override {return _dvireader->stackDepth();} unsigned getCurrentPageNumber () const override {return _dvireader->currentPageNumber();} void setTextOrientation (bool vertical) override {_svg.setVertical(vertical);} void moveToX (double x, bool forceSVGMove) override; void moveToY (double y, bool forceSVGMove) override; void setFont (int num, const Font &font) override; void special (const std::string &spc, double dvi2bp, bool preprocessing=false) override; void beginPage (unsigned pageno, const std::vector &c) override; void endPage (unsigned pageno) override; void progress (size_t current, size_t total, const char *id=nullptr) override; void progress (const char *id) override; double getX() const override {return _dvireader->getXPos();} double getY() const override {return _dvireader->getYPos();} void setX (double x) override {_dvireader->translateToX(x); _svg.setX(x);} void setY (double y) override {_dvireader->translateToY(y); _svg.setY(y);} void finishLine () override {_dvireader->finishLine();} void lockOutput () override {_outputLocked = true;} void unlockOutput () override {_outputLocked = false;} bool outputLocked () const override {return _outputLocked;} const SVGTree& svgTree () const override {return _svg;} BoundingBox& bbox () override {return _bbox;} BoundingBox& bbox (const std::string &name, bool reset=false) override; void embed (const BoundingBox &bbox) override; void embed (const DPair &p, double r=0) override; FilePath getSVGFilePath (unsigned pageno) const override; std::string getBBoxFormatString () const override; void setDVIReader (BasicDVIReader &r) {_dvireader = &r;} private: SVGTree &_svg; BasicDVIReader *_dvireader; BoundingBox _bbox; int _pageCount=0; Color _bgcolor=Color(0, Color::ColorSpace::TRANSPARENT); BoxMap _boxes; bool _outputLocked=false; }; #endif dvisvgm-3.5/src/Directory.cpp000066400000000000000000000065011501401750600163000ustar00rootroot00000000000000/************************************************************************* ** Directory.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #include "Directory.hpp" using namespace std; #ifndef _WIN32 #include #include #endif Directory::Directory () { #ifdef _WIN32 memset(&_fileData, 0, sizeof(WIN32_FIND_DATA)); #endif } Directory::Directory (const string &dirname) : Directory() { open(dirname); } Directory::~Directory () { close(); } bool Directory::open (string dirname) { _dirname = dirname; #ifdef _WIN32 if (dirname.empty()) return false; _firstread = true; if (dirname.back() == '/' || dirname.back() == '\\') dirname.pop_back(); dirname += "\\*"; _handle = FindFirstFile(dirname.c_str(), &_fileData); return _handle != INVALID_HANDLE_VALUE; #else _dir = opendir(_dirname.c_str()); return bool(_dir); #endif } void Directory::close () { #ifdef _WIN32 FindClose(_handle); #else if (_dir) { closedir(_dir); _dir = nullptr; } #endif } /** Reads first/next directory entry. * @param[in] type type of entry to return (a: file or dir, f: file, d: dir) * @return name of entry */ const char* Directory::read (EntryType type) { #ifdef _WIN32 if (_handle == INVALID_HANDLE_VALUE) return nullptr; while (_firstread || FindNextFile(_handle, &_fileData)) { _firstread = false; if (_fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (type == ET_FILE_OR_DIR || type == ET_DIR) return _fileData.cFileName; } else if (type == ET_FILE_OR_DIR || type == ET_FILE) return _fileData.cFileName; } FindClose(_handle); _handle = INVALID_HANDLE_VALUE; return nullptr; #else if (_dir) { while ((_dirent = readdir(_dir))) { string path = _dirname + "/" + _dirent->d_name; struct stat stats; if (stat(path.c_str(), &stats) == 0) { if (S_ISDIR(stats.st_mode)) { if (type == ET_FILE_OR_DIR || type == ET_DIR) return _dirent->d_name; } else if (type == ET_FILE_OR_DIR || type == ET_FILE) return _dirent->d_name; } } closedir(_dir); _dir = nullptr; } return nullptr; #endif } dvisvgm-3.5/src/Directory.hpp000066400000000000000000000040051501401750600163020ustar00rootroot00000000000000/************************************************************************* ** Directory.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2025 Martin Gieseking ** ** ** ** 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 . ** *************************************************************************/ #ifndef DIRECTORY_HPP #define DIRECTORY_HPP #include #ifdef _WIN32 #include "windows.hpp" #else #include #endif class Directory { public: enum EntryType {ET_FILE, ET_DIR, ET_FILE_OR_DIR}; public: Directory (); explicit Directory (const std::string &path); ~Directory (); bool open (std::string path); void close (); const char* read (EntryType type=ET_FILE_OR_DIR); private: std::string _dirname; #ifdef _WIN32 bool _firstread=true; HANDLE _handle=INVALID_HANDLE_VALUE; WIN32_FIND_DATA _fileData; #else DIR *_dir=nullptr; struct dirent *_dirent=nullptr; #endif }; #endif dvisvgm-3.5/src/Doxyfile000066400000000000000000003076101501401750600153430ustar00rootroot00000000000000# Doxyfile 1.8.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = dvisvgm # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = 3.5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doxy # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = /home/mgieseki/develop/cpp/dvisvgm-hg/src/ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = YES # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = . # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.vhd \ *.vhdl \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM \ *.PY \ *.F90 \ *.F \ *.VHD \ *.VHDL # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /