Repository: M2Team/NanaZip
Branch: main
Commit: b4d39da98afb
Files: 2780
Total size: 25.7 MB
Directory structure:
gitextract_ul7qcrqt/
├── .editorconfig
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── feature_request.yml
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dco.yml
│ └── workflows/
│ ├── BuildBinaries.yml
│ ├── UpdatePrecompiledBuildTools.yml
│ └── UpdateWebsite.yml
├── .gitignore
├── BuildAllTargets.cmd
├── BuildAllTargets.proj
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Directory.Build.props
├── Documents/
│ ├── ChannelSwitchNote.md
│ ├── DevelopmentRoadmapArchived.md
│ ├── People.md
│ ├── Policies.md
│ ├── PolicyDefinitions/
│ │ ├── NanaZip.admx
│ │ └── en-US/
│ │ └── NanaZip.adml
│ ├── Privacy.md
│ ├── ReleaseNotes.md
│ ├── ReleaseNotesPreview.md
│ ├── Section508/
│ │ ├── NanaZip.html
│ │ └── NanaZip.yaml
│ ├── SponsorEdition.md
│ ├── UpstreamSynchronization.md
│ ├── Versioning.md
│ └── Website/
│ ├── .gitignore
│ ├── .vscode/
│ │ ├── extensions.json
│ │ ├── launch.json
│ │ └── mcp.json
│ ├── ReadMe.md
│ ├── astro.config.mjs
│ ├── package.json
│ ├── src/
│ │ ├── assets/
│ │ │ └── styles/
│ │ │ ├── button.css
│ │ │ ├── global.css
│ │ │ ├── icons.css
│ │ │ ├── image.css
│ │ │ ├── pages/
│ │ │ │ └── index.css
│ │ │ ├── text.css
│ │ │ └── theme.css
│ │ ├── components/
│ │ │ ├── Footer/
│ │ │ │ ├── Footer.astro
│ │ │ │ └── Footer.css
│ │ │ ├── InfoBar/
│ │ │ │ ├── InfoBar.astro
│ │ │ │ └── InfoBar.scss
│ │ │ ├── Navbar/
│ │ │ │ ├── Navbar.astro
│ │ │ │ ├── Navbar.scss
│ │ │ │ └── Navbar.ts
│ │ │ ├── PageSection/
│ │ │ │ ├── PageSection.astro
│ │ │ │ └── PageSection.scss
│ │ │ ├── StoreBadge/
│ │ │ │ ├── StoreBadge.astro
│ │ │ │ ├── StoreBadge.css
│ │ │ │ └── StoreBadge.ts
│ │ │ ├── ThemedLocalPicture/
│ │ │ │ └── ThemedLocalPicture.astro
│ │ │ └── Tree/
│ │ │ ├── Tree.astro
│ │ │ └── Tree.css
│ │ ├── layouts/
│ │ │ └── Layout.astro
│ │ └── pages/
│ │ ├── downloads.astro
│ │ ├── index.astro
│ │ └── section508.astro
│ └── tsconfig.json
├── K7Base/
│ ├── K7Base.def
│ ├── K7Base.h
│ ├── K7Base.props
│ ├── K7Base.vcxproj
│ ├── K7BaseDetours.cpp
│ ├── K7BaseHash.cpp
│ ├── K7BaseInitialize.cpp
│ ├── K7BaseMitigations.cpp
│ ├── K7BaseModern.cpp
│ ├── K7BasePolicies.cpp
│ ├── K7BasePrivate.h
│ ├── K7BaseRedirector.cpp
│ ├── K7BaseStatic.props
│ ├── K7BaseStatic.vcxproj
│ └── ReadMe.md
├── K7User/
│ ├── K7User.def
│ ├── K7User.h
│ ├── K7User.props
│ ├── K7User.vcxproj
│ ├── K7UserDarkMode.cpp
│ ├── K7UserModern.cpp
│ ├── K7UserPrivate.h
│ ├── K7UserRedirector.cpp
│ ├── K7UserStatic.props
│ ├── K7UserStatic.vcxproj
│ └── ReadMe.md
├── License.md
├── NanaZip.Build.Tasks/
│ ├── NanaZip.Build.Tasks.csproj
│ ├── RefreshAppxManifestVersion.cs
│ └── RefreshProjectBuildNumberDate.cs
├── NanaZip.Codecs/
│ ├── BLAKE3/
│ │ ├── blake3.c
│ │ ├── blake3.h
│ │ ├── blake3_avx2_x86-64_windows_msvc.asm
│ │ ├── blake3_avx512_x86-64_windows_msvc.asm
│ │ ├── blake3_dispatch.c
│ │ ├── blake3_impl.h
│ │ ├── blake3_neon.c
│ │ ├── blake3_portable.c
│ │ ├── blake3_sse2_x86-64_windows_msvc.asm
│ │ └── blake3_sse41_x86-64_windows_msvc.asm
│ ├── Brotli/
│ │ ├── common/
│ │ │ ├── constants.c
│ │ │ ├── constants.h
│ │ │ ├── context.c
│ │ │ ├── context.h
│ │ │ ├── dictionary.c
│ │ │ ├── dictionary.h
│ │ │ ├── dictionary_inc.h
│ │ │ ├── platform.c
│ │ │ ├── platform.h
│ │ │ ├── shared_dictionary.c
│ │ │ ├── shared_dictionary_internal.h
│ │ │ ├── static_init.h
│ │ │ ├── transform.c
│ │ │ ├── transform.h
│ │ │ └── version.h
│ │ ├── dec/
│ │ │ ├── bit_reader.c
│ │ │ ├── bit_reader.h
│ │ │ ├── dec_static_init.c
│ │ │ ├── decode.c
│ │ │ ├── huffman.c
│ │ │ ├── huffman.h
│ │ │ ├── prefix.c
│ │ │ ├── prefix.h
│ │ │ ├── prefix_inc.h
│ │ │ ├── state.c
│ │ │ ├── state.h
│ │ │ └── static_init.h
│ │ ├── enc/
│ │ │ ├── backward_references.c
│ │ │ ├── backward_references.h
│ │ │ ├── backward_references_hq.c
│ │ │ ├── backward_references_hq.h
│ │ │ ├── backward_references_inc.h
│ │ │ ├── bit_cost.c
│ │ │ ├── bit_cost.h
│ │ │ ├── bit_cost_inc.h
│ │ │ ├── block_encoder_inc.h
│ │ │ ├── block_splitter.c
│ │ │ ├── block_splitter.h
│ │ │ ├── block_splitter_inc.h
│ │ │ ├── brotli_bit_stream.c
│ │ │ ├── brotli_bit_stream.h
│ │ │ ├── cluster.c
│ │ │ ├── cluster.h
│ │ │ ├── cluster_inc.h
│ │ │ ├── command.c
│ │ │ ├── command.h
│ │ │ ├── compound_dictionary.c
│ │ │ ├── compound_dictionary.h
│ │ │ ├── compress_fragment.c
│ │ │ ├── compress_fragment.h
│ │ │ ├── compress_fragment_two_pass.c
│ │ │ ├── compress_fragment_two_pass.h
│ │ │ ├── dictionary_hash.c
│ │ │ ├── dictionary_hash.h
│ │ │ ├── dictionary_hash_inc.h
│ │ │ ├── enc_static_init.c
│ │ │ ├── encode.c
│ │ │ ├── encoder_dict.c
│ │ │ ├── encoder_dict.h
│ │ │ ├── entropy_encode.c
│ │ │ ├── entropy_encode.h
│ │ │ ├── entropy_encode_static.h
│ │ │ ├── fast_log.c
│ │ │ ├── fast_log.h
│ │ │ ├── find_match_length.h
│ │ │ ├── hash.h
│ │ │ ├── hash_base.h
│ │ │ ├── hash_composite_inc.h
│ │ │ ├── hash_forgetful_chain_inc.h
│ │ │ ├── hash_longest_match64_inc.h
│ │ │ ├── hash_longest_match64_simd_inc.h
│ │ │ ├── hash_longest_match_inc.h
│ │ │ ├── hash_longest_match_quickly_inc.h
│ │ │ ├── hash_longest_match_simd_inc.h
│ │ │ ├── hash_rolling_inc.h
│ │ │ ├── hash_to_binary_tree_inc.h
│ │ │ ├── histogram.c
│ │ │ ├── histogram.h
│ │ │ ├── histogram_inc.h
│ │ │ ├── literal_cost.c
│ │ │ ├── literal_cost.h
│ │ │ ├── matching_tag_mask.h
│ │ │ ├── memory.c
│ │ │ ├── memory.h
│ │ │ ├── metablock.c
│ │ │ ├── metablock.h
│ │ │ ├── metablock_inc.h
│ │ │ ├── params.h
│ │ │ ├── prefix.h
│ │ │ ├── quality.h
│ │ │ ├── ringbuffer.h
│ │ │ ├── state.h
│ │ │ ├── static_dict.c
│ │ │ ├── static_dict.h
│ │ │ ├── static_dict_lut.c
│ │ │ ├── static_dict_lut.h
│ │ │ ├── static_dict_lut_inc.h
│ │ │ ├── static_init.h
│ │ │ ├── utf8_util.c
│ │ │ ├── utf8_util.h
│ │ │ └── write_bits.h
│ │ └── include/
│ │ └── brotli/
│ │ ├── decode.h
│ │ ├── encode.h
│ │ ├── port.h
│ │ ├── shared_dictionary.h
│ │ └── types.h
│ ├── FastLZMA2/
│ │ ├── atomic.h
│ │ ├── compiler.h
│ │ ├── count.h
│ │ ├── data_block.h
│ │ ├── dict_buffer.c
│ │ ├── dict_buffer.h
│ │ ├── fast-lzma2.h
│ │ ├── fastpos_table.h
│ │ ├── fl2_common.c
│ │ ├── fl2_compress.c
│ │ ├── fl2_compress_internal.h
│ │ ├── fl2_errors.h
│ │ ├── fl2_internal.h
│ │ ├── fl2_pool.c
│ │ ├── fl2_pool.h
│ │ ├── fl2_threading.c
│ │ ├── fl2_threading.h
│ │ ├── lzma2_enc.c
│ │ ├── lzma2_enc.h
│ │ ├── mem.h
│ │ ├── platform.h
│ │ ├── radix_bitpack.c
│ │ ├── radix_engine.h
│ │ ├── radix_get.h
│ │ ├── radix_internal.h
│ │ ├── radix_mf.c
│ │ ├── radix_mf.h
│ │ ├── radix_struct.c
│ │ ├── range_enc.c
│ │ ├── range_enc.h
│ │ ├── util.c
│ │ └── util.h
│ ├── FreeBSD/
│ │ ├── dinode.h
│ │ ├── dir.h
│ │ └── fs.h
│ ├── GmSSL/
│ │ ├── endian.h
│ │ ├── sm3.c
│ │ └── sm3.h
│ ├── LZ4/
│ │ ├── lz4.c
│ │ ├── lz4.h
│ │ ├── lz4frame.c
│ │ ├── lz4frame.h
│ │ ├── lz4frame_static.h
│ │ ├── lz4hc.c
│ │ └── lz4hc.h
│ ├── LZ5/
│ │ ├── lz5.c
│ │ ├── lz5.h
│ │ ├── lz5common.h
│ │ ├── lz5frame.c
│ │ ├── lz5frame.h
│ │ ├── lz5frame_static.h
│ │ ├── lz5hc.c
│ │ ├── lz5hc.h
│ │ └── mem.h
│ ├── LittleFS/
│ │ ├── lfs.c
│ │ ├── lfs.h
│ │ ├── lfs_util.c
│ │ └── lfs_util.h
│ ├── Lizard/
│ │ ├── entropy/
│ │ │ ├── bitstream.h
│ │ │ ├── compiler.h
│ │ │ ├── debug.h
│ │ │ ├── error_private.h
│ │ │ ├── error_public.h
│ │ │ ├── fse.h
│ │ │ ├── hist.h
│ │ │ ├── huf.h
│ │ │ ├── lizard_entropy_common.c
│ │ │ ├── lizard_fse_compress.c
│ │ │ ├── lizard_fse_decompress.c
│ │ │ ├── lizard_huf_compress.c
│ │ │ ├── lizard_huf_decompress.c
│ │ │ └── mem.h
│ │ ├── lizard_common.h
│ │ ├── lizard_compress.c
│ │ ├── lizard_compress.h
│ │ ├── lizard_compress_liz.h
│ │ ├── lizard_compress_lz4.h
│ │ ├── lizard_decompress.c
│ │ ├── lizard_decompress.h
│ │ ├── lizard_decompress_liz.h
│ │ ├── lizard_decompress_lz4.h
│ │ ├── lizard_frame.c
│ │ ├── lizard_frame.h
│ │ ├── lizard_frame_static.h
│ │ ├── lizard_parser_fast.h
│ │ ├── lizard_parser_fastbig.h
│ │ ├── lizard_parser_fastsmall.h
│ │ ├── lizard_parser_hashchain.h
│ │ ├── lizard_parser_lowestprice.h
│ │ ├── lizard_parser_nochain.h
│ │ ├── lizard_parser_optimal.h
│ │ └── lizard_parser_pricefast.h
│ ├── Mile.Helpers.Portable.Base.Unstaged.cpp
│ ├── Mile.Helpers.Portable.Base.Unstaged.h
│ ├── NanaZip.Codecs.Archive.DotNetSingleFile.cpp
│ ├── NanaZip.Codecs.Archive.ElectronAsar.cpp
│ ├── NanaZip.Codecs.Archive.Littlefs.cpp
│ ├── NanaZip.Codecs.Archive.Romfs.cpp
│ ├── NanaZip.Codecs.Archive.Ufs.cpp
│ ├── NanaZip.Codecs.Archive.WebAssembly.cpp
│ ├── NanaZip.Codecs.Archive.Zealfs.cpp
│ ├── NanaZip.Codecs.Hash.Aich.cpp
│ ├── NanaZip.Codecs.Hash.BCryptProvider.cpp
│ ├── NanaZip.Codecs.Hash.Blake2b.cpp
│ ├── NanaZip.Codecs.Hash.Blake3.cpp
│ ├── NanaZip.Codecs.Hash.Ed2k.cpp
│ ├── NanaZip.Codecs.Hash.EdonR224.cpp
│ ├── NanaZip.Codecs.Hash.EdonR256.cpp
│ ├── NanaZip.Codecs.Hash.EdonR384.cpp
│ ├── NanaZip.Codecs.Hash.EdonR512.cpp
│ ├── NanaZip.Codecs.Hash.Gost12256.cpp
│ ├── NanaZip.Codecs.Hash.Gost12512.cpp
│ ├── NanaZip.Codecs.Hash.Gost94.cpp
│ ├── NanaZip.Codecs.Hash.Gost94CryptoPro.cpp
│ ├── NanaZip.Codecs.Hash.Has160.cpp
│ ├── NanaZip.Codecs.Hash.Ripemd160.cpp
│ ├── NanaZip.Codecs.Hash.Sha224.cpp
│ ├── NanaZip.Codecs.Hash.Sha3224.cpp
│ ├── NanaZip.Codecs.Hash.Sha3256.cpp
│ ├── NanaZip.Codecs.Hash.Sha3384.cpp
│ ├── NanaZip.Codecs.Hash.Sha3512.cpp
│ ├── NanaZip.Codecs.Hash.Sm3.cpp
│ ├── NanaZip.Codecs.Hash.Snefru128.cpp
│ ├── NanaZip.Codecs.Hash.Snefru256.cpp
│ ├── NanaZip.Codecs.Hash.Tiger.cpp
│ ├── NanaZip.Codecs.Hash.Tiger2.cpp
│ ├── NanaZip.Codecs.Hash.Torrent.cpp
│ ├── NanaZip.Codecs.Hash.Tth.cpp
│ ├── NanaZip.Codecs.Hash.Whirlpool.cpp
│ ├── NanaZip.Codecs.Hash.Xxh3128.cpp
│ ├── NanaZip.Codecs.Hash.Xxh32.cpp
│ ├── NanaZip.Codecs.Hash.Xxh364.cpp
│ ├── NanaZip.Codecs.Hash.Xxh64.cpp
│ ├── NanaZip.Codecs.MultiThreadWrapper.Brotli.cpp
│ ├── NanaZip.Codecs.MultiThreadWrapper.Brotli.h
│ ├── NanaZip.Codecs.MultiThreadWrapper.Common.cpp
│ ├── NanaZip.Codecs.MultiThreadWrapper.Common.h
│ ├── NanaZip.Codecs.MultiThreadWrapper.LZ4.cpp
│ ├── NanaZip.Codecs.MultiThreadWrapper.LZ4.h
│ ├── NanaZip.Codecs.MultiThreadWrapper.LZ5.cpp
│ ├── NanaZip.Codecs.MultiThreadWrapper.LZ5.h
│ ├── NanaZip.Codecs.MultiThreadWrapper.Lizard.cpp
│ ├── NanaZip.Codecs.MultiThreadWrapper.Lizard.h
│ ├── NanaZip.Codecs.SevenZipWrapper.cpp
│ ├── NanaZip.Codecs.SevenZipWrapper.h
│ ├── NanaZip.Codecs.Sfx.Shared.props
│ ├── NanaZip.Codecs.Sfx.Shared.vcxproj
│ ├── NanaZip.Codecs.Sfx.Shared.vcxproj.filters
│ ├── NanaZip.Codecs.Specification.Fat.h
│ ├── NanaZip.Codecs.Specification.Zealfs.h
│ ├── NanaZip.Codecs.cpp
│ ├── NanaZip.Codecs.def
│ ├── NanaZip.Codecs.h
│ ├── NanaZip.Codecs.props
│ ├── NanaZip.Codecs.vcxproj
│ ├── NanaZip.Codecs.vcxproj.filters
│ ├── RHash/
│ │ ├── aich.c
│ │ ├── aich.h
│ │ ├── blake2b.c
│ │ ├── blake2b.h
│ │ ├── byte_order.c
│ │ ├── byte_order.h
│ │ ├── edonr.c
│ │ ├── edonr.h
│ │ ├── gost12.c
│ │ ├── gost12.h
│ │ ├── gost94.c
│ │ ├── gost94.h
│ │ ├── has160.c
│ │ ├── has160.h
│ │ ├── hex.c
│ │ ├── hex.h
│ │ ├── rhash_sha256.c
│ │ ├── rhash_util.c
│ │ ├── ripemd-160.c
│ │ ├── ripemd-160.h
│ │ ├── sha1.h
│ │ ├── sha256.h
│ │ ├── sha3.c
│ │ ├── sha3.h
│ │ ├── snefru.c
│ │ ├── snefru.h
│ │ ├── tiger.c
│ │ ├── tiger.h
│ │ ├── tiger_sbox.c
│ │ ├── torrent.c
│ │ ├── torrent.h
│ │ ├── tth.c
│ │ ├── tth.h
│ │ ├── ustd.h
│ │ ├── util.h
│ │ ├── whirlpool.c
│ │ ├── whirlpool.h
│ │ └── whirlpool_sbox.c
│ ├── ZSTDMT/
│ │ ├── brotli-mt.h
│ │ ├── brotli-mt_common.c
│ │ ├── brotli-mt_compress.c
│ │ ├── brotli-mt_decompress.c
│ │ ├── list.h
│ │ ├── lizard-mt.h
│ │ ├── lizard-mt_common.c
│ │ ├── lizard-mt_compress.c
│ │ ├── lizard-mt_decompress.c
│ │ ├── lz4-mt.h
│ │ ├── lz4-mt_common.c
│ │ ├── lz4-mt_compress.c
│ │ ├── lz4-mt_decompress.c
│ │ ├── lz5-mt.h
│ │ ├── lz5-mt_common.c
│ │ ├── lz5-mt_compress.c
│ │ ├── lz5-mt_decompress.c
│ │ ├── memmt.h
│ │ ├── threading.h
│ │ └── zstd-mt_threading.c
│ ├── Zstandard/
│ │ ├── common/
│ │ │ ├── allocations.h
│ │ │ ├── bits.h
│ │ │ ├── bitstream.h
│ │ │ ├── compiler.h
│ │ │ ├── cpu.h
│ │ │ ├── debug.c
│ │ │ ├── debug.h
│ │ │ ├── entropy_common.c
│ │ │ ├── error_private.c
│ │ │ ├── error_private.h
│ │ │ ├── fse.h
│ │ │ ├── fse_decompress.c
│ │ │ ├── huf.h
│ │ │ ├── mem.h
│ │ │ ├── pool.c
│ │ │ ├── pool.h
│ │ │ ├── portability_macros.h
│ │ │ ├── threading.c
│ │ │ ├── threading.h
│ │ │ ├── zstd_common.c
│ │ │ ├── zstd_deps.h
│ │ │ ├── zstd_internal.h
│ │ │ └── zstd_trace.h
│ │ ├── compress/
│ │ │ ├── clevels.h
│ │ │ ├── fse_compress.c
│ │ │ ├── hist.c
│ │ │ ├── hist.h
│ │ │ ├── huf_compress.c
│ │ │ ├── zstd_compress.c
│ │ │ ├── zstd_compress_internal.h
│ │ │ ├── zstd_compress_literals.c
│ │ │ ├── zstd_compress_literals.h
│ │ │ ├── zstd_compress_sequences.c
│ │ │ ├── zstd_compress_sequences.h
│ │ │ ├── zstd_compress_superblock.c
│ │ │ ├── zstd_compress_superblock.h
│ │ │ ├── zstd_cwksp.h
│ │ │ ├── zstd_double_fast.c
│ │ │ ├── zstd_double_fast.h
│ │ │ ├── zstd_fast.c
│ │ │ ├── zstd_fast.h
│ │ │ ├── zstd_lazy.c
│ │ │ ├── zstd_lazy.h
│ │ │ ├── zstd_ldm.c
│ │ │ ├── zstd_ldm.h
│ │ │ ├── zstd_ldm_geartab.h
│ │ │ ├── zstd_opt.c
│ │ │ ├── zstd_opt.h
│ │ │ ├── zstd_preSplit.c
│ │ │ ├── zstd_preSplit.h
│ │ │ ├── zstdmt_compress.c
│ │ │ └── zstdmt_compress.h
│ │ ├── decompress/
│ │ │ ├── huf_decompress.c
│ │ │ ├── zstd_ddict.c
│ │ │ ├── zstd_ddict.h
│ │ │ ├── zstd_decompress.c
│ │ │ ├── zstd_decompress_block.c
│ │ │ ├── zstd_decompress_block.h
│ │ │ └── zstd_decompress_internal.h
│ │ ├── legacy/
│ │ │ ├── zstd_legacy.h
│ │ │ ├── zstd_v01.c
│ │ │ ├── zstd_v01.h
│ │ │ ├── zstd_v02.c
│ │ │ ├── zstd_v02.h
│ │ │ ├── zstd_v03.c
│ │ │ ├── zstd_v03.h
│ │ │ ├── zstd_v04.c
│ │ │ ├── zstd_v04.h
│ │ │ ├── zstd_v05.c
│ │ │ ├── zstd_v05.h
│ │ │ ├── zstd_v06.c
│ │ │ ├── zstd_v06.h
│ │ │ ├── zstd_v07.c
│ │ │ └── zstd_v07.h
│ │ ├── zstd.h
│ │ └── zstd_errors.h
│ └── xxHash/
│ ├── xxhash.c
│ └── xxhash.h
├── NanaZip.Core/
│ ├── Extensions/
│ │ └── ZSCodecs/
│ │ ├── BrotliDecoder.cpp
│ │ ├── BrotliDecoder.h
│ │ ├── BrotliEncoder.cpp
│ │ ├── BrotliEncoder.h
│ │ ├── BrotliHandler.cpp
│ │ ├── BrotliRegister.cpp
│ │ ├── FastLzma2Encoder.cpp
│ │ ├── FastLzma2Encoder.h
│ │ ├── FastLzma2Register.cpp
│ │ ├── LizardDecoder.cpp
│ │ ├── LizardDecoder.h
│ │ ├── LizardEncoder.cpp
│ │ ├── LizardEncoder.h
│ │ ├── LizardHandler.cpp
│ │ ├── LizardRegister.cpp
│ │ ├── Lz4Decoder.cpp
│ │ ├── Lz4Decoder.h
│ │ ├── Lz4Encoder.cpp
│ │ ├── Lz4Encoder.h
│ │ ├── Lz4Handler.cpp
│ │ ├── Lz4Register.cpp
│ │ ├── Lz5Decoder.cpp
│ │ ├── Lz5Decoder.h
│ │ ├── Lz5Encoder.cpp
│ │ ├── Lz5Encoder.h
│ │ ├── Lz5Handler.cpp
│ │ ├── Lz5Register.cpp
│ │ ├── LzHandler.cpp
│ │ ├── ZstdDecoder.cpp
│ │ ├── ZstdDecoder.h
│ │ ├── ZstdEncoder.cpp
│ │ ├── ZstdEncoder.h
│ │ ├── ZstdHandler.cpp
│ │ └── ZstdRegister.cpp
│ ├── NanaZip.Core.Sfx.Console.manifest
│ ├── NanaZip.Core.Sfx.Console.vcxproj
│ ├── NanaZip.Core.Sfx.Console.vcxproj.filters
│ ├── NanaZip.Core.Sfx.Setup.manifest
│ ├── NanaZip.Core.Sfx.Setup.vcxproj
│ ├── NanaZip.Core.Sfx.Setup.vcxproj.filters
│ ├── NanaZip.Core.Sfx.Shared.props
│ ├── NanaZip.Core.Sfx.Shared.vcxproj
│ ├── NanaZip.Core.Sfx.Shared.vcxproj.filters
│ ├── NanaZip.Core.Sfx.Windows.Resources.h
│ ├── NanaZip.Core.Sfx.Windows.Resources.rc
│ ├── NanaZip.Core.Sfx.Windows.manifest
│ ├── NanaZip.Core.Sfx.Windows.vcxproj
│ ├── NanaZip.Core.Sfx.Windows.vcxproj.filters
│ ├── NanaZip.Core.vcxproj
│ ├── NanaZip.Core.vcxproj.filters
│ ├── SevenZip/
│ │ ├── .gitignore
│ │ ├── C/
│ │ │ ├── 7zBuf.h
│ │ │ ├── 7zBuf2.c
│ │ │ ├── 7zCrc.c
│ │ │ ├── 7zCrc.h
│ │ │ ├── 7zCrcOpt.c
│ │ │ ├── 7zStream.c
│ │ │ ├── 7zTypes.h
│ │ │ ├── 7zVersion.h
│ │ │ ├── 7zWindows.h
│ │ │ ├── Aes.c
│ │ │ ├── Aes.h
│ │ │ ├── AesOpt.c
│ │ │ ├── Alloc.c
│ │ │ ├── Alloc.h
│ │ │ ├── Bcj2.c
│ │ │ ├── Bcj2.h
│ │ │ ├── Bcj2Enc.c
│ │ │ ├── Blake2.h
│ │ │ ├── Blake2s.c
│ │ │ ├── Bra.c
│ │ │ ├── Bra.h
│ │ │ ├── Bra86.c
│ │ │ ├── BwtSort.c
│ │ │ ├── BwtSort.h
│ │ │ ├── Compiler.h
│ │ │ ├── CpuArch.c
│ │ │ ├── CpuArch.h
│ │ │ ├── Delta.c
│ │ │ ├── Delta.h
│ │ │ ├── DllSecur.c
│ │ │ ├── DllSecur.h
│ │ │ ├── HuffEnc.c
│ │ │ ├── HuffEnc.h
│ │ │ ├── LzFind.c
│ │ │ ├── LzFind.h
│ │ │ ├── LzFindMt.c
│ │ │ ├── LzFindMt.h
│ │ │ ├── LzFindOpt.c
│ │ │ ├── LzHash.h
│ │ │ ├── Lzma2Dec.c
│ │ │ ├── Lzma2Dec.h
│ │ │ ├── Lzma2DecMt.c
│ │ │ ├── Lzma2DecMt.h
│ │ │ ├── Lzma2Enc.c
│ │ │ ├── Lzma2Enc.h
│ │ │ ├── LzmaDec.c
│ │ │ ├── LzmaDec.h
│ │ │ ├── LzmaEnc.c
│ │ │ ├── LzmaEnc.h
│ │ │ ├── MtCoder.c
│ │ │ ├── MtCoder.h
│ │ │ ├── MtDec.c
│ │ │ ├── MtDec.h
│ │ │ ├── Ppmd.h
│ │ │ ├── Ppmd7.c
│ │ │ ├── Ppmd7.h
│ │ │ ├── Ppmd7Dec.c
│ │ │ ├── Ppmd7Enc.c
│ │ │ ├── Ppmd7aDec.c
│ │ │ ├── Ppmd8.c
│ │ │ ├── Ppmd8.h
│ │ │ ├── Ppmd8Dec.c
│ │ │ ├── Ppmd8Enc.c
│ │ │ ├── Precomp.h
│ │ │ ├── RotateDefs.h
│ │ │ ├── Sha1.h
│ │ │ ├── Sha256.h
│ │ │ ├── Sha512.h
│ │ │ ├── Sort.c
│ │ │ ├── Sort.h
│ │ │ ├── SwapBytes.c
│ │ │ ├── SwapBytes.h
│ │ │ ├── Threads.c
│ │ │ ├── Threads.h
│ │ │ ├── Xz.c
│ │ │ ├── Xz.h
│ │ │ ├── XzCrc64.c
│ │ │ ├── XzCrc64.h
│ │ │ ├── XzCrc64Opt.c
│ │ │ ├── XzDec.c
│ │ │ ├── XzEnc.c
│ │ │ ├── XzEnc.h
│ │ │ └── XzIn.c
│ │ └── CPP/
│ │ ├── 7zip/
│ │ │ ├── Archive/
│ │ │ │ ├── 7z/
│ │ │ │ │ ├── 7zCompressionMode.h
│ │ │ │ │ ├── 7zDecode.cpp
│ │ │ │ │ ├── 7zDecode.h
│ │ │ │ │ ├── 7zEncode.cpp
│ │ │ │ │ ├── 7zEncode.h
│ │ │ │ │ ├── 7zExtract.cpp
│ │ │ │ │ ├── 7zFolderInStream.cpp
│ │ │ │ │ ├── 7zFolderInStream.h
│ │ │ │ │ ├── 7zHandler.cpp
│ │ │ │ │ ├── 7zHandler.h
│ │ │ │ │ ├── 7zHandlerOut.cpp
│ │ │ │ │ ├── 7zHeader.cpp
│ │ │ │ │ ├── 7zHeader.h
│ │ │ │ │ ├── 7zIn.cpp
│ │ │ │ │ ├── 7zIn.h
│ │ │ │ │ ├── 7zItem.h
│ │ │ │ │ ├── 7zOut.cpp
│ │ │ │ │ ├── 7zOut.h
│ │ │ │ │ ├── 7zProperties.cpp
│ │ │ │ │ ├── 7zProperties.h
│ │ │ │ │ ├── 7zRegister.cpp
│ │ │ │ │ ├── 7zSpecStream.h
│ │ │ │ │ ├── 7zUpdate.cpp
│ │ │ │ │ ├── 7zUpdate.h
│ │ │ │ │ └── StdAfx.h
│ │ │ │ ├── ApfsHandler.cpp
│ │ │ │ ├── ApmHandler.cpp
│ │ │ │ ├── ArHandler.cpp
│ │ │ │ ├── Archive2.def
│ │ │ │ ├── ArchiveExports.cpp
│ │ │ │ ├── ArjHandler.cpp
│ │ │ │ ├── AvbHandler.cpp
│ │ │ │ ├── Base64Handler.cpp
│ │ │ │ ├── Bz2Handler.cpp
│ │ │ │ ├── Cab/
│ │ │ │ │ ├── CabBlockInStream.cpp
│ │ │ │ │ ├── CabBlockInStream.h
│ │ │ │ │ ├── CabHandler.cpp
│ │ │ │ │ ├── CabHandler.h
│ │ │ │ │ ├── CabHeader.cpp
│ │ │ │ │ ├── CabHeader.h
│ │ │ │ │ ├── CabIn.cpp
│ │ │ │ │ ├── CabIn.h
│ │ │ │ │ ├── CabItem.h
│ │ │ │ │ ├── CabRegister.cpp
│ │ │ │ │ └── StdAfx.h
│ │ │ │ ├── Chm/
│ │ │ │ │ ├── ChmHandler.cpp
│ │ │ │ │ ├── ChmHandler.h
│ │ │ │ │ ├── ChmIn.cpp
│ │ │ │ │ ├── ChmIn.h
│ │ │ │ │ └── StdAfx.h
│ │ │ │ ├── ComHandler.cpp
│ │ │ │ ├── Common/
│ │ │ │ │ ├── CoderMixer2.cpp
│ │ │ │ │ ├── CoderMixer2.h
│ │ │ │ │ ├── DummyOutStream.cpp
│ │ │ │ │ ├── DummyOutStream.h
│ │ │ │ │ ├── FindSignature.cpp
│ │ │ │ │ ├── FindSignature.h
│ │ │ │ │ ├── HandlerOut.cpp
│ │ │ │ │ ├── HandlerOut.h
│ │ │ │ │ ├── InStreamWithCRC.cpp
│ │ │ │ │ ├── InStreamWithCRC.h
│ │ │ │ │ ├── ItemNameUtils.cpp
│ │ │ │ │ ├── ItemNameUtils.h
│ │ │ │ │ ├── MultiStream.cpp
│ │ │ │ │ ├── MultiStream.h
│ │ │ │ │ ├── OutStreamWithCRC.cpp
│ │ │ │ │ ├── OutStreamWithCRC.h
│ │ │ │ │ ├── OutStreamWithSha1.cpp
│ │ │ │ │ ├── OutStreamWithSha1.h
│ │ │ │ │ ├── ParseProperties.h
│ │ │ │ │ └── StdAfx.h
│ │ │ │ ├── CpioHandler.cpp
│ │ │ │ ├── CramfsHandler.cpp
│ │ │ │ ├── DllExports2.cpp
│ │ │ │ ├── DmgHandler.cpp
│ │ │ │ ├── ElfHandler.cpp
│ │ │ │ ├── ExtHandler.cpp
│ │ │ │ ├── FatHandler.cpp
│ │ │ │ ├── FlvHandler.cpp
│ │ │ │ ├── GptHandler.cpp
│ │ │ │ ├── GzHandler.cpp
│ │ │ │ ├── HandlerCont.cpp
│ │ │ │ ├── HandlerCont.h
│ │ │ │ ├── HfsHandler.cpp
│ │ │ │ ├── HfsHandler.h
│ │ │ │ ├── IArchive.h
│ │ │ │ ├── IhexHandler.cpp
│ │ │ │ ├── Iso/
│ │ │ │ │ ├── IsoHandler.cpp
│ │ │ │ │ ├── IsoHandler.h
│ │ │ │ │ ├── IsoHeader.cpp
│ │ │ │ │ ├── IsoHeader.h
│ │ │ │ │ ├── IsoIn.cpp
│ │ │ │ │ ├── IsoIn.h
│ │ │ │ │ ├── IsoItem.h
│ │ │ │ │ ├── IsoRegister.cpp
│ │ │ │ │ └── StdAfx.h
│ │ │ │ ├── LpHandler.cpp
│ │ │ │ ├── LvmHandler.cpp
│ │ │ │ ├── LzhHandler.cpp
│ │ │ │ ├── LzmaHandler.cpp
│ │ │ │ ├── MachoHandler.cpp
│ │ │ │ ├── MbrHandler.cpp
│ │ │ │ ├── MslzHandler.cpp
│ │ │ │ ├── MubHandler.cpp
│ │ │ │ ├── Nsis/
│ │ │ │ │ ├── NsisDecode.cpp
│ │ │ │ │ ├── NsisDecode.h
│ │ │ │ │ ├── NsisHandler.cpp
│ │ │ │ │ ├── NsisHandler.h
│ │ │ │ │ ├── NsisIn.cpp
│ │ │ │ │ ├── NsisIn.h
│ │ │ │ │ ├── NsisRegister.cpp
│ │ │ │ │ └── StdAfx.h
│ │ │ │ ├── NtfsHandler.cpp
│ │ │ │ ├── PeHandler.cpp
│ │ │ │ ├── PpmdHandler.cpp
│ │ │ │ ├── QcowHandler.cpp
│ │ │ │ ├── Rar/
│ │ │ │ │ ├── Rar5Handler.cpp
│ │ │ │ │ ├── Rar5Handler.h
│ │ │ │ │ ├── RarHandler.cpp
│ │ │ │ │ ├── RarHandler.h
│ │ │ │ │ ├── RarHeader.h
│ │ │ │ │ ├── RarItem.h
│ │ │ │ │ ├── RarVol.h
│ │ │ │ │ └── StdAfx.h
│ │ │ │ ├── RpmHandler.cpp
│ │ │ │ ├── SparseHandler.cpp
│ │ │ │ ├── SplitHandler.cpp
│ │ │ │ ├── SquashfsHandler.cpp
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── SwfHandler.cpp
│ │ │ │ ├── Tar/
│ │ │ │ │ ├── StdAfx.h
│ │ │ │ │ ├── TarHandler.cpp
│ │ │ │ │ ├── TarHandler.h
│ │ │ │ │ ├── TarHandlerOut.cpp
│ │ │ │ │ ├── TarHeader.cpp
│ │ │ │ │ ├── TarHeader.h
│ │ │ │ │ ├── TarIn.cpp
│ │ │ │ │ ├── TarIn.h
│ │ │ │ │ ├── TarItem.h
│ │ │ │ │ ├── TarOut.cpp
│ │ │ │ │ ├── TarOut.h
│ │ │ │ │ ├── TarRegister.cpp
│ │ │ │ │ ├── TarUpdate.cpp
│ │ │ │ │ └── TarUpdate.h
│ │ │ │ ├── Udf/
│ │ │ │ │ ├── StdAfx.h
│ │ │ │ │ ├── UdfHandler.cpp
│ │ │ │ │ ├── UdfHandler.h
│ │ │ │ │ ├── UdfIn.cpp
│ │ │ │ │ └── UdfIn.h
│ │ │ │ ├── UefiHandler.cpp
│ │ │ │ ├── VdiHandler.cpp
│ │ │ │ ├── VhdHandler.cpp
│ │ │ │ ├── VhdxHandler.cpp
│ │ │ │ ├── VmdkHandler.cpp
│ │ │ │ ├── Wim/
│ │ │ │ │ ├── StdAfx.h
│ │ │ │ │ ├── WimHandler.cpp
│ │ │ │ │ ├── WimHandler.h
│ │ │ │ │ ├── WimHandlerOut.cpp
│ │ │ │ │ ├── WimIn.cpp
│ │ │ │ │ ├── WimIn.h
│ │ │ │ │ └── WimRegister.cpp
│ │ │ │ ├── XarHandler.cpp
│ │ │ │ ├── XzHandler.cpp
│ │ │ │ ├── XzHandler.h
│ │ │ │ ├── ZHandler.cpp
│ │ │ │ └── Zip/
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── ZipAddCommon.cpp
│ │ │ │ ├── ZipAddCommon.h
│ │ │ │ ├── ZipCompressionMode.h
│ │ │ │ ├── ZipHandler.cpp
│ │ │ │ ├── ZipHandler.h
│ │ │ │ ├── ZipHandlerOut.cpp
│ │ │ │ ├── ZipHeader.h
│ │ │ │ ├── ZipIn.cpp
│ │ │ │ ├── ZipIn.h
│ │ │ │ ├── ZipItem.cpp
│ │ │ │ ├── ZipItem.h
│ │ │ │ ├── ZipOut.cpp
│ │ │ │ ├── ZipOut.h
│ │ │ │ ├── ZipRegister.cpp
│ │ │ │ ├── ZipUpdate.cpp
│ │ │ │ └── ZipUpdate.h
│ │ │ ├── Bundles/
│ │ │ │ ├── SFXCon/
│ │ │ │ │ ├── SfxCon.cpp
│ │ │ │ │ ├── StdAfx.h
│ │ │ │ │ └── resource.rc
│ │ │ │ ├── SFXSetup/
│ │ │ │ │ ├── ExtractCallbackSfx.cpp
│ │ │ │ │ ├── ExtractCallbackSfx.h
│ │ │ │ │ ├── ExtractEngine.cpp
│ │ │ │ │ ├── ExtractEngine.h
│ │ │ │ │ ├── SfxSetup.cpp
│ │ │ │ │ ├── StdAfx.h
│ │ │ │ │ ├── resource.h
│ │ │ │ │ └── resource.rc
│ │ │ │ └── SFXWin/
│ │ │ │ ├── SfxWin.cpp
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── resource.h
│ │ │ │ └── resource.rc
│ │ │ ├── Common/
│ │ │ │ ├── CWrappers.cpp
│ │ │ │ ├── CWrappers.h
│ │ │ │ ├── CreateCoder.cpp
│ │ │ │ ├── CreateCoder.h
│ │ │ │ ├── FilePathAutoRename.cpp
│ │ │ │ ├── FilePathAutoRename.h
│ │ │ │ ├── FileStreams.cpp
│ │ │ │ ├── FileStreams.h
│ │ │ │ ├── FilterCoder.cpp
│ │ │ │ ├── FilterCoder.h
│ │ │ │ ├── InBuffer.cpp
│ │ │ │ ├── InBuffer.h
│ │ │ │ ├── InOutTempBuffer.cpp
│ │ │ │ ├── InOutTempBuffer.h
│ │ │ │ ├── LimitedStreams.cpp
│ │ │ │ ├── LimitedStreams.h
│ │ │ │ ├── LockedStream.h
│ │ │ │ ├── MemBlocks.cpp
│ │ │ │ ├── MemBlocks.h
│ │ │ │ ├── MethodId.h
│ │ │ │ ├── MethodProps.cpp
│ │ │ │ ├── MethodProps.h
│ │ │ │ ├── OffsetStream.cpp
│ │ │ │ ├── OffsetStream.h
│ │ │ │ ├── OutBuffer.cpp
│ │ │ │ ├── OutBuffer.h
│ │ │ │ ├── OutMemStream.cpp
│ │ │ │ ├── OutMemStream.h
│ │ │ │ ├── ProgressMt.cpp
│ │ │ │ ├── ProgressMt.h
│ │ │ │ ├── ProgressUtils.cpp
│ │ │ │ ├── ProgressUtils.h
│ │ │ │ ├── PropId.cpp
│ │ │ │ ├── RegisterArc.h
│ │ │ │ ├── RegisterCodec.h
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── StreamBinder.cpp
│ │ │ │ ├── StreamBinder.h
│ │ │ │ ├── StreamObjects.cpp
│ │ │ │ ├── StreamObjects.h
│ │ │ │ ├── StreamUtils.cpp
│ │ │ │ ├── StreamUtils.h
│ │ │ │ ├── UniqBlocks.cpp
│ │ │ │ ├── UniqBlocks.h
│ │ │ │ ├── VirtThread.cpp
│ │ │ │ └── VirtThread.h
│ │ │ ├── Compress/
│ │ │ │ ├── BZip2Const.h
│ │ │ │ ├── BZip2Crc.cpp
│ │ │ │ ├── BZip2Crc.h
│ │ │ │ ├── BZip2Decoder.cpp
│ │ │ │ ├── BZip2Decoder.h
│ │ │ │ ├── BZip2Encoder.cpp
│ │ │ │ ├── BZip2Encoder.h
│ │ │ │ ├── BZip2Register.cpp
│ │ │ │ ├── Bcj2Coder.cpp
│ │ │ │ ├── Bcj2Coder.h
│ │ │ │ ├── Bcj2Register.cpp
│ │ │ │ ├── BcjCoder.cpp
│ │ │ │ ├── BcjCoder.h
│ │ │ │ ├── BcjRegister.cpp
│ │ │ │ ├── BitlDecoder.cpp
│ │ │ │ ├── BitlDecoder.h
│ │ │ │ ├── BitlEncoder.h
│ │ │ │ ├── BitmDecoder.h
│ │ │ │ ├── BitmEncoder.h
│ │ │ │ ├── BranchMisc.cpp
│ │ │ │ ├── BranchMisc.h
│ │ │ │ ├── BranchRegister.cpp
│ │ │ │ ├── ByteSwap.cpp
│ │ │ │ ├── CodecExports.cpp
│ │ │ │ ├── CopyCoder.cpp
│ │ │ │ ├── CopyCoder.h
│ │ │ │ ├── CopyRegister.cpp
│ │ │ │ ├── Deflate64Register.cpp
│ │ │ │ ├── DeflateConst.h
│ │ │ │ ├── DeflateDecoder.cpp
│ │ │ │ ├── DeflateDecoder.h
│ │ │ │ ├── DeflateEncoder.cpp
│ │ │ │ ├── DeflateEncoder.h
│ │ │ │ ├── DeflateRegister.cpp
│ │ │ │ ├── DeltaFilter.cpp
│ │ │ │ ├── HuffmanDecoder.h
│ │ │ │ ├── ImplodeDecoder.cpp
│ │ │ │ ├── ImplodeDecoder.h
│ │ │ │ ├── LzOutWindow.cpp
│ │ │ │ ├── LzOutWindow.h
│ │ │ │ ├── LzfseDecoder.cpp
│ │ │ │ ├── LzfseDecoder.h
│ │ │ │ ├── LzhDecoder.cpp
│ │ │ │ ├── LzhDecoder.h
│ │ │ │ ├── Lzma2Decoder.cpp
│ │ │ │ ├── Lzma2Decoder.h
│ │ │ │ ├── Lzma2Encoder.cpp
│ │ │ │ ├── Lzma2Encoder.h
│ │ │ │ ├── Lzma2Register.cpp
│ │ │ │ ├── LzmaDecoder.cpp
│ │ │ │ ├── LzmaDecoder.h
│ │ │ │ ├── LzmaEncoder.cpp
│ │ │ │ ├── LzmaEncoder.h
│ │ │ │ ├── LzmaRegister.cpp
│ │ │ │ ├── LzmsDecoder.cpp
│ │ │ │ ├── LzmsDecoder.h
│ │ │ │ ├── Lzx.h
│ │ │ │ ├── LzxDecoder.cpp
│ │ │ │ ├── LzxDecoder.h
│ │ │ │ ├── Mtf8.h
│ │ │ │ ├── PpmdDecoder.cpp
│ │ │ │ ├── PpmdDecoder.h
│ │ │ │ ├── PpmdEncoder.cpp
│ │ │ │ ├── PpmdEncoder.h
│ │ │ │ ├── PpmdRegister.cpp
│ │ │ │ ├── PpmdZip.cpp
│ │ │ │ ├── PpmdZip.h
│ │ │ │ ├── QuantumDecoder.cpp
│ │ │ │ ├── QuantumDecoder.h
│ │ │ │ ├── Rar1Decoder.cpp
│ │ │ │ ├── Rar1Decoder.h
│ │ │ │ ├── Rar2Decoder.cpp
│ │ │ │ ├── Rar2Decoder.h
│ │ │ │ ├── Rar3Decoder.cpp
│ │ │ │ ├── Rar3Decoder.h
│ │ │ │ ├── Rar3Vm.cpp
│ │ │ │ ├── Rar3Vm.h
│ │ │ │ ├── Rar5Decoder.cpp
│ │ │ │ ├── Rar5Decoder.h
│ │ │ │ ├── RarCodecsRegister.cpp
│ │ │ │ ├── ShrinkDecoder.cpp
│ │ │ │ ├── ShrinkDecoder.h
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── XpressDecoder.cpp
│ │ │ │ ├── XpressDecoder.h
│ │ │ │ ├── XzDecoder.cpp
│ │ │ │ ├── XzDecoder.h
│ │ │ │ ├── XzEncoder.cpp
│ │ │ │ ├── XzEncoder.h
│ │ │ │ ├── ZDecoder.cpp
│ │ │ │ ├── ZDecoder.h
│ │ │ │ ├── ZlibDecoder.cpp
│ │ │ │ ├── ZlibDecoder.h
│ │ │ │ ├── ZlibEncoder.cpp
│ │ │ │ └── ZlibEncoder.h
│ │ │ ├── Crypto/
│ │ │ │ ├── 7zAes.cpp
│ │ │ │ ├── 7zAes.h
│ │ │ │ ├── 7zAesRegister.cpp
│ │ │ │ ├── HmacSha1.cpp
│ │ │ │ ├── HmacSha1.h
│ │ │ │ ├── HmacSha256.cpp
│ │ │ │ ├── HmacSha256.h
│ │ │ │ ├── MyAes.cpp
│ │ │ │ ├── MyAes.h
│ │ │ │ ├── MyAesReg.cpp
│ │ │ │ ├── Pbkdf2HmacSha1.cpp
│ │ │ │ ├── Pbkdf2HmacSha1.h
│ │ │ │ ├── RandGen.cpp
│ │ │ │ ├── RandGen.h
│ │ │ │ ├── Rar20Crypto.cpp
│ │ │ │ ├── Rar20Crypto.h
│ │ │ │ ├── Rar5Aes.cpp
│ │ │ │ ├── Rar5Aes.h
│ │ │ │ ├── RarAes.cpp
│ │ │ │ ├── RarAes.h
│ │ │ │ ├── Sha1Cls.h
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── WzAes.cpp
│ │ │ │ ├── WzAes.h
│ │ │ │ ├── ZipCrypto.cpp
│ │ │ │ ├── ZipCrypto.h
│ │ │ │ ├── ZipStrong.cpp
│ │ │ │ └── ZipStrong.h
│ │ │ ├── GuiCommon.rc
│ │ │ ├── Guid.txt
│ │ │ ├── ICoder.h
│ │ │ ├── IDecl.h
│ │ │ ├── IPassword.h
│ │ │ ├── IProgress.h
│ │ │ ├── IStream.h
│ │ │ ├── MyVersion.h
│ │ │ ├── PropID.h
│ │ │ └── UI/
│ │ │ ├── Common/
│ │ │ │ ├── ArchiveCommandLine.h
│ │ │ │ ├── ArchiveExtractCallback.cpp
│ │ │ │ ├── ArchiveExtractCallback.h
│ │ │ │ ├── ArchiveOpenCallback.cpp
│ │ │ │ ├── ArchiveOpenCallback.h
│ │ │ │ ├── DefaultName.cpp
│ │ │ │ ├── DefaultName.h
│ │ │ │ ├── DirItem.h
│ │ │ │ ├── EnumDirItems.h
│ │ │ │ ├── ExitCode.h
│ │ │ │ ├── Extract.cpp
│ │ │ │ ├── Extract.h
│ │ │ │ ├── ExtractMode.h
│ │ │ │ ├── ExtractingFilePath.cpp
│ │ │ │ ├── ExtractingFilePath.h
│ │ │ │ ├── HashCalc.h
│ │ │ │ ├── IFileExtractCallback.h
│ │ │ │ ├── LoadCodecs.cpp
│ │ │ │ ├── LoadCodecs.h
│ │ │ │ ├── OpenArchive.cpp
│ │ │ │ ├── OpenArchive.h
│ │ │ │ ├── PropIDUtils.cpp
│ │ │ │ ├── PropIDUtils.h
│ │ │ │ ├── Property.h
│ │ │ │ ├── SetProperties.h
│ │ │ │ ├── SortUtils.cpp
│ │ │ │ ├── SortUtils.h
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── Update.h
│ │ │ │ ├── UpdateAction.h
│ │ │ │ ├── UpdateCallback.h
│ │ │ │ ├── UpdatePair.h
│ │ │ │ ├── UpdateProduce.h
│ │ │ │ └── ZipRegistry.h
│ │ │ ├── Console/
│ │ │ │ ├── ConsoleClose.cpp
│ │ │ │ ├── ConsoleClose.h
│ │ │ │ ├── ExtractCallbackConsole.cpp
│ │ │ │ ├── ExtractCallbackConsole.h
│ │ │ │ ├── List.cpp
│ │ │ │ ├── List.h
│ │ │ │ ├── MainAr.cpp
│ │ │ │ ├── OpenCallbackConsole.cpp
│ │ │ │ ├── OpenCallbackConsole.h
│ │ │ │ ├── PercentPrinter.cpp
│ │ │ │ ├── PercentPrinter.h
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── UserInputUtils.cpp
│ │ │ │ └── UserInputUtils.h
│ │ │ ├── Explorer/
│ │ │ │ ├── MyMessages.cpp
│ │ │ │ ├── MyMessages.h
│ │ │ │ └── StdAfx.h
│ │ │ ├── FileManager/
│ │ │ │ ├── BrowseDialog.cpp
│ │ │ │ ├── BrowseDialog.h
│ │ │ │ ├── BrowseDialog.rc
│ │ │ │ ├── BrowseDialogRes.h
│ │ │ │ ├── ComboDialog.cpp
│ │ │ │ ├── ComboDialog.h
│ │ │ │ ├── ComboDialog.rc
│ │ │ │ ├── ComboDialogRes.h
│ │ │ │ ├── DialogSize.h
│ │ │ │ ├── ExtractCallback.cpp
│ │ │ │ ├── ExtractCallback.h
│ │ │ │ ├── FormatUtils.cpp
│ │ │ │ ├── FormatUtils.h
│ │ │ │ ├── LangUtils.cpp
│ │ │ │ ├── LangUtils.h
│ │ │ │ ├── MemDialog.h
│ │ │ │ ├── MemDialogRes.h
│ │ │ │ ├── MyWindowsNew.h
│ │ │ │ ├── OverwriteDialog.cpp
│ │ │ │ ├── OverwriteDialog.h
│ │ │ │ ├── OverwriteDialog.rc
│ │ │ │ ├── OverwriteDialogRes.h
│ │ │ │ ├── PasswordDialog.cpp
│ │ │ │ ├── PasswordDialog.h
│ │ │ │ ├── PasswordDialog.rc
│ │ │ │ ├── PasswordDialogRes.h
│ │ │ │ ├── ProgressDialog.cpp
│ │ │ │ ├── ProgressDialog.h
│ │ │ │ ├── ProgressDialog.rc
│ │ │ │ ├── ProgressDialog2.cpp
│ │ │ │ ├── ProgressDialog2.h
│ │ │ │ ├── ProgressDialog2.rc
│ │ │ │ ├── ProgressDialog2Res.h
│ │ │ │ ├── ProgressDialog2a.rc
│ │ │ │ ├── ProgressDialogRes.h
│ │ │ │ ├── PropertyName.cpp
│ │ │ │ ├── PropertyName.h
│ │ │ │ ├── PropertyNameRes.h
│ │ │ │ ├── RegistryUtils.cpp
│ │ │ │ ├── RegistryUtils.h
│ │ │ │ ├── StdAfx.h
│ │ │ │ ├── SysIconUtils.cpp
│ │ │ │ ├── SysIconUtils.h
│ │ │ │ ├── resource.h
│ │ │ │ └── resourceGui.h
│ │ │ └── GUI/
│ │ │ ├── ExtractDialog.cpp
│ │ │ ├── ExtractDialog.h
│ │ │ ├── ExtractDialog.rc
│ │ │ ├── ExtractDialogRes.h
│ │ │ ├── ExtractGUI.cpp
│ │ │ ├── ExtractGUI.h
│ │ │ ├── ExtractRes.h
│ │ │ ├── HashGUI.h
│ │ │ ├── StdAfx.h
│ │ │ └── resource2.h
│ │ ├── Common/
│ │ │ ├── AutoPtr.h
│ │ │ ├── CRC.cpp
│ │ │ ├── ComTry.h
│ │ │ ├── CommandLineParser.cpp
│ │ │ ├── CommandLineParser.h
│ │ │ ├── Common.h
│ │ │ ├── Common0.h
│ │ │ ├── CrcReg.cpp
│ │ │ ├── Defs.h
│ │ │ ├── DynLimBuf.cpp
│ │ │ ├── DynLimBuf.h
│ │ │ ├── DynamicBuffer.h
│ │ │ ├── IntToString.cpp
│ │ │ ├── IntToString.h
│ │ │ ├── Lang.cpp
│ │ │ ├── Lang.h
│ │ │ ├── ListFileUtils.cpp
│ │ │ ├── ListFileUtils.h
│ │ │ ├── LzFindPrepare.cpp
│ │ │ ├── MyBuffer.h
│ │ │ ├── MyBuffer2.h
│ │ │ ├── MyCom.h
│ │ │ ├── MyException.h
│ │ │ ├── MyInitGuid.h
│ │ │ ├── MyLinux.h
│ │ │ ├── MyMap.cpp
│ │ │ ├── MyMap.h
│ │ │ ├── MyString.cpp
│ │ │ ├── MyString.h
│ │ │ ├── MyTypes.h
│ │ │ ├── MyUnknown.h
│ │ │ ├── MyVector.h
│ │ │ ├── MyWindows.h
│ │ │ ├── MyXml.cpp
│ │ │ ├── MyXml.h
│ │ │ ├── NewHandler.cpp
│ │ │ ├── NewHandler.h
│ │ │ ├── StdAfx.h
│ │ │ ├── StdInStream.cpp
│ │ │ ├── StdInStream.h
│ │ │ ├── StdOutStream.cpp
│ │ │ ├── StdOutStream.h
│ │ │ ├── StringConvert.cpp
│ │ │ ├── StringConvert.h
│ │ │ ├── StringToInt.cpp
│ │ │ ├── StringToInt.h
│ │ │ ├── TextConfig.cpp
│ │ │ ├── TextConfig.h
│ │ │ ├── UTFConvert.cpp
│ │ │ ├── UTFConvert.h
│ │ │ ├── Wildcard.cpp
│ │ │ ├── Wildcard.h
│ │ │ ├── XzCrc64Init.cpp
│ │ │ └── XzCrc64Reg.cpp
│ │ └── Windows/
│ │ ├── COM.h
│ │ ├── Clipboard.cpp
│ │ ├── Clipboard.h
│ │ ├── CommonDialog.cpp
│ │ ├── CommonDialog.h
│ │ ├── Control/
│ │ │ ├── ComboBox.cpp
│ │ │ ├── ComboBox.h
│ │ │ ├── Dialog.cpp
│ │ │ ├── Dialog.h
│ │ │ ├── Edit.h
│ │ │ ├── ListView.cpp
│ │ │ ├── ListView.h
│ │ │ ├── ProgressBar.h
│ │ │ ├── Static.h
│ │ │ └── StdAfx.h
│ │ ├── DLL.cpp
│ │ ├── DLL.h
│ │ ├── Defs.h
│ │ ├── ErrorMsg.cpp
│ │ ├── ErrorMsg.h
│ │ ├── FileDir.cpp
│ │ ├── FileDir.h
│ │ ├── FileFind.cpp
│ │ ├── FileFind.h
│ │ ├── FileIO.cpp
│ │ ├── FileIO.h
│ │ ├── FileLink.cpp
│ │ ├── FileMapping.cpp
│ │ ├── FileMapping.h
│ │ ├── FileName.cpp
│ │ ├── FileName.h
│ │ ├── Handle.h
│ │ ├── MemoryGlobal.cpp
│ │ ├── MemoryGlobal.h
│ │ ├── MemoryLock.cpp
│ │ ├── MemoryLock.h
│ │ ├── NtCheck.h
│ │ ├── PropVariant.cpp
│ │ ├── PropVariant.h
│ │ ├── PropVariantConv.cpp
│ │ ├── PropVariantConv.h
│ │ ├── PropVariantUtils.cpp
│ │ ├── PropVariantUtils.h
│ │ ├── Registry.cpp
│ │ ├── Registry.h
│ │ ├── ResourceString.cpp
│ │ ├── ResourceString.h
│ │ ├── SecurityUtils.cpp
│ │ ├── SecurityUtils.h
│ │ ├── Shell.cpp
│ │ ├── Shell.h
│ │ ├── StdAfx.h
│ │ ├── Synchronization.cpp
│ │ ├── Synchronization.h
│ │ ├── System.cpp
│ │ ├── System.h
│ │ ├── Thread.h
│ │ ├── TimeUtils.cpp
│ │ ├── TimeUtils.h
│ │ ├── Window.cpp
│ │ └── Window.h
│ └── Wrappers/
│ ├── Sha1Wrapper.cpp
│ ├── Sha1Wrapper.h
│ ├── Sha256Wrapper.cpp
│ ├── Sha256Wrapper.h
│ ├── Sha512Wrapper.cpp
│ └── Sha512Wrapper.h
├── NanaZip.ExtensionPackage/
│ ├── NanaZip.ExtensionPackage.Installer.iss
│ └── NanaZip.ExtensionPackage.Installer.proj
├── NanaZip.MaintainerTools.slnx
├── NanaZip.MigrateLegacyStringResources/
│ ├── NanaZip.MigrateLegacyStringResources.csproj
│ ├── Program.cs
│ └── VSWhereHelper.cs
├── NanaZip.Modern/
│ ├── AboutPage.cpp
│ ├── AboutPage.h
│ ├── AboutPage.idl
│ ├── AboutPage.xaml
│ ├── AddressBar.cpp
│ ├── AddressBar.h
│ ├── AddressBar.idl
│ ├── AddressBarTemplate.cpp
│ ├── AddressBarTemplate.h
│ ├── AddressBarTemplate.idl
│ ├── AddressBarTemplate.xaml
│ ├── App.cpp
│ ├── App.h
│ ├── App.idl
│ ├── App.xaml
│ ├── ControlMacros.h
│ ├── CopyLocationPage.cpp
│ ├── CopyLocationPage.h
│ ├── CopyLocationPage.idl
│ ├── CopyLocationPage.xaml
│ ├── InformationPage.cpp
│ ├── InformationPage.h
│ ├── InformationPage.idl
│ ├── InformationPage.xaml
│ ├── MainWindowToolBarPage.cpp
│ ├── MainWindowToolBarPage.h
│ ├── MainWindowToolBarPage.idl
│ ├── MainWindowToolBarPage.xaml
│ ├── NanaZip.Modern.Wrapper.cpp
│ ├── NanaZip.Modern.cpp
│ ├── NanaZip.Modern.def
│ ├── NanaZip.Modern.h
│ ├── NanaZip.Modern.manifest
│ ├── NanaZip.Modern.props
│ ├── NanaZip.Modern.vcxproj
│ ├── NanaZip.Modern.vcxproj.filters
│ ├── ProgressPage.cpp
│ ├── ProgressPage.h
│ ├── ProgressPage.idl
│ ├── ProgressPage.xaml
│ ├── SponsorPage.cpp
│ ├── SponsorPage.h
│ ├── SponsorPage.idl
│ ├── SponsorPage.xaml
│ ├── StatusBar.cpp
│ ├── StatusBar.h
│ ├── StatusBar.idl
│ ├── StatusBarTemplate.cpp
│ ├── StatusBarTemplate.h
│ ├── StatusBarTemplate.idl
│ ├── StatusBarTemplate.xaml
│ ├── Strings/
│ │ ├── af/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ar/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── az-arab/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── be/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── bg/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── bn/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ca/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ca-es-valencia/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── cs/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── cy/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── da/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── de/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── el/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── en/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── eo/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── es/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── et/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── eu/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── fa/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── fi/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── fr/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── fy/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ga/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── gl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── gu/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── he/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── hi/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── hr/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── hu/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── hy/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── id/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── is/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── it/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ja/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ka/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── kk/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ko/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ku-arab/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ky-kg/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── lt/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── lv/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── mk/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── mn-cyrl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── mn-mong/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── mr/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ms/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── nb/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ne/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── nl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── nn/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── pa-in/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── pl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── ps/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── pt/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── pt-BR/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── ro/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ru/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── si/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── sk/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── sl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── sq/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ ├── sr-Latn/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── sr-cyrl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── sv/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── sw/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ta/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── tg-arab/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── th/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── tk-cyrl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── tr/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── tt-arab/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── ug-arab/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── uk/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── uz-cyrl/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── uz-latn/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── vi/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── yo-latn/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ └── ProgressPage.resw
│ │ ├── zh-Hans/
│ │ │ ├── Common.resw
│ │ │ ├── CopyLocationPage.resw
│ │ │ ├── MainWindowToolBarPage.resw
│ │ │ ├── ProgressPage.resw
│ │ │ └── SponsorPage.resw
│ │ └── zh-Hant/
│ │ ├── Common.resw
│ │ ├── CopyLocationPage.resw
│ │ └── ProgressPage.resw
│ ├── pch.cpp
│ └── pch.h
├── NanaZip.Project/
│ ├── NanaZip.Project.Version.props
│ ├── NanaZip.Project.props
│ └── ReadMe.md
├── NanaZip.ProjectAssetsGenerator/
│ ├── NanaZip.ProjectAssetsGenerator.csproj
│ └── Program.cs
├── NanaZip.RefreshPackageVersion/
│ ├── NanaZip.RefreshPackageVersion.csproj
│ └── Program.cs
├── NanaZip.Specification/
│ ├── NanaZip.Specification.SevenZip.h
│ └── NanaZip.Specification.props
├── NanaZip.UI.Classic/
│ ├── AboutDialog.cpp
│ ├── AboutDialog.h
│ ├── NanaZip.manifest
│ ├── NanaZip.vcxproj
│ ├── NanaZip.vcxproj.filters
│ └── SevenZip/
│ ├── .gitignore
│ ├── C/
│ │ ├── 7zTypes.h
│ │ ├── Alloc.c
│ │ ├── Alloc.h
│ │ ├── Compiler.h
│ │ ├── CpuArch.c
│ │ ├── CpuArch.h
│ │ ├── DllSecur.c
│ │ ├── DllSecur.h
│ │ ├── Precomp.h
│ │ ├── RotateDefs.h
│ │ ├── Sort.c
│ │ ├── Sort.h
│ │ ├── Threads.c
│ │ └── Threads.h
│ └── CPP/
│ ├── 7zip/
│ │ ├── Archive/
│ │ │ ├── Common/
│ │ │ │ ├── ItemNameUtils.cpp
│ │ │ │ ├── ItemNameUtils.h
│ │ │ │ └── StdAfx.h
│ │ │ └── IArchive.h
│ │ ├── Common/
│ │ │ ├── CreateCoder.cpp
│ │ │ ├── CreateCoder.h
│ │ │ ├── FilePathAutoRename.cpp
│ │ │ ├── FilePathAutoRename.h
│ │ │ ├── FileStreams.cpp
│ │ │ ├── FileStreams.h
│ │ │ ├── FilterCoder.cpp
│ │ │ ├── FilterCoder.h
│ │ │ ├── LimitedStreams.cpp
│ │ │ ├── LimitedStreams.h
│ │ │ ├── MethodId.h
│ │ │ ├── MethodProps.cpp
│ │ │ ├── MethodProps.h
│ │ │ ├── ProgressUtils.cpp
│ │ │ ├── ProgressUtils.h
│ │ │ ├── PropId.cpp
│ │ │ ├── RegisterArc.h
│ │ │ ├── RegisterCodec.h
│ │ │ ├── StdAfx.h
│ │ │ ├── StreamObjects.cpp
│ │ │ ├── StreamObjects.h
│ │ │ ├── StreamUtils.cpp
│ │ │ ├── StreamUtils.h
│ │ │ ├── UniqBlocks.cpp
│ │ │ └── UniqBlocks.h
│ │ ├── Compress/
│ │ │ ├── CopyCoder.cpp
│ │ │ ├── CopyCoder.h
│ │ │ └── StdAfx.h
│ │ ├── GuiCommon.rc
│ │ ├── Guid.txt
│ │ ├── ICoder.h
│ │ ├── IDecl.h
│ │ ├── IPassword.h
│ │ ├── IProgress.h
│ │ ├── IStream.h
│ │ ├── PropID.h
│ │ └── UI/
│ │ ├── Agent/
│ │ │ ├── Agent.cpp
│ │ │ ├── Agent.h
│ │ │ ├── AgentOut.cpp
│ │ │ ├── AgentProxy.cpp
│ │ │ ├── AgentProxy.h
│ │ │ ├── ArchiveFolder.cpp
│ │ │ ├── ArchiveFolderOpen.cpp
│ │ │ ├── ArchiveFolderOut.cpp
│ │ │ ├── IFolderArchive.h
│ │ │ ├── StdAfx.h
│ │ │ ├── UpdateCallbackAgent.cpp
│ │ │ └── UpdateCallbackAgent.h
│ │ ├── Common/
│ │ │ ├── ArchiveExtractCallback.cpp
│ │ │ ├── ArchiveExtractCallback.h
│ │ │ ├── ArchiveName.cpp
│ │ │ ├── ArchiveName.h
│ │ │ ├── ArchiveOpenCallback.cpp
│ │ │ ├── ArchiveOpenCallback.h
│ │ │ ├── CompressCall.cpp
│ │ │ ├── CompressCall.h
│ │ │ ├── DefaultName.cpp
│ │ │ ├── DefaultName.h
│ │ │ ├── DirItem.h
│ │ │ ├── EnumDirItems.cpp
│ │ │ ├── EnumDirItems.h
│ │ │ ├── ExitCode.h
│ │ │ ├── Extract.h
│ │ │ ├── ExtractMode.h
│ │ │ ├── ExtractingFilePath.cpp
│ │ │ ├── ExtractingFilePath.h
│ │ │ ├── HashCalc.cpp
│ │ │ ├── HashCalc.h
│ │ │ ├── IFileExtractCallback.h
│ │ │ ├── LoadCodecs.cpp
│ │ │ ├── LoadCodecs.h
│ │ │ ├── OpenArchive.cpp
│ │ │ ├── OpenArchive.h
│ │ │ ├── PropIDUtils.cpp
│ │ │ ├── PropIDUtils.h
│ │ │ ├── Property.h
│ │ │ ├── SetProperties.cpp
│ │ │ ├── SetProperties.h
│ │ │ ├── SortUtils.cpp
│ │ │ ├── SortUtils.h
│ │ │ ├── StdAfx.h
│ │ │ ├── Update.h
│ │ │ ├── UpdateAction.cpp
│ │ │ ├── UpdateAction.h
│ │ │ ├── UpdateCallback.cpp
│ │ │ ├── UpdateCallback.h
│ │ │ ├── UpdatePair.cpp
│ │ │ ├── UpdatePair.h
│ │ │ ├── UpdateProduce.cpp
│ │ │ ├── UpdateProduce.h
│ │ │ ├── WorkDir.cpp
│ │ │ ├── WorkDir.h
│ │ │ ├── ZipRegistry.cpp
│ │ │ └── ZipRegistry.h
│ │ ├── Explorer/
│ │ │ ├── ContextMenu.cpp
│ │ │ ├── ContextMenu.h
│ │ │ ├── ContextMenuFlags.h
│ │ │ ├── MyExplorerCommand.h
│ │ │ ├── MyMessages.h
│ │ │ ├── StdAfx.h
│ │ │ ├── resource.h
│ │ │ └── resource2.rc
│ │ ├── FileManager/
│ │ │ ├── AltStreamsFolder.cpp
│ │ │ ├── AltStreamsFolder.h
│ │ │ ├── App.cpp
│ │ │ ├── App.h
│ │ │ ├── AppState.h
│ │ │ ├── BrowseDialog.cpp
│ │ │ ├── BrowseDialog.h
│ │ │ ├── BrowseDialog.rc
│ │ │ ├── BrowseDialogRes.h
│ │ │ ├── ClassDefs.cpp
│ │ │ ├── ComboDialog.cpp
│ │ │ ├── ComboDialog.h
│ │ │ ├── ComboDialog.rc
│ │ │ ├── ComboDialogRes.h
│ │ │ ├── CopyDialog.cpp
│ │ │ ├── CopyDialog.h
│ │ │ ├── CopyDialog.rc
│ │ │ ├── CopyDialogRes.h
│ │ │ ├── DialogSize.h
│ │ │ ├── EditDialog.cpp
│ │ │ ├── EditDialog.h
│ │ │ ├── EditDialog.rc
│ │ │ ├── EditDialogRes.h
│ │ │ ├── EditPage.cpp
│ │ │ ├── EditPage.h
│ │ │ ├── EditPage.rc
│ │ │ ├── EditPage2.rc
│ │ │ ├── EditPageRes.h
│ │ │ ├── EnumFormatEtc.cpp
│ │ │ ├── EnumFormatEtc.h
│ │ │ ├── ExtractCallback.cpp
│ │ │ ├── ExtractCallback.h
│ │ │ ├── FM.cpp
│ │ │ ├── FSDrives.cpp
│ │ │ ├── FSDrives.h
│ │ │ ├── FSFolder.cpp
│ │ │ ├── FSFolder.h
│ │ │ ├── FSFolderCopy.cpp
│ │ │ ├── FileFolderPluginOpen.cpp
│ │ │ ├── FileFolderPluginOpen.h
│ │ │ ├── FilePlugins.cpp
│ │ │ ├── FilePlugins.h
│ │ │ ├── FoldersPage.cpp
│ │ │ ├── FoldersPage.h
│ │ │ ├── FoldersPage.rc
│ │ │ ├── FoldersPage2.rc
│ │ │ ├── FoldersPageRes.h
│ │ │ ├── FormatUtils.cpp
│ │ │ ├── FormatUtils.h
│ │ │ ├── IFolder.h
│ │ │ ├── LangUtils.cpp
│ │ │ ├── LangUtils.h
│ │ │ ├── LinkDialog.cpp
│ │ │ ├── LinkDialog.h
│ │ │ ├── LinkDialog.rc
│ │ │ ├── LinkDialogRes.h
│ │ │ ├── MenuPage.cpp
│ │ │ ├── MenuPage.h
│ │ │ ├── MenuPage.rc
│ │ │ ├── MenuPage2.rc
│ │ │ ├── MenuPageRes.h
│ │ │ ├── MessagesDialog.cpp
│ │ │ ├── MessagesDialog.h
│ │ │ ├── MessagesDialog.rc
│ │ │ ├── MessagesDialogRes.h
│ │ │ ├── MyCom2.h
│ │ │ ├── MyLoadMenu.cpp
│ │ │ ├── MyLoadMenu.h
│ │ │ ├── MyWindowsNew.h
│ │ │ ├── NetFolder.cpp
│ │ │ ├── NetFolder.h
│ │ │ ├── OpenCallback.cpp
│ │ │ ├── OpenCallback.h
│ │ │ ├── OptionsDialog.cpp
│ │ │ ├── OverwriteDialog.cpp
│ │ │ ├── OverwriteDialog.h
│ │ │ ├── OverwriteDialog.rc
│ │ │ ├── OverwriteDialogRes.h
│ │ │ ├── Panel.cpp
│ │ │ ├── Panel.h
│ │ │ ├── PanelCopy.cpp
│ │ │ ├── PanelCrc.cpp
│ │ │ ├── PanelDrag.cpp
│ │ │ ├── PanelFolderChange.cpp
│ │ │ ├── PanelItemOpen.cpp
│ │ │ ├── PanelItems.cpp
│ │ │ ├── PanelKey.cpp
│ │ │ ├── PanelListNotify.cpp
│ │ │ ├── PanelMenu.cpp
│ │ │ ├── PanelOperations.cpp
│ │ │ ├── PanelSelect.cpp
│ │ │ ├── PanelSort.cpp
│ │ │ ├── PanelSplitFile.cpp
│ │ │ ├── PasswordDialog.cpp
│ │ │ ├── PasswordDialog.h
│ │ │ ├── PasswordDialog.rc
│ │ │ ├── PasswordDialogRes.h
│ │ │ ├── PluginInterface.h
│ │ │ ├── PluginLoader.h
│ │ │ ├── ProgressDialog2.cpp
│ │ │ ├── ProgressDialog2.h
│ │ │ ├── ProgressDialog2.rc
│ │ │ ├── ProgressDialog2Res.h
│ │ │ ├── ProgressDialog2a.rc
│ │ │ ├── PropertyName.cpp
│ │ │ ├── PropertyName.h
│ │ │ ├── PropertyName.rc
│ │ │ ├── PropertyNameRes.h
│ │ │ ├── RegistryAssociations.cpp
│ │ │ ├── RegistryAssociations.h
│ │ │ ├── RegistryPlugins.cpp
│ │ │ ├── RegistryPlugins.h
│ │ │ ├── RegistryUtils.cpp
│ │ │ ├── RegistryUtils.h
│ │ │ ├── RootFolder.cpp
│ │ │ ├── RootFolder.h
│ │ │ ├── SettingsPage.cpp
│ │ │ ├── SettingsPage.h
│ │ │ ├── SettingsPage.rc
│ │ │ ├── SettingsPage2.rc
│ │ │ ├── SettingsPageRes.h
│ │ │ ├── SplitDialog.cpp
│ │ │ ├── SplitDialog.h
│ │ │ ├── SplitDialog.rc
│ │ │ ├── SplitDialogRes.h
│ │ │ ├── SplitUtils.cpp
│ │ │ ├── SplitUtils.h
│ │ │ ├── StdAfx.cpp
│ │ │ ├── StdAfx.h
│ │ │ ├── StringUtils.cpp
│ │ │ ├── StringUtils.h
│ │ │ ├── SysIconUtils.cpp
│ │ │ ├── SysIconUtils.h
│ │ │ ├── TextPairs.cpp
│ │ │ ├── TextPairs.h
│ │ │ ├── UpdateCallback100.cpp
│ │ │ ├── UpdateCallback100.h
│ │ │ ├── VerCtrl.cpp
│ │ │ ├── ViewSettings.cpp
│ │ │ ├── ViewSettings.h
│ │ │ ├── resource.h
│ │ │ ├── resource.rc
│ │ │ ├── resourceGui.h
│ │ │ └── resourceGui.rc
│ │ └── GUI/
│ │ ├── Extract.rc
│ │ ├── ExtractDialogRes.h
│ │ ├── ExtractRes.h
│ │ ├── HashGUI.cpp
│ │ ├── HashGUI.h
│ │ ├── StdAfx.h
│ │ ├── UpdateCallbackGUI.h
│ │ ├── UpdateCallbackGUI2.cpp
│ │ ├── UpdateCallbackGUI2.h
│ │ ├── resource2.h
│ │ ├── resource3.h
│ │ └── resource3.rc
│ ├── Common/
│ │ ├── AutoPtr.h
│ │ ├── ComTry.h
│ │ ├── Common.h
│ │ ├── Defs.h
│ │ ├── DynLimBuf.cpp
│ │ ├── DynLimBuf.h
│ │ ├── DynamicBuffer.h
│ │ ├── IntToString.cpp
│ │ ├── IntToString.h
│ │ ├── Lang.cpp
│ │ ├── Lang.h
│ │ ├── MyBuffer.h
│ │ ├── MyBuffer2.h
│ │ ├── MyCom.h
│ │ ├── MyException.h
│ │ ├── MyGuidDef.h
│ │ ├── MyInitGuid.h
│ │ ├── MyLinux.h
│ │ ├── MyString.cpp
│ │ ├── MyString.h
│ │ ├── MyTypes.h
│ │ ├── MyUnknown.h
│ │ ├── MyVector.h
│ │ ├── MyWindows.h
│ │ ├── NewHandler.cpp
│ │ ├── NewHandler.h
│ │ ├── Random.cpp
│ │ ├── Random.h
│ │ ├── StdAfx.h
│ │ ├── StringConvert.cpp
│ │ ├── StringConvert.h
│ │ ├── StringToInt.cpp
│ │ ├── StringToInt.h
│ │ ├── UTFConvert.cpp
│ │ ├── UTFConvert.h
│ │ ├── Wildcard.cpp
│ │ └── Wildcard.h
│ └── Windows/
│ ├── COM.h
│ ├── Clipboard.cpp
│ ├── Clipboard.h
│ ├── CommonDialog.cpp
│ ├── CommonDialog.h
│ ├── Control/
│ │ ├── ComboBox.cpp
│ │ ├── ComboBox.h
│ │ ├── CommandBar.h
│ │ ├── Dialog.cpp
│ │ ├── Dialog.h
│ │ ├── Edit.h
│ │ ├── ImageList.h
│ │ ├── ListView.cpp
│ │ ├── ListView.h
│ │ ├── ProgressBar.h
│ │ ├── PropertyPage.cpp
│ │ ├── PropertyPage.h
│ │ ├── ReBar.h
│ │ ├── Static.h
│ │ ├── StatusBar.h
│ │ ├── StdAfx.h
│ │ ├── ToolBar.h
│ │ ├── Window2.cpp
│ │ └── Window2.h
│ ├── DLL.cpp
│ ├── DLL.h
│ ├── Defs.h
│ ├── ErrorMsg.cpp
│ ├── ErrorMsg.h
│ ├── FileDir.cpp
│ ├── FileDir.h
│ ├── FileFind.cpp
│ ├── FileFind.h
│ ├── FileIO.cpp
│ ├── FileIO.h
│ ├── FileLink.cpp
│ ├── FileMapping.h
│ ├── FileName.cpp
│ ├── FileName.h
│ ├── FileSystem.cpp
│ ├── FileSystem.h
│ ├── Handle.h
│ ├── MemoryGlobal.cpp
│ ├── MemoryGlobal.h
│ ├── MemoryLock.cpp
│ ├── MemoryLock.h
│ ├── Menu.cpp
│ ├── Menu.h
│ ├── Net.cpp
│ ├── Net.h
│ ├── NtCheck.h
│ ├── ProcessUtils.cpp
│ ├── ProcessUtils.h
│ ├── PropVariant.cpp
│ ├── PropVariant.h
│ ├── PropVariantConv.cpp
│ ├── PropVariantConv.h
│ ├── Registry.cpp
│ ├── Registry.h
│ ├── ResourceString.cpp
│ ├── ResourceString.h
│ ├── SecurityUtils.cpp
│ ├── SecurityUtils.h
│ ├── Shell.cpp
│ ├── Shell.h
│ ├── StdAfx.h
│ ├── Synchronization.cpp
│ ├── Synchronization.h
│ ├── System.cpp
│ ├── System.h
│ ├── Thread.h
│ ├── TimeUtils.cpp
│ ├── TimeUtils.h
│ ├── Window.cpp
│ └── Window.h
├── NanaZip.UI.Modern/
│ ├── NanaZip.Modern.FileManager.manifest
│ ├── NanaZip.Modern.FileManager.vcxproj
│ ├── NanaZip.Modern.FileManager.vcxproj.filters
│ ├── NanaZip.ShellExtension.cpp
│ ├── NanaZip.ShellExtension.def
│ ├── NanaZip.ShellExtension.manifest
│ ├── NanaZip.ShellExtension.vcxproj
│ ├── NanaZip.ShellExtension.vcxproj.filters
│ ├── NanaZip.UI.cpp
│ ├── NanaZip.UI.h
│ └── SevenZip/
│ ├── .gitignore
│ ├── C/
│ │ ├── 7zTypes.h
│ │ ├── Alloc.c
│ │ ├── Alloc.h
│ │ ├── Compiler.h
│ │ ├── CpuArch.c
│ │ ├── CpuArch.h
│ │ ├── DllSecur.c
│ │ ├── DllSecur.h
│ │ ├── Precomp.h
│ │ ├── RotateDefs.h
│ │ ├── Sort.c
│ │ ├── Sort.h
│ │ ├── Threads.c
│ │ └── Threads.h
│ └── CPP/
│ ├── 7zip/
│ │ ├── Archive/
│ │ │ ├── Common/
│ │ │ │ ├── ItemNameUtils.cpp
│ │ │ │ ├── ItemNameUtils.h
│ │ │ │ └── StdAfx.h
│ │ │ └── IArchive.h
│ │ ├── Common/
│ │ │ ├── CreateCoder.cpp
│ │ │ ├── CreateCoder.h
│ │ │ ├── FilePathAutoRename.cpp
│ │ │ ├── FilePathAutoRename.h
│ │ │ ├── FileStreams.cpp
│ │ │ ├── FileStreams.h
│ │ │ ├── FilterCoder.cpp
│ │ │ ├── FilterCoder.h
│ │ │ ├── LimitedStreams.cpp
│ │ │ ├── LimitedStreams.h
│ │ │ ├── MethodId.h
│ │ │ ├── MethodProps.cpp
│ │ │ ├── MethodProps.h
│ │ │ ├── ProgressUtils.cpp
│ │ │ ├── ProgressUtils.h
│ │ │ ├── PropId.cpp
│ │ │ ├── RegisterArc.h
│ │ │ ├── RegisterCodec.h
│ │ │ ├── StdAfx.h
│ │ │ ├── StreamObjects.cpp
│ │ │ ├── StreamObjects.h
│ │ │ ├── StreamUtils.cpp
│ │ │ ├── StreamUtils.h
│ │ │ ├── UniqBlocks.cpp
│ │ │ └── UniqBlocks.h
│ │ ├── Compress/
│ │ │ ├── CopyCoder.cpp
│ │ │ ├── CopyCoder.h
│ │ │ └── StdAfx.h
│ │ ├── GuiCommon.rc
│ │ ├── Guid.txt
│ │ ├── ICoder.h
│ │ ├── IDecl.h
│ │ ├── IPassword.h
│ │ ├── IProgress.h
│ │ ├── IStream.h
│ │ ├── PropID.h
│ │ └── UI/
│ │ ├── Agent/
│ │ │ ├── Agent.cpp
│ │ │ ├── Agent.h
│ │ │ ├── AgentOut.cpp
│ │ │ ├── AgentProxy.cpp
│ │ │ ├── AgentProxy.h
│ │ │ ├── ArchiveFolder.cpp
│ │ │ ├── ArchiveFolderOpen.cpp
│ │ │ ├── ArchiveFolderOut.cpp
│ │ │ ├── IFolderArchive.h
│ │ │ ├── StdAfx.h
│ │ │ ├── UpdateCallbackAgent.cpp
│ │ │ └── UpdateCallbackAgent.h
│ │ ├── Common/
│ │ │ ├── ArchiveExtractCallback.cpp
│ │ │ ├── ArchiveExtractCallback.h
│ │ │ ├── ArchiveName.cpp
│ │ │ ├── ArchiveName.h
│ │ │ ├── ArchiveOpenCallback.cpp
│ │ │ ├── ArchiveOpenCallback.h
│ │ │ ├── CompressCall.cpp
│ │ │ ├── CompressCall.h
│ │ │ ├── DefaultName.cpp
│ │ │ ├── DefaultName.h
│ │ │ ├── DirItem.h
│ │ │ ├── EnumDirItems.cpp
│ │ │ ├── EnumDirItems.h
│ │ │ ├── ExitCode.h
│ │ │ ├── Extract.h
│ │ │ ├── ExtractMode.h
│ │ │ ├── ExtractingFilePath.cpp
│ │ │ ├── ExtractingFilePath.h
│ │ │ ├── HashCalc.cpp
│ │ │ ├── HashCalc.h
│ │ │ ├── IFileExtractCallback.h
│ │ │ ├── LoadCodecs.cpp
│ │ │ ├── LoadCodecs.h
│ │ │ ├── OpenArchive.cpp
│ │ │ ├── OpenArchive.h
│ │ │ ├── PropIDUtils.cpp
│ │ │ ├── PropIDUtils.h
│ │ │ ├── Property.h
│ │ │ ├── SetProperties.cpp
│ │ │ ├── SetProperties.h
│ │ │ ├── SortUtils.cpp
│ │ │ ├── SortUtils.h
│ │ │ ├── StdAfx.h
│ │ │ ├── Update.h
│ │ │ ├── UpdateAction.cpp
│ │ │ ├── UpdateAction.h
│ │ │ ├── UpdateCallback.cpp
│ │ │ ├── UpdateCallback.h
│ │ │ ├── UpdatePair.cpp
│ │ │ ├── UpdatePair.h
│ │ │ ├── UpdateProduce.cpp
│ │ │ ├── UpdateProduce.h
│ │ │ ├── WorkDir.cpp
│ │ │ ├── WorkDir.h
│ │ │ ├── ZipRegistry.cpp
│ │ │ └── ZipRegistry.h
│ │ ├── Explorer/
│ │ │ ├── ContextMenu.cpp
│ │ │ ├── ContextMenu.h
│ │ │ ├── ContextMenuFlags.h
│ │ │ ├── MyExplorerCommand.h
│ │ │ ├── MyMessages.cpp
│ │ │ ├── MyMessages.h
│ │ │ ├── StdAfx.cpp
│ │ │ ├── StdAfx.h
│ │ │ ├── resource.h
│ │ │ ├── resource.rc
│ │ │ └── resource2.rc
│ │ ├── FileManager/
│ │ │ ├── AltStreamsFolder.cpp
│ │ │ ├── AltStreamsFolder.h
│ │ │ ├── App.cpp
│ │ │ ├── App.h
│ │ │ ├── AppState.h
│ │ │ ├── BrowseDialog.cpp
│ │ │ ├── BrowseDialog.h
│ │ │ ├── BrowseDialog.rc
│ │ │ ├── BrowseDialogRes.h
│ │ │ ├── ClassDefs.cpp
│ │ │ ├── ComboDialog.cpp
│ │ │ ├── ComboDialog.h
│ │ │ ├── ComboDialog.rc
│ │ │ ├── ComboDialogRes.h
│ │ │ ├── CopyDialog.cpp
│ │ │ ├── CopyDialog.h
│ │ │ ├── CopyDialog.rc
│ │ │ ├── CopyDialogRes.h
│ │ │ ├── DialogSize.h
│ │ │ ├── EditDialog.cpp
│ │ │ ├── EditDialog.h
│ │ │ ├── EditDialog.rc
│ │ │ ├── EditDialogRes.h
│ │ │ ├── EditPage.cpp
│ │ │ ├── EditPage.h
│ │ │ ├── EditPage.rc
│ │ │ ├── EditPage2.rc
│ │ │ ├── EditPageRes.h
│ │ │ ├── EnumFormatEtc.cpp
│ │ │ ├── EnumFormatEtc.h
│ │ │ ├── ExtractCallback.cpp
│ │ │ ├── ExtractCallback.h
│ │ │ ├── FM.cpp
│ │ │ ├── FSDrives.cpp
│ │ │ ├── FSDrives.h
│ │ │ ├── FSFolder.cpp
│ │ │ ├── FSFolder.h
│ │ │ ├── FSFolderCopy.cpp
│ │ │ ├── FileFolderPluginOpen.cpp
│ │ │ ├── FileFolderPluginOpen.h
│ │ │ ├── FilePlugins.cpp
│ │ │ ├── FilePlugins.h
│ │ │ ├── FoldersPage.cpp
│ │ │ ├── FoldersPage.h
│ │ │ ├── FoldersPage.rc
│ │ │ ├── FoldersPage2.rc
│ │ │ ├── FoldersPageRes.h
│ │ │ ├── FormatUtils.cpp
│ │ │ ├── FormatUtils.h
│ │ │ ├── IFolder.h
│ │ │ ├── LangUtils.cpp
│ │ │ ├── LangUtils.h
│ │ │ ├── LinkDialog.cpp
│ │ │ ├── LinkDialog.h
│ │ │ ├── LinkDialog.rc
│ │ │ ├── LinkDialogRes.h
│ │ │ ├── MenuPage.cpp
│ │ │ ├── MenuPage.h
│ │ │ ├── MenuPage.rc
│ │ │ ├── MenuPage2.rc
│ │ │ ├── MenuPageRes.h
│ │ │ ├── MessagesDialog.cpp
│ │ │ ├── MessagesDialog.h
│ │ │ ├── MessagesDialog.rc
│ │ │ ├── MessagesDialogRes.h
│ │ │ ├── MyCom2.h
│ │ │ ├── MyLoadMenu.cpp
│ │ │ ├── MyLoadMenu.h
│ │ │ ├── MyWindowsNew.h
│ │ │ ├── NetFolder.cpp
│ │ │ ├── NetFolder.h
│ │ │ ├── OpenCallback.cpp
│ │ │ ├── OpenCallback.h
│ │ │ ├── OptionsDialog.cpp
│ │ │ ├── OverwriteDialog.cpp
│ │ │ ├── OverwriteDialog.h
│ │ │ ├── OverwriteDialog.rc
│ │ │ ├── OverwriteDialogRes.h
│ │ │ ├── Panel.cpp
│ │ │ ├── Panel.h
│ │ │ ├── PanelCopy.cpp
│ │ │ ├── PanelCrc.cpp
│ │ │ ├── PanelDrag.cpp
│ │ │ ├── PanelFolderChange.cpp
│ │ │ ├── PanelItemOpen.cpp
│ │ │ ├── PanelItems.cpp
│ │ │ ├── PanelKey.cpp
│ │ │ ├── PanelListNotify.cpp
│ │ │ ├── PanelMenu.cpp
│ │ │ ├── PanelOperations.cpp
│ │ │ ├── PanelSelect.cpp
│ │ │ ├── PanelSort.cpp
│ │ │ ├── PanelSplitFile.cpp
│ │ │ ├── PasswordDialog.cpp
│ │ │ ├── PasswordDialog.h
│ │ │ ├── PasswordDialog.rc
│ │ │ ├── PasswordDialogRes.h
│ │ │ ├── PluginInterface.h
│ │ │ ├── PluginLoader.h
│ │ │ ├── ProgressDialog2.cpp
│ │ │ ├── ProgressDialog2.h
│ │ │ ├── ProgressDialog2.rc
│ │ │ ├── ProgressDialog2Res.h
│ │ │ ├── ProgressDialog2a.rc
│ │ │ ├── PropertyName.cpp
│ │ │ ├── PropertyName.h
│ │ │ ├── PropertyName.rc
│ │ │ ├── PropertyNameRes.h
│ │ │ ├── RegistryAssociations.cpp
│ │ │ ├── RegistryAssociations.h
│ │ │ ├── RegistryPlugins.cpp
│ │ │ ├── RegistryPlugins.h
│ │ │ ├── RegistryUtils.cpp
│ │ │ ├── RegistryUtils.h
│ │ │ ├── RootFolder.cpp
│ │ │ ├── RootFolder.h
│ │ │ ├── SettingsPage.cpp
│ │ │ ├── SettingsPage.h
│ │ │ ├── SettingsPage.rc
│ │ │ ├── SettingsPage2.rc
│ │ │ ├── SettingsPageRes.h
│ │ │ ├── SplitDialog.cpp
│ │ │ ├── SplitDialog.h
│ │ │ ├── SplitDialog.rc
│ │ │ ├── SplitDialogRes.h
│ │ │ ├── SplitUtils.cpp
│ │ │ ├── SplitUtils.h
│ │ │ ├── StdAfx.cpp
│ │ │ ├── StdAfx.h
│ │ │ ├── StringUtils.cpp
│ │ │ ├── StringUtils.h
│ │ │ ├── SysIconUtils.cpp
│ │ │ ├── SysIconUtils.h
│ │ │ ├── TextPairs.cpp
│ │ │ ├── TextPairs.h
│ │ │ ├── UpdateCallback100.cpp
│ │ │ ├── UpdateCallback100.h
│ │ │ ├── VerCtrl.cpp
│ │ │ ├── ViewSettings.cpp
│ │ │ ├── ViewSettings.h
│ │ │ ├── resource.h
│ │ │ ├── resource.rc
│ │ │ ├── resourceGui.h
│ │ │ └── resourceGui.rc
│ │ └── GUI/
│ │ ├── Extract.rc
│ │ ├── ExtractDialogRes.h
│ │ ├── ExtractRes.h
│ │ ├── HashGUI.cpp
│ │ ├── HashGUI.h
│ │ ├── StdAfx.h
│ │ ├── UpdateCallbackGUI.h
│ │ ├── UpdateCallbackGUI2.cpp
│ │ ├── UpdateCallbackGUI2.h
│ │ ├── resource2.h
│ │ ├── resource3.h
│ │ └── resource3.rc
│ ├── Common/
│ │ ├── AutoPtr.h
│ │ ├── ComTry.h
│ │ ├── Common.h
│ │ ├── Defs.h
│ │ ├── DynLimBuf.cpp
│ │ ├── DynLimBuf.h
│ │ ├── DynamicBuffer.h
│ │ ├── IntToString.cpp
│ │ ├── IntToString.h
│ │ ├── Lang.cpp
│ │ ├── Lang.h
│ │ ├── MyBuffer.h
│ │ ├── MyBuffer2.h
│ │ ├── MyCom.h
│ │ ├── MyException.h
│ │ ├── MyGuidDef.h
│ │ ├── MyInitGuid.h
│ │ ├── MyLinux.h
│ │ ├── MyString.cpp
│ │ ├── MyString.h
│ │ ├── MyTypes.h
│ │ ├── MyUnknown.h
│ │ ├── MyVector.h
│ │ ├── MyWindows.h
│ │ ├── NewHandler.cpp
│ │ ├── NewHandler.h
│ │ ├── Random.cpp
│ │ ├── Random.h
│ │ ├── StdAfx.h
│ │ ├── StringConvert.cpp
│ │ ├── StringConvert.h
│ │ ├── StringToInt.cpp
│ │ ├── StringToInt.h
│ │ ├── UTFConvert.cpp
│ │ ├── UTFConvert.h
│ │ ├── Wildcard.cpp
│ │ └── Wildcard.h
│ └── Windows/
│ ├── COM.h
│ ├── Clipboard.cpp
│ ├── Clipboard.h
│ ├── CommonDialog.cpp
│ ├── CommonDialog.h
│ ├── Control/
│ │ ├── ComboBox.cpp
│ │ ├── ComboBox.h
│ │ ├── CommandBar.h
│ │ ├── Dialog.cpp
│ │ ├── Dialog.h
│ │ ├── Edit.h
│ │ ├── ImageList.h
│ │ ├── ListView.cpp
│ │ ├── ListView.h
│ │ ├── ProgressBar.h
│ │ ├── PropertyPage.cpp
│ │ ├── PropertyPage.h
│ │ ├── ReBar.h
│ │ ├── Static.h
│ │ ├── StatusBar.h
│ │ ├── StdAfx.h
│ │ ├── ToolBar.h
│ │ ├── Window2.cpp
│ │ └── Window2.h
│ ├── DLL.cpp
│ ├── DLL.h
│ ├── Defs.h
│ ├── ErrorMsg.cpp
│ ├── ErrorMsg.h
│ ├── FileDir.cpp
│ ├── FileDir.h
│ ├── FileFind.cpp
│ ├── FileFind.h
│ ├── FileIO.cpp
│ ├── FileIO.h
│ ├── FileLink.cpp
│ ├── FileMapping.h
│ ├── FileName.cpp
│ ├── FileName.h
│ ├── FileSystem.cpp
│ ├── FileSystem.h
│ ├── Handle.h
│ ├── MemoryGlobal.cpp
│ ├── MemoryGlobal.h
│ ├── MemoryLock.cpp
│ ├── MemoryLock.h
│ ├── Menu.cpp
│ ├── Menu.h
│ ├── Net.cpp
│ ├── Net.h
│ ├── NtCheck.h
│ ├── ProcessUtils.cpp
│ ├── ProcessUtils.h
│ ├── PropVariant.cpp
│ ├── PropVariant.h
│ ├── PropVariantConv.cpp
│ ├── PropVariantConv.h
│ ├── Registry.cpp
│ ├── Registry.h
│ ├── ResourceString.cpp
│ ├── ResourceString.h
│ ├── SecurityUtils.cpp
│ ├── SecurityUtils.h
│ ├── Shell.cpp
│ ├── Shell.h
│ ├── StdAfx.h
│ ├── Synchronization.cpp
│ ├── Synchronization.h
│ ├── System.cpp
│ ├── System.h
│ ├── Thread.h
│ ├── TimeUtils.cpp
│ ├── TimeUtils.h
│ ├── Window.cpp
│ └── Window.h
├── NanaZip.Universal/
│ ├── NanaZip.Universal.Console.manifest
│ ├── NanaZip.Universal.Console.vcxproj
│ ├── NanaZip.Universal.Console.vcxproj.filters
│ ├── NanaZip.Universal.Windows.manifest
│ ├── NanaZip.Universal.Windows.vcxproj
│ ├── NanaZip.Universal.Windows.vcxproj.filters
│ └── SevenZip/
│ ├── .gitignore
│ ├── C/
│ │ ├── 7zCrc.c
│ │ ├── 7zCrc.h
│ │ ├── 7zCrcOpt.c
│ │ ├── 7zTypes.h
│ │ ├── 7zVersion.h
│ │ ├── 7zWindows.h
│ │ ├── Alloc.c
│ │ ├── Alloc.h
│ │ ├── Compiler.h
│ │ ├── CpuArch.c
│ │ ├── CpuArch.h
│ │ ├── DllSecur.c
│ │ ├── DllSecur.h
│ │ ├── Precomp.h
│ │ ├── RotateDefs.h
│ │ ├── Sort.c
│ │ ├── Sort.h
│ │ ├── Threads.c
│ │ └── Threads.h
│ └── CPP/
│ ├── 7zip/
│ │ ├── Archive/
│ │ │ ├── Common/
│ │ │ │ ├── ItemNameUtils.cpp
│ │ │ │ ├── ItemNameUtils.h
│ │ │ │ ├── OutStreamWithCRC.cpp
│ │ │ │ ├── OutStreamWithCRC.h
│ │ │ │ └── StdAfx.h
│ │ │ └── IArchive.h
│ │ ├── Common/
│ │ │ ├── CreateCoder.cpp
│ │ │ ├── CreateCoder.h
│ │ │ ├── FilePathAutoRename.cpp
│ │ │ ├── FilePathAutoRename.h
│ │ │ ├── FileStreams.cpp
│ │ │ ├── FileStreams.h
│ │ │ ├── FilterCoder.cpp
│ │ │ ├── FilterCoder.h
│ │ │ ├── LimitedStreams.cpp
│ │ │ ├── LimitedStreams.h
│ │ │ ├── MethodId.h
│ │ │ ├── MethodProps.cpp
│ │ │ ├── MethodProps.h
│ │ │ ├── MultiOutStream.cpp
│ │ │ ├── MultiOutStream.h
│ │ │ ├── OutBuffer.h
│ │ │ ├── ProgressUtils.cpp
│ │ │ ├── ProgressUtils.h
│ │ │ ├── PropId.cpp
│ │ │ ├── RegisterArc.h
│ │ │ ├── RegisterCodec.h
│ │ │ ├── StdAfx.h
│ │ │ ├── StreamObjects.cpp
│ │ │ ├── StreamObjects.h
│ │ │ ├── StreamUtils.cpp
│ │ │ ├── StreamUtils.h
│ │ │ ├── UniqBlocks.cpp
│ │ │ └── UniqBlocks.h
│ │ ├── Compress/
│ │ │ ├── CopyCoder.cpp
│ │ │ ├── CopyCoder.h
│ │ │ └── StdAfx.h
│ │ ├── GuiCommon.rc
│ │ ├── ICoder.h
│ │ ├── IDecl.h
│ │ ├── IPassword.h
│ │ ├── IProgress.h
│ │ ├── IStream.h
│ │ ├── MyVersion.h
│ │ ├── PropID.h
│ │ └── UI/
│ │ ├── Agent/
│ │ │ └── IFolderArchive.h
│ │ ├── Common/
│ │ │ ├── ArchiveCommandLine.cpp
│ │ │ ├── ArchiveCommandLine.h
│ │ │ ├── ArchiveExtractCallback.cpp
│ │ │ ├── ArchiveExtractCallback.h
│ │ │ ├── ArchiveOpenCallback.cpp
│ │ │ ├── ArchiveOpenCallback.h
│ │ │ ├── Bench.cpp
│ │ │ ├── Bench.h
│ │ │ ├── DefaultName.cpp
│ │ │ ├── DefaultName.h
│ │ │ ├── DirItem.h
│ │ │ ├── EnumDirItems.cpp
│ │ │ ├── EnumDirItems.h
│ │ │ ├── ExitCode.h
│ │ │ ├── Extract.cpp
│ │ │ ├── Extract.h
│ │ │ ├── ExtractMode.h
│ │ │ ├── ExtractingFilePath.cpp
│ │ │ ├── ExtractingFilePath.h
│ │ │ ├── HashCalc.cpp
│ │ │ ├── HashCalc.h
│ │ │ ├── IFileExtractCallback.h
│ │ │ ├── LoadCodecs.cpp
│ │ │ ├── LoadCodecs.h
│ │ │ ├── OpenArchive.cpp
│ │ │ ├── OpenArchive.h
│ │ │ ├── PropIDUtils.cpp
│ │ │ ├── PropIDUtils.h
│ │ │ ├── Property.h
│ │ │ ├── SetProperties.cpp
│ │ │ ├── SetProperties.h
│ │ │ ├── SortUtils.cpp
│ │ │ ├── SortUtils.h
│ │ │ ├── StdAfx.h
│ │ │ ├── TempFiles.cpp
│ │ │ ├── TempFiles.h
│ │ │ ├── Update.cpp
│ │ │ ├── Update.h
│ │ │ ├── UpdateAction.cpp
│ │ │ ├── UpdateAction.h
│ │ │ ├── UpdateCallback.cpp
│ │ │ ├── UpdateCallback.h
│ │ │ ├── UpdatePair.cpp
│ │ │ ├── UpdatePair.h
│ │ │ ├── UpdateProduce.cpp
│ │ │ ├── UpdateProduce.h
│ │ │ ├── WorkDir.cpp
│ │ │ ├── WorkDir.h
│ │ │ ├── ZipRegistry.cpp
│ │ │ └── ZipRegistry.h
│ │ ├── Console/
│ │ │ ├── BenchCon.cpp
│ │ │ ├── BenchCon.h
│ │ │ ├── ConsoleClose.cpp
│ │ │ ├── ConsoleClose.h
│ │ │ ├── ExtractCallbackConsole.cpp
│ │ │ ├── ExtractCallbackConsole.h
│ │ │ ├── HashCon.cpp
│ │ │ ├── HashCon.h
│ │ │ ├── List.cpp
│ │ │ ├── List.h
│ │ │ ├── Main.cpp
│ │ │ ├── MainAr.cpp
│ │ │ ├── OpenCallbackConsole.cpp
│ │ │ ├── OpenCallbackConsole.h
│ │ │ ├── PercentPrinter.cpp
│ │ │ ├── PercentPrinter.h
│ │ │ ├── StdAfx.h
│ │ │ ├── UpdateCallbackConsole.cpp
│ │ │ ├── UpdateCallbackConsole.h
│ │ │ ├── UserInputUtils.cpp
│ │ │ └── UserInputUtils.h
│ │ ├── Explorer/
│ │ │ ├── MyMessages.cpp
│ │ │ ├── MyMessages.h
│ │ │ └── StdAfx.h
│ │ ├── FileManager/
│ │ │ ├── BrowseDialog.cpp
│ │ │ ├── BrowseDialog.h
│ │ │ ├── BrowseDialog.rc
│ │ │ ├── BrowseDialogRes.h
│ │ │ ├── ComboDialog.cpp
│ │ │ ├── ComboDialog.h
│ │ │ ├── ComboDialog.rc
│ │ │ ├── ComboDialogRes.h
│ │ │ ├── DialogSize.h
│ │ │ ├── EditDialog.cpp
│ │ │ ├── EditDialog.h
│ │ │ ├── EditDialog.rc
│ │ │ ├── EditDialogRes.h
│ │ │ ├── ExtractCallback.cpp
│ │ │ ├── ExtractCallback.h
│ │ │ ├── FormatUtils.cpp
│ │ │ ├── FormatUtils.h
│ │ │ ├── IFolder.h
│ │ │ ├── LangUtils.cpp
│ │ │ ├── LangUtils.h
│ │ │ ├── MemDialog.cpp
│ │ │ ├── MemDialog.h
│ │ │ ├── MemDialog.rc
│ │ │ ├── MemDialogRes.h
│ │ │ ├── MyWindowsNew.h
│ │ │ ├── OpenCallback.cpp
│ │ │ ├── OpenCallback.h
│ │ │ ├── OverwriteDialog.cpp
│ │ │ ├── OverwriteDialog.h
│ │ │ ├── OverwriteDialog.rc
│ │ │ ├── OverwriteDialogRes.h
│ │ │ ├── PasswordDialog.cpp
│ │ │ ├── PasswordDialog.h
│ │ │ ├── PasswordDialog.rc
│ │ │ ├── PasswordDialogRes.h
│ │ │ ├── ProgressDialog2.cpp
│ │ │ ├── ProgressDialog2.h
│ │ │ ├── ProgressDialog2.rc
│ │ │ ├── ProgressDialog2Res.h
│ │ │ ├── ProgressDialog2a.rc
│ │ │ ├── PropertyName.cpp
│ │ │ ├── PropertyName.h
│ │ │ ├── PropertyName.rc
│ │ │ ├── PropertyNameRes.h
│ │ │ ├── RegistryUtils.cpp
│ │ │ ├── RegistryUtils.h
│ │ │ ├── SplitUtils.cpp
│ │ │ ├── SplitUtils.h
│ │ │ ├── StdAfx.h
│ │ │ ├── StringUtils.cpp
│ │ │ ├── StringUtils.h
│ │ │ ├── SysIconUtils.cpp
│ │ │ ├── SysIconUtils.h
│ │ │ ├── resource.h
│ │ │ ├── resourceGui.h
│ │ │ └── resourceGui.rc
│ │ └── GUI/
│ │ ├── BenchmarkDialog.cpp
│ │ ├── BenchmarkDialog.h
│ │ ├── BenchmarkDialog.rc
│ │ ├── BenchmarkDialogRes.h
│ │ ├── CompressDialog.cpp
│ │ ├── CompressDialog.h
│ │ ├── CompressDialog.rc
│ │ ├── CompressDialogRes.h
│ │ ├── CompressOptionsDialog.rc
│ │ ├── Extract.rc
│ │ ├── ExtractDialog.cpp
│ │ ├── ExtractDialog.h
│ │ ├── ExtractDialog.rc
│ │ ├── ExtractDialogRes.h
│ │ ├── ExtractGUI.cpp
│ │ ├── ExtractGUI.h
│ │ ├── ExtractRes.h
│ │ ├── GUI.cpp
│ │ ├── HashGUI.cpp
│ │ ├── HashGUI.h
│ │ ├── StdAfx.h
│ │ ├── UpdateCallbackGUI.cpp
│ │ ├── UpdateCallbackGUI.h
│ │ ├── UpdateCallbackGUI2.cpp
│ │ ├── UpdateCallbackGUI2.h
│ │ ├── UpdateGUI.cpp
│ │ ├── UpdateGUI.h
│ │ ├── resource.rc
│ │ ├── resource2.h
│ │ ├── resource2.rc
│ │ ├── resource3.h
│ │ └── resource3.rc
│ ├── Common/
│ │ ├── CRC.cpp
│ │ ├── ComTry.h
│ │ ├── CommandLineParser.cpp
│ │ ├── CommandLineParser.h
│ │ ├── Common.h
│ │ ├── Common0.h
│ │ ├── Defs.h
│ │ ├── DynLimBuf.cpp
│ │ ├── DynLimBuf.h
│ │ ├── IntToString.cpp
│ │ ├── IntToString.h
│ │ ├── Lang.cpp
│ │ ├── Lang.h
│ │ ├── ListFileUtils.cpp
│ │ ├── ListFileUtils.h
│ │ ├── MyBuffer.h
│ │ ├── MyBuffer2.h
│ │ ├── MyCom.h
│ │ ├── MyException.h
│ │ ├── MyInitGuid.h
│ │ ├── MyLinux.h
│ │ ├── MyString.cpp
│ │ ├── MyString.h
│ │ ├── MyTypes.h
│ │ ├── MyUnknown.h
│ │ ├── MyVector.h
│ │ ├── MyWindows.h
│ │ ├── NewHandler.cpp
│ │ ├── NewHandler.h
│ │ ├── StdAfx.h
│ │ ├── StdInStream.cpp
│ │ ├── StdInStream.h
│ │ ├── StdOutStream.cpp
│ │ ├── StdOutStream.h
│ │ ├── StringConvert.cpp
│ │ ├── StringConvert.h
│ │ ├── StringToInt.cpp
│ │ ├── StringToInt.h
│ │ ├── UTFConvert.cpp
│ │ ├── UTFConvert.h
│ │ ├── Wildcard.cpp
│ │ └── Wildcard.h
│ └── Windows/
│ ├── COM.h
│ ├── Clipboard.cpp
│ ├── Clipboard.h
│ ├── CommonDialog.cpp
│ ├── CommonDialog.h
│ ├── Control/
│ │ ├── ComboBox.cpp
│ │ ├── ComboBox.h
│ │ ├── Dialog.cpp
│ │ ├── Dialog.h
│ │ ├── Edit.h
│ │ ├── ListView.cpp
│ │ ├── ListView.h
│ │ ├── ProgressBar.h
│ │ ├── Static.h
│ │ └── StdAfx.h
│ ├── DLL.cpp
│ ├── DLL.h
│ ├── Defs.h
│ ├── ErrorMsg.cpp
│ ├── ErrorMsg.h
│ ├── FileDir.cpp
│ ├── FileDir.h
│ ├── FileFind.cpp
│ ├── FileFind.h
│ ├── FileIO.cpp
│ ├── FileIO.h
│ ├── FileLink.cpp
│ ├── FileMapping.h
│ ├── FileName.cpp
│ ├── FileName.h
│ ├── FileSystem.cpp
│ ├── FileSystem.h
│ ├── Handle.h
│ ├── MemoryGlobal.cpp
│ ├── MemoryGlobal.h
│ ├── MemoryLock.cpp
│ ├── MemoryLock.h
│ ├── NtCheck.h
│ ├── PropVariant.cpp
│ ├── PropVariant.h
│ ├── PropVariantConv.cpp
│ ├── PropVariantConv.h
│ ├── Registry.cpp
│ ├── Registry.h
│ ├── ResourceString.cpp
│ ├── ResourceString.h
│ ├── SecurityUtils.h
│ ├── Shell.cpp
│ ├── Shell.h
│ ├── StdAfx.h
│ ├── Synchronization.cpp
│ ├── Synchronization.h
│ ├── System.cpp
│ ├── System.h
│ ├── SystemInfo.cpp
│ ├── SystemInfo.h
│ ├── Thread.h
│ ├── TimeUtils.cpp
│ ├── TimeUtils.h
│ ├── Window.cpp
│ └── Window.h
├── NanaZip.slnx
├── NanaZipPackage/
│ ├── NanaZipPackage.wapproj
│ ├── Package.appxmanifest
│ └── Strings/
│ ├── af/
│ │ └── Legacy.resw
│ ├── ar/
│ │ └── Legacy.resw
│ ├── az-arab/
│ │ └── Legacy.resw
│ ├── be/
│ │ └── Legacy.resw
│ ├── bg/
│ │ └── Legacy.resw
│ ├── bn/
│ │ └── Legacy.resw
│ ├── ca/
│ │ └── Legacy.resw
│ ├── ca-es-valencia/
│ │ └── Legacy.resw
│ ├── cs/
│ │ └── Legacy.resw
│ ├── cy/
│ │ └── Legacy.resw
│ ├── da/
│ │ └── Legacy.resw
│ ├── de/
│ │ └── Legacy.resw
│ ├── el/
│ │ └── Legacy.resw
│ ├── en/
│ │ └── Legacy.resw
│ ├── eo/
│ │ └── Legacy.resw
│ ├── es/
│ │ └── Legacy.resw
│ ├── et/
│ │ └── Legacy.resw
│ ├── eu/
│ │ └── Legacy.resw
│ ├── fa/
│ │ └── Legacy.resw
│ ├── fi/
│ │ └── Legacy.resw
│ ├── fr/
│ │ └── Legacy.resw
│ ├── fy/
│ │ └── Legacy.resw
│ ├── ga/
│ │ └── Legacy.resw
│ ├── gl/
│ │ └── Legacy.resw
│ ├── gu/
│ │ └── Legacy.resw
│ ├── he/
│ │ └── Legacy.resw
│ ├── hi/
│ │ └── Legacy.resw
│ ├── hr/
│ │ └── Legacy.resw
│ ├── hu/
│ │ └── Legacy.resw
│ ├── hy/
│ │ └── Legacy.resw
│ ├── id/
│ │ └── Legacy.resw
│ ├── is/
│ │ └── Legacy.resw
│ ├── it/
│ │ └── Legacy.resw
│ ├── ja/
│ │ └── Legacy.resw
│ ├── ka/
│ │ └── Legacy.resw
│ ├── kk/
│ │ └── Legacy.resw
│ ├── ko/
│ │ └── Legacy.resw
│ ├── ku-arab/
│ │ └── Legacy.resw
│ ├── ky-kg/
│ │ └── Legacy.resw
│ ├── lt/
│ │ └── Legacy.resw
│ ├── lv/
│ │ └── Legacy.resw
│ ├── mk/
│ │ └── Legacy.resw
│ ├── mn-cyrl/
│ │ └── Legacy.resw
│ ├── mn-mong/
│ │ └── Legacy.resw
│ ├── mr/
│ │ └── Legacy.resw
│ ├── ms/
│ │ └── Legacy.resw
│ ├── nb/
│ │ └── Legacy.resw
│ ├── ne/
│ │ └── Legacy.resw
│ ├── nl/
│ │ └── Legacy.resw
│ ├── nn/
│ │ └── Legacy.resw
│ ├── pa-in/
│ │ └── Legacy.resw
│ ├── pl/
│ │ └── Legacy.resw
│ ├── ps/
│ │ └── Legacy.resw
│ ├── pt/
│ │ └── Legacy.resw
│ ├── pt-br/
│ │ └── Legacy.resw
│ ├── ro/
│ │ └── Legacy.resw
│ ├── ru/
│ │ └── Legacy.resw
│ ├── si/
│ │ └── Legacy.resw
│ ├── sk/
│ │ └── Legacy.resw
│ ├── sl/
│ │ └── Legacy.resw
│ ├── sq/
│ │ └── Legacy.resw
│ ├── sr-Latn/
│ │ └── Legacy.resw
│ ├── sr-cyrl/
│ │ └── Legacy.resw
│ ├── sv/
│ │ └── Legacy.resw
│ ├── sw/
│ │ └── Legacy.resw
│ ├── ta/
│ │ └── Legacy.resw
│ ├── tg-arab/
│ │ └── Legacy.resw
│ ├── th/
│ │ └── Legacy.resw
│ ├── tk-cyrl/
│ │ └── Legacy.resw
│ ├── tr/
│ │ └── Legacy.resw
│ ├── tt-arab/
│ │ └── Legacy.resw
│ ├── ug-arab/
│ │ └── Legacy.resw
│ ├── uk/
│ │ └── Legacy.resw
│ ├── uz-cyrl/
│ │ └── Legacy.resw
│ ├── uz-latn/
│ │ └── Legacy.resw
│ ├── vi/
│ │ └── Legacy.resw
│ ├── yo-latn/
│ │ └── Legacy.resw
│ ├── zh-Hans/
│ │ └── Legacy.resw
│ └── zh-Hant/
│ └── Legacy.resw
├── ReadMe.md
├── RestoreNuGetPackages.cmd
├── Security.md
└── Settings.XamlStyler
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
##
## PROJECT: Mouri Internal Library Essentials
## FILE: .editorconfig
## PURPOSE: The root .editorconfig file
##
## LICENSE: The MIT License
##
## MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
##
root = true
[*]
charset = utf-8-bom
end_of_line = crlf
[*.md]
insert_final_newline = true
[*.{c,c++,cc,cpp,cxx,h,h++,hh,hpp,hxx,ixx,cppm,ipp,odl,idl,inl,ipp,tlh,tli}]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
vc_generate_documentation_comments = doxygen_slash_star
cpp_new_line_before_open_brace_function = new_line
cpp_new_line_before_open_brace_block = new_line
cpp_new_line_before_open_brace_lambda = new_line
cpp_new_line_before_open_brace_type = new_line
cpp_new_line_before_open_brace_namespace = new_line
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_else = true
cpp_new_line_before_catch = true
cpp_new_line_before_while_in_do_while = true
cpp_naming_rule.general_names.symbols = all_symbols
cpp_naming_rule.general_names.style = mile_project_cpp
cpp_naming_symbols.all_symbols.applicable_kinds = *
cpp_naming_style.mile_project_cpp.capitalization = pascal_case
[*.{cs,csx,vb,vbx,asmx}]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.{js,json,xml,toml,xaml}]
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.rc]
charset = utf-16le
[*.inf]
charset = utf-16le
[*.bat]
charset = utf-8
insert_final_newline = true
[*.sh]
charset = utf-8
end_of_line = lf
insert_final_newline = true
[*.{asm,inc,s,nasm}]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: .github/FUNDING.yml
================================================
custom: [
"https://github.com/M2Team/NanaZip/blob/main/Documents/SponsorEdition.md"
]
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug report
description: Something isn't working as expected.
labels: ["bug"]
body:
- type: checkboxes
attributes:
label: Prerequisite checks
description: These items are required before submitting the bug report.
options:
- label: My system fulfills [the minimum software requirements](https://github.com/M2Team/NanaZip?tab=readme-ov-file#system-requirements).
required: true
- label: I have downloaded NanaZip from an official source (GitHub, Microsoft Store, My Digital Life Forums, SourceForge, and Windows App Community)
required: true
- type: textarea
attributes:
label: Describe the issue
validations:
required: true
- type: textarea
attributes:
label: Reproduction steps
description: What steps did you take for this bug to happen?
placeholder: |
1.
2.
3.
validations:
required: true
- type: textarea
attributes:
label: Expected behavior
description: What did you expect this feature to do?
validations:
required: true
- type: input
attributes:
label: NanaZip veresion
description: What version of NanaZip are you using?
validations:
required: true
- type: input
attributes:
label: Windows version
description: What version of Windows are you using?
placeholder: Windows 11, version 25H2; Windows 11 Insider build xxxxx
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Any other information related to this bug that you want to tell us.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
- name: Report a security vulnerability
url: https://github.com/M2Team/NanaZip/security/advisories/new
about: Don't open a GitHub issue to report a vulnerability. Please create a new security advisory instead.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature request
description: Request a new feature into NanaZip.
labels: ["enhancement"]
body:
- type: textarea
attributes:
label: Describe the feature
validations:
required: true
- type: checkboxes
attributes:
label: Prerequisite checks
options:
- label: I have confirmed that this feature isn't yet implemented in the latest Preview release.
required: true
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
================================================
FILE: .github/dco.yml
================================================
allowRemediationCommits:
individual: true
thirdParty: true
require:
members: true
================================================
FILE: .github/workflows/BuildBinaries.yml
================================================
name: Build Binaries
on:
push:
paths-ignore:
- 'Documents/**'
- '**/*.md'
pull_request:
paths-ignore:
- 'Documents/**'
- '**/*.md'
jobs:
build:
runs-on: windows-latest
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- uses: microsoft/setup-msbuild@v2
- name: Clear local NuGet cache (workaround for failed restores on windows-latest)
run: dotnet nuget locals all --clear
- name: Build
run: MSBuild -binaryLogger:Output\BuildAllTargets.binlog -m BuildAllTargets.proj
- name: Upload MSIX Bundle
uses: actions/upload-artifact@v4
with:
name: NanaZip_Mainline_ApplicationPackages
path: Output/Binaries/AppPackages
- name: Upload Extension Package Installer
uses: actions/upload-artifact@v4
with:
name: NanaZip_Mainline_ExtensionPackageInstaller
path: Output/NanaZip.ExtensionPackage_*.exe
- name: Upload MSBuild Build Process Binary Log
uses: actions/upload-artifact@v4
if: '!cancelled()'
with:
name: NanaZip_Mainline_BuildBinaryLog
path: Output/BuildAllTargets.binlog
- name: Upload Portable Binaries
uses: actions/upload-artifact@v4
with:
name: NanaZip_Mainline_PortableBinaries
path: Output/Binaries/Root/Binaries
- name: Upload Debug Symbols
uses: actions/upload-artifact@v4
with:
name: NanaZip_Mainline_DebugSymbols
path: Output/Binaries/Root/Symbols
================================================
FILE: .github/workflows/UpdatePrecompiledBuildTools.yml
================================================
name: Update Precompiled Build Tools
on:
push:
branches:
- main
paths:
- 'NanaZip.Build.Tasks/**'
- '.github/workflows/UpdatePrecompiledBuildTools.yml'
jobs:
build:
runs-on: windows-latest
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- uses: microsoft/setup-msbuild@v2
- name: Clear local NuGet cache (workaround for failed restores on windows-latest)
run: dotnet nuget locals all --clear
- name: Configure the git commit information
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- name: Refresh the build number
run: |
MSBuild -target:RefreshVersion BuildAllTargets.proj
git commit -a -m "Refresh the build number for the precompiled build tools."
- name: Prepare the compiled build tools binaries
run: |
dotnet build --configuration Release NanaZip.Build.Tasks\NanaZip.Build.Tasks.csproj
git commit -a -m "Update the precompiled build tools."
- name: Push changes to the repository
run: |
git checkout -b unstaged/update-precompiled-build-tools
git push origin unstaged/update-precompiled-build-tools --force
================================================
FILE: .github/workflows/UpdateWebsite.yml
================================================
name: Update Website
on:
push:
branches:
- main
paths:
- 'Documents/Website/**'
- '.github/workflows/UpdateWebsite.yml'
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Build and upload website
uses: withastro/action@v5
with:
path: ./Documents/Website
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
================================================
FILE: .gitignore
================================================
##
## PROJECT: Mouri Internal Library Essentials
## FILE: .gitignore
## PURPOSE: The root .gitignore file for Visual Studio C++ Project
##
## LICENSE: The MIT License
##
## MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
##
##
## Ignore Mile.Project specific temporary files, build results,
## and files generated by popular Visual Studio add-ons.
##
Output/
##
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
MSBuild_Logs/
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
================================================
FILE: BuildAllTargets.cmd
================================================
@setlocal
@echo off
rem Change to the current folder.
cd "%~dp0"
rem Remove the output folder for a fresh compile.
rd /s /q Output
rem Initialize Visual Studio environment
set VisualStudioInstallerFolder="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"
if %PROCESSOR_ARCHITECTURE%==x86 set VisualStudioInstallerFolder="%ProgramFiles%\Microsoft Visual Studio\Installer"
pushd %VisualStudioInstallerFolder%
for /f "usebackq tokens=*" %%i in (`vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do (
set VisualStudioInstallDir=%%i
)
popd
call "%VisualStudioInstallDir%\VC\Auxiliary\Build\vcvarsall.bat" x86
rem Build all targets
MSBuild -binaryLogger:Output\BuildAllTargets.binlog -m BuildAllTargets.proj
@endlocal
================================================
FILE: BuildAllTargets.proj
================================================
$(GitBuildNumberDate)
$(NanaZipMajorVersion).$(NanaZipMinorVersion).$([System.DateTime]::Parse('$(NanaZipBuildNumberDate)').Subtract($([System.DateTime]::Parse('$(NanaZipProjectCreationDate)'))).TotalDays).0
Configuration=Debug;Platform=x64
Configuration=Release;Platform=x64
Configuration=Release
$(MSBuildThisFileDirectory)Output\Binaries\Release\
$(MSBuildThisFileDirectory)Output\Binaries\Root\Binaries\
$(MSBuildThisFileDirectory)Output\Binaries\Root\Symbols\
NanaZip_$(MileProjectVersion)
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age,
body size, disability, ethnicity, sex characteristics, gender identity and
expression, level of experience, education, socio-economic status, nationality,
personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an
appointed representative at an online or offline event. Representation of
project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at Kenji.Mouri@outlook.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an
incident. Further details of specific enforcement policies may be posted
separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4, available at
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to NanaZip
## How to become a contributor
- Direct contributions
- We use a code style similar but not identical to that of Windows NT kernel
drivers. You must read the code style guidelines carefully, word by word,
before submitting your pull request. To maintain NanaZip's source code
quality, and to respect our reviewers' time, we will not accept PRs that
don't follow these guidelines.
- We expect all contributions to match our existing style WITHOUT EXCEPTION.
If you have any questions about our coding standards, please open an issue
for discussion before submitting your pull request.
- By submitting a pull request, you agree to license your contribution under
the MIT license. We reserve the right to reuse and rewrite contributors' PRs
as needed.
- You are forbidden to modify any content in any files and folders starting
with the "Mile." prefix because those implementations are shared across many
projects, or your pull request will not be merged and will be closed
immediately, unless you get the permission from Kenji Mouri.
- It's OK to use AI/LLM tools to help you write code, but you must ensure that
the final commit is written and reviewed by yourself, following our coding
style and conventions. If we find that your pull request has no contribution
from you, or the contribution is not reviewed by you, your pull request will
not be merged and will be closed immediately.
- Feedback suggestions and bugs.
- We use GitHub issues to track bugs and features.
- For bugs and general issues please
[file a new issue](https://github.com/M2Team/NanaZip/issues/new).
## Code contribution guidelines
### Prerequisites
- Visual Studio 2022 or later.
- You also need install ARM64 components (MSVC Toolchain and ATL/MFC) if you
want to compile the ARM64 version of NanaZip.
- Windows 11 SDK or later.
- You also need to install ARM64 components if you want to compile the ARM64
version of NanaZip.
### How to build all targets of NanaZip
Run `BuildAllTargets.bat` in the root of the repository.
### How to modify or debugging NanaZip
Recommend to run `RestoreNuGetPackages.cmd` in the root of the repository to
restore NuGet packages if you have not run this script or `BuildAllTargets.bat`
before. (Recent versions of Visual Studio 2026 has some issues to restore NuGet
packages automatically.)
Open `NanaZip.slnx` in the root of the repository.
### Code style and conventions
Read Kenji Mouri's [MD24: The coding style for all my open-source projects] for
more information.
[MD24: The coding style for all my open-source projects]: https://github.com/MouriNaruto/MouriDocs/tree/main/docs/24
For all languages respect the [.editorconfig](https://editorconfig.org/) file
specified in the source tree. Many IDEs natively support this or can with a
plugin.
#### Modifications for inherited 7-Zip mainline source code
> [!NOTE]
> Read https://github.com/M2Team/NanaZip/blob/main/License.md first for knowing
> which files whether belong to inherited 7-Zip mainline source code.**
> [!NOTE]
> For adding something to inherited 7-Zip code, don't add extra empty line if
> there is no empty line in the existed inherited 7-Zip methods and functions.
For simplifying the synchronization from 7-Zip mainline, the modification mark
is necessary, which the original 7-Zip mainline code should be commented as
original, Here is the format:
```
// **************** NanaZip Modification Start ****************
// xzProps.numTotalThreads = (int)(prop.ulVal);
xzProps.numTotalThreads = ((int)prop.ulVal) > 1 ? (int)prop.ulVal : 1;
// **************** NanaZip Modification End ****************
```
For multiple lines, you can also use the following format:
```
// **************** 7-Zip ZS Modification Start ****************
#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********
kBZip2 = 12,
kLZMA = 14,
kTerse = 18,
kLz77 = 19,
kZstdPk = 20,
kZstdWz = 93,
kMP3 = 94,
kXz = 95,
kJpeg = 96,
kWavPack = 97,
kPPMd = 98,
kWzAES = 99
#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********
kBZip2 = 12, // File is compressed using BZIP2 algorithm
kLZMA = 14, // LZMA
kTerse = 18, // File is compressed using IBM TERSE (new)
kLz77 = 19, // IBM LZ77 z Architecture
kZstdPk = 20, // deprecated (use method 93 for zstd)
kZstd = 93, // Zstandard (zstd) Compression
kMP3 = 94, // MP3 Compression
kXz = 95, // XZ Compression
kJpeg = 96, // JPEG variant
kWavPack = 97, // WavPack compressed data
kPPMd = 98, // PPMd version I, Rev 1
kWzAES = 99 // AE-x encryption marker (see APPENDIX E)
// **************** 7-Zip ZS Modification End ****************
```
#### Translation contribution notice
All `comment` in `resw` files should be kept English to make it better for
maintenance in the future.
================================================
FILE: Directory.Build.props
================================================
$(MSBuildThisFileDirectory)Output\
================================================
FILE: Documents/ChannelSwitchNote.md
================================================
# Channel Switch Note for NanaZip development
P.S. Only for Kenji Mouri
## Preview
- DisplayName="NanaZip Preview"
- Name="40174MouriNaruto.NanaZipPreview"
- NanaZip Preview
- 469D94E9-6AF4-4395-B396-99B1308F8CE5
- return ::SHStrDupW(L"NanaZip Preview", ppszName);
## Stable
- DisplayName="NanaZip"
- Name="40174MouriNaruto.NanaZip"
- NanaZip
- CAE3F1D4-7765-4D98-A060-52CD14D56EAB
- return ::SHStrDupW(L"NanaZip", ppszName);
================================================
FILE: Documents/DevelopmentRoadmapArchived.md
================================================
# Development Roadmap (Archived)
These will be migrated to the new roadmap issue in the future.
- Blue Moon (3.x) Series (Before 2024 Q3)
- [ ] Continue to modernize the UI with XAML Islands with the Windows 11
control style, dark and light mode support.
- [ ] Full Accessibility support in all UI components.
- [ ] Migrate configurations from registry to json. (Suggested by
AndromedaMelody.)
- [ ] Continue to modernize the core implementation.
- [ ] Try to Windows Runtime component for interoperability.
- [ ] Provide NanaZip Installer for simplify the deployment.
- [ ] Try to add option for save file names with UTF-8 in 7z archives.
- [ ] Add batch task support. (Suggested by 刘泪.)
- [ ] Try to design the new UI layout. (Suggested by wangwenx190.)
- [ ] Try to add option for using Windows Imaging API (WIMGAPI) backend to
make better creation and extraction support for wim archives, also add
creation and extraction support for esd archives.
- [ ] Try to add pri archive extracting support.
- [ ] Try to add smart extraction.
- [ ] Try to add language encoding switching support for file names in File
Manager. (Suggested by 刘泪 and zjkmxy.)
- [ ] Try to add deleting source after archiving support. (Suggested by
OrionGrant.)
- [ ] Try to add an option when extracting an archive to open the folder
where you extracted the files, like WinRAR. (Suggested by maicol07.)
- [ ] Try to add ISO creation support.
- Sherlock Holmes (5.x) Series (Before 2025 Q3)
- Currently no new feature plans for this series.
- Unpredictable Future Series (T.B.D.)
- [ ] Try to create a new archive file format optimized for software
distribution and image backup and restore.
- [ ] Keeping metadata provided by file system.
- [ ] File referencing support.
- [ ] Integrity verification support.
- [ ] Differential support.
- [ ] Recovery record support.
- [ ] Provide lightweight SDK for authoring and consuming.
- [ ] Try to contribute recovery record support for 7z archives to 7-Zip
mainline. (Suggested by SakuraNeko.)
- [ ] Try to port NanaZip to Linux.
- [ ] Try to port MegaUI (an developing lightweight UI framework created by
mingkuang, under internal developing at the current stage, will be
open source if the work has done) framework to Linux.
- [ ] Try to create MinLin (a.k.a. Minimum Linux, a distro intended for
helping publish distroless binaries and provide some Windows API
functions as static libraries for having a lightweight platform
abstraction layer) project because I think NanaZip should support
distroless environment for reducing time wasting for compiling for
different distros.
- [ ] After porting NanaZip to Linux, accept contributions from community
folks for other POSIX platforms (e.g. FreeBSD) and macOS support.
- [ ] Try to add extension for Windows File Explorer for give user immersive
experience like builtin zip file support in Windows. (Suggested by
SakuraNeko and shuax.)
- [ ] Try to create isolated and portable plugin infrastructure based on
64-bit RISC-V Unprivileged ISA Specification.
Runtime Project: https://github.com/ChaosAIOfficial/RaySoul
================================================
FILE: Documents/People.md
================================================
# Relevant People
## Notice
- This list is sorted in alphabetical order.
## Development Team
### Benevolent Dictators For Life
The project is governed by multiple Benevolent Dictators For Life who make final
decisions by reaching an agreement offline. This structure is chosen to avoid
the risks of a single point of control while maintaining efficiency over a large
committee. Here are current active Benevolent Dictators For Life:
- dinhngtu (Tu Dinh), https://github.com/dinhngtu
- Kenji Mouri, https://github.com/MouriNaruto
### Consultants and Benevolent Dictator For Life Candidates
The following contributors are recognized as candidates for the Benevolent
Dictator For Life role. In their current capacity, they serve as valued
consultants to the active Benevolent Dictators For Life due to their significant
and valuable contributions to the project.
- AndromedaMelody, https://github.com/AndromedaMelody
- Dongle, https://github.com/dongle-the-gadget
- Sakura Neko, https://github.com/SakuraNeko
## Microsoft Store preinstall permission OEM Sponsor
- Moespirit Tech, https://github.com/Moespirit
## Logo Designers
### 2.x Series
- Shomnipotence, https://github.com/Shomnipotence
### 1.x Series
- Alice (四月天), https://twitter.com/alice_alice49
- Chi Lei, https://github.com/lychichem
- Kenji Mouri, https://github.com/MouriNaruto
- Rúben Garrido, https://github.com/RGarrido03
- Sakura Neko, https://github.com/SakuraNeko
## Contributors
Read https://github.com/M2Team/NanaZip/graphs/contributors for getting the
contributors list.
## Special thanks
- Belleve, https://github.com/be5invis
- Igor Pavlov, https://sourceforge.net/u/ipavlov
- mingkuang, https://github.com/mingkuang-Chuyu
- myfreeer, https://github.com/myfreeer
- Tino Reichardt, https://github.com/mcmilk
================================================
FILE: Documents/Policies.md
================================================
# NanaZip Policies
Starting with NanaZip 6.0, users can configure system‑wide policies under the
Windows registry key `HKLM\Software\Policies\M2Team\NanaZip`.
These system-wide policies override user settings and are intended for use by
system administrators to enforce specific configurations across multiple users
or systems.
You can enforce these policies on an entire domain using our
[Group Policy Administrative Templates](PolicyDefinitions).
Here are the currently provided policies and their descriptions.
## Available policies since NanaZip 6.0
### Allow dynamic code generation for all NanaZip components
NanaZip disables dynamic code generation for its components by default in
Release builds to reduce the risk of running potentially malicious code at
runtime. However, some third‑party software that relies on dynamic code
generation and injects code into NanaZip processes may require this feature
to be enabled for compatibility.
- Name: `AllowDynamicCodeGeneration`
- Type: `REG_DWORD`
- Value:
- `0`: Disabled (Default)
- `1`: Enabled
### Allow child processes creation for all NanaZip components
NanaZip blocks child process creation by default in its command line components
and self‑extracting executables to reduce the risk of process abuse by malicious
archives. However, some third‑party input method editors (IMEs) and assistive
technologies (ATs) may require child process creation to function correctly. In
such cases, this policy can be used to allow child process creation.
- Name: `AllowChildProcessCreation`
- Type: `REG_DWORD`
- Value:
- `0`: Disabled (Default)
- `1`: Enabled
### Archive handler restrictions
These values control which archive handlers can be loaded by NanaZip.
With this policy, you can significantly limit the attack surface of NanaZip by
blocking the parsing of unusual archive formats.
If AllowedHandlers is present, only the handlers specified in said list will be
allowed.
If BlockedHandlers is present, the handlers specified in said list will be
blocked. BlockedHandlers takes precedence over AllowedHandlers; i.e. handlers
specified in BlockedHandlers will still be blocked even if they're specified in
AllowedHandlers.
Note that when editing a `REG_MULTI_SZ` value in Registry Editor, each entry
must be on its own line.
- Name: `AllowedHandlers`
- Type: `REG_MULTI_SZ`
- Value: List of allowed archive handlers (case-sensitive).
- Name: `BlockedHandlers`
- Type: `REG_MULTI_SZ`
- Value: List of blocked archive handlers (case-sensitive).
Known archive handlers (as of NanaZip 6.0 Preview 2):
```
.Electron Archive (asar), .NET Single File Application, 7z, APFS, APM, Ar, Arj,
AVB, Base64, brotli, bzip2, Cab, Chm, COFF, Compound, Cpio, CramFS, Dmg, ELF,
Ext, FAT, FLV, GPT, gzip, HFS, Hxs, IHex, Iso, littlefs, lizard, LP, LVM, lz4,
lz5, Lzh, lzip, lzma, lzma86, MachO, MBR, MsLZ, Mub, Nsis, NTFS, PE, Ppmd, QCOW,
Rar, Rar5, ROMFS, Rpm, Sparse, Split, SquashFS, SWF, SWFc, tar, TE, Udf, UEFIc,
UEFIf, UFS, VDI, VHD, VHDX, VMDK, WebAssembly (WASM), wim, Xar, xz, Z, ZealFS,
zip, zstd
```
Run `NanaZipC --version` to see the full list of currently-enabled handlers.
### Codec restrictions
Similarly to archive handler restrictions, these values control which codecs can
be loaded by NanaZip.
**Note:** Some single-codec archive formats (e.g. Brotli) may call their
associated codecs without respecting codec restrictions. If you want to fully
block a codec from being used, make sure that its associated formats are also
blocked.
- Name: `AllowedCodecs`
- Type: `REG_MULTI_SZ`
- Value: List of allowed codecs (case-sensitive).
- Name: `BlockedCodecs`
- Type: `REG_MULTI_SZ`
- Value: List of blocked codecs (case-sensitive).
Known codecs (as of NanaZip 6.0 Preview 2):
```
7zAES, AES256CBC, ARM, ARM64, ARMT, BCJ, BCJ2, BROTLI, BZip2, Copy, Deflate,
Deflate64, Delta, FLZMA2, IA64, LIZARD, LZ4, LZ5, LZMA, LZMA2, PPC, PPMD, Rar1,
Rar2, Rar3, Rar5, RISCV, SPARC, Swap2, Swap4, ZSTD
```
Run `NanaZipC --version` to see the full list of currently-enabled codecs.
### Propagate Zone.Id stream
This value controls Mark-of-the-Web (MOTW) propagation of archive files.
- Name: `WriteZoneIdExtract`
- Type: `REG_DWORD`
- Value:
- `0`: No
- `1`: Yes (all files)
- `2`: Only for unsafe extensions (does not support all nested archives)
## Legacy Policies in NanaZip 6.0 Preview 1
In NanaZip 6.0 Preview 1, system-wide policies should be set via creating
Registry values in the key `HKLM\Software\NanaZip\Policies` instead.
Here are the policies can be applied in NanaZip 6.0 Preview 1.
- WriteZoneIdExtract
Here are some policies only available in NanaZip 6.0 Preview 1.
### Disable mitigations
This value controls which security mitigations should not be applied by NanaZip.
- Name: `DisableMitigations`
- Type: `REG_DWORD`
- Value:
- `0`: Don't disable mitigations
- `1`: Disable all mitigations
- Other values are reserved.
================================================
FILE: Documents/PolicyDefinitions/NanaZip.admx
================================================
================================================
FILE: Documents/PolicyDefinitions/en-US/NanaZip.adml
================================================
NanaZip
NanaZip
NanaZip
NanaZip 6.0 Preview 1
NanaZip 6.0 Preview 2
NanaZip 6.0 Preview 1 only
At least NanaZip 6.0 Preview 2
NanaZip
Handler and Codec Restrictions
Legacy Policies
Allow dynamic code generation for all NanaZip components
NanaZip disables dynamic code generation for its components by default in Release builds to reduce the risk of running potentially malicious code at runtime. However, some third-party software that relies on dynamic code generation and injects code into NanaZip processes may require this feature to be enabled for compatibility.
If you enable this policy setting, NanaZip allows third-party components to generate dynamic code at runtime.
If you disable or do not configure this policy setting, NanaZip blocks the ability to create dynamic code in its own processes.
Allow child processes creation for all NanaZip components
NanaZip blocks child process creation by default in its command line components and self-extracting executables to reduce the risk of process abuse by malicious archives. However, some third-party input method editors (IMEs) and assistive technologies (ATs) may require child process creation to function correctly. In such cases, this policy can be used to allow child process creation.
If you enable this policy setting, NanaZip processes can create child processes at runtime.
If you disable or do not configure this policy setting, NanaZip blocks the ability to create child processes from many of its own processes.
Allowed archive handlers
This policy setting controls which archive handlers can be loaded by NanaZip.
With this policy setting, you can significantly limit the attack surface of NanaZip by blocking the parsing of uncommon archive formats.
If you enable this policy setting, only the handlers specified in this list (one in each line, case sensitive) will be allowed to load.
If you disable or do not configure this policy setting, all otherwise-unspecified archive handlers can load.
Run NanaZipC --version to see the full list of currently-enabled handlers.
Blocked archive handlers
This policy setting controls which archive handlers cannot be loaded by NanaZip.
With this policy setting, you can significantly limit the attack surface of NanaZip by blocking the parsing of uncommon archive formats.
If you enable this policy setting, the handlers specified in this list (one in each line, case sensitive) will be blocked from loading.
If you disable or do not configure this policy setting, all otherwise-unspecified archive handlers can load.
Run NanaZipC --version to see the full list of currently-enabled handlers.
Allowed compression codecs
This policy setting controls which compression codecs can be loaded by NanaZip.
With this policy setting, you can significantly limit the attack surface of NanaZip by blocking the execution of uncommon compression codecs.
If you enable this policy setting, only the codecs specified in this list (one in each line, case sensitive) will be allowed to load.
If you disable or do not configure this policy setting, all otherwise-unspecified compression codecs can load.
Run NanaZipC --version to see the full list of currently-enabled codecs.
Blocked compression codecs
This policy setting controls which compression codecs cannot be loaded by NanaZip.
With this policy setting, you can significantly limit the attack surface of NanaZip by blocking the execution of uncommon compression codecs.
If you enable this policy setting, the codecs specified in this list (one in each line, case sensitive) will be blocked from loading.
If you disable or do not configure this policy setting, all otherwise-unspecified compression codecs can load.
Run NanaZipC --version to see the full list of currently-enabled codecs.
Disable mitigations
This policy setting controls the application of security mitigations on NanaZip processes.
If you enable this policy setting, NanaZip disables all security mitigations in its processes.
If you disable or do not configure this policy setting, NanaZip enables all mitigations by default.
List of allowed archive handlers:
List of blocked archive handlers:
List of allowed compression codecs:
List of blocked compression codecs:
================================================
FILE: Documents/Privacy.md
================================================
# NanaZip - Privacy Policy
## Information collected
NanaZip does not collect any information. However it does provide you access to
files and folders on your file system. Additionally, the Windows Store and
Windows App Host collect data on usage, for example, who bought/used the app
and crash reports. If you open any files or links in the app that go to other
websites you will need to look at their privacy policy.
## Sponsored edition
Due to the Microsoft Store Licensing API implementation, you will find NanaZip
will try to access the Internet beginning with NanaZip 3.0 because NanaZip
needs to use that to check the Sponsor Edition addon licensing status.
For optimizing the user experience, NanaZip will only check the Sponsor
Edition addon licensing status at the first time your launch NanaZip File
Manager. You can click the sponsor button if you want to refresh the status
after you have purchased or redeemed the Sponsor Edition addon.
## Use of information
No other data is collected or shared online. We reserve the right to
make changes to this policy. Any changes to this policy will be updated.
## Last updated: May 28, 2024
================================================
FILE: Documents/ReleaseNotes.md
================================================
# NanaZip Release Notes
For preview versions, please read
[NanaZip Preview Release Notes](ReleaseNotesPreview.md).
**NanaZip 6.0 Update 2 (6.0.1650.0)**
- Add NanaZip official website link to the XAML About Dialog.
- Fix some crash issues caused by dark mode support.
- Fix some crash issues caused by the XAML information dialog.
- Fix the issue that we cannot use NanaZip.Universal.Windows.exe without
NanaZip.Modern.dll.
- Fix the issue that we cannot set the initial folder for the copy location
dialog browse button.
- Fix the buffer overflow issue introduced since 7-Zip mainline 26.00 when using
NanaZip.Core.Setup.sfx which you need to compiled manually to get. (Backported
from https://github.com/M2Team/NanaZip/pull/850 and
https://github.com/mcmilk/7-Zip-zstd/pull/468/changes/f4efd0f2d960b18fd51a894d04b5eadebf8c270b.)
**NanaZip 6.0 Update 1 (6.0.1638.0)**
- Fix several issues for the UFS/UFS2 file system image readonly support.
(Cooperated with HO-9.)
- Fix several issues for the .NET Single File Application bundle readonly
support. (Cooperated with HO-9.)
- Fix the white flashes when initializing the file panels in the NanaZip File
Manager main window. (Thanks to anhelloooo.)
- Disable text wrapping for textbox control in XAML information dialog to show
information better.
- Make the hash calculation result output text format more compact to improve
the copy and paste experience.
- Fix the Win32 TaskDialog-based Folders History dialog not functioning when
users navigate to the desktop virtual folder.
- Update Japanese translation. (Contributed by noangel.)
- Update Brazilian Portuguese translation. (Contributed by maisondasilva.)
**NanaZip 6.0 (6.0.1632.0)**
- Notes
- Start to transition to community driven development model.
- Update system requirement to Windows 10, version 2004 (Build 19041) or
later, and remove the x86 (32-bit) for all components.
- Start to provide the official portable binaries package of NanaZip with both
Modern and Classic flavors, except the NanaZip File Manager.
- Introduce formal version of contributing guide and security policies.
(Cooperated with dinhngtu and dongle-the-gadget.)
- Add Release Tags to NanaZip Versioning.
- Features
- Introduce extract-on-open feature. (Contributed by dinhngtu.)
- To disable this temporarily, hold Shift while opening the file.
- To disable this permanently, go to Settings, Integration tab, and disable
"Extract on open" at the bottom.
- Introduce registry settings for Mark of the Web (MoTW) enforcement policies.
(Contributed by dinhngtu.)
- Improve the dynamic library block list for resolving compatibility issues.
(Contributed by dinhngtu.)
- Introduce registry settings for disabling security mitigation policies,
which should be helpful for debugging and resolving compatibility issues.
(Contributed by dinhngtu.)
- Introduce registry settings for the archive handler and codec handler
restriction. (Contributed by dinhngtu.)
- Introduce Group Policy Administrative Template (ADMX/ADML) for NanaZip.
(Contributed by dinhngtu.)
- Set the LOAD_LIBRARY_SEARCH_SYSTEM32 dependent load flag on Release builds
of Self Extracting Executables stubs to mitigate static imports level DLL
planting attack on Windows 10 build 14393 and later. (Contributed by
dinhngtu.)
- Introduce the XAML-based address bar. (Contributed by dongle-the-gadget.)
- Introduce the XAML-based status bar. (Contributed by dongle-the-gadget.)
- Introduce the XAML-based properties and information dialog. (Contributed by
dongle-the-gadget.)
- Introduce the XAML-based progress dialog. (Contributed by
dongle-the-gadget.)
- Introduce extract all automatically policy when opening executable files in
archives. (Contributed by MajThomas.)
- Introduce the environment variable parsing support for address bar. (Thanks
to dongle-the-gadget's huge help.)
- Add support for CBR and CBZ file associations. (Contributed by dinhngtu.)
- Add support for ASAR file association. (Contributed by dongle-the-gadget.)
- Display file system version in archive property window for the UFS/UFS2 file
system image readonly support.
- Display bundle version in archive property for the .NET Single File
Application bundle readonly support.
- Display file system version in archive property for the littlefs file system
image readonly support.
- Allow to associate more file types to NanaZip. (Contributed by manfromarce.)
- Enable Ctrl+Backspace on edit fields using SHAutoComplete. (Contributed by
dinhngtu.)
- Introduce NanaZip.Universal.Windows project for making NanaZip Command Line
Interface (Windows) for both NanaZip (Modern) and NanaZip Classic a.k.a.
NanaZipG or K7G to synchronize to the latest 7-Zip mainline and 7-Zip ZS
implementations.
- Introduce NanaZip Platform Base Library (K7Base) and NanaZip Platform User
Library (K7User) to replace NanaZip Platform Abstraction Layer (K7Pal) and
NanaZip.Frieren for better code sharing and maintainability.
- Create NanaZip.Modern project for the modern user experience development.
- Introduce Mile.Mobility dependence to NanaZip.Codecs project for making
better portability between NanaZip and AptxZip (a.k.a. NanaZip for POSIX).
- Introduce NanaZip.ExtensionPackage project for future development of
features which need to be distributed as legacy installer. (Contributed by
dinhngtu.)
- Introduce Mile.Helpers.Portable.Base.Unstaged as the temporary
infrastructure to standardize some portable things in NanaZip.Codecs.
- Introduce NanaZip.Codecs.Specification.Fat for adding definitions of FAT12,
FAT16 and FAT32.
- Introduce NanaZip.Codecs.Specification.Zealfs for adding definitions of
ZealFS series file system. (Cooperated with Zeal 8-bit.)
- Add littlefs v1 on-disk definitions to the littlefs file system image
readonly support.
- Move NanaZip.Core's NanaZip.Core.Console project to NanaZip.Universal's
NanaZip.Universal.Console project.
- Improvements
- Start to use Zstandard decoder instead of 7-Zip mainline's implementation
for better reliability, especially it can reduce more potential
vulnerabilities.
- Use x-generate to define language resources in AppX manifest to solve the
Windows AppX language fallback issue. (Suggested by dongle-the-gadget.)
- Make texts have better contrast in dark mode.
- Improve the Smart Extraction feature. (Contributed by R-YaTian.)
- Improve the NanaZip startup performance by initializing the StoreContext
later. (Contributed by dongle-the-gadget.)
- Move open folder checkbox to extract dialog. (Contributed by dinhngtu.)
- Update Albanian translation. (Contributed by F1219R.)
- Update Hungarian translation. (Contributed by John Fowler.)
- Update Greek translation. (Contributed by Lefteris T.)
- Update German translation. (Contributed by HackZy01.)
- Update Bengali translation. (Contributed by Sumon Kayal.)
- Update Dutch translation. (Contributed by Stephan-P.)
- Localize Open Inside menu text. (Contributed by dinhngtu.)
- Remove Help button from compress option dialogs. (Contributed by
peashooter2.)
- Update the icon assets with optimized assets to reduce the binary size.
- Use Win32 TaskDialog to implement the Folders History dialog to simplify the
implementation.
- Synchronize 7-Zip mainline implementations to 26.00. (Except the NanaZip
File Manager.) (Thanks to Igor Pavlov. Noticed by FadeMind and Pinguin2001.)
- Synchronize the 7-Zip ZS implementations to
https://github.com/mcmilk/7-Zip-zstd/tree/5766dd7745f6517f7ea42f6de9a190dfd92aa25f.
(Except the NanaZip File Manager.) (Thanks to Sergey G. Brester and Tino
Reichardt.)
- Make FastLZMA2 and Lizard reuse partial Zstandard implementations.
- Update Zstandard to v1.5.7. (Noticed by dcog989.)
- Update Lizard to v2.1.
- Synchronize Brotli implementations to v1.2.0.
(https://github.com/google/brotli/releases/tag/v1.2.0)
- Synchronize the FastLZMA2 implementations to
https://github.com/conor42/fast-lzma2/tree/a793db99fade2957d2453035390f97e573acecb2,
which can fix some issues. (Contributed by dinhngtu.)
- Synchronize the BLAKE3 implementation to 1.8.3. (Noticed by peashooter2.)
(https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.8.3)
- Use assembly hardware acceleration for BLAKE3 implementation.
- Synchronize RHash to the latest master
(https://github.com/rhash/RHash/tree/b76c6a3312422c09817c2cef40442b2f2d9d4689)
which is after v1.4.6.
- Update Mile.Project.Configurations to 1.0.1917, which solve some issues for
using NuGet Package References Support in Visual Studio 2026 version 18.3 or
later. (Cooperated by AndromedaMelody.)
- Update Mile.Project.Helpers to 1.0.975.
- Update Mile.Windows.Helpers to 1.0.1171.
- Update Mile.Windows.Internal to 1.0.3515.
- Update Mile.Xaml to 2.5.1616.
- Update Mile.Detours to 1.0.2180.
- Update Mile.Json to 1.0.1057.
- Update .NET projects to .NET 10 and update NuGet package dependencies.
- Add littlefs v2.10.2 to NanaZip.Codecs for future development of work in
progress littlefs archive format readonly support.
- Update build binary logs when failed to build in GitHub Actions.
(Contributed by dongle-the-gadget.)
- Introduce legacy string migrator. (Contributed by dongle-the-gadget.)
- Add more targeted editorconfig rules. (Contributed by dongle-the-gadget.)
- Move NanaZip.Core's NanaZip.Core.Console project to NanaZip.Universal's
NanaZip.Universal.Console project.
- Disable WinRT metadata generation for all WinRT component consumers.
- Move NanaZip.Modern as the first item to workaround the AppX toolchain
manifest generation issues.
- Improve the GitHub Actions artifacts generation.
- Update to Windows 11 SDK Build 26100 for NanaZipPackage.
- Introduce reproducible build support for the whole project.
- Migrate solution from sln to slnx, and start to build with MSVC 14.50
toolset.
- Support opening NanaZip Visual Studio solution without installing WinUI
application and/or Universal Windows Platform development workload.
(Contributed by AndromedaMelody.)
- Add RestoreNuGetPackages.cmd script to workaround some issues for people who
want to use Visual Studio to build NanaZip without running
BuildAllTargets.bat script.
- Make the precompiled build tools generated by GitHub Actions workflow
automatically.
- Improve several implementations.
- Fixes
- Fix dead loop issue when compressing files with Brotli, Lizard, LZ4 and LZ5
mentioned in https://github.com/M2Team/NanaZip/issues/639. (Thanks to
gigano01, InfiniteLoopGameDev and iOrange.)
- Backport CVE-2025-0411 and CVE-2025-11001 for the NanaZip File Manager which
still use the old 7-Zip mainline codebase. (Contributed by dinhngtu.)
- Fix several crash issues for the .NET Single File Application bundle
readonly support. (Thanks to haaeein.)
- Fix several hang issues for the ROMFS file system image readonly support
support. (Contributed by dinhngtu. Thanks to haaeein.)
- Fix the flickering issues when selecting list view in dark mode.
- Fix the unable to return the processed bytes count issue for
NanaZipCodecsReadInputStream.
- Fix the parsing padding issue for Electron Archive (asar) readonly support.
(Contributed by Vlad-Andrei Popescu).
- Improve the ZealFS file system image readonly support implementation to fix
several issues. (Cooperated with Zeal 8-bit.)
- Try to bring dialog window to the foreground to resolve user experience
issues when opened from context menu. (Contributed by dinhngtu.)
- Fix flickering XAML dialogs. (Contributed by dongle-the-gadget.)
- Fix crash issue from XAML address bar. (Contributed by dongle-the-gadget.)
- Use a low name as the shell extension name prefix to work around our context
menu not appearing in the classic context menu. (Contributed by dinhngtu.)
- Don't reset compression method after changing level. (Contributed by
dongle-the-gadget.)
- Fix text overflow in German translation. (Contributed by Pinguin2001.)
- Fix UI assignment of WriteZone setting. (Contributed by dinhngtu.)
- Handle Add button when inside archives. (Contributed by dinhngtu.)
- Fix issues for NanaZip Preview SVG icon assets for Contrast Black mode.
- Fix several issues for context menu support. (Contributed by dinhngtu.)
- Fix some potential issues for the dark mode support.
- Try to partially improve the NanaZip File Manager main window keyboard
navigation experience.
- Fix some string resources issues. (Contributed by dinhngtu.)
- Fix issues in compression levels combobox. (Contributed by dongle-the-gadget.)
- Fix the source code file header comment format.
- Use C++ zero initialization to reduce potential issues.
- Fix several issues.
**NanaZip 5.0 Update 2 (5.0.1263.0)**
- Features
- Provide K7 style execution aliases (K7.exe, K7C.exe, and K7G.exe) for
simplifying the command line user experience and providing the same command
name style in work-in-progress NanaZip for POSIX a.k.a. AptxZip.
- Improvements
- Update Mile.Windows.UniCrt to 1.2.328.
- Update Mile.Xaml to 2.5.1250.
- Migrate from Mile.Project.Windows to Mile.Project.Configurations.
- Fixes
- Fix crash issue when using Open Inside # mode for the WebAssembly (WASM)
binary file readonly support for NanaZip.Codecs.
- Fix crash issue when using Open Inside # mode for the .NET Single File
Application bundle readonly support for NanaZip.Codecs.
- Fix crash issue when using Open Inside # mode for the Electron Archive
(asar) readonly support for NanaZip.Codecs.
- Fix the crash issue when extracting *.br archives. (Thanks to HikariCalyx.)
- Fix the XXH3_128bits printable results with wrong byte order. (Thanks to
fuchanghao.)
**NanaZip 5.0 Update 1 (5.0.1252.0)**
- Features
- Introduce the .NET Single File Application bundle readonly support which
currently extracting compressed files in the bundle are not supported.
- Introduce the Electron Archive (asar) readonly support.
- Introduce the ROMFS file system image readonly support.
- Introduce the ZealFS file system image readonly support.
- Introduce the WebAssembly (WASM) binary file readonly support.
- Introduce the **Work In Progress** littlefs file system image readonly
support which currently only block information can acquired.
- Improvements
- Update Ukrainian and Russian translation. (Contributed by SlowDancer011.)
- Update Hungarian translation. (Contributed by JohnFowler58.)
- Update packages for maintainer tools.
- Fixes
- Fix the empty folders are excluded issue for the UFS/UFS2 file system image
readonly support.
- Fix the unavailable issue when cancelling the extraction for the UFS/UFS2
file system image readonly support.
**NanaZip 5.0 (5.0.1250.0)**
- Features
- Introduce the UFS/UFS2 file system image readonly support. (Thanks to
NishiOwO.)
- Introduce work-in-progress NanaZip Platform Abstraction Layer (K7Pal) for
wrapping the platform specific infrastructures. (Thanks to RuesanG's
feedback.) (https://github.com/M2Team/NanaZip/tree/main/K7Pal)
- Provide hash functions interfaces implemented with Windows CNG API.
NanaZip uses these hash functions from K7Pal:
- MD2
- MD4
- MD5
- SHA-1
- SHA-256
- SHA-384
- SHA-512
- ED2K (Implemented as the K7Pal MD4 wrapper in NanaZip.Codecs.)
- Update NanaZip.Specification.SevenZip header file.
- Introduce the Smart Extraction. (Contributed by R-YaTian.)
- Adds a setting for opening the folder after extracting from archive.
(Contributing by DaxDupont.)
- Improvements
- Synchronize the 7-Zip mainline implementations to 24.09.
(https://github.com/ip7z/7zip/releases/tag/24.09) (Thanks to Igor Pavlov.
Noticed by FadeMind and peashooter2.)
- Synchronize the BLAKE3 implementation to 1.5.5.
(https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.5.5)
- Synchronize the RHash implementation to the latest master branch which is
after v1.4.5.
(https://github.com/rhash/RHash/commit/cf2adf22ae7c39d9b8e5e7b87222046a8f42b3dc)
- Synchronize the xxHash implementation to v0.8.3.
(https://github.com/Cyan4973/xxHash/releases/tag/v0.8.3)
- Update Mile.Windows.Helpers to 1.0.671.
(https://github.com/ProjectMile/Mile.Windows.Helpers/tree/1.0.671.0)
- Update Brazilian Portuguese translation. (Contributed by maisondasilva.)
- Update Polish translation. (Contributed by ChuckMichael.)
- Update zh-Hans and zh-Hant translations for 'Want * History' strings.
(Contributed by R-YaTian.) (Forget to mentioned in NanaZip 5.0 Preview 1.)
- Make sure NanaZip Core (except the Self Extracting Executables) and NanaZip
Classic using ucrtbase.dll with 10.0.19041.0 version or later.
- Move NanaZip console version to NanaZip.Core project.
- Remove C++/WinRT dependency for NanaZip.Codecs and NanaZip.Frieren.
- Remove VC-LTL dependency for all components, and also use
Mile.Windows.UniCrt (https://github.com/ProjectMile/Mile.Windows.UniCrt)
instead of VC-LTL for non Self Extracting Executables stub components.
- Adjust the compilation configurations to optimize the binary size for the
Self Extracting Executables.
- Start to simplify the NanaZip specific decoders and encoders implementation.
- Enable disabling child process creation for NanaZip Self Extracting
Executables. (Except installer mode of Self Extracting Executables, which
compiled binaries is not provided in the NanaZip MSIX package.)
- Fixes
- Add GetDpiForWindowWrapper for NanaZip.Frieren.DarkMode to fix the legacy
Windows compatibility issues.
- Don't fail ModernSHBrowseForFolderW when DefaultFolder cannot be set.
(Contributed by dinhngtu.)
- Fix the issue that which NanaZip windows and dialogs will be opened in the
background when using NanaZip from context menu. (Contributed by R-YaTian.)
**NanaZip 3.1 (3.1.1080.0)**
- Try to discover the new Sponsor button design but finally reverted to the old
design for more natural looking. (Contributed by dongle-the-gadget and
Gaoyifei1011.)
- Improve Simplified Chinese translation. (Contributed by DeepChirp.)
- Improve the Sponsor Edition documentation. (Contributed by sirredbeard.)
- Improve Albanian translation. (Contributed by RDN000.)
- Improve German translation. (Contributed by CennoxX.)
- Fix several dark mode UI style issues. (Contributed by rounk-ctrl.)
- Ignore the text scale factor for solving the UI layout issues.
- Synchronize the 7-Zip mainline implementations to 24.08.
(https://github.com/ip7z/7zip/releases/tag/24.08) (Thanks to Igor Pavlov.
Noticed by atplsx and wallrik.)
- Synchronize the LZ4 implementations to 1.10.0.
(https://github.com/lz4/lz4/releases/tag/v1.10.0)
- Update Mile.Project.Windows submodule to the August 12, 2024 latest.
- Update VC-LTL to 5.1.1.
- Update YY-Thunks to 1.1.2.
- Update Mile.Windows.Helpers to 1.0.645.
- Update Mile.Xaml to 2.3.1064.
- Update Mile.Windows.Internal to 1.0.2971.
- Defer package updates while the app is running in Windows 11 23H2 or later.
(Suggested by AndromedaMelody.)
- Improve maintainer tools for introducing automatic packaging support when
building all targets for NanaZip.
**NanaZip 3.0 Update 1 (3.0.1000.0)**
- Update Mile.Windows.Internal to 1.0.2889.
- Make the 7-Zip Zstandard branch's specific options translatable. (Contributed
by ChuckMichael.)
- Polish translation for Sponsor dialog. (Contributed by ChuckMichael.)
- Fix compatibility issues with iFlyIME, Sogou Pinyin, and Transparent Flyout.
(Contributed by dinhngtu.)
- Update the UI layout for the sponsor button. (Suggested by namazso.)
- NanaZip will only check the Sponsor Edition addon licensing status the first
time you launch NanaZip File Manager or click the sponsor button to optimize
the user experience.
- Update NanaZip installation documentation. (Contributed by dongle-the-gadget.)
- Use Extract dialog when extracting without selection. (Contributed by
dinhngtu.)
- Fix tooltips from XAML controls cannot be transparent.
- Fix dark mode UI font rendering issues in some Windows 10 environments.
- Adjust the dark mode text color for improving the user experience. (Suggested
by userzzzq.)
- Synchronize the 7-Zip mainline implementations to 24.06.
(https://github.com/ip7z/7zip/releases/tag/24.06) (Thanks to Igor Pavlov.
Noticed by KsZAO.)
**NanaZip 3.0 (3.0.996.0)**
- Notes
- NanaZip 3.0 and onwards will have two distribution flavors called NanaZip
and NanaZip Classic. But NanaZip 3.0 does not have the Classic flavor yet
because it's not ready. Read
https://github.com/M2Team/NanaZip#differences-between-nanazip-and-nanazip-classic
for more information.
- The 32-bit x86 support for NanaZip packaged version is removed because
supported 32-bit x86 Windows versions don't support running on 32-bit
only x86 processors.
- NanaZip 3.0 and onwards will have NanaZip Sponsor Edition. Read
https://github.com/M2Team/NanaZip/blob/main/Documents/SponsorEdition.md
for more information.
- NanaZip has introduced the Preinstall Support. Read
https://github.com/M2Team/NanaZip/issues/398 for more information.
- Features
- Introducing dark mode support for all GUI components.
- Introducing the Mica support. You will enjoy the full window immersive Mica
support for all GUI components if you are using dark mode with HDR disabled.
(Thanks to Andarwinux.)
- Synchronize the 7-Zip mainline implementations to 24.05.
(https://github.com/ip7z/7zip/releases/tag/24.05) (Thanks to Igor Pavlov.
Noticed by AVMLOVER-4885955 and PopuriAO29.)
- Make NanaZip Self Extracting Executable stubs use 7-Zip mainline
Zstandard decoder instead of Zstandard official's for reducing the
size for binaries.
- Use 7-Zip mainline Zstandard decoder instead of Zstandard official
decoder for NanaZip.Core project.
- Remove 7-Zip mainline XXH64 Hash handler for NanaZip.Core because we
have the xxHash-based implementation in NanaZip.Codecs. It will have
much better performance, especially for non-x86 targets.
- Implement the new toolbar and use it to replace the old menubar and old
toolbar.
- Refresh the UI layout for About Dialog via following other Nana series
project design.
- Add the SM3 HASH algorithm from GmSSL. (https://github.com/guanzhi/GmSSL)
- Improvements
- Rewrite and split the implementation of the Core Library and the Self
Extracting Executable to the separate NanaZip.Codecs and NanaZip.Core
projects. Read https://github.com/M2Team/NanaZip/issues/336 for more
information.
- Ensure the implementation of Core Library and the Self Extracting Executable
supports Windows Vista RTM (Build 6000.16386).
- Reduce the binary size for the Self Extracting Executables.
- Synchronize the 7-Zip ZS implementations to the latest master branch.
(https://github.com/mcmilk/7-Zip-zstd/commit/79b2c78e9e7735ddf90147129b75cf2797ff6522)
- Synchronize Zstandard and builtin xxHash implementations to v1.5.6.
(https://github.com/facebook/zstd/releases/tag/v1.5.6)
- Synchronize Brotli implementations to v1.1.0.
(https://github.com/google/brotli/releases/tag/v1.1.0)
- Synchronize the RHash implementation to the latest master branch which is
after v1.4.4.
(https://github.com/rhash/RHash/commit/d916787590b9dc57eb9d420fd13e469160e0b04c)
- Synchronize the BLAKE3 implementation to latest master which is after 1.5.1.
(https://github.com/BLAKE3-team/BLAKE3/commit/0816badf3ada3ec48e712dd4f4cbc2cd60828278)
- Update to Git submodule version of Mile.Project.Windows.
(https://github.com/ProjectMile/Mile.Project.Windows)
- Update Mile.Windows.Helpers to 1.0.558.
(https://github.com/ProjectMile/Mile.Windows.Helpers/tree/1.0.558.0)
- Update Mile.Xaml to 2.2.944.
(https://github.com/ProjectMile/Mile.Xaml/releases/tag/2.2.944.0)
- Use Mile.Windows.Internal package.
(https://github.com/ProjectMile/Mile.Windows.Internal)
- Use Mile.Detours package.
(https://github.com/ProjectMile/Mile.Detours)
- Use modern IFileDialog for folder picker dialog. (Contributed by
reflectronic.)
- Launch directly to the settings page of association for NanaZip.
(Contributed by AndromedaMelody.)
- Show NanaZip in Drives' ContextMenu. (Contributed by AndromedaMelody.)
- Sync file extension support from https://github.com/mcmilk/7-Zip-zstd.
- Add other methods to compression dialog.
(https://github.com/mcmilk/7-Zip-zstd/commit/cf29d0c1babcd5ddf2c67eda8bb36e11f9c643b9)
- Reorder initialization in constructor matching to member declaration order.
(https://github.com/mcmilk/7-Zip-zstd/commit/8b011d230f1ccd8990943bd2eaad38d70e6e3fdf)
- Fix selectable uppercase / lowercase hash formatting.
(https://github.com/mcmilk/7-Zip-zstd/commit/4fae369d2d6aa60e2bb45eea1fb05659a2599caa)
- Update russian translation. (Contributed by Blueberryy.)
- Update Polish translation. (Contributed by ChuckMichael.)
- Add mitigation policy of disabling child process creation for command line
version of NanaZip. (Contributed by dinhngtu.)
- Add Explorer Patcher DLL blocking for NanaZip File Manager for reenabling
mitigation policy of blocking loading unexpected libraries from remote
sources at runtime for the main thread of NanaZip File Manager without the
stability issues. (Contributed by dinhngtu.)
- Fixes
- Fix issue in IEnumExplorerCommand::Next for shell extension. (Thanks to
cnbluefire.)
- Other adjustments for project development.
**NanaZip 2.0 Update 1 (2.0.450.0)**
- Optimize NanaZip binaries via adjusting the WindowsTargetPlatformMinVersion
to 10.0.19041.0 in all packaged NanaZip binaries projects except the Self
Extracting Executable stubs projects.
- Opt out of dynamic code mitigation on main NanaZip thread for resolving the
compatibility issues with Explorer Patcher. (Contributed by dinhngtu.)
- Update Mile.Xaml to 1.1.434.
(https://github.com/ProjectMile/Mile.Xaml/releases/tag/1.1.434.0)
- Update Mile.Windows.Helpers to 1.0.8.
(https://github.com/ProjectMile/Mile.Windows.Helpers/commits/main)
- Add dark mode support for context menus.
- Refresh the about dialog with Windows 11 XAML control styles and the
immersive Mica effects.
- Fix model dialog style behavior for About dialog.
- Continue to refresh application and file type icons. (Designed by
Shomnipotence.)
**NanaZip 2.0 (2.0.396.0)**
- Notes
- Update the minimum system requirement to Windows 10 Version 2004 (Build
1) or later for solving issues in the XAML Islands.
- Add instructions for installing NanaZip for all users. (Contributed by
AndromedaMelody. Suggested by Wolverine1977.)
- Features
- Integrate the following HASH algorithms to NanaZip from RHash (AICH,
BLAKE2b, BTIH, ED2K, EDON-R 224, EDON-R 256, EDON-R 384, EDON-R 512,
GOST R 34.11-94, GOST R 34.11-94 CryptoPro, GOST R 34.11-2012 256,
GOST R 34.11-2012 512, HAS-160, RIPEMD-160, SHA-224, SHA3-224, SHA3-256,
SHA3-384, SHA3-512, Snefru-128, Snefru-256, Tiger, Tiger2, TTH, Whirlpool)
and xxHash (XXH3_64bits, XXH3_128bits).
- Allow NanaZip to be associated with any file type. (Contributed by
manfromarce.)
- Add hfsx to file type association. (Suggested by AndromedaMelody.)
- Improvements
- Refresh application and file type icons. (Designed by Shomnipotence.)
- Refresh the about dialog with XAML Islands.
- Update 7-Zip to 22.01. (https://www.7-zip.org/history.txt) (Thanks to Igor
Pavlov. Noticed by HylianSteel, Random-name-hi and DJxSpeedy.)
- Update Zstandard to 1.5.2.
(https://github.com/facebook/zstd/releases/tag/v1.5.2).
- Update BLAKE3 to 1.3.1.
(https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.3.1)
- Update LZ4 to 1.9.4. (https://github.com/lz4/lz4/releases/tag/v1.9.4)
- Enable Control Flow Guard (CFG) to all target binaries for mitigating ROP
attacks. (Contributed by dinhngtu.)
- Mark all x86 and x64 target binaries as compatible with Control-flow
Enforcement Technology (CET) Shadow Stack. (Contributed by dinhngtu.)
- Strict handle checks at runtime to block the use of invalid handles.
(Contributed by dinhngtu.)
- Disable dynamic code generation in Release builds prevents generating
malicious code at runtime. (Contributed by dinhngtu. Thanks to
AndromedaMelody.)
- Block loading unexpected libraries from remote sources at runtime.
(Contributed by dinhngtu.)
- Enable Package Integrity Check. (Contributed by AndromedaMelody.)
- Enable EH Continuation Metadata. (Suggested by dinhngtu. Thanks to
mingkuang.)
- Enable Signed Returns.
- Add Mile.Xaml to NanaZip project.
- Start adding prerequisite support for unpackaged mode.
- Fixes
- Fix the shell extension issue which cause Everything crashed. (Thanks to
No5972, startkkkkkk, SakuraNeko, bfgxp and riverar.)
- Improve the Per-Monitor DPI Awareness support in Windows 10 Version 1607
for Self Extracting Executable stubs.
- Fix line break issue for i18n resource files. (Thanks to ygjsz.)
- Generate resource identities for package manifest manually. (Suggested by
AndromedaMelody.)
- Add workaround for NanaZip not appearing in classic context menu.
(Contributed by dinhngtu.)
- Check 7z compression parameter validity upon start of compression.
(Contributed by dinhngtu.)
**NanaZip 1.2 (1.2.252.0)**
- Fix no ordinal 345 was found in the dynamically attached library issue in
Self Extracting Executables. (Thanks to FadeMind.)
- Add Per-Monitor DPI-Aware support for all GUI components.
- Adjust and simplify the compiler options for modernizing.
- Fix i18n issue for the About dialog. (Thanks to AndromedaMelody.)
- Update installation tutorial. (Suggested by AndromedaMelody.)
- Fix cannot start editor issue when only store edition of notepad existed.
(Thanks to AndromedaMelody.)
- Modernize the i18n implementation via migrating language files from .txt to
.resw. (Contributed by AndromedaMelody. Suggested by Maicol Battistini.)
- Update ModernWin32MessageBox for solving the infinite loop issue in some
cases. (Thanks to AndromedaMelody.)
- Tweak icons and provide icons for preview versions. (Designed by Alice
(四月天). Thanks to StarlightMelody.)
- Fix crash issue when opening archive files. (Thanks to 1human and Maicol
Battistini.)
- Remove Language page in Options dialog because NanaZip will follow the
language settings from Windows itself.
- Fix the issue of the i18n implementation of File Type Association.
(Contributed by AndromedaMelody.)
- Add i18n support for GUI edition of Self Extracting Executable.
(Contributed by AndromedaMelody.)
**NanaZip 1.1 (1.1.194.0)**
- Add assembly implementations from 7-Zip back for improving performance.
- Reimplement the about dialog with Task Dialog.
- Modernize the message boxes with Task Dialog. (Thanks to DJxSpeedy.)
- Update 7-Zip to 21.07. (Thanks to Igor Pavlov. Noticed by HylianSteel.)
- Update translations inherited from 7-Zip.
- Update Deutsch translations. (Contributed by Hen Ry.)
- Update Polish translation. (Contributed by ChuckMichael.)
- Improve the multi volume rar file detection for solving
https://github.com/M2Team/NanaZip/issues/82. (Thanks to 1human.)
- Simplify the file type association definitions and add the open verb for
them. (Thanks to Fabio286.)
- Fix CI issue.
- Update VC-LTL to 5.0.4.
- Update C++/WinRT to 2.0.211028.7.
**NanaZip 1.0 (1.0.95.0)**
- Modernize the build toolchain with MSBuild for using MSIX packaging and
parallel compilation support. (Thanks to AndromedaMelody, be5invis,
青春永不落幕 and oxygen-dioxide.)
- Use [VC-LTL 5.x](https://github.com/Chuyu-Team/VC-LTL5) toolchain to make the
binary size even smaller than the official 7-Zip because we can use
ucrtbase.dll directly and the optimizations from modern compile toolchain.
(Thanks to mingkuang.)
- Add the context menu support in Windows 10/11 File Explorer. (Thanks to
shiroshan.)
- New icons. (Designed by Alice (四月天), Chi Lei, Kenji Mouri, Rúben Garrido
and Sakura Neko. Thanks to AndromedaMelody and 奕然.)
- Minor tweaks. (Thanks to adrianghc, Blueberryy, ChuckMichael, Legna, Maicol
Battistini, SakuraNeko and Zbynius.)
- Update 7-Zip from 21.03 to 21.06. (Noticed by Dan, lychichem and sanderdewit.
Thanks to Igor Pavlov.)
- Enable parsing the NSIS script support in the NSIS archives. (Suggested by
alanfox2000. Thanks to myfreeer.)
- Merge features from 7-Zip ZStandard branch. (Suggested by fcharlie. Thanks to
Tino Reichardt.)
================================================
FILE: Documents/ReleaseNotesPreview.md
================================================
# NanaZip Preview Release Notes
For stable versions, please read [NanaZip Release Notes](ReleaseNotes.md).
**NanaZip 6.5 Preview (6.5.16xx.0)**
- Includes all the improvements from NanaZip 6.0 Update 2 (6.0.1650.0).
- Introduce XAML XAML copy location dialog. (Contributed by dongle-the-gadget.)
**NanaZip 6.5 Preview (6.5.1638.0)**
This release includes all the improvements from NanaZip 6.0 Update 1
(6.0.1638.0).
**NanaZip 6.0 Final (6.0.1630.0)**
- Start to provide the official portable binaries package of NanaZip with both
Modern and Classic flavors, except the NanaZip File Manager.
- Fix several crash issues for the .NET Single File Application bundle readonly
support. (Thanks to haaeein.)
- Fix several hang issues for the ROMFS file system image readonly support
support. (Contributed by dinhngtu. Thanks to haaeein.)
- Fix several issues for context menu support. (Contributed by dinhngtu.)
- Synchronize 7-Zip mainline implementations to 26.00. (Except the NanaZip File
Manager.) (Thanks to Igor Pavlov. Noticed by FadeMind.)
- Improve the address bar UI layout. (Cooperated with dinhngtu. Suggested by
VinaC2.)
- Make the splitter bar fully white to workaround the light mode UI visual
issues in the 2 Panels mode.
- Fix the splitter bar cannot have Mica in the dark mode.
- Add the dark mode support for Win32 task dialog.
- Use Win32 TaskDialog to implement the Folders History dialog to simplify the
implementation.
- Introduce Group Policy Administrative Template (ADMX/ADML) for NanaZip.
(Contributed by dinhngtu.)
- Update Dutch translation. (Contributed by Stephan-P.)
- Synchronize the NanaZip File Manager implementations between NanaZip (Modern)
and NanaZip Classic.
- Fix some potential issues for the dark mode support.
- Try to partially improve the NanaZip File Manager main window keyboard
navigation experience.
- Update Mile.Project.Configurations to 1.0.1917, which solve some issues for
using NuGet Package References Support in Visual Studio 2026 version 18.3 or
later. (Cooperated by AndromedaMelody.)
- Update Mile.Windows.Internal to 1.0.3515.
- Update Mile.Xaml to 2.5.1616.
- Add RestoreNuGetPackages.cmd script to workaround some issues for people who
want to use Visual Studio to build NanaZip without running BuildAllTargets.bat
script.
**NanaZip 6.0 Preview 2 (6.0.1621.0)**
- Introduce NanaZip.Universal.Windows project for making NanaZip Command Line
Interface (Windows) for both NanaZip (Modern) and NanaZip Classic a.k.a.
NanaZipG or K7G to synchronize to the latest 7-Zip mainline and 7-Zip ZS
implementations.
- Introduce NanaZip Platform Base Library (K7Base) and NanaZip Platform User
Library (K7User) to replace NanaZip Platform Abstraction Layer (K7Pal) and
NanaZip.Frieren for better code sharing and maintainability.
- Redesign the security mitigation policies settings support (followed some
suggestions from dongle-the-gadget), also introduces several new security
mitigation policies like the archive handler and codec handler restriction
(which is contributed by dinhngtu). Read
https://github.com/M2Team/NanaZip/blob/main/Documents/Policies.md for more
information.
- Backport CVE-2025-0411 and CVE-2025-11001 for the NanaZip File Manager which
still use the old 7-Zip mainline codebase. (Contributed by dinhngtu.)
- Set the LOAD_LIBRARY_SEARCH_SYSTEM32 dependent load flag on Release builds of
Self Extracting Executables stubs to mitigate static imports level DLL
planting attack on Windows 10 build 14393 and later. (Contributed by
dinhngtu.)
- Allow to associate more file types to NanaZip. (Contributed by manfromarce.)
- Enable Ctrl+Backspace on edit fields using SHAutoComplete. (Contributed by
dinhngtu.)
- Fix the flickering issues when selecting list view in dark mode.
- Make texts have better contrast in dark mode.
- Make FastLZMA2 and Lizard reuse partial Zstandard implementations.
- Fix crash issue when using NanaZip.Core.Setup.sfx.
(https://github.com/M2Team/NanaZip/issues/795) (Thanks to kbarnes3.)
- Fix flickering XAML dialogs. (Contributed by dongle-the-gadget.)
- Fix crash issue from XAML address bar. (Contributed by dongle-the-gadget.)
- Use a low name as the shell extension name prefix to work around our context
menu not appearing in the classic context menu. (Contributed by dinhngtu.)
- Don't reset compression method after changing level. (Contributed by
dongle-the-gadget.)
- Fix text overflow in German translation. (Contributed by Pinguin2001.)
- Localize Open Inside menu text. (Contributed by dinhngtu.)
- Remove Help button from compress option dialogs. (Contributed by peashooter2.)
- Fix UI assignment of WriteZone setting. (Contributed by dinhngtu.)
- Handle Add button when inside archives. (Contributed by dinhngtu.)
- Use assembly hardware acceleration for BLAKE3 implementation.
- Fix issues for NanaZip Preview SVG icon assets for Contrast Black mode.
- Update the icon assets with optimized assets to reduce the binary size.
- Don't contain Mile.Project.Wap.Unstaged.targets in the MSIX package.
- Synchronize 7-Zip mainline implementations to 25.01 for NanaZip components
which still use the old 7-Zip mainline codebase (command line version).
(Thanks to Igor Pavlov.)
- Synchronize the 7-Zip ZS implementations to
https://github.com/mcmilk/7-Zip-zstd/tree/5766dd7745f6517f7ea42f6de9a190dfd92aa25f.
(Except the NanaZip File Manager.) (Thanks to Sergey G. Brester and Tino
Reichardt.)
- Synchronize Brotli implementations to v1.2.0.
(https://github.com/google/brotli/releases/tag/v1.2.0)
- Synchronize the FastLZMA2 implementations to
https://github.com/conor42/fast-lzma2/tree/a793db99fade2957d2453035390f97e573acecb2,
which can fix some issues. (Contributed by dinhngtu.)
- Synchronize the BLAKE3 implementation to 1.8.3.
(https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.8.3)
- Synchronize RHash to the latest master
(https://github.com/rhash/RHash/tree/b76c6a3312422c09817c2cef40442b2f2d9d4689)
which is after v1.4.6.
- Update Mile.Project.Configurations to 1.0.1827.
- Update Mile.Mobility to 1.0.372.
- Update Mile.Project.Helpers to 1.0.975.
- Update Mile.Windows.Helpers to 1.0.1171.
- Update Mile.Detours to 1.0.2180.
- Update .NET projects to .NET 10 and update NuGet package dependencies.
- Add Release Tags to NanaZip Versioning.
- Migrate solution from sln to slnx, and start to build with MSVC 14.50 toolset.
- Support opening NanaZip Visual Studio solution without installing WinUI
application and/or Universal Windows Platform development workload.
(Contributed by AndromedaMelody.)
- Make the precompiled build tools generated by GitHub Actions workflow
automatically.
- Improve several implementations and fix several issues.
**NanaZip 6.0 Preview 1 (6.0.1461.0)**
- Start to transition to community driven development model.
- Introduce extract-on-open feature. (Contributed by dinhngtu.)
- To disable this temporarily, hold Shift while opening the file.
- To disable this permanently, go to Settings, Integration tab, and disable
"Extract on open" at the bottom.
- Introduce formal version of contributing guide and security policies.
(Cooperated with dinhngtu and dongle-the-gadget.)
- Update system requirement to Windows 10, version 2004 (Build 19041) or later,
and remove the x86 (32-bit) for all components.
- Start to use Zstandard decoder instead of 7-Zip mainline's implementation for
better reliability, especially it can reduce more potential vulnerabilities.
- Introduce the XAML-based address bar. (Contributed by dongle-the-gadget.)
- Introduce the XAML-based status bar. (Contributed by dongle-the-gadget.)
- Introduce the XAML-based properties and information dialog. (Contributed by
dongle-the-gadget.)
- Introduce the XAML-based progress dialog. (Contributed by dongle-the-gadget.)
- Improve the Smart Extraction feature. (Contributed by R-YaTian.)
- Introduce extract all automatically policy when opening executable files in
archives. (Contributed by MajThomas.)
- Introduce the environment variable parsing support for address bar. (Thanks to
dongle-the-gadget's huge help.)
- Improve the NanaZip startup performance by initializing the StoreContext
later. (Contributed by dongle-the-gadget.)
- Add support for CBR and CBZ file associations. (Contributed by dinhngtu.)
- Add support for ASAR file association. (Contributed by dongle-the-gadget.)
- Display file system version in archive property window for the UFS/UFS2 file
system image readonly support.
- Display bundle version in archive property for the .NET Single File
Application bundle readonly support.
- Display file system version in archive property for the littlefs file system
image readonly support.
- Fix the parsing padding issue for Electron Archive (asar) readonly support.
(Contributed by Vlad-Andrei Popescu).
- Improve the ZealFS file system image readonly support implementation to fix
several issues. (Cooperated with Zeal 8-bit.)
- Try to bring dialog window to the foreground to resolve user experience issues
when opened from context menu. (Contributed by dinhngtu.)
- Move open folder checkbox to extract dialog. (Contributed by dinhngtu.)
- Introduce registry settings for Mark of the Web (MoTW) enforcement policies.
(Contributed by dinhngtu.)
- Improve the dynamic library block list for resolving compatibility issues.
(Contributed by dinhngtu.)
- Introduce registry settings for disabling security mitigation policies, which
should be helpful for debugging and resolving compatibility issues.
(Contributed by dinhngtu.)
- Fix dead loop issue when compressing files with Brotli, Lizard, LZ4 and LZ5
mentioned in https://github.com/M2Team/NanaZip/issues/639. (Thanks to
gigano01, InfiniteLoopGameDev and iOrange.)
- Fix the unable to return the processed bytes count issue for
NanaZipCodecsReadInputStream.
- Fix some string resources issues. (Contributed by dinhngtu.)
- Fix issues in compression levels combobox. (Contributed by dongle-the-gadget.)
- Update Albanian translation. (Contributed by F1219R.)
- Update Hungarian translation. (Contributed by John Fowler.)
- Update Greek translation. (Contributed by Lefteris T.)
- Update German translation. (Contributed by HackZy01.)
- Update Bengali translation. (Contributed by Sumon Kayal.)
- Synchronize 7-Zip mainline implementations to 25.01. (Thanks to Igor Pavlov.
Noticed by FadeMind and Pinguin2001.)
- Synchronize the 7-Zip ZS implementations to
https://github.com/mcmilk/7-Zip-zstd/tree/2a2dcb293b80180dc305544bf6a9e081750bccfe.
(Thanks to Sergey G. Brester and Tino Reichardt.)
- Update Zstandard to v1.5.7. (Noticed by dcog989.)
- Update Lizard to v2.1.
- Synchronize the BLAKE3 implementation to 1.8.2. (Noticed by peashooter2.)
- Synchronize the RHash implementation to latest master a.k.a.
https://github.com/rhash/RHash/commit/cce6c628f93d9ed332921656aa5e1750d12b8d3e
which is after v1.4.6.
- Update Mile.Windows.Helpers to 1.0.952.
- Update Mile.Windows.Internal to 1.0.3259.
- Update Mile.Json to 1.0.1057.
- Add littlefs v2.10.2 to NanaZip.Codecs for future development of work in
progress littlefs archive format readonly support.
- Create NanaZip.Modern project for the modern user experience development.
- Introduce Mile.Mobility dependence to NanaZip.Codecs project for making better
portability between NanaZip and AptxZip (a.k.a. NanaZip for POSIX).
- Introduce NanaZip.ExtensionPackage project for future development of features
which need to be distributed as legacy installer. (Contributed by dinhngtu.)
- Introduce Mile.Helpers.Portable.Base.Unstaged as the temporary infrastructure
to standardize some portable things in NanaZip.Codecs.
- Introduce NanaZip.Codecs.Specification.Fat for adding definitions of FAT12,
FAT16 and FAT32.
- Introduce NanaZip.Codecs.Specification.Zealfs for adding definitions of
ZealFS series file system. (Cooperated with Zeal 8-bit.)
- Add littlefs v1 on-disk definitions to the littlefs file system image readonly
support.
- Introduce Mile.Project.Wap.Unstaged.targets for solving the issue that
unnecessary XAML files contained in the final MSIX package.
- Add XAML Styler indentation configuration. (Contributed by dongle-the-gadget.)
- Use x-generate to define language resources in AppX manifest to solve the
Windows AppX language fallback issue. (Suggested by dongle-the-gadget.)
- Update build binary logs when failed to build in GitHub Actions. (Contributed
by dongle-the-gadget.)
- Introduce legacy string migrator. (Contributed by dongle-the-gadget.)
- Add more targeted editorconfig rules. (Contributed by dongle-the-gadget.)
- Move NanaZip.Core's NanaZip.Core.Console project to NanaZip.Universal's
NanaZip.Universal.Console project.
- Disable WinRT metadata generation for all WinRT component consumers.
- Move NanaZip.Modern as the first item to workaround the AppX toolchain
manifest generation issues.
- Improve the GitHub Actions artifacts generation.
- Update to Windows 11 SDK Build 26100 for NanaZipPackage.
- Fix the source code file header comment format.
- Use C++ zero initialization to reduce potential issues.
- Introduce reproducible build support for the whole project.
**NanaZip 5.1 Preview 0 (5.1.1263.0)**
This release includes all the improvements from NanaZip 5.0 Update 2
(5.0.1263.0).
**NanaZip 5.1 Preview 0 (5.1.1252.0)**
This release includes all the improvements from NanaZip 5.0 Update 1
(5.0.1252.0).
**NanaZip 5.0 Preview 2 (5.0.1243.0)**
- Continue to improve the work-in-progress NanaZip Platform Abstraction Layer
(K7Pal). (https://github.com/M2Team/NanaZip/tree/main/K7Pal)
- Fix the crash and encrypted RAR5 format extraction wrong password issue for
7-Zip's hash algorithms wrappers which mentioned in
https://github.com/M2Team/NanaZip/issues/542. (Thanks to RuesanG.)
- Introduce K7PalHashDuplicate API.
- Remove K7PalHashReset API for improving the security.
- Reduce the saved information in hash contexts to improve the security.
- Use NanaZip Platform Abstraction Layer (K7Pal) to implement 7-Zip's SHA-1
hash algorithms.
- Update zh-Hans and zh-Hant translations for 'Want * History' strings.
(Contributed by R-YaTian.) (Forget to mentioned in NanaZip 5.0 Preview 1.)
- Adds a setting for opening the folder after extracting from archive.
(Contributing by DaxDupont.)
- Introduce the Smart Extraction. (Contributed by R-YaTian.)
- Fix the issue that which NanaZip windows and dialogs will be opened in the
background when using NanaZip from context menu. (Contributed by R-YaTian.)
- Update xxHash to v0.8.3.
(https://github.com/Cyan4973/xxHash/releases/tag/v0.8.3)
**NanaZip 5.0 Preview 1 (5.0.1215.0)**
- Introduce NanaZip Platform Abstraction Layer (K7Pal) for wrapping the platform
specific infrastructures. (https://github.com/M2Team/NanaZip/tree/main/K7Pal)
(Work In Progress)
- Provide hash functions interfaces implemented with Windows CNG API. NanaZip
uses these hash functions from K7Pal:
- MD2
- MD4
- MD5
- SHA-1
- SHA-256
- SHA-384
- SHA-512
- ED2K (Implemented as the K7Pal MD4 wrapper in NanaZip.Codecs.)
- Synchronize the 7-Zip mainline implementations to 24.09.
(https://github.com/ip7z/7zip/releases/tag/24.09) (Thanks to Igor Pavlov.
Noticed by FadeMind and peashooter2.)
- Finally move NanaZip console version to NanaZip.Core project.
- Don't fail ModernSHBrowseForFolderW when DefaultFolder cannot be set.
(Contributed by dinhngtu.)
- Update Mile.Windows.UniCrt to 1.1.278.
**NanaZip 5.0 Preview 0 (5.0.1188.0)**
- This release includes all the improvements from NanaZip 3.1 (3.1.1080.0)
(https://github.com/M2Team/NanaZip/releases/tag/3.1.1080.0).
- Update Brazilian Portuguese translation. (Contributed by maisondasilva.)
- Make sure NanaZip Core (except the Self Extracting Executables) and NanaZip
Classic using ucrtbase.dll with 10.0.19041.0 version or later.
- Update Mile.Windows.Helpers to 1.0.671.
(https://github.com/ProjectMile/Mile.Windows.Helpers/tree/1.0.671.0)
- Move NanaZip console version to NanaZip.Core project. (Not used in NanaZip
MSIX package because we need to release the next preview to contain the
CVE-2024-11477 fix in NanaZip 3.1.)
- Remove C++/WinRT dependency for NanaZip.Codecs and NanaZip.Frieren.
- Add GetDpiForWindowWrapper for NanaZip.Frieren.DarkMode to fix the legacy
Windows compatibility issues.
- Remove VC-LTL dependency for the Self Extracting Executables related projects.
- Adjust the compilation configurations to optimize the binary size for the Self
Extracting Executables.
- Use Mile.Windows.UniCrt (https://github.com/ProjectMile/Mile.Windows.UniCrt)
instead of VC-LTL.
- Update NanaZip.Specification.SevenZip header file.
- Start to simplify the NanaZip specific decoders and encoders implementation.
- Synchronize the BLAKE3 implementation to 1.5.5.
(https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.5.5)
- Synchronize the RHash implementation to the latest master branch which is
after v1.4.5.
(https://github.com/rhash/RHash/commit/cf2adf22ae7c39d9b8e5e7b87222046a8f42b3dc)
- Enable disabling child process creation for NanaZip Self Extracting
Executables. (Except installer mode of Self Extracting Executables, which
compiled binaries is not provided in the NanaZip MSIX package.)
**NanaZip 3.5 Preview 0 (3.5.1000.0)**
This release includes all the improvements from NanaZip 3.0 Update 1
(3.0.1000.0).
**NanaZip 3.5 Preview 0 (3.5.996.0)**
This release includes all the improvements from NanaZip 3.0 (3.0.996.0).
**NanaZip 3.0 Preview 0 (3.0.756.0)**
- Rewrite and split the implementation of the Core Library and the Self
Extracting Executable to the separate NanaZip.Core project.
- Ensure the implementation of Core Library and the Self Extracting Executable
supports Windows Vista RTM (Build 6000.16386).
- Reduce the binary size for the Self Extracting Executables.
- Synchronize the 7-Zip mainline implementations to 23.01.
(https://www.7-zip.org/history.txt)
- Synchronize the 7-Zip ZS implementations to the latest master branch.
(https://github.com/mcmilk/7-Zip-zstd/commit/ce27b4a0d3a94313d256c3d077f1784baffb9eee)
- Add the SM3 HASH algorithm from GmSSL.
(https://github.com/guanzhi/GmSSL)
- Synchronize Zstandard and builtin xxHash implementations to v1.5.5.
(https://github.com/facebook/zstd/releases/tag/v1.5.5)
- Synchronize Brotli implementations to v1.1.0.
(https://github.com/google/brotli/releases/tag/v1.1.0)
- Synchronize the RHash implementation to the latest master branch.
(https://github.com/rhash/RHash/commit/b8c91ea6551e99e10352386cd46ea26973bb4a4d)
- Update to Git submodule version of Mile.Project.Windows.
(https://github.com/ProjectMile/Mile.Project.Windows)
- Update Mile.Windows.Helpers to 1.0.15.
(https://github.com/ProjectMile/Mile.Windows.Helpers/commit/b522a956f7dd42dc205869d362f96a777bcb2aa0)
- Update Mile.Xaml to 2.1.661.
(https://github.com/ProjectMile/Mile.Xaml/releases/tag/2.1.661.0)
- Update russian translation. (Contributed by Blueberryy.)
- Fix the text wrapping issue in the About dialog. (Thanks to MenschenToaster.)
- Use modern IFileDialog for folder picker dialog. (Contributed by
reflectronic.)
- Launch directly to the settings page of association for NanaZip. (Contributed
by AndromedaMelody.)
- Show NanaZip in Drives' ContextMenu. (Contributed by AndromedaMelody.)
- Sync file extension support from https://github.com/mcmilk/7-Zip-zstd.
- Add other methods to compression dialog.
(https://github.com/mcmilk/7-Zip-zstd/commit/cf29d0c1babcd5ddf2c67eda8bb36e11f9c643b9)
- Reorder initialization in constructor matching to member declaration order.
(https://github.com/mcmilk/7-Zip-zstd/commit/8b011d230f1ccd8990943bd2eaad38d70e6e3fdf)
- Fix selectable uppercase / lowercase hash formatting.
(https://github.com/mcmilk/7-Zip-zstd/commit/4fae369d2d6aa60e2bb45eea1fb05659a2599caa)
- Other adjustments for project development.
**NanaZip 2.1 Preview 0 (2.1.451.0)**
- Update icons. (Designed by Shomnipotence. Updated in NanaZip 2.0 Stable.)
- Add instructions for installing NanaZip for all users. (Updated in NanaZip
2.0 Stable.)
- Add Mile.Xaml to NanaZip project. (Updated in NanaZip 2.0 Stable.)
- Refresh the about dialog with XAML Islands. (Updated in NanaZip 2.0 Stable.)
- Start adding prerequisite support for unpackaged mode. (Updated in NanaZip
2.0 Stable.)
- Optimize NanaZip binaries via adjusting the WindowsTargetPlatformMinVersion
to 10.0.19041.0 in all packaged NanaZip binaries projects except the Self
Extracting Executable stubs projects. (Updated in NanaZip 2.0 Update 1.)
- Opt out of dynamic code mitigation on main NanaZip thread for resolving the
compatibility issues with Explorer Patcher. (Contributed by dinhngtu. Updated
in NanaZip 2.0 Update 1.)
- Update Mile.Xaml to 1.1.434. (Updated in NanaZip 2.0 Update 1.)
(https://github.com/ProjectMile/Mile.Xaml/releases/tag/1.1.434.0)
- Update Mile.Windows.Helpers to 1.0.8. (Updated in NanaZip 2.0 Update 1.)
(https://github.com/ProjectMile/Mile.Windows.Helpers/commits/main)
- Add dark mode support for context menus. (Updated in NanaZip 2.0 Update 1.)
- Refresh the about dialog with Windows 11 XAML control styles and the
immersive Mica effects. (Updated in NanaZip 2.0 Update 1.)
- Fix model dialog style behavior for About dialog. (Updated in NanaZip 2.0
Update 1.)
- Continue to refresh application and file type icons. (Designed by
Shomnipotence. Updated in NanaZip 2.0 Update 1.)
**NanaZip 2.0 Preview 2 (2.0.376.0)**
- Update 7-Zip to 22.01. (Thanks to Igor Pavlov. Noticed by HylianSteel,
Random-name-hi and DJxSpeedy.)
- Add hfsx to file type association. (Suggested by AndromedaMelody.)
- Update the minimum system requirement to Windows 10 Version 2004 (Build 19041)
or later for solving issues in the XAML Islands.
- Update LZ4 to v1.9.4.
- Enable Package Integrity. (Contributed by AndromedaMelody.)
- Don't enable "Disable dynamic code generation" mitigation in Debug builds for
solving codec load error issue. (Thanks to AndromedaMelody.)
- Continue to enable several security mitigations.
- Enable EH Continuation Metadata.
- Enable Signed Returns.
- Generate resource identities for package manifest manually. (Suggested by
AndromedaMelody.)
- Add workaround for NanaZip not appearing in classic context menu.
(Contributed by dinhngtu.)
- Check 7z compression parameter validity upon start of compression.
(Contributed by dinhngtu.)
- Update icons. (Designed by Shomnipotence.)
**NanaZip 2.0 Preview 1 (2.0.313.0)**
- Fix the shell extension issue which cause Everything crashed. (Thanks to
No5972, startkkkkkk, SakuraNeko, bfgxp and riverar.)
- Allow NanaZip to be associated with any file type. (Contributed by
manfromarce.)
- Update 7-Zip to 22.00. (Thanks to Igor Pavlov. Noticed by HylianSteel.)
- Integrate the following HASH algorithms to NanaZip from RHash and xxHash.
- AICH
- BLAKE2b
- BTIH
- ED2K
- EDON-R 224, EDON-R 256, EDON-R 384, EDON-R 512
- GOST R 34.11-94, GOST R 34.11-94 CryptoPro
- GOST R 34.11-2012 256, GOST R 34.11-2012 512
- HAS-160, RIPEMD-160
- SHA-224
- SHA3-224, SHA3-256, SHA3-384, SHA3-512
- Snefru-128, Snefru-256
- Tiger, Tiger2
- TTH
- Whirlpool
- XXH3_64bits, XXH3_128bits
- Update Zstandard to 1.5.2.
- Update BLAKE3 to 1.3.1.
- Improve the Per-Monitor DPI Awareness support in Windows 10 Version 1607 for
Self Extracting Executable stubs.
- Fix line break issue for i18n resource files. (Thanks to ygjsz.)
- Enable several security mitigations. (Contributed by dinhngtu.)
- Enable Control Flow Guard (CFG) to all target binaries for mitigating ROP
attacks.
- Mark all x86 and x64 target binaries as compatible with Control-flow
Enforcement Technology (CET) Shadow Stack.
- Strict handle checks at runtime to block the use of invalid handles.
- Disable dynamic code generation prevents generating malicious code at
runtime.
- Block loading unexpected libraries from remote sources at runtime.
**NanaZip 1.2 Update 1 Preview 1 (1.2.253.0)**
- Fix the issue of the i18n implementation of File Type Association.
(Contributed by AndromedaMelody. Updated in NanaZip 1.2 Stable.)
- Add i18n support for GUI edition of Self Extracting Executable.
(Contributed by AndromedaMelody. Updated in NanaZip 1.2 Stable.)
**NanaZip 1.2 Preview 4 (1.2.225.0)**
- Continue to update ModernWin32MessageBox for solving the infinite loop issue
in some cases. (Thanks to AndromedaMelody.)
- Fix crash issue when opening archive files. (Thanks to 1human and Maicol
Battistini.)
- Remove Language page in Options dialog because NanaZip will follow the
language settings from Windows itself.
**NanaZip 1.1 Servicing Update 1 Preview 3 (1.1.220.0)**
- Modernize the i18n implementation via migrating language files from .txt to
.resw. (Contributed by AndromedaMelody. Suggested by Maicol Battistini.)
- Update ModernWin32MessageBox for solving the infinite loop issue in some
cases. (Thanks to AndromedaMelody.)
- Tweak icons and provide icons for preview versions. (Designed by Alice
(四月天). Thanks to StarlightMelody.)
**NanaZip 1.1 Servicing Update 1 Preview 2 (1.1.201.0)**
- Fix no ordinal 345 was found in the dynamically attached library issue in
Self Extracting Executables. (Thanks to FadeMind.)
- Add Per-Monitor DPI-Aware support for all GUI components.
- Adjust and simplify the compiler options for modernizing.
- Fix i18n issue for the About dialog. (Thanks to AndromedaMelody.)
- Update installation tutorial. (Suggested by AndromedaMelody.)
- Fix cannot start editor issue when only store edition of notepad existed.
(Thanks to AndromedaMelody.)
**NanaZip 1.1 Servicing Update 1 Preview 1 (1.1.196.0)**
- Simplify the file type association definitions and add the open verb for
them. (Thanks to Fabio286. Fixed in NanaZip 1.1 Stable.)
- Update VC-LTL to 5.0.4. (Updated in NanaZip 1.1 Stable.)
**NanaZip 1.1 Preview 2 (1.1.153.0)**
- Fix the issue which can't load context menu properly. (Thanks to DJxSpeedy.)
**NanaZip 1.1 Preview 2 (1.1.152.0)**
- Reimplement the about dialog with Task Dialog.
- Update Deutsch translations. (Contributed by Hen Ry.)
- Add assembly implementations from 7-Zip back for improving performance.
- Update translations inherited from 7-Zip.
- Update 7-Zip to 21.07. (Thanks to Igor Pavlov. Noticed by HylianSteel.)
- Improve the multi volume rar file detection for solving
https://github.com/M2Team/NanaZip/issues/82. (Thanks to 1human.)
- Modernize the message boxes with Task Dialog.
**NanaZip 1.1 Preview 1 (1.1.101.0)**
- Exclude .webp in the archive file type list for solving
https://github.com/M2Team/NanaZip/issues/57. (Thanks to Zbynius. Fixed in
NanaZip 1.0 Stable.)
- Update Polish translation. (Contributed by ChuckMichael.)
- Fix CI issue.
- Update VC-LTL to 5.0.3.
- Update C++/WinRT to 2.0.211028.7.
**NanaZip 1.0 Preview 4 (1.0.88.0)**
- Update Italian, Russian and Polish Translations. (Contributed by Blueberryy,
Maicol Battistini and ChuckMichael.)
- Provide 7-Zip execution alias for helping users to migrate to NanaZip.
(Suggested by AndromedaMelody.)
- Adjust file association icon. (Suggested by 奕然.)
- Merge features from 7-Zip ZStandard branch. (Suggested by fcharlie. Thanks to
Tino Reichardt.)
- Update 7-Zip to 21.06. (Noticed by Dan, lychichem and sanderdewit. Thanks to
Igor Pavlov.)
- Fix compression level display issue in the compress dialog. (Thanks to
SakuraNeko.)
- Make every file extension have own file type in file type association
definitions for solving https://github.com/M2Team/NanaZip/issues/53. (Thanks
to oxygen-dioxide.)
- Disable virtualization:ExcludedDirectories for resolve
https://github.com/M2Team/NanaZip/issues/34. (Thanks to AndromedaMelody.)
- Reduce the compilation warnings.
- Change the configuration for NanaZipPackage project for solve the issue when
referencing the Windows Runtime Components.
- Update Mile.Cpp.
**NanaZip 1.0 Preview 3 (1.0.46.0)**
- Enable parsing the NSIS script support in the NSIS archives. (Suggested by
alanfox2000. Thanks to myfreeer.)
- Simplify the separator layout in the context menu implementation.
- Fix app still displays in folder context menu, resulting in empty entry
that doesn't do anything when no options that could interact. (Thanks to
shiroshan.)
- Fix the application crash in some cases caused by some issues in the
exception handler implementation from VC-LTL 5.x. (Thanks to mingkuang.)
- Update new icons. (Designed by Alice (四月天), Chi Lei, Kenji Mouri, Rúben
Garrido and Sakura Neko.)
- Make main NanaZip package contains all resources.
- Fix the command line help string. (Thanks to adrianghc.)
**NanaZip 1.0 Preview 2 (1.0.31.0)**
- Remove IObjectWithSite in shell extension implementation to reduce the
complexity and crashes.
- Add altform-lightunplated assets for display the contrast standard mode icon
in the taskbar instead of contrast white icon. (Thanks to AndromedaMelody.)
- Remove Windows.Universal TargetDeviceFamily for solving the minimum OS
requirements display issue. (Thanks to 青春永不落幕.)
- Enable NanaZipC and NanaZipG in AppX manifest. (Thanks to be5invis.)
- Change "The operation can require big amount of RAM (memory)" error dialog to
warning dialog. (Thanks to Legna.)
**NanaZip 1.0 Preview 1 (1.0.25.0)**
- Modernize the build toolchain with MSBuild for using MSIX packaging and
parallel compilation support.
- Use [VC-LTL 5.x](https://github.com/Chuyu-Team/VC-LTL5) toolchain to make the
binary size even smaller than the official 7-Zip because we can use
ucrtbase.dll directly and the optimizations from modern compile toolchain.
- Add the context menu support in Windows 10/11 File Explorer.
- New icons and minor UI tweaks.
================================================
FILE: Documents/Section508/NanaZip.html
================================================
NanaZip Accessibility Conformance Report NanaZip Accessibility Conformance Report
Based on VPAT® 2.4 WCAG 2.1 and Revised Section 508 Edition
Name of Product/Version NanaZip
Report Dates and Version Report Date: 2026/2/25 Last Modified Date: 2026/2/25 Version: nanazip-1 Product Description NanaZip is an open source file archiver intended for the modern Windows experience, forked from the source code of well-known open source file archiver 7-Zip.
Author Information Vendor Information Applicable Standards/Guidelines
This report covers the degree of conformance for the following accessibility standard/guidelines:
Terms
The terms used in the Conformance Level information are defined as follows:
Supports : The functionality of the product has at least one method that meets the criterion without known defects or meets with equivalent facilitation.Partially Supports : Some functionality of the product does not meet the criterion.Does Not Support : The majority of product functionality does not meet the criterion.Not Applicable : The criterion is not relevant to the product.Not Evaluated : The product has not been evaluated against the criterion. This can be used only in WCAG 2.x Level AAA. WCAG 2.1 Report Table 1: Success Criteria, Level A Table 2: Success Criteria, Level AA Table 3: Success Criteria, Level AAA Revised Section 508 Report Chapter 4: Hardware Chapter 5: Software Chapter 6: Support Documentation and Services Repository https://github.com/M2Team/NanaZip (opens in a new window or tab) Feedback https://github.com/M2Team/NanaZip (opens in a new window or tab)
================================================
FILE: Documents/Section508/NanaZip.yaml
================================================
title: NanaZip Accessibility Conformance Report
product:
name: NanaZip
version: ''
description: >-
NanaZip is an open source file archiver intended for the modern Windows
experience, forked from the source code of well-known open source file
archiver 7-Zip.
author:
name: Kenji Mouri
company_name: M2-Team
address: ''
email: Kenji.Mouri@outlook.com
phone: ''
website: 'http://nanazip.org/'
vendor:
name: Kenji Mouri
company_name: M2-Team
address: ''
email: Kenji.Mouri@outlook.com
phone: ''
website: 'http://nanazip.org/'
report_date: 2026/2/25
last_modified_date: 2026/2/25
version: 1
notes: ''
evaluation_methods_used: ''
legal_disclaimer: ''
repository: 'https://github.com/M2Team/NanaZip'
feedback: 'https://github.com/M2Team/NanaZip'
license: MIT
related_openacrs: []
catalog: 2.4-edition-wcag-2.1-508-en
chapters:
success_criteria_level_a:
notes: ''
disabled: true
criteria:
- num: 1.1.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.2.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.2.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.2.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.3.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.3.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.3.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.1.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.1.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.1.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.2.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.2.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.3.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.5.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.5.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.5.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.5.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.1.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.2.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.2.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.3.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.3.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 4.1.1
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 4.1.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
success_criteria_level_aa:
notes: ''
disabled: true
criteria:
- num: 1.2.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.2.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.3.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.3.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.10
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.11
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.12
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.13
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.7
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.1.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.2.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.2.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.3.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.3.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 4.1.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
success_criteria_level_aaa:
notes: ''
disabled: true
criteria:
- num: 1.2.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.2.7
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.2.8
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.2.9
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.3.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.7
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.8
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 1.4.9
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.1.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.2.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.2.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.2.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.2.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.3.2
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.3.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.8
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.9
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.4.10
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.5.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 2.5.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.1.3
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.1.4
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.1.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.1.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.2.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.3.5
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
- num: 3.3.6
components:
- name: web
adherence:
level: ''
notes: ''
- name: electronic-docs
adherence:
level: ''
notes: ''
- name: software
adherence:
level: ''
notes: ''
- name: authoring-tool
adherence:
level: ''
notes: ''
functional_performance_criteria:
notes: ''
disabled: false
criteria:
- num: '302.1'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.2'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.3'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.4'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.5'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.6'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.7'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.8'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '302.9'
components:
- name: none
adherence:
level: supports
notes: ''
hardware:
notes: ''
disabled: true
criteria:
- num: 402.2.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 402.2.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 402.2.3
components:
- name: none
adherence:
level: ''
notes: ''
- num: 402.2.4
components:
- name: none
adherence:
level: ''
notes: ''
- num: 402.2.5
components:
- name: none
adherence:
level: ''
notes: ''
- num: 402.3.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 402.3.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: '402.4'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '402.5'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '403.1'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '404.1'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '405.1'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '406.1'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '407.2'
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.3.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.3.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.3.3
components:
- name: none
adherence:
level: ''
notes: ''
- num: '407.4'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '407.5'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '407.6'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '407.7'
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.1.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.1.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.2.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.2.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.3
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.3.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.3.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.3.2.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 407.8.3.2.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: '408.2'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '408.3'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '409.1'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '410.1'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '411.1'
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.2.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.2.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.3.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.3.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: '412.4'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '412.5'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '412.6'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '412.7'
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.8.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.8.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.8.3
components:
- name: none
adherence:
level: ''
notes: ''
- num: 412.8.4
components:
- name: none
adherence:
level: ''
notes: ''
- num: 413.1.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 413.1.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 414.1.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 414.1.2
components:
- name: none
adherence:
level: ''
notes: ''
- num: 415.1.1
components:
- name: none
adherence:
level: ''
notes: ''
- num: 415.1.2
components:
- name: none
adherence:
level: ''
notes: ''
software:
notes: ''
disabled: false
criteria:
- num: 502.2.1
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.2.2
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.1
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.2
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.3
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.4
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.5
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.6
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.7
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.8
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.9
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.10
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.11
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.12
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.13
components:
- name: none
adherence:
level: supports
notes: ''
- num: 502.3.14
components:
- name: none
adherence:
level: supports
notes: ''
- num: '502.4'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '503.2'
components:
- name: none
adherence:
level: supports
notes: ''
- num: '503.3'
components:
- name: none
adherence:
level: not-applicable
notes: ''
- num: 503.4.1
components:
- name: none
adherence:
level: not-applicable
notes: ''
- num: 503.4.2
components:
- name: none
adherence:
level: not-applicable
notes: ''
- num: '504.2'
components:
- name: none
adherence:
level: not-applicable
notes: ''
- num: 504.2.1
components:
- name: none
adherence:
level: not-applicable
notes: ''
- num: 504.2.2
components:
- name: none
adherence:
level: not-applicable
notes: ''
- num: '504.3'
components:
- name: none
adherence:
level: not-applicable
notes: ''
- num: '504.4'
components:
- name: none
adherence:
level: not-applicable
notes: ''
support_documentation_and_services:
notes: ''
disabled: true
criteria:
- num: '602.2'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '602.3'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '602.4'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '603.2'
components:
- name: none
adherence:
level: ''
notes: ''
- num: '603.3'
components:
- name: none
adherence:
level: ''
notes: ''
================================================
FILE: Documents/SponsorEdition.md
================================================
# NanaZip Sponsor Edition
NanaZip provides a $99.99 USD Sponsor Edition addon to the Microsoft Store to
attract more sponsors and contributors.
It's free for NanaZip source code repository contributors and NanaZip sponsors
who sponsored before March 30, 2024.
## Feature
The only difference for NanaZip Sponsor Edition is showing "Appreciate your
sponsorship" button instead of "Sponsor NanaZip" button in the next
stable version of NanaZip's toolbar like the Visual Studio administrator mode.

## Purpose
We hope every NanaZip user is happier than before. Here is why we offer a
sponsored version:
- Most users: We are happy with using a $99.99 product freely without feature
differences.
- Contributors: We want to show "Appreciate your sponsorship" button to
others. It's free because we are the contributors. Contribute it if you want
to get that free.
- Sponsors: You can show "Appreciate your sponsorship" button to others
because sponsors deserve that.
- The author of NanaZip, Kenji Mouri: Finally, NanaZip has a price. Nobody
will think this is a worthless product. Efforts from contributors and I should
have value even NanaZip is a fully free and open source project.
## Notes for NanaZip source code repository contributors
If you are the contributor of NanaZip source code repository, please contact
with Kenji.Mouri@outlook.com for more information.
Note: If you are the contributor of Project Mile projects which is used in
NanaZip, you are eligibled too. I think I have sent e-mails or QQ message
to all eligible Project Mile contributors.
## Notes for NanaZip sponsors who sponsored before March 30, 2024
I think I have sent e-mails or QQ message to all eligible NanaZip sponsors.
Contact with Kenji.Mouri@outlook.com for more information.
================================================
FILE: Documents/UpstreamSynchronization.md
================================================
# NanaZip Upstream Synchronization Status
## 7-Zip Mainline
- NanaZip.Core: 26.00
- NanaZip.UI.Classic: 22.01
- Fix for CVE-2025-0411 backported from 7-Zip 24.09.
- Fix for CVE-2025-11001 and CVE-2025-11002 backported from 7-Zip 25.00.
- Security enhancements for symbolic link handling backported from 7-Zip 25.01.
- NanaZip.UI.Modern: 22.01
- Fix for CVE-2025-0411 backported from 7-Zip 24.09.
- Fix for CVE-2025-11001 and CVE-2025-11002 backported from 7-Zip 25.00.
- Security enhancements for symbolic link handling backported from 7-Zip 25.01.
- NanaZip.Universal: 26.00
## 7-Zip ZS
- NanaZip.Core: Commit 5766dd7745f6517f7ea42f6de9a190dfd92aa25f.
- NanaZip.UI.Classic: Unknown because it modifies the old codebase a lot.
- NanaZip.UI.Modern: Unknown because it modifies the old codebase a lot.
- NanaZip.Universal: Commit 5766dd7745f6517f7ea42f6de9a190dfd92aa25f.
## BLAKE3
- NanaZip.Codecs: 1.8.2
## Brotli
- NanaZip.Codecs: 1.2.0
## FastLZMA2
- NanaZip.Codecs: Commit a793db99fade2957d2453035390f97e573acecb2.
## FreeBSD
- NanaZip.Codecs: 14.2.0 with Windows-specific adaptations.
## GmSSL
- NanaZip.Codecs: 3.1.1
## LittleFS
- NanaZip.Codecs: 2.10.2 with actually has not been integrated yet.
## Lizard
- NanaZip.Codecs: 2.1
## LZ4
- NanaZip.Codecs: 1.10.0
## LZ5
- NanaZip.Codecs: 1.5
## RHash
- NanaZip.Codecs: Commit b76c6a3312422c09817c2cef40442b2f2d9d4689 after v1.4.6.
## xxHash
- NanaZip.Codecs: 0.8.3
## Zstandard
- NanaZip.Codecs: 1.5.7
## ZSTDMT
- NanaZip.Codecs: Follow 7-Zip ZS's integration.
================================================
FILE: Documents/Versioning.md
================================================
# NanaZip Versioning
This document applies to all versions of NanaZip.
## Version Format
- Simple Version: `. `
- Example: `9.0 Preview 1`
- Binary Version: `...`
- Example: `9.0.2654.0`
## The rule for build and revision number
The build number is the number of days since August 31, 2021 because the first
version of NanaZip is created and published on that day.
The revision number is the number of releases releases in the day corresponding
to the build number, and it counts from zero. So the first revision is 0 and
the second revision is 1.
## Release Tags
The tag timeline for each release is:
```
"Preview {N}" (one or more) -> "Final" (one or more) -> "No Tag"
-> {"Update N Final" (one or more) -> "Update N"} (zero or more)
-> Repeat again for vNext
```
Here is the explanation for each tag:
- "Preview {N}"
- This tag only appears in NanaZip Preview.
- N is the preview release number, starting from 1.
- N is also optional if there is only one preview release.
- "Final" and "Update N Final"
- This tag only appears in NanaZip Preview.
- The last corresponding "Final" release in NanaZip Preview has the same
implementation as the corresponding stable release in NanaZip.
- There will be more than one "Final" release if there are some big issues
found before the corresponding stable release.
- "Update N Final" is used for validating updates after the corresponding
"No Tag" stable release.
- "Update N Final" corresponds to the stable release "Update N".
- "No Tag" or "Update N"
- This tag only appears in NanaZip a.k.a. the stable release.
- This indicates the stable release of NanaZip.
- There is only one stable release for each minor version.
- N is the update release number, starting from 1.
Here is the example timeline:
```
6.0 Preview 1 -> 6.0 Final -> 6.0 -> 6.0 Update 1 Final -> 6.0 Update 1
-> 6.0 Update 2 Final -> 6.0 Update 2 -> 6.5 Preview -> ...
```
================================================
FILE: Documents/Website/.gitignore
================================================
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/
================================================
FILE: Documents/Website/.vscode/extensions.json
================================================
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}
================================================
FILE: Documents/Website/.vscode/launch.json
================================================
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}
================================================
FILE: Documents/Website/.vscode/mcp.json
================================================
{
"servers": {
"Astro docs": {
"url": "https://mcp.docs.astro.build/mcp",
"type": "http"
}
},
"inputs": []
}
================================================
FILE: Documents/Website/ReadMe.md
================================================
# NanaZip Website
This folder contains the source code of the NanaZip website,
built using [Astro](https://astro.build).
## Images
When taking screenshots for the website, please note the following guidelines:
- Use the default Bloom wallpapers for Windows 11.
- Do not use Snipping Tool (or the built-in `Windows` + `Shift` + `S` shortcut),
as it adds ugly borders around the screenshot. Use
[ShareX](https://getsharex.com/) (with transparency on and shadows off), or
an equivalent tool.
- To turn on transparency mode in ShareX:
1. Open ShareX and go to "Task settings".
2. On the left sidebar, click on "Capture".
3. Turn on "Capture window with transparency" and
turn off "Capture window with shadow".
- Compress the PNG files using [pngquant](https://pngquant.org/),
with the following command:
```
pngquant --force --ext .png --quality 85-85
```
When adding images to the website, place them in `src/assets/images`,
and reference them like this:
```html
---
import exampleImage from '[path to picture]';
---
```
Where `[loading mode]` can be either `eager` or `lazy`.
Use `eager` for images that are above the fold (i.e. visible without scrolling),
and `lazy` for images that are below the fold.
If the image has both a light and a dark version,
you can use the `ThemedLocalPicture` component instead,
like this:
```html
---
import exampleImageLight from '[path to light version of picture]';
import exampleImageDark from '[path to dark version of picture]';
---
```
================================================
FILE: Documents/Website/astro.config.mjs
================================================
// @ts-check
import { defineConfig } from 'astro/config';
// https://astro.build/config
export default defineConfig({
site: 'https://nanazip.org',
});
================================================
FILE: Documents/Website/package.json
================================================
{
"name": "k7site",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@fluentui/svg-icons": "^1.1.320",
"astro": "^5.17.1"
},
"devDependencies": {
"sass-embedded": "^1.97.3"
}
}
================================================
FILE: Documents/Website/src/assets/styles/button.css
================================================
button, .btn {
border-radius: var(--fds-control-corner-radius);
font-size: var(--fds-body-font-size);
border: 1px solid var(--fds-control-border-default);
background-color: var(--fds-control-fill-default);
color: var(--fds-text-primary);
font-family: var(--fds-font-family-text);
padding: 4px 11px 6px 11px;
transition: var(--fds-control-faster-duration) ease background;
font-size: var(--fds-body-font-size);
cursor: pointer;
user-select: none;
text-decoration: none;
display: inline-block;
}
button:hover, .btn:hover {
background-color: var(--fds-control-fill-secondary);
}
button:active, .btn:active {
background-color: var(--fds-control-fill-tertiary);
border-color: var(--fds-control-stroke-default);
color: var(--fds-text-secondary);
}
.btn-hyper {
background-color: transparent;
color: var(--fds-accent-text-primary);
}
.btn-hyper:hover {
background-color: var(--fds-subtle-fill-secondary);
}
.btn-hyper:active {
background-color: var(--fds-subtle-fill-tertiary);
color: var(--fds-accent-text-tertiary);
}
.btn-accent {
background-color: var(--fds-accent-default);
border: 1px solid var(--fds-control-stroke-on-accent-default);
border-bottom-color: var(--fds-control-stroke-on-accent-secondary);
color: var(--fds-text-on-accent-primary);
transition: var(--fds-control-faster-duration) ease border-color;
}
.btn-accent:hover {
background-color: var(--fds-accent-secondary);
}
.btn-accent:active {
background-color: var(--fds-accent-tertiary);
border-color: transparent;
color: var(--fds-text-on-accent-secondary);
}
================================================
FILE: Documents/Website/src/assets/styles/global.css
================================================
body {
background-color: var(--fds-solid-background-base);
color: var(--fds-text-primary);
font-family: var(--fds-font-family-text);
font-size: var(--fds-body-font-size);
line-height: 20px;
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
}
main {
display: flex;
flex-direction: column;
flex: 1 0 auto;
}
main article {
max-width: 800px;
margin: 40px 16px 16px 16px;
align-self: center;
}
html {
color-scheme: light;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
@view-transition {
navigation: auto;
}
================================================
FILE: Documents/Website/src/assets/styles/icons.css
================================================
@font-face {
font-family: "FluentSystemIcons-Regular";
src: url("/FluentSystemIcons-Regular.woff2") format("woff2"),
url("/FluentSystemIcons-Regular.woff") format("woff"),
url("/FluentSystemIcons-Regular.ttf") format("truetype");
font-display: swap;
}
.icon:before {
font-family: FluentSystemIcons-Regular !important;
font-style: normal;
font-weight: normal !important;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon {
line-height: 0;
}
================================================
FILE: Documents/Website/src/assets/styles/image.css
================================================
img {
max-width: 100%;
height: auto;
}
.image-card {
border: 1px solid var(--fds-surface-stroke-default);
border-radius: 8px;
}
================================================
FILE: Documents/Website/src/assets/styles/pages/index.css
================================================
.se-demo-scenario {
display: flex;
flex-direction: row;
align-items: center;
gap: 16px;
}
.card {
border: 1px solid var(--fds-card-stroke-default);
background-color: var(--fds-card-background-default);
border-radius: 8px;
padding: 16px;
}
.se-demo-scenario .card {
flex: 1;
}
@media (max-width: 768px) {
.se-demo {
gap: 32px;
}
#right-arrow {
transform: rotate(90deg);
}
.se-demo-scenario .card {
flex: unset;
}
.se-demo-scenario {
flex-direction: column;
}
}
.format-list {
display: flex;
flex-direction: row;
gap: 16px;
flex-wrap: wrap;
align-items: center;
justify-content: center;
text-align: center;
}
.format-list .card {
font-size: 18px;
}
================================================
FILE: Documents/Website/src/assets/styles/text.css
================================================
h1, h2, h3, h4, h5, h6 {
font-family: var(--fds-font-family-display);
margin: 0;
padding: 0;
}
h1 {
font-size: var(--fds-title-large-font-size);
font-weight: 600;
line-height: 52px;
}
h2 {
font-size: var(--fds-title-font-size);
font-weight: 600;
line-height: 36px;
}
h3 {
font-size: var(--fds-subtitle-font-size);
font-weight: 600;
line-height: 28px;
}
small {
font-size: var(--fds-caption-font-size);
font-family: var(--fds-font-family-small);
line-height: 16px;
}
article h1, article h2 {
margin-top: 16px;
margin-bottom: 16px;
}
a {
color: var(--fds-accent-text-primary);
}
a:active {
color: var(--fds-accent-text-tertiary);
}
================================================
FILE: Documents/Website/src/assets/styles/theme.css
================================================
/* Global Variables */
:root {
/* Accent Colors */
--fds-accent-light-3: 191, 98%, 80%;
--fds-accent-light-2: 199, 99%, 69%;
--fds-accent-light-1: 205, 100%, 49%;
--fds-accent-base: 206, 100%, 42%;
--fds-accent-dark-1: 209, 100%, 36%;
--fds-accent-dark-2: 215, 100%, 29%;
--fds-accent-dark-3: 226, 100%, 20%;
/* Font Families */
--fds-font-family-fallback: "Segoe UI", -apple-system, ui-sans-serif, system-ui,
BlinkMacSystemFont, Helvetica, Arial, sans-serif;
--fds-font-family-text: "Segoe UI Variable Text", "Seoge UI Variable Static Text",
var(--fds-font-family-fallback);
--fds-font-family-small: "Segoe UI Variable Small", "Seoge UI Variable Static Small",
var(--fds-font-family-fallback);
--fds-font-family-display: "Segoe UI Variable Display", "Seoge UI Variable Static Display",
var(--fds-font-family-fallback);
/* Font Size */
--fds-caption-font-size: 12px;
--fds-body-font-size: 14px;
--fds-body-large-font-size: 18px;
--fds-subtitle-font-size: 20px;
--fds-title-font-size: 28px;
--fds-title-large-font-size: 40px;
--fds-display-font-size: 68px;
/* Roundness */
--fds-control-corner-radius: 4px;
--fds-overlay-corner-radius: 8px;
/* Duration */
--fds-control-slow-duration: 333ms;
--fds-control-normal-duration: 250ms;
--fds-control-fast-duration: 167ms;
/* --fds-control-fast-after-duration: 168ms; */
--fds-control-faster-duration: 83ms;
/* Easing */
--fds-control-fast-out-slow-in-easing: cubic-bezier(0, 0, 0, 1);
/* Focus Stroke */
--fds-focus-stroke: 0 0 0 1px var(--fds-focus-stroke-inner),
0 0 0 3px var(--fds-focus-stroke-outer);
}
/* Reduced Motion Support */
@media (prefers-reduced-motion: reduce) {
:root {
--fds-control-slow-duration: 0ms;
--fds-control-normal-duration: 0ms;
--fds-control-fast-duration: 0ms;
/* --fds-control-fast-after-duration: 0ms; */
--fds-control-faster-duration: 0ms;
}
}
/* Light Theme Colors */
@media (prefers-color-scheme: light) {
:root {
/* Text */
--fds-text-primary: hsla(0, 0%, 0%, 89.56%);
--fds-text-secondary: hsla(0, 0%, 0%, 60.63%);
--fds-text-tertiary: hsla(0, 0%, 0%, 44.58%);
--fds-text-disabled: hsla(0, 0%, 0%, 36.14%);
/* Accent */
--fds-accent-default: hsl(var(--fds-accent-dark-1));
--fds-accent-secondary: hsla(var(--fds-accent-dark-1), 90%);
--fds-accent-tertiary: hsla(var(--fds-accent-dark-1), 80%);
--fds-accent-disabled: hsla(0, 0%, 0%, 21.69%);
/* Accent Text */
--fds-accent-text-primary: hsl(var(--fds-accent-dark-2));
--fds-accent-text-secondary: hsl(var(--fds-accent-dark-3));
--fds-accent-text-tertiary: hsl(var(--fds-accent-dark-1));
--fds-accent-text-disabled: hsla(0, 0%, 0%, 36.14%);
/* Text on Accent */
--fds-text-on-accent-primary: hsl(0, 0%, 100%);
--fds-text-on-accent-secondary: hsla(0, 0%, 100%, 70%);
--fds-text-on-accent-disabled: var(--fds-text-on-accent-secondary);
--fds-text-on-accent-selected: var(--fds-text-on-accent-primary);
/* Control Fill */
--fds-control-fill-transparent: transparent;
--fds-control-fill-default: hsla(0, 0%, 100%, 70%);
--fds-control-fill-secondary: hsla(0, 0%, 98%, 50%);
--fds-control-fill-tertiary: hsla(0, 0%, 98%, 30%);
--fds-control-fill-disabled: var(--fds-control-fill-tertiary);
--fds-control-fill-input-active: hsl(0, 0%, 100%);
/* Control Strong Fill */
--fds-control-strong-fill-default: hsla(0, 0%, 0%, 44.58%);
--fds-control-strong-fill-disabled: hsla(0, 0%, 0%, 31.73%);
/* Control Solid Fill */
--fds-control-solid-fill-default: hsl(0, 0%, 100%);
/* Control Alt Fill */
--fds-control-alt-fill-transparent: transparent;
--fds-control-alt-fill-secondary: hsla(0, 0%, 0%, 2.41%);
--fds-control-alt-fill-tertiary: hsla(0, 0%, 0%, 5.78%);
--fds-control-alt-fill-quarternary: hsla(0, 0%, 0%, 9.24%);
--fds-control-alt-fill-disabled: var(--fds-control-alt-fill-transparent);
/* Control on Image Fill */
--fds-control-on-image-fill-default: hsla(0, 0%, 100%, 79%);
--fds-control-on-image-fill-secondary: hsl(0, 0%, 95%);
--fds-control-on-image-fill-tertiary: hsl(0, 0%, 92%);
--fds-control-on-image-fill-disabled: transparent;
/* Subtle Fill */
--fds-subtle-fill-transparent: transparent;
--fds-subtle-fill-secondary: hsla(0, 0%, 0%, 3.73%);
--fds-subtle-fill-tertiary: hsla(0, 0%, 0%, 2.41%);
--fds-subtle-fill-disabled: var(--fds-subtle-fill-transparent);
/* Control Stroke */
--fds-control-stroke-default: hsla(0, 0%, 0%, 5.78%);
--fds-control-stroke-secondary: hsla(0, 0%, 0%, 16.22%);
/* Control Strong Stroke */
--fds-control-strong-stroke-default: hsla(0, 0%, 0%, 44.58%);
--fds-control-strong-stroke-disabled: hsla(0, 0%, 0%, 21.69%);
/* Control Stroke on Accent */
--fds-control-stroke-on-accent-default: hsla(0, 0%, 100%, 8%);
--fds-control-stroke-on-accent-secondary: hsla(0, 0%, 0%, 40%);
--fds-control-stroke-on-accent-tertiary: hsla(0, 0%, 0%, 21.69%);
--fds-control-stroke-on-accent-disabled: var(--fds-control-stroke-on-accent-default);
/* Control Strong Stroke on Image */
--fds-control-strong-stroke-on-image-default: hsla(0, 0%, 100%, 35%);
/* Card Stroke */
--fds-card-stroke-default: hsla(0, 0%, 0%, 5.78%);
--fds-card-stroke-default-solid: hsl(0, 0%, 92%);
/* Surface Stroke */
--fds-surface-stroke-default: hsla(0, 0%, 46%, 40%);
--fds-surface-stroke-flyout: hsla(0, 0%, 0%, 5.78%);
/* Divider Stroke */
--fds-divider-stroke-default: hsla(0, 0%, 0%, 8.03%);
/* Focus Stroke */
--fds-focus-stroke-outer: hsla(0, 0%, 0%, 89.56%);
--fds-focus-stroke-inner: hsl(0, 0%, 100%);
/* Card Background */
--fds-card-background-default: hsla(0, 0%, 100%, 70%);
--fds-card-background-secondary: hsla(0, 0%, 96%, 50%);
/* --fds-card-background-tertiary: hsl(0, 0%, 100%); */
/* Smoke Background */
--fds-smoke-background-default: hsla(0, 0%, 0%, 30%);
/* Layer */
--fds-layer-background-default: hsla(0, 0%, 100%, 50%);
--fds-layer-background-alt: hsl(0, 0%, 100%);
/* Solid Background */
--fds-solid-background-base: hsl(0, 0%, 95%);
--fds-solid-background-secondary: hsl(0, 0%, 93%);
--fds-solid-background-tertiary: hsl(0, 0%, 98%);
--fds-solid-background-quarternary: hsl(0, 0%, 100%);
/* System */
--fds-system-attention: hsl(209, 100%, 36%);
--fds-system-success: hsl(120, 78%, 27%);
--fds-system-caution: hsl(36, 100%, 31%);
--fds-system-critical: hsl(5, 75%, 44%);
--fds-system-neutral: hsla(0, 0%, 0%, 44.58%);
/* System Solid */
--fds-system-solid-neutral: hsl(0, 0%, 54%);
/* System Background */
--fds-system-background-attention: hsla(0, 0%, 96%, 50%);
--fds-system-background-success: hsl(115, 58%, 92%);
--fds-system-background-caution: hsl(47, 100%, 90%);
--fds-system-background-critical: hsl(355, 85%, 95%);
/* System Background Solid */
--fds-system-background-solid-attention: hsl(0, 0%, 97%);
--fds-system-background-solid-neutral: hsl(0, 0%, 95%);
/* Borders */
--fds-control-border-default: var(--fds-control-stroke-default)
var(--fds-control-stroke-default) var(--fds-control-stroke-secondary)
var(--fds-control-stroke-default);
/* Shadows */
--fds-card-shadow: 0px 2px 4px hsla(0, 0%, 0%, 4%);
--fds-tooltip-shadow: 0px 4px 8px hsla(0, 0%, 0%, 14%);
--fds-flyout-shadow: 0px 8px 16px hsla(0, 0%, 0%, 14%);
--fds-dialog-shadow: 0px 32px 64px hsla(0, 0%, 0%, 18.76%),
0px 2px 21px hsl(0, 0%, 0%, 14.74%);
/* Shell Shadows */
--fds-inactive-window-shadow: 0px 16px 32px hsla(0, 0%, 0%, 18%),
0px 2px 10.67px hsla(0, 0%, 0%, 0.1474);
--fds-active-window-shadow: 0px 32px 64px hsla(0, 0%, 0%, 28%),
0px 2px 21px hsla(0, 0%, 0%, 22%);
}
}
/* Dark Theme Colors */
@media (prefers-color-scheme: dark) {
:root {
/* Text */
--fds-text-primary: hsla(0, 0%, 100%, 100%);
--fds-text-secondary: hsla(0, 0%, 100%, 78.6%);
--fds-text-tertiary: hsla(0, 0%, 100%, 54.42%);
--fds-text-disabled: hsla(0, 0%, 100%, 36.28%);
/* Accent */
--fds-accent-default: hsla(var(--fds-accent-light-2));
--fds-accent-secondary: hsla(var(--fds-accent-light-2), 90%);
--fds-accent-tertiary: hsla(var(--fds-accent-light-2), 80%);
--fds-accent-disabled: hsla(0, 0%, 100%, 15.81%);
/* Accent Text */
--fds-accent-text-primary: hsl(var(--fds-accent-light-3));
--fds-accent-text-secondary: hsl(var(--fds-accent-light-3));
--fds-accent-text-tertiary: hsl(var(--fds-accent-light-2));
--fds-accent-text-disabled: hsla(0, 0%, 100%, 36.28%);
/* Text on Accent */
--fds-text-on-accent-primary: hsl(0, 0%, 0%);
--fds-text-on-accent-secondary: hsla(0, 0%, 0%, 0.5);
--fds-text-on-accent-disabled: hsla(0, 0%, 100%, 0.53);
--fds-text-on-accent-selected: hsl(0, 0%, 100%);
/* Control Fill */
--fds-control-fill-transparent: transparent;
--fds-control-fill-default: hsla(0, 0%, 100%, 0.061);
--fds-control-fill-secondary: hsla(0, 0%, 100%, 0.084);
--fds-control-fill-tertiary: hsla(0, 0%, 100%, 0.033);
--fds-control-fill-disabled: hsla(0, 0%, 100%, 0.042);
--fds-control-fill-input-active: hsla(0, 0%, 12%, 70%);
/* Control Strong Fill */
--fds-control-strong-fill-default: hsla(0, 0%, 100%, 54.42%);
--fds-control-strong-fill-disabled: hsla(0, 0%, 100%, 24.65%);
/* Control Solid Fill */
--fds-control-solid-fill-default: hsl(0, 0%, 27%);
/* Control Alt Fill */
--fds-control-alt-fill-transparent: transparent;
--fds-control-alt-fill-secondary: hsla(0, 0%, 0%, 0.1);
--fds-control-alt-fill-tertiary: hsla(0, 0%, 100%, 0.042);
--fds-control-alt-fill-quarternary: hsla(0, 0%, 100%, 0.07);
--fds-control-alt-fill-disabled: var(--fds-control-fill-transparent);
/* Control on Image Fill */
--fds-control-on-image-fill-default: hsla(0, 0%, 11%, 70%);
--fds-control-on-image-fill-secondary: hsl(0, 0%, 10%);
--fds-control-on-image-fill-tertiary: hsl(0, 0%, 7%);
--fds-control-on-image-fill-disabled: transparent;
/* Subtle Fill */
--fds-subtle-fill-transparent: transparent;
--fds-subtle-fill-secondary: hsla(0, 0%, 100%, 6.05%);
--fds-subtle-fill-tertiary: hsla(0, 0%, 100%, 4.19%);
--fds-subtle-fill-disabled: transparent;
/* Control Stroke */
--fds-control-stroke-default: hsla(0, 0%, 100%, 6.98%);
--fds-control-stroke-secondary: hsla(0, 0%, 100%, 9.3%);
/* Control Strong Stroke */
--fds-control-strong-stroke-default: hsla(0, 0%, 100%, 54.42%);
--fds-control-strong-stroke-disabled: hsla(0, 0%, 100%, 15.81%);
/* Control Stroke on Accent */
--fds-control-stroke-on-accent-default: hsla(0, 0%, 100%, 8%);
--fds-control-stroke-on-accent-secondary: hsla(0, 0%, 0%, 14%);
--fds-control-stroke-on-accent-tertiary: hsla(0, 0%, 0%, 21.69%);
--fds-control-stroke-on-accent-disabled: hsla(0, 0%, 0%, 20%);
/* Control Strong Stroke on Image */
--fds-control-strong-stroke-on-image-default: hsla(0, 0%, 0%, 42%);
/* Card Stroke */
--fds-card-stroke-default: hsla(0, 0%, 0%, 10%);
--fds-card-stroke-default-solid: hsl(0, 0%, 11%);
/* Surface Stroke */
--fds-surface-stroke-default: hsla(0, 0%, 46%, 40%);
--fds-surface-stroke-flyout: hsla(0, 0%, 0%, 20%);
/* Divider Stroke */
--fds-divider-stroke-default: hsla(0, 0%, 100%, 8.37%);
/* Focus Stroke */
--fds-focus-stroke-outer: hsl(0, 0%, 100%);
--fds-focus-stroke-inner: hsla(0, 0%, 0%, 70%);
/* Card Background */
--fds-card-background-default: hsla(0, 0%, 100%, 5.12%);
--fds-card-background-secondary: hsla(0, 0%, 100%, 3.26%);
/* --fds-card-background-tertiary: unset; */
/* Smoke Background */
--fds-smoke-background-default: hsla(0, 0%, 0%, 30%);
/* Layer */
--fds-layer-background-default: hsla(0, 0%, 23%, 30%);
--fds-layer-background-alt: hsla(0, 0%, 100%, 5.38%);
/* Solid Background */
--fds-solid-background-base: hsl(0, 0%, 13%);
--fds-solid-background-secondary: hsl(0, 0%, 11%);
--fds-solid-background-tertiary: hsl(0, 0%, 16%);
--fds-solid-background-quarternary: hsl(0, 0%, 17%);
/* System */
--fds-system-attention: hsl(199, 100%, 69%);
--fds-system-success: hsl(113, 51%, 58%);
--fds-system-caution: hsl(54, 100%, 49%);
--fds-system-critical: hsl(354, 100%, 80%);
--fds-system-neutral: hsla(0, 0%, 100%, 54.42%);
/* System Solid */
--fds-system-solid-neutral: hsl(0, 0%, 62%);
/* System Background */
--fds-system-background-attention: hsla(0, 0%, 100%, 3.26%);
--fds-system-background-success: hsl(67, 39%, 17%);
--fds-system-background-caution: hsl(40, 46%, 18%);
--fds-system-background-critical: hsl(2, 28%, 21%);
/* System Background Solid */
--fds-system-background-solid-attention: hsl(0, 0%, 18%);
--fds-system-background-solid-neutral: hsl(0, 0%, 62%);
/* Borders */
--fds-control-border-default: var(--fds-control-stroke-secondary)
var(--fds-control-stroke-default) var(--fds-control-stroke-default)
var(--fds-control-stroke-default);
/* Shadows */
--fds-card-shadow: 0px 2px 4px hsla(0, 0%, 0%, 0.13);
--fds-tooltip-shadow: 0px 4px 8px hsla(0, 0%, 0%, 0.26);
--fds-flyout-shadow: 0px 8px 16px hsla(0, 0%, 0%, 0.14);
--fds-dialog-shadow: 0px 32px 64px hsla(0, 0%, 0%, 0.37), 0px 2px 21px hsla(0, 0%, 0%, 0.37);
/* Shell Shadows */
--fds-inactive-window-shadow: 0px 16px 32px hsla(0, 0%, 0%, 0.37),
0px 2px 10.67px hsla(0, 0%, 0%, 0.37);
--fds-active-window-shadow: 0px 32px 64px hsla(0, 0%, 0%, 0.56),
0px 2px 21px hsla(0, 0%, 0%, 0.55);
}
}
================================================
FILE: Documents/Website/src/components/Footer/Footer.astro
================================================
---
import './Footer.css';
---
NanaZip, with ❤️ by M2-Team and contributors.
Note: NanaZip.org is the only official website for NanaZip.
Any other websites claiming to be NanaZip are fake.
We are not responsible for content on those websites.
================================================
FILE: Documents/Website/src/components/Footer/Footer.css
================================================
footer {
background-color: var(--fds-card-stroke-default-solid);
border-top: 1px solid var(--fds-surface-stroke-flyout);
padding: 8px 32px;
margin-top: 16px;
}
================================================
FILE: Documents/Website/src/components/InfoBar/InfoBar.astro
================================================
---
import "./InfoBar.scss";
interface Props {
title?: string;
severity: "information" | "success" | "caution" | "critical" | "attention";
wrap?: boolean;
}
const { title, severity, wrap = false } = Astro.props;
let path = "";
if (severity === "attention") {
path =
"M862.5,680C862.5,687.333 861.083,694.25 858.25,700.75C855.417,707.25 851.583,712.917 846.75,717.75C841.917,722.583 836.25,726.417 829.75,729.25C823.25,732.083 816.333,733.5 809,733.5C800,733.5 791.333,731.167 783,726.5L565.5,603.5L565.5,853.5C565.5,860.833 564.083,867.75 561.25,874.25C558.417,880.75 554.583,886.333 549.75,891C544.917,895.667 539.25,899.417 532.75,902.25C526.25,905.083 519.333,906.5 512,906.5C504.667,906.5 497.75,905.083 491.25,902.25C484.75,899.417 479.083,895.667 474.25,891C469.417,886.333 465.583,880.75 462.75,874.25C459.917,867.75 458.5,860.833 458.5,853.5L458.5,603.5L241,726.5C232.667,731.167 224,733.5 215,733.5C207.667,733.5 200.75,732.083 194.25,729.25C187.75,726.417 182.083,722.583 177.25,717.75C172.417,712.917 168.583,707.25 165.75,700.75C162.917,694.25 161.5,687.333 161.5,680C161.5,670.667 164,661.75 169,653.25C174,644.75 180.5,638.167 188.5,633.5L403.5,512L188.5,390.5C180.5,385.833 174,379.25 169,370.75C164,362.25 161.5,353.333 161.5,344C161.5,336.667 162.917,329.75 165.75,323.25C168.583,316.75 172.417,311.083 177.25,306.25C182.083,301.417 187.75,297.583 194.25,294.75C200.75,291.917 207.667,290.5 215,290.5C224.667,290.5 233.333,292.833 241,297.5L458.5,420.5L458.5,170.5C458.5,163.167 459.917,156.25 462.75,149.75C465.583,143.25 469.417,137.667 474.25,133C479.083,128.333 484.75,124.583 491.25,121.75C497.75,118.917 504.667,117.5 512,117.5C519.333,117.5 526.25,118.917 532.75,121.75C539.25,124.583 544.917,128.333 549.75,133C554.583,137.667 558.417,143.25 561.25,149.75C564.083,156.25 565.5,163.167 565.5,170.5L565.5,420.5L783,297.5C791.333,292.833 800,290.5 809,290.5C816.333,290.5 823.25,291.917 829.75,294.75C836.25,297.583 841.917,301.417 846.75,306.25C851.583,311.083 855.417,316.75 858.25,323.25C861.083,329.75 862.5,336.667 862.5,344C862.5,353.333 860,362.25 855,370.75C850,379.25 843.5,385.833 835.5,390.5L620.5,512L835.5,633.5C843.5,638.167 850,644.75 855,653.25C860,661.75 862.5,670.667 862.5,680Z";
} else if (severity === "success") {
path =
"M117.5,554.5C117.5,547.167 118.917,540.25 121.75,533.75C124.583,527.25 128.417,521.583 133.25,516.75C138.083,511.917 143.75,508.083 150.25,505.25C156.75,502.417 163.667,501 171,501C185.333,501 197.833,506.333 208.5,517L384,692.5L815.5,261C826.167,250.333 838.833,245 853.5,245C860.833,245 867.75,246.417 874.25,249.25C880.75,252.083 886.417,256 891.25,261C896.083,266 899.917,271.75 902.75,278.25C905.583,284.75 907,291.5 907,298.5C907,313.167 901.667,325.833 891,336.5L421.5,805.5C416.5,810.5 410.75,814.417 404.25,817.25C397.75,820.083 391,821.5 384,821.5C369.667,821.5 357.167,816.167 346.5,805.5L133,592.5C122.667,582.167 117.5,569.5 117.5,554.5Z";
} else if (severity == "caution") {
path =
"M426.5,512L426.5,170.5C426.5,158.833 428.75,147.833 433.25,137.5C437.75,127.167 443.917,118.167 451.75,110.5C459.583,102.833 468.667,96.75 479,92.25C489.333,87.75 500.333,85.5 512,85.5C523.667,85.5 534.667,87.75 545,92.25C555.333,96.75 564.417,102.833 572.25,110.5C580.083,118.167 586.25,127.167 590.75,137.5C595.25,147.833 597.5,158.833 597.5,170.5L597.5,512C597.5,523.667 595.25,534.667 590.75,545C586.25,555.333 580.083,564.417 572.25,572.25C564.417,580.083 555.333,586.25 545,590.75C534.667,595.25 523.667,597.5 512,597.5C500.333,597.5 489.333,595.25 479,590.75C468.667,586.25 459.583,580.083 451.75,572.25C443.917,564.417 437.75,555.333 433.25,545C428.75,534.667 426.5,523.667 426.5,512ZM405.5,853.5C405.5,838.833 408.333,825 414,812C419.667,799 427.333,787.667 437,778C446.667,768.333 457.917,760.667 470.75,755C483.583,749.333 497.333,746.5 512,746.5C526.667,746.5 540.417,749.333 553.25,755C566.083,760.667 577.333,768.333 587,778C596.667,787.667 604.333,799 610,812C615.667,825 618.5,838.833 618.5,853.5C618.5,868.167 615.667,881.917 610,894.75C604.333,907.583 596.667,918.833 587,928.5C577.333,938.167 566,945.833 553,951.5C540,957.167 526.333,960 512,960C497.333,960 483.583,957.167 470.75,951.5C457.917,945.833 446.667,938.167 437,928.5C427.333,918.833 419.667,907.583 414,894.75C408.333,881.917 405.5,868.167 405.5,853.5Z";
} else if (severity === "critical") {
path =
"M512.5,587.5L262.5,838C252.167,848.333 239.5,853.5 224.5,853.5C209.5,853.5 196.917,848.417 186.75,838.25C176.583,828.083 171.5,815.5 171.5,800.5C171.5,785.5 176.667,772.833 187,762.5L437,512L187,262C176.667,251.667 171.5,239.167 171.5,224.5C171.5,217.167 172.833,210.167 175.5,203.5C178.167,196.833 181.917,191.167 186.75,186.5C191.583,181.833 197.167,178.083 203.5,175.25C209.833,172.417 216.833,171 224.5,171C239.167,171 251.667,176.167 262,186.5L512.5,437L762.5,186.5C773.167,175.833 785.833,170.5 800.5,170.5C807.833,170.5 814.75,171.917 821.25,174.75C827.75,177.583 833.417,181.417 838.25,186.25C843.083,191.083 846.833,196.75 849.5,203.25C852.167,209.75 853.5,216.667 853.5,224C853.5,238.667 848.333,251.167 838,261.5L587.5,512L838,762.5C848.667,773.167 854,785.833 854,800.5C854,807.833 852.583,814.667 849.75,821C846.917,827.333 843.083,832.917 838.25,837.75C833.417,842.583 827.75,846.417 821.25,849.25C814.75,852.083 807.833,853.5 800.5,853.5C785.5,853.5 772.833,848.333 762.5,838Z";
} else if (severity === "information") {
path =
"M405.5,170.5C405.5,156.167 408.333,142.5 414,129.5C419.667,116.5 427.333,105.167 437,95.5C446.667,85.8334 457.917,78.1667 470.75,72.5C483.583,66.8334 497.333,64.0001 512,64C526.333,64.0001 540,66.8334 553,72.5C566,78.1667 577.333,85.8334 587,95.5C596.667,105.167 604.333,116.5 610,129.5C615.667,142.5 618.5,156.167 618.5,170.5C618.5,185.167 615.667,199 610,212C604.333,225 596.667,236.333 587,246C577.333,255.667 566.083,263.333 553.25,269C540.417,274.667 526.667,277.5 512,277.5C497.333,277.5 483.583,274.667 470.75,269C457.917,263.333 446.667,255.667 437,246C427.333,236.333 419.667,225 414,212C408.333,199 405.5,185.167 405.5,170.5ZM426.5,853.5L426.5,512C426.5,500.333 428.75,489.333 433.25,479C437.75,468.667 443.917,459.583 451.75,451.75C459.583,443.917 468.667,437.75 479,433.25C489.333,428.75 500.333,426.5 512,426.5C523.667,426.5 534.667,428.75 545,433.25C555.333,437.75 564.417,443.917 572.25,451.75C580.083,459.583 586.25,468.667 590.75,479C595.25,489.333 597.5,500.333 597.5,512L597.5,853.5C597.5,865.167 595.25,876.167 590.75,886.5C586.25,896.833 580.083,905.833 572.25,913.5C564.417,921.167 555.333,927.25 545,931.75C534.667,936.25 523.667,938.5 512,938.5C500.333,938.5 489.333,936.25 479,931.75C468.667,927.25 459.583,921.167 451.75,913.5C443.917,905.833 437.75,896.833 433.25,886.5C428.75,876.167 426.5,865.167 426.5,853.5Z";
}
let viewBox = "";
if (severity === "attention") {
viewBox = "162 118 701 789";
} else if (severity === "success") {
viewBox = "118 245 790 577";
} else if (severity === "caution") {
viewBox = "406 86 213 875";
} else if (severity === "critical") {
viewBox = "172 171 683 683";
} else if (severity === "information") {
viewBox = "406 64 213 875";
}
---
================================================
FILE: Documents/Website/src/components/InfoBar/InfoBar.scss
================================================
.info-badge {
display: flex;
align-items: center;
box-sizing: border-box;
user-select: none;
min-inline-size: 16px;
min-block-size: 16px;
border-radius: 16px;
padding: 2px 4px;
color: var(--fds-text-on-accent-primary);
line-height: var(--fds-caption-font-size);
font: {
family: var(--fds-font-family-small);
size: var(--fds-caption-font-size);
}
&.severity- {
&attention {
background-color: var(--fds-system-attention);
}
&success {
background-color: var(--fds-system-success);
}
&caution {
background-color: var(--fds-system-caution);
}
&critical {
background-color: var(--fds-system-critical);
}
&information {
background-color: var(--fds-system-solid-neutral);
}
}
svg {
inline-size: 8px;
block-size: 8px;
fill: currentColor;
}
}
.info-bar {
display: flex;
align-items: center;
position: relative;
min-block-size: 48px;
padding-inline-start: 15px;
box-sizing: border-box;
user-select: none;
background-clip: padding-box;
font-family: var(--fds-font-family-text);
border: 1px solid var(--fds-card-stroke-default);
border-radius: var(--fds-control-corner-radius);
margin-bottom: 16px;
&.severity- {
&information {
background-color: var(--fds-card-background-secondary);
}
&success {
background-color: var(--fds-system-background-success);
}
&caution {
background-color: var(--fds-system-background-caution);
}
&critical {
background-color: var(--fds-system-background-critical);
}
&attention {
background-color: var(--fds-system-background-attention);
}
}
&-icon {
align-self: flex-start;
display: flex;
flex: 0 0 auto;
margin: {
block-start: 16px;
}
}
&-content {
display: flex;
align-items: center;
flex-wrap: wrap;
position: relative;
box-sizing: border-box;
flex: 1 1 auto;
margin: {
inline-start: 13px;
block-start: 7px;
block-end: 7px;
}
&.message-wrapped,
&.action-wrapped {
margin: {
block-start: 13px;
block-end: 15px;
}
}
&.message-wrapped {
h5,
p {
align-self: flex-start;
}
.info-bar-action {
margin-inline-end: 50%;
}
}
&.action-wrapped .info-bar-action {
padding-block-start: 16px;
}
}
h5,
p {
color: var(--text-primary);
margin: 0;
line-height: 20px;
font: {
size: var(--body-font-size);
weight: 400;
}
}
h5 {
font-weight: 600;
margin-inline-end: 12px;
}
p {
flex: 1 1 auto;
margin-inline-end: 15px;
}
}
================================================
FILE: Documents/Website/src/components/Navbar/Navbar.astro
================================================
---
import "./Navbar.scss";
import Logo from "../../assets/images/NanaZip.svg";
import NavIcon from '@fluentui/svg-icons/icons/navigation_24_regular.svg';
import HomeIcon from '@fluentui/svg-icons/icons/home_20_regular.svg';
import DownloadIcon from '@fluentui/svg-icons/icons/arrow_download_20_regular.svg';
---
================================================
FILE: Documents/Website/src/components/Navbar/Navbar.scss
================================================
.navbar {
position: sticky;
top: 0;
z-index: 1000;
background-color: var(--fds-layer-background-default);
border-bottom: 1px solid var(--fds-surface-stroke-flyout);
backdrop-filter: blur(60px);
padding: 8px;
gap: 8px;
display: flex;
justify-content: space-between;
flex-direction: row;
align-items: center;
& .btn:not(.skip-to-content), button {
padding: 8px;
background-color: transparent;
align-items: center;
gap: 8px;
& svg {
display: block;
}
&:hover {
background-color: var(--fds-subtle-fill-secondary);
}
&:active {
background-color: var(--fds-subtle-fill-tertiary);
color: var(--fds-text-secondary);
}
}
& .btn {
display: flex;
}
}
nav, .nav-items {
display: flex;
align-items: center;
flex-direction: row;
gap: 8px;
}
nav {
flex: 1;
justify-content: space-between;
}
.logo {
display: flex;
align-items: center;
color: var(--fds-text-primary);
text-decoration: none;
font-size: var(--fds-body-large-font-size);
gap: 8px;
margin-right: 8px;
}
.logo:active {
color: var(--fds-text-secondary);
}
.skip-to-content {
position: absolute;
left: -9999px;
top: 0;
overflow: hidden;
&:focus {
left: 0;
z-index: 1001;
}
}
.menu-button {
display: none;
}
.icon-button>span:not(.icon) {
display: none;
}
@media screen and (max-width: 768px) {
.navbar {
flex-wrap: wrap;
}
nav, .nav-items {
flex-direction: column;
align-items: stretch;
}
nav {
flex-basis: 100%;
display: none;
justify-content: unset;
&.active {
display: flex;
}
}
.menu-button {
display: unset;
}
.icon-button > span:not(.icon) {
display: unset;
}
}
.icon {
font-size: 20px;
}
.icon-home::before {
content: '\F480';
}
.icon-download::before {
content: '\F150';
}
:global(body.active) {
overflow-y: hidden;
}
================================================
FILE: Documents/Website/src/components/Navbar/Navbar.ts
================================================
document.querySelector('.menu-button')?.addEventListener('click', () => {
const nav = document.querySelector('nav');
if (nav) {
nav.classList.toggle('active');
}
});
================================================
FILE: Documents/Website/src/components/PageSection/PageSection.astro
================================================
---
import './PageSection.scss';
interface Props {
header: string;
}
const { header } = Astro.props;
---
================================================
FILE: Documents/Website/src/components/PageSection/PageSection.scss
================================================
.page-section {
padding: 72px;
display: flex;
flex-direction: row;
align-items: center;
gap: 72px;
min-height: 50vh;
& .subtitle {
font-size: var(--fds-subtitle-font-size);
line-height: 1.65;
margin: 12px 0;
}
&-left {
display: flex;
flex-direction: column;
justify-items: center;
flex: 1 1 0;
min-width: 0;
}
&-right {
flex: 1 1 0;
min-width: 480px;
}
@media screen and (width < 960px) {
padding: 36px;
gap: 36px;
flex-direction: column;
align-items: center;
min-height: unset;
&-left {
align-items: center;
text-align: center;
flex: auto;
}
&-right {
min-width: 0;
flex: auto;
}
}
}
================================================
FILE: Documents/Website/src/components/StoreBadge/StoreBadge.astro
================================================
---
interface Props {
productId: string;
windowMode?: "direct" | "full";
size?: "large" | "small";
campaignId?: string;
}
const { productId, windowMode = "direct", size = "large", campaignId } = Astro.props;
import "./StoreBadge.css";
---
================================================
FILE: Documents/Website/src/components/StoreBadge/StoreBadge.css
================================================
.store-badge-link img.large {
height: 104px;
}
.store-badge-link img {
display: block;
transition: 0.35s ease;
}
.store-badge-link img:hover {
transform: translate(0, -4px);
cursor: pointer;
box-shadow: 0 12px 40px 20px rgba(0, 0, 0, 0.05);
}
iframe {
border: none;
width: 0;
height: 0;
}
ms-store-badge::part(img), .store-badge-link img {
max-width: 100%;
min-width: 200px;
}
ms-store-badge, .store-badge-link {
display: block;
width: fit-content;
line-height: 0;
}
================================================
FILE: Documents/Website/src/components/StoreBadge/StoreBadge.ts
================================================
function changeStoreBadge(darkMode: boolean) {
document.querySelectorAll("ms-store-badge").forEach((badge) => {
badge.setAttribute("theme", darkMode ? "light" : "dark");
});
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {
changeStoreBadge(e.matches);
});
================================================
FILE: Documents/Website/src/components/ThemedLocalPicture/ThemedLocalPicture.astro
================================================
---
import type { ImageMetadata } from "astro";
import { getImage } from 'astro:assets';
interface Props {
lightSrc: string | ImageMetadata;
darkSrc: string | ImageMetadata;
alt: string;
loading?: "eager" | "lazy";
class?: string;
fetchPriority?: "high" | "low" | "auto";
}
const { lightSrc, darkSrc, alt, loading = "lazy", class: className, fetchPriority = "auto" } = Astro.props as Props;
const lightImgAvif = await getImage({
src: lightSrc,
format: 'avif',
layout: 'full-width'
});
const lightImgWebp = await getImage({
src: lightSrc,
format: 'webp',
layout: 'full-width'
});
const lightImgPng = await getImage({
src: lightSrc,
format: 'png',
layout: 'full-width'
});
const darkImgAvif = await getImage({
src: darkSrc,
format: 'avif',
layout: 'full-width'
});
const darkImgWebp = await getImage({
src: darkSrc,
format: 'webp',
layout: 'full-width'
});
const darkImgPng = await getImage({
src: darkSrc,
format: 'png',
layout: 'full-width'
});
---
================================================
FILE: Documents/Website/src/components/Tree/Tree.astro
================================================
---
interface Props {
text: string;
}
const { text } = Astro.props;
import './Tree.css';
---
================================================
FILE: Documents/Website/src/components/Tree/Tree.css
================================================
.tree > .tree {
margin-left: 16px;
}
.tree p {
margin-top: 8px;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 4px;
}
================================================
FILE: Documents/Website/src/layouts/Layout.astro
================================================
---
import '../assets/styles/theme.css';
import '../assets/styles/global.css';
import '../assets/styles/text.css';
import '../assets/styles/image.css';
import '../assets/styles/button.css';
import Navbar from '../components/Navbar/Navbar.astro';
import Footer from '../components/Footer/Footer.astro';
interface Props {
title?: string;
description: string;
}
const { title, description } = Astro.props;
---
{title ? `${title} - NanaZip` : "NanaZip"}
================================================
FILE: Documents/Website/src/pages/downloads.astro
================================================
---
import Layout from "../layouts/Layout.astro";
import StoreBadge from "../components/StoreBadge/StoreBadge.astro";
import InfoBar from "../components/InfoBar/InfoBar.astro";
---
Downloads
Only GitHub, Microsoft Store, My Digital Life Forums,
SourceForge, and Windows App Community hosts official downloads.
Microsoft Store (recommended)
NanaZip
NanaZip Preview
SourceForge
Go to SourceForge
GitHub Releases
GitHub Releases include experimental portable versions. These
versions are intended for users without access to MSIX (such as
Windows PE and Wine).
Some features are not available (such as File Manager), and no support
is provided for these versions.
Latest stable release
All releases
================================================
FILE: Documents/Website/src/pages/index.astro
================================================
---
import Layout from "../layouts/Layout.astro";
import PageSection from "../components/PageSection/PageSection.astro";
import StoreBadge from "../components/StoreBadge/StoreBadge.astro";
import ThemedLocalPicture from "../components/ThemedLocalPicture/ThemedLocalPicture.astro";
import Tree from "../components/Tree/Tree.astro";
import '../assets/styles/pages/index.css';
import heroImageDark from "../assets/images/MainWindowDarkMode.png";
import heroImageLight from "../assets/images/MainWindowLightMode.png";
import contextMenuDark from "../assets/images/ContextMenuDark.png";
import contextMenuLight from "../assets/images/ContextMenuLight.png";
import ArchiveFile from "../assets/images/ArchiveFile.svg";
import RightArrow from '@fluentui/svg-icons/icons/arrow_right_32_regular.svg';
import FileIcon from '@fluentui/svg-icons/icons/document_20_regular.svg';
import FolderIcon from '@fluentui/svg-icons/icons/folder_20_regular.svg';
---
The 7-Zip derivative intended for the modern Windows
experience
Or check out alternative download options
NanaZip supports the new Windows 11 context menu and adopts the
Fluent Design System, using the Mica material and adding dark
mode support.
NanaZip supports Windows accessibility features and
meets Section 508 compliance standards .
Smart Extraction saves you clicks for archives with a single root item,
and keeps your files organized for those with multiple root items.
In addition, you can configure NanaZip to start Smart Extraction
upon opening an archive, instead of opening NanaZip File Manager.
NanaZip supports additional file formats on top of 7-zip, such as Zstandard, WASM, Electron ASAR, and .NET Single File Bundle.
NanaZip integrates multiple security mitigations to reduce the impact of vulnerabilities.
These mitigations are enabled by default and configurable using Group Policy .
================================================
FILE: Documents/Website/src/pages/section508.astro
================================================
NanaZip Accessibility Conformance Report NanaZip Accessibility Conformance Report
Based on VPAT® 2.4 WCAG 2.1 and Revised Section 508 Edition
Name of Product/Version NanaZip
Report Dates and Version Report Date: 2026/2/25 Last Modified Date: 2026/2/25 Version: nanazip-1 Product Description NanaZip is an open source file archiver intended for the modern Windows experience, forked from the source code of well-known open source file archiver 7-Zip.
Author Information Vendor Information Applicable Standards/Guidelines
This report covers the degree of conformance for the following accessibility standard/guidelines:
Terms
The terms used in the Conformance Level information are defined as follows:
Supports : The functionality of the product has at least one method that meets the criterion without known defects or meets with equivalent facilitation.Partially Supports : Some functionality of the product does not meet the criterion.Does Not Support : The majority of product functionality does not meet the criterion.Not Applicable : The criterion is not relevant to the product.Not Evaluated : The product has not been evaluated against the criterion. This can be used only in WCAG 2.x Level AAA. WCAG 2.1 Report Table 1: Success Criteria, Level A Table 2: Success Criteria, Level AA Table 3: Success Criteria, Level AAA Revised Section 508 Report Chapter 4: Hardware Chapter 5: Software Chapter 6: Support Documentation and Services Repository https://github.com/M2Team/NanaZip (opens in a new window or tab) Feedback https://github.com/M2Team/NanaZip (opens in a new window or tab)
================================================
FILE: Documents/Website/tsconfig.json
================================================
{
"extends": "astro/tsconfigs/strictest",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}
================================================
FILE: K7Base/K7Base.def
================================================
LIBRARY
EXPORTS
K7BaseDetourTransactionBegin
K7BaseDetourTransactionAbort
K7BaseDetourTransactionCommit
K7BaseDetourUpdateThread
K7BaseDetourAttach
K7BaseDetourDetach
K7BaseHashCreate
K7BaseHashDestroy
K7BaseHashUpdate
K7BaseHashFinal
K7BaseHashGetSize
K7BaseHashDuplicate
K7BaseGetAllowedHandlerPolicy
K7BaseGetAllowedCodecPolicy
K7BaseGetWriteZoneIdExtractPolicy
K7BaseDisableDynamicCodeGeneration
K7BaseDisableChildProcessCreation
K7BaseInitialize
K7BaseModernFileTimeToLocalFileTime
K7BaseModernLocalFileTimeToFileTime
================================================
FILE: K7Base/K7Base.h
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7Base.h
* PURPOSE: Definition for NanaZip Platform Base Public Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#ifndef K7_BASE
#define K7_BASE
#include
#ifndef MILE_MOBILITY_ENABLE_MINIMUM_SAL
#include
#endif // !MILE_MOBILITY_ENABLE_MINIMUM_SAL
// Workaround for Windows SDK, which defines these types in #ifndef VOID block.
// That design is terrible, but needs to have a workaround.
#ifdef VOID
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
#endif // VOID
#include
#ifndef K7_BASE_DETOURS
#define K7_BASE_DETOURS
/**
* @brief Begin a new transaction for attaching or detaching detours.
* @return Returns NO_ERROR if successful; otherwise, returns an error code.
* @remark For more information, see DetourTransactionBegin.
*/
EXTERN_C LONG MOAPI K7BaseDetourTransactionBegin();
/**
* @brief Abort the current transaction for attaching or detaching detours.
* @return Returns NO_ERROR if the pending transaction was completely aborted;
* otherwise, returns an error code.
* @remark For more information, see DetourTransactionAbort.
*/
EXTERN_C LONG MOAPI K7BaseDetourTransactionAbort();
/**
* @brief Commit the current transaction for attaching or detaching detours.
* @return Returns NO_ERROR if successful; otherwise, returns an error code.
* @remark For more information, see DetourTransactionCommit.
*/
EXTERN_C LONG MOAPI K7BaseDetourTransactionCommit();
/**
* @brief Enlist a thread for update in the current transaction.
* @param ThreadHandle The handle of the thread to be updated with the pending
* transaction. If hThread is equal to the current threads
* pseudo handle (as returned by GetCurrentThread()) no
* action is performed and NO_ERROR is returned.
* @return Returns NO_ERROR if successful; otherwise, returns an error code.
* @remark For more information, see DetourUpdateThread.
*/
EXTERN_C LONG MOAPI K7BaseDetourUpdateThread(
_In_ HANDLE ThreadHandle);
/**
* @brief Attach a detour to a target function.
* @param OriginalFunction Pointer to the target pointer to which the detour
* will be attached.
* @param DetouredFunction Pointer to the detour function.
* @return Returns NO_ERROR if successful; otherwise, returns an error code.
* @remark For more information, see DetourAttach.
*/
EXTERN_C LONG MOAPI K7BaseDetourAttach(
_Inout_ PMO_POINTER OriginalFunction,
_In_ MO_POINTER DetouredFunction);
/**
* @brief Detach a detour from a target function.
* @param OriginalFunction Pointer to the target pointer from which the detour
* will be detached.
* @param DetouredFunction Pointer to the detour function.
* @return Returns NO_ERROR if successful; otherwise, returns an error code.
* @remark For more information, see DetourDetach.
*/
EXTERN_C LONG MOAPI K7BaseDetourDetach(
_Inout_ PMO_POINTER OriginalFunction,
_In_ MO_POINTER DetouredFunction);
#endif // !K7_BASE_DETOURS
#ifndef K7_BASE_HASH
#define K7_BASE_HASH
/**
* @brief Enumeration for supported hash algorithm types.
* @remarks The sequence and values of this enumeration must keep the same for
* binary-level backward compatibility.
*/
typedef enum _K7_BASE_HASH_ALGORITHM_TYPE
{
/**
* @brief The MD2 hash algorithm.
*/
K7_BASE_HASH_ALGORITHM_MD2 = 0,
/**
* @brief The MD4 hash algorithm.
*/
K7_BASE_HASH_ALGORITHM_MD4 = 1,
/**
* @brief The MD5 hash algorithm.
*/
K7_BASE_HASH_ALGORITHM_MD5 = 2,
/**
* @brief The SHA-1 hash algorithm.
*/
K7_BASE_HASH_ALGORITHM_SHA1 = 3,
/**
* @brief The SHA-256 hash algorithm.
*/
K7_BASE_HASH_ALGORITHM_SHA256 = 4,
/**
* @brief The SHA-384 hash algorithm.
*/
K7_BASE_HASH_ALGORITHM_SHA384 = 5,
/**
* @brief The SHA-512 hash algorithm.
*/
K7_BASE_HASH_ALGORITHM_SHA512 = 6,
/**
* @brief Indicates the maximum value for the K7_BASE_HASH_ALGORITHM_TYPE
* enumeration, which is useful for validation purposes.
*/
K7_BASE_HASH_ALGORITHM_MAXIMUM
} K7_BASE_HASH_ALGORITHM_TYPE, *PK7_BASE_HASH_ALGORITHM_TYPE;
MO_DECLARE_HANDLE(K7_BASE_HASH_HANDLE);
typedef K7_BASE_HASH_HANDLE *PK7_BASE_HASH_HANDLE;
/**
* @brief Creates a hash handle for the specified algorithm.
* @param HashHandle A pointer to receive the created hash handle.
* @param Algorithm The hash algorithm type.
* @param SecretBuffer An optional buffer containing the secret key for HMAC.
* @param SecretSize The size of the secret key in bytes.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseHashCreate(
_Inout_ PK7_BASE_HASH_HANDLE HashHandle,
_In_ K7_BASE_HASH_ALGORITHM_TYPE Algorithm,
_In_opt_ MO_POINTER SecretBuffer,
_In_ MO_UINT32 SecretSize);
/**
* @brief Destroys the specified hash handle and releases associated resources.
* @param HashHandle The handle of the hash to be destroyed.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseHashDestroy(
_Inout_opt_ K7_BASE_HASH_HANDLE HashHandle);
/**
* @brief Updates the hash with the specified input data.
* @param HashHandle The handle of the hash to be updated.
* @param InputBuffer The input data to be hashed.
* @param InputSize The size of the input data in bytes.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseHashUpdate(
_Inout_ K7_BASE_HASH_HANDLE HashHandle,
_In_ MO_POINTER InputBuffer,
_In_ MO_UINT32 InputSize);
/**
* @brief Finalizes the hash computation and retrieves the hash value.
* @param HashHandle The handle of the hash to be finalized.
* @param OutputBuffer The buffer to receive the computed hash value.
* @param OutputSize The size of the output buffer in bytes.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseHashFinal(
_Inout_ K7_BASE_HASH_HANDLE HashHandle,
_Out_ MO_POINTER OutputBuffer,
_In_ MO_UINT32 OutputSize);
/**
* @brief Retrieves the size of the hash value for the specified hash handle.
* @param HashHandle The handle of the hash.
* @param HashSize A pointer to receive the size of the hash value in bytes.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseHashGetSize(
_In_ K7_BASE_HASH_HANDLE HashHandle,
_Out_ PMO_UINT32 HashSize);
/**
* @brief Duplicates the specified hash handle.
* @param SourceHashHandle The handle of the hash to be duplicated.
* @param DestinationHashHandle A pointer to receive the duplicated hash handle.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseHashDuplicate(
_In_ K7_BASE_HASH_HANDLE SourceHashHandle,
_Out_ PK7_BASE_HASH_HANDLE DestinationHashHandle);
#endif // !K7_BASE_HASH
#ifndef K7_BASE_POLICIES
#define K7_BASE_POLICIES
/**
* @brief Retrieves the policy setting for allowing a specific handler.
* @param Name The name of the handler to check.
* @return Returns MO_TRUE if the handler is allowed, or MO_FALSE if not.
*/
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowedHandlerPolicy(
_In_ MO_CONSTANT_STRING Name);
/**
* @brief Retrieves the policy setting for allowing a specific codec.
* @param Name The name of the codec to check.
* @return Returns MO_TRUE if the codec is allowed, or MO_FALSE if not.
*/
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowedCodecPolicy(
_In_ MO_CONSTANT_STRING Name);
/**
* @brief Retrieves the policy setting for Zone.Id stream propagation.
* @return Returns a Zone.Id stream propagation policy value set by the user, or
* MO_UINT32_MAX if user has not defined the policy.
*/
EXTERN_C MO_UINT32 MOAPI K7BaseGetWriteZoneIdExtractPolicy();
#endif // !K7_BASE_POLICIES
#ifndef K7_BASE_MITIGATIONS
#define K7_BASE_MITIGATIONS
/**
* @brief Disables dynamic code generation for the current process if the policy
* is set to disallow it.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseDisableDynamicCodeGeneration();
/**
* @brief Disables child process creation for the current process if the policy
* is set to disallow it.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseDisableChildProcessCreation();
#endif // !K7_BASE_MITIGATIONS
#ifndef K7_BASE_INITIALIZE
#define K7_BASE_INITIALIZE
/**
* @brief Initializes the K7Base library.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
* @remarks The function should be called only once during the initialization
* phase as early as possible.
*/
EXTERN_C MO_RESULT MOAPI K7BaseInitialize();
#endif // !K7_BASE_INITIALIZE
#ifndef K7_BASE_MODERN
#define K7_BASE_MODERN
/**
* @brief Converts a file time to a local file time.
* @param lpFileTime A pointer to a FILETIME structure containing the UTC-based
* file time to be converted into a local file time.
* @param lpLocalFileTime A pointer to a FILETIME structure to receive the
* converted local file time. This parameter cannot be
* the same as the lpFileTime parameter.
* @return If the function succeeds, the return value is nonzero. If the
* function fails, the return value is zero. To get extended error
* information, call GetLastError.
* @remark For more information, see FileTimeToLocalFileTime.
*/
EXTERN_C BOOL WINAPI K7BaseModernFileTimeToLocalFileTime(
_In_ CONST FILETIME* lpFileTime,
_Out_ LPFILETIME lpLocalFileTime);
/**
* @brief Converts a local file time to a file time based on the Coordinated
* Universal Time (UTC).
* @param lpLocalFileTime A pointer to a FILETIME structure that specifies the
* local file time to be converted into a UTC-based file
* time.
* @param lpFileTime A pointer to a FILETIME structure to receive the converted
* UTC-based file time. This parameter cannot be the same as
* the lpLocalFileTime parameter.
* @return If the function succeeds, the return value is nonzero. If the
* function fails, the return value is zero. To get extended error
* information, use the GetLastError function.
* @remark For more information, see LocalFileTimeToFileTime.
*/
EXTERN_C BOOL WINAPI K7BaseModernLocalFileTimeToFileTime(
_In_ CONST FILETIME* lpLocalFileTime,
_Out_ LPFILETIME lpFileTime);
#endif // !K7_BASE_MODERN
#endif // !K7_BASE
================================================
FILE: K7Base/K7Base.props
================================================
$(MSBuildThisFileDirectory);$(IncludePath)
$(OutDir)K7Base.lib;%(AdditionalDependencies)
1.0.372
{5998305E-D017-47C2-8025-A19111F73539}
================================================
FILE: K7Base/K7Base.vcxproj
================================================
{5998305E-D017-47C2-8025-A19111F73539}
K7Base
DynamicLibrary
10.0.19041.0
true
true
M2-Team
NanaZip Platform Base Library
K7Base
© M2-Team and Contributors. All rights reserved.
K7Base.dll
NanaZip
true
MultiThreadedDebug
MultiThreaded
K7Base.def
10.0
1.2.410
================================================
FILE: K7Base/K7BaseDetours.cpp
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BaseDetours.cpp
* PURPOSE: Implementation for NanaZip Platform Detours Library Wrappers
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7BasePrivate.h"
#include
EXTERN_C LONG MOAPI K7BaseDetourTransactionBegin()
{
return ::DetourTransactionBegin();
}
EXTERN_C LONG MOAPI K7BaseDetourTransactionAbort()
{
return ::DetourTransactionAbort();
}
EXTERN_C LONG MOAPI K7BaseDetourTransactionCommit()
{
return ::DetourTransactionCommit();
}
EXTERN_C LONG MOAPI K7BaseDetourUpdateThread(
_In_ HANDLE ThreadHandle)
{
return ::DetourUpdateThread(ThreadHandle);
}
EXTERN_C LONG MOAPI K7BaseDetourAttach(
_Inout_ PMO_POINTER OriginalFunction,
_In_ MO_POINTER DetouredFunction)
{
return ::DetourAttach(OriginalFunction, DetouredFunction);
}
EXTERN_C LONG MOAPI K7BaseDetourDetach(
_Inout_ PMO_POINTER OriginalFunction,
_In_ MO_POINTER DetouredFunction)
{
return ::DetourDetach(OriginalFunction, DetouredFunction);
}
================================================
FILE: K7Base/K7BaseHash.cpp
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BaseHash.cpp
* PURPOSE: Implementation for NanaZip Platform Hash Algorithms Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7BasePrivate.h"
#include
#include
#pragma comment(lib, "bcrypt.lib")
#include
#include
namespace
{
typedef struct _K7_BASE_HASH_ALGORITHM
{
MO_CONSTANT_WIDE_STRING Identifier;
BCRYPT_ALG_HANDLE Handle;
BCRYPT_ALG_HANDLE HmacHandle;
} K7_BASE_HASH_ALGORITHM, *PK7_BASE_HASH_ALGORITHM;
K7_BASE_HASH_ALGORITHM g_HashAlgorithms[K7_BASE_HASH_ALGORITHM_MAXIMUM] =
{
{ BCRYPT_MD2_ALGORITHM, nullptr, nullptr },
{ BCRYPT_MD4_ALGORITHM, nullptr, nullptr },
{ BCRYPT_MD5_ALGORITHM, nullptr, nullptr },
{ BCRYPT_SHA1_ALGORITHM, nullptr, nullptr },
{ BCRYPT_SHA256_ALGORITHM, nullptr, nullptr },
{ BCRYPT_SHA384_ALGORITHM, nullptr, nullptr },
{ BCRYPT_SHA512_ALGORITHM, nullptr, nullptr },
};
typedef struct _K7_BASE_HASH_CONTEXT
{
MO_UINT32 ContextSize;
MO_UINT32 HashSize;
MO_UINT32 HashObjectSize;
MO_POINTER HashObject;
BCRYPT_HASH_HANDLE HashHandle;
} K7_BASE_HASH_CONTEXT, *PK7_BASE_HASH_CONTEXT;
static PK7_BASE_HASH_CONTEXT K7BaseHashInternalGetContextFromHandle(
_In_opt_ K7_BASE_HASH_HANDLE HashHandle)
{
if (HashHandle)
{
__try
{
PK7_BASE_HASH_CONTEXT Context =
reinterpret_cast(HashHandle);
if (sizeof(K7_BASE_HASH_CONTEXT) == Context->ContextSize)
{
return Context;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// Fall through.
}
}
return nullptr;
}
}
EXTERN_C MO_RESULT MOAPI K7BaseHashCreate(
_Inout_ PK7_BASE_HASH_HANDLE HashHandle,
_In_ K7_BASE_HASH_ALGORITHM_TYPE Algorithm,
_In_opt_ MO_POINTER SecretBuffer,
_In_ MO_UINT32 SecretSize)
{
if (Algorithm < 0 ||
Algorithm >= K7_BASE_HASH_ALGORITHM_MAXIMUM)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
if (!HashHandle)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
*HashHandle = nullptr;
bool Result = false;
do
{
PK7_BASE_HASH_CONTEXT Context = reinterpret_cast(
::MileAllocateMemory(sizeof(K7_BASE_HASH_CONTEXT)));
if (!Context)
{
break;
}
*HashHandle = reinterpret_cast(Context);
Context->ContextSize = sizeof(K7_BASE_HASH_CONTEXT);
BCRYPT_ALG_HANDLE AlgorithmHandle = nullptr;
if (SecretBuffer)
{
if (!g_HashAlgorithms[Algorithm].HmacHandle)
{
if (!BCRYPT_SUCCESS(::BCryptOpenAlgorithmProvider(
&g_HashAlgorithms[Algorithm].HmacHandle,
g_HashAlgorithms[Algorithm].Identifier,
nullptr,
BCRYPT_ALG_HANDLE_HMAC_FLAG)))
{
break;
}
}
AlgorithmHandle = g_HashAlgorithms[Algorithm].HmacHandle;
}
else
{
if (!g_HashAlgorithms[Algorithm].Handle)
{
if (!BCRYPT_SUCCESS(::BCryptOpenAlgorithmProvider(
&g_HashAlgorithms[Algorithm].Handle,
g_HashAlgorithms[Algorithm].Identifier,
nullptr,
0)))
{
break;
}
}
AlgorithmHandle = g_HashAlgorithms[Algorithm].Handle;
}
{
DWORD ReturnLength = 0;
if (!BCRYPT_SUCCESS(::BCryptGetProperty(
AlgorithmHandle,
BCRYPT_HASH_LENGTH,
reinterpret_cast(&Context->HashSize),
sizeof(Context->HashSize),
&ReturnLength,
0)))
{
break;
}
}
{
DWORD ReturnLength = 0;
if (!BCRYPT_SUCCESS(::BCryptGetProperty(
AlgorithmHandle,
BCRYPT_OBJECT_LENGTH,
reinterpret_cast(&Context->HashObjectSize),
sizeof(Context->HashObjectSize),
&ReturnLength,
0)))
{
break;
}
}
Context->HashObject = ::MileAllocateMemory(Context->HashObjectSize);
if (!Context->HashObject)
{
break;
}
Result = BCRYPT_SUCCESS(::BCryptCreateHash(
AlgorithmHandle,
&Context->HashHandle,
reinterpret_cast(Context->HashObject),
Context->HashObjectSize,
SecretBuffer ? reinterpret_cast(SecretBuffer) : nullptr,
SecretBuffer ? SecretSize : 0,
0));
} while (false);
if (!Result)
{
::K7BaseHashDestroy(*HashHandle);
*HashHandle = nullptr;
}
return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;
}
EXTERN_C MO_RESULT MOAPI K7BaseHashDestroy(
_Inout_opt_ K7_BASE_HASH_HANDLE HashHandle)
{
PK7_BASE_HASH_CONTEXT Context =
::K7BaseHashInternalGetContextFromHandle(HashHandle);
if (!Context)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
Context->ContextSize = 0;
Context->HashSize = 0;
Context->HashObjectSize = 0;
if (Context->HashHandle)
{
::BCryptDestroyHash(Context->HashHandle);
Context->HashHandle = nullptr;
}
if (Context->HashObject)
{
::MileFreeMemory(Context->HashObject);
Context->HashObject = nullptr;
}
::MileFreeMemory(Context);
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7BaseHashUpdate(
_Inout_ K7_BASE_HASH_HANDLE HashHandle,
_In_ MO_POINTER InputBuffer,
_In_ MO_UINT32 InputSize)
{
PK7_BASE_HASH_CONTEXT Context =
::K7BaseHashInternalGetContextFromHandle(HashHandle);
if (!Context)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
bool Result = BCRYPT_SUCCESS(::BCryptHashData(
Context->HashHandle,
reinterpret_cast(InputBuffer),
InputSize,
0));
return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;
}
EXTERN_C MO_RESULT MOAPI K7BaseHashFinal(
_Inout_ K7_BASE_HASH_HANDLE HashHandle,
_Out_ MO_POINTER OutputBuffer,
_In_ MO_UINT32 OutputSize)
{
PK7_BASE_HASH_CONTEXT Context =
::K7BaseHashInternalGetContextFromHandle(HashHandle);
if (!Context)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
bool Result = false;
PVOID FinishHashObject = ::MileAllocateMemory(
Context->HashObjectSize);
if (FinishHashObject)
{
BCRYPT_HASH_HANDLE FinishHashHandle = nullptr;
if (BCRYPT_SUCCESS(::BCryptDuplicateHash(
Context->HashHandle,
&FinishHashHandle,
reinterpret_cast(FinishHashObject),
Context->HashObjectSize,
0)))
{
Result = BCRYPT_SUCCESS(::BCryptFinishHash(
FinishHashHandle,
reinterpret_cast(OutputBuffer),
OutputSize,
0));
::BCryptDestroyHash(FinishHashHandle);
}
::MileFreeMemory(FinishHashObject);
}
if (!Result)
{
if (OutputBuffer)
{
std::memset(OutputBuffer, 0, OutputSize);
}
}
return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;
}
EXTERN_C MO_RESULT MOAPI K7BaseHashGetSize(
_In_ K7_BASE_HASH_HANDLE HashHandle,
_Out_ PMO_UINT32 HashSize)
{
if (!HashSize)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
PK7_BASE_HASH_CONTEXT Context =
::K7BaseHashInternalGetContextFromHandle(HashHandle);
if (!Context)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
*HashSize = Context->HashSize;
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7BaseHashDuplicate(
_In_ K7_BASE_HASH_HANDLE SourceHashHandle,
_Out_ PK7_BASE_HASH_HANDLE DestinationHashHandle)
{
if (!DestinationHashHandle)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
*DestinationHashHandle = nullptr;
PK7_BASE_HASH_CONTEXT SourceContext =
::K7BaseHashInternalGetContextFromHandle(SourceHashHandle);
if (!SourceContext)
{
return MO_RESULT_ERROR_INVALID_PARAMETER;
}
bool Result = false;
do
{
PK7_BASE_HASH_CONTEXT Context = reinterpret_cast(
::MileAllocateMemory(sizeof(K7_BASE_HASH_CONTEXT)));
if (!Context)
{
break;
}
*DestinationHashHandle = reinterpret_cast(Context);
Context->ContextSize = sizeof(K7_BASE_HASH_CONTEXT);
Context->HashSize = SourceContext->HashSize;
Context->HashObjectSize = SourceContext->HashObjectSize;
Context->HashObject = ::MileAllocateMemory(Context->HashObjectSize);
if (!Context->HashObject)
{
break;
}
Result = BCRYPT_SUCCESS(::BCryptDuplicateHash(
SourceContext->HashHandle,
&Context->HashHandle,
reinterpret_cast(Context->HashObject),
Context->HashObjectSize,
0));
} while (false);
if (!Result)
{
::K7BaseHashDestroy(*DestinationHashHandle);
*DestinationHashHandle = nullptr;
}
return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;
}
================================================
FILE: K7Base/K7BaseInitialize.cpp
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BaseInitialize.cpp
* PURPOSE: Implementation for NanaZip Platform Base Initialize Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7BasePrivate.h"
EXTERN_C MO_RESULT MOAPI K7BaseInitialize()
{
static MO_BOOL g_Initialized = MO_FALSE;
if (g_Initialized)
{
return MO_RESULT_SUCCESS_OK;
}
MO_RESULT Result = MO_RESULT_SUCCESS_OK;
Result = ::K7BaseInitializePolicies();
if (MO_RESULT_SUCCESS_OK != Result)
{
return Result;
}
Result = ::K7BaseEnableMandatoryMitigations();
if (MO_RESULT_SUCCESS_OK != Result)
{
return Result;
}
Result = ::K7BaseInitializeDynamicLinkLibraryBlocker();
if (MO_RESULT_SUCCESS_OK != Result)
{
return Result;
}
g_Initialized = MO_TRUE;
// Do nothing if already initialized.
return MO_RESULT_SUCCESS_OK;
}
================================================
FILE: K7Base/K7BaseMitigations.cpp
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BaseMitigations.cpp
* PURPOSE: Implementation for NanaZip Platform Base Mitigations Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: dinhngtu (contact@tudinh.xyz)
* MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include
#include "K7BasePrivate.h"
#include
#include
#include
namespace
{
static BOOL GetCurrentProcessMitigationPolicy(
_In_ PROCESS_MITIGATION_POLICY MitigationPolicy,
_Out_ PVOID lpBuffer,
_In_ SIZE_T dwLength)
{
return ::GetProcessMitigationPolicy(
::GetCurrentProcess(),
MitigationPolicy,
lpBuffer,
dwLength);
}
}
EXTERN_C MO_RESULT MOAPI K7BaseEnableMandatoryMitigations()
{
{
PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY Policy = {};
// Get the current policy state to avoid failing to set the mitigation
// policy when the callers already have set the policy to a more strict
// state.
if (!::GetCurrentProcessMitigationPolicy(
ProcessStrictHandleCheckPolicy,
&Policy,
sizeof(PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY)))
{
// We should not trust the policy state if the get call fails, but
// we can still try to set the policy.
Policy = {};
}
Policy.RaiseExceptionOnInvalidHandleReference = 1;
Policy.HandleExceptionsPermanentlyEnabled = 1;
if (!::SetProcessMitigationPolicy(
ProcessStrictHandleCheckPolicy,
&Policy,
sizeof(PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY)))
{
return MO_RESULT_ERROR_FAIL;
}
}
{
PROCESS_MITIGATION_IMAGE_LOAD_POLICY Policy = {};
// Get the current policy state to avoid failing to set the mitigation
// policy when the callers already have set the policy to a more strict
// state.
if (!::GetCurrentProcessMitigationPolicy(
ProcessImageLoadPolicy,
&Policy,
sizeof(PROCESS_MITIGATION_IMAGE_LOAD_POLICY)))
{
// We should not trust the policy state if the get call fails, but
// we can still try to set the policy.
Policy = {};
}
Policy.NoRemoteImages = 1;
Policy.NoLowMandatoryLabelImages = 1;
if (!::SetProcessMitigationPolicy(
ProcessImageLoadPolicy,
&Policy,
sizeof(PROCESS_MITIGATION_IMAGE_LOAD_POLICY)))
{
return MO_RESULT_ERROR_FAIL;
}
}
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7BaseDisableDynamicCodeGeneration()
{
#ifndef _DEBUG
if (!::K7BaseGetAllowDynamicCodeGenerationPolicy())
{
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY Policy = {};
// Get the current policy state to avoid failing to set the mitigation
// policy when the callers already have set the policy to a more strict
// state.
if (!::GetCurrentProcessMitigationPolicy(
ProcessDynamicCodePolicy,
&Policy,
sizeof(PROCESS_MITIGATION_DYNAMIC_CODE_POLICY)))
{
// We should not trust the policy state if the get call fails, but
// we can still try to set the policy.
Policy = {};
}
Policy.ProhibitDynamicCode = 1;
Policy.AllowThreadOptOut = 1;
if (!::SetProcessMitigationPolicy(
ProcessDynamicCodePolicy,
&Policy,
sizeof(PROCESS_MITIGATION_DYNAMIC_CODE_POLICY)))
{
return MO_RESULT_ERROR_FAIL;
}
}
#endif // _DEBUG
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7BaseDisableChildProcessCreation()
{
if (!::K7BaseGetAllowChildProcessCreationPolicy())
{
PROCESS_MITIGATION_CHILD_PROCESS_POLICY Policy = {};
// Get the current policy state to avoid failing to set the mitigation
// policy when the callers already have set the policy to a more strict
// state.
if (!::GetCurrentProcessMitigationPolicy(
ProcessChildProcessPolicy,
&Policy,
sizeof(PROCESS_MITIGATION_CHILD_PROCESS_POLICY)))
{
// We should not trust the policy state if the get call fails, but
// we can still try to set the policy.
Policy = {};
}
Policy.NoChildProcessCreation = 1;
if (!::SetProcessMitigationPolicy(
ProcessChildProcessPolicy,
&Policy,
sizeof(PROCESS_MITIGATION_CHILD_PROCESS_POLICY)))
{
return MO_RESULT_ERROR_FAIL;
}
}
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7BaseSetCurrentThreadDynamicCodePolicyOptOut(
_In_ MO_BOOL AllowDynamicCodeGeneration)
{
#ifndef _DEBUG
if (::K7BaseGetAllowDynamicCodeGenerationPolicy())
{
return TRUE;
}
DWORD PolicyValue = AllowDynamicCodeGeneration
? THREAD_DYNAMIC_CODE_ALLOW
: 0;
if (!::SetThreadInformation(
::GetCurrentThread(),
ThreadDynamicCodePolicy,
&PolicyValue,
sizeof(DWORD)))
{
return MO_RESULT_ERROR_FAIL;
}
#else
UNREFERENCED_PARAMETER(AllowDynamicCodeGeneration);
#endif
return MO_RESULT_SUCCESS_OK;
}
#ifndef _DEBUG
namespace
{
namespace ModuleTypes
{
enum
{
Unknown,
NeedsBlocking,
NeedsDynamicCodeOptout,
};
}
struct ModuleItem
{
MO_UINT8 ModuleType;
MO_CONSTANT_STRING ModuleName;
};
/**
* @remarks Make sure that this list is sorted for _stricmp.
*/
const ModuleItem g_ModuleRules[] =
{
{ ModuleTypes::NeedsDynamicCodeOptout, "BaseGUI.dll" },
{ ModuleTypes::NeedsBlocking, "ExplorerPatcher.amd64.dll" },
{ ModuleTypes::NeedsBlocking, "ExplorerPatcher.IA-32.dll" },
{ ModuleTypes::NeedsBlocking, "PrxDrvPE.dll" },
{ ModuleTypes::NeedsBlocking, "PrxDrvPE64.dll" },
{ ModuleTypes::NeedsBlocking, "TFMain32.dll" },
{ ModuleTypes::NeedsBlocking, "TFMain64.dll" },
};
static MO_UINT8 QueryModuleType(
_In_ MO_CONSTANT_STRING ModuleName)
{
for (MO_UINT32 i = 0; i < MO_ARRAY_SIZE(g_ModuleRules); ++i)
{
if (!::_stricmp(ModuleName, g_ModuleRules[i].ModuleName))
{
return g_ModuleRules[i].ModuleType;
}
}
return ModuleTypes::Unknown;
}
static std::mutex g_DynamicCodeRangesMutex;
static std::vector> g_DynamicCodeRanges;
static bool IsDynamicCodeAllowed(
_In_ MO_POINTER CallerPointer)
{
MO_UINTN CallerAddress = reinterpret_cast(CallerPointer);
std::lock_guard Lock(g_DynamicCodeRangesMutex);
for (auto const& Range : g_DynamicCodeRanges)
{
if (CallerAddress >= Range.first &&
CallerAddress < Range.first + Range.second)
{
return true;
}
}
return false;
}
static bool IsCurrentProcessHandle(
_In_ HANDLE ProcessHandle)
{
if (ProcessHandle == ::GetCurrentProcess() ||
::GetCurrentProcessId() == ::GetProcessId(ProcessHandle))
{
return true;
}
return false;
}
static bool IsPageExecute(
_In_ DWORD Protect)
{
if (PAGE_EXECUTE == Protect ||
PAGE_EXECUTE_READ == Protect ||
PAGE_EXECUTE_READWRITE == Protect ||
PAGE_EXECUTE_WRITECOPY == Protect)
{
return true;
}
return false;
}
static inline bool CheckExtents(
_In_ MO_UINTN ViewSize,
_In_ MO_UINTN Offset,
_In_ MO_UINTN Size)
{
return (
Offset < ViewSize &&
Size <= ViewSize &&
Offset + Size <= ViewSize);
}
static bool GetModuleExportName(
_In_ MO_CHAR(&ModuleName)[256],
_In_ MO_STRING Base,
_In_ MO_UINTN ViewSize)
{
if (sizeof(IMAGE_DOS_HEADER) > ViewSize)
{
return false;
}
PIMAGE_DOS_HEADER DosHeader = reinterpret_cast(Base);
if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic)
{
return false;
}
if (0 > DosHeader->e_lfanew ||
!::CheckExtents(
ViewSize,
DosHeader->e_lfanew,
sizeof(IMAGE_NT_HEADERS)))
{
return false;
}
PIMAGE_NT_HEADERS NtHeader = reinterpret_cast(
Base + DosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != NtHeader->Signature ||
IMAGE_DIRECTORY_ENTRY_EXPORT >
NtHeader->OptionalHeader.NumberOfRvaAndSizes)
{
return false;
}
PIMAGE_DATA_DIRECTORY ExportDirectory =
&(NtHeader->OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_EXPORT]);
if (sizeof(IMAGE_EXPORT_DIRECTORY) > ExportDirectory->Size ||
!ExportDirectory->VirtualAddress ||
!::CheckExtents(
ViewSize,
ExportDirectory->VirtualAddress,
sizeof(IMAGE_EXPORT_DIRECTORY)))
{
return false;
}
PIMAGE_EXPORT_DIRECTORY Exports =
reinterpret_cast(
Base + ExportDirectory->VirtualAddress);
// We don't know the export directory name size so assume that at least
// 256 bytes after the name are safe.
if (!Exports->Name ||
!::CheckExtents(
ViewSize,
Exports->Name,
MO_ARRAY_SIZE(ModuleName)))
{
return false;
}
const char* Name = Base + Exports->Name;
if (::strncpy_s(ModuleName, Name, _TRUNCATE))
{
return false;
}
return true;
}
namespace FunctionTypes
{
enum
{
NtMapViewOfSection,
NtQuerySection,
NtUnmapViewOfSection,
VirtualAlloc,
VirtualAllocEx,
VirtualProtect,
VirtualProtectEx,
MaximumFunction
};
}
struct FunctionItem
{
PVOID Original;
PVOID Detoured;
};
static FunctionItem g_FunctionTable[FunctionTypes::MaximumFunction];
static NTSTATUS NTAPI OriginalNtMapViewOfSection(
_In_ HANDLE SectionHandle,
_In_ HANDLE ProcessHandle,
_Inout_ PVOID* BaseAddress,
_In_ ULONG_PTR ZeroBits,
_In_ SIZE_T CommitSize,
_Inout_opt_ PLARGE_INTEGER SectionOffset,
_Inout_ PSIZE_T ViewSize,
_In_ SECTION_INHERIT InheritDisposition,
_In_ ULONG AllocationType,
_In_ ULONG PageProtection)
{
using FunctionType = decltype(::NtMapViewOfSection)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::NtMapViewOfSection].Original);
if (!FunctionAddress)
{
return STATUS_NOINTERFACE;
}
return FunctionAddress(
SectionHandle,
ProcessHandle,
BaseAddress,
ZeroBits,
CommitSize,
SectionOffset,
ViewSize,
InheritDisposition,
AllocationType,
PageProtection);
}
static NTSTATUS NTAPI OriginalNtQuerySection(
_In_ HANDLE SectionHandle,
_In_ SECTION_INFORMATION_CLASS SectionInformationClass,
_Out_ PVOID SectionInformation,
_In_ SIZE_T SectionInformationLength,
_Out_opt_ PSIZE_T ReturnLength)
{
using FunctionType = decltype(::NtQuerySection)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::NtQuerySection].Original);
if (!FunctionAddress)
{
return STATUS_NOINTERFACE;
}
return FunctionAddress(
SectionHandle,
SectionInformationClass,
SectionInformation,
SectionInformationLength,
ReturnLength);
}
static NTSTATUS NTAPI OriginalNtUnmapViewOfSection(
_In_ HANDLE ProcessHandle,
_In_opt_ PVOID BaseAddress)
{
using FunctionType = decltype(::NtUnmapViewOfSection)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::NtUnmapViewOfSection].Original);
if (!FunctionAddress)
{
return STATUS_NOINTERFACE;
}
return FunctionAddress(
ProcessHandle,
BaseAddress);
}
static LPVOID WINAPI OriginalVirtualAlloc(
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect)
{
using FunctionType = decltype(::VirtualAlloc)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::VirtualAlloc].Original);
if (!FunctionAddress)
{
::SetLastError(ERROR_NOINTERFACE);
return nullptr;
}
return FunctionAddress(
lpAddress,
dwSize,
flAllocationType,
flProtect);
}
static LPVOID WINAPI OriginalVirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect)
{
using FunctionType = decltype(::VirtualAllocEx)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::VirtualAllocEx].Original);
if (!FunctionAddress)
{
::SetLastError(ERROR_NOINTERFACE);
return nullptr;
}
return FunctionAddress(
hProcess,
lpAddress,
dwSize,
flAllocationType,
flProtect);
}
static BOOL WINAPI OriginalVirtualProtect(
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flNewProtect,
_Out_ PDWORD lpflOldProtect)
{
using FunctionType = decltype(::VirtualProtect)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::VirtualProtect].Original);
if (!FunctionAddress)
{
::SetLastError(ERROR_NOINTERFACE);
return FALSE;
}
return FunctionAddress(
lpAddress,
dwSize,
flNewProtect,
lpflOldProtect);
}
static BOOL WINAPI OriginalVirtualProtectEx(
_In_ HANDLE hProcess,
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flNewProtect,
_Out_ PDWORD lpflOldProtect)
{
using FunctionType = decltype(::VirtualProtectEx)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::VirtualProtectEx].Original);
if (!FunctionAddress)
{
::SetLastError(ERROR_NOINTERFACE);
return FALSE;
}
return FunctionAddress(
hProcess,
lpAddress,
dwSize,
flNewProtect,
lpflOldProtect);
}
static NTSTATUS NTAPI DetouredNtMapViewOfSection(
_In_ HANDLE SectionHandle,
_In_ HANDLE ProcessHandle,
_Inout_ PVOID* BaseAddress,
_In_ ULONG_PTR ZeroBits,
_In_ SIZE_T CommitSize,
_Inout_opt_ PLARGE_INTEGER SectionOffset,
_Inout_ PSIZE_T ViewSize,
_In_ SECTION_INHERIT InheritDisposition,
_In_ ULONG AllocationType,
_In_ ULONG PageProtection)
{
NTSTATUS Status = ::OriginalNtMapViewOfSection(
SectionHandle,
ProcessHandle,
BaseAddress,
ZeroBits,
CommitSize,
SectionOffset,
ViewSize,
InheritDisposition,
AllocationType,
PageProtection);
if (!NT_SUCCESS(Status) ||
!::IsCurrentProcessHandle(ProcessHandle) ||
!::IsPageExecute(PageProtection))
{
return Status;
}
{
SECTION_BASIC_INFORMATION Information = {};
if (!NT_SUCCESS(::OriginalNtQuerySection(
SectionHandle,
SectionBasicInformation,
&Information,
sizeof(SECTION_BASIC_INFORMATION),
nullptr)) ||
!(SEC_IMAGE & Information.AllocationAttributes))
{
return Status;
}
}
MO_CHAR ModuleName[256] = {};
if (!::GetModuleExportName(
ModuleName,
reinterpret_cast(*BaseAddress),
*ViewSize))
{
return Status;
}
MO_UINT8 ModuleType = ::QueryModuleType(ModuleName);
if (ModuleTypes::NeedsBlocking & ModuleType)
{
::OriginalNtUnmapViewOfSection(ProcessHandle, *BaseAddress);
return STATUS_ACCESS_DENIED;
}
else if (ModuleTypes::NeedsDynamicCodeOptout & ModuleType)
{
std::lock_guard Lock(g_DynamicCodeRangesMutex);
g_DynamicCodeRanges.emplace_back(
reinterpret_cast(*BaseAddress),
*ViewSize);
}
return Status;
}
static NTSTATUS NTAPI DetouredNtUnmapViewOfSection(
_In_ HANDLE ProcessHandle,
_In_opt_ PVOID BaseAddress)
{
NTSTATUS Status = ::OriginalNtUnmapViewOfSection(
ProcessHandle,
BaseAddress);
if (NT_SUCCESS(Status) &&
::IsCurrentProcessHandle(ProcessHandle))
{
MO_UINTN BaseStart = reinterpret_cast(BaseAddress);
std::lock_guard Lock(g_DynamicCodeRangesMutex);
for (auto Iterator = g_DynamicCodeRanges.begin();
Iterator != g_DynamicCodeRanges.end();
++Iterator)
{
if (BaseStart >= Iterator->first &&
BaseStart < Iterator->first + Iterator->second)
{
g_DynamicCodeRanges.erase(Iterator);
break;
}
}
}
return Status;
}
static LPVOID WINAPI DetouredVirtualAlloc(
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect)
{
if (!::IsPageExecute(flProtect) ||
!::IsDynamicCodeAllowed(::_ReturnAddress()))
{
return ::OriginalVirtualAlloc(
lpAddress,
dwSize,
flAllocationType,
flProtect);
}
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);
LPVOID Result = ::OriginalVirtualAlloc(
lpAddress,
dwSize,
flAllocationType,
flProtect);
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);
return Result;
}
static LPVOID WINAPI DetouredVirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect)
{
if (!::IsCurrentProcessHandle(hProcess) ||
!::IsPageExecute(flProtect) ||
!::IsDynamicCodeAllowed(::_ReturnAddress()))
{
return ::OriginalVirtualAllocEx(
hProcess,
lpAddress,
dwSize,
flAllocationType,
flProtect);
}
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);
LPVOID Result = ::OriginalVirtualAllocEx(
hProcess,
lpAddress,
dwSize,
flAllocationType,
flProtect);
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);
return Result;
}
static BOOL WINAPI DetouredVirtualProtect(
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flNewProtect,
_Out_ PDWORD lpflOldProtect)
{
if (!::IsPageExecute(flNewProtect) ||
!::IsDynamicCodeAllowed(::_ReturnAddress()))
{
return ::OriginalVirtualProtect(
lpAddress,
dwSize,
flNewProtect,
lpflOldProtect);
}
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);
BOOL Result = ::OriginalVirtualProtect(
lpAddress,
dwSize,
flNewProtect,
lpflOldProtect);
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);
return Result;
}
static BOOL WINAPI DetouredVirtualProtectEx(
_In_ HANDLE hProcess,
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flNewProtect,
_Out_ PDWORD lpflOldProtect)
{
if (!::IsCurrentProcessHandle(hProcess) ||
!::IsPageExecute(flNewProtect) ||
!::IsDynamicCodeAllowed(::_ReturnAddress()))
{
return ::OriginalVirtualProtectEx(
hProcess,
lpAddress,
dwSize,
flNewProtect,
lpflOldProtect);
}
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);
BOOL Result = ::OriginalVirtualProtectEx(
hProcess,
lpAddress,
dwSize,
flNewProtect,
lpflOldProtect);
::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);
return Result;
}
static bool InitializeFunctionTable()
{
HMODULE NtDllModuleHandle = ::GetModuleHandleW(L"ntdll.dll");
if (!NtDllModuleHandle)
{
return false;
}
g_FunctionTable[FunctionTypes::NtMapViewOfSection].Original =
::GetProcAddress(NtDllModuleHandle, "NtMapViewOfSection");
g_FunctionTable[FunctionTypes::NtMapViewOfSection].Detoured =
::DetouredNtMapViewOfSection;
g_FunctionTable[FunctionTypes::NtQuerySection].Original =
::GetProcAddress(NtDllModuleHandle, "NtQuerySection");
g_FunctionTable[FunctionTypes::NtQuerySection].Detoured =
nullptr;
g_FunctionTable[FunctionTypes::NtUnmapViewOfSection].Original =
::GetProcAddress(NtDllModuleHandle, "NtUnmapViewOfSection");
g_FunctionTable[FunctionTypes::NtUnmapViewOfSection].Detoured =
::DetouredNtUnmapViewOfSection;
g_FunctionTable[FunctionTypes::VirtualAlloc].Original =
::VirtualAlloc;
g_FunctionTable[FunctionTypes::VirtualAlloc].Detoured =
::DetouredVirtualAlloc;
g_FunctionTable[FunctionTypes::VirtualAllocEx].Original =
::VirtualAllocEx;
g_FunctionTable[FunctionTypes::VirtualAllocEx].Detoured =
::DetouredVirtualAllocEx;
g_FunctionTable[FunctionTypes::VirtualProtect].Original =
::VirtualProtect;
g_FunctionTable[FunctionTypes::VirtualProtect].Detoured =
::DetouredVirtualProtect;
g_FunctionTable[FunctionTypes::VirtualProtectEx].Original =
::VirtualProtectEx;
g_FunctionTable[FunctionTypes::VirtualProtectEx].Detoured =
::DetouredVirtualProtectEx;
return true;
}
static void UninitializeFunctionTable()
{
for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)
{
g_FunctionTable[i].Original = nullptr;
g_FunctionTable[i].Detoured = nullptr;
}
}
}
#endif // _DEBUG
EXTERN_C MO_RESULT MOAPI K7BaseInitializeDynamicLinkLibraryBlocker()
{
#ifndef _DEBUG
if (::K7BaseGetAllowDynamicCodeGenerationPolicy())
{
return MO_RESULT_SUCCESS_OK;
}
if (!::InitializeFunctionTable())
{
return MO_RESULT_ERROR_FAIL;
}
::K7BaseDetourTransactionBegin();
::K7BaseDetourUpdateThread(::GetCurrentThread());
for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)
{
if (g_FunctionTable[i].Original &&
g_FunctionTable[i].Detoured)
{
if (NO_ERROR != ::K7BaseDetourAttach(
&g_FunctionTable[i].Original,
g_FunctionTable[i].Detoured))
{
::K7BaseDetourTransactionAbort();
::UninitializeFunctionTable();
return MO_RESULT_ERROR_FAIL;
}
}
}
::K7BaseDetourTransactionCommit();
#endif // _DEBUG
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7BaseUninitializeDynamicLinkLibraryBlocker()
{
#ifndef _DEBUG
if (::K7BaseGetAllowDynamicCodeGenerationPolicy())
{
return MO_RESULT_SUCCESS_OK;
}
::K7BaseDetourTransactionBegin();
::K7BaseDetourUpdateThread(::GetCurrentThread());
for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)
{
if (g_FunctionTable[i].Original &&
g_FunctionTable[i].Detoured)
{
if (NO_ERROR != ::K7BaseDetourDetach(
&g_FunctionTable[i].Original,
g_FunctionTable[i].Detoured))
{
::K7BaseDetourTransactionAbort();
return MO_RESULT_ERROR_FAIL;
}
}
}
::K7BaseDetourTransactionCommit();
::UninitializeFunctionTable();
{
std::lock_guard Lock(g_DynamicCodeRangesMutex);
g_DynamicCodeRanges.clear();
}
#endif // _DEBUG
return MO_RESULT_SUCCESS_OK;
}
================================================
FILE: K7Base/K7BaseModern.cpp
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BaseModern.cpp
* PURPOSE: Implementation for NanaZip Platform Base Modern Experiences
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7BasePrivate.h"
EXTERN_C BOOL WINAPI K7BaseModernFileTimeToLocalFileTime(
_In_ CONST FILETIME* lpFileTime,
_Out_ LPFILETIME lpLocalFileTime)
{
if (!lpFileTime || !lpLocalFileTime)
{
::SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SYSTEMTIME UtcSystemTime = {};
if (!::FileTimeToSystemTime(lpFileTime, &UtcSystemTime))
{
return FALSE;
}
SYSTEMTIME LocalSystemTime = {};
if (!::SystemTimeToTzSpecificLocalTimeEx(
nullptr,
&UtcSystemTime,
&LocalSystemTime))
{
return FALSE;
}
return ::SystemTimeToFileTime(&LocalSystemTime, lpLocalFileTime);
}
EXTERN_C BOOL WINAPI K7BaseModernLocalFileTimeToFileTime(
_In_ CONST FILETIME* lpLocalFileTime,
_Out_ LPFILETIME lpFileTime)
{
if (!lpLocalFileTime || !lpFileTime)
{
::SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SYSTEMTIME LocalSystemTime = {};
if (!::FileTimeToSystemTime(lpLocalFileTime, &LocalSystemTime))
{
return FALSE;
}
SYSTEMTIME UtcSystemTime = {};
if (!::TzSpecificLocalTimeToSystemTimeEx(
nullptr,
&LocalSystemTime,
&UtcSystemTime))
{
return FALSE;
}
return ::SystemTimeToFileTime(&UtcSystemTime, lpFileTime);
}
================================================
FILE: K7Base/K7BasePolicies.cpp
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BasePolicies.cpp
* PURPOSE: Implementation for NanaZip Platform Base Policies Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: dinhngtu (contact@tudinh.xyz)
* MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7BasePrivate.h"
#include
#include
#include
namespace
{
// Note: These static variables are initialized with default policy
// settings. Also, no thread-safety mechanism is needed here because the
// only modification of these variables happens in the
// K7BaseInitializePolicies function should be called only once during the
// K7Base library initialization phase as early as possible.
static MO_BOOL g_AllowDynamicCodeGeneration = MO_FALSE;
static MO_BOOL g_AllowChildProcessCreation = MO_FALSE;
static std::set g_AllowedHandlers;
static std::set g_BlockedHandlers;
static std::set g_AllowedCodecs;
static std::set g_BlockedCodecs;
// MO_UINT32_MAX is undefined
static MO_UINT32 g_WriteZoneIdExtract = MO_UINT32_MAX;
static bool QueryDwordValue(
_Out_ PDWORD Value,
_In_ HKEY KeyHandle,
_In_ LPCWSTR ValueName)
{
DWORD Type = REG_NONE;
DWORD Length = sizeof(DWORD);
if (ERROR_SUCCESS != ::RegQueryValueExW(
KeyHandle,
ValueName,
nullptr,
&Type,
reinterpret_cast(Value),
&Length))
{
return false;
}
if (REG_DWORD != Type || sizeof(DWORD) != Length)
{
return false;
}
return true;
}
static std::set QueryMultiStringValue(
_In_ HKEY KeyHandle,
_In_ LPCWSTR ValueName)
{
std::set Result;
PMO_WIDE_CHAR Buffer = nullptr;
do
{
DWORD Type = REG_NONE;
DWORD Length = sizeof(DWORD);
if (ERROR_SUCCESS != ::RegQueryValueExW(
KeyHandle,
ValueName,
nullptr,
&Type,
nullptr,
&Length))
{
break;
}
if (REG_MULTI_SZ != Type)
{
break;
}
Buffer = static_cast(::MileAllocateMemory(Length));
if (!Buffer)
{
break;
}
if (ERROR_SUCCESS != ::RegQueryValueExW(
KeyHandle,
ValueName,
nullptr,
nullptr,
reinterpret_cast(Buffer),
&Length))
{
break;
}
for (PMO_WIDE_CHAR Current = Buffer;
*Current;
Current += std::wcslen(Current) + 1)
{
Result.insert(Mile::ToString(CP_UTF8, std::wstring(Current)));
}
}
while (false);
if (Buffer)
{
::MileFreeMemory(Buffer);
}
return Result;
}
}
EXTERN_C MO_RESULT MOAPI K7BaseInitializePolicies()
{
HKEY PoliciesKeyHandle = nullptr;
if (ERROR_SUCCESS != ::RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"Software\\Policies\\M2Team\\NanaZip",
0,
KEY_READ | KEY_WOW64_64KEY,
&PoliciesKeyHandle))
{
// NanaZip should use the default policy settings if the relevant
// policies registry key cannot be opened successfully.
return MO_RESULT_SUCCESS_OK;
}
{
DWORD Value = 0;
if (::QueryDwordValue(
&Value,
PoliciesKeyHandle,
L"AllowDynamicCodeGeneration"))
{
if (1 == Value)
{
// Only when the registry value is 1, NanaZip will allow dynamic
// code generation.
g_AllowDynamicCodeGeneration = MO_TRUE;
}
}
}
{
DWORD Value = 0;
if (::QueryDwordValue(
&Value,
PoliciesKeyHandle,
L"AllowChildProcessCreation"))
{
if (1 == Value)
{
// Only when the registry value is 1, NanaZip will allow child
// process creation.
g_AllowChildProcessCreation = MO_TRUE;
}
}
}
g_AllowedHandlers = ::QueryMultiStringValue(
PoliciesKeyHandle,
L"AllowedHandlers");
g_BlockedHandlers = ::QueryMultiStringValue(
PoliciesKeyHandle,
L"BlockedHandlers");
g_AllowedCodecs = ::QueryMultiStringValue(
PoliciesKeyHandle,
L"AllowedCodecs");
g_BlockedCodecs = ::QueryMultiStringValue(
PoliciesKeyHandle,
L"BlockedCodecs");
{
DWORD Value = 0;
if (::QueryDwordValue(
&Value,
PoliciesKeyHandle,
L"WriteZoneIdExtract"))
{
// Valid values are 0, 1, and 2.
if (Value <= 2)
{
g_WriteZoneIdExtract = Value;
}
}
}
::RegCloseKey(PoliciesKeyHandle);
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowDynamicCodeGenerationPolicy()
{
return g_AllowDynamicCodeGeneration;
}
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowChildProcessCreationPolicy()
{
return g_AllowChildProcessCreation;
}
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowedHandlerPolicy(
_In_ MO_CONSTANT_STRING Name)
{
std::string HandlerName = std::string(Name);
if (!g_AllowedHandlers.empty())
{
return g_AllowedHandlers.contains(HandlerName) ? MO_TRUE : MO_FALSE;
}
if (!g_BlockedHandlers.empty())
{
return g_BlockedHandlers.contains(HandlerName) ? MO_FALSE : MO_TRUE;
}
return MO_TRUE;
}
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowedCodecPolicy(
_In_ MO_CONSTANT_STRING Name)
{
std::string CodecName = std::string(Name);
if (!g_AllowedCodecs.empty())
{
return g_AllowedCodecs.contains(CodecName) ? MO_TRUE : MO_FALSE;
}
if (!g_BlockedCodecs.empty())
{
return g_BlockedCodecs.contains(CodecName) ? MO_FALSE : MO_TRUE;
}
return MO_TRUE;
}
EXTERN_C MO_UINT32 MOAPI K7BaseGetWriteZoneIdExtractPolicy()
{
return g_WriteZoneIdExtract;
}
================================================
FILE: K7Base/K7BasePrivate.h
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BasePrivate.h
* PURPOSE: Definition for NanaZip Platform Base Private Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#ifndef K7_BASE_PRIVATE
#define K7_BASE_PRIVATE
#include "K7Base.h"
#ifndef K7_BASE_POLICIES_PRIVATE
#define K7_BASE_POLICIES_PRIVATE
/**
* @brief Initializes the NanaZip policy settings.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
* @remarks The function should be called only once during the K7Base library
* initialization phase as early as possible.
*/
EXTERN_C MO_RESULT MOAPI K7BaseInitializePolicies();
/**
* @brief Retrieves the policy setting for allowing dynamic code generation.
* @return Returns MO_TRUE if dynamic code generation is allowed, or MO_FALSE if
* not.
*/
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowDynamicCodeGenerationPolicy();
/**
* @brief Retrieves the policy setting for allowing child process creation.
* @return Returns MO_TRUE if child process creation is allowed, or MO_FALSE if
* not.
*/
EXTERN_C MO_BOOL MOAPI K7BaseGetAllowChildProcessCreationPolicy();
#endif // !K7_BASE_POLICIES_PRIVATE
#ifndef K7_BASE_MITIGATIONS_PRIVATE
#define K7_BASE_MITIGATIONS_PRIVATE
/**
* @brief Enables the mandatory mitigations for the current process.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseEnableMandatoryMitigations();
/**
* @brief Sets the dynamic code generation policy for the current thread.
* @param AllowDynamicCodeGeneration Indicates whether to allow dynamic code
* generation for the current thread.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseSetCurrentThreadDynamicCodePolicyOptOut(
_In_ MO_BOOL AllowDynamicCodeGeneration);
/**
* @brief Initializes the dynamic link library blocker to workaround various
* issues caused by incompatible dynamic link libraries.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseInitializeDynamicLinkLibraryBlocker();
/**
* @brief Uninitializes the dynamic link library blocker.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7BaseUninitializeDynamicLinkLibraryBlocker();
#endif // !K7_BASE_MITIGATIONS_PRIVATE
#endif // !K7_BASE_PRIVATE
================================================
FILE: K7Base/K7BaseRedirector.cpp
================================================
/*
* PROJECT: NanaZip Platform Base Library (K7Base)
* FILE: K7BaseRedirector.cpp
* PURPOSE: Implementation for NanaZip Platform Base API Redirector
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7BasePrivate.h"
// Here are the linker-time redirections to replace the original APIs.
// Implementations only for x64 and ARM64, if you want to learn how to achieve
// that in x86, please refer to NanaZip.Shared.ModernExperienceShims project in
// the historical NanaZip versions source code.
#ifndef K7_REDIRECT
#define K7_REDIRECT(Source, Target) \
extern "C" __declspec(selectany) void const* const __imp_##Source = \
reinterpret_cast(::Target); \
__pragma(comment(linker, "/include:__imp_" #Source))
#endif // !K7_REDIRECT
K7_REDIRECT(FileTimeToLocalFileTime, K7BaseModernFileTimeToLocalFileTime);
K7_REDIRECT(LocalFileTimeToFileTime, K7BaseModernLocalFileTimeToFileTime);
================================================
FILE: K7Base/K7BaseStatic.props
================================================
$(MSBuildThisFileDirectory);$(IncludePath)
$(OutDir)K7BaseStatic.lib;%(AdditionalDependencies)
1.0.372
{38BB5165-3DB0-45B7-85CE-0A72DEF5CCD6}
================================================
FILE: K7Base/K7BaseStatic.vcxproj
================================================
{38BB5165-3DB0-45B7-85CE-0A72DEF5CCD6}
K7Base
StaticLibrary
true
MultiThreadedDebug
MultiThreaded
1.0.372
1.0.3550
1.0.2180
1.0.1171
================================================
FILE: K7Base/ReadMe.md
================================================
# NanaZip Platform Base Library (K7Base)
***Work In Progress***
The static and dynamic library that encapsulates the non-GUI portion of the base
platform infrastructure for the NanaZip. It's one of the foundational libraries
of the NanaZip Platform Abstraction Layer.
K7 is the alias of NanaZip. Here is the relationship between K7 and NanaZip: I
had mentioned one of the reasons that I call this project NanaZip because Nana
is the romaji of なな which means seven in Japanese. But I had not mentioned the
way I confirm that: I had recalled one of the Japanese VTubers called Kagura
Nana when I waiting my elder sister for dinner at Taiyanggong subway station,
Beijing. For playing more puns, NanaZip uses the K7 (K -> Kagura, 7 -> Nana) as
the alias.
K7Base is designed for Windows only, although the most of the K7Base interfaces
are designed to be platform-independent. Maybe in the future, the K7Base will
have the implementations for Linux and FreeBSD, although the implementation may
not in this repository.
## Features
- Cryptography Support
- Hash Functions
- MD2
- MD4
- MD5
- SHA-1
- SHA-256
- SHA-384
- SHA-512
- Detours Library Wrappers
- Modern Experiences Support (non-GUI)
- Policies Support
- Security Mitigations Support
================================================
FILE: K7User/K7User.def
================================================
LIBRARY
EXPORTS
K7UserInitializeDarkModeSupport
K7UserModernMessageBoxW
K7UserModernSHBrowseForFolderW
K7UserModernLaunchDefaultAppsSettings
K7UserModernSetForegroundWindow
K7UserModernSetForegroundProcessMainWindow
================================================
FILE: K7User/K7User.h
================================================
/*
* PROJECT: NanaZip Platform User Library (K7User)
* FILE: K7User.h
* PURPOSE: Definition for NanaZip Platform User Public Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#ifndef K7_USER
#define K7_USER
#include
#ifndef MILE_MOBILITY_ENABLE_MINIMUM_SAL
#include
#endif // !MILE_MOBILITY_ENABLE_MINIMUM_SAL
// Workaround for Windows SDK, which defines these types in #ifndef VOID block.
// That design is terrible, but needs to have a workaround.
#ifdef VOID
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
#endif // VOID
#include
#include
#ifndef K7_USER_DARK_MODE
#define K7_USER_DARK_MODE
/**
* @brief Initializes the dark mode support.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7UserInitializeDarkModeSupport();
#endif // !K7_USER_DARK_MODE
#ifndef K7_USER_MODERN
#define K7_USER_MODERN
/**
* @brief Displays a modal dialog box that contains a system icon, a set of
* buttons, and a brief application-specific message, such as status or
* error information. The message box returns an integer value that
* indicates which button the user clicked.
* @param hWnd A handle to the owner window of the message box to be created. If
* this parameter is nullptr, the message box has no owner window.
* @param lpText The message to be displayed. If the string consists of more
* than one line, you can separate the lines using a carriage
* return and/or linefeed character between each line.
* @param lpCaption The dialog box title. If this parameter is nullptr, the
* default title is Error.
* @param uType The contents and behavior of the dialog box.
* @return If the function fails, the return value is zero. To get extended
* error information, call GetLastError. If the function succeeds, the
* return value is one of the button ID values.
* @remark For more information, see MessageBoxW.
*/
EXTERN_C int WINAPI K7UserModernMessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType);
/**
* @brief Displays a dialog box that enables the user to select a Shell folder.
* @param lpbi A pointer to a BROWSEINFO structure that contains information
* used to display the dialog box.
* @return Returns a PIDL that specifies the location of the selected folder
* relative to the root of the namespace. If the user chooses the Cancel
* button in the dialog box, the return value is nullptr. It is possible
* that the PIDL returned is that of a folder shortcut rather than a
* folder.
* @remark For more information, see SHBrowseForFolderW.
*/
EXTERN_C PIDLIST_ABSOLUTE WINAPI K7UserModernSHBrowseForFolderW(
_In_ LPBROWSEINFOW lpbi);
/**
* @brief Launches the Windows Settings Default Apps settings page for the
* current application.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7UserModernLaunchDefaultAppsSettings();
/**
* @brief Tries to bring the specified window to the foreground and activates
* the window. Keyboard input is directed to the window, and various
* visual cues are changed for the user.
* @param WindowHandle A handle to the window that should be activated and
* brought to the foreground.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundWindow(
_In_ HWND WindowHandle);
/**
* @brief Tries to bring the main window of the specified process to the
* foreground and activates the window. Keyboard input is directed to the
* window, and various visual cues are changed for the user.
* @param ProcessHandle A handle to the process whose main window should be
* activated and brought to the foreground.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundProcessMainWindow(
_In_ HANDLE ProcessHandle);
#endif // !K7_USER_MODERN
#endif // !K7_USER
================================================
FILE: K7User/K7User.props
================================================
$(MSBuildThisFileDirectory);$(IncludePath)
$(OutDir)K7User.lib;%(AdditionalDependencies)
1.0.372
{F9BF062B-998F-45A4-8285-96E4A0D5EC00}
================================================
FILE: K7User/K7User.vcxproj
================================================
{F9BF062B-998F-45A4-8285-96E4A0D5EC00}
K7User
DynamicLibrary
10.0.19041.0
true
true
M2-Team
NanaZip Platform User Library
K7User
© M2-Team and Contributors. All rights reserved.
K7User.dll
NanaZip
true
true
MultiThreadedDebug
MultiThreaded
K7User.def
10.0
1.2.410
================================================
FILE: K7User/K7UserDarkMode.cpp
================================================
/*
* PROJECT: NanaZip Platform User Library (K7User)
* FILE: K7UserDarkMode.cpp
* PURPOSE: Implementation for NanaZip Platform User Dark Mode Support
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7UserPrivate.h"
#include
#include
#include
#include
#pragma comment(lib, "Uxtheme.lib")
EXTERN_C HTHEME WINAPI OpenNcThemeData(
_In_opt_ HWND hwnd,
_In_ LPCWSTR pszClassList);
EXTERN_C HRESULT WINAPI GetThemeClass(
_In_ HTHEME hTheme,
_Out_ LPWSTR pszClassName,
_In_ int cchClassName);
#include
#include
#include
#pragma comment(lib, "dwmapi.lib")
#include
#include
#pragma comment(lib,"comctl32.lib")
// TODO: Move some workaround for NanaZip.UI.* to this.
namespace
{
const COLORREF g_LightModeBackgroundColor = RGB(255, 255, 255);
const COLORREF g_LightModeForegroundColor = RGB(0, 0, 0);
const COLORREF g_DarkModeBackgroundColor = RGB(0, 0, 0);
const COLORREF g_DarkModeForegroundColor = RGB(255, 255, 255);
const COLORREF g_DarkModeBorderColor = RGB(127, 127, 127);
const COLORREF g_DarkModeMenuSelectedBackgroundColor = RGB(65, 65, 65);
static HBRUSH GetDarkModeBackgroundBrush()
{
static HBRUSH CachedResult =
::CreateSolidBrush(g_DarkModeBackgroundColor);
return CachedResult;
}
static HBRUSH GetDarkModeForegroundBrush()
{
static HBRUSH CachedResult =
::CreateSolidBrush(g_DarkModeForegroundColor);
return CachedResult;
}
static HBRUSH GetDarkModeBorderBrush()
{
static HBRUSH CachedResult =
::CreateSolidBrush(g_DarkModeBorderColor);
return CachedResult;
}
static HBRUSH GetDarkModeMenuSelectedBackgroundBrush()
{
static HBRUSH CachedResult =
::CreateSolidBrush(g_DarkModeMenuSelectedBackgroundColor);
return CachedResult;
}
static bool IsStandardDynamicRangeMode()
{
static bool CachedResult = ([]() -> bool
{
bool Result = true;
UINT32 NumPathArrayElements = 0;
UINT32 NumModeInfoArrayElements = 0;
if (ERROR_SUCCESS == ::GetDisplayConfigBufferSizes(
QDC_ONLY_ACTIVE_PATHS,
&NumPathArrayElements,
&NumModeInfoArrayElements))
{
std::vector PathArray(
NumPathArrayElements);
std::vector ModeInfoArray(
NumModeInfoArrayElements);
if (ERROR_SUCCESS == ::QueryDisplayConfig(
QDC_ONLY_ACTIVE_PATHS,
&NumPathArrayElements,
&PathArray[0],
&NumModeInfoArrayElements,
&ModeInfoArray[0],
nullptr))
{
for (DISPLAYCONFIG_PATH_INFO const& Path : PathArray)
{
DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO AdvancedColorInfo;
std::memset(
&AdvancedColorInfo,
0,
sizeof(DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO));
AdvancedColorInfo.header.type =
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
AdvancedColorInfo.header.size =
sizeof(DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO);
AdvancedColorInfo.header.adapterId =
Path.targetInfo.adapterId;
AdvancedColorInfo.header.id =
Path.targetInfo.id;
if (ERROR_SUCCESS == ::DisplayConfigGetDeviceInfo(
&AdvancedColorInfo.header))
{
if (AdvancedColorInfo.advancedColorEnabled)
{
Result = false;
break;
}
}
}
}
}
return Result;
}());
return CachedResult;
}
static volatile bool g_GlobalInitialized = false;
static LRESULT CALLBACK CallWndProcCallback(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam);
struct ThreadContext
{
public:
// Fields for all scenarios.
// Should always be available if ShouldAppsUseDarkMode is true.
bool volatile ShouldAppsUseDarkMode = false;
HHOOK volatile WindowsHookHandle = nullptr;
// Fields for specific scenarios.
// May not be available, which need to be checked before use.
bool volatile MicaBackdropAvailable = false;
HTHEME TabControlThemeHandle = nullptr;
HTHEME StatusBarThemeHandle = nullptr;
public:
ThreadContext()
{
this->WindowsHookHandle = ::SetWindowsHookExW(
WH_CALLWNDPROC,
::CallWndProcCallback,
nullptr,
::GetCurrentThreadId());
if (!this->WindowsHookHandle)
{
return;
}
// Put this at the end of constructor to ensure that the dark mode
// support won't be enabled before the thread context is fully
// initialized to reduce the possibility of unintended behaviors.
this->ShouldAppsUseDarkMode =
::MileShouldAppsUseDarkMode() &&
!::MileShouldAppsUseHighContrastMode();
}
~ThreadContext()
{
// Put this at the beginning of destructor to ensure that the dark
// mode support won't be enabled after the thread context starts to
// uninitialize to reduce the possibility of unintended behaviors.
this->ShouldAppsUseDarkMode = false;
if (this->WindowsHookHandle)
{
::UnhookWindowsHookEx(this->WindowsHookHandle);
this->WindowsHookHandle = nullptr;
}
}
};
thread_local ThreadContext g_ThreadContext;
static void RefreshWindowTheme(
_In_ HWND WindowHandle)
{
wchar_t ClassName[256] = {};
if (0 != ::GetClassNameW(
WindowHandle,
ClassName,
MO_ARRAY_SIZE(ClassName)))
{
if (0 == std::wcscmp(ClassName, WC_BUTTONW))
{
::SetWindowTheme(WindowHandle, L"Explorer", nullptr);
}
else if (
(0 == std::wcscmp(ClassName, WC_COMBOBOXW)) ||
(0 == std::wcscmp(ClassName, WC_EDITW)))
{
::SetWindowTheme(WindowHandle, L"CFD", nullptr);
::MileAllowDarkModeForWindow(WindowHandle, TRUE);
}
else if (0 == std::wcscmp(ClassName, WC_HEADERW))
{
::SetWindowTheme(WindowHandle, L"ItemsView", nullptr);
}
else if (0 == std::wcscmp(ClassName, WC_LISTVIEWW))
{
::SetWindowTheme(WindowHandle, L"ItemsView", nullptr);
if (g_ThreadContext.ShouldAppsUseDarkMode)
{
ListView_SetTextBkColor(
WindowHandle,
g_DarkModeBackgroundColor);
ListView_SetBkColor(
WindowHandle,
g_DarkModeBackgroundColor);
ListView_SetTextColor(
WindowHandle,
g_DarkModeForegroundColor);
}
else
{
ListView_SetTextBkColor(
WindowHandle,
g_LightModeBackgroundColor);
ListView_SetBkColor(
WindowHandle,
g_LightModeBackgroundColor);
ListView_SetTextColor(
WindowHandle,
g_LightModeForegroundColor);
}
}
else if (0 == std::wcscmp(ClassName, STATUSCLASSNAMEW))
{
::SetWindowLongW(
WindowHandle,
GWL_EXSTYLE,
::GetWindowLongW(
WindowHandle,
GWL_EXSTYLE) | WS_EX_COMPOSITED);
}
else if (0 == std::wcscmp(ClassName, WC_TABCONTROLW))
{
::SetWindowLongW(
WindowHandle,
GWL_EXSTYLE,
::GetWindowLongW(
WindowHandle,
GWL_EXSTYLE) | WS_EX_COMPOSITED);
}
else
{
// DO NOT USE ELSE IF INSTEAD
// FOR HANDLING DYNAMIC DARK AND LIGHT MODE SWITCH PROPERLY
if (0 == std::wcscmp(ClassName, TOOLBARCLASSNAMEW))
{
// make it double bufferred
::SetWindowLongW(
WindowHandle,
GWL_EXSTYLE,
::GetWindowLongW(
WindowHandle,
GWL_EXSTYLE) | WS_EX_COMPOSITED);
COLORSCHEME ColorScheme;
ColorScheme.dwSize = sizeof(COLORSCHEME);
ColorScheme.clrBtnHighlight = CLR_DEFAULT;
ColorScheme.clrBtnShadow = CLR_DEFAULT;
if (g_ThreadContext.ShouldAppsUseDarkMode)
{
ColorScheme.clrBtnHighlight = g_DarkModeBackgroundColor;
ColorScheme.clrBtnShadow = g_DarkModeBackgroundColor;
}
::SendMessageW(
WindowHandle,
TB_SETCOLORSCHEME,
0,
reinterpret_cast(&ColorScheme));
}
::SendMessageW(WindowHandle, WM_THEMECHANGED, 0, 0);
}
}
}
static bool IsFileManagerWindowClassName(
_In_ LPCWSTR ClassName)
{
return (0 == std::wcscmp(ClassName, L"NanaZip.Modern.FileManager"));
}
static bool IsFileManagerPanelWindowClassName(
_In_ LPCWSTR ClassName)
{
return (0 == std::wcscmp(ClassName, L"NanaZip::Panel"));
}
static bool IsFileManagerWindow(
_In_ HWND WindowHandle)
{
wchar_t ClassName[256] = {};
if (0 != ::GetClassNameW(
WindowHandle,
ClassName,
MO_ARRAY_SIZE(ClassName)))
{
return ::IsFileManagerWindowClassName(ClassName);
}
return false;
}
LRESULT CALLBACK WindowSubclassCallback(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ UINT_PTR uIdSubclass,
_In_ DWORD_PTR dwRefData)
{
UNREFERENCED_PARAMETER(uIdSubclass);
UNREFERENCED_PARAMETER(dwRefData);
switch (uMsg)
{
case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
case WM_CTLCOLORBTN:
{
if (g_ThreadContext.ShouldAppsUseDarkMode)
{
HDC DeviceContextHandle = reinterpret_cast(wParam);
if (DeviceContextHandle)
{
::SetTextColor(
DeviceContextHandle,
g_DarkModeForegroundColor);
::SetBkColor(
DeviceContextHandle,
g_DarkModeBackgroundColor);
}
return reinterpret_cast(
::GetDarkModeBackgroundBrush());
}
break;
}
default:
break;
}
LRESULT Result = ::DefSubclassProc(
hWnd,
uMsg,
wParam,
lParam);
switch (uMsg)
{
case WM_SETTINGCHANGE:
{
LPCTSTR Section = reinterpret_cast(lParam);
if (Section && 0 == std::wcscmp(Section, L"ImmersiveColorSet"))
{
::MileRefreshImmersiveColorPolicyState();
g_ThreadContext.ShouldAppsUseDarkMode =
::MileShouldAppsUseDarkMode() &&
!::MileShouldAppsUseHighContrastMode();
::MileEnableImmersiveDarkModeForWindow(
hWnd,
g_ThreadContext.ShouldAppsUseDarkMode);
bool ShouldExtendFrame = (
g_ThreadContext.ShouldAppsUseDarkMode &&
::IsStandardDynamicRangeMode() &&
g_ThreadContext.MicaBackdropAvailable);
MARGINS Margins = {};
if (ShouldExtendFrame)
{
Margins = { -1 };
}
else if (::IsFileManagerWindow(hWnd))
{
UINT DpiValue = ::GetDpiForWindow(hWnd);
Margins.cyTopHeight =
::MulDiv(84, DpiValue, USER_DEFAULT_SCREEN_DPI);
Margins.cyBottomHeight =
::MulDiv(32, DpiValue, USER_DEFAULT_SCREEN_DPI);
}
::DwmExtendFrameIntoClientArea(hWnd, &Margins);
::EnumChildWindows(
hWnd,
[](
_In_ HWND hWnd,
_In_ LPARAM lParam) -> BOOL
{
UNREFERENCED_PARAMETER(lParam);
::RefreshWindowTheme(hWnd);
return TRUE;
},
0);
::InvalidateRect(hWnd, nullptr, TRUE);
}
break;
}
case WM_INITDIALOG:
case WM_CREATE:
{
::MileAllowDarkModeForWindow(
hWnd,
TRUE);
::MileSetWindowSystemBackdropTypeAttribute(
hWnd,
MILE_WINDOW_SYSTEM_BACKDROP_TYPE_MICA);
g_ThreadContext.MicaBackdropAvailable =
(S_OK == ::MileEnableImmersiveDarkModeForWindow(
hWnd,
g_ThreadContext.ShouldAppsUseDarkMode));
bool ShouldExtendFrame = (
g_ThreadContext.ShouldAppsUseDarkMode &&
::IsStandardDynamicRangeMode() &&
g_ThreadContext.MicaBackdropAvailable);
if (ShouldExtendFrame)
{
MARGINS Margins = { -1 };
::DwmExtendFrameIntoClientArea(hWnd, &Margins);
}
else if (::IsFileManagerWindow(hWnd))
{
UINT DpiValue = ::GetDpiForWindow(hWnd);
MARGINS Margins = {};
Margins.cyTopHeight =
::MulDiv(84, DpiValue, USER_DEFAULT_SCREEN_DPI);
Margins.cyBottomHeight =
::MulDiv(32, DpiValue, USER_DEFAULT_SCREEN_DPI);
::DwmExtendFrameIntoClientArea(hWnd, &Margins);
}
::RefreshWindowTheme(hWnd);
wchar_t ClassName[256] = {};
if (0 != ::GetClassNameW(
hWnd,
ClassName,
MO_ARRAY_SIZE(ClassName)))
{
if (0 == std::wcscmp(ClassName, WC_TABCONTROLW))
{
::SetWindowLongPtrW(
hWnd,
GWL_STYLE,
(::GetWindowLongPtrW(hWnd, GWL_STYLE) & ~TCS_BUTTONS)
| TCS_TABS);
::SetWindowTheme(hWnd, nullptr, nullptr);
g_ThreadContext.TabControlThemeHandle =
::GetWindowTheme(hWnd);
}
else if (0 == std::wcscmp(ClassName, STATUSCLASSNAMEW))
{
g_ThreadContext.StatusBarThemeHandle =
::GetWindowTheme(hWnd);
}
}
break;
}
case WM_ERASEBKGND:
{
wchar_t ClassName[256] = {};
if (0 != ::GetClassNameW(
hWnd,
ClassName,
MO_ARRAY_SIZE(ClassName)))
{
if (g_ThreadContext.ShouldAppsUseDarkMode &&
0 == std::wcscmp(ClassName, STATUSCLASSNAMEW))
{
RECT ClientArea = {};
if (::GetClientRect(hWnd, &ClientArea))
{
::FillRect(
reinterpret_cast(wParam),
&ClientArea,
reinterpret_cast(
::GetStockObject(BLACK_BRUSH)));
return TRUE;
}
}
if (::IsFileManagerWindowClassName(ClassName) ||
::IsFileManagerPanelWindowClassName(ClassName))
{
RECT ClientArea = {};
if (::GetClientRect(hWnd, &ClientArea))
{
::FillRect(
reinterpret_cast(wParam),
&ClientArea,
reinterpret_cast(
::GetStockObject(
g_ThreadContext.ShouldAppsUseDarkMode
? BLACK_BRUSH
: WHITE_BRUSH)));
return TRUE;
}
}
}
break;
}
case WM_DPICHANGED:
{
bool ShouldExtendFrame = (
g_ThreadContext.ShouldAppsUseDarkMode &&
::IsStandardDynamicRangeMode() &&
g_ThreadContext.MicaBackdropAvailable);
if (!ShouldExtendFrame && ::IsFileManagerWindow(hWnd))
{
UINT DpiValue = ::GetDpiForWindow(hWnd);
MARGINS Margins = {};
Margins.cyTopHeight =
::MulDiv(84, DpiValue, USER_DEFAULT_SCREEN_DPI);
Margins.cyBottomHeight =
::MulDiv(32, DpiValue, USER_DEFAULT_SCREEN_DPI);
::DwmExtendFrameIntoClientArea(hWnd, &Margins);
}
break;
}
default:
break;
}
if (g_ThreadContext.ShouldAppsUseDarkMode && ::GetMenu(hWnd))
{
if (WM_UAHDRAWMENU == uMsg)
{
PUAHMENU UahMenu = reinterpret_cast(lParam);
if (UahMenu)
{
MENUBARINFO MenuBarInfo;
MenuBarInfo.cbSize = sizeof(MENUBARINFO);
if (::GetMenuBarInfo(hWnd, OBJID_MENU, 0, &MenuBarInfo))
{
RECT WindowRect = {};
::GetWindowRect(hWnd, &WindowRect);
RECT MenuRect = MenuBarInfo.rcBar;
::OffsetRect(
&MenuRect,
-WindowRect.left,
-WindowRect.top);
::FillRect(
UahMenu->hdc,
&MenuRect,
::GetDarkModeBackgroundBrush());
}
}
return TRUE;
}
else if (WM_UAHDRAWMENUITEM == uMsg)
{
PUAHDRAWMENUITEM UahDrawMenuItem =
reinterpret_cast(lParam);
if (UahDrawMenuItem)
{
PDRAWITEMSTRUCT DrawItemStruct = &UahDrawMenuItem->dis;
if (ODT_MENU == DrawItemStruct->CtlType)
{
wchar_t Buffer[256] = {};
MENUITEMINFOW MenuItemInfo;
MenuItemInfo.cbSize = sizeof(MENUITEMINFOW);
MenuItemInfo.fMask = MIIM_STRING;
MenuItemInfo.dwTypeData = Buffer;
MenuItemInfo.cch = MO_ARRAY_SIZE(Buffer) - 1;
if (::GetMenuItemInfoW(
UahDrawMenuItem->um.hmenu,
UahDrawMenuItem->umi.iPosition,
TRUE,
&MenuItemInfo))
{
int StateId = 0;
COLORREF TextColor = g_DarkModeForegroundColor;
HBRUSH BackgroundBrush =
::GetDarkModeBackgroundBrush();
if (DrawItemStruct->itemState & ODS_INACTIVE)
{
StateId = MBI_DISABLED;
TextColor = RGB(109, 109, 109);
}
else if ((DrawItemStruct->itemState & ODS_GRAYED) &&
(DrawItemStruct->itemState & ODS_HOTLIGHT))
{
StateId = MBI_DISABLEDHOT;
}
else if (DrawItemStruct->itemState & ODS_GRAYED)
{
StateId = MBI_DISABLED;
TextColor = RGB(109, 109, 109);
}
else if (DrawItemStruct->itemState
& (ODS_HOTLIGHT | ODS_SELECTED))
{
StateId = MBI_HOT;
BackgroundBrush =
::GetDarkModeMenuSelectedBackgroundBrush();
}
else
{
StateId = MBI_NORMAL;
}
::FillRect(
DrawItemStruct->hDC,
&DrawItemStruct->rcItem,
BackgroundBrush);
// We have to specify the text colour explicitly as
// by default black would be used, making the menu
// label unreadable on the (almost) black
// background.
DTTOPTS TextOptions = {};
TextOptions.dwSize = sizeof(DTTOPTS);
TextOptions.dwFlags = DTT_TEXTCOLOR;
TextOptions.crText = TextColor;
DWORD TextFlags =
DT_CENTER | DT_VCENTER | DT_SINGLELINE;
if (DrawItemStruct->itemState & ODS_NOACCEL)
{
TextFlags |= DT_HIDEPREFIX;
}
HTHEME ThemeHandle = ::OpenThemeData(hWnd, L"Menu");
if (ThemeHandle)
{
::DrawThemeTextEx(
ThemeHandle,
UahDrawMenuItem->um.hdc,
MENU_BARITEM,
StateId,
Buffer,
static_cast(std::wcslen(Buffer)),
TextFlags,
&DrawItemStruct->rcItem,
&TextOptions);
::CloseThemeData(ThemeHandle);
}
}
}
}
return TRUE;
}
else if (WM_NCPAINT == uMsg || WM_NCACTIVATE == uMsg)
{
MENUBARINFO MenuBarInfo;
MenuBarInfo.cbSize = sizeof(MENUBARINFO);
if (::GetMenuBarInfo(hWnd, OBJID_MENU, 0, &MenuBarInfo))
{
RECT ClientRect = {};
::GetClientRect(hWnd, &ClientRect);
::MapWindowPoints(
hWnd,
nullptr,
reinterpret_cast(&ClientRect),
2);
RECT WindowRect = {};
::GetWindowRect(hWnd, &WindowRect);
::OffsetRect(
&ClientRect,
-WindowRect.left,
-WindowRect.top);
RECT AnnoyingLineRect = ClientRect;
AnnoyingLineRect.bottom = AnnoyingLineRect.top;
--AnnoyingLineRect.top;
HDC DeviceContextHandle = ::GetWindowDC(hWnd);
if (DeviceContextHandle)
{
::FillRect(
DeviceContextHandle,
&AnnoyingLineRect,
::GetDarkModeBackgroundBrush());
::ReleaseDC(hWnd, DeviceContextHandle);
}
}
}
}
return Result;
}
static std::wstring GetAssociatedModuleNameFromWindowHandle(
_In_ HWND WindowHandle)
{
// 32767 is the maximum path length without the terminating null
// character.
std::wstring Path(32767, L'\0');
Path.resize(::GetWindowModuleFileNameW(
WindowHandle, &Path[0], static_cast(Path.size())));
wchar_t* LastBackslash = std::wcsrchr(Path.data(), L'\\');
return LastBackslash ? std::wstring(LastBackslash + 1) : Path;
}
static bool IsModernizedWindow(
_In_ HWND WindowHandle)
{
std::wstring ModuleName =
::GetAssociatedModuleNameFromWindowHandle(WindowHandle);
if (!::_wcsicmp(ModuleName.c_str(), L"combase.dll") ||
!::_wcsicmp(ModuleName.c_str(), L"CoreMessaging.dll") ||
!::_wcsicmp(ModuleName.c_str(), L"InputHost.dll") ||
!::_wcsicmp(ModuleName.c_str(), L"Windows.UI.dll") ||
!::_wcsicmp(ModuleName.c_str(), L"Windows.UI.Xaml.dll"))
{
return true;
}
wchar_t ClassName[256] = {};
if (0 != ::GetClassNameW(
WindowHandle,
ClassName,
MO_ARRAY_SIZE(ClassName)))
{
if (std::wcsstr(ClassName, L"Windows.UI.") ||
std::wcsstr(ClassName, L"Mile.Xaml.") ||
std::wcsstr(ClassName, L"Xaml_WindowedPopupClass"))
{
return true;
}
}
return false;
}
static LRESULT CALLBACK CallWndProcCallback(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
if (g_GlobalInitialized && nCode == HC_ACTION)
{
PCWPSTRUCT WndProcStruct =
reinterpret_cast(lParam);
switch (WndProcStruct->message)
{
case WM_CREATE:
case WM_INITDIALOG:
{
if (!::IsModernizedWindow(WndProcStruct->hwnd))
{
::SetWindowSubclass(
WndProcStruct->hwnd,
::WindowSubclassCallback,
0,
0);
}
break;
}
default:
break;
}
}
return ::CallNextHookEx(
nullptr,
nCode,
wParam,
lParam);
}
namespace FunctionTypes
{
enum
{
GetSysColor,
GetSysColorBrush,
GetThemeColor,
DrawThemeText,
DrawThemeBackground,
DrawThemeBackgroundEx,
OpenNcThemeData,
GetThemeClass,
MaximumFunction
};
}
struct FunctionItem
{
PVOID Original;
PVOID Detoured;
};
FunctionItem g_FunctionTable[FunctionTypes::MaximumFunction];
static DWORD WINAPI OriginalGetSysColor(
_In_ int nIndex)
{
using FunctionType = decltype(::GetSysColor)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::GetSysColor].Original);
if (!FunctionAddress)
{
return 0;
}
return FunctionAddress(nIndex);
}
static HBRUSH WINAPI OriginalGetSysColorBrush(
_In_ int nIndex)
{
using FunctionType = decltype(::GetSysColorBrush)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::GetSysColorBrush].Original);
if (!FunctionAddress)
{
return nullptr;
}
return FunctionAddress(nIndex);
}
static HRESULT WINAPI OriginalGetThemeColor(
_In_ HTHEME hTheme,
_In_ int iPartId,
_In_ int iStateId,
_In_ int iPropId,
_Out_ COLORREF* pColor)
{
using FunctionType = decltype(::GetThemeColor)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::GetThemeColor].Original);
if (!FunctionAddress)
{
return E_NOINTERFACE;
}
return FunctionAddress(
hTheme,
iPartId,
iStateId,
iPropId,
pColor);
}
static HRESULT WINAPI OriginalDrawThemeText(
_In_ HTHEME hTheme,
_In_ HDC hdc,
_In_ int iPartId,
_In_ int iStateId,
_In_ LPCWSTR pszText,
_In_ int cchText,
_In_ DWORD dwTextFlags,
_In_ DWORD dwTextFlags2,
_In_ LPCRECT pRect)
{
using FunctionType = decltype(::DrawThemeText)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::DrawThemeText].Original);
if (!FunctionAddress)
{
return E_NOINTERFACE;
}
return FunctionAddress(
hTheme,
hdc,
iPartId,
iStateId,
pszText,
cchText,
dwTextFlags,
dwTextFlags2,
pRect);
}
static HRESULT WINAPI OriginalDrawThemeBackground(
_In_ HTHEME hTheme,
_In_ HDC hdc,
_In_ int iPartId,
_In_ int iStateId,
_In_ LPCRECT pRect,
_In_opt_ LPCRECT pClipRect)
{
using FunctionType = decltype(::DrawThemeBackground)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::DrawThemeBackground].Original);
if (!FunctionAddress)
{
return E_NOINTERFACE;
}
return FunctionAddress(
hTheme,
hdc,
iPartId,
iStateId,
pRect,
pClipRect);
}
static HRESULT WINAPI OriginalDrawThemeBackgroundEx(
_In_ HTHEME hTheme,
_In_ HDC hdc,
_In_ int iPartId,
_In_ int iStateId,
_In_ LPCRECT pRect,
_In_opt_ const DTBGOPTS* pOptions)
{
using FunctionType = decltype(::DrawThemeBackgroundEx)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::DrawThemeBackgroundEx].Original);
if (!FunctionAddress)
{
return E_NOINTERFACE;
}
return FunctionAddress(
hTheme,
hdc,
iPartId,
iStateId,
pRect,
pOptions);
}
static HTHEME WINAPI OriginalOpenNcThemeData(
_In_opt_ HWND hwnd,
_In_ LPCWSTR pszClassList)
{
using FunctionType = decltype(::OpenNcThemeData)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::OpenNcThemeData].Original);
if (!FunctionAddress)
{
return nullptr;
}
return FunctionAddress(hwnd, pszClassList);
}
static HRESULT WINAPI OriginalGetThemeClass(
_In_ HTHEME hTheme,
_Out_ LPWSTR pszClassName,
_In_ int cchClassName)
{
using FunctionType = decltype(::GetThemeClass)*;
FunctionType FunctionAddress = reinterpret_cast(
g_FunctionTable[FunctionTypes::GetThemeClass].Original);
if (!FunctionAddress)
{
return E_NOINTERFACE;
}
return FunctionAddress(
hTheme,
pszClassName,
cchClassName);
}
static DWORD WINAPI DetouredGetSysColor(
_In_ int nIndex)
{
if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)
{
return ::OriginalGetSysColor(nIndex);
}
switch (nIndex)
{
case COLOR_WINDOW:
case COLOR_BTNFACE:
return g_DarkModeBackgroundColor;
case COLOR_WINDOWTEXT:
case COLOR_BTNTEXT:
return g_DarkModeForegroundColor;
default:
return ::OriginalGetSysColor(nIndex);
}
}
static HBRUSH WINAPI DetouredGetSysColorBrush(
_In_ int nIndex)
{
if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)
{
return ::OriginalGetSysColorBrush(nIndex);
}
switch (nIndex)
{
case COLOR_BTNFACE:
return ::GetDarkModeBackgroundBrush();
case COLOR_BTNTEXT:
return ::GetDarkModeForegroundBrush();
default:
return ::OriginalGetSysColorBrush(nIndex);
}
}
static HRESULT WINAPI DetouredGetThemeColor(
_In_ HTHEME hTheme,
_In_ int iPartId,
_In_ int iStateId,
_In_ int iPropId,
_Out_ COLORREF* pColor)
{
if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)
{
return ::OriginalGetThemeColor(
hTheme,
iPartId,
iStateId,
iPropId,
pColor);
}
HRESULT hr = ::OriginalGetThemeColor(
hTheme,
iPartId,
iStateId,
iPropId,
pColor);
if (S_OK != hr)
{
return hr;
}
wchar_t ClassName[256] = {};
if (S_OK == ::OriginalGetThemeClass(
hTheme,
ClassName,
MO_ARRAY_SIZE(ClassName)))
{
if (0 == ::_wcsicmp(ClassName, VSCLASS_TASKDIALOGSTYLE))
{
if (TMT_TEXTCOLOR == iPropId)
{
*pColor = g_DarkModeForegroundColor;
}
}
}
return S_OK;
}
static HRESULT WINAPI DetouredDrawThemeText(
_In_ HTHEME hTheme,
_In_ HDC hdc,
_In_ int iPartId,
_In_ int iStateId,
_In_ LPCWSTR pszText,
_In_ int cchText,
_In_ DWORD dwTextFlags,
_In_ DWORD dwTextFlags2,
_In_ LPCRECT pRect)
{
if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)
{
return ::OriginalDrawThemeText(
hTheme,
hdc,
iPartId,
iStateId,
pszText,
cchText,
dwTextFlags,
dwTextFlags2,
pRect);
}
DTTOPTS TextOptions = {};
TextOptions.dwSize = sizeof(DTTOPTS);
TextOptions.dwFlags = DTT_TEXTCOLOR;
TextOptions.crText = g_DarkModeForegroundColor;
return ::DrawThemeTextEx(
hTheme,
hdc,
iPartId,
iStateId,
pszText,
cchText,
dwTextFlags,
const_cast(pRect),
&TextOptions);
}
static HRESULT WINAPI DetouredDrawThemeBackground(
_In_ HTHEME hTheme,
_In_ HDC hdc,
_In_ int iPartId,
_In_ int iStateId,
_In_ LPCRECT pRect,
_In_opt_ LPCRECT pClipRect)
{
if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)
{
return ::OriginalDrawThemeBackground(
hTheme,
hdc,
iPartId,
iStateId,
pRect,
pClipRect);
}
if (hTheme == g_ThreadContext.TabControlThemeHandle)
{
const int HoveredCheckStateId[] =
{
-1,
TIS_HOT,
TILES_HOT,
TIRES_HOT,
TIBES_HOT,
TTIS_HOT,
TTILES_HOT,
TTIRES_HOT,
TTIBES_HOT,
-1,
-1,
-1
};
const int SelectedCheckStateId[] =
{
-1,
TIS_SELECTED,
TILES_SELECTED,
TIRES_SELECTED,
TIBES_SELECTED,
TTIS_SELECTED,
TTILES_SELECTED,
TTIRES_SELECTED,
TTIBES_SELECTED,
-1,
-1,
-1
};
switch (iPartId)
{
case TABP_TABITEM:
case TABP_TABITEMLEFTEDGE:
case TABP_TABITEMRIGHTEDGE:
case TABP_TABITEMBOTHEDGE:
case TABP_TOPTABITEM:
case TABP_TOPTABITEMLEFTEDGE:
case TABP_TOPTABITEMRIGHTEDGE:
case TABP_TOPTABITEMBOTHEDGE:
{
RECT paddedRect = *pRect;
RECT insideRect =
{
pRect->left + 1,
pRect->top + 1,
pRect->right - 1,
pRect->bottom - 1
};
if (iStateId == SelectedCheckStateId[iPartId])
{
paddedRect.top += 1;
paddedRect.bottom -= 2;
// Allow the rect to overlap so the bottom border outline is removed
insideRect.top += 1;
insideRect.bottom += 1;
}
::FrameRect(
hdc,
&paddedRect,
::GetDarkModeBorderBrush());
::FillRect(
hdc,
&insideRect,
iStateId == HoveredCheckStateId[iPartId]
? ::GetDarkModeBorderBrush()
: ::GetDarkModeBackgroundBrush());
return S_OK;
}
case TABP_PANE:
return S_OK;
default:
break;
}
}
else if (hTheme == g_ThreadContext.StatusBarThemeHandle)
{
switch (iPartId)
{
case 0:
{
// Outside border (top, right)
::FillRect(hdc, pRect, ::GetDarkModeBorderBrush());
return S_OK;
}
case SP_PANE:
case SP_GRIPPERPANE:
case SP_GRIPPER:
{
// Everything else
::FillRect(hdc, pRect, ::GetDarkModeBackgroundBrush());
return S_OK;
}
default:
break;
}
}
return ::OriginalDrawThemeBackground(
hTheme,
hdc,
iPartId,
iStateId,
pRect,
pClipRect);
}
static HRESULT WINAPI DetouredDrawThemeBackgroundEx(
_In_ HTHEME hTheme,
_In_ HDC hdc,
_In_ int iPartId,
_In_ int iStateId,
_In_ LPCRECT pRect,
_In_opt_ const DTBGOPTS* pOptions)
{
if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)
{
return ::OriginalDrawThemeBackgroundEx(
hTheme,
hdc,
iPartId,
iStateId,
pRect,
pOptions);
}
bool NeedTaskDialogWorkaround = (
TDLG_PRIMARYPANEL == iPartId ||
TDLG_SECONDARYPANEL == iPartId ||
TDLG_EXPANDOBUTTON == iPartId ||
TDLG_FOOTNOTEPANE == iPartId ||
TDLG_FOOTNOTESEPARATOR == iPartId);
if (NeedTaskDialogWorkaround)
{
NeedTaskDialogWorkaround = false;
wchar_t ClassName[256] = {};
if (S_OK == ::OriginalGetThemeClass(
hTheme,
ClassName,
MO_ARRAY_SIZE(ClassName)))
{
NeedTaskDialogWorkaround =
(0 == ::_wcsicmp(ClassName, VSCLASS_TASKDIALOG));
}
}
if (NeedTaskDialogWorkaround)
{
if (TDLG_PRIMARYPANEL == iPartId)
{
::FillRect(hdc, pRect, ::GetDarkModeBackgroundBrush());
return S_OK;
}
else if (
TDLG_SECONDARYPANEL == iPartId ||
TDLG_FOOTNOTEPANE == iPartId ||
TDLG_FOOTNOTESEPARATOR == iPartId)
{
::FillRect(hdc, pRect, ::GetDarkModeBorderBrush());
RECT ContentRect = *pRect;
ContentRect.top += 1;
::FillRect(hdc, &ContentRect, ::GetDarkModeBackgroundBrush());
return S_OK;
}
else if (iPartId == TDLG_EXPANDOBUTTON)
{
// It seems our current implementation doesn't have the issue
// that the button becomes invisible on dark mode in Windows 11,
// so we don't need to do anything here for now.
}
}
return ::OriginalDrawThemeBackgroundEx(
hTheme,
hdc,
iPartId,
iStateId,
pRect,
pOptions);
}
static HTHEME WINAPI DetouredOpenNcThemeData(
_In_opt_ HWND hwnd,
_In_ LPCWSTR pszClassList)
{
// Workaround for dark mode scrollbar
if (0 == std::wcscmp(pszClassList, L"ScrollBar"))
{
return ::OriginalOpenNcThemeData(nullptr, L"Explorer::ScrollBar");
}
return ::OriginalOpenNcThemeData(hwnd, pszClassList);
}
static bool InitializeFunctionTable()
{
g_FunctionTable[FunctionTypes::GetSysColor].Original =
::GetSysColor;
g_FunctionTable[FunctionTypes::GetSysColor].Detoured =
::DetouredGetSysColor;
g_FunctionTable[FunctionTypes::GetSysColorBrush].Original =
::GetSysColorBrush;
g_FunctionTable[FunctionTypes::GetSysColorBrush].Detoured =
::DetouredGetSysColorBrush;
g_FunctionTable[FunctionTypes::GetThemeColor].Original =
::GetThemeColor;
g_FunctionTable[FunctionTypes::GetThemeColor].Detoured =
::DetouredGetThemeColor;
g_FunctionTable[FunctionTypes::DrawThemeText].Original =
::DrawThemeText;
g_FunctionTable[FunctionTypes::DrawThemeText].Detoured =
::DetouredDrawThemeText;
g_FunctionTable[FunctionTypes::DrawThemeBackground].Original =
::DrawThemeBackground;
g_FunctionTable[FunctionTypes::DrawThemeBackground].Detoured =
::DetouredDrawThemeBackground;
g_FunctionTable[FunctionTypes::DrawThemeBackgroundEx].Original =
::DrawThemeBackgroundEx;
g_FunctionTable[FunctionTypes::DrawThemeBackgroundEx].Detoured =
::DetouredDrawThemeBackgroundEx;
{
HMODULE ModuleHandle = ::GetModuleHandleW(
L"uxtheme.dll");
if (ModuleHandle)
{
PVOID ProcAddress = ::GetProcAddress(
ModuleHandle,
MAKEINTRESOURCEA(49));
if (ProcAddress)
{
g_FunctionTable[FunctionTypes::OpenNcThemeData].Original =
ProcAddress;
g_FunctionTable[FunctionTypes::OpenNcThemeData].Detoured =
::DetouredOpenNcThemeData;
}
}
if (ModuleHandle)
{
PVOID ProcAddress = ::GetProcAddress(
ModuleHandle,
MAKEINTRESOURCEA(74));
if (ProcAddress)
{
g_FunctionTable[FunctionTypes::GetThemeClass].Original =
ProcAddress;
g_FunctionTable[FunctionTypes::GetThemeClass].Detoured =
nullptr;
}
}
}
return true;
}
static void UninitializeFunctionTable()
{
for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)
{
g_FunctionTable[i].Original = nullptr;
g_FunctionTable[i].Detoured = nullptr;
}
}
}
EXTERN_C MO_RESULT MOAPI K7UserInitializeDarkModeSupport()
{
if (g_GlobalInitialized)
{
return MO_RESULT_SUCCESS_OK;
}
if (!::MileIsWindowsVersionAtLeast(10, 0, 0))
{
// Dark mode is only supported on Windows 10 and above, so we can just
// return success without doing anything on older versions of Windows.
return MO_RESULT_SUCCESS_OK;
}
if (!::InitializeFunctionTable())
{
return MO_RESULT_ERROR_FAIL;
}
::MileAllowDarkModeForApp(TRUE);
::MileRefreshImmersiveColorPolicyState();
::K7BaseDetourTransactionBegin();
::K7BaseDetourUpdateThread(::GetCurrentThread());
for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)
{
if (g_FunctionTable[i].Original &&
g_FunctionTable[i].Detoured)
{
if (NO_ERROR != ::K7BaseDetourAttach(
&g_FunctionTable[i].Original,
g_FunctionTable[i].Detoured))
{
::K7BaseDetourTransactionAbort();
::UninitializeFunctionTable();
return MO_RESULT_ERROR_FAIL;
}
}
}
::K7BaseDetourTransactionCommit();
g_GlobalInitialized = true;
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7UserUninitializeDarkModeSupport()
{
if (!g_GlobalInitialized)
{
return MO_RESULT_SUCCESS_OK;
}
g_GlobalInitialized = false;
::MileAllowDarkModeForApp(FALSE);
::MileRefreshImmersiveColorPolicyState();
::K7BaseDetourTransactionBegin();
::K7BaseDetourUpdateThread(::GetCurrentThread());
for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)
{
if (g_FunctionTable[i].Original &&
g_FunctionTable[i].Detoured)
{
if (NO_ERROR != ::K7BaseDetourDetach(
&g_FunctionTable[i].Original,
g_FunctionTable[i].Detoured))
{
::K7BaseDetourTransactionAbort();
return MO_RESULT_ERROR_FAIL;
}
}
}
::K7BaseDetourTransactionCommit();
::UninitializeFunctionTable();
return MO_RESULT_SUCCESS_OK;
}
================================================
FILE: K7User/K7UserModern.cpp
================================================
/*
* PROJECT: NanaZip Platform User Library (K7User)
* FILE: K7UserModern.cpp
* PURPOSE: Implementation for NanaZip Platform User Modern Experiences
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
* reflectronic (john-tur@outlook.com)
*/
#include "K7UserPrivate.h"
#include
#include
#pragma comment(lib,"comctl32.lib")
#include
#include
namespace
{
int WINAPI OriginalMessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType)
{
static decltype(::MessageBoxW)* ProcAddress =
reinterpret_cast(::GetProcAddress(
::GetModuleHandleW(L"user32.dll"),
"MessageBoxW"));
if (ProcAddress)
{
return ProcAddress(hWnd, lpText, lpCaption, uType);
}
else
{
::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
}
}
EXTERN_C int WINAPI K7UserModernMessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType)
{
if (uType != (uType & (MB_ICONMASK | MB_TYPEMASK)))
{
return ::OriginalMessageBoxW(hWnd, lpText, lpCaption, uType);
}
TASKDIALOGCONFIG TaskDialogConfig = {};
TaskDialogConfig.cbSize = sizeof(TASKDIALOGCONFIG);
TaskDialogConfig.hwndParent = hWnd;
TaskDialogConfig.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION;
TaskDialogConfig.pszWindowTitle = lpCaption;
TaskDialogConfig.pszMainInstruction = lpText;
switch (uType & MB_TYPEMASK)
{
case MB_OK:
TaskDialogConfig.dwCommonButtons =
TDCBF_OK_BUTTON;
break;
case MB_OKCANCEL:
TaskDialogConfig.dwCommonButtons =
TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON;
break;
case MB_YESNOCANCEL:
TaskDialogConfig.dwCommonButtons =
TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON;
break;
case MB_YESNO:
TaskDialogConfig.dwCommonButtons =
TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;
break;
case MB_RETRYCANCEL:
TaskDialogConfig.dwCommonButtons =
TDCBF_RETRY_BUTTON | TDCBF_CANCEL_BUTTON;
break;
default:
return ::OriginalMessageBoxW(hWnd, lpText, lpCaption, uType);
}
switch (uType & MB_ICONMASK)
{
case MB_ICONHAND:
TaskDialogConfig.pszMainIcon = TD_ERROR_ICON;
break;
case MB_ICONQUESTION:
TaskDialogConfig.dwFlags |= TDF_USE_HICON_MAIN;
TaskDialogConfig.hMainIcon = ::LoadIconW(nullptr, IDI_QUESTION);
break;
case MB_ICONEXCLAMATION:
TaskDialogConfig.pszMainIcon = TD_WARNING_ICON;
break;
case MB_ICONASTERISK:
TaskDialogConfig.pszMainIcon = TD_INFORMATION_ICON;
break;
default:
break;
}
int ButtonID = 0;
HRESULT hr = ::TaskDialogIndirect(
&TaskDialogConfig,
&ButtonID,
nullptr,
nullptr);
if (0 == ButtonID)
{
// According to the documentation of TaskDialogIndirect, if the function
// fails, the value pointed to by pnButton will be set to zero. To
// follow the ABI of MessageBoxW, we will return zero in this case and
// set TaskDialogIndirect's HRESULT code to the last error code.
::SetLastError(hr);
}
return ButtonID;
}
EXTERN_C PIDLIST_ABSOLUTE WINAPI K7UserModernSHBrowseForFolderW(
_In_ LPBROWSEINFOW lpbi)
{
LPITEMIDLIST IDList = nullptr;
IFileDialog* FileDialog = nullptr;
if (SUCCEEDED(::CoCreateInstance(
CLSID_FileOpenDialog,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&FileDialog))))
{
DWORD Flags = 0;
if (SUCCEEDED(FileDialog->GetOptions(
&Flags)))
{
if (SUCCEEDED(FileDialog->SetOptions(
Flags | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM)))
{
if (SUCCEEDED(FileDialog->SetTitle(
lpbi->lpszTitle)))
{
// 7-Zip does not use the pidlRoot parameter to configure
// the default folder. Instead, it sets it by configuring
// the message loop for the shell dialog, passing the path
// of the default folder through the lParam, and navigating
// to that folder inside the message loop.
//
// Since we cannot augment the IFileDialog's message loop,
// we will reach into the lParam given to us to find the
// initial path and hope that 7-Zip does not change this
// behavior.
IShellItem* DefaultFolder = nullptr;
if (SUCCEEDED(::SHCreateItemFromParsingName(
reinterpret_cast(lpbi->lParam),
nullptr,
IID_PPV_ARGS(&DefaultFolder))))
{
FileDialog->SetFolder(DefaultFolder);
DefaultFolder->Release();
}
if (SUCCEEDED(FileDialog->Show(
lpbi->hwndOwner)))
{
IShellItem* Result = nullptr;
if (SUCCEEDED(FileDialog->GetResult(
&Result)))
{
::SHGetIDListFromObject(Result, &IDList);
Result->Release();
}
}
}
}
}
FileDialog->Release();
}
return IDList;
}
namespace
{
static LONG GetCurrentApplicationUserModelIdWrapper(
_Inout_ PUINT32 applicationUserModelIdLength,
_Out_opt_ PWSTR applicationUserModelId)
{
using ProcType = decltype(::GetCurrentApplicationUserModelId)*;
static ProcType ProcAddress = reinterpret_cast([]() -> FARPROC
{
HMODULE ModuleHandle = ::GetModuleHandleW(L"kernel32.dll");
if (ModuleHandle)
{
return ::GetProcAddress(
ModuleHandle,
"GetCurrentApplicationUserModelId");
}
return nullptr;
}());
if (ProcAddress)
{
return ProcAddress(
applicationUserModelIdLength,
applicationUserModelId);
}
return ERROR_NOINTERFACE;
}
static std::wstring GetCurrentApplicationUserModelIdSimple()
{
static std::wstring CachedResult = ([]() -> std::wstring
{
std::wstring ApplicationUserModelId;
{
UINT32 ApplicationUserModelIdLength = 0;
LONG Result = ::GetCurrentApplicationUserModelIdWrapper(
&ApplicationUserModelIdLength,
nullptr);
if (ERROR_INSUFFICIENT_BUFFER == Result)
{
ApplicationUserModelId.resize(ApplicationUserModelIdLength);
Result = ::GetCurrentApplicationUserModelIdWrapper(
&ApplicationUserModelIdLength,
reinterpret_cast(ApplicationUserModelId.data()));
if (ERROR_SUCCESS == Result)
{
// Remove the trailing null character added by the API.
if (!ApplicationUserModelId.empty() &&
L'\0' == ApplicationUserModelId.back())
{
ApplicationUserModelId.pop_back();
}
}
}
}
return ApplicationUserModelId;
}());
return CachedResult;
}
}
EXTERN_C MO_RESULT MOAPI K7UserModernLaunchDefaultAppsSettings()
{
std::wstring NavigateUri = L"ms-settings:defaultapps";
std::wstring CurrentApplicationUserModelId =
::GetCurrentApplicationUserModelIdSimple();
if (!CurrentApplicationUserModelId.empty())
{
NavigateUri.append(L"?registeredAUMID=");
NavigateUri.append(CurrentApplicationUserModelId);
}
SHELLEXECUTEINFOW Information = {};
Information.cbSize = sizeof(SHELLEXECUTEINFOW);
Information.lpVerb = L"open";
Information.lpFile = NavigateUri.c_str();
Information.nShow = SW_SHOWNORMAL;
return ::ShellExecuteExW(&Information)
? MO_RESULT_SUCCESS_OK
: MO_RESULT_ERROR_FAIL;
}
EXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundWindow(
_In_ HWND WindowHandle)
{
DWORD ForegroundThreadId = ::GetWindowThreadProcessId(
::GetForegroundWindow(),
nullptr);
DWORD CurrentThreadId = ::GetCurrentThreadId();
::AttachThreadInput(ForegroundThreadId, CurrentThreadId, TRUE);
::SetWindowPos(
WindowHandle,
HWND_TOPMOST,
0,
0,
0,
0,
SWP_NOSIZE | SWP_NOMOVE);
::SetWindowPos(
WindowHandle,
HWND_NOTOPMOST,
0,
0,
0,
0,
SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
::SetForegroundWindow(WindowHandle);
::SetFocus(WindowHandle);
::SetActiveWindow(WindowHandle);
::AttachThreadInput(ForegroundThreadId, CurrentThreadId, FALSE);
return MO_RESULT_SUCCESS_OK;
}
EXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundProcessMainWindow(
_In_ HANDLE ProcessHandle)
{
DWORD ProcessId = ::GetProcessId(ProcessHandle);
::AllowSetForegroundWindow(ProcessId);
::WaitForInputIdle(ProcessHandle, 500);
::EnumWindows(
[](
_In_ HWND hWnd,
_In_ LPARAM lParam) -> BOOL
{
DWORD ProcessId = 0;
::GetWindowThreadProcessId(hWnd, &ProcessId);
if (!lParam || ProcessId == (DWORD)lParam)
{
::K7UserModernSetForegroundWindow(hWnd);
return FALSE;
}
return TRUE;
},
static_cast(ProcessId));
return MO_RESULT_SUCCESS_OK;
}
================================================
FILE: K7User/K7UserPrivate.h
================================================
/*
* PROJECT: NanaZip Platform User Library (K7User)
* FILE: K7UserPrivate.h
* PURPOSE: Definition for NanaZip Platform User Private Interfaces
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#ifndef K7_USER_PRIVATE
#define K7_USER_PRIVATE
#include "K7User.h"
#ifndef K7_USER_WIN_USER_PRIVATE
#define K7_USER_WIN_USER_PRIVATE
// Reference: https://github.com/adzm/win32-custom-menubar-aero-theme
// window messages related to menu bar drawing
#define WM_UAHDESTROYWINDOW 0x0090 // handled by DefWindowProc
#define WM_UAHDRAWMENU 0x0091 // lParam is UAHMENU
#define WM_UAHDRAWMENUITEM 0x0092 // lParam is UAHDRAWMENUITEM
#define WM_UAHINITMENU 0x0093 // handled by DefWindowProc
#define WM_UAHMEASUREMENUITEM 0x0094 // lParam is UAHMEASUREMENUITEM
#define WM_UAHNCPAINTMENUPOPUP 0x0095 // handled by DefWindowProc
// describes the sizes of the menu bar or menu item
typedef union tagUAHMENUITEMMETRICS
{
// cx appears to be 14 / 0xE less than rcItem's width!
// cy 0x14 seems stable, i wonder if it is 4 less than rcItem's height which
// is always 24 atm
struct {
DWORD cx;
DWORD cy;
} rgsizeBar[2];
struct {
DWORD cx;
DWORD cy;
} rgsizePopup[4];
} UAHMENUITEMMETRICS, *PUAHMENUITEMMETRICS;
// not really used in our case but part of the other structures
typedef struct tagUAHMENUPOPUPMETRICS
{
DWORD rgcx[4];
// from kernel symbols, padded to full dword
DWORD fUpdateMaxWidths : 2;
} UAHMENUPOPUPMETRICS, *PUAHMENUPOPUPMETRICS;
// hmenu is the main window menu; hdc is the context to draw in
typedef struct tagUAHMENU
{
HMENU hmenu;
HDC hdc;
// no idea what these mean, in my testing it's either 0x00000a00 or
// sometimes 0x00000a10
DWORD dwFlags;
} UAHMENU, *PUAHMENU;
// menu items are always referred to by iPosition here
typedef struct tagUAHMENUITEM
{
int iPosition; // 0-based position of menu item in menubar
UAHMENUITEMMETRICS umim;
UAHMENUPOPUPMETRICS umpm;
} UAHMENUITEM, *PUAHMENUITEM;
// the DRAWITEMSTRUCT contains the states of the menu items, as well as
// the position index of the item in the menu, which is duplicated in
// the UAHMENUITEM's iPosition as well
typedef struct UAHDRAWMENUITEM
{
DRAWITEMSTRUCT dis; // itemID looks uninitialized
UAHMENU um;
UAHMENUITEM umi;
} UAHDRAWMENUITEM, *PUAHDRAWMENUITEM;
// the MEASUREITEMSTRUCT is intended to be filled with the size of the item
// height appears to be ignored, but width can be modified
typedef struct tagUAHMEASUREMENUITEM
{
MEASUREITEMSTRUCT mis;
UAHMENU um;
UAHMENUITEM umi;
} UAHMEASUREMENUITEM, *PUAHMEASUREMENUITEM;
#endif // !K7_USER_WIN_USER_PRIVATE
#ifndef K7_USER_DARK_MODE_PRIVATE
#define K7_USER_DARK_MODE_PRIVATE
/**
* @brief Uninitializes the dark mode support.
* @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,
* it returns an MO_RESULT error code.
*/
EXTERN_C MO_RESULT MOAPI K7UserUninitializeDarkModeSupport();
#endif // !K7_USER_DARK_MODE_PRIVATE
#endif // !K7_USER_PRIVATE
================================================
FILE: K7User/K7UserRedirector.cpp
================================================
/*
* PROJECT: NanaZip Platform User Library (K7User)
* FILE: K7UserRedirector.cpp
* PURPOSE: Implementation for NanaZip Platform User API Redirector
*
* LICENSE: The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
*/
#include "K7UserPrivate.h"
// Here are the linker-time redirections to replace the original APIs.
// Implementations only for x64 and ARM64, if you want to learn how to achieve
// that in x86, please refer to NanaZip.Shared.ModernExperienceShims project in
// the historical NanaZip versions source code.
#ifndef K7_REDIRECT
#define K7_REDIRECT(Source, Target) \
extern "C" __declspec(selectany) void const* const __imp_##Source = \
reinterpret_cast(::Target); \
__pragma(comment(linker, "/include:__imp_" #Source))
#endif // !K7_REDIRECT
K7_REDIRECT(MessageBoxW, K7UserModernMessageBoxW);
K7_REDIRECT(SHBrowseForFolderW, K7UserModernSHBrowseForFolderW);
================================================
FILE: K7User/K7UserStatic.props
================================================
$(MSBuildThisFileDirectory);$(IncludePath)
$(OutDir)K7UserStatic.lib;%(AdditionalDependencies)
1.0.372
{0B7D00BE-6890-453E-86A4-DEF68B5C22A4}
================================================
FILE: K7User/K7UserStatic.vcxproj
================================================
{0B7D00BE-6890-453E-86A4-DEF68B5C22A4}
K7UserStatic
StaticLibrary
true
$(MSBuildThisFileDirectory)..\K7Base\;$(IncludePath)
MultiThreadedDebug
MultiThreaded
1.0.372
1.0.3550
1.0.1171
================================================
FILE: K7User/ReadMe.md
================================================
# NanaZip Platform User Library (K7User)
***Work In Progress***
The static and dynamic library that encapsulates the GUI portion of the base
platform infrastructure for the NanaZip. It's one of the foundational libraries
of the NanaZip Platform Abstraction Layer.
K7 is the alias of NanaZip. Here is the relationship between K7 and NanaZip: I
had mentioned one of the reasons that I call this project NanaZip because Nana
is the romaji of なな which means seven in Japanese. But I had not mentioned the
way I confirm that: I had recalled one of the Japanese VTubers called Kagura
Nana when I waiting my elder sister for dinner at Taiyanggong subway station,
Beijing. For playing more puns, NanaZip uses the K7 (K -> Kagura, 7 -> Nana) as
the alias.
K7User is designed for Windows only, although the most of the K7User interfaces
are designed to be platform-independent. Maybe in the future, the K7User will
have the implementations for Linux and FreeBSD, although the implementation may
not in this repository.
## Features
- Dark Mode Support
- Modern Experiences Support (GUI)
================================================
FILE: License.md
================================================
# NanaZip License
For giving the maximum respect for the upstream projects and following the
philosophy about open-source software from Kenji Mouri (MouriNaruto), the one
of the M2-Team founders.
The source code of NanaZip (not including the source code from third-party
libraries, 7-Zip or other 7-Zip derivatives) is distributed under the MIT
License.
The application file association icons of NanaZip (these contents are only in
the `Assets` folder) are designed by Shomnipotence and authorized to the
NanaZip project, and it is distributed under the CC BY-ND 4.0 License.
The source code from 7-Zip or other 7-Zip derivatives (these contents are only
in the `NanaZip.Core\SevenZip`, `NanaZip.Core\Extensions\ZSCodecs`,
`NanaZip.Universal\SevenZip`, `NanaZip.UI.Classic\SevenZip` and
`NanaZip.UI.Modern\SevenZip` folders) is distributed under the 7-Zip License.
The source code from the third-party libraries is distributed under the original
license used in the third-party libraries.
This permission notice shall be included in all copies or substantial portions
of the Software.
### The philosophy about open-source software from Kenji Mouri (MouriNaruto)
- The source code from the third-party projects should be distributed under
their original licenses to give the maximum respect for the upstream
projects.
- Don't make your software open source if you don't want your source code or
ideas used in proprietary software. Because they always have the way to cross
restrictions if they really want to do, even you distributed your source code
under the strictest copyleft license, they can use clean room to resolve it.
- I prefer permissive licenses because using copyleft licenses will make you
feel anxious in most cases because you always need to worry about someone
using your source code in proprietary software. So, I choose to give the
maximum respect to users, and I also hope people can try their best to treat
others kindly.
### The MIT License
```
The MIT License (MIT)
Copyright (c) M2-Team and Contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
### The 7-Zip License
```
7-Zip
~~~~~
License for use and distribution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7-Zip Copyright (C) 1999-2021 Igor Pavlov.
The licenses for files are:
1) 7z.dll:
- The "GNU LGPL" as main license for most of the code
- The "GNU LGPL" with "unRAR license restriction" for some code
- The "BSD 3-clause License" for some code
2) All other files: the "GNU LGPL".
Redistributions in binary form must reproduce related license information
from this file.
Note:
You can use 7-Zip on any computer, including a computer in a commercial
organization. You don't need to register or pay for 7-Zip.
GNU LGPL information
--------------------
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 can receive a copy of the GNU Lesser General Public License from
http://www.gnu.org/
BSD 3-clause License
--------------------
The "BSD 3-clause License" is used for the code in 7z.dll that implements
LZFSE data decompression. That code was derived from the code in the "LZFSE
compression library" developed by Apple Inc, that also uses the "BSD
3-clause License":
----
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the copyright holder(s) nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
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.
----
unRAR license restriction
-------------------------
The decompression engine for RAR archives was developed using source
code of unRAR program.
All copyrights to original unRAR code are owned by Alexander Roshal.
The license for original unRAR code has the following restriction:
The unRAR sources cannot be used to re-create the RAR compression
algorithm, which is proprietary. Distribution of modified unRAR sources
in separate form or as a part of other software is permitted, provided
that it is clearly stated in the documentation and source comments that
the code may not be used to develop a RAR (WinRAR) compatible archiver.
--
Igor Pavlov
```
### The CC BY-ND 4.0 License
```
Copyright (c) Shomnipotence and M2-Team. All rights reserved.
This work is licensed under a Creative Commons Attribution-NoDerivatives 4.0
International License.
Attribution-NoDerivatives 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-NoDerivatives 4.0 International Public
License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NoDerivatives 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
c. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
d. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
e. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
f. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
g. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
h. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
i. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
j. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce and reproduce, but not Share, Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material, You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
For the avoidance of doubt, You do not have permission under
this Public License to Share Adapted Material.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database, provided You do not Share
Adapted Material;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
```
### The 7-Zip branches used in NanaZip
- https://www.7-zip.org/
- https://github.com/myfreeer/7z-build-nsis
- https://github.com/mcmilk/7-Zip-zstd
### The third-party libraries used in NanaZip
- BLAKE3, https://github.com/BLAKE3-team/BLAKE3
- Brotli, https://github.com/google/brotli
- C++/WinRT, https://github.com/microsoft/cppwinrt
- Fast LZMA2, https://github.com/conor42/fast-lzma2
- FreeBSD, https://github.com/freebsd/freebsd-src
- GmSSL, https://github.com/guanzhi/GmSSL
- littlefs, https://github.com/littlefs-project/littlefs
- Lizard, https://github.com/inikep/lizard
- LZ4, https://github.com/lz4/lz4
- LZ5, https://github.com/inikep/lizard
- LZMA SDK, https://www.7-zip.org/sdk.html
- Mile.Detours, https://github.com/ProjectMile/Mile.Detours
- Mile.Json, https://github.com/ProjectMile/Mile.Json
- Mile.Mobility, https://github.com/ProjectMile/Mile.Mobility
- Mile.Project.Configurations, https://github.com/ProjectMile/Mile.Project.Configurations
- Mile.Windows.Helpers, https://github.com/ProjectMile/Mile.Windows.Helpers
- Mile.Windows.Internal, https://github.com/ProjectMile/Mile.Windows.Internal
- Mile.Windows.UniCrt, https://github.com/ProjectMile/Mile.Windows.UniCrt
- Mile.Xaml, https://github.com/ProjectMile/Mile.Xaml
- RHash, https://github.com/rhash/RHash
- Windows-driver-samples, https://github.com/microsoft/Windows-driver-samples
- xxHash, https://github.com/Cyan4973/xxHash
- Zstandard, https://github.com/facebook/zstd
- ZSTDMT, https://github.com/mcmilk/zstdmt
================================================
FILE: NanaZip.Build.Tasks/NanaZip.Build.Tasks.csproj
================================================
netstandard2.0
default
enable
M2-Team
© M2-Team and Contributors. All rights reserved.
$(MileProjectVersion)
================================================
FILE: NanaZip.Build.Tasks/RefreshAppxManifestVersion.cs
================================================
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Mile.Project.Helpers;
using System.IO;
using System.Xml;
namespace NanaZip.Build.Tasks
{
public class RefreshAppxManifestVersion : Task
{
[Required]
public string? FilePath { get; set; }
[Required]
public string? Version { get; set; }
public override bool Execute()
{
XmlDocument Document = new XmlDocument();
Document.PreserveWhitespace = true;
Document.Load(FilePath);
XmlNode? PackageNode = Document["Package"];
if (PackageNode == null)
{
Log.LogError("Cannot find Package node in the manifest.");
return false;
}
XmlNode? IdentityNode = PackageNode["Identity"];
if (IdentityNode == null)
{
Log.LogError("Cannot find Identity node in the manifest.");
return false;
}
XmlAttribute? VersionAttribute = IdentityNode.Attributes["Version"];
if (VersionAttribute == null)
{
Log.LogError("Cannot find Version attribute in the manifest.");
return false;
}
FileUtilities.SaveTextToFileAsUtf8Bom(
FilePath,
File.ReadAllText(FilePath).Replace(
string.Format(
" {0}=\"{1}\"",
VersionAttribute.Name,
VersionAttribute.Value),
string.Format(
" {0}=\"{1}\"",
VersionAttribute.Name,
Version)));
return true;
}
}
}
================================================
FILE: NanaZip.Build.Tasks/RefreshProjectBuildNumberDate.cs
================================================
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Mile.Project.Helpers;
using System.IO;
using System.Xml;
namespace NanaZip.Build.Tasks
{
public class RefreshProjectBuildNumberDate : Task
{
[Required]
public string? FilePath { get; set; }
[Required]
public string? BuildNumberDate { get; set; }
public override bool Execute()
{
XmlDocument Document = new XmlDocument();
Document.PreserveWhitespace = true;
Document.Load(FilePath);
XmlNode? ProjectNode = Document["Project"];
if (ProjectNode == null)
{
Log.LogError(
"Cannot find Project node in the manifest.");
return false;
}
XmlNode? PropertyGroupNode = ProjectNode["PropertyGroup"];
if (PropertyGroupNode == null)
{
Log.LogError(
"Cannot find PropertyGroup node in the manifest.");
return false;
}
XmlNode? NanaZipBuildNumberDateNode =
PropertyGroupNode["NanaZipBuildNumberDate"];
if (NanaZipBuildNumberDateNode == null)
{
Log.LogError(
"Cannot find NanaZipBuildNumberDate node in the manifest.");
return false;
}
FileUtilities.SaveTextToFileAsUtf8Bom(
FilePath,
File.ReadAllText(FilePath).Replace(
string.Format(
"<{0}>{1}{0}>",
NanaZipBuildNumberDateNode.Name,
NanaZipBuildNumberDateNode.InnerText),
string.Format(
"<{0}>{1}{0}>",
NanaZipBuildNumberDateNode.Name,
BuildNumberDate)));
return true;
}
}
}
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3.c
================================================
#include
#include
#include
#include "blake3.h"
#include "blake3_impl.h"
const char *blake3_version(void) { return BLAKE3_VERSION_STRING; }
INLINE void chunk_state_init(blake3_chunk_state *self, const uint32_t key[8],
uint8_t flags) {
memcpy(self->cv, key, BLAKE3_KEY_LEN);
self->chunk_counter = 0;
memset(self->buf, 0, BLAKE3_BLOCK_LEN);
self->buf_len = 0;
self->blocks_compressed = 0;
self->flags = flags;
}
INLINE void chunk_state_reset(blake3_chunk_state *self, const uint32_t key[8],
uint64_t chunk_counter) {
memcpy(self->cv, key, BLAKE3_KEY_LEN);
self->chunk_counter = chunk_counter;
self->blocks_compressed = 0;
memset(self->buf, 0, BLAKE3_BLOCK_LEN);
self->buf_len = 0;
}
INLINE size_t chunk_state_len(const blake3_chunk_state *self) {
return (BLAKE3_BLOCK_LEN * (size_t)self->blocks_compressed) +
((size_t)self->buf_len);
}
INLINE size_t chunk_state_fill_buf(blake3_chunk_state *self,
const uint8_t *input, size_t input_len) {
size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len);
if (take > input_len) {
take = input_len;
}
uint8_t *dest = self->buf + ((size_t)self->buf_len);
memcpy(dest, input, take);
self->buf_len += (uint8_t)take;
return take;
}
INLINE uint8_t chunk_state_maybe_start_flag(const blake3_chunk_state *self) {
if (self->blocks_compressed == 0) {
return CHUNK_START;
} else {
return 0;
}
}
typedef struct {
uint32_t input_cv[8];
uint64_t counter;
uint8_t block[BLAKE3_BLOCK_LEN];
uint8_t block_len;
uint8_t flags;
} output_t;
INLINE output_t make_output(const uint32_t input_cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags) {
output_t ret;
memcpy(ret.input_cv, input_cv, 32);
memcpy(ret.block, block, BLAKE3_BLOCK_LEN);
ret.block_len = block_len;
ret.counter = counter;
ret.flags = flags;
return ret;
}
// Chaining values within a given chunk (specifically the compress_in_place
// interface) are represented as words. This avoids unnecessary bytes<->words
// conversion overhead in the portable implementation. However, the hash_many
// interface handles both user input and parent node blocks, so it accepts
// bytes. For that reason, chaining values in the CV stack are represented as
// bytes.
INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) {
uint32_t cv_words[8];
memcpy(cv_words, self->input_cv, 32);
blake3_compress_in_place(cv_words, self->block, self->block_len,
self->counter, self->flags);
store_cv_words(cv, cv_words);
}
INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out,
size_t out_len) {
if (out_len == 0) {
return;
}
uint64_t output_block_counter = seek / 64;
size_t offset_within_block = seek % 64;
uint8_t wide_buf[64];
if(offset_within_block) {
blake3_compress_xof(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, wide_buf);
const size_t available_bytes = 64 - offset_within_block;
const size_t bytes = out_len > available_bytes ? available_bytes : out_len;
memcpy(out, wide_buf + offset_within_block, bytes);
out += bytes;
out_len -= bytes;
output_block_counter += 1;
}
if(out_len / 64) {
blake3_xof_many(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, out, out_len / 64);
}
output_block_counter += out_len / 64;
out += out_len & -64;
out_len -= out_len & -64;
if(out_len) {
blake3_compress_xof(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, wide_buf);
memcpy(out, wide_buf, out_len);
}
}
INLINE void chunk_state_update(blake3_chunk_state *self, const uint8_t *input,
size_t input_len) {
if (self->buf_len > 0) {
size_t take = chunk_state_fill_buf(self, input, input_len);
input += take;
input_len -= take;
if (input_len > 0) {
blake3_compress_in_place(
self->cv, self->buf, BLAKE3_BLOCK_LEN, self->chunk_counter,
self->flags | chunk_state_maybe_start_flag(self));
self->blocks_compressed += 1;
self->buf_len = 0;
memset(self->buf, 0, BLAKE3_BLOCK_LEN);
}
}
while (input_len > BLAKE3_BLOCK_LEN) {
blake3_compress_in_place(self->cv, input, BLAKE3_BLOCK_LEN,
self->chunk_counter,
self->flags | chunk_state_maybe_start_flag(self));
self->blocks_compressed += 1;
input += BLAKE3_BLOCK_LEN;
input_len -= BLAKE3_BLOCK_LEN;
}
chunk_state_fill_buf(self, input, input_len);
}
INLINE output_t chunk_state_output(const blake3_chunk_state *self) {
uint8_t block_flags =
self->flags | chunk_state_maybe_start_flag(self) | CHUNK_END;
return make_output(self->cv, self->buf, self->buf_len, self->chunk_counter,
block_flags);
}
INLINE output_t parent_output(const uint8_t block[BLAKE3_BLOCK_LEN],
const uint32_t key[8], uint8_t flags) {
return make_output(key, block, BLAKE3_BLOCK_LEN, 0, flags | PARENT);
}
// Given some input larger than one chunk, return the number of bytes that
// should go in the left subtree. This is the largest power-of-2 number of
// chunks that leaves at least 1 byte for the right subtree.
INLINE size_t left_subtree_len(size_t input_len) {
// Subtract 1 to reserve at least one byte for the right side. input_len
// should always be greater than BLAKE3_CHUNK_LEN.
size_t full_chunks = (input_len - 1) / BLAKE3_CHUNK_LEN;
return round_down_to_power_of_2(full_chunks) * BLAKE3_CHUNK_LEN;
}
// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE chunks at the same time
// on a single thread. Write out the chunk chaining values and return the
// number of chunks hashed. These chunks are never the root and never empty;
// those cases use a different codepath.
INLINE size_t compress_chunks_parallel(const uint8_t *input, size_t input_len,
const uint32_t key[8],
uint64_t chunk_counter, uint8_t flags,
uint8_t *out) {
#if defined(BLAKE3_TESTING)
assert(0 < input_len);
assert(input_len <= MAX_SIMD_DEGREE * BLAKE3_CHUNK_LEN);
#endif
const uint8_t *chunks_array[MAX_SIMD_DEGREE];
size_t input_position = 0;
size_t chunks_array_len = 0;
while (input_len - input_position >= BLAKE3_CHUNK_LEN) {
chunks_array[chunks_array_len] = &input[input_position];
input_position += BLAKE3_CHUNK_LEN;
chunks_array_len += 1;
}
blake3_hash_many(chunks_array, chunks_array_len,
BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter,
true, flags, CHUNK_START, CHUNK_END, out);
// Hash the remaining partial chunk, if there is one. Note that the empty
// chunk (meaning the empty message) is a different codepath.
if (input_len > input_position) {
uint64_t counter = chunk_counter + (uint64_t)chunks_array_len;
blake3_chunk_state chunk_state;
chunk_state_init(&chunk_state, key, flags);
chunk_state.chunk_counter = counter;
chunk_state_update(&chunk_state, &input[input_position],
input_len - input_position);
output_t output = chunk_state_output(&chunk_state);
output_chaining_value(&output, &out[chunks_array_len * BLAKE3_OUT_LEN]);
return chunks_array_len + 1;
} else {
return chunks_array_len;
}
}
// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE parents at the same time
// on a single thread. Write out the parent chaining values and return the
// number of parents hashed. (If there's an odd input chaining value left over,
// return it as an additional output.) These parents are never the root and
// never empty; those cases use a different codepath.
INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values,
size_t num_chaining_values,
const uint32_t key[8], uint8_t flags,
uint8_t *out) {
#if defined(BLAKE3_TESTING)
assert(2 <= num_chaining_values);
assert(num_chaining_values <= 2 * MAX_SIMD_DEGREE_OR_2);
#endif
const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2];
size_t parents_array_len = 0;
while (num_chaining_values - (2 * parents_array_len) >= 2) {
parents_array[parents_array_len] =
&child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN];
parents_array_len += 1;
}
blake3_hash_many(parents_array, parents_array_len, 1, key,
0, // Parents always use counter 0.
false, flags | PARENT,
0, // Parents have no start flags.
0, // Parents have no end flags.
out);
// If there's an odd child left over, it becomes an output.
if (num_chaining_values > 2 * parents_array_len) {
memcpy(&out[parents_array_len * BLAKE3_OUT_LEN],
&child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN],
BLAKE3_OUT_LEN);
return parents_array_len + 1;
} else {
return parents_array_len;
}
}
// The wide helper function returns (writes out) an array of chaining values
// and returns the length of that array. The number of chaining values returned
// is the dynamically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer,
// if the input is shorter than that many chunks. The reason for maintaining a
// wide array of chaining values going back up the tree, is to allow the
// implementation to hash as many parents in parallel as possible.
//
// As a special case when the SIMD degree is 1, this function will still return
// at least 2 outputs. This guarantees that this function doesn't perform the
// root compression. (If it did, it would use the wrong flags, and also we
// wouldn't be able to implement extendable output.) Note that this function is
// not used when the whole input is only 1 chunk long; that's a different
// codepath.
//
// Why not just have the caller split the input on the first update(), instead
// of implementing this special rule? Because we don't want to limit SIMD or
// multi-threading parallelism for that update().
size_t blake3_compress_subtree_wide(const uint8_t *input, size_t input_len,
const uint32_t key[8],
uint64_t chunk_counter, uint8_t flags,
uint8_t *out, bool use_tbb) {
// Note that the single chunk case does *not* bump the SIMD degree up to 2
// when it is 1. If this implementation adds multi-threading in the future,
// this gives us the option of multi-threading even the 2-chunk case, which
// can help performance on smaller platforms.
if (input_len <= blake3_simd_degree() * BLAKE3_CHUNK_LEN) {
return compress_chunks_parallel(input, input_len, key, chunk_counter, flags,
out);
}
// With more than simd_degree chunks, we need to recurse. Start by dividing
// the input into left and right subtrees. (Note that this is only optimal
// as long as the SIMD degree is a power of 2. If we ever get a SIMD degree
// of 3 or something, we'll need a more complicated strategy.)
size_t left_input_len = left_subtree_len(input_len);
size_t right_input_len = input_len - left_input_len;
const uint8_t *right_input = &input[left_input_len];
uint64_t right_chunk_counter =
chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN);
// Make space for the child outputs. Here we use MAX_SIMD_DEGREE_OR_2 to
// account for the special case of returning 2 outputs when the SIMD degree
// is 1.
uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN];
size_t degree = blake3_simd_degree();
if (left_input_len > BLAKE3_CHUNK_LEN && degree == 1) {
// The special case: We always use a degree of at least two, to make
// sure there are two outputs. Except, as noted above, at the chunk
// level, where we allow degree=1. (Note that the 1-chunk-input case is
// a different codepath.)
degree = 2;
}
uint8_t *right_cvs = &cv_array[degree * BLAKE3_OUT_LEN];
// Recurse!
size_t left_n = -1;
size_t right_n = -1;
#if defined(BLAKE3_USE_TBB)
blake3_compress_subtree_wide_join_tbb(
key, flags, use_tbb,
// left-hand side
input, left_input_len, chunk_counter, cv_array, &left_n,
// right-hand side
right_input, right_input_len, right_chunk_counter, right_cvs, &right_n);
#else
left_n = blake3_compress_subtree_wide(
input, left_input_len, key, chunk_counter, flags, cv_array, use_tbb);
right_n = blake3_compress_subtree_wide(right_input, right_input_len, key,
right_chunk_counter, flags, right_cvs,
use_tbb);
#endif // BLAKE3_USE_TBB
// The special case again. If simd_degree=1, then we'll have left_n=1 and
// right_n=1. Rather than compressing them into a single output, return
// them directly, to make sure we always have at least two outputs.
if (left_n == 1) {
memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN);
return 2;
}
// Otherwise, do one layer of parent node compression.
size_t num_chaining_values = left_n + right_n;
return compress_parents_parallel(cv_array, num_chaining_values, key, flags,
out);
}
// Hash a subtree with compress_subtree_wide(), and then condense the resulting
// list of chaining values down to a single parent node. Don't compress that
// last parent node, however. Instead, return its message bytes (the
// concatenated chaining values of its children). This is necessary when the
// first call to update() supplies a complete subtree, because the topmost
// parent node of that subtree could end up being the root. It's also necessary
// for extended output in the general case.
//
// As with compress_subtree_wide(), this function is not used on inputs of 1
// chunk or less. That's a different codepath.
INLINE void
compress_subtree_to_parent_node(const uint8_t *input, size_t input_len,
const uint32_t key[8], uint64_t chunk_counter,
uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN],
bool use_tbb) {
#if defined(BLAKE3_TESTING)
assert(input_len > BLAKE3_CHUNK_LEN);
#endif
uint8_t cv_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN];
size_t num_cvs = blake3_compress_subtree_wide(input, input_len, key,
chunk_counter, flags, cv_array, use_tbb);
assert(num_cvs <= MAX_SIMD_DEGREE_OR_2);
// The following loop never executes when MAX_SIMD_DEGREE_OR_2 is 2, because
// as we just asserted, num_cvs will always be <=2 in that case. But GCC
// (particularly GCC 8.5) can't tell that it never executes, and if NDEBUG is
// set then it emits incorrect warnings here. We tried a few different
// hacks to silence these, but in the end our hacks just produced different
// warnings (see https://github.com/BLAKE3-team/BLAKE3/pull/380). Out of
// desperation, we ifdef out this entire loop when we know it's not needed.
#if MAX_SIMD_DEGREE_OR_2 > 2
// If MAX_SIMD_DEGREE_OR_2 is greater than 2 and there's enough input,
// compress_subtree_wide() returns more than 2 chaining values. Condense
// them into 2 by forming parent nodes repeatedly.
uint8_t out_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN / 2];
while (num_cvs > 2) {
num_cvs =
compress_parents_parallel(cv_array, num_cvs, key, flags, out_array);
memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN);
}
#endif
memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN);
}
INLINE void hasher_init_base(blake3_hasher *self, const uint32_t key[8],
uint8_t flags) {
memcpy(self->key, key, BLAKE3_KEY_LEN);
chunk_state_init(&self->chunk, key, flags);
self->cv_stack_len = 0;
}
void blake3_hasher_init(blake3_hasher *self) { hasher_init_base(self, IV, 0); }
void blake3_hasher_init_keyed(blake3_hasher *self,
const uint8_t key[BLAKE3_KEY_LEN]) {
uint32_t key_words[8];
load_key_words(key, key_words);
hasher_init_base(self, key_words, KEYED_HASH);
}
void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context,
size_t context_len) {
blake3_hasher context_hasher;
hasher_init_base(&context_hasher, IV, DERIVE_KEY_CONTEXT);
blake3_hasher_update(&context_hasher, context, context_len);
uint8_t context_key[BLAKE3_KEY_LEN];
blake3_hasher_finalize(&context_hasher, context_key, BLAKE3_KEY_LEN);
uint32_t context_key_words[8];
load_key_words(context_key, context_key_words);
hasher_init_base(self, context_key_words, DERIVE_KEY_MATERIAL);
}
void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context) {
blake3_hasher_init_derive_key_raw(self, context, strlen(context));
}
// As described in hasher_push_cv() below, we do "lazy merging", delaying
// merges until right before the next CV is about to be added. This is
// different from the reference implementation. Another difference is that we
// aren't always merging 1 chunk at a time. Instead, each CV might represent
// any power-of-two number of chunks, as long as the smaller-above-larger stack
// order is maintained. Instead of the "count the trailing 0-bits" algorithm
// described in the spec, we use a "count the total number of 1-bits" variant
// that doesn't require us to retain the subtree size of the CV on top of the
// stack. The principle is the same: each CV that should remain in the stack is
// represented by a 1-bit in the total number of chunks (or bytes) so far.
INLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) {
size_t post_merge_stack_len = (size_t)popcnt(total_len);
while (self->cv_stack_len > post_merge_stack_len) {
uint8_t *parent_node =
&self->cv_stack[(self->cv_stack_len - 2) * BLAKE3_OUT_LEN];
output_t output = parent_output(parent_node, self->key, self->chunk.flags);
output_chaining_value(&output, parent_node);
self->cv_stack_len -= 1;
}
}
// In reference_impl.rs, we merge the new CV with existing CVs from the stack
// before pushing it. We can do that because we know more input is coming, so
// we know none of the merges are root.
//
// This setting is different. We want to feed as much input as possible to
// compress_subtree_wide(), without setting aside anything for the chunk_state.
// If the user gives us 64 KiB, we want to parallelize over all 64 KiB at once
// as a single subtree, if at all possible.
//
// This leads to two problems:
// 1) This 64 KiB input might be the only call that ever gets made to update.
// In this case, the root node of the 64 KiB subtree would be the root node
// of the whole tree, and it would need to be ROOT finalized. We can't
// compress it until we know.
// 2) This 64 KiB input might complete a larger tree, whose root node is
// similarly going to be the root of the whole tree. For example, maybe
// we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the
// node at the root of the 256 KiB subtree until we know how to finalize it.
//
// The second problem is solved with "lazy merging". That is, when we're about
// to add a CV to the stack, we don't merge it with anything first, as the
// reference impl does. Instead we do merges using the *previous* CV that was
// added, which is sitting on top of the stack, and we put the new CV
// (unmerged) on top of the stack afterwards. This guarantees that we never
// merge the root node until finalize().
//
// Solving the first problem requires an additional tool,
// compress_subtree_to_parent_node(). That function always returns the top
// *two* chaining values of the subtree it's compressing. We then do lazy
// merging with each of them separately, so that the second CV will always
// remain unmerged. (That also helps us support extendable output when we're
// hashing an input all-at-once.)
INLINE void hasher_push_cv(blake3_hasher *self, uint8_t new_cv[BLAKE3_OUT_LEN],
uint64_t chunk_counter) {
hasher_merge_cv_stack(self, chunk_counter);
memcpy(&self->cv_stack[self->cv_stack_len * BLAKE3_OUT_LEN], new_cv,
BLAKE3_OUT_LEN);
self->cv_stack_len += 1;
}
INLINE void blake3_hasher_update_base(blake3_hasher *self, const void *input,
size_t input_len, bool use_tbb) {
// Explicitly checking for zero avoids causing UB by passing a null pointer
// to memcpy. This comes up in practice with things like:
// std::vector v;
// blake3_hasher_update(&hasher, v.data(), v.size());
if (input_len == 0) {
return;
}
const uint8_t *input_bytes = (const uint8_t *)input;
// If we have some partial chunk bytes in the internal chunk_state, we need
// to finish that chunk first.
if (chunk_state_len(&self->chunk) > 0) {
size_t take = BLAKE3_CHUNK_LEN - chunk_state_len(&self->chunk);
if (take > input_len) {
take = input_len;
}
chunk_state_update(&self->chunk, input_bytes, take);
input_bytes += take;
input_len -= take;
// If we've filled the current chunk and there's more coming, finalize this
// chunk and proceed. In this case we know it's not the root.
if (input_len > 0) {
output_t output = chunk_state_output(&self->chunk);
uint8_t chunk_cv[32];
output_chaining_value(&output, chunk_cv);
hasher_push_cv(self, chunk_cv, self->chunk.chunk_counter);
chunk_state_reset(&self->chunk, self->key, self->chunk.chunk_counter + 1);
} else {
return;
}
}
// Now the chunk_state is clear, and we have more input. If there's more than
// a single chunk (so, definitely not the root chunk), hash the largest whole
// subtree we can, with the full benefits of SIMD (and maybe in the future,
// multi-threading) parallelism. Two restrictions:
// - The subtree has to be a power-of-2 number of chunks. Only subtrees along
// the right edge can be incomplete, and we don't know where the right edge
// is going to be until we get to finalize().
// - The subtree must evenly divide the total number of chunks up until this
// point (if total is not 0). If the current incomplete subtree is only
// waiting for 1 more chunk, we can't hash a subtree of 4 chunks. We have
// to complete the current subtree first.
// Because we might need to break up the input to form powers of 2, or to
// evenly divide what we already have, this part runs in a loop.
while (input_len > BLAKE3_CHUNK_LEN) {
size_t subtree_len = round_down_to_power_of_2(input_len);
uint64_t count_so_far = self->chunk.chunk_counter * BLAKE3_CHUNK_LEN;
// Shrink the subtree_len until it evenly divides the count so far. We know
// that subtree_len itself is a power of 2, so we can use a bitmasking
// trick instead of an actual remainder operation. (Note that if the caller
// consistently passes power-of-2 inputs of the same size, as is hopefully
// typical, this loop condition will always fail, and subtree_len will
// always be the full length of the input.)
//
// An aside: We don't have to shrink subtree_len quite this much. For
// example, if count_so_far is 1, we could pass 2 chunks to
// compress_subtree_to_parent_node. Since we'll get 2 CVs back, we'll still
// get the right answer in the end, and we might get to use 2-way SIMD
// parallelism. The problem with this optimization, is that it gets us
// stuck always hashing 2 chunks. The total number of chunks will remain
// odd, and we'll never graduate to higher degrees of parallelism. See
// https://github.com/BLAKE3-team/BLAKE3/issues/69.
while ((((uint64_t)(subtree_len - 1)) & count_so_far) != 0) {
subtree_len /= 2;
}
// The shrunken subtree_len might now be 1 chunk long. If so, hash that one
// chunk by itself. Otherwise, compress the subtree into a pair of CVs.
uint64_t subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN;
if (subtree_len <= BLAKE3_CHUNK_LEN) {
blake3_chunk_state chunk_state;
chunk_state_init(&chunk_state, self->key, self->chunk.flags);
chunk_state.chunk_counter = self->chunk.chunk_counter;
chunk_state_update(&chunk_state, input_bytes, subtree_len);
output_t output = chunk_state_output(&chunk_state);
uint8_t cv[BLAKE3_OUT_LEN];
output_chaining_value(&output, cv);
hasher_push_cv(self, cv, chunk_state.chunk_counter);
} else {
// This is the high-performance happy path, though getting here depends
// on the caller giving us a long enough input.
uint8_t cv_pair[2 * BLAKE3_OUT_LEN];
compress_subtree_to_parent_node(input_bytes, subtree_len, self->key,
self->chunk.chunk_counter,
self->chunk.flags, cv_pair, use_tbb);
hasher_push_cv(self, cv_pair, self->chunk.chunk_counter);
hasher_push_cv(self, &cv_pair[BLAKE3_OUT_LEN],
self->chunk.chunk_counter + (subtree_chunks / 2));
}
self->chunk.chunk_counter += subtree_chunks;
input_bytes += subtree_len;
input_len -= subtree_len;
}
// If there's any remaining input less than a full chunk, add it to the chunk
// state. In that case, also do a final merge loop to make sure the subtree
// stack doesn't contain any unmerged pairs. The remaining input means we
// know these merges are non-root. This merge loop isn't strictly necessary
// here, because hasher_push_chunk_cv already does its own merge loop, but it
// simplifies blake3_hasher_finalize below.
if (input_len > 0) {
chunk_state_update(&self->chunk, input_bytes, input_len);
hasher_merge_cv_stack(self, self->chunk.chunk_counter);
}
}
void blake3_hasher_update(blake3_hasher *self, const void *input,
size_t input_len) {
bool use_tbb = false;
blake3_hasher_update_base(self, input, input_len, use_tbb);
}
#if defined(BLAKE3_USE_TBB)
void blake3_hasher_update_tbb(blake3_hasher *self, const void *input,
size_t input_len) {
bool use_tbb = true;
blake3_hasher_update_base(self, input, input_len, use_tbb);
}
#endif // BLAKE3_USE_TBB
void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
size_t out_len) {
blake3_hasher_finalize_seek(self, 0, out, out_len);
}
void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,
uint8_t *out, size_t out_len) {
// Explicitly checking for zero avoids causing UB by passing a null pointer
// to memcpy. This comes up in practice with things like:
// std::vector v;
// blake3_hasher_finalize(&hasher, v.data(), v.size());
if (out_len == 0) {
return;
}
// If the subtree stack is empty, then the current chunk is the root.
if (self->cv_stack_len == 0) {
output_t output = chunk_state_output(&self->chunk);
output_root_bytes(&output, seek, out, out_len);
return;
}
// If there are any bytes in the chunk state, finalize that chunk and do a
// roll-up merge between that chunk hash and every subtree in the stack. In
// this case, the extra merge loop at the end of blake3_hasher_update
// guarantees that none of the subtrees in the stack need to be merged with
// each other first. Otherwise, if there are no bytes in the chunk state,
// then the top of the stack is a chunk hash, and we start the merge from
// that.
output_t output;
size_t cvs_remaining;
if (chunk_state_len(&self->chunk) > 0) {
cvs_remaining = self->cv_stack_len;
output = chunk_state_output(&self->chunk);
} else {
// There are always at least 2 CVs in the stack in this case.
cvs_remaining = self->cv_stack_len - 2;
output = parent_output(&self->cv_stack[cvs_remaining * 32], self->key,
self->chunk.flags);
}
while (cvs_remaining > 0) {
cvs_remaining -= 1;
uint8_t parent_block[BLAKE3_BLOCK_LEN];
memcpy(parent_block, &self->cv_stack[cvs_remaining * 32], 32);
output_chaining_value(&output, &parent_block[32]);
output = parent_output(parent_block, self->key, self->chunk.flags);
}
output_root_bytes(&output, seek, out, out_len);
}
void blake3_hasher_reset(blake3_hasher *self) {
chunk_state_reset(&self->chunk, self->key, 0);
self->cv_stack_len = 0;
}
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3.h
================================================
#ifndef BLAKE3_H
#define BLAKE3_H
#include
#include
#if !defined(BLAKE3_API)
# if defined(_WIN32) || defined(__CYGWIN__)
# if defined(BLAKE3_DLL)
# if defined(BLAKE3_DLL_EXPORTS)
# define BLAKE3_API __declspec(dllexport)
# else
# define BLAKE3_API __declspec(dllimport)
# endif
# define BLAKE3_PRIVATE
# else
# define BLAKE3_API
# define BLAKE3_PRIVATE
# endif
# elif __GNUC__ >= 4
# define BLAKE3_API __attribute__((visibility("default")))
# define BLAKE3_PRIVATE __attribute__((visibility("hidden")))
# else
# define BLAKE3_API
# define BLAKE3_PRIVATE
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define BLAKE3_VERSION_STRING "1.8.3"
#define BLAKE3_KEY_LEN 32
#define BLAKE3_OUT_LEN 32
#define BLAKE3_BLOCK_LEN 64
#define BLAKE3_CHUNK_LEN 1024
#define BLAKE3_MAX_DEPTH 54
// This struct is a private implementation detail. It has to be here because
// it's part of the blake3_hasher structure defined below.
typedef struct {
uint32_t cv[8];
uint64_t chunk_counter;
uint8_t buf[BLAKE3_BLOCK_LEN];
uint8_t buf_len;
uint8_t blocks_compressed;
uint8_t flags;
} blake3_chunk_state;
typedef struct {
uint32_t key[8];
blake3_chunk_state chunk;
uint8_t cv_stack_len;
// The stack size is MAX_DEPTH + 1 because we do lazy merging. For example,
// with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk
// requires a 4th entry, rather than merging everything down to 1, because we
// don't know whether more input is coming. This is different from how the
// reference implementation does things.
uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN];
} blake3_hasher;
BLAKE3_API const char *blake3_version(void);
BLAKE3_API void blake3_hasher_init(blake3_hasher *self);
BLAKE3_API void blake3_hasher_init_keyed(blake3_hasher *self,
const uint8_t key[BLAKE3_KEY_LEN]);
BLAKE3_API void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context);
BLAKE3_API void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context,
size_t context_len);
BLAKE3_API void blake3_hasher_update(blake3_hasher *self, const void *input,
size_t input_len);
#if defined(BLAKE3_USE_TBB)
BLAKE3_API void blake3_hasher_update_tbb(blake3_hasher *self, const void *input,
size_t input_len);
#endif // BLAKE3_USE_TBB
BLAKE3_API void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
size_t out_len);
BLAKE3_API void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,
uint8_t *out, size_t out_len);
BLAKE3_API void blake3_hasher_reset(blake3_hasher *self);
#ifdef __cplusplus
}
#endif
#endif /* BLAKE3_H */
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_avx2_x86-64_windows_msvc.asm
================================================
public _blake3_hash_many_avx2
public blake3_hash_many_avx2
_TEXT SEGMENT ALIGN(16) 'CODE'
ALIGN 16
blake3_hash_many_avx2 PROC
_blake3_hash_many_avx2 PROC
push r15
push r14
push r13
push r12
push rsi
push rdi
push rbx
push rbp
mov rbp, rsp
sub rsp, 880
and rsp, 0FFFFFFFFFFFFFFC0H
vmovdqa xmmword ptr [rsp+2D0H], xmm6
vmovdqa xmmword ptr [rsp+2E0H], xmm7
vmovdqa xmmword ptr [rsp+2F0H], xmm8
vmovdqa xmmword ptr [rsp+300H], xmm9
vmovdqa xmmword ptr [rsp+310H], xmm10
vmovdqa xmmword ptr [rsp+320H], xmm11
vmovdqa xmmword ptr [rsp+330H], xmm12
vmovdqa xmmword ptr [rsp+340H], xmm13
vmovdqa xmmword ptr [rsp+350H], xmm14
vmovdqa xmmword ptr [rsp+360H], xmm15
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, qword ptr [rbp+68H]
movzx r9, byte ptr [rbp+70H]
neg r9d
vmovd xmm0, r9d
vpbroadcastd ymm0, xmm0
vmovdqa ymmword ptr [rsp+260H], ymm0
vpand ymm1, ymm0, ymmword ptr [ADD0]
vpand ymm2, ymm0, ymmword ptr [ADD1]
vmovdqa ymmword ptr [rsp+2A0H], ymm2
vmovd xmm2, r8d
vpbroadcastd ymm2, xmm2
vpaddd ymm2, ymm2, ymm1
vmovdqa ymmword ptr [rsp+220H], ymm2
vpxor ymm1, ymm1, ymmword ptr [CMP_MSB_MASK]
vpxor ymm2, ymm2, ymmword ptr [CMP_MSB_MASK]
vpcmpgtd ymm2, ymm1, ymm2
shr r8, 32
vmovd xmm3, r8d
vpbroadcastd ymm3, xmm3
vpsubd ymm3, ymm3, ymm2
vmovdqa ymmword ptr [rsp+240H], ymm3
shl rdx, 6
mov qword ptr [rsp+2C0H], rdx
cmp rsi, 8
jc final7blocks
outerloop8:
vpbroadcastd ymm0, dword ptr [rcx]
vpbroadcastd ymm1, dword ptr [rcx+4H]
vpbroadcastd ymm2, dword ptr [rcx+8H]
vpbroadcastd ymm3, dword ptr [rcx+0CH]
vpbroadcastd ymm4, dword ptr [rcx+10H]
vpbroadcastd ymm5, dword ptr [rcx+14H]
vpbroadcastd ymm6, dword ptr [rcx+18H]
vpbroadcastd ymm7, dword ptr [rcx+1CH]
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
mov r12, qword ptr [rdi+20H]
mov r13, qword ptr [rdi+28H]
mov r14, qword ptr [rdi+30H]
mov r15, qword ptr [rdi+38H]
movzx eax, byte ptr [rbp+78H]
movzx ebx, byte ptr [rbp+80H]
or eax, ebx
xor edx, edx
ALIGN 16
innerloop8:
movzx ebx, byte ptr [rbp+88H]
or ebx, eax
add rdx, 64
cmp rdx, qword ptr [rsp+2C0H]
cmove eax, ebx
mov dword ptr [rsp+200H], eax
vmovups xmm8, xmmword ptr [r8+rdx-40H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-40H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-40H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-40H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-40H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-40H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-40H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-40H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm8, ymm12, ymm14, 136
vmovaps ymmword ptr [rsp], ymm8
vshufps ymm9, ymm12, ymm14, 221
vmovaps ymmword ptr [rsp+20H], ymm9
vshufps ymm10, ymm13, ymm15, 136
vmovaps ymmword ptr [rsp+40H], ymm10
vshufps ymm11, ymm13, ymm15, 221
vmovaps ymmword ptr [rsp+60H], ymm11
vmovups xmm8, xmmword ptr [r8+rdx-30H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-30H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-30H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-30H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-30H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-30H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-30H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-30H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm8, ymm12, ymm14, 136
vmovaps ymmword ptr [rsp+80H], ymm8
vshufps ymm9, ymm12, ymm14, 221
vmovaps ymmword ptr [rsp+0A0H], ymm9
vshufps ymm10, ymm13, ymm15, 136
vmovaps ymmword ptr [rsp+0C0H], ymm10
vshufps ymm11, ymm13, ymm15, 221
vmovaps ymmword ptr [rsp+0E0H], ymm11
vmovups xmm8, xmmword ptr [r8+rdx-20H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-20H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-20H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-20H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-20H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-20H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-20H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-20H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm8, ymm12, ymm14, 136
vmovaps ymmword ptr [rsp+100H], ymm8
vshufps ymm9, ymm12, ymm14, 221
vmovaps ymmword ptr [rsp+120H], ymm9
vshufps ymm10, ymm13, ymm15, 136
vmovaps ymmword ptr [rsp+140H], ymm10
vshufps ymm11, ymm13, ymm15, 221
vmovaps ymmword ptr [rsp+160H], ymm11
vmovups xmm8, xmmword ptr [r8+rdx-10H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-10H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-10H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-10H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-10H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-10H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-10H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-10H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm8, ymm12, ymm14, 136
vmovaps ymmword ptr [rsp+180H], ymm8
vshufps ymm9, ymm12, ymm14, 221
vmovaps ymmword ptr [rsp+1A0H], ymm9
vshufps ymm10, ymm13, ymm15, 136
vmovaps ymmword ptr [rsp+1C0H], ymm10
vshufps ymm11, ymm13, ymm15, 221
vmovaps ymmword ptr [rsp+1E0H], ymm11
vpbroadcastd ymm15, dword ptr [rsp+200H]
prefetcht0 byte ptr [r8+rdx+80H]
prefetcht0 byte ptr [r12+rdx+80H]
prefetcht0 byte ptr [r9+rdx+80H]
prefetcht0 byte ptr [r13+rdx+80H]
prefetcht0 byte ptr [r10+rdx+80H]
prefetcht0 byte ptr [r14+rdx+80H]
prefetcht0 byte ptr [r11+rdx+80H]
prefetcht0 byte ptr [r15+rdx+80H]
vpaddd ymm0, ymm0, ymmword ptr [rsp]
vpaddd ymm1, ymm1, ymmword ptr [rsp+40H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+80H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm0, ymmword ptr [rsp+220H]
vpxor ymm13, ymm1, ymmword ptr [rsp+240H]
vpxor ymm14, ymm2, ymmword ptr [BLAKE3_BLOCK_LEN]
vpxor ymm15, ymm3, ymm15
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [BLAKE3_IV_0]
vpaddd ymm9, ymm13, ymmword ptr [BLAKE3_IV_1]
vpaddd ymm10, ymm14, ymmword ptr [BLAKE3_IV_2]
vpaddd ymm11, ymm15, ymmword ptr [BLAKE3_IV_3]
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+20H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+60H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+0A0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+100H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+140H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+180H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1C0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+120H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+160H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+1A0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+40H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+60H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+0E0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+80H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+0C0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+140H]
vpaddd ymm2, ymm2, ymmword ptr [rsp]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1A0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+20H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+180H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+120H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+160H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+1C0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+100H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+60H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+140H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+1A0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+80H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+180H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+40H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1C0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+0C0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+120H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+160H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+100H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+0A0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp]
vpaddd ymm2, ymm2, ymmword ptr [rsp+1E0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+20H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+140H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+180H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+1C0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1A0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+0E0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+120H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+60H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+80H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+160H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+0A0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+20H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp]
vpaddd ymm1, ymm1, ymmword ptr [rsp+40H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+100H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+180H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+120H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+1E0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1C0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+1A0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+160H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+140H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+100H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+0E0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H]
vpaddd ymm2, ymm2, ymmword ptr [rsp]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+40H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+60H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+20H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+80H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+120H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+160H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+100H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+1C0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+180H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+20H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+1A0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp]
vpaddd ymm2, ymm2, ymmword ptr [rsp+40H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+80H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+60H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+140H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+0C0H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+160H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+20H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+100H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+1E0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp]
vpaddd ymm2, ymm2, ymmword ptr [rsp+120H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H]
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxor ymm12, ymm12, ymm0
vpxor ymm13, ymm13, ymm1
vpxor ymm14, ymm14, ymm2
vpxor ymm15, ymm15, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpshufb ymm15, ymm15, ymm8
vpaddd ymm8, ymm12, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxor ymm4, ymm4, ymm8
vpxor ymm5, ymm5, ymm9
vpxor ymm6, ymm6, ymm10
vpxor ymm7, ymm7, ymm11
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+1C0H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+40H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+60H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT16]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vmovdqa ymmword ptr [rsp+200H], ymm8
vpsrld ymm8, ymm5, 12
vpslld ymm5, ymm5, 20
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 12
vpslld ymm6, ymm6, 20
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 12
vpslld ymm7, ymm7, 20
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 12
vpslld ymm4, ymm4, 20
vpor ymm4, ymm4, ymm8
vpaddd ymm0, ymm0, ymmword ptr [rsp+140H]
vpaddd ymm1, ymm1, ymmword ptr [rsp+180H]
vpaddd ymm2, ymm2, ymmword ptr [rsp+80H]
vpaddd ymm3, ymm3, ymmword ptr [rsp+1A0H]
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxor ymm15, ymm15, ymm0
vpxor ymm12, ymm12, ymm1
vpxor ymm13, ymm13, ymm2
vpxor ymm14, ymm14, ymm3
vbroadcasti128 ymm8, xmmword ptr [ROT8]
vpshufb ymm15, ymm15, ymm8
vpshufb ymm12, ymm12, ymm8
vpshufb ymm13, ymm13, ymm8
vpshufb ymm14, ymm14, ymm8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm13, ymmword ptr [rsp+200H]
vpaddd ymm9, ymm9, ymm14
vpxor ymm5, ymm5, ymm10
vpxor ymm6, ymm6, ymm11
vpxor ymm7, ymm7, ymm8
vpxor ymm4, ymm4, ymm9
vpxor ymm0, ymm0, ymm8
vpxor ymm1, ymm1, ymm9
vpxor ymm2, ymm2, ymm10
vpxor ymm3, ymm3, ymm11
vpsrld ymm8, ymm5, 7
vpslld ymm5, ymm5, 25
vpor ymm5, ymm5, ymm8
vpsrld ymm8, ymm6, 7
vpslld ymm6, ymm6, 25
vpor ymm6, ymm6, ymm8
vpsrld ymm8, ymm7, 7
vpslld ymm7, ymm7, 25
vpor ymm7, ymm7, ymm8
vpsrld ymm8, ymm4, 7
vpslld ymm4, ymm4, 25
vpor ymm4, ymm4, ymm8
vpxor ymm4, ymm4, ymm12
vpxor ymm5, ymm5, ymm13
vpxor ymm6, ymm6, ymm14
vpxor ymm7, ymm7, ymm15
movzx eax, byte ptr [rbp+78H]
jne innerloop8
mov rbx, qword ptr [rbp+90H]
vunpcklps ymm8, ymm0, ymm1
vunpcklps ymm9, ymm2, ymm3
vunpckhps ymm10, ymm0, ymm1
vunpcklps ymm11, ymm4, ymm5
vunpcklps ymm0, ymm6, ymm7
vshufps ymm12, ymm8, ymm9, 78
vblendps ymm1, ymm8, ymm12, 0CCH
vshufps ymm8, ymm11, ymm0, 78
vunpckhps ymm13, ymm2, ymm3
vblendps ymm2, ymm11, ymm8, 0CCH
vblendps ymm3, ymm12, ymm9, 0CCH
vperm2f128 ymm12, ymm1, ymm2, 20H
vmovups ymmword ptr [rbx], ymm12
vunpckhps ymm14, ymm4, ymm5
vblendps ymm4, ymm8, ymm0, 0CCH
vunpckhps ymm15, ymm6, ymm7
vperm2f128 ymm7, ymm3, ymm4, 20H
vmovups ymmword ptr [rbx+20H], ymm7
vshufps ymm5, ymm10, ymm13, 78
vblendps ymm6, ymm5, ymm13, 0CCH
vshufps ymm13, ymm14, ymm15, 78
vblendps ymm10, ymm10, ymm5, 0CCH
vblendps ymm14, ymm14, ymm13, 0CCH
vperm2f128 ymm8, ymm10, ymm14, 20H
vmovups ymmword ptr [rbx+40H], ymm8
vblendps ymm15, ymm13, ymm15, 0CCH
vperm2f128 ymm13, ymm6, ymm15, 20H
vmovups ymmword ptr [rbx+60H], ymm13
vperm2f128 ymm9, ymm1, ymm2, 31H
vperm2f128 ymm11, ymm3, ymm4, 31H
vmovups ymmword ptr [rbx+80H], ymm9
vperm2f128 ymm14, ymm10, ymm14, 31H
vperm2f128 ymm15, ymm6, ymm15, 31H
vmovups ymmword ptr [rbx+0A0H], ymm11
vmovups ymmword ptr [rbx+0C0H], ymm14
vmovups ymmword ptr [rbx+0E0H], ymm15
vmovdqa ymm0, ymmword ptr [rsp+2A0H]
vpaddd ymm1, ymm0, ymmword ptr [rsp+220H]
vmovdqa ymmword ptr [rsp+220H], ymm1
vpxor ymm0, ymm0, ymmword ptr [CMP_MSB_MASK]
vpxor ymm2, ymm1, ymmword ptr [CMP_MSB_MASK]
vpcmpgtd ymm2, ymm0, ymm2
vmovdqa ymm0, ymmword ptr [rsp+240H]
vpsubd ymm2, ymm0, ymm2
vmovdqa ymmword ptr [rsp+240H], ymm2
add rdi, 64
add rbx, 256
mov qword ptr [rbp+90H], rbx
sub rsi, 8
cmp rsi, 8
jnc outerloop8
test rsi, rsi
jnz final7blocks
unwind:
vzeroupper
vmovdqa xmm6, xmmword ptr [rsp+2D0H]
vmovdqa xmm7, xmmword ptr [rsp+2E0H]
vmovdqa xmm8, xmmword ptr [rsp+2F0H]
vmovdqa xmm9, xmmword ptr [rsp+300H]
vmovdqa xmm10, xmmword ptr [rsp+310H]
vmovdqa xmm11, xmmword ptr [rsp+320H]
vmovdqa xmm12, xmmword ptr [rsp+330H]
vmovdqa xmm13, xmmword ptr [rsp+340H]
vmovdqa xmm14, xmmword ptr [rsp+350H]
vmovdqa xmm15, xmmword ptr [rsp+360H]
mov rsp, rbp
pop rbp
pop rbx
pop rdi
pop rsi
pop r12
pop r13
pop r14
pop r15
ret
ALIGN 16
final7blocks:
mov rbx, qword ptr [rbp+90H]
mov r15, qword ptr [rsp+2C0H]
movzx r13d, byte ptr [rbp+78H]
movzx r12d, byte ptr [rbp+88H]
test rsi, 4H
je final3blocks
vbroadcasti128 ymm0, xmmword ptr [rcx]
vbroadcasti128 ymm1, xmmword ptr [rcx+10H]
vmovdqa ymm8, ymm0
vmovdqa ymm9, ymm1
vbroadcasti128 ymm12, xmmword ptr [rsp+220H]
vbroadcasti128 ymm13, xmmword ptr [rsp+240H]
vpunpckldq ymm14, ymm12, ymm13
vpunpckhdq ymm15, ymm12, ymm13
vpermq ymm14, ymm14, 50H
vpermq ymm15, ymm15, 50H
vbroadcasti128 ymm12, xmmword ptr [BLAKE3_BLOCK_LEN]
vpblendd ymm14, ymm14, ymm12, 44H
vpblendd ymm15, ymm15, ymm12, 44H
vmovdqa ymmword ptr [rsp], ymm14
vmovdqa ymmword ptr [rsp+20H], ymm15
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
ALIGN 16
innerloop4:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
mov dword ptr [rsp+200H], eax
vmovups ymm2, ymmword ptr [r8+rdx-40H]
vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-40H], 01H
vmovups ymm3, ymmword ptr [r8+rdx-30H]
vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-30H], 01H
vshufps ymm4, ymm2, ymm3, 136
vshufps ymm5, ymm2, ymm3, 221
vmovups ymm2, ymmword ptr [r8+rdx-20H]
vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-20H], 01H
vmovups ymm3, ymmword ptr [r8+rdx-10H]
vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-10H], 01H
vshufps ymm6, ymm2, ymm3, 136
vshufps ymm7, ymm2, ymm3, 221
vpshufd ymm6, ymm6, 93H
vpshufd ymm7, ymm7, 93H
vmovups ymm10, ymmword ptr [r10+rdx-40H]
vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-40H], 01H
vmovups ymm11, ymmword ptr [r10+rdx-30H]
vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-30H], 01H
vshufps ymm12, ymm10, ymm11, 136
vshufps ymm13, ymm10, ymm11, 221
vmovups ymm10, ymmword ptr [r10+rdx-20H]
vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-20H], 01H
vmovups ymm11, ymmword ptr [r10+rdx-10H]
vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-10H], 01H
vshufps ymm14, ymm10, ymm11, 136
vshufps ymm15, ymm10, ymm11, 221
vpshufd ymm14, ymm14, 93H
vpshufd ymm15, ymm15, 93H
vpbroadcastd ymm2, dword ptr [rsp+200H]
vmovdqa ymm3, ymmword ptr [rsp]
vmovdqa ymm11, ymmword ptr [rsp+20H]
vpblendd ymm3, ymm3, ymm2, 88H
vpblendd ymm11, ymm11, ymm2, 88H
vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV]
vmovdqa ymm10, ymm2
mov al, 7
roundloop4:
vpaddd ymm0, ymm0, ymm4
vpaddd ymm8, ymm8, ymm12
vmovdqa ymmword ptr [rsp+40H], ymm4
nop
vmovdqa ymmword ptr [rsp+60H], ymm12
nop
vpaddd ymm0, ymm0, ymm1
vpaddd ymm8, ymm8, ymm9
vpxor ymm3, ymm3, ymm0
vpxor ymm11, ymm11, ymm8
vbroadcasti128 ymm4, xmmword ptr [ROT16]
vpshufb ymm3, ymm3, ymm4
vpshufb ymm11, ymm11, ymm4
vpaddd ymm2, ymm2, ymm3
vpaddd ymm10, ymm10, ymm11
vpxor ymm1, ymm1, ymm2
vpxor ymm9, ymm9, ymm10
vpsrld ymm4, ymm1, 12
vpslld ymm1, ymm1, 20
vpor ymm1, ymm1, ymm4
vpsrld ymm4, ymm9, 12
vpslld ymm9, ymm9, 20
vpor ymm9, ymm9, ymm4
vpaddd ymm0, ymm0, ymm5
vpaddd ymm8, ymm8, ymm13
vpaddd ymm0, ymm0, ymm1
vpaddd ymm8, ymm8, ymm9
vmovdqa ymmword ptr [rsp+80H], ymm5
vmovdqa ymmword ptr [rsp+0A0H], ymm13
vpxor ymm3, ymm3, ymm0
vpxor ymm11, ymm11, ymm8
vbroadcasti128 ymm4, xmmword ptr [ROT8]
vpshufb ymm3, ymm3, ymm4
vpshufb ymm11, ymm11, ymm4
vpaddd ymm2, ymm2, ymm3
vpaddd ymm10, ymm10, ymm11
vpxor ymm1, ymm1, ymm2
vpxor ymm9, ymm9, ymm10
vpsrld ymm4, ymm1, 7
vpslld ymm1, ymm1, 25
vpor ymm1, ymm1, ymm4
vpsrld ymm4, ymm9, 7
vpslld ymm9, ymm9, 25
vpor ymm9, ymm9, ymm4
vpshufd ymm0, ymm0, 93H
vpshufd ymm8, ymm8, 93H
vpshufd ymm3, ymm3, 4EH
vpshufd ymm11, ymm11, 4EH
vpshufd ymm2, ymm2, 39H
vpshufd ymm10, ymm10, 39H
vpaddd ymm0, ymm0, ymm6
vpaddd ymm8, ymm8, ymm14
vpaddd ymm0, ymm0, ymm1
vpaddd ymm8, ymm8, ymm9
vpxor ymm3, ymm3, ymm0
vpxor ymm11, ymm11, ymm8
vbroadcasti128 ymm4, xmmword ptr [ROT16]
vpshufb ymm3, ymm3, ymm4
vpshufb ymm11, ymm11, ymm4
vpaddd ymm2, ymm2, ymm3
vpaddd ymm10, ymm10, ymm11
vpxor ymm1, ymm1, ymm2
vpxor ymm9, ymm9, ymm10
vpsrld ymm4, ymm1, 12
vpslld ymm1, ymm1, 20
vpor ymm1, ymm1, ymm4
vpsrld ymm4, ymm9, 12
vpslld ymm9, ymm9, 20
vpor ymm9, ymm9, ymm4
vpaddd ymm0, ymm0, ymm7
vpaddd ymm8, ymm8, ymm15
vpaddd ymm0, ymm0, ymm1
vpaddd ymm8, ymm8, ymm9
vpxor ymm3, ymm3, ymm0
vpxor ymm11, ymm11, ymm8
vbroadcasti128 ymm4, xmmword ptr [ROT8]
vpshufb ymm3, ymm3, ymm4
vpshufb ymm11, ymm11, ymm4
vpaddd ymm2, ymm2, ymm3
vpaddd ymm10, ymm10, ymm11
vpxor ymm1, ymm1, ymm2
vpxor ymm9, ymm9, ymm10
vpsrld ymm4, ymm1, 7
vpslld ymm1, ymm1, 25
vpor ymm1, ymm1, ymm4
vpsrld ymm4, ymm9, 7
vpslld ymm9, ymm9, 25
vpor ymm9, ymm9, ymm4
vpshufd ymm0, ymm0, 39H
vpshufd ymm8, ymm8, 39H
vpshufd ymm3, ymm3, 4EH
vpshufd ymm11, ymm11, 4EH
vpshufd ymm2, ymm2, 93H
vpshufd ymm10, ymm10, 93H
dec al
je endroundloop4
vmovdqa ymm4, ymmword ptr [rsp+40H]
vmovdqa ymm5, ymmword ptr [rsp+80H]
vshufps ymm12, ymm4, ymm5, 214
vpshufd ymm13, ymm4, 0FH
vpshufd ymm4, ymm12, 39H
vshufps ymm12, ymm6, ymm7, 250
vpblendd ymm13, ymm13, ymm12, 0AAH
vpunpcklqdq ymm12, ymm7, ymm5
vpblendd ymm12, ymm12, ymm6, 88H
vpshufd ymm12, ymm12, 78H
vpunpckhdq ymm5, ymm5, ymm7
vpunpckldq ymm6, ymm6, ymm5
vpshufd ymm7, ymm6, 1EH
vmovdqa ymmword ptr [rsp+40H], ymm13
vmovdqa ymmword ptr [rsp+80H], ymm12
vmovdqa ymm12, ymmword ptr [rsp+60H]
vmovdqa ymm13, ymmword ptr [rsp+0A0H]
vshufps ymm5, ymm12, ymm13, 214
vpshufd ymm6, ymm12, 0FH
vpshufd ymm12, ymm5, 39H
vshufps ymm5, ymm14, ymm15, 250
vpblendd ymm6, ymm6, ymm5, 0AAH
vpunpcklqdq ymm5, ymm15, ymm13
vpblendd ymm5, ymm5, ymm14, 88H
vpshufd ymm5, ymm5, 78H
vpunpckhdq ymm13, ymm13, ymm15
vpunpckldq ymm14, ymm14, ymm13
vpshufd ymm15, ymm14, 1EH
vmovdqa ymm13, ymm6
vmovdqa ymm14, ymm5
vmovdqa ymm5, ymmword ptr [rsp+40H]
vmovdqa ymm6, ymmword ptr [rsp+80H]
jmp roundloop4
endroundloop4:
vpxor ymm0, ymm0, ymm2
vpxor ymm1, ymm1, ymm3
vpxor ymm8, ymm8, ymm10
vpxor ymm9, ymm9, ymm11
mov eax, r13d
cmp rdx, r15
jne innerloop4
vmovdqu xmmword ptr [rbx], xmm0
vmovdqu xmmword ptr [rbx+10H], xmm1
vextracti128 xmmword ptr [rbx+20H], ymm0, 01H
vextracti128 xmmword ptr [rbx+30H], ymm1, 01H
vmovdqu xmmword ptr [rbx+40H], xmm8
vmovdqu xmmword ptr [rbx+50H], xmm9
vextracti128 xmmword ptr [rbx+60H], ymm8, 01H
vextracti128 xmmword ptr [rbx+70H], ymm9, 01H
vmovaps xmm8, xmmword ptr [rsp+260H]
vmovaps xmm0, xmmword ptr [rsp+220H]
vmovaps xmm1, xmmword ptr [rsp+230H]
vmovaps xmm2, xmmword ptr [rsp+240H]
vmovaps xmm3, xmmword ptr [rsp+250H]
vblendvps xmm0, xmm0, xmm1, xmm8
vblendvps xmm2, xmm2, xmm3, xmm8
vmovaps xmmword ptr [rsp+220H], xmm0
vmovaps xmmword ptr [rsp+240H], xmm2
add rbx, 128
add rdi, 32
sub rsi, 4
final3blocks:
test rsi, 2H
je final1blocks
vbroadcasti128 ymm0, xmmword ptr [rcx]
vbroadcasti128 ymm1, xmmword ptr [rcx+10H]
vmovd xmm13, dword ptr [rsp+220H]
vpinsrd xmm13, xmm13, dword ptr [rsp+240H], 1
vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2
vmovd xmm14, dword ptr [rsp+224H]
vpinsrd xmm14, xmm14, dword ptr [rsp+244H], 1
vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2
vinserti128 ymm13, ymm13, xmm14, 01H
vbroadcasti128 ymm14, xmmword ptr [ROT16]
vbroadcasti128 ymm15, xmmword ptr [ROT8]
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
ALIGN 16
innerloop2:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
mov dword ptr [rsp+200H], eax
vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV]
vpbroadcastd ymm8, dword ptr [rsp+200H]
vpblendd ymm3, ymm13, ymm8, 88H
vmovups ymm8, ymmword ptr [r8+rdx-40H]
vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-40H], 01H
vmovups ymm9, ymmword ptr [r8+rdx-30H]
vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-30H], 01H
vshufps ymm4, ymm8, ymm9, 136
vshufps ymm5, ymm8, ymm9, 221
vmovups ymm8, ymmword ptr [r8+rdx-20H]
vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-20H], 01H
vmovups ymm9, ymmword ptr [r8+rdx-10H]
vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-10H], 01H
vshufps ymm6, ymm8, ymm9, 136
vshufps ymm7, ymm8, ymm9, 221
vpshufd ymm6, ymm6, 93H
vpshufd ymm7, ymm7, 93H
mov al, 7
roundloop2:
vpaddd ymm0, ymm0, ymm4
vpaddd ymm0, ymm0, ymm1
vpxor ymm3, ymm3, ymm0
vpshufb ymm3, ymm3, ymm14
vpaddd ymm2, ymm2, ymm3
vpxor ymm1, ymm1, ymm2
vpsrld ymm8, ymm1, 12
vpslld ymm1, ymm1, 20
vpor ymm1, ymm1, ymm8
vpaddd ymm0, ymm0, ymm5
vpaddd ymm0, ymm0, ymm1
vpxor ymm3, ymm3, ymm0
vpshufb ymm3, ymm3, ymm15
vpaddd ymm2, ymm2, ymm3
vpxor ymm1, ymm1, ymm2
vpsrld ymm8, ymm1, 7
vpslld ymm1, ymm1, 25
vpor ymm1, ymm1, ymm8
vpshufd ymm0, ymm0, 93H
vpshufd ymm3, ymm3, 4EH
vpshufd ymm2, ymm2, 39H
vpaddd ymm0, ymm0, ymm6
vpaddd ymm0, ymm0, ymm1
vpxor ymm3, ymm3, ymm0
vpshufb ymm3, ymm3, ymm14
vpaddd ymm2, ymm2, ymm3
vpxor ymm1, ymm1, ymm2
vpsrld ymm8, ymm1, 12
vpslld ymm1, ymm1, 20
vpor ymm1, ymm1, ymm8
vpaddd ymm0, ymm0, ymm7
vpaddd ymm0, ymm0, ymm1
vpxor ymm3, ymm3, ymm0
vpshufb ymm3, ymm3, ymm15
vpaddd ymm2, ymm2, ymm3
vpxor ymm1, ymm1, ymm2
vpsrld ymm8, ymm1, 7
vpslld ymm1, ymm1, 25
vpor ymm1, ymm1, ymm8
vpshufd ymm0, ymm0, 39H
vpshufd ymm3, ymm3, 4EH
vpshufd ymm2, ymm2, 93H
dec al
jz endroundloop2
vshufps ymm8, ymm4, ymm5, 214
vpshufd ymm9, ymm4, 0FH
vpshufd ymm4, ymm8, 39H
vshufps ymm8, ymm6, ymm7, 250
vpblendd ymm9, ymm9, ymm8, 0AAH
vpunpcklqdq ymm8, ymm7, ymm5
vpblendd ymm8, ymm8, ymm6, 88H
vpshufd ymm8, ymm8, 78H
vpunpckhdq ymm5, ymm5, ymm7
vpunpckldq ymm6, ymm6, ymm5
vpshufd ymm7, ymm6, 1EH
vmovdqa ymm5, ymm9
vmovdqa ymm6, ymm8
jmp roundloop2
endroundloop2:
vpxor ymm0, ymm0, ymm2
vpxor ymm1, ymm1, ymm3
mov eax, r13d
cmp rdx, r15
jne innerloop2
vmovdqu xmmword ptr [rbx], xmm0
vmovdqu xmmword ptr [rbx+10H], xmm1
vextracti128 xmmword ptr [rbx+20H], ymm0, 01H
vextracti128 xmmword ptr [rbx+30H], ymm1, 01H
vmovaps ymm8, ymmword ptr [rsp+260H]
vmovaps ymm0, ymmword ptr [rsp+220H]
vmovups ymm1, ymmword ptr [rsp+228H]
vmovaps ymm2, ymmword ptr [rsp+240H]
vmovups ymm3, ymmword ptr [rsp+248H]
vblendvps ymm0, ymm0, ymm1, ymm8
vblendvps ymm2, ymm2, ymm3, ymm8
vmovaps ymmword ptr [rsp+220H], ymm0
vmovaps ymmword ptr [rsp+240H], ymm2
add rbx, 64
add rdi, 16
sub rsi, 2
final1blocks:
test rsi, 1H
je unwind
vmovdqu xmm0, xmmword ptr [rcx]
vmovdqu xmm1, xmmword ptr [rcx+10H]
vmovd xmm3, dword ptr [rsp+220H]
vpinsrd xmm3, xmm3, dword ptr [rsp+240H], 1
vpinsrd xmm13, xmm3, dword ptr [BLAKE3_BLOCK_LEN], 2
vmovdqa xmm14, xmmword ptr [ROT16]
vmovdqa xmm15, xmmword ptr [ROT8]
mov r8, qword ptr [rdi]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
ALIGN 16
innerloop1:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
vmovdqa xmm2, xmmword ptr [BLAKE3_IV]
vmovdqa xmm3, xmm13
vpinsrd xmm3, xmm3, eax, 3
vmovups xmm8, xmmword ptr [r8+rdx-40H]
vmovups xmm9, xmmword ptr [r8+rdx-30H]
vshufps xmm4, xmm8, xmm9, 136
vshufps xmm5, xmm8, xmm9, 221
vmovups xmm8, xmmword ptr [r8+rdx-20H]
vmovups xmm9, xmmword ptr [r8+rdx-10H]
vshufps xmm6, xmm8, xmm9, 136
vshufps xmm7, xmm8, xmm9, 221
vpshufd xmm6, xmm6, 93H
vpshufd xmm7, xmm7, 93H
mov al, 7
roundloop1:
vpaddd xmm0, xmm0, xmm4
vpaddd xmm0, xmm0, xmm1
vpxor xmm3, xmm3, xmm0
vpshufb xmm3, xmm3, xmm14
vpaddd xmm2, xmm2, xmm3
vpxor xmm1, xmm1, xmm2
vpsrld xmm8, xmm1, 12
vpslld xmm1, xmm1, 20
vpor xmm1, xmm1, xmm8
vpaddd xmm0, xmm0, xmm5
vpaddd xmm0, xmm0, xmm1
vpxor xmm3, xmm3, xmm0
vpshufb xmm3, xmm3, xmm15
vpaddd xmm2, xmm2, xmm3
vpxor xmm1, xmm1, xmm2
vpsrld xmm8, xmm1, 7
vpslld xmm1, xmm1, 25
vpor xmm1, xmm1, xmm8
vpshufd xmm0, xmm0, 93H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 39H
vpaddd xmm0, xmm0, xmm6
vpaddd xmm0, xmm0, xmm1
vpxor xmm3, xmm3, xmm0
vpshufb xmm3, xmm3, xmm14
vpaddd xmm2, xmm2, xmm3
vpxor xmm1, xmm1, xmm2
vpsrld xmm8, xmm1, 12
vpslld xmm1, xmm1, 20
vpor xmm1, xmm1, xmm8
vpaddd xmm0, xmm0, xmm7
vpaddd xmm0, xmm0, xmm1
vpxor xmm3, xmm3, xmm0
vpshufb xmm3, xmm3, xmm15
vpaddd xmm2, xmm2, xmm3
vpxor xmm1, xmm1, xmm2
vpsrld xmm8, xmm1, 7
vpslld xmm1, xmm1, 25
vpor xmm1, xmm1, xmm8
vpshufd xmm0, xmm0, 39H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 93H
dec al
jz endroundloop1
vshufps xmm8, xmm4, xmm5, 214
vpshufd xmm9, xmm4, 0FH
vpshufd xmm4, xmm8, 39H
vshufps xmm8, xmm6, xmm7, 250
vpblendd xmm9, xmm9, xmm8, 0AAH
vpunpcklqdq xmm8, xmm7, xmm5
vpblendd xmm8, xmm8, xmm6, 88H
vpshufd xmm8, xmm8, 78H
vpunpckhdq xmm5, xmm5, xmm7
vpunpckldq xmm6, xmm6, xmm5
vpshufd xmm7, xmm6, 1EH
vmovdqa xmm5, xmm9
vmovdqa xmm6, xmm8
jmp roundloop1
endroundloop1:
vpxor xmm0, xmm0, xmm2
vpxor xmm1, xmm1, xmm3
mov eax, r13d
cmp rdx, r15
jne innerloop1
vmovdqu xmmword ptr [rbx], xmm0
vmovdqu xmmword ptr [rbx+10H], xmm1
jmp unwind
_blake3_hash_many_avx2 ENDP
blake3_hash_many_avx2 ENDP
_TEXT ENDS
_RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST'
ALIGN 64
ADD0:
dd 0, 1, 2, 3, 4, 5, 6, 7
ADD1:
dd 8 dup (8)
BLAKE3_IV_0:
dd 8 dup (6A09E667H)
BLAKE3_IV_1:
dd 8 dup (0BB67AE85H)
BLAKE3_IV_2:
dd 8 dup (3C6EF372H)
BLAKE3_IV_3:
dd 8 dup (0A54FF53AH)
BLAKE3_BLOCK_LEN:
dd 8 dup (64)
ROT16:
db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13
ROT8:
db 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12
CMP_MSB_MASK:
dd 8 dup(80000000H)
BLAKE3_IV:
dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH
_RDATA ENDS
END
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_avx512_x86-64_windows_msvc.asm
================================================
public _blake3_hash_many_avx512
public blake3_hash_many_avx512
public blake3_compress_in_place_avx512
public _blake3_compress_in_place_avx512
public blake3_compress_xof_avx512
public _blake3_compress_xof_avx512
_TEXT SEGMENT ALIGN(16) 'CODE'
ALIGN 16
blake3_hash_many_avx512 PROC
_blake3_hash_many_avx512 PROC
push r15
push r14
push r13
push r12
push rdi
push rsi
push rbx
push rbp
mov rbp, rsp
sub rsp, 304
and rsp, 0FFFFFFFFFFFFFFC0H
vmovdqa xmmword ptr [rsp+90H], xmm6
vmovdqa xmmword ptr [rsp+0A0H], xmm7
vmovdqa xmmword ptr [rsp+0B0H], xmm8
vmovdqa xmmword ptr [rsp+0C0H], xmm9
vmovdqa xmmword ptr [rsp+0D0H], xmm10
vmovdqa xmmword ptr [rsp+0E0H], xmm11
vmovdqa xmmword ptr [rsp+0F0H], xmm12
vmovdqa xmmword ptr [rsp+100H], xmm13
vmovdqa xmmword ptr [rsp+110H], xmm14
vmovdqa xmmword ptr [rsp+120H], xmm15
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, qword ptr [rbp+68H]
movzx r9, byte ptr [rbp+70H]
neg r9
kmovw k1, r9d
vmovd xmm0, r8d
vpbroadcastd ymm0, xmm0
shr r8, 32
vmovd xmm1, r8d
vpbroadcastd ymm1, xmm1
vmovdqa ymm4, ymm1
vmovdqa ymm5, ymm1
vpaddd ymm2, ymm0, ymmword ptr [ADD0]
vpaddd ymm3, ymm0, ymmword ptr [ADD0+32]
vpcmpud k2, ymm2, ymm0, 1
vpcmpud k3, ymm3, ymm0, 1
; XXX: ml64.exe does not currently understand the syntax. We use a workaround.
vpbroadcastd ymm6, dword ptr [ADD1]
vpaddd ymm4 {k2}, ymm4, ymm6
vpaddd ymm5 {k3}, ymm5, ymm6
; vpaddd ymm4 {k2}, ymm4, dword ptr [ADD1] {1to8}
; vpaddd ymm5 {k3}, ymm5, dword ptr [ADD1] {1to8}
knotw k2, k1
vmovdqa32 ymm2 {k2}, ymm0
vmovdqa32 ymm3 {k2}, ymm0
vmovdqa32 ymm4 {k2}, ymm1
vmovdqa32 ymm5 {k2}, ymm1
vmovdqa ymmword ptr [rsp], ymm2
vmovdqa ymmword ptr [rsp+20H], ymm3
vmovdqa ymmword ptr [rsp+40H], ymm4
vmovdqa ymmword ptr [rsp+60H], ymm5
shl rdx, 6
mov qword ptr [rsp+80H], rdx
cmp rsi, 16
jc final15blocks
outerloop16:
vpbroadcastd zmm0, dword ptr [rcx]
vpbroadcastd zmm1, dword ptr [rcx+1H*4H]
vpbroadcastd zmm2, dword ptr [rcx+2H*4H]
vpbroadcastd zmm3, dword ptr [rcx+3H*4H]
vpbroadcastd zmm4, dword ptr [rcx+4H*4H]
vpbroadcastd zmm5, dword ptr [rcx+5H*4H]
vpbroadcastd zmm6, dword ptr [rcx+6H*4H]
vpbroadcastd zmm7, dword ptr [rcx+7H*4H]
movzx eax, byte ptr [rbp+78H]
movzx ebx, byte ptr [rbp+80H]
or eax, ebx
xor edx, edx
ALIGN 16
innerloop16:
movzx ebx, byte ptr [rbp+88H]
or ebx, eax
add rdx, 64
cmp rdx, qword ptr [rsp+80H]
cmove eax, ebx
mov dword ptr [rsp+88H], eax
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
mov r12, qword ptr [rdi+40H]
mov r13, qword ptr [rdi+48H]
mov r14, qword ptr [rdi+50H]
mov r15, qword ptr [rdi+58H]
vmovdqu32 ymm16, ymmword ptr [rdx+r8-2H*20H]
vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-2H*20H], 01H
vmovdqu32 ymm17, ymmword ptr [rdx+r9-2H*20H]
vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-2H*20H], 01H
vpunpcklqdq zmm8, zmm16, zmm17
vpunpckhqdq zmm9, zmm16, zmm17
vmovdqu32 ymm18, ymmword ptr [rdx+r10-2H*20H]
vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-2H*20H], 01H
vmovdqu32 ymm19, ymmword ptr [rdx+r11-2H*20H]
vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-2H*20H], 01H
vpunpcklqdq zmm10, zmm18, zmm19
vpunpckhqdq zmm11, zmm18, zmm19
mov r8, qword ptr [rdi+20H]
mov r9, qword ptr [rdi+28H]
mov r10, qword ptr [rdi+30H]
mov r11, qword ptr [rdi+38H]
mov r12, qword ptr [rdi+60H]
mov r13, qword ptr [rdi+68H]
mov r14, qword ptr [rdi+70H]
mov r15, qword ptr [rdi+78H]
vmovdqu32 ymm16, ymmword ptr [rdx+r8-2H*20H]
vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-2H*20H], 01H
vmovdqu32 ymm17, ymmword ptr [rdx+r9-2H*20H]
vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-2H*20H], 01H
vpunpcklqdq zmm12, zmm16, zmm17
vpunpckhqdq zmm13, zmm16, zmm17
vmovdqu32 ymm18, ymmword ptr [rdx+r10-2H*20H]
vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-2H*20H], 01H
vmovdqu32 ymm19, ymmword ptr [rdx+r11-2H*20H]
vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-2H*20H], 01H
vpunpcklqdq zmm14, zmm18, zmm19
vpunpckhqdq zmm15, zmm18, zmm19
vmovdqa32 zmm27, zmmword ptr [INDEX0]
vmovdqa32 zmm31, zmmword ptr [INDEX1]
vshufps zmm16, zmm8, zmm10, 136
vshufps zmm17, zmm12, zmm14, 136
vmovdqa32 zmm20, zmm16
vpermt2d zmm16, zmm27, zmm17
vpermt2d zmm20, zmm31, zmm17
vshufps zmm17, zmm8, zmm10, 221
vshufps zmm30, zmm12, zmm14, 221
vmovdqa32 zmm21, zmm17
vpermt2d zmm17, zmm27, zmm30
vpermt2d zmm21, zmm31, zmm30
vshufps zmm18, zmm9, zmm11, 136
vshufps zmm8, zmm13, zmm15, 136
vmovdqa32 zmm22, zmm18
vpermt2d zmm18, zmm27, zmm8
vpermt2d zmm22, zmm31, zmm8
vshufps zmm19, zmm9, zmm11, 221
vshufps zmm8, zmm13, zmm15, 221
vmovdqa32 zmm23, zmm19
vpermt2d zmm19, zmm27, zmm8
vpermt2d zmm23, zmm31, zmm8
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
mov r12, qword ptr [rdi+40H]
mov r13, qword ptr [rdi+48H]
mov r14, qword ptr [rdi+50H]
mov r15, qword ptr [rdi+58H]
vmovdqu32 ymm24, ymmword ptr [r8+rdx-1H*20H]
vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-1H*20H], 01H
vmovdqu32 ymm25, ymmword ptr [r9+rdx-1H*20H]
vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-1H*20H], 01H
vpunpcklqdq zmm8, zmm24, zmm25
vpunpckhqdq zmm9, zmm24, zmm25
vmovdqu32 ymm24, ymmword ptr [r10+rdx-1H*20H]
vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-1H*20H], 01H
vmovdqu32 ymm25, ymmword ptr [r11+rdx-1H*20H]
vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-1H*20H], 01H
vpunpcklqdq zmm10, zmm24, zmm25
vpunpckhqdq zmm11, zmm24, zmm25
prefetcht0 byte ptr [r8+rdx+80H]
prefetcht0 byte ptr [r12+rdx+80H]
prefetcht0 byte ptr [r9+rdx+80H]
prefetcht0 byte ptr [r13+rdx+80H]
prefetcht0 byte ptr [r10+rdx+80H]
prefetcht0 byte ptr [r14+rdx+80H]
prefetcht0 byte ptr [r11+rdx+80H]
prefetcht0 byte ptr [r15+rdx+80H]
mov r8, qword ptr [rdi+20H]
mov r9, qword ptr [rdi+28H]
mov r10, qword ptr [rdi+30H]
mov r11, qword ptr [rdi+38H]
mov r12, qword ptr [rdi+60H]
mov r13, qword ptr [rdi+68H]
mov r14, qword ptr [rdi+70H]
mov r15, qword ptr [rdi+78H]
vmovdqu32 ymm24, ymmword ptr [r8+rdx-1H*20H]
vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-1H*20H], 01H
vmovdqu32 ymm25, ymmword ptr [r9+rdx-1H*20H]
vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-1H*20H], 01H
vpunpcklqdq zmm12, zmm24, zmm25
vpunpckhqdq zmm13, zmm24, zmm25
vmovdqu32 ymm24, ymmword ptr [r10+rdx-1H*20H]
vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-1H*20H], 01H
vmovdqu32 ymm25, ymmword ptr [r11+rdx-1H*20H]
vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-1H*20H], 01H
vpunpcklqdq zmm14, zmm24, zmm25
vpunpckhqdq zmm15, zmm24, zmm25
prefetcht0 byte ptr [r8+rdx+80H]
prefetcht0 byte ptr [r12+rdx+80H]
prefetcht0 byte ptr [r9+rdx+80H]
prefetcht0 byte ptr [r13+rdx+80H]
prefetcht0 byte ptr [r10+rdx+80H]
prefetcht0 byte ptr [r14+rdx+80H]
prefetcht0 byte ptr [r11+rdx+80H]
prefetcht0 byte ptr [r15+rdx+80H]
vshufps zmm24, zmm8, zmm10, 136
vshufps zmm30, zmm12, zmm14, 136
vmovdqa32 zmm28, zmm24
vpermt2d zmm24, zmm27, zmm30
vpermt2d zmm28, zmm31, zmm30
vshufps zmm25, zmm8, zmm10, 221
vshufps zmm30, zmm12, zmm14, 221
vmovdqa32 zmm29, zmm25
vpermt2d zmm25, zmm27, zmm30
vpermt2d zmm29, zmm31, zmm30
vshufps zmm26, zmm9, zmm11, 136
vshufps zmm8, zmm13, zmm15, 136
vmovdqa32 zmm30, zmm26
vpermt2d zmm26, zmm27, zmm8
vpermt2d zmm30, zmm31, zmm8
vshufps zmm8, zmm9, zmm11, 221
vshufps zmm10, zmm13, zmm15, 221
vpermi2d zmm27, zmm8, zmm10
vpermi2d zmm31, zmm8, zmm10
vpbroadcastd zmm8, dword ptr [BLAKE3_IV_0]
vpbroadcastd zmm9, dword ptr [BLAKE3_IV_1]
vpbroadcastd zmm10, dword ptr [BLAKE3_IV_2]
vpbroadcastd zmm11, dword ptr [BLAKE3_IV_3]
vmovdqa32 zmm12, zmmword ptr [rsp]
vmovdqa32 zmm13, zmmword ptr [rsp+1H*40H]
vpbroadcastd zmm14, dword ptr [BLAKE3_BLOCK_LEN]
vpbroadcastd zmm15, dword ptr [rsp+22H*4H]
vpaddd zmm0, zmm0, zmm16
vpaddd zmm1, zmm1, zmm18
vpaddd zmm2, zmm2, zmm20
vpaddd zmm3, zmm3, zmm22
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vprord zmm15, zmm15, 16
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 12
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vpaddd zmm0, zmm0, zmm17
vpaddd zmm1, zmm1, zmm19
vpaddd zmm2, zmm2, zmm21
vpaddd zmm3, zmm3, zmm23
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vprord zmm15, zmm15, 8
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 7
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vpaddd zmm0, zmm0, zmm24
vpaddd zmm1, zmm1, zmm26
vpaddd zmm2, zmm2, zmm28
vpaddd zmm3, zmm3, zmm30
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 16
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vprord zmm4, zmm4, 12
vpaddd zmm0, zmm0, zmm25
vpaddd zmm1, zmm1, zmm27
vpaddd zmm2, zmm2, zmm29
vpaddd zmm3, zmm3, zmm31
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 8
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vprord zmm4, zmm4, 7
vpaddd zmm0, zmm0, zmm18
vpaddd zmm1, zmm1, zmm19
vpaddd zmm2, zmm2, zmm23
vpaddd zmm3, zmm3, zmm20
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vprord zmm15, zmm15, 16
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 12
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vpaddd zmm0, zmm0, zmm22
vpaddd zmm1, zmm1, zmm26
vpaddd zmm2, zmm2, zmm16
vpaddd zmm3, zmm3, zmm29
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vprord zmm15, zmm15, 8
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 7
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vpaddd zmm0, zmm0, zmm17
vpaddd zmm1, zmm1, zmm28
vpaddd zmm2, zmm2, zmm25
vpaddd zmm3, zmm3, zmm31
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 16
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vprord zmm4, zmm4, 12
vpaddd zmm0, zmm0, zmm27
vpaddd zmm1, zmm1, zmm21
vpaddd zmm2, zmm2, zmm30
vpaddd zmm3, zmm3, zmm24
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 8
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vprord zmm4, zmm4, 7
vpaddd zmm0, zmm0, zmm19
vpaddd zmm1, zmm1, zmm26
vpaddd zmm2, zmm2, zmm29
vpaddd zmm3, zmm3, zmm23
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vprord zmm15, zmm15, 16
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 12
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vpaddd zmm0, zmm0, zmm20
vpaddd zmm1, zmm1, zmm28
vpaddd zmm2, zmm2, zmm18
vpaddd zmm3, zmm3, zmm30
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vprord zmm15, zmm15, 8
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 7
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vpaddd zmm0, zmm0, zmm22
vpaddd zmm1, zmm1, zmm25
vpaddd zmm2, zmm2, zmm27
vpaddd zmm3, zmm3, zmm24
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 16
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vprord zmm4, zmm4, 12
vpaddd zmm0, zmm0, zmm21
vpaddd zmm1, zmm1, zmm16
vpaddd zmm2, zmm2, zmm31
vpaddd zmm3, zmm3, zmm17
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 8
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vprord zmm4, zmm4, 7
vpaddd zmm0, zmm0, zmm26
vpaddd zmm1, zmm1, zmm28
vpaddd zmm2, zmm2, zmm30
vpaddd zmm3, zmm3, zmm29
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vprord zmm15, zmm15, 16
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 12
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vpaddd zmm0, zmm0, zmm23
vpaddd zmm1, zmm1, zmm25
vpaddd zmm2, zmm2, zmm19
vpaddd zmm3, zmm3, zmm31
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vprord zmm15, zmm15, 8
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 7
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vpaddd zmm0, zmm0, zmm20
vpaddd zmm1, zmm1, zmm27
vpaddd zmm2, zmm2, zmm21
vpaddd zmm3, zmm3, zmm17
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 16
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vprord zmm4, zmm4, 12
vpaddd zmm0, zmm0, zmm16
vpaddd zmm1, zmm1, zmm18
vpaddd zmm2, zmm2, zmm24
vpaddd zmm3, zmm3, zmm22
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 8
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vprord zmm4, zmm4, 7
vpaddd zmm0, zmm0, zmm28
vpaddd zmm1, zmm1, zmm25
vpaddd zmm2, zmm2, zmm31
vpaddd zmm3, zmm3, zmm30
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vprord zmm15, zmm15, 16
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 12
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vpaddd zmm0, zmm0, zmm29
vpaddd zmm1, zmm1, zmm27
vpaddd zmm2, zmm2, zmm26
vpaddd zmm3, zmm3, zmm24
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vprord zmm15, zmm15, 8
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 7
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vpaddd zmm0, zmm0, zmm23
vpaddd zmm1, zmm1, zmm21
vpaddd zmm2, zmm2, zmm16
vpaddd zmm3, zmm3, zmm22
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 16
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vprord zmm4, zmm4, 12
vpaddd zmm0, zmm0, zmm18
vpaddd zmm1, zmm1, zmm19
vpaddd zmm2, zmm2, zmm17
vpaddd zmm3, zmm3, zmm20
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 8
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vprord zmm4, zmm4, 7
vpaddd zmm0, zmm0, zmm25
vpaddd zmm1, zmm1, zmm27
vpaddd zmm2, zmm2, zmm24
vpaddd zmm3, zmm3, zmm31
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vprord zmm15, zmm15, 16
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 12
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vpaddd zmm0, zmm0, zmm30
vpaddd zmm1, zmm1, zmm21
vpaddd zmm2, zmm2, zmm28
vpaddd zmm3, zmm3, zmm17
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vprord zmm15, zmm15, 8
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 7
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vpaddd zmm0, zmm0, zmm29
vpaddd zmm1, zmm1, zmm16
vpaddd zmm2, zmm2, zmm18
vpaddd zmm3, zmm3, zmm20
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 16
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vprord zmm4, zmm4, 12
vpaddd zmm0, zmm0, zmm19
vpaddd zmm1, zmm1, zmm26
vpaddd zmm2, zmm2, zmm22
vpaddd zmm3, zmm3, zmm23
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 8
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vprord zmm4, zmm4, 7
vpaddd zmm0, zmm0, zmm27
vpaddd zmm1, zmm1, zmm21
vpaddd zmm2, zmm2, zmm17
vpaddd zmm3, zmm3, zmm24
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vprord zmm15, zmm15, 16
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 12
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vpaddd zmm0, zmm0, zmm31
vpaddd zmm1, zmm1, zmm16
vpaddd zmm2, zmm2, zmm25
vpaddd zmm3, zmm3, zmm22
vpaddd zmm0, zmm0, zmm4
vpaddd zmm1, zmm1, zmm5
vpaddd zmm2, zmm2, zmm6
vpaddd zmm3, zmm3, zmm7
vpxord zmm12, zmm12, zmm0
vpxord zmm13, zmm13, zmm1
vpxord zmm14, zmm14, zmm2
vpxord zmm15, zmm15, zmm3
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vprord zmm15, zmm15, 8
vpaddd zmm8, zmm8, zmm12
vpaddd zmm9, zmm9, zmm13
vpaddd zmm10, zmm10, zmm14
vpaddd zmm11, zmm11, zmm15
vpxord zmm4, zmm4, zmm8
vpxord zmm5, zmm5, zmm9
vpxord zmm6, zmm6, zmm10
vpxord zmm7, zmm7, zmm11
vprord zmm4, zmm4, 7
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vpaddd zmm0, zmm0, zmm30
vpaddd zmm1, zmm1, zmm18
vpaddd zmm2, zmm2, zmm19
vpaddd zmm3, zmm3, zmm23
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 16
vprord zmm12, zmm12, 16
vprord zmm13, zmm13, 16
vprord zmm14, zmm14, 16
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 12
vprord zmm6, zmm6, 12
vprord zmm7, zmm7, 12
vprord zmm4, zmm4, 12
vpaddd zmm0, zmm0, zmm26
vpaddd zmm1, zmm1, zmm28
vpaddd zmm2, zmm2, zmm20
vpaddd zmm3, zmm3, zmm29
vpaddd zmm0, zmm0, zmm5
vpaddd zmm1, zmm1, zmm6
vpaddd zmm2, zmm2, zmm7
vpaddd zmm3, zmm3, zmm4
vpxord zmm15, zmm15, zmm0
vpxord zmm12, zmm12, zmm1
vpxord zmm13, zmm13, zmm2
vpxord zmm14, zmm14, zmm3
vprord zmm15, zmm15, 8
vprord zmm12, zmm12, 8
vprord zmm13, zmm13, 8
vprord zmm14, zmm14, 8
vpaddd zmm10, zmm10, zmm15
vpaddd zmm11, zmm11, zmm12
vpaddd zmm8, zmm8, zmm13
vpaddd zmm9, zmm9, zmm14
vpxord zmm5, zmm5, zmm10
vpxord zmm6, zmm6, zmm11
vpxord zmm7, zmm7, zmm8
vpxord zmm4, zmm4, zmm9
vprord zmm5, zmm5, 7
vprord zmm6, zmm6, 7
vprord zmm7, zmm7, 7
vprord zmm4, zmm4, 7
vpxord zmm0, zmm0, zmm8
vpxord zmm1, zmm1, zmm9
vpxord zmm2, zmm2, zmm10
vpxord zmm3, zmm3, zmm11
vpxord zmm4, zmm4, zmm12
vpxord zmm5, zmm5, zmm13
vpxord zmm6, zmm6, zmm14
vpxord zmm7, zmm7, zmm15
movzx eax, byte ptr [rbp+78H]
jne innerloop16
mov rbx, qword ptr [rbp+90H]
vpunpckldq zmm16, zmm0, zmm1
vpunpckhdq zmm17, zmm0, zmm1
vpunpckldq zmm18, zmm2, zmm3
vpunpckhdq zmm19, zmm2, zmm3
vpunpckldq zmm20, zmm4, zmm5
vpunpckhdq zmm21, zmm4, zmm5
vpunpckldq zmm22, zmm6, zmm7
vpunpckhdq zmm23, zmm6, zmm7
vpunpcklqdq zmm0, zmm16, zmm18
vpunpckhqdq zmm1, zmm16, zmm18
vpunpcklqdq zmm2, zmm17, zmm19
vpunpckhqdq zmm3, zmm17, zmm19
vpunpcklqdq zmm4, zmm20, zmm22
vpunpckhqdq zmm5, zmm20, zmm22
vpunpcklqdq zmm6, zmm21, zmm23
vpunpckhqdq zmm7, zmm21, zmm23
vshufi32x4 zmm16, zmm0, zmm4, 88H
vshufi32x4 zmm17, zmm1, zmm5, 88H
vshufi32x4 zmm18, zmm2, zmm6, 88H
vshufi32x4 zmm19, zmm3, zmm7, 88H
vshufi32x4 zmm20, zmm0, zmm4, 0DDH
vshufi32x4 zmm21, zmm1, zmm5, 0DDH
vshufi32x4 zmm22, zmm2, zmm6, 0DDH
vshufi32x4 zmm23, zmm3, zmm7, 0DDH
vshufi32x4 zmm0, zmm16, zmm17, 88H
vshufi32x4 zmm1, zmm18, zmm19, 88H
vshufi32x4 zmm2, zmm20, zmm21, 88H
vshufi32x4 zmm3, zmm22, zmm23, 88H
vshufi32x4 zmm4, zmm16, zmm17, 0DDH
vshufi32x4 zmm5, zmm18, zmm19, 0DDH
vshufi32x4 zmm6, zmm20, zmm21, 0DDH
vshufi32x4 zmm7, zmm22, zmm23, 0DDH
vmovdqu32 zmmword ptr [rbx], zmm0
vmovdqu32 zmmword ptr [rbx+1H*40H], zmm1
vmovdqu32 zmmword ptr [rbx+2H*40H], zmm2
vmovdqu32 zmmword ptr [rbx+3H*40H], zmm3
vmovdqu32 zmmword ptr [rbx+4H*40H], zmm4
vmovdqu32 zmmword ptr [rbx+5H*40H], zmm5
vmovdqu32 zmmword ptr [rbx+6H*40H], zmm6
vmovdqu32 zmmword ptr [rbx+7H*40H], zmm7
vmovdqa32 zmm0, zmmword ptr [rsp]
vmovdqa32 zmm1, zmmword ptr [rsp+1H*40H]
vmovdqa32 zmm2, zmm0
; XXX: ml64.exe does not currently understand the syntax. We use a workaround.
vpbroadcastd zmm4, dword ptr [ADD16]
vpbroadcastd zmm5, dword ptr [ADD1]
vpaddd zmm2{k1}, zmm0, zmm4
; vpaddd zmm2{k1}, zmm0, dword ptr [ADD16] ; {1to16}
vpcmpud k2, zmm2, zmm0, 1
vpaddd zmm1 {k2}, zmm1, zmm5
; vpaddd zmm1 {k2}, zmm1, dword ptr [ADD1] ; {1to16}
vmovdqa32 zmmword ptr [rsp], zmm2
vmovdqa32 zmmword ptr [rsp+1H*40H], zmm1
add rdi, 128
add rbx, 512
mov qword ptr [rbp+90H], rbx
sub rsi, 16
cmp rsi, 16
jnc outerloop16
test rsi, rsi
jne final15blocks
unwind:
vzeroupper
vmovdqa xmm6, xmmword ptr [rsp+90H]
vmovdqa xmm7, xmmword ptr [rsp+0A0H]
vmovdqa xmm8, xmmword ptr [rsp+0B0H]
vmovdqa xmm9, xmmword ptr [rsp+0C0H]
vmovdqa xmm10, xmmword ptr [rsp+0D0H]
vmovdqa xmm11, xmmword ptr [rsp+0E0H]
vmovdqa xmm12, xmmword ptr [rsp+0F0H]
vmovdqa xmm13, xmmword ptr [rsp+100H]
vmovdqa xmm14, xmmword ptr [rsp+110H]
vmovdqa xmm15, xmmword ptr [rsp+120H]
mov rsp, rbp
pop rbp
pop rbx
pop rsi
pop rdi
pop r12
pop r13
pop r14
pop r15
ret
ALIGN 16
final15blocks:
test esi, 8H
je final7blocks
vpbroadcastd ymm0, dword ptr [rcx]
vpbroadcastd ymm1, dword ptr [rcx+4H]
vpbroadcastd ymm2, dword ptr [rcx+8H]
vpbroadcastd ymm3, dword ptr [rcx+0CH]
vpbroadcastd ymm4, dword ptr [rcx+10H]
vpbroadcastd ymm5, dword ptr [rcx+14H]
vpbroadcastd ymm6, dword ptr [rcx+18H]
vpbroadcastd ymm7, dword ptr [rcx+1CH]
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
mov r12, qword ptr [rdi+20H]
mov r13, qword ptr [rdi+28H]
mov r14, qword ptr [rdi+30H]
mov r15, qword ptr [rdi+38H]
movzx eax, byte ptr [rbp+78H]
movzx ebx, byte ptr [rbp+80H]
or eax, ebx
xor edx, edx
innerloop8:
movzx ebx, byte ptr [rbp+88H]
or ebx, eax
add rdx, 64
cmp rdx, qword ptr [rsp+80H]
cmove eax, ebx
mov dword ptr [rsp+88H], eax
vmovups xmm8, xmmword ptr [r8+rdx-40H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-40H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-40H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-40H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-40H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-40H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-40H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-40H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm16, ymm12, ymm14, 136
vshufps ymm17, ymm12, ymm14, 221
vshufps ymm18, ymm13, ymm15, 136
vshufps ymm19, ymm13, ymm15, 221
vmovups xmm8, xmmword ptr [r8+rdx-30H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-30H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-30H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-30H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-30H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-30H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-30H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-30H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm20, ymm12, ymm14, 136
vshufps ymm21, ymm12, ymm14, 221
vshufps ymm22, ymm13, ymm15, 136
vshufps ymm23, ymm13, ymm15, 221
vmovups xmm8, xmmword ptr [r8+rdx-20H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-20H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-20H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-20H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-20H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-20H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-20H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-20H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm24, ymm12, ymm14, 136
vshufps ymm25, ymm12, ymm14, 221
vshufps ymm26, ymm13, ymm15, 136
vshufps ymm27, ymm13, ymm15, 221
vmovups xmm8, xmmword ptr [r8+rdx-10H]
vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-10H], 01H
vmovups xmm9, xmmword ptr [r9+rdx-10H]
vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-10H], 01H
vunpcklpd ymm12, ymm8, ymm9
vunpckhpd ymm13, ymm8, ymm9
vmovups xmm10, xmmword ptr [r10+rdx-10H]
vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-10H], 01H
vmovups xmm11, xmmword ptr [r11+rdx-10H]
vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-10H], 01H
vunpcklpd ymm14, ymm10, ymm11
vunpckhpd ymm15, ymm10, ymm11
vshufps ymm28, ymm12, ymm14, 136
vshufps ymm29, ymm12, ymm14, 221
vshufps ymm30, ymm13, ymm15, 136
vshufps ymm31, ymm13, ymm15, 221
vpbroadcastd ymm8, dword ptr [BLAKE3_IV_0]
vpbroadcastd ymm9, dword ptr [BLAKE3_IV_1]
vpbroadcastd ymm10, dword ptr [BLAKE3_IV_2]
vpbroadcastd ymm11, dword ptr [BLAKE3_IV_3]
vmovdqa ymm12, ymmword ptr [rsp]
vmovdqa ymm13, ymmword ptr [rsp+40H]
vpbroadcastd ymm14, dword ptr [BLAKE3_BLOCK_LEN]
vpbroadcastd ymm15, dword ptr [rsp+88H]
vpaddd ymm0, ymm0, ymm16
vpaddd ymm1, ymm1, ymm18
vpaddd ymm2, ymm2, ymm20
vpaddd ymm3, ymm3, ymm22
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vprord ymm15, ymm15, 16
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 12
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vpaddd ymm0, ymm0, ymm17
vpaddd ymm1, ymm1, ymm19
vpaddd ymm2, ymm2, ymm21
vpaddd ymm3, ymm3, ymm23
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vprord ymm15, ymm15, 8
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 7
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vpaddd ymm0, ymm0, ymm24
vpaddd ymm1, ymm1, ymm26
vpaddd ymm2, ymm2, ymm28
vpaddd ymm3, ymm3, ymm30
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 16
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vprord ymm4, ymm4, 12
vpaddd ymm0, ymm0, ymm25
vpaddd ymm1, ymm1, ymm27
vpaddd ymm2, ymm2, ymm29
vpaddd ymm3, ymm3, ymm31
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 8
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vprord ymm4, ymm4, 7
vpaddd ymm0, ymm0, ymm18
vpaddd ymm1, ymm1, ymm19
vpaddd ymm2, ymm2, ymm23
vpaddd ymm3, ymm3, ymm20
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vprord ymm15, ymm15, 16
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 12
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vpaddd ymm0, ymm0, ymm22
vpaddd ymm1, ymm1, ymm26
vpaddd ymm2, ymm2, ymm16
vpaddd ymm3, ymm3, ymm29
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vprord ymm15, ymm15, 8
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 7
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vpaddd ymm0, ymm0, ymm17
vpaddd ymm1, ymm1, ymm28
vpaddd ymm2, ymm2, ymm25
vpaddd ymm3, ymm3, ymm31
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 16
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vprord ymm4, ymm4, 12
vpaddd ymm0, ymm0, ymm27
vpaddd ymm1, ymm1, ymm21
vpaddd ymm2, ymm2, ymm30
vpaddd ymm3, ymm3, ymm24
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 8
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vprord ymm4, ymm4, 7
vpaddd ymm0, ymm0, ymm19
vpaddd ymm1, ymm1, ymm26
vpaddd ymm2, ymm2, ymm29
vpaddd ymm3, ymm3, ymm23
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vprord ymm15, ymm15, 16
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 12
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vpaddd ymm0, ymm0, ymm20
vpaddd ymm1, ymm1, ymm28
vpaddd ymm2, ymm2, ymm18
vpaddd ymm3, ymm3, ymm30
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vprord ymm15, ymm15, 8
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 7
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vpaddd ymm0, ymm0, ymm22
vpaddd ymm1, ymm1, ymm25
vpaddd ymm2, ymm2, ymm27
vpaddd ymm3, ymm3, ymm24
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 16
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vprord ymm4, ymm4, 12
vpaddd ymm0, ymm0, ymm21
vpaddd ymm1, ymm1, ymm16
vpaddd ymm2, ymm2, ymm31
vpaddd ymm3, ymm3, ymm17
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 8
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vprord ymm4, ymm4, 7
vpaddd ymm0, ymm0, ymm26
vpaddd ymm1, ymm1, ymm28
vpaddd ymm2, ymm2, ymm30
vpaddd ymm3, ymm3, ymm29
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vprord ymm15, ymm15, 16
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 12
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vpaddd ymm0, ymm0, ymm23
vpaddd ymm1, ymm1, ymm25
vpaddd ymm2, ymm2, ymm19
vpaddd ymm3, ymm3, ymm31
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vprord ymm15, ymm15, 8
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 7
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vpaddd ymm0, ymm0, ymm20
vpaddd ymm1, ymm1, ymm27
vpaddd ymm2, ymm2, ymm21
vpaddd ymm3, ymm3, ymm17
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 16
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vprord ymm4, ymm4, 12
vpaddd ymm0, ymm0, ymm16
vpaddd ymm1, ymm1, ymm18
vpaddd ymm2, ymm2, ymm24
vpaddd ymm3, ymm3, ymm22
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 8
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vprord ymm4, ymm4, 7
vpaddd ymm0, ymm0, ymm28
vpaddd ymm1, ymm1, ymm25
vpaddd ymm2, ymm2, ymm31
vpaddd ymm3, ymm3, ymm30
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vprord ymm15, ymm15, 16
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 12
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vpaddd ymm0, ymm0, ymm29
vpaddd ymm1, ymm1, ymm27
vpaddd ymm2, ymm2, ymm26
vpaddd ymm3, ymm3, ymm24
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vprord ymm15, ymm15, 8
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 7
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vpaddd ymm0, ymm0, ymm23
vpaddd ymm1, ymm1, ymm21
vpaddd ymm2, ymm2, ymm16
vpaddd ymm3, ymm3, ymm22
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 16
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vprord ymm4, ymm4, 12
vpaddd ymm0, ymm0, ymm18
vpaddd ymm1, ymm1, ymm19
vpaddd ymm2, ymm2, ymm17
vpaddd ymm3, ymm3, ymm20
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 8
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vprord ymm4, ymm4, 7
vpaddd ymm0, ymm0, ymm25
vpaddd ymm1, ymm1, ymm27
vpaddd ymm2, ymm2, ymm24
vpaddd ymm3, ymm3, ymm31
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vprord ymm15, ymm15, 16
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 12
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vpaddd ymm0, ymm0, ymm30
vpaddd ymm1, ymm1, ymm21
vpaddd ymm2, ymm2, ymm28
vpaddd ymm3, ymm3, ymm17
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vprord ymm15, ymm15, 8
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 7
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vpaddd ymm0, ymm0, ymm29
vpaddd ymm1, ymm1, ymm16
vpaddd ymm2, ymm2, ymm18
vpaddd ymm3, ymm3, ymm20
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 16
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vprord ymm4, ymm4, 12
vpaddd ymm0, ymm0, ymm19
vpaddd ymm1, ymm1, ymm26
vpaddd ymm2, ymm2, ymm22
vpaddd ymm3, ymm3, ymm23
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 8
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vprord ymm4, ymm4, 7
vpaddd ymm0, ymm0, ymm27
vpaddd ymm1, ymm1, ymm21
vpaddd ymm2, ymm2, ymm17
vpaddd ymm3, ymm3, ymm24
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vprord ymm15, ymm15, 16
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 12
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vpaddd ymm0, ymm0, ymm31
vpaddd ymm1, ymm1, ymm16
vpaddd ymm2, ymm2, ymm25
vpaddd ymm3, ymm3, ymm22
vpaddd ymm0, ymm0, ymm4
vpaddd ymm1, ymm1, ymm5
vpaddd ymm2, ymm2, ymm6
vpaddd ymm3, ymm3, ymm7
vpxord ymm12, ymm12, ymm0
vpxord ymm13, ymm13, ymm1
vpxord ymm14, ymm14, ymm2
vpxord ymm15, ymm15, ymm3
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vprord ymm15, ymm15, 8
vpaddd ymm8, ymm8, ymm12
vpaddd ymm9, ymm9, ymm13
vpaddd ymm10, ymm10, ymm14
vpaddd ymm11, ymm11, ymm15
vpxord ymm4, ymm4, ymm8
vpxord ymm5, ymm5, ymm9
vpxord ymm6, ymm6, ymm10
vpxord ymm7, ymm7, ymm11
vprord ymm4, ymm4, 7
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vpaddd ymm0, ymm0, ymm30
vpaddd ymm1, ymm1, ymm18
vpaddd ymm2, ymm2, ymm19
vpaddd ymm3, ymm3, ymm23
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 16
vprord ymm12, ymm12, 16
vprord ymm13, ymm13, 16
vprord ymm14, ymm14, 16
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 12
vprord ymm6, ymm6, 12
vprord ymm7, ymm7, 12
vprord ymm4, ymm4, 12
vpaddd ymm0, ymm0, ymm26
vpaddd ymm1, ymm1, ymm28
vpaddd ymm2, ymm2, ymm20
vpaddd ymm3, ymm3, ymm29
vpaddd ymm0, ymm0, ymm5
vpaddd ymm1, ymm1, ymm6
vpaddd ymm2, ymm2, ymm7
vpaddd ymm3, ymm3, ymm4
vpxord ymm15, ymm15, ymm0
vpxord ymm12, ymm12, ymm1
vpxord ymm13, ymm13, ymm2
vpxord ymm14, ymm14, ymm3
vprord ymm15, ymm15, 8
vprord ymm12, ymm12, 8
vprord ymm13, ymm13, 8
vprord ymm14, ymm14, 8
vpaddd ymm10, ymm10, ymm15
vpaddd ymm11, ymm11, ymm12
vpaddd ymm8, ymm8, ymm13
vpaddd ymm9, ymm9, ymm14
vpxord ymm5, ymm5, ymm10
vpxord ymm6, ymm6, ymm11
vpxord ymm7, ymm7, ymm8
vpxord ymm4, ymm4, ymm9
vprord ymm5, ymm5, 7
vprord ymm6, ymm6, 7
vprord ymm7, ymm7, 7
vprord ymm4, ymm4, 7
vpxor ymm0, ymm0, ymm8
vpxor ymm1, ymm1, ymm9
vpxor ymm2, ymm2, ymm10
vpxor ymm3, ymm3, ymm11
vpxor ymm4, ymm4, ymm12
vpxor ymm5, ymm5, ymm13
vpxor ymm6, ymm6, ymm14
vpxor ymm7, ymm7, ymm15
movzx eax, byte ptr [rbp+78H]
jne innerloop8
mov rbx, qword ptr [rbp+90H]
vunpcklps ymm8, ymm0, ymm1
vunpcklps ymm9, ymm2, ymm3
vunpckhps ymm10, ymm0, ymm1
vunpcklps ymm11, ymm4, ymm5
vunpcklps ymm0, ymm6, ymm7
vshufps ymm12, ymm8, ymm9, 78
vblendps ymm1, ymm8, ymm12, 0CCH
vshufps ymm8, ymm11, ymm0, 78
vunpckhps ymm13, ymm2, ymm3
vblendps ymm2, ymm11, ymm8, 0CCH
vblendps ymm3, ymm12, ymm9, 0CCH
vperm2f128 ymm12, ymm1, ymm2, 20H
vmovups ymmword ptr [rbx], ymm12
vunpckhps ymm14, ymm4, ymm5
vblendps ymm4, ymm8, ymm0, 0CCH
vunpckhps ymm15, ymm6, ymm7
vperm2f128 ymm7, ymm3, ymm4, 20H
vmovups ymmword ptr [rbx+20H], ymm7
vshufps ymm5, ymm10, ymm13, 78
vblendps ymm6, ymm5, ymm13, 0CCH
vshufps ymm13, ymm14, ymm15, 78
vblendps ymm10, ymm10, ymm5, 0CCH
vblendps ymm14, ymm14, ymm13, 0CCH
vperm2f128 ymm8, ymm10, ymm14, 20H
vmovups ymmword ptr [rbx+40H], ymm8
vblendps ymm15, ymm13, ymm15, 0CCH
vperm2f128 ymm13, ymm6, ymm15, 20H
vmovups ymmword ptr [rbx+60H], ymm13
vperm2f128 ymm9, ymm1, ymm2, 31H
vperm2f128 ymm11, ymm3, ymm4, 31H
vmovups ymmword ptr [rbx+80H], ymm9
vperm2f128 ymm14, ymm10, ymm14, 31H
vperm2f128 ymm15, ymm6, ymm15, 31H
vmovups ymmword ptr [rbx+0A0H], ymm11
vmovups ymmword ptr [rbx+0C0H], ymm14
vmovups ymmword ptr [rbx+0E0H], ymm15
vmovdqa ymm0, ymmword ptr [rsp]
vmovdqa ymm2, ymmword ptr [rsp+40H]
vmovdqa32 ymm0 {k1}, ymmword ptr [rsp+1H*20H]
vmovdqa32 ymm2 {k1}, ymmword ptr [rsp+3H*20H]
vmovdqa ymmword ptr [rsp], ymm0
vmovdqa ymmword ptr [rsp+40H], ymm2
add rbx, 256
mov qword ptr [rbp+90H], rbx
add rdi, 64
sub rsi, 8
final7blocks:
mov rbx, qword ptr [rbp+90H]
mov r15, qword ptr [rsp+80H]
movzx r13, byte ptr [rbp+78H]
movzx r12, byte ptr [rbp+88H]
test esi, 4H
je final3blocks
vbroadcasti32x4 zmm0, xmmword ptr [rcx]
vbroadcasti32x4 zmm1, xmmword ptr [rcx+1H*10H]
vmovdqa xmm12, xmmword ptr [rsp]
vmovdqa xmm13, xmmword ptr [rsp+40H]
vpunpckldq xmm14, xmm12, xmm13
vpunpckhdq xmm15, xmm12, xmm13
vpermq ymm14, ymm14, 0DCH
vpermq ymm15, ymm15, 0DCH
vpbroadcastd zmm12, dword ptr [BLAKE3_BLOCK_LEN]
vinserti64x4 zmm13, zmm14, ymm15, 01H
mov eax, 17476
kmovw k2, eax
vpblendmd zmm13 {k2}, zmm13, zmm12
vbroadcasti32x4 zmm15, xmmword ptr [BLAKE3_IV]
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
mov eax, 43690
kmovw k3, eax
mov eax, 34952
kmovw k4, eax
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
ALIGN 16
innerloop4:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
mov dword ptr [rsp+88H], eax
vmovdqa32 zmm2, zmm15
vpbroadcastd zmm8, dword ptr [rsp+22H*4H]
vpblendmd zmm3 {k4}, zmm13, zmm8
vmovups zmm8, zmmword ptr [r8+rdx-1H*40H]
vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-4H*10H], 01H
vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-4H*10H], 02H
vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-4H*10H], 03H
vmovups zmm9, zmmword ptr [r8+rdx-30H]
vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-3H*10H], 01H
vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-3H*10H], 02H
vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-3H*10H], 03H
vshufps zmm4, zmm8, zmm9, 136
vshufps zmm5, zmm8, zmm9, 221
vmovups zmm8, zmmword ptr [r8+rdx-20H]
vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-2H*10H], 01H
vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-2H*10H], 02H
vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-2H*10H], 03H
vmovups zmm9, zmmword ptr [r8+rdx-10H]
vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-1H*10H], 01H
vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-1H*10H], 02H
vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-1H*10H], 03H
vshufps zmm6, zmm8, zmm9, 136
vshufps zmm7, zmm8, zmm9, 221
vpshufd zmm6, zmm6, 93H
vpshufd zmm7, zmm7, 93H
mov al, 7
roundloop4:
vpaddd zmm0, zmm0, zmm4
vpaddd zmm0, zmm0, zmm1
vpxord zmm3, zmm3, zmm0
vprord zmm3, zmm3, 16
vpaddd zmm2, zmm2, zmm3
vpxord zmm1, zmm1, zmm2
vprord zmm1, zmm1, 12
vpaddd zmm0, zmm0, zmm5
vpaddd zmm0, zmm0, zmm1
vpxord zmm3, zmm3, zmm0
vprord zmm3, zmm3, 8
vpaddd zmm2, zmm2, zmm3
vpxord zmm1, zmm1, zmm2
vprord zmm1, zmm1, 7
vpshufd zmm0, zmm0, 93H
vpshufd zmm3, zmm3, 4EH
vpshufd zmm2, zmm2, 39H
vpaddd zmm0, zmm0, zmm6
vpaddd zmm0, zmm0, zmm1
vpxord zmm3, zmm3, zmm0
vprord zmm3, zmm3, 16
vpaddd zmm2, zmm2, zmm3
vpxord zmm1, zmm1, zmm2
vprord zmm1, zmm1, 12
vpaddd zmm0, zmm0, zmm7
vpaddd zmm0, zmm0, zmm1
vpxord zmm3, zmm3, zmm0
vprord zmm3, zmm3, 8
vpaddd zmm2, zmm2, zmm3
vpxord zmm1, zmm1, zmm2
vprord zmm1, zmm1, 7
vpshufd zmm0, zmm0, 39H
vpshufd zmm3, zmm3, 4EH
vpshufd zmm2, zmm2, 93H
dec al
jz endroundloop4
vshufps zmm8, zmm4, zmm5, 214
vpshufd zmm9, zmm4, 0FH
vpshufd zmm4, zmm8, 39H
vshufps zmm8, zmm6, zmm7, 250
vpblendmd zmm9 {k3}, zmm9, zmm8
vpunpcklqdq zmm8, zmm7, zmm5
vpblendmd zmm8 {k4}, zmm8, zmm6
vpshufd zmm8, zmm8, 78H
vpunpckhdq zmm5, zmm5, zmm7
vpunpckldq zmm6, zmm6, zmm5
vpshufd zmm7, zmm6, 1EH
vmovdqa32 zmm5, zmm9
vmovdqa32 zmm6, zmm8
jmp roundloop4
endroundloop4:
vpxord zmm0, zmm0, zmm2
vpxord zmm1, zmm1, zmm3
mov eax, r13d
cmp rdx, r15
jne innerloop4
vmovdqu xmmword ptr [rbx], xmm0
vmovdqu xmmword ptr [rbx+10H], xmm1
vextracti128 xmmword ptr [rbx+20H], ymm0, 01H
vextracti128 xmmword ptr [rbx+30H], ymm1, 01H
vextracti32x4 xmmword ptr [rbx+4H*10H], zmm0, 02H
vextracti32x4 xmmword ptr [rbx+5H*10H], zmm1, 02H
vextracti32x4 xmmword ptr [rbx+6H*10H], zmm0, 03H
vextracti32x4 xmmword ptr [rbx+7H*10H], zmm1, 03H
vmovdqa xmm0, xmmword ptr [rsp]
vmovdqa xmm2, xmmword ptr [rsp+40H]
vmovdqa32 xmm0 {k1}, xmmword ptr [rsp+1H*10H]
vmovdqa32 xmm2 {k1}, xmmword ptr [rsp+5H*10H]
vmovdqa xmmword ptr [rsp], xmm0
vmovdqa xmmword ptr [rsp+40H], xmm2
add rbx, 128
add rdi, 32
sub rsi, 4
final3blocks:
test esi, 2H
je final1block
vbroadcasti128 ymm0, xmmword ptr [rcx]
vbroadcasti128 ymm1, xmmword ptr [rcx+10H]
vmovd xmm13, dword ptr [rsp]
vpinsrd xmm13, xmm13, dword ptr [rsp+40H], 1
vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2
vmovd xmm14, dword ptr [rsp+4H]
vpinsrd xmm14, xmm14, dword ptr [rsp+44H], 1
vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2
vinserti128 ymm13, ymm13, xmm14, 01H
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
ALIGN 16
innerloop2:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
mov dword ptr [rsp+88H], eax
vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV]
vpbroadcastd ymm8, dword ptr [rsp+88H]
vpblendd ymm3, ymm13, ymm8, 88H
vmovups ymm8, ymmword ptr [r8+rdx-40H]
vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-40H], 01H
vmovups ymm9, ymmword ptr [r8+rdx-30H]
vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-30H], 01H
vshufps ymm4, ymm8, ymm9, 136
vshufps ymm5, ymm8, ymm9, 221
vmovups ymm8, ymmword ptr [r8+rdx-20H]
vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-20H], 01H
vmovups ymm9, ymmword ptr [r8+rdx-10H]
vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-10H], 01H
vshufps ymm6, ymm8, ymm9, 136
vshufps ymm7, ymm8, ymm9, 221
vpshufd ymm6, ymm6, 93H
vpshufd ymm7, ymm7, 93H
mov al, 7
roundloop2:
vpaddd ymm0, ymm0, ymm4
vpaddd ymm0, ymm0, ymm1
vpxord ymm3, ymm3, ymm0
vprord ymm3, ymm3, 16
vpaddd ymm2, ymm2, ymm3
vpxord ymm1, ymm1, ymm2
vprord ymm1, ymm1, 12
vpaddd ymm0, ymm0, ymm5
vpaddd ymm0, ymm0, ymm1
vpxord ymm3, ymm3, ymm0
vprord ymm3, ymm3, 8
vpaddd ymm2, ymm2, ymm3
vpxord ymm1, ymm1, ymm2
vprord ymm1, ymm1, 7
vpshufd ymm0, ymm0, 93H
vpshufd ymm3, ymm3, 4EH
vpshufd ymm2, ymm2, 39H
vpaddd ymm0, ymm0, ymm6
vpaddd ymm0, ymm0, ymm1
vpxord ymm3, ymm3, ymm0
vprord ymm3, ymm3, 16
vpaddd ymm2, ymm2, ymm3
vpxord ymm1, ymm1, ymm2
vprord ymm1, ymm1, 12
vpaddd ymm0, ymm0, ymm7
vpaddd ymm0, ymm0, ymm1
vpxord ymm3, ymm3, ymm0
vprord ymm3, ymm3, 8
vpaddd ymm2, ymm2, ymm3
vpxord ymm1, ymm1, ymm2
vprord ymm1, ymm1, 7
vpshufd ymm0, ymm0, 39H
vpshufd ymm3, ymm3, 4EH
vpshufd ymm2, ymm2, 93H
dec al
jz endroundloop2
vshufps ymm8, ymm4, ymm5, 214
vpshufd ymm9, ymm4, 0FH
vpshufd ymm4, ymm8, 39H
vshufps ymm8, ymm6, ymm7, 250
vpblendd ymm9, ymm9, ymm8, 0AAH
vpunpcklqdq ymm8, ymm7, ymm5
vpblendd ymm8, ymm8, ymm6, 88H
vpshufd ymm8, ymm8, 78H
vpunpckhdq ymm5, ymm5, ymm7
vpunpckldq ymm6, ymm6, ymm5
vpshufd ymm7, ymm6, 1EH
vmovdqa ymm5, ymm9
vmovdqa ymm6, ymm8
jmp roundloop2
endroundloop2:
vpxor ymm0, ymm0, ymm2
vpxor ymm1, ymm1, ymm3
mov eax, r13d
cmp rdx, r15
jne innerloop2
vmovdqu xmmword ptr [rbx], xmm0
vmovdqu xmmword ptr [rbx+10H], xmm1
vextracti128 xmmword ptr [rbx+20H], ymm0, 01H
vextracti128 xmmword ptr [rbx+30H], ymm1, 01H
vmovdqa xmm0, xmmword ptr [rsp]
vmovdqa xmm2, xmmword ptr [rsp+40H]
vmovdqu32 xmm0 {k1}, xmmword ptr [rsp+8H]
vmovdqu32 xmm2 {k1}, xmmword ptr [rsp+48H]
vmovdqa xmmword ptr [rsp], xmm0
vmovdqa xmmword ptr [rsp+40H], xmm2
add rbx, 64
add rdi, 16
sub rsi, 2
final1block:
test esi, 1H
je unwind
vmovdqu xmm0, xmmword ptr [rcx]
vmovdqu xmm1, xmmword ptr [rcx+10H]
vmovd xmm14, dword ptr [rsp]
vpinsrd xmm14, xmm14, dword ptr [rsp+40H], 1
vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2
vmovdqa xmm15, xmmword ptr [BLAKE3_IV]
mov r8, qword ptr [rdi]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
ALIGN 16
innerloop1:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
vpinsrd xmm3, xmm14, eax, 3
vmovdqa xmm2, xmm15
vmovups xmm8, xmmword ptr [r8+rdx-40H]
vmovups xmm9, xmmword ptr [r8+rdx-30H]
vshufps xmm4, xmm8, xmm9, 136
vshufps xmm5, xmm8, xmm9, 221
vmovups xmm8, xmmword ptr [r8+rdx-20H]
vmovups xmm9, xmmword ptr [r8+rdx-10H]
vshufps xmm6, xmm8, xmm9, 136
vshufps xmm7, xmm8, xmm9, 221
vpshufd xmm6, xmm6, 93H
vpshufd xmm7, xmm7, 93H
mov al, 7
roundloop1:
vpaddd xmm0, xmm0, xmm4
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 16
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 12
vpaddd xmm0, xmm0, xmm5
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 8
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 7
vpshufd xmm0, xmm0, 93H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 39H
vpaddd xmm0, xmm0, xmm6
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 16
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 12
vpaddd xmm0, xmm0, xmm7
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 8
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 7
vpshufd xmm0, xmm0, 39H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 93H
dec al
jz endroundloop1
vshufps xmm8, xmm4, xmm5, 214
vpshufd xmm9, xmm4, 0FH
vpshufd xmm4, xmm8, 39H
vshufps xmm8, xmm6, xmm7, 250
vpblendd xmm9, xmm9, xmm8, 0AAH
vpunpcklqdq xmm8, xmm7, xmm5
vpblendd xmm8, xmm8, xmm6, 88H
vpshufd xmm8, xmm8, 78H
vpunpckhdq xmm5, xmm5, xmm7
vpunpckldq xmm6, xmm6, xmm5
vpshufd xmm7, xmm6, 1EH
vmovdqa xmm5, xmm9
vmovdqa xmm6, xmm8
jmp roundloop1
endroundloop1:
vpxor xmm0, xmm0, xmm2
vpxor xmm1, xmm1, xmm3
mov eax, r13d
cmp rdx, r15
jne innerloop1
vmovdqu xmmword ptr [rbx], xmm0
vmovdqu xmmword ptr [rbx+10H], xmm1
jmp unwind
_blake3_hash_many_avx512 ENDP
blake3_hash_many_avx512 ENDP
ALIGN 16
blake3_compress_in_place_avx512 PROC
_blake3_compress_in_place_avx512 PROC
sub rsp, 72
vmovdqa xmmword ptr [rsp], xmm6
vmovdqa xmmword ptr [rsp+10H], xmm7
vmovdqa xmmword ptr [rsp+20H], xmm8
vmovdqa xmmword ptr [rsp+30H], xmm9
vmovdqu xmm0, xmmword ptr [rcx]
vmovdqu xmm1, xmmword ptr [rcx+10H]
movzx eax, byte ptr [rsp+70H]
movzx r8d, r8b
shl rax, 32
add r8, rax
vmovq xmm3, r9
vmovq xmm4, r8
vpunpcklqdq xmm3, xmm3, xmm4
vmovaps xmm2, xmmword ptr [BLAKE3_IV]
vmovups xmm8, xmmword ptr [rdx]
vmovups xmm9, xmmword ptr [rdx+10H]
vshufps xmm4, xmm8, xmm9, 136
vshufps xmm5, xmm8, xmm9, 221
vmovups xmm8, xmmword ptr [rdx+20H]
vmovups xmm9, xmmword ptr [rdx+30H]
vshufps xmm6, xmm8, xmm9, 136
vshufps xmm7, xmm8, xmm9, 221
vpshufd xmm6, xmm6, 93H
vpshufd xmm7, xmm7, 93H
mov al, 7
@@:
vpaddd xmm0, xmm0, xmm4
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 16
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 12
vpaddd xmm0, xmm0, xmm5
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 8
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 7
vpshufd xmm0, xmm0, 93H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 39H
vpaddd xmm0, xmm0, xmm6
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 16
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 12
vpaddd xmm0, xmm0, xmm7
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 8
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 7
vpshufd xmm0, xmm0, 39H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 93H
dec al
jz @F
vshufps xmm8, xmm4, xmm5, 214
vpshufd xmm9, xmm4, 0FH
vpshufd xmm4, xmm8, 39H
vshufps xmm8, xmm6, xmm7, 250
vpblendd xmm9, xmm9, xmm8, 0AAH
vpunpcklqdq xmm8, xmm7, xmm5
vpblendd xmm8, xmm8, xmm6, 88H
vpshufd xmm8, xmm8, 78H
vpunpckhdq xmm5, xmm5, xmm7
vpunpckldq xmm6, xmm6, xmm5
vpshufd xmm7, xmm6, 1EH
vmovdqa xmm5, xmm9
vmovdqa xmm6, xmm8
jmp @B
@@:
vpxor xmm0, xmm0, xmm2
vpxor xmm1, xmm1, xmm3
vmovdqu xmmword ptr [rcx], xmm0
vmovdqu xmmword ptr [rcx+10H], xmm1
vmovdqa xmm6, xmmword ptr [rsp]
vmovdqa xmm7, xmmword ptr [rsp+10H]
vmovdqa xmm8, xmmword ptr [rsp+20H]
vmovdqa xmm9, xmmword ptr [rsp+30H]
add rsp, 72
ret
_blake3_compress_in_place_avx512 ENDP
blake3_compress_in_place_avx512 ENDP
ALIGN 16
blake3_compress_xof_avx512 PROC
_blake3_compress_xof_avx512 PROC
sub rsp, 72
vmovdqa xmmword ptr [rsp], xmm6
vmovdqa xmmword ptr [rsp+10H], xmm7
vmovdqa xmmword ptr [rsp+20H], xmm8
vmovdqa xmmword ptr [rsp+30H], xmm9
vmovdqu xmm0, xmmword ptr [rcx]
vmovdqu xmm1, xmmword ptr [rcx+10H]
movzx eax, byte ptr [rsp+70H]
movzx r8d, r8b
mov r10, qword ptr [rsp+78H]
shl rax, 32
add r8, rax
vmovq xmm3, r9
vmovq xmm4, r8
vpunpcklqdq xmm3, xmm3, xmm4
vmovaps xmm2, xmmword ptr [BLAKE3_IV]
vmovups xmm8, xmmword ptr [rdx]
vmovups xmm9, xmmword ptr [rdx+10H]
vshufps xmm4, xmm8, xmm9, 136
vshufps xmm5, xmm8, xmm9, 221
vmovups xmm8, xmmword ptr [rdx+20H]
vmovups xmm9, xmmword ptr [rdx+30H]
vshufps xmm6, xmm8, xmm9, 136
vshufps xmm7, xmm8, xmm9, 221
vpshufd xmm6, xmm6, 93H
vpshufd xmm7, xmm7, 93H
mov al, 7
@@:
vpaddd xmm0, xmm0, xmm4
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 16
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 12
vpaddd xmm0, xmm0, xmm5
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 8
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 7
vpshufd xmm0, xmm0, 93H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 39H
vpaddd xmm0, xmm0, xmm6
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 16
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 12
vpaddd xmm0, xmm0, xmm7
vpaddd xmm0, xmm0, xmm1
vpxord xmm3, xmm3, xmm0
vprord xmm3, xmm3, 8
vpaddd xmm2, xmm2, xmm3
vpxord xmm1, xmm1, xmm2
vprord xmm1, xmm1, 7
vpshufd xmm0, xmm0, 39H
vpshufd xmm3, xmm3, 4EH
vpshufd xmm2, xmm2, 93H
dec al
jz @F
vshufps xmm8, xmm4, xmm5, 214
vpshufd xmm9, xmm4, 0FH
vpshufd xmm4, xmm8, 39H
vshufps xmm8, xmm6, xmm7, 250
vpblendd xmm9, xmm9, xmm8, 0AAH
vpunpcklqdq xmm8, xmm7, xmm5
vpblendd xmm8, xmm8, xmm6, 88H
vpshufd xmm8, xmm8, 78H
vpunpckhdq xmm5, xmm5, xmm7
vpunpckldq xmm6, xmm6, xmm5
vpshufd xmm7, xmm6, 1EH
vmovdqa xmm5, xmm9
vmovdqa xmm6, xmm8
jmp @B
@@:
vpxor xmm0, xmm0, xmm2
vpxor xmm1, xmm1, xmm3
vpxor xmm2, xmm2, xmmword ptr [rcx]
vpxor xmm3, xmm3, xmmword ptr [rcx+10H]
vmovdqu xmmword ptr [r10], xmm0
vmovdqu xmmword ptr [r10+10H], xmm1
vmovdqu xmmword ptr [r10+20H], xmm2
vmovdqu xmmword ptr [r10+30H], xmm3
vmovdqa xmm6, xmmword ptr [rsp]
vmovdqa xmm7, xmmword ptr [rsp+10H]
vmovdqa xmm8, xmmword ptr [rsp+20H]
vmovdqa xmm9, xmmword ptr [rsp+30H]
add rsp, 72
ret
_blake3_compress_xof_avx512 ENDP
blake3_compress_xof_avx512 ENDP
_TEXT ENDS
_RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST'
ALIGN 64
INDEX0:
dd 0, 1, 2, 3, 16, 17, 18, 19
dd 8, 9, 10, 11, 24, 25, 26, 27
INDEX1:
dd 4, 5, 6, 7, 20, 21, 22, 23
dd 12, 13, 14, 15, 28, 29, 30, 31
ADD0:
dd 0, 1, 2, 3, 4, 5, 6, 7
dd 8, 9, 10, 11, 12, 13, 14, 15
ADD1:
dd 1
ADD16:
dd 16
BLAKE3_BLOCK_LEN:
dd 64
ALIGN 64
BLAKE3_IV:
BLAKE3_IV_0:
dd 06A09E667H
BLAKE3_IV_1:
dd 0BB67AE85H
BLAKE3_IV_2:
dd 03C6EF372H
BLAKE3_IV_3:
dd 0A54FF53AH
_RDATA ENDS
END
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_dispatch.c
================================================
#include
#include
#include
#include "blake3_impl.h"
#if defined(_MSC_VER)
#include
#endif
#if defined(IS_X86)
#if defined(_MSC_VER)
#include
#elif defined(__GNUC__)
#include
#else
#undef IS_X86 /* Unimplemented! */
#endif
#endif
#if !defined(BLAKE3_ATOMICS)
#if defined(__has_include)
#if __has_include() && !defined(_MSC_VER)
#define BLAKE3_ATOMICS 1
#else
#define BLAKE3_ATOMICS 0
#endif /* __has_include() && !defined(_MSC_VER) */
#else
#define BLAKE3_ATOMICS 0
#endif /* defined(__has_include) */
#endif /* BLAKE3_ATOMICS */
#if BLAKE3_ATOMICS
#define ATOMIC_INT _Atomic int
#define ATOMIC_LOAD(x) x
#define ATOMIC_STORE(x, y) x = y
#elif defined(_MSC_VER)
#define ATOMIC_INT LONG
#define ATOMIC_LOAD(x) InterlockedOr(&x, 0)
#define ATOMIC_STORE(x, y) InterlockedExchange(&x, y)
#else
#define ATOMIC_INT int
#define ATOMIC_LOAD(x) x
#define ATOMIC_STORE(x, y) x = y
#endif
#define MAYBE_UNUSED(x) (void)((x))
#if defined(IS_X86)
static uint64_t xgetbv(void) {
#if defined(_MSC_VER)
return _xgetbv(0);
#else
uint32_t eax = 0, edx = 0;
__asm__ __volatile__("xgetbv\n" : "=a"(eax), "=d"(edx) : "c"(0));
return ((uint64_t)edx << 32) | eax;
#endif
}
static void cpuid(uint32_t out[4], uint32_t id) {
#if defined(_MSC_VER)
__cpuid((int *)out, id);
#elif defined(__i386__) || defined(_M_IX86)
__asm__ __volatile__("movl %%ebx, %1\n"
"cpuid\n"
"xchgl %1, %%ebx\n"
: "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3])
: "a"(id));
#else
__asm__ __volatile__("cpuid\n"
: "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3])
: "a"(id));
#endif
}
static void cpuidex(uint32_t out[4], uint32_t id, uint32_t sid) {
#if defined(_MSC_VER)
__cpuidex((int *)out, id, sid);
#elif defined(__i386__) || defined(_M_IX86)
__asm__ __volatile__("movl %%ebx, %1\n"
"cpuid\n"
"xchgl %1, %%ebx\n"
: "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3])
: "a"(id), "c"(sid));
#else
__asm__ __volatile__("cpuid\n"
: "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3])
: "a"(id), "c"(sid));
#endif
}
enum cpu_feature {
SSE2 = 1 << 0,
SSSE3 = 1 << 1,
SSE41 = 1 << 2,
AVX = 1 << 3,
AVX2 = 1 << 4,
AVX512F = 1 << 5,
AVX512VL = 1 << 6,
/* ... */
UNDEFINED = 1 << 30
};
#if !defined(BLAKE3_TESTING)
static /* Allow the variable to be controlled manually for testing */
#endif
ATOMIC_INT g_cpu_features = UNDEFINED;
#if !defined(BLAKE3_TESTING)
static
#endif
enum cpu_feature
get_cpu_features(void) {
/* If TSAN detects a data race here, try compiling with -DBLAKE3_ATOMICS=1 */
enum cpu_feature features = ATOMIC_LOAD(g_cpu_features);
if (features != UNDEFINED) {
return features;
} else {
#if defined(IS_X86)
uint32_t regs[4] = {0};
uint32_t *eax = ®s[0], *ebx = ®s[1], *ecx = ®s[2], *edx = ®s[3];
(void)edx;
features = 0;
cpuid(regs, 0);
const int max_id = *eax;
cpuid(regs, 1);
#if defined(__amd64__) || defined(_M_X64)
features |= SSE2;
#else
if (*edx & (1UL << 26))
features |= SSE2;
#endif
if (*ecx & (1UL << 9))
features |= SSSE3;
if (*ecx & (1UL << 19))
features |= SSE41;
if (*ecx & (1UL << 27)) { // OSXSAVE
const uint64_t mask = xgetbv();
if ((mask & 6) == 6) { // SSE and AVX states
if (*ecx & (1UL << 28))
features |= AVX;
if (max_id >= 7) {
cpuidex(regs, 7, 0);
if (*ebx & (1UL << 5))
features |= AVX2;
if ((mask & 224) == 224) { // Opmask, ZMM_Hi256, Hi16_Zmm
if (*ebx & (1UL << 31))
features |= AVX512VL;
if (*ebx & (1UL << 16))
features |= AVX512F;
}
}
}
}
ATOMIC_STORE(g_cpu_features, features);
return features;
#else
/* How to detect NEON? */
return 0;
#endif
}
}
#endif
void blake3_compress_in_place(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags) {
#if defined(IS_X86)
const enum cpu_feature features = get_cpu_features();
MAYBE_UNUSED(features);
#if !defined(BLAKE3_NO_AVX512)
if (features & AVX512VL) {
blake3_compress_in_place_avx512(cv, block, block_len, counter, flags);
return;
}
#endif
#if !defined(BLAKE3_NO_SSE41)
if (features & SSE41) {
blake3_compress_in_place_sse41(cv, block, block_len, counter, flags);
return;
}
#endif
#if !defined(BLAKE3_NO_SSE2)
if (features & SSE2) {
blake3_compress_in_place_sse2(cv, block, block_len, counter, flags);
return;
}
#endif
#endif
blake3_compress_in_place_portable(cv, block, block_len, counter, flags);
}
void blake3_compress_xof(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter, uint8_t flags,
uint8_t out[64]) {
#if defined(IS_X86)
const enum cpu_feature features = get_cpu_features();
MAYBE_UNUSED(features);
#if !defined(BLAKE3_NO_AVX512)
if (features & AVX512VL) {
blake3_compress_xof_avx512(cv, block, block_len, counter, flags, out);
return;
}
#endif
#if !defined(BLAKE3_NO_SSE41)
if (features & SSE41) {
blake3_compress_xof_sse41(cv, block, block_len, counter, flags, out);
return;
}
#endif
#if !defined(BLAKE3_NO_SSE2)
if (features & SSE2) {
blake3_compress_xof_sse2(cv, block, block_len, counter, flags, out);
return;
}
#endif
#endif
blake3_compress_xof_portable(cv, block, block_len, counter, flags, out);
}
void blake3_xof_many(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter, uint8_t flags,
uint8_t out[64], size_t outblocks) {
if (outblocks == 0) {
// The current assembly implementation always outputs at least 1 block.
return;
}
#if defined(IS_X86)
const enum cpu_feature features = get_cpu_features();
MAYBE_UNUSED(features);
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(BLAKE3_NO_AVX512)
if (features & AVX512VL) {
blake3_xof_many_avx512(cv, block, block_len, counter, flags, out, outblocks);
return;
}
#endif
#endif
for(size_t i = 0; i < outblocks; ++i) {
blake3_compress_xof(cv, block, block_len, counter + i, flags, out + 64*i);
}
}
void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8], uint64_t counter,
bool increment_counter, uint8_t flags,
uint8_t flags_start, uint8_t flags_end, uint8_t *out) {
#if defined(IS_X86)
const enum cpu_feature features = get_cpu_features();
MAYBE_UNUSED(features);
#if !defined(BLAKE3_NO_AVX512)
if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) {
blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter,
increment_counter, flags, flags_start, flags_end,
out);
return;
}
#endif
#if !defined(BLAKE3_NO_AVX2)
if (features & AVX2) {
blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter,
increment_counter, flags, flags_start, flags_end,
out);
return;
}
#endif
#if !defined(BLAKE3_NO_SSE41)
if (features & SSE41) {
blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter,
increment_counter, flags, flags_start, flags_end,
out);
return;
}
#endif
#if !defined(BLAKE3_NO_SSE2)
if (features & SSE2) {
blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter,
increment_counter, flags, flags_start, flags_end,
out);
return;
}
#endif
#endif
#if BLAKE3_USE_NEON == 1
blake3_hash_many_neon(inputs, num_inputs, blocks, key, counter,
increment_counter, flags, flags_start, flags_end, out);
return;
#endif
blake3_hash_many_portable(inputs, num_inputs, blocks, key, counter,
increment_counter, flags, flags_start, flags_end,
out);
}
// The dynamically detected SIMD degree of the current platform.
size_t blake3_simd_degree(void) {
#if defined(IS_X86)
const enum cpu_feature features = get_cpu_features();
MAYBE_UNUSED(features);
#if !defined(BLAKE3_NO_AVX512)
if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) {
return 16;
}
#endif
#if !defined(BLAKE3_NO_AVX2)
if (features & AVX2) {
return 8;
}
#endif
#if !defined(BLAKE3_NO_SSE41)
if (features & SSE41) {
return 4;
}
#endif
#if !defined(BLAKE3_NO_SSE2)
if (features & SSE2) {
return 4;
}
#endif
#endif
#if BLAKE3_USE_NEON == 1
return 4;
#endif
return 1;
}
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_impl.h
================================================
#ifndef BLAKE3_IMPL_H
#define BLAKE3_IMPL_H
#include
#include
#include
#include
#include
#include "blake3.h"
#ifdef __cplusplus
extern "C" {
#endif
// internal flags
enum blake3_flags {
CHUNK_START = 1 << 0,
CHUNK_END = 1 << 1,
PARENT = 1 << 2,
ROOT = 1 << 3,
KEYED_HASH = 1 << 4,
DERIVE_KEY_CONTEXT = 1 << 5,
DERIVE_KEY_MATERIAL = 1 << 6,
};
// This C implementation tries to support recent versions of GCC, Clang, and
// MSVC.
#if defined(_MSC_VER)
#define INLINE static __forceinline
#else
#define INLINE static inline __attribute__((always_inline))
#endif
#ifdef __cplusplus
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
#if (defined(__x86_64__) || defined(_M_X64)) && !defined(_M_ARM64EC)
#define IS_X86
#define IS_X86_64
#endif
#if defined(__i386__) || defined(_M_IX86)
#define IS_X86
#define IS_X86_32
#endif
#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
#define IS_AARCH64
#endif
#if defined(IS_X86)
#if defined(_MSC_VER)
#include
#endif
#endif
#if !defined(BLAKE3_USE_NEON)
// If BLAKE3_USE_NEON not manually set, autodetect based on AArch64ness
#if defined(IS_AARCH64)
#if defined(__ARM_BIG_ENDIAN)
#define BLAKE3_USE_NEON 0
#else
#define BLAKE3_USE_NEON 1
#endif
#else
#define BLAKE3_USE_NEON 0
#endif
#endif
#if defined(IS_X86)
#define MAX_SIMD_DEGREE 16
#elif BLAKE3_USE_NEON == 1
#define MAX_SIMD_DEGREE 4
#else
#define MAX_SIMD_DEGREE 1
#endif
// There are some places where we want a static size that's equal to the
// MAX_SIMD_DEGREE, but also at least 2.
#define MAX_SIMD_DEGREE_OR_2 (MAX_SIMD_DEGREE > 2 ? MAX_SIMD_DEGREE : 2)
static const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL,
0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL,
0x1F83D9ABUL, 0x5BE0CD19UL};
static const uint8_t MSG_SCHEDULE[7][16] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8},
{3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1},
{10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6},
{12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4},
{9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7},
{11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13},
};
/* Find index of the highest set bit */
/* x is assumed to be nonzero. */
static unsigned int highest_one(uint64_t x) {
#if defined(__GNUC__) || defined(__clang__)
return 63 ^ (unsigned int)__builtin_clzll(x);
#elif defined(_MSC_VER) && defined(IS_X86_64)
unsigned long index;
_BitScanReverse64(&index, x);
return index;
#elif defined(_MSC_VER) && defined(IS_X86_32)
if(x >> 32) {
unsigned long index;
_BitScanReverse(&index, (unsigned long)(x >> 32));
return 32 + index;
} else {
unsigned long index;
_BitScanReverse(&index, (unsigned long)x);
return index;
}
#else
unsigned int c = 0;
if(x & 0xffffffff00000000ULL) { x >>= 32; c += 32; }
if(x & 0x00000000ffff0000ULL) { x >>= 16; c += 16; }
if(x & 0x000000000000ff00ULL) { x >>= 8; c += 8; }
if(x & 0x00000000000000f0ULL) { x >>= 4; c += 4; }
if(x & 0x000000000000000cULL) { x >>= 2; c += 2; }
if(x & 0x0000000000000002ULL) { c += 1; }
return c;
#endif
}
// Count the number of 1 bits.
INLINE unsigned int popcnt(uint64_t x) {
#if defined(__GNUC__) || defined(__clang__)
return (unsigned int)__builtin_popcountll(x);
#else
unsigned int count = 0;
while (x != 0) {
count += 1;
x &= x - 1;
}
return count;
#endif
}
// Largest power of two less than or equal to x. As a special case, returns 1
// when x is 0.
INLINE uint64_t round_down_to_power_of_2(uint64_t x) {
return 1ULL << highest_one(x | 1);
}
INLINE uint32_t counter_low(uint64_t counter) { return (uint32_t)counter; }
INLINE uint32_t counter_high(uint64_t counter) {
return (uint32_t)(counter >> 32);
}
INLINE uint32_t load32(const void *src) {
const uint8_t *p = (const uint8_t *)src;
return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);
}
INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN],
uint32_t key_words[8]) {
key_words[0] = load32(&key[0 * 4]);
key_words[1] = load32(&key[1 * 4]);
key_words[2] = load32(&key[2 * 4]);
key_words[3] = load32(&key[3 * 4]);
key_words[4] = load32(&key[4 * 4]);
key_words[5] = load32(&key[5 * 4]);
key_words[6] = load32(&key[6 * 4]);
key_words[7] = load32(&key[7 * 4]);
}
INLINE void load_block_words(const uint8_t block[BLAKE3_BLOCK_LEN],
uint32_t block_words[16]) {
for (size_t i = 0; i < 16; i++) {
block_words[i] = load32(&block[i * 4]);
}
}
INLINE void store32(void *dst, uint32_t w) {
uint8_t *p = (uint8_t *)dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
}
INLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) {
store32(&bytes_out[0 * 4], cv_words[0]);
store32(&bytes_out[1 * 4], cv_words[1]);
store32(&bytes_out[2 * 4], cv_words[2]);
store32(&bytes_out[3 * 4], cv_words[3]);
store32(&bytes_out[4 * 4], cv_words[4]);
store32(&bytes_out[5 * 4], cv_words[5]);
store32(&bytes_out[6 * 4], cv_words[6]);
store32(&bytes_out[7 * 4], cv_words[7]);
}
void blake3_compress_in_place(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags);
void blake3_compress_xof(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter, uint8_t flags,
uint8_t out[64]);
void blake3_xof_many(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter, uint8_t flags,
uint8_t out[64], size_t outblocks);
void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8], uint64_t counter,
bool increment_counter, uint8_t flags,
uint8_t flags_start, uint8_t flags_end, uint8_t *out);
size_t blake3_simd_degree(void);
BLAKE3_PRIVATE size_t blake3_compress_subtree_wide(const uint8_t *input, size_t input_len,
const uint32_t key[8],
uint64_t chunk_counter, uint8_t flags,
uint8_t *out, bool use_tbb);
#if defined(BLAKE3_USE_TBB)
BLAKE3_PRIVATE void blake3_compress_subtree_wide_join_tbb(
// shared params
const uint32_t key[8], uint8_t flags, bool use_tbb,
// left-hand side params
const uint8_t *l_input, size_t l_input_len, uint64_t l_chunk_counter,
uint8_t *l_cvs, size_t *l_n,
// right-hand side params
const uint8_t *r_input, size_t r_input_len, uint64_t r_chunk_counter,
uint8_t *r_cvs, size_t *r_n) NOEXCEPT;
#endif
// Declarations for implementation-specific functions.
void blake3_compress_in_place_portable(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags);
void blake3_compress_xof_portable(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags, uint8_t out[64]);
void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out);
#if defined(IS_X86)
#if !defined(BLAKE3_NO_SSE2)
void blake3_compress_in_place_sse2(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags);
void blake3_compress_xof_sse2(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags, uint8_t out[64]);
void blake3_hash_many_sse2(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out);
#endif
#if !defined(BLAKE3_NO_SSE41)
void blake3_compress_in_place_sse41(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags);
void blake3_compress_xof_sse41(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags, uint8_t out[64]);
void blake3_hash_many_sse41(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out);
#endif
#if !defined(BLAKE3_NO_AVX2)
void blake3_hash_many_avx2(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out);
#endif
#if !defined(BLAKE3_NO_AVX512)
void blake3_compress_in_place_avx512(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags);
void blake3_compress_xof_avx512(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags, uint8_t out[64]);
void blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out);
#if !defined(_WIN32) && !defined(__CYGWIN__)
void blake3_xof_many_avx512(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter, uint8_t flags,
uint8_t* out, size_t outblocks);
#endif
#endif
#endif
#if BLAKE3_USE_NEON == 1
void blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out);
#endif
#ifdef __cplusplus
}
#endif
#endif /* BLAKE3_IMPL_H */
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_neon.c
================================================
#include "blake3_impl.h"
#include
#ifdef __ARM_BIG_ENDIAN
#error "This implementation only supports little-endian ARM."
// It might be that all we need for big-endian support here is to get the loads
// and stores right, but step zero would be finding a way to test it in CI.
#endif
INLINE uint32x4_t loadu_128(const uint8_t src[16]) {
// vld1q_u32 has alignment requirements. Don't use it.
return vreinterpretq_u32_u8(vld1q_u8(src));
}
INLINE void storeu_128(uint32x4_t src, uint8_t dest[16]) {
// vst1q_u32 has alignment requirements. Don't use it.
vst1q_u8(dest, vreinterpretq_u8_u32(src));
}
INLINE uint32x4_t add_128(uint32x4_t a, uint32x4_t b) {
return vaddq_u32(a, b);
}
INLINE uint32x4_t xor_128(uint32x4_t a, uint32x4_t b) {
return veorq_u32(a, b);
}
INLINE uint32x4_t set1_128(uint32_t x) { return vld1q_dup_u32(&x); }
INLINE uint32x4_t set4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
uint32_t array[4] = {a, b, c, d};
return vld1q_u32(array);
}
INLINE uint32x4_t rot16_128(uint32x4_t x) {
// The straightforward implementation would be two shifts and an or, but that's
// slower on microarchitectures we've tested. See
// https://github.com/BLAKE3-team/BLAKE3/pull/319.
// return vorrq_u32(vshrq_n_u32(x, 16), vshlq_n_u32(x, 32 - 16));
return vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(x)));
}
INLINE uint32x4_t rot12_128(uint32x4_t x) {
// See comment in rot16_128.
// return vorrq_u32(vshrq_n_u32(x, 12), vshlq_n_u32(x, 32 - 12));
return vsriq_n_u32(vshlq_n_u32(x, 32-12), x, 12);
}
INLINE uint32x4_t rot8_128(uint32x4_t x) {
// See comment in rot16_128.
// return vorrq_u32(vshrq_n_u32(x, 8), vshlq_n_u32(x, 32 - 8));
#if defined(__clang__)
return vreinterpretq_u32_u8(__builtin_shufflevector(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12));
#elif __GNUC__ * 10000 + __GNUC_MINOR__ * 100 >=40700
static const uint8x16_t r8 = {1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12};
return vreinterpretq_u32_u8(__builtin_shuffle(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), r8));
#else
return vsriq_n_u32(vshlq_n_u32(x, 32-8), x, 8);
#endif
}
INLINE uint32x4_t rot7_128(uint32x4_t x) {
// See comment in rot16_128.
// return vorrq_u32(vshrq_n_u32(x, 7), vshlq_n_u32(x, 32 - 7));
return vsriq_n_u32(vshlq_n_u32(x, 32-7), x, 7);
}
// TODO: compress_neon
// TODO: hash2_neon
/*
* ----------------------------------------------------------------------------
* hash4_neon
* ----------------------------------------------------------------------------
*/
INLINE void round_fn4(uint32x4_t v[16], uint32x4_t m[16], size_t r) {
v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][0]]);
v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][2]]);
v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][4]]);
v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][6]]);
v[0] = add_128(v[0], v[4]);
v[1] = add_128(v[1], v[5]);
v[2] = add_128(v[2], v[6]);
v[3] = add_128(v[3], v[7]);
v[12] = xor_128(v[12], v[0]);
v[13] = xor_128(v[13], v[1]);
v[14] = xor_128(v[14], v[2]);
v[15] = xor_128(v[15], v[3]);
v[12] = rot16_128(v[12]);
v[13] = rot16_128(v[13]);
v[14] = rot16_128(v[14]);
v[15] = rot16_128(v[15]);
v[8] = add_128(v[8], v[12]);
v[9] = add_128(v[9], v[13]);
v[10] = add_128(v[10], v[14]);
v[11] = add_128(v[11], v[15]);
v[4] = xor_128(v[4], v[8]);
v[5] = xor_128(v[5], v[9]);
v[6] = xor_128(v[6], v[10]);
v[7] = xor_128(v[7], v[11]);
v[4] = rot12_128(v[4]);
v[5] = rot12_128(v[5]);
v[6] = rot12_128(v[6]);
v[7] = rot12_128(v[7]);
v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][1]]);
v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][3]]);
v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][5]]);
v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][7]]);
v[0] = add_128(v[0], v[4]);
v[1] = add_128(v[1], v[5]);
v[2] = add_128(v[2], v[6]);
v[3] = add_128(v[3], v[7]);
v[12] = xor_128(v[12], v[0]);
v[13] = xor_128(v[13], v[1]);
v[14] = xor_128(v[14], v[2]);
v[15] = xor_128(v[15], v[3]);
v[12] = rot8_128(v[12]);
v[13] = rot8_128(v[13]);
v[14] = rot8_128(v[14]);
v[15] = rot8_128(v[15]);
v[8] = add_128(v[8], v[12]);
v[9] = add_128(v[9], v[13]);
v[10] = add_128(v[10], v[14]);
v[11] = add_128(v[11], v[15]);
v[4] = xor_128(v[4], v[8]);
v[5] = xor_128(v[5], v[9]);
v[6] = xor_128(v[6], v[10]);
v[7] = xor_128(v[7], v[11]);
v[4] = rot7_128(v[4]);
v[5] = rot7_128(v[5]);
v[6] = rot7_128(v[6]);
v[7] = rot7_128(v[7]);
v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][8]]);
v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][10]]);
v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][12]]);
v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][14]]);
v[0] = add_128(v[0], v[5]);
v[1] = add_128(v[1], v[6]);
v[2] = add_128(v[2], v[7]);
v[3] = add_128(v[3], v[4]);
v[15] = xor_128(v[15], v[0]);
v[12] = xor_128(v[12], v[1]);
v[13] = xor_128(v[13], v[2]);
v[14] = xor_128(v[14], v[3]);
v[15] = rot16_128(v[15]);
v[12] = rot16_128(v[12]);
v[13] = rot16_128(v[13]);
v[14] = rot16_128(v[14]);
v[10] = add_128(v[10], v[15]);
v[11] = add_128(v[11], v[12]);
v[8] = add_128(v[8], v[13]);
v[9] = add_128(v[9], v[14]);
v[5] = xor_128(v[5], v[10]);
v[6] = xor_128(v[6], v[11]);
v[7] = xor_128(v[7], v[8]);
v[4] = xor_128(v[4], v[9]);
v[5] = rot12_128(v[5]);
v[6] = rot12_128(v[6]);
v[7] = rot12_128(v[7]);
v[4] = rot12_128(v[4]);
v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][9]]);
v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][11]]);
v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][13]]);
v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][15]]);
v[0] = add_128(v[0], v[5]);
v[1] = add_128(v[1], v[6]);
v[2] = add_128(v[2], v[7]);
v[3] = add_128(v[3], v[4]);
v[15] = xor_128(v[15], v[0]);
v[12] = xor_128(v[12], v[1]);
v[13] = xor_128(v[13], v[2]);
v[14] = xor_128(v[14], v[3]);
v[15] = rot8_128(v[15]);
v[12] = rot8_128(v[12]);
v[13] = rot8_128(v[13]);
v[14] = rot8_128(v[14]);
v[10] = add_128(v[10], v[15]);
v[11] = add_128(v[11], v[12]);
v[8] = add_128(v[8], v[13]);
v[9] = add_128(v[9], v[14]);
v[5] = xor_128(v[5], v[10]);
v[6] = xor_128(v[6], v[11]);
v[7] = xor_128(v[7], v[8]);
v[4] = xor_128(v[4], v[9]);
v[5] = rot7_128(v[5]);
v[6] = rot7_128(v[6]);
v[7] = rot7_128(v[7]);
v[4] = rot7_128(v[4]);
}
INLINE void transpose_vecs_128(uint32x4_t vecs[4]) {
// Individually transpose the four 2x2 sub-matrices in each corner.
uint32x4x2_t rows01 = vtrnq_u32(vecs[0], vecs[1]);
uint32x4x2_t rows23 = vtrnq_u32(vecs[2], vecs[3]);
// Swap the top-right and bottom-left 2x2s (which just got transposed).
vecs[0] =
vcombine_u32(vget_low_u32(rows01.val[0]), vget_low_u32(rows23.val[0]));
vecs[1] =
vcombine_u32(vget_low_u32(rows01.val[1]), vget_low_u32(rows23.val[1]));
vecs[2] =
vcombine_u32(vget_high_u32(rows01.val[0]), vget_high_u32(rows23.val[0]));
vecs[3] =
vcombine_u32(vget_high_u32(rows01.val[1]), vget_high_u32(rows23.val[1]));
}
INLINE void transpose_msg_vecs4(const uint8_t *const *inputs,
size_t block_offset, uint32x4_t out[16]) {
out[0] = loadu_128(&inputs[0][block_offset + 0 * sizeof(uint32x4_t)]);
out[1] = loadu_128(&inputs[1][block_offset + 0 * sizeof(uint32x4_t)]);
out[2] = loadu_128(&inputs[2][block_offset + 0 * sizeof(uint32x4_t)]);
out[3] = loadu_128(&inputs[3][block_offset + 0 * sizeof(uint32x4_t)]);
out[4] = loadu_128(&inputs[0][block_offset + 1 * sizeof(uint32x4_t)]);
out[5] = loadu_128(&inputs[1][block_offset + 1 * sizeof(uint32x4_t)]);
out[6] = loadu_128(&inputs[2][block_offset + 1 * sizeof(uint32x4_t)]);
out[7] = loadu_128(&inputs[3][block_offset + 1 * sizeof(uint32x4_t)]);
out[8] = loadu_128(&inputs[0][block_offset + 2 * sizeof(uint32x4_t)]);
out[9] = loadu_128(&inputs[1][block_offset + 2 * sizeof(uint32x4_t)]);
out[10] = loadu_128(&inputs[2][block_offset + 2 * sizeof(uint32x4_t)]);
out[11] = loadu_128(&inputs[3][block_offset + 2 * sizeof(uint32x4_t)]);
out[12] = loadu_128(&inputs[0][block_offset + 3 * sizeof(uint32x4_t)]);
out[13] = loadu_128(&inputs[1][block_offset + 3 * sizeof(uint32x4_t)]);
out[14] = loadu_128(&inputs[2][block_offset + 3 * sizeof(uint32x4_t)]);
out[15] = loadu_128(&inputs[3][block_offset + 3 * sizeof(uint32x4_t)]);
transpose_vecs_128(&out[0]);
transpose_vecs_128(&out[4]);
transpose_vecs_128(&out[8]);
transpose_vecs_128(&out[12]);
}
INLINE void load_counters4(uint64_t counter, bool increment_counter,
uint32x4_t *out_low, uint32x4_t *out_high) {
uint64_t mask = (increment_counter ? ~0 : 0);
*out_low = set4(
counter_low(counter + (mask & 0)), counter_low(counter + (mask & 1)),
counter_low(counter + (mask & 2)), counter_low(counter + (mask & 3)));
*out_high = set4(
counter_high(counter + (mask & 0)), counter_high(counter + (mask & 1)),
counter_high(counter + (mask & 2)), counter_high(counter + (mask & 3)));
}
static void blake3_hash4_neon(const uint8_t *const *inputs, size_t blocks,
const uint32_t key[8], uint64_t counter,
bool increment_counter, uint8_t flags,
uint8_t flags_start, uint8_t flags_end,
uint8_t *out) {
uint32x4_t h_vecs[8] = {
set1_128(key[0]), set1_128(key[1]), set1_128(key[2]), set1_128(key[3]),
set1_128(key[4]), set1_128(key[5]), set1_128(key[6]), set1_128(key[7]),
};
uint32x4_t counter_low_vec, counter_high_vec;
load_counters4(counter, increment_counter, &counter_low_vec,
&counter_high_vec);
uint8_t block_flags = flags | flags_start;
for (size_t block = 0; block < blocks; block++) {
if (block + 1 == blocks) {
block_flags |= flags_end;
}
uint32x4_t block_len_vec = set1_128(BLAKE3_BLOCK_LEN);
uint32x4_t block_flags_vec = set1_128(block_flags);
uint32x4_t msg_vecs[16];
transpose_msg_vecs4(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs);
uint32x4_t v[16] = {
h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3],
h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7],
set1_128(IV[0]), set1_128(IV[1]), set1_128(IV[2]), set1_128(IV[3]),
counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec,
};
round_fn4(v, msg_vecs, 0);
round_fn4(v, msg_vecs, 1);
round_fn4(v, msg_vecs, 2);
round_fn4(v, msg_vecs, 3);
round_fn4(v, msg_vecs, 4);
round_fn4(v, msg_vecs, 5);
round_fn4(v, msg_vecs, 6);
h_vecs[0] = xor_128(v[0], v[8]);
h_vecs[1] = xor_128(v[1], v[9]);
h_vecs[2] = xor_128(v[2], v[10]);
h_vecs[3] = xor_128(v[3], v[11]);
h_vecs[4] = xor_128(v[4], v[12]);
h_vecs[5] = xor_128(v[5], v[13]);
h_vecs[6] = xor_128(v[6], v[14]);
h_vecs[7] = xor_128(v[7], v[15]);
block_flags = flags;
}
transpose_vecs_128(&h_vecs[0]);
transpose_vecs_128(&h_vecs[4]);
// The first four vecs now contain the first half of each output, and the
// second four vecs contain the second half of each output.
storeu_128(h_vecs[0], &out[0 * sizeof(uint32x4_t)]);
storeu_128(h_vecs[4], &out[1 * sizeof(uint32x4_t)]);
storeu_128(h_vecs[1], &out[2 * sizeof(uint32x4_t)]);
storeu_128(h_vecs[5], &out[3 * sizeof(uint32x4_t)]);
storeu_128(h_vecs[2], &out[4 * sizeof(uint32x4_t)]);
storeu_128(h_vecs[6], &out[5 * sizeof(uint32x4_t)]);
storeu_128(h_vecs[3], &out[6 * sizeof(uint32x4_t)]);
storeu_128(h_vecs[7], &out[7 * sizeof(uint32x4_t)]);
}
/*
* ----------------------------------------------------------------------------
* hash_many_neon
* ----------------------------------------------------------------------------
*/
void blake3_compress_in_place_portable(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags);
INLINE void hash_one_neon(const uint8_t *input, size_t blocks,
const uint32_t key[8], uint64_t counter,
uint8_t flags, uint8_t flags_start, uint8_t flags_end,
uint8_t out[BLAKE3_OUT_LEN]) {
uint32_t cv[8];
memcpy(cv, key, BLAKE3_KEY_LEN);
uint8_t block_flags = flags | flags_start;
while (blocks > 0) {
if (blocks == 1) {
block_flags |= flags_end;
}
// TODO: Implement compress_neon. However note that according to
// https://github.com/BLAKE2/BLAKE2/commit/7965d3e6e1b4193438b8d3a656787587d2579227,
// compress_neon might not be any faster than compress_portable.
blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter,
block_flags);
input = &input[BLAKE3_BLOCK_LEN];
blocks -= 1;
block_flags = flags;
}
memcpy(out, cv, BLAKE3_OUT_LEN);
}
void blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out) {
while (num_inputs >= 4) {
blake3_hash4_neon(inputs, blocks, key, counter, increment_counter, flags,
flags_start, flags_end, out);
if (increment_counter) {
counter += 4;
}
inputs += 4;
num_inputs -= 4;
out = &out[4 * BLAKE3_OUT_LEN];
}
while (num_inputs > 0) {
hash_one_neon(inputs[0], blocks, key, counter, flags, flags_start,
flags_end, out);
if (increment_counter) {
counter += 1;
}
inputs += 1;
num_inputs -= 1;
out = &out[BLAKE3_OUT_LEN];
}
}
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_portable.c
================================================
#include "blake3_impl.h"
#include
INLINE uint32_t rotr32(uint32_t w, uint32_t c) {
return (w >> c) | (w << (32 - c));
}
INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d,
uint32_t x, uint32_t y) {
state[a] = state[a] + state[b] + x;
state[d] = rotr32(state[d] ^ state[a], 16);
state[c] = state[c] + state[d];
state[b] = rotr32(state[b] ^ state[c], 12);
state[a] = state[a] + state[b] + y;
state[d] = rotr32(state[d] ^ state[a], 8);
state[c] = state[c] + state[d];
state[b] = rotr32(state[b] ^ state[c], 7);
}
INLINE void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) {
// Select the message schedule based on the round.
const uint8_t *schedule = MSG_SCHEDULE[round];
// Mix the columns.
g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]);
g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]);
g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]);
g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]);
// Mix the rows.
g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]);
g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]);
g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]);
g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]);
}
INLINE void compress_pre(uint32_t state[16], const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter, uint8_t flags) {
uint32_t block_words[16];
block_words[0] = load32(block + 4 * 0);
block_words[1] = load32(block + 4 * 1);
block_words[2] = load32(block + 4 * 2);
block_words[3] = load32(block + 4 * 3);
block_words[4] = load32(block + 4 * 4);
block_words[5] = load32(block + 4 * 5);
block_words[6] = load32(block + 4 * 6);
block_words[7] = load32(block + 4 * 7);
block_words[8] = load32(block + 4 * 8);
block_words[9] = load32(block + 4 * 9);
block_words[10] = load32(block + 4 * 10);
block_words[11] = load32(block + 4 * 11);
block_words[12] = load32(block + 4 * 12);
block_words[13] = load32(block + 4 * 13);
block_words[14] = load32(block + 4 * 14);
block_words[15] = load32(block + 4 * 15);
state[0] = cv[0];
state[1] = cv[1];
state[2] = cv[2];
state[3] = cv[3];
state[4] = cv[4];
state[5] = cv[5];
state[6] = cv[6];
state[7] = cv[7];
state[8] = IV[0];
state[9] = IV[1];
state[10] = IV[2];
state[11] = IV[3];
state[12] = counter_low(counter);
state[13] = counter_high(counter);
state[14] = (uint32_t)block_len;
state[15] = (uint32_t)flags;
round_fn(state, &block_words[0], 0);
round_fn(state, &block_words[0], 1);
round_fn(state, &block_words[0], 2);
round_fn(state, &block_words[0], 3);
round_fn(state, &block_words[0], 4);
round_fn(state, &block_words[0], 5);
round_fn(state, &block_words[0], 6);
}
void blake3_compress_in_place_portable(uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags) {
uint32_t state[16];
compress_pre(state, cv, block, block_len, counter, flags);
cv[0] = state[0] ^ state[8];
cv[1] = state[1] ^ state[9];
cv[2] = state[2] ^ state[10];
cv[3] = state[3] ^ state[11];
cv[4] = state[4] ^ state[12];
cv[5] = state[5] ^ state[13];
cv[6] = state[6] ^ state[14];
cv[7] = state[7] ^ state[15];
}
void blake3_compress_xof_portable(const uint32_t cv[8],
const uint8_t block[BLAKE3_BLOCK_LEN],
uint8_t block_len, uint64_t counter,
uint8_t flags, uint8_t out[64]) {
uint32_t state[16];
compress_pre(state, cv, block, block_len, counter, flags);
store32(&out[0 * 4], state[0] ^ state[8]);
store32(&out[1 * 4], state[1] ^ state[9]);
store32(&out[2 * 4], state[2] ^ state[10]);
store32(&out[3 * 4], state[3] ^ state[11]);
store32(&out[4 * 4], state[4] ^ state[12]);
store32(&out[5 * 4], state[5] ^ state[13]);
store32(&out[6 * 4], state[6] ^ state[14]);
store32(&out[7 * 4], state[7] ^ state[15]);
store32(&out[8 * 4], state[8] ^ cv[0]);
store32(&out[9 * 4], state[9] ^ cv[1]);
store32(&out[10 * 4], state[10] ^ cv[2]);
store32(&out[11 * 4], state[11] ^ cv[3]);
store32(&out[12 * 4], state[12] ^ cv[4]);
store32(&out[13 * 4], state[13] ^ cv[5]);
store32(&out[14 * 4], state[14] ^ cv[6]);
store32(&out[15 * 4], state[15] ^ cv[7]);
}
INLINE void hash_one_portable(const uint8_t *input, size_t blocks,
const uint32_t key[8], uint64_t counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) {
uint32_t cv[8];
memcpy(cv, key, BLAKE3_KEY_LEN);
uint8_t block_flags = flags | flags_start;
while (blocks > 0) {
if (blocks == 1) {
block_flags |= flags_end;
}
blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter,
block_flags);
input = &input[BLAKE3_BLOCK_LEN];
blocks -= 1;
block_flags = flags;
}
store_cv_words(out, cv);
}
void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out) {
while (num_inputs > 0) {
hash_one_portable(inputs[0], blocks, key, counter, flags, flags_start,
flags_end, out);
if (increment_counter) {
counter += 1;
}
inputs += 1;
num_inputs -= 1;
out = &out[BLAKE3_OUT_LEN];
}
}
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_sse2_x86-64_windows_msvc.asm
================================================
public _blake3_hash_many_sse2
public blake3_hash_many_sse2
public blake3_compress_in_place_sse2
public _blake3_compress_in_place_sse2
public blake3_compress_xof_sse2
public _blake3_compress_xof_sse2
_TEXT SEGMENT ALIGN(16) 'CODE'
ALIGN 16
blake3_hash_many_sse2 PROC
_blake3_hash_many_sse2 PROC
push r15
push r14
push r13
push r12
push rsi
push rdi
push rbx
push rbp
mov rbp, rsp
sub rsp, 528
and rsp, 0FFFFFFFFFFFFFFC0H
movdqa xmmword ptr [rsp+170H], xmm6
movdqa xmmword ptr [rsp+180H], xmm7
movdqa xmmword ptr [rsp+190H], xmm8
movdqa xmmword ptr [rsp+1A0H], xmm9
movdqa xmmword ptr [rsp+1B0H], xmm10
movdqa xmmword ptr [rsp+1C0H], xmm11
movdqa xmmword ptr [rsp+1D0H], xmm12
movdqa xmmword ptr [rsp+1E0H], xmm13
movdqa xmmword ptr [rsp+1F0H], xmm14
movdqa xmmword ptr [rsp+200H], xmm15
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, qword ptr [rbp+68H]
movzx r9, byte ptr [rbp+70H]
neg r9d
movd xmm0, r9d
pshufd xmm0, xmm0, 00H
movdqa xmmword ptr [rsp+130H], xmm0
movdqa xmm1, xmm0
pand xmm1, xmmword ptr [ADD0]
pand xmm0, xmmword ptr [ADD1]
movdqa xmmword ptr [rsp+150H], xmm0
movd xmm0, r8d
pshufd xmm0, xmm0, 00H
paddd xmm0, xmm1
movdqa xmmword ptr [rsp+110H], xmm0
pxor xmm0, xmmword ptr [CMP_MSB_MASK]
pxor xmm1, xmmword ptr [CMP_MSB_MASK]
pcmpgtd xmm1, xmm0
shr r8, 32
movd xmm2, r8d
pshufd xmm2, xmm2, 00H
psubd xmm2, xmm1
movdqa xmmword ptr [rsp+120H], xmm2
mov rbx, qword ptr [rbp+90H]
mov r15, rdx
shl r15, 6
movzx r13d, byte ptr [rbp+78H]
movzx r12d, byte ptr [rbp+88H]
cmp rsi, 4
jc final3blocks
outerloop4:
movdqu xmm3, xmmword ptr [rcx]
pshufd xmm0, xmm3, 00H
pshufd xmm1, xmm3, 55H
pshufd xmm2, xmm3, 0AAH
pshufd xmm3, xmm3, 0FFH
movdqu xmm7, xmmword ptr [rcx+10H]
pshufd xmm4, xmm7, 00H
pshufd xmm5, xmm7, 55H
pshufd xmm6, xmm7, 0AAH
pshufd xmm7, xmm7, 0FFH
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
innerloop4:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
movdqu xmm8, xmmword ptr [r8+rdx-40H]
movdqu xmm9, xmmword ptr [r9+rdx-40H]
movdqu xmm10, xmmword ptr [r10+rdx-40H]
movdqu xmm11, xmmword ptr [r11+rdx-40H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp], xmm8
movdqa xmmword ptr [rsp+10H], xmm9
movdqa xmmword ptr [rsp+20H], xmm12
movdqa xmmword ptr [rsp+30H], xmm13
movdqu xmm8, xmmword ptr [r8+rdx-30H]
movdqu xmm9, xmmword ptr [r9+rdx-30H]
movdqu xmm10, xmmword ptr [r10+rdx-30H]
movdqu xmm11, xmmword ptr [r11+rdx-30H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp+40H], xmm8
movdqa xmmword ptr [rsp+50H], xmm9
movdqa xmmword ptr [rsp+60H], xmm12
movdqa xmmword ptr [rsp+70H], xmm13
movdqu xmm8, xmmword ptr [r8+rdx-20H]
movdqu xmm9, xmmword ptr [r9+rdx-20H]
movdqu xmm10, xmmword ptr [r10+rdx-20H]
movdqu xmm11, xmmword ptr [r11+rdx-20H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp+80H], xmm8
movdqa xmmword ptr [rsp+90H], xmm9
movdqa xmmword ptr [rsp+0A0H], xmm12
movdqa xmmword ptr [rsp+0B0H], xmm13
movdqu xmm8, xmmword ptr [r8+rdx-10H]
movdqu xmm9, xmmword ptr [r9+rdx-10H]
movdqu xmm10, xmmword ptr [r10+rdx-10H]
movdqu xmm11, xmmword ptr [r11+rdx-10H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp+0C0H], xmm8
movdqa xmmword ptr [rsp+0D0H], xmm9
movdqa xmmword ptr [rsp+0E0H], xmm12
movdqa xmmword ptr [rsp+0F0H], xmm13
movdqa xmm9, xmmword ptr [BLAKE3_IV_1]
movdqa xmm10, xmmword ptr [BLAKE3_IV_2]
movdqa xmm11, xmmword ptr [BLAKE3_IV_3]
movdqa xmm12, xmmword ptr [rsp+110H]
movdqa xmm13, xmmword ptr [rsp+120H]
movdqa xmm14, xmmword ptr [BLAKE3_BLOCK_LEN]
movd xmm15, eax
pshufd xmm15, xmm15, 00H
prefetcht0 byte ptr [r8+rdx+80H]
prefetcht0 byte ptr [r9+rdx+80H]
prefetcht0 byte ptr [r10+rdx+80H]
prefetcht0 byte ptr [r11+rdx+80H]
paddd xmm0, xmmword ptr [rsp]
paddd xmm1, xmmword ptr [rsp+20H]
paddd xmm2, xmmword ptr [rsp+40H]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
movdqa xmm8, xmmword ptr [BLAKE3_IV_0]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+10H]
paddd xmm1, xmmword ptr [rsp+30H]
paddd xmm2, xmmword ptr [rsp+50H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+80H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp+0C0H]
paddd xmm3, xmmword ptr [rsp+0E0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+90H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+0D0H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+20H]
paddd xmm1, xmmword ptr [rsp+30H]
paddd xmm2, xmmword ptr [rsp+70H]
paddd xmm3, xmmword ptr [rsp+40H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+60H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp]
paddd xmm3, xmmword ptr [rsp+0D0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+10H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+90H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0B0H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp+0E0H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+30H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp+0D0H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+40H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+20H]
paddd xmm3, xmmword ptr [rsp+0E0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+60H]
paddd xmm1, xmmword ptr [rsp+90H]
paddd xmm2, xmmword ptr [rsp+0B0H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+50H]
paddd xmm1, xmmword ptr [rsp]
paddd xmm2, xmmword ptr [rsp+0F0H]
paddd xmm3, xmmword ptr [rsp+10H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0A0H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+0E0H]
paddd xmm3, xmmword ptr [rsp+0D0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+70H]
paddd xmm1, xmmword ptr [rsp+90H]
paddd xmm2, xmmword ptr [rsp+30H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+40H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+50H]
paddd xmm3, xmmword ptr [rsp+10H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp]
paddd xmm1, xmmword ptr [rsp+20H]
paddd xmm2, xmmword ptr [rsp+80H]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0C0H]
paddd xmm1, xmmword ptr [rsp+90H]
paddd xmm2, xmmword ptr [rsp+0F0H]
paddd xmm3, xmmword ptr [rsp+0E0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0D0H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+0A0H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+70H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+20H]
paddd xmm1, xmmword ptr [rsp+30H]
paddd xmm2, xmmword ptr [rsp+10H]
paddd xmm3, xmmword ptr [rsp+40H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+90H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+80H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0E0H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp+0C0H]
paddd xmm3, xmmword ptr [rsp+10H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0D0H]
paddd xmm1, xmmword ptr [rsp]
paddd xmm2, xmmword ptr [rsp+20H]
paddd xmm3, xmmword ptr [rsp+40H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+30H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp+60H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0B0H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp+10H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0F0H]
paddd xmm1, xmmword ptr [rsp]
paddd xmm2, xmmword ptr [rsp+90H]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0E0H]
paddd xmm1, xmmword ptr [rsp+20H]
paddd xmm2, xmmword ptr [rsp+30H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
pshuflw xmm15, xmm15, 0B1H
pshufhw xmm15, xmm15, 0B1H
pshuflw xmm12, xmm12, 0B1H
pshufhw xmm12, xmm12, 0B1H
pshuflw xmm13, xmm13, 0B1H
pshufhw xmm13, xmm13, 0B1H
pshuflw xmm14, xmm14, 0B1H
pshufhw xmm14, xmm14, 0B1H
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0A0H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+40H]
paddd xmm3, xmmword ptr [rsp+0D0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmm15
psrld xmm15, 8
pslld xmm8, 24
pxor xmm15, xmm8
movdqa xmm8, xmm12
psrld xmm12, 8
pslld xmm8, 24
pxor xmm12, xmm8
movdqa xmm8, xmm13
psrld xmm13, 8
pslld xmm8, 24
pxor xmm13, xmm8
movdqa xmm8, xmm14
psrld xmm14, 8
pslld xmm8, 24
pxor xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
pxor xmm0, xmm8
pxor xmm1, xmm9
pxor xmm2, xmm10
pxor xmm3, xmm11
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
pxor xmm4, xmm12
pxor xmm5, xmm13
pxor xmm6, xmm14
pxor xmm7, xmm15
mov eax, r13d
jne innerloop4
movdqa xmm9, xmm0
punpckldq xmm0, xmm1
punpckhdq xmm9, xmm1
movdqa xmm11, xmm2
punpckldq xmm2, xmm3
punpckhdq xmm11, xmm3
movdqa xmm1, xmm0
punpcklqdq xmm0, xmm2
punpckhqdq xmm1, xmm2
movdqa xmm3, xmm9
punpcklqdq xmm9, xmm11
punpckhqdq xmm3, xmm11
movdqu xmmword ptr [rbx], xmm0
movdqu xmmword ptr [rbx+20H], xmm1
movdqu xmmword ptr [rbx+40H], xmm9
movdqu xmmword ptr [rbx+60H], xmm3
movdqa xmm9, xmm4
punpckldq xmm4, xmm5
punpckhdq xmm9, xmm5
movdqa xmm11, xmm6
punpckldq xmm6, xmm7
punpckhdq xmm11, xmm7
movdqa xmm5, xmm4
punpcklqdq xmm4, xmm6
punpckhqdq xmm5, xmm6
movdqa xmm7, xmm9
punpcklqdq xmm9, xmm11
punpckhqdq xmm7, xmm11
movdqu xmmword ptr [rbx+10H], xmm4
movdqu xmmword ptr [rbx+30H], xmm5
movdqu xmmword ptr [rbx+50H], xmm9
movdqu xmmword ptr [rbx+70H], xmm7
movdqa xmm1, xmmword ptr [rsp+110H]
movdqa xmm0, xmm1
paddd xmm1, xmmword ptr [rsp+150H]
movdqa xmmword ptr [rsp+110H], xmm1
pxor xmm0, xmmword ptr [CMP_MSB_MASK]
pxor xmm1, xmmword ptr [CMP_MSB_MASK]
pcmpgtd xmm0, xmm1
movdqa xmm1, xmmword ptr [rsp+120H]
psubd xmm1, xmm0
movdqa xmmword ptr [rsp+120H], xmm1
add rbx, 128
add rdi, 32
sub rsi, 4
cmp rsi, 4
jnc outerloop4
test rsi, rsi
jne final3blocks
unwind:
movdqa xmm6, xmmword ptr [rsp+170H]
movdqa xmm7, xmmword ptr [rsp+180H]
movdqa xmm8, xmmword ptr [rsp+190H]
movdqa xmm9, xmmword ptr [rsp+1A0H]
movdqa xmm10, xmmword ptr [rsp+1B0H]
movdqa xmm11, xmmword ptr [rsp+1C0H]
movdqa xmm12, xmmword ptr [rsp+1D0H]
movdqa xmm13, xmmword ptr [rsp+1E0H]
movdqa xmm14, xmmword ptr [rsp+1F0H]
movdqa xmm15, xmmword ptr [rsp+200H]
mov rsp, rbp
pop rbp
pop rbx
pop rdi
pop rsi
pop r12
pop r13
pop r14
pop r15
ret
ALIGN 16
final3blocks:
test esi, 2H
je final1block
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movaps xmm8, xmm0
movaps xmm9, xmm1
movd xmm13, dword ptr [rsp+110H]
movd xmm14, dword ptr [rsp+120H]
punpckldq xmm13, xmm14
movaps xmmword ptr [rsp], xmm13
movd xmm14, dword ptr [rsp+114H]
movd xmm13, dword ptr [rsp+124H]
punpckldq xmm14, xmm13
movaps xmmword ptr [rsp+10H], xmm14
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
innerloop2:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
movaps xmm2, xmmword ptr [BLAKE3_IV]
movaps xmm10, xmm2
movups xmm4, xmmword ptr [r8+rdx-40H]
movups xmm5, xmmword ptr [r8+rdx-30H]
movaps xmm3, xmm4
shufps xmm4, xmm5, 136
shufps xmm3, xmm5, 221
movaps xmm5, xmm3
movups xmm6, xmmword ptr [r8+rdx-20H]
movups xmm7, xmmword ptr [r8+rdx-10H]
movaps xmm3, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm3, xmm7, 221
pshufd xmm7, xmm3, 93H
movups xmm12, xmmword ptr [r9+rdx-40H]
movups xmm13, xmmword ptr [r9+rdx-30H]
movaps xmm11, xmm12
shufps xmm12, xmm13, 136
shufps xmm11, xmm13, 221
movaps xmm13, xmm11
movups xmm14, xmmword ptr [r9+rdx-20H]
movups xmm15, xmmword ptr [r9+rdx-10H]
movaps xmm11, xmm14
shufps xmm14, xmm15, 136
pshufd xmm14, xmm14, 93H
shufps xmm11, xmm15, 221
pshufd xmm15, xmm11, 93H
shl rax, 20H
or rax, 40H
movd xmm3, rax
movdqa xmmword ptr [rsp+20H], xmm3
movaps xmm3, xmmword ptr [rsp]
movaps xmm11, xmmword ptr [rsp+10H]
punpcklqdq xmm3, xmmword ptr [rsp+20H]
punpcklqdq xmm11, xmmword ptr [rsp+20H]
mov al, 7
roundloop2:
paddd xmm0, xmm4
paddd xmm8, xmm12
movaps xmmword ptr [rsp+20H], xmm4
movaps xmmword ptr [rsp+30H], xmm12
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
pshuflw xmm11, xmm11, 0B1H
pshufhw xmm11, xmm11, 0B1H
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 20
psrld xmm4, 12
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 20
psrld xmm4, 12
por xmm9, xmm4
paddd xmm0, xmm5
paddd xmm8, xmm13
movaps xmmword ptr [rsp+40H], xmm5
movaps xmmword ptr [rsp+50H], xmm13
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
movdqa xmm13, xmm3
psrld xmm3, 8
pslld xmm13, 24
pxor xmm3, xmm13
movdqa xmm13, xmm11
psrld xmm11, 8
pslld xmm13, 24
pxor xmm11, xmm13
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 25
psrld xmm4, 7
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 25
psrld xmm4, 7
por xmm9, xmm4
pshufd xmm0, xmm0, 93H
pshufd xmm8, xmm8, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm11, xmm11, 4EH
pshufd xmm2, xmm2, 39H
pshufd xmm10, xmm10, 39H
paddd xmm0, xmm6
paddd xmm8, xmm14
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
pshuflw xmm11, xmm11, 0B1H
pshufhw xmm11, xmm11, 0B1H
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 20
psrld xmm4, 12
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 20
psrld xmm4, 12
por xmm9, xmm4
paddd xmm0, xmm7
paddd xmm8, xmm15
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
movdqa xmm13, xmm3
psrld xmm3, 8
pslld xmm13, 24
pxor xmm3, xmm13
movdqa xmm13, xmm11
psrld xmm11, 8
pslld xmm13, 24
pxor xmm11, xmm13
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 25
psrld xmm4, 7
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 25
psrld xmm4, 7
por xmm9, xmm4
pshufd xmm0, xmm0, 39H
pshufd xmm8, xmm8, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm11, xmm11, 4EH
pshufd xmm2, xmm2, 93H
pshufd xmm10, xmm10, 93H
dec al
je endroundloop2
movdqa xmm12, xmmword ptr [rsp+20H]
movdqa xmm5, xmmword ptr [rsp+40H]
pshufd xmm13, xmm12, 0FH
shufps xmm12, xmm5, 214
pshufd xmm4, xmm12, 39H
movdqa xmm12, xmm6
shufps xmm12, xmm7, 250
pand xmm13, xmmword ptr [PBLENDW_0x33_MASK]
pand xmm12, xmmword ptr [PBLENDW_0xCC_MASK]
por xmm13, xmm12
movdqa xmmword ptr [rsp+20H], xmm13
movdqa xmm12, xmm7
punpcklqdq xmm12, xmm5
movdqa xmm13, xmm6
pand xmm12, xmmword ptr [PBLENDW_0x3F_MASK]
pand xmm13, xmmword ptr [PBLENDW_0xC0_MASK]
por xmm12, xmm13
pshufd xmm12, xmm12, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmmword ptr [rsp+40H], xmm12
movdqa xmm5, xmmword ptr [rsp+30H]
movdqa xmm13, xmmword ptr [rsp+50H]
pshufd xmm6, xmm5, 0FH
shufps xmm5, xmm13, 214
pshufd xmm12, xmm5, 39H
movdqa xmm5, xmm14
shufps xmm5, xmm15, 250
pand xmm6, xmmword ptr [PBLENDW_0x33_MASK]
pand xmm5, xmmword ptr [PBLENDW_0xCC_MASK]
por xmm6, xmm5
movdqa xmm5, xmm15
punpcklqdq xmm5, xmm13
movdqa xmmword ptr [rsp+30H], xmm2
movdqa xmm2, xmm14
pand xmm5, xmmword ptr [PBLENDW_0x3F_MASK]
pand xmm2, xmmword ptr [PBLENDW_0xC0_MASK]
por xmm5, xmm2
movdqa xmm2, xmmword ptr [rsp+30H]
pshufd xmm5, xmm5, 78H
punpckhdq xmm13, xmm15
punpckldq xmm14, xmm13
pshufd xmm15, xmm14, 1EH
movdqa xmm13, xmm6
movdqa xmm14, xmm5
movdqa xmm5, xmmword ptr [rsp+20H]
movdqa xmm6, xmmword ptr [rsp+40H]
jmp roundloop2
endroundloop2:
pxor xmm0, xmm2
pxor xmm1, xmm3
pxor xmm8, xmm10
pxor xmm9, xmm11
mov eax, r13d
cmp rdx, r15
jne innerloop2
movups xmmword ptr [rbx], xmm0
movups xmmword ptr [rbx+10H], xmm1
movups xmmword ptr [rbx+20H], xmm8
movups xmmword ptr [rbx+30H], xmm9
mov eax, dword ptr [rsp+130H]
neg eax
mov r10d, dword ptr [rsp+110H+8*rax]
mov r11d, dword ptr [rsp+120H+8*rax]
mov dword ptr [rsp+110H], r10d
mov dword ptr [rsp+120H], r11d
add rdi, 16
add rbx, 64
sub rsi, 2
final1block:
test esi, 1H
je unwind
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movd xmm13, dword ptr [rsp+110H]
movd xmm14, dword ptr [rsp+120H]
punpckldq xmm13, xmm14
mov r8, qword ptr [rdi]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
innerloop1:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
movaps xmm2, xmmword ptr [BLAKE3_IV]
shl rax, 32
or rax, 64
movd xmm12, rax
movdqa xmm3, xmm13
punpcklqdq xmm3, xmm12
movups xmm4, xmmword ptr [r8+rdx-40H]
movups xmm5, xmmword ptr [r8+rdx-30H]
movaps xmm8, xmm4
shufps xmm4, xmm5, 136
shufps xmm8, xmm5, 221
movaps xmm5, xmm8
movups xmm6, xmmword ptr [r8+rdx-20H]
movups xmm7, xmmword ptr [r8+rdx-10H]
movaps xmm8, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm8, xmm7, 221
pshufd xmm7, xmm8, 93H
mov al, 7
roundloop1:
paddd xmm0, xmm4
paddd xmm0, xmm1
pxor xmm3, xmm0
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm5
paddd xmm0, xmm1
pxor xmm3, xmm0
movdqa xmm14, xmm3
psrld xmm3, 8
pslld xmm14, 24
pxor xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 39H
paddd xmm0, xmm6
paddd xmm0, xmm1
pxor xmm3, xmm0
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm7
paddd xmm0, xmm1
pxor xmm3, xmm0
movdqa xmm14, xmm3
psrld xmm3, 8
pslld xmm14, 24
pxor xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 93H
dec al
jz endroundloop1
movdqa xmm8, xmm4
shufps xmm8, xmm5, 214
pshufd xmm9, xmm4, 0FH
pshufd xmm4, xmm8, 39H
movdqa xmm8, xmm6
shufps xmm8, xmm7, 250
pand xmm9, xmmword ptr [PBLENDW_0x33_MASK]
pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK]
por xmm9, xmm8
movdqa xmm8, xmm7
punpcklqdq xmm8, xmm5
movdqa xmm10, xmm6
pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK]
pand xmm10, xmmword ptr [PBLENDW_0xC0_MASK]
por xmm8, xmm10
pshufd xmm8, xmm8, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmm5, xmm9
movdqa xmm6, xmm8
jmp roundloop1
endroundloop1:
pxor xmm0, xmm2
pxor xmm1, xmm3
mov eax, r13d
cmp rdx, r15
jne innerloop1
movups xmmword ptr [rbx], xmm0
movups xmmword ptr [rbx+10H], xmm1
jmp unwind
_blake3_hash_many_sse2 ENDP
blake3_hash_many_sse2 ENDP
blake3_compress_in_place_sse2 PROC
_blake3_compress_in_place_sse2 PROC
sub rsp, 120
movdqa xmmword ptr [rsp], xmm6
movdqa xmmword ptr [rsp+10H], xmm7
movdqa xmmword ptr [rsp+20H], xmm8
movdqa xmmword ptr [rsp+30H], xmm9
movdqa xmmword ptr [rsp+40H], xmm11
movdqa xmmword ptr [rsp+50H], xmm14
movdqa xmmword ptr [rsp+60H], xmm15
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movaps xmm2, xmmword ptr [BLAKE3_IV]
movzx eax, byte ptr [rsp+0A0H]
movzx r8d, r8b
shl rax, 32
add r8, rax
movd xmm3, r9
movd xmm4, r8
punpcklqdq xmm3, xmm4
movups xmm4, xmmword ptr [rdx]
movups xmm5, xmmword ptr [rdx+10H]
movaps xmm8, xmm4
shufps xmm4, xmm5, 136
shufps xmm8, xmm5, 221
movaps xmm5, xmm8
movups xmm6, xmmword ptr [rdx+20H]
movups xmm7, xmmword ptr [rdx+30H]
movaps xmm8, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm8, xmm7, 221
pshufd xmm7, xmm8, 93H
mov al, 7
@@:
paddd xmm0, xmm4
paddd xmm0, xmm1
pxor xmm3, xmm0
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm5
paddd xmm0, xmm1
pxor xmm3, xmm0
movdqa xmm14, xmm3
psrld xmm3, 8
pslld xmm14, 24
pxor xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 39H
paddd xmm0, xmm6
paddd xmm0, xmm1
pxor xmm3, xmm0
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm7
paddd xmm0, xmm1
pxor xmm3, xmm0
movdqa xmm14, xmm3
psrld xmm3, 8
pslld xmm14, 24
pxor xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 93H
dec al
jz @F
movdqa xmm8, xmm4
shufps xmm8, xmm5, 214
pshufd xmm9, xmm4, 0FH
pshufd xmm4, xmm8, 39H
movdqa xmm8, xmm6
shufps xmm8, xmm7, 250
pand xmm9, xmmword ptr [PBLENDW_0x33_MASK]
pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK]
por xmm9, xmm8
movdqa xmm8, xmm7
punpcklqdq xmm8, xmm5
movdqa xmm14, xmm6
pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK]
pand xmm14, xmmword ptr [PBLENDW_0xC0_MASK]
por xmm8, xmm14
pshufd xmm8, xmm8, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmm5, xmm9
movdqa xmm6, xmm8
jmp @B
@@:
pxor xmm0, xmm2
pxor xmm1, xmm3
movups xmmword ptr [rcx], xmm0
movups xmmword ptr [rcx+10H], xmm1
movdqa xmm6, xmmword ptr [rsp]
movdqa xmm7, xmmword ptr [rsp+10H]
movdqa xmm8, xmmword ptr [rsp+20H]
movdqa xmm9, xmmword ptr [rsp+30H]
movdqa xmm11, xmmword ptr [rsp+40H]
movdqa xmm14, xmmword ptr [rsp+50H]
movdqa xmm15, xmmword ptr [rsp+60H]
add rsp, 120
ret
_blake3_compress_in_place_sse2 ENDP
blake3_compress_in_place_sse2 ENDP
ALIGN 16
blake3_compress_xof_sse2 PROC
_blake3_compress_xof_sse2 PROC
sub rsp, 120
movdqa xmmword ptr [rsp], xmm6
movdqa xmmword ptr [rsp+10H], xmm7
movdqa xmmword ptr [rsp+20H], xmm8
movdqa xmmword ptr [rsp+30H], xmm9
movdqa xmmword ptr [rsp+40H], xmm11
movdqa xmmword ptr [rsp+50H], xmm14
movdqa xmmword ptr [rsp+60H], xmm15
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movaps xmm2, xmmword ptr [BLAKE3_IV]
movzx eax, byte ptr [rsp+0A0H]
movzx r8d, r8b
mov r10, qword ptr [rsp+0A8H]
shl rax, 32
add r8, rax
movd xmm3, r9
movd xmm4, r8
punpcklqdq xmm3, xmm4
movups xmm4, xmmword ptr [rdx]
movups xmm5, xmmword ptr [rdx+10H]
movaps xmm8, xmm4
shufps xmm4, xmm5, 136
shufps xmm8, xmm5, 221
movaps xmm5, xmm8
movups xmm6, xmmword ptr [rdx+20H]
movups xmm7, xmmword ptr [rdx+30H]
movaps xmm8, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm8, xmm7, 221
pshufd xmm7, xmm8, 93H
mov al, 7
@@:
paddd xmm0, xmm4
paddd xmm0, xmm1
pxor xmm3, xmm0
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm5
paddd xmm0, xmm1
pxor xmm3, xmm0
movdqa xmm14, xmm3
psrld xmm3, 8
pslld xmm14, 24
pxor xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 39H
paddd xmm0, xmm6
paddd xmm0, xmm1
pxor xmm3, xmm0
pshuflw xmm3, xmm3, 0B1H
pshufhw xmm3, xmm3, 0B1H
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm7
paddd xmm0, xmm1
pxor xmm3, xmm0
movdqa xmm14, xmm3
psrld xmm3, 8
pslld xmm14, 24
pxor xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 93H
dec al
jz @F
movdqa xmm8, xmm4
shufps xmm8, xmm5, 214
pshufd xmm9, xmm4, 0FH
pshufd xmm4, xmm8, 39H
movdqa xmm8, xmm6
shufps xmm8, xmm7, 250
pand xmm9, xmmword ptr [PBLENDW_0x33_MASK]
pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK]
por xmm9, xmm8
movdqa xmm8, xmm7
punpcklqdq xmm8, xmm5
movdqa xmm14, xmm6
pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK]
pand xmm14, xmmword ptr [PBLENDW_0xC0_MASK]
por xmm8, xmm14
pshufd xmm8, xmm8, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmm5, xmm9
movdqa xmm6, xmm8
jmp @B
@@:
movdqu xmm4, xmmword ptr [rcx]
movdqu xmm5, xmmword ptr [rcx+10H]
pxor xmm0, xmm2
pxor xmm1, xmm3
pxor xmm2, xmm4
pxor xmm3, xmm5
movups xmmword ptr [r10], xmm0
movups xmmword ptr [r10+10H], xmm1
movups xmmword ptr [r10+20H], xmm2
movups xmmword ptr [r10+30H], xmm3
movdqa xmm6, xmmword ptr [rsp]
movdqa xmm7, xmmword ptr [rsp+10H]
movdqa xmm8, xmmword ptr [rsp+20H]
movdqa xmm9, xmmword ptr [rsp+30H]
movdqa xmm11, xmmword ptr [rsp+40H]
movdqa xmm14, xmmword ptr [rsp+50H]
movdqa xmm15, xmmword ptr [rsp+60H]
add rsp, 120
ret
_blake3_compress_xof_sse2 ENDP
blake3_compress_xof_sse2 ENDP
_TEXT ENDS
_RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST'
ALIGN 64
BLAKE3_IV:
dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH
ADD0:
dd 0, 1, 2, 3
ADD1:
dd 4 dup (4)
BLAKE3_IV_0:
dd 4 dup (6A09E667H)
BLAKE3_IV_1:
dd 4 dup (0BB67AE85H)
BLAKE3_IV_2:
dd 4 dup (3C6EF372H)
BLAKE3_IV_3:
dd 4 dup (0A54FF53AH)
BLAKE3_BLOCK_LEN:
dd 4 dup (64)
CMP_MSB_MASK:
dd 8 dup(80000000H)
PBLENDW_0x33_MASK:
dd 0FFFFFFFFH, 000000000H, 0FFFFFFFFH, 000000000H
PBLENDW_0xCC_MASK:
dd 000000000H, 0FFFFFFFFH, 000000000H, 0FFFFFFFFH
PBLENDW_0x3F_MASK:
dd 0FFFFFFFFH, 0FFFFFFFFH, 0FFFFFFFFH, 000000000H
PBLENDW_0xC0_MASK:
dd 000000000H, 000000000H, 000000000H, 0FFFFFFFFH
_RDATA ENDS
END
================================================
FILE: NanaZip.Codecs/BLAKE3/blake3_sse41_x86-64_windows_msvc.asm
================================================
public _blake3_hash_many_sse41
public blake3_hash_many_sse41
public blake3_compress_in_place_sse41
public _blake3_compress_in_place_sse41
public blake3_compress_xof_sse41
public _blake3_compress_xof_sse41
_TEXT SEGMENT ALIGN(16) 'CODE'
ALIGN 16
blake3_hash_many_sse41 PROC
_blake3_hash_many_sse41 PROC
push r15
push r14
push r13
push r12
push rsi
push rdi
push rbx
push rbp
mov rbp, rsp
sub rsp, 528
and rsp, 0FFFFFFFFFFFFFFC0H
movdqa xmmword ptr [rsp+170H], xmm6
movdqa xmmword ptr [rsp+180H], xmm7
movdqa xmmword ptr [rsp+190H], xmm8
movdqa xmmword ptr [rsp+1A0H], xmm9
movdqa xmmword ptr [rsp+1B0H], xmm10
movdqa xmmword ptr [rsp+1C0H], xmm11
movdqa xmmword ptr [rsp+1D0H], xmm12
movdqa xmmword ptr [rsp+1E0H], xmm13
movdqa xmmword ptr [rsp+1F0H], xmm14
movdqa xmmword ptr [rsp+200H], xmm15
mov rdi, rcx
mov rsi, rdx
mov rdx, r8
mov rcx, r9
mov r8, qword ptr [rbp+68H]
movzx r9, byte ptr [rbp+70H]
neg r9d
movd xmm0, r9d
pshufd xmm0, xmm0, 00H
movdqa xmmword ptr [rsp+130H], xmm0
movdqa xmm1, xmm0
pand xmm1, xmmword ptr [ADD0]
pand xmm0, xmmword ptr [ADD1]
movdqa xmmword ptr [rsp+150H], xmm0
movd xmm0, r8d
pshufd xmm0, xmm0, 00H
paddd xmm0, xmm1
movdqa xmmword ptr [rsp+110H], xmm0
pxor xmm0, xmmword ptr [CMP_MSB_MASK]
pxor xmm1, xmmword ptr [CMP_MSB_MASK]
pcmpgtd xmm1, xmm0
shr r8, 32
movd xmm2, r8d
pshufd xmm2, xmm2, 00H
psubd xmm2, xmm1
movdqa xmmword ptr [rsp+120H], xmm2
mov rbx, qword ptr [rbp+90H]
mov r15, rdx
shl r15, 6
movzx r13d, byte ptr [rbp+78H]
movzx r12d, byte ptr [rbp+88H]
cmp rsi, 4
jc final3blocks
outerloop4:
movdqu xmm3, xmmword ptr [rcx]
pshufd xmm0, xmm3, 00H
pshufd xmm1, xmm3, 55H
pshufd xmm2, xmm3, 0AAH
pshufd xmm3, xmm3, 0FFH
movdqu xmm7, xmmword ptr [rcx+10H]
pshufd xmm4, xmm7, 00H
pshufd xmm5, xmm7, 55H
pshufd xmm6, xmm7, 0AAH
pshufd xmm7, xmm7, 0FFH
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
mov r10, qword ptr [rdi+10H]
mov r11, qword ptr [rdi+18H]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
innerloop4:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
movdqu xmm8, xmmword ptr [r8+rdx-40H]
movdqu xmm9, xmmword ptr [r9+rdx-40H]
movdqu xmm10, xmmword ptr [r10+rdx-40H]
movdqu xmm11, xmmword ptr [r11+rdx-40H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp], xmm8
movdqa xmmword ptr [rsp+10H], xmm9
movdqa xmmword ptr [rsp+20H], xmm12
movdqa xmmword ptr [rsp+30H], xmm13
movdqu xmm8, xmmword ptr [r8+rdx-30H]
movdqu xmm9, xmmword ptr [r9+rdx-30H]
movdqu xmm10, xmmword ptr [r10+rdx-30H]
movdqu xmm11, xmmword ptr [r11+rdx-30H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp+40H], xmm8
movdqa xmmword ptr [rsp+50H], xmm9
movdqa xmmword ptr [rsp+60H], xmm12
movdqa xmmword ptr [rsp+70H], xmm13
movdqu xmm8, xmmword ptr [r8+rdx-20H]
movdqu xmm9, xmmword ptr [r9+rdx-20H]
movdqu xmm10, xmmword ptr [r10+rdx-20H]
movdqu xmm11, xmmword ptr [r11+rdx-20H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp+80H], xmm8
movdqa xmmword ptr [rsp+90H], xmm9
movdqa xmmword ptr [rsp+0A0H], xmm12
movdqa xmmword ptr [rsp+0B0H], xmm13
movdqu xmm8, xmmword ptr [r8+rdx-10H]
movdqu xmm9, xmmword ptr [r9+rdx-10H]
movdqu xmm10, xmmword ptr [r10+rdx-10H]
movdqu xmm11, xmmword ptr [r11+rdx-10H]
movdqa xmm12, xmm8
punpckldq xmm8, xmm9
punpckhdq xmm12, xmm9
movdqa xmm14, xmm10
punpckldq xmm10, xmm11
punpckhdq xmm14, xmm11
movdqa xmm9, xmm8
punpcklqdq xmm8, xmm10
punpckhqdq xmm9, xmm10
movdqa xmm13, xmm12
punpcklqdq xmm12, xmm14
punpckhqdq xmm13, xmm14
movdqa xmmword ptr [rsp+0C0H], xmm8
movdqa xmmword ptr [rsp+0D0H], xmm9
movdqa xmmword ptr [rsp+0E0H], xmm12
movdqa xmmword ptr [rsp+0F0H], xmm13
movdqa xmm9, xmmword ptr [BLAKE3_IV_1]
movdqa xmm10, xmmword ptr [BLAKE3_IV_2]
movdqa xmm11, xmmword ptr [BLAKE3_IV_3]
movdqa xmm12, xmmword ptr [rsp+110H]
movdqa xmm13, xmmword ptr [rsp+120H]
movdqa xmm14, xmmword ptr [BLAKE3_BLOCK_LEN]
movd xmm15, eax
pshufd xmm15, xmm15, 00H
prefetcht0 byte ptr [r8+rdx+80H]
prefetcht0 byte ptr [r9+rdx+80H]
prefetcht0 byte ptr [r10+rdx+80H]
prefetcht0 byte ptr [r11+rdx+80H]
paddd xmm0, xmmword ptr [rsp]
paddd xmm1, xmmword ptr [rsp+20H]
paddd xmm2, xmmword ptr [rsp+40H]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [BLAKE3_IV_0]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+10H]
paddd xmm1, xmmword ptr [rsp+30H]
paddd xmm2, xmmword ptr [rsp+50H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+80H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp+0C0H]
paddd xmm3, xmmword ptr [rsp+0E0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+90H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+0D0H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+20H]
paddd xmm1, xmmword ptr [rsp+30H]
paddd xmm2, xmmword ptr [rsp+70H]
paddd xmm3, xmmword ptr [rsp+40H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+60H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp]
paddd xmm3, xmmword ptr [rsp+0D0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+10H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+90H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0B0H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp+0E0H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+30H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp+0D0H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+40H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+20H]
paddd xmm3, xmmword ptr [rsp+0E0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+60H]
paddd xmm1, xmmword ptr [rsp+90H]
paddd xmm2, xmmword ptr [rsp+0B0H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+50H]
paddd xmm1, xmmword ptr [rsp]
paddd xmm2, xmmword ptr [rsp+0F0H]
paddd xmm3, xmmword ptr [rsp+10H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0A0H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+0E0H]
paddd xmm3, xmmword ptr [rsp+0D0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+70H]
paddd xmm1, xmmword ptr [rsp+90H]
paddd xmm2, xmmword ptr [rsp+30H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+40H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+50H]
paddd xmm3, xmmword ptr [rsp+10H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp]
paddd xmm1, xmmword ptr [rsp+20H]
paddd xmm2, xmmword ptr [rsp+80H]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0C0H]
paddd xmm1, xmmword ptr [rsp+90H]
paddd xmm2, xmmword ptr [rsp+0F0H]
paddd xmm3, xmmword ptr [rsp+0E0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0D0H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+0A0H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+70H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+20H]
paddd xmm1, xmmword ptr [rsp+30H]
paddd xmm2, xmmword ptr [rsp+10H]
paddd xmm3, xmmword ptr [rsp+40H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+90H]
paddd xmm1, xmmword ptr [rsp+0B0H]
paddd xmm2, xmmword ptr [rsp+80H]
paddd xmm3, xmmword ptr [rsp+0F0H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0E0H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp+0C0H]
paddd xmm3, xmmword ptr [rsp+10H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0D0H]
paddd xmm1, xmmword ptr [rsp]
paddd xmm2, xmmword ptr [rsp+20H]
paddd xmm3, xmmword ptr [rsp+40H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+30H]
paddd xmm1, xmmword ptr [rsp+0A0H]
paddd xmm2, xmmword ptr [rsp+60H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0B0H]
paddd xmm1, xmmword ptr [rsp+50H]
paddd xmm2, xmmword ptr [rsp+10H]
paddd xmm3, xmmword ptr [rsp+80H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0F0H]
paddd xmm1, xmmword ptr [rsp]
paddd xmm2, xmmword ptr [rsp+90H]
paddd xmm3, xmmword ptr [rsp+60H]
paddd xmm0, xmm4
paddd xmm1, xmm5
paddd xmm2, xmm6
paddd xmm3, xmm7
pxor xmm12, xmm0
pxor xmm13, xmm1
pxor xmm14, xmm2
pxor xmm15, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
pshufb xmm15, xmm8
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm12
paddd xmm9, xmm13
paddd xmm10, xmm14
paddd xmm11, xmm15
pxor xmm4, xmm8
pxor xmm5, xmm9
pxor xmm6, xmm10
pxor xmm7, xmm11
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
paddd xmm0, xmmword ptr [rsp+0E0H]
paddd xmm1, xmmword ptr [rsp+20H]
paddd xmm2, xmmword ptr [rsp+30H]
paddd xmm3, xmmword ptr [rsp+70H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT16]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
movdqa xmmword ptr [rsp+100H], xmm8
movdqa xmm8, xmm5
psrld xmm8, 12
pslld xmm5, 20
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 12
pslld xmm6, 20
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 12
pslld xmm7, 20
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 12
pslld xmm4, 20
por xmm4, xmm8
paddd xmm0, xmmword ptr [rsp+0A0H]
paddd xmm1, xmmword ptr [rsp+0C0H]
paddd xmm2, xmmword ptr [rsp+40H]
paddd xmm3, xmmword ptr [rsp+0D0H]
paddd xmm0, xmm5
paddd xmm1, xmm6
paddd xmm2, xmm7
paddd xmm3, xmm4
pxor xmm15, xmm0
pxor xmm12, xmm1
pxor xmm13, xmm2
pxor xmm14, xmm3
movdqa xmm8, xmmword ptr [ROT8]
pshufb xmm15, xmm8
pshufb xmm12, xmm8
pshufb xmm13, xmm8
pshufb xmm14, xmm8
paddd xmm10, xmm15
paddd xmm11, xmm12
movdqa xmm8, xmmword ptr [rsp+100H]
paddd xmm8, xmm13
paddd xmm9, xmm14
pxor xmm5, xmm10
pxor xmm6, xmm11
pxor xmm7, xmm8
pxor xmm4, xmm9
pxor xmm0, xmm8
pxor xmm1, xmm9
pxor xmm2, xmm10
pxor xmm3, xmm11
movdqa xmm8, xmm5
psrld xmm8, 7
pslld xmm5, 25
por xmm5, xmm8
movdqa xmm8, xmm6
psrld xmm8, 7
pslld xmm6, 25
por xmm6, xmm8
movdqa xmm8, xmm7
psrld xmm8, 7
pslld xmm7, 25
por xmm7, xmm8
movdqa xmm8, xmm4
psrld xmm8, 7
pslld xmm4, 25
por xmm4, xmm8
pxor xmm4, xmm12
pxor xmm5, xmm13
pxor xmm6, xmm14
pxor xmm7, xmm15
mov eax, r13d
jne innerloop4
movdqa xmm9, xmm0
punpckldq xmm0, xmm1
punpckhdq xmm9, xmm1
movdqa xmm11, xmm2
punpckldq xmm2, xmm3
punpckhdq xmm11, xmm3
movdqa xmm1, xmm0
punpcklqdq xmm0, xmm2
punpckhqdq xmm1, xmm2
movdqa xmm3, xmm9
punpcklqdq xmm9, xmm11
punpckhqdq xmm3, xmm11
movdqu xmmword ptr [rbx], xmm0
movdqu xmmword ptr [rbx+20H], xmm1
movdqu xmmword ptr [rbx+40H], xmm9
movdqu xmmword ptr [rbx+60H], xmm3
movdqa xmm9, xmm4
punpckldq xmm4, xmm5
punpckhdq xmm9, xmm5
movdqa xmm11, xmm6
punpckldq xmm6, xmm7
punpckhdq xmm11, xmm7
movdqa xmm5, xmm4
punpcklqdq xmm4, xmm6
punpckhqdq xmm5, xmm6
movdqa xmm7, xmm9
punpcklqdq xmm9, xmm11
punpckhqdq xmm7, xmm11
movdqu xmmword ptr [rbx+10H], xmm4
movdqu xmmword ptr [rbx+30H], xmm5
movdqu xmmword ptr [rbx+50H], xmm9
movdqu xmmword ptr [rbx+70H], xmm7
movdqa xmm1, xmmword ptr [rsp+110H]
movdqa xmm0, xmm1
paddd xmm1, xmmword ptr [rsp+150H]
movdqa xmmword ptr [rsp+110H], xmm1
pxor xmm0, xmmword ptr [CMP_MSB_MASK]
pxor xmm1, xmmword ptr [CMP_MSB_MASK]
pcmpgtd xmm0, xmm1
movdqa xmm1, xmmword ptr [rsp+120H]
psubd xmm1, xmm0
movdqa xmmword ptr [rsp+120H], xmm1
add rbx, 128
add rdi, 32
sub rsi, 4
cmp rsi, 4
jnc outerloop4
test rsi, rsi
jne final3blocks
unwind:
movdqa xmm6, xmmword ptr [rsp+170H]
movdqa xmm7, xmmword ptr [rsp+180H]
movdqa xmm8, xmmword ptr [rsp+190H]
movdqa xmm9, xmmword ptr [rsp+1A0H]
movdqa xmm10, xmmword ptr [rsp+1B0H]
movdqa xmm11, xmmword ptr [rsp+1C0H]
movdqa xmm12, xmmword ptr [rsp+1D0H]
movdqa xmm13, xmmword ptr [rsp+1E0H]
movdqa xmm14, xmmword ptr [rsp+1F0H]
movdqa xmm15, xmmword ptr [rsp+200H]
mov rsp, rbp
pop rbp
pop rbx
pop rdi
pop rsi
pop r12
pop r13
pop r14
pop r15
ret
ALIGN 16
final3blocks:
test esi, 2H
je final1block
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movaps xmm8, xmm0
movaps xmm9, xmm1
movd xmm13, dword ptr [rsp+110H]
pinsrd xmm13, dword ptr [rsp+120H], 1
pinsrd xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2
movaps xmmword ptr [rsp], xmm13
movd xmm14, dword ptr [rsp+114H]
pinsrd xmm14, dword ptr [rsp+124H], 1
pinsrd xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2
movaps xmmword ptr [rsp+10H], xmm14
mov r8, qword ptr [rdi]
mov r9, qword ptr [rdi+8H]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
innerloop2:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
movaps xmm2, xmmword ptr [BLAKE3_IV]
movaps xmm10, xmm2
movups xmm4, xmmword ptr [r8+rdx-40H]
movups xmm5, xmmword ptr [r8+rdx-30H]
movaps xmm3, xmm4
shufps xmm4, xmm5, 136
shufps xmm3, xmm5, 221
movaps xmm5, xmm3
movups xmm6, xmmword ptr [r8+rdx-20H]
movups xmm7, xmmword ptr [r8+rdx-10H]
movaps xmm3, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm3, xmm7, 221
pshufd xmm7, xmm3, 93H
movups xmm12, xmmword ptr [r9+rdx-40H]
movups xmm13, xmmword ptr [r9+rdx-30H]
movaps xmm11, xmm12
shufps xmm12, xmm13, 136
shufps xmm11, xmm13, 221
movaps xmm13, xmm11
movups xmm14, xmmword ptr [r9+rdx-20H]
movups xmm15, xmmword ptr [r9+rdx-10H]
movaps xmm11, xmm14
shufps xmm14, xmm15, 136
pshufd xmm14, xmm14, 93H
shufps xmm11, xmm15, 221
pshufd xmm15, xmm11, 93H
movaps xmm3, xmmword ptr [rsp]
movaps xmm11, xmmword ptr [rsp+10H]
pinsrd xmm3, eax, 3
pinsrd xmm11, eax, 3
mov al, 7
roundloop2:
paddd xmm0, xmm4
paddd xmm8, xmm12
movaps xmmword ptr [rsp+20H], xmm4
movaps xmmword ptr [rsp+30H], xmm12
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
movaps xmm12, xmmword ptr [ROT16]
pshufb xmm3, xmm12
pshufb xmm11, xmm12
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 20
psrld xmm4, 12
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 20
psrld xmm4, 12
por xmm9, xmm4
paddd xmm0, xmm5
paddd xmm8, xmm13
movaps xmmword ptr [rsp+40H], xmm5
movaps xmmword ptr [rsp+50H], xmm13
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
movaps xmm13, xmmword ptr [ROT8]
pshufb xmm3, xmm13
pshufb xmm11, xmm13
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 25
psrld xmm4, 7
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 25
psrld xmm4, 7
por xmm9, xmm4
pshufd xmm0, xmm0, 93H
pshufd xmm8, xmm8, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm11, xmm11, 4EH
pshufd xmm2, xmm2, 39H
pshufd xmm10, xmm10, 39H
paddd xmm0, xmm6
paddd xmm8, xmm14
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
pshufb xmm3, xmm12
pshufb xmm11, xmm12
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 20
psrld xmm4, 12
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 20
psrld xmm4, 12
por xmm9, xmm4
paddd xmm0, xmm7
paddd xmm8, xmm15
paddd xmm0, xmm1
paddd xmm8, xmm9
pxor xmm3, xmm0
pxor xmm11, xmm8
pshufb xmm3, xmm13
pshufb xmm11, xmm13
paddd xmm2, xmm3
paddd xmm10, xmm11
pxor xmm1, xmm2
pxor xmm9, xmm10
movdqa xmm4, xmm1
pslld xmm1, 25
psrld xmm4, 7
por xmm1, xmm4
movdqa xmm4, xmm9
pslld xmm9, 25
psrld xmm4, 7
por xmm9, xmm4
pshufd xmm0, xmm0, 39H
pshufd xmm8, xmm8, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm11, xmm11, 4EH
pshufd xmm2, xmm2, 93H
pshufd xmm10, xmm10, 93H
dec al
je endroundloop2
movdqa xmm12, xmmword ptr [rsp+20H]
movdqa xmm5, xmmword ptr [rsp+40H]
pshufd xmm13, xmm12, 0FH
shufps xmm12, xmm5, 214
pshufd xmm4, xmm12, 39H
movdqa xmm12, xmm6
shufps xmm12, xmm7, 250
pblendw xmm13, xmm12, 0CCH
movdqa xmm12, xmm7
punpcklqdq xmm12, xmm5
pblendw xmm12, xmm6, 0C0H
pshufd xmm12, xmm12, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmmword ptr [rsp+20H], xmm13
movdqa xmmword ptr [rsp+40H], xmm12
movdqa xmm5, xmmword ptr [rsp+30H]
movdqa xmm13, xmmword ptr [rsp+50H]
pshufd xmm6, xmm5, 0FH
shufps xmm5, xmm13, 214
pshufd xmm12, xmm5, 39H
movdqa xmm5, xmm14
shufps xmm5, xmm15, 250
pblendw xmm6, xmm5, 0CCH
movdqa xmm5, xmm15
punpcklqdq xmm5, xmm13
pblendw xmm5, xmm14, 0C0H
pshufd xmm5, xmm5, 78H
punpckhdq xmm13, xmm15
punpckldq xmm14, xmm13
pshufd xmm15, xmm14, 1EH
movdqa xmm13, xmm6
movdqa xmm14, xmm5
movdqa xmm5, xmmword ptr [rsp+20H]
movdqa xmm6, xmmword ptr [rsp+40H]
jmp roundloop2
endroundloop2:
pxor xmm0, xmm2
pxor xmm1, xmm3
pxor xmm8, xmm10
pxor xmm9, xmm11
mov eax, r13d
cmp rdx, r15
jne innerloop2
movups xmmword ptr [rbx], xmm0
movups xmmword ptr [rbx+10H], xmm1
movups xmmword ptr [rbx+20H], xmm8
movups xmmword ptr [rbx+30H], xmm9
movdqa xmm0, xmmword ptr [rsp+130H]
movdqa xmm1, xmmword ptr [rsp+110H]
movdqa xmm2, xmmword ptr [rsp+120H]
movdqu xmm3, xmmword ptr [rsp+118H]
movdqu xmm4, xmmword ptr [rsp+128H]
blendvps xmm1, xmm3, xmm0
blendvps xmm2, xmm4, xmm0
movdqa xmmword ptr [rsp+110H], xmm1
movdqa xmmword ptr [rsp+120H], xmm2
add rdi, 16
add rbx, 64
sub rsi, 2
final1block:
test esi, 1H
je unwind
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movd xmm13, dword ptr [rsp+110H]
pinsrd xmm13, dword ptr [rsp+120H], 1
pinsrd xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2
movaps xmm14, xmmword ptr [ROT8]
movaps xmm15, xmmword ptr [ROT16]
mov r8, qword ptr [rdi]
movzx eax, byte ptr [rbp+80H]
or eax, r13d
xor edx, edx
innerloop1:
mov r14d, eax
or eax, r12d
add rdx, 64
cmp rdx, r15
cmovne eax, r14d
movaps xmm2, xmmword ptr [BLAKE3_IV]
movaps xmm3, xmm13
pinsrd xmm3, eax, 3
movups xmm4, xmmword ptr [r8+rdx-40H]
movups xmm5, xmmword ptr [r8+rdx-30H]
movaps xmm8, xmm4
shufps xmm4, xmm5, 136
shufps xmm8, xmm5, 221
movaps xmm5, xmm8
movups xmm6, xmmword ptr [r8+rdx-20H]
movups xmm7, xmmword ptr [r8+rdx-10H]
movaps xmm8, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm8, xmm7, 221
pshufd xmm7, xmm8, 93H
mov al, 7
roundloop1:
paddd xmm0, xmm4
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm15
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm5
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 39H
paddd xmm0, xmm6
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm15
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm7
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 93H
dec al
jz endroundloop1
movdqa xmm8, xmm4
shufps xmm8, xmm5, 214
pshufd xmm9, xmm4, 0FH
pshufd xmm4, xmm8, 39H
movdqa xmm8, xmm6
shufps xmm8, xmm7, 250
pblendw xmm9, xmm8, 0CCH
movdqa xmm8, xmm7
punpcklqdq xmm8, xmm5
pblendw xmm8, xmm6, 0C0H
pshufd xmm8, xmm8, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmm5, xmm9
movdqa xmm6, xmm8
jmp roundloop1
endroundloop1:
pxor xmm0, xmm2
pxor xmm1, xmm3
mov eax, r13d
cmp rdx, r15
jne innerloop1
movups xmmword ptr [rbx], xmm0
movups xmmword ptr [rbx+10H], xmm1
jmp unwind
_blake3_hash_many_sse41 ENDP
blake3_hash_many_sse41 ENDP
blake3_compress_in_place_sse41 PROC
_blake3_compress_in_place_sse41 PROC
sub rsp, 120
movdqa xmmword ptr [rsp], xmm6
movdqa xmmword ptr [rsp+10H], xmm7
movdqa xmmword ptr [rsp+20H], xmm8
movdqa xmmword ptr [rsp+30H], xmm9
movdqa xmmword ptr [rsp+40H], xmm11
movdqa xmmword ptr [rsp+50H], xmm14
movdqa xmmword ptr [rsp+60H], xmm15
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movaps xmm2, xmmword ptr [BLAKE3_IV]
movzx eax, byte ptr [rsp+0A0H]
movzx r8d, r8b
shl rax, 32
add r8, rax
movd xmm3, r9
movd xmm4, r8
punpcklqdq xmm3, xmm4
movups xmm4, xmmword ptr [rdx]
movups xmm5, xmmword ptr [rdx+10H]
movaps xmm8, xmm4
shufps xmm4, xmm5, 136
shufps xmm8, xmm5, 221
movaps xmm5, xmm8
movups xmm6, xmmword ptr [rdx+20H]
movups xmm7, xmmword ptr [rdx+30H]
movaps xmm8, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm8, xmm7, 221
pshufd xmm7, xmm8, 93H
movaps xmm14, xmmword ptr [ROT8]
movaps xmm15, xmmword ptr [ROT16]
mov al, 7
@@:
paddd xmm0, xmm4
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm15
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm5
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 39H
paddd xmm0, xmm6
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm15
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm7
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 93H
dec al
jz @F
movdqa xmm8, xmm4
shufps xmm8, xmm5, 214
pshufd xmm9, xmm4, 0FH
pshufd xmm4, xmm8, 39H
movdqa xmm8, xmm6
shufps xmm8, xmm7, 250
pblendw xmm9, xmm8, 0CCH
movdqa xmm8, xmm7
punpcklqdq xmm8, xmm5
pblendw xmm8, xmm6, 0C0H
pshufd xmm8, xmm8, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmm5, xmm9
movdqa xmm6, xmm8
jmp @B
@@:
pxor xmm0, xmm2
pxor xmm1, xmm3
movups xmmword ptr [rcx], xmm0
movups xmmword ptr [rcx+10H], xmm1
movdqa xmm6, xmmword ptr [rsp]
movdqa xmm7, xmmword ptr [rsp+10H]
movdqa xmm8, xmmword ptr [rsp+20H]
movdqa xmm9, xmmword ptr [rsp+30H]
movdqa xmm11, xmmword ptr [rsp+40H]
movdqa xmm14, xmmword ptr [rsp+50H]
movdqa xmm15, xmmword ptr [rsp+60H]
add rsp, 120
ret
_blake3_compress_in_place_sse41 ENDP
blake3_compress_in_place_sse41 ENDP
ALIGN 16
blake3_compress_xof_sse41 PROC
_blake3_compress_xof_sse41 PROC
sub rsp, 120
movdqa xmmword ptr [rsp], xmm6
movdqa xmmword ptr [rsp+10H], xmm7
movdqa xmmword ptr [rsp+20H], xmm8
movdqa xmmword ptr [rsp+30H], xmm9
movdqa xmmword ptr [rsp+40H], xmm11
movdqa xmmword ptr [rsp+50H], xmm14
movdqa xmmword ptr [rsp+60H], xmm15
movups xmm0, xmmword ptr [rcx]
movups xmm1, xmmword ptr [rcx+10H]
movaps xmm2, xmmword ptr [BLAKE3_IV]
movzx eax, byte ptr [rsp+0A0H]
movzx r8d, r8b
mov r10, qword ptr [rsp+0A8H]
shl rax, 32
add r8, rax
movd xmm3, r9
movd xmm4, r8
punpcklqdq xmm3, xmm4
movups xmm4, xmmword ptr [rdx]
movups xmm5, xmmword ptr [rdx+10H]
movaps xmm8, xmm4
shufps xmm4, xmm5, 136
shufps xmm8, xmm5, 221
movaps xmm5, xmm8
movups xmm6, xmmword ptr [rdx+20H]
movups xmm7, xmmword ptr [rdx+30H]
movaps xmm8, xmm6
shufps xmm6, xmm7, 136
pshufd xmm6, xmm6, 93H
shufps xmm8, xmm7, 221
pshufd xmm7, xmm8, 93H
movaps xmm14, xmmword ptr [ROT8]
movaps xmm15, xmmword ptr [ROT16]
mov al, 7
@@:
paddd xmm0, xmm4
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm15
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm5
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 93H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 39H
paddd xmm0, xmm6
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm15
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 20
psrld xmm11, 12
por xmm1, xmm11
paddd xmm0, xmm7
paddd xmm0, xmm1
pxor xmm3, xmm0
pshufb xmm3, xmm14
paddd xmm2, xmm3
pxor xmm1, xmm2
movdqa xmm11, xmm1
pslld xmm1, 25
psrld xmm11, 7
por xmm1, xmm11
pshufd xmm0, xmm0, 39H
pshufd xmm3, xmm3, 4EH
pshufd xmm2, xmm2, 93H
dec al
jz @F
movdqa xmm8, xmm4
shufps xmm8, xmm5, 214
pshufd xmm9, xmm4, 0FH
pshufd xmm4, xmm8, 39H
movdqa xmm8, xmm6
shufps xmm8, xmm7, 250
pblendw xmm9, xmm8, 0CCH
movdqa xmm8, xmm7
punpcklqdq xmm8, xmm5
pblendw xmm8, xmm6, 0C0H
pshufd xmm8, xmm8, 78H
punpckhdq xmm5, xmm7
punpckldq xmm6, xmm5
pshufd xmm7, xmm6, 1EH
movdqa xmm5, xmm9
movdqa xmm6, xmm8
jmp @B
@@:
movdqu xmm4, xmmword ptr [rcx]
movdqu xmm5, xmmword ptr [rcx+10H]
pxor xmm0, xmm2
pxor xmm1, xmm3
pxor xmm2, xmm4
pxor xmm3, xmm5
movups xmmword ptr [r10], xmm0
movups xmmword ptr [r10+10H], xmm1
movups xmmword ptr [r10+20H], xmm2
movups xmmword ptr [r10+30H], xmm3
movdqa xmm6, xmmword ptr [rsp]
movdqa xmm7, xmmword ptr [rsp+10H]
movdqa xmm8, xmmword ptr [rsp+20H]
movdqa xmm9, xmmword ptr [rsp+30H]
movdqa xmm11, xmmword ptr [rsp+40H]
movdqa xmm14, xmmword ptr [rsp+50H]
movdqa xmm15, xmmword ptr [rsp+60H]
add rsp, 120
ret
_blake3_compress_xof_sse41 ENDP
blake3_compress_xof_sse41 ENDP
_TEXT ENDS
_RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST'
ALIGN 64
BLAKE3_IV:
dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH
ADD0:
dd 0, 1, 2, 3
ADD1:
dd 4 dup (4)
BLAKE3_IV_0:
dd 4 dup (6A09E667H)
BLAKE3_IV_1:
dd 4 dup (0BB67AE85H)
BLAKE3_IV_2:
dd 4 dup (3C6EF372H)
BLAKE3_IV_3:
dd 4 dup (0A54FF53AH)
BLAKE3_BLOCK_LEN:
dd 4 dup (64)
ROT16:
db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13
ROT8:
db 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12
CMP_MSB_MASK:
dd 8 dup(80000000H)
_RDATA ENDS
END
================================================
FILE: NanaZip.Codecs/Brotli/common/constants.c
================================================
/* 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 BROTLI_MODEL("small")
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}};
================================================
FILE: NanaZip.Codecs/Brotli/common/constants.h
================================================
/* 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 "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 BROTLI_MODEL("small")
BrotliPrefixCodeRange _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS];
#endif /* BROTLI_COMMON_CONSTANTS_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/common/context.c
================================================
#include "context.h"
#include "platform.h"
/* Common context lookup table for all context modes. */
const BROTLI_MODEL("small") 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,
};
================================================
FILE: NanaZip.Codecs/Brotli/common/context.h
================================================
/* 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 "platform.h"
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_ */
================================================
FILE: NanaZip.Codecs/Brotli/common/dictionary.c
================================================
/* 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)
/* Embed kBrotliDictionaryData */
#include "dictionary_inc.h"
static const BROTLI_MODEL("small") BrotliDictionary kBrotliDictionary = {
#else
static BROTLI_MODEL("small") 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
================================================
FILE: NanaZip.Codecs/Brotli/common/dictionary.h
================================================
/* 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 "platform.h"
#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_ */
================================================
FILE: NanaZip.Codecs/Brotli/common/dictionary_inc.h
================================================
static const BROTLI_MODEL("small") uint8_t kBrotliDictionaryData[] = {
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
};
================================================
FILE: NanaZip.Codecs/Brotli/common/platform.c
================================================
/* 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 "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);
}
================================================
FILE: NanaZip.Codecs/Brotli/common/platform.h
================================================
/* 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 /* IWYU pragma: export memcmp, memcpy, memset */
#include /* IWYU pragma: export exit, free, malloc */
#include /* should include endian.h for us */
#include /* IWYU pragma: export */
#include /* IWYU pragma: export */
#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
/* This does not seem to be an indicator of z/Architecture (64-bit); neither
that allows to use unaligned loads. */
#if defined(__s390x__)
#define BROTLI_TARGET_S390X
#endif
#if defined(__mips64)
#define BROTLI_TARGET_MIPS64
#endif
#if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) || \
defined(BROTLI_TARGET_LOONGARCH64) || defined(BROTLI_TARGET_MIPS64)
#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
/* Likely target platform is iOS / OSX. */
#elif defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
#define BROTLI_LITTLE_ENDIAN 1
#elif defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
#define BROTLI_BIG_ENDIAN 1
#endif
#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_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. */
#if !defined(BROTLI_USE_PACKED_FOR_UNALIGNED)
#if defined(__mips__) && (!defined(__mips_isa_rev) || __mips_isa_rev < 6)
#define BROTLI_USE_PACKED_FOR_UNALIGNED 1
#else
#define BROTLI_USE_PACKED_FOR_UNALIGNED 0
#endif
#endif /* defined(BROTLI_USE_PACKED_FOR_UNALIGNED) */
#if BROTLI_USE_PACKED_FOR_UNALIGNED
typedef union BrotliPackedValue {
uint16_t u16;
uint32_t u32;
uint64_t u64;
size_t szt;
} __attribute__ ((packed)) BrotliPackedValue;
static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
const BrotliPackedValue* address = (const BrotliPackedValue*)p;
return address->u16;
}
static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {
const BrotliPackedValue* address = (const BrotliPackedValue*)p;
return address->u32;
}
static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
const BrotliPackedValue* address = (const BrotliPackedValue*)p;
return address->u64;
}
static BROTLI_INLINE size_t BrotliUnalignedReadSizeT(const void* p) {
const BrotliPackedValue* address = (const BrotliPackedValue*)p;
return address->szt;
}
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
BrotliPackedValue* address = (BrotliPackedValue*)p;
address->u64 = v;
}
#else /* not BROTLI_USE_PACKED_FOR_UNALIGNED */
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 size_t BrotliUnalignedReadSizeT(const void* p) {
size_t t;
memcpy(&t, p, sizeof t);
return t;
}
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
memcpy(p, &v, sizeof v);
}
#endif /* BROTLI_USE_PACKED_FOR_UNALIGNED */
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_bswap16, 4, 3, 0)
#define BROTLI_BSWAP16(V) ((uint16_t)__builtin_bswap16(V))
#else
#define BROTLI_BSWAP16(V) ((uint16_t)( \
(((V) & 0xFFU) << 8) | \
(((V) >> 8) & 0xFFU)))
#endif
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_bswap32, 4, 3, 0)
#define BROTLI_BSWAP32(V) ((uint32_t)__builtin_bswap32(V))
#else
#define BROTLI_BSWAP32(V) ((uint32_t)( \
(((V) & 0xFFU) << 24) | (((V) & 0xFF00U) << 8) | \
(((V) >> 8) & 0xFF00U) | (((V) >> 24) & 0xFFU)))
#endif
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_bswap64, 4, 3, 0)
#define BROTLI_BSWAP64(V) ((uint64_t)__builtin_bswap64(V))
#else
#define BROTLI_BSWAP64(V) ((uint64_t)( \
(((V) & 0xFFU) << 56) | (((V) & 0xFF00U) << 40) | \
(((V) & 0xFF0000U) << 24) | (((V) & 0xFF000000U) << 8) | \
(((V) >> 8) & 0xFF000000U) | (((V) >> 24) & 0xFF0000U) | \
(((V) >> 40) & 0xFF00U) | (((V) >> 56) & 0xFFU)))
#endif
#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 */
static BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) {
uint16_t value = BrotliUnalignedRead16(p);
return BROTLI_BSWAP16(value);
}
static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) {
uint32_t value = BrotliUnalignedRead32(p);
return BROTLI_BSWAP32(value);
}
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) && !defined(_M_ARM64EC)
#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);
/* Circular logical rotates. */
static BROTLI_INLINE uint16_t BrotliRotateRight16(uint16_t const value,
size_t count) {
count &= 0x0F; /* for fickle pattern recognition */
return (value >> count) | (uint16_t)(value << ((0U - count) & 0x0F));
}
static BROTLI_INLINE uint32_t BrotliRotateRight32(uint32_t const value,
size_t count) {
count &= 0x1F; /* for fickle pattern recognition */
return (value >> count) | (uint32_t)(value << ((0U - count) & 0x1F));
}
static BROTLI_INLINE uint64_t BrotliRotateRight64(uint64_t const value,
size_t count) {
count &= 0x3F; /* for fickle pattern recognition */
return (value >> count) | (uint64_t)(value << ((0U - count) & 0x3F));
}
BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
BROTLI_UNUSED(&BrotliSuppressUnusedFunctions);
BROTLI_UNUSED(&BrotliUnalignedRead16);
BROTLI_UNUSED(&BrotliUnalignedRead32);
BROTLI_UNUSED(&BrotliUnalignedRead64);
BROTLI_UNUSED(&BrotliUnalignedReadSizeT);
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);
BROTLI_UNUSED(&BrotliRotateRight16);
BROTLI_UNUSED(&BrotliRotateRight32);
BROTLI_UNUSED(&BrotliRotateRight64);
#if BROTLI_ENABLE_DUMP
BROTLI_UNUSED(&BrotliDump);
#endif
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && \
!defined(_M_ARM64EC)
/* _mm_prefetch() is not defined outside of x86/x64 */
/* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
#include
#define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
#define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1)
#elif BROTLI_GNUC_HAS_BUILTIN(__builtin_prefetch, 3, 1, 0)
#define PREFETCH_L1(ptr) \
__builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
#define PREFETCH_L2(ptr) \
__builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
#elif defined(__aarch64__)
#define PREFETCH_L1(ptr) \
do { \
__asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))); \
} while (0)
#define PREFETCH_L2(ptr) \
do { \
__asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))); \
} while (0)
#else
#define PREFETCH_L1(ptr) \
do { \
(void)(ptr); \
} while (0) /* disabled */
#define PREFETCH_L2(ptr) \
do { \
(void)(ptr); \
} while (0) /* disabled */
#endif
/* The SIMD matchers are only faster at certain quality levels. */
#if defined(_M_X64) && defined(BROTLI_TZCNT64)
#define BROTLI_MAX_SIMD_QUALITY 7
#elif defined(BROTLI_TZCNT64)
#define BROTLI_MAX_SIMD_QUALITY 6
#endif
}
#if defined(_MSC_VER)
#define BROTLI_CRASH() __debugbreak(), (void)abort()
#elif BROTLI_GNUC_HAS_BUILTIN(__builtin_trap, 3, 0, 0)
#define BROTLI_CRASH() (void)__builtin_trap()
#else
#define BROTLI_CRASH() (void)abort()
#endif
/* Make BROTLI_TEST=0 act same as undefined. */
#if defined(BROTLI_TEST) && ((1-BROTLI_TEST-1) == 0)
#undef BROTLI_TEST
#endif
#if BROTLI_GNUC_HAS_ATTRIBUTE(model, 3, 0, 3)
#define BROTLI_MODEL(M) __attribute__((model(M)))
#else
#define BROTLI_MODEL(M) /* M */
#endif
#if BROTLI_GNUC_HAS_ATTRIBUTE(cold, 4, 3, 0)
#define BROTLI_COLD __attribute__((cold))
#else
#define BROTLI_COLD /* cold */
#endif
#endif /* BROTLI_COMMON_PLATFORM_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/common/shared_dictionary.c
================================================
/* Copyright 2017 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Shared Dictionary definition and utilities. */
#include
#include "dictionary.h"
#include "platform.h"
#include "shared_dictionary_internal.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if defined(BROTLI_EXPERIMENTAL)
#define BROTLI_NUM_ENCODED_LENGTHS (SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH \
- SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH + 1)
/* Max allowed by spec */
#define BROTLI_MAX_SIZE_BITS 15u
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
static BROTLI_BOOL ReadBool(const uint8_t* encoded, size_t size, size_t* pos,
BROTLI_BOOL* result) {
uint8_t value;
size_t position = *pos;
if (position >= size) return BROTLI_FALSE; /* past file end */
value = encoded[position++];
if (value > 1) return BROTLI_FALSE; /* invalid bool */
*result = TO_BROTLI_BOOL(value);
*pos = position;
return BROTLI_TRUE; /* success */
}
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
static BROTLI_BOOL ReadUint8(const uint8_t* encoded, size_t size, size_t* pos,
uint8_t* result) {
size_t position = *pos;
if (position + sizeof(uint8_t) > size) return BROTLI_FALSE;
*result = encoded[position++];
*pos = position;
return BROTLI_TRUE;
}
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
static BROTLI_BOOL ReadUint16(const uint8_t* encoded, size_t size, size_t* pos,
uint16_t* result) {
size_t position = *pos;
if (position + sizeof(uint16_t) > size) return BROTLI_FALSE;
*result = BROTLI_UNALIGNED_LOAD16LE(&encoded[position]);
position += 2;
*pos = position;
return BROTLI_TRUE;
}
/* Reads a varint into a uint32_t, and returns error if it's too large */
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
static BROTLI_BOOL ReadVarint32(const uint8_t* encoded, size_t size,
size_t* pos, uint32_t* result) {
int num = 0;
uint8_t byte;
*result = 0;
for (;;) {
if (*pos >= size) return BROTLI_FALSE;
byte = encoded[(*pos)++];
if (num == 4 && byte > 15) return BROTLI_FALSE;
*result |= (uint32_t)(byte & 127) << (num * 7);
if (byte < 128) return BROTLI_TRUE;
num++;
}
}
/* Returns the total length of word list. */
static size_t BrotliSizeBitsToOffsets(const uint8_t* size_bits_by_length,
uint32_t* offsets_by_length) {
uint32_t pos = 0;
uint32_t i;
for (i = 0; i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {
offsets_by_length[i] = pos;
if (size_bits_by_length[i] != 0) {
pos += i << size_bits_by_length[i];
}
}
return pos;
}
static BROTLI_BOOL ParseWordList(size_t size, const uint8_t* encoded,
size_t* pos, BrotliDictionary* out) {
size_t offset;
size_t i;
size_t position = *pos;
if (position + BROTLI_NUM_ENCODED_LENGTHS > size) {
return BROTLI_FALSE;
}
memset(out->size_bits_by_length, 0, SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH);
memcpy(out->size_bits_by_length + SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH,
&encoded[position], BROTLI_NUM_ENCODED_LENGTHS);
for (i = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;
i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {
if (out->size_bits_by_length[i] > BROTLI_MAX_SIZE_BITS) {
return BROTLI_FALSE;
}
}
position += BROTLI_NUM_ENCODED_LENGTHS;
offset = BrotliSizeBitsToOffsets(
out->size_bits_by_length, out->offsets_by_length);
out->data = &encoded[position];
out->data_size = offset;
position += offset;
if (position > size) return BROTLI_FALSE;
*pos = position;
return BROTLI_TRUE;
}
/* Computes the cutOffTransforms of a BrotliTransforms which already has the
transforms data correctly filled in. */
static void ComputeCutoffTransforms(BrotliTransforms* transforms) {
uint32_t i;
for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {
transforms->cutOffTransforms[i] = -1;
}
for (i = 0; i < transforms->num_transforms; i++) {
const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, i);
uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, i);
const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, i);
if (type <= BROTLI_TRANSFORM_OMIT_LAST_9 && *prefix == 0 && *suffix == 0 &&
transforms->cutOffTransforms[type] == -1) {
transforms->cutOffTransforms[type] = (int16_t)i;
}
}
}
static BROTLI_BOOL ParsePrefixSuffixTable(size_t size, const uint8_t* encoded,
size_t* pos, BrotliTransforms* out, uint16_t* out_table,
size_t* out_table_size) {
size_t position = *pos;
size_t offset = 0;
size_t stringlet_count = 0; /* NUM_PREFIX_SUFFIX */
size_t data_length = 0;
/* PREFIX_SUFFIX_LENGTH */
if (!ReadUint16(encoded, size, &position, &out->prefix_suffix_size)) {
return BROTLI_FALSE;
}
data_length = out->prefix_suffix_size;
/* Must at least have space for null terminator. */
if (data_length < 1) return BROTLI_FALSE;
out->prefix_suffix = &encoded[position];
if (position + data_length >= size) return BROTLI_FALSE;
while (BROTLI_TRUE) {
/* STRING_LENGTH */
size_t stringlet_len = encoded[position + offset];
out_table[stringlet_count] = (uint16_t)offset;
stringlet_count++;
offset++;
if (stringlet_len == 0) {
if (offset == data_length) {
break;
} else {
return BROTLI_FALSE;
}
}
if (stringlet_count > 255) return BROTLI_FALSE;
offset += stringlet_len;
if (offset >= data_length) return BROTLI_FALSE;
}
position += data_length;
*pos = position;
*out_table_size = (uint16_t)stringlet_count;
return BROTLI_TRUE;
}
static BROTLI_BOOL ParseTransformsList(size_t size, const uint8_t* encoded,
size_t* pos, BrotliTransforms* out, uint16_t* prefix_suffix_table,
size_t* prefix_suffix_count) {
uint32_t i;
BROTLI_BOOL has_params = BROTLI_FALSE;
BROTLI_BOOL prefix_suffix_ok = BROTLI_FALSE;
size_t position = *pos;
size_t stringlet_cnt = 0;
if (position >= size) return BROTLI_FALSE;
prefix_suffix_ok = ParsePrefixSuffixTable(
size, encoded, &position, out, prefix_suffix_table, &stringlet_cnt);
if (!prefix_suffix_ok) return BROTLI_FALSE;
out->prefix_suffix_map = prefix_suffix_table;
*prefix_suffix_count = stringlet_cnt;
out->num_transforms = encoded[position++];
out->transforms = &encoded[position];
position += (size_t)out->num_transforms * 3;
if (position > size) return BROTLI_FALSE;
/* Check for errors and read extra parameters. */
for (i = 0; i < out->num_transforms; i++) {
uint8_t prefix_id = BROTLI_TRANSFORM_PREFIX_ID(out, i);
uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);
uint8_t suffix_id = BROTLI_TRANSFORM_SUFFIX_ID(out, i);
if (prefix_id >= stringlet_cnt) return BROTLI_FALSE;
if (type >= BROTLI_NUM_TRANSFORM_TYPES) return BROTLI_FALSE;
if (suffix_id >= stringlet_cnt) return BROTLI_FALSE;
if (type == BROTLI_TRANSFORM_SHIFT_FIRST ||
type == BROTLI_TRANSFORM_SHIFT_ALL) {
has_params = BROTLI_TRUE;
}
}
if (has_params) {
out->params = &encoded[position];
position += (size_t)out->num_transforms * 2;
if (position > size) return BROTLI_FALSE;
for (i = 0; i < out->num_transforms; i++) {
uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);
if (type != BROTLI_TRANSFORM_SHIFT_FIRST &&
type != BROTLI_TRANSFORM_SHIFT_ALL) {
if (out->params[i * 2] != 0 || out->params[i * 2 + 1] != 0) {
return BROTLI_FALSE;
}
}
}
} else {
out->params = NULL;
}
ComputeCutoffTransforms(out);
*pos = position;
return BROTLI_TRUE;
}
static BROTLI_BOOL DryParseDictionary(const uint8_t* encoded,
size_t size, uint32_t* num_prefix, BROTLI_BOOL* is_custom_static_dict) {
size_t pos = 0;
uint32_t chunk_size = 0;
uint8_t num_word_lists;
uint8_t num_transform_lists;
*is_custom_static_dict = BROTLI_FALSE;
*num_prefix = 0;
/* Skip magic header bytes. */
pos += 2;
/* LZ77_DICTIONARY_LENGTH */
if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;
if (chunk_size != 0) {
/* This limitation is not specified but the 32-bit Brotli decoder for now */
if (chunk_size > 1073741823) return BROTLI_FALSE;
*num_prefix = 1;
if (pos + chunk_size > size) return BROTLI_FALSE;
pos += chunk_size;
}
if (!ReadUint8(encoded, size, &pos, &num_word_lists)) {
return BROTLI_FALSE;
}
if (!ReadUint8(encoded, size, &pos, &num_transform_lists)) {
return BROTLI_FALSE;
}
if (num_word_lists > 0 || num_transform_lists > 0) {
*is_custom_static_dict = BROTLI_TRUE;
}
return BROTLI_TRUE;
}
static BROTLI_BOOL ParseDictionary(const uint8_t* encoded, size_t size,
BrotliSharedDictionary* dict) {
uint32_t i;
size_t pos = 0;
uint32_t chunk_size = 0;
size_t total_prefix_suffix_count = 0;
size_t transform_list_start[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
uint16_t temporary_prefix_suffix_table[256];
/* Skip magic header bytes. */
pos += 2;
/* LZ77_DICTIONARY_LENGTH */
if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;
if (chunk_size != 0) {
if (pos + chunk_size > size) return BROTLI_FALSE;
dict->prefix_size[dict->num_prefix] = chunk_size;
dict->prefix[dict->num_prefix] = &encoded[pos];
dict->num_prefix++;
/* LZ77_DICTIONARY_LENGTH bytes. */
pos += chunk_size;
}
/* NUM_WORD_LISTS */
if (!ReadUint8(encoded, size, &pos, &dict->num_word_lists)) {
return BROTLI_FALSE;
}
if (dict->num_word_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
return BROTLI_FALSE;
}
if (dict->num_word_lists != 0) {
dict->words_instances = (BrotliDictionary*)dict->alloc_func(
dict->memory_manager_opaque,
dict->num_word_lists * sizeof(*dict->words_instances));
if (!dict->words_instances) return BROTLI_FALSE; /* OOM */
}
for (i = 0; i < dict->num_word_lists; i++) {
if (!ParseWordList(size, encoded, &pos, &dict->words_instances[i])) {
return BROTLI_FALSE;
}
}
/* NUM_TRANSFORM_LISTS */
if (!ReadUint8(encoded, size, &pos, &dict->num_transform_lists)) {
return BROTLI_FALSE;
}
if (dict->num_transform_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
return BROTLI_FALSE;
}
if (dict->num_transform_lists != 0) {
dict->transforms_instances = (BrotliTransforms*)dict->alloc_func(
dict->memory_manager_opaque,
dict->num_transform_lists * sizeof(*dict->transforms_instances));
if (!dict->transforms_instances) return BROTLI_FALSE; /* OOM */
}
for (i = 0; i < dict->num_transform_lists; i++) {
BROTLI_BOOL ok = BROTLI_FALSE;
size_t prefix_suffix_count = 0;
transform_list_start[i] = pos;
dict->transforms_instances[i].prefix_suffix_map =
temporary_prefix_suffix_table;
ok = ParseTransformsList(
size, encoded, &pos, &dict->transforms_instances[i],
temporary_prefix_suffix_table, &prefix_suffix_count);
if (!ok) return BROTLI_FALSE;
total_prefix_suffix_count += prefix_suffix_count;
}
if (total_prefix_suffix_count != 0) {
dict->prefix_suffix_maps = (uint16_t*)dict->alloc_func(
dict->memory_manager_opaque,
total_prefix_suffix_count * sizeof(*dict->prefix_suffix_maps));
if (!dict->prefix_suffix_maps) return BROTLI_FALSE; /* OOM */
}
total_prefix_suffix_count = 0;
for (i = 0; i < dict->num_transform_lists; i++) {
size_t prefix_suffix_count = 0;
size_t position = transform_list_start[i];
uint16_t* prefix_suffix_map =
&dict->prefix_suffix_maps[total_prefix_suffix_count];
BROTLI_BOOL ok = ParsePrefixSuffixTable(
size, encoded, &position, &dict->transforms_instances[i],
prefix_suffix_map, &prefix_suffix_count);
if (!ok) return BROTLI_FALSE;
dict->transforms_instances[i].prefix_suffix_map = prefix_suffix_map;
total_prefix_suffix_count += prefix_suffix_count;
}
if (dict->num_word_lists != 0 || dict->num_transform_lists != 0) {
if (!ReadUint8(encoded, size, &pos, &dict->num_dictionaries)) {
return BROTLI_FALSE;
}
if (dict->num_dictionaries == 0 ||
dict->num_dictionaries > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
return BROTLI_FALSE;
}
for (i = 0; i < dict->num_dictionaries; i++) {
uint8_t words_index;
uint8_t transforms_index;
if (!ReadUint8(encoded, size, &pos, &words_index)) {
return BROTLI_FALSE;
}
if (words_index > dict->num_word_lists) return BROTLI_FALSE;
if (!ReadUint8(encoded, size, &pos, &transforms_index)) {
return BROTLI_FALSE;
}
if (transforms_index > dict->num_transform_lists) return BROTLI_FALSE;
dict->words[i] = words_index == dict->num_word_lists ?
BrotliGetDictionary() : &dict->words_instances[words_index];
dict->transforms[i] = transforms_index == dict->num_transform_lists ?
BrotliGetTransforms(): &dict->transforms_instances[transforms_index];
}
/* CONTEXT_ENABLED */
if (!ReadBool(encoded, size, &pos, &dict->context_based)) {
return BROTLI_FALSE;
}
/* CONTEXT_MAP */
if (dict->context_based) {
for (i = 0; i < SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS; i++) {
if (!ReadUint8(encoded, size, &pos, &dict->context_map[i])) {
return BROTLI_FALSE;
}
if (dict->context_map[i] >= dict->num_dictionaries) {
return BROTLI_FALSE;
}
}
}
} else {
dict->context_based = BROTLI_FALSE;
dict->num_dictionaries = 1;
dict->words[0] = BrotliGetDictionary();
dict->transforms[0] = BrotliGetTransforms();
}
return BROTLI_TRUE;
}
/* Decodes shared dictionary and verifies correctness.
Returns BROTLI_TRUE if dictionary is valid, BROTLI_FALSE otherwise.
The BrotliSharedDictionary must already have been initialized. If the
BrotliSharedDictionary already contains data, compound dictionaries
will be appended, but an error will be returned if it already has
custom words or transforms.
TODO(lode): link to RFC for shared brotli once published. */
static BROTLI_BOOL DecodeSharedDictionary(
const uint8_t* encoded, size_t size, BrotliSharedDictionary* dict) {
uint32_t num_prefix = 0;
BROTLI_BOOL is_custom_static_dict = BROTLI_FALSE;
BROTLI_BOOL has_custom_static_dict =
dict->num_word_lists > 0 || dict->num_transform_lists > 0;
/* Check magic header bytes. */
if (size < 2) return BROTLI_FALSE;
if (encoded[0] != 0x91 || encoded[1] != 0) return BROTLI_FALSE;
if (!DryParseDictionary(encoded, size, &num_prefix, &is_custom_static_dict)) {
return BROTLI_FALSE;
}
if (num_prefix + dict->num_prefix > SHARED_BROTLI_MAX_COMPOUND_DICTS) {
return BROTLI_FALSE;
}
/* Cannot combine different static dictionaries, only prefix dictionaries */
if (has_custom_static_dict && is_custom_static_dict) return BROTLI_FALSE;
return ParseDictionary(encoded, size, dict);
}
#endif /* BROTLI_EXPERIMENTAL */
void BrotliSharedDictionaryDestroyInstance(
BrotliSharedDictionary* dict) {
if (!dict) {
return;
} else {
brotli_free_func free_func = dict->free_func;
void* opaque = dict->memory_manager_opaque;
/* Cleanup. */
free_func(opaque, dict->words_instances);
free_func(opaque, dict->transforms_instances);
free_func(opaque, dict->prefix_suffix_maps);
/* Self-destruction. */
free_func(opaque, dict);
}
}
BROTLI_BOOL BrotliSharedDictionaryAttach(
BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,
size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {
if (!dict) {
return BROTLI_FALSE;
}
#if defined(BROTLI_EXPERIMENTAL)
if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) {
return DecodeSharedDictionary(data, data_size, dict);
}
#endif /* BROTLI_EXPERIMENTAL */
if (type == BROTLI_SHARED_DICTIONARY_RAW) {
if (dict->num_prefix >= SHARED_BROTLI_MAX_COMPOUND_DICTS) {
return BROTLI_FALSE;
}
dict->prefix_size[dict->num_prefix] = data_size;
dict->prefix[dict->num_prefix] = data;
dict->num_prefix++;
return BROTLI_TRUE;
}
return BROTLI_FALSE;
}
BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
BrotliSharedDictionary* dict = 0;
if (!alloc_func && !free_func) {
dict = (BrotliSharedDictionary*)malloc(sizeof(BrotliSharedDictionary));
} else if (alloc_func && free_func) {
dict = (BrotliSharedDictionary*)alloc_func(
opaque, sizeof(BrotliSharedDictionary));
}
if (dict == 0) {
return 0;
}
/* TODO(eustas): explicitly initialize all the fields? */
memset(dict, 0, sizeof(BrotliSharedDictionary));
dict->context_based = BROTLI_FALSE;
dict->num_dictionaries = 1;
dict->num_word_lists = 0;
dict->num_transform_lists = 0;
dict->words[0] = BrotliGetDictionary();
dict->transforms[0] = BrotliGetTransforms();
dict->alloc_func = alloc_func ? alloc_func : BrotliDefaultAllocFunc;
dict->free_func = free_func ? free_func : BrotliDefaultFreeFunc;
dict->memory_manager_opaque = opaque;
return dict;
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/common/shared_dictionary_internal.h
================================================
/* 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 "dictionary.h"
#include "platform.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_ */
================================================
FILE: NanaZip.Codecs/Brotli/common/static_init.h
================================================
/* Copyright 2025 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/*
Central point for static initialization.
In case of "lazy" mode `BrotliXxxLazyStaticInit` is not provided by the
library. Embedder is responsible for providing it. This function should call
`BrotliXxxLazyStaticInitInner` on the first invocation. This function should
not return until execution of `BrotliXxxLazyStaticInitInner` is finished.
In C or before C++11 it is possible to call `BrotliXxxLazyStaticInitInner`
on start-up path and then `BrotliEncoderLazyStaticInit` is could be no-op;
another option is to use available thread execution controls to meet the
requirements. For possible C++11 implementation see static_init_lazy.cc.
*/
#ifndef THIRD_PARTY_BROTLI_COMMON_STATIC_INIT_H_
#define THIRD_PARTY_BROTLI_COMMON_STATIC_INIT_H_
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* Static data is "initialized" in compile time. */
#define BROTLI_STATIC_INIT_NONE 0
/* Static data is initialized before "main". */
#define BROTLI_STATIC_INIT_EARLY 1
/* Static data is initialized when first encoder is created. */
#define BROTLI_STATIC_INIT_LAZY 2
#define BROTLI_STATIC_INIT_DEFAULT BROTLI_STATIC_INIT_NONE
#if !defined(BROTLI_STATIC_INIT)
#define BROTLI_STATIC_INIT BROTLI_STATIC_INIT_DEFAULT
#endif
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE) && \
(BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_EARLY) && \
(BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_LAZY)
#error Invalid value for BROTLI_STATIC_INIT
#endif
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)
#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)
#error BROTLI_STATIC_INIT_EARLY will fail with BROTLI_EXTERNAL_DICTIONARY_DATA
#endif
#endif /* BROTLI_STATIC_INIT */
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif // THIRD_PARTY_BROTLI_COMMON_STATIC_INIT_H_
================================================
FILE: NanaZip.Codecs/Brotli/common/transform.c
================================================
/* 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 "platform.h"
#include "transform.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* RFC 7932 transforms string data */
static const BROTLI_MODEL("small") 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 BROTLI_MODEL("small") 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 BROTLI_MODEL("small") 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 BROTLI_MODEL("small")
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
================================================
FILE: NanaZip.Codecs/Brotli/common/transform.h
================================================
/* 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 "platform.h"
#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_ */
================================================
FILE: NanaZip.Codecs/Brotli/common/version.h
================================================
/* 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 2
#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 3
#define BROTLI_ABI_REVISION 0
#define BROTLI_ABI_AGE 2
#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_ */
================================================
FILE: NanaZip.Codecs/Brotli/dec/bit_reader.c
================================================
/* Copyright 2013 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Bit reading helpers */
#include "bit_reader.h"
#include "../common/platform.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
const BROTLI_MODEL("small")
brotli_reg_t kBrotliBitMask[33] = { 0x00000000,
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
};
void BrotliInitBitReader(BrotliBitReader* const br) {
br->val_ = 0;
br->bit_pos_ = 0;
}
BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
size_t aligned_read_mask = (sizeof(br->val_) >> 1) - 1;
/* Fixing alignment after unaligned BrotliFillWindow would result accumulator
overflow. If unalignment is caused by BrotliSafeReadBits, then there is
enough space in accumulator to fix alignment. */
if (BROTLI_UNALIGNED_READ_FAST) {
aligned_read_mask = 0;
}
if (BrotliGetAvailableBits(br) == 0) {
br->val_ = 0;
if (!BrotliPullByte(br)) {
return BROTLI_FALSE;
}
}
while ((((size_t)br->next_in) & aligned_read_mask) != 0) {
if (!BrotliPullByte(br)) {
/* If we consumed all the input, we don't care about the alignment. */
return BROTLI_TRUE;
}
}
return BROTLI_TRUE;
}
BROTLI_BOOL BrotliSafeReadBits32Slow(BrotliBitReader* const br,
brotli_reg_t n_bits, brotli_reg_t* val) {
brotli_reg_t low_val;
brotli_reg_t high_val;
BrotliBitReaderState memento;
BROTLI_DCHECK(n_bits <= 32);
BROTLI_DCHECK(n_bits > 24);
BrotliBitReaderSaveState(br, &memento);
if (!BrotliSafeReadBits(br, 16, &low_val) ||
!BrotliSafeReadBits(br, n_bits - 16, &high_val)) {
BrotliBitReaderRestoreState(br, &memento);
return BROTLI_FALSE;
}
*val = low_val | (high_val << 16);
return BROTLI_TRUE;
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/dec/bit_reader.h
================================================
/* Copyright 2013 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Bit reading helpers */
#ifndef BROTLI_DEC_BIT_READER_H_
#define BROTLI_DEC_BIT_READER_H_
#include "../common/constants.h"
#include "../common/platform.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1)
/* 162 bits + 7 bytes */
#define BROTLI_FAST_INPUT_SLACK 28
BROTLI_INTERNAL extern const brotli_reg_t kBrotliBitMask[33];
static BROTLI_INLINE brotli_reg_t BitMask(brotli_reg_t n) {
if (BROTLI_IS_CONSTANT(n) || BROTLI_HAS_UBFX) {
/* Masking with this expression turns to a single
"Unsigned Bit Field Extract" UBFX instruction on ARM. */
return ~(~((brotli_reg_t)0) << n);
} else {
return kBrotliBitMask[n];
}
}
typedef struct {
brotli_reg_t val_; /* pre-fetched bits */
brotli_reg_t bit_pos_; /* current bit-reading position in val_ */
const uint8_t* next_in; /* the byte we're reading from */
const uint8_t* guard_in; /* position from which "fast-path" is prohibited */
const uint8_t* last_in; /* == next_in + avail_in */
} BrotliBitReader;
typedef struct {
brotli_reg_t val_;
brotli_reg_t bit_pos_;
const uint8_t* next_in;
size_t avail_in;
} BrotliBitReaderState;
/* Initializes the BrotliBitReader fields. */
BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* br);
/* Ensures that accumulator is not empty.
May consume up to sizeof(brotli_reg_t) - 1 bytes of input.
Returns BROTLI_FALSE if data is required but there is no input available.
For !BROTLI_UNALIGNED_READ_FAST this function also prepares bit reader for
aligned reading. */
BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* br);
/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden
the main code-path. Never called for RFC brotli streams, required only for
"large-window" mode and other extensions. */
BROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow(
BrotliBitReader* br, brotli_reg_t n_bits, brotli_reg_t* val);
static BROTLI_INLINE size_t
BrotliBitReaderGetAvailIn(BrotliBitReader* const br) {
return (size_t)(br->last_in - br->next_in);
}
static BROTLI_INLINE void BrotliBitReaderSaveState(
BrotliBitReader* const from, BrotliBitReaderState* to) {
to->val_ = from->val_;
to->bit_pos_ = from->bit_pos_;
to->next_in = from->next_in;
to->avail_in = BrotliBitReaderGetAvailIn(from);
}
static BROTLI_INLINE void BrotliBitReaderSetInput(
BrotliBitReader* const br, const uint8_t* next_in, size_t avail_in) {
br->next_in = next_in;
br->last_in = (avail_in == 0) ? next_in : (next_in + avail_in);
if (avail_in + 1 > BROTLI_FAST_INPUT_SLACK) {
br->guard_in = next_in + (avail_in + 1 - BROTLI_FAST_INPUT_SLACK);
} else {
br->guard_in = next_in;
}
}
static BROTLI_INLINE void BrotliBitReaderRestoreState(
BrotliBitReader* const to, BrotliBitReaderState* from) {
to->val_ = from->val_;
to->bit_pos_ = from->bit_pos_;
to->next_in = from->next_in;
BrotliBitReaderSetInput(to, from->next_in, from->avail_in);
}
static BROTLI_INLINE brotli_reg_t BrotliGetAvailableBits(
const BrotliBitReader* br) {
return br->bit_pos_;
}
/* Returns amount of unread bytes the bit reader still has buffered from the
BrotliInput, including whole bytes in br->val_. Result is capped with
maximal ring-buffer size (larger number won't be utilized anyway). */
static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {
static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS;
size_t avail_in = BrotliBitReaderGetAvailIn(br);
if (avail_in > kCap) return kCap;
return avail_in + (BrotliGetAvailableBits(br) >> 3);
}
/* Checks if there is at least |num| bytes left in the input ring-buffer
(excluding the bits remaining in br->val_). */
static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(
BrotliBitReader* const br) {
return TO_BROTLI_BOOL(br->next_in < br->guard_in);
}
/* Load more bits into accumulator. */
static BROTLI_INLINE brotli_reg_t BrotliBitReaderLoadBits(brotli_reg_t val,
brotli_reg_t new_bits,
brotli_reg_t count,
brotli_reg_t offset) {
BROTLI_DCHECK(
!((val >> offset) & ~new_bits & ~(~((brotli_reg_t)0) << count)));
(void)count;
return val | (new_bits << offset);
}
/* Guarantees that there are at least |n_bits| + 1 bits in accumulator.
Precondition: accumulator contains at least 1 bit.
|n_bits| should be in the range [1..24] for regular build. For portable
non-64-bit little-endian build only 16 bits are safe to request. */
static BROTLI_INLINE void BrotliFillBitWindow(
BrotliBitReader* const br, brotli_reg_t n_bits) {
#if (BROTLI_64_BITS)
if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
(n_bits <= 8)) {
brotli_reg_t bit_pos = br->bit_pos_;
if (bit_pos <= 8) {
br->val_ = BrotliBitReaderLoadBits(br->val_,
BROTLI_UNALIGNED_LOAD64LE(br->next_in), 56, bit_pos);
br->bit_pos_ = bit_pos + 56;
br->next_in += 7;
}
} else if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
(n_bits <= 16)) {
brotli_reg_t bit_pos = br->bit_pos_;
if (bit_pos <= 16) {
br->val_ = BrotliBitReaderLoadBits(br->val_,
BROTLI_UNALIGNED_LOAD64LE(br->next_in), 48, bit_pos);
br->bit_pos_ = bit_pos + 48;
br->next_in += 6;
}
} else {
brotli_reg_t bit_pos = br->bit_pos_;
if (bit_pos <= 32) {
br->val_ = BrotliBitReaderLoadBits(br->val_,
(uint64_t)BROTLI_UNALIGNED_LOAD32LE(br->next_in), 32, bit_pos);
br->bit_pos_ = bit_pos + 32;
br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
}
}
#else
if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
(n_bits <= 8)) {
brotli_reg_t bit_pos = br->bit_pos_;
if (bit_pos <= 8) {
br->val_ = BrotliBitReaderLoadBits(br->val_,
BROTLI_UNALIGNED_LOAD32LE(br->next_in), 24, bit_pos);
br->bit_pos_ = bit_pos + 24;
br->next_in += 3;
}
} else {
brotli_reg_t bit_pos = br->bit_pos_;
if (bit_pos <= 16) {
br->val_ = BrotliBitReaderLoadBits(br->val_,
(uint32_t)BROTLI_UNALIGNED_LOAD16LE(br->next_in), 16, bit_pos);
br->bit_pos_ = bit_pos + 16;
br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
}
}
#endif
}
/* Mostly like BrotliFillBitWindow, but guarantees only 16 bits and reads no
more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */
static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) {
BrotliFillBitWindow(br, 17);
}
/* Tries to pull one byte of input to accumulator.
Returns BROTLI_FALSE if there is no input available. */
static BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) {
if (br->next_in == br->last_in) {
return BROTLI_FALSE;
}
br->val_ = BrotliBitReaderLoadBits(br->val_,
(brotli_reg_t)*br->next_in, 8, br->bit_pos_);
br->bit_pos_ += 8;
++br->next_in;
return BROTLI_TRUE;
}
/* Returns currently available bits.
The number of valid bits could be calculated by BrotliGetAvailableBits. */
static BROTLI_INLINE brotli_reg_t BrotliGetBitsUnmasked(
BrotliBitReader* const br) {
return br->val_;
}
/* Like BrotliGetBits, but does not mask the result.
The result contains at least 16 valid bits. */
static BROTLI_INLINE brotli_reg_t BrotliGet16BitsUnmasked(
BrotliBitReader* const br) {
BrotliFillBitWindow(br, 16);
return (brotli_reg_t)BrotliGetBitsUnmasked(br);
}
/* Returns the specified number of bits from |br| without advancing bit
position. */
static BROTLI_INLINE brotli_reg_t BrotliGetBits(
BrotliBitReader* const br, brotli_reg_t n_bits) {
BrotliFillBitWindow(br, n_bits);
return BrotliGetBitsUnmasked(br) & BitMask(n_bits);
}
/* Tries to peek the specified amount of bits. Returns BROTLI_FALSE, if there
is not enough input. */
static BROTLI_INLINE BROTLI_BOOL BrotliSafeGetBits(
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
while (BrotliGetAvailableBits(br) < n_bits) {
if (!BrotliPullByte(br)) {
return BROTLI_FALSE;
}
}
*val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);
return BROTLI_TRUE;
}
/* Advances the bit pos by |n_bits|. */
static BROTLI_INLINE void BrotliDropBits(
BrotliBitReader* const br, brotli_reg_t n_bits) {
br->bit_pos_ -= n_bits;
br->val_ >>= n_bits;
}
/* Make sure that there are no spectre bits in accumulator.
This is important for the cases when some bytes are skipped
(i.e. never placed into accumulator). */
static BROTLI_INLINE void BrotliBitReaderNormalize(BrotliBitReader* br) {
/* Actually, it is enough to normalize when br->bit_pos_ == 0 */
if (br->bit_pos_ < (sizeof(brotli_reg_t) << 3u)) {
br->val_ &= (((brotli_reg_t)1) << br->bit_pos_) - 1;
}
}
static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {
brotli_reg_t unused_bytes = BrotliGetAvailableBits(br) >> 3;
brotli_reg_t unused_bits = unused_bytes << 3;
br->next_in =
(unused_bytes == 0) ? br->next_in : (br->next_in - unused_bytes);
br->bit_pos_ -= unused_bits;
BrotliBitReaderNormalize(br);
}
/* Reads the specified number of bits from |br| and advances the bit pos.
Precondition: accumulator MUST contain at least |n_bits|. */
static BROTLI_INLINE void BrotliTakeBits(BrotliBitReader* const br,
brotli_reg_t n_bits,
brotli_reg_t* val) {
*val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);
BROTLI_LOG(("[BrotliTakeBits] %d %d %d val: %6x\n",
(int)BrotliBitReaderGetAvailIn(br), (int)br->bit_pos_,
(int)n_bits, (int)*val));
BrotliDropBits(br, n_bits);
}
/* Reads the specified number of bits from |br| and advances the bit pos.
Assumes that there is enough input to perform BrotliFillBitWindow.
Up to 24 bits are allowed to be requested from this method. */
static BROTLI_INLINE brotli_reg_t BrotliReadBits24(
BrotliBitReader* const br, brotli_reg_t n_bits) {
BROTLI_DCHECK(n_bits <= 24);
if (BROTLI_64_BITS || (n_bits <= 16)) {
brotli_reg_t val;
BrotliFillBitWindow(br, n_bits);
BrotliTakeBits(br, n_bits, &val);
return val;
} else {
brotli_reg_t low_val;
brotli_reg_t high_val;
BrotliFillBitWindow(br, 16);
BrotliTakeBits(br, 16, &low_val);
BrotliFillBitWindow(br, 8);
BrotliTakeBits(br, n_bits - 16, &high_val);
return low_val | (high_val << 16);
}
}
/* Same as BrotliReadBits24, but allows reading up to 32 bits. */
static BROTLI_INLINE brotli_reg_t BrotliReadBits32(
BrotliBitReader* const br, brotli_reg_t n_bits) {
BROTLI_DCHECK(n_bits <= 32);
if (BROTLI_64_BITS || (n_bits <= 16)) {
brotli_reg_t val;
BrotliFillBitWindow(br, n_bits);
BrotliTakeBits(br, n_bits, &val);
return val;
} else {
brotli_reg_t low_val;
brotli_reg_t high_val;
BrotliFillBitWindow(br, 16);
BrotliTakeBits(br, 16, &low_val);
BrotliFillBitWindow(br, 16);
BrotliTakeBits(br, n_bits - 16, &high_val);
return low_val | (high_val << 16);
}
}
/* Tries to read the specified amount of bits. Returns BROTLI_FALSE, if there
is not enough input. |n_bits| MUST be positive.
Up to 24 bits are allowed to be requested from this method. */
static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
BROTLI_DCHECK(n_bits <= 24);
while (BrotliGetAvailableBits(br) < n_bits) {
if (!BrotliPullByte(br)) {
return BROTLI_FALSE;
}
}
BrotliTakeBits(br, n_bits, val);
return BROTLI_TRUE;
}
/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */
static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
BROTLI_DCHECK(n_bits <= 32);
if (BROTLI_64_BITS || (n_bits <= 24)) {
while (BrotliGetAvailableBits(br) < n_bits) {
if (!BrotliPullByte(br)) {
return BROTLI_FALSE;
}
}
BrotliTakeBits(br, n_bits, val);
return BROTLI_TRUE;
} else {
return BrotliSafeReadBits32Slow(br, n_bits, val);
}
}
/* Advances the bit reader position to the next byte boundary and verifies
that any skipped bits are set to zero. */
static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
brotli_reg_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;
brotli_reg_t pad_bits = 0;
if (pad_bits_count != 0) {
BrotliTakeBits(br, pad_bits_count, &pad_bits);
}
BrotliBitReaderNormalize(br);
return TO_BROTLI_BOOL(pad_bits == 0);
}
static BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) {
/* Check detour is legal: accumulator must to be empty. */
BROTLI_DCHECK(br->bit_pos_ == 0);
BROTLI_DCHECK(br->val_ == 0);
br->next_in += num;
}
/* Copies remaining input bytes stored in the bit reader to the output. Value
|num| may not be larger than BrotliGetRemainingBytes. The bit reader must be
warmed up again after this. */
static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,
BrotliBitReader* br, size_t num) {
while (BrotliGetAvailableBits(br) >= 8 && num > 0) {
*dest = (uint8_t)BrotliGetBitsUnmasked(br);
BrotliDropBits(br, 8);
++dest;
--num;
}
BrotliBitReaderNormalize(br);
if (num > 0) {
memcpy(dest, br->next_in, num);
BrotliDropBytes(br, num);
}
}
BROTLI_UNUSED_FUNCTION void BrotliBitReaderSuppressUnusedFunctions(void) {
BROTLI_UNUSED(&BrotliBitReaderSuppressUnusedFunctions);
BROTLI_UNUSED(&BrotliBitReaderGetAvailIn);
BROTLI_UNUSED(&BrotliBitReaderLoadBits);
BROTLI_UNUSED(&BrotliBitReaderRestoreState);
BROTLI_UNUSED(&BrotliBitReaderSaveState);
BROTLI_UNUSED(&BrotliBitReaderSetInput);
BROTLI_UNUSED(&BrotliBitReaderUnload);
BROTLI_UNUSED(&BrotliCheckInputAmount);
BROTLI_UNUSED(&BrotliCopyBytes);
BROTLI_UNUSED(&BrotliFillBitWindow16);
BROTLI_UNUSED(&BrotliGet16BitsUnmasked);
BROTLI_UNUSED(&BrotliGetBits);
BROTLI_UNUSED(&BrotliGetRemainingBytes);
BROTLI_UNUSED(&BrotliJumpToByteBoundary);
BROTLI_UNUSED(&BrotliReadBits24);
BROTLI_UNUSED(&BrotliReadBits32);
BROTLI_UNUSED(&BrotliSafeGetBits);
BROTLI_UNUSED(&BrotliSafeReadBits);
BROTLI_UNUSED(&BrotliSafeReadBits32);
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_DEC_BIT_READER_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/dec/dec_static_init.c
================================================
/* Copyright 2025 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
#include "static_init.h"
#include "../common/platform.h"
#include "../common/static_init.h"
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
#include "../common/dictionary.h"
#include "prefix.h"
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
static BROTLI_BOOL DoBrotliDecoderStaticInit(void) {
BROTLI_BOOL ok = BrotliDecoderInitCmdLut(kCmdLut);
if (!ok) return BROTLI_FALSE;
return BROTLI_TRUE;
}
#endif /* BROTLI_STATIC_INIT_NONE */
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)
static BROTLI_BOOL kEarlyInitOk;
static __attribute__((constructor)) void BrotliDecoderStaticInitEarly(void) {
kEarlyInitOk = DoBrotliDecoderStaticInit();
}
#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)
static BROTLI_BOOL kLazyInitOk;
void BrotliDecoderLazyStaticInitInner(void) {
kLazyInitOk = DoBrotliDecoderStaticInit();
}
#endif /* BROTLI_STATIC_INIT_EARLY */
BROTLI_BOOL BrotliDecoderEnsureStaticInit(void) {
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)
return BROTLI_TRUE;
#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)
return kEarlyInitOk;
#else
return kLazyInitOk;
#endif
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/dec/decode.c
================================================
/* 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
#include "../common/constants.h"
#include "../common/context.h"
#include "../common/dictionary.h"
#include "../common/platform.h"
#include "../common/shared_dictionary_internal.h"
#include "../common/transform.h"
#include "../common/version.h"
#include "bit_reader.h"
#include "huffman.h"
#include "prefix.h"
#include "state.h"
#include "static_init.h"
#if defined(BROTLI_TARGET_NEON)
#include
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define BROTLI_FAILURE(CODE) (BROTLI_DUMP(), CODE)
#define BROTLI_LOG_UINT(name) \
BROTLI_LOG(("[%s] %s = %lu\n", __func__, #name, (unsigned long)(name)))
#define BROTLI_LOG_ARRAY_INDEX(array_name, idx) \
BROTLI_LOG(("[%s] %s[%lu] = %lu\n", __func__, #array_name, \
(unsigned long)(idx), (unsigned long)array_name[idx]))
#define HUFFMAN_TABLE_BITS 8U
#define HUFFMAN_TABLE_MASK 0xFF
/* We need the slack region for the following reasons:
- doing up to two 16-byte copies for fast backward copying
- inserting transformed dictionary word:
255 prefix + 32 base + 255 suffix */
static const brotli_reg_t kRingBufferWriteAheadSlack = 542;
static const BROTLI_MODEL("small")
uint8_t kCodeLengthCodeOrder[BROTLI_CODE_LENGTH_CODES] = {
1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
};
/* Static prefix code for the complex code length code lengths. */
static const BROTLI_MODEL("small")
uint8_t kCodeLengthPrefixLength[16] = {
2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4,
};
static const BROTLI_MODEL("small")
uint8_t kCodeLengthPrefixValue[16] = {
0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5,
};
BROTLI_BOOL BrotliDecoderSetParameter(
BrotliDecoderState* state, BrotliDecoderParameter p, uint32_t value) {
if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
switch (p) {
case BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:
state->canny_ringbuffer_allocation = !!value ? 0 : 1;
return BROTLI_TRUE;
case BROTLI_DECODER_PARAM_LARGE_WINDOW:
state->large_window = TO_BROTLI_BOOL(!!value);
return BROTLI_TRUE;
default: return BROTLI_FALSE;
}
}
BrotliDecoderState* BrotliDecoderCreateInstance(
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
BrotliDecoderState* state = 0;
if (!BrotliDecoderEnsureStaticInit()) {
BROTLI_DUMP();
return 0;
}
if (!alloc_func && !free_func) {
state = (BrotliDecoderState*)malloc(sizeof(BrotliDecoderState));
} else if (alloc_func && free_func) {
state = (BrotliDecoderState*)alloc_func(opaque, sizeof(BrotliDecoderState));
}
if (state == 0) {
BROTLI_DUMP();
return 0;
}
if (!BrotliDecoderStateInit(state, alloc_func, free_func, opaque)) {
BROTLI_DUMP();
if (!alloc_func && !free_func) {
free(state);
} else if (alloc_func && free_func) {
free_func(opaque, state);
}
return 0;
}
return state;
}
/* Deinitializes and frees BrotliDecoderState instance. */
void BrotliDecoderDestroyInstance(BrotliDecoderState* state) {
if (!state) {
return;
} else {
brotli_free_func free_func = state->free_func;
void* opaque = state->memory_manager_opaque;
BrotliDecoderStateCleanup(state);
free_func(opaque, state);
}
}
/* Saves error code and converts it to BrotliDecoderResult. */
static BROTLI_NOINLINE BrotliDecoderResult SaveErrorCode(
BrotliDecoderState* s, BrotliDecoderErrorCode e, size_t consumed_input) {
s->error_code = (int)e;
s->used_input += consumed_input;
if ((s->buffer_length != 0) && (s->br.next_in == s->br.last_in)) {
/* If internal buffer is depleted at last, reset it. */
s->buffer_length = 0;
}
switch (e) {
case BROTLI_DECODER_SUCCESS:
return BROTLI_DECODER_RESULT_SUCCESS;
case BROTLI_DECODER_NEEDS_MORE_INPUT:
return BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
case BROTLI_DECODER_NEEDS_MORE_OUTPUT:
return BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
default:
return BROTLI_DECODER_RESULT_ERROR;
}
}
/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for "Large Window Brotli".
Precondition: bit-reader accumulator has at least 8 bits. */
static BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState* s,
BrotliBitReader* br) {
brotli_reg_t n;
BROTLI_BOOL large_window = s->large_window;
s->large_window = BROTLI_FALSE;
BrotliTakeBits(br, 1, &n);
if (n == 0) {
s->window_bits = 16;
return BROTLI_DECODER_SUCCESS;
}
BrotliTakeBits(br, 3, &n);
if (n != 0) {
s->window_bits = (17u + n) & 63u;
return BROTLI_DECODER_SUCCESS;
}
BrotliTakeBits(br, 3, &n);
if (n == 1) {
if (large_window) {
BrotliTakeBits(br, 1, &n);
if (n == 1) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
}
s->large_window = BROTLI_TRUE;
return BROTLI_DECODER_SUCCESS;
} else {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
}
}
if (n != 0) {
s->window_bits = (8u + n) & 63u;
return BROTLI_DECODER_SUCCESS;
}
s->window_bits = 17;
return BROTLI_DECODER_SUCCESS;
}
static BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {
#if defined(BROTLI_TARGET_NEON)
vst1q_u8(dst, vld1q_u8(src));
#else
uint32_t buffer[4];
memcpy(buffer, src, 16);
memcpy(dst, buffer, 16);
#endif
}
/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */
static BROTLI_NOINLINE BrotliDecoderErrorCode DecodeVarLenUint8(
BrotliDecoderState* s, BrotliBitReader* br, brotli_reg_t* value) {
brotli_reg_t bits;
switch (s->substate_decode_uint8) {
case BROTLI_STATE_DECODE_UINT8_NONE:
if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 1, &bits))) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (bits == 0) {
*value = 0;
return BROTLI_DECODER_SUCCESS;
}
/* Fall through. */
case BROTLI_STATE_DECODE_UINT8_SHORT:
if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) {
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_SHORT;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (bits == 0) {
*value = 1;
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
return BROTLI_DECODER_SUCCESS;
}
/* Use output value as a temporary storage. It MUST be persisted. */
*value = bits;
/* Fall through. */
case BROTLI_STATE_DECODE_UINT8_LONG:
if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) {
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_LONG;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
*value = ((brotli_reg_t)1U << *value) + bits;
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
return BROTLI_DECODER_SUCCESS;
default:
return
BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
}
}
/* Decodes a metablock length and flags by reading 2 - 31 bits. */
static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
BrotliDecoderState* s, BrotliBitReader* br) {
brotli_reg_t bits;
int i;
for (;;) {
switch (s->substate_metablock_header) {
case BROTLI_STATE_METABLOCK_HEADER_NONE:
if (!BrotliSafeReadBits(br, 1, &bits)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
s->is_last_metablock = bits ? 1 : 0;
s->meta_block_remaining_len = 0;
s->is_uncompressed = 0;
s->is_metadata = 0;
if (!s->is_last_metablock) {
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
break;
}
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_EMPTY;
/* Fall through. */
case BROTLI_STATE_METABLOCK_HEADER_EMPTY:
if (!BrotliSafeReadBits(br, 1, &bits)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (bits) {
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
return BROTLI_DECODER_SUCCESS;
}
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
/* Fall through. */
case BROTLI_STATE_METABLOCK_HEADER_NIBBLES:
if (!BrotliSafeReadBits(br, 2, &bits)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
s->size_nibbles = (uint8_t)(bits + 4);
s->loop_counter = 0;
if (bits == 3) {
s->is_metadata = 1;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_RESERVED;
break;
}
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_SIZE;
/* Fall through. */
case BROTLI_STATE_METABLOCK_HEADER_SIZE:
i = s->loop_counter;
for (; i < (int)s->size_nibbles; ++i) {
if (!BrotliSafeReadBits(br, 4, &bits)) {
s->loop_counter = i;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 4 &&
bits == 0) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE);
}
s->meta_block_remaining_len |= (int)(bits << (i * 4));
}
s->substate_metablock_header =
BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;
/* Fall through. */
case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED:
if (!s->is_last_metablock) {
if (!BrotliSafeReadBits(br, 1, &bits)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
s->is_uncompressed = bits ? 1 : 0;
}
++s->meta_block_remaining_len;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
return BROTLI_DECODER_SUCCESS;
case BROTLI_STATE_METABLOCK_HEADER_RESERVED:
if (!BrotliSafeReadBits(br, 1, &bits)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (bits != 0) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_RESERVED);
}
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES;
/* Fall through. */
case BROTLI_STATE_METABLOCK_HEADER_BYTES:
if (!BrotliSafeReadBits(br, 2, &bits)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (bits == 0) {
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
return BROTLI_DECODER_SUCCESS;
}
s->size_nibbles = (uint8_t)bits;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA;
/* Fall through. */
case BROTLI_STATE_METABLOCK_HEADER_METADATA:
i = s->loop_counter;
for (; i < (int)s->size_nibbles; ++i) {
if (!BrotliSafeReadBits(br, 8, &bits)) {
s->loop_counter = i;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 1 &&
bits == 0) {
return BROTLI_FAILURE(
BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE);
}
s->meta_block_remaining_len |= (int)(bits << (i * 8));
}
++s->meta_block_remaining_len;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
return BROTLI_DECODER_SUCCESS;
default:
return
BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
}
}
}
/* Decodes the Huffman code.
This method doesn't read data from the bit reader, BUT drops the amount of
bits that correspond to the decoded symbol.
bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */
static BROTLI_INLINE brotli_reg_t DecodeSymbol(brotli_reg_t bits,
const HuffmanCode* table,
BrotliBitReader* br) {
BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
BROTLI_HC_ADJUST_TABLE_INDEX(table, bits & HUFFMAN_TABLE_MASK);
if (BROTLI_HC_FAST_LOAD_BITS(table) > HUFFMAN_TABLE_BITS) {
brotli_reg_t nbits = BROTLI_HC_FAST_LOAD_BITS(table) - HUFFMAN_TABLE_BITS;
BrotliDropBits(br, HUFFMAN_TABLE_BITS);
BROTLI_HC_ADJUST_TABLE_INDEX(table,
BROTLI_HC_FAST_LOAD_VALUE(table) +
((bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits)));
}
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
return BROTLI_HC_FAST_LOAD_VALUE(table);
}
/* Reads and decodes the next Huffman code from bit-stream.
This method peeks 16 bits of input and drops 0 - 15 of them. */
static BROTLI_INLINE brotli_reg_t ReadSymbol(const HuffmanCode* table,
BrotliBitReader* br) {
return DecodeSymbol(BrotliGet16BitsUnmasked(br), table, br);
}
/* Same as DecodeSymbol, but it is known that there is less than 15 bits of
input are currently available. */
static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {
brotli_reg_t val;
brotli_reg_t available_bits = BrotliGetAvailableBits(br);
BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
if (available_bits == 0) {
if (BROTLI_HC_FAST_LOAD_BITS(table) == 0) {
*result = BROTLI_HC_FAST_LOAD_VALUE(table);
return BROTLI_TRUE;
}
return BROTLI_FALSE; /* No valid bits at all. */
}
val = BrotliGetBitsUnmasked(br);
BROTLI_HC_ADJUST_TABLE_INDEX(table, val & HUFFMAN_TABLE_MASK);
if (BROTLI_HC_FAST_LOAD_BITS(table) <= HUFFMAN_TABLE_BITS) {
if (BROTLI_HC_FAST_LOAD_BITS(table) <= available_bits) {
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
*result = BROTLI_HC_FAST_LOAD_VALUE(table);
return BROTLI_TRUE;
} else {
return BROTLI_FALSE; /* Not enough bits for the first level. */
}
}
if (available_bits <= HUFFMAN_TABLE_BITS) {
return BROTLI_FALSE; /* Not enough bits to move to the second level. */
}
/* Speculatively drop HUFFMAN_TABLE_BITS. */
val = (val & BitMask(BROTLI_HC_FAST_LOAD_BITS(table))) >> HUFFMAN_TABLE_BITS;
available_bits -= HUFFMAN_TABLE_BITS;
BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + val);
if (available_bits < BROTLI_HC_FAST_LOAD_BITS(table)) {
return BROTLI_FALSE; /* Not enough bits for the second level. */
}
BrotliDropBits(br, HUFFMAN_TABLE_BITS + BROTLI_HC_FAST_LOAD_BITS(table));
*result = BROTLI_HC_FAST_LOAD_VALUE(table);
return BROTLI_TRUE;
}
static BROTLI_INLINE BROTLI_BOOL SafeReadSymbol(
const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {
brotli_reg_t val;
if (BROTLI_PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) {
*result = DecodeSymbol(val, table, br);
return BROTLI_TRUE;
}
return SafeDecodeSymbol(table, br, result);
}
/* Makes a look-up in first level Huffman table. Peeks 8 bits. */
static BROTLI_INLINE void PreloadSymbol(int safe,
const HuffmanCode* table,
BrotliBitReader* br,
brotli_reg_t* bits,
brotli_reg_t* value) {
if (safe) {
return;
}
BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
BROTLI_HC_ADJUST_TABLE_INDEX(table, BrotliGetBits(br, HUFFMAN_TABLE_BITS));
*bits = BROTLI_HC_FAST_LOAD_BITS(table);
*value = BROTLI_HC_FAST_LOAD_VALUE(table);
}
/* Decodes the next Huffman code using data prepared by PreloadSymbol.
Reads 0 - 15 bits. Also peeks 8 following bits. */
static BROTLI_INLINE brotli_reg_t ReadPreloadedSymbol(const HuffmanCode* table,
BrotliBitReader* br,
brotli_reg_t* bits,
brotli_reg_t* value) {
brotli_reg_t result = *value;
if (BROTLI_PREDICT_FALSE(*bits > HUFFMAN_TABLE_BITS)) {
brotli_reg_t val = BrotliGet16BitsUnmasked(br);
const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value;
brotli_reg_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS));
BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(ext);
BrotliDropBits(br, HUFFMAN_TABLE_BITS);
BROTLI_HC_ADJUST_TABLE_INDEX(ext, (val >> HUFFMAN_TABLE_BITS) & mask);
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(ext));
result = BROTLI_HC_FAST_LOAD_VALUE(ext);
} else {
BrotliDropBits(br, *bits);
}
PreloadSymbol(0, table, br, bits, value);
return result;
}
/* Reads up to limit symbols from br and copies them into ringbuffer,
starting from pos. Caller must ensure that there is enough space
for the write. Returns the amount of symbols actually copied. */
static BROTLI_INLINE int BrotliCopyPreloadedSymbolsToU8(const HuffmanCode* table,
BrotliBitReader* br,
brotli_reg_t* bits,
brotli_reg_t* value,
uint8_t* ringbuffer,
int pos,
const int limit) {
/* Calculate range where CheckInputAmount is always true.
Start with the number of bytes we can read. */
int64_t new_lim = br->guard_in - br->next_in;
/* Convert to bits, since symbols use variable number of bits. */
new_lim *= 8;
/* At most 15 bits per symbol, so this is safe. */
new_lim /= 15;
const int kMaximalOverread = 4;
int pos_limit = limit;
int copies = 0;
if ((new_lim - kMaximalOverread) <= limit) {
// Safe cast, since new_lim is already < num_steps
pos_limit = (int)(new_lim - kMaximalOverread);
}
if (pos_limit < 0) {
pos_limit = 0;
}
copies = pos_limit;
pos_limit += pos;
/* Fast path, caller made sure it is safe to write,
we verified that is is safe to read. */
for (; pos < pos_limit; pos++) {
BROTLI_DCHECK(BrotliCheckInputAmount(br));
ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol(table, br, bits, value);
BROTLI_LOG_ARRAY_INDEX(ringbuffer, pos);
}
/* Do the remainder, caller made sure it is safe to write,
we need to bverify that it is safe to read. */
while (BrotliCheckInputAmount(br) && copies < limit) {
ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol(table, br, bits, value);
BROTLI_LOG_ARRAY_INDEX(ringbuffer, pos);
pos++;
copies++;
}
return copies;
}
static BROTLI_INLINE brotli_reg_t Log2Floor(brotli_reg_t x) {
brotli_reg_t result = 0;
while (x) {
x >>= 1;
++result;
}
return result;
}
/* Reads (s->symbol + 1) symbols.
Totally 1..4 symbols are read, 1..11 bits each.
The list of symbols MUST NOT contain duplicates. */
static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(
brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit,
BrotliDecoderState* s) {
/* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */
BrotliBitReader* br = &s->br;
BrotliMetablockHeaderArena* h = &s->arena.header;
brotli_reg_t max_bits = Log2Floor(alphabet_size_max - 1);
brotli_reg_t i = h->sub_loop_counter;
brotli_reg_t num_symbols = h->symbol;
while (i <= num_symbols) {
brotli_reg_t v;
if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {
h->sub_loop_counter = i;
h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (v >= alphabet_size_limit) {
return
BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
}
h->symbols_lists_array[i] = (uint16_t)v;
BROTLI_LOG_UINT(h->symbols_lists_array[i]);
++i;
}
for (i = 0; i < num_symbols; ++i) {
brotli_reg_t k = i + 1;
for (; k <= num_symbols; ++k) {
if (h->symbols_lists_array[i] == h->symbols_lists_array[k]) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);
}
}
}
return BROTLI_DECODER_SUCCESS;
}
/* Process single decoded symbol code length:
A) reset the repeat variable
B) remember code length (if it is not 0)
C) extend corresponding index-chain
D) reduce the Huffman space
E) update the histogram */
static BROTLI_INLINE void ProcessSingleCodeLength(brotli_reg_t code_len,
brotli_reg_t* symbol, brotli_reg_t* repeat, brotli_reg_t* space,
brotli_reg_t* prev_code_len, uint16_t* symbol_lists,
uint16_t* code_length_histo, int* next_symbol) {
*repeat = 0;
if (code_len != 0) { /* code_len == 1..15 */
symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol);
next_symbol[code_len] = (int)(*symbol);
*prev_code_len = code_len;
*space -= 32768U >> code_len;
code_length_histo[code_len]++;
BROTLI_LOG(("[ReadHuffmanCode] code_length[%d] = %d\n",
(int)*symbol, (int)code_len));
}
(*symbol)++;
}
/* Process repeated symbol code length.
A) Check if it is the extension of previous repeat sequence; if the decoded
value is not BROTLI_REPEAT_PREVIOUS_CODE_LENGTH, then it is a new
symbol-skip
B) Update repeat variable
C) Check if operation is feasible (fits alphabet)
D) For each symbol do the same operations as in ProcessSingleCodeLength
PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or
code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */
static BROTLI_INLINE void ProcessRepeatedCodeLength(brotli_reg_t code_len,
brotli_reg_t repeat_delta, brotli_reg_t alphabet_size, brotli_reg_t* symbol,
brotli_reg_t* repeat, brotli_reg_t* space, brotli_reg_t* prev_code_len,
brotli_reg_t* repeat_code_len, uint16_t* symbol_lists,
uint16_t* code_length_histo, int* next_symbol) {
brotli_reg_t old_repeat;
brotli_reg_t extra_bits = 3; /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */
brotli_reg_t new_len = 0; /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */
if (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
new_len = *prev_code_len;
extra_bits = 2;
}
if (*repeat_code_len != new_len) {
*repeat = 0;
*repeat_code_len = new_len;
}
old_repeat = *repeat;
if (*repeat > 0) {
*repeat -= 2;
*repeat <<= extra_bits;
}
*repeat += repeat_delta + 3U;
repeat_delta = *repeat - old_repeat;
if (*symbol + repeat_delta > alphabet_size) {
BROTLI_DUMP();
*symbol = alphabet_size;
*space = 0xFFFFF;
return;
}
BROTLI_LOG(("[ReadHuffmanCode] code_length[%d..%d] = %d\n",
(int)*symbol, (int)(*symbol + repeat_delta - 1), (int)*repeat_code_len));
if (*repeat_code_len != 0) {
brotli_reg_t last = *symbol + repeat_delta;
int next = next_symbol[*repeat_code_len];
do {
symbol_lists[next] = (uint16_t)*symbol;
next = (int)*symbol;
} while (++(*symbol) != last);
next_symbol[*repeat_code_len] = next;
*space -= repeat_delta << (15 - *repeat_code_len);
code_length_histo[*repeat_code_len] =
(uint16_t)(code_length_histo[*repeat_code_len] + repeat_delta);
} else {
*symbol += repeat_delta;
}
}
/* Reads and decodes symbol codelengths. */
static BrotliDecoderErrorCode ReadSymbolCodeLengths(
brotli_reg_t alphabet_size, BrotliDecoderState* s) {
BrotliBitReader* br = &s->br;
BrotliMetablockHeaderArena* h = &s->arena.header;
brotli_reg_t symbol = h->symbol;
brotli_reg_t repeat = h->repeat;
brotli_reg_t space = h->space;
brotli_reg_t prev_code_len = h->prev_code_len;
brotli_reg_t repeat_code_len = h->repeat_code_len;
uint16_t* symbol_lists = h->symbol_lists;
uint16_t* code_length_histo = h->code_length_histo;
int* next_symbol = h->next_symbol;
if (!BrotliWarmupBitReader(br)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
while (symbol < alphabet_size && space > 0) {
const HuffmanCode* p = h->table;
brotli_reg_t code_len;
BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
if (!BrotliCheckInputAmount(br)) {
h->symbol = symbol;
h->repeat = repeat;
h->prev_code_len = prev_code_len;
h->repeat_code_len = repeat_code_len;
h->space = space;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
BrotliFillBitWindow16(br);
BROTLI_HC_ADJUST_TABLE_INDEX(p, BrotliGetBitsUnmasked(br) &
BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p)); /* Use 1..5 bits. */
code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */
if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,
&prev_code_len, symbol_lists, code_length_histo, next_symbol);
} else { /* code_len == 16..17, extra_bits == 2..3 */
brotli_reg_t extra_bits =
(code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) ? 2 : 3;
brotli_reg_t repeat_delta =
BrotliGetBitsUnmasked(br) & BitMask(extra_bits);
BrotliDropBits(br, extra_bits);
ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
&symbol, &repeat, &space, &prev_code_len, &repeat_code_len,
symbol_lists, code_length_histo, next_symbol);
}
}
h->space = space;
return BROTLI_DECODER_SUCCESS;
}
static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
brotli_reg_t alphabet_size, BrotliDecoderState* s) {
BrotliBitReader* br = &s->br;
BrotliMetablockHeaderArena* h = &s->arena.header;
BROTLI_BOOL get_byte = BROTLI_FALSE;
while (h->symbol < alphabet_size && h->space > 0) {
const HuffmanCode* p = h->table;
brotli_reg_t code_len;
brotli_reg_t available_bits;
brotli_reg_t bits = 0;
BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
if (get_byte && !BrotliPullByte(br)) return BROTLI_DECODER_NEEDS_MORE_INPUT;
get_byte = BROTLI_FALSE;
available_bits = BrotliGetAvailableBits(br);
if (available_bits != 0) {
bits = (uint32_t)BrotliGetBitsUnmasked(br);
}
BROTLI_HC_ADJUST_TABLE_INDEX(p,
bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
if (BROTLI_HC_FAST_LOAD_BITS(p) > available_bits) {
get_byte = BROTLI_TRUE;
continue;
}
code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */
if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));
ProcessSingleCodeLength(code_len, &h->symbol, &h->repeat, &h->space,
&h->prev_code_len, h->symbol_lists, h->code_length_histo,
h->next_symbol);
} else { /* code_len == 16..17, extra_bits == 2..3 */
brotli_reg_t extra_bits = code_len - 14U;
brotli_reg_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) &
BitMask(extra_bits);
if (available_bits < BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits) {
get_byte = BROTLI_TRUE;
continue;
}
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits);
ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
&h->symbol, &h->repeat, &h->space, &h->prev_code_len,
&h->repeat_code_len, h->symbol_lists, h->code_length_histo,
h->next_symbol);
}
}
return BROTLI_DECODER_SUCCESS;
}
/* Reads and decodes 15..18 codes using static prefix code.
Each code is 2..4 bits long. In total 30..72 bits are used. */
static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
BrotliBitReader* br = &s->br;
BrotliMetablockHeaderArena* h = &s->arena.header;
brotli_reg_t num_codes = h->repeat;
brotli_reg_t space = h->space;
brotli_reg_t i = h->sub_loop_counter;
for (; i < BROTLI_CODE_LENGTH_CODES; ++i) {
const uint8_t code_len_idx = kCodeLengthCodeOrder[i];
brotli_reg_t ix;
brotli_reg_t v;
if (BROTLI_PREDICT_FALSE(!BrotliSafeGetBits(br, 4, &ix))) {
brotli_reg_t available_bits = BrotliGetAvailableBits(br);
if (available_bits != 0) {
ix = BrotliGetBitsUnmasked(br) & 0xF;
} else {
ix = 0;
}
if (kCodeLengthPrefixLength[ix] > available_bits) {
h->sub_loop_counter = i;
h->repeat = num_codes;
h->space = space;
h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
}
v = kCodeLengthPrefixValue[ix];
BrotliDropBits(br, kCodeLengthPrefixLength[ix]);
h->code_length_code_lengths[code_len_idx] = (uint8_t)v;
BROTLI_LOG_ARRAY_INDEX(h->code_length_code_lengths, code_len_idx);
if (v != 0) {
space = space - (32U >> v);
++num_codes;
++h->code_length_histo[v];
if (space - 1U >= 32U) {
/* space is 0 or wrapped around. */
break;
}
}
}
if (!(num_codes == 1 || space == 0)) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CL_SPACE);
}
return BROTLI_DECODER_SUCCESS;
}
/* Decodes the Huffman tables.
There are 2 scenarios:
A) Huffman code contains only few symbols (1..4). Those symbols are read
directly; their code lengths are defined by the number of symbols.
For this scenario 4 - 49 bits will be read.
B) 2-phase decoding:
B.1) Small Huffman table is decoded; it is specified with code lengths
encoded with predefined entropy code. 32 - 74 bits are used.
B.2) Decoded table is used to decode code lengths of symbols in resulting
Huffman table. In worst case 3520 bits are read. */
static BrotliDecoderErrorCode ReadHuffmanCode(brotli_reg_t alphabet_size_max,
brotli_reg_t alphabet_size_limit,
HuffmanCode* table,
brotli_reg_t* opt_table_size,
BrotliDecoderState* s) {
BrotliBitReader* br = &s->br;
BrotliMetablockHeaderArena* h = &s->arena.header;
/* State machine. */
for (;;) {
switch (h->substate_huffman) {
case BROTLI_STATE_HUFFMAN_NONE:
if (!BrotliSafeReadBits(br, 2, &h->sub_loop_counter)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
BROTLI_LOG_UINT(h->sub_loop_counter);
/* The value is used as follows:
1 for simple code;
0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
if (h->sub_loop_counter != 1) {
h->space = 32;
h->repeat = 0; /* num_codes */
memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo[0]) *
(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1));
memset(&h->code_length_code_lengths[0], 0,
sizeof(h->code_length_code_lengths));
h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
continue;
}
/* Fall through. */
case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:
/* Read symbols, codes & code lengths directly. */
if (!BrotliSafeReadBits(br, 2, &h->symbol)) { /* num_symbols */
h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
h->sub_loop_counter = 0;
/* Fall through. */
case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {
BrotliDecoderErrorCode result =
ReadSimpleHuffmanSymbols(alphabet_size_max, alphabet_size_limit, s);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
}
/* Fall through. */
case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {
brotli_reg_t table_size;
if (h->symbol == 3) {
brotli_reg_t bits;
if (!BrotliSafeReadBits(br, 1, &bits)) {
h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
h->symbol += bits;
}
BROTLI_LOG_UINT(h->symbol);
table_size = BrotliBuildSimpleHuffmanTable(table, HUFFMAN_TABLE_BITS,
h->symbols_lists_array,
(uint32_t)h->symbol);
if (opt_table_size) {
*opt_table_size = table_size;
}
h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
return BROTLI_DECODER_SUCCESS;
}
/* Decode Huffman-coded code lengths. */
case BROTLI_STATE_HUFFMAN_COMPLEX: {
brotli_reg_t i;
BrotliDecoderErrorCode result = ReadCodeLengthCodeLengths(s);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
BrotliBuildCodeLengthsHuffmanTable(h->table,
h->code_length_code_lengths,
h->code_length_histo);
memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo));
for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) {
h->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
h->symbol_lists[h->next_symbol[i]] = 0xFFFF;
}
h->symbol = 0;
h->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;
h->repeat = 0;
h->repeat_code_len = 0;
h->space = 32768;
h->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
}
/* Fall through. */
case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {
brotli_reg_t table_size;
BrotliDecoderErrorCode result = ReadSymbolCodeLengths(
alphabet_size_limit, s);
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
result = SafeReadSymbolCodeLengths(alphabet_size_limit, s);
}
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
if (h->space != 0) {
BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)h->space));
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);
}
table_size = BrotliBuildHuffmanTable(
table, HUFFMAN_TABLE_BITS, h->symbol_lists, h->code_length_histo);
if (opt_table_size) {
*opt_table_size = table_size;
}
h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
return BROTLI_DECODER_SUCCESS;
}
default:
return
BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
}
}
}
/* Decodes a block length by reading 3..39 bits. */
static BROTLI_INLINE brotli_reg_t ReadBlockLength(const HuffmanCode* table,
BrotliBitReader* br) {
brotli_reg_t code;
brotli_reg_t nbits;
code = ReadSymbol(table, br);
nbits = _kBrotliPrefixCodeRanges[code].nbits; /* nbits == 2..24 */
return _kBrotliPrefixCodeRanges[code].offset + BrotliReadBits24(br, nbits);
}
/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then
reading can't be continued with ReadBlockLength. */
static BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(
BrotliDecoderState* s, brotli_reg_t* result, const HuffmanCode* table,
BrotliBitReader* br) {
brotli_reg_t index;
if (s->substate_read_block_length == BROTLI_STATE_READ_BLOCK_LENGTH_NONE) {
if (!SafeReadSymbol(table, br, &index)) {
return BROTLI_FALSE;
}
} else {
index = s->block_length_index;
}
{
brotli_reg_t bits;
brotli_reg_t nbits = _kBrotliPrefixCodeRanges[index].nbits;
brotli_reg_t offset = _kBrotliPrefixCodeRanges[index].offset;
if (!BrotliSafeReadBits(br, nbits, &bits)) {
s->block_length_index = index;
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;
return BROTLI_FALSE;
}
*result = offset + bits;
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
return BROTLI_TRUE;
}
}
/* Transform:
1) initialize list L with values 0, 1,... 255
2) For each input element X:
2.1) let Y = L[X]
2.2) remove X-th element from L
2.3) prepend Y to L
2.4) append Y to output
In most cases max(Y) <= 7, so most of L remains intact.
To reduce the cost of initialization, we reuse L, remember the upper bound
of Y values, and reinitialize only first elements in L.
Most of input values are 0 and 1. To reduce number of branches, we replace
inner for loop with do-while. */
static BROTLI_NOINLINE void InverseMoveToFrontTransform(
uint8_t* v, brotli_reg_t v_len, BrotliDecoderState* state) {
/* Reinitialize elements that could have been changed. */
brotli_reg_t i = 1;
brotli_reg_t upper_bound = state->mtf_upper_bound;
uint32_t* mtf = &state->mtf[1]; /* Make mtf[-1] addressable. */
uint8_t* mtf_u8 = (uint8_t*)mtf;
/* Load endian-aware constant. */
const uint8_t b0123[4] = {0, 1, 2, 3};
uint32_t pattern;
memcpy(&pattern, &b0123, 4);
/* Initialize list using 4 consequent values pattern. */
mtf[0] = pattern;
do {
pattern += 0x04040404; /* Advance all 4 values by 4. */
mtf[i] = pattern;
i++;
} while (i <= upper_bound);
/* Transform the input. */
upper_bound = 0;
for (i = 0; i < v_len; ++i) {
int index = v[i];
uint8_t value = mtf_u8[index];
upper_bound |= v[i];
v[i] = value;
mtf_u8[-1] = value;
do {
index--;
mtf_u8[index + 1] = mtf_u8[index];
} while (index >= 0);
}
/* Remember amount of elements to be reinitialized. */
state->mtf_upper_bound = upper_bound >> 2;
}
/* Decodes a series of Huffman table using ReadHuffmanCode function. */
static BrotliDecoderErrorCode HuffmanTreeGroupDecode(
HuffmanTreeGroup* group, BrotliDecoderState* s) {
BrotliMetablockHeaderArena* h = &s->arena.header;
if (h->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
h->next = group->codes;
h->htree_index = 0;
h->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;
}
while (h->htree_index < group->num_htrees) {
brotli_reg_t table_size;
BrotliDecoderErrorCode result = ReadHuffmanCode(group->alphabet_size_max,
group->alphabet_size_limit, h->next, &table_size, s);
if (result != BROTLI_DECODER_SUCCESS) return result;
group->htrees[h->htree_index] = h->next;
h->next += table_size;
++h->htree_index;
}
h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
return BROTLI_DECODER_SUCCESS;
}
/* Decodes a context map.
Decoding is done in 4 phases:
1) Read auxiliary information (6..16 bits) and allocate memory.
In case of trivial context map, decoding is finished at this phase.
2) Decode Huffman table using ReadHuffmanCode function.
This table will be used for reading context map items.
3) Read context map items; "0" values could be run-length encoded.
4) Optionally, apply InverseMoveToFront transform to the resulting map. */
static BrotliDecoderErrorCode DecodeContextMap(brotli_reg_t context_map_size,
brotli_reg_t* num_htrees,
uint8_t** context_map_arg,
BrotliDecoderState* s) {
BrotliBitReader* br = &s->br;
BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
BrotliMetablockHeaderArena* h = &s->arena.header;
switch ((int)h->substate_context_map) {
case BROTLI_STATE_CONTEXT_MAP_NONE:
result = DecodeVarLenUint8(s, br, num_htrees);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
(*num_htrees)++;
h->context_index = 0;
BROTLI_LOG_UINT(context_map_size);
BROTLI_LOG_UINT(*num_htrees);
*context_map_arg =
(uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)context_map_size);
if (*context_map_arg == 0) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP);
}
if (*num_htrees <= 1) {
memset(*context_map_arg, 0, (size_t)context_map_size);
return BROTLI_DECODER_SUCCESS;
}
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
/* Fall through. */
case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {
brotli_reg_t bits;
/* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe
to peek 4 bits ahead. */
if (!BrotliSafeGetBits(br, 5, &bits)) {
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if ((bits & 1) != 0) { /* Use RLE for zeros. */
h->max_run_length_prefix = (bits >> 1) + 1;
BrotliDropBits(br, 5);
} else {
h->max_run_length_prefix = 0;
BrotliDropBits(br, 1);
}
BROTLI_LOG_UINT(h->max_run_length_prefix);
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
}
/* Fall through. */
case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: {
brotli_reg_t alphabet_size = *num_htrees + h->max_run_length_prefix;
result = ReadHuffmanCode(alphabet_size, alphabet_size,
h->context_map_table, NULL, s);
if (result != BROTLI_DECODER_SUCCESS) return result;
h->code = 0xFFFF;
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
}
/* Fall through. */
case BROTLI_STATE_CONTEXT_MAP_DECODE: {
brotli_reg_t context_index = h->context_index;
brotli_reg_t max_run_length_prefix = h->max_run_length_prefix;
uint8_t* context_map = *context_map_arg;
brotli_reg_t code = h->code;
BROTLI_BOOL skip_preamble = (code != 0xFFFF);
while (context_index < context_map_size || skip_preamble) {
if (!skip_preamble) {
if (!SafeReadSymbol(h->context_map_table, br, &code)) {
h->code = 0xFFFF;
h->context_index = context_index;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
BROTLI_LOG_UINT(code);
if (code == 0) {
context_map[context_index++] = 0;
continue;
}
if (code > max_run_length_prefix) {
context_map[context_index++] =
(uint8_t)(code - max_run_length_prefix);
continue;
}
} else {
skip_preamble = BROTLI_FALSE;
}
/* RLE sub-stage. */
{
brotli_reg_t reps;
if (!BrotliSafeReadBits(br, code, &reps)) {
h->code = code;
h->context_index = context_index;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
reps += (brotli_reg_t)1U << code;
BROTLI_LOG_UINT(reps);
if (context_index + reps > context_map_size) {
return
BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT);
}
do {
context_map[context_index++] = 0;
} while (--reps);
}
}
}
/* Fall through. */
case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {
brotli_reg_t bits;
if (!BrotliSafeReadBits(br, 1, &bits)) {
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
if (bits != 0) {
InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);
}
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
return BROTLI_DECODER_SUCCESS;
}
default:
return
BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
}
}
/* Decodes a command or literal and updates block type ring-buffer.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
int safe, BrotliDecoderState* s, int tree_type) {
brotli_reg_t max_block_type = s->num_block_types[tree_type];
const HuffmanCode* type_tree = &s->block_type_trees[
tree_type * BROTLI_HUFFMAN_MAX_SIZE_258];
const HuffmanCode* len_tree = &s->block_len_trees[
tree_type * BROTLI_HUFFMAN_MAX_SIZE_26];
BrotliBitReader* br = &s->br;
brotli_reg_t* ringbuffer = &s->block_type_rb[tree_type * 2];
brotli_reg_t block_type;
if (max_block_type <= 1) {
return BROTLI_FALSE;
}
/* Read 0..15 + 3..39 bits. */
if (!safe) {
block_type = ReadSymbol(type_tree, br);
s->block_length[tree_type] = ReadBlockLength(len_tree, br);
} else {
BrotliBitReaderState memento;
BrotliBitReaderSaveState(br, &memento);
if (!SafeReadSymbol(type_tree, br, &block_type)) return BROTLI_FALSE;
if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) {
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
BrotliBitReaderRestoreState(br, &memento);
return BROTLI_FALSE;
}
}
if (block_type == 1) {
block_type = ringbuffer[1] + 1;
} else if (block_type == 0) {
block_type = ringbuffer[0];
} else {
block_type -= 2;
}
if (block_type >= max_block_type) {
block_type -= max_block_type;
}
ringbuffer[0] = ringbuffer[1];
ringbuffer[1] = block_type;
return BROTLI_TRUE;
}
static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(
BrotliDecoderState* s) {
size_t i;
for (i = 0; i < 8; ++i) s->trivial_literal_contexts[i] = 0;
for (i = 0; i < s->num_block_types[0]; i++) {
size_t offset = i << BROTLI_LITERAL_CONTEXT_BITS;
size_t error = 0;
size_t sample = s->context_map[offset];
size_t j;
for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS);) {
/* NOLINTNEXTLINE(bugprone-macro-repeated-side-effects) */
BROTLI_REPEAT_4({ error |= s->context_map[offset + j++] ^ sample; })
}
if (error == 0) {
s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31);
}
}
}
static BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState* s) {
uint8_t context_mode;
size_t trivial;
brotli_reg_t block_type = s->block_type_rb[1];
brotli_reg_t context_offset = block_type << BROTLI_LITERAL_CONTEXT_BITS;
s->context_map_slice = s->context_map + context_offset;
trivial = s->trivial_literal_contexts[block_type >> 5];
s->trivial_literal_context = (trivial >> (block_type & 31)) & 1;
s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]];
context_mode = s->context_modes[block_type] & 3;
s->context_lookup = BROTLI_CONTEXT_LUT(context_mode);
}
/* Decodes the block type and updates the state for literal context.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(
int safe, BrotliDecoderState* s) {
if (!DecodeBlockTypeAndLength(safe, s, 0)) {
return BROTLI_FALSE;
}
PrepareLiteralDecoding(s);
return BROTLI_TRUE;
}
static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
DecodeLiteralBlockSwitchInternal(0, s);
}
static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(
BrotliDecoderState* s) {
return DecodeLiteralBlockSwitchInternal(1, s);
}
/* Block switch for insert/copy length.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(
int safe, BrotliDecoderState* s) {
if (!DecodeBlockTypeAndLength(safe, s, 1)) {
return BROTLI_FALSE;
}
s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]];
return BROTLI_TRUE;
}
static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {
DecodeCommandBlockSwitchInternal(0, s);
}
static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(
BrotliDecoderState* s) {
return DecodeCommandBlockSwitchInternal(1, s);
}
/* Block switch for distance codes.
Reads 3..54 bits. */
static BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(
int safe, BrotliDecoderState* s) {
if (!DecodeBlockTypeAndLength(safe, s, 2)) {
return BROTLI_FALSE;
}
s->dist_context_map_slice = s->dist_context_map +
(s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS);
s->dist_htree_index = s->dist_context_map_slice[s->distance_context];
return BROTLI_TRUE;
}
static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
DecodeDistanceBlockSwitchInternal(0, s);
}
static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(
BrotliDecoderState* s) {
return DecodeDistanceBlockSwitchInternal(1, s);
}
static size_t UnwrittenBytes(const BrotliDecoderState* s, BROTLI_BOOL wrap) {
size_t pos = wrap && s->pos > s->ringbuffer_size ?
(size_t)s->ringbuffer_size : (size_t)(s->pos);
size_t partial_pos_rb = (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos;
return partial_pos_rb - s->partial_pos_out;
}
/* Dumps output.
Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push
and either ring-buffer is as big as window size, or |force| is true. */
static BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(
BrotliDecoderState* s, size_t* available_out, uint8_t** next_out,
size_t* total_out, BROTLI_BOOL force) {
uint8_t* start =
s->ringbuffer + (s->partial_pos_out & (size_t)s->ringbuffer_mask);
size_t to_write = UnwrittenBytes(s, BROTLI_TRUE);
size_t num_written = *available_out;
if (num_written > to_write) {
num_written = to_write;
}
if (s->meta_block_remaining_len < 0) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1);
}
if (next_out && !*next_out) {
*next_out = start;
} else {
if (next_out) {
memcpy(*next_out, start, num_written);
*next_out += num_written;
}
}
*available_out -= num_written;
BROTLI_LOG_UINT(to_write);
BROTLI_LOG_UINT(num_written);
s->partial_pos_out += num_written;
if (total_out) {
*total_out = s->partial_pos_out;
}
if (num_written < to_write) {
if (s->ringbuffer_size == (1 << s->window_bits) || force) {
return BROTLI_DECODER_NEEDS_MORE_OUTPUT;
} else {
return BROTLI_DECODER_SUCCESS;
}
}
/* Wrap ring buffer only if it has reached its maximal size. */
if (s->ringbuffer_size == (1 << s->window_bits) &&
s->pos >= s->ringbuffer_size) {
s->pos -= s->ringbuffer_size;
s->rb_roundtrips++;
s->should_wrap_ringbuffer = (size_t)s->pos != 0 ? 1 : 0;
}
return BROTLI_DECODER_SUCCESS;
}
static void BROTLI_NOINLINE WrapRingBuffer(BrotliDecoderState* s) {
if (s->should_wrap_ringbuffer) {
memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos);
s->should_wrap_ringbuffer = 0;
}
}
/* Allocates ring-buffer.
s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before
this function is called.
Last two bytes of ring-buffer are initialized to 0, so context calculation
could be done uniformly for the first two and all other positions. */
static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
BrotliDecoderState* s) {
uint8_t* old_ringbuffer = s->ringbuffer;
if (s->ringbuffer_size == s->new_ringbuffer_size) {
return BROTLI_TRUE;
}
s->ringbuffer = (uint8_t*)BROTLI_DECODER_ALLOC(s,
(size_t)(s->new_ringbuffer_size) + kRingBufferWriteAheadSlack);
if (s->ringbuffer == 0) {
/* Restore previous value. */
s->ringbuffer = old_ringbuffer;
return BROTLI_FALSE;
}
s->ringbuffer[s->new_ringbuffer_size - 2] = 0;
s->ringbuffer[s->new_ringbuffer_size - 1] = 0;
if (!!old_ringbuffer) {
memcpy(s->ringbuffer, old_ringbuffer, (size_t)s->pos);
BROTLI_DECODER_FREE(s, old_ringbuffer);
}
s->ringbuffer_size = s->new_ringbuffer_size;
s->ringbuffer_mask = s->new_ringbuffer_size - 1;
s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;
return BROTLI_TRUE;
}
static BrotliDecoderErrorCode BROTLI_NOINLINE
SkipMetadataBlock(BrotliDecoderState* s) {
BrotliBitReader* br = &s->br;
int nbytes;
if (s->meta_block_remaining_len == 0) {
return BROTLI_DECODER_SUCCESS;
}
BROTLI_DCHECK((BrotliGetAvailableBits(br) & 7) == 0);
/* Drain accumulator. */
if (BrotliGetAvailableBits(br) >= 8) {
uint8_t buffer[8];
nbytes = (int)(BrotliGetAvailableBits(br)) >> 3;
BROTLI_DCHECK(nbytes <= 8);
if (nbytes > s->meta_block_remaining_len) {
nbytes = s->meta_block_remaining_len;
}
BrotliCopyBytes(buffer, br, (size_t)nbytes);
if (s->metadata_chunk_func) {
s->metadata_chunk_func(s->metadata_callback_opaque, buffer,
(size_t)nbytes);
}
s->meta_block_remaining_len -= nbytes;
if (s->meta_block_remaining_len == 0) {
return BROTLI_DECODER_SUCCESS;
}
}
/* Direct access to metadata is possible. */
nbytes = (int)BrotliGetRemainingBytes(br);
if (nbytes > s->meta_block_remaining_len) {
nbytes = s->meta_block_remaining_len;
}
if (nbytes > 0) {
if (s->metadata_chunk_func) {
s->metadata_chunk_func(s->metadata_callback_opaque, br->next_in,
(size_t)nbytes);
}
BrotliDropBytes(br, (size_t)nbytes);
s->meta_block_remaining_len -= nbytes;
if (s->meta_block_remaining_len == 0) {
return BROTLI_DECODER_SUCCESS;
}
}
BROTLI_DCHECK(BrotliGetRemainingBytes(br) == 0);
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
size_t* available_out, uint8_t** next_out, size_t* total_out,
BrotliDecoderState* s) {
/* TODO(eustas): avoid allocation for single uncompressed block. */
if (!BrotliEnsureRingBuffer(s)) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1);
}
/* State machine */
for (;;) {
switch (s->substate_uncompressed) {
case BROTLI_STATE_UNCOMPRESSED_NONE: {
int nbytes = (int)BrotliGetRemainingBytes(&s->br);
if (nbytes > s->meta_block_remaining_len) {
nbytes = s->meta_block_remaining_len;
}
if (s->pos + nbytes > s->ringbuffer_size) {
nbytes = s->ringbuffer_size - s->pos;
}
/* Copy remaining bytes from s->br.buf_ to ring-buffer. */
BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes);
s->pos += nbytes;
s->meta_block_remaining_len -= nbytes;
if (s->pos < 1 << s->window_bits) {
if (s->meta_block_remaining_len == 0) {
return BROTLI_DECODER_SUCCESS;
}
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE;
}
/* Fall through. */
case BROTLI_STATE_UNCOMPRESSED_WRITE: {
BrotliDecoderErrorCode result;
result = WriteRingBuffer(
s, available_out, next_out, total_out, BROTLI_FALSE);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
if (s->ringbuffer_size == 1 << s->window_bits) {
s->max_distance = s->max_backward_distance;
}
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
break;
}
}
}
BROTLI_DCHECK(0); /* Unreachable */
}
static BROTLI_BOOL AttachCompoundDictionary(
BrotliDecoderState* state, const uint8_t* data, size_t size) {
BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;
if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
if (!addon) {
addon = (BrotliDecoderCompoundDictionary*)BROTLI_DECODER_ALLOC(
state, sizeof(BrotliDecoderCompoundDictionary));
if (!addon) return BROTLI_FALSE;
addon->num_chunks = 0;
addon->total_size = 0;
addon->br_length = 0;
addon->br_copied = 0;
addon->block_bits = -1;
addon->chunk_offsets[0] = 0;
state->compound_dictionary = addon;
}
if (addon->num_chunks == 15) return BROTLI_FALSE;
addon->chunks[addon->num_chunks] = data;
addon->num_chunks++;
addon->total_size += (int)size;
addon->chunk_offsets[addon->num_chunks] = addon->total_size;
return BROTLI_TRUE;
}
static void EnsureCompoundDictionaryInitialized(BrotliDecoderState* state) {
BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;
/* 256 = (1 << 8) slots in block map. */
int block_bits = 8;
int cursor = 0;
int index = 0;
if (addon->block_bits != -1) return;
while (((addon->total_size - 1) >> block_bits) != 0) block_bits++;
block_bits -= 8;
addon->block_bits = block_bits;
while (cursor < addon->total_size) {
while (addon->chunk_offsets[index + 1] < cursor) index++;
addon->block_map[cursor >> block_bits] = (uint8_t)index;
cursor += 1 << block_bits;
}
}
static BROTLI_BOOL InitializeCompoundDictionaryCopy(BrotliDecoderState* s,
int address, int length) {
BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;
int index;
EnsureCompoundDictionaryInitialized(s);
index = addon->block_map[address >> addon->block_bits];
while (address >= addon->chunk_offsets[index + 1]) index++;
if (addon->total_size < address + length) return BROTLI_FALSE;
/* Update the recent distances cache. */
s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
++s->dist_rb_idx;
s->meta_block_remaining_len -= length;
addon->br_index = index;
addon->br_offset = address - addon->chunk_offsets[index];
addon->br_length = length;
addon->br_copied = 0;
return BROTLI_TRUE;
}
static int GetCompoundDictionarySize(BrotliDecoderState* s) {
return s->compound_dictionary ? s->compound_dictionary->total_size : 0;
}
static int CopyFromCompoundDictionary(BrotliDecoderState* s, int pos) {
BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;
int orig_pos = pos;
while (addon->br_length != addon->br_copied) {
uint8_t* copy_dst = &s->ringbuffer[pos];
const uint8_t* copy_src =
addon->chunks[addon->br_index] + addon->br_offset;
int space = s->ringbuffer_size - pos;
int rem_chunk_length = (addon->chunk_offsets[addon->br_index + 1] -
addon->chunk_offsets[addon->br_index]) - addon->br_offset;
int length = addon->br_length - addon->br_copied;
if (length > rem_chunk_length) length = rem_chunk_length;
if (length > space) length = space;
memcpy(copy_dst, copy_src, (size_t)length);
pos += length;
addon->br_offset += length;
addon->br_copied += length;
if (length == rem_chunk_length) {
addon->br_index++;
addon->br_offset = 0;
}
if (pos == s->ringbuffer_size) break;
}
return pos - orig_pos;
}
BROTLI_BOOL BrotliDecoderAttachDictionary(
BrotliDecoderState* state, BrotliSharedDictionaryType type,
size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {
brotli_reg_t i;
brotli_reg_t num_prefix_before = state->dictionary->num_prefix;
if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
if (!BrotliSharedDictionaryAttach(state->dictionary, type, data_size, data)) {
return BROTLI_FALSE;
}
for (i = num_prefix_before; i < state->dictionary->num_prefix; i++) {
if (!AttachCompoundDictionary(
state, state->dictionary->prefix[i],
state->dictionary->prefix_size[i])) {
return BROTLI_FALSE;
}
}
return BROTLI_TRUE;
}
/* Calculates the smallest feasible ring buffer.
If we know the data size is small, do not allocate more ring buffer
size than needed to reduce memory usage.
When this method is called, metablock size and flags MUST be decoded. */
static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(
BrotliDecoderState* s) {
int window_size = 1 << s->window_bits;
int new_ringbuffer_size = window_size;
/* We need at least 2 bytes of ring buffer size to get the last two
bytes for context from there */
int min_size = s->ringbuffer_size ? s->ringbuffer_size : 1024;
int output_size;
/* If maximum is already reached, no further extension is retired. */
if (s->ringbuffer_size == window_size) {
return;
}
/* Metadata blocks does not touch ring buffer. */
if (s->is_metadata) {
return;
}
if (!s->ringbuffer) {
output_size = 0;
} else {
output_size = s->pos;
}
output_size += s->meta_block_remaining_len;
min_size = min_size < output_size ? output_size : min_size;
if (!!s->canny_ringbuffer_allocation) {
/* Reduce ring buffer size to save memory when server is unscrupulous.
In worst case memory usage might be 1.5x bigger for a short period of
ring buffer reallocation. */
while ((new_ringbuffer_size >> 1) >= min_size) {
new_ringbuffer_size >>= 1;
}
}
s->new_ringbuffer_size = new_ringbuffer_size;
}
/* Reads 1..256 2-bit context modes. */
static BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState* s) {
BrotliBitReader* br = &s->br;
int i = s->loop_counter;
while (i < (int)s->num_block_types[0]) {
brotli_reg_t bits;
if (!BrotliSafeReadBits(br, 2, &bits)) {
s->loop_counter = i;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
}
s->context_modes[i] = (uint8_t)bits;
BROTLI_LOG_ARRAY_INDEX(s->context_modes, i);
i++;
}
return BROTLI_DECODER_SUCCESS;
}
static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {
int offset = s->distance_code - 3;
if (s->distance_code <= 3) {
/* Compensate double distance-ring-buffer roll for dictionary items. */
s->distance_context = 1 >> s->distance_code;
s->distance_code = s->dist_rb[(s->dist_rb_idx - offset) & 3];
s->dist_rb_idx -= s->distance_context;
} else {
int index_delta = 3;
int delta;
int base = s->distance_code - 10;
if (s->distance_code < 10) {
base = s->distance_code - 4;
} else {
index_delta = 2;
}
/* Unpack one of six 4-bit values. */
delta = ((0x605142 >> (4 * base)) & 0xF) - 3;
s->distance_code = s->dist_rb[(s->dist_rb_idx + index_delta) & 0x3] + delta;
if (s->distance_code <= 0) {
/* A huge distance will cause a BROTLI_FAILURE() soon.
This is a little faster than failing here. */
s->distance_code = 0x7FFFFFFF;
}
}
}
static BROTLI_INLINE BROTLI_BOOL SafeReadBits(
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
if (n_bits != 0) {
return BrotliSafeReadBits(br, n_bits, val);
} else {
*val = 0;
return BROTLI_TRUE;
}
}
static BROTLI_INLINE BROTLI_BOOL SafeReadBits32(
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
if (n_bits != 0) {
return BrotliSafeReadBits32(br, n_bits, val);
} else {
*val = 0;
return BROTLI_TRUE;
}
}
/*
RFC 7932 Section 4 with "..." shortenings and "[]" emendations.
Each distance ... is represented with a pair ...
The distance code is encoded using a prefix code... The number of extra bits
can be 0..24... Two additional parameters: NPOSTFIX (0..3), and ...
NDIRECT (0..120) ... are encoded in the meta-block header...
The first 16 distance symbols ... reference past distances... ring buffer ...
Next NDIRECT distance symbols ... represent distances from 1 to NDIRECT...
[For] distance symbols 16 + NDIRECT and greater ... the number of extra bits
... is given by the following formula:
[ xcode = dcode - NDIRECT - 16 ]
ndistbits = 1 + [ xcode ] >> (NPOSTFIX + 1)
...
*/
/*
RFC 7932 Section 9.2 with "..." shortenings and "[]" emendations.
... to get the actual value of the parameter NDIRECT, left-shift this
four-bit number by NPOSTFIX bits ...
*/
/* Remaining formulas from RFC 7932 Section 4 could be rewritten as following:
alphabet_size = 16 + NDIRECT + (max_distbits << (NPOSTFIX + 1))
half = ((xcode >> NPOSTFIX) & 1) << ndistbits
postfix = xcode & ((1 << NPOSTFIX) - 1)
range_start = 2 * (1 << ndistbits - 1 - 1)
distance = (range_start + half + extra) << NPOSTFIX + postfix + NDIRECT + 1
NB: ndistbits >= 1 -> range_start >= 0
NB: range_start has factor 2, as the range is covered by 2 "halves"
NB: extra -1 offset in range_start formula covers the absence of
ndistbits = 0 case
NB: when NPOSTFIX = 0, NDIRECT is not greater than 15
In other words, xcode has the following binary structure - XXXHPPP:
- XXX represent the number of extra distance bits
- H selects upper / lower range of distances
- PPP represent "postfix"
"Regular" distance encoding has NPOSTFIX = 0; omitting the postfix part
simplifies distance calculation.
Using NPOSTFIX > 0 allows cheaper encoding of regular structures, e.g. where
most of distances have the same reminder of division by 2/4/8. For example,
the table of int32_t values that come from different sources; if it is likely
that 3 highest bytes of values from the same source are the same, then
copy distance often looks like 4x + y.
Distance calculation could be rewritten to:
ndistbits = NDISTBITS(NDIRECT, NPOSTFIX)[dcode]
distance = OFFSET(NDIRECT, NPOSTFIX)[dcode] + extra << NPOSTFIX
NDISTBITS and OFFSET could be pre-calculated, as NDIRECT and NPOSTFIX could
change only once per meta-block.
*/
/* Calculates distance lookup table.
NB: it is possible to have all 64 tables precalculated. */
static void CalculateDistanceLut(BrotliDecoderState* s) {
BrotliMetablockBodyArena* b = &s->arena.body;
brotli_reg_t npostfix = s->distance_postfix_bits;
brotli_reg_t ndirect = s->num_direct_distance_codes;
brotli_reg_t alphabet_size_limit = s->distance_hgroup.alphabet_size_limit;
brotli_reg_t postfix = (brotli_reg_t)1u << npostfix;
brotli_reg_t j;
brotli_reg_t bits = 1;
brotli_reg_t half = 0;
/* Skip short codes. */
brotli_reg_t i = BROTLI_NUM_DISTANCE_SHORT_CODES;
/* Fill direct codes. */
for (j = 0; j < ndirect; ++j) {
b->dist_extra_bits[i] = 0;
b->dist_offset[i] = j + 1;
++i;
}
/* Fill regular distance codes. */
while (i < alphabet_size_limit) {
brotli_reg_t base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
/* Always fill the complete group. */
for (j = 0; j < postfix; ++j) {
b->dist_extra_bits[i] = (uint8_t)bits;
b->dist_offset[i] = base + j;
++i;
}
bits = bits + half;
half = half ^ 1;
}
}
/* Precondition: s->distance_code < 0. */
static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(
int safe, BrotliDecoderState* s, BrotliBitReader* br) {
BrotliMetablockBodyArena* b = &s->arena.body;
brotli_reg_t code;
brotli_reg_t bits;
BrotliBitReaderState memento;
HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index];
if (!safe) {
code = ReadSymbol(distance_tree, br);
} else {
BrotliBitReaderSaveState(br, &memento);
if (!SafeReadSymbol(distance_tree, br, &code)) {
return BROTLI_FALSE;
}
}
--s->block_length[2];
/* Convert the distance code to the actual distance by possibly
looking up past distances from the s->dist_rb. */
s->distance_context = 0;
if ((code & ~0xFu) == 0) {
s->distance_code = (int)code;
TakeDistanceFromRingBuffer(s);
return BROTLI_TRUE;
}
if (!safe) {
bits = BrotliReadBits32(br, b->dist_extra_bits[code]);
} else {
if (!SafeReadBits32(br, b->dist_extra_bits[code], &bits)) {
++s->block_length[2];
BrotliBitReaderRestoreState(br, &memento);
return BROTLI_FALSE;
}
}
s->distance_code =
(int)(b->dist_offset[code] + (bits << s->distance_postfix_bits));
return BROTLI_TRUE;
}
static BROTLI_INLINE void ReadDistance(
BrotliDecoderState* s, BrotliBitReader* br) {
ReadDistanceInternal(0, s, br);
}
static BROTLI_INLINE BROTLI_BOOL SafeReadDistance(
BrotliDecoderState* s, BrotliBitReader* br) {
return ReadDistanceInternal(1, s, br);
}
static BROTLI_INLINE BROTLI_BOOL ReadCommandInternal(
int safe, BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {
brotli_reg_t cmd_code;
brotli_reg_t insert_len_extra = 0;
brotli_reg_t copy_length;
CmdLutElement v;
BrotliBitReaderState memento;
if (!safe) {
cmd_code = ReadSymbol(s->htree_command, br);
} else {
BrotliBitReaderSaveState(br, &memento);
if (!SafeReadSymbol(s->htree_command, br, &cmd_code)) {
return BROTLI_FALSE;
}
}
v = kCmdLut[cmd_code];
s->distance_code = v.distance_code;
s->distance_context = v.context;
s->dist_htree_index = s->dist_context_map_slice[s->distance_context];
*insert_length = v.insert_len_offset;
if (!safe) {
if (BROTLI_PREDICT_FALSE(v.insert_len_extra_bits != 0)) {
insert_len_extra = BrotliReadBits24(br, v.insert_len_extra_bits);
}
copy_length = BrotliReadBits24(br, v.copy_len_extra_bits);
} else {
if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) ||
!SafeReadBits(br, v.copy_len_extra_bits, ©_length)) {
BrotliBitReaderRestoreState(br, &memento);
return BROTLI_FALSE;
}
}
s->copy_length = (int)copy_length + v.copy_len_offset;
--s->block_length[1];
*insert_length += (int)insert_len_extra;
return BROTLI_TRUE;
}
static BROTLI_INLINE void ReadCommand(
BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {
ReadCommandInternal(0, s, br, insert_length);
}
static BROTLI_INLINE BROTLI_BOOL SafeReadCommand(
BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {
return ReadCommandInternal(1, s, br, insert_length);
}
static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
int safe, BrotliBitReader* const br) {
if (safe) {
return BROTLI_TRUE;
}
return BrotliCheckInputAmount(br);
}
#define BROTLI_SAFE(METHOD) \
{ \
if (safe) { \
if (!Safe##METHOD) { \
result = BROTLI_DECODER_NEEDS_MORE_INPUT; \
goto saveStateAndReturn; \
} \
} else { \
METHOD; \
} \
}
static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
int safe, BrotliDecoderState* s) {
int pos = s->pos;
int i = s->loop_counter;
BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
BrotliBitReader* br = &s->br;
int compound_dictionary_size = GetCompoundDictionarySize(s);
if (!CheckInputAmount(safe, br)) {
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (!safe) {
BROTLI_UNUSED(BrotliWarmupBitReader(br));
}
/* Jump into state machine. */
if (s->state == BROTLI_STATE_COMMAND_BEGIN) {
goto CommandBegin;
} else if (s->state == BROTLI_STATE_COMMAND_INNER) {
goto CommandInner;
} else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) {
goto CommandPostDecodeLiterals;
} else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) {
goto CommandPostWrapCopy;
} else {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
}
CommandBegin:
if (safe) {
s->state = BROTLI_STATE_COMMAND_BEGIN;
}
if (!CheckInputAmount(safe, br)) {
s->state = BROTLI_STATE_COMMAND_BEGIN;
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) {
BROTLI_SAFE(DecodeCommandBlockSwitch(s));
goto CommandBegin;
}
/* Read the insert/copy length in the command. */
BROTLI_SAFE(ReadCommand(s, br, &i));
BROTLI_LOG(("[ProcessCommandsInternal] pos = %d insert = %d copy = %d\n",
pos, i, s->copy_length));
if (i == 0) {
goto CommandPostDecodeLiterals;
}
s->meta_block_remaining_len -= i;
CommandInner:
if (safe) {
s->state = BROTLI_STATE_COMMAND_INNER;
}
/* Read the literals in the command. */
if (s->trivial_literal_context) {
brotli_reg_t bits;
brotli_reg_t value;
PreloadSymbol(safe, s->literal_htree, br, &bits, &value);
if (!safe) {
// This is a hottest part of the decode, so we copy the loop below
// and optimize it by calculating the number of steps where all checks
// evaluate to false (ringbuffer size/block size/input size).
// Since all checks are loop invariant, we just need to find
// minimal number of iterations for a simple loop, and run
// the full version for the remainder.
int num_steps = i - 1;
if (num_steps > 0 && ((brotli_reg_t)(num_steps) > s->block_length[0])) {
// Safe cast, since block_length < steps
num_steps = (int)s->block_length[0];
}
if (s->ringbuffer_size >= pos &&
(s->ringbuffer_size - pos) <= num_steps) {
num_steps = s->ringbuffer_size - pos - 1;
}
if (num_steps < 0) {
num_steps = 0;
}
num_steps = BrotliCopyPreloadedSymbolsToU8(s->literal_htree, br, &bits,
&value, s->ringbuffer, pos,
num_steps);
pos += num_steps;
s->block_length[0] -= (brotli_reg_t)num_steps;
i -= num_steps;
do {
if (!CheckInputAmount(safe, br)) {
s->state = BROTLI_STATE_COMMAND_INNER;
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {
goto NextLiteralBlock;
}
BrotliCopyPreloadedSymbolsToU8(s->literal_htree, br, &bits, &value,
s->ringbuffer, pos, 1);
--s->block_length[0];
BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);
++pos;
if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {
s->state = BROTLI_STATE_COMMAND_INNER_WRITE;
--i;
goto saveStateAndReturn;
}
} while (--i != 0);
} else { /* safe */
do {
if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {
goto NextLiteralBlock;
}
brotli_reg_t literal;
if (!SafeReadSymbol(s->literal_htree, br, &literal)) {
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
s->ringbuffer[pos] = (uint8_t)literal;
--s->block_length[0];
BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);
++pos;
if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {
s->state = BROTLI_STATE_COMMAND_INNER_WRITE;
--i;
goto saveStateAndReturn;
}
} while (--i != 0);
}
} else {
uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];
uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];
do {
const HuffmanCode* hc;
uint8_t context;
if (!CheckInputAmount(safe, br)) {
s->state = BROTLI_STATE_COMMAND_INNER;
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {
goto NextLiteralBlock;
}
context = BROTLI_CONTEXT(p1, p2, s->context_lookup);
BROTLI_LOG_UINT(context);
hc = s->literal_hgroup.htrees[s->context_map_slice[context]];
p2 = p1;
if (!safe) {
p1 = (uint8_t)ReadSymbol(hc, br);
} else {
brotli_reg_t literal;
if (!SafeReadSymbol(hc, br, &literal)) {
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
p1 = (uint8_t)literal;
}
s->ringbuffer[pos] = p1;
--s->block_length[0];
BROTLI_LOG_UINT(s->context_map_slice[context]);
BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask);
++pos;
if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {
s->state = BROTLI_STATE_COMMAND_INNER_WRITE;
--i;
goto saveStateAndReturn;
}
} while (--i != 0);
}
BROTLI_LOG_UINT(s->meta_block_remaining_len);
if (BROTLI_PREDICT_FALSE(s->meta_block_remaining_len <= 0)) {
s->state = BROTLI_STATE_METABLOCK_DONE;
goto saveStateAndReturn;
}
CommandPostDecodeLiterals:
if (safe) {
s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
}
if (s->distance_code >= 0) {
/* Implicit distance case. */
s->distance_context = s->distance_code ? 0 : 1;
--s->dist_rb_idx;
s->distance_code = s->dist_rb[s->dist_rb_idx & 3];
} else {
/* Read distance code in the command, unless it was implicitly zero. */
if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) {
BROTLI_SAFE(DecodeDistanceBlockSwitch(s));
}
BROTLI_SAFE(ReadDistance(s, br));
}
BROTLI_LOG(("[ProcessCommandsInternal] pos = %d distance = %d\n",
pos, s->distance_code));
if (s->max_distance != s->max_backward_distance) {
s->max_distance =
(pos < s->max_backward_distance) ? pos : s->max_backward_distance;
}
i = s->copy_length;
/* Apply copy of LZ77 back-reference, or static dictionary reference if
the distance is larger than the max LZ77 distance */
if (s->distance_code > s->max_distance) {
/* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC.
With this choice, no signed overflow can occur after decoding
a special distance code (e.g., after adding 3 to the last distance). */
if (s->distance_code > BROTLI_MAX_ALLOWED_DISTANCE) {
BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
"len: %d bytes left: %d\n",
pos, s->distance_code, i, s->meta_block_remaining_len));
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DISTANCE);
}
if (s->distance_code - s->max_distance - 1 < compound_dictionary_size) {
int address = compound_dictionary_size -
(s->distance_code - s->max_distance);
if (!InitializeCompoundDictionaryCopy(s, address, i)) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY);
}
pos += CopyFromCompoundDictionary(s, pos);
if (pos >= s->ringbuffer_size) {
s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;
goto saveStateAndReturn;
}
} else if (i >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH &&
i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) {
uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];
uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];
uint8_t dict_id = s->dictionary->context_based ?
s->dictionary->context_map[BROTLI_CONTEXT(p1, p2, s->context_lookup)]
: 0;
const BrotliDictionary* words = s->dictionary->words[dict_id];
const BrotliTransforms* transforms = s->dictionary->transforms[dict_id];
int offset = (int)words->offsets_by_length[i];
brotli_reg_t shift = words->size_bits_by_length[i];
int address =
s->distance_code - s->max_distance - 1 - compound_dictionary_size;
int mask = (int)BitMask(shift);
int word_idx = address & mask;
int transform_idx = address >> shift;
/* Compensate double distance-ring-buffer roll. */
s->dist_rb_idx += s->distance_context;
offset += word_idx * i;
/* If the distance is out of bound, select a next static dictionary if
there exist multiple. */
if ((transform_idx >= (int)transforms->num_transforms ||
words->size_bits_by_length[i] == 0) &&
s->dictionary->num_dictionaries > 1) {
uint8_t dict_id2;
int dist_remaining = address -
(int)(((1u << shift) & ~1u)) * (int)transforms->num_transforms;
for (dict_id2 = 0; dict_id2 < s->dictionary->num_dictionaries;
dict_id2++) {
const BrotliDictionary* words2 = s->dictionary->words[dict_id2];
if (dict_id2 != dict_id && words2->size_bits_by_length[i] != 0) {
const BrotliTransforms* transforms2 =
s->dictionary->transforms[dict_id2];
brotli_reg_t shift2 = words2->size_bits_by_length[i];
int num = (int)((1u << shift2) & ~1u) *
(int)transforms2->num_transforms;
if (dist_remaining < num) {
dict_id = dict_id2;
words = words2;
transforms = transforms2;
address = dist_remaining;
shift = shift2;
mask = (int)BitMask(shift);
word_idx = address & mask;
transform_idx = address >> shift;
offset = (int)words->offsets_by_length[i] + word_idx * i;
break;
}
dist_remaining -= num;
}
}
}
if (BROTLI_PREDICT_FALSE(words->size_bits_by_length[i] == 0)) {
BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
"len: %d bytes left: %d\n",
pos, s->distance_code, i, s->meta_block_remaining_len));
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);
}
if (BROTLI_PREDICT_FALSE(!words->data)) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET);
}
if (transform_idx < (int)transforms->num_transforms) {
const uint8_t* word = &words->data[offset];
int len = i;
if (transform_idx == transforms->cutOffTransforms[0]) {
memcpy(&s->ringbuffer[pos], word, (size_t)len);
BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s]\n",
len, word));
} else {
len = BrotliTransformDictionaryWord(&s->ringbuffer[pos], word, len,
transforms, transform_idx);
BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s],"
" transform_idx = %d, transformed: [%.*s]\n",
i, word, transform_idx, len, &s->ringbuffer[pos]));
if (len == 0 && s->distance_code <= 120) {
BROTLI_LOG(("Invalid length-0 dictionary word after transform\n"));
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);
}
}
pos += len;
s->meta_block_remaining_len -= len;
if (pos >= s->ringbuffer_size) {
s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;
goto saveStateAndReturn;
}
} else {
BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
"len: %d bytes left: %d\n",
pos, s->distance_code, i, s->meta_block_remaining_len));
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);
}
} else {
BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
"len: %d bytes left: %d\n",
pos, s->distance_code, i, s->meta_block_remaining_len));
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);
}
} else {
int src_start = (pos - s->distance_code) & s->ringbuffer_mask;
uint8_t* copy_dst = &s->ringbuffer[pos];
uint8_t* copy_src = &s->ringbuffer[src_start];
int dst_end = pos + i;
int src_end = src_start + i;
/* Update the recent distances cache. */
s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
++s->dist_rb_idx;
s->meta_block_remaining_len -= i;
/* There are 32+ bytes of slack in the ring-buffer allocation.
Also, we have 16 short codes, that make these 16 bytes irrelevant
in the ring-buffer. Let's copy over them as a first guess. */
memmove16(copy_dst, copy_src);
if (src_end > pos && dst_end > src_start) {
/* Regions intersect. */
goto CommandPostWrapCopy;
}
if (dst_end >= s->ringbuffer_size || src_end >= s->ringbuffer_size) {
/* At least one region wraps. */
goto CommandPostWrapCopy;
}
pos += i;
if (i > 16) {
if (i > 32) {
memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16));
} else {
/* This branch covers about 45% cases.
Fixed size short copy allows more compiler optimizations. */
memmove16(copy_dst + 16, copy_src + 16);
}
}
}
BROTLI_LOG_UINT(s->meta_block_remaining_len);
if (s->meta_block_remaining_len <= 0) {
/* Next metablock, if any. */
s->state = BROTLI_STATE_METABLOCK_DONE;
goto saveStateAndReturn;
} else {
goto CommandBegin;
}
CommandPostWrapCopy:
{
int wrap_guard = s->ringbuffer_size - pos;
while (--i >= 0) {
s->ringbuffer[pos] =
s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask];
++pos;
if (BROTLI_PREDICT_FALSE(--wrap_guard == 0)) {
s->state = BROTLI_STATE_COMMAND_POST_WRITE_2;
goto saveStateAndReturn;
}
}
}
if (s->meta_block_remaining_len <= 0) {
/* Next metablock, if any. */
s->state = BROTLI_STATE_METABLOCK_DONE;
goto saveStateAndReturn;
} else {
goto CommandBegin;
}
NextLiteralBlock:
BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
goto CommandInner;
saveStateAndReturn:
s->pos = pos;
s->loop_counter = i;
return result;
}
#undef BROTLI_SAFE
static BROTLI_NOINLINE BrotliDecoderErrorCode ProcessCommands(
BrotliDecoderState* s) {
return ProcessCommandsInternal(0, s);
}
static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(
BrotliDecoderState* s) {
return ProcessCommandsInternal(1, s);
}
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)]) {
BrotliDecoderState s;
BrotliDecoderResult result;
size_t total_out = 0;
size_t available_in = encoded_size;
const uint8_t* next_in = encoded_buffer;
size_t available_out = *decoded_size;
uint8_t* next_out = decoded_buffer;
if (!BrotliDecoderStateInit(&s, 0, 0, 0)) {
return BROTLI_DECODER_RESULT_ERROR;
}
result = BrotliDecoderDecompressStream(
&s, &available_in, &next_in, &available_out, &next_out, &total_out);
*decoded_size = total_out;
BrotliDecoderStateCleanup(&s);
if (result != BROTLI_DECODER_RESULT_SUCCESS) {
result = BROTLI_DECODER_RESULT_ERROR;
}
return result;
}
/* Invariant: input stream is never overconsumed:
- invalid input implies that the whole stream is invalid -> any amount of
input could be read and discarded
- when result is "needs more input", then at least one more byte is REQUIRED
to complete decoding; all input data MUST be consumed by decoder, so
client could swap the input buffer
- when result is "needs more output" decoder MUST ensure that it doesn't
hold more than 7 bits in bit reader; this saves client from swapping input
buffer ahead of time
- when result is "success" decoder MUST return all unused data back to input
buffer; this is possible because the invariant is held on enter */
BrotliDecoderResult BrotliDecoderDecompressStream(
BrotliDecoderState* s, size_t* available_in, const uint8_t** next_in,
size_t* available_out, uint8_t** next_out, size_t* total_out) {
BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
BrotliBitReader* br = &s->br;
size_t input_size = *available_in;
#define BROTLI_SAVE_ERROR_CODE(code) \
SaveErrorCode(s, (code), input_size - *available_in)
/* Ensure that |total_out| is set, even if no data will ever be pushed out. */
if (total_out) {
*total_out = s->partial_pos_out;
}
/* Do not try to process further in a case of unrecoverable error. */
if ((int)s->error_code < 0) {
return BROTLI_DECODER_RESULT_ERROR;
}
if (*available_out && (!next_out || !*next_out)) {
return BROTLI_SAVE_ERROR_CODE(
BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS));
}
if (!*available_out) next_out = 0;
if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */
BrotliBitReaderSetInput(br, *next_in, *available_in);
} else {
/* At least one byte of input is required. More than one byte of input may
be required to complete the transaction -> reading more data must be
done in a loop -> do it in a main loop. */
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length);
}
/* State machine */
for (;;) {
if (result != BROTLI_DECODER_SUCCESS) {
/* Error, needs more input/output. */
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
if (s->ringbuffer != 0) { /* Pro-actively push output. */
BrotliDecoderErrorCode intermediate_result = WriteRingBuffer(s,
available_out, next_out, total_out, BROTLI_TRUE);
/* WriteRingBuffer checks s->meta_block_remaining_len validity. */
if ((int)intermediate_result < 0) {
result = intermediate_result;
break;
}
}
if (s->buffer_length != 0) { /* Used with internal buffer. */
if (br->next_in == br->last_in) {
/* Successfully finished read transaction.
Accumulator contains less than 8 bits, because internal buffer
is expanded byte-by-byte until it is enough to complete read. */
s->buffer_length = 0;
/* Switch to input stream and restart. */
result = BROTLI_DECODER_SUCCESS;
BrotliBitReaderSetInput(br, *next_in, *available_in);
continue;
} else if (*available_in != 0) {
/* Not enough data in buffer, but can take one more byte from
input stream. */
result = BROTLI_DECODER_SUCCESS;
BROTLI_DCHECK(s->buffer_length < 8);
s->buffer.u8[s->buffer_length] = **next_in;
s->buffer_length++;
BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length);
(*next_in)++;
(*available_in)--;
/* Retry with more data in buffer. */
continue;
}
/* Can't finish reading and no more input. */
break;
} else { /* Input stream doesn't contain enough input. */
/* Copy tail to internal buffer and return. */
*next_in = br->next_in;
*available_in = BrotliBitReaderGetAvailIn(br);
while (*available_in) {
s->buffer.u8[s->buffer_length] = **next_in;
s->buffer_length++;
(*next_in)++;
(*available_in)--;
}
break;
}
/* Unreachable. */
}
/* Fail or needs more output. */
if (s->buffer_length != 0) {
/* Just consumed the buffered input and produced some output. Otherwise
it would result in "needs more input". Reset internal buffer. */
s->buffer_length = 0;
} else {
/* Using input stream in last iteration. When decoder switches to input
stream it has less than 8 bits in accumulator, so it is safe to
return unused accumulator bits there. */
BrotliBitReaderUnload(br);
*available_in = BrotliBitReaderGetAvailIn(br);
*next_in = br->next_in;
}
break;
}
switch (s->state) {
case BROTLI_STATE_UNINITED:
/* Prepare to the first read. */
if (!BrotliWarmupBitReader(br)) {
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
break;
}
/* Decode window size. */
result = DecodeWindowBits(s, br); /* Reads 1..8 bits. */
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
if (s->large_window) {
s->state = BROTLI_STATE_LARGE_WINDOW_BITS;
break;
}
s->state = BROTLI_STATE_INITIALIZE;
break;
case BROTLI_STATE_LARGE_WINDOW_BITS: {
brotli_reg_t bits;
if (!BrotliSafeReadBits(br, 6, &bits)) {
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
break;
}
s->window_bits = bits & 63u;
if (s->window_bits < BROTLI_LARGE_MIN_WBITS ||
s->window_bits > BROTLI_LARGE_MAX_WBITS) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
break;
}
s->state = BROTLI_STATE_INITIALIZE;
}
/* Fall through. */
case BROTLI_STATE_INITIALIZE:
BROTLI_LOG_UINT(s->window_bits);
/* Maximum distance, see section 9.1. of the spec. */
s->max_backward_distance = (1 << s->window_bits) - BROTLI_WINDOW_GAP;
/* Allocate memory for both block_type_trees and block_len_trees. */
s->block_type_trees = (HuffmanCode*)BROTLI_DECODER_ALLOC(s,
sizeof(HuffmanCode) * 3 *
(BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26));
if (s->block_type_trees == 0) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES);
break;
}
s->block_len_trees =
s->block_type_trees + 3 * BROTLI_HUFFMAN_MAX_SIZE_258;
s->state = BROTLI_STATE_METABLOCK_BEGIN;
/* Fall through. */
case BROTLI_STATE_METABLOCK_BEGIN:
BrotliDecoderStateMetablockBegin(s);
BROTLI_LOG_UINT(s->pos);
s->state = BROTLI_STATE_METABLOCK_HEADER;
/* Fall through. */
case BROTLI_STATE_METABLOCK_HEADER:
result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
BROTLI_LOG_UINT(s->is_last_metablock);
BROTLI_LOG_UINT(s->meta_block_remaining_len);
BROTLI_LOG_UINT(s->is_metadata);
BROTLI_LOG_UINT(s->is_uncompressed);
if (s->is_metadata || s->is_uncompressed) {
if (!BrotliJumpToByteBoundary(br)) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_1);
break;
}
}
if (s->is_metadata) {
s->state = BROTLI_STATE_METADATA;
if (s->metadata_start_func) {
s->metadata_start_func(s->metadata_callback_opaque,
(size_t)s->meta_block_remaining_len);
}
break;
}
if (s->meta_block_remaining_len == 0) {
s->state = BROTLI_STATE_METABLOCK_DONE;
break;
}
BrotliCalculateRingBufferSize(s);
if (s->is_uncompressed) {
s->state = BROTLI_STATE_UNCOMPRESSED;
break;
}
s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER;
/* Fall through. */
case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER: {
BrotliMetablockHeaderArena* h = &s->arena.header;
s->loop_counter = 0;
/* Initialize compressed metablock header arena. */
h->sub_loop_counter = 0;
/* Make small negative indexes addressable. */
h->symbol_lists =
&h->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
s->state = BROTLI_STATE_HUFFMAN_CODE_0;
}
/* Fall through. */
case BROTLI_STATE_HUFFMAN_CODE_0:
if (s->loop_counter >= 3) {
s->state = BROTLI_STATE_METABLOCK_HEADER_2;
break;
}
/* Reads 1..11 bits. */
result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
s->num_block_types[s->loop_counter]++;
BROTLI_LOG_UINT(s->num_block_types[s->loop_counter]);
if (s->num_block_types[s->loop_counter] < 2) {
s->loop_counter++;
break;
}
s->state = BROTLI_STATE_HUFFMAN_CODE_1;
/* Fall through. */
case BROTLI_STATE_HUFFMAN_CODE_1: {
brotli_reg_t alphabet_size = s->num_block_types[s->loop_counter] + 2;
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258;
result = ReadHuffmanCode(alphabet_size, alphabet_size,
&s->block_type_trees[tree_offset], NULL, s);
if (result != BROTLI_DECODER_SUCCESS) break;
s->state = BROTLI_STATE_HUFFMAN_CODE_2;
}
/* Fall through. */
case BROTLI_STATE_HUFFMAN_CODE_2: {
brotli_reg_t alphabet_size = BROTLI_NUM_BLOCK_LEN_SYMBOLS;
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
result = ReadHuffmanCode(alphabet_size, alphabet_size,
&s->block_len_trees[tree_offset], NULL, s);
if (result != BROTLI_DECODER_SUCCESS) break;
s->state = BROTLI_STATE_HUFFMAN_CODE_3;
}
/* Fall through. */
case BROTLI_STATE_HUFFMAN_CODE_3: {
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter],
&s->block_len_trees[tree_offset], br)) {
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
break;
}
BROTLI_LOG_UINT(s->block_length[s->loop_counter]);
s->loop_counter++;
s->state = BROTLI_STATE_HUFFMAN_CODE_0;
break;
}
case BROTLI_STATE_UNCOMPRESSED: {
result = CopyUncompressedBlockToOutput(
available_out, next_out, total_out, s);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
s->state = BROTLI_STATE_METABLOCK_DONE;
break;
}
case BROTLI_STATE_METADATA:
result = SkipMetadataBlock(s);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
s->state = BROTLI_STATE_METABLOCK_DONE;
break;
case BROTLI_STATE_METABLOCK_HEADER_2: {
brotli_reg_t bits;
if (!BrotliSafeReadBits(br, 6, &bits)) {
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
break;
}
s->distance_postfix_bits = bits & BitMask(2);
bits >>= 2;
s->num_direct_distance_codes = bits << s->distance_postfix_bits;
BROTLI_LOG_UINT(s->num_direct_distance_codes);
BROTLI_LOG_UINT(s->distance_postfix_bits);
s->context_modes =
(uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]);
if (s->context_modes == 0) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES);
break;
}
s->loop_counter = 0;
s->state = BROTLI_STATE_CONTEXT_MODES;
}
/* Fall through. */
case BROTLI_STATE_CONTEXT_MODES:
result = ReadContextModes(s);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
s->state = BROTLI_STATE_CONTEXT_MAP_1;
/* Fall through. */
case BROTLI_STATE_CONTEXT_MAP_1:
result = DecodeContextMap(
s->num_block_types[0] << BROTLI_LITERAL_CONTEXT_BITS,
&s->num_literal_htrees, &s->context_map, s);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
DetectTrivialLiteralBlockTypes(s);
s->state = BROTLI_STATE_CONTEXT_MAP_2;
/* Fall through. */
case BROTLI_STATE_CONTEXT_MAP_2: {
brotli_reg_t npostfix = s->distance_postfix_bits;
brotli_reg_t ndirect = s->num_direct_distance_codes;
brotli_reg_t distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);
brotli_reg_t distance_alphabet_size_limit = distance_alphabet_size_max;
BROTLI_BOOL allocation_success = BROTLI_TRUE;
if (s->large_window) {
BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(
BROTLI_MAX_ALLOWED_DISTANCE, (uint32_t)npostfix,
(uint32_t)ndirect);
distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);
distance_alphabet_size_limit = limit.max_alphabet_size;
}
result = DecodeContextMap(
s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,
&s->num_dist_htrees, &s->dist_context_map, s);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
s, &s->literal_hgroup, BROTLI_NUM_LITERAL_SYMBOLS,
BROTLI_NUM_LITERAL_SYMBOLS, s->num_literal_htrees);
allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS,
BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]);
allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
s, &s->distance_hgroup, distance_alphabet_size_max,
distance_alphabet_size_limit, s->num_dist_htrees);
if (!allocation_success) {
return BROTLI_SAVE_ERROR_CODE(
BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));
}
s->loop_counter = 0;
s->state = BROTLI_STATE_TREE_GROUP;
}
/* Fall through. */
case BROTLI_STATE_TREE_GROUP: {
HuffmanTreeGroup* hgroup = NULL;
switch (s->loop_counter) {
case 0: hgroup = &s->literal_hgroup; break;
case 1: hgroup = &s->insert_copy_hgroup; break;
case 2: hgroup = &s->distance_hgroup; break;
default: return BROTLI_SAVE_ERROR_CODE(BROTLI_FAILURE(
BROTLI_DECODER_ERROR_UNREACHABLE)); /* COV_NF_LINE */
}
result = HuffmanTreeGroupDecode(hgroup, s);
if (result != BROTLI_DECODER_SUCCESS) break;
s->loop_counter++;
if (s->loop_counter < 3) {
break;
}
s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY;
}
/* Fall through. */
case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY:
PrepareLiteralDecoding(s);
s->dist_context_map_slice = s->dist_context_map;
s->htree_command = s->insert_copy_hgroup.htrees[0];
if (!BrotliEnsureRingBuffer(s)) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
break;
}
CalculateDistanceLut(s);
s->state = BROTLI_STATE_COMMAND_BEGIN;
/* Fall through. */
case BROTLI_STATE_COMMAND_BEGIN:
/* Fall through. */
case BROTLI_STATE_COMMAND_INNER:
/* Fall through. */
case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS:
/* Fall through. */
case BROTLI_STATE_COMMAND_POST_WRAP_COPY:
result = ProcessCommands(s);
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
result = SafeProcessCommands(s);
}
break;
case BROTLI_STATE_COMMAND_INNER_WRITE:
/* Fall through. */
case BROTLI_STATE_COMMAND_POST_WRITE_1:
/* Fall through. */
case BROTLI_STATE_COMMAND_POST_WRITE_2:
result = WriteRingBuffer(
s, available_out, next_out, total_out, BROTLI_FALSE);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
WrapRingBuffer(s);
if (s->ringbuffer_size == 1 << s->window_bits) {
s->max_distance = s->max_backward_distance;
}
if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) {
BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;
if (addon && (addon->br_length != addon->br_copied)) {
s->pos += CopyFromCompoundDictionary(s, s->pos);
if (s->pos >= s->ringbuffer_size) continue;
}
if (s->meta_block_remaining_len == 0) {
/* Next metablock, if any. */
s->state = BROTLI_STATE_METABLOCK_DONE;
} else {
s->state = BROTLI_STATE_COMMAND_BEGIN;
}
break;
} else if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_2) {
s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY;
} else { /* BROTLI_STATE_COMMAND_INNER_WRITE */
if (s->loop_counter == 0) {
if (s->meta_block_remaining_len == 0) {
s->state = BROTLI_STATE_METABLOCK_DONE;
} else {
s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
}
break;
}
s->state = BROTLI_STATE_COMMAND_INNER;
}
break;
case BROTLI_STATE_METABLOCK_DONE:
if (s->meta_block_remaining_len < 0) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2);
break;
}
BrotliDecoderStateCleanupAfterMetablock(s);
if (!s->is_last_metablock) {
s->state = BROTLI_STATE_METABLOCK_BEGIN;
break;
}
if (!BrotliJumpToByteBoundary(br)) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_2);
break;
}
if (s->buffer_length == 0) {
BrotliBitReaderUnload(br);
*available_in = BrotliBitReaderGetAvailIn(br);
*next_in = br->next_in;
}
s->state = BROTLI_STATE_DONE;
/* Fall through. */
case BROTLI_STATE_DONE:
if (s->ringbuffer != 0) {
result = WriteRingBuffer(
s, available_out, next_out, total_out, BROTLI_TRUE);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
}
return BROTLI_SAVE_ERROR_CODE(result);
}
}
return BROTLI_SAVE_ERROR_CODE(result);
#undef BROTLI_SAVE_ERROR_CODE
}
BROTLI_BOOL BrotliDecoderHasMoreOutput(const BrotliDecoderState* s) {
/* After unrecoverable error remaining output is considered nonsensical. */
if ((int)s->error_code < 0) {
return BROTLI_FALSE;
}
return TO_BROTLI_BOOL(
s->ringbuffer != 0 && UnwrittenBytes(s, BROTLI_FALSE) != 0);
}
const uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) {
uint8_t* result = 0;
size_t available_out = *size ? *size : 1u << 24;
size_t requested_out = available_out;
BrotliDecoderErrorCode status;
if ((s->ringbuffer == 0) || ((int)s->error_code < 0)) {
*size = 0;
return 0;
}
WrapRingBuffer(s);
status = WriteRingBuffer(s, &available_out, &result, 0, BROTLI_TRUE);
/* Either WriteRingBuffer returns those "success" codes... */
if (status == BROTLI_DECODER_SUCCESS ||
status == BROTLI_DECODER_NEEDS_MORE_OUTPUT) {
*size = requested_out - available_out;
} else {
/* ... or stream is broken. Normally this should be caught by
BrotliDecoderDecompressStream, this is just a safeguard. */
if ((int)status < 0) SaveErrorCode(s, status, 0);
*size = 0;
result = 0;
}
return result;
}
BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s) {
return TO_BROTLI_BOOL(s->state != BROTLI_STATE_UNINITED ||
BrotliGetAvailableBits(&s->br) != 0);
}
BROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s) {
return TO_BROTLI_BOOL(s->state == BROTLI_STATE_DONE) &&
!BrotliDecoderHasMoreOutput(s);
}
BrotliDecoderErrorCode BrotliDecoderGetErrorCode(const BrotliDecoderState* s) {
return (BrotliDecoderErrorCode)s->error_code;
}
const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c) {
switch (c) {
#define BROTLI_ERROR_CODE_CASE_(PREFIX, NAME, CODE) \
case BROTLI_DECODER ## PREFIX ## NAME: return #PREFIX #NAME;
#define BROTLI_NOTHING_
BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_CASE_, BROTLI_NOTHING_)
#undef BROTLI_ERROR_CODE_CASE_
#undef BROTLI_NOTHING_
default: return "INVALID";
}
}
uint32_t BrotliDecoderVersion(void) {
return BROTLI_VERSION;
}
void BrotliDecoderSetMetadataCallbacks(
BrotliDecoderState* state,
brotli_decoder_metadata_start_func start_func,
brotli_decoder_metadata_chunk_func chunk_func, void* opaque) {
state->metadata_start_func = start_func;
state->metadata_chunk_func = chunk_func;
state->metadata_callback_opaque = opaque;
}
/* Escalate internal functions visibility; for testing purposes only. */
#if defined(BROTLI_TEST)
BROTLI_BOOL BrotliSafeReadSymbolForTest(
const HuffmanCode*, BrotliBitReader*, brotli_reg_t*);
BROTLI_BOOL BrotliSafeReadSymbolForTest(
const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {
return SafeReadSymbol(table, br, result);
}
void BrotliInverseMoveToFrontTransformForTest(
uint8_t*, brotli_reg_t, BrotliDecoderState*);
void BrotliInverseMoveToFrontTransformForTest(
uint8_t* v, brotli_reg_t l, BrotliDecoderState* s) {
InverseMoveToFrontTransform(v, l, s);
}
#endif
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/dec/huffman.c
================================================
/* 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 building Huffman decoding tables. */
#include "huffman.h"
#include "../common/constants.h"
#include "../common/platform.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define BROTLI_REVERSE_BITS_MAX 8
#if defined(BROTLI_RBIT)
#define BROTLI_REVERSE_BITS_BASE \
((sizeof(brotli_reg_t) << 3) - BROTLI_REVERSE_BITS_MAX)
#else
#define BROTLI_REVERSE_BITS_BASE 0
static BROTLI_MODEL("small")
uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
#endif /* BROTLI_RBIT */
#define BROTLI_REVERSE_BITS_LOWEST \
((brotli_reg_t)1 << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE))
/* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX),
where reverse(value, len) is the bit-wise reversal of the len least
significant bits of value. */
static BROTLI_INLINE brotli_reg_t BrotliReverseBits(brotli_reg_t num) {
#if defined(BROTLI_RBIT)
return BROTLI_RBIT(num);
#else
return kReverseBits[num];
#endif
}
/* Stores code in table[0], table[step], table[2*step], ..., table[end] */
/* Assumes that end is an integer multiple of step */
static BROTLI_INLINE void ReplicateValue(HuffmanCode* table,
int step, int end,
HuffmanCode code) {
do {
end -= step;
table[end] = code;
} while (end > 0);
}
/* Returns the table width of the next 2nd level table. |count| is the histogram
of bit lengths for the remaining symbols, |len| is the code length of the
next processed symbol. */
static BROTLI_INLINE int NextTableBitSize(const uint16_t* const count,
int len, int root_bits) {
int left = 1 << (len - root_bits);
while (len < BROTLI_HUFFMAN_MAX_CODE_LENGTH) {
left -= count[len];
if (left <= 0) break;
++len;
left <<= 1;
}
return len - root_bits;
}
void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
const uint8_t* const code_lengths,
uint16_t* count) {
HuffmanCode code; /* current table entry */
int symbol; /* symbol index in original or sorted table */
brotli_reg_t key; /* prefix code */
brotli_reg_t key_step; /* prefix code addend */
int step; /* step size to replicate values in current table */
int table_size; /* size of current table */
int sorted[BROTLI_CODE_LENGTH_CODES]; /* symbols sorted by code length */
/* offsets in sorted table for each length */
int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1];
int bits;
int bits_count;
BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <=
BROTLI_REVERSE_BITS_MAX);
BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5);
/* Generate offsets into sorted symbol table by code length. */
symbol = -1;
bits = 1;
/* BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5 */
BROTLI_REPEAT_5({
symbol += count[bits];
offset[bits] = symbol;
bits++;
});
/* Symbols with code length 0 are placed after all other symbols. */
offset[0] = BROTLI_CODE_LENGTH_CODES - 1;
/* Sort symbols by length, by symbol order within each length. */
symbol = BROTLI_CODE_LENGTH_CODES;
do {
BROTLI_REPEAT_6({
symbol--;
sorted[offset[code_lengths[symbol]]--] = symbol;
});
} while (symbol != 0);
table_size = 1 << BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH;
/* Special case: all symbols but one have 0 code length. */
if (offset[0] == 0) {
code = ConstructHuffmanCode(0, (uint16_t)sorted[0]);
for (key = 0; key < (brotli_reg_t)table_size; ++key) {
table[key] = code;
}
return;
}
/* Fill in table. */
key = 0;
key_step = BROTLI_REVERSE_BITS_LOWEST;
symbol = 0;
bits = 1;
step = 2;
do {
for (bits_count = count[bits]; bits_count != 0; --bits_count) {
code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)sorted[symbol++]);
ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
key += key_step;
}
step <<= 1;
key_step >>= 1;
} while (++bits <= BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
}
uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
int root_bits,
const uint16_t* const symbol_lists,
uint16_t* count) {
HuffmanCode code; /* current table entry */
HuffmanCode* table; /* next available space in table */
int len; /* current code length */
int symbol; /* symbol index in original or sorted table */
brotli_reg_t key; /* prefix code */
brotli_reg_t key_step; /* prefix code addend */
brotli_reg_t sub_key; /* 2nd level table prefix code */
brotli_reg_t sub_key_step; /* 2nd level table prefix code addend */
int step; /* step size to replicate values in current table */
int table_bits; /* key length of current table */
int table_size; /* size of current table */
int total_size; /* sum of root table size and 2nd level table sizes */
int max_length = -1;
int bits;
int bits_count;
BROTLI_DCHECK(root_bits <= BROTLI_REVERSE_BITS_MAX);
BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <=
BROTLI_REVERSE_BITS_MAX);
while (symbol_lists[max_length] == 0xFFFF) max_length--;
max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1;
table = root_table;
table_bits = root_bits;
table_size = 1 << table_bits;
total_size = table_size;
/* Fill in the root table. Reduce the table size to if possible,
and create the repetitions by memcpy. */
if (table_bits > max_length) {
table_bits = max_length;
table_size = 1 << table_bits;
}
key = 0;
key_step = BROTLI_REVERSE_BITS_LOWEST;
bits = 1;
step = 2;
do {
symbol = bits - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
for (bits_count = count[bits]; bits_count != 0; --bits_count) {
symbol = symbol_lists[symbol];
code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)symbol);
ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
key += key_step;
}
step <<= 1;
key_step >>= 1;
} while (++bits <= table_bits);
/* If root_bits != table_bits then replicate to fill the remaining slots. */
while (total_size != table_size) {
memcpy(&table[table_size], &table[0],
(size_t)table_size * sizeof(table[0]));
table_size <<= 1;
}
/* Fill in 2nd level tables and add pointers to root table. */
key_step = BROTLI_REVERSE_BITS_LOWEST >> (root_bits - 1);
sub_key = (BROTLI_REVERSE_BITS_LOWEST << 1);
sub_key_step = BROTLI_REVERSE_BITS_LOWEST;
for (len = root_bits + 1, step = 2; len <= max_length; ++len) {
symbol = len - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
for (; count[len] != 0; --count[len]) {
if (sub_key == (BROTLI_REVERSE_BITS_LOWEST << 1U)) {
table += table_size;
table_bits = NextTableBitSize(count, len, root_bits);
table_size = 1 << table_bits;
total_size += table_size;
sub_key = BrotliReverseBits(key);
key += key_step;
root_table[sub_key] = ConstructHuffmanCode(
(uint8_t)(table_bits + root_bits),
(uint16_t)(((size_t)(table - root_table)) - sub_key));
sub_key = 0;
}
symbol = symbol_lists[symbol];
code = ConstructHuffmanCode((uint8_t)(len - root_bits), (uint16_t)symbol);
ReplicateValue(
&table[BrotliReverseBits(sub_key)], step, table_size, code);
sub_key += sub_key_step;
}
step <<= 1;
sub_key_step >>= 1;
}
return (uint32_t)total_size;
}
uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
int root_bits,
uint16_t* val,
uint32_t num_symbols) {
uint32_t table_size = 1;
const uint32_t goal_size = 1U << root_bits;
switch (num_symbols) {
case 0:
table[0] = ConstructHuffmanCode(0, val[0]);
break;
case 1:
if (val[1] > val[0]) {
table[0] = ConstructHuffmanCode(1, val[0]);
table[1] = ConstructHuffmanCode(1, val[1]);
} else {
table[0] = ConstructHuffmanCode(1, val[1]);
table[1] = ConstructHuffmanCode(1, val[0]);
}
table_size = 2;
break;
case 2:
table[0] = ConstructHuffmanCode(1, val[0]);
table[2] = ConstructHuffmanCode(1, val[0]);
if (val[2] > val[1]) {
table[1] = ConstructHuffmanCode(2, val[1]);
table[3] = ConstructHuffmanCode(2, val[2]);
} else {
table[1] = ConstructHuffmanCode(2, val[2]);
table[3] = ConstructHuffmanCode(2, val[1]);
}
table_size = 4;
break;
case 3: {
int i, k;
for (i = 0; i < 3; ++i) {
for (k = i + 1; k < 4; ++k) {
if (val[k] < val[i]) {
uint16_t t = val[k];
val[k] = val[i];
val[i] = t;
}
}
}
table[0] = ConstructHuffmanCode(2, val[0]);
table[2] = ConstructHuffmanCode(2, val[1]);
table[1] = ConstructHuffmanCode(2, val[2]);
table[3] = ConstructHuffmanCode(2, val[3]);
table_size = 4;
break;
}
case 4: {
if (val[3] < val[2]) {
uint16_t t = val[3];
val[3] = val[2];
val[2] = t;
}
table[0] = ConstructHuffmanCode(1, val[0]);
table[1] = ConstructHuffmanCode(2, val[1]);
table[2] = ConstructHuffmanCode(1, val[0]);
table[3] = ConstructHuffmanCode(3, val[2]);
table[4] = ConstructHuffmanCode(1, val[0]);
table[5] = ConstructHuffmanCode(2, val[1]);
table[6] = ConstructHuffmanCode(1, val[0]);
table[7] = ConstructHuffmanCode(3, val[3]);
table_size = 8;
break;
}
}
while (table_size != goal_size) {
memcpy(&table[table_size], &table[0],
(size_t)table_size * sizeof(table[0]));
table_size <<= 1;
}
return goal_size;
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/dec/huffman.h
================================================
/* 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 building Huffman decoding tables. */
#ifndef BROTLI_DEC_HUFFMAN_H_
#define BROTLI_DEC_HUFFMAN_H_
#include "../common/platform.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15
/* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */
#define BROTLI_HUFFMAN_MAX_SIZE_26 396
/* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */
#define BROTLI_HUFFMAN_MAX_SIZE_258 632
/* BROTLI_MAX_CONTEXT_MAP_SYMBOLS == 272 */
#define BROTLI_HUFFMAN_MAX_SIZE_272 646
#define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5
#if ((defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_32)) && \
BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0))
#define BROTLI_HUFFMAN_CODE_FAST_LOAD
#endif
#if !defined(BROTLI_HUFFMAN_CODE_FAST_LOAD)
/* Do not create this struct directly - use the ConstructHuffmanCode
* constructor below! */
typedef struct {
uint8_t bits; /* number of bits used for this symbol */
uint16_t value; /* symbol value or table offset */
} HuffmanCode;
static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
const uint16_t value) {
HuffmanCode h;
h.bits = bits;
h.value = value;
return h;
}
/* Please use the following macros to optimize HuffmanCode accesses in hot
* paths.
*
* For example, assuming |table| contains a HuffmanCode pointer:
*
* BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
* BROTLI_HC_ADJUST_TABLE_INDEX(table, index_into_table);
* *bits = BROTLI_HC_GET_BITS(table);
* *value = BROTLI_HC_GET_VALUE(table);
* BROTLI_HC_ADJUST_TABLE_INDEX(table, offset);
* *bits2 = BROTLI_HC_GET_BITS(table);
* *value2 = BROTLI_HC_GET_VALUE(table);
*
*/
#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H)
#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V)
/* These must be given a HuffmanCode pointer! */
#define BROTLI_HC_FAST_LOAD_BITS(H) (H->bits)
#define BROTLI_HC_FAST_LOAD_VALUE(H) (H->value)
#else /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
typedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;
static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
const uint16_t value) {
return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF);
}
#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)
#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V); __fastload_##H = (*H)
/* These must be given a HuffmanCode pointer! */
#define BROTLI_HC_FAST_LOAD_BITS(H) ((__fastload_##H) & 0xFF)
#define BROTLI_HC_FAST_LOAD_VALUE(H) ((__fastload_##H) >> 16)
#endif /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
/* Builds Huffman lookup table assuming code lengths are in symbol order. */
BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
const uint8_t* const code_lengths, uint16_t* count);
/* Builds Huffman lookup table assuming code lengths are in symbol order.
Returns size of resulting table. */
BROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
int root_bits, const uint16_t* const symbol_lists, uint16_t* count);
/* Builds a simple Huffman table. The |num_symbols| parameter is to be
interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,
2 means 3 symbols, 3 means 4 symbols with lengths [2, 2, 2, 2],
4 means 4 symbols with lengths [1, 2, 3, 3]. */
BROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
int root_bits, uint16_t* symbols, uint32_t num_symbols);
/* Contains a collection of Huffman trees with the same alphabet size. */
/* alphabet_size_limit is needed due to simple codes, since
log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */
typedef struct {
HuffmanCode** htrees;
HuffmanCode* codes;
uint16_t alphabet_size_max;
uint16_t alphabet_size_limit;
uint16_t num_htrees;
} HuffmanTreeGroup;
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_DEC_HUFFMAN_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/dec/prefix.c
================================================
/* Copyright 2025 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
#include "prefix.h"
#include "../common/platform.h" /* IWYU pragma: keep */
#include "../common/static_init.h"
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
#include "../common/constants.h"
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)
/* Embed kCmdLut. */
#include "prefix_inc.h"
#else
BROTLI_COLD BROTLI_BOOL BrotliDecoderInitCmdLut(CmdLutElement* items) {
static const uint8_t kInsertLengthExtraBits[24] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0E, 0x18};
static const uint8_t kCopyLengthExtraBits[24] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x18};
static const uint8_t kCellPos[11] = {0, 1, 0, 1, 8, 9, 2, 16, 10, 17, 18};
uint16_t insert_length_offsets[24];
uint16_t copy_length_offsets[24];
insert_length_offsets[0] = 0;
copy_length_offsets[0] = 2;
for (size_t i = 0; i < 23; ++i) {
insert_length_offsets[i + 1] =
insert_length_offsets[i] + (uint16_t)(1u << kInsertLengthExtraBits[i]);
copy_length_offsets[i + 1] =
copy_length_offsets[i] + (uint16_t)(1u << kCopyLengthExtraBits[i]);
}
for (size_t symbol = 0; symbol < BROTLI_NUM_COMMAND_SYMBOLS; ++symbol) {
CmdLutElement* item = items + symbol;
const size_t cell_idx = symbol >> 6;
const size_t cell_pos = kCellPos[cell_idx];
const size_t copy_code = ((cell_pos << 3) & 0x18) + (symbol & 0x7);
const uint16_t copy_len_offset = copy_length_offsets[copy_code];
const size_t insert_code = (cell_pos & 0x18) + ((symbol >> 3) & 0x7);
item->copy_len_extra_bits = kCopyLengthExtraBits[copy_code];
item->context = (copy_len_offset > 4) ? 3 : ((uint8_t)copy_len_offset - 2);
item->copy_len_offset = copy_len_offset;
item->distance_code = (cell_idx >= 2) ? -1 : 0;
item->insert_len_extra_bits = kInsertLengthExtraBits[insert_code];
item->insert_len_offset = insert_length_offsets[insert_code];
}
return BROTLI_TRUE;
}
BROTLI_MODEL("small")
CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];
#endif /* BROTLI_STATIC_INIT */
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/dec/prefix.h
================================================
/* 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 tables to map prefix codes to value ranges. This is used during
decoding of the block lengths, literal insertion lengths and copy lengths. */
#ifndef BROTLI_DEC_PREFIX_H_
#define BROTLI_DEC_PREFIX_H_
#include "../common/constants.h"
#include "../common/platform.h" /* IWYU pragma: keep */
#include "../common/static_init.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
typedef struct CmdLutElement {
uint8_t insert_len_extra_bits;
uint8_t copy_len_extra_bits;
int8_t distance_code;
uint8_t context;
uint16_t insert_len_offset;
uint16_t copy_len_offset;
} CmdLutElement;
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)
BROTLI_INTERNAL extern const BROTLI_MODEL("small")
CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];
#else
BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderInitCmdLut(CmdLutElement* items);
BROTLI_INTERNAL extern BROTLI_MODEL("small")
CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];
#endif
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_DEC_PREFIX_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/dec/prefix_inc.h
================================================
const BROTLI_MODEL("small")
CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS] = {
{ 0x00, 0x00, 0, 0x00, 0x0000, 0x0002 },
{ 0x00, 0x00, 0, 0x01, 0x0000, 0x0003 },
{ 0x00, 0x00, 0, 0x02, 0x0000, 0x0004 },
{ 0x00, 0x00, 0, 0x03, 0x0000, 0x0005 },
{ 0x00, 0x00, 0, 0x03, 0x0000, 0x0006 },
{ 0x00, 0x00, 0, 0x03, 0x0000, 0x0007 },
{ 0x00, 0x00, 0, 0x03, 0x0000, 0x0008 },
{ 0x00, 0x00, 0, 0x03, 0x0000, 0x0009 },
{ 0x00, 0x00, 0, 0x00, 0x0001, 0x0002 },
{ 0x00, 0x00, 0, 0x01, 0x0001, 0x0003 },
{ 0x00, 0x00, 0, 0x02, 0x0001, 0x0004 },
{ 0x00, 0x00, 0, 0x03, 0x0001, 0x0005 },
{ 0x00, 0x00, 0, 0x03, 0x0001, 0x0006 },
{ 0x00, 0x00, 0, 0x03, 0x0001, 0x0007 },
{ 0x00, 0x00, 0, 0x03, 0x0001, 0x0008 },
{ 0x00, 0x00, 0, 0x03, 0x0001, 0x0009 },
{ 0x00, 0x00, 0, 0x00, 0x0002, 0x0002 },
{ 0x00, 0x00, 0, 0x01, 0x0002, 0x0003 },
{ 0x00, 0x00, 0, 0x02, 0x0002, 0x0004 },
{ 0x00, 0x00, 0, 0x03, 0x0002, 0x0005 },
{ 0x00, 0x00, 0, 0x03, 0x0002, 0x0006 },
{ 0x00, 0x00, 0, 0x03, 0x0002, 0x0007 },
{ 0x00, 0x00, 0, 0x03, 0x0002, 0x0008 },
{ 0x00, 0x00, 0, 0x03, 0x0002, 0x0009 },
{ 0x00, 0x00, 0, 0x00, 0x0003, 0x0002 },
{ 0x00, 0x00, 0, 0x01, 0x0003, 0x0003 },
{ 0x00, 0x00, 0, 0x02, 0x0003, 0x0004 },
{ 0x00, 0x00, 0, 0x03, 0x0003, 0x0005 },
{ 0x00, 0x00, 0, 0x03, 0x0003, 0x0006 },
{ 0x00, 0x00, 0, 0x03, 0x0003, 0x0007 },
{ 0x00, 0x00, 0, 0x03, 0x0003, 0x0008 },
{ 0x00, 0x00, 0, 0x03, 0x0003, 0x0009 },
{ 0x00, 0x00, 0, 0x00, 0x0004, 0x0002 },
{ 0x00, 0x00, 0, 0x01, 0x0004, 0x0003 },
{ 0x00, 0x00, 0, 0x02, 0x0004, 0x0004 },
{ 0x00, 0x00, 0, 0x03, 0x0004, 0x0005 },
{ 0x00, 0x00, 0, 0x03, 0x0004, 0x0006 },
{ 0x00, 0x00, 0, 0x03, 0x0004, 0x0007 },
{ 0x00, 0x00, 0, 0x03, 0x0004, 0x0008 },
{ 0x00, 0x00, 0, 0x03, 0x0004, 0x0009 },
{ 0x00, 0x00, 0, 0x00, 0x0005, 0x0002 },
{ 0x00, 0x00, 0, 0x01, 0x0005, 0x0003 },
{ 0x00, 0x00, 0, 0x02, 0x0005, 0x0004 },
{ 0x00, 0x00, 0, 0x03, 0x0005, 0x0005 },
{ 0x00, 0x00, 0, 0x03, 0x0005, 0x0006 },
{ 0x00, 0x00, 0, 0x03, 0x0005, 0x0007 },
{ 0x00, 0x00, 0, 0x03, 0x0005, 0x0008 },
{ 0x00, 0x00, 0, 0x03, 0x0005, 0x0009 },
{ 0x01, 0x00, 0, 0x00, 0x0006, 0x0002 },
{ 0x01, 0x00, 0, 0x01, 0x0006, 0x0003 },
{ 0x01, 0x00, 0, 0x02, 0x0006, 0x0004 },
{ 0x01, 0x00, 0, 0x03, 0x0006, 0x0005 },
{ 0x01, 0x00, 0, 0x03, 0x0006, 0x0006 },
{ 0x01, 0x00, 0, 0x03, 0x0006, 0x0007 },
{ 0x01, 0x00, 0, 0x03, 0x0006, 0x0008 },
{ 0x01, 0x00, 0, 0x03, 0x0006, 0x0009 },
{ 0x01, 0x00, 0, 0x00, 0x0008, 0x0002 },
{ 0x01, 0x00, 0, 0x01, 0x0008, 0x0003 },
{ 0x01, 0x00, 0, 0x02, 0x0008, 0x0004 },
{ 0x01, 0x00, 0, 0x03, 0x0008, 0x0005 },
{ 0x01, 0x00, 0, 0x03, 0x0008, 0x0006 },
{ 0x01, 0x00, 0, 0x03, 0x0008, 0x0007 },
{ 0x01, 0x00, 0, 0x03, 0x0008, 0x0008 },
{ 0x01, 0x00, 0, 0x03, 0x0008, 0x0009 },
{ 0x00, 0x01, 0, 0x03, 0x0000, 0x000a },
{ 0x00, 0x01, 0, 0x03, 0x0000, 0x000c },
{ 0x00, 0x02, 0, 0x03, 0x0000, 0x000e },
{ 0x00, 0x02, 0, 0x03, 0x0000, 0x0012 },
{ 0x00, 0x03, 0, 0x03, 0x0000, 0x0016 },
{ 0x00, 0x03, 0, 0x03, 0x0000, 0x001e },
{ 0x00, 0x04, 0, 0x03, 0x0000, 0x0026 },
{ 0x00, 0x04, 0, 0x03, 0x0000, 0x0036 },
{ 0x00, 0x01, 0, 0x03, 0x0001, 0x000a },
{ 0x00, 0x01, 0, 0x03, 0x0001, 0x000c },
{ 0x00, 0x02, 0, 0x03, 0x0001, 0x000e },
{ 0x00, 0x02, 0, 0x03, 0x0001, 0x0012 },
{ 0x00, 0x03, 0, 0x03, 0x0001, 0x0016 },
{ 0x00, 0x03, 0, 0x03, 0x0001, 0x001e },
{ 0x00, 0x04, 0, 0x03, 0x0001, 0x0026 },
{ 0x00, 0x04, 0, 0x03, 0x0001, 0x0036 },
{ 0x00, 0x01, 0, 0x03, 0x0002, 0x000a },
{ 0x00, 0x01, 0, 0x03, 0x0002, 0x000c },
{ 0x00, 0x02, 0, 0x03, 0x0002, 0x000e },
{ 0x00, 0x02, 0, 0x03, 0x0002, 0x0012 },
{ 0x00, 0x03, 0, 0x03, 0x0002, 0x0016 },
{ 0x00, 0x03, 0, 0x03, 0x0002, 0x001e },
{ 0x00, 0x04, 0, 0x03, 0x0002, 0x0026 },
{ 0x00, 0x04, 0, 0x03, 0x0002, 0x0036 },
{ 0x00, 0x01, 0, 0x03, 0x0003, 0x000a },
{ 0x00, 0x01, 0, 0x03, 0x0003, 0x000c },
{ 0x00, 0x02, 0, 0x03, 0x0003, 0x000e },
{ 0x00, 0x02, 0, 0x03, 0x0003, 0x0012 },
{ 0x00, 0x03, 0, 0x03, 0x0003, 0x0016 },
{ 0x00, 0x03, 0, 0x03, 0x0003, 0x001e },
{ 0x00, 0x04, 0, 0x03, 0x0003, 0x0026 },
{ 0x00, 0x04, 0, 0x03, 0x0003, 0x0036 },
{ 0x00, 0x01, 0, 0x03, 0x0004, 0x000a },
{ 0x00, 0x01, 0, 0x03, 0x0004, 0x000c },
{ 0x00, 0x02, 0, 0x03, 0x0004, 0x000e },
{ 0x00, 0x02, 0, 0x03, 0x0004, 0x0012 },
{ 0x00, 0x03, 0, 0x03, 0x0004, 0x0016 },
{ 0x00, 0x03, 0, 0x03, 0x0004, 0x001e },
{ 0x00, 0x04, 0, 0x03, 0x0004, 0x0026 },
{ 0x00, 0x04, 0, 0x03, 0x0004, 0x0036 },
{ 0x00, 0x01, 0, 0x03, 0x0005, 0x000a },
{ 0x00, 0x01, 0, 0x03, 0x0005, 0x000c },
{ 0x00, 0x02, 0, 0x03, 0x0005, 0x000e },
{ 0x00, 0x02, 0, 0x03, 0x0005, 0x0012 },
{ 0x00, 0x03, 0, 0x03, 0x0005, 0x0016 },
{ 0x00, 0x03, 0, 0x03, 0x0005, 0x001e },
{ 0x00, 0x04, 0, 0x03, 0x0005, 0x0026 },
{ 0x00, 0x04, 0, 0x03, 0x0005, 0x0036 },
{ 0x01, 0x01, 0, 0x03, 0x0006, 0x000a },
{ 0x01, 0x01, 0, 0x03, 0x0006, 0x000c },
{ 0x01, 0x02, 0, 0x03, 0x0006, 0x000e },
{ 0x01, 0x02, 0, 0x03, 0x0006, 0x0012 },
{ 0x01, 0x03, 0, 0x03, 0x0006, 0x0016 },
{ 0x01, 0x03, 0, 0x03, 0x0006, 0x001e },
{ 0x01, 0x04, 0, 0x03, 0x0006, 0x0026 },
{ 0x01, 0x04, 0, 0x03, 0x0006, 0x0036 },
{ 0x01, 0x01, 0, 0x03, 0x0008, 0x000a },
{ 0x01, 0x01, 0, 0x03, 0x0008, 0x000c },
{ 0x01, 0x02, 0, 0x03, 0x0008, 0x000e },
{ 0x01, 0x02, 0, 0x03, 0x0008, 0x0012 },
{ 0x01, 0x03, 0, 0x03, 0x0008, 0x0016 },
{ 0x01, 0x03, 0, 0x03, 0x0008, 0x001e },
{ 0x01, 0x04, 0, 0x03, 0x0008, 0x0026 },
{ 0x01, 0x04, 0, 0x03, 0x0008, 0x0036 },
{ 0x00, 0x00, -1, 0x00, 0x0000, 0x0002 },
{ 0x00, 0x00, -1, 0x01, 0x0000, 0x0003 },
{ 0x00, 0x00, -1, 0x02, 0x0000, 0x0004 },
{ 0x00, 0x00, -1, 0x03, 0x0000, 0x0005 },
{ 0x00, 0x00, -1, 0x03, 0x0000, 0x0006 },
{ 0x00, 0x00, -1, 0x03, 0x0000, 0x0007 },
{ 0x00, 0x00, -1, 0x03, 0x0000, 0x0008 },
{ 0x00, 0x00, -1, 0x03, 0x0000, 0x0009 },
{ 0x00, 0x00, -1, 0x00, 0x0001, 0x0002 },
{ 0x00, 0x00, -1, 0x01, 0x0001, 0x0003 },
{ 0x00, 0x00, -1, 0x02, 0x0001, 0x0004 },
{ 0x00, 0x00, -1, 0x03, 0x0001, 0x0005 },
{ 0x00, 0x00, -1, 0x03, 0x0001, 0x0006 },
{ 0x00, 0x00, -1, 0x03, 0x0001, 0x0007 },
{ 0x00, 0x00, -1, 0x03, 0x0001, 0x0008 },
{ 0x00, 0x00, -1, 0x03, 0x0001, 0x0009 },
{ 0x00, 0x00, -1, 0x00, 0x0002, 0x0002 },
{ 0x00, 0x00, -1, 0x01, 0x0002, 0x0003 },
{ 0x00, 0x00, -1, 0x02, 0x0002, 0x0004 },
{ 0x00, 0x00, -1, 0x03, 0x0002, 0x0005 },
{ 0x00, 0x00, -1, 0x03, 0x0002, 0x0006 },
{ 0x00, 0x00, -1, 0x03, 0x0002, 0x0007 },
{ 0x00, 0x00, -1, 0x03, 0x0002, 0x0008 },
{ 0x00, 0x00, -1, 0x03, 0x0002, 0x0009 },
{ 0x00, 0x00, -1, 0x00, 0x0003, 0x0002 },
{ 0x00, 0x00, -1, 0x01, 0x0003, 0x0003 },
{ 0x00, 0x00, -1, 0x02, 0x0003, 0x0004 },
{ 0x00, 0x00, -1, 0x03, 0x0003, 0x0005 },
{ 0x00, 0x00, -1, 0x03, 0x0003, 0x0006 },
{ 0x00, 0x00, -1, 0x03, 0x0003, 0x0007 },
{ 0x00, 0x00, -1, 0x03, 0x0003, 0x0008 },
{ 0x00, 0x00, -1, 0x03, 0x0003, 0x0009 },
{ 0x00, 0x00, -1, 0x00, 0x0004, 0x0002 },
{ 0x00, 0x00, -1, 0x01, 0x0004, 0x0003 },
{ 0x00, 0x00, -1, 0x02, 0x0004, 0x0004 },
{ 0x00, 0x00, -1, 0x03, 0x0004, 0x0005 },
{ 0x00, 0x00, -1, 0x03, 0x0004, 0x0006 },
{ 0x00, 0x00, -1, 0x03, 0x0004, 0x0007 },
{ 0x00, 0x00, -1, 0x03, 0x0004, 0x0008 },
{ 0x00, 0x00, -1, 0x03, 0x0004, 0x0009 },
{ 0x00, 0x00, -1, 0x00, 0x0005, 0x0002 },
{ 0x00, 0x00, -1, 0x01, 0x0005, 0x0003 },
{ 0x00, 0x00, -1, 0x02, 0x0005, 0x0004 },
{ 0x00, 0x00, -1, 0x03, 0x0005, 0x0005 },
{ 0x00, 0x00, -1, 0x03, 0x0005, 0x0006 },
{ 0x00, 0x00, -1, 0x03, 0x0005, 0x0007 },
{ 0x00, 0x00, -1, 0x03, 0x0005, 0x0008 },
{ 0x00, 0x00, -1, 0x03, 0x0005, 0x0009 },
{ 0x01, 0x00, -1, 0x00, 0x0006, 0x0002 },
{ 0x01, 0x00, -1, 0x01, 0x0006, 0x0003 },
{ 0x01, 0x00, -1, 0x02, 0x0006, 0x0004 },
{ 0x01, 0x00, -1, 0x03, 0x0006, 0x0005 },
{ 0x01, 0x00, -1, 0x03, 0x0006, 0x0006 },
{ 0x01, 0x00, -1, 0x03, 0x0006, 0x0007 },
{ 0x01, 0x00, -1, 0x03, 0x0006, 0x0008 },
{ 0x01, 0x00, -1, 0x03, 0x0006, 0x0009 },
{ 0x01, 0x00, -1, 0x00, 0x0008, 0x0002 },
{ 0x01, 0x00, -1, 0x01, 0x0008, 0x0003 },
{ 0x01, 0x00, -1, 0x02, 0x0008, 0x0004 },
{ 0x01, 0x00, -1, 0x03, 0x0008, 0x0005 },
{ 0x01, 0x00, -1, 0x03, 0x0008, 0x0006 },
{ 0x01, 0x00, -1, 0x03, 0x0008, 0x0007 },
{ 0x01, 0x00, -1, 0x03, 0x0008, 0x0008 },
{ 0x01, 0x00, -1, 0x03, 0x0008, 0x0009 },
{ 0x00, 0x01, -1, 0x03, 0x0000, 0x000a },
{ 0x00, 0x01, -1, 0x03, 0x0000, 0x000c },
{ 0x00, 0x02, -1, 0x03, 0x0000, 0x000e },
{ 0x00, 0x02, -1, 0x03, 0x0000, 0x0012 },
{ 0x00, 0x03, -1, 0x03, 0x0000, 0x0016 },
{ 0x00, 0x03, -1, 0x03, 0x0000, 0x001e },
{ 0x00, 0x04, -1, 0x03, 0x0000, 0x0026 },
{ 0x00, 0x04, -1, 0x03, 0x0000, 0x0036 },
{ 0x00, 0x01, -1, 0x03, 0x0001, 0x000a },
{ 0x00, 0x01, -1, 0x03, 0x0001, 0x000c },
{ 0x00, 0x02, -1, 0x03, 0x0001, 0x000e },
{ 0x00, 0x02, -1, 0x03, 0x0001, 0x0012 },
{ 0x00, 0x03, -1, 0x03, 0x0001, 0x0016 },
{ 0x00, 0x03, -1, 0x03, 0x0001, 0x001e },
{ 0x00, 0x04, -1, 0x03, 0x0001, 0x0026 },
{ 0x00, 0x04, -1, 0x03, 0x0001, 0x0036 },
{ 0x00, 0x01, -1, 0x03, 0x0002, 0x000a },
{ 0x00, 0x01, -1, 0x03, 0x0002, 0x000c },
{ 0x00, 0x02, -1, 0x03, 0x0002, 0x000e },
{ 0x00, 0x02, -1, 0x03, 0x0002, 0x0012 },
{ 0x00, 0x03, -1, 0x03, 0x0002, 0x0016 },
{ 0x00, 0x03, -1, 0x03, 0x0002, 0x001e },
{ 0x00, 0x04, -1, 0x03, 0x0002, 0x0026 },
{ 0x00, 0x04, -1, 0x03, 0x0002, 0x0036 },
{ 0x00, 0x01, -1, 0x03, 0x0003, 0x000a },
{ 0x00, 0x01, -1, 0x03, 0x0003, 0x000c },
{ 0x00, 0x02, -1, 0x03, 0x0003, 0x000e },
{ 0x00, 0x02, -1, 0x03, 0x0003, 0x0012 },
{ 0x00, 0x03, -1, 0x03, 0x0003, 0x0016 },
{ 0x00, 0x03, -1, 0x03, 0x0003, 0x001e },
{ 0x00, 0x04, -1, 0x03, 0x0003, 0x0026 },
{ 0x00, 0x04, -1, 0x03, 0x0003, 0x0036 },
{ 0x00, 0x01, -1, 0x03, 0x0004, 0x000a },
{ 0x00, 0x01, -1, 0x03, 0x0004, 0x000c },
{ 0x00, 0x02, -1, 0x03, 0x0004, 0x000e },
{ 0x00, 0x02, -1, 0x03, 0x0004, 0x0012 },
{ 0x00, 0x03, -1, 0x03, 0x0004, 0x0016 },
{ 0x00, 0x03, -1, 0x03, 0x0004, 0x001e },
{ 0x00, 0x04, -1, 0x03, 0x0004, 0x0026 },
{ 0x00, 0x04, -1, 0x03, 0x0004, 0x0036 },
{ 0x00, 0x01, -1, 0x03, 0x0005, 0x000a },
{ 0x00, 0x01, -1, 0x03, 0x0005, 0x000c },
{ 0x00, 0x02, -1, 0x03, 0x0005, 0x000e },
{ 0x00, 0x02, -1, 0x03, 0x0005, 0x0012 },
{ 0x00, 0x03, -1, 0x03, 0x0005, 0x0016 },
{ 0x00, 0x03, -1, 0x03, 0x0005, 0x001e },
{ 0x00, 0x04, -1, 0x03, 0x0005, 0x0026 },
{ 0x00, 0x04, -1, 0x03, 0x0005, 0x0036 },
{ 0x01, 0x01, -1, 0x03, 0x0006, 0x000a },
{ 0x01, 0x01, -1, 0x03, 0x0006, 0x000c },
{ 0x01, 0x02, -1, 0x03, 0x0006, 0x000e },
{ 0x01, 0x02, -1, 0x03, 0x0006, 0x0012 },
{ 0x01, 0x03, -1, 0x03, 0x0006, 0x0016 },
{ 0x01, 0x03, -1, 0x03, 0x0006, 0x001e },
{ 0x01, 0x04, -1, 0x03, 0x0006, 0x0026 },
{ 0x01, 0x04, -1, 0x03, 0x0006, 0x0036 },
{ 0x01, 0x01, -1, 0x03, 0x0008, 0x000a },
{ 0x01, 0x01, -1, 0x03, 0x0008, 0x000c },
{ 0x01, 0x02, -1, 0x03, 0x0008, 0x000e },
{ 0x01, 0x02, -1, 0x03, 0x0008, 0x0012 },
{ 0x01, 0x03, -1, 0x03, 0x0008, 0x0016 },
{ 0x01, 0x03, -1, 0x03, 0x0008, 0x001e },
{ 0x01, 0x04, -1, 0x03, 0x0008, 0x0026 },
{ 0x01, 0x04, -1, 0x03, 0x0008, 0x0036 },
{ 0x02, 0x00, -1, 0x00, 0x000a, 0x0002 },
{ 0x02, 0x00, -1, 0x01, 0x000a, 0x0003 },
{ 0x02, 0x00, -1, 0x02, 0x000a, 0x0004 },
{ 0x02, 0x00, -1, 0x03, 0x000a, 0x0005 },
{ 0x02, 0x00, -1, 0x03, 0x000a, 0x0006 },
{ 0x02, 0x00, -1, 0x03, 0x000a, 0x0007 },
{ 0x02, 0x00, -1, 0x03, 0x000a, 0x0008 },
{ 0x02, 0x00, -1, 0x03, 0x000a, 0x0009 },
{ 0x02, 0x00, -1, 0x00, 0x000e, 0x0002 },
{ 0x02, 0x00, -1, 0x01, 0x000e, 0x0003 },
{ 0x02, 0x00, -1, 0x02, 0x000e, 0x0004 },
{ 0x02, 0x00, -1, 0x03, 0x000e, 0x0005 },
{ 0x02, 0x00, -1, 0x03, 0x000e, 0x0006 },
{ 0x02, 0x00, -1, 0x03, 0x000e, 0x0007 },
{ 0x02, 0x00, -1, 0x03, 0x000e, 0x0008 },
{ 0x02, 0x00, -1, 0x03, 0x000e, 0x0009 },
{ 0x03, 0x00, -1, 0x00, 0x0012, 0x0002 },
{ 0x03, 0x00, -1, 0x01, 0x0012, 0x0003 },
{ 0x03, 0x00, -1, 0x02, 0x0012, 0x0004 },
{ 0x03, 0x00, -1, 0x03, 0x0012, 0x0005 },
{ 0x03, 0x00, -1, 0x03, 0x0012, 0x0006 },
{ 0x03, 0x00, -1, 0x03, 0x0012, 0x0007 },
{ 0x03, 0x00, -1, 0x03, 0x0012, 0x0008 },
{ 0x03, 0x00, -1, 0x03, 0x0012, 0x0009 },
{ 0x03, 0x00, -1, 0x00, 0x001a, 0x0002 },
{ 0x03, 0x00, -1, 0x01, 0x001a, 0x0003 },
{ 0x03, 0x00, -1, 0x02, 0x001a, 0x0004 },
{ 0x03, 0x00, -1, 0x03, 0x001a, 0x0005 },
{ 0x03, 0x00, -1, 0x03, 0x001a, 0x0006 },
{ 0x03, 0x00, -1, 0x03, 0x001a, 0x0007 },
{ 0x03, 0x00, -1, 0x03, 0x001a, 0x0008 },
{ 0x03, 0x00, -1, 0x03, 0x001a, 0x0009 },
{ 0x04, 0x00, -1, 0x00, 0x0022, 0x0002 },
{ 0x04, 0x00, -1, 0x01, 0x0022, 0x0003 },
{ 0x04, 0x00, -1, 0x02, 0x0022, 0x0004 },
{ 0x04, 0x00, -1, 0x03, 0x0022, 0x0005 },
{ 0x04, 0x00, -1, 0x03, 0x0022, 0x0006 },
{ 0x04, 0x00, -1, 0x03, 0x0022, 0x0007 },
{ 0x04, 0x00, -1, 0x03, 0x0022, 0x0008 },
{ 0x04, 0x00, -1, 0x03, 0x0022, 0x0009 },
{ 0x04, 0x00, -1, 0x00, 0x0032, 0x0002 },
{ 0x04, 0x00, -1, 0x01, 0x0032, 0x0003 },
{ 0x04, 0x00, -1, 0x02, 0x0032, 0x0004 },
{ 0x04, 0x00, -1, 0x03, 0x0032, 0x0005 },
{ 0x04, 0x00, -1, 0x03, 0x0032, 0x0006 },
{ 0x04, 0x00, -1, 0x03, 0x0032, 0x0007 },
{ 0x04, 0x00, -1, 0x03, 0x0032, 0x0008 },
{ 0x04, 0x00, -1, 0x03, 0x0032, 0x0009 },
{ 0x05, 0x00, -1, 0x00, 0x0042, 0x0002 },
{ 0x05, 0x00, -1, 0x01, 0x0042, 0x0003 },
{ 0x05, 0x00, -1, 0x02, 0x0042, 0x0004 },
{ 0x05, 0x00, -1, 0x03, 0x0042, 0x0005 },
{ 0x05, 0x00, -1, 0x03, 0x0042, 0x0006 },
{ 0x05, 0x00, -1, 0x03, 0x0042, 0x0007 },
{ 0x05, 0x00, -1, 0x03, 0x0042, 0x0008 },
{ 0x05, 0x00, -1, 0x03, 0x0042, 0x0009 },
{ 0x05, 0x00, -1, 0x00, 0x0062, 0x0002 },
{ 0x05, 0x00, -1, 0x01, 0x0062, 0x0003 },
{ 0x05, 0x00, -1, 0x02, 0x0062, 0x0004 },
{ 0x05, 0x00, -1, 0x03, 0x0062, 0x0005 },
{ 0x05, 0x00, -1, 0x03, 0x0062, 0x0006 },
{ 0x05, 0x00, -1, 0x03, 0x0062, 0x0007 },
{ 0x05, 0x00, -1, 0x03, 0x0062, 0x0008 },
{ 0x05, 0x00, -1, 0x03, 0x0062, 0x0009 },
{ 0x02, 0x01, -1, 0x03, 0x000a, 0x000a },
{ 0x02, 0x01, -1, 0x03, 0x000a, 0x000c },
{ 0x02, 0x02, -1, 0x03, 0x000a, 0x000e },
{ 0x02, 0x02, -1, 0x03, 0x000a, 0x0012 },
{ 0x02, 0x03, -1, 0x03, 0x000a, 0x0016 },
{ 0x02, 0x03, -1, 0x03, 0x000a, 0x001e },
{ 0x02, 0x04, -1, 0x03, 0x000a, 0x0026 },
{ 0x02, 0x04, -1, 0x03, 0x000a, 0x0036 },
{ 0x02, 0x01, -1, 0x03, 0x000e, 0x000a },
{ 0x02, 0x01, -1, 0x03, 0x000e, 0x000c },
{ 0x02, 0x02, -1, 0x03, 0x000e, 0x000e },
{ 0x02, 0x02, -1, 0x03, 0x000e, 0x0012 },
{ 0x02, 0x03, -1, 0x03, 0x000e, 0x0016 },
{ 0x02, 0x03, -1, 0x03, 0x000e, 0x001e },
{ 0x02, 0x04, -1, 0x03, 0x000e, 0x0026 },
{ 0x02, 0x04, -1, 0x03, 0x000e, 0x0036 },
{ 0x03, 0x01, -1, 0x03, 0x0012, 0x000a },
{ 0x03, 0x01, -1, 0x03, 0x0012, 0x000c },
{ 0x03, 0x02, -1, 0x03, 0x0012, 0x000e },
{ 0x03, 0x02, -1, 0x03, 0x0012, 0x0012 },
{ 0x03, 0x03, -1, 0x03, 0x0012, 0x0016 },
{ 0x03, 0x03, -1, 0x03, 0x0012, 0x001e },
{ 0x03, 0x04, -1, 0x03, 0x0012, 0x0026 },
{ 0x03, 0x04, -1, 0x03, 0x0012, 0x0036 },
{ 0x03, 0x01, -1, 0x03, 0x001a, 0x000a },
{ 0x03, 0x01, -1, 0x03, 0x001a, 0x000c },
{ 0x03, 0x02, -1, 0x03, 0x001a, 0x000e },
{ 0x03, 0x02, -1, 0x03, 0x001a, 0x0012 },
{ 0x03, 0x03, -1, 0x03, 0x001a, 0x0016 },
{ 0x03, 0x03, -1, 0x03, 0x001a, 0x001e },
{ 0x03, 0x04, -1, 0x03, 0x001a, 0x0026 },
{ 0x03, 0x04, -1, 0x03, 0x001a, 0x0036 },
{ 0x04, 0x01, -1, 0x03, 0x0022, 0x000a },
{ 0x04, 0x01, -1, 0x03, 0x0022, 0x000c },
{ 0x04, 0x02, -1, 0x03, 0x0022, 0x000e },
{ 0x04, 0x02, -1, 0x03, 0x0022, 0x0012 },
{ 0x04, 0x03, -1, 0x03, 0x0022, 0x0016 },
{ 0x04, 0x03, -1, 0x03, 0x0022, 0x001e },
{ 0x04, 0x04, -1, 0x03, 0x0022, 0x0026 },
{ 0x04, 0x04, -1, 0x03, 0x0022, 0x0036 },
{ 0x04, 0x01, -1, 0x03, 0x0032, 0x000a },
{ 0x04, 0x01, -1, 0x03, 0x0032, 0x000c },
{ 0x04, 0x02, -1, 0x03, 0x0032, 0x000e },
{ 0x04, 0x02, -1, 0x03, 0x0032, 0x0012 },
{ 0x04, 0x03, -1, 0x03, 0x0032, 0x0016 },
{ 0x04, 0x03, -1, 0x03, 0x0032, 0x001e },
{ 0x04, 0x04, -1, 0x03, 0x0032, 0x0026 },
{ 0x04, 0x04, -1, 0x03, 0x0032, 0x0036 },
{ 0x05, 0x01, -1, 0x03, 0x0042, 0x000a },
{ 0x05, 0x01, -1, 0x03, 0x0042, 0x000c },
{ 0x05, 0x02, -1, 0x03, 0x0042, 0x000e },
{ 0x05, 0x02, -1, 0x03, 0x0042, 0x0012 },
{ 0x05, 0x03, -1, 0x03, 0x0042, 0x0016 },
{ 0x05, 0x03, -1, 0x03, 0x0042, 0x001e },
{ 0x05, 0x04, -1, 0x03, 0x0042, 0x0026 },
{ 0x05, 0x04, -1, 0x03, 0x0042, 0x0036 },
{ 0x05, 0x01, -1, 0x03, 0x0062, 0x000a },
{ 0x05, 0x01, -1, 0x03, 0x0062, 0x000c },
{ 0x05, 0x02, -1, 0x03, 0x0062, 0x000e },
{ 0x05, 0x02, -1, 0x03, 0x0062, 0x0012 },
{ 0x05, 0x03, -1, 0x03, 0x0062, 0x0016 },
{ 0x05, 0x03, -1, 0x03, 0x0062, 0x001e },
{ 0x05, 0x04, -1, 0x03, 0x0062, 0x0026 },
{ 0x05, 0x04, -1, 0x03, 0x0062, 0x0036 },
{ 0x00, 0x05, -1, 0x03, 0x0000, 0x0046 },
{ 0x00, 0x05, -1, 0x03, 0x0000, 0x0066 },
{ 0x00, 0x06, -1, 0x03, 0x0000, 0x0086 },
{ 0x00, 0x07, -1, 0x03, 0x0000, 0x00c6 },
{ 0x00, 0x08, -1, 0x03, 0x0000, 0x0146 },
{ 0x00, 0x09, -1, 0x03, 0x0000, 0x0246 },
{ 0x00, 0x0a, -1, 0x03, 0x0000, 0x0446 },
{ 0x00, 0x18, -1, 0x03, 0x0000, 0x0846 },
{ 0x00, 0x05, -1, 0x03, 0x0001, 0x0046 },
{ 0x00, 0x05, -1, 0x03, 0x0001, 0x0066 },
{ 0x00, 0x06, -1, 0x03, 0x0001, 0x0086 },
{ 0x00, 0x07, -1, 0x03, 0x0001, 0x00c6 },
{ 0x00, 0x08, -1, 0x03, 0x0001, 0x0146 },
{ 0x00, 0x09, -1, 0x03, 0x0001, 0x0246 },
{ 0x00, 0x0a, -1, 0x03, 0x0001, 0x0446 },
{ 0x00, 0x18, -1, 0x03, 0x0001, 0x0846 },
{ 0x00, 0x05, -1, 0x03, 0x0002, 0x0046 },
{ 0x00, 0x05, -1, 0x03, 0x0002, 0x0066 },
{ 0x00, 0x06, -1, 0x03, 0x0002, 0x0086 },
{ 0x00, 0x07, -1, 0x03, 0x0002, 0x00c6 },
{ 0x00, 0x08, -1, 0x03, 0x0002, 0x0146 },
{ 0x00, 0x09, -1, 0x03, 0x0002, 0x0246 },
{ 0x00, 0x0a, -1, 0x03, 0x0002, 0x0446 },
{ 0x00, 0x18, -1, 0x03, 0x0002, 0x0846 },
{ 0x00, 0x05, -1, 0x03, 0x0003, 0x0046 },
{ 0x00, 0x05, -1, 0x03, 0x0003, 0x0066 },
{ 0x00, 0x06, -1, 0x03, 0x0003, 0x0086 },
{ 0x00, 0x07, -1, 0x03, 0x0003, 0x00c6 },
{ 0x00, 0x08, -1, 0x03, 0x0003, 0x0146 },
{ 0x00, 0x09, -1, 0x03, 0x0003, 0x0246 },
{ 0x00, 0x0a, -1, 0x03, 0x0003, 0x0446 },
{ 0x00, 0x18, -1, 0x03, 0x0003, 0x0846 },
{ 0x00, 0x05, -1, 0x03, 0x0004, 0x0046 },
{ 0x00, 0x05, -1, 0x03, 0x0004, 0x0066 },
{ 0x00, 0x06, -1, 0x03, 0x0004, 0x0086 },
{ 0x00, 0x07, -1, 0x03, 0x0004, 0x00c6 },
{ 0x00, 0x08, -1, 0x03, 0x0004, 0x0146 },
{ 0x00, 0x09, -1, 0x03, 0x0004, 0x0246 },
{ 0x00, 0x0a, -1, 0x03, 0x0004, 0x0446 },
{ 0x00, 0x18, -1, 0x03, 0x0004, 0x0846 },
{ 0x00, 0x05, -1, 0x03, 0x0005, 0x0046 },
{ 0x00, 0x05, -1, 0x03, 0x0005, 0x0066 },
{ 0x00, 0x06, -1, 0x03, 0x0005, 0x0086 },
{ 0x00, 0x07, -1, 0x03, 0x0005, 0x00c6 },
{ 0x00, 0x08, -1, 0x03, 0x0005, 0x0146 },
{ 0x00, 0x09, -1, 0x03, 0x0005, 0x0246 },
{ 0x00, 0x0a, -1, 0x03, 0x0005, 0x0446 },
{ 0x00, 0x18, -1, 0x03, 0x0005, 0x0846 },
{ 0x01, 0x05, -1, 0x03, 0x0006, 0x0046 },
{ 0x01, 0x05, -1, 0x03, 0x0006, 0x0066 },
{ 0x01, 0x06, -1, 0x03, 0x0006, 0x0086 },
{ 0x01, 0x07, -1, 0x03, 0x0006, 0x00c6 },
{ 0x01, 0x08, -1, 0x03, 0x0006, 0x0146 },
{ 0x01, 0x09, -1, 0x03, 0x0006, 0x0246 },
{ 0x01, 0x0a, -1, 0x03, 0x0006, 0x0446 },
{ 0x01, 0x18, -1, 0x03, 0x0006, 0x0846 },
{ 0x01, 0x05, -1, 0x03, 0x0008, 0x0046 },
{ 0x01, 0x05, -1, 0x03, 0x0008, 0x0066 },
{ 0x01, 0x06, -1, 0x03, 0x0008, 0x0086 },
{ 0x01, 0x07, -1, 0x03, 0x0008, 0x00c6 },
{ 0x01, 0x08, -1, 0x03, 0x0008, 0x0146 },
{ 0x01, 0x09, -1, 0x03, 0x0008, 0x0246 },
{ 0x01, 0x0a, -1, 0x03, 0x0008, 0x0446 },
{ 0x01, 0x18, -1, 0x03, 0x0008, 0x0846 },
{ 0x06, 0x00, -1, 0x00, 0x0082, 0x0002 },
{ 0x06, 0x00, -1, 0x01, 0x0082, 0x0003 },
{ 0x06, 0x00, -1, 0x02, 0x0082, 0x0004 },
{ 0x06, 0x00, -1, 0x03, 0x0082, 0x0005 },
{ 0x06, 0x00, -1, 0x03, 0x0082, 0x0006 },
{ 0x06, 0x00, -1, 0x03, 0x0082, 0x0007 },
{ 0x06, 0x00, -1, 0x03, 0x0082, 0x0008 },
{ 0x06, 0x00, -1, 0x03, 0x0082, 0x0009 },
{ 0x07, 0x00, -1, 0x00, 0x00c2, 0x0002 },
{ 0x07, 0x00, -1, 0x01, 0x00c2, 0x0003 },
{ 0x07, 0x00, -1, 0x02, 0x00c2, 0x0004 },
{ 0x07, 0x00, -1, 0x03, 0x00c2, 0x0005 },
{ 0x07, 0x00, -1, 0x03, 0x00c2, 0x0006 },
{ 0x07, 0x00, -1, 0x03, 0x00c2, 0x0007 },
{ 0x07, 0x00, -1, 0x03, 0x00c2, 0x0008 },
{ 0x07, 0x00, -1, 0x03, 0x00c2, 0x0009 },
{ 0x08, 0x00, -1, 0x00, 0x0142, 0x0002 },
{ 0x08, 0x00, -1, 0x01, 0x0142, 0x0003 },
{ 0x08, 0x00, -1, 0x02, 0x0142, 0x0004 },
{ 0x08, 0x00, -1, 0x03, 0x0142, 0x0005 },
{ 0x08, 0x00, -1, 0x03, 0x0142, 0x0006 },
{ 0x08, 0x00, -1, 0x03, 0x0142, 0x0007 },
{ 0x08, 0x00, -1, 0x03, 0x0142, 0x0008 },
{ 0x08, 0x00, -1, 0x03, 0x0142, 0x0009 },
{ 0x09, 0x00, -1, 0x00, 0x0242, 0x0002 },
{ 0x09, 0x00, -1, 0x01, 0x0242, 0x0003 },
{ 0x09, 0x00, -1, 0x02, 0x0242, 0x0004 },
{ 0x09, 0x00, -1, 0x03, 0x0242, 0x0005 },
{ 0x09, 0x00, -1, 0x03, 0x0242, 0x0006 },
{ 0x09, 0x00, -1, 0x03, 0x0242, 0x0007 },
{ 0x09, 0x00, -1, 0x03, 0x0242, 0x0008 },
{ 0x09, 0x00, -1, 0x03, 0x0242, 0x0009 },
{ 0x0a, 0x00, -1, 0x00, 0x0442, 0x0002 },
{ 0x0a, 0x00, -1, 0x01, 0x0442, 0x0003 },
{ 0x0a, 0x00, -1, 0x02, 0x0442, 0x0004 },
{ 0x0a, 0x00, -1, 0x03, 0x0442, 0x0005 },
{ 0x0a, 0x00, -1, 0x03, 0x0442, 0x0006 },
{ 0x0a, 0x00, -1, 0x03, 0x0442, 0x0007 },
{ 0x0a, 0x00, -1, 0x03, 0x0442, 0x0008 },
{ 0x0a, 0x00, -1, 0x03, 0x0442, 0x0009 },
{ 0x0c, 0x00, -1, 0x00, 0x0842, 0x0002 },
{ 0x0c, 0x00, -1, 0x01, 0x0842, 0x0003 },
{ 0x0c, 0x00, -1, 0x02, 0x0842, 0x0004 },
{ 0x0c, 0x00, -1, 0x03, 0x0842, 0x0005 },
{ 0x0c, 0x00, -1, 0x03, 0x0842, 0x0006 },
{ 0x0c, 0x00, -1, 0x03, 0x0842, 0x0007 },
{ 0x0c, 0x00, -1, 0x03, 0x0842, 0x0008 },
{ 0x0c, 0x00, -1, 0x03, 0x0842, 0x0009 },
{ 0x0e, 0x00, -1, 0x00, 0x1842, 0x0002 },
{ 0x0e, 0x00, -1, 0x01, 0x1842, 0x0003 },
{ 0x0e, 0x00, -1, 0x02, 0x1842, 0x0004 },
{ 0x0e, 0x00, -1, 0x03, 0x1842, 0x0005 },
{ 0x0e, 0x00, -1, 0x03, 0x1842, 0x0006 },
{ 0x0e, 0x00, -1, 0x03, 0x1842, 0x0007 },
{ 0x0e, 0x00, -1, 0x03, 0x1842, 0x0008 },
{ 0x0e, 0x00, -1, 0x03, 0x1842, 0x0009 },
{ 0x18, 0x00, -1, 0x00, 0x5842, 0x0002 },
{ 0x18, 0x00, -1, 0x01, 0x5842, 0x0003 },
{ 0x18, 0x00, -1, 0x02, 0x5842, 0x0004 },
{ 0x18, 0x00, -1, 0x03, 0x5842, 0x0005 },
{ 0x18, 0x00, -1, 0x03, 0x5842, 0x0006 },
{ 0x18, 0x00, -1, 0x03, 0x5842, 0x0007 },
{ 0x18, 0x00, -1, 0x03, 0x5842, 0x0008 },
{ 0x18, 0x00, -1, 0x03, 0x5842, 0x0009 },
{ 0x02, 0x05, -1, 0x03, 0x000a, 0x0046 },
{ 0x02, 0x05, -1, 0x03, 0x000a, 0x0066 },
{ 0x02, 0x06, -1, 0x03, 0x000a, 0x0086 },
{ 0x02, 0x07, -1, 0x03, 0x000a, 0x00c6 },
{ 0x02, 0x08, -1, 0x03, 0x000a, 0x0146 },
{ 0x02, 0x09, -1, 0x03, 0x000a, 0x0246 },
{ 0x02, 0x0a, -1, 0x03, 0x000a, 0x0446 },
{ 0x02, 0x18, -1, 0x03, 0x000a, 0x0846 },
{ 0x02, 0x05, -1, 0x03, 0x000e, 0x0046 },
{ 0x02, 0x05, -1, 0x03, 0x000e, 0x0066 },
{ 0x02, 0x06, -1, 0x03, 0x000e, 0x0086 },
{ 0x02, 0x07, -1, 0x03, 0x000e, 0x00c6 },
{ 0x02, 0x08, -1, 0x03, 0x000e, 0x0146 },
{ 0x02, 0x09, -1, 0x03, 0x000e, 0x0246 },
{ 0x02, 0x0a, -1, 0x03, 0x000e, 0x0446 },
{ 0x02, 0x18, -1, 0x03, 0x000e, 0x0846 },
{ 0x03, 0x05, -1, 0x03, 0x0012, 0x0046 },
{ 0x03, 0x05, -1, 0x03, 0x0012, 0x0066 },
{ 0x03, 0x06, -1, 0x03, 0x0012, 0x0086 },
{ 0x03, 0x07, -1, 0x03, 0x0012, 0x00c6 },
{ 0x03, 0x08, -1, 0x03, 0x0012, 0x0146 },
{ 0x03, 0x09, -1, 0x03, 0x0012, 0x0246 },
{ 0x03, 0x0a, -1, 0x03, 0x0012, 0x0446 },
{ 0x03, 0x18, -1, 0x03, 0x0012, 0x0846 },
{ 0x03, 0x05, -1, 0x03, 0x001a, 0x0046 },
{ 0x03, 0x05, -1, 0x03, 0x001a, 0x0066 },
{ 0x03, 0x06, -1, 0x03, 0x001a, 0x0086 },
{ 0x03, 0x07, -1, 0x03, 0x001a, 0x00c6 },
{ 0x03, 0x08, -1, 0x03, 0x001a, 0x0146 },
{ 0x03, 0x09, -1, 0x03, 0x001a, 0x0246 },
{ 0x03, 0x0a, -1, 0x03, 0x001a, 0x0446 },
{ 0x03, 0x18, -1, 0x03, 0x001a, 0x0846 },
{ 0x04, 0x05, -1, 0x03, 0x0022, 0x0046 },
{ 0x04, 0x05, -1, 0x03, 0x0022, 0x0066 },
{ 0x04, 0x06, -1, 0x03, 0x0022, 0x0086 },
{ 0x04, 0x07, -1, 0x03, 0x0022, 0x00c6 },
{ 0x04, 0x08, -1, 0x03, 0x0022, 0x0146 },
{ 0x04, 0x09, -1, 0x03, 0x0022, 0x0246 },
{ 0x04, 0x0a, -1, 0x03, 0x0022, 0x0446 },
{ 0x04, 0x18, -1, 0x03, 0x0022, 0x0846 },
{ 0x04, 0x05, -1, 0x03, 0x0032, 0x0046 },
{ 0x04, 0x05, -1, 0x03, 0x0032, 0x0066 },
{ 0x04, 0x06, -1, 0x03, 0x0032, 0x0086 },
{ 0x04, 0x07, -1, 0x03, 0x0032, 0x00c6 },
{ 0x04, 0x08, -1, 0x03, 0x0032, 0x0146 },
{ 0x04, 0x09, -1, 0x03, 0x0032, 0x0246 },
{ 0x04, 0x0a, -1, 0x03, 0x0032, 0x0446 },
{ 0x04, 0x18, -1, 0x03, 0x0032, 0x0846 },
{ 0x05, 0x05, -1, 0x03, 0x0042, 0x0046 },
{ 0x05, 0x05, -1, 0x03, 0x0042, 0x0066 },
{ 0x05, 0x06, -1, 0x03, 0x0042, 0x0086 },
{ 0x05, 0x07, -1, 0x03, 0x0042, 0x00c6 },
{ 0x05, 0x08, -1, 0x03, 0x0042, 0x0146 },
{ 0x05, 0x09, -1, 0x03, 0x0042, 0x0246 },
{ 0x05, 0x0a, -1, 0x03, 0x0042, 0x0446 },
{ 0x05, 0x18, -1, 0x03, 0x0042, 0x0846 },
{ 0x05, 0x05, -1, 0x03, 0x0062, 0x0046 },
{ 0x05, 0x05, -1, 0x03, 0x0062, 0x0066 },
{ 0x05, 0x06, -1, 0x03, 0x0062, 0x0086 },
{ 0x05, 0x07, -1, 0x03, 0x0062, 0x00c6 },
{ 0x05, 0x08, -1, 0x03, 0x0062, 0x0146 },
{ 0x05, 0x09, -1, 0x03, 0x0062, 0x0246 },
{ 0x05, 0x0a, -1, 0x03, 0x0062, 0x0446 },
{ 0x05, 0x18, -1, 0x03, 0x0062, 0x0846 },
{ 0x06, 0x01, -1, 0x03, 0x0082, 0x000a },
{ 0x06, 0x01, -1, 0x03, 0x0082, 0x000c },
{ 0x06, 0x02, -1, 0x03, 0x0082, 0x000e },
{ 0x06, 0x02, -1, 0x03, 0x0082, 0x0012 },
{ 0x06, 0x03, -1, 0x03, 0x0082, 0x0016 },
{ 0x06, 0x03, -1, 0x03, 0x0082, 0x001e },
{ 0x06, 0x04, -1, 0x03, 0x0082, 0x0026 },
{ 0x06, 0x04, -1, 0x03, 0x0082, 0x0036 },
{ 0x07, 0x01, -1, 0x03, 0x00c2, 0x000a },
{ 0x07, 0x01, -1, 0x03, 0x00c2, 0x000c },
{ 0x07, 0x02, -1, 0x03, 0x00c2, 0x000e },
{ 0x07, 0x02, -1, 0x03, 0x00c2, 0x0012 },
{ 0x07, 0x03, -1, 0x03, 0x00c2, 0x0016 },
{ 0x07, 0x03, -1, 0x03, 0x00c2, 0x001e },
{ 0x07, 0x04, -1, 0x03, 0x00c2, 0x0026 },
{ 0x07, 0x04, -1, 0x03, 0x00c2, 0x0036 },
{ 0x08, 0x01, -1, 0x03, 0x0142, 0x000a },
{ 0x08, 0x01, -1, 0x03, 0x0142, 0x000c },
{ 0x08, 0x02, -1, 0x03, 0x0142, 0x000e },
{ 0x08, 0x02, -1, 0x03, 0x0142, 0x0012 },
{ 0x08, 0x03, -1, 0x03, 0x0142, 0x0016 },
{ 0x08, 0x03, -1, 0x03, 0x0142, 0x001e },
{ 0x08, 0x04, -1, 0x03, 0x0142, 0x0026 },
{ 0x08, 0x04, -1, 0x03, 0x0142, 0x0036 },
{ 0x09, 0x01, -1, 0x03, 0x0242, 0x000a },
{ 0x09, 0x01, -1, 0x03, 0x0242, 0x000c },
{ 0x09, 0x02, -1, 0x03, 0x0242, 0x000e },
{ 0x09, 0x02, -1, 0x03, 0x0242, 0x0012 },
{ 0x09, 0x03, -1, 0x03, 0x0242, 0x0016 },
{ 0x09, 0x03, -1, 0x03, 0x0242, 0x001e },
{ 0x09, 0x04, -1, 0x03, 0x0242, 0x0026 },
{ 0x09, 0x04, -1, 0x03, 0x0242, 0x0036 },
{ 0x0a, 0x01, -1, 0x03, 0x0442, 0x000a },
{ 0x0a, 0x01, -1, 0x03, 0x0442, 0x000c },
{ 0x0a, 0x02, -1, 0x03, 0x0442, 0x000e },
{ 0x0a, 0x02, -1, 0x03, 0x0442, 0x0012 },
{ 0x0a, 0x03, -1, 0x03, 0x0442, 0x0016 },
{ 0x0a, 0x03, -1, 0x03, 0x0442, 0x001e },
{ 0x0a, 0x04, -1, 0x03, 0x0442, 0x0026 },
{ 0x0a, 0x04, -1, 0x03, 0x0442, 0x0036 },
{ 0x0c, 0x01, -1, 0x03, 0x0842, 0x000a },
{ 0x0c, 0x01, -1, 0x03, 0x0842, 0x000c },
{ 0x0c, 0x02, -1, 0x03, 0x0842, 0x000e },
{ 0x0c, 0x02, -1, 0x03, 0x0842, 0x0012 },
{ 0x0c, 0x03, -1, 0x03, 0x0842, 0x0016 },
{ 0x0c, 0x03, -1, 0x03, 0x0842, 0x001e },
{ 0x0c, 0x04, -1, 0x03, 0x0842, 0x0026 },
{ 0x0c, 0x04, -1, 0x03, 0x0842, 0x0036 },
{ 0x0e, 0x01, -1, 0x03, 0x1842, 0x000a },
{ 0x0e, 0x01, -1, 0x03, 0x1842, 0x000c },
{ 0x0e, 0x02, -1, 0x03, 0x1842, 0x000e },
{ 0x0e, 0x02, -1, 0x03, 0x1842, 0x0012 },
{ 0x0e, 0x03, -1, 0x03, 0x1842, 0x0016 },
{ 0x0e, 0x03, -1, 0x03, 0x1842, 0x001e },
{ 0x0e, 0x04, -1, 0x03, 0x1842, 0x0026 },
{ 0x0e, 0x04, -1, 0x03, 0x1842, 0x0036 },
{ 0x18, 0x01, -1, 0x03, 0x5842, 0x000a },
{ 0x18, 0x01, -1, 0x03, 0x5842, 0x000c },
{ 0x18, 0x02, -1, 0x03, 0x5842, 0x000e },
{ 0x18, 0x02, -1, 0x03, 0x5842, 0x0012 },
{ 0x18, 0x03, -1, 0x03, 0x5842, 0x0016 },
{ 0x18, 0x03, -1, 0x03, 0x5842, 0x001e },
{ 0x18, 0x04, -1, 0x03, 0x5842, 0x0026 },
{ 0x18, 0x04, -1, 0x03, 0x5842, 0x0036 },
{ 0x06, 0x05, -1, 0x03, 0x0082, 0x0046 },
{ 0x06, 0x05, -1, 0x03, 0x0082, 0x0066 },
{ 0x06, 0x06, -1, 0x03, 0x0082, 0x0086 },
{ 0x06, 0x07, -1, 0x03, 0x0082, 0x00c6 },
{ 0x06, 0x08, -1, 0x03, 0x0082, 0x0146 },
{ 0x06, 0x09, -1, 0x03, 0x0082, 0x0246 },
{ 0x06, 0x0a, -1, 0x03, 0x0082, 0x0446 },
{ 0x06, 0x18, -1, 0x03, 0x0082, 0x0846 },
{ 0x07, 0x05, -1, 0x03, 0x00c2, 0x0046 },
{ 0x07, 0x05, -1, 0x03, 0x00c2, 0x0066 },
{ 0x07, 0x06, -1, 0x03, 0x00c2, 0x0086 },
{ 0x07, 0x07, -1, 0x03, 0x00c2, 0x00c6 },
{ 0x07, 0x08, -1, 0x03, 0x00c2, 0x0146 },
{ 0x07, 0x09, -1, 0x03, 0x00c2, 0x0246 },
{ 0x07, 0x0a, -1, 0x03, 0x00c2, 0x0446 },
{ 0x07, 0x18, -1, 0x03, 0x00c2, 0x0846 },
{ 0x08, 0x05, -1, 0x03, 0x0142, 0x0046 },
{ 0x08, 0x05, -1, 0x03, 0x0142, 0x0066 },
{ 0x08, 0x06, -1, 0x03, 0x0142, 0x0086 },
{ 0x08, 0x07, -1, 0x03, 0x0142, 0x00c6 },
{ 0x08, 0x08, -1, 0x03, 0x0142, 0x0146 },
{ 0x08, 0x09, -1, 0x03, 0x0142, 0x0246 },
{ 0x08, 0x0a, -1, 0x03, 0x0142, 0x0446 },
{ 0x08, 0x18, -1, 0x03, 0x0142, 0x0846 },
{ 0x09, 0x05, -1, 0x03, 0x0242, 0x0046 },
{ 0x09, 0x05, -1, 0x03, 0x0242, 0x0066 },
{ 0x09, 0x06, -1, 0x03, 0x0242, 0x0086 },
{ 0x09, 0x07, -1, 0x03, 0x0242, 0x00c6 },
{ 0x09, 0x08, -1, 0x03, 0x0242, 0x0146 },
{ 0x09, 0x09, -1, 0x03, 0x0242, 0x0246 },
{ 0x09, 0x0a, -1, 0x03, 0x0242, 0x0446 },
{ 0x09, 0x18, -1, 0x03, 0x0242, 0x0846 },
{ 0x0a, 0x05, -1, 0x03, 0x0442, 0x0046 },
{ 0x0a, 0x05, -1, 0x03, 0x0442, 0x0066 },
{ 0x0a, 0x06, -1, 0x03, 0x0442, 0x0086 },
{ 0x0a, 0x07, -1, 0x03, 0x0442, 0x00c6 },
{ 0x0a, 0x08, -1, 0x03, 0x0442, 0x0146 },
{ 0x0a, 0x09, -1, 0x03, 0x0442, 0x0246 },
{ 0x0a, 0x0a, -1, 0x03, 0x0442, 0x0446 },
{ 0x0a, 0x18, -1, 0x03, 0x0442, 0x0846 },
{ 0x0c, 0x05, -1, 0x03, 0x0842, 0x0046 },
{ 0x0c, 0x05, -1, 0x03, 0x0842, 0x0066 },
{ 0x0c, 0x06, -1, 0x03, 0x0842, 0x0086 },
{ 0x0c, 0x07, -1, 0x03, 0x0842, 0x00c6 },
{ 0x0c, 0x08, -1, 0x03, 0x0842, 0x0146 },
{ 0x0c, 0x09, -1, 0x03, 0x0842, 0x0246 },
{ 0x0c, 0x0a, -1, 0x03, 0x0842, 0x0446 },
{ 0x0c, 0x18, -1, 0x03, 0x0842, 0x0846 },
{ 0x0e, 0x05, -1, 0x03, 0x1842, 0x0046 },
{ 0x0e, 0x05, -1, 0x03, 0x1842, 0x0066 },
{ 0x0e, 0x06, -1, 0x03, 0x1842, 0x0086 },
{ 0x0e, 0x07, -1, 0x03, 0x1842, 0x00c6 },
{ 0x0e, 0x08, -1, 0x03, 0x1842, 0x0146 },
{ 0x0e, 0x09, -1, 0x03, 0x1842, 0x0246 },
{ 0x0e, 0x0a, -1, 0x03, 0x1842, 0x0446 },
{ 0x0e, 0x18, -1, 0x03, 0x1842, 0x0846 },
{ 0x18, 0x05, -1, 0x03, 0x5842, 0x0046 },
{ 0x18, 0x05, -1, 0x03, 0x5842, 0x0066 },
{ 0x18, 0x06, -1, 0x03, 0x5842, 0x0086 },
{ 0x18, 0x07, -1, 0x03, 0x5842, 0x00c6 },
{ 0x18, 0x08, -1, 0x03, 0x5842, 0x0146 },
{ 0x18, 0x09, -1, 0x03, 0x5842, 0x0246 },
{ 0x18, 0x0a, -1, 0x03, 0x5842, 0x0446 },
{ 0x18, 0x18, -1, 0x03, 0x5842, 0x0846 },
};
================================================
FILE: NanaZip.Codecs/Brotli/dec/state.c
================================================
/* Copyright 2015 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
#include "state.h"
#include "../common/dictionary.h"
#include "../common/platform.h"
#include "huffman.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#ifdef BROTLI_REPORTING
/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */
void BrotliDecoderOnStart(const BrotliDecoderState* s);
void BrotliDecoderOnFinish(const BrotliDecoderState* s);
#define BROTLI_DECODER_ON_START(s) BrotliDecoderOnStart(s);
#define BROTLI_DECODER_ON_FINISH(s) BrotliDecoderOnFinish(s);
#else
#if !defined(BROTLI_DECODER_ON_START)
#define BROTLI_DECODER_ON_START(s) (void)(s);
#endif
#if !defined(BROTLI_DECODER_ON_FINISH)
#define BROTLI_DECODER_ON_FINISH(s) (void)(s);
#endif
#endif
BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
BROTLI_DECODER_ON_START(s);
if (!alloc_func) {
s->alloc_func = BrotliDefaultAllocFunc;
s->free_func = BrotliDefaultFreeFunc;
s->memory_manager_opaque = 0;
} else {
s->alloc_func = alloc_func;
s->free_func = free_func;
s->memory_manager_opaque = opaque;
}
s->error_code = 0; /* BROTLI_DECODER_NO_ERROR */
BrotliInitBitReader(&s->br);
s->state = BROTLI_STATE_UNINITED;
s->large_window = 0;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
s->buffer_length = 0;
s->loop_counter = 0;
s->pos = 0;
s->rb_roundtrips = 0;
s->partial_pos_out = 0;
s->used_input = 0;
s->block_type_trees = NULL;
s->block_len_trees = NULL;
s->ringbuffer = NULL;
s->ringbuffer_size = 0;
s->new_ringbuffer_size = 0;
s->ringbuffer_mask = 0;
s->context_map = NULL;
s->context_modes = NULL;
s->dist_context_map = NULL;
s->context_map_slice = NULL;
s->dist_context_map_slice = NULL;
s->literal_hgroup.codes = NULL;
s->literal_hgroup.htrees = NULL;
s->insert_copy_hgroup.codes = NULL;
s->insert_copy_hgroup.htrees = NULL;
s->distance_hgroup.codes = NULL;
s->distance_hgroup.htrees = NULL;
s->is_last_metablock = 0;
s->is_uncompressed = 0;
s->is_metadata = 0;
s->should_wrap_ringbuffer = 0;
s->canny_ringbuffer_allocation = 1;
s->window_bits = 0;
s->max_distance = 0;
s->dist_rb[0] = 16;
s->dist_rb[1] = 15;
s->dist_rb[2] = 11;
s->dist_rb[3] = 4;
s->dist_rb_idx = 0;
s->block_type_trees = NULL;
s->block_len_trees = NULL;
s->mtf_upper_bound = 63;
s->compound_dictionary = NULL;
s->dictionary =
BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque);
if (!s->dictionary) return BROTLI_FALSE;
s->metadata_start_func = NULL;
s->metadata_chunk_func = NULL;
s->metadata_callback_opaque = 0;
return BROTLI_TRUE;
}
void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s) {
s->meta_block_remaining_len = 0;
s->block_length[0] = BROTLI_BLOCK_SIZE_CAP;
s->block_length[1] = BROTLI_BLOCK_SIZE_CAP;
s->block_length[2] = BROTLI_BLOCK_SIZE_CAP;
s->num_block_types[0] = 1;
s->num_block_types[1] = 1;
s->num_block_types[2] = 1;
s->block_type_rb[0] = 1;
s->block_type_rb[1] = 0;
s->block_type_rb[2] = 1;
s->block_type_rb[3] = 0;
s->block_type_rb[4] = 1;
s->block_type_rb[5] = 0;
s->context_map = NULL;
s->context_modes = NULL;
s->dist_context_map = NULL;
s->context_map_slice = NULL;
s->literal_htree = NULL;
s->dist_context_map_slice = NULL;
s->dist_htree_index = 0;
s->context_lookup = NULL;
s->literal_hgroup.codes = NULL;
s->literal_hgroup.htrees = NULL;
s->insert_copy_hgroup.codes = NULL;
s->insert_copy_hgroup.htrees = NULL;
s->distance_hgroup.codes = NULL;
s->distance_hgroup.htrees = NULL;
}
void BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState* s) {
BROTLI_DECODER_FREE(s, s->context_modes);
BROTLI_DECODER_FREE(s, s->context_map);
BROTLI_DECODER_FREE(s, s->dist_context_map);
BROTLI_DECODER_FREE(s, s->literal_hgroup.htrees);
BROTLI_DECODER_FREE(s, s->insert_copy_hgroup.htrees);
BROTLI_DECODER_FREE(s, s->distance_hgroup.htrees);
}
void BrotliDecoderStateCleanup(BrotliDecoderState* s) {
BrotliDecoderStateCleanupAfterMetablock(s);
BROTLI_DECODER_ON_FINISH(s);
BROTLI_DECODER_FREE(s, s->compound_dictionary);
BrotliSharedDictionaryDestroyInstance(s->dictionary);
s->dictionary = NULL;
BROTLI_DECODER_FREE(s, s->ringbuffer);
BROTLI_DECODER_FREE(s, s->block_type_trees);
}
BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,
HuffmanTreeGroup* group, brotli_reg_t alphabet_size_max,
brotli_reg_t alphabet_size_limit, brotli_reg_t ntrees) {
/* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)
This number is discovered "unlimited" "enough" calculator; it is actually
a wee bigger than required in several cases (especially for alphabets with
less than 16 symbols). */
const size_t max_table_size = alphabet_size_limit + 376;
const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;
const size_t htree_size = sizeof(HuffmanCode*) * ntrees;
/* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */
HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s,
code_size + htree_size);
group->alphabet_size_max = (uint16_t)alphabet_size_max;
group->alphabet_size_limit = (uint16_t)alphabet_size_limit;
group->num_htrees = (uint16_t)ntrees;
group->htrees = p;
group->codes = p ? (HuffmanCode*)(&p[ntrees]) : NULL;
return !!p;
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/dec/state.h
================================================
/* Copyright 2015 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Brotli state for partial streaming decoding. */
#ifndef BROTLI_DEC_STATE_H_
#define BROTLI_DEC_STATE_H_
#include "../common/constants.h"
#include "../common/platform.h"
#include
#include
#include "bit_reader.h"
#include "huffman.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* Graphviz diagram that describes state transitions:
digraph States {
graph [compound=true]
concentrate=true
node [shape="box"]
UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE}
subgraph cluster_metablock_workflow {
style="rounded"
label=< METABLOCK CYCLE >
METABLOCK_BEGIN -> METABLOCK_HEADER
METABLOCK_HEADER:sw -> METADATA
METABLOCK_HEADER:s -> UNCOMPRESSED
METABLOCK_HEADER:se -> METABLOCK_DONE:ne
METADATA:s -> METABLOCK_DONE:w
UNCOMPRESSED:s -> METABLOCK_DONE:n
METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint="false"]
}
INITIALIZE -> METABLOCK_BEGIN
METABLOCK_DONE -> DONE
subgraph cluster_compressed_metablock {
style="rounded"
label=< COMPRESSED METABLOCK >
subgraph cluster_command {
style="rounded"
label=< HOT LOOP >
_METABLOCK_DONE_PORT_ [shape=point style=invis]
{
// Set different shape for nodes returning from "compressed metablock".
node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS;
CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1;
}
CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY
// IO ("write") nodes are not in the hot loop!
CMD_INNER_WRITE [style=dashed]
CMD_INNER -> CMD_INNER_WRITE
CMD_POST_WRITE_1 [style=dashed]
CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1
CMD_POST_WRITE_2 [style=dashed]
CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2
CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint="false"]
CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS}
[constraint="false"]
CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint="false"]
CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint="false"]
CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint="false"]
CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint="false"]
{rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS;
CMD_POST_WRAP_COPY}
{rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2}
{CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} ->
_METABLOCK_DONE_PORT_ [style=invis]
{CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_
[constraint="false" style=invis]
}
BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n
HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3
HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1
CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP
TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e
BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n
HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint="false"]
{rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3}
{rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2;
TREE_GROUP}
}
METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n
_METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se
[constraint="false" ltail=cluster_command]
UNINITED [shape=Mdiamond];
DONE [shape=Msquare];
}
*/
typedef enum {
BROTLI_STATE_UNINITED,
BROTLI_STATE_LARGE_WINDOW_BITS,
BROTLI_STATE_INITIALIZE,
BROTLI_STATE_METABLOCK_BEGIN,
BROTLI_STATE_METABLOCK_HEADER,
BROTLI_STATE_METABLOCK_HEADER_2,
BROTLI_STATE_CONTEXT_MODES,
BROTLI_STATE_COMMAND_BEGIN,
BROTLI_STATE_COMMAND_INNER,
BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,
BROTLI_STATE_COMMAND_POST_WRAP_COPY,
BROTLI_STATE_UNCOMPRESSED,
BROTLI_STATE_METADATA,
BROTLI_STATE_COMMAND_INNER_WRITE,
BROTLI_STATE_METABLOCK_DONE,
BROTLI_STATE_COMMAND_POST_WRITE_1,
BROTLI_STATE_COMMAND_POST_WRITE_2,
BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER,
BROTLI_STATE_HUFFMAN_CODE_0,
BROTLI_STATE_HUFFMAN_CODE_1,
BROTLI_STATE_HUFFMAN_CODE_2,
BROTLI_STATE_HUFFMAN_CODE_3,
BROTLI_STATE_CONTEXT_MAP_1,
BROTLI_STATE_CONTEXT_MAP_2,
BROTLI_STATE_TREE_GROUP,
BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY,
BROTLI_STATE_DONE
} BrotliRunningState;
typedef enum {
BROTLI_STATE_METABLOCK_HEADER_NONE,
BROTLI_STATE_METABLOCK_HEADER_EMPTY,
BROTLI_STATE_METABLOCK_HEADER_NIBBLES,
BROTLI_STATE_METABLOCK_HEADER_SIZE,
BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED,
BROTLI_STATE_METABLOCK_HEADER_RESERVED,
BROTLI_STATE_METABLOCK_HEADER_BYTES,
BROTLI_STATE_METABLOCK_HEADER_METADATA
} BrotliRunningMetablockHeaderState;
typedef enum {
BROTLI_STATE_UNCOMPRESSED_NONE,
BROTLI_STATE_UNCOMPRESSED_WRITE
} BrotliRunningUncompressedState;
typedef enum {
BROTLI_STATE_TREE_GROUP_NONE,
BROTLI_STATE_TREE_GROUP_LOOP
} BrotliRunningTreeGroupState;
typedef enum {
BROTLI_STATE_CONTEXT_MAP_NONE,
BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,
BROTLI_STATE_CONTEXT_MAP_HUFFMAN,
BROTLI_STATE_CONTEXT_MAP_DECODE,
BROTLI_STATE_CONTEXT_MAP_TRANSFORM
} BrotliRunningContextMapState;
typedef enum {
BROTLI_STATE_HUFFMAN_NONE,
BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,
BROTLI_STATE_HUFFMAN_SIMPLE_READ,
BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,
BROTLI_STATE_HUFFMAN_COMPLEX,
BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS
} BrotliRunningHuffmanState;
typedef enum {
BROTLI_STATE_DECODE_UINT8_NONE,
BROTLI_STATE_DECODE_UINT8_SHORT,
BROTLI_STATE_DECODE_UINT8_LONG
} BrotliRunningDecodeUint8State;
typedef enum {
BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
} BrotliRunningReadBlockLengthState;
/* BrotliDecoderState addon, used for Compound Dictionary functionality. */
typedef struct BrotliDecoderCompoundDictionary {
int num_chunks;
int total_size;
int br_index;
int br_offset;
int br_length;
int br_copied;
const uint8_t* chunks[16];
int chunk_offsets[16];
int block_bits;
uint8_t block_map[256];
} BrotliDecoderCompoundDictionary;
typedef struct BrotliMetablockHeaderArena {
BrotliRunningTreeGroupState substate_tree_group;
BrotliRunningContextMapState substate_context_map;
BrotliRunningHuffmanState substate_huffman;
brotli_reg_t sub_loop_counter;
brotli_reg_t repeat_code_len;
brotli_reg_t prev_code_len;
/* For ReadHuffmanCode. */
brotli_reg_t symbol;
brotli_reg_t repeat;
brotli_reg_t space;
/* Huffman table for "histograms". */
HuffmanCode table[32];
/* List of heads of symbol chains. */
uint16_t* symbol_lists;
/* Storage from symbol_lists. */
uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
BROTLI_NUM_COMMAND_SYMBOLS];
/* Tails of symbol chains. */
int next_symbol[32];
uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
/* Population counts for the code lengths. */
uint16_t code_length_histo[16];
/* TODO(eustas): +2 bytes padding */
/* For HuffmanTreeGroupDecode. */
int htree_index;
HuffmanCode* next;
/* For DecodeContextMap. */
brotli_reg_t context_index;
brotli_reg_t max_run_length_prefix;
brotli_reg_t code;
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
} BrotliMetablockHeaderArena;
typedef struct BrotliMetablockBodyArena {
uint8_t dist_extra_bits[544];
brotli_reg_t dist_offset[544];
} BrotliMetablockBodyArena;
struct BrotliDecoderStateStruct {
BrotliRunningState state;
/* This counter is reused for several disjoint loops. */
int loop_counter;
BrotliBitReader br;
brotli_alloc_func alloc_func;
brotli_free_func free_func;
void* memory_manager_opaque;
/* Temporary storage for remaining input. Brotli stream format is designed in
a way, that 64 bits are enough to make progress in decoding. */
union {
uint64_t u64;
uint8_t u8[8];
} buffer;
brotli_reg_t buffer_length;
int pos;
int max_backward_distance;
int max_distance;
int ringbuffer_size;
int ringbuffer_mask;
int dist_rb_idx;
int dist_rb[4];
int error_code;
int meta_block_remaining_len;
uint8_t* ringbuffer;
uint8_t* ringbuffer_end;
HuffmanCode* htree_command;
const uint8_t* context_lookup;
uint8_t* context_map_slice;
uint8_t* dist_context_map_slice;
/* This ring buffer holds a few past copy distances that will be used by
some special distance codes. */
HuffmanTreeGroup literal_hgroup;
HuffmanTreeGroup insert_copy_hgroup;
HuffmanTreeGroup distance_hgroup;
HuffmanCode* block_type_trees;
HuffmanCode* block_len_trees;
/* This is true if the literal context map histogram type always matches the
block type. It is then not needed to keep the context (faster decoding). */
int trivial_literal_context;
/* Distance context is actual after command is decoded and before distance is
computed. After distance computation it is used as a temporary variable. */
int distance_context;
brotli_reg_t block_length[3];
brotli_reg_t block_length_index;
brotli_reg_t num_block_types[3];
brotli_reg_t block_type_rb[6];
brotli_reg_t distance_postfix_bits;
brotli_reg_t num_direct_distance_codes;
brotli_reg_t num_dist_htrees;
uint8_t* dist_context_map;
HuffmanCode* literal_htree;
/* For partial write operations. */
size_t rb_roundtrips; /* how many times we went around the ring-buffer */
size_t partial_pos_out; /* how much output to the user in total */
/* For InverseMoveToFrontTransform. */
brotli_reg_t mtf_upper_bound;
uint32_t mtf[64 + 1];
int copy_length;
int distance_code;
uint8_t dist_htree_index;
/* TODO(eustas): +3 bytes padding */
/* Less used attributes are at the end of this struct. */
brotli_decoder_metadata_start_func metadata_start_func;
brotli_decoder_metadata_chunk_func metadata_chunk_func;
void* metadata_callback_opaque;
/* For reporting. */
uint64_t used_input; /* how many bytes of input are consumed */
/* States inside function calls. */
BrotliRunningMetablockHeaderState substate_metablock_header;
BrotliRunningUncompressedState substate_uncompressed;
BrotliRunningDecodeUint8State substate_decode_uint8;
BrotliRunningReadBlockLengthState substate_read_block_length;
int new_ringbuffer_size;
/* TODO(eustas): +4 bytes padding */
unsigned int is_last_metablock : 1;
unsigned int is_uncompressed : 1;
unsigned int is_metadata : 1;
unsigned int should_wrap_ringbuffer : 1;
unsigned int canny_ringbuffer_allocation : 1;
unsigned int large_window : 1;
unsigned int window_bits : 6;
unsigned int size_nibbles : 8;
/* TODO(eustas): +12 bits padding */
brotli_reg_t num_literal_htrees;
uint8_t* context_map;
uint8_t* context_modes;
BrotliSharedDictionary* dictionary;
BrotliDecoderCompoundDictionary* compound_dictionary;
uint32_t trivial_literal_contexts[8]; /* 256 bits */
union {
BrotliMetablockHeaderArena header;
BrotliMetablockBodyArena body;
} arena;
};
typedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal;
#define BrotliDecoderState BrotliDecoderStateInternal
BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
BROTLI_INTERNAL void BrotliDecoderStateCleanup(BrotliDecoderState* s);
BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);
BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(
BrotliDecoderState* s);
BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(
BrotliDecoderState* s, HuffmanTreeGroup* group,
brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit,
brotli_reg_t ntrees);
#define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
#define BROTLI_DECODER_FREE(S, X) { \
S->free_func(S->memory_manager_opaque, X); \
X = NULL; \
}
/* Literal/Command/Distance block size maximum; same as maximum metablock size;
used as block size when there is no block switching. */
#define BROTLI_BLOCK_SIZE_CAP (1U << 24)
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_DEC_STATE_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/dec/static_init.h
================================================
/* Copyright 2025 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Central point for static initialization. */
#ifndef THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_
#define THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_
#include "../common/platform.h"
#include "../common/static_init.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)
BROTLI_INTERNAL void BrotliDecoderLazyStaticInitInner(void);
BROTLI_INTERNAL void BrotliDecoderLazyStaticInit(void);
#endif /* BROTLI_STATIC_INIT */
BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderEnsureStaticInit(void);
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif // THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_
================================================
FILE: NanaZip.Codecs/Brotli/enc/backward_references.c
================================================
/* 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 "../common/constants.h"
#include "../common/context.h"
#include "../common/platform.h"
#include "command.h"
#include "compound_dictionary.h"
#include "encoder_dict.h"
#include "hash.h"
#include "params.h"
#include "quality.h" /* IWYU pragma: keep for inc */
#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
#if defined(BROTLI_MAX_SIMD_QUALITY)
#define HASHER() H58
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER
#define HASHER() H68
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER
#endif
#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
#if defined(BROTLI_MAX_SIMD_QUALITY)
#define HASHER() H58
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER
#define HASHER() H68
/* NOLINTNEXTLINE(build/include) */
#include "backward_references_inc.h"
#undef HASHER
#endif
#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)
#if defined(BROTLI_MAX_SIMD_QUALITY)
CASE_(58)
CASE_(68)
#endif
CASE_(40)
CASE_(41)
CASE_(42)
CASE_(55)
CASE_(65)
#undef CASE_
default:
BROTLI_DCHECK(BROTLI_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(BROTLI_FALSE);
break;
}
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/enc/backward_references.h
================================================
/* 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 "../common/context.h"
#include "../common/platform.h"
#include "command.h"
#include "hash.h"
#include "params.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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/backward_references_hq.c
================================================
/* 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 "../common/constants.h"
#include "../common/context.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 "hash.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 BROTLI_MODEL("small") uint32_t kDistanceCacheIndex[] = {
0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
};
static const BROTLI_MODEL("small") 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 c_len = ZopfliNodeCopyLength(&nodes[pos]);
const size_t i_len = 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 - c_len|. 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 + c_len <= block_start + pos + gap &&
dist <= max_backward_limit + gap &&
ZopfliNodeDistanceCode(&nodes[pos]) > 0) {
return (uint32_t)pos;
} else {
return nodes[pos - c_len - i_len].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 i_len = nodes[p].dcode_insert_length & 0x7FFFFFF;
const size_t c_len = ZopfliNodeCopyLength(&nodes[p]);
const size_t dist = ZopfliNodeCopyDistance(&nodes[p]);
dist_cache[idx++] = (int)dist;
/* Because of prerequisite, p >= c_len + i_len >= 2. */
p = nodes[p - c_len - i_len].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;
BROTLI_DCHECK(cur_ix_masked + max_len <= ringbuffer_mask);
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
================================================
FILE: NanaZip.Codecs/Brotli/enc/backward_references_hq.h
================================================
/* 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 "../common/context.h"
#include "../common/platform.h"
#include "command.h"
#include "hash.h"
#include "memory.h"
#include "params.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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/backward_references_inc.h
================================================
/* 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);
}
================================================
FILE: NanaZip.Codecs/Brotli/enc/bit_cost.c
================================================
/* 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 "../common/platform.h"
#include "fast_log.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
double BrotliBitsEntropy(const uint32_t* population, size_t size) {
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);
if (retval < (double)sum) {
/* TODO(eustas): consider doing that per-symbol? */
/* At least one bit per literal is needed. */
retval = (double)sum;
}
return retval;
}
#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
================================================
FILE: NanaZip.Codecs/Brotli/enc/bit_cost.h
================================================
/* 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 "../common/platform.h"
#include "histogram.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
BROTLI_INTERNAL double BrotliBitsEntropy(
const uint32_t* population, size_t size);
BROTLI_INTERNAL double BrotliPopulationCostLiteral(
const HistogramLiteral* histogram);
BROTLI_INTERNAL double BrotliPopulationCostCommand(
const HistogramCommand* histogram);
BROTLI_INTERNAL double BrotliPopulationCostDistance(
const HistogramDistance* histogram);
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_ENC_BIT_COST_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/bit_cost_inc.h
================================================
/* 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 += BrotliBitsEntropy(depth_histo, BROTLI_CODE_LENGTH_CODES);
}
return bits;
}
#undef HistogramType
================================================
FILE: NanaZip.Codecs/Brotli/enc/block_encoder_inc.h
================================================
/* 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/block_splitter.c
================================================
/* 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 "../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 accommodate 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 partition 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 BrotliCountLiteralsForTest(const Command*, size_t);
size_t BrotliCountLiteralsForTest(const Command* cmds, size_t num_commands) {
return CountLiterals(cmds, num_commands);
}
void BrotliCopyLiteralsToByteArrayForTest(
const Command*, size_t, const uint8_t*, size_t, size_t, uint8_t*);
void BrotliCopyLiteralsToByteArrayForTest(const Command* cmds,
size_t num_commands, const uint8_t* data, size_t offset, size_t mask,
uint8_t* literals) {
CopyLiteralsToByteArray(cmds, num_commands, data, offset, mask, literals);
}
#endif
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/enc/block_splitter.h
================================================
/* 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 "../common/platform.h"
#include "command.h"
#include "memory.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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/block_splitter_inc.h
================================================
/* 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 histogram -> 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;
static const size_t prologue_length = 2000;
static const double multiplier = 0.07 / 2000;
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 < prologue_length) {
block_switch_cost *= 0.77 + multiplier * (double)byte_ix;
}
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 ? (u32 + 0 * HISTOGRAMS_PER_BATCH) : NULL;
uint32_t* BROTLI_RESTRICT const new_clusters =
u32 ? (u32 + 1 * HISTOGRAMS_PER_BATCH) : NULL;
uint32_t* BROTLI_RESTRICT const symbols =
u32 ? (u32 + 2 * HISTOGRAMS_PER_BATCH) : NULL;
uint32_t* BROTLI_RESTRICT const remap =
u32 ? (u32 + 3 * HISTOGRAMS_PER_BATCH) : NULL;
uint32_t* BROTLI_RESTRICT const block_lengths =
u32 ? (u32 + 4 * HISTOGRAMS_PER_BATCH) : NULL;
/* 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/brotli_bit_stream.c
================================================
/* 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 "../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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
uint8_t kHuffmanBitLengthHuffmanCodeSymbols[6] = {
0, 7, 3, 2, 1, 15
};
static const BROTLI_MODEL("small")
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 BrotliGetBlockLengthPrefixCodeForTest(uint32_t len, size_t* code,
uint32_t* n_extra, uint32_t* extra);
void BrotliGetBlockLengthPrefixCodeForTest(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
================================================
FILE: NanaZip.Codecs/Brotli/enc/brotli_bit_stream.h
================================================
/* 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 "../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(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_ENC_BROTLI_BIT_STREAM_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/cluster.c
================================================
/* 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 "../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
================================================
FILE: NanaZip.Codecs/Brotli/enc/cluster.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/cluster_inc.h
================================================
/* 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/command.c
================================================
/* 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 "../common/platform.h"
#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
================================================
FILE: NanaZip.Codecs/Brotli/enc/command.h
================================================
/* 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 "../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 BROTLI_MODEL("small")
uint32_t kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES];
BROTLI_INTERNAL extern const BROTLI_MODEL("small")
uint32_t kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES];
BROTLI_INTERNAL extern const BROTLI_MODEL("small")
uint32_t kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES];
BROTLI_INTERNAL extern const BROTLI_MODEL("small")
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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/compound_dictionary.c
================================================
/* 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 "../common/platform.h"
#include
#include "memory.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[(size_t)1u << dictionary->slot_bits]);
uint32_t* items = (uint32_t*)(&heads[(size_t)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;
}
================================================
FILE: NanaZip.Codecs/Brotli/enc/compound_dictionary.h
================================================
/* 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 "../common/platform.h"
#include
#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 */
================================================
FILE: NanaZip.Codecs/Brotli/enc/compress_fragment.c
================================================
/* 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 "../common/constants.h"
#include "../common/platform.h"
#include "brotli_bit_stream.h"
#include "entropy_encode.h"
#include "fast_log.h"
#include "find_match_length.h"
#include "hash_base.h"
#include "write_bits.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)
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 BROTLI_MODEL("small") 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/compress_fragment.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/compress_fragment_two_pass.c
================================================
/* 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 "../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 "hash_base.h"
#include "write_bits.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)
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 BROTLI_MODEL("small") 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 BROTLI_MODEL("small") 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(
BrotliBitsEntropy(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
================================================
FILE: NanaZip.Codecs/Brotli/enc/compress_fragment_two_pass.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/dictionary_hash.c
================================================
/* 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 "dictionary_hash.h"
#include "../common/platform.h" /* IWYU pragma: keep */
#include "../common/static_init.h"
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
#include "../common/dictionary.h"
#include "hash_base.h"
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
BROTLI_BOOL BROTLI_COLD BrotliEncoderInitDictionaryHash(
const BrotliDictionary* dict, uint16_t* words, uint8_t* lengths) {
size_t global_idx = 0;
size_t len;
size_t i;
static const uint8_t frozen_idx[1688] = {0, 0, 8, 164, 32, 56, 31, 191, 36, 4,
128, 81, 68, 132, 145, 129, 0, 0, 0, 28, 0, 8, 1, 1, 64, 3, 1, 0, 0, 0, 0, 0, 4,
64, 1, 2, 128, 0, 132, 49, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 1, 0, 36, 152,
0, 0, 0, 0, 128, 8, 0, 0, 128, 0, 0, 8, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,
0, 0, 0, 1, 0, 64, 133, 0, 32, 0, 0, 128, 1, 0, 0, 0, 0, 4, 4, 4, 32, 16, 130,
0, 128, 8, 0, 0, 0, 0, 0, 64, 0, 64, 0, 160, 0, 148, 53, 0, 0, 0, 0, 0, 128, 0,
130, 0, 0, 0, 8, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 32, 1, 32, 129, 0, 12, 0,
1, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8,
0, 0, 2, 0, 0, 0, 0, 0, 32, 0, 0, 0, 2, 66, 128, 0, 0, 16, 0, 0, 0, 0, 64, 1, 6,
128, 8, 0, 192, 24, 32, 0, 0, 8, 4, 128, 128, 2, 160, 0, 160, 0, 64, 0, 0, 2, 0,
0, 0, 0, 0, 0, 0, 0, 0, 32, 1, 0, 0, 64, 0, 0, 0, 0, 0, 0, 32, 0, 66, 0, 2, 0,
4, 0, 8, 0, 2, 0, 0, 33, 8, 0, 0, 0, 8, 0, 128, 162, 4, 128, 0, 2, 33, 0, 160,
0, 8, 0, 64, 0, 160, 0, 129, 4, 0, 0, 32, 0, 0, 32, 0, 2, 0, 0, 0, 0, 0, 0, 128,
0, 0, 0, 0, 0, 64, 10, 0, 0, 0, 0, 32, 64, 0, 0, 0, 0, 0, 16, 0, 16, 16, 0, 0,
80, 2, 0, 0, 0, 0, 8, 0, 0, 16, 0, 8, 0, 0, 0, 8, 64, 128, 0, 0, 0, 8, 208, 0,
0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 32, 0, 8, 0, 128, 0, 0, 0, 1, 0, 0, 0,
16, 8, 1, 136, 0, 0, 36, 0, 64, 9, 0, 1, 32, 8, 0, 64, 64, 131, 16, 224, 32, 4,
0, 4, 5, 160, 0, 131, 0, 4, 96, 0, 0, 184, 192, 0, 177, 205, 96, 0, 0, 0, 0, 2,
0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 128, 0, 0, 8, 0, 0, 0, 0, 1, 4, 0, 1,
0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 4, 0, 0, 64, 69, 0, 0, 8, 2, 66, 32, 64, 0, 0, 0,
0, 0, 1, 0, 128, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 16, 0, 0, 4, 128, 64,
0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 8, 0, 0, 130, 16, 64, 128, 2, 64, 0, 0, 0, 128,
2, 192, 64, 0, 65, 0, 0, 0, 16, 0, 0, 0, 32, 4, 2, 2, 76, 0, 0, 0, 4, 72, 52,
131, 44, 76, 0, 0, 0, 0, 64, 1, 16, 148, 4, 0, 16, 10, 64, 0, 2, 0, 1, 0, 128,
64, 68, 0, 0, 0, 0, 0, 64, 144, 0, 8, 0, 2, 0, 0, 0, 0, 0, 0, 3, 64, 0, 0, 0, 0,
1, 128, 0, 0, 32, 66, 0, 0, 0, 40, 0, 18, 0, 0, 0, 0, 0, 33, 0, 0, 32, 0, 0, 32,
0, 128, 4, 64, 145, 140, 0, 0, 0, 128, 0, 2, 0, 0, 20, 0, 80, 38, 0, 0, 32, 0,
32, 64, 4, 4, 0, 4, 0, 0, 0, 129, 4, 0, 0, 144, 17, 32, 130, 16, 132, 24, 134,
0, 0, 64, 2, 5, 50, 8, 194, 33, 1, 68, 117, 1, 8, 32, 161, 54, 0, 130, 34, 0, 0,
0, 64, 128, 0, 0, 2, 0, 0, 0, 0, 32, 1, 0, 0, 0, 3, 14, 0, 0, 0, 0, 0, 16, 4, 0,
0, 0, 0, 0, 0, 0, 0, 96, 1, 24, 18, 0, 1, 128, 24, 0, 64, 0, 4, 0, 16, 128, 0,
64, 0, 0, 0, 64, 0, 8, 0, 0, 0, 0, 0, 66, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 16, 0, 64, 2, 0, 0, 0, 0, 6, 0, 8, 8, 2, 0, 64, 0, 0, 0, 0, 128, 2,
2, 12, 64, 0, 64, 0, 8, 0, 128, 32, 0, 0, 10, 0, 0, 32, 0, 128, 32, 33, 8, 136,
0, 96, 64, 0, 0, 0, 0, 0, 64, 4, 16, 4, 8, 0, 0, 0, 16, 0, 2, 0, 0, 1, 128, 0,
64, 16, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 2, 0, 16, 0, 4, 0, 8, 0, 0, 0, 0, 0,
20, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 136, 0, 0, 0, 0, 0, 8, 0,
0, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0,
0, 0, 4, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 128, 0, 0, 0, 8, 2, 0, 0, 128, 0, 16, 2, 0, 0, 4, 0, 32, 0, 0, 1,
4, 64, 64, 0, 4, 0, 1, 0, 16, 0, 32, 68, 4, 4, 65, 10, 0, 20, 37, 18, 1, 148, 0,
32, 128, 3, 8, 0, 64, 0, 0, 0, 0, 0, 0, 4, 0, 16, 1, 128, 0, 0, 0, 128, 16, 0,
0, 0, 0, 1, 128, 0, 0, 128, 64, 128, 64, 0, 130, 0, 164, 8, 0, 0, 1, 64, 128, 0,
18, 0, 2, 150, 0, 8, 0, 0, 64, 0, 81, 0, 0, 16, 128, 2, 8, 36, 32, 129, 4, 144,
13, 0, 0, 3, 8, 1, 0, 2, 0, 0, 64, 0, 5, 0, 1, 34, 1, 32, 2, 16, 128, 128, 128,
0, 0, 0, 2, 0, 4, 18, 8, 12, 34, 32, 192, 6, 64, 224, 33, 0, 0, 137, 72, 64, 0,
24, 8, 128, 128, 0, 16, 0, 32, 128, 128, 132, 8, 0, 0, 16, 0, 64, 0, 0, 4, 0, 0,
16, 0, 4, 128, 64, 0, 0, 1, 0, 4, 64, 32, 144, 130, 2, 128, 0, 192, 0, 64, 82,
64, 1, 32, 128, 128, 2, 0, 84, 0, 32, 0, 44, 24, 72, 80, 32, 16, 0, 0, 44, 16,
96, 64, 1, 72, 131, 0, 0, 0, 16, 0, 0, 165, 0, 129, 2, 49, 48, 64, 64, 12, 64,
176, 64, 84, 8, 128, 20, 64, 213, 136, 104, 1, 41, 15, 83, 170, 0, 0, 41, 1, 64,
64, 0, 193, 64, 64, 8, 0, 128, 0, 0, 64, 8, 64, 8, 1, 16, 0, 8, 0, 0, 2, 1, 128,
28, 84, 141, 97, 0, 0, 68, 0, 0, 129, 8, 0, 16, 8, 32, 0, 64, 0, 0, 0, 24, 0, 0,
0, 192, 0, 8, 128, 0, 0, 0, 0, 0, 64, 0, 1, 0, 0, 0, 0, 40, 1, 128, 64, 0, 4, 2,
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 32, 8, 0, 32, 0, 0, 0, 16, 17, 0,
2, 4, 0, 0, 33, 128, 2, 0, 0, 0, 0, 129, 0, 2, 0, 0, 0, 36, 0, 32, 2, 0, 0, 0,
0, 0, 0, 32, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 32, 64, 0, 0, 0, 0, 0, 0,
32, 0, 0, 32, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 16, 0, 0, 0, 0, 0, 0, 0,
1, 0, 136, 0, 0, 24, 192, 128, 3, 0, 17, 18, 2, 0, 66, 0, 4, 24, 0, 9, 208, 167,
0, 144, 20, 64, 0, 130, 64, 0, 2, 16, 136, 8, 74, 32, 0, 168, 0, 65, 32, 8, 12,
1, 3, 1, 64, 180, 3, 0, 64, 0, 8, 0, 0, 32, 65, 0, 4, 16, 4, 16, 68, 32, 64, 36,
32, 24, 33, 1, 128, 0, 0, 8, 0, 32, 64, 81, 0, 1, 10, 19, 8, 0, 0, 4, 5, 144, 0,
0, 8, 128, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 0, 0, 80, 1, 0, 0,
33, 0, 32, 66, 4, 2, 0, 1, 43, 2, 0, 0, 4, 32, 16, 0, 64, 0, 3, 32, 0, 2, 64,
64, 116, 0, 65, 52, 64, 0, 17, 64, 192, 96, 8, 10, 8, 2, 4, 0, 17, 64, 0, 4, 0,
0, 4, 128, 0, 0, 9, 0, 0, 130, 2, 0, 192, 0, 48, 128, 64, 0, 96, 0, 64, 0, 1,
16, 32, 0, 1, 32, 6, 128, 2, 32, 0, 12, 0, 0, 48, 32, 8, 0, 0, 128, 0, 18, 0,
0, 28, 24, 41, 16, 5, 32, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 0, 64, 0, 0, 0, 0, 8, 0, 0, 0, 0, 16, 128,
0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0};
memset(lengths, 0, BROTLI_ENC_NUM_HASH_BUCKETS);
for (len = BROTLI_MAX_DICTIONARY_WORD_LENGTH;
len >= BROTLI_MIN_DICTIONARY_WORD_LENGTH; --len) {
size_t length_lt_8 = len < 8 ? 1 : 0;
size_t n = 1u << dict->size_bits_by_length[len];
const uint8_t* dict_words = dict->data + dict->offsets_by_length[len];
for (i = 0; i < n; ++i) {
size_t j = n - 1 - i;
const uint8_t* word = dict_words + len * j;
const uint32_t key = Hash14(word);
size_t idx = (key << 1) + length_lt_8;
if ((lengths[idx] & 0x80) == 0) {
BROTLI_BOOL is_final = TO_BROTLI_BOOL(frozen_idx[global_idx / 8] &
(1u << (global_idx % 8)));
words[idx] = (uint16_t)j;
lengths[idx] = (uint8_t)(len + (is_final ? 0x80 : 0));
}
global_idx++;
}
}
for (i = 0; i < BROTLI_ENC_NUM_HASH_BUCKETS; ++i) {
lengths[i] &= 0x7F;
}
return BROTLI_TRUE;
}
BROTLI_MODEL("small")
uint16_t kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS];
BROTLI_MODEL("small")
uint8_t kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS];
#else /* BROTLI_STATIC_INIT */
/* Embed kStaticDictionaryHashWords and kStaticDictionaryHashLengths. */
#include "dictionary_hash_inc.h"
#endif /* BROTLI_STATIC_INIT */
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/enc/dictionary_hash.h
================================================
/* 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 "../common/platform.h"
#include "../common/static_init.h"
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
#include "../common/dictionary.h"
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* Bucket is (Hash14 * 2 + length_lt_8); in other words we reserve 2 buckets
for each hash - one for shorter words and one for longer words. */
#define BROTLI_ENC_NUM_HASH_BUCKETS 32768
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
BROTLI_BOOL BROTLI_INTERNAL BrotliEncoderInitDictionaryHash(
const BrotliDictionary* dictionary, uint16_t* words, uint8_t* lengths);
BROTLI_INTERNAL extern BROTLI_MODEL("small") uint16_t
kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS];
BROTLI_INTERNAL extern BROTLI_MODEL("small") uint8_t
kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS];
#else
BROTLI_INTERNAL extern const BROTLI_MODEL("small") uint16_t
kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS];
BROTLI_INTERNAL extern const BROTLI_MODEL("small") uint8_t
kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS];
#endif
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_ENC_DICTIONARY_HASH_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/dictionary_hash_inc.h
================================================
const BROTLI_MODEL("small")
uint16_t kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS] = {
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};
const BROTLI_MODEL("small")
uint8_t kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS] = {
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};
================================================
FILE: NanaZip.Codecs/Brotli/enc/enc_static_init.c
================================================
/* Copyright 2025 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
#include "static_init.h"
#include "../common/platform.h"
#include "../common/static_init.h"
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
#include "../common/dictionary.h"
#include "dictionary_hash.h"
#include "static_dict_lut.h"
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
static BROTLI_BOOL DoBrotliEncoderStaticInit(void) {
const BrotliDictionary* dict = BrotliGetDictionary();
BROTLI_BOOL ok = BrotliEncoderInitStaticDictionaryLut(
dict, kStaticDictionaryBuckets, kStaticDictionaryWords);
if (!ok) return BROTLI_FALSE;
ok = BrotliEncoderInitDictionaryHash(dict, kStaticDictionaryHashWords,
kStaticDictionaryHashLengths);
if (!ok) return BROTLI_FALSE;
return BROTLI_TRUE;
}
#endif /* BROTLI_STATIC_INIT_NONE */
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)
static BROTLI_BOOL kEarlyInitOk;
static __attribute__((constructor)) void BrotliEncoderStaticInitEarly(void) {
kEarlyInitOk = DoBrotliEncoderStaticInit();
}
#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)
static BROTLI_BOOL kLazyInitOk;
void BrotliEncoderLazyStaticInitInner(void) {
kLazyInitOk = DoBrotliEncoderStaticInit();
}
#endif /* BROTLI_STATIC_INIT_EARLY */
BROTLI_BOOL BrotliEncoderEnsureStaticInit(void) {
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)
return BROTLI_TRUE;
#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)
return kEarlyInitOk;
#else
return kLazyInitOk;
#endif
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/enc/encode.c
================================================
/* 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 "../common/constants.h"
#include "../common/context.h"
#include "../common/platform.h"
#include
#include "../common/version.h"
#include "backward_references_hq.h"
#include "backward_references.h"
#include "bit_cost.h"
#include "brotli_bit_stream.h"
#include "command.h"
#include "compound_dictionary.h"
#include "compress_fragment_two_pass.h"
#include "compress_fragment.h"
#include "dictionary_hash.h"
#include "encoder_dict.h"
#include "fast_log.h"
#include "hash.h"
#include "histogram.h"
#include "memory.h"
#include "metablock.h"
#include "params.h"
#include "quality.h"
#include "ringbuffer.h"
#include "state.h"
#include "static_init.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 BROTLI_MODEL("small") 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 BROTLI_MODEL("small") 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 BROTLI_MODEL("small") 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;
}
/* TODO(eustas): avoid FP calculations. */
static double EstimateEntropy(const uint32_t* population, size_t size) {
size_t total = 0;
double result = 0;
for (size_t i = 0; i < size; ++i) {
uint32_t p = population[i];
total += p;
result += (double)p * FastLog2(p);
}
result = (double)total * FastLog2(total) - result;
return result;
}
/* 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 'BrotliBitsEntropy' since the prefix will be
encoded with the remaining 6 bits of the following byte, and
BrotliBitsEntropy 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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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;
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] = EstimateEntropy(monogram_histo, 3);
entropy[2] = (EstimateEntropy(two_prefix_histo, 3) +
EstimateEntropy(two_prefix_histo + 3, 3));
entropy[3] = 0;
for (i = 0; i < 3; ++i) {
entropy[3] += EstimateEntropy(bigram_histo + 3 * i, 3);
}
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 BROTLI_MODEL("small")
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 i;
ContextLut utf8_lut = BROTLI_CONTEXT_LUT(CONTEXT_UTF8);
memset(arena, 0, sizeof(arena[0]) * 32 * (BROTLI_MAX_STATIC_CONTEXTS + 1));
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] = EstimateEntropy(combined_histo, 32);
entropy[2] = 0;
for (i = 0; i < BROTLI_MAX_STATIC_CONTEXTS; ++i) {
entropy[2] += EstimateEntropy(context_histo + (i << 5), 32);
}
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 = BROTLI_MAX_STATIC_CONTEXTS;
*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 kInvSampleRate = 1.0 / 13.0;
static const double kMinEntropy = 7.92;
const double bit_cost_threshold =
(double)bytes * kMinEntropy * kInvSampleRate;
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 (BrotliBitsEntropy(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, 32 * (BROTLI_MAX_STATIC_CONTEXTS + 1));
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);
}
#ifdef BROTLI_REPORTING
/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */
void BrotliEncoderOnStart(const BrotliEncoderState* s);
void BrotliEncoderOnFinish(const BrotliEncoderState* s);
#define BROTLI_ENCODER_ON_START(s) BrotliEncoderOnStart(s);
#define BROTLI_ENCODER_ON_FINISH(s) BrotliEncoderOnFinish(s);
#else
#if !defined(BROTLI_ENCODER_ON_START)
#define BROTLI_ENCODER_ON_START(s) (void)(s);
#endif
#if !defined(BROTLI_ENCODER_ON_FINISH)
#define BROTLI_ENCODER_ON_FINISH(s) (void)(s);
#endif
#endif
static void BrotliEncoderInitState(BrotliEncoderState* s) {
BROTLI_ENCODER_ON_START(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) {
BROTLI_BOOL healthy = BrotliEncoderEnsureStaticInit();
if (!healthy) {
return 0;
}
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;
}
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 overwrite with 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 BROTLI_COLD 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 BROTLI_COLD 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 BROTLI_COLD 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, ((size_t)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 : ((size_t)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 BROTLI_COLD 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 BrotliMakeUncompressedStreamForTest(const uint8_t*, size_t, uint8_t*);
size_t BrotliMakeUncompressedStreamForTest(
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
================================================
FILE: NanaZip.Codecs/Brotli/enc/encoder_dict.c
================================================
/* 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 "../common/dictionary.h"
#include "../common/platform.h"
#include
#include "../common/shared_dictionary_internal.h"
#include "../common/transform.h"
#include
#include "compound_dictionary.h"
#include "dictionary_hash.h"
#include "hash_base.h"
#include "hash.h"
#include "memory.h"
#include "quality.h"
#include "static_dict_lut.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 placeholder 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 BrotliInitEncoderDictionaryForTest(BrotliEncoderDictionary*);
void BrotliInitEncoderDictionaryForTest(BrotliEncoderDictionary* d) {
InitEncoderDictionary(d);
}
#endif
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/enc/encoder_dict.h
================================================
/* 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 "../common/dictionary.h"
#include
#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 hierarchy 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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/entropy_encode.c
================================================
/* 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 "../common/constants.h"
#include "../common/platform.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
const BROTLI_MODEL("small") 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 BROTLI_MODEL("small") 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/entropy_encode.h
================================================
/* 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 "../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 length,
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 BROTLI_MODEL("small") 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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/entropy_encode_static.h
================================================
/* 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 "../common/constants.h"
#include "../common/platform.h"
#include "write_bits.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static const BROTLI_MODEL("small") uint8_t kCodeLengthDepth[18] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 0, 4, 4,
};
static const BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small")
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 BROTLI_MODEL("small") 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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/fast_log.c
================================================
/* 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 BROTLI_MODEL("small") 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/fast_log.h
================================================
/* 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 "../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 BROTLI_MODEL("small")
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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/find_match_length.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash.h
================================================
/* 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 "../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 "hash_base.h"
#include "matching_tag_mask.h"
#include "memory.h"
#include "params.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 first 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;
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
#if defined(BROTLI_MAX_SIMD_QUALITY)
#define HASHER() H58
#include "hash_longest_match_simd_inc.h" /* NOLINT(build/include) */
#undef HASHER
#define HASHER() H68
#include "hash_longest_match64_simd_inc.h" /* NOLINT(build/include) */
#undef HASHER
#endif
#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
#if defined(BROTLI_MAX_SIMD_QUALITY)
#define FOR_SIMPLE_HASHERS(H) \
H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) H(58) H(68)
#else
#define FOR_SIMPLE_HASHERS(H) \
H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
#endif
#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[(size_t)1u << slot_bits]);
const uint32_t* items = (uint32_t*)(&heads[(size_t)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);
}
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
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;
}
}
}
}
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
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 ||
/* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&source[offset + best_len - 3])) {
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[(size_t)1u << slot_bits]);
const uint32_t* items = (uint32_t*)(&heads[(size_t)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);
}
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_base.h
================================================
/* Copyright 2025 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Basic common hash functions / constants. */
#ifndef THIRD_PARTY_BROTLI_ENC_HASH_BASE_H_
#define THIRD_PARTY_BROTLI_ENC_HASH_BASE_H_
#include "../common/platform.h"
/* 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 uint32_t Hash15(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 - 15);
}
#endif // THIRD_PARTY_BROTLI_ENC_HASH_BASE_H_
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_composite_inc.h
================================================
/* 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_forgetful_chain_inc.h
================================================
/* 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;
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
/* 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;
}
}
}
}
}
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{
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 ||
/* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_longest_match64_inc.h
================================================
/* 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;
/* Precalculate the hash key and prefetch the bucket. */
const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_);
uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
PREFETCH_L1(bucket);
if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);
out->len = 0;
out->len_code_delta = 0;
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
/* 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) {
break;
}
if (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;
}
}
}
}
}
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{
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) {
break;
}
if (prev_ix + best_len > ring_buffer_mask ||
/* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_longest_match64_simd_inc.h
================================================
/* 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()
#define TAG_HASH_BITS 8
#define TAG_HASH_MASK ((1 << TAG_HASH_BITS) - 1)
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 - TAG_HASH_BITS));
}
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]; */
uint8_t* tags_;
/* 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->tags_ = (uint8_t*)common->extra[1];
self->buckets_ = (uint32_t*)common->extra[2];
}
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 hash = FN(HashBytes)(&data[i], self->hash_mul_);
const size_t key = hash >> TAG_HASH_BITS;
num[key] = 65535;
}
} else {
/* Set all the bytes of num to 255, which makes each uint16_t 65535. */
memset(num, 255, 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(uint8_t) * bucket_size * block_size;
alloc_size[2] = 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_;
uint8_t* BROTLI_RESTRICT tags = self->tags_;
uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
const size_t hash = FN(HashBytes)(&data[ix & mask], self->hash_mul_);
const size_t key = hash >> TAG_HASH_BITS;
const uint8_t tag = hash & TAG_HASH_MASK;
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;
tags[offset] = tag;
}
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_;
uint8_t* BROTLI_RESTRICT tags = self->tags_;
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;
/* Precalculate the hash key and prefetch the bucket. */
const size_t hash = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_);
const size_t key = hash >> TAG_HASH_BITS;
uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
uint8_t* BROTLI_RESTRICT tag_bucket = &tags[key << self->block_bits_];
PREFETCH_L1(bucket);
PREFETCH_L1(tag_bucket);
if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);
out->len = 0;
out->len_code_delta = 0;
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
/* 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) {
break;
}
if (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;
}
}
}
}
}
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{
const uint8_t tag = hash & TAG_HASH_MASK;
const uint32_t first4 = BrotliUnalignedRead32(data + cur_ix_masked);
const size_t max_length_m4 = max_length - 4;
const size_t head = (num[key] + 1) & self->block_mask_;
uint64_t matches =
GetMatchingTagMask(self->block_size_ / 16, tag, tag_bucket, head);
/* Mask off any matches from uninitialized tags. */
uint16_t n = 65535 - num[key];
uint64_t block_has_unused_slots = self->block_size_ > n;
uint64_t mask = (block_has_unused_slots << (n & (64 - 1))) - 1;
matches &= mask;
for (; matches > 0; matches &= (matches - 1)) {
const size_t rb_index =
(head + (size_t)BROTLI_TZCNT64(matches)) & self->block_mask_;
size_t prev_ix = bucket[rb_index];
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) {
break;
}
if (prev_ix + best_len > ring_buffer_mask ||
/* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
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;
tag_bucket[num[key] & self->block_mask_] = tag;
--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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_longest_match_inc.h
================================================
/* 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) {
uint16_t* BROTLI_RESTRICT num = self->num_;
uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_shift_);
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;
/* Precalculate the hash key and prefetch the bucket. */
const uint32_t key =
FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);
uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
PREFETCH_L1(bucket);
if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);
out->len = 0;
out->len_code_delta = 0;
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
/* 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) {
break;
}
if (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;
}
}
}
}
}
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{
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) {
break;
}
if (prev_ix + best_len > ring_buffer_mask ||
/* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_longest_match_quickly_inc.h
================================================
/* 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;
/* TODO: compare 4 bytes at once (and set the minimum best len to 4) */
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;
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_longest_match_simd_inc.h
================================================
/* 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()
#define TAG_HASH_BITS 8
#define TAG_HASH_MASK ((1 << TAG_HASH_BITS) - 1)
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]; */
uint8_t* tags_;
/* 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 - TAG_HASH_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->tags_ = (uint8_t*)common->extra[1];
self->buckets_ = (uint32_t*)common->extra[2];
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 hash = FN(HashBytes)(&data[i], self->hash_shift_);
const uint32_t key = hash >> TAG_HASH_BITS;
num[key] = 65535;
}
} else {
/* Set all the bytes of num to 255, which makes each uint16_t 65535. */
memset(num, 255, 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(uint8_t) * bucket_size * block_size;
alloc_size[2] = 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_;
uint8_t* BROTLI_RESTRICT tags = self->tags_;
uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
const size_t hash = FN(HashBytes)(&data[ix & mask], self->hash_shift_);
const size_t key = hash >> TAG_HASH_BITS;
const uint8_t tag = hash & TAG_HASH_MASK;
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;
tags[offset] = tag;
}
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_;
uint8_t* BROTLI_RESTRICT tags = self->tags_;
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;
/* Precalculate the hash key and prefetch the bucket. */
const uint32_t hash =
FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);
const uint32_t key = hash >> TAG_HASH_BITS;
uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
uint8_t* BROTLI_RESTRICT tag_bucket = &tags[key << self->block_bits_];
PREFETCH_L1(bucket);
PREFETCH_L1(tag_bucket);
if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);
out->len = 0;
out->len_code_delta = 0;
BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);
/* 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) {
break;
}
if (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;
}
}
}
}
}
/* we require matches of len >4, so increase best_len to 3, so we can compare
* 4 bytes all the time. */
if (best_len < 3) {
best_len = 3;
}
{
const uint8_t tag = hash & TAG_HASH_MASK;
const size_t head = (num[key] + 1) & self->block_mask_;
uint64_t matches =
GetMatchingTagMask(self->block_size_ / 16, tag, tag_bucket, head);
/* Mask off any matches from uninitialized tags. */
uint16_t n = 65535 - num[key];
uint64_t block_has_unused_slots = self->block_size_ > n;
uint64_t mask = (block_has_unused_slots << (n & (64 - 1))) - 1;
matches &= mask;
for (; matches > 0; matches &= (matches - 1)) {
const size_t rb_index =
(head + (size_t)BROTLI_TZCNT64(matches)) & self->block_mask_;
size_t prev_ix = bucket[rb_index];
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) {
break;
}
if (prev_ix + best_len > ring_buffer_mask ||
/* compare 4 bytes ending at best_len + 1 */
BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
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;
tag_bucket[num[key] & self->block_mask_] = tag;
--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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_rolling_inc.h
================================================
/* 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/hash_to_binary_tree_inc.h
================================================
/* 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
================================================
FILE: NanaZip.Codecs/Brotli/enc/histogram.c
================================================
/* 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 "../common/platform.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
================================================
FILE: NanaZip.Codecs/Brotli/enc/histogram.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/histogram_inc.h
================================================
/* 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; }
================================================
FILE: NanaZip.Codecs/Brotli/enc/literal_cost.c
================================================
/* 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 "../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]];
static const size_t prologue_length = 2000;
static const double multiplier = 0.35 / 2000;
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 < prologue_length) {
lit_cost += 0.35 + multiplier * (double)i;
}
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
================================================
FILE: NanaZip.Codecs/Brotli/enc/literal_cost.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/matching_tag_mask.h
================================================
#ifndef THIRD_PARTY_BROTLI_ENC_MATCHING_TAG_MASK_H_
#define THIRD_PARTY_BROTLI_ENC_MATCHING_TAG_MASK_H_
#include "../common/platform.h"
#if defined(__SSE2__) || defined(_M_AMD64) || \
(defined(_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))
#define SUPPORTS_SSE_2
#endif
#if defined(SUPPORTS_SSE_2)
#include
#endif
static BROTLI_INLINE uint64_t GetMatchingTagMask(
size_t chunk_count, const uint8_t tag,
const uint8_t* BROTLI_RESTRICT tag_bucket, const size_t head) {
uint64_t matches = 0;
#if defined(SUPPORTS_SSE_2)
const __m128i comparison_mask = _mm_set1_epi8((char)tag);
size_t i;
for (i = 0; i < chunk_count && i < 4; i++) {
const __m128i chunk =
_mm_loadu_si128((const __m128i*)(const void*)(tag_bucket + 16 * i));
const __m128i equal_mask = _mm_cmpeq_epi8(chunk, comparison_mask);
matches |= (uint64_t)_mm_movemask_epi8(equal_mask) << 16 * i;
}
#else
const int chunk_size = sizeof(size_t);
const size_t shift_amount = ((chunk_size * 8) - chunk_size);
const size_t xFF = ~((size_t)0);
const size_t x01 = xFF / 0xFF;
const size_t x80 = x01 << 7;
const size_t splat_char = tag * x01;
int i = ((int)chunk_count * 16) - chunk_size;
BROTLI_DCHECK((sizeof(size_t) == 4) || (sizeof(size_t) == 8));
#if BROTLI_LITTLE_ENDIAN
const size_t extractMagic = (xFF / 0x7F) >> chunk_size;
do {
size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);
chunk ^= splat_char;
chunk = (((chunk | x80) - x01) | chunk) & x80;
matches <<= chunk_size;
matches |= (chunk * extractMagic) >> shift_amount;
i -= chunk_size;
} while (i >= 0);
#else
const size_t msb = xFF ^ (xFF >> 1);
const size_t extractMagic = (msb / 0x1FF) | msb;
do {
size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);
chunk ^= splat_char;
chunk = (((chunk | x80) - x01) | chunk) & x80;
matches <<= chunk_size;
matches |= ((chunk >> 7) * extractMagic) >> shift_amount;
i -= chunk_size;
} while (i >= 0);
#endif
matches = ~matches;
#endif
if (chunk_count == 1) return BrotliRotateRight16((uint16_t)matches, head);
if (chunk_count == 2) return BrotliRotateRight32((uint32_t)matches, head);
return BrotliRotateRight64(matches, head);
}
#undef SUPPORTS_SSE_2
#endif // THIRD_PARTY_BROTLI_ENC_MATCHING_TAG_MASK_H_
================================================
FILE: NanaZip.Codecs/Brotli/enc/memory.c
================================================
/* 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 "../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
================================================
FILE: NanaZip.Codecs/Brotli/enc/memory.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/metablock.c
================================================
/* 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 "../common/constants.h"
#include "../common/context.h"
#include "../common/platform.h"
#include "bit_cost.h"
#include "block_splitter.h"
#include "cluster.h"
#include "command.h"
#include "entropy_encode.h"
#include "histogram.h"
#include "memory.h"
#include "params.h"
#include "prefix.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
/* 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] =
BrotliBitsEntropy(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] = BrotliBitsEntropy(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] = BrotliBitsEntropy(
&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
================================================
FILE: NanaZip.Codecs/Brotli/enc/metablock.h
================================================
/* 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 "../common/context.h"
#include "../common/platform.h"
#include "block_splitter.h"
#include "command.h"
#include "histogram.h"
#include "memory.h"
#include "params.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define BROTLI_MAX_STATIC_CONTEXTS 13
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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/metablock_inc.h
================================================
/* 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] =
BrotliBitsEntropy(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 = BrotliBitsEntropy(
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] = BrotliBitsEntropy(
&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
================================================
FILE: NanaZip.Codecs/Brotli/enc/params.h
================================================
/* 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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/prefix.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/quality.h
================================================
/* 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 "../common/platform.h"
#include
#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: h58 (longest_match_simd ), b14, l4
- q05: h68 (longest_match64_simd ), b15, l5 | for large files
- q05: h40 (forgetful_chain ), b15, l4 | for small window
- q06: h58 (longest_match_simd ), b14, l4
- q06: h68 (longest_match64_simd ), b15, l5 | for large files
- q06: h40 (forgetful_chain ), b15, l4 | for small window
- q07: h58 (longest_match_simd ), b15, l4
- q07: h68 (longest_match64_simd ), 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) {
#if defined(BROTLI_MAX_SIMD_QUALITY)
hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 68 : 6;
#else
hparams->type = 6;
#endif
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. */
#if defined(BROTLI_MAX_SIMD_QUALITY)
hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 58 : 5;
#else
hparams->type = 5;
#endif
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/H68 --> 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 == 68) {
hparams->type = 65;
}
}
}
#endif /* BROTLI_ENC_QUALITY_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/ringbuffer.h
================================================
/* 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 "../common/platform.h"
#include "memory.h"
#include "params.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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/state.h
================================================
/* 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 "../common/constants.h"
#include "../common/platform.h"
#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_
================================================
FILE: NanaZip.Codecs/Brotli/enc/static_dict.c
================================================
/* 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"
#include "hash_base.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
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[Hash15(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[Hash15(&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[Hash15(&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[Hash15(&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
================================================
FILE: NanaZip.Codecs/Brotli/enc/static_dict.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/static_dict_lut.c
================================================
/* Copyright 2025 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. */
#include "static_dict_lut.h"
#include "../common/platform.h" /* IWYU pragma: keep */
#include "../common/static_init.h"
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
#include "../common/dictionary.h"
#include "../common/transform.h"
#include "hash_base.h"
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
/* TODO(eustas): deal with largest bucket(s). Not it contains 163 items. */
static BROTLI_BOOL BROTLI_COLD DoBrotliEncoderInitStaticDictionaryLut(
const BrotliDictionary* dict, uint16_t* buckets, DictWord* words,
void* arena) {
DictWord* slots = (DictWord*)arena;
uint16_t* heads = (uint16_t*)(slots + BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS);
uint16_t* counts = heads + BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS;
uint16_t* prev = counts + BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS;
size_t next_slot = 0;
uint8_t transformed_word[24];
uint8_t transformed_other_word[24];
size_t l;
size_t pos;
size_t i;
memset(counts, 0, BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS * sizeof(uint16_t));
memset(heads, 0, BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS * sizeof(uint16_t));
memset(prev, 0, BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS * sizeof(uint16_t));
for (l = 4; l <= 24; ++l) {
size_t n = 1u << dict->size_bits_by_length[l];
const uint8_t* dict_words = dict->data + dict->offsets_by_length[l];
for (i = 0; i < n; ++i) {
const uint8_t* dict_word = dict_words + l * i;
uint32_t key = Hash15(dict_word);
slots[next_slot].len = (uint8_t)l;
slots[next_slot].transform = BROTLI_TRANSFORM_IDENTITY;
slots[next_slot].idx = (uint16_t)i;
prev[next_slot] = heads[key];
heads[key] = (uint16_t)next_slot;
counts[key]++;
++next_slot;
}
for (i = 0; i < n; ++i) {
uint32_t key;
uint32_t prefix;
BROTLI_BOOL found;
size_t curr;
const uint8_t* dict_word = dict_words + l * i;
if (dict_word[0] < 'a' || dict_word[0] > 'z') continue;
memcpy(transformed_word, dict_word, l);
transformed_word[0] = transformed_word[0] - 32;
key = Hash15(transformed_word);
prefix = BROTLI_UNALIGNED_LOAD32LE(transformed_word) & ~0x20202020u;
found = BROTLI_FALSE;
curr = heads[key];
while (curr != 0) {
const uint8_t* other_word;
uint32_t other_prefix;
if (slots[curr].len != l) break;
other_word = dict_words + l * slots[curr].idx;
other_prefix = BROTLI_UNALIGNED_LOAD32LE(other_word) & ~0x20202020u;
if (prefix == other_prefix) {
if (memcmp(transformed_word, other_word, l) == 0) {
found = BROTLI_TRUE;
break;
}
}
curr = prev[curr];
}
if (found) continue;
slots[next_slot].len = (uint8_t)l;
slots[next_slot].transform = BROTLI_TRANSFORM_UPPERCASE_FIRST;
slots[next_slot].idx = (uint16_t)i;
prev[next_slot] = heads[key];
heads[key] = (uint16_t)next_slot;
counts[key]++;
++next_slot;
}
for (i = 0; i < n; ++i) {
const uint8_t* dict_word = dict_words + l * i;
BROTLI_BOOL is_ascii = BROTLI_TRUE;
BROTLI_BOOL has_lower = BROTLI_FALSE;
size_t k;
uint32_t prefix;
uint32_t key;
size_t curr;
BROTLI_BOOL found;
for (k = 0; k < l; ++k) {
if (dict_word[k] >= 128) is_ascii = BROTLI_FALSE;
if (k > 0 && dict_word[k] >= 'a' && dict_word[k] <= 'z')
has_lower = BROTLI_TRUE;
}
if (!is_ascii || !has_lower) continue;
memcpy(transformed_word, dict_word, l);
prefix = BROTLI_UNALIGNED_LOAD32LE(transformed_word) & ~0x20202020u;
for (k = 0; k < l; ++k) {
if (transformed_word[k] >= 'a' && transformed_word[k] <= 'z') {
transformed_word[k] = transformed_word[k] - 32;
}
}
key = Hash15(transformed_word);
found = BROTLI_FALSE;
curr = heads[key];
while (curr != 0) {
const uint8_t* other_word;
uint32_t other_prefix;
if (slots[curr].len != l) break;
other_word = dict_words + l * slots[curr].idx;
other_prefix = BROTLI_UNALIGNED_LOAD32LE(other_word) & ~0x20202020u;
if (prefix == other_prefix) {
if (slots[curr].transform == BROTLI_TRANSFORM_IDENTITY) {
if (memcmp(transformed_word, other_word, l) == 0) {
found = BROTLI_TRUE;
break;
}
} else if (slots[curr].transform ==
BROTLI_TRANSFORM_UPPERCASE_FIRST) {
if ((transformed_word[0] == (other_word[0] - 32)) &&
memcmp(transformed_word + 1, other_word + 1, l - 1) == 0) {
found = BROTLI_TRUE;
break;
}
} else {
for (k = 0; k < l; ++k) {
if (other_word[k] >= 'a' && other_word[k] <= 'z') {
transformed_other_word[k] = other_word[k] - 32;
} else {
transformed_other_word[k] = other_word[k];
}
}
if (memcmp(transformed_word, transformed_other_word, l) == 0) {
found = BROTLI_TRUE;
break;
}
}
}
curr = prev[curr];
}
if (found) {
continue;
}
slots[next_slot].len = (uint8_t)l;
slots[next_slot].transform = BROTLI_TRANSFORM_UPPERCASE_ALL;
slots[next_slot].idx = (uint16_t)i;
prev[next_slot] = heads[key];
heads[key] = (uint16_t)next_slot;
counts[key]++;
++next_slot;
}
}
if (next_slot != 31704) return BROTLI_FALSE;
pos = 0;
/* Unused; makes offsets start from 1. */
words[pos].len = 0;
words[pos].transform = 0;
words[pos].idx = 0;
pos++;
for (i = 0; i < BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS; ++i) {
size_t num_words = counts[i];
size_t curr;
if (num_words == 0) {
buckets[i] = 0;
continue;
}
buckets[i] = (uint16_t)pos;
curr = heads[i];
pos += num_words;
for (size_t k = 0; k < num_words; ++k) {
words[pos - 1 - k] = slots[curr];
curr = prev[curr];
}
words[pos - 1].len |= 0x80;
}
return BROTLI_TRUE;
}
BROTLI_BOOL BrotliEncoderInitStaticDictionaryLut(
const BrotliDictionary* dict, uint16_t* buckets, DictWord* words) {
size_t arena_size =
BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS *
(sizeof(uint16_t) + sizeof(DictWord)) +
BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS * 2 * sizeof(uint16_t);
void* arena = malloc(arena_size);
BROTLI_BOOL ok;
if (arena == NULL) {
return BROTLI_FALSE;
}
ok = DoBrotliEncoderInitStaticDictionaryLut(dict, buckets, words, arena);
free(arena);
return ok;
}
BROTLI_MODEL("small")
uint16_t kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS];
BROTLI_MODEL("small")
DictWord kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS];
#else /* BROTLI_STATIC_INIT */
/* Embed kStaticDictionaryBuckets and kStaticDictionaryWords. */
#include "static_dict_lut_inc.h"
#endif /* BROTLI_STATIC_INIT */
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
================================================
FILE: NanaZip.Codecs/Brotli/enc/static_dict_lut.h
================================================
/* 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 "../common/dictionary.h"
#include "../common/platform.h"
#include "../common/static_init.h"
#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;
/* Buckets are Hash15 results. */
#define BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS 32768
#define BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS 31705
#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
BROTLI_INTERNAL BROTLI_BOOL BrotliEncoderInitStaticDictionaryLut(
const BrotliDictionary* dictionary, uint16_t* buckets, DictWord* words);
BROTLI_INTERNAL extern BROTLI_MODEL("small") uint16_t
kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS];
BROTLI_INTERNAL extern BROTLI_MODEL("small") DictWord
kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS];
#else
BROTLI_INTERNAL extern const BROTLI_MODEL("small") uint16_t
kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS];
BROTLI_INTERNAL extern const BROTLI_MODEL("small") DictWord
kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS];
#endif
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif /* BROTLI_ENC_STATIC_DICT_LUT_H_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/static_dict_lut_inc.h
================================================
const BROTLI_MODEL("small")
uint16_t kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS] = {
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};
const BROTLI_MODEL("small")
DictWord kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS] = {
{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},{4,10,718},{7,0,
1689},{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},{7,10,1531},{8,10,416},{9,0,586},{9
,10,275},{10,10,100},{11,10,658},{11,10,979},{12,10,86},{13,0,468},{14,0,66},{14
,10,207},{15,10,20},{15,10,25},{144,0,58},{5,0,603},{5,10,915},{6,10,1783},{7,0,
1212},{7,10,211},{7,10,1353},{9,0,565},{9,10,83},{10,10,376},{10,10,431},{11,10,
543},{12,10,664},{13,10,280},{13,10,428},{14,0,301},{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},{6,11,198},{7,0,520},{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},{4,10,188},{7,10,805
},{143,0,78},{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},{8,10,770},{138,0,645},{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},{6,10,1658},{7,0,1621},{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},{6,10,1670},{
137,0,110},{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},{6,11,
240},{9,0,800},{10,0,693},{11,0,482},{11,0,734},{139,0,789},{4,0,116},{4,11,292}
,{4,11,736},{5,0,95},{5,0,445},{5,11,871},{6,11,171},{6,11,1689},{7,0,1688},{7,
11,1324},{7,11,1944},{8,0,29},{9,0,272},{9,11,415},{9,11,580},{11,0,509},{11,0,
915},{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},{6,11,63},{7,11,920},{136,0,41},{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}
,{9,11,790},{10,0,554},{11,0,83},{12,0,136},{12,11,47},{147,0,109},{138,10,661},
{4,0,963},{7,10,1945},{10,0,927},{142,0,442},{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},{12,11,314},{13,0,112},{13,0,361},{14,0,77},{14,0,78},{17,
0,28},{147,0,110},{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},{4,11,253},{5,0,188},{5,0,814},{5,10,410},{5,11,544},{7,11,300},{8,
0,10},{9,0,421},{9,0,729},{9,11,340},{10,0,609},{139,0,689},{134,0,624},{138,11,
321},{135,0,1941},{5,10,322},{8,10,186},{9,10,262},{10,10,187},{14,10,208},{146,
0,130},{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},{7,10,
1190},{137,0,620},{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},{5,10,63},{5,10,509},{6,0,1941},{136
,0,944},{132,0,629},{132,11,104},{4,0,246},{133,0,375},{4,10,288},{134,0,1636},{
135,11,1614},{8,10,89},{8,10,620},{9,0,49},{10,0,774},{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},{4,11
,619},{136,0,943},{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},{9,11,707},{11,0,326},{11,0,339},{11,11,326},{11,11,339},{12,0,423},{12,0,
502},{12,11,423},{12,11,502},{20,0,62},{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},{4,11,517},{7,0,1948},{135,0,2004},{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},{4,10,227},{5,10,159},{5,10,409},{7,10,80},{10,0,294},{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},{7,11,1148},{148,0,109},{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},{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,0,399
},{13,10,465},{14,0,337},{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,10,911},{5,11,
604},{136,10,278},{132,0,667},{4,10,151},{7,10,1567},{8,0,351},{137,0,322},{134,
0,902},{133,10,990},{5,10,194},{7,10,1662},{9,10,90},{140,0,180},{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},{9,10,662},{13,0,260},{14,0,82},{146,0,63},{
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},{4,11,439},{6,0,565},{7,0,1667},{10,10,95},{11,10,
603},{12,11,242},{13,10,443},{14,10,160},{143,10,4},{134,0,1464},{134,10,431},{5
,10,874},{6,10,1677},{9,0,372},{15,0,2},{15,10,0},{19,0,10},{147,0,18},{132,0,
787},{6,0,380},{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},{12,0,399},{13,10,438},{149,0,19},{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},{4,10,726},{5,0,684
},{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},{4,10,120},{142,0,314},{132,0,983},{5,0,193},{140
,0,178},{138,10,429},{5,10,820},{135,10,931},{5,11,732},{6,0,994},{6,0,1051},{6,
0,1439},{135,0,174},{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},{
6,10,1624},{11,0,583},{12,10,422},{13,0,262},{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},{5,10,888},{135,0,352},{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},{4,10,65},{5,10,479},{5,10,1004},{7,10,1913},{8,0,719},{8,10,317
},{9,10,302},{10,10,612},{141,10,22},{4,0,5},{4,10,261},{4,11,213},{5,0,498},{7,
10,510},{7,11,223},{8,0,637},{8,11,80},{137,0,521},{4,10,291},{5,0,927},{7,0,101
},{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,10,443}
,{12,11,162},{13,10,392},{13,11,75},{14,10,357},{14,11,106},{14,11,198},{14,11,
320},{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},{5,10,42},{5,10,879},{6,0,1296},{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},{4,10,644},{5,0,806},{7,0,176},{7,0,178},{7,0,1240},{135,0,1976},{
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},{4,10,238},{5,10,503},{6,10,179},{7,10,2003},{8,10,381},{8,10,473},{9
,10,149},{10,0,183},{10,10,788},{15,10,45},{15,10,86},{20,10,110},{150,10,57},{4
,10,121},{5,10,156},{5,10,349},{9,0,136},{10,10,605},{14,10,342},{147,0,107},{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},{6,10,459},{7,0,502},{7,0,519},{7,0,
1122},{7,0,1751},{7,10,1753},{7,10,1805},{8,10,658},{9,10,1},{11,10,959},{13,10,
446},{142,0,211},{4,11,470},{5,11,473},{6,0,814},{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},{4,10,140},{7,10,362},{8,10,209}
,{9,0,327},{9,10,10},{9,10,503},{9,10,614},{10,10,689},{11,0,350},{11,0,831},{11
,10,327},{11,10,725},{12,10,252},{12,10,583},{13,0,352},{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
},{7,10,197},{8,10,142},{8,10,325},{9,10,150},{9,10,596},{10,0,557},{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},{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,0,19},{18,10,25},{21,10,14},{22,10,12},{151,10,18},{7,10,1546},{11,10,299},{
12,0,459},{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},{5,10,242},{7,0,1744},{8,0,602},{11,0,247},{11,0,826},{
145,0,65},{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,10,1811},{135,11,435},{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},{4,10,38},{6,0,256},{7,10,307},{7,10,999},{7,10,1481},{7,
10,1732},{7,10,1738},{8,0,265},{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},{4,11,154},{5,10,109},{6,10,
1784},{7,10,1895},{7,11,1134},{8,11,105},{12,0,522},{12,10,296},{140,10,302},{4,
11,31},{6,11,429},{7,11,962},{9,11,458},{139,11,691},{4,11,312},{5,10,216},{7,10
,1879},{9,10,141},{9,10,270},{9,10,679},{10,0,553},{10,10,159},{11,0,876},{11,10
,197},{12,10,538},{12,10,559},{13,0,193},{13,0,423},{14,0,166},{14,10,144},{14,
10,167},{15,10,67},{147,0,84},{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},{7,10,948},{7,10,1042},{8,10,235},{8,10,461},{9,0,530},{9,10,
453},{10,10,354},{17,10,77},{147,0,99},{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
},{7,10,1912},{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},{148,0,105},{4,11,71},{5,11,376},{7,11,119},{138,11,665},{4
,10,686},{8,11,55},{10,0,918},{138,0,926},{138,10,625},{136,10,706},{132,11,479}
,{4,10,30},{133,10,43},{6,0,379},{7,0,270},{7,11,607},{8,0,176},{8,0,183},{8,11,
99},{9,0,432},{9,0,661},{12,0,247},{12,0,617},{18,0,125},{152,11,4},{5,0,792},{
133,0,900},{4,11,612},{133,11,561},{4,10,220},{4,11,41},{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},{6,10,178},{6,10,1750},{6,11,289},{7,11,1670},{8,0,440},
{9,10,690},{10,0,359},{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},{6,10,324},{6,10,520},{7,0,1616},{7,10,338},{7,10,1729},{8,10,228}
,{9,0,69},{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},{4,10,73},{6,10,612},{7,10,
927},{7,10,1330},{7,10,1822},{8,10,217},{9,0,472},{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},{5,10,389},{8,10,636},{137
,0,229},{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},{4,11,
685},{5,0,172},{134,0,1971},{149,11,8},{133,11,797},{5,10,189},{7,10,442},{7,10,
443},{8,10,281},{12,10,174},{13,0,83},{141,10,261},{134,0,1568},{133,11,565},{
139,0,384},{133,0,260},{6,10,2},{7,0,758},{7,0,880},{7,0,1359},{7,10,1262},{7,10
,1737},{8,10,22},{8,10,270},{8,10,612},{9,0,164},{9,0,167},{9,10,312},{9,10,436}
,{10,0,156},{10,0,588},{10,10,311},{10,10,623},{11,10,72},{11,10,330},{11,10,455
},{12,0,101},{12,10,321},{12,10,504},{12,10,530},{12,10,543},{13,10,17},{13,10,
156},{13,10,334},{14,0,48},{15,0,70},{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},{6,10,166},{7,0,1174},{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},{9,11,
744},{138,0,620},{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},{6,11,584},{7,0,1249},{139,0,896},{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},{5,11,860},{
135,0,508},{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},{4,11,396},{7,0,570},{7,10,120},{7,11,728},{8,10,489},{9,10,319
},{9,11,117},{10,10,820},{11,10,1004},{12,10,379},{12,10,679},{13,10,117},{13,10
,412},{13,11,202},{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},{4,10,937},{5,10,801},{8,0,449},{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},{13,11,463},{20,0,49},{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},{7,10,27},{7,
10,316},{140,0,257},{140,0,1003},{4,0,207},{5,0,586},{5,0,676},{5,10,552},{6,0,
448},{8,0,244},{11,0,1},{13,0,3},{16,0,54},{17,0,4},{146,0,13},{4,10,401},{137,
10,264},{5,0,516},{7,0,1883},{135,11,1883},{4,11,894},{140,0,960},{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},{9,10,543},{10,10,524},{11,0,
30},{12,10,524},{14,0,315},{16,10,18},{20,10,26},{148,10,65},{4,10,205},{5,10,
623},{6,0,748},{7,10,104},{136,10,519},{11,0,542},{139,0,852},{140,0,6},{132,0,
848},{7,0,1385},{7,10,579},{9,10,41},{9,10,244},{9,10,669},{10,10,5},{11,0,582},
{11,0,650},{11,0,901},{11,0,949},{11,10,861},{11,10,951},{11,10,980},{12,0,232},
{12,0,236},{13,0,413},{13,0,501},{146,0,116},{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},{7,10,819},{7,11,481},{9,10,26},{9,10,
392},{9,11,792},{10,10,152},{10,10,226},{11,0,64},{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},{4,10,251},{4,10,688},{7,10,513},{
7,10,1284},{9,0,87},{138,0,365},{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},{5,10,731},{135,0,986},{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},{5,10,633},{6,0,279},{7,0,219},{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},{7,11,709},{11,0,934},{13,0,391},{145
,0,76},{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},{7,11,1652},{9,0,982},{15,0,173},{15,0,178},{15,0,200},{18,0,189},{18,0,
207},{149,0,47},{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},{4,11,579},{5,11,226
},{5,11,323},{7,11,960},{9,0,790},{140,0,47},{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},{5,10,985},{7,0,897},{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},{6,10,337},{7
,0,243},{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},{9,10,869},{138,0,728},{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},{8,10,203},{11,10,823},{11,10,846},{12,10,482},{13,0,133},{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,10,758},{10,11,233},{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},{5
,10,977},{6,0,305},{7,0,775},{135,0,1065},{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
},{4,10,275},{6,0,214},{7,10,1219},{12,0,540},{140,10,376},{8,0,667},{11,0,403},
{146,0,83},{10,11,648},{11,11,671},{12,0,74},{143,11,46},{135,0,125},{134,10,
1753},{133,0,761},{4,11,518},{6,0,912},{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},{7,10,657},{136,0,103},{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},{4,11,267},{
134,0,869},{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},{5,10,291},{5,10,318},{7,10,765},{9,10,389},{12,10,548},{147,0,121},{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},{5,11,594
},{135,0,346},{133,10,865},{5,10,914},{134,10,1625},{135,0,334},{5,0,795},{5,10,
234},{134,0,1741},{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},{15,11,29},{16,0,38},{144,11,38},{5,0,338},{135,0,
1256},{135,10,1493},{6,10,421},{7,10,61},{7,10,1540},{10,0,130},{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},{6,10,102},{7,0,311},{7,10,72},{9,0,308},{12,0,255},{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},{7
,11,1946},{8,10,48},{8,10,88},{8,10,582},{8,10,681},{9,10,373},{9,10,864},{11,0,
690},{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},{4,10,938},{135,0,1831},{6,0,776},
{134,0,915},{138,10,351},{5,11,348},{6,10,1668},{6,11,522},{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},
{4,10,44},{5,10,311},{6,0,463},{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},{7,11,140
},{7,11,1950},{8,0,296},{8,11,680},{11,11,817},{147,11,88},{7,11,1222},{138,11,
386},{142,0,137},{132,0,454},{6,11,5},{7,0,1914},{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},{4,10,327},{5,10,478},{7,10,1332},{8,10,753},{140,0,227},{5,10,1020},{5,10,
1022},{134,0,1491},{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},{7,11,1837},
{10,0,62},{141,0,400},{140,0,207},{135,0,869},{4,11,773},{5,11,618},{137,11,756}
,{132,10,96},{4,0,213},{7,0,223},{7,10,968},{136,0,80},{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},{5,11,81},{7,0,366},{7,11,146},{7,11,1342},{
7,11,1446},{8,11,53},{8,11,561},{8,11,694},{8,11,754},{9,0,287},{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,0,199},{12,0,556},{12,0,577},{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},{8,10,528},{9,0,567},{9,
10,348},{11,0,150},{11,0,444},{141,0,119},{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},{5,11,762},{6,0,359},{7,11,1880},{9,
11,680},{11,0,3},{11,11,798},{13,0,108},{14,0,89},{144,0,22},{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},{7,11,237},{8,0,349},{8,11,664},{9,0,100},{9,11,42}
,{9,11,266},{9,11,380},{9,11,645},{10,0,677},{10,11,177},{10,11,276},{14,0,169},
{14,0,302},{14,0,313},{15,0,48},{143,0,84},{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},{4,10,40},{5,0,587},{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},{4,11,704},{5,0,539},{5,0,754},{134,0,876},{135,11,
1078},{5,10,92},{10,10,736},{140,10,102},{5,10,590},{9,10,213},{145,0,91},{134,0
,1565},{6,0,91},{135,0,435},{4,0,939},{140,0,792},{134,0,1399},{4,0,16},{4,11,
720},{5,0,316},{5,0,842},{5,11,306},{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},{149,0,21},{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},{6,10,466},{135,0,671},{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,10,406},{5,
11,34},{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},{4,10,520},{5,0,308},{7,0,1088},{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,10,676},{7,11,196},{8,
10,443},{8,10,609},{9,10,24},{9,10,325},{10,10,35},{10,11,765},{11,10,535},{11,
10,672},{11,10,1018},{11,11,347},{11,11,552},{11,11,576},{11,11,790},{12,10,637}
,{12,11,263},{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},{5,10,981},{138,0,509},{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,10,1791},{7,11,616},{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,10,369},{4,11,352},
{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},{6,10,622},{135,0,1030},{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},{10,11,438},{12,0,648},{12,0,649},{14,0,455},{144,0,112},{137,0,203},
{134,10,292},{134,0,1492},{5,10,177},{6,10,616},{7,0,1374},{7,10,827},{8,0,540},
{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},{9,10,469},{9,10,709},{11,0,990},{12,0,235},{12,0,453},{12,10,
512},{13,0,47},{13,0,266},{14,10,65},{145,10,12},{10,10,229},{11,0,807},{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},{4,11,535},{6,0,121},{6,0,124},{
6,0,357},{6,10,558},{7,0,1138},{7,0,1295},{7,10,651},{8,0,162},{8,0,508},{8,11,
618},{9,10,0},{10,10,34},{11,0,655},{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
},{5,11,811},{6,0,1536},{6,11,1679},{6,11,1714},{7,11,2032},{138,0,348},{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},{4,10,185},{5,10,257},{5,10,839},{5,10,936},{7,0,171},{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},{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,0,588},{11,0,864},{11,0,936},{11,0,968},{11,10,239},{11,10,295},{11,10
,447},{11,10,528},{11,10,639},{11,10,800},{12,0,73},{12,0,343},{12,0,394},{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,0,275},{13,10,50},{13,10,53},{13,10,132},{
13,10,198},{13,10,322},{13,10,415},{13,10,511},{14,0,257},{14,10,71},{14,10,395}
,{15,0,160},{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},{4,10,171},{6,0,1346},{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},{7,11,1276},{8,0,16},{8,11,474},{9,0,825},{9,11,652},{
140,0,568},{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},{10,10,508},{146,0,97},{7,11,1454},{10,0,703},{
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},{6,10,209},{8,10,468},{9,0,162},{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},{7,10,915},{8,10,247},{9,0,628},{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},{6,10,445},{7,0,332},{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},{4,11,620},{6,0,
1993},{138,11,280},{136,0,769},{7,11,1810},{11,0,290},{11,0,665},{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},{4,10,226},{7,0,1874},{137,0,641},{5,10,426},{6,0,644},{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,10,1259},
{7,11,353},{7,11,1523},{9,10,125},{139,10,65},{5,10,136},{6,0,325},{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},{7,10,1768},{137,0,76},{132,11,757},{5,0,29},{140,0,638}
,{7,11,655},{135,11,1844},{6,11,257},{7,0,1418},{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},{4,10,902},{5,10,809},{6,
10,122},{135,0,896},{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},{5,10,620},{134,0,1709},{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},{4,11,625},{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},{144,0,24},{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},{
4,10,137},{6,0,1827},{7,10,1178},{7,10,1520},{7,11,1319},{10,0,931},{18,0,166},{
148,0,114},{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},{5,10,89},{7,10,1915},{9,0,496},{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},{4,10,494},{6,10,74},{7,0,
562},{7,10,44},{8,0,551},{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},{5,10,872},{6,0,479},{6,0,562},{6,10,57},{7,0,1060},{7,
10,471},{9,10,447},{9,10,454},{141,0,6},{136,11,413},{145,11,19},{4,11,117},{6,
11,372},{7,11,1905},{142,11,323},{4,11,722},{139,11,471},{5,10,31},{6,10,614},{
145,0,61},{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},{7,10,1071},{7,10,1541},{7,10,1767},{7,10,1806},{11,0
,178},{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},{8,10,1},{9,0,112},{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},{5,11,32},{6,0,1352},{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},{4,10,424},{5,0,433},{9,0,633},{139,0,629},{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},{4,11,410},{5,0,545},{7,0,754},{7,11,521},{9,
0,186},{10,0,72},{10,0,782},{11,0,577},{11,0,610},{11,0,960},{12,0,354},{12,0,
362},{140,0,595},{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},{4,10,563},{7,0,251},{7,0,1701},{7,
10,592},{7,10,637},{7,10,770},{8,0,436},{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},{7,11,899},{9,0,688},{10,
0,522},{11,0,788},{12,0,137},{12,0,566},{14,0,9},{14,0,24},{14,0,64},{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},{4,10,309},{5,10,462},{7,10,970}
,{7,10,1097},{139,0,292},{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},{5,10,86},{7,10,743},{9,10,85
},{10,10,281},{10,10,432},{11,0,490},{12,10,251},{13,10,118},{14,10,378},{146,0,
143},{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},{12,10,670},{13,0,
248},{13,0,371},{14,0,142},{146,10,94},{134,0,721},{4,11,113},{5,11,163},{5,11,
735},{7,10,1149},{7,11,1009},{9,10,156},{9,11,9},{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},{4,11,935},{5
,11,823},{135,0,1596},{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},{
6,11,1713},{8,0,4},{9,0,39},{10,0,166},{11,0,918},{12,0,635},{20,0,10},{22,0,27}
,{22,0,43},{150,0,52},{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},{4,10,732},{
137,0,859},{7,0,1846},{136,0,628},{136,10,733},{133,0,762},{4,10,428},{135,10,
1789},{7,10,2015},{10,0,784},{12,10,665},{141,0,191},{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},{6,10,1623},{6,10,1681},{7,0,845},{8,0,
160},{137,0,318},{134,0,1447},{134,0,1255},{138,0,735},{4,11,168},{136,0,76},{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},{4,10,63},{5,10,347},{134,0,474},{133,10,749}
,{138,0,841},{133,10,366},{4,11,225},{134,0,836},{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,10
,977},{7,11,956},{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},{6,11,464},{135,0,1078},{6,11,509},{10,11,82},{20,11,91}
,{151,11,13},{4,0,720},{133,0,306},{133,0,431},{4,10,914},{5,10,800},{5,10,852},
{135,0,1196},{135,11,1189},{10,0,54},{141,10,115},{7,10,564},{142,10,168},{4,10,
918},{5,0,464},{5,10,876},{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},{
145,0,41},{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},{5,10,272},{5,10,908},{5,10,942},{6,0,675},{7
,0,1008},{7,0,1560},{8,10,197},{9,0,642},{9,10,47},{11,0,236},{11,10,538},{11,10
,742},{142,0,193},{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},{5,11,5},{10,0,648},{11,0,671},{
143,0,46},{133,0,928},{4,10,475},{11,0,90},{11,10,35},{13,0,7},{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},{6,10,222},{7,10,1620},{8,10,409},{9,10,693},{
139,0,300},{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},{7,11,1897},{8,0,610},{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},{6,10,58},{7,0,654
},{7,10,745},{7,10,1969},{8,0,240},{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},{6,10,48},{7,0,952},{
9,10,139},{10,10,399},{11,10,469},{12,10,634},{141,10,223},{133,0,673},{7,11,8},
{8,11,206},{137,0,850},{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},{7,11,1297},{9,0,279},{10,0,407},{14,0,84},{150,0,18},{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},{7,10,56},{7,10,1989},{8,10,337},{8,10,738},{9,10,600},{
10,0,483},{12,0,368},{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},{11,11,194},{12,0,62},{12,0,88},{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},{5,10,540},{6,10,1697},{7,0,222},{136,0
,341},{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},{4,10,511},{6,10
,608},{9,0,683},{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},{5,11,249},{8,0,618},{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},{4,10,
500},{135,0,938},{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,10,244},{6,11,132},{7,10
,40},{7,10,200},{7,10,906},{7,10,1199},{7,11,128},{7,11,283},{7,11,1299},{9,10,
616},{10,10,716},{10,11,52},{10,11,514},{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},{5,10,598
},{7,10,791},{8,0,525},{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},{6,11,588},{9,0,936},{15,0,214},{18,0,199},{152,0,26},
{4,11,284},{6,11,223},{7,0,1462},{139,0,659},{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,10,70},{13,11,9}
,{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},{12,10,610},{13,10,431},{16,10,59},{
146,0,109},{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},{5,10,964},{136,0,68},{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,10,649},{5,11,69},{
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},{6,10,225
},{7,0,1978},{8,0,676},{137,10,211},{7,0,972},{8,10,687},{139,0,102},{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},{6,11
,1667},{7,0,1780},{7,11,2036},{9,0,230},{10,11,600},{11,0,297},{11,0,558},{14,0,
322},{147,0,76},{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},{4,11,922},{5,11,1023},{6,0
,842},{134,0,1400},{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},{5,10,181},{6,0,247},{8,10,41},{137
,0,555},{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},{4,10,206},{135,0,746},{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},{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,0,230},{13,10,361},{14,10,77},
{14,10,78},{17,0,113},{147,10,110},{4,0,792},{4,10,769},{7,0,1717},{138,0,546},{
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},{5,11,254},{6
,0,1157},{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},{4,11,321},{6,0,889},{6,0,1067},{6,0,1183},{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},{4,10,282},{7,10,1034},{9,0,820},{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},{4,11,45},{7,0,1325},{135,11,1257},{138,0,301},{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,0,298}
,{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,0,291},{12,10,27},{12,10,131},{12,10,245},{12,10,312},{12,
10,446},{12,10,454},{13,0,276},{13,10,98},{13,10,426},{13,10,508},{14,0,6},{14,
10,163},{14,10,272},{14,10,277},{14,10,370},{15,10,95},{15,10,138},{15,10,167},{
17,0,18},{17,10,38},{20,10,96},{149,0,32},{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},{7,10,1948},{7,10,
2004},{8,0,329},{136,0,414},{5,0,517},{6,10,439},{7,10,780},{135,10,1040},{132,0
,816},{5,10,1},{6,10,81},{138,10,520},{5,10,482},{8,10,98},{9,0,713},{10,0,222},
{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,10,
129},{10,10,225},{10,11,108},{11,10,118},{11,10,226},{11,10,251},{11,10,430},{11
,10,701},{11,10,974},{11,10,982},{11,11,116},{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},{4,10
,12},{7,0,420},{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},{4,10,39},{5,0,173},{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},{7,10,1980},{
10,10,487},{10,10,809},{11,0,164},{12,0,76},{146,0,9},{12,0,111},{13,10,260},{14
,0,294},{18,10,63},{147,0,45},{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},{4,11,523},{5,11,638},{8,0,87},{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},{4,10,10},{7,0
,1802},{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},{6,10,1718},{7,0,375},{137,0,438},{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},{5,10,193},{8,0,782},{12,10,178},{13,0
,130},{145,0,84},{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},{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,0,356},{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},{5,11,414},{7,0,629},{7,0,1698},{7,0,1711},{140,0,
215},{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},{10,10,592},{10,10,753},{12,10,317},{12,10,355},{12,10,
465},{12,10,469},{12,10,560},{12,10,578},{141,0,318},{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},{12,11,229},{12,11,239},{15,0,12},{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}
,{5,10,238},{135,0,1350},{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},{4,10,60},{5,0,710},{7,0,760},{7,0,1926},{7,10,1800},{8,10,314},{9,0,428},{
9,0,708},{9,10,700},{10,0,254},{10,0,296},{10,0,720},{11,0,109},{11,0,255},{11,
10,487},{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},{150,0,17},{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},{5,10,828},{135,0,521
},{134,0,673},{7,0,1110},{7,0,1778},{7,10,176},{135,10,178},{5,10,806},{7,10,
1976},{7,11,268},{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},{4,10,51},{5,0,341},{6,10,4},{7,0,1129
},{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,0,414},{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,10,340},{7,10,867},{7,
11,306},{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},{5,
10,757},{138,0,916},{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},{5,10,265},{6,10,212},{135,0,460},{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},{5,10,808},{7,0,434},{7,0,891},{7,10,2045},{
8,0,339},{9,0,702},{11,0,594},{11,0,718},{145,0,100},{7,0,1014},{9,0,485},{141,0
,264},{134,0,1713},{7,0,1810},{11,0,866},{12,0,103},{12,11,233},{141,0,495},{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},{5,11,458},{134,0,
1099},{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},{7,10,
1104},{8,0,82},{11,0,250},{11,0,607},{11,10,269},{11,10,539},{11,10,627},{11,10,
706},{11,10,975},{12,0,311},{12,0,420},{12,10,248},{12,10,434},{12,10,600},{12,
10,622},{13,0,184},{13,0,367},{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,10,484},{11,11,53
},{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},{5,11,907},{134,0,2037},{6,10,1700},{7,0,373},{7,10,
293},{7,10,382},{7,10,1026},{7,10,1087},{7,10,2027},{8,0,335},{8,0,596},{8,10,
252},{8,10,727},{8,10,729},{9,0,488},{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},{6,10,379},{7,0,1116},{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},{5,11,1002
},{7,0,902},{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},{7,10,1952},{139,0,156},{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},{6,11,473},{12,0,554},{145,11,105},{
133,0,784},{8,0,908},{136,11,306},{139,0,882},{6,0,358},{7,0,1393},{7,11,1759},{
8,0,396},{8,11,396},{10,0,263},{10,11,263},{14,0,154},{14,11,154},{16,0,48},{16,
11,48},{17,0,8},{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},{8,10,167},{8,10,375},{9,10,82},{9,
10,561},{10,0,770},{138,10,620},{132,0,845},{9,0,14},{9,0,441},{10,0,306},{139,0
,9},{8,10,194},{8,10,756},{11,0,966},{12,0,287},{13,0,342},{13,0,402},{15,0,110}
,{143,0,163},{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},{7,11,883},{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},{149,0,22},{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},{4,11,587},{134,0,1338
},{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},{6,10
,310},{7,10,1849},{8,10,72},{8,10,272},{8,10,431},{9,0,351},{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,10,244},{4,11,217},{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},{5,10,4},{
5,10,810},{6,10,13},{6,10,538},{6,10,1690},{6,10,1726},{7,0,1059},{7,10,1819},{8
,10,148},{8,10,696},{8,10,791},{12,10,125},{13,0,54},{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,10,1385},{7,11,345},{9,11,94},{11
,10,582},{11,10,650},{11,10,901},{11,10,949},{12,10,232},{12,10,236},{12,11,169}
,{13,10,413},{13,10,501},{146,10,116},{4,0,917},{133,0,1005},{5,11,183},{6,11,
582},{7,0,1598},{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},{5,11,704},{8,11,357},{10,11,745},
{14,11,426},{17,11,94},{19,0,65},{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
},{7,10,572},{9,10,592},{11,0,842},{11,0,924},{11,10,680},{12,10,356},{12,10,550
},{13,0,317},{13,0,370},{13,0,469},{13,0,471},{14,0,397},{18,0,69},{146,0,145},{
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},{4,11,248},{5
,0,192},{6,0,332},{7,0,1322},{7,11,137},{137,11,349},{140,0,661},{7,0,1517},{7,
10,748},{11,0,597},{11,10,700},{14,0,76},{14,0,335},{148,0,33},{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},{5,10,276},{6,10,55},{7,0,379},{7,10,1369},{8,0,
481},{137,0,377},{138,11,286},{5,0,1003},{6,0,149},{6,10,1752},{136,10,726},{6,
11,1647},{7,11,1552},{7,11,2010},{8,0,262},{9,0,627},{9,11,494},{9,11,509},{10,0
,18},{11,0,214},{11,0,404},{11,0,457},{11,0,780},{11,0,913},{13,0,401},{142,0,
200},{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,10,986},{7,11,214},{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},
{5,10,24},{5,10,569},{6,10,3},{6,10,119},{6,10,143},{6,10,440},{7,0,929},{7,10,
599},{7,10,1686},{7,10,1854},{8,10,424},{9,10,43},{9,10,584},{9,10,760},{10,0,
452},{10,10,328},{11,0,878},{11,10,159},{11,10,253},{12,10,487},{12,10,531},{144
,0,33},{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},{6,11,219},{135,0,865},{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},{5,11,851},{6,0,
42},{7,0,1416},{7,0,2005},{8,0,131},{8,0,466},{9,0,672},{13,0,252},{148,0,103},{
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},{6,10,573},{140,0,132},{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},{4,10,292},{4,10,736},{5,10,871},{6,0,171},{6,10,1689},{
7,0,1002},{7,0,1324},{7,10,1944},{9,0,415},{9,10,580},{14,0,230},{146,0,68},{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},{5,10,67},{6,10,62},{6,10,374},{7,10,1391},{8,0,691
},{136,0,731},{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},{7,11,
610},{7,11,1501},{136,0,888},{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},{6,10,36},{7,10,658},{8,10,454},{147,0,86},{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},{7,
10,988},{7,10,1939},{9,10,64},{9,10,502},{12,0,7},{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},{5,10,761},{134,0,672},{9,0,157},{10,
10,131},{140,10,72},{6,11,460},{135,0,714},{134,0,456},{133,0,925},{5,11,682},{
135,11,1887},{136,11,510},{136,11,475},{133,11,1016},{7,11,602},{8,11,179},{9,0,
19},{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},
{8,10,103},{145,0,69},{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},{7,10,1274},{7,10,1386},{7,11,2008},{9,11,337},{10,11,517},{12,
0,129},{146,10,87},{6,10,187},{7,0,803},{7,10,1203},{8,0,542},{8,10,380},{14,10,
117},{149,10,28},{6,10,297},{7,10,793},{139,10,938},{7,10,464},{8,0,438},{11,0,
363},{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},{4,11,486},{5,11,491},{134,0,717},{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},{7,10,1010},{11,10,733},{11,10,759}
,{12,0,563},{13,10,34},{14,0,101},{18,0,129},{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},{5,10,20},{6,0,1116},{6,10,298},{6,11,197},{7,0,1366},{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},{4,10,439},{140,0,242},{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},{9,11,106},{9,11,
163},{9,11,296},{10,11,167},{10,11,172},{10,11,777},{11,11,16},{14,0,438},{14,0,
444},{14,0,456},{22,0,60},{150,0,63},{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},{4,10,100},{7,0,
679},{7,11,821},{136,0,313},{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},{5,10,55},{7,0,1639},{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},{8,11,146},{16,0,94},{144,0,108},{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},{5,11,559},{9,0,194},{10,0,92},{11,0,198},{12,0,84},{141,0,128},{6,11,
21},{6,11,1737},{7,11,1444},{8,11,224},{10,0,57},{138,0,277},{4,10,204},{137,10,
902},{136,10,833},{7,10,366},{9,10,287},{11,0,348},{12,0,99},{12,10,199},{12,10,
556},{12,10,577},{18,0,1},{18,0,11},{147,0,4},{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,10,384},{6,11,11},{7,10,583},{7,11,187},{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},{4,10,470},{5,0,
473},{6,10,153},{7,10,1503},{7,10,1923},{10,10,701},{11,0,168},{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},{5
,10,80},{6,10,405},{7,0,1626},{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},{6,11,336},{8,11,552},{9
,0,99},{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},{5,10,101},{5,11,256},{6,0,543},{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},{4,10,456},{7,0,1445},{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},{5,11,396},{6,0,447},{
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},{7,10,619},{10,0,687},{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},{7,11,1461}
,{12,11,91},{145,0,17},{4,10,236},{132,11,602},{138,0,907},{136,0,110},{5,10,836
},{5,10,857},{6,10,1680},{7,0,272},{147,0,53},{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},{10,10,68},{11,0,
656},{11,0,998},{11,10,494},{18,0,0},{18,0,2},{147,0,21},{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},{5,10,282},{8,10,650},{9,0,
295},{9,10,907},{138,0,443},{132,11,735},{4,10,775},{4,11,170},{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},{11,10,827},{12,0,56},{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},{4,10,182},{6,10,205},{7,10,220},{136,0,722},{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},{9,10
,307},{139,0,68},{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},{5,10,493},{134,0,528},{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},{5,10,126},{8,10,297},{9,0,445},{9,10,366},{12,0,53},{12,10
,374},{141,0,492},{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,10,1068},{7,11,299},{7,11,
1666},{8,11,195},{8,11,316},{9,11,178},{9,11,276},{9,11,339},{9,11,536},{10,10,
434},{10,11,102},{10,11,362},{10,11,785},{11,10,228},{11,10,426},{11,11,55},{11,
11,149},{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},{5,10,231},{7,0,1602},{7,10,601},{
9,10,277},{9,10,674},{10,0,257},{10,0,698},{10,10,178},{10,10,418},{10,10,509},{
11,0,544},{11,0,585},{11,10,531},{12,0,212},{12,10,113},{12,10,475},{13,0,307},{
13,10,99},{142,10,428},{6,0,473},{145,0,105},{5,11,645},{6,0,1949},{143,0,156},{
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},{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,0,186},{12,0,292},{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,0,100},{14,10,63},{14,10,380},{14,10,384}
,{15,10,133},{18,0,70},{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},{9,11,534},{10,0,598},{10,0,769},{11,0,134
},{11,0,747},{12,0,378},{142,0,97},{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},{6,10,422},{7,10,0
},{7,10,1544},{8,11,364},{9,0,577},{11,10,990},{12,0,141},{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,10,571},{7,10,1877},{7
,11,342},{10,10,366},{141,11,23},{133,11,641},{9,10,513},{10,0,22},{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},{11,10,588},{11,10,864},{11,10,968},{15,0,145},{15,
10,160},{17,0,34},{19,0,50},{151,0,20},{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},{4,10,894},{
133,0,435},{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},{6,10,272},{7,0,1993},{136,0,684},{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},{7,11,166},{8,0,
181},{138,0,711},{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},{6,11,273},{7
,0,1593},{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},{8,10,398},{9,0,422},{
9,0,670},{9,10,681},{10,0,775},{10,0,894},{10,0,909},{10,0,910},{10,0,935},{11,0
,210},{11,10,632},{12,0,750},{12,0,755},{13,0,26},{13,0,457},{13,0,476},{16,0,
100},{16,0,109},{18,0,173},{146,0,175},{9,11,417},{137,11,493},{136,10,645},{138
,0,906},{134,0,1730},{134,10,20},{133,11,1019},{134,0,1185},{8,10,769},{138,0,40
},{6,11,208},{137,0,147},{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}
,{7,10,1652},{16,0,49},{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,10,973},{133,11,679},{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},{6
,10,281},{7,0,318},{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},{14,11,324},{15,0,55},{15,0,80},{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},{5,10,29},{7,0,1764},{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},{4,10,17},{5,10,23},{6,0,129},{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},{6,10,442},{135,0,1397},{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
,10,596},{10,11,486},{11,11,13},{11,11,381},{11,11,736},{11,11,766},{11,11,845},
{13,10,218},{13,11,114},{13,11,292},{14,10,153},{142,11,47},{7,11,759},{140,0,
693},{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},{5,10,87},{7,10,313},{7,10,1103},{10,0,112},{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,10,760},{4,11,656},{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},{6,11,248},{8,0,863},{8,0,864},{8,0,868},{8,0,884},{9
,11,546},{10,0,866},{10,0,868},{10,0,873},{10,0,911},{10,0,912},{10,0,944},{10,
11,535},{11,11,681},{12,0,727},{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},{4,10,392},{5,0,751},{7,10,1597},{8,0,266},{139,0,578},{5,10,433},{9,10,633}
,{139,10,629},{135,0,821},{6,0,715},{134,0,1325},{133,11,116},{4,11,457},{134,0,
868},{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},{6,10,5},{7,0,1595},{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},
{4,10,90},{5,0,337},{5,10,545},{7,10,754},{9,10,186},{10,10,72},{10,10,782},{11,
0,513},{11,0,889},{11,0,961},{11,10,577},{11,10,610},{12,0,461},{12,10,354},{12,
10,362},{12,10,595},{13,0,79},{143,0,121},{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}
,{9,10,187},{10,0,299},{11,10,1016},{17,10,44},{146,0,74},{4,10,506},{7,0,165},{
7,0,919},{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
},{4,11,648},{6,0,82},{6,10,1775},{7,0,138},{7,0,517},{7,0,1741},{139,0,238},{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},{7,10,1283},{9,0,499},{9,10,227},{10,0,341},{11,10,325},{11,10,408},
{14,10,180},{15,0,144},{18,10,47},{147,0,49},{6,0,21},{6,0,1737},{7,0,1444},{136
,0,224},{133,11,1006},{5,10,81},{7,0,1446},{7,10,146},{7,10,1342},{8,10,53},{8,
10,561},{8,10,694},{8,10,754},{9,0,97},{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},{14,10,273},{145,0,15},{5,10,408},{137,10,747},{135,11,431},{135,11,832
},{6,0,729},{134,0,953},{4,0,727},{5,11,351},{7,11,264},{8,0,565},{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},{5,11,205},{6,0,1285},{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},{12,10,644},
{16,0,20},{16,0,70},{16,10,90},{147,0,55},{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},{4,11,275},{7,0,259},{12,11,376},
{145,0,73},{132,11,509},{7,11,273},{139,11,377},{4,0,759},{9,10,804},{141,0,169}
,{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},{5,11,167},{5,11,899},{6,0,
1035},{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},{5,10,
431},{8,0,46},{136,0,740},{7,11,646},{7,11,1730},{11,11,446},{141,11,178},{5,10,
464},{6,10,236},{7,0,276},{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},{4,10,95},{7,10,416},{8
,0,211},{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},{7,11,1023},{9,0,124},{11,0,521},{140,0,405},{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},{5,10,864},{7,0,1403},{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},{8,10,44},{9,10,884},{10,10,580}
,{11,10,399},{11,10,894},{15,10,122},{18,0,144},{147,0,61},{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},{4,11,58},{5,11,286},{6,0,995},{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},{4,10,934},{5,0,138},{136,10,610},{4,0,965},{10,0,863},{138,0,898},{
10,10,804},{138,10,832},{8,10,96},{9,10,36},{10,10,607},{11,10,423},{11,10,442},
{12,0,631},{12,10,309},{14,10,199},{15,10,90},{145,10,110},{134,0,1394},{4,0,652
},{8,0,320},{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},{13,10,257}
,{22,0,6},{150,0,16},{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,10,995},{5,11,919},{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},{5,10,589},{6,0,39},{6,0,451},{7,0,218
},{7,0,667},{7,0,1166},{7,0,1687},{8,0,662},{144,0,2},{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
},{7,10,196},{10,10,765},{11,0,576},{11,10,347},{11,10,552},{11,10,790},{12,10,
263},{13,10,246},{13,10,270},{13,10,395},{14,0,74},{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},{4,10,192},{5,10,49},{6,10,200},{6,10,293},
{6,10,1696},{135,0,488},{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},{4,11,434},{9,0,534},{
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},{6,10,170},{7,0,1334},{7,11,393},{8,10,395},{8,10,487},{10,11,603},{11,
0,125},{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},{6,10,34},{7,0,206},{7,0,397},{7,0,621}
,{7,0,640},{7,10,1089},{8,0,124},{8,0,619},{8,10,708},{8,10,721},{9,0,305},{9,0,
643},{9,10,363},{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},{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},{5,10,220},{6,0,243},{6,0,
1708},{7,0,1865},{11,0,161},{16,0,37},{145,0,99},{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},{4,11,763},{135,0,166},{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},{6,10,127},{7,0,1612},{7,10,1511},
{8,10,613},{11,0,186},{12,0,133},{12,10,495},{12,10,586},{12,10,660},{12,10,668}
,{14,10,385},{15,10,118},{17,10,20},{146,10,98},{5,11,816},{134,0,1785},{134,0,
1339},{6,10,230},{7,0,961},{7,0,1085},{7,0,1727},{7,11,1727},{136,0,462},{7,10,
1954},{137,0,636},{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},{6,11,108},{7,0,1276},{7,11
,1003},{7,11,1181},{8,0,474},{8,11,343},{137,0,652},{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},{7,11,461},{8,0,292}
,{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},{4,10,361},{5,10,315},{145,0,114},{137,0,883},{132,10,461},{138,0,
274},{134,0,2008},{134,0,1794},{4,0,703},{135,0,207},{4,10,472},{140,0,285},{132
,0,571},{5,0,873},{5,0,960},{8,0,823},{8,11,577},{137,0,881},{7,0,617},{10,0,498
},{11,0,501},{12,0,16},{140,0,150},{138,10,747},{132,0,431},{133,10,155},{7,10,
163},{8,10,319},{9,10,402},{10,10,24},{10,10,681},{11,0,283},{11,0,567},{11,10,
200},{12,10,253},{12,10,410},{142,10,219},{4,11,413},{5,11,677},{8,11,432},{140,
11,280},{5,10,475},{7,10,1780},{9,0,401},{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},{7,10,1956},{140,0,783},{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},{5,10,428},{
138,0,442},{10,0,930},{140,0,778},{6,0,68},{7,0,448},{7,0,1629},{7,0,1769},{7,0,
1813},{7,10,1717},{8,0,442},{8,0,516},{9,0,710},{10,0,282},{10,0,722},{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},{4,10,397},{
8,0,491},{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},{7,11,396},{138,0,160}
,{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},{5,10,160},{6,0,737},{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},{4,10,108},{4,11,366}
,{7,0,405},{10,0,491},{139,10,498},{11,11,337},{142,11,303},{134,11,1736},{7,0,
1081},{140,11,364},{7,10,1005},{140,10,609},{4,10,895},{5,10,772},{135,0,1676},{
135,0,2037},{6,0,1207},{11,11,916},{142,11,419},{14,11,140},{148,11,41},{6,11,
331},{136,11,623},{4,10,926},{5,10,983},{9,0,944},{9,0,969},{9,0,1022},{12,0,913
},{12,0,936},{15,0,177},{143,0,193},{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},{7,11,1931},{137,0,191},{7,11,574},{7,11,
1719},{137,11,145},{132,11,658},{4,11,369},{138,0,790},{9,11,781},{10,11,144},{
11,11,385},{13,11,161},{13,11,228},{13,11,268},{148,11,107},{8,0,469},{8,11,374}
,{138,0,47},{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},{5,10,150},{7,0,175},{8,10,603},{9,10,593},{9,10,634},{10,0,
494},{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,10,493},{4,11,305},{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},{6,10,568},{7,0,669},{7,10,1804},{8,10,
362},{8,10,410},{8,10,830},{9,10,514},{11,10,649},{142,10,157},{6,11,1703},{135,
0,673},{132,10,625},{134,0,1303},{5,0,299},{135,0,1083},{138,0,704},{6,0,275},{6
,10,158},{7,0,408},{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},{4,10,1},{4,11,737},
{6,11,317},{7,10,1143},{7,10,1463},{8,0,216},{9,10,207},{9,10,390},{9,10,467},{
10,11,98},{11,10,836},{11,11,294},{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},{5,10,125},{6,0,1010},{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,10,270},{139,11,62},{134,11,1766},{6,11,0},{7,10,816},{7,10,1241},{7,11,84},{
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,10,903},{7,10,1963},{7,11,
848},{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},{4,10,289},{6,0,2047},{7,10,629},{7,10,1698},{
7,10,1711},{10,0,969},{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},{7,10,1587},{7,10,1707},{10,0,528},{139,0,504},{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},{6,11,468},{7,0,899},{7,11,567},{7,11,1478}
,{8,11,530},{14,0,325},{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},{5,11,305},
{6,0,56},{7,0,1758},{8,0,500},{9,0,730},{9,11,560},{11,0,331},{13,0,150},{13,11,
208},{142,0,282},{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},{4,11,480},{5,0,205},{6,0,438},{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,0,711},{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},{5
,11,712},{7,0,184},{7,11,1855},{8,10,425},{8,10,693},{9,10,720},{10,10,380},{10,
10,638},{11,0,307},{11,0,400},{11,10,473},{11,11,17},{12,10,61},{13,11,321},{15,
0,130},{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},{6,10,509},{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},{151,0,13},{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},{8,11,122},{
139,0,1015},{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},{4,11,507},{136,0,724},{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},{7,10,192},{136,0,1008},{132,0,842},{8,10,763},{11,0,643},{140,0
,115},{139,0,67},{133,10,759},{4,0,821},{5,0,760},{7,0,542},{7,11,580},{8,0,135}
,{136,0,496},{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},{4,10,209},{5,0,474},{7,0,507},{7,10,902},{135,11,507},{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},{5,10,1017},{7,0,799},{7,
0,1972},{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},{9,10,14},{9,10,441},{10,0,367},{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},{7,10,1428},{7,10,1640},{7,10,1867},{9,0,651},{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,0,971},{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,0,273},{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},{5,10,161},{7,0,887},{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},{7,10
,643},{8,10,236},{12,0,271},{145,0,109},{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},{5,10,54},{6,11,254},{7,0,1513},{9,11,109
},{138,11,103},{135,0,981},{133,11,729},{132,10,744},{132,0,434},{134,0,550},{6,
11,1630},{7,0,930},{10,0,476},{10,10,402},{13,0,452},{18,10,55},{147,0,104},{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},{6,10,43},{7,10,38
},{8,10,248},{9,0,504},{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},{7,
11,202},{10,0,603},{11,0,206},{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},{7,11,841},{137,0,232},{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},{7,10,1968},{
10,0,19},{11,0,911},{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},{4,10
,255},{5,10,302},{6,10,132},{7,10,128},{7,10,283},{7,10,1299},{9,0,463},{10,0,
595},{10,10,52},{10,10,514},{11,10,925},{13,10,92},{142,10,309},{135,0,1454},{
134,0,1287},{9,10,173},{11,0,600},{141,0,245},{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},{4,10,284},{6,10,223},{136,0,
625},{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},{4,10,270},{5,10,192},{6
,10,332},{7,10,1322},{13,0,9},{14,0,104},{142,0,311},{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},{5,11,204},{9,0,73},{10,0,110},{14,0,185},
{145,0,119},{7,0,624},{7,0,916},{10,0,256},{139,0,87},{7,10,379},{8,10,481},{137
,10,377},{5,0,212},{5,11,970},{6,11,1706},{12,0,35},{141,0,382},{5,10,1003},{6,
10,149},{137,0,746},{8,10,262},{9,10,627},{10,0,150},{11,0,849},{11,10,214},{11,
10,404},{11,10,457},{11,10,780},{11,10,913},{13,0,330},{13,10,401},{142,10,200},
{134,0,1466},{135,11,3},{4,11,35},{5,11,121},{5,11,483},{5,11,685},{6,0,1299},{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},{4,10,471},{4,
11,712},{5,10,51},{6,10,602},{7,10,925},{8,10,484},{10,10,195},{140,0,159},{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},{8
,10,688},{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},{141,0,190},{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},{4,11,285},{5,0,643},{5,11,317},{6,0,516},{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},{4,10,111},{135,
0,302},{135,0,1871},{132,0,728},{4,10,767},{137,0,252},{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},{6,10,
1667},{7,10,2036},{7,11,967},{10,0,600},{141,11,11},{6,10,511},{140,10,132},{5,
10,568},{6,0,799},{6,10,138},{135,10,1293},{4,10,565},{8,0,159},{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},{7,10,1002},{139,0,145},{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},{4,11,445},{9,0,977},{137,0,983},{
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},{8,10,532},{9,0,999},{12,0,807},{12,0,825},{15,0,179},{15,0,190},{146,0,
182},{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},{9,11,734},{10,0,636},{11,0,208},{12
,0,360},{17,0,118},{18,0,27},{148,0,67},{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},{8,10,723},{11,0,24
},{140,0,170},{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},{4,10,36},{7,10,1387},{10,0,327},{11,10,755},{141,0,271},{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},{4,10,353},{6,10,146},{6,10,1789}
,{7,0,288},{7,10,990},{7,10,1348},{9,10,665},{9,10,898},{11,10,893},{142,10,212}
,{6,0,916},{134,0,1592},{4,10,45},{7,0,1888},{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},{6,11,1669},{9,0,781},{10,
0,144},{11,0,385},{13,0,161},{13,0,228},{13,0,268},{148,0,107},{136,0,374},{135,
0,735},{4,0,344},{6,0,498},{139,0,323},{6,10,559},{6,10,1691},{7,0,586},{135,0,
1063},{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},{4,11,199},{8,0,857},{8,0,902},{8,0,910},{10,0,879},{11,11,
34},{140,0,726},{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},{9,10,222},{10,0,252},{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},{6,10,242},{7,10,
227},{7,10,1581},{8,10,104},{9,10,113},{9,10,220},{9,10,427},{10,0,74},{10,10,
239},{11,0,663},{11,10,579},{11,10,1023},{12,0,210},{13,0,166},{13,0,310},{13,10
,4},{13,10,204},{13,10,316},{14,0,373},{18,0,95},{19,0,43},{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},{5,11,747},{134,0,1581},{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},{4,11,691},{7,0,1935},{7,11,1935},{8,0,324},{8,11,324},{9,11,35},{10,11,
680},{11,11,364},{12,0,42},{12,11,42},{13,11,357},{146,11,16},{135,0,2014},{6,11
,32},{7,0,2007},{7,11,385},{7,11,757},{7,11,1916},{8,11,37},{8,11,94},{8,11,711}
,{9,0,101},{9,0,450},{9,11,541},{10,0,66},{10,0,842},{10,11,162},{10,11,795},{11
,0,536},{11,11,989},{11,11,1010},{12,0,587},{12,11,14},{142,11,308},{139,0,586},
{135,10,1703},{7,0,1077},{9,10,159},{11,0,28},{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},{4,10,136},{5,10,551},{11,0,670},{150,0,25},{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},{5,11,169},{6,0,1803},{7,11,333},{8,11,45},
{18,0,165},{152,0,21},{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},{7,10,229},{8,10,59},{9,0,257},{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},{7,10,690},{9,0,433},{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},{4,10,733},{9,10,194},{10,10,92},{11,10,198},{12,0,87},{12,10,84}
,{13,10,128},{144,0,74},{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},{5,11,999},{6,0,468},{7,0,567
},{7,0,1478},{8,0,530},{142,0,290},{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},{4,10
,390},{133,0,640},{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},{5,10,105},{135,0,1236},{4,0,480},{6,0,217},{6,0,302},{6,0
,1642},{6,11,232},{6,11,412},{7,0,130},{7,0,837},{7,0,1321},{7,0,1547},{7,0,1657
},{7,11,1074},{8,0,429},{8,11,9},{8,11,157},{8,11,786},{9,0,228},{9,11,196},{9,
11,352},{9,11,457},{10,11,337},{11,11,232},{11,11,877},{12,11,480},{12,11,546},{
13,0,289},{13,0,343},{147,0,101},{5,10,438},{7,11,958},{9,10,694},{12,10,627},{
13,10,210},{141,11,38},{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},{5,11,655},{134
,0,2017},{6,0,1488},{139,11,290},{132,10,308},{134,0,1590},{134,0,1800},{134,0,
1259},{6,11,231},{7,11,95},{8,11,423},{144,0,28},{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},{14,11,26},{17,0,36},{
146,11,150},{5,10,339},{7,0,1442},{14,0,22},{15,10,41},{15,10,166},{147,10,66},{
6,11,581},{7,11,1119},{136,0,378},{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},{7,
10,1635},{8,10,17},{10,0,445},{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},{4,10,609},{4,11,405},{6,0,109},{7,10,756}
,{7,11,817},{9,10,544},{10,0,382},{11,10,413},{14,10,307},{14,11,58},{16,10,25},
{17,11,37},{146,11,124},{5,11,974},{6,0,330},{7,0,1084},{139,0,142},{4,10,930},{
133,10,947},{5,10,939},{142,11,394},{16,0,91},{145,0,87},{5,10,962},{5,11,235},{
7,11,1239},{11,11,131},{140,11,370},{5,10,651},{8,10,170},{9,10,61},{9,10,63},{
10,10,23},{10,10,37},{10,10,834},{11,0,492},{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},{6,10,17},{7,0,321},{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},{4,10,208},{5,10,106},{6,0,630},{6,10,531},{8,10,
408},{9,0,811},{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},{4,10,241},{134,0,575},{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},{8,11,173},{10,
0,821},{11,0,970},{139,0,1021},{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},{8,11,300},{137,0,896},{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},{5,11,427},{5,11,734},{7,11,478}
,{8,0,800},{8,11,52},{9,0,148},{9,0,872},{9,0,890},{11,0,309},{11,0,1001},{13,0,
267},{141,0,323},{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},{7,10,1672},{11,0,429},{143,0,51},{
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},{4,10,409},{4,11,263},{5,10,78},
{6,0,938},{134,0,1060},{137,0,874},{4,11,916},{6,10,473},{7,10,1602},{8,0,774},{
10,0,670},{10,10,698},{12,0,51},{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},{7,11,1853},{9,0,603},{10,11,437},{141,0,397},{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},{4
,10,546},{7,10,2042},{142,0,233},{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},{11,10,402},{12,10,109},{12,10,431},{13,10,179},
{13,10,206},{14,0,175},{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},{5,10,957},{5,10
,1008},{135,0,249},{4,10,129},{135,10,465},{6,0,254},{7,0,842},{7,0,1659},{7,10,
908},{7,10,1201},{9,0,109},{9,10,755},{10,0,103},{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},{5,10,85},{6,10,419},{7,0,349},{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},{5,10,183},{6,10,582},{9,0,344},{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,10,583},{6,11,290},{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},{5,11,245},{6,11,576},{7,0,1193},{7,11,
582},{136,11,225},{144,0,82},{7,10,1270},{139,10,612},{5,0,454},{10,0,352},{138,
11,352},{5,10,371},{7,10,563},{146,0,57},{135,0,1333},{6,0,107},{6,11,610},{7,0,
638},{7,0,1632},{137,0,396},{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},{5,11,164},{6,0,1177},{6,0,1271},{7,11,121},{142
,11,189},{4,10,707},{5,10,588},{6,10,393},{7,0,1608},{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},{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},{14,0,52},{14,10,93},{145,0,50},{
138,11,97},{5,10,851},{20,0,21},{148,0,44},{136,0,819},{139,0,917},{5,11,230},{5
,11,392},{6,11,420},{8,10,762},{8,10,812},{9,10,910},{9,11,568},{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},{6,11,1645},{8,
10,192},{10,0,555},{10,10,78},{11,0,308},{13,10,359},{147,0,95},{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},{6,10,1638},{7,10,79},{7,10,496},{9,10,138},{10,10,336},
{11,0,386},{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},{4,10,29},{6,10,532},{7,10,1628},{7,10,1648},{9,0,303},{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,10,1692},{7,11,423},{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},{6,11,403},{7,0,901},{7,0,1343},{136,0,493},{7,11,719},{8,11,809},{136,
11,834},{5,11,210},{6,11,213},{7,11,60},{10,11,364},{139,11,135},{5,11,607},{7,0
,341},{8,11,326},{8,11,490},{139,0,219},{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},{4,11
,78},{5,11,96},{5,11,182},{7,11,1724},{7,11,1825},{8,0,1013},{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},{5,10,1016},{6,0,605},{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,
10,1687},{6,11,67},{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},{5,10,71},{7,
10,1407},{9,0,388},{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},{6,
10,265},{7,0,847},{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},{5,10,751},{140,0,203},{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},{4,10,350},{6,0,688},{137,0,834},{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},{4,10,473},{
7,10,623},{8,10,808},{9,10,871},{9,10,893},{11,0,114},{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},{4,11,84},{5,0,
140},{5,0,185},{7,0,1500},{7,11,1482},{10,11,76},{10,11,142},{11,0,565},{139,0,
838},{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},{6,11,1722},{140,0,116},{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},{7,10,138},{7,10,517},{9,0,673},{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},{5,10,495},{7,0,1840},{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},{4,10,402},{135,0,1679},{7,0,693},{8,0,180},{8,10,323},{8,10,479},
{140,0,163},{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},{5,11,830},{12,0,695},{12,0,704},{14
,11,338},{20,0,113},{148,11,81},{135,0,1464},{6,10,11},{135,10,187},{135,0,975},
{4,10,522},{141,0,335},{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},{4,10,383},{5,0,805},{5,0,819},{5,0,961},{5,10,520},{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},{149,0,24},{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},{11,11,584},{11,11,616},{14,0,275},{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},{6,10,
336},{7,0,611},{8,0,100},{8,10,552},{9,0,416},{9,10,285},{10,10,99},{11,0,335},{
11,10,568},{12,0,173},{146,0,101},{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},{7,10,634
},{136,0,665},{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},{7,11,421},{9,0,16},{141,0,386},{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,10,2001},{7,11,1656},{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},{4,10,13},{5,0,325},{5,10,567},{7,10,1498},{8,0,5},{8,0,
227},{9,0,105},{9,10,124},{10,0,585},{11,10,521},{12,0,614},{140,10,405},{135,10
,1006},{6,11,1720},{7,0,800},{138,0,12},{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},{6,11,224},{7,0,195},{7,11,877},{9,
0,226},{9,11,647},{10,0,197},{10,0,575},{11,0,502},{139,0,899},{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},{5,11,595},{7,0,1759},{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},{5,10,
783},{6,0,584},{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},{16,11,35},{148,0,40},{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},{5,10,37},{6,10
,39},{6,10,451},{7,0,1109},{7,10,218},{7,10,1166},{7,10,1687},{8,10,662},{11,0,7
},{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},{7,
10,635},{7,10,796},{8,10,331},{9,0,328},{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},{13,0,186},{13,0,364},{
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},{6,10,37},{7,0,873},{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},{8,11,102},{10,11,578},{10,11,672},{12,11,496},{13,11,408},{14,11,
121},{15,0,155},{16,0,79},{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},{4,10,290},{135,0,1356},{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},{5,
10,453},{6,0,765},{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},{5,11,70},{6,0,299},{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},{7,10,397},{8,10,124},{8,10,619},{9,10,305},{10,0,495},{11,
10,40},{12,10,349},{13,10,134},{13,10,295},{14,10,155},{15,10,120},{146,10,105},
{138,0,106},{5,11,107},{6,0,859},{7,11,201},{136,11,518},{6,11,446},{135,11,1817
},{4,10,262},{7,10,342},{141,0,23},{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},{7,11,787},{9,0,40},{139,0,136},{5,10,954},{5,11,993},{7,11,515},{
137,11,91},{139,0,259},{6,10,304},{7,0,1114},{8,10,418},{9,0,310},{9,0,682},{10,
0,440},{11,10,341},{11,10,675},{141,0,40},{9,10,410},{11,10,425},{142,0,296},{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},{5,10,113},{6,10
,243},{7,10,1865},{11,10,161},{16,10,37},{17,10,99},{149,0,39},{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},{9,10,304},{144,0,111},{4,0,425},{5,11,387},{7,11,
557},{12,11,547},{142,11,86},{135,11,1747},{5,10,654},{135,11,1489},{4,11,6},{5,
11,708},{7,0,789},{136,11,75},{6,10,273},{10,10,188},{13,10,377},{146,10,77},{4,
11,303},{6,0,1593},{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},{7,10,767},{137,0,829},{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},{9,10,883},{10,0,436},{12,0,673},{141,0,
255},{10,10,274},{139,0,530},{133,0,844},{134,0,984},{4,10,703},{7,10,207},{13,0
,232},{146,0,35},{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,10,448},{8,10,828},{8,11,81},{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},{7,
10,448},{7,10,1629},{7,10,1813},{8,0,387},{8,10,442},{9,10,710},{10,0,344},{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},{4,11,690},{134,0,1742},{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},{4,
10,574},{7,10,350},{7,10,1024},{8,10,338},{9,10,677},{10,10,808},{139,0,508},{
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},{6,10,306},{7,0,719},{7,10,1140},{7,
10,1340},{8,0,796},{8,0,809},{8,0,834},{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},{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,0,
1347},{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,10,322},{10,10,719},{10,
11,4},{11,10,407},{11,11,638},{12,11,177},{148,11,57},{7,0,1823},{139,0,693},{5,
11,758},{7,0,759},{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},{6
,10,1684},{6,10,1731},{7,0,1932},{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,10,1761},{7,11,1422},{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},{12,10,428},{14,0,80},{145,0,
80},{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},{5,11,601},{5,11,870},{136,0,783},{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},{7,11,1447},
{9,0,418},{137,0,803},{7,11,1044},{136,0,677},{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},{4,11,718},{11,0,0},{144,0,78},{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},{5,10,878},{5,10,972},{6,0,436},{139,0,481},{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},{7,10,438},{7
,10,627},{7,10,1516},{8,10,40},{9,10,56},{9,10,294},{10,0,259},{10,0,428},{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},{4,10,738},{134,0,1580},{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},{10,11,361},{12,0,181},{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},{5,10,378},{7,0,1402},{7,0,1414},{8,10,465},{9,10,286},{10,
10,185},{10,10,562},{10,10,635},{11,10,31},{11,10,393},{12,0,456},{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},{7,10,832},{138,0,97},
{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},{5,10,351},{135,0,264},{5,10,40},{7,10,598},{
7,10,1638},{8,0,213},{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},{5,11,227},{8,0,574},{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},{5,10,923},{12,0,553},{142,0
,118},{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},{4,10,924},{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},{
141,0,305},{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},
{5,10,233},{5,10,320},{6,10,140},{7,0,330},{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},{7,
10,273},{9,11,381},{139,0,377},{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,10,899
},{5,11,558},{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},{7,11,1539},{
11,0,512},{13,0,205},{19,0,30},{22,0,36},{151,0,19},{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},{6,11,239},{7,0,1180},{7,11,
118},{10,11,95},{11,11,603},{13,11,443},{14,11,160},{15,11,4},{148,0,112},{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},{4,11,726},{5,0
,8},{5,11,630},{6,0,89},{6,0,400},{7,0,1569},{7,0,1623},{7,0,1850},{8,0,218},{8,
0,422},{9,0,570},{138,0,626},{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},{4,10,389},{9,0,510}
,{9,10,181},{10,0,53},{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,10,373},{133,11,225},{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},{7,10,1651},{8,0,804},{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},{7,11,148},{8,0,467},
{8,0,1006},{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},{4,11,134},{5,
11,372},{8,0,115},{8,0,350},{9,0,489},{10,0,128},{11,0,306},{12,0,373},{14,0,30}
,{17,0,79},{147,0,80},{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},{7,10,1106},{9,10,770},{10,0,618},{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},{7,10,304},{9,
10,646},{9,10,862},{10,0,262},{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},{6,10,550},{
135,0,652},{5,10,553},{7,0,766},{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},{5,10,733},{142,0,103},{132,11,
595},{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},{12,0,158},{13,11,446},{14,11,
211},{18,0,8},{19,0,62},{20,0,6},{22,0,4},{23,0,2},{151,0,9},{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},{6,11,490},{135,0,1817},{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,10,600},{11,11,348},{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},{5,10,484},{5,10,510},{6,10,434},{7,10
,1000},{7,10,1098},{8,0,200},{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},{5,11,411},{6,0,2004},{7,0,921},{7,11,653},
{8,0,580},{8,0,593},{8,0,630},{138,0,28},{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},{6,
10,76},{7,0,1925},{12,0,39},{13,0,265},{141,0,439},{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},{7,
11,864},{137,0,470},{5,11,242},{137,0,836},{134,0,1937},{4,10,763},{133,11,953},
{132,10,622},{132,0,393},{133,10,253},{7,10,546},{8,0,357},{10,0,745},{14,0,426}
,{17,0,94},{147,0,57},{5,11,615},{146,11,37},{9,10,73},{10,10,110},{14,10,185},{
145,10,119},{7,10,624},{7,10,916},{10,10,256},{11,0,703},{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},{5,10,869},{5,10,968},{6,0,1065},{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},{5,11,723},{7,0,310},{139,0,717},{4,
10,232},{5,0,890},{5,0,988},{9,10,202},{10,10,474},{140,10,433},{6,0,626},{142,0
,431},{10,0,706},{150,0,44},{6,10,108},{7,10,1003},{7,10,1181},{8,10,111},{8,10,
343},{141,0,51},{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},{4,10,133},{5,11,216},{7,0,1929},{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},{6,10,574},{7,0,1250},{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},{6,10,323},{7,0,1582
},{7,10,1564},{8,0,458},{10,0,101},{10,0,318},{10,0,945},{12,0,734},{16,0,104},{
146,0,177},{5,11,632},{138,11,526},{7,10,461},{8,10,775},{138,0,435},{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},{4,11,30},{5,11,43},{24,0,8},{152,11,8},{7,0,1046}
,{139,0,160},{4,10,413},{5,10,677},{7,0,492},{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},{
4,10,395},{139,0,762},{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},{5,10,476},{134,0,2011},{4,0,4},{6,11,178},{6,11,1750},{7,0,
1118},{7,0,1320},{7,0,1706},{8,0,277},{8,11,251},{9,0,622},{9,11,690},{10,0,9},{
10,11,155},{10,11,196},{10,11,373},{11,0,724},{11,11,698},{12,0,350},{12,0,397},
{13,0,28},{13,0,159},{13,11,155},{15,0,89},{18,0,5},{19,0,9},{20,0,34},{20,11,93
},{150,0,47},{5,11,97},{137,11,393},{5,10,76},{6,10,458},{6,10,497},{7,0,764},{7
,10,868},{9,10,658},{10,10,594},{11,0,461},{11,10,566},{12,0,172},{12,10,338},{
141,10,200},{134,0,1449},{138,11,40},{134,11,1639},{134,0,1445},{4,10,526},{6,0,
1168},{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},{8,11,128},{9,0,216},{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},{5,11,57},{6,11,101},{6,11,1663},{7,0,285},{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,10,1743},{7,11,1073},{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},{6,10,202},{7,11,705},{10,0,448},{11,0,630},{12,
10,360},{17,0,117},{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},{6,11,166},{7,0,506},{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},{7,10,1931},{8,0,485},{18,0,28},{147,0,116},{7,10,574},{7,10,1719},{137,0,
145},{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},{4,10,616}
,{133,0,738},{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},{5,10,214},{7,10,
603},{8,10,611},{9,10,686},{10,10,88},{11,10,459},{11,10,496},{12,10,463},{12,10
,590},{13,0,44},{142,0,214},{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},{4,10,737},{6,0,317},{10,0,512},
{11,10,294},{12,10,60},{12,10,437},{13,10,64},{13,10,380},{142,10,430},{7,11,
1591},{9,0,371},{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},{4,10,107},{7,10,613},{8,0,
358},{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},{4,10,903},{6,0,537
},{7,0,788},{135,0,1816},{140,10,71},{6,0,743},{134,0,1223},{6,0,375},{7,0,169},
{7,0,254},{7,11,1493},{136,0,780},{4,10,47},{6,10,373},{7,0,1714},{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},{5,10,19},{6,10,533},{146,0,126},{4,0,788},{5,11,
552},{5,11,586},{5,11,676},{6,11,448},{8,11,244},{11,0,41},{11,11,1},{11,11,41},
{13,11,3},{16,11,54},{17,11,4},{146,11,13},{4,0,985},{4,11,401},{6,0,1801},{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},{5,10,284},{6,0,1371},{6,10,
49},{6,10,350},{7,0,31},{7,10,377},{7,10,1693},{8,0,373},{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},{7,11,761},{7,11,1051},{9,0,947},{9,0,974},{9,11,545},{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},{152,0,29},{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,10,101},{9,10,
450},{9,11,46},{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},{4,10,22},{5,10
,10},{7,0,848},{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},{6,10,134},{7,0,959},{7,10,437},{9,10,37},{14,10,285},{14,10,
371},{144,0,60},{7,10,486},{8,10,155},{11,10,93},{140,10,164},{134,0,1653},{5,10
,591},{135,0,337},{5,11,374},{6,0,1989},{8,0,922},{136,0,978},{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},{6,10,73},{135,0,1271},{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},{5,10,
413},{134,0,883},{4,11,758},{134,0,923},{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},{6,10,468},
{7,0,875},{7,10,1478},{8,10,530},{142,10,290},{135,0,1788},{5,11,918},{145,0,49}
,{12,11,398},{20,11,39},{21,11,11},{150,11,41},{6,10,484},{7,10,822},{138,0,661}
,{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},{5,10,305},{9,0,560},{141,0,208},{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},{4,10,480},{6,0,167},{6,10,302},{6,10,1642},{7,0,186},{7,0,656},{7,10,837}
,{7,10,1547},{7,10,1657},{8,10,429},{9,10,228},{10,0,643},{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},{4,11,67},{5,11,422},{6,10,363},{
7,0,1189},{7,10,1955},{7,11,1037},{7,11,1289},{7,11,1555},{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},{5,10,712},{7,
0,1855},{11,10,17},{13,10,321},{144,10,67},{6,10,320},{7,10,781},{7,10,1921},{9,
0,461},{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,10,271},{8,11,203},{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},{7,10,103},{7,10,863},{11,
10,184},{14,0,299},{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},{4
,11,254},{5,0,17},{6,0,371},{9,0,528},{140,0,364},{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},{10,11,525},{11,11,82},{143,0,0},{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},{8,10,145},{147,0,56},{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},{7,10,1999},{7,11,816},{7,11,1241},{9,0,248},{9,11,283},{9
,11,520},{10,0,400},{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},{5,10,168},{5,10,930},{8,10,74},{9,10,623},{12,10,500},{12,10
,579},{13,0,41},{143,0,93},{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},{7,11,1870
},{138,0,209},{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},{5,10,
133},{138,0,199},{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},{4,11,499
},{5,0,958},{5,0,987},{135,11,1421},{6,10,59},{6,10,1762},{7,0,885},{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},{4,11,96},{5,0,479},{5,0,1004},{7,0,1913},{8,0,317},{9,0,302},{10,0,
612},{141,0,22},{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},{4,11,910},{5,11,832},{135,0,1390},{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},{4,11,20},{5,11,616},{7,0,1995},{8,0,299},{11,0,
890},{140,0,674},{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,10,1910},{135,11,
1382},{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},{7,11,1495}
,{9,0,547},{10,0,730},{14,0,18},{150,0,39},{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},{15,11,83},{16,0,11},{144,11,11},{6,0,1057},{6,0,1335}
,{7,10,85},{7,10,247},{8,10,585},{10,0,316},{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},{4,10,124},{10,10,457},{11,0,422},{11,10,121},{11,10,169},{11
,10,870},{12,10,214},{13,0,389},{14,10,187},{143,10,77},{11,0,615},{11,11,615},{
15,0,58},{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},{5,10,1007},{134,0,1028},{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},{4,10,285},{5,0,216},{5,0,294},{5,10,317},{6,0,591},{6,10,
301},{7,0,1879},{7,10,7},{8,10,153},{9,0,141},{9,0,270},{9,0,679},{10,0,159},{10
,10,766},{11,0,197},{11,0,438},{11,10,468},{12,0,538},{12,0,559},{12,10,467},{13
,10,143},{14,0,144},{14,0,167},{143,0,67},{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},{7,11,954},{8,0,235},{8,0,461},{9,0,453},{9,0,796},{10,0,354},{145,
0,77},{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},{4,10,430},{5,0,165},{7,11,357},{9,0,346},{10,0,655},{
139,0,885},{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},{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},{18,10,114},{21,0,30},{
150,0,53},{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},{5,11,1000},{7,0,705},{7,11,733},{9,0,734},{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},{4,11,297},{6,11,529},
{7,0,1330},{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},{10,
10,115},{11,10,420},{12,0,425},{13,10,404},{14,10,346},{15,0,112},{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},{5,10,1011},{6,0,
1478},{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},{6,10,1669},{7,0,1159},{10,0,621},{139,0,192},{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},{5,10,82},{5,10,131},{7,10,1755},{8,10,31},{9,10,168},{9,10,764},{11,
0,1000},{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},{7,10,1316},{7,10,1412},{7,10,1839},{9,0,192},{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,0,30}
,{13,0,49},{13,10,381},{14,10,188},{15,0,150},{16,0,76},{18,10,30},{148,0,52},{
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},{5,
10,358},{7,0,473},{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},{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,0,384},{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},{4,11,491},{5,10,747},{134,0,
1024},{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
},{11,11,926},{140,0,659},{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},{10,10,680},{10,10
,793},{11,0,765},{141,10,357},{133,11,765},{6,10,32},{7,10,385},{7,10,757},{7,10
,1916},{8,0,229},{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},{11,11
,190},{15,0,49},{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},{4,10,590},{146,0,76},{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},{10,11,287},{12,0,138},{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},{4,10,897},{5,10,786},{136,0,655},{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},{7,10,958},{141,0,38},{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},{6,10,231},{7,0,95},{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},{8,11,501},{9,11,
696},{138,0,96},{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},{6,10,312},{6,10,1715},{10,0,758},{10,10,584},{
11,10,546},{11,10,692},{12,10,259},{12,10,295},{13,10,46},{141,10,154},{136,11,
822},{4,11,902},{5,0,827},{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},{4,11,34},{5,0,
977},{5,11,574},{6,0,288},{7,0,528},{7,11,279},{7,11,1624},{136,11,601},{4,10,
231},{5,10,61},{6,0,1375},{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},{5,11,332},{7,0,1309},{135,
11,1309},{6,11,261},{8,11,182},{139,11,943},{132,10,225},{6,0,12},{135,0,1219},{
4,0,275},{6,11,1721},{12,0,376},{141,11,490},{4,11,933},{133,11,880},{4,10,405},
{6,0,951},{6,0,1109},{6,0,1181},{7,0,154},{7,10,817},{14,10,58},{17,10,37},{146,
10,124},{5,10,974},{134,0,1520},{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},{4,11,137},{6,0,1017},{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},{6,11,1661
},{7,11,1975},{7,11,2009},{7,11,2011},{136,0,533},{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},{5,10,325},{7,0,1483},{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},{5,11,
6},{6,10,621},{6,11,183},{7,11,680},{7,11,978},{7,11,1013},{7,11,1055},{12,11,
230},{13,10,504},{13,11,172},{16,0,19},{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},{15,11,8},{18,0,39
},{18,11,39},{20,0,54},{20,11,54},{21,0,31},{21,11,31},{22,0,3},{22,11,3},{23,0,
0},{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},{8,11,522},{9,0,389},{12,0,548},{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},{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},{11,11,757},{142,0,453},{135,0,666},{22
,10,29},{150,11,29},{4,0,422},{147,10,8},{5,0,355},{145,0,0},{6,0,1873},{7,11,
588},{9,0,918},{9,11,175},{138,11,530},{143,11,31},{7,10,1125},{9,10,143},{11,0,
165},{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},{5,11,31},{6,11,614},{7,0,
1383},{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},{15,11,156},{18,0,218},{18,0,219},{146,
0,233},{135,10,1759},{136,10,173},{5,11,13},{6,11,142},{13,0,163},{13,0,180},{18
,0,78},{148,0,35},{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},{7,
11,866},{7,11,1163},{12,0,733},{140,0,766},{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},{9,11,7},{23,0,6},{151,11,6},{5,10,62},{6,0,282},{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},{4,11,896},{6,11,1777},{7,0,115},{9,0
,180},{9,0,456},{138,0,363},{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},{4,10,916},{140,
0,653},{4,11,603},{133,11,661},{4,11,11},{6,11,128},{7,11,231},{7,11,1533},{8,0,
344},{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},{4,10,599},{6,10,1634},{7,0,93},{7,0,210},{7,0,
1223},{7,10,67},{7,10,691},{7,10,979},{7,10,1697},{8,0,451},{8,0,460},{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
,0,353},{11,0,475},{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},{4,10,215},{8,0,914},{9,10,38},{10,0,3},{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},{5,11,626},{8,0,861},{10,0,905},{12,0,730},{140,0,789},{134,
0,946},{5,0,746},{12,0,333},{12,11,333},{14,0,332},{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},{5,10,853},{134,0,1393
},{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},{7,10,392},{8,10
,20},{8,10,172},{8,10,690},{9,10,383},{9,10,845},{10,0,510},{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}
,{11,10,259},{140,0,270},{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},
{4,10,296},{6,0,352},{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},{4,10,747},{6,0,515},{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},{4,10,14},{7,0,1145},{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},{6,10,1768},{7,0,825},{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},{4,10,298},{137,0,483},{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},{4,11,49},{7,11,280},{7,11,1633},{8,0,503},{145,0,
29},{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},{5,10,41},{7,0,1618},{7
,10,1459},{7,10,1469},{7,10,1859},{8,0,670},{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},{4,10,771},{4
,11,336},{134,0,1027},{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},{7,
11,102},{9,11,538},{12,0,582},{146,0,131},{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},{12,10,330},{144,0,36},{141,11,366},{6,10,
18},{7,0,721},{7,10,932},{8,10,757},{9,10,54},{9,10,65},{9,10,844},{10,0,236},{
10,10,113},{10,10,315},{10,10,798},{11,10,153},{12,0,204},{12,10,151},{12,10,392
},{12,10,666},{142,10,248},{7,0,241},{8,10,548},{9,10,532},{10,0,430},{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},{5,11,833},{7,0,723},
{7,0,1135},{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},{5,10,607},
{6,0,154},{7,0,676},{8,0,443},{8,0,609},{8,10,326},{8,10,490},{9,0,24},{9,0,325}
,{10,0,35},{11,0,535},{11,0,672},{11,0,1018},{12,0,637},{144,0,30},{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},{4,10,386},{7,0,139},{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},{6,10,215},{7,10,1028},{7,10,1473},{7,10,1721},{9,10,424},{10
,0,31},{138,10,779},{135,10,584},{136,11,293},{134,0,685},{135,11,1868},{133,11,
460},{6,10,67},{7,0,647},{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},{4,11,511},{6,0,722},{6,0,
1267},{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},{5,11,938},{8,11,707},{9,0,469},{9,0,709},{12
,0,512},{14,0,65},{145,0,12},{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},{5,10,602},{6,0,106},{7,
0,1786},{7,0,1821},{7,10,2018},{9,0,102},{9,0,763},{137,10,418},{5,0,65},{6,0,
416},{7,0,1720},{7,0,1924},{8,10,677},{10,0,109},{11,0,14},{11,0,70},{11,0,569},
{11,0,735},{15,0,153},{148,0,80},{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},{7,10,329},{11,0,571},{12,0,198},{13,
0,283},{14,0,186},{15,0,21},{143,0,103},{4,0,185},{5,0,257},{5,0,839},{5,0,936},
{7,11,1735},{9,0,399},{10,0,258},{10,0,395},{10,0,734},{11,0,1014},{12,0,23},{13
,0,350},{14,0,150},{147,0,6},{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},{4,
11,155},{7,11,1689},{11,10,0},{16,10,78},{152,0,13},{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}
,{5,10,571},{135,0,1842},{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},{4,10,48},{5,10,271},{7,10,953},{7,11,1878},{9,0,931},{10,0,
334},{148,0,71},{5,10,610},{8,10,457},{139,0,170},{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},{4,11,307},{135,0,685},{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},{6,11,225},{7,0,1838},{137,11,211
},{16,0,101},{20,0,115},{20,0,118},{148,0,122},{4,0,496},{135,0,856},{4,0,318},{
7,11,718},{11,0,654},{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},{7,11,1949},{8,0,247},{8,11,674},{147,0,0},{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},{8,11,254},{137,0,909},{10,0,776},{
13,0,345},{142,0,425},{4,10,84},{7,10,1482},{10,10,76},{138,10,142},{135,11,742}
,{5,10,1015},{134,0,578},{4,10,315},{5,10,507},{6,0,1387},{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},{4,11,319},{5,11,699},{7,0,1770},{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},{4,11,528},{134,0,808},{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,10,547},{134,11,95},{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},{7,10,1076},{8,0,
546},{9,10,80},{11,10,78},{11,10,421},{11,10,534},{140,10,545},{134,11,1636},{
135,11,1344},{7,10,274},{11,10,479},{11,10,507},{140,0,277},{4,11,282},{6,0,705}
,{6,0,783},{6,0,1275},{6,0,1481},{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},{
4,10,497},{7,10,1584},{8,0,536},{10,0,288},{139,0,1005},{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},{5,11,748},{6,11,553},{135,0,262},{133,0
,620},{4,0,34},{5,0,574},{7,0,279},{7,0,1624},{136,0,601},{6,10,322},{9,0,170},{
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},{4,11,50},{6,0,1609},{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},{7,10,205},{7,10,2000},{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},{146,0,192},{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},{8,10,735},{11,0,714},{142,0,281},{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},{4,11
,891},{134,0,735},{7,10,1409},{8,0,845},{136,0,916},{5,0,31},{134,0,614},{11,0,
458},{12,0,15},{140,0,432},{8,0,330},{140,0,477},{4,0,530},{4,11,687},{5,0,521},
{7,0,1200},{138,0,460},{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},{7,11,1304},{8,0,322},{8,0,755},{9,0,548},{10,0,714},{10,11,477},{11,
0,884},{141,0,324},{132,10,628},{134,11,1718},{7,10,266},{136,10,804},{135,10,
208},{6,10,79},{7,0,1021},{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},{5,11,705},{8,0,1},{9,0,650},{9,11,606},{138,0,326},{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,10,791},{5,11,179},{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},{4,11,66},{7,11,722},{7,11,904},{137,0,476},{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},{6,
10,427},{7,0,1371},{138,10,692},{4,0,424},{4,10,195},{135,10,802},{5,11,564},{
136,0,785},{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},{12,11,238},{18,0,155},{146,11,155},{151,10,28},{133,11,927},{5,10,3}
,{8,10,578},{9,10,118},{10,10,705},{12,0,383},{141,10,279},{4,11,893},{5,11,780}
,{133,11,893},{4,0,603},{133,0,661},{4,0,11},{5,10,229},{5,11,238},{6,0,128},{7,
0,231},{7,0,1533},{7,11,1350},{138,0,725},{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},{7,11,176},{7,11,178},{7,11,1110},{9,0,292},{10,0,481},{10,11,481},{20,0,
13},{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},{5,11,
902},{134,0,1244},{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},{5,10,70},{5,10,622},{6,0,347},{6,10,334},{7,10,1032},{9,10,171},{
10,0,161},{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},{4,10,23},{4,10,141},{5,10,313},{5,
10,1014},{6,0,465},{6,10,50},{7,0,1465},{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},{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},{18
,11,116},{22,0,30},{150,0,33},{5,10,222},{9,0,140},{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},{4,10,91},{5,
10,388},{5,10,845},{6,10,206},{6,10,252},{6,10,365},{7,10,136},{7,10,531},{8,0,
264},{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},{4,10,504},{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},{148,0,9},{4,11,
450},{135,11,1158},{5,10,883},{5,10,975},{8,10,392},{11,0,54},{13,0,173},{13,0,
294},{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},{4,10,300},{5,10,436},{135
,0,484},{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},{5,10,387},{7,0
,557},{12,0,547},{142,0,86},{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},{4,10,303},{135,0,89},{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},{4,10,106},{7,0,1543},{7,0,1785},{10,0,690},{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},{10,10,706},{17,0,32},{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},{5,10,986},{6,10,130},{7,10,1582},{8,0,501},{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},{7,10,558},{8,10,353}
,{141,0,490},{4,0,475},{5,10,785},{6,0,731},{11,0,35},{13,0,71},{13,0,177},{142,
0,422},{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},
{4,10,4},{7,10,1118},{7,10,1320},{7,10,1706},{8,10,277},{9,10,622},{10,0,86},{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},{4,11,483},{9,0,139},{10,0,399},{
11,0,469},{12,0,634},{141,0,223},{6,0,48},{135,0,63},{7,10,1862},{12,10,491},{12
,10,520},{13,10,383},{14,10,244},{146,0,12},{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}
,{5,10,1001},{8,0,576},{137,0,267},{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},{5,11,260},{137
,0,96},{139,11,587},{135,10,1231},{4,10,304},{12,0,30},{13,0,148},{14,0,87},{14,
0,182},{16,0,42},{148,0,70},{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},{6,10,53},{6,10,199},{7,10,1408},{8,10,32},{8,10,93},{9,0,437},{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},{5,10,114},{5,10,255},{6,0,
1003},{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},{6,11,52},{7,0,111},{8,0,581},{9,11,104},{
9,11,559},{10,10,4},{10,10,13},{11,10,638},{12,0,177},{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},{6,10,133},{9,10,353},
{11,10,993},{12,0,628},{146,0,79},{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},{4,10,181},{9,0,333},{9,0,379},{10,0,602},{11,
0,441},{11,0,723},{11,0,976},{140,0,357},{134,0,608},{134,10,1652},{9,11,338},{
150,0,49},{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},{4,10,420},{140,0,756},{
134,0,1504},{5,11,383},{134,0,757},{6,0,1266},{135,0,1735},{5,0,598},{7,0,791},{
7,10,1570},{8,0,108},{9,0,123},{140,10,542},{142,11,410},{9,11,660},{138,11,347}
};
================================================
FILE: NanaZip.Codecs/Brotli/enc/static_init.h
================================================
/* Copyright 2025 Google Inc. All Rights Reserved.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Central point for static initialization. */
#ifndef THIRD_PARTY_BROTLI_ENC_STATIC_INIT_H_
#define THIRD_PARTY_BROTLI_ENC_STATIC_INIT_H_
#include "../common/platform.h"
#include "../common/static_init.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)
BROTLI_INTERNAL void BrotliEncoderLazyStaticInitInner(void);
BROTLI_INTERNAL void BrotliEncoderLazyStaticInit(void);
#endif /* BROTLI_STATIC_INIT */
BROTLI_INTERNAL BROTLI_BOOL BrotliEncoderEnsureStaticInit(void);
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
#endif // THIRD_PARTY_BROTLI_ENC_STATIC_INIT_H_
================================================
FILE: NanaZip.Codecs/Brotli/enc/utf8_util.c
================================================
/* 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 "../common/platform.h"
#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
================================================
FILE: NanaZip.Codecs/Brotli/enc/utf8_util.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/enc/write_bits.h
================================================
/* 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 "../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_ */
================================================
FILE: NanaZip.Codecs/Brotli/include/brotli/decode.h
================================================
/* 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 /* IWYU pragma: export */
#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_ */
================================================
FILE: NanaZip.Codecs/Brotli/include/brotli/encode.h
================================================
/* 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 /* IWYU pragma: export */
#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.
*
* @warning Created instance is "lean"; it does not contain copy of @p data,
* rather it contains only pointer to it; therefore,
* @p data @b MUST outlive the created instance.
*
* @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_ */
================================================
FILE: NanaZip.Codecs/Brotli/include/brotli/port.h
================================================
/* 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
#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
#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 /* !BROTLICOMMON_SHARED_COMPILATION */
#define BROTLI_COMMON_API __declspec(dllimport)
#endif /* BROTLICOMMON_SHARED_COMPILATION */
#if defined(BROTLIDEC_SHARED_COMPILATION)
#define BROTLI_DEC_API __declspec(dllexport)
#else /* !BROTLIDEC_SHARED_COMPILATION */
#define BROTLI_DEC_API __declspec(dllimport)
#endif /* BROTLIDEC_SHARED_COMPILATION */
#if defined(BROTLIENC_SHARED_COMPILATION)
#define BROTLI_ENC_API __declspec(dllexport)
#else /* !BROTLIENC_SHARED_COMPILATION */
#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_ */
================================================
FILE: NanaZip.Codecs/Brotli/include/brotli/shared_dictionary.h
================================================
/* 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_ */
================================================
FILE: NanaZip.Codecs/Brotli/include/brotli/types.h
================================================
/* 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 /* IWYU pragma: export */
#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 /* IWYU pragma: export */
#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_ */
================================================
FILE: NanaZip.Codecs/FastLZMA2/atomic.h
================================================
/*
* Copyright (c) 2018 Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
*
*/
#ifndef FL2_ATOMIC_H
#define FL2_ATOMIC_H
#if defined (__cplusplus)
extern "C" {
#endif
/* atomic add */
#if !defined(FL2_SINGLETHREAD) && defined(_WIN32)
#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x0600
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include
typedef LONG volatile FL2_atomic;
#define ATOMIC_INITIAL_VALUE -1
#define FL2_atomic_increment(n) InterlockedIncrement(&n)
#define FL2_atomic_add(n, a) InterlockedAdd(&n, a)
#define FL2_nonAtomic_increment(n) (++n)
#elif !defined(FL2_SINGLETHREAD) && defined(__GNUC__)
typedef long FL2_atomic;
#define ATOMIC_INITIAL_VALUE 0
#define FL2_atomic_increment(n) __sync_fetch_and_add(&n, 1)
#define FL2_atomic_add(n, a) __sync_fetch_and_add(&n, a)
#define FL2_nonAtomic_increment(n) (n++)
#elif !defined(FL2_SINGLETHREAD) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) /* C11 */
#include
typedef _Atomic long FL2_atomic;
#define ATOMIC_INITIAL_VALUE 0
#define FL2_atomic_increment(n) atomic_fetch_add(&n, 1)
#define FL2_atomic_add(n, a) atomic_fetch_add(&n, a)
#define FL2_nonAtomic_increment(n) (n++)
#else /* No atomics */
# ifndef FL2_SINGLETHREAD
# error No atomic operations available. Change compiler config or define FL2_SINGLETHREAD for the entire build.
# endif
typedef long FL2_atomic;
#define ATOMIC_INITIAL_VALUE 0
#define FL2_atomic_increment(n) (n++)
#define FL2_atomic_add(n, a) (n += (a))
#define FL2_nonAtomic_increment(n) (n++)
#endif /* FL2_SINGLETHREAD */
#if defined (__cplusplus)
}
#endif
#endif /* FL2_ATOMIC_H */
================================================
FILE: NanaZip.Codecs/FastLZMA2/compiler.h
================================================
/* NanaZip Header File Redirection */
#include "../Zstandard/common/compiler.h"
================================================
FILE: NanaZip.Codecs/FastLZMA2/count.h
================================================
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef ZSTD_COUNT_H_
#define ZSTD_COUNT_H_
#include "mem.h"
#if defined (__cplusplus)
extern "C" {
#endif
/*-*************************************
* Match length counter
***************************************/
static unsigned ZSTD_NbCommonBytes(register size_t val)
{
if (MEM_isLittleEndian()) {
if (MEM_64bits()) {
# if defined(_MSC_VER) && defined(_WIN64)
unsigned long r = 0;
_BitScanForward64(&r, (U64)val);
return (unsigned)(r >> 3);
# elif defined(__GNUC__) && (__GNUC__ >= 4)
return (__builtin_ctzll((U64)val) >> 3);
# else
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
0, 3, 1, 3, 1, 4, 2, 7,
0, 2, 3, 6, 1, 5, 3, 5,
1, 3, 4, 4, 2, 5, 6, 7,
7, 0, 1, 2, 3, 3, 4, 6,
2, 6, 5, 5, 3, 4, 5, 6,
7, 1, 2, 4, 6, 4, 4, 5,
7, 2, 6, 5, 7, 6, 7, 7 };
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
# endif
}
else { /* 32 bits */
# if defined(_MSC_VER)
unsigned long r = 0;
_BitScanForward(&r, (U32)val);
return (unsigned)(r >> 3);
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return (__builtin_ctz((U32)val) >> 3);
# else
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
3, 2, 2, 1, 3, 2, 0, 1,
3, 3, 1, 2, 2, 2, 2, 0,
3, 1, 2, 0, 1, 0, 1, 1 };
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
# endif
}
}
else { /* Big Endian CPU */
if (MEM_64bits()) {
# if defined(_MSC_VER) && defined(_WIN64)
unsigned long r = 0;
_BitScanReverse64(&r, val);
return (unsigned)(r >> 3);
# elif defined(__GNUC__) && (__GNUC__ >= 4)
return (__builtin_clzll(val) >> 3);
# else
unsigned r;
const unsigned n32 = sizeof(size_t) * 4; /* calculate this way due to compiler complaining in 32-bits mode */
if (!(val >> n32)) { r = 4; }
else { r = 0; val >>= n32; }
if (!(val >> 16)) { r += 2; val >>= 8; }
else { val >>= 24; }
r += (!val);
return r;
# endif
}
else { /* 32 bits */
# if defined(_MSC_VER)
unsigned long r = 0;
_BitScanReverse(&r, (unsigned long)val);
return (unsigned)(r >> 3);
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return (__builtin_clz((U32)val) >> 3);
# else
unsigned r;
if (!(val >> 16)) { r = 2; val >>= 8; }
else { r = 0; val >>= 24; }
r += (!val);
return r;
# endif
}
}
}
static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
{
const BYTE* const pStart = pIn;
const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t) - 1);
if (pIn < pInLoopLimit) {
{ size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
if (diff) return ZSTD_NbCommonBytes(diff); }
pIn += sizeof(size_t); pMatch += sizeof(size_t);
while (pIn < pInLoopLimit) {
size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
if (!diff) { pIn += sizeof(size_t); pMatch += sizeof(size_t); continue; }
pIn += ZSTD_NbCommonBytes(diff);
return (size_t)(pIn - pStart);
}
}
if (MEM_64bits() && (pIn<(pInLimit - 3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn += 4; pMatch += 4; }
if ((pIn<(pInLimit - 1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn += 2; pMatch += 2; }
if ((pIn
#include "dict_buffer.h"
#include "fl2_internal.h"
#define ALIGNMENT_SIZE 16U
#define ALIGNMENT_MASK (~(size_t)(ALIGNMENT_SIZE-1))
/* DICT_buffer functions */
int DICT_construct(DICT_buffer * const buf, int const async)
{
buf->data[0] = NULL;
buf->data[1] = NULL;
buf->size = 0;
buf->async = (async != 0);
#ifndef NO_XXHASH
buf->xxh = NULL;
#endif
return 0;
}
int DICT_init(DICT_buffer * const buf, size_t const dict_size, size_t const overlap, unsigned const reset_multiplier, int const do_hash)
{
/* Allocate if not yet allocated or existing dict too small */
if (buf->data[0] == NULL || dict_size > buf->size) {
/* Free any existing buffers */
DICT_destruct(buf);
buf->data[0] = malloc(dict_size);
buf->data[1] = NULL;
if (buf->async)
buf->data[1] = malloc(dict_size);
if (buf->data[0] == NULL || (buf->async && buf->data[1] == NULL)) {
DICT_destruct(buf);
return 1;
}
}
buf->index = 0;
buf->overlap = overlap;
buf->start = 0;
buf->end = 0;
buf->size = dict_size;
buf->total = 0;
buf->reset_interval = (reset_multiplier != 0) ? dict_size * reset_multiplier : ((size_t)1 << 31);
#ifndef NO_XXHASH
if (do_hash) {
if (buf->xxh == NULL) {
buf->xxh = XXH32_createState();
if (buf->xxh == NULL) {
DICT_destruct(buf);
return 1;
}
}
XXH32_reset(buf->xxh, 0);
}
else {
XXH32_freeState(buf->xxh);
buf->xxh = NULL;
}
#else
(void)do_hash;
#endif
return 0;
}
void DICT_destruct(DICT_buffer * const buf)
{
free(buf->data[0]);
free(buf->data[1]);
buf->data[0] = NULL;
buf->data[1] = NULL;
buf->size = 0;
#ifndef NO_XXHASH
XXH32_freeState(buf->xxh);
buf->xxh = NULL;
#endif
}
size_t DICT_size(const DICT_buffer * const buf)
{
return buf->size;
}
/* Get the dictionary buffer for adding input */
size_t DICT_get(DICT_buffer * const buf, void **const dict)
{
DICT_shift(buf);
DEBUGLOG(5, "Getting dict buffer %u, pos %u, avail %u", (unsigned)buf->index, (unsigned)buf->end, (unsigned)(buf->size - buf->end));
*dict = buf->data[buf->index] + buf->end;
return buf->size - buf->end;
}
/* Update with the amount added */
int DICT_update(DICT_buffer * const buf, size_t const added_size)
{
DEBUGLOG(5, "Added %u bytes to dict buffer %u", (unsigned)added_size, (unsigned)buf->index);
buf->end += added_size;
assert(buf->end <= buf->size);
return !DICT_availSpace(buf);
}
/* Read from input and write to the dict */
void DICT_put(DICT_buffer * const buf, FL2_inBuffer * const input)
{
size_t const to_read = MIN(buf->size - buf->end, input->size - input->pos);
DEBUGLOG(5, "CStream : reading %u bytes", (U32)to_read);
memcpy(buf->data[buf->index] + buf->end, (BYTE*)input->src + input->pos, to_read);
input->pos += to_read;
buf->end += to_read;
}
size_t DICT_availSpace(const DICT_buffer * const buf)
{
return buf->size - buf->end;
}
/* Get the size of uncompressed data. start is set to end after compression */
int DICT_hasUnprocessed(const DICT_buffer * const buf)
{
return buf->start < buf->end;
}
/* Get the buffer, overlap and end for compression */
void DICT_getBlock(DICT_buffer * const buf, FL2_dataBlock * const block)
{
block->data = buf->data[buf->index];
block->start = buf->start;
block->end = buf->end;
#ifndef NO_XXHASH
if (buf->xxh != NULL)
XXH32_update(buf->xxh, buf->data[buf->index] + buf->start, buf->end - buf->start);
#endif
buf->total += buf->end - buf->start;
buf->start = buf->end;
}
/* Shift occurs when all is processed and end is beyond the overlap size */
int DICT_needShift(DICT_buffer * const buf)
{
if (buf->start < buf->end)
return 0;
/* Reset the dict if the next compression cycle would exceed the reset interval */
size_t overlap = (buf->total + buf->size - buf->overlap > buf->reset_interval) ? 0 : buf->overlap;
return buf->start == buf->end && (overlap == 0 || buf->end >= overlap + ALIGNMENT_SIZE);
}
int DICT_async(const DICT_buffer * const buf)
{
return (int)buf->async;
}
/* Shift the overlap amount to the start of either the only dict buffer or the alternate one
* if it exists */
void DICT_shift(DICT_buffer * const buf)
{
if (buf->start < buf->end)
return;
size_t overlap = buf->overlap;
/* Reset the dict if the next compression cycle would exceed the reset interval */
if (buf->total + buf->size - buf->overlap > buf->reset_interval) {
DEBUGLOG(4, "Resetting dictionary after %u bytes", (unsigned)buf->total);
overlap = 0;
}
if (overlap == 0) {
/* No overlap means a simple buffer switch */
buf->start = 0;
buf->end = 0;
buf->index ^= buf->async;
buf->total = 0;
}
else if (buf->end >= overlap + ALIGNMENT_SIZE) {
size_t const from = (buf->end - overlap) & ALIGNMENT_MASK;
const BYTE *const src = buf->data[buf->index];
/* Copy to the alternate if one exists */
BYTE *const dst = buf->data[buf->index ^ buf->async];
overlap = buf->end - from;
if (overlap <= from || dst != src) {
DEBUGLOG(5, "Copy overlap data : %u bytes from %u", (unsigned)overlap, (unsigned)from);
memcpy(dst, src + from, overlap);
}
else if (from != 0) {
DEBUGLOG(5, "Move overlap data : %u bytes from %u", (unsigned)overlap, (unsigned)from);
memmove(dst, src + from, overlap);
}
/* New data will be written after the overlap */
buf->start = overlap;
buf->end = overlap;
/* Switch buffers */
buf->index ^= buf->async;
}
}
#ifndef NO_XXHASH
XXH32_hash_t DICT_getDigest(const DICT_buffer * const buf)
{
return XXH32_digest(buf->xxh);
}
#endif
size_t DICT_memUsage(const DICT_buffer * const buf)
{
return (1 + buf->async) * buf->size;
}
================================================
FILE: NanaZip.Codecs/FastLZMA2/dict_buffer.h
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include "fast-lzma2.h"
#include "mem.h"
#include "data_block.h"
#ifndef NO_XXHASH
# include "xxhash.h"
#endif
#ifndef FL2_DICT_BUFFER_H_
#define FL2_DICT_BUFFER_H_
#if defined (__cplusplus)
extern "C" {
#endif
/* DICT_buffer structure.
* Maintains one or two dictionary buffers. In a dual dict configuration (asyc==1), when the
* current buffer is full, the overlap region will be copied to the other buffer and it
* becomes the destination for input while the first is compressed. This is useful when I/O
* is much slower than compression. */
typedef struct {
BYTE* data[2];
size_t index;
size_t async;
size_t overlap;
size_t start; /* start = 0 (first block) or overlap */
size_t end; /* never < overlap */
size_t size; /* allocation size */
size_t total; /* total size compressed after last dict reset */
size_t reset_interval;
#ifndef NO_XXHASH
XXH32_state_t *xxh;
#endif
} DICT_buffer;
int DICT_construct(DICT_buffer *const buf, int const async);
int DICT_init(DICT_buffer *const buf, size_t const dict_size, size_t const overlap, unsigned const reset_multiplier, int const do_hash);
void DICT_destruct(DICT_buffer *const buf);
size_t DICT_size(const DICT_buffer *const buf);
size_t DICT_get(DICT_buffer *const buf, void **const dict);
int DICT_update(DICT_buffer *const buf, size_t const added_size);
void DICT_put(DICT_buffer *const buf, FL2_inBuffer* const input);
size_t DICT_availSpace(const DICT_buffer *const buf);
int DICT_hasUnprocessed(const DICT_buffer *const buf);
void DICT_getBlock(DICT_buffer *const buf, FL2_dataBlock *const block);
int DICT_needShift(DICT_buffer *const buf);
int DICT_async(const DICT_buffer *const buf);
void DICT_shift(DICT_buffer *const buf);
#ifndef NO_XXHASH
XXH32_hash_t DICT_getDigest(const DICT_buffer *const buf);
#endif
size_t DICT_memUsage(const DICT_buffer *const buf);
#if defined (__cplusplus)
}
#endif
#endif /* FL2_DICT_BUFFER_H_ */
================================================
FILE: NanaZip.Codecs/FastLZMA2/fast-lzma2.h
================================================
/*
* Copyright (c) 2017-present, Conor McCarthy
* All rights reserved.
* Based on zstd.h copyright Yann Collet
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#if defined (__cplusplus)
extern "C" {
#endif
#ifndef FAST_LZMA2_H
#define FAST_LZMA2_H
/* ====== Dependency ======*/
#include /* size_t */
/* ===== FL2LIB_API : control library symbols visibility ===== */
#ifndef FL2LIB_VISIBILITY
# if defined(__GNUC__) && (__GNUC__ >= 4)
# define FL2LIB_VISIBILITY __attribute__ ((visibility ("default")))
# else
# define FL2LIB_VISIBILITY
# endif
#endif
#if defined(FL2_DLL_EXPORT) && (FL2_DLL_EXPORT==1)
# define FL2LIB_API __declspec(dllexport) FL2LIB_VISIBILITY
#elif defined(FL2_DLL_IMPORT) && (FL2_DLL_IMPORT==1)
# define FL2LIB_API __declspec(dllimport) FL2LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
#else
# define FL2LIB_API FL2LIB_VISIBILITY
#endif
/* ====== Calling convention ======*/
#if !defined _WIN32 || defined __x86_64__s || defined _M_X64 || (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8)
# define FL2LIB_CALL
#elif defined(__GNUC__)
# define FL2LIB_CALL __attribute__((cdecl))
#elif defined(_MSC_VER)
# define FL2LIB_CALL __cdecl
#else
# define FL2LIB_CALL
#endif
/*******************************************************************************************************
Introduction
*********************************************************************************************************/
/*------ Version ------*/
#define FL2_VERSION_MAJOR 1
#define FL2_VERSION_MINOR 0
#define FL2_VERSION_RELEASE 1
#define FL2_VERSION_NUMBER (FL2_VERSION_MAJOR *100*100 + FL2_VERSION_MINOR *100 + FL2_VERSION_RELEASE)
FL2LIB_API unsigned FL2LIB_CALL FL2_versionNumber(void); /**< useful to check dll version */
#define FL2_LIB_VERSION FL2_VERSION_MAJOR.FL2_VERSION_MINOR.FL2_VERSION_RELEASE
#define FL2_QUOTE(str) #str
#define FL2_EXPAND_AND_QUOTE(str) FL2_QUOTE(str)
#define FL2_VERSION_STRING FL2_EXPAND_AND_QUOTE(FL2_LIB_VERSION)
FL2LIB_API const char* FL2LIB_CALL FL2_versionString(void);
#define FL2_MAXTHREADS 200
/***************************************
* Simple API
***************************************/
/*! FL2_compress() :
* Compresses `src` content as a single LZMA2 compressed stream into already allocated `dst`.
* Call FL2_compressMt() to use > 1 thread. Specify nbThreads = 0 to use all cores.
* @return : compressed size written into `dst` (<= `dstCapacity),
* or an error code if it fails (which can be tested using FL2_isError()). */
FL2LIB_API size_t FL2LIB_CALL FL2_compress(void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel);
FL2LIB_API size_t FL2LIB_CALL FL2_compressMt(void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel,
unsigned nbThreads);
/*! FL2_decompress() :
* Decompresses a single LZMA2 compressed stream from `src` into already allocated `dst`.
* `compressedSize` : must be at least the size of the LZMA2 stream.
* `dstCapacity` is the original, uncompressed size to regenerate, returned by calling
* FL2_findDecompressedSize().
* Call FL2_decompressMt() to use > 1 thread. Specify nbThreads = 0 to use all cores. The stream
* must contain dictionary resets to use multiple threads. These are inserted during compression by
* default. The frequency can be changed/disabled with the FL2_p_resetInterval parameter setting.
* @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
* or an errorCode if it fails (which can be tested using FL2_isError()). */
FL2LIB_API size_t FL2LIB_CALL FL2_decompress(void* dst, size_t dstCapacity,
const void* src, size_t compressedSize);
FL2LIB_API size_t FL2LIB_CALL FL2_decompressMt(void* dst, size_t dstCapacity,
const void* src, size_t compressedSize,
unsigned nbThreads);
/*! FL2_findDecompressedSize()
* `src` should point to the start of a LZMA2 encoded stream.
* `srcSize` must be at least as large as the LZMA2 stream including end marker.
* A property byte is assumed to exist at position 0 in `src`. If the stream was created without one,
* subtract 1 byte from `src` when passing it to the function.
* @return : - decompressed size of the stream in `src`, if known
* - FL2_CONTENTSIZE_ERROR if an error occurred (e.g. corruption, srcSize too small)
* note 1 : a 0 return value means the stream is valid but "empty".
* note 2 : decompressed size can be very large (64-bits value),
* potentially larger than what local system can handle as a single memory segment.
* In which case, it's necessary to use streaming mode to decompress data.
* note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified.
* Always ensure return value fits within application's authorized limits.
* Each application can set its own limits. */
#define FL2_CONTENTSIZE_ERROR (size_t)-1
FL2LIB_API unsigned long long FL2LIB_CALL FL2_findDecompressedSize(const void *src, size_t srcSize);
/*====== Helper functions ======*/
FL2LIB_API size_t FL2LIB_CALL FL2_compressBound(size_t srcSize); /*!< maximum compressed size in worst case scenario */
FL2LIB_API unsigned FL2LIB_CALL FL2_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
FL2LIB_API unsigned FL2LIB_CALL FL2_isTimedOut(size_t code); /*!< tells if a `size_t` function result is the timeout code */
FL2LIB_API const char* FL2LIB_CALL FL2_getErrorName(size_t code); /*!< provides readable string from an error code */
FL2LIB_API int FL2LIB_CALL FL2_maxCLevel(void); /*!< maximum compression level available */
FL2LIB_API int FL2LIB_CALL FL2_maxHighCLevel(void); /*!< maximum compression level available in high mode */
/***************************************
* Explicit memory management
***************************************/
/*= Compression context
* When compressing many times, it is recommended to allocate a context just once,
* and re-use it for each successive compression operation. This will make workload
* friendlier for system's memory. The context may not use the number of threads requested
* if the library is compiled for single-threaded compression or nbThreads > FL2_MAXTHREADS.
* Call FL2_getCCtxThreadCount to obtain the actual number allocated. */
typedef struct FL2_CCtx_s FL2_CCtx;
FL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtx(void);
FL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtxMt(unsigned nbThreads);
FL2LIB_API void FL2LIB_CALL FL2_freeCCtx(FL2_CCtx* cctx);
FL2LIB_API unsigned FL2LIB_CALL FL2_getCCtxThreadCount(const FL2_CCtx* cctx);
/*! FL2_compressCCtx() :
* Same as FL2_compress(), but requires an allocated FL2_CCtx (see FL2_createCCtx()). */
FL2LIB_API size_t FL2LIB_CALL FL2_compressCCtx(FL2_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel);
/*! FL2_getCCtxDictProp() :
* Get the dictionary size property.
* Intended for use with the FL2_p_omitProperties parameter for creating a
* 7-zip or XZ compatible LZMA2 stream. */
FL2LIB_API unsigned char FL2LIB_CALL FL2_getCCtxDictProp(FL2_CCtx* cctx);
/****************************
* Decompression
****************************/
/*= Decompression context
* When decompressing many times, it is recommended to allocate a context only once,
* and re-use it for each successive decompression operation. This will make the workload
* friendlier for the system's memory.
* The context may not allocate the number of threads requested if the library is
* compiled for single-threaded compression or nbThreads > FL2_MAXTHREADS.
* Call FL2_getDCtxThreadCount to obtain the actual number allocated.
* At least nbThreads dictionary resets must exist in the stream to use all of the
* threads. Dictionary resets are inserted into the stream according to the
* FL2_p_resetInterval parameter used in the compression context. */
typedef struct FL2_DCtx_s FL2_DCtx;
FL2LIB_API FL2_DCtx* FL2LIB_CALL FL2_createDCtx(void);
FL2LIB_API FL2_DCtx* FL2LIB_CALL FL2_createDCtxMt(unsigned nbThreads);
FL2LIB_API size_t FL2LIB_CALL FL2_freeDCtx(FL2_DCtx* dctx);
FL2LIB_API unsigned FL2LIB_CALL FL2_getDCtxThreadCount(const FL2_DCtx* dctx);
/*! FL2_initDCtx() :
* Use only when a property byte is not present at input byte 0. No init is necessary otherwise.
* The caller must store the result from FL2_getCCtxDictProp() and pass it to this function. */
FL2LIB_API size_t FL2LIB_CALL FL2_initDCtx(FL2_DCtx* dctx, unsigned char prop);
/*! FL2_decompressDCtx() :
* Same as FL2_decompress(), requires an allocated FL2_DCtx (see FL2_createDCtx()) */
FL2LIB_API size_t FL2LIB_CALL FL2_decompressDCtx(FL2_DCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
/****************************
* Streaming
****************************/
typedef struct {
const void* src; /**< start of input buffer */
size_t size; /**< size of input buffer */
size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
} FL2_inBuffer;
typedef struct {
void* dst; /**< start of output buffer */
size_t size; /**< size of output buffer */
size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
} FL2_outBuffer;
/*** Push/pull structs ***/
typedef struct {
void* dst; /**< start of available dict buffer */
unsigned long size; /**< size of dict remaining */
} FL2_dictBuffer;
typedef struct {
const void* src; /**< start of compressed data */
size_t size; /**< size of compressed data */
} FL2_cBuffer;
/*-***********************************************************************
* Streaming compression
*
* A FL2_CStream object is required to track streaming operation.
* Use FL2_createCStream() and FL2_freeCStream() to create/release resources.
* FL2_CStream objects can be reused multiple times on consecutive compression operations.
* It is recommended to re-use FL2_CStream in situations where many streaming operations will be done
* consecutively, since it will reduce allocation and initialization time.
*
* Call FL2_createCStreamMt() with a nonzero dualBuffer parameter to use two input dictionary buffers.
* The stream will not block on FL2_compressStream() and continues to accept data while compression is
* underway, until both buffers are full. Useful when I/O is slow.
* To compress with a single thread with dual buffering, call FL2_createCStreamMt with nbThreads=1.
*
* Use FL2_initCStream() on the FL2_CStream object to start a new compression operation.
*
* Use FL2_compressStream() repetitively to consume input stream.
* The function will automatically update the `pos` field.
* It will always consume the entire input unless an error occurs or the dictionary buffer is filled,
* unlike the decompression function.
*
* The radix match finder allows compressed data to be stored in its match table during encoding.
* Applications may call streaming compression functions with output == NULL. In this case,
* when the function returns 1, the compressed data must be read from the internal buffers.
* Call FL2_getNextCompressedBuffer() repeatedly until it returns 0.
* Each call returns buffer information in the FL2_inBuffer parameter. Applications typically will
* passed this to an I/O write function or downstream filter.
* Alternately, applications may pass an FL2_outBuffer object pointer to receive the output. In this
* case the return value is 1 if the buffer is full and more compressed data remains.
*
* FL2_endStream() instructs to finish a stream. It will perform a flush and write the LZMA2
* termination byte (required). Call FL2_endStream() repeatedly until it returns 0.
*
* Most functions may return a size_t error code, which can be tested using FL2_isError().
*
* *******************************************************************/
typedef struct FL2_CCtx_s FL2_CStream;
/*===== FL2_CStream management functions =====*/
FL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStream(void);
FL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStreamMt(unsigned nbThreads, int dualBuffer);
FL2LIB_API void FL2LIB_CALL FL2_freeCStream(FL2_CStream * fcs);
/*===== Streaming compression functions =====*/
/*! FL2_initCStream() :
* Call this function before beginning a new compressed data stream. To keep the stream object's
* current parameters, specify zero for the compression level. The object is set to the default
* level upon creation. */
FL2LIB_API size_t FL2LIB_CALL FL2_initCStream(FL2_CStream* fcs, int compressionLevel);
/*! FL2_setCStreamTimeout() :
* Sets a timeout in milliseconds. Zero disables the timeout (default). If a nonzero timout is set, functions
* FL2_compressStream(), FL2_getDictionaryBuffer(), FL2_updateDictionary(), FL2_getNextCompressedBuffer(),
* FL2_flushStream(), and FL2_endStream() may return a timeout code before compression of the current
* dictionary of data completes. FL2_isError() returns true for the timeout code, so check the code with
* FL2_isTimedOut() before testing for errors. With the exception of FL2_updateDictionary(), the above
* functions may be called again to wait for completion. A typical application for timeouts is to update the
* user on compression progress. */
FL2LIB_API size_t FL2LIB_CALL FL2_setCStreamTimeout(FL2_CStream * fcs, unsigned timeout);
/*! FL2_compressStream() :
* Reads data from input into the dictionary buffer. Compression will begin if the buffer fills up.
* A dual buffering stream will fill the second buffer while compression proceeds on the first.
* A call to FL2_compressStream() will wait for ongoing compression to complete if all dictionary space
* is filled. FL2_compressStream() must not be called with output == NULL unless the caller has read all
* compressed data from the CStream object.
* Returns 1 to indicate compressed data must be read (or output is full), or 0 otherwise. */
FL2LIB_API size_t FL2LIB_CALL FL2_compressStream(FL2_CStream* fcs, FL2_outBuffer *output, FL2_inBuffer* input);
/*! FL2_copyCStreamOutput() :
* Copies compressed data to the output buffer until the buffer is full or all available data is copied.
* If asynchronous compression is in progress, the function returns 0 without waiting.
* Returns 1 to indicate some compressed data remains, or 0 otherwise. */
FL2LIB_API size_t FL2LIB_CALL FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output);
/*** Push/pull functions ***/
/*! FL2_getDictionaryBuffer() :
* Returns a buffer in the FL2_outBuffer object, which the caller can directly read data into.
* Applications will normally pass this buffer to an I/O read function or upstream filter.
* Returns 0, or an error or timeout code. */
FL2LIB_API size_t FL2LIB_CALL FL2_getDictionaryBuffer(FL2_CStream* fcs, FL2_dictBuffer* dict);
/*! FL2_updateDictionary() :
* Informs the CStream how much data was added to the buffer. Compression begins if the dictionary
* was filled. Returns 1 to indicate compressed data must be read, 0 if not, or an error code. */
FL2LIB_API size_t FL2LIB_CALL FL2_updateDictionary(FL2_CStream* fcs, size_t addedSize);
/*! FL2_getNextCompressedBuffer() :
* Returns a buffer containing a slice of the compressed data. Call this function and process the data
* until the function returns zero. In most cases it will return a buffer for each compression thread
* used. It is sometimes less but never more than nbThreads. If asynchronous compression is in progress,
* this function will wait for completion before returning, or it will return the timeout code. */
FL2LIB_API size_t FL2LIB_CALL FL2_getNextCompressedBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf);
/******/
/*! FL2_getCStreamProgress() :
* Returns the number of bytes processed since the stream was initialized. This is a synthetic
* estimate because the match finder does not proceed sequentially through the data. If
* outputSize is not NULL, returns the number of bytes of compressed data generated. */
FL2LIB_API unsigned long long FL2LIB_CALL FL2_getCStreamProgress(const FL2_CStream * fcs, unsigned long long *outputSize);
/*! FL2_waitCStream() :
* Waits for compression to end. This function returns after the timeout set using
* FL2_setCStreamTimeout has elapsed. Unnecessary when no timeout is set.
* Returns 1 if compressed output is available, 0 if not, or the timeout code. */
FL2LIB_API size_t FL2LIB_CALL FL2_waitCStream(FL2_CStream * fcs);
/*! FL2_cancelCStream() :
* Cancels any compression operation underway. Useful only when dual buffering and/or timeouts
* are enabled. The stream will be returned to an uninitialized state. */
FL2LIB_API void FL2LIB_CALL FL2_cancelCStream(FL2_CStream *fcs);
/*! FL2_remainingOutputSize() :
* The amount of compressed data remaining to be read from the CStream object. */
FL2LIB_API size_t FL2LIB_CALL FL2_remainingOutputSize(const FL2_CStream* fcs);
/*! FL2_flushStream() :
* Compress all data remaining in the dictionary buffer(s). It may be necessary to call
* FL2_flushStream() more than once. If output == NULL the compressed data must be read from the
* CStream object after each call.
* Flushing is not normally useful and produces larger output.
* Returns 1 if input or output still exists in the CStream object, 0 if complete, or an error code. */
FL2LIB_API size_t FL2LIB_CALL FL2_flushStream(FL2_CStream* fcs, FL2_outBuffer *output);
/*! FL2_endStream() :
* Compress all data remaining in the dictionary buffer(s) and write the stream end marker. It may
* be necessary to call FL2_endStream() more than once. If output == NULL the compressed data must
* be read from the CStream object after each call.
* Returns 0 when compression is complete and all output has been flushed, 1 if not complete, or
* an error code. */
FL2LIB_API size_t FL2LIB_CALL FL2_endStream(FL2_CStream* fcs, FL2_outBuffer *output);
/*-***************************************************************************
* Streaming decompression
*
* A FL2_DStream object is required to track streaming operations.
* Use FL2_createDStream() and FL2_freeDStream() to create/release resources.
* FL2_DStream objects can be re-used multiple times.
*
* Use FL2_initDStream() to start a new decompression operation.
* @return : zero or an error code
*
* Use FL2_decompressStream() repetitively to consume your input.
* The function will update both `pos` fields.
* If `input.pos < input.size`, some input has not been consumed.
* It's up to the caller to present again the remaining data.
* If `output.pos < output.size`, decoder has flushed everything it could.
* @return : 0 when a stream is completely decoded and fully flushed,
* 1, which means there is still some decoding to do to complete the stream,
* or an error code, which can be tested using FL2_isError().
* *******************************************************************************/
typedef struct FL2_DStream_s FL2_DStream;
/*===== FL2_DStream management functions =====*/
FL2LIB_API FL2_DStream* FL2LIB_CALL FL2_createDStream(void);
FL2LIB_API FL2_DStream* FL2LIB_CALL FL2_createDStreamMt(unsigned nbThreads);
FL2LIB_API size_t FL2LIB_CALL FL2_freeDStream(FL2_DStream* fds);
/*! FL2_setDStreamMemoryLimitMt() :
* Set a total size limit for multithreaded decoder input and output buffers. MT decoder memory
* usage is unknown until the input is parsed. If the limit is exceeded, the decoder switches to
* using a single thread.
* MT decoding memory usage is typically dictionary_size * 4 * nbThreads for the output
* buffers plus the size of the compressed input for that amount of output. */
FL2LIB_API void FL2LIB_CALL FL2_setDStreamMemoryLimitMt(FL2_DStream* fds, size_t limit);
/*! FL2_setDStreamTimeout() :
* Sets a timeout in milliseconds. Zero disables the timeout. If a nonzero timout is set,
* FL2_decompressStream() may return a timeout code before decompression of the available data
* completes. FL2_isError() returns true for the timeout code, so check the code with FL2_isTimedOut()
* before testing for errors. After a timeout occurs, do not call FL2_decompressStream() again unless
* a call to FL2_waitDStream() returns 1. A typical application for timeouts is to update the user on
* decompression progress. */
FL2LIB_API size_t FL2LIB_CALL FL2_setDStreamTimeout(FL2_DStream * fds, unsigned timeout);
/*! FL2_waitDStream() :
* Waits for decompression to end after a timeout has occurred. This function returns after the
* timeout set using FL2_setDStreamTimeout() has elapsed, or when decompression of available input is
* complete. Unnecessary when no timeout is set.
* Returns 0 if the stream is complete, 1 if not complete, or an error code. */
FL2LIB_API size_t FL2LIB_CALL FL2_waitDStream(FL2_DStream * fds);
/*! FL2_cancelDStream() :
* Frees memory allocated for MT decoding. If a timeout is set and the caller is waiting
* for completion of MT decoding, decompression in progress will be canceled. */
FL2LIB_API void FL2LIB_CALL FL2_cancelDStream(FL2_DStream *fds);
/*! FL2_getDStreamProgress() :
* Returns the number of bytes decoded since the stream was initialized. */
FL2LIB_API unsigned long long FL2LIB_CALL FL2_getDStreamProgress(const FL2_DStream * fds);
/*===== Streaming decompression functions =====*/
/*! FL2_initDStream() :
* Call this function before decompressing a stream. FL2_initDStream_withProp()
* must be used for streams which do not include a property byte at position zero.
* The caller is responsible for storing and passing the property byte.
* Returns 0 if okay, or an error if the stream object is still in use from a
* previous call to FL2_decompressStream() (see timeout info above). */
FL2LIB_API size_t FL2LIB_CALL FL2_initDStream(FL2_DStream* fds);
FL2LIB_API size_t FL2LIB_CALL FL2_initDStream_withProp(FL2_DStream* fds, unsigned char prop);
/*! FL2_decompressStream() :
* Reads data from input and decompresses to output.
* Returns 1 if the stream is unfinished, 0 if the terminator was encountered (he'll be back)
* and all data was written to output, or an error code. Call this function repeatedly if
* necessary, removing data from output and/or loading data into input before each call. */
FL2LIB_API size_t FL2LIB_CALL FL2_decompressStream(FL2_DStream* fds, FL2_outBuffer* output, FL2_inBuffer* input);
/*-***************************************************************************
* Compression parameters
*
* Any function that takes a 'compressionLevel' parameter will replace any
* parameters affected by compression level that are already set.
* To use a preset level and modify it, call FL2_CCtx_setParameter with
* FL2_p_compressionLevel to set the level, then call FL2_CCtx_setParameter again
* with any other settings to change.
* Specify a compressionLevel of 0 when calling a compression function to keep
* the current parameters.
* *******************************************************************************/
#define FL2_DICTLOG_MIN 20
#define FL2_DICTLOG_MAX_32 27
#define FL2_DICTLOG_MAX_64 30
#define FL2_DICTLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? FL2_DICTLOG_MAX_32 : FL2_DICTLOG_MAX_64))
#define FL2_DICTSIZE_MAX (1U << FL2_DICTLOG_MAX)
#define FL2_DICTSIZE_MIN (1U << FL2_DICTLOG_MIN)
#define FL2_BLOCK_OVERLAP_MIN 0
#define FL2_BLOCK_OVERLAP_MAX 14
#define FL2_RESET_INTERVAL_MIN 1
#define FL2_RESET_INTERVAL_MAX 16 /* small enough to fit FL2_DICTSIZE_MAX * FL2_RESET_INTERVAL_MAX in 32-bit size_t */
#define FL2_BUFFER_RESIZE_MIN 0
#define FL2_BUFFER_RESIZE_MAX 4
#define FL2_BUFFER_RESIZE_DEFAULT 2
#define FL2_CHAINLOG_MIN 4
#define FL2_CHAINLOG_MAX 14
#define FL2_HYBRIDCYCLES_MIN 1
#define FL2_HYBRIDCYCLES_MAX 64
#define FL2_SEARCH_DEPTH_MIN 6
#define FL2_SEARCH_DEPTH_MAX 254
#define FL2_FASTLENGTH_MIN 6 /* only used by optimizer */
#define FL2_FASTLENGTH_MAX 273 /* only used by optimizer */
#define FL2_LC_MIN 0
#define FL2_LC_MAX 4
#define FL2_LP_MIN 0
#define FL2_LP_MAX 4
#define FL2_PB_MIN 0
#define FL2_PB_MAX 4
#define FL2_LCLP_MAX 4
typedef enum {
FL2_fast,
FL2_opt,
FL2_ultra
} FL2_strategy;
typedef struct {
size_t dictionarySize; /* largest match distance : larger == more compression, more memory needed during decompression; > 64Mb == more memory per byte, slower */
unsigned overlapFraction; /* overlap between consecutive blocks in 1/16 units: larger == more compression, slower */
unsigned chainLog; /* HC3 sliding window : larger == more compression, slower; hybrid mode only (ultra) */
unsigned cyclesLog; /* nb of searches : larger == more compression, slower; hybrid mode only (ultra) */
unsigned searchDepth; /* maximum depth for resolving string matches : larger == more compression, slower */
unsigned fastLength; /* acceptable match size for parser : larger == more compression, slower; fast bytes parameter from 7-Zip */
unsigned divideAndConquer; /* split long chains of 2-byte matches into shorter chains with a small overlap : faster, somewhat less compression; enabled by default */
FL2_strategy strategy; /* encoder strategy : fast, optimized or ultra (hybrid) */
} FL2_compressionParameters;
typedef enum {
/* compression parameters */
FL2_p_compressionLevel, /* Update all compression parameters according to pre-defined cLevel table
* Default level is FL2_CLEVEL_DEFAULT==6.
* Setting FL2_p_highCompression to 1 switches to an alternate cLevel table. */
FL2_p_highCompression, /* Maximize compression ratio for a given dictionary size.
* Levels 1..10 = dictionaryLog 20..29 (1 Mb..512 Mb).
* Typically provides a poor speed/ratio tradeoff. */
FL2_p_dictionaryLog, /* Maximum allowed back-reference distance, expressed as power of 2.
* Must be clamped between FL2_DICTLOG_MIN and FL2_DICTLOG_MAX.
* Default = 24 */
FL2_p_dictionarySize, /* Same as above but expressed as an absolute value.
* Must be clamped between FL2_DICTSIZE_MIN and FL2_DICTSIZE_MAX.
* Default = 16 Mb */
FL2_p_overlapFraction, /* The radix match finder is block-based, so some overlap is retained from
* each block to improve compression of the next. This value is expressed
* as n / 16 of the block size (dictionary size). Larger values are slower.
* Values above 2 mostly yield only a small improvement in compression.
* A large value for a small dictionary may worsen multithreaded compression.
* Default = 2 */
FL2_p_resetInterval, /* For multithreaded decompression. A dictionary reset will occur
* after each dictionarySize * resetInterval bytes of input.
* Default = 4 */
FL2_p_bufferResize, /* Buffering speeds up the matchfinder. Buffer resize determines the percentage of
* the normal buffer size used, which depends on dictionary size.
* 0=50, 1=75, 2=100, 3=150, 4=200. Higher number = slower, better
* compression, higher memory usage. A CPU with a large memory cache
* may make effective use of a larger buffer.
* Default = 2 */
FL2_p_hybridChainLog, /* Size of the hybrid mode HC3 hash chain, as a power of 2.
* Resulting table size is (1 << (chainLog+2)) bytes.
* Larger tables result in better and slower compression.
* This parameter is only used by the hybrid "ultra" strategy.
* Default = 9 */
FL2_p_hybridCycles, /* Number of search attempts made by the HC3 match finder.
* Used only by the hybrid "ultra" strategy.
* More attempts result in slightly better and slower compression.
* Default = 1 */
FL2_p_searchDepth, /* Match finder will resolve string matches up to this length. If a longer
* match exists further back in the input, it will not be found.
* Default = 42 */
FL2_p_fastLength, /* Only useful for strategies >= opt.
* Length of match considered "good enough" to stop search.
* Larger values make compression stronger and slower.
* Default = 48 */
FL2_p_divideAndConquer, /* Split long chains of 2-byte matches into shorter chains with a small overlap
* for further processing. Allows buffering of all chains at length 2.
* Faster, less compression. Generally a good tradeoff.
* Default = enabled */
FL2_p_strategy, /* 1 = fast; 2 = optimized, 3 = ultra (hybrid mode).
* The higher the value of the selected strategy, the more complex it is,
* resulting in stronger and slower compression.
* Default = ultra */
FL2_p_literalCtxBits, /* lc value for LZMA2 encoder
* Default = 3 */
FL2_p_literalPosBits, /* lp value for LZMA2 encoder
* Default = 0 */
FL2_p_posBits, /* pb value for LZMA2 encoder
* Default = 2 */
FL2_p_omitProperties, /* Omit the property byte at the start of the stream. For use within 7-zip */
/* or other containers which store the property byte elsewhere. */
/* A stream compressed under this setting cannot be decoded by this library. */
#ifndef NO_XXHASH
FL2_p_doXXHash, /* Calculate a 32-bit xxhash value from the input data and store it
* after the stream terminator. The value will be checked on decompression.
* 0 = do not calculate; 1 = calculate (default) */
#endif
#ifdef RMF_REFERENCE
FL2_p_useReferenceMF /* Use the reference matchfinder for development purposes. SLOW. */
#endif
} FL2_cParameter;
/*! FL2_CCtx_setParameter() :
* Set one compression parameter, selected by enum FL2_cParameter.
* @result : informational value (typically, the one being set, possibly corrected),
* or an error code (which can be tested with FL2_isError()). */
FL2LIB_API size_t FL2LIB_CALL FL2_CCtx_setParameter(FL2_CCtx* cctx, FL2_cParameter param, size_t value);
/*! FL2_CCtx_getParameter() :
* Get one compression parameter, selected by enum FL2_cParameter.
* @result : the parameter value, or the parameter_unsupported error code
* (which can be tested with FL2_isError()). */
FL2LIB_API size_t FL2LIB_CALL FL2_CCtx_getParameter(FL2_CCtx* cctx, FL2_cParameter param);
/*! FL2_CStream_setParameter() :
* Set one compression parameter, selected by enum FL2_cParameter.
* @result : informational value (typically, the one being set, possibly corrected),
* or an error code (which can be tested with FL2_isError()). */
FL2LIB_API size_t FL2LIB_CALL FL2_CStream_setParameter(FL2_CStream* fcs, FL2_cParameter param, size_t value);
/*! FL2_CStream_getParameter() :
* Get one compression parameter, selected by enum FL2_cParameter.
* @result : the parameter value, or the parameter_unsupported error code
* (which can be tested with FL2_isError()). */
FL2LIB_API size_t FL2LIB_CALL FL2_CStream_getParameter(FL2_CStream* fcs, FL2_cParameter param);
/*! FL2_getLevelParameters() :
* Get all compression parameter values defined by the preset compressionLevel.
* @result : the values in a FL2_compressionParameters struct, or the parameter_outOfBound error code
* (which can be tested with FL2_isError()) if compressionLevel is invalid. */
FL2LIB_API size_t FL2LIB_CALL FL2_getLevelParameters(int compressionLevel, int high, FL2_compressionParameters *params);
/***************************************
* Context memory usage
***************************************/
/*! FL2_estimate*() :
* These functions estimate memory usage of a CCtx before its creation or before any operation has begun.
* FL2_estimateCCtxSize() will provide a budget large enough for any compression level up to selected one.
* To use FL2_estimateCCtxSize_usingCCtx, set the compression level and any other settings for the context,
* then call the function. Some allocation occurs when the context is created, but the large memory buffers
* used for string matching are allocated only when compression is initialized. */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize(int compressionLevel, unsigned nbThreads); /*!< memory usage determined by level */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_byParams(const FL2_compressionParameters *params, unsigned nbThreads); /*!< memory usage determined by params */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_usingCCtx(const FL2_CCtx* cctx); /*!< memory usage determined by settings */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize(int compressionLevel, unsigned nbThreads, int dualBuffer); /*!< memory usage determined by level */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_byParams(const FL2_compressionParameters *params, unsigned nbThreads, int dualBuffer); /*!< memory usage determined by params */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_usingCStream(const FL2_CStream* fcs); /*!< memory usage determined by settings */
/*! FL2_getDictSizeFromProp() :
* Get the dictionary size from the property byte for a stream. The property byte is the first byte
* in the stream, unless omitProperties was enabled, in which case the caller must store it. */
FL2LIB_API size_t FL2LIB_CALL FL2_getDictSizeFromProp(unsigned char prop);
/*! FL2_estimateDCtxSize() :
* The size of a DCtx does not include a dictionary buffer because the caller must supply one. */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateDCtxSize(unsigned nbThreads);
/*! FL2_estimateDStreamSize() :
* Estimate decompression memory use from the dictionary size and number of threads.
* For nbThreads == 0 the number of available cores will be used.
* Obtain dictSize by passing the property byte to FL2_getDictSizeFromProp. */
FL2LIB_API size_t FL2LIB_CALL FL2_estimateDStreamSize(size_t dictSize, unsigned nbThreads); /*!< obtain dictSize from FL2_getDictSizeFromProp() */
#endif /* FAST_LZMA2_H */
#if defined (__cplusplus)
}
#endif
================================================
FILE: NanaZip.Codecs/FastLZMA2/fastpos_table.h
================================================
/* This file has been automatically generated by fastpos_tablegen.c. */
/* Copied from the XZ project */
static const BYTE distance_table[1 << kFastDistBits] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 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,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
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,
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,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 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, 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, 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, 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,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23
};
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_common.c
================================================
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* All rights reserved.
* Modified for FL2 by Conor McCarthy
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
/*-*************************************
* Dependencies
***************************************/
#include "fast-lzma2.h"
#include "fl2_errors.h"
#include "fl2_internal.h"
#include "lzma2_enc.h"
/*-****************************************
* Version
******************************************/
FL2LIB_API unsigned FL2LIB_CALL FL2_versionNumber(void) { return FL2_VERSION_NUMBER; }
FL2LIB_API const char* FL2LIB_CALL FL2_versionString(void) { return FL2_VERSION_STRING; }
/*-****************************************
* Compression helpers
******************************************/
FL2LIB_API size_t FL2LIB_CALL FL2_compressBound(size_t srcSize)
{
return LZMA2_compressBound(srcSize);
}
/*-****************************************
* FL2 Error Management
******************************************/
HINT_INLINE
unsigned IsError(size_t code)
{
return (code > FL2_ERROR(maxCode));
}
/*! FL2_isError() :
* tells if a return value is an error code */
FL2LIB_API unsigned FL2LIB_CALL FL2_isError(size_t code)
{
return IsError(code);
}
/*! FL2_isTimedOut() :
* tells if a return value is the timeout code */
FL2LIB_API unsigned FL2LIB_CALL FL2_isTimedOut(size_t code)
{
return (code == FL2_ERROR(timedOut));
}
/*! FL2_getErrorName() :
* provides error code string from function result (useful for debugging) */
FL2LIB_API const char* FL2LIB_CALL FL2_getErrorName(size_t code)
{
return FL2_getErrorString(FL2_getErrorCode(code));
}
/*! FL2_getError() :
* convert a `size_t` function result into a proper FL2_errorCode enum */
FL2LIB_API FL2_ErrorCode FL2LIB_CALL FL2_getErrorCode(size_t code)
{
if (!IsError(code))
return (FL2_ErrorCode)0;
return (FL2_ErrorCode)(0 - code);
}
/*! FL2_getErrorString() :
* provides error code string from enum */
FL2LIB_API const char* FL2LIB_CALL FL2_getErrorString(FL2_ErrorCode code)
{
static const char* const notErrorCode = "Unspecified error code";
switch (code)
{
case PREFIX(no_error): return "No error detected";
case PREFIX(GENERIC): return "Error (generic)";
case PREFIX(internal): return "Internal error (bug)";
case PREFIX(corruption_detected): return "Corrupted block detected";
case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
case PREFIX(parameter_unsupported): return "Unsupported parameter";
case PREFIX(parameter_outOfBound): return "Parameter is out of bound";
case PREFIX(lclpMax_exceeded): return "Parameters lc+lp > 4";
case PREFIX(stage_wrong): return "Not possible at this stage of encoding";
case PREFIX(init_missing): return "Context should be init first";
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
case PREFIX(srcSize_wrong): return "Src size is incorrect";
case PREFIX(canceled): return "Processing was canceled by a call to FL2_cancelCStream() or FL2_cancelDStream()";
case PREFIX(buffer): return "Streaming progress halted due to buffer(s) full/empty";
case PREFIX(timedOut): return "Wait timed out. Timeouts should be handled before errors using FL2_isTimedOut()";
/* following error codes are not stable and may be removed or changed in a future version */
case PREFIX(maxCode):
default: return notErrorCode;
}
}
/*! g_debuglog_enable :
* turn on/off debug traces (global switch) */
#if defined(FL2_DEBUG) && (FL2_DEBUG >= 2)
int g_debuglog_enable = 1;
#endif
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_compress.c
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
* Parts based on zstd_compress.c copyright Yann Collet
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include
#include "fast-lzma2.h"
#include "fl2_errors.h"
#include "fl2_internal.h"
#include "platform.h"
#include "mem.h"
#include "util.h"
#include "fl2_compress_internal.h"
#include "fl2_threading.h"
#include "fl2_pool.h"
#include "radix_mf.h"
#include "lzma2_enc.h"
#define FL2_MAX_LOOPS 10U
/*-===== Pre-defined compression levels =====-*/
#define MB *(1U<<20)
#define FL2_MAX_HIGH_CLEVEL 10
#ifdef FL2_XZ_BUILD
#define FL2_CLEVEL_DEFAULT 6
#define FL2_MAX_CLEVEL 9
static const FL2_compressionParameters FL2_defaultCParameters[FL2_MAX_CLEVEL + 1] = {
{ 0,0,0,0,0,0,0,0 },
{ 1 MB, 1, 7, 0, 6, 32, 1, FL2_fast }, /* 1 */
{ 2 MB, 2, 7, 0, 14, 32, 1, FL2_fast }, /* 2 */
{ 2 MB, 2, 7, 0, 14, 40, 1, FL2_opt }, /* 3 */
{ 8 MB, 2, 7, 0, 26, 40, 1, FL2_opt }, /* 4 */
{ 16 MB, 2, 8, 0, 42, 48, 1, FL2_opt }, /* 5 */
{ 16 MB, 2, 9, 1, 42, 48, 1, FL2_ultra }, /* 6 */
{ 32 MB, 2, 10, 1, 50, 64, 1, FL2_ultra }, /* 7 */
{ 64 MB, 2, 11, 2, 62, 96, 1, FL2_ultra }, /* 8 */
{ 128 MB, 2, 12, 3, 90, 128, 1, FL2_ultra }, /* 9 */
};
#elif defined(FL2_7ZIP_BUILD)
#define FL2_CLEVEL_DEFAULT 5
#define FL2_MAX_CLEVEL 9
static const FL2_compressionParameters FL2_defaultCParameters[FL2_MAX_CLEVEL + 1] = {
{ 0,0,0,0,0,0,0,0 },
{ 1 MB, 1, 7, 0, 6, 32, 1, FL2_fast }, /* 1 */
{ 2 MB, 2, 7, 0, 10, 32, 1, FL2_fast }, /* 2 */
{ 2 MB, 2, 7, 0, 10, 32, 1, FL2_opt }, /* 3 */
{ 4 MB, 2, 7, 0, 14, 32, 1, FL2_opt }, /* 4 */
{ 16 MB, 2, 9, 0, 42, 48, 1, FL2_ultra }, /* 5 */
{ 32 MB, 2, 10, 0, 50, 64, 1, FL2_ultra }, /* 6 */
{ 64 MB, 2, 11, 1, 62, 96, 1, FL2_ultra }, /* 7 */
{ 64 MB, 4, 12, 2, 90, 273, 1, FL2_ultra }, /* 8 */
{ 128 MB, 2, 14, 3, 254, 273, 0, FL2_ultra } /* 9 */
};
#else
#define FL2_CLEVEL_DEFAULT 6
#define FL2_MAX_CLEVEL 10
static const FL2_compressionParameters FL2_defaultCParameters[FL2_MAX_CLEVEL + 1] = {
{ 0,0,0,0,0,0,0,0 },
{ 1 MB, 1, 7, 0, 6, 32, 1, FL2_fast }, /* 1 */
{ 2 MB, 2, 7, 0, 10, 32, 1, FL2_fast }, /* 2 */
{ 2 MB, 2, 7, 0, 10, 32, 1, FL2_opt }, /* 3 */
{ 4 MB, 2, 7, 0, 26, 40, 1, FL2_opt }, /* 4 */
{ 8 MB, 2, 8, 0, 42, 48, 1, FL2_opt }, /* 5 */
{ 16 MB, 2, 9, 0, 42, 48, 1, FL2_ultra }, /* 6 */
{ 32 MB, 2, 10, 0, 50, 64, 1, FL2_ultra }, /* 7 */
{ 64 MB, 2, 11, 1, 62, 96, 1, FL2_ultra }, /* 8 */
{ 64 MB, 4, 12, 2, 90, 273, 1, FL2_ultra }, /* 9 */
{ 128 MB, 2, 14, 3, 254, 273, 0, FL2_ultra } /* 10 */
};
#endif
static const FL2_compressionParameters FL2_highCParameters[FL2_MAX_HIGH_CLEVEL + 1] = {
{ 0,0,0,0,0,0,0,0 },
{ 1 MB, 4, 9, 2, 254, 273, 0, FL2_ultra }, /* 1 */
{ 2 MB, 4, 10, 2, 254, 273, 0, FL2_ultra }, /* 2 */
{ 4 MB, 4, 11, 2, 254, 273, 0, FL2_ultra }, /* 3 */
{ 8 MB, 4, 12, 2, 254, 273, 0, FL2_ultra }, /* 4 */
{ 16 MB, 4, 13, 3, 254, 273, 0, FL2_ultra }, /* 5 */
{ 32 MB, 4, 14, 3, 254, 273, 0, FL2_ultra }, /* 6 */
{ 64 MB, 4, 14, 4, 254, 273, 0, FL2_ultra }, /* 7 */
{ 128 MB, 4, 14, 4, 254, 273, 0, FL2_ultra }, /* 8 */
{ 256 MB, 4, 14, 5, 254, 273, 0, FL2_ultra }, /* 9 */
{ 512 MB, 4, 14, 5, 254, 273, 0, FL2_ultra } /* 10 */
};
#undef MB
FL2LIB_API int FL2LIB_CALL FL2_maxCLevel(void)
{
return FL2_MAX_CLEVEL;
}
FL2LIB_API int FL2LIB_CALL FL2_maxHighCLevel(void)
{
return FL2_MAX_HIGH_CLEVEL;
}
static void FL2_fillParameters(FL2_CCtx* const cctx, const FL2_compressionParameters* const params)
{
FL2_lzma2Parameters* const cParams = &cctx->params.cParams;
cParams->lc = 3;
cParams->lp = 0;
cParams->pb = 2;
cParams->fast_length = params->fastLength;
cParams->match_cycles = 1U << params->cyclesLog;
cParams->strategy = params->strategy;
cParams->second_dict_bits = params->chainLog;
RMF_parameters* const rParams = &cctx->params.rParams;
rParams->dictionary_size = MIN(params->dictionarySize, FL2_DICTSIZE_MAX); /* allows for reduced dict in 32-bit version */
rParams->match_buffer_resize = FL2_BUFFER_RESIZE_DEFAULT;
rParams->overlap_fraction = params->overlapFraction;
rParams->divide_and_conquer = params->divideAndConquer;
rParams->depth = params->searchDepth;
#ifdef RMF_REFERENCE
rParams->use_ref_mf = 1;
#endif
}
static FL2_CCtx* FL2_createCCtx_internal(unsigned nbThreads, int const dualBuffer)
{
nbThreads = FL2_checkNbThreads(nbThreads);
DEBUGLOG(3, "FL2_createCCtxMt : %u threads", nbThreads);
FL2_CCtx* const cctx = calloc(1, sizeof(FL2_CCtx) + (nbThreads - 1) * sizeof(FL2_job));
if (cctx == NULL)
return NULL;
cctx->jobCount = nbThreads;
for (unsigned u = 0; u < nbThreads; ++u)
cctx->jobs[u].enc = NULL;
#ifndef NO_XXHASH
cctx->params.doXXH = 1;
#endif
cctx->matchTable = NULL;
#ifndef FL2_SINGLETHREAD
cctx->compressThread = NULL;
cctx->factory = FL2POOL_create(nbThreads - 1);
if (nbThreads > 1 && cctx->factory == NULL) {
FL2_freeCCtx(cctx);
return NULL;
}
if (dualBuffer) {
cctx->compressThread = FL2POOL_create(1);
if (cctx->compressThread == NULL)
return NULL;
}
#endif
for (unsigned u = 0; u < nbThreads; ++u) {
cctx->jobs[u].enc = LZMA2_createECtx();
if (cctx->jobs[u].enc == NULL) {
FL2_freeCCtx(cctx);
return NULL;
}
cctx->jobs[u].cctx = cctx;
}
DICT_construct(&cctx->buf, dualBuffer);
FL2_CCtx_setParameter(cctx, FL2_p_compressionLevel, FL2_CLEVEL_DEFAULT);
cctx->params.cParams.reset_interval = 4;
return cctx;
}
FL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtx(void)
{
return FL2_createCCtx_internal(1, 0);
}
FL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtxMt(unsigned nbThreads)
{
return FL2_createCCtx_internal(nbThreads, 0);
}
FL2LIB_API void FL2LIB_CALL FL2_freeCCtx(FL2_CCtx* cctx)
{
if (cctx == NULL)
return;
DEBUGLOG(3, "FL2_freeCCtx : %u threads", cctx->jobCount);
DICT_destruct(&cctx->buf);
for (unsigned u = 0; u < cctx->jobCount; ++u) {
LZMA2_freeECtx(cctx->jobs[u].enc);
}
#ifndef FL2_SINGLETHREAD
FL2POOL_free(cctx->factory);
FL2POOL_free(cctx->compressThread);
#endif
RMF_freeMatchTable(cctx->matchTable);
free(cctx);
}
FL2LIB_API unsigned FL2LIB_CALL FL2_getCCtxThreadCount(const FL2_CCtx* cctx)
{
return cctx->jobCount;
}
/* FL2_buildRadixTable() : FL2POOL_function type */
static void FL2_buildRadixTable(void* const jobDescription, ptrdiff_t const n)
{
FL2_CCtx* const cctx = (FL2_CCtx*)jobDescription;
RMF_buildTable(cctx->matchTable, n, 1, cctx->curBlock);
}
/* FL2_compressRadixChunk() : FL2POOL_function type */
static void FL2_compressRadixChunk(void* const jobDescription, ptrdiff_t const n)
{
FL2_CCtx* const cctx = (FL2_CCtx*)jobDescription;
cctx->jobs[n].cSize = LZMA2_encode(cctx->jobs[n].enc, cctx->matchTable,
cctx->jobs[n].block,
&cctx->params.cParams,
-1,
&cctx->progressIn, &cctx->progressOut, &cctx->canceled);
}
static int FL2_initEncoders(FL2_CCtx* const cctx)
{
for(unsigned u = 0; u < cctx->jobCount; ++u) {
if (LZMA2_hashAlloc(cctx->jobs[u].enc, &cctx->params.cParams) != 0)
return 1;
}
return 0;
}
static void FL2_initProgress(FL2_CCtx* const cctx)
{
RMF_initProgress(cctx->matchTable);
cctx->progressIn = 0;
cctx->streamCsize += cctx->progressOut;
cctx->progressOut = 0;
cctx->canceled = 0;
}
/* FL2_compressCurBlock_blocking() :
* Compress cctx->curBlock and wait until complete.
* Write streamProp as the first byte if >= 0
*/
static size_t FL2_compressCurBlock_blocking(FL2_CCtx* const cctx, int const streamProp)
{
size_t const encodeSize = (cctx->curBlock.end - cctx->curBlock.start);
#ifndef FL2_SINGLETHREAD
size_t mfThreads = cctx->curBlock.end / RMF_MIN_BYTES_PER_THREAD;
size_t nbThreads = MIN(cctx->jobCount, encodeSize / ENC_MIN_BYTES_PER_THREAD);
nbThreads += !nbThreads;
#else
size_t mfThreads = 1;
size_t nbThreads = 1;
#endif
DEBUGLOG(5, "FL2_compressCurBlock : %u threads, %u start, %u bytes", (U32)nbThreads, (U32)cctx->curBlock.start, (U32)encodeSize);
size_t sliceStart = cctx->curBlock.start;
size_t const sliceSize = encodeSize / nbThreads;
cctx->jobs[0].block.data = cctx->curBlock.data;
cctx->jobs[0].block.start = sliceStart;
cctx->jobs[0].block.end = sliceStart + sliceSize;
for (size_t u = 1; u < nbThreads; ++u) {
sliceStart += sliceSize;
cctx->jobs[u].block.data = cctx->curBlock.data;
cctx->jobs[u].block.start = sliceStart;
cctx->jobs[u].block.end = sliceStart + sliceSize;
}
cctx->jobs[nbThreads - 1].block.end = cctx->curBlock.end;
/* initialize to length 2 */
RMF_initTable(cctx->matchTable, cctx->curBlock.data, cctx->curBlock.end);
if (cctx->canceled) {
RMF_resetIncompleteBuild(cctx->matchTable);
return FL2_ERROR(canceled);
}
#ifndef FL2_SINGLETHREAD
mfThreads = MIN(RMF_threadCount(cctx->matchTable), mfThreads);
FL2POOL_addRange(cctx->factory, FL2_buildRadixTable, cctx, 1, mfThreads);
#endif
int err = RMF_buildTable(cctx->matchTable, 0, mfThreads > 1, cctx->curBlock);
#ifndef FL2_SINGLETHREAD
FL2POOL_waitAll(cctx->factory, 0);
if (err)
return FL2_ERROR(canceled);
#ifdef RMF_CHECK_INTEGRITY
err = RMF_integrityCheck(cctx->matchTable, cctx->curBlock.data, cctx->curBlock.start, cctx->curBlock.end, cctx->params.rParams.depth);
if (err)
return FL2_ERROR(internal);
#endif
FL2POOL_addRange(cctx->factory, FL2_compressRadixChunk, cctx, 1, nbThreads);
cctx->jobs[0].cSize = LZMA2_encode(cctx->jobs[0].enc, cctx->matchTable,
cctx->jobs[0].block,
&cctx->params.cParams, streamProp,
&cctx->progressIn, &cctx->progressOut, &cctx->canceled);
FL2POOL_waitAll(cctx->factory, 0);
#else /* FL2_SINGLETHREAD */
if (err)
return FL2_ERROR(canceled);
#ifdef RMF_CHECK_INTEGRITY
err = RMF_integrityCheck(cctx->matchTable, cctx->curBlock.data, cctx->curBlock.start, cctx->curBlock.end, cctx->params.rParams.depth);
if (err)
return FL2_ERROR(internal);
#endif
cctx->jobs[0].cSize = LZMA2_encode(cctx->jobs[0].enc, cctx->matchTable,
cctx->jobs[0].block,
&cctx->params.cParams, streamProp,
&cctx->progressIn, &cctx->progressOut, &cctx->canceled);
#endif
for (size_t u = 0; u < nbThreads; ++u)
if (FL2_isError(cctx->jobs[u].cSize))
return cctx->jobs[u].cSize;
cctx->threadCount = nbThreads;
return FL2_error_no_error;
}
/* FL2_compressCurBlock_async() : FL2POOL_function type */
static void FL2_compressCurBlock_async(void* const jobDescription, ptrdiff_t const n)
{
FL2_CCtx* const cctx = (FL2_CCtx*)jobDescription;
cctx->asyncRes = FL2_compressCurBlock_blocking(cctx, (int)n);
}
/* FL2_compressCurBlock() :
* Update total input size.
* Clear the compressed data buffers.
* Init progress info.
* Start compression of cctx->curBlock, and wait for completion if no async compression thread exists.
*/
static size_t FL2_compressCurBlock(FL2_CCtx* const cctx, int const streamProp)
{
FL2_initProgress(cctx);
if (cctx->curBlock.start == cctx->curBlock.end)
return FL2_error_no_error;
/* update largest dict size used */
cctx->dictMax = MAX(cctx->dictMax, cctx->curBlock.end);
cctx->outThread = 0;
cctx->threadCount = 0;
cctx->outPos = 0;
U32 rmfWeight = ZSTD_highbit32((U32)cctx->curBlock.end);
U32 depthWeight = 2 + (cctx->params.rParams.depth >= 12) + (cctx->params.rParams.depth >= 28);
U32 encWeight;
if (rmfWeight >= 20) {
rmfWeight = depthWeight * (rmfWeight - 10) + (rmfWeight - 19) * 12;
if (cctx->params.cParams.strategy == 0)
encWeight = 20;
else if (cctx->params.cParams.strategy == 1)
encWeight = 50;
else
encWeight = 60 + cctx->params.cParams.second_dict_bits + ZSTD_highbit32(cctx->params.cParams.fast_length) * 3U;
rmfWeight = (rmfWeight << 4) / (rmfWeight + encWeight);
encWeight = 16 - rmfWeight;
}
else {
rmfWeight = 8;
encWeight = 8;
}
cctx->rmfWeight = rmfWeight;
cctx->encWeight = encWeight;
#ifndef FL2_SINGLETHREAD
if(cctx->compressThread != NULL)
FL2POOL_add(cctx->compressThread, FL2_compressCurBlock_async, cctx, streamProp);
else
#endif
cctx->asyncRes = FL2_compressCurBlock_blocking(cctx, streamProp);
return cctx->asyncRes;
}
/* FL2_getProp() :
* Get the LZMA2 dictionary size property byte. If xxhash is enabled, includes the xxhash flag bit.
*/
static BYTE FL2_getProp(FL2_CCtx* const cctx, size_t const dictionarySize)
{
#ifndef NO_XXHASH
return LZMA2_getDictSizeProp(dictionarySize) | (BYTE)((cctx->params.doXXH != 0) << FL2_PROP_HASH_BIT);
#else
(void)cctx;
return LZMA2_getDictSizeProp(dictionarySize);
#endif
}
static void FL2_preBeginFrame(FL2_CCtx* const cctx, size_t const dictReduce)
{
/* Free unsuitable match table before reallocating anything else */
if (cctx->matchTable && !RMF_compatibleParameters(cctx->matchTable, &cctx->params.rParams, dictReduce)) {
RMF_freeMatchTable(cctx->matchTable);
cctx->matchTable = NULL;
}
}
static size_t FL2_beginFrame(FL2_CCtx* const cctx, size_t const dictReduce)
{
if (FL2_initEncoders(cctx) != 0) /* Create hash objects together, leaving the (large) match table last */
return FL2_ERROR(memory_allocation);
if (cctx->matchTable == NULL) {
cctx->matchTable = RMF_createMatchTable(&cctx->params.rParams, dictReduce, cctx->jobCount);
if (cctx->matchTable == NULL)
return FL2_ERROR(memory_allocation);
}
else {
DEBUGLOG(5, "Have compatible match table");
RMF_applyParameters(cctx->matchTable, &cctx->params.rParams, dictReduce);
}
cctx->dictMax = 0;
cctx->streamTotal = 0;
cctx->streamCsize = 0;
cctx->progressIn = 0;
cctx->progressOut = 0;
RMF_initProgress(cctx->matchTable);
cctx->asyncRes = 0;
cctx->outThread = 0;
cctx->threadCount = 0;
cctx->outPos = 0;
cctx->curBlock.start = 0;
cctx->curBlock.end = 0;
cctx->lockParams = 1;
return FL2_error_no_error;
}
static void FL2_endFrame(FL2_CCtx* const cctx)
{
cctx->dictMax = 0;
cctx->asyncRes = 0;
cctx->lockParams = 0;
}
/* Compress a memory buffer which may be larger than the dictionary.
* The property byte is written first unless the omit flag is set.
* Return: compressed size.
*/
static size_t FL2_compressBuffer(FL2_CCtx* const cctx,
const void* const src, size_t srcSize,
void* const dst, size_t dstCapacity)
{
if (srcSize == 0)
return 0;
BYTE* dstBuf = dst;
size_t const dictionarySize = cctx->params.rParams.dictionary_size;
size_t const blockOverlap = OVERLAP_FROM_DICT_SIZE(dictionarySize, cctx->params.rParams.overlap_fraction);
int streamProp = cctx->params.omitProp ? -1 : FL2_getProp(cctx, MIN(srcSize, dictionarySize));
cctx->curBlock.data = src;
cctx->curBlock.start = 0;
size_t blockTotal = 0;
do {
cctx->curBlock.end = cctx->curBlock.start + MIN(srcSize, dictionarySize - cctx->curBlock.start);
blockTotal += cctx->curBlock.end - cctx->curBlock.start;
CHECK_F(FL2_compressCurBlock(cctx, streamProp));
streamProp = -1;
for (size_t u = 0; u < cctx->threadCount; ++u) {
DEBUGLOG(5, "Write thread %u : %u bytes", (U32)u, (U32)cctx->jobs[u].cSize);
if (dstCapacity < cctx->jobs[u].cSize)
return FL2_ERROR(dstSize_tooSmall);
const BYTE* const outBuf = RMF_getTableAsOutputBuffer(cctx->matchTable, cctx->jobs[u].block.start);
memcpy(dstBuf, outBuf, cctx->jobs[u].cSize);
dstBuf += cctx->jobs[u].cSize;
dstCapacity -= cctx->jobs[u].cSize;
}
srcSize -= cctx->curBlock.end - cctx->curBlock.start;
if (cctx->params.cParams.reset_interval
&& blockTotal + MIN(dictionarySize - blockOverlap, srcSize) > dictionarySize * cctx->params.cParams.reset_interval) {
/* periodically reset the dictionary for mt decompression */
DEBUGLOG(4, "Resetting dictionary after %u bytes", (unsigned)blockTotal);
cctx->curBlock.start = 0;
blockTotal = 0;
}
else {
cctx->curBlock.start = blockOverlap;
}
cctx->curBlock.data += cctx->curBlock.end - cctx->curBlock.start;
} while (srcSize != 0);
return dstBuf - (const BYTE*)dst;
}
FL2LIB_API size_t FL2LIB_CALL FL2_compressCCtx(FL2_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel)
{
if (dstCapacity < 2U - cctx->params.omitProp) /* empty LZMA2 stream is byte sequence {0, 0} */
return FL2_ERROR(dstSize_tooSmall);
if (compressionLevel > 0)
FL2_CCtx_setParameter(cctx, FL2_p_compressionLevel, compressionLevel);
DEBUGLOG(4, "FL2_compressCCtx : level %u, %u src => %u avail", cctx->params.compressionLevel, (U32)srcSize, (U32)dstCapacity);
#ifndef FL2_SINGLETHREAD
/* No async compression for in-memory function */
FL2POOL_free(cctx->compressThread);
cctx->compressThread = NULL;
cctx->timeout = 0;
#endif
FL2_preBeginFrame(cctx, srcSize);
CHECK_F(FL2_beginFrame(cctx, srcSize));
size_t const cSize = FL2_compressBuffer(cctx, src, srcSize, dst, dstCapacity);
if (FL2_isError(cSize))
return cSize;
BYTE* dstBuf = dst;
BYTE* const end = dstBuf + dstCapacity;
dstBuf += cSize;
if(dstBuf >= end)
return FL2_ERROR(dstSize_tooSmall);
if (cSize == 0)
*dstBuf++ = FL2_getProp(cctx, 0);
*dstBuf++ = LZMA2_END_MARKER;
#ifndef NO_XXHASH
if (cctx->params.doXXH && !cctx->params.omitProp) {
XXH32_canonical_t canonical;
DEBUGLOG(5, "Writing hash");
// **************** 7-Zip ZS Modification Start ****************
//if(end - dstBuf < XXHASH_SIZEOF)
if (end - dstBuf < (long)XXHASH_SIZEOF)
// **************** 7-Zip ZS Modification End ****************
return FL2_ERROR(dstSize_tooSmall);
XXH32_canonicalFromHash(&canonical, XXH32(src, srcSize, 0));
memcpy(dstBuf, &canonical, XXHASH_SIZEOF);
dstBuf += XXHASH_SIZEOF;
}
#endif
FL2_endFrame(cctx);
return dstBuf - (BYTE*)dst;
}
FL2LIB_API size_t FL2LIB_CALL FL2_compressMt(void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel,
unsigned nbThreads)
{
FL2_CCtx* const cctx = FL2_createCCtxMt(nbThreads);
if (cctx == NULL)
return FL2_ERROR(memory_allocation);
size_t const cSize = FL2_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);
FL2_freeCCtx(cctx);
return cSize;
}
FL2LIB_API size_t FL2LIB_CALL FL2_compress(void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel)
{
return FL2_compressMt(dst, dstCapacity, src, srcSize, compressionLevel, 1);
}
FL2LIB_API BYTE FL2LIB_CALL FL2_getCCtxDictProp(FL2_CCtx* cctx)
{
return LZMA2_getDictSizeProp(cctx->dictMax ? cctx->dictMax : cctx->params.rParams.dictionary_size);
}
#define MAXCHECK(val,max) do { \
if ((val)>(max)) { \
return FL2_ERROR(parameter_outOfBound); \
} } while(0)
#define CLAMPCHECK(val,min,max) do { \
if (((val)<(min)) | ((val)>(max))) { \
return FL2_ERROR(parameter_outOfBound); \
} } while(0)
FL2LIB_API size_t FL2LIB_CALL FL2_CCtx_setParameter(FL2_CCtx* cctx, FL2_cParameter param, size_t value)
{
if (cctx->lockParams
&& param != FL2_p_literalCtxBits && param != FL2_p_literalPosBits && param != FL2_p_posBits)
return FL2_ERROR(stage_wrong);
switch (param)
{
case FL2_p_compressionLevel:
if (cctx->params.highCompression) {
CLAMPCHECK(value, 1, FL2_MAX_HIGH_CLEVEL);
FL2_fillParameters(cctx, &FL2_highCParameters[value]);
}
else {
CLAMPCHECK(value, 1, FL2_MAX_CLEVEL);
FL2_fillParameters(cctx, &FL2_defaultCParameters[value]);
}
cctx->params.compressionLevel = (unsigned)value;
break;
case FL2_p_highCompression:
cctx->params.highCompression = value != 0;
FL2_CCtx_setParameter(cctx, FL2_p_compressionLevel, cctx->params.compressionLevel);
break;
case FL2_p_dictionaryLog:
CLAMPCHECK(value, FL2_DICTLOG_MIN, FL2_DICTLOG_MAX);
cctx->params.rParams.dictionary_size = (size_t)1 << value;
break;
case FL2_p_dictionarySize:
CLAMPCHECK(value, FL2_DICTSIZE_MIN, FL2_DICTSIZE_MAX);
cctx->params.rParams.dictionary_size = value;
break;
case FL2_p_overlapFraction:
MAXCHECK(value, FL2_BLOCK_OVERLAP_MAX);
cctx->params.rParams.overlap_fraction = (unsigned)value;
break;
case FL2_p_resetInterval:
if (value != 0)
CLAMPCHECK(value, FL2_RESET_INTERVAL_MIN, FL2_RESET_INTERVAL_MAX);
cctx->params.cParams.reset_interval = (unsigned)value;
break;
case FL2_p_bufferResize:
MAXCHECK(value, FL2_BUFFER_RESIZE_MAX);
cctx->params.rParams.match_buffer_resize = (unsigned)value;
break;
case FL2_p_hybridChainLog:
CLAMPCHECK(value, FL2_CHAINLOG_MIN, FL2_CHAINLOG_MAX);
cctx->params.cParams.second_dict_bits = (unsigned)value;
break;
case FL2_p_hybridCycles:
CLAMPCHECK(value, FL2_HYBRIDCYCLES_MIN, FL2_HYBRIDCYCLES_MAX);
cctx->params.cParams.match_cycles = (unsigned)value;
break;
case FL2_p_searchDepth:
CLAMPCHECK(value, FL2_SEARCH_DEPTH_MIN, FL2_SEARCH_DEPTH_MAX);
cctx->params.rParams.depth = (unsigned)value;
break;
case FL2_p_fastLength:
CLAMPCHECK(value, FL2_FASTLENGTH_MIN, FL2_FASTLENGTH_MAX);
cctx->params.cParams.fast_length = (unsigned)value;
break;
case FL2_p_divideAndConquer:
cctx->params.rParams.divide_and_conquer = value != 0;
break;
case FL2_p_strategy:
MAXCHECK(value, (unsigned)FL2_ultra);
cctx->params.cParams.strategy = (FL2_strategy)value;
break;
/* lc, lp, pb can be changed between encoder chunks.
* A condition where lc+lp > 4 is permitted to allow sequential setting,
* but will return an error code to alert the calling function.
* If lc+lp is still >4 when encoding begins, lc will be reduced. */
case FL2_p_literalCtxBits:
MAXCHECK(value, FL2_LC_MAX);
cctx->params.cParams.lc = (unsigned)value;
if (value + cctx->params.cParams.lp > FL2_LCLP_MAX)
return FL2_ERROR(lclpMax_exceeded);
break;
case FL2_p_literalPosBits:
MAXCHECK(value, FL2_LP_MAX);
cctx->params.cParams.lp = (unsigned)value;
if (cctx->params.cParams.lc + value > FL2_LCLP_MAX)
return FL2_ERROR(lclpMax_exceeded);
break;
case FL2_p_posBits:
MAXCHECK(value, FL2_PB_MAX);
cctx->params.cParams.pb = (unsigned)value;
break;
#ifndef NO_XXHASH
case FL2_p_doXXHash:
cctx->params.doXXH = value != 0;
break;
#endif
case FL2_p_omitProperties:
cctx->params.omitProp = value != 0;
break;
#ifdef RMF_REFERENCE
case FL2_p_useReferenceMF:
cctx->params.rParams.use_ref_mf = value != 0;
break;
#endif
default: return FL2_ERROR(parameter_unsupported);
}
return value;
}
FL2LIB_API size_t FL2LIB_CALL FL2_CCtx_getParameter(FL2_CCtx* cctx, FL2_cParameter param)
{
switch (param)
{
case FL2_p_compressionLevel:
return cctx->params.compressionLevel;
case FL2_p_highCompression:
return cctx->params.highCompression;
case FL2_p_dictionaryLog: {
size_t dictLog = FL2_DICTLOG_MIN;
while (((size_t)1 << dictLog) < cctx->params.rParams.dictionary_size)
++dictLog;
return dictLog;
}
case FL2_p_dictionarySize:
return cctx->params.rParams.dictionary_size;
case FL2_p_overlapFraction:
return cctx->params.rParams.overlap_fraction;
case FL2_p_resetInterval:
return cctx->params.cParams.reset_interval;
case FL2_p_bufferResize:
return cctx->params.rParams.match_buffer_resize;
case FL2_p_hybridChainLog:
return cctx->params.cParams.second_dict_bits;
case FL2_p_hybridCycles:
return cctx->params.cParams.match_cycles;
case FL2_p_literalCtxBits:
return cctx->params.cParams.lc;
case FL2_p_literalPosBits:
return cctx->params.cParams.lp;
case FL2_p_posBits:
return cctx->params.cParams.pb;
case FL2_p_searchDepth:
return cctx->params.rParams.depth;
case FL2_p_fastLength:
return cctx->params.cParams.fast_length;
case FL2_p_divideAndConquer:
return cctx->params.rParams.divide_and_conquer;
case FL2_p_strategy:
return (size_t)cctx->params.cParams.strategy;
#ifndef NO_XXHASH
case FL2_p_doXXHash:
return cctx->params.doXXH;
#endif
case FL2_p_omitProperties:
return cctx->params.omitProp;
#ifdef RMF_REFERENCE
case FL2_p_useReferenceMF:
return cctx->params.rParams.use_ref_mf;
#endif
default: return FL2_ERROR(parameter_unsupported);
}
}
FL2LIB_API size_t FL2LIB_CALL FL2_CStream_setParameter(FL2_CStream* fcs, FL2_cParameter param, size_t value)
{
return FL2_CCtx_setParameter(fcs, param, value);
}
FL2LIB_API size_t FL2LIB_CALL FL2_CStream_getParameter(FL2_CStream* fcs, FL2_cParameter param)
{
return FL2_CCtx_getParameter(fcs, param);
}
FL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStream(void)
{
return FL2_createCCtx_internal(1, 0);
}
FL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStreamMt(unsigned nbThreads, int dualBuffer)
{
return FL2_createCCtx_internal(nbThreads, dualBuffer);
}
FL2LIB_API void FL2LIB_CALL FL2_freeCStream(FL2_CStream * fcs)
{
FL2_freeCCtx(fcs);
}
FL2LIB_API size_t FL2LIB_CALL FL2_initCStream(FL2_CStream* fcs, int compressionLevel)
{
DEBUGLOG(4, "FL2_initCStream level %d", compressionLevel);
fcs->endMarked = 0;
fcs->wroteProp = 0;
fcs->loopCount = 0;
if(compressionLevel > 0)
FL2_CCtx_setParameter(fcs, FL2_p_compressionLevel, compressionLevel);
DICT_buffer *const buf = &fcs->buf;
size_t const dictSize = fcs->params.rParams.dictionary_size;
/* Free unsuitable objects before reallocating anything new */
if (DICT_size(buf) < dictSize)
DICT_destruct(buf);
FL2_preBeginFrame(fcs, 0);
#ifdef NO_XXHASH
int const doHash = 0;
#else
int const doHash = (fcs->params.doXXH && !fcs->params.omitProp);
#endif
size_t dictOverlap = OVERLAP_FROM_DICT_SIZE(fcs->params.rParams.dictionary_size, fcs->params.rParams.overlap_fraction);
if (DICT_init(buf, dictSize, dictOverlap, fcs->params.cParams.reset_interval, doHash) != 0)
return FL2_ERROR(memory_allocation);
CHECK_F(FL2_beginFrame(fcs, 0));
return 0;
}
FL2LIB_API size_t FL2LIB_CALL FL2_setCStreamTimeout(FL2_CStream * fcs, unsigned timeout)
{
#ifndef FL2_SINGLETHREAD
if (timeout != 0) {
if (fcs->compressThread == NULL) {
fcs->compressThread = FL2POOL_create(1);
if (fcs->compressThread == NULL)
return FL2_ERROR(memory_allocation);
}
}
else if (!DICT_async(&fcs->buf) && fcs->dictMax == 0) {
/* Only free the thread if not dual buffering and compression not underway */
FL2POOL_free(fcs->compressThread);
fcs->compressThread = NULL;
}
fcs->timeout = timeout;
#endif
return FL2_error_no_error;
}
static size_t FL2_compressStream_internal(FL2_CStream* const fcs, int const ending)
{
CHECK_F(FL2_waitCStream(fcs));
DICT_buffer *const buf = &fcs->buf;
/* no compression can occur while compressed output exists */
if (fcs->outThread == fcs->threadCount && DICT_hasUnprocessed(buf)) {
fcs->streamTotal += fcs->curBlock.end - fcs->curBlock.start;
DICT_getBlock(buf, &fcs->curBlock);
int streamProp = -1;
if (!fcs->wroteProp && !fcs->params.omitProp) {
/* If the LZMA2 property byte is required and not already written,
* pass it to the compression function
*/
size_t dictionarySize = ending ? MAX(fcs->dictMax, fcs->curBlock.end)
: fcs->params.rParams.dictionary_size;
streamProp = FL2_getProp(fcs, dictionarySize);
DEBUGLOG(4, "Writing property byte : 0x%X", streamProp);
fcs->wroteProp = 1;
}
CHECK_F(FL2_compressCurBlock(fcs, streamProp));
}
return FL2_error_no_error;
}
/* Copy the compressed output stored in the match table buffer.
* One slice exists per thread.
*/
FL2LIB_API size_t FL2LIB_CALL FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output)
{
for (; fcs->outThread < fcs->threadCount; ++fcs->outThread) {
const BYTE* const outBuf = RMF_getTableAsOutputBuffer(fcs->matchTable, fcs->jobs[fcs->outThread].block.start) + fcs->outPos;
BYTE* const dstBuf = (BYTE*)output->dst + output->pos;
size_t const dstCapacity = output->size - output->pos;
size_t toWrite = fcs->jobs[fcs->outThread].cSize;
toWrite = MIN(toWrite - fcs->outPos, dstCapacity);
DEBUGLOG(5, "CStream : writing %u bytes", (U32)toWrite);
memcpy(dstBuf, outBuf, toWrite);
fcs->outPos += toWrite;
output->pos += toWrite;
/* If the slice is not flushed, the output is full */
if (fcs->outPos < fcs->jobs[fcs->outThread].cSize)
return 1;
fcs->outPos = 0;
}
return 0;
}
static size_t FL2_compressStream_input(FL2_CStream* fcs, FL2_inBuffer* input)
{
CHECK_F(fcs->asyncRes);
DICT_buffer * const buf = &fcs->buf;
while (input->pos < input->size) {
/* read input until the buffer(s) are full */
if (DICT_needShift(buf)) {
/* cannot shift single dict during compression */
if(!DICT_async(buf))
CHECK_F(FL2_waitCStream(fcs));
DICT_shift(buf);
}
CHECK_F(fcs->asyncRes);
DICT_put(buf, input);
if (!DICT_availSpace(buf)) {
/* break if the compressor is not available */
if (fcs->outThread < fcs->threadCount)
break;
CHECK_F(FL2_compressStream_internal(fcs, 0));
}
CHECK_F(fcs->asyncRes);
}
return FL2_error_no_error;
}
static size_t FL2_loopCheck(FL2_CStream* fcs, int unchanged)
{
if (unchanged) {
++fcs->loopCount;
if (fcs->loopCount > FL2_MAX_LOOPS) {
FL2_cancelCStream(fcs);
return FL2_ERROR(buffer);
}
}
else {
fcs->loopCount = 0;
}
return FL2_error_no_error;
}
FL2LIB_API size_t FL2LIB_CALL FL2_compressStream(FL2_CStream* fcs, FL2_outBuffer *output, FL2_inBuffer* input)
{
if (!fcs->lockParams)
return FL2_ERROR(init_missing);
size_t const prevIn = input->pos;
size_t const prevOut = (output != NULL) ? output->pos : 0;
if (output != NULL && fcs->outThread < fcs->threadCount)
FL2_copyCStreamOutput(fcs, output);
CHECK_F(FL2_compressStream_input(fcs, input));
if(output != NULL && fcs->outThread < fcs->threadCount)
FL2_copyCStreamOutput(fcs, output);
CHECK_F(FL2_loopCheck(fcs, prevIn == input->pos && (output == NULL || prevOut == output->pos)));
return fcs->outThread < fcs->threadCount;
}
FL2LIB_API size_t FL2LIB_CALL FL2_getDictionaryBuffer(FL2_CStream * fcs, FL2_dictBuffer * dict)
{
if (!fcs->lockParams)
return FL2_ERROR(init_missing);
CHECK_F(fcs->asyncRes);
DICT_buffer *buf = &fcs->buf;
if (!DICT_availSpace(buf) && DICT_hasUnprocessed(buf))
CHECK_F(FL2_compressStream_internal(fcs, 0));
if (DICT_needShift(buf) && !DICT_async(buf))
CHECK_F(FL2_waitCStream(fcs));
dict->size = (unsigned long)DICT_get(buf, &dict->dst);
return FL2_error_no_error;
}
FL2LIB_API size_t FL2LIB_CALL FL2_updateDictionary(FL2_CStream * fcs, size_t addedSize)
{
if (DICT_update(&fcs->buf, addedSize))
CHECK_F(FL2_compressStream_internal(fcs, 0));
return fcs->outThread < fcs->threadCount;
}
FL2LIB_API size_t FL2LIB_CALL FL2_getNextCompressedBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf)
{
cbuf->src = NULL;
cbuf->size = 0;
#ifndef FL2_SINGLETHREAD
CHECK_F(FL2_waitCStream(fcs));
#endif
if (fcs->outThread < fcs->threadCount) {
cbuf->src = RMF_getTableAsOutputBuffer(fcs->matchTable, fcs->jobs[fcs->outThread].block.start) + fcs->outPos;
cbuf->size = fcs->jobs[fcs->outThread].cSize - fcs->outPos;
++fcs->outThread;
fcs->outPos = 0;
}
return cbuf->size;
}
FL2LIB_API unsigned long long FL2LIB_CALL FL2_getCStreamProgress(const FL2_CStream * fcs, unsigned long long *outputSize)
{
if (outputSize != NULL)
*outputSize = fcs->streamCsize + fcs->progressOut;
U64 const encodeSize = fcs->curBlock.end - fcs->curBlock.start;
if (fcs->progressIn == 0 && fcs->curBlock.end != 0)
return fcs->streamTotal + ((fcs->matchTable->progress * encodeSize / fcs->curBlock.end * fcs->rmfWeight) >> 4);
return fcs->streamTotal + ((fcs->rmfWeight * encodeSize) >> 4) + ((fcs->progressIn * fcs->encWeight) >> 4);
}
FL2LIB_API size_t FL2LIB_CALL FL2_waitCStream(FL2_CStream * fcs)
{
#ifndef FL2_SINGLETHREAD
if (FL2POOL_waitAll(fcs->compressThread, fcs->timeout) != 0)
return FL2_ERROR(timedOut);
CHECK_F(fcs->asyncRes);
#endif
return fcs->outThread < fcs->threadCount;
}
FL2LIB_API void FL2LIB_CALL FL2_cancelCStream(FL2_CStream *fcs)
{
#ifndef FL2_SINGLETHREAD
if (fcs->compressThread != NULL) {
fcs->canceled = 1;
RMF_cancelBuild(fcs->matchTable);
FL2POOL_waitAll(fcs->compressThread, 0);
fcs->canceled = 0;
}
#endif
FL2_endFrame(fcs);
}
FL2LIB_API size_t FL2LIB_CALL FL2_remainingOutputSize(const FL2_CStream* fcs)
{
CHECK_F(fcs->asyncRes);
size_t cSize = 0;
for (size_t u = fcs->outThread; u < fcs->threadCount; ++u)
cSize += fcs->jobs[u].cSize;
return cSize;
}
/* Write the properties byte (if required), the hash and the end marker
* into the output buffer.
*/
static void FL2_writeEnd(FL2_CStream* const fcs)
{
size_t thread = fcs->threadCount - 1;
if (fcs->outThread == fcs->threadCount) {
fcs->outThread = 0;
fcs->threadCount = 1;
fcs->jobs[0].cSize = 0;
thread = 0;
}
BYTE *const dst = RMF_getTableAsOutputBuffer(fcs->matchTable, fcs->jobs[thread].block.start)
+ fcs->jobs[thread].cSize;
size_t pos = 0;
if (!fcs->wroteProp && !fcs->params.omitProp) {
/* no compression occurred */
dst[pos] = FL2_getProp(fcs, 0);
DEBUGLOG(4, "Writing property byte : 0x%X", dst[pos]);
++pos;
fcs->wroteProp = 1;
}
DEBUGLOG(4, "Writing end marker");
dst[pos++] = LZMA2_END_MARKER;
#ifndef NO_XXHASH
if (fcs->params.doXXH && !fcs->params.omitProp) {
XXH32_canonical_t canonical;
XXH32_canonicalFromHash(&canonical, DICT_getDigest(&fcs->buf));
DEBUGLOG(4, "Writing XXH32");
memcpy(dst + pos, &canonical, XXHASH_SIZEOF);
pos += XXHASH_SIZEOF;
}
#endif
fcs->jobs[thread].cSize += pos;
fcs->endMarked = 1;
FL2_endFrame(fcs);
}
static size_t FL2_flushStream_internal(FL2_CStream* fcs, int const ending)
{
CHECK_F(fcs->asyncRes);
DEBUGLOG(4, "FL2_flushStream_internal : %u to compress, %u to write",
(U32)(fcs->buf.end - fcs->buf.start),
(U32)FL2_remainingOutputSize(fcs));
CHECK_F(FL2_compressStream_internal(fcs, ending));
return fcs->outThread < fcs->threadCount;
}
FL2LIB_API size_t FL2LIB_CALL FL2_flushStream(FL2_CStream* fcs, FL2_outBuffer *output)
{
if (!fcs->lockParams)
return FL2_ERROR(init_missing);
size_t const prevOut = (output != NULL) ? output->pos : 0;
if (output != NULL && fcs->outThread < fcs->threadCount)
FL2_copyCStreamOutput(fcs, output);
size_t res = FL2_flushStream_internal(fcs, 0);
CHECK_F(res);
if (output != NULL && res != 0) {
FL2_copyCStreamOutput(fcs, output);
res = fcs->outThread < fcs->threadCount;
}
CHECK_F(FL2_loopCheck(fcs, output != NULL && prevOut == output->pos));
return res;
}
FL2LIB_API size_t FL2LIB_CALL FL2_endStream(FL2_CStream* fcs, FL2_outBuffer *output)
{
if (!fcs->endMarked && !fcs->lockParams)
return FL2_ERROR(init_missing);
size_t const prevOut = (output != NULL) ? output->pos : 0;
if (output != NULL && fcs->outThread < fcs->threadCount)
FL2_copyCStreamOutput(fcs, output);
CHECK_F(FL2_flushStream_internal(fcs, 1));
size_t res = FL2_waitCStream(fcs);
CHECK_F(res);
if (!fcs->endMarked && !DICT_hasUnprocessed(&fcs->buf)) {
FL2_writeEnd(fcs);
res = 1;
}
if (output != NULL && res != 0) {
FL2_copyCStreamOutput(fcs, output);
res = fcs->outThread < fcs->threadCount || DICT_hasUnprocessed(&fcs->buf);
}
CHECK_F(FL2_loopCheck(fcs, output != NULL && prevOut == output->pos));
return res;
}
FL2LIB_API size_t FL2LIB_CALL FL2_getLevelParameters(int compressionLevel, int high, FL2_compressionParameters * params)
{
if (high) {
if (compressionLevel < 0 || compressionLevel > FL2_MAX_HIGH_CLEVEL)
return FL2_ERROR(parameter_outOfBound);
*params = FL2_highCParameters[compressionLevel];
}
else {
if (compressionLevel < 0 || compressionLevel > FL2_MAX_CLEVEL)
return FL2_ERROR(parameter_outOfBound);
*params = FL2_defaultCParameters[compressionLevel];
}
return FL2_error_no_error;
}
static size_t FL2_memoryUsage_internal(size_t const dictionarySize, unsigned const bufferResize,
unsigned const chainLog,
FL2_strategy const strategy,
unsigned const nbThreads)
{
return RMF_memoryUsage(dictionarySize, bufferResize, nbThreads)
+ LZMA2_encMemoryUsage(chainLog, strategy, nbThreads);
}
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize(int compressionLevel, unsigned nbThreads)
{
if (compressionLevel == 0)
compressionLevel = FL2_CLEVEL_DEFAULT;
CLAMPCHECK(compressionLevel, 1, FL2_MAX_CLEVEL);
return FL2_estimateCCtxSize_byParams(FL2_defaultCParameters + compressionLevel, nbThreads);
}
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_byParams(const FL2_compressionParameters * params, unsigned nbThreads)
{
nbThreads = FL2_checkNbThreads(nbThreads);
return FL2_memoryUsage_internal(params->dictionarySize,
FL2_BUFFER_RESIZE_DEFAULT,
params->chainLog,
params->strategy,
nbThreads);
}
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_usingCCtx(const FL2_CCtx * cctx)
{
return FL2_memoryUsage_internal(cctx->params.rParams.dictionary_size,
cctx->params.rParams.match_buffer_resize,
cctx->params.cParams.second_dict_bits,
cctx->params.cParams.strategy,
cctx->jobCount) + DICT_memUsage(&cctx->buf);
}
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize(int compressionLevel, unsigned nbThreads, int dualBuffer)
{
return FL2_estimateCCtxSize(compressionLevel, nbThreads)
+ (FL2_defaultCParameters[compressionLevel].dictionarySize << (dualBuffer != 0));
}
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_byParams(const FL2_compressionParameters * params, unsigned nbThreads, int dualBuffer)
{
return FL2_estimateCCtxSize_byParams(params, nbThreads)
+ (params->dictionarySize << (dualBuffer != 0));
}
FL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_usingCStream(const FL2_CStream* fcs)
{
return FL2_estimateCCtxSize_usingCCtx(fcs);
}
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_compress_internal.h
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
* Parts based on zstd_compress_internal.h copyright Yann Collet
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef FL2_COMPRESS_H
#define FL2_COMPRESS_H
/*-*************************************
* Dependencies
***************************************/
#include "mem.h"
#include "data_block.h"
#include "radix_internal.h"
#include "lzma2_enc.h"
#include "fast-lzma2.h"
#include "fl2_threading.h"
#include "fl2_pool.h"
#include "dict_buffer.h"
#ifndef NO_XXHASH
# include "xxhash.h"
#endif
#if defined (__cplusplus)
extern "C" {
#endif
/*-*************************************
* Context memory management
***************************************/
typedef struct {
FL2_lzma2Parameters cParams;
RMF_parameters rParams;
unsigned compressionLevel;
BYTE highCompression;
#ifndef NO_XXHASH
BYTE doXXH;
#endif
BYTE omitProp;
} FL2_CCtx_params;
typedef struct {
FL2_CCtx* cctx;
LZMA2_ECtx* enc;
FL2_dataBlock block;
size_t cSize;
} FL2_job;
struct FL2_CCtx_s {
DICT_buffer buf;
FL2_CCtx_params params;
#ifndef FL2_SINGLETHREAD
FL2POOL_ctx* factory;
FL2POOL_ctx* compressThread;
#endif
FL2_dataBlock curBlock;
size_t asyncRes;
size_t threadCount;
size_t outThread;
size_t outPos;
size_t dictMax;
U64 streamTotal;
U64 streamCsize;
FL2_matchTable* matchTable;
#ifndef FL2_SINGLETHREAD
U32 timeout;
#endif
U32 rmfWeight;
U32 encWeight;
FL2_atomic progressIn;
FL2_atomic progressOut;
int canceled;
BYTE wroteProp;
BYTE endMarked;
BYTE loopCount;
BYTE lockParams;
unsigned jobCount;
FL2_job jobs[1];
};
#if defined (__cplusplus)
}
#endif
#endif /* FL2_COMPRESS_H */
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_errors.h
================================================
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* All rights reserved.
* Modified for FL2 by Conor McCarthy
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef FL2_ERRORS_H_398273423
#define FL2_ERRORS_H_398273423
#if defined (__cplusplus)
extern "C" {
#endif
/*===== dependency =====*/
#include /* size_t */
#include "fast-lzma2.h"
/*-****************************************
* error codes list
* note : this API is still considered unstable
* and shall not be used with a dynamic library.
* only static linking is allowed
******************************************/
typedef enum {
FL2_error_no_error = 0,
FL2_error_GENERIC = 1,
FL2_error_internal = 2,
FL2_error_corruption_detected = 3,
FL2_error_checksum_wrong = 4,
FL2_error_parameter_unsupported = 5,
FL2_error_parameter_outOfBound = 6,
FL2_error_lclpMax_exceeded = 7,
FL2_error_stage_wrong = 8,
FL2_error_init_missing = 9,
FL2_error_memory_allocation = 10,
FL2_error_dstSize_tooSmall = 11,
FL2_error_srcSize_wrong = 12,
FL2_error_canceled = 13,
FL2_error_buffer = 14,
FL2_error_timedOut = 15,
FL2_error_maxCode = 20 /* never EVER use this value directly, it can change in future versions! Use FL2_isError() instead */
} FL2_ErrorCode;
/*! FL2_getErrorCode() :
convert a `size_t` function result into a `FL2_ErrorCode` enum type,
which can be used to compare with enum list published above */
FL2LIB_API FL2_ErrorCode FL2LIB_CALL FL2_getErrorCode(size_t functionResult);
FL2LIB_API const char* FL2LIB_CALL FL2_getErrorString(FL2_ErrorCode code); /**< Same as FL2_getErrorName, but using a `FL2_ErrorCode` enum argument */
#if defined (__cplusplus)
}
#endif
#endif /* FL2_ERRORS_H_398273423 */
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_internal.h
================================================
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* All rights reserved.
* Modified for FL2 by Conor McCarthy
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef FL2_INTERNAL_H_
#define FL2_INTERNAL_H_
/*-*************************************
* Dependencies
***************************************/
#include "mem.h"
#include "compiler.h"
#if defined (__cplusplus)
extern "C" {
#endif
/*-****************************************
* Error codes handling
******************************************/
#define PREFIX(name) FL2_error_##name
#define FL2_ERROR(name) ((size_t)-PREFIX(name))
/*-*************************************
* Stream properties
***************************************/
#define FL2_PROP_HASH_BIT 7
#define FL2_LZMA_PROP_MASK 0x3FU
#ifndef NO_XXHASH
# define XXHASH_SIZEOF sizeof(XXH32_canonical_t)
#endif
/*-*************************************
* Debug
***************************************/
#if defined(FL2_DEBUG) && (FL2_DEBUG>=1)
# include
#else
# ifndef assert
# define assert(condition) ((void)0)
# endif
#endif
#define FL2_STATIC_ASSERT(c) { enum { FL2_static_assert = 1/(int)(!!(c)) }; }
// **************** NanaZip Modification Start ****************
#if 0 // ******** Annotated FastLZMA2 Mainline Source Code snippet Start ********
#if defined(FL2_DEBUG) && (FL2_DEBUG>=2)
# include
extern int g_debuglog_enable;
/* recommended values for FL2_DEBUG display levels :
* 1 : no display, enables assert() only
* 2 : reserved for currently active debugging path
* 3 : events once per object lifetime (CCtx, CDict)
* 4 : events once per frame
* 5 : events once per block
* 6 : events once per sequence (*very* verbose) */
# define RAWLOG(l, ...) { \
if ((g_debuglog_enable) & (l<=FL2_DEBUG)) { \
fprintf(stderr, __VA_ARGS__); \
} }
# define DEBUGLOG(l, ...) { \
if ((g_debuglog_enable) & (l<=FL2_DEBUG)) { \
fprintf(stderr, __FILE__ ": "); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, " \n"); \
} }
#else
# define RAWLOG(l, ...) {} /* disabled */
# define DEBUGLOG(l, ...) {} /* disabled */
#endif
#endif // ******** Annotated FastLZMA2 Mainline Source Code snippet End ********
// **************** NanaZip Modification End ****************
/*-*************************************
* shared macros
***************************************/
#undef MIN
#undef MAX
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b))
#define CHECK_F(f) do { size_t const errcod = f; if (FL2_isError(errcod)) return errcod; } while(0) /* check and Forward error code */
#define CHECK_E(f, e) do { size_t const errcod = f; if (FL2_isError(errcod)) return FL2_ERROR(e); } while(0) /* check and send Error code */
MEM_STATIC U32 ZSTD_highbit32(U32 val)
{
assert(val != 0);
{
# if defined(_MSC_VER) /* Visual */
unsigned long r=0;
_BitScanReverse(&r, val);
return (unsigned)r;
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
return 31 - __builtin_clz(val);
# else /* Software version */
static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
U32 v = val;
int r;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
return r;
# endif
}
}
#if defined (__cplusplus)
}
#endif
#endif /* FL2_INTERNAL_H_ */
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_pool.c
================================================
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* All rights reserved.
* Modified for FL2 by Conor McCarthy
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
/* ====== Dependencies ======= */
#include /* size_t */
#include /* malloc, calloc */
#include "fl2_pool.h"
#include "fl2_internal.h"
#ifndef FL2_SINGLETHREAD
#include "fl2_threading.h" /* pthread adaptation */
struct FL2POOL_ctx_s {
/* Keep track of the threads */
size_t numThreads;
/* All threads work on the same function and object during a job */
FL2POOL_function function;
void *opaque;
/* The number of threads working on jobs */
size_t numThreadsBusy;
/* Indicates the number of threads requested and the values to pass */
ptrdiff_t queueIndex;
ptrdiff_t queueEnd;
/* The mutex protects the queue */
FL2_pthread_mutex_t queueMutex;
/* Condition variable for pushers to wait on when the queue is full */
FL2_pthread_cond_t busyCond;
/* Condition variable for poppers to wait on when the queue is empty */
FL2_pthread_cond_t newJobsCond;
/* Indicates if the queue is shutting down */
int shutdown;
/* The threads. Extras to be calloc'd */
FL2_pthread_t threads[1];
};
/* FL2POOL_thread() :
Work thread for the thread pool.
Waits for jobs and executes them.
@returns : NULL on failure else non-null.
*/
static void* FL2POOL_thread(void* opaque)
{
FL2POOL_ctx* const ctx = (FL2POOL_ctx*)opaque;
if (!ctx) { return NULL; }
FL2_pthread_mutex_lock(&ctx->queueMutex);
for (;;) {
/* While the mutex is locked, wait for a non-empty queue or until shutdown */
while (ctx->queueIndex >= ctx->queueEnd && !ctx->shutdown) {
FL2_pthread_cond_wait(&ctx->newJobsCond, &ctx->queueMutex);
}
/* empty => shutting down: so stop */
if (ctx->shutdown) {
FL2_pthread_mutex_unlock(&ctx->queueMutex);
return opaque;
}
/* Pop a job off the queue */
size_t n = ctx->queueIndex;
++ctx->queueIndex;
++ctx->numThreadsBusy;
/* Unlock the mutex and run the job */
FL2_pthread_mutex_unlock(&ctx->queueMutex);
ctx->function(ctx->opaque, n);
FL2_pthread_mutex_lock(&ctx->queueMutex);
--ctx->numThreadsBusy;
/* Signal the master thread waiting for jobs to complete */
FL2_pthread_cond_signal(&ctx->busyCond);
} /* for (;;) */
/* Unreachable */
}
FL2POOL_ctx* FL2POOL_create(size_t numThreads)
{
FL2POOL_ctx* ctx;
/* Check the parameters */
if (!numThreads) { return NULL; }
/* Allocate the context and zero initialize */
ctx = calloc(1, sizeof(FL2POOL_ctx) + (numThreads - 1) * sizeof(FL2_pthread_t));
if (!ctx) { return NULL; }
/* Initialize the busy count and jobs range */
ctx->numThreadsBusy = 0;
ctx->queueIndex = 0;
ctx->queueEnd = 0;
(void)FL2_pthread_mutex_init(&ctx->queueMutex, NULL);
(void)FL2_pthread_cond_init(&ctx->busyCond, NULL);
(void)FL2_pthread_cond_init(&ctx->newJobsCond, NULL);
ctx->shutdown = 0;
ctx->numThreads = 0;
/* Initialize the threads */
{ size_t i;
for (i = 0; i < numThreads; ++i) {
if (FL2_pthread_create(&ctx->threads[i], NULL, &FL2POOL_thread, ctx)) {
ctx->numThreads = i;
FL2POOL_free(ctx);
return NULL;
} }
ctx->numThreads = numThreads;
}
return ctx;
}
/*! FL2POOL_join() :
Shutdown the queue, wake any sleeping threads, and join all of the threads.
*/
static void FL2POOL_join(FL2POOL_ctx* ctx)
{
/* Shut down the queue */
FL2_pthread_mutex_lock(&ctx->queueMutex);
ctx->shutdown = 1;
/* Wake up sleeping threads */
FL2_pthread_cond_broadcast(&ctx->newJobsCond);
FL2_pthread_mutex_unlock(&ctx->queueMutex);
/* Join all of the threads */
for (size_t i = 0; i < ctx->numThreads; ++i)
FL2_pthread_join(ctx->threads[i], NULL);
}
void FL2POOL_free(FL2POOL_ctx *ctx)
{
if (!ctx) { return; }
FL2POOL_join(ctx);
FL2_pthread_mutex_destroy(&ctx->queueMutex);
FL2_pthread_cond_destroy(&ctx->busyCond);
FL2_pthread_cond_destroy(&ctx->newJobsCond);
free(ctx);
}
size_t FL2POOL_sizeof(FL2POOL_ctx *ctx)
{
if (ctx==NULL) return 0; /* supports sizeof NULL */
return sizeof(*ctx) + ctx->numThreads * sizeof(FL2_pthread_t);
}
void FL2POOL_addRange(void* ctxVoid, FL2POOL_function function, void *opaque, ptrdiff_t first, ptrdiff_t end)
{
FL2POOL_ctx* const ctx = (FL2POOL_ctx*)ctxVoid;
if (!ctx)
return;
/* Callers always wait for jobs to complete before adding a new set */
assert(!ctx->numThreadsBusy);
FL2_pthread_mutex_lock(&ctx->queueMutex);
ctx->function = function;
ctx->opaque = opaque;
ctx->queueIndex = first;
ctx->queueEnd = end;
FL2_pthread_cond_broadcast(&ctx->newJobsCond);
FL2_pthread_mutex_unlock(&ctx->queueMutex);
}
void FL2POOL_add(void* ctxVoid, FL2POOL_function function, void *opaque, ptrdiff_t n)
{
FL2POOL_addRange(ctxVoid, function, opaque, n, n + 1);
}
int FL2POOL_waitAll(void *ctxVoid, unsigned timeout)
{
FL2POOL_ctx* const ctx = (FL2POOL_ctx*)ctxVoid;
if (!ctx || (!ctx->numThreadsBusy && ctx->queueIndex >= ctx->queueEnd) || ctx->shutdown) { return 0; }
FL2_pthread_mutex_lock(&ctx->queueMutex);
/* Need to test for ctx->queueIndex < ctx->queueEnd in case not all jobs have started */
if (timeout != 0) {
if ((ctx->numThreadsBusy || ctx->queueIndex < ctx->queueEnd) && !ctx->shutdown)
FL2_pthread_cond_timedwait(&ctx->busyCond, &ctx->queueMutex, timeout);
}
else {
while ((ctx->numThreadsBusy || ctx->queueIndex < ctx->queueEnd) && !ctx->shutdown)
FL2_pthread_cond_wait(&ctx->busyCond, &ctx->queueMutex);
}
FL2_pthread_mutex_unlock(&ctx->queueMutex);
return ctx->numThreadsBusy && !ctx->shutdown;
}
size_t FL2POOL_threadsBusy(void * ctx)
{
return ((FL2POOL_ctx*)ctx)->numThreadsBusy;
}
#endif /* FL2_SINGLETHREAD */
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_pool.h
================================================
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* All rights reserved.
* Modified for FL2 by Conor McCarthy
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef FL2POOL_H
#define FL2POOL_H
#if defined (__cplusplus)
extern "C" {
#endif
#include /* size_t */
typedef struct FL2POOL_ctx_s FL2POOL_ctx;
/*! FL2POOL_create() :
* Create a thread pool with at most `numThreads` threads.
* `numThreads` must be at least 1.
* @return : FL2POOL_ctx pointer on success, else NULL.
*/
FL2POOL_ctx *FL2POOL_create(size_t numThreads);
/*! FL2POOL_free() :
Free a thread pool returned by FL2POOL_create().
*/
void FL2POOL_free(FL2POOL_ctx *ctx);
/*! FL2POOL_sizeof() :
return memory usage of pool returned by FL2POOL_create().
*/
size_t FL2POOL_sizeof(FL2POOL_ctx *ctx);
/*! FL2POOL_function :
The function type that can be added to a thread pool.
*/
typedef void(*FL2POOL_function)(void *, ptrdiff_t);
/*! FL2POOL_add() :
Add the job `function(opaque)` to the thread pool.
FL2POOL_addRange adds multiple jobs with size_t parameter from first to less than end.
Possibly blocks until there is room in the queue.
Note : The function may be executed asynchronously, so `opaque` must live until the function has been completed.
*/
void FL2POOL_add(void* ctxVoid, FL2POOL_function function, void *opaque, ptrdiff_t n);
void FL2POOL_addRange(void *ctx, FL2POOL_function function, void *opaque, ptrdiff_t first, ptrdiff_t end);
int FL2POOL_waitAll(void *ctx, unsigned timeout);
size_t FL2POOL_threadsBusy(void *ctx);
#if defined (__cplusplus)
}
#endif
#endif
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_threading.c
================================================
/**
* Copyright (c) 2016 Tino Reichardt
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
*
* You can contact the author at:
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
*/
/**
* This file will hold wrapper for systems, which do not support pthreads
*/
/* create fake symbol to avoid empty translation unit warning */
int g_ZSTD_threading_useles_symbol;
#include "fast-lzma2.h"
#include "fl2_threading.h"
#include "util.h"
#if !defined(FL2_SINGLETHREAD) && defined(_WIN32)
/**
* Windows minimalist Pthread Wrapper, based on :
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
*/
/* === Dependencies === */
#include
#include
/* === Implementation === */
static unsigned __stdcall worker(void *arg)
{
FL2_pthread_t* const thread = (FL2_pthread_t*) arg;
thread->arg = thread->start_routine(thread->arg);
return 0;
}
int FL2_pthread_create(FL2_pthread_t* thread, const void* unused,
void* (*start_routine) (void*), void* arg)
{
(void)unused;
thread->arg = arg;
thread->start_routine = start_routine;
thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);
if (!thread->handle)
return errno;
else
return 0;
}
int FL2_pthread_join(FL2_pthread_t thread, void **value_ptr)
{
DWORD result;
if (!thread.handle) return 0;
result = WaitForSingleObject(thread.handle, INFINITE);
switch (result) {
case WAIT_OBJECT_0:
if (value_ptr) *value_ptr = thread.arg;
return 0;
case WAIT_ABANDONED:
return EINVAL;
default:
return GetLastError();
}
}
#endif /* FL2_SINGLETHREAD */
unsigned FL2_checkNbThreads(unsigned nbThreads)
{
#ifndef FL2_SINGLETHREAD
if (nbThreads == 0) {
nbThreads = UTIL_countPhysicalCores();
nbThreads += !nbThreads;
}
if (nbThreads > FL2_MAXTHREADS) {
nbThreads = FL2_MAXTHREADS;
}
#else
nbThreads = 1;
#endif
return nbThreads;
}
================================================
FILE: NanaZip.Codecs/FastLZMA2/fl2_threading.h
================================================
/**
* Copyright (c) 2016 Tino Reichardt
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
*
* You can contact the author at:
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
*/
#ifndef THREADING_H_938743
#define THREADING_H_938743
#include "mem.h"
#ifndef FL2_XZ_BUILD
# ifdef _WIN32
# define MYTHREAD_VISTA
# else
# define MYTHREAD_POSIX /* posix assumed ; need a better detection method */
# endif
#elif defined(HAVE_CONFIG_H)
# include
#endif
#if defined (__cplusplus)
extern "C" {
#endif
unsigned FL2_checkNbThreads(unsigned nbThreads);
#if !defined(FL2_SINGLETHREAD) && defined(MYTHREAD_VISTA)
/**
* Windows minimalist Pthread Wrapper, based on :
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
*/
#ifdef WINVER
# undef WINVER
#endif
#define WINVER 0x0600
#ifdef _WIN32_WINNT
# undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include
#include
/* mutex */
#define FL2_pthread_mutex_t CRITICAL_SECTION
#define FL2_pthread_mutex_init(a, b) (InitializeCriticalSection((a)), 0)
#define FL2_pthread_mutex_destroy(a) DeleteCriticalSection((a))
#define FL2_pthread_mutex_lock(a) EnterCriticalSection((a))
#define FL2_pthread_mutex_unlock(a) LeaveCriticalSection((a))
/* condition variable */
#define FL2_pthread_cond_t CONDITION_VARIABLE
#define FL2_pthread_cond_init(a, b) (InitializeConditionVariable((a)), 0)
#define FL2_pthread_cond_destroy(a) /* No delete */
#define FL2_pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
#define FL2_pthread_cond_timedwait(a, b, c) SleepConditionVariableCS((a), (b), (c))
#define FL2_pthread_cond_signal(a) WakeConditionVariable((a))
#define FL2_pthread_cond_broadcast(a) WakeAllConditionVariable((a))
/* FL2_pthread_create() and FL2_pthread_join() */
typedef struct {
HANDLE handle;
void* (*start_routine)(void*);
void* arg;
} FL2_pthread_t;
int FL2_pthread_create(FL2_pthread_t* thread, const void* unused,
void* (*start_routine) (void*), void* arg);
int FL2_pthread_join(FL2_pthread_t thread, void** value_ptr);
/**
* add here more wrappers as required
*/
#elif !defined(FL2_SINGLETHREAD) && defined(MYTHREAD_POSIX)
/* === POSIX Systems === */
# include
# include
#define FL2_pthread_mutex_t pthread_mutex_t
#define FL2_pthread_mutex_init(a, b) pthread_mutex_init((a), (b))
#define FL2_pthread_mutex_destroy(a) pthread_mutex_destroy((a))
#define FL2_pthread_mutex_lock(a) pthread_mutex_lock((a))
#define FL2_pthread_mutex_unlock(a) pthread_mutex_unlock((a))
#define FL2_pthread_cond_t pthread_cond_t
#define FL2_pthread_cond_init(a, b) pthread_cond_init((a), (b))
#define FL2_pthread_cond_destroy(a) pthread_cond_destroy((a))
#define FL2_pthread_cond_wait(a, b) pthread_cond_wait((a), (b))
#define FL2_pthread_cond_signal(a) pthread_cond_signal((a))
#define FL2_pthread_cond_broadcast(a) pthread_cond_broadcast((a))
#define FL2_pthread_t pthread_t
#define FL2_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
#define FL2_pthread_join(a, b) pthread_join((a),(b))
/* Timed wait functions from XZ by Lasse Collin
*/
/* Sets condtime to the absolute time that is timeout_ms milliseconds
* in the future.
*/
static inline void
mythread_condtime_set(struct timespec *condtime, U32 timeout_ms)
{
condtime->tv_sec = timeout_ms / 1000;
condtime->tv_nsec = (timeout_ms % 1000) * 1000000;
struct timeval now;
gettimeofday(&now, NULL);
condtime->tv_sec += now.tv_sec;
condtime->tv_nsec += now.tv_usec * 1000L;
/* tv_nsec must stay in the range [0, 999_999_999]. */
if (condtime->tv_nsec >= 1000000000L) {
condtime->tv_nsec -= 1000000000L;
++condtime->tv_sec;
}
}
/* Waits on a condition or until a timeout expires. If the timeout expires,
* non-zero is returned, otherwise zero is returned.
*/
static inline void
FL2_pthread_cond_timedwait(FL2_pthread_cond_t *cond, FL2_pthread_mutex_t *mutex,
U32 timeout_ms)
{
struct timespec condtime;
mythread_condtime_set(&condtime, timeout_ms);
pthread_cond_timedwait(cond, mutex, &condtime);
}
#elif defined(FL2_SINGLETHREAD)
/* No multithreading support */
typedef int FL2_pthread_mutex_t;
#define FL2_pthread_mutex_init(a, b) ((void)a, 0)
#define FL2_pthread_mutex_destroy(a)
#define FL2_pthread_mutex_lock(a)
#define FL2_pthread_mutex_unlock(a)
typedef int FL2_pthread_cond_t;
#define FL2_pthread_cond_init(a, b) ((void)a, 0)
#define FL2_pthread_cond_destroy(a)
#define FL2_pthread_cond_wait(a, b)
#define FL2_pthread_cond_signal(a)
#define FL2_pthread_cond_broadcast(a)
/* do not use FL2_pthread_t */
#else
# error FL2_SINGLETHREAD not defined but no threading support found
#endif /* FL2_SINGLETHREAD */
#if defined (__cplusplus)
}
#endif
#endif /* THREADING_H_938743 */
================================================
FILE: NanaZip.Codecs/FastLZMA2/lzma2_enc.c
================================================
/* lzma2_enc.c -- LZMA2 Encoder
Based on LzmaEnc.c and Lzma2Enc.c : Igor Pavlov
Modified for FL2 by Conor McCarthy
Public domain
*/
#include
#include
#include "fl2_errors.h"
#include "fl2_internal.h"
#include "lzma2_enc.h"
#include "fl2_compress_internal.h"
#include "mem.h"
#include "count.h"
#include "radix_mf.h"
#include "range_enc.h"
#ifdef FL2_XZ_BUILD
# include "tuklib_integer.h"
# define MEM_readLE32(a) unaligned_read32le(a)
# ifdef TUKLIB_FAST_UNALIGNED_ACCESS
# define MEM_read16(a) (*(const U16*)(a))
# endif
#endif
#define kNumReps 4U
#define kNumStates 12U
#define kNumLiterals 0x100U
#define kNumLitTables 3U
#define kNumLenToPosStates 4U
#define kNumPosSlotBits 6U
#define kDicLogSizeMin 18U
#define kDicLogSizeMax 31U
#define kDistTableSizeMax (kDicLogSizeMax * 2U)
#define kNumAlignBits 4U
#define kAlignTableSize (1U << kNumAlignBits)
#define kAlignMask (kAlignTableSize - 1U)
#define kMatchRepriceFrequency 64U
#define kRepLenRepriceFrequency 64U
#define kStartPosModelIndex 4U
#define kEndPosModelIndex 14U
#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
#define kNumFullDistancesBits (kEndPosModelIndex >> 1U)
#define kNumFullDistances (1U << kNumFullDistancesBits)
#define kNumPositionBitsMax 4U
#define kNumPositionStatesMax (1U << kNumPositionBitsMax)
#define kNumLiteralContextBitsMax 4U
#define kNumLiteralPosBitsMax 4U
#define kLcLpMax 4U
#define kLenNumLowBits 3U
#define kLenNumLowSymbols (1U << kLenNumLowBits)
#define kLenNumHighBits 8U
#define kLenNumHighSymbols (1U << kLenNumHighBits)
#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
#define kMatchLenMin 2U
#define kMatchLenMax (kMatchLenMin + kLenNumSymbolsTotal - 1U)
#define kMatchesMax 65U /* Doesn't need to be larger than FL2_HYBRIDCYCLES_MAX + 1 */
#define kOptimizerEndSize 32U
#define kOptimizerBufferSize (kMatchLenMax * 2U + kOptimizerEndSize)
#define kOptimizerSkipSize 16U
#define kInfinityPrice (1UL << 30U)
#define kNullDist (U32)-1
#define kMaxMatchEncodeSize 20
#define kMaxChunkCompressedSize (1UL << 16U)
/* Need to leave sufficient space for expanded output from a full opt buffer with bad starting probs */
#define kChunkSize (kMaxChunkCompressedSize - 2048U)
#define kSqrtChunkSize 252U
/* Hard to define where the match table read pos definitely catches up with the output size, but
* 64 bytes of input expanding beyond 256 bytes right after an encoder reset is most likely impossible.
* The encoder will error out if this happens. */
#define kTempMinOutput 256U
#define kTempBufferSize (kTempMinOutput + kOptimizerBufferSize + kOptimizerBufferSize / 4U)
#define kMaxChunkUncompressedSize (1UL << 21U)
#define kChunkHeaderSize 5U
#define kChunkResetShift 5U
#define kChunkUncompressedDictReset 1U
#define kChunkUncompressed 2U
#define kChunkCompressedFlag 0x80U
#define kChunkNothingReset 0U
#define kChunkStateReset (1U << kChunkResetShift)
#define kChunkStatePropertiesReset (2U << kChunkResetShift)
#define kChunkAllReset (3U << kChunkResetShift)
#define kMaxHashDictBits 14U
#define kHash3Bits 14U
#define kNullLink -1
#define kMinTestChunkSize 0x4000U
#define kRandomFilterMarginBits 8U
#define kState_LitAfterMatch 4
#define kState_LitAfterRep 5
#define kState_MatchAfterLit 7
#define kState_RepAfterLit 8
static const BYTE kLiteralNextStates[kNumStates] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
#define LIT_NEXT_STATE(s) kLiteralNextStates[s]
static const BYTE kMatchNextStates[kNumStates] = { 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 };
#define MATCH_NEXT_STATE(s) kMatchNextStates[s]
static const BYTE kRepNextStates[kNumStates] = { 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11 };
#define REP_NEXT_STATE(s) kRepNextStates[s]
static const BYTE kShortRepNextStates[kNumStates] = { 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11 };
#define SHORT_REP_NEXT_STATE(s) kShortRepNextStates[s]
#include "fastpos_table.h"
#include "radix_get.h"
/* Probabilities and prices for encoding match lengths.
* Two objects of this type are needed, one for normal matches
* and another for rep matches.
*/
typedef struct
{
size_t table_size;
unsigned prices[kNumPositionStatesMax][kLenNumSymbolsTotal];
LZMA2_prob choice; /* low[0] is choice_2. Must be consecutive for speed */
LZMA2_prob low[kNumPositionStatesMax << (kLenNumLowBits + 1)];
LZMA2_prob high[kLenNumHighSymbols];
} LZMA2_lenStates;
/* All probabilities for the encoder. This is a separate from the encoder object
* so the state can be saved and restored in case a chunk is not compressible.
*/
typedef struct
{
/* Fields are ordered for speed */
LZMA2_lenStates rep_len_states;
LZMA2_prob is_rep0_long[kNumStates][kNumPositionStatesMax];
size_t state;
U32 reps[kNumReps];
LZMA2_prob is_match[kNumStates][kNumPositionStatesMax];
LZMA2_prob is_rep[kNumStates];
LZMA2_prob is_rep_G0[kNumStates];
LZMA2_prob is_rep_G1[kNumStates];
LZMA2_prob is_rep_G2[kNumStates];
LZMA2_lenStates len_states;
LZMA2_prob dist_slot_encoders[kNumLenToPosStates][1 << kNumPosSlotBits];
LZMA2_prob dist_align_encoders[1 << kNumAlignBits];
LZMA2_prob dist_encoders[kNumFullDistances - kEndPosModelIndex];
LZMA2_prob literal_probs[(kNumLiterals * kNumLitTables) << kLcLpMax];
} LZMA2_encStates;
/*
* Linked list item for optimal parsing
*/
typedef struct
{
size_t state;
U32 price;
unsigned extra; /* 0 : normal
* 1 : LIT : MATCH
* > 1 : MATCH (extra-1) : LIT : REP0 (len) */
unsigned len;
U32 dist;
U32 reps[kNumReps];
} LZMA2_node;
#define MARK_LITERAL(node) (node).dist = kNullDist; (node).extra = 0;
#define MARK_SHORT_REP(node) (node).dist = 0; (node).extra = 0;
/*
* Table and chain for 3-byte hash. Extra elements in hash_chain_3 are malloced.
*/
typedef struct {
S32 table_3[1 << kHash3Bits];
S32 hash_chain_3[1];
} LZMA2_hc3;
/*
* LZMA2 encoder.
*/
struct LZMA2_ECtx_s
{
unsigned lc;
unsigned lp;
unsigned pb;
unsigned fast_length;
size_t len_end_max;
size_t lit_pos_mask;
size_t pos_mask;
unsigned match_cycles;
FL2_strategy strategy;
RC_encoder rc;
/* Finish writing the chunk at this size */
size_t chunk_size;
/* Don't encode a symbol beyond this limit (used by fast mode) */
size_t chunk_limit;
LZMA2_encStates states;
unsigned match_price_count;
unsigned rep_len_price_count;
size_t dist_price_table_size;
unsigned align_prices[kAlignTableSize];
unsigned dist_slot_prices[kNumLenToPosStates][kDistTableSizeMax];
unsigned distance_prices[kNumLenToPosStates][kNumFullDistances];
/* All access must be via MATCH_TBL_INDEX() to allow access to index (-1) in LZMA_optimalParse */
RMF_match matches[kMatchesMax + 1];
size_t match_count;
LZMA2_node opt_buf[kOptimizerBufferSize];
LZMA2_hc3* hash_buf;
ptrdiff_t chain_mask_2;
ptrdiff_t chain_mask_3;
ptrdiff_t hash_dict_3;
ptrdiff_t hash_prev_index;
ptrdiff_t hash_alloc_3;
/* Temp output buffer before space frees up in the match table */
BYTE out_buf[kTempBufferSize];
};
LZMA2_ECtx* LZMA2_createECtx(void)
{
LZMA2_ECtx *const enc = malloc(sizeof(LZMA2_ECtx));
DEBUGLOG(3, "LZMA2_createECtx");
if (enc == NULL)
return NULL;
enc->lc = 3;
enc->lp = 0;
enc->pb = 2;
enc->fast_length = 48;
enc->len_end_max = kOptimizerBufferSize - 1;
enc->lit_pos_mask = (1 << enc->lp) - 1;
enc->pos_mask = (1 << enc->pb) - 1;
enc->match_cycles = 1;
enc->strategy = FL2_ultra;
enc->match_price_count = 0;
enc->rep_len_price_count = 0;
enc->dist_price_table_size = kDistTableSizeMax;
enc->hash_buf = NULL;
enc->hash_dict_3 = 0;
enc->chain_mask_3 = 0;
enc->hash_alloc_3 = 0;
return enc;
}
void LZMA2_freeECtx(LZMA2_ECtx *const enc)
{
if (enc == NULL)
return;
free(enc->hash_buf);
free(enc);
}
#define LITERAL_PROBS(enc, pos, prev_symbol) (enc->states.literal_probs + ((((pos) & enc->lit_pos_mask) << enc->lc) + ((prev_symbol) >> (8 - enc->lc))) * kNumLiterals * kNumLitTables)
#define LEN_TO_DIST_STATE(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
#define IS_LIT_STATE(state) ((state) < 7)
#define MATCH_TBL_INDEX(index) ((index) + 1)
HINT_INLINE
unsigned LZMA_getRepLen1Price(LZMA2_ECtx* const enc, size_t const state, size_t const pos_state)
{
unsigned const rep_G0_prob = enc->states.is_rep_G0[state];
unsigned const rep0_long_prob = enc->states.is_rep0_long[state][pos_state];
return GET_PRICE_0(rep_G0_prob) + GET_PRICE_0(rep0_long_prob);
}
static unsigned LZMA_getRepPrice(LZMA2_ECtx* const enc, size_t const rep_index, size_t const state, size_t const pos_state)
{
unsigned price;
unsigned const rep_G0_prob = enc->states.is_rep_G0[state];
if (rep_index == 0) {
unsigned const rep0_long_prob = enc->states.is_rep0_long[state][pos_state];
price = GET_PRICE_0(rep_G0_prob);
price += GET_PRICE_1(rep0_long_prob);
}
else {
unsigned const rep_G1_prob = enc->states.is_rep_G1[state];
price = GET_PRICE_1(rep_G0_prob);
if (rep_index == 1) {
price += GET_PRICE_0(rep_G1_prob);
}
else {
unsigned const rep_G2_prob = enc->states.is_rep_G2[state];
price += GET_PRICE_1(rep_G1_prob);
price += GET_PRICE(rep_G2_prob, rep_index - 2);
}
}
return price;
}
static unsigned LZMA_getRepMatch0Price(LZMA2_ECtx *const enc, size_t const len, size_t const state, size_t const pos_state)
{
unsigned const rep_G0_prob = enc->states.is_rep_G0[state];
unsigned const rep0_long_prob = enc->states.is_rep0_long[state][pos_state];
return enc->states.rep_len_states.prices[pos_state][len - kMatchLenMin]
+ GET_PRICE_0(rep_G0_prob)
+ GET_PRICE_1(rep0_long_prob);
}
static unsigned LZMA_getLiteralPriceMatched(const LZMA2_prob *const prob_table, U32 symbol, unsigned match_byte)
{
unsigned price = 0;
unsigned offs = 0x100;
symbol |= 0x100;
do {
match_byte <<= 1;
price += GET_PRICE(prob_table[offs + (match_byte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
symbol <<= 1;
offs &= ~(match_byte ^ symbol);
} while (symbol < 0x10000);
return price;
}
HINT_INLINE
void LZMA_encodeLiteral(LZMA2_ECtx *const enc, size_t const pos, U32 symbol, unsigned const prev_symbol)
{
RC_encodeBit0(&enc->rc, &enc->states.is_match[enc->states.state][pos & enc->pos_mask]);
enc->states.state = LIT_NEXT_STATE(enc->states.state);
LZMA2_prob* const prob_table = LITERAL_PROBS(enc, pos, prev_symbol);
symbol |= 0x100;
do {
RC_encodeBit(&enc->rc, prob_table + (symbol >> 8), symbol & (1 << 7));
symbol <<= 1;
} while (symbol < 0x10000);
}
HINT_INLINE
void LZMA_encodeLiteralMatched(LZMA2_ECtx *const enc, const BYTE* const data_block, size_t const pos, U32 symbol)
{
RC_encodeBit0(&enc->rc, &enc->states.is_match[enc->states.state][pos & enc->pos_mask]);
enc->states.state = LIT_NEXT_STATE(enc->states.state);
unsigned match_symbol = data_block[pos - enc->states.reps[0] - 1];
LZMA2_prob* const prob_table = LITERAL_PROBS(enc, pos, data_block[pos - 1]);
unsigned offset = 0x100;
symbol |= 0x100;
do {
match_symbol <<= 1;
size_t prob_index = offset + (match_symbol & offset) + (symbol >> 8);
RC_encodeBit(&enc->rc, prob_table + prob_index, symbol & (1 << 7));
symbol <<= 1;
offset &= ~(match_symbol ^ symbol);
} while (symbol < 0x10000);
}
HINT_INLINE
void LZMA_encodeLiteralBuf(LZMA2_ECtx *const enc, const BYTE* const data_block, size_t const pos)
{
U32 const symbol = data_block[pos];
if (IS_LIT_STATE(enc->states.state)) {
unsigned const prev_symbol = data_block[pos - 1];
LZMA_encodeLiteral(enc, pos, symbol, prev_symbol);
}
else {
LZMA_encodeLiteralMatched(enc, data_block, pos, symbol);
}
}
static void LZMA_lengthStates_SetPrices(const LZMA2_prob *probs, U32 start_price, unsigned *prices)
{
for (size_t i = 0; i < 8; i += 2) {
U32 prob = probs[4 + (i >> 1)];
U32 price = start_price + GET_PRICE(probs[1], (i >> 2))
+ GET_PRICE(probs[2 + (i >> 2)], (i >> 1) & 1);
prices[i] = price + GET_PRICE_0(prob);
prices[i + 1] = price + GET_PRICE_1(prob);
}
}
FORCE_NOINLINE
// **************** NanaZip Modification Start ****************
//static void LZMA_lengthStates_updatePrices(LZMA2_ECtx *const enc, LZMA2_lenStates* const ls)
void LZMA_lengthStates_updatePrices(LZMA2_ECtx* const enc, LZMA2_lenStates* const ls)
// **************** NanaZip Modification End ****************
{
U32 b;
{
unsigned const prob = ls->choice;
U32 a, c;
b = GET_PRICE_1(prob);
a = GET_PRICE_0(prob);
c = b + GET_PRICE_0(ls->low[0]);
for (size_t pos_state = 0; pos_state <= enc->pos_mask; pos_state++) {
unsigned *const prices = ls->prices[pos_state];
const LZMA2_prob *const probs = ls->low + (pos_state << (1 + kLenNumLowBits));
LZMA_lengthStates_SetPrices(probs, a, prices);
LZMA_lengthStates_SetPrices(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols);
}
}
size_t i = ls->table_size;
if (i > kLenNumLowSymbols * 2) {
const LZMA2_prob *const probs = ls->high;
unsigned *const prices = ls->prices[0] + kLenNumLowSymbols * 2;
i = (i - (kLenNumLowSymbols * 2 - 1)) >> 1;
b += GET_PRICE_1(ls->low[0]);
do {
--i;
size_t sym = i + (1 << (kLenNumHighBits - 1));
U32 price = b;
do {
size_t bit = sym & 1;
sym >>= 1;
price += GET_PRICE(probs[sym], bit);
} while (sym >= 2);
unsigned const prob = probs[i + (1 << (kLenNumHighBits - 1))];
prices[i * 2] = price + GET_PRICE_0(prob);
prices[i * 2 + 1] = price + GET_PRICE_1(prob);
} while (i);
size_t const size = (ls->table_size - kLenNumLowSymbols * 2) * sizeof(ls->prices[0][0]);
for (size_t pos_state = 1; pos_state <= enc->pos_mask; pos_state++)
memcpy(ls->prices[pos_state] + kLenNumLowSymbols * 2, ls->prices[0] + kLenNumLowSymbols * 2, size);
}
}
/* Rare enough that not inlining is faster overall */
FORCE_NOINLINE
// **************** NanaZip Modification Start ****************
//static void LZMA_encodeLength_MidHigh(LZMA2_ECtx *const enc, LZMA2_lenStates* const len_prob_table, unsigned const len, size_t const pos_state)
void LZMA_encodeLength_MidHigh(LZMA2_ECtx* const enc, LZMA2_lenStates* const len_prob_table, unsigned const len, size_t const pos_state)
// **************** NanaZip Modification End ****************
{
RC_encodeBit1(&enc->rc, &len_prob_table->choice);
if (len < kLenNumLowSymbols * 2) {
RC_encodeBit0(&enc->rc, &len_prob_table->low[0]);
RC_encodeBitTree(&enc->rc, len_prob_table->low + kLenNumLowSymbols + (pos_state << (1 + kLenNumLowBits)), kLenNumLowBits, len - kLenNumLowSymbols);
}
else {
RC_encodeBit1(&enc->rc, &len_prob_table->low[0]);
RC_encodeBitTree(&enc->rc, len_prob_table->high, kLenNumHighBits, len - kLenNumLowSymbols * 2);
}
}
HINT_INLINE
void LZMA_encodeLength(LZMA2_ECtx *const enc, LZMA2_lenStates* const len_prob_table, unsigned len, size_t const pos_state)
{
len -= kMatchLenMin;
if (len < kLenNumLowSymbols) {
RC_encodeBit0(&enc->rc, &len_prob_table->choice);
RC_encodeBitTree(&enc->rc, len_prob_table->low + (pos_state << (1 + kLenNumLowBits)), kLenNumLowBits, len);
}
else {
LZMA_encodeLength_MidHigh(enc, len_prob_table, len, pos_state);
}
}
FORCE_NOINLINE
// **************** NanaZip Modification Start ****************
//static void LZMA_encodeRepMatchShort(LZMA2_ECtx *const enc, size_t const pos_state)
void LZMA_encodeRepMatchShort(LZMA2_ECtx* const enc, size_t const pos_state)
// **************** NanaZip Modification End ****************
{
DEBUGLOG(7, "LZMA_encodeRepMatchShort");
RC_encodeBit1(&enc->rc, &enc->states.is_match[enc->states.state][pos_state]);
RC_encodeBit1(&enc->rc, &enc->states.is_rep[enc->states.state]);
RC_encodeBit0(&enc->rc, &enc->states.is_rep_G0[enc->states.state]);
RC_encodeBit0(&enc->rc, &enc->states.is_rep0_long[enc->states.state][pos_state]);
enc->states.state = SHORT_REP_NEXT_STATE(enc->states.state);
}
FORCE_NOINLINE
// **************** NanaZip Modification Start ****************
//static void LZMA_encodeRepMatchLong(LZMA2_ECtx *const enc, unsigned const len, unsigned const rep, size_t const pos_state)
void LZMA_encodeRepMatchLong(LZMA2_ECtx* const enc, unsigned const len, unsigned const rep, size_t const pos_state)
// **************** NanaZip Modification End ****************
{
DEBUGLOG(7, "LZMA_encodeRepMatchLong : length %u, rep %u", len, rep);
RC_encodeBit1(&enc->rc, &enc->states.is_match[enc->states.state][pos_state]);
RC_encodeBit1(&enc->rc, &enc->states.is_rep[enc->states.state]);
if (rep == 0) {
RC_encodeBit0(&enc->rc, &enc->states.is_rep_G0[enc->states.state]);
RC_encodeBit1(&enc->rc, &enc->states.is_rep0_long[enc->states.state][pos_state]);
}
else {
U32 const distance = enc->states.reps[rep];
RC_encodeBit1(&enc->rc, &enc->states.is_rep_G0[enc->states.state]);
if (rep == 1) {
RC_encodeBit0(&enc->rc, &enc->states.is_rep_G1[enc->states.state]);
}
else {
RC_encodeBit1(&enc->rc, &enc->states.is_rep_G1[enc->states.state]);
RC_encodeBit(&enc->rc, &enc->states.is_rep_G2[enc->states.state], rep - 2);
if (rep == 3)
enc->states.reps[3] = enc->states.reps[2];
enc->states.reps[2] = enc->states.reps[1];
}
enc->states.reps[1] = enc->states.reps[0];
enc->states.reps[0] = distance;
}
LZMA_encodeLength(enc, &enc->states.rep_len_states, len, pos_state);
enc->states.state = REP_NEXT_STATE(enc->states.state);
++enc->rep_len_price_count;
}
/*
* Distance slot functions based on fastpos.h from XZ
*/
HINT_INLINE
unsigned LZMA_fastDistShift(unsigned const n)
{
return n * (kFastDistBits - 1);
}
HINT_INLINE
unsigned LZMA_fastDistResult(U32 const dist, unsigned const n)
{
return distance_table[dist >> LZMA_fastDistShift(n)]
+ 2 * LZMA_fastDistShift(n);
}
static size_t LZMA_getDistSlot(U32 const distance)
{
U32 limit = 1UL << kFastDistBits;
/* If it is small enough, we can pick the result directly from */
/* the precalculated table. */
if (distance < limit) {
return distance_table[distance];
}
limit <<= LZMA_fastDistShift(1);
if (distance < limit) {
return LZMA_fastDistResult(distance, 1);
}
return LZMA_fastDistResult(distance, 2);
}
/* * */
HINT_INLINE
void LZMA_encodeNormalMatch(LZMA2_ECtx *const enc, unsigned const len, U32 const dist, size_t const pos_state)
{
DEBUGLOG(7, "LZMA_encodeNormalMatch : length %u, dist %u", len, dist);
RC_encodeBit1(&enc->rc, &enc->states.is_match[enc->states.state][pos_state]);
RC_encodeBit0(&enc->rc, &enc->states.is_rep[enc->states.state]);
enc->states.state = MATCH_NEXT_STATE(enc->states.state);
LZMA_encodeLength(enc, &enc->states.len_states, len, pos_state);
size_t const dist_slot = LZMA_getDistSlot(dist);
RC_encodeBitTree(&enc->rc, enc->states.dist_slot_encoders[LEN_TO_DIST_STATE(len)], kNumPosSlotBits, (unsigned)dist_slot);
if (dist_slot >= kStartPosModelIndex) {
unsigned const footer_bits = ((unsigned)(dist_slot >> 1) - 1);
size_t const base = ((2 | (dist_slot & 1)) << footer_bits);
unsigned const dist_reduced = (unsigned)(dist - base);
if (dist_slot < kEndPosModelIndex) {
RC_encodeBitTreeReverse(&enc->rc, enc->states.dist_encoders + base - dist_slot - 1, footer_bits, dist_reduced);
}
else {
RC_encodeDirect(&enc->rc, dist_reduced >> kNumAlignBits, footer_bits - kNumAlignBits);
RC_encodeBitTreeReverse(&enc->rc, enc->states.dist_align_encoders, kNumAlignBits, dist_reduced & kAlignMask);
}
}
enc->states.reps[3] = enc->states.reps[2];
enc->states.reps[2] = enc->states.reps[1];
enc->states.reps[1] = enc->states.reps[0];
enc->states.reps[0] = dist;
++enc->match_price_count;
}
FORCE_INLINE_TEMPLATE
size_t LZMA_encodeChunkFast(LZMA2_ECtx *const enc,
FL2_dataBlock const block,
FL2_matchTable* const tbl,
int const struct_tbl,
size_t pos,
size_t const uncompressed_end)
{
size_t const pos_mask = enc->pos_mask;
size_t prev = pos;
unsigned const search_depth = tbl->params.depth;
while (pos < uncompressed_end && enc->rc.out_index < enc->chunk_size) {
size_t max_len;
const BYTE* data;
/* Table of distance restrictions for short matches */
static const U32 max_dist_table[] = { 0, 0, 0, 1 << 6, 1 << 14 };
/* Get a match from the table, extended to its full length */
RMF_match best_match = RMF_getMatch(block, tbl, search_depth, struct_tbl, pos);
if (best_match.length < kMatchLenMin) {
++pos;
continue;
}
/* Use if near enough */
if (best_match.length >= 5 || best_match.dist < max_dist_table[best_match.length])
best_match.dist += kNumReps;
else
best_match.length = 0;
max_len = MIN(kMatchLenMax, block.end - pos);
data = block.data + pos;
RMF_match best_rep = { 0, 0 };
RMF_match rep_match;
/* Search all of the rep distances */
for (rep_match.dist = 0; rep_match.dist < kNumReps; ++rep_match.dist) {
const BYTE *data_2 = data - enc->states.reps[rep_match.dist] - 1;
if (MEM_read16(data) != MEM_read16(data_2))
continue;
rep_match.length = (U32)(ZSTD_count(data + 2, data_2 + 2, data + max_len) + 2);
if (rep_match.length >= max_len) {
best_match = rep_match;
goto _encode;
}
if (rep_match.length > best_rep.length)
best_rep = rep_match;
}
/* Encode if it is kMatchLenMax or completes the block */
if (best_match.length >= max_len)
goto _encode;
if (best_rep.length >= 2) {
if (best_rep.length > best_match.length) {
best_match = best_rep;
}
else {
/* Modified ZSTD scheme for estimating cost */
int const gain2 = (int)(best_rep.length * 3 - best_rep.dist);
int const gain1 = (int)(best_match.length * 3 - ZSTD_highbit32(best_match.dist + 1) + 1);
if (gain2 > gain1) {
DEBUGLOG(7, "Replace match (%u, %u) with rep (%u, %u)", best_match.length, best_match.dist, best_rep.length, best_rep.dist);
best_match = best_rep;
}
}
}
if (best_match.length < kMatchLenMin) {
++pos;
continue;
}
for (size_t next = pos + 1; best_match.length < kMatchLenMax && next < uncompressed_end; ++next) {
/* lazy matching scheme from ZSTD */
RMF_match next_match = RMF_getNextMatch(block, tbl, search_depth, struct_tbl, next);
if (next_match.length >= kMatchLenMin) {
best_rep.length = 0;
data = block.data + next;
max_len = MIN(kMatchLenMax, block.end - next);
for (rep_match.dist = 0; rep_match.dist < kNumReps; ++rep_match.dist) {
const BYTE *data_2 = data - enc->states.reps[rep_match.dist] - 1;
if (MEM_read16(data) != MEM_read16(data_2))
continue;
rep_match.length = (U32)(ZSTD_count(data + 2, data_2 + 2, data + max_len) + 2);
if (rep_match.length > best_rep.length)
best_rep = rep_match;
}
if (best_rep.length >= 3) {
int const gain2 = (int)(best_rep.length * 3 - best_rep.dist);
int const gain1 = (int)(best_match.length * 3 - ZSTD_highbit32((U32)best_match.dist + 1) + 1);
if (gain2 > gain1) {
DEBUGLOG(7, "Replace match (%u, %u) with rep (%u, %u)", best_match.length, best_match.dist, best_rep.length, best_rep.dist);
best_match = best_rep;
pos = next;
}
}
if (next_match.length >= 3 && next_match.dist != best_match.dist) {
int const gain2 = (int)(next_match.length * 4 - ZSTD_highbit32((U32)next_match.dist + 1)); /* raw approx */
int const gain1 = (int)(best_match.length * 4 - ZSTD_highbit32((U32)best_match.dist + 1) + 4);
if (gain2 > gain1) {
DEBUGLOG(7, "Replace match (%u, %u) with match (%u, %u)", best_match.length, best_match.dist, next_match.length, next_match.dist + kNumReps);
best_match = next_match;
best_match.dist += kNumReps;
pos = next;
continue;
}
}
}
++next;
/* Recheck next < uncompressed_end. uncompressed_end could be block.end so decrementing the max chunk size won't obviate the need. */
if (next >= uncompressed_end)
break;
next_match = RMF_getNextMatch(block, tbl, search_depth, struct_tbl, next);
if (next_match.length < 4)
break;
data = block.data + next;
max_len = MIN(kMatchLenMax, block.end - next);
best_rep.length = 0;
for (rep_match.dist = 0; rep_match.dist < kNumReps; ++rep_match.dist) {
const BYTE *data_2 = data - enc->states.reps[rep_match.dist] - 1;
if (MEM_read16(data) != MEM_read16(data_2))
continue;
rep_match.length = (U32)(ZSTD_count(data + 2, data_2 + 2, data + max_len) + 2);
if (rep_match.length > best_rep.length)
best_rep = rep_match;
}
if (best_rep.length >= 4) {
int const gain2 = (int)(best_rep.length * 4 - (best_rep.dist >> 1));
int const gain1 = (int)(best_match.length * 4 - ZSTD_highbit32((U32)best_match.dist + 1) + 1);
if (gain2 > gain1) {
DEBUGLOG(7, "Replace match (%u, %u) with rep (%u, %u)", best_match.length, best_match.dist, best_rep.length, best_rep.dist);
best_match = best_rep;
pos = next;
}
}
if (next_match.dist != best_match.dist) {
int const gain2 = (int)(next_match.length * 4 - ZSTD_highbit32((U32)next_match.dist + 1));
int const gain1 = (int)(best_match.length * 4 - ZSTD_highbit32((U32)best_match.dist + 1) + 7);
if (gain2 > gain1) {
DEBUGLOG(7, "Replace match (%u, %u) with match (%u, %u)", best_match.length, best_match.dist, next_match.length, next_match.dist + kNumReps);
best_match = next_match;
best_match.dist += kNumReps;
pos = next;
continue;
}
}
break;
}
_encode:
assert(pos + best_match.length <= block.end);
while (prev < pos) {
if (enc->rc.out_index >= enc->chunk_limit)
return prev;
if (block.data[prev] != block.data[prev - enc->states.reps[0] - 1]) {
LZMA_encodeLiteralBuf(enc, block.data, prev);
++prev;
}
else {
LZMA_encodeRepMatchShort(enc, prev & pos_mask);
++prev;
}
}
if(best_match.length >= kMatchLenMin) {
if (best_match.dist >= kNumReps) {
LZMA_encodeNormalMatch(enc, best_match.length, best_match.dist - kNumReps, pos & pos_mask);
pos += best_match.length;
prev = pos;
}
else {
LZMA_encodeRepMatchLong(enc, best_match.length, best_match.dist, pos & pos_mask);
pos += best_match.length;
prev = pos;
}
}
}
while (prev < pos && enc->rc.out_index < enc->chunk_limit) {
if (block.data[prev] != block.data[prev - enc->states.reps[0] - 1])
LZMA_encodeLiteralBuf(enc, block.data, prev);
else
LZMA_encodeRepMatchShort(enc, prev & pos_mask);
++prev;
}
return prev;
}
/*
* Reverse the direction of the linked list generated by the optimal parser
*/
FORCE_NOINLINE
// **************** NanaZip Modification Start ****************
//static void LZMA_reverseOptimalChain(LZMA2_node* const opt_buf, size_t cur)
void LZMA_reverseOptimalChain(LZMA2_node* const opt_buf, size_t cur)
// **************** NanaZip Modification End ****************
{
unsigned len = (unsigned)opt_buf[cur].len;
U32 dist = opt_buf[cur].dist;
for(;;) {
unsigned const extra = (unsigned)opt_buf[cur].extra;
cur -= len;
if (extra) {
opt_buf[cur].len = (U32)len;
len = extra;
if (extra == 1) {
opt_buf[cur].dist = dist;
dist = kNullDist;
--cur;
}
else {
opt_buf[cur].dist = 0;
--cur;
--len;
opt_buf[cur].dist = kNullDist;
opt_buf[cur].len = 1;
cur -= len;
}
}
unsigned const next_len = opt_buf[cur].len;
U32 const next_dist = opt_buf[cur].dist;
opt_buf[cur].dist = dist;
opt_buf[cur].len = (U32)len;
if (cur == 0)
break;
len = next_len;
dist = next_dist;
}
}
static unsigned LZMA_getLiteralPrice(LZMA2_ECtx *const enc, size_t const pos, size_t const state, unsigned const prev_symbol, U32 symbol, unsigned const match_byte)
{
const LZMA2_prob* const prob_table = LITERAL_PROBS(enc, pos, prev_symbol);
if (IS_LIT_STATE(state)) {
unsigned price = 0;
symbol |= 0x100;
do {
price += GET_PRICE(prob_table[symbol >> 8], (symbol >> 7) & 1);
symbol <<= 1;
} while (symbol < 0x10000);
return price;
}
return LZMA_getLiteralPriceMatched(prob_table, symbol, match_byte);
}
/*
* Reset the hash object for encoding a new slice of a block
*/
static void LZMA_hashReset(LZMA2_ECtx *const enc, unsigned const dictionary_bits_3)
{
enc->hash_dict_3 = (ptrdiff_t)1 << dictionary_bits_3;
enc->chain_mask_3 = enc->hash_dict_3 - 1;
memset(enc->hash_buf->table_3, 0xFF, sizeof(enc->hash_buf->table_3));
}
/*
* Create hash table and chain with dict size dictionary_bits_3. Frees any existing object.
*/
static int LZMA_hashCreate(LZMA2_ECtx *const enc, unsigned const dictionary_bits_3)
{
DEBUGLOG(3, "Create hash chain : dict bits %u", dictionary_bits_3);
if (enc->hash_buf)
free(enc->hash_buf);
enc->hash_alloc_3 = (ptrdiff_t)1 << dictionary_bits_3;
enc->hash_buf = malloc(sizeof(LZMA2_hc3) + (enc->hash_alloc_3 - 1) * sizeof(S32));
if (enc->hash_buf == NULL)
return 1;
LZMA_hashReset(enc, dictionary_bits_3);
return 0;
}
/* Create a hash chain for hybrid mode if options require one.
* Used for allocating before compression begins. Any existing table will be reused if
* it is at least as large as required.
*/
int LZMA2_hashAlloc(LZMA2_ECtx *const enc, const FL2_lzma2Parameters* const options)
{
if (enc->strategy == FL2_ultra && enc->hash_alloc_3 < ((ptrdiff_t)1 << options->second_dict_bits))
return LZMA_hashCreate(enc, options->second_dict_bits);
return 0;
}
#define GET_HASH_3(data) ((((MEM_readLE32(data)) << 8) * 506832829U) >> (32 - kHash3Bits))
/* Find matches nearer than the match from the RMF. If none is at least as long as
* the RMF match (most likely), insert that match at the end of the list.
*/
HINT_INLINE
size_t LZMA_hashGetMatches(LZMA2_ECtx *const enc, FL2_dataBlock const block,
ptrdiff_t const pos,
size_t const length_limit,
RMF_match const match)
{
ptrdiff_t const hash_dict_3 = enc->hash_dict_3;
const BYTE* data = block.data;
LZMA2_hc3* const tbl = enc->hash_buf;
ptrdiff_t const chain_mask_3 = enc->chain_mask_3;
enc->match_count = 0;
enc->hash_prev_index = MAX(enc->hash_prev_index, pos - hash_dict_3);
/* Update hash tables and chains for any positions that were skipped */
while (++enc->hash_prev_index < pos) {
size_t hash = GET_HASH_3(data + enc->hash_prev_index);
tbl->hash_chain_3[enc->hash_prev_index & chain_mask_3] = tbl->table_3[hash];
tbl->table_3[hash] = (S32)enc->hash_prev_index;
}
data += pos;
size_t const hash = GET_HASH_3(data);
ptrdiff_t const first_3 = tbl->table_3[hash];
tbl->table_3[hash] = (S32)pos;
size_t max_len = 2;
if (first_3 >= 0) {
int cycles = enc->match_cycles;
ptrdiff_t const end_index = pos - (((ptrdiff_t)match.dist < hash_dict_3) ? match.dist : hash_dict_3);
ptrdiff_t match_3 = first_3;
if (match_3 >= end_index) {
do {
--cycles;
const BYTE* data_2 = block.data + match_3;
size_t len_test = ZSTD_count(data + 1, data_2 + 1, data + length_limit) + 1;
if (len_test > max_len) {
enc->matches[MATCH_TBL_INDEX(enc->match_count)].length = (U32)len_test;
enc->matches[MATCH_TBL_INDEX(enc->match_count)].dist = (U32)(pos - match_3 - 1);
++enc->match_count;
max_len = len_test;
if (len_test >= length_limit)
break;
}
if (cycles <= 0)
break;
match_3 = tbl->hash_chain_3[match_3 & chain_mask_3];
} while (match_3 >= end_index);
}
}
tbl->hash_chain_3[pos & chain_mask_3] = (S32)first_3;
if ((unsigned)max_len < match.length) {
/* Insert the match from the RMF */
enc->matches[MATCH_TBL_INDEX(enc->match_count)] = match;
++enc->match_count;
return match.length;
}
return max_len;
}
/* The speed of this function is critical. The sections have many variables
* in common, so breaking it up into shorter functions is not feasible.
* For each position cur, starting at 1, check some or all possible
* encoding choices - a literal, 1-byte rep 0 match, all rep match lengths, and
* all match lengths at available distances. It also checks the combined
* sequences literal+rep0, rep+lit+rep0 and match+lit+rep0.
* If is_hybrid != 0, this method works in hybrid mode, using the
* hash chain to find shorter matches at near distances. */
FORCE_INLINE_TEMPLATE
size_t LZMA_optimalParse(LZMA2_ECtx* const enc, FL2_dataBlock const block,
RMF_match match,
size_t const pos,
size_t const cur,
size_t len_end,
int const is_hybrid,
U32* const reps)
{
LZMA2_node* const cur_opt = &enc->opt_buf[cur];
size_t const pos_mask = enc->pos_mask;
size_t const pos_state = (pos & pos_mask);
const BYTE* const data = block.data + pos;
size_t const fast_length = enc->fast_length;
size_t prev_index = cur - cur_opt->len;
size_t state;
size_t bytes_avail;
U32 match_price;
U32 rep_match_price;
/* Update the states according to how this location was reached */
if (cur_opt->len == 1) {
/* Literal or 1-byte rep */
const BYTE *next_state = (cur_opt->dist == 0) ? kShortRepNextStates : kLiteralNextStates;
state = next_state[enc->opt_buf[prev_index].state];
}
else {
/* Match or rep match */
size_t const dist = cur_opt->dist;
if (cur_opt->extra) {
prev_index -= cur_opt->extra;
state = kState_RepAfterLit - ((dist >= kNumReps) & (cur_opt->extra == 1));
}
else {
state = enc->opt_buf[prev_index].state;
state = MATCH_NEXT_STATE(state) + (dist < kNumReps);
}
const LZMA2_node *const prev_opt = &enc->opt_buf[prev_index];
if (dist < kNumReps) {
/* Move the chosen rep to the front.
* The table is hideous but faster than branching :D */
reps[0] = prev_opt->reps[dist];
size_t table = 1 | (2 << 2) | (3 << 4)
| (0 << 8) | (2 << 10) | (3 << 12)
| (0L << 16) | (1L << 18) | (3L << 20)
| (0L << 24) | (1L << 26) | (2L << 28);
table >>= (dist << 3);
reps[1] = prev_opt->reps[table & 3];
table >>= 2;
reps[2] = prev_opt->reps[table & 3];
table >>= 2;
reps[3] = prev_opt->reps[table & 3];
}
else {
reps[0] = (U32)(dist - kNumReps);
reps[1] = prev_opt->reps[0];
reps[2] = prev_opt->reps[1];
reps[3] = prev_opt->reps[2];
}
}
cur_opt->state = state;
memcpy(cur_opt->reps, reps, sizeof(cur_opt->reps));
LZMA2_prob const is_rep_prob = enc->states.is_rep[state];
{ LZMA2_node *const next_opt = &enc->opt_buf[cur + 1];
U32 const cur_price = cur_opt->price;
U32 const next_price = next_opt->price;
LZMA2_prob const is_match_prob = enc->states.is_match[state][pos_state];
unsigned const cur_byte = *data;
unsigned const match_byte = *(data - reps[0] - 1);
U32 cur_and_lit_price = cur_price + GET_PRICE_0(is_match_prob);
/* This is a compromise to try to filter out cases where literal + rep0 is unlikely to be cheaper */
BYTE try_lit = cur_and_lit_price + kMinLitPrice / 2U <= next_price;
if (try_lit) {
/* cur_and_lit_price is used later for the literal + rep0 test */
cur_and_lit_price += LZMA_getLiteralPrice(enc, pos, state, data[-1], cur_byte, match_byte);
/* Try literal */
if (cur_and_lit_price < next_price) {
next_opt->price = cur_and_lit_price;
next_opt->len = 1;
MARK_LITERAL(*next_opt);
if (is_hybrid) /* Evaluates as a constant expression due to inlining */
try_lit = 0;
}
}
match_price = cur_price + GET_PRICE_1(is_match_prob);
rep_match_price = match_price + GET_PRICE_1(is_rep_prob);
if (match_byte == cur_byte) {
/* Try 1-byte rep0 */
U32 short_rep_price = rep_match_price + LZMA_getRepLen1Price(enc, state, pos_state);
if (short_rep_price <= next_opt->price) {
next_opt->price = short_rep_price;
next_opt->len = 1;
MARK_SHORT_REP(*next_opt);
}
}
bytes_avail = MIN(block.end - pos, kOptimizerBufferSize - 1 - cur);
if (bytes_avail < 2)
return len_end;
/* If match_byte == cur_byte a rep0 begins at the current position */
if (is_hybrid && try_lit && match_byte != cur_byte) {
/* Try literal + rep0 */
const BYTE *const data_2 = data - reps[0];
size_t limit = MIN(bytes_avail - 1, fast_length);
size_t len_test_2 = ZSTD_count(data + 1, data_2, data + 1 + limit);
if (len_test_2 >= 2) {
size_t const state_2 = LIT_NEXT_STATE(state);
size_t const pos_state_next = (pos + 1) & pos_mask;
U32 const next_rep_match_price = cur_and_lit_price +
GET_PRICE_1(enc->states.is_match[state_2][pos_state_next]) +
GET_PRICE_1(enc->states.is_rep[state_2]);
U32 const cur_and_len_price = next_rep_match_price + LZMA_getRepMatch0Price(enc, len_test_2, state_2, pos_state_next);
size_t const offset = cur + 1 + len_test_2;
if (cur_and_len_price < enc->opt_buf[offset].price) {
len_end = MAX(len_end, offset);
enc->opt_buf[offset].price = cur_and_len_price;
enc->opt_buf[offset].len = (unsigned)len_test_2;
enc->opt_buf[offset].dist = 0;
enc->opt_buf[offset].extra = 1;
}
}
}
}
size_t const max_length = MIN(bytes_avail, fast_length);
size_t start_len = 2;
if (match.length > 0) {
size_t len_test;
size_t len;
U32 cur_rep_price;
for (size_t rep_index = 0; rep_index < kNumReps; ++rep_index) {
const BYTE *const data_2 = data - reps[rep_index] - 1;
if (MEM_read16(data) != MEM_read16(data_2))
continue;
/* Test is limited to fast_length, but it is rare for the RMF to miss the longest match,
* therefore this function is rarely called when a rep len > fast_length exists */
len_test = ZSTD_count(data + 2, data_2 + 2, data + max_length) + 2;
len_end = MAX(len_end, cur + len_test);
cur_rep_price = rep_match_price + LZMA_getRepPrice(enc, rep_index, state, pos_state);
len = 2;
/* Try rep match */
do {
U32 const cur_and_len_price = cur_rep_price + enc->states.rep_len_states.prices[pos_state][len - kMatchLenMin];
LZMA2_node *const opt = &enc->opt_buf[cur + len];
if (cur_and_len_price < opt->price) {
opt->price = cur_and_len_price;
opt->len = (unsigned)len;
opt->dist = (U32)rep_index;
opt->extra = 0;
}
} while (++len <= len_test);
if (rep_index == 0) {
/* Save time by exluding normal matches not longer than the rep */
start_len = len_test + 1;
}
/* rep + literal + rep0 is not common so this test is skipped for faster, non-hybrid encoding */
if (is_hybrid && len_test + 3 <= bytes_avail && MEM_read16(data + len_test + 1) == MEM_read16(data_2 + len_test + 1)) {
/* Try rep + literal + rep0.
* The second rep may be > fast_length, but it is not worth the extra time to handle this case
* and the price table is not filled for it */
size_t const len_test_2 = ZSTD_count(data + len_test + 3,
data_2 + len_test + 3,
data + MIN(len_test + 1 + fast_length, bytes_avail)) + 2;
size_t state_2 = REP_NEXT_STATE(state);
size_t pos_state_next = (pos + len_test) & pos_mask;
U32 rep_lit_rep_total_price =
cur_rep_price + enc->states.rep_len_states.prices[pos_state][len_test - kMatchLenMin]
+ GET_PRICE_0(enc->states.is_match[state_2][pos_state_next])
+ LZMA_getLiteralPriceMatched(LITERAL_PROBS(enc, pos + len_test, data[len_test - 1]),
data[len_test], data_2[len_test]);
state_2 = kState_LitAfterRep;
pos_state_next = (pos + len_test + 1) & pos_mask;
rep_lit_rep_total_price +=
GET_PRICE_1(enc->states.is_match[state_2][pos_state_next]) +
GET_PRICE_1(enc->states.is_rep[state_2]);
size_t const offset = cur + len_test + 1 + len_test_2;
rep_lit_rep_total_price += LZMA_getRepMatch0Price(enc, len_test_2, state_2, pos_state_next);
if (rep_lit_rep_total_price < enc->opt_buf[offset].price) {
len_end = MAX(len_end, offset);
enc->opt_buf[offset].price = rep_lit_rep_total_price;
enc->opt_buf[offset].len = (unsigned)len_test_2;
enc->opt_buf[offset].dist = (U32)rep_index;
enc->opt_buf[offset].extra = (unsigned)(len_test + 1);
}
}
}
}
if (match.length >= start_len && max_length >= start_len) {
/* Try normal match */
U32 const normal_match_price = match_price + GET_PRICE_0(is_rep_prob);
if (!is_hybrid) {
/* Normal mode - single match */
size_t const length = MIN(match.length, max_length);
size_t const cur_dist = match.dist;
size_t const dist_slot = LZMA_getDistSlot(match.dist);
size_t len_test = length;
len_end = MAX(len_end, cur + length);
for (; len_test >= start_len; --len_test) {
U32 cur_and_len_price = normal_match_price + enc->states.len_states.prices[pos_state][len_test - kMatchLenMin];
size_t const len_to_dist_state = LEN_TO_DIST_STATE(len_test);
if (cur_dist < kNumFullDistances)
cur_and_len_price += enc->distance_prices[len_to_dist_state][cur_dist];
else
cur_and_len_price += enc->dist_slot_prices[len_to_dist_state][dist_slot] + enc->align_prices[cur_dist & kAlignMask];
LZMA2_node *const opt = &enc->opt_buf[cur + len_test];
if (cur_and_len_price < opt->price) {
opt->price = cur_and_len_price;
opt->len = (unsigned)len_test;
opt->dist = (U32)(cur_dist + kNumReps);
opt->extra = 0;
}
else break;
}
}
else {
/* Hybrid mode */
size_t main_len;
match.length = MIN(match.length, (U32)max_length);
/* Need to test max_length < 4 because the hash fn reads a U32 */
if (match.length < 3 || max_length < 4) {
enc->matches[MATCH_TBL_INDEX(0)] = match;
enc->match_count = 1;
main_len = match.length;
}
else {
main_len = LZMA_hashGetMatches(enc, block, pos, max_length, match);
}
ptrdiff_t match_index = enc->match_count - 1;
len_end = MAX(len_end, cur + main_len);
/* Start with a match longer than the best rep if one exists */
ptrdiff_t start_match = 0;
while (start_len > enc->matches[MATCH_TBL_INDEX(start_match)].length)
++start_match;
enc->matches[MATCH_TBL_INDEX(start_match - 1)].length = (U32)start_len - 1; /* Avoids an if..else branch in the loop. [-1] is ok */
for (; match_index >= start_match; --match_index) {
size_t len_test = enc->matches[MATCH_TBL_INDEX(match_index)].length;
size_t const cur_dist = enc->matches[MATCH_TBL_INDEX(match_index)].dist;
const BYTE *const data_2 = data - cur_dist - 1;
size_t const rep_0_pos = len_test + 1;
size_t dist_slot = LZMA_getDistSlot((U32)cur_dist);
U32 cur_and_len_price;
/* Test from the full length down to 1 more than the next shorter match */
size_t base_len = enc->matches[MATCH_TBL_INDEX(match_index - 1)].length + 1;
for (; len_test >= base_len; --len_test) {
cur_and_len_price = normal_match_price + enc->states.len_states.prices[pos_state][len_test - kMatchLenMin];
size_t const len_to_dist_state = LEN_TO_DIST_STATE(len_test);
if (cur_dist < kNumFullDistances)
cur_and_len_price += enc->distance_prices[len_to_dist_state][cur_dist];
else
cur_and_len_price += enc->dist_slot_prices[len_to_dist_state][dist_slot] + enc->align_prices[cur_dist & kAlignMask];
BYTE const sub_len = len_test < enc->matches[MATCH_TBL_INDEX(match_index)].length;
LZMA2_node *const opt = &enc->opt_buf[cur + len_test];
if (cur_and_len_price < opt->price) {
opt->price = cur_and_len_price;
opt->len = (unsigned)len_test;
opt->dist = (U32)(cur_dist + kNumReps);
opt->extra = 0;
}
else if(sub_len)
break; /* End the tests if prices for shorter lengths are not lower than those already recorded */
if (!sub_len && rep_0_pos + 2 <= bytes_avail && MEM_read16(data + rep_0_pos) == MEM_read16(data_2 + rep_0_pos)) {
/* Try match + literal + rep0 */
size_t const limit = MIN(rep_0_pos + fast_length, bytes_avail);
size_t const len_test_2 = ZSTD_count(data + rep_0_pos + 2, data_2 + rep_0_pos + 2, data + limit) + 2;
size_t state_2 = MATCH_NEXT_STATE(state);
size_t pos_state_next = (pos + len_test) & pos_mask;
U32 match_lit_rep_total_price = cur_and_len_price +
GET_PRICE_0(enc->states.is_match[state_2][pos_state_next]) +
LZMA_getLiteralPriceMatched(LITERAL_PROBS(enc, pos + len_test, data[len_test - 1]),
data[len_test], data_2[len_test]);
state_2 = kState_LitAfterMatch;
pos_state_next = (pos_state_next + 1) & pos_mask;
match_lit_rep_total_price +=
GET_PRICE_1(enc->states.is_match[state_2][pos_state_next]) +
GET_PRICE_1(enc->states.is_rep[state_2]);
size_t const offset = cur + rep_0_pos + len_test_2;
match_lit_rep_total_price += LZMA_getRepMatch0Price(enc, len_test_2, state_2, pos_state_next);
if (match_lit_rep_total_price < enc->opt_buf[offset].price) {
len_end = MAX(len_end, offset);
enc->opt_buf[offset].price = match_lit_rep_total_price;
enc->opt_buf[offset].len = (unsigned)len_test_2;
enc->opt_buf[offset].extra = (unsigned)rep_0_pos;
enc->opt_buf[offset].dist = (U32)(cur_dist + kNumReps);
}
}
}
}
}
}
return len_end;
}
FORCE_NOINLINE
// **************** NanaZip Modification Start ****************
//static void LZMA_initMatchesPos0(LZMA2_ECtx *const enc,
void LZMA_initMatchesPos0(LZMA2_ECtx* const enc,
// **************** NanaZip Modification End ****************
RMF_match const match,
size_t const pos_state,
size_t len,
unsigned const normal_match_price)
{
if ((unsigned)len <= match.length) {
size_t const distance = match.dist;
size_t const slot = LZMA_getDistSlot(match.dist);
/* Test every available length of the match */
do {
unsigned cur_and_len_price = normal_match_price + enc->states.len_states.prices[pos_state][len - kMatchLenMin];
size_t const len_to_dist_state = LEN_TO_DIST_STATE(len);
if (distance < kNumFullDistances)
cur_and_len_price += enc->distance_prices[len_to_dist_state][distance];
else
cur_and_len_price += enc->align_prices[distance & kAlignMask] + enc->dist_slot_prices[len_to_dist_state][slot];
if (cur_and_len_price < enc->opt_buf[len].price) {
enc->opt_buf[len].price = cur_and_len_price;
enc->opt_buf[len].len = (unsigned)len;
enc->opt_buf[len].dist = (U32)(distance + kNumReps);
enc->opt_buf[len].extra = 0;
}
++len;
} while ((U32)len <= match.length);
}
}
FORCE_NOINLINE
// **************** NanaZip Modification Start ****************
//static size_t LZMA_initMatchesPos0Best(LZMA2_ECtx *const enc, FL2_dataBlock const block,
size_t LZMA_initMatchesPos0Best(LZMA2_ECtx* const enc, FL2_dataBlock const block,
// **************** NanaZip Modification End ****************
RMF_match const match,
size_t const pos,
size_t start_len,
unsigned const normal_match_price)
{
if (start_len <= match.length) {
size_t main_len;
if (match.length < 3 || block.end - pos < 4) {
enc->matches[MATCH_TBL_INDEX(0)] = match;
enc->match_count = 1;
main_len = match.length;
}
else {
main_len = LZMA_hashGetMatches(enc, block, pos, MIN(block.end - pos, enc->fast_length), match);
}
ptrdiff_t start_match = 0;
while (start_len > enc->matches[MATCH_TBL_INDEX(start_match)].length)
++start_match;
enc->matches[MATCH_TBL_INDEX(start_match - 1)].length = (U32)start_len - 1; /* Avoids an if..else branch in the loop. [-1] is ok */
size_t pos_state = pos & enc->pos_mask;
for (ptrdiff_t match_index = enc->match_count - 1; match_index >= start_match; --match_index) {
size_t len_test = enc->matches[MATCH_TBL_INDEX(match_index)].length;
size_t const distance = enc->matches[MATCH_TBL_INDEX(match_index)].dist;
size_t const slot = LZMA_getDistSlot((U32)distance);
size_t const base_len = enc->matches[MATCH_TBL_INDEX(match_index - 1)].length + 1;
/* Test every available match length at the shortest distance. The buffer is sorted */
/* in order of increasing length, and therefore increasing distance too. */
for (; len_test >= base_len; --len_test) {
unsigned cur_and_len_price = normal_match_price
+ enc->states.len_states.prices[pos_state][len_test - kMatchLenMin];
size_t const len_to_dist_state = LEN_TO_DIST_STATE(len_test);
if (distance < kNumFullDistances)
cur_and_len_price += enc->distance_prices[len_to_dist_state][distance];
else
cur_and_len_price += enc->align_prices[distance & kAlignMask] + enc->dist_slot_prices[len_to_dist_state][slot];
if (cur_and_len_price < enc->opt_buf[len_test].price) {
enc->opt_buf[len_test].price = cur_and_len_price;
enc->opt_buf[len_test].len = (unsigned)len_test;
enc->opt_buf[len_test].dist = (U32)(distance + kNumReps);
enc->opt_buf[len_test].extra = 0;
}
else break;
}
}
return main_len;
}
return 0;
}
/* Test all available options at position 0 of the optimizer buffer.
* The prices at this point are all initialized to kInfinityPrice.
* This function must not be called at a position where no match is
* available. */
FORCE_INLINE_TEMPLATE
size_t LZMA_initOptimizerPos0(LZMA2_ECtx *const enc, FL2_dataBlock const block,
RMF_match const match,
size_t const pos,
int const is_hybrid,
U32* const reps)
{
size_t const max_length = MIN(block.end - pos, kMatchLenMax);
const BYTE *const data = block.data + pos;
const BYTE *data_2;
size_t rep_max_index = 0;
size_t rep_lens[kNumReps];
/* Find any rep matches */
for (size_t i = 0; i < kNumReps; ++i) {
reps[i] = enc->states.reps[i];
data_2 = data - reps[i] - 1;
if (MEM_read16(data) != MEM_read16(data_2)) {
rep_lens[i] = 0;
continue;
}
rep_lens[i] = ZSTD_count(data + 2, data_2 + 2, data + max_length) + 2;
if (rep_lens[i] > rep_lens[rep_max_index])
rep_max_index = i;
}
if (rep_lens[rep_max_index] >= enc->fast_length) {
enc->opt_buf[0].len = (unsigned)(rep_lens[rep_max_index]);
enc->opt_buf[0].dist = (U32)rep_max_index;
return 0;
}
if (match.length >= enc->fast_length) {
enc->opt_buf[0].len = match.length;
enc->opt_buf[0].dist = match.dist + kNumReps;
return 0;
}
unsigned const cur_byte = *data;
unsigned const match_byte = *(data - reps[0] - 1);
size_t const state = enc->states.state;
size_t const pos_state = pos & enc->pos_mask;
LZMA2_prob const is_match_prob = enc->states.is_match[state][pos_state];
LZMA2_prob const is_rep_prob = enc->states.is_rep[state];
enc->opt_buf[0].state = state;
/* Set the price for literal */
enc->opt_buf[1].price = GET_PRICE_0(is_match_prob) +
LZMA_getLiteralPrice(enc, pos, state, data[-1], cur_byte, match_byte);
MARK_LITERAL(enc->opt_buf[1]);
unsigned const match_price = GET_PRICE_1(is_match_prob);
unsigned const rep_match_price = match_price + GET_PRICE_1(is_rep_prob);
if (match_byte == cur_byte) {
/* Try 1-byte rep0 */
unsigned const short_rep_price = rep_match_price + LZMA_getRepLen1Price(enc, state, pos_state);
if (short_rep_price < enc->opt_buf[1].price) {
enc->opt_buf[1].price = short_rep_price;
MARK_SHORT_REP(enc->opt_buf[1]);
}
}
memcpy(enc->opt_buf[0].reps, reps, sizeof(enc->opt_buf[0].reps));
enc->opt_buf[1].len = 1;
/* Test the rep match prices */
for (size_t i = 0; i < kNumReps; ++i) {
size_t rep_len = rep_lens[i];
if (rep_len < 2)
continue;
unsigned const price = rep_match_price + LZMA_getRepPrice(enc, i, state, pos_state);
/* Test every available length of the rep */
do {
unsigned const cur_and_len_price = price + enc->states.rep_len_states.prices[pos_state][rep_len - kMatchLenMin];
if (cur_and_len_price < enc->opt_buf[rep_len].price) {
enc->opt_buf[rep_len].price = cur_and_len_price;
enc->opt_buf[rep_len].len = (unsigned)rep_len;
enc->opt_buf[rep_len].dist = (U32)i;
enc->opt_buf[rep_len].extra = 0;
}
} while (--rep_len >= kMatchLenMin);
}
unsigned const normal_match_price = match_price + GET_PRICE_0(is_rep_prob);
size_t const len = (rep_lens[0] >= 2) ? rep_lens[0] + 1 : 2;
/* Test the match prices */
if (!is_hybrid) {
/* Normal mode */
LZMA_initMatchesPos0(enc, match, pos_state, len, normal_match_price);
return MAX(match.length, rep_lens[rep_max_index]);
}
else {
/* Hybrid mode */
size_t main_len = LZMA_initMatchesPos0Best(enc, block, match, pos, len, normal_match_price);
return MAX(main_len, rep_lens[rep_max_index]);
}
}
FORCE_INLINE_TEMPLATE
size_t LZMA_encodeOptimumSequence(LZMA2_ECtx *const enc, FL2_dataBlock const block,
FL2_matchTable* const tbl,
int const struct_tbl,
int const is_hybrid,
size_t start_index,
size_t const uncompressed_end,
RMF_match match)
{
size_t len_end = enc->len_end_max;
unsigned const search_depth = tbl->params.depth;
do {
size_t const pos_mask = enc->pos_mask;
/* Reset all prices that were set last time */
for (; (len_end & 3) != 0; --len_end)
enc->opt_buf[len_end].price = kInfinityPrice;
for (; len_end >= 4; len_end -= 4) {
enc->opt_buf[len_end].price = kInfinityPrice;
enc->opt_buf[len_end - 1].price = kInfinityPrice;
enc->opt_buf[len_end - 2].price = kInfinityPrice;
enc->opt_buf[len_end - 3].price = kInfinityPrice;
}
/* Set everything up at position 0 */
size_t pos = start_index;
U32 reps[kNumReps];
len_end = LZMA_initOptimizerPos0(enc, block, match, pos, is_hybrid, reps);
match.length = 0;
size_t cur = 1;
/* len_end == 0 if a match of fast_length was found */
if (len_end > 0) {
++pos;
for (; cur < len_end; ++cur, ++pos) {
/* Terminate if the farthest calculated price is too near the buffer end */
if (len_end >= kOptimizerBufferSize - kOptimizerEndSize) {
U32 price = enc->opt_buf[cur].price;
/* This is a compromise to favor more distant end points
* even if the price is a bit higher */
U32 const delta = price / (U32)cur / 2U;
for (size_t j = cur + 1; j <= len_end; j++) {
U32 const price2 = enc->opt_buf[j].price;
if (price >= price2) {
price = price2;
cur = j;
}
price += delta;
}
break;
}
/* Skip ahead if a lower or equal price is available at greater distance */
size_t const end = MIN(cur + kOptimizerSkipSize, len_end);
U32 price = enc->opt_buf[cur].price;
for (size_t j = cur + 1; j <= end; j++) {
U32 const price2 = enc->opt_buf[j].price;
if (price >= price2) {
price = price2;
pos += j - cur;
cur = j;
if (cur == len_end)
goto reverse;
}
}
match = RMF_getMatch(block, tbl, search_depth, struct_tbl, pos);
if (match.length >= enc->fast_length)
break;
len_end = LZMA_optimalParse(enc, block, match, pos, cur, len_end, is_hybrid, reps);
}
reverse:
DEBUGLOG(6, "End optimal parse at %u", (U32)cur);
LZMA_reverseOptimalChain(enc->opt_buf, cur);
}
/* Encode the selections in the buffer */
size_t i = 0;
do {
unsigned const len = enc->opt_buf[i].len;
if (len == 1 && enc->opt_buf[i].dist == kNullDist) {
LZMA_encodeLiteralBuf(enc, block.data, start_index + i);
++i;
}
else {
size_t const pos_state = (start_index + i) & pos_mask;
U32 const dist = enc->opt_buf[i].dist;
/* Updating i separately for each case may allow a branch to be eliminated */
if (dist >= kNumReps) {
LZMA_encodeNormalMatch(enc, len, dist - kNumReps, pos_state);
i += len;
}
else if(len == 1) {
LZMA_encodeRepMatchShort(enc, pos_state);
++i;
}
else {
LZMA_encodeRepMatchLong(enc, len, dist, pos_state);
i += len;
}
}
} while (i < cur);
start_index += i;
/* Do another round if there is a long match pending,
* because the reps must be checked and the match encoded. */
} while (match.length >= enc->fast_length && start_index < uncompressed_end && enc->rc.out_index < enc->chunk_size);
enc->len_end_max = len_end;
return start_index;
}
// **************** NanaZip Modification Start ****************
//static void FORCE_NOINLINE LZMA_fillAlignPrices(LZMA2_ECtx *const enc)
FORCE_NOINLINE void LZMA_fillAlignPrices(LZMA2_ECtx* const enc)
// **************** NanaZip Modification End ****************
{
unsigned i;
const LZMA2_prob *const probs = enc->states.dist_align_encoders;
for (i = 0; i < kAlignTableSize / 2; i++) {
U32 price = 0;
unsigned sym = i;
unsigned m = 1;
unsigned bit;
bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[m], bit); m = (m << 1) + bit;
bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[m], bit); m = (m << 1) + bit;
bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[m], bit); m = (m << 1) + bit;
U32 const prob = probs[m];
enc->align_prices[i] = price + GET_PRICE_0(prob);
enc->align_prices[i + 8] = price + GET_PRICE_1(prob);
}
}
// **************** NanaZip Modification Start ****************
//static void FORCE_NOINLINE LZMA_fillDistancesPrices(LZMA2_ECtx *const enc)
FORCE_NOINLINE void LZMA_fillDistancesPrices(LZMA2_ECtx* const enc)
// **************** NanaZip Modification End ****************
{
U32 * const temp_prices = enc->distance_prices[kNumLenToPosStates - 1];
enc->match_price_count = 0;
for (size_t i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++) {
unsigned const dist_slot = distance_table[i];
unsigned footer_bits = (dist_slot >> 1) - 1;
size_t base = ((2 | (dist_slot & 1)) << footer_bits);
const LZMA2_prob *probs = enc->states.dist_encoders + base * 2U;
base += i;
probs = probs - distance_table[base] - 1;
U32 price = 0;
unsigned m = 1;
unsigned sym = (unsigned)i;
unsigned const offset = (unsigned)1 << footer_bits;
for (; footer_bits != 0; --footer_bits) {
unsigned bit = sym & 1;
sym >>= 1;
price += GET_PRICE(probs[m], bit);
m = (m << 1) + bit;
};
unsigned const prob = probs[m];
temp_prices[base] = price + GET_PRICE_0(prob);
temp_prices[base + offset] = price + GET_PRICE_1(prob);
}
for (unsigned lps = 0; lps < kNumLenToPosStates; lps++) {
size_t slot;
size_t const dist_table_size2 = (enc->dist_price_table_size + 1) >> 1;
U32 *const dist_slot_prices = enc->dist_slot_prices[lps];
const LZMA2_prob *const probs = enc->states.dist_slot_encoders[lps];
for (slot = 0; slot < dist_table_size2; slot++) {
/* dist_slot_prices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices); */
U32 price;
unsigned bit;
unsigned sym = (unsigned)slot + (1 << (kNumPosSlotBits - 1));
bit = sym & 1; sym >>= 1; price = GET_PRICE(probs[sym], bit);
bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);
bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);
bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);
bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);
unsigned const prob = probs[slot + (1 << (kNumPosSlotBits - 1))];
dist_slot_prices[slot * 2] = price + GET_PRICE_0(prob);
dist_slot_prices[slot * 2 + 1] = price + GET_PRICE_1(prob);
}
{
U32 delta = ((U32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
for (slot = kEndPosModelIndex / 2; slot < dist_table_size2; slot++) {
dist_slot_prices[slot * 2] += delta;
dist_slot_prices[slot * 2 + 1] += delta;
delta += ((U32)1 << kNumBitPriceShiftBits);
}
}
{
U32 *const dp = enc->distance_prices[lps];
dp[0] = dist_slot_prices[0];
dp[1] = dist_slot_prices[1];
dp[2] = dist_slot_prices[2];
dp[3] = dist_slot_prices[3];
for (size_t i = 4; i < kNumFullDistances; i += 2) {
U32 slot_price = dist_slot_prices[distance_table[i]];
dp[i] = slot_price + temp_prices[i];
dp[i + 1] = slot_price + temp_prices[i + 1];
}
}
}
}
FORCE_INLINE_TEMPLATE
size_t LZMA_encodeChunkBest(LZMA2_ECtx *const enc,
FL2_dataBlock const block,
FL2_matchTable* const tbl,
int const struct_tbl,
size_t pos,
size_t const uncompressed_end)
{
unsigned const search_depth = tbl->params.depth;
LZMA_fillDistancesPrices(enc);
LZMA_fillAlignPrices(enc);
LZMA_lengthStates_updatePrices(enc, &enc->states.len_states);
LZMA_lengthStates_updatePrices(enc, &enc->states.rep_len_states);
while (pos < uncompressed_end && enc->rc.out_index < enc->chunk_size)
{
RMF_match const match = RMF_getMatch(block, tbl, search_depth, struct_tbl, pos);
if (match.length > 1) {
/* Template-like inline function */
if (enc->strategy == FL2_ultra) {
pos = LZMA_encodeOptimumSequence(enc, block, tbl, struct_tbl, 1, pos, uncompressed_end, match);
}
else {
pos = LZMA_encodeOptimumSequence(enc, block, tbl, struct_tbl, 0, pos, uncompressed_end, match);
}
if (enc->match_price_count >= kMatchRepriceFrequency) {
LZMA_fillAlignPrices(enc);
LZMA_fillDistancesPrices(enc);
LZMA_lengthStates_updatePrices(enc, &enc->states.len_states);
}
if (enc->rep_len_price_count >= kRepLenRepriceFrequency) {
enc->rep_len_price_count = 0;
LZMA_lengthStates_updatePrices(enc, &enc->states.rep_len_states);
}
}
else {
if (block.data[pos] != block.data[pos - enc->states.reps[0] - 1]) {
LZMA_encodeLiteralBuf(enc, block.data, pos);
++pos;
}
else {
LZMA_encodeRepMatchShort(enc, pos & enc->pos_mask);
++pos;
}
}
}
return pos;
}
static void LZMA_lengthStates_Reset(LZMA2_lenStates* const ls, unsigned const fast_length)
{
ls->choice = kProbInitValue;
for (size_t i = 0; i < (kNumPositionStatesMax << (kLenNumLowBits + 1)); ++i)
ls->low[i] = kProbInitValue;
for (size_t i = 0; i < kLenNumHighSymbols; ++i)
ls->high[i] = kProbInitValue;
ls->table_size = fast_length + 1 - kMatchLenMin;
}
static void LZMA_encoderStates_Reset(LZMA2_encStates* const es, unsigned const lc, unsigned const lp, unsigned fast_length)
{
es->state = 0;
for (size_t i = 0; i < kNumReps; ++i)
es->reps[i] = 0;
for (size_t i = 0; i < kNumStates; ++i) {
for (size_t j = 0; j < kNumPositionStatesMax; ++j) {
es->is_match[i][j] = kProbInitValue;
es->is_rep0_long[i][j] = kProbInitValue;
}
es->is_rep[i] = kProbInitValue;
es->is_rep_G0[i] = kProbInitValue;
es->is_rep_G1[i] = kProbInitValue;
es->is_rep_G2[i] = kProbInitValue;
}
size_t const num = (size_t)(kNumLiterals * kNumLitTables) << (lp + lc);
for (size_t i = 0; i < num; ++i)
es->literal_probs[i] = kProbInitValue;
for (size_t i = 0; i < kNumLenToPosStates; ++i) {
LZMA2_prob *probs = es->dist_slot_encoders[i];
for (size_t j = 0; j < (1 << kNumPosSlotBits); ++j)
probs[j] = kProbInitValue;
}
for (size_t i = 0; i < kNumFullDistances - kEndPosModelIndex; ++i)
es->dist_encoders[i] = kProbInitValue;
LZMA_lengthStates_Reset(&es->len_states, fast_length);
LZMA_lengthStates_Reset(&es->rep_len_states, fast_length);
for (size_t i = 0; i < (1 << kNumAlignBits); ++i)
es->dist_align_encoders[i] = kProbInitValue;
}
BYTE LZMA2_getDictSizeProp(size_t const dictionary_size)
{
BYTE dict_size_prop = 0;
for (BYTE bit = 11; bit < 32; ++bit) {
if (((size_t)2 << bit) >= dictionary_size) {
dict_size_prop = (bit - 11) << 1;
break;
}
if (((size_t)3 << bit) >= dictionary_size) {
dict_size_prop = ((bit - 11) << 1) | 1;
break;
}
}
return dict_size_prop;
}
size_t LZMA2_compressBound(size_t src_size)
{
/* Minimum average uncompressed size. An average size of half kChunkSize should be assumed
* to account for thread_count incomplete end chunks per block. LZMA expansion is < 2% so 1/16
* is a safe overestimate. */
static const unsigned chunk_min_avg = (kChunkSize - (kChunkSize / 16U)) / 2U;
/* Maximum size of data stored in a sequence of uncompressed chunks */
return src_size + ((src_size + chunk_min_avg - 1) / chunk_min_avg) * 3 + 6;
}
size_t LZMA2_encMemoryUsage(unsigned const chain_log, FL2_strategy const strategy, unsigned const thread_count)
{
size_t size = sizeof(LZMA2_ECtx);
if(strategy == FL2_ultra)
size += sizeof(LZMA2_hc3) + (sizeof(U32) << chain_log) - sizeof(U32);
return size * thread_count;
}
static void LZMA2_reset(LZMA2_ECtx *const enc, size_t const max_distance)
{
DEBUGLOG(5, "LZMA encoder reset : max_distance %u", (unsigned)max_distance);
RC_reset(&enc->rc);
LZMA_encoderStates_Reset(&enc->states, enc->lc, enc->lp, enc->fast_length);
enc->pos_mask = (1 << enc->pb) - 1;
enc->lit_pos_mask = (1 << enc->lp) - 1;
U32 i = 0;
for (; max_distance > (size_t)1 << i; ++i) {
}
enc->dist_price_table_size = i * 2;
enc->rep_len_price_count = 0;
enc->match_price_count = 0;
}
static BYTE LZMA_getLcLpPbCode(LZMA2_ECtx *const enc)
{
return (BYTE)((enc->pb * 5 + enc->lp) * 9 + enc->lc);
}
/* Integer square root from https://stackoverflow.com/a/1101217 */
static U32 LZMA2_isqrt(U32 op)
{
U32 res = 0;
/* "one" starts at the highest power of four <= than the argument. */
U32 one = (U32)1 << (ZSTD_highbit32(op) & ~1);
while (one != 0) {
if (op >= res + one) {
op -= res + one;
res = res + 2U * one;
}
res >>= 1;
one >>= 2;
}
return res;
}
static BYTE LZMA2_isChunkIncompressible(const FL2_matchTable* const tbl,
FL2_dataBlock const block, size_t const start,
unsigned const strategy)
{
if (block.end - start >= kMinTestChunkSize) {
static const size_t max_dist_table[][5] = {
{ 0, 0, 0, 1U << 6, 1U << 14 }, /* fast */
{ 0, 0, 1U << 6, 1U << 14, 1U << 22 }, /* opt */
{ 0, 0, 1U << 6, 1U << 14, 1U << 22 } }; /* ultra */
static const size_t margin_divisor[3] = { 60U, 45U, 120U };
static const U32 dev_table[3] = { 24, 24, 20};
size_t const end = MIN(start + kChunkSize, block.end);
size_t const chunk_size = end - start;
size_t count = 0;
size_t const margin = chunk_size / margin_divisor[strategy];
size_t const terminator = start + margin;
if (tbl->is_struct) {
size_t prev_dist = 0;
for (size_t pos = start; pos < end; ) {
U32 const link = GetMatchLink(tbl->table, pos);
if (link == RADIX_NULL_LINK) {
++pos;
++count;
prev_dist = 0;
}
else {
size_t const length = GetMatchLength(tbl->table, pos);
size_t const dist = pos - GetMatchLink(tbl->table, pos);
if (length > 4) {
/* Increase the cost if it's not the same match */
count += dist != prev_dist;
}
else {
/* Increment the cost for a short match. The cost is the entire length if it's too far */
count += (dist < max_dist_table[strategy][length]) ? 1 : length;
}
pos += length;
prev_dist = dist;
}
if (count + terminator <= pos)
return 0;
}
}
else {
size_t prev_dist = 0;
for (size_t pos = start; pos < end; ) {
U32 const link = tbl->table[pos];
if (link == RADIX_NULL_LINK) {
++pos;
++count;
prev_dist = 0;
}
else {
size_t const length = link >> RADIX_LINK_BITS;
size_t const dist = pos - (link & RADIX_LINK_MASK);
if (length > 4)
count += dist != prev_dist;
else
count += (dist < max_dist_table[strategy][length]) ? 1 : length;
pos += length;
prev_dist = dist;
}
if (count + terminator <= pos)
return 0;
}
}
U32 char_count[256];
U32 char_total = 0;
/* Expected normal character count * 4 */
U32 const avg = (U32)(chunk_size / 64U);
memset(char_count, 0, sizeof(char_count));
for (size_t pos = start; pos < end; ++pos)
char_count[block.data[pos]] += 4;
/* Sum the deviations */
for (size_t i = 0; i < 256; ++i) {
S32 delta = char_count[i] - avg;
char_total += delta * delta;
}
U32 sqrt_chunk = (chunk_size == kChunkSize) ? kSqrtChunkSize : LZMA2_isqrt((U32)chunk_size);
/* Result base on character count std dev */
return LZMA2_isqrt(char_total) / sqrt_chunk <= dev_table[strategy];
}
return 0;
}
static size_t LZMA2_encodeChunk(LZMA2_ECtx *const enc,
FL2_matchTable* const tbl,
FL2_dataBlock const block,
size_t const pos, size_t const uncompressed_end)
{
/* Template-like inline functions */
if (enc->strategy == FL2_fast) {
if (tbl->is_struct) {
return LZMA_encodeChunkFast(enc, block, tbl, 1,
pos, uncompressed_end);
}
else {
return LZMA_encodeChunkFast(enc, block, tbl, 0,
pos, uncompressed_end);
}
}
else {
if (tbl->is_struct) {
return LZMA_encodeChunkBest(enc, block, tbl, 1,
pos, uncompressed_end);
}
else {
return LZMA_encodeChunkBest(enc, block, tbl, 0,
pos, uncompressed_end);
}
}
}
size_t LZMA2_encode(LZMA2_ECtx *const enc,
FL2_matchTable* const tbl,
FL2_dataBlock const block,
const FL2_lzma2Parameters* const options,
int stream_prop,
FL2_atomic *const progress_in,
FL2_atomic *const progress_out,
int *const canceled)
{
size_t const start = block.start;
/* Output starts in the temp buffer */
BYTE* out_dest = enc->out_buf;
enc->chunk_size = kTempMinOutput;
enc->chunk_limit = kTempBufferSize - kMaxMatchEncodeSize * 2;
/* Each encoder writes a properties byte because the upstream encoder(s) could */
/* write only uncompressed chunks with no properties. */
BYTE encode_properties = 1;
BYTE incompressible = 0;
if (block.end <= block.start)
return 0;
enc->lc = options->lc;
enc->lp = MIN(options->lp, kNumLiteralPosBitsMax);
if (enc->lc + enc->lp > kLcLpMax)
enc->lc = kLcLpMax - enc->lp;
enc->pb = MIN(options->pb, kNumPositionBitsMax);
enc->strategy = options->strategy;
enc->fast_length = MIN(options->fast_length, kMatchLenMax);
enc->match_cycles = MIN(options->match_cycles, kMatchesMax - 1);
LZMA2_reset(enc, block.end);
if (enc->strategy == FL2_ultra) {
/* Create a hash chain to put the encoder into hybrid mode */
if (enc->hash_alloc_3 < ((ptrdiff_t)1 << options->second_dict_bits)) {
if(LZMA_hashCreate(enc, options->second_dict_bits) != 0)
return FL2_ERROR(memory_allocation);
}
else {
LZMA_hashReset(enc, options->second_dict_bits);
}
enc->hash_prev_index = (start >= (size_t)enc->hash_dict_3) ? (ptrdiff_t)(start - enc->hash_dict_3) : (ptrdiff_t)-1;
}
enc->len_end_max = kOptimizerBufferSize - 1;
/* Limit the matches near the end of this slice to not exceed block.end */
RMF_limitLengths(tbl, block.end);
for (size_t pos = start; pos < block.end;) {
size_t header_size = (stream_prop >= 0) + (encode_properties ? kChunkHeaderSize + 1 : kChunkHeaderSize);
LZMA2_encStates saved_states;
size_t next_index;
RC_reset(&enc->rc);
RC_setOutputBuffer(&enc->rc, out_dest + header_size);
if (!incompressible) {
size_t cur = pos;
size_t const end = (enc->strategy == FL2_fast) ? MIN(block.end, pos + kMaxChunkUncompressedSize - kMatchLenMax + 1)
: MIN(block.end, pos + kMaxChunkUncompressedSize - kOptimizerBufferSize + 2); /* last byte of opt_buf unused */
/* Copy states in case chunk is incompressible */
saved_states = enc->states;
if (pos == 0) {
/* First byte of the dictionary */
LZMA_encodeLiteral(enc, 0, block.data[0], 0);
++cur;
}
if (pos == start) {
/* After kTempMinOutput bytes we can write data to the match table because the */
/* compressed data will never catch up with the table position being read. */
cur = LZMA2_encodeChunk(enc, tbl, block, cur, end);
if (header_size + enc->rc.out_index > kTempBufferSize)
return FL2_ERROR(internal);
/* Switch to the match table as output buffer */
out_dest = RMF_getTableAsOutputBuffer(tbl, start);
memcpy(out_dest, enc->out_buf, header_size + enc->rc.out_index);
enc->rc.out_buffer = out_dest + header_size;
/* Now encode up to the full chunk size */
enc->chunk_size = kChunkSize;
enc->chunk_limit = kMaxChunkCompressedSize - kMaxMatchEncodeSize * 2;
}
next_index = LZMA2_encodeChunk(enc, tbl, block, cur, end);
RC_flush(&enc->rc);
}
else {
next_index = MIN(pos + kChunkSize, block.end);
}
size_t compressed_size = enc->rc.out_index;
size_t uncompressed_size = next_index - pos;
if (compressed_size > kMaxChunkCompressedSize || uncompressed_size > kMaxChunkUncompressedSize)
return FL2_ERROR(internal);
BYTE* header = out_dest;
if (stream_prop >= 0) {
*header++ = (BYTE)stream_prop;
stream_prop = -1;
}
header[1] = (BYTE)((uncompressed_size - 1) >> 8);
header[2] = (BYTE)(uncompressed_size - 1);
/* Output an uncompressed chunk if necessary */
if (incompressible || uncompressed_size + 3 <= compressed_size + header_size) {
DEBUGLOG(6, "Storing chunk : was %u => %u", (unsigned)uncompressed_size, (unsigned)compressed_size);
header[0] = (pos == 0) ? kChunkUncompressedDictReset : kChunkUncompressed;
/* Copy uncompressed data into the output */
memcpy(header + 3, block.data + pos, uncompressed_size);
compressed_size = uncompressed_size;
header_size = 3 + (header - out_dest);
/* Restore states if compression was attempted */
if (!incompressible)
enc->states = saved_states;
}
else {
DEBUGLOG(6, "Compressed chunk : %u => %u", (unsigned)uncompressed_size, (unsigned)compressed_size);
if (pos == 0)
header[0] = kChunkCompressedFlag | kChunkAllReset;
else if (encode_properties)
header[0] = kChunkCompressedFlag | kChunkStatePropertiesReset;
else
header[0] = kChunkCompressedFlag | kChunkNothingReset;
header[0] |= (BYTE)((uncompressed_size - 1) >> 16);
header[3] = (BYTE)((compressed_size - 1) >> 8);
header[4] = (BYTE)(compressed_size - 1);
if (encode_properties) {
header[5] = LZMA_getLcLpPbCode(enc);
encode_properties = 0;
}
}
if (incompressible || uncompressed_size + 3 <= compressed_size + (compressed_size >> kRandomFilterMarginBits) + header_size) {
/* Test the next chunk for compressibility */
incompressible = LZMA2_isChunkIncompressible(tbl, block, next_index, enc->strategy);
}
out_dest += compressed_size + header_size;
/* Update progress concurrently with other encoder threads */
FL2_atomic_add(*progress_in, (long)(next_index - pos));
FL2_atomic_add(*progress_out, (long)(compressed_size + header_size));
pos = next_index;
if (*canceled)
return FL2_ERROR(canceled);
}
return out_dest - RMF_getTableAsOutputBuffer(tbl, start);
}
================================================
FILE: NanaZip.Codecs/FastLZMA2/lzma2_enc.h
================================================
/* lzma2_enc.h -- LZMA2 Encoder
Based on LzmaEnc.h and Lzma2Enc.h : Igor Pavlov
Modified for FL2 by Conor McCarthy
Public domain
*/
#ifndef RADYX_LZMA2_ENCODER_H
#define RADYX_LZMA2_ENCODER_H
#include "mem.h"
#include "data_block.h"
#include "radix_mf.h"
#include "atomic.h"
#if defined (__cplusplus)
extern "C" {
#endif
#define kFastDistBits 12U
#define LZMA2_END_MARKER '\0'
#define ENC_MIN_BYTES_PER_THREAD 0x1C000 /* Enough for 8 threads, 1 Mb dict, 2/16 overlap */
typedef struct LZMA2_ECtx_s LZMA2_ECtx;
typedef struct
{
unsigned lc;
unsigned lp;
unsigned pb;
unsigned fast_length;
unsigned match_cycles;
FL2_strategy strategy;
unsigned second_dict_bits;
unsigned reset_interval;
} FL2_lzma2Parameters;
LZMA2_ECtx* LZMA2_createECtx(void);
void LZMA2_freeECtx(LZMA2_ECtx *const enc);
int LZMA2_hashAlloc(LZMA2_ECtx *const enc, const FL2_lzma2Parameters* const options);
size_t LZMA2_encode(LZMA2_ECtx *const enc,
FL2_matchTable* const tbl,
FL2_dataBlock const block,
const FL2_lzma2Parameters* const options,
int stream_prop,
FL2_atomic *const progress_in,
FL2_atomic *const progress_out,
int *const canceled);
BYTE LZMA2_getDictSizeProp(size_t const dictionary_size);
size_t LZMA2_compressBound(size_t src_size);
size_t LZMA2_encMemoryUsage(unsigned const chain_log, FL2_strategy const strategy, unsigned const thread_count);
#if defined (__cplusplus)
}
#endif
#endif /* RADYX_LZMA2_ENCODER_H */
================================================
FILE: NanaZip.Codecs/FastLZMA2/mem.h
================================================
/* NanaZip Header File Redirection */
#include "../Zstandard/common/mem.h"
================================================
FILE: NanaZip.Codecs/FastLZMA2/platform.h
================================================
/*
* Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef PLATFORM_H_MODULE
#define PLATFORM_H_MODULE
#if defined (__cplusplus)
extern "C" {
#endif
/* **************************************
* Compiler Options
****************************************/
#if defined(_MSC_VER)
# define _CRT_SECURE_NO_WARNINGS /* Disable Visual Studio warning messages for fopen, strncpy, strerror */
# if (_MSC_VER <= 1800) /* 1800 == Visual Studio 2013 */
# define _CRT_SECURE_NO_DEPRECATE /* VS2005 - must be declared before and */
# define snprintf sprintf_s /* snprintf unsupported by Visual <= 2013 */
# endif
#endif
/* **************************************
* Detect 64-bit OS
* http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
****************************************/
#if defined __ia64 || defined _M_IA64 /* Intel Itanium */ \
|| defined __powerpc64__ || defined __ppc64__ || defined __PPC64__ /* POWER 64-bit */ \
|| (defined __sparc && (defined __sparcv9 || defined __sparc_v9__ || defined __arch64__)) || defined __sparc64__ /* SPARC 64-bit */ \
|| defined __x86_64__s || defined _M_X64 /* x86 64-bit */ \
|| defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__ /* ARM 64-bit */ \
|| (defined __mips && (__mips == 64 || __mips == 4 || __mips == 3)) /* MIPS 64-bit */ \
|| defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */ \
|| (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8) /* gcc */
# if !defined(__64BIT__)
# define __64BIT__ 1
# endif
#endif
/* *********************************************************
* Turn on Large Files support (>4GB) for 32-bit Linux/Unix
***********************************************************/
#if !defined(__64BIT__) || defined(__MINGW32__) /* No point defining Large file for 64 bit but MinGW-w64 requires it */
# if !defined(_FILE_OFFSET_BITS)
# define _FILE_OFFSET_BITS 64 /* turn off_t into a 64-bit type for ftello, fseeko */
# endif
# if !defined(_LARGEFILE_SOURCE) /* obsolete macro, replaced with _FILE_OFFSET_BITS */
# define _LARGEFILE_SOURCE 1 /* Large File Support extension (LFS) - fseeko, ftello */
# endif
# if defined(_AIX) || defined(__hpux)
# define _LARGE_FILES /* Large file support on 32-bits AIX and HP-UX */
# endif
#endif
/* ************************************************************
* Detect POSIX version
* PLATFORM_POSIX_VERSION = 0 for non-Unix e.g. Windows
* PLATFORM_POSIX_VERSION = 1 for Unix-like but non-POSIX
* PLATFORM_POSIX_VERSION > 1 is equal to found _POSIX_VERSION
* Value of PLATFORM_POSIX_VERSION can be forced on command line
***************************************************************/
#ifndef PLATFORM_POSIX_VERSION
# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */ \
|| defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) /* BSD distros */
/* exception rule : force posix version to 200112L,
* note: it's better to use unistd.h's _POSIX_VERSION whenever possible */
# define PLATFORM_POSIX_VERSION 200112L
/* try to determine posix version through official unistd.h's _POSIX_VERSION (http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html).
* note : there is no simple way to know in advance if is present or not on target system,
* Posix specification mandates its presence and its content, but target system must respect this spec.
* It's necessary to _not_ #include whenever target OS is not unix-like
* otherwise it will block preprocessing stage.
* The following list of build macros tries to "guess" if target OS is likely unix-like, and therefore can #include
*/
# elif !defined(_WIN32) \
&& (defined(__unix__) || defined(__unix) \
|| defined(__midipix__) || defined(__VMS) || defined(__HAIKU__))
# if defined(__linux__) || defined(__linux)
# ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200112L /* feature test macro : https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */
# endif
# endif
# include /* declares _POSIX_VERSION */
# if defined(_POSIX_VERSION) /* POSIX compliant */
# define PLATFORM_POSIX_VERSION _POSIX_VERSION
# else
# define PLATFORM_POSIX_VERSION 1
# endif
# else /* non-unix target platform (like Windows) */
# define PLATFORM_POSIX_VERSION 0
# endif
#endif /* PLATFORM_POSIX_VERSION */
/*-*********************************************
* Detect if isatty() and fileno() are available
************************************************/
#if (defined(__linux__) && (PLATFORM_POSIX_VERSION > 1)) \
|| (PLATFORM_POSIX_VERSION >= 200112L) \
|| defined(__DJGPP__) \
|| defined(__MSYS__)
# include /* isatty */
# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))
#elif defined(MSDOS) || defined(OS2) || defined(__CYGWIN__)
# include /* _isatty */
# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
#elif defined(WIN32) || defined(_WIN32)
# include /* _isatty */
# include /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
# include /* FILE */
static __inline int IS_CONSOLE(FILE* stdStream) {
DWORD dummy;
return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy);
}
#else
# define IS_CONSOLE(stdStream) 0
#endif
/******************************
* OS-specific IO behaviors
******************************/
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32)
# include /* _O_BINARY */
# include /* _setmode, _fileno, _get_osfhandle */
# if !defined(__DJGPP__)
# include /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
# include /* FSCTL_SET_SPARSE */
# define SET_BINARY_MODE(file) { int const unused=_setmode(_fileno(file), _O_BINARY); (void)unused; }
# define SET_SPARSE_FILE_MODE(file) { DWORD dw; DeviceIoControl((HANDLE) _get_osfhandle(_fileno(file)), FSCTL_SET_SPARSE, 0, 0, 0, 0, &dw, 0); }
# else
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
# define SET_SPARSE_FILE_MODE(file)
# endif
#else
# define SET_BINARY_MODE(file)
# define SET_SPARSE_FILE_MODE(file)
#endif
#ifndef ZSTD_SPARSE_DEFAULT
# if (defined(__APPLE__) && defined(__MACH__))
# define ZSTD_SPARSE_DEFAULT 0
# else
# define ZSTD_SPARSE_DEFAULT 1
# endif
#endif
#ifndef ZSTD_START_SYMBOLLIST_FRAME
# ifdef __linux__
# define ZSTD_START_SYMBOLLIST_FRAME 2
# elif defined __APPLE__
# define ZSTD_START_SYMBOLLIST_FRAME 4
# else
# define ZSTD_START_SYMBOLLIST_FRAME 0
# endif
#endif
#ifndef ZSTD_SETPRIORITY_SUPPORT
/* mandates presence of and support for setpriority() : http://man7.org/linux/man-pages/man2/setpriority.2.html */
# define ZSTD_SETPRIORITY_SUPPORT (PLATFORM_POSIX_VERSION >= 200112L)
#endif
#ifndef ZSTD_NANOSLEEP_SUPPORT
/* mandates support of nanosleep() within : http://man7.org/linux/man-pages/man2/nanosleep.2.html */
# if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 199309L)) \
|| (PLATFORM_POSIX_VERSION >= 200112L)
# define ZSTD_NANOSLEEP_SUPPORT 1
# else
# define ZSTD_NANOSLEEP_SUPPORT 0
# endif
#endif
#if defined (__cplusplus)
}
#endif
#endif /* PLATFORM_H_MODULE */
================================================
FILE: NanaZip.Codecs/FastLZMA2/radix_bitpack.c
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include "mem.h" /* U32, U64 */
#include "fl2_threading.h"
#include "fl2_internal.h"
#include "radix_internal.h"
#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define RMF_BITPACK
#define RADIX_MAX_LENGTH BITPACK_MAX_LENGTH
#define InitMatchLink(pos, link) tbl->table[pos] = link
#define GetMatchLink(link) (tbl->table[link] & RADIX_LINK_MASK)
#define GetInitialMatchLink(pos) tbl->table[pos]
#define GetMatchLength(pos) (tbl->table[pos] >> RADIX_LINK_BITS)
#define SetMatchLink(pos, link, length) tbl->table[pos] = (link) | ((U32)(length) << RADIX_LINK_BITS)
#define SetMatchLength(pos, link, length) tbl->table[pos] = (link) | ((U32)(length) << RADIX_LINK_BITS)
#define SetMatchLinkAndLength(pos, link, length) tbl->table[pos] = (link) | ((U32)(length) << RADIX_LINK_BITS)
#define SetNull(pos) tbl->table[pos] = RADIX_NULL_LINK
#define IsNull(pos) (tbl->table[pos] == RADIX_NULL_LINK)
BYTE* RMF_bitpackAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos)
{
return (BYTE*)(tbl->table + pos);
}
/* Restrict the match lengths so that they don't reach beyond pos */
void RMF_bitpackLimitLengths(FL2_matchTable* const tbl, size_t const pos)
{
DEBUGLOG(5, "RMF_limitLengths : end %u, max length %u", (U32)pos, RADIX_MAX_LENGTH);
SetNull(pos - 1);
for (U32 length = 2; length < RADIX_MAX_LENGTH && length <= pos; ++length) {
U32 const link = tbl->table[pos - length];
if (link != RADIX_NULL_LINK)
tbl->table[pos - length] = (MIN(length, link >> RADIX_LINK_BITS) << RADIX_LINK_BITS) | (link & RADIX_LINK_MASK);
}
}
#include "radix_engine.h"
================================================
FILE: NanaZip.Codecs/FastLZMA2/radix_engine.h
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include
#define MAX_READ_BEYOND_DEPTH 2
/* If a repeating byte is found, fill that section of the table with matches of distance 1 */
static size_t RMF_handleRepeat(RMF_builder* const tbl, const BYTE* const data_block, size_t const start, ptrdiff_t i, U32 depth)
{
/* Normally the last 2 bytes, but may be 4 if depth == 4 */
ptrdiff_t const last_2 = i + MAX_REPEAT / 2 - 1;
/* Find the start */
i += (4 - (i & 3)) & 3;
U32 u = *(U32*)(data_block + i);
while (i != 0 && *(U32*)(data_block + i - 4) == u)
i -= 4;
while (i != 0 && data_block[i - 1] == (BYTE)u)
--i;
ptrdiff_t const rpt_index = i;
/* No point if it's in the overlap region */
if (last_2 >= (ptrdiff_t)start) {
U32 len = depth;
/* Set matches at distance 1 and available length */
for (i = last_2; i > rpt_index && len <= RADIX_MAX_LENGTH; --i) {
SetMatchLinkAndLength(i, (U32)(i - 1), len);
++len;
}
/* Set matches at distance 1 and max length */
for (; i > rpt_index; --i)
SetMatchLinkAndLength(i, (U32)(i - 1), RADIX_MAX_LENGTH);
}
return rpt_index;
}
/* If a 2-byte repeat is found, fill that section of the table with matches of distance 2 */
static size_t RMF_handleRepeat2(RMF_builder* const tbl, const BYTE* const data_block, size_t const start, ptrdiff_t i, U32 depth)
{
/* Normally the last 2 bytes, but may be 4 if depth == 4 */
ptrdiff_t const last_2 = i + MAX_REPEAT * 2U - 4;
/* Find the start */
ptrdiff_t realign = i & 1;
i += (4 - (i & 3)) & 3;
U32 u = *(U32*)(data_block + i);
while (i != 0 && *(U32*)(data_block + i - 4) == u)
i -= 4;
while (i != 0 && data_block[i - 1] == data_block[i + 1])
--i;
i += (i & 1) ^ realign;
ptrdiff_t const rpt_index = i;
/* No point if it's in the overlap region */
if (i >= (ptrdiff_t)start) {
U32 len = depth + (data_block[last_2 + depth] == data_block[last_2]);
/* Set matches at distance 2 and available length */
for (i = last_2; i > rpt_index && len <= RADIX_MAX_LENGTH; i -= 2) {
SetMatchLinkAndLength(i, (U32)(i - 2), len);
len += 2;
}
/* Set matches at distance 2 and max length */
for (; i > rpt_index; i -= 2)
SetMatchLinkAndLength(i, (U32)(i - 2), RADIX_MAX_LENGTH);
}
return rpt_index;
}
/* Initialization for the reference algortithm */
#ifdef RMF_REFERENCE
static void RMF_initReference(FL2_matchTable* const tbl, const void* const data, size_t const end)
{
const BYTE* const data_block = (const BYTE*)data;
ptrdiff_t const block_size = end - 1;
size_t st_index = 0;
for (ptrdiff_t i = 0; i < block_size; ++i)
{
size_t const radix_16 = ((size_t)data_block[i] << 8) | data_block[i + 1];
U32 const prev = tbl->list_heads[radix_16].head;
if (prev != RADIX_NULL_LINK) {
SetMatchLinkAndLength(i, prev, 2U);
tbl->list_heads[radix_16].head = (U32)i;
++tbl->list_heads[radix_16].count;
}
else {
SetNull(i);
tbl->list_heads[radix_16].head = (U32)i;
tbl->list_heads[radix_16].count = 1;
tbl->stack[st_index++] = (U32)radix_16;
}
}
SetNull(end - 1);
tbl->end_index = (U32)st_index;
tbl->st_index = ATOMIC_INITIAL_VALUE;
}
#endif
void
#ifdef RMF_BITPACK
RMF_bitpackInit
#else
RMF_structuredInit
#endif
(FL2_matchTable* const tbl, const void* const data, size_t const end)
{
if (end <= 2) {
for (size_t i = 0; i < end; ++i)
SetNull(i);
tbl->end_index = 0;
return;
}
#ifdef RMF_REFERENCE
if (tbl->params.use_ref_mf) {
RMF_initReference(tbl, data, end);
return;
}
#endif
SetNull(0);
const BYTE* const data_block = (const BYTE*)data;
size_t st_index = 0;
/* Initial 2-byte radix value */
size_t radix_16 = ((size_t)data_block[0] << 8) | data_block[1];
tbl->stack[st_index++] = (U32)radix_16;
tbl->list_heads[radix_16].head = 0;
tbl->list_heads[radix_16].count = 1;
radix_16 = ((size_t)((BYTE)radix_16) << 8) | data_block[2];
ptrdiff_t i = 1;
ptrdiff_t const block_size = end - 2;
for (; i < block_size; ++i) {
/* Pre-load the next value for speed increase on some hardware. Execution can continue while memory read is pending */
size_t const next_radix = ((size_t)((BYTE)radix_16) << 8) | data_block[i + 2];
U32 const prev = tbl->list_heads[radix_16].head;
if (prev != RADIX_NULL_LINK) {
/* Link this position to the previous occurrence */
InitMatchLink(i, prev);
/* Set the previous to this position */
tbl->list_heads[radix_16].head = (U32)i;
++tbl->list_heads[radix_16].count;
radix_16 = next_radix;
}
else {
SetNull(i);
tbl->list_heads[radix_16].head = (U32)i;
tbl->list_heads[radix_16].count = 1;
tbl->stack[st_index++] = (U32)radix_16;
radix_16 = next_radix;
}
}
/* Handle the last value */
if (tbl->list_heads[radix_16].head != RADIX_NULL_LINK)
SetMatchLinkAndLength(block_size, tbl->list_heads[radix_16].head, 2);
else
SetNull(block_size);
/* Never a match at the last byte */
SetNull(end - 1);
tbl->end_index = (U32)st_index;
}
/* Copy the list into a buffer and recurse it there. This decreases cache misses and allows */
/* data characters to be loaded every fourth pass and stored for use in the next 4 passes */
static void RMF_recurseListsBuffered(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t const block_end,
size_t link,
U32 depth,
U32 const max_depth,
U32 orig_list_count,
size_t const stack_base)
{
if (orig_list_count < 2 || tbl->match_buffer_limit < 2)
return;
/* Create an offset data buffer pointer for reading the next bytes */
const BYTE* data_src = data_block + depth;
size_t start = 0;
do {
U32 list_count = (U32)(start + orig_list_count);
if (list_count > tbl->match_buffer_limit)
list_count = (U32)tbl->match_buffer_limit;
size_t count = start;
size_t prev_link = (size_t)-1;
size_t rpt = 0;
size_t rpt_tail = link;
for (; count < list_count; ++count) {
/* Pre-load next link */
size_t const next_link = GetMatchLink(link);
size_t dist = prev_link - link;
if (dist > 2) {
/* Get 4 data characters for later. This doesn't block on a cache miss. */
tbl->match_buffer[count].src.u32 = MEM_read32(data_src + link);
/* Record the actual location of this suffix */
tbl->match_buffer[count].from = (U32)link;
/* Initialize the next link */
tbl->match_buffer[count].next = (U32)(count + 1) | (depth << 24);
rpt = 0;
prev_link = link;
rpt_tail = link;
link = next_link;
}
else {
rpt += 3 - dist;
/* Do the usual if the repeat is too short */
if (rpt < MAX_REPEAT - 2) {
/* Get 4 data characters for later. This doesn't block on a cache miss. */
tbl->match_buffer[count].src.u32 = MEM_read32(data_src + link);
/* Record the actual location of this suffix */
tbl->match_buffer[count].from = (U32)link;
/* Initialize the next link */
tbl->match_buffer[count].next = (U32)(count + 1) | (depth << 24);
prev_link = link;
link = next_link;
}
else {
/* Eliminate the repeat from the linked list to save time */
if (dist == 1) {
link = RMF_handleRepeat(tbl, data_block, block_start, link, depth);
count -= MAX_REPEAT / 2;
orig_list_count -= (U32)(rpt_tail - link);
}
else {
link = RMF_handleRepeat2(tbl, data_block, block_start, link, depth);
count -= MAX_REPEAT - 1;
orig_list_count -= (U32)(rpt_tail - link) >> 1;
}
rpt = 0;
list_count = (U32)(start + orig_list_count);
if (list_count > tbl->match_buffer_limit)
list_count = (U32)tbl->match_buffer_limit;
}
}
}
count = list_count;
/* Make the last element circular so pre-loading doesn't read past the end. */
tbl->match_buffer[count - 1].next = (U32)(count - 1) | (depth << 24);
U32 overlap = 0;
if (list_count < (U32)(start + orig_list_count)) {
overlap = list_count >> MATCH_BUFFER_OVERLAP;
overlap += !overlap;
}
RMF_recurseListChunk(tbl, data_block, block_start, block_end, depth, max_depth, list_count, stack_base);
orig_list_count -= (U32)(list_count - start);
/* Copy everything back, except the last link which never changes, and any extra overlap */
count -= overlap + (overlap == 0);
#ifdef RMF_BITPACK
if (max_depth > RADIX_MAX_LENGTH) for (size_t pos = 0; pos < count; ++pos) {
size_t const from = tbl->match_buffer[pos].from;
if (from < block_start)
return;
U32 length = tbl->match_buffer[pos].next >> 24;
length = (length > RADIX_MAX_LENGTH) ? RADIX_MAX_LENGTH : length;
size_t const next = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
SetMatchLinkAndLength(from, tbl->match_buffer[next].from, length);
}
else
#endif
for (size_t pos = 0; pos < count; ++pos) {
size_t const from = tbl->match_buffer[pos].from;
if (from < block_start)
return;
U32 const length = tbl->match_buffer[pos].next >> 24;
size_t const next = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
SetMatchLinkAndLength(from, tbl->match_buffer[next].from, length);
}
start = 0;
if (overlap) {
size_t dest = 0;
for (size_t src = list_count - overlap; src < list_count; ++src) {
tbl->match_buffer[dest].from = tbl->match_buffer[src].from;
tbl->match_buffer[dest].src.u32 = MEM_read32(data_src + tbl->match_buffer[src].from);
tbl->match_buffer[dest].next = (U32)(dest + 1) | (depth << 24);
++dest;
}
start = dest;
}
} while (orig_list_count != 0);
}
/* Parse the list with an upper bound check on data reads. Stop at the point where bound checks are not required. */
/* Buffering is used so that parsing can continue below the bound to find a few matches without altering the main table. */
static void RMF_recurseListsBound(RMF_builder* const tbl,
const BYTE* const data_block,
ptrdiff_t const block_size,
RMF_tableHead* const list_head,
U32 max_depth)
{
U32 list_count = list_head->count;
if (list_count < 2)
return;
ptrdiff_t link = list_head->head;
ptrdiff_t const bounded_size = max_depth + MAX_READ_BEYOND_DEPTH;
ptrdiff_t const bounded_start = block_size - MIN(block_size, bounded_size);
size_t count = 0;
size_t extra_count = (max_depth >> 4) + 4;
list_count = MIN((U32)bounded_size, list_count);
list_count = MIN(list_count, (U32)tbl->match_buffer_size);
for (; count < list_count && extra_count; ++count) {
ptrdiff_t next_link = GetMatchLink(link);
if (link >= bounded_start) {
--list_head->count;
if (next_link < bounded_start)
list_head->head = (U32)next_link;
}
else {
--extra_count;
}
/* Record the actual location of this suffix */
tbl->match_buffer[count].from = (U32)link;
/* Initialize the next link */
tbl->match_buffer[count].next = (U32)(count + 1) | ((U32)2 << 24);
link = next_link;
}
list_count = (U32)count;
ptrdiff_t limit = block_size - 2;
/* Create an offset data buffer pointer for reading the next bytes */
const BYTE* data_src = data_block + 2;
U32 depth = 3;
size_t pos = 0;
size_t st_index = 0;
RMF_listTail* const tails_8 = tbl->tails_8;
do {
link = tbl->match_buffer[pos].from;
if (link < limit) {
size_t const radix_8 = data_src[link];
/* Seen this char before? */
U32 const prev = tails_8[radix_8].prev_index;
tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
++tails_8[radix_8].list_count;
/* Link the previous occurrence to this one and record the new length */
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
tails_8[radix_8].list_count = 1;
/* Add the new sub list to the stack */
tbl->stack[st_index].head = (U32)pos;
/* This will be converted to a count at the end */
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
}
++pos;
} while (pos < list_count);
/* Convert radix values on the stack to counts and reset any used tail slots */
for (size_t j = 0; j < st_index; ++j) {
tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;
tbl->stack[j].count = tails_8[tbl->stack[j].count].list_count;
}
while (st_index > 0) {
size_t prev_st_index;
/* Pop an item off the stack */
--st_index;
list_count = tbl->stack[st_index].count;
if (list_count < 2) /* Nothing to match with */
continue;
pos = tbl->stack[st_index].head;
depth = (tbl->match_buffer[pos].next >> 24);
if (depth >= max_depth)
continue;
link = tbl->match_buffer[pos].from;
if (link < bounded_start) {
/* Chain starts before the bounded region */
continue;
}
data_src = data_block + depth;
limit = block_size - depth;
++depth;
prev_st_index = st_index;
do {
link = tbl->match_buffer[pos].from;
if (link < limit) {
size_t const radix_8 = data_src[link];
U32 const prev = tails_8[radix_8].prev_index;
tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
++tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
tails_8[radix_8].list_count = 1;
tbl->stack[st_index].head = (U32)pos;
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
}
pos = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
} while (--list_count != 0);
for (size_t j = prev_st_index; j < st_index; ++j) {
tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;
tbl->stack[j].count = tails_8[tbl->stack[j].count].list_count;
}
}
/* Copy everything back above the bound */
--count;
for (pos = 0; pos < count; ++pos) {
ptrdiff_t const from = tbl->match_buffer[pos].from;
if (from < bounded_start)
break;
U32 length = tbl->match_buffer[pos].next >> 24;
length = MIN(length, (U32)(block_size - from));
length = MIN(length, RADIX_MAX_LENGTH);
size_t const next = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
SetMatchLinkAndLength(from, tbl->match_buffer[next].from, length);
}
}
/* Compare each string with all others to find the best match */
static void RMF_bruteForce(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t link,
size_t const list_count,
U32 const depth,
U32 const max_depth)
{
const BYTE* data_src = data_block + depth;
size_t buffer[MAX_BRUTE_FORCE_LIST_SIZE + 1];
size_t const limit = max_depth - depth;
size_t i = 1;
buffer[0] = link;
/* Pre-load all locations */
do {
link = GetMatchLink(link);
buffer[i] = link;
} while (++i < list_count);
i = 0;
do {
size_t longest = 0;
size_t j = i + 1;
size_t longest_index = j;
const BYTE* const data = data_src + buffer[i];
do {
const BYTE* data_2 = data_src + buffer[j];
size_t len_test = 0;
while (data[len_test] == data_2[len_test] && len_test < limit)
++len_test;
if (len_test > longest) {
longest_index = j;
longest = len_test;
if (len_test >= limit)
break;
}
} while (++j < list_count);
if (longest > 0)
SetMatchLinkAndLength(buffer[i], (U32)buffer[longest_index], depth + (U32)longest);
++i;
/* Test with block_start to avoid wasting time matching strings in the overlap region with each other */
} while (i < list_count - 1 && buffer[i] >= block_start);
}
/* RMF_recurseLists16() :
* Match strings at depth 2 using a 16-bit radix to lengthen to depth 4
*/
static void RMF_recurseLists16(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t const block_end,
size_t link,
U32 count,
U32 const max_depth)
{
U32 const table_max_depth = MIN(max_depth, RADIX_MAX_LENGTH);
/* Offset data pointer. This function is only called at depth 2 */
const BYTE* const data_src = data_block + 2;
/* Load radix values from the data chars */
size_t next_radix_8 = data_src[link];
size_t next_radix_16 = next_radix_8 + ((size_t)(data_src[link + 1]) << 8);
size_t reset_list[RADIX8_TABLE_SIZE];
size_t reset_count = 0;
size_t st_index = 0;
/* Last one is done separately */
--count;
do
{
/* Pre-load the next link */
size_t const next_link = GetInitialMatchLink(link);
size_t const radix_8 = next_radix_8;
size_t const radix_16 = next_radix_16;
/* Initialization doesn't set lengths to 2 because it's a waste of time if buffering is used */
SetMatchLength(link, (U32)next_link, 2);
next_radix_8 = data_src[next_link];
next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);
U32 prev = tbl->tails_8[radix_8].prev_index;
tbl->tails_8[radix_8].prev_index = (U32)link;
if (prev != RADIX_NULL_LINK) {
/* Link the previous occurrence to this one at length 3. */
/* This will be overwritten if a 4 is found. */
SetMatchLinkAndLength(prev, (U32)link, 3);
}
else {
reset_list[reset_count++] = radix_8;
}
prev = tbl->tails_16[radix_16].prev_index;
tbl->tails_16[radix_16].prev_index = (U32)link;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_16[radix_16].list_count;
/* Link at length 4, overwriting the 3 */
SetMatchLinkAndLength(prev, (U32)link, 4);
}
else {
tbl->tails_16[radix_16].list_count = 1;
tbl->stack[st_index].head = (U32)link;
/* Store a reference to this table location to retrieve the count at the end */
tbl->stack[st_index].count = (U32)radix_16;
++st_index;
}
link = next_link;
} while (--count > 0);
/* Do the last location */
U32 prev = tbl->tails_8[next_radix_8].prev_index;
if (prev != RADIX_NULL_LINK)
SetMatchLinkAndLength(prev, (U32)link, 3);
prev = tbl->tails_16[next_radix_16].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_16[next_radix_16].list_count;
SetMatchLinkAndLength(prev, (U32)link, 4);
}
for (size_t i = 0; i < reset_count; ++i)
tbl->tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;
for (size_t i = 0; i < st_index; ++i) {
tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;
tbl->stack[i].count = tbl->tails_16[tbl->stack[i].count].list_count;
}
while (st_index > 0) {
--st_index;
U32 const list_count = tbl->stack[st_index].count;
if (list_count < 2) {
/* Nothing to do */
continue;
}
link = tbl->stack[st_index].head;
if (link < block_start)
continue;
if (st_index > STACK_SIZE - RADIX16_TABLE_SIZE
&& st_index > STACK_SIZE - list_count)
{
/* Potential stack overflow. Rare. */
continue;
}
/* The current depth */
U32 const depth = GetMatchLength(link);
if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE) {
/* Quicker to use brute force, each string compared with all previous strings */
RMF_bruteForce(tbl, data_block,
block_start,
link,
list_count,
depth,
table_max_depth);
continue;
}
/* Send to the buffer at depth 4 */
RMF_recurseListsBuffered(tbl,
data_block,
block_start,
block_end,
link,
(BYTE)depth,
(BYTE)max_depth,
list_count,
st_index);
}
}
#if 0
/* Unbuffered complete processing to max_depth.
* This may be faster on CPUs without a large memory cache.
*/
static void RMF_recurseListsUnbuf16(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t link,
U32 count,
U32 const max_depth)
{
/* Offset data pointer. This method is only called at depth 2 */
const BYTE* data_src = data_block + 2;
/* Load radix values from the data chars */
size_t next_radix_8 = data_src[link];
size_t next_radix_16 = next_radix_8 + ((size_t)(data_src[link + 1]) << 8);
RMF_listTail* tails_8 = tbl->tails_8;
size_t reset_list[RADIX8_TABLE_SIZE];
size_t reset_count = 0;
size_t st_index = 0;
/* Last one is done separately */
--count;
do
{
/* Pre-load the next link */
size_t next_link = GetInitialMatchLink(link);
/* Initialization doesn't set lengths to 2 because it's a waste of time if buffering is used */
SetMatchLength(link, (U32)next_link, 2);
size_t radix_8 = next_radix_8;
size_t radix_16 = next_radix_16;
next_radix_8 = data_src[next_link];
next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);
U32 prev = tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
/* Link the previous occurrence to this one at length 3. */
/* This will be overwritten if a 4 is found. */
SetMatchLinkAndLength(prev, (U32)link, 3);
}
else {
reset_list[reset_count++] = radix_8;
}
tails_8[radix_8].prev_index = (U32)link;
prev = tbl->tails_16[radix_16].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_16[radix_16].list_count;
/* Link at length 4, overwriting the 3 */
SetMatchLinkAndLength(prev, (U32)link, 4);
}
else {
tbl->tails_16[radix_16].list_count = 1;
tbl->stack[st_index].head = (U32)link;
tbl->stack[st_index].count = (U32)radix_16;
++st_index;
}
tbl->tails_16[radix_16].prev_index = (U32)link;
link = next_link;
} while (--count > 0);
/* Do the last location */
U32 prev = tails_8[next_radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
SetMatchLinkAndLength(prev, (U32)link, 3);
}
prev = tbl->tails_16[next_radix_16].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_16[next_radix_16].list_count;
SetMatchLinkAndLength(prev, (U32)link, 4);
}
for (size_t i = 0; i < reset_count; ++i) {
tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;
}
reset_count = 0;
for (size_t i = 0; i < st_index; ++i) {
tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;
tbl->stack[i].count = tbl->tails_16[tbl->stack[i].count].list_count;
}
while (st_index > 0) {
--st_index;
U32 list_count = tbl->stack[st_index].count;
if (list_count < 2) {
/* Nothing to do */
continue;
}
link = tbl->stack[st_index].head;
if (link < block_start)
continue;
if (st_index > STACK_SIZE - RADIX16_TABLE_SIZE
&& st_index > STACK_SIZE - list_count)
{
/* Potential stack overflow. Rare. */
continue;
}
/* The current depth */
U32 depth = GetMatchLength(link);
if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE) {
/* Quicker to use brute force, each string compared with all previous strings */
RMF_bruteForce(tbl, data_block,
block_start,
link,
list_count,
depth,
max_depth);
continue;
}
const BYTE* data_src = data_block + depth;
size_t next_radix_8 = data_src[link];
size_t next_radix_16 = next_radix_8 + ((size_t)(data_src[link + 1]) << 8);
/* Next depth for 1 extra char */
++depth;
/* and for 2 */
U32 depth_2 = depth + 1;
size_t prev_st_index = st_index;
/* Last location is done separately */
--list_count;
/* Last pass is done separately. Both of these values are always even. */
if (depth_2 < max_depth) {
do {
size_t radix_8 = next_radix_8;
size_t radix_16 = next_radix_16;
size_t next_link = GetMatchLink(link);
next_radix_8 = data_src[next_link];
next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);
size_t prev = tbl->tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
/* Odd numbered match length, will be overwritten if 2 chars are matched */
SetMatchLinkAndLength(prev, (U32)(link), depth);
}
else {
reset_list[reset_count++] = radix_8;
}
tbl->tails_8[radix_8].prev_index = (U32)link;
prev = tbl->tails_16[radix_16].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_16[radix_16].list_count;
SetMatchLinkAndLength(prev, (U32)(link), depth_2);
}
else {
tbl->tails_16[radix_16].list_count = 1;
tbl->stack[st_index].head = (U32)(link);
tbl->stack[st_index].count = (U32)(radix_16);
++st_index;
}
tbl->tails_16[radix_16].prev_index = (U32)(link);
link = next_link;
} while (--list_count != 0);
size_t prev = tbl->tails_8[next_radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
SetMatchLinkAndLength(prev, (U32)(link), depth);
}
prev = tbl->tails_16[next_radix_16].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_16[next_radix_16].list_count;
SetMatchLinkAndLength(prev, (U32)(link), depth_2);
}
for (size_t i = prev_st_index; i < st_index; ++i) {
tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;
tbl->stack[i].count = tbl->tails_16[tbl->stack[i].count].list_count;
}
for (size_t i = 0; i < reset_count; ++i) {
tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;
}
reset_count = 0;
}
else {
do {
size_t radix_8 = next_radix_8;
size_t radix_16 = next_radix_16;
size_t next_link = GetMatchLink(link);
next_radix_8 = data_src[next_link];
next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);
size_t prev = tbl->tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
SetMatchLinkAndLength(prev, (U32)(link), depth);
}
else {
reset_list[reset_count++] = radix_8;
}
tbl->tails_8[radix_8].prev_index = (U32)link;
prev = tbl->tails_16[radix_16].prev_index;
if (prev != RADIX_NULL_LINK) {
SetMatchLinkAndLength(prev, (U32)(link), depth_2);
}
else {
tbl->stack[st_index].count = (U32)radix_16;
++st_index;
}
tbl->tails_16[radix_16].prev_index = (U32)(link);
link = next_link;
} while (--list_count != 0);
size_t prev = tbl->tails_8[next_radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
SetMatchLinkAndLength(prev, (U32)(link), depth);
}
prev = tbl->tails_16[next_radix_16].prev_index;
if (prev != RADIX_NULL_LINK) {
SetMatchLinkAndLength(prev, (U32)(link), depth_2);
}
for (size_t i = prev_st_index; i < st_index; ++i) {
tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;
}
st_index = prev_st_index;
for (size_t i = 0; i < reset_count; ++i) {
tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;
}
reset_count = 0;
}
}
}
#endif
#ifdef RMF_REFERENCE
/* Simple, slow, complete parsing for reference */
static void RMF_recurseListsReference(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_size,
size_t link,
U32 count,
U32 const max_depth)
{
/* Offset data pointer. This method is only called at depth 2 */
const BYTE* data_src = data_block + 2;
size_t limit = block_size - 2;
size_t st_index = 0;
do
{
if (link < limit) {
size_t const radix_8 = data_src[link];
size_t const prev = tbl->tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_8[radix_8].list_count;
SetMatchLinkAndLength(prev, (U32)link, 3);
}
else {
tbl->tails_8[radix_8].list_count = 1;
tbl->stack[st_index].head = (U32)link;
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
tbl->tails_8[radix_8].prev_index = (U32)link;
}
link = GetMatchLink(link);
} while (--count > 0);
for (size_t i = 0; i < st_index; ++i) {
tbl->stack[i].count = tbl->tails_8[tbl->stack[i].count].list_count;
}
memset(tbl->tails_8, 0xFF, sizeof(tbl->tails_8));
while (st_index > 0) {
--st_index;
U32 list_count = tbl->stack[st_index].count;
if (list_count < 2) {
/* Nothing to do */
continue;
}
if (st_index > STACK_SIZE - RADIX8_TABLE_SIZE
&& st_index > STACK_SIZE - list_count)
{
/* Potential stack overflow. Rare. */
continue;
}
link = tbl->stack[st_index].head;
/* The current depth */
U32 depth = GetMatchLength(link);
if (depth >= max_depth)
continue;
data_src = data_block + depth;
limit = block_size - depth;
/* Next depth for 1 extra char */
++depth;
size_t prev_st_index = st_index;
do {
if (link < limit) {
size_t const radix_8 = data_src[link];
size_t const prev = tbl->tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_8[radix_8].list_count;
SetMatchLinkAndLength(prev, (U32)link, depth);
}
else {
tbl->tails_8[radix_8].list_count = 1;
tbl->stack[st_index].head = (U32)link;
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
tbl->tails_8[radix_8].prev_index = (U32)link;
}
link = GetMatchLink(link);
} while (--list_count != 0);
for (size_t i = prev_st_index; i < st_index; ++i) {
tbl->stack[i].count = tbl->tails_8[tbl->stack[i].count].list_count;
}
memset(tbl->tails_8, 0xFF, sizeof(tbl->tails_8));
}
}
#endif /* RMF_REFERENCE */
/* Atomically take a list from the head table */
static ptrdiff_t RMF_getNextList_mt(FL2_matchTable* const tbl)
{
if (tbl->st_index < tbl->end_index) {
long pos = FL2_atomic_increment(tbl->st_index);
if (pos < tbl->end_index)
return pos;
}
return -1;
}
/* Non-atomically take a list from the head table */
static ptrdiff_t RMF_getNextList_st(FL2_matchTable* const tbl)
{
if (tbl->st_index < tbl->end_index) {
long pos = FL2_nonAtomic_increment(tbl->st_index);
if (pos < tbl->end_index)
return pos;
}
return -1;
}
/* Iterate the head table concurrently with other threads, and recurse each list until max_depth is reached */
void
#ifdef RMF_BITPACK
RMF_bitpackBuildTable
#else
RMF_structuredBuildTable
#endif
(FL2_matchTable* const tbl,
size_t const job,
unsigned const multi_thread,
FL2_dataBlock const block)
{
if (block.end == 0)
return;
unsigned const best = !tbl->params.divide_and_conquer;
unsigned const max_depth = MIN(tbl->params.depth, STRUCTURED_MAX_LENGTH) & ~1;
size_t bounded_start = max_depth + MAX_READ_BEYOND_DEPTH;
bounded_start = block.end - MIN(block.end, bounded_start);
ptrdiff_t next_progress = (job == 0) ? 0 : RADIX16_TABLE_SIZE;
ptrdiff_t(*getNextList)(FL2_matchTable* const tbl)
= multi_thread ? RMF_getNextList_mt : RMF_getNextList_st;
for (;;)
{
/* Get the next to process */
ptrdiff_t pos = getNextList(tbl);
if (pos < 0)
break;
while (next_progress < pos) {
/* initial value of next_progress ensures only thread 0 executes this */
tbl->progress += tbl->list_heads[tbl->stack[next_progress]].count;
++next_progress;
}
pos = tbl->stack[pos];
RMF_tableHead list_head = tbl->list_heads[pos];
tbl->list_heads[pos].head = RADIX_NULL_LINK;
if (list_head.count < 2 || list_head.head < block.start)
continue;
#ifdef RMF_REFERENCE
if (tbl->params.use_ref_mf) {
RMF_recurseListsReference(tbl->builders[job], block.data, block.end, list_head.head, list_head.count, max_depth);
continue;
}
#endif
if (list_head.head >= bounded_start) {
RMF_recurseListsBound(tbl->builders[job], block.data, block.end, &list_head, max_depth);
if (list_head.count < 2 || list_head.head < block.start)
continue;
}
if (best && list_head.count > tbl->builders[job]->match_buffer_limit)
{
/* Not worth buffering or too long */
RMF_recurseLists16(tbl->builders[job], block.data, block.start, block.end, list_head.head, list_head.count, max_depth);
}
else {
RMF_recurseListsBuffered(tbl->builders[job], block.data, block.start, block.end, list_head.head, 2, (BYTE)max_depth, list_head.count, 0);
}
}
}
int
#ifdef RMF_BITPACK
RMF_bitpackIntegrityCheck
#else
RMF_structuredIntegrityCheck
#endif
(const FL2_matchTable* const tbl, const BYTE* const data, size_t pos, size_t const end, unsigned max_depth)
{
max_depth &= ~1;
int err = 0;
for (pos += !pos; pos < end; ++pos) {
if (IsNull(pos))
continue;
U32 const link = GetMatchLink(pos);
if (link >= pos) {
printf("Forward link at %X to %u\r\n", (U32)pos, link);
err = 1;
continue;
}
U32 const length = GetMatchLength(pos);
if (pos && length < RADIX_MAX_LENGTH && link - 1 == GetMatchLink(pos - 1) && length + 1 == GetMatchLength(pos - 1))
continue;
U32 len_test = 0;
U32 const limit = MIN((U32)(end - pos), RADIX_MAX_LENGTH);
for (; len_test < limit && data[link + len_test] == data[pos + len_test]; ++len_test) {
}
if (len_test < length) {
printf("Failed integrity check: pos %X, length %u, actual %u\r\n", (U32)pos, length, len_test);
err = 1;
}
if (length < max_depth && len_test > length)
/* These occur occasionally due to splitting of chains in the buffer when long repeats are present */
printf("Shortened match at %X: %u of %u\r\n", (U32)pos, length, len_test);
}
return err;
}
================================================
FILE: NanaZip.Codecs/FastLZMA2/radix_get.h
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef FL2_RADIX_GET_H_
#define FL2_RADIX_GET_H_
#if defined (__cplusplus)
extern "C" {
#endif
typedef struct
{
U32 length;
U32 dist;
} RMF_match;
static size_t RMF_bitpackExtendMatch(const BYTE* const data,
const U32* const table,
ptrdiff_t const start_index,
ptrdiff_t limit,
U32 const link,
size_t const length)
{
ptrdiff_t end_index = start_index + length;
ptrdiff_t const dist = start_index - link;
if (limit > start_index + (ptrdiff_t)kMatchLenMax)
limit = start_index + kMatchLenMax;
while (end_index < limit && end_index - (ptrdiff_t)(table[end_index] & RADIX_LINK_MASK) == dist)
end_index += table[end_index] >> RADIX_LINK_BITS;
if (end_index >= limit) {
DEBUGLOG(7, "RMF_bitpackExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(limit - start_index));
return limit - start_index;
}
while (end_index < limit && data[end_index - dist] == data[end_index])
++end_index;
DEBUGLOG(7, "RMF_bitpackExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(end_index - start_index));
return end_index - start_index;
}
#define GetMatchLink(table, pos) ((const RMF_unit*)(table))[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK]
#define GetMatchLength(table, pos) ((const RMF_unit*)(table))[(pos) >> UNIT_BITS].lengths[(pos) & UNIT_MASK]
static size_t RMF_structuredExtendMatch(const BYTE* const data,
const U32* const table,
ptrdiff_t const start_index,
ptrdiff_t limit,
U32 const link,
size_t const length)
{
ptrdiff_t end_index = start_index + length;
ptrdiff_t const dist = start_index - link;
if (limit > start_index + (ptrdiff_t)kMatchLenMax)
limit = start_index + kMatchLenMax;
while (end_index < limit && end_index - (ptrdiff_t)GetMatchLink(table, end_index) == dist)
end_index += GetMatchLength(table, end_index);
if (end_index >= limit) {
DEBUGLOG(7, "RMF_structuredExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(limit - start_index));
return limit - start_index;
}
while (end_index < limit && data[end_index - dist] == data[end_index])
++end_index;
DEBUGLOG(7, "RMF_structuredExtendMatch : pos %u, link %u, init length %u, full length %u", (U32)start_index, link, (U32)length, (U32)(end_index - start_index));
return end_index - start_index;
}
FORCE_INLINE_TEMPLATE
RMF_match RMF_getMatch(FL2_dataBlock block,
FL2_matchTable* tbl,
unsigned max_depth,
int structTbl,
size_t pos)
{
if (structTbl)
{
U32 const link = GetMatchLink(tbl->table, pos);
RMF_match match;
match.length = 0;
if (link == RADIX_NULL_LINK)
return match;
size_t const length = GetMatchLength(tbl->table, pos);
size_t const dist = pos - link - 1;
if (length == max_depth || length == STRUCTURED_MAX_LENGTH /* from HandleRepeat */)
match.length = (U32)RMF_structuredExtendMatch(block.data, tbl->table, pos, block.end, link, length);
else
match.length = (U32)length;
match.dist = (U32)dist;
return match;
}
else {
U32 link = tbl->table[pos];
RMF_match match;
match.length = 0;
if (link == RADIX_NULL_LINK)
return match;
size_t const length = link >> RADIX_LINK_BITS;
link &= RADIX_LINK_MASK;
size_t const dist = pos - link - 1;
if (length == max_depth || length == BITPACK_MAX_LENGTH /* from HandleRepeat */)
match.length = (U32)RMF_bitpackExtendMatch(block.data, tbl->table, pos, block.end, link, length);
else
match.length = (U32)length;
match.dist = (U32)dist;
return match;
}
}
FORCE_INLINE_TEMPLATE
RMF_match RMF_getNextMatch(FL2_dataBlock block,
FL2_matchTable* tbl,
unsigned max_depth,
int structTbl,
size_t pos)
{
if (structTbl)
{
U32 const link = GetMatchLink(tbl->table, pos);
RMF_match match;
match.length = 0;
if (link == RADIX_NULL_LINK)
return match;
size_t const length = GetMatchLength(tbl->table, pos);
size_t const dist = pos - link - 1;
/* same distance, one byte shorter */
if (link - 1 == GetMatchLink(tbl->table, pos - 1))
return match;
if (length == max_depth || length == STRUCTURED_MAX_LENGTH /* from HandleRepeat */)
match.length = (U32)RMF_structuredExtendMatch(block.data, tbl->table, pos, block.end, link, length);
else
match.length = (U32)length;
match.dist = (U32)dist;
return match;
}
else {
U32 link = tbl->table[pos];
RMF_match match;
match.length = 0;
if (link == RADIX_NULL_LINK)
return match;
size_t const length = link >> RADIX_LINK_BITS;
link &= RADIX_LINK_MASK;
size_t const dist = pos - link - 1;
/* same distance, one byte shorter */
if (link - 1 == (tbl->table[pos - 1] & RADIX_LINK_MASK))
return match;
if (length == max_depth || length == BITPACK_MAX_LENGTH /* from HandleRepeat */)
match.length = (U32)RMF_bitpackExtendMatch(block.data, tbl->table, pos, block.end, link, length);
else
match.length = (U32)length;
match.dist = (U32)dist;
return match;
}
}
#if defined (__cplusplus)
}
#endif
#endif /* FL2_RADIX_GET_H_ */
================================================
FILE: NanaZip.Codecs/FastLZMA2/radix_internal.h
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef RADIX_INTERNAL_H
#define RADIX_INTERNAL_H
#include "atomic.h"
#include "radix_mf.h"
#if defined(FL2_XZ_BUILD) && defined(TUKLIB_FAST_UNALIGNED_ACCESS)
# define MEM_read32(a) (*(const U32*)(a))
#endif
#if defined (__cplusplus)
extern "C" {
#endif
#define DICTIONARY_LOG_MIN 12U
#define DICTIONARY_LOG_MAX_64 30U
#define DICTIONARY_LOG_MAX_32 27U
#define DICTIONARY_SIZE_MIN ((size_t)1 << DICTIONARY_LOG_MIN)
#define DICTIONARY_SIZE_MAX_64 ((size_t)1 << DICTIONARY_LOG_MAX_64)
#define DICTIONARY_SIZE_MAX_32 ((size_t)1 << DICTIONARY_LOG_MAX_32)
#define MAX_REPEAT 24
#define RADIX16_TABLE_SIZE ((size_t)1 << 16)
#define RADIX8_TABLE_SIZE ((size_t)1 << 8)
#define STACK_SIZE (RADIX16_TABLE_SIZE * 3)
#define MAX_BRUTE_FORCE_LIST_SIZE 5
#define BUFFER_LINK_MASK 0xFFFFFFU
#define MATCH_BUFFER_OVERLAP 6
#define BITPACK_MAX_LENGTH 63U
#define STRUCTURED_MAX_LENGTH 255U
#define RADIX_LINK_BITS 26
#define RADIX_LINK_MASK ((1U << RADIX_LINK_BITS) - 1)
#define RADIX_NULL_LINK 0xFFFFFFFFU
#define UNIT_BITS 2
#define UNIT_MASK ((1U << UNIT_BITS) - 1)
#define RADIX_CANCEL_INDEX (long)(RADIX16_TABLE_SIZE + FL2_MAXTHREADS + 2)
typedef struct
{
U32 head;
U32 count;
} RMF_tableHead;
union src_data_u {
BYTE chars[4];
U32 u32;
};
typedef struct
{
U32 from;
union src_data_u src;
U32 next;
} RMF_buildMatch;
typedef struct
{
U32 prev_index;
U32 list_count;
} RMF_listTail;
typedef struct
{
U32 links[1 << UNIT_BITS];
BYTE lengths[1 << UNIT_BITS];
} RMF_unit;
typedef struct
{
unsigned max_len;
U32* table;
size_t match_buffer_size;
size_t match_buffer_limit;
RMF_listTail tails_8[RADIX8_TABLE_SIZE];
RMF_tableHead stack[STACK_SIZE];
RMF_listTail tails_16[RADIX16_TABLE_SIZE];
RMF_buildMatch match_buffer[1];
} RMF_builder;
struct FL2_matchTable_s
{
FL2_atomic st_index;
long end_index;
int is_struct;
int alloc_struct;
unsigned thread_count;
size_t unreduced_dict_size;
size_t progress;
RMF_parameters params;
RMF_builder** builders;
U32 stack[RADIX16_TABLE_SIZE];
RMF_tableHead list_heads[RADIX16_TABLE_SIZE];
U32 table[1];
};
void RMF_bitpackInit(struct FL2_matchTable_s* const tbl, const void* data, size_t const end);
void RMF_structuredInit(struct FL2_matchTable_s* const tbl, const void* data, size_t const end);
void RMF_bitpackBuildTable(struct FL2_matchTable_s* const tbl,
size_t const job,
unsigned const multi_thread,
FL2_dataBlock const block);
void RMF_structuredBuildTable(struct FL2_matchTable_s* const tbl,
size_t const job,
unsigned const multi_thread,
FL2_dataBlock const block);
void RMF_recurseListChunk(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t const block_end,
U32 const depth,
U32 const max_depth,
U32 const list_count,
size_t const stack_base);
int RMF_bitpackIntegrityCheck(const struct FL2_matchTable_s* const tbl, const BYTE* const data, size_t pos, size_t const end, unsigned max_depth);
int RMF_structuredIntegrityCheck(const struct FL2_matchTable_s* const tbl, const BYTE* const data, size_t pos, size_t const end, unsigned max_depth);
void RMF_bitpackLimitLengths(struct FL2_matchTable_s* const tbl, size_t const pos);
void RMF_structuredLimitLengths(struct FL2_matchTable_s* const tbl, size_t const pos);
BYTE* RMF_bitpackAsOutputBuffer(struct FL2_matchTable_s* const tbl, size_t const pos);
BYTE* RMF_structuredAsOutputBuffer(struct FL2_matchTable_s* const tbl, size_t const pos);
size_t RMF_bitpackGetMatch(const struct FL2_matchTable_s* const tbl,
const BYTE* const data,
size_t const pos,
size_t const limit,
unsigned const max_depth,
size_t* const offset_ptr);
size_t RMF_structuredGetMatch(const struct FL2_matchTable_s* const tbl,
const BYTE* const data,
size_t const pos,
size_t const limit,
unsigned const max_depth,
size_t* const offset_ptr);
#if defined (__cplusplus)
}
#endif
#endif /* RADIX_INTERNAL_H */
================================================
FILE: NanaZip.Codecs/FastLZMA2/radix_mf.c
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include /* size_t, ptrdiff_t */
#include /* malloc, free */
#include "fast-lzma2.h"
#include "fl2_errors.h"
#include "mem.h" /* U32, U64, MEM_64bits */
#include "fl2_internal.h"
#include "radix_internal.h"
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" /* warning: 'rpt_head_next' may be used uninitialized in this function */
#elif defined(_MSC_VER)
# pragma warning(disable : 4701) /* warning: 'rpt_head_next' may be used uninitialized in this function */
#endif
#define MATCH_BUFFER_SHIFT 8;
#define MATCH_BUFFER_ELBOW_BITS 17
#define MATCH_BUFFER_ELBOW (1UL << MATCH_BUFFER_ELBOW_BITS)
#define MIN_MATCH_BUFFER_SIZE 256U /* min buffer size at least FL2_SEARCH_DEPTH_MAX + 2 for bounded build */
#define MAX_MATCH_BUFFER_SIZE (1UL << 24) /* max buffer size constrained by 24-bit link values */
static void RMF_initTailTable(RMF_builder* const tbl)
{
for (size_t i = 0; i < RADIX8_TABLE_SIZE; i += 2) {
tbl->tails_8[i].prev_index = RADIX_NULL_LINK;
tbl->tails_8[i + 1].prev_index = RADIX_NULL_LINK;
}
for (size_t i = 0; i < RADIX16_TABLE_SIZE; i += 2) {
tbl->tails_16[i].prev_index = RADIX_NULL_LINK;
tbl->tails_16[i + 1].prev_index = RADIX_NULL_LINK;
}
}
static RMF_builder* RMF_createBuilder(size_t match_buffer_size)
{
match_buffer_size = MIN(match_buffer_size, MAX_MATCH_BUFFER_SIZE);
match_buffer_size = MAX(match_buffer_size, MIN_MATCH_BUFFER_SIZE);
RMF_builder* const builder = malloc(
sizeof(RMF_builder) + (match_buffer_size - 1) * sizeof(RMF_buildMatch));
if (builder == NULL)
return NULL;
builder->match_buffer_size = match_buffer_size;
builder->match_buffer_limit = match_buffer_size;
RMF_initTailTable(builder);
return builder;
}
static void RMF_freeBuilderTable(RMF_builder** const builders, unsigned const size)
{
if (builders == NULL)
return;
for (unsigned i = 0; i < size; ++i)
free(builders[i]);
free(builders);
}
/* RMF_createBuilderTable() :
* Create one match table builder object per thread.
* max_len : maximum match length supported by the table structure
* size : number of threads
*/
static RMF_builder** RMF_createBuilderTable(U32* const match_table, size_t const match_buffer_size, unsigned const max_len, unsigned const size)
{
DEBUGLOG(3, "RMF_createBuilderTable : match_buffer_size %u, builders %u", (U32)match_buffer_size, size);
RMF_builder** const builders = malloc(size * sizeof(RMF_builder*));
if (builders == NULL)
return NULL;
for (unsigned i = 0; i < size; ++i)
builders[i] = NULL;
for (unsigned i = 0; i < size; ++i) {
builders[i] = RMF_createBuilder(match_buffer_size);
if (builders[i] == NULL) {
RMF_freeBuilderTable(builders, i);
return NULL;
}
builders[i]->table = match_table;
builders[i]->max_len = max_len;
}
return builders;
}
static int RMF_isStruct(size_t const dictionary_size)
{
return dictionary_size > ((size_t)1 << RADIX_LINK_BITS);
}
/* RMF_clampParams() :
* Make param values within valid range.
* Return : valid RMF_parameters */
static RMF_parameters RMF_clampParams(RMF_parameters params)
{
# define CLAMP(val,min,max) { \
if (val<(min)) val=(min); \
else if (val>(max)) val=(max); \
}
# define MAXCLAMP(val,max) { \
if (val>(max)) val=(max); \
}
CLAMP(params.dictionary_size, DICTIONARY_SIZE_MIN, MEM_64bits() ? DICTIONARY_SIZE_MAX_64 : DICTIONARY_SIZE_MAX_32);
MAXCLAMP(params.match_buffer_resize, FL2_BUFFER_RESIZE_MAX);
MAXCLAMP(params.overlap_fraction, FL2_BLOCK_OVERLAP_MAX);
CLAMP(params.depth, FL2_SEARCH_DEPTH_MIN, FL2_SEARCH_DEPTH_MAX);
return params;
# undef MAXCLAMP
# undef CLAMP
}
static size_t RMF_calBufSize(size_t dictionary_size, unsigned buffer_resize)
{
size_t buffer_size = dictionary_size >> MATCH_BUFFER_SHIFT;
if (buffer_size > MATCH_BUFFER_ELBOW) {
size_t extra = 0;
unsigned n = MATCH_BUFFER_ELBOW_BITS - 1;
for (; (4UL << n) <= buffer_size; ++n)
extra += MATCH_BUFFER_ELBOW >> 4;
if((3UL << n) <= buffer_size)
extra += MATCH_BUFFER_ELBOW >> 5;
buffer_size = MATCH_BUFFER_ELBOW + extra;
}
if (buffer_resize > 2)
buffer_size += buffer_size >> (4 - buffer_resize);
else if (buffer_resize < 2)
buffer_size -= buffer_size >> (buffer_resize + 1);
return buffer_size;
}
/* RMF_applyParameters_internal() :
* Set parameters to those specified.
* Create a builder table if none exists. Free an existing one if incompatible.
* Set match_buffer_limit and max supported match length.
* Returns an error if dictionary won't fit.
*/
static size_t RMF_applyParameters_internal(FL2_matchTable* const tbl, const RMF_parameters* const params)
{
int const is_struct = RMF_isStruct(params->dictionary_size);
size_t const dictionary_size = tbl->params.dictionary_size;
/* dictionary is allocated with the struct and is immutable */
if (params->dictionary_size > tbl->params.dictionary_size
|| (params->dictionary_size == tbl->params.dictionary_size && is_struct > tbl->alloc_struct))
return FL2_ERROR(parameter_unsupported);
size_t const match_buffer_size = RMF_calBufSize(tbl->unreduced_dict_size, params->match_buffer_resize);
tbl->params = *params;
tbl->params.dictionary_size = dictionary_size;
tbl->is_struct = is_struct;
if (tbl->builders == NULL
|| match_buffer_size > tbl->builders[0]->match_buffer_size)
{
RMF_freeBuilderTable(tbl->builders, tbl->thread_count);
tbl->builders = RMF_createBuilderTable(tbl->table, match_buffer_size, tbl->is_struct ? STRUCTURED_MAX_LENGTH : BITPACK_MAX_LENGTH, tbl->thread_count);
if (tbl->builders == NULL) {
return FL2_ERROR(memory_allocation);
}
}
else {
for (unsigned i = 0; i < tbl->thread_count; ++i) {
tbl->builders[i]->match_buffer_limit = match_buffer_size;
tbl->builders[i]->max_len = tbl->is_struct ? STRUCTURED_MAX_LENGTH : BITPACK_MAX_LENGTH;
}
}
return 0;
}
/* RMF_reduceDict() :
* Reduce dictionary and match buffer size if the total input size is known and < dictionary_size.
*/
static void RMF_reduceDict(RMF_parameters* const params, size_t const dict_reduce)
{
if (dict_reduce)
params->dictionary_size = MIN(params->dictionary_size, MAX(dict_reduce, DICTIONARY_SIZE_MIN));
}
static void RMF_initListHeads(FL2_matchTable* const tbl)
{
for (size_t i = 0; i < RADIX16_TABLE_SIZE; i += 2) {
tbl->list_heads[i].head = RADIX_NULL_LINK;
tbl->list_heads[i].count = 0;
tbl->list_heads[i + 1].head = RADIX_NULL_LINK;
tbl->list_heads[i + 1].count = 0;
}
}
/* RMF_createMatchTable() :
* Create a match table. Reduce the dict size to input size if possible.
* A thread_count of 0 will be raised to 1.
*/
FL2_matchTable* RMF_createMatchTable(const RMF_parameters* const p, size_t const dict_reduce, unsigned const thread_count)
{
RMF_parameters params = RMF_clampParams(*p);
size_t unreduced_dict_size = params.dictionary_size;
RMF_reduceDict(¶ms, dict_reduce);
int const is_struct = RMF_isStruct(params.dictionary_size);
size_t dictionary_size = params.dictionary_size;
DEBUGLOG(3, "RMF_createMatchTable : is_struct %d, dict %u", is_struct, (U32)dictionary_size);
size_t const table_bytes = is_struct ? ((dictionary_size + 3U) / 4U) * sizeof(RMF_unit)
: dictionary_size * sizeof(U32);
FL2_matchTable* const tbl = malloc(sizeof(FL2_matchTable) + table_bytes - sizeof(U32));
if (tbl == NULL)
return NULL;
tbl->is_struct = is_struct;
tbl->alloc_struct = is_struct;
tbl->thread_count = thread_count + !thread_count;
tbl->params = params;
tbl->unreduced_dict_size = unreduced_dict_size;
tbl->builders = NULL;
RMF_applyParameters_internal(tbl, ¶ms);
RMF_initListHeads(tbl);
RMF_initProgress(tbl);
return tbl;
}
void RMF_freeMatchTable(FL2_matchTable* const tbl)
{
if (tbl == NULL)
return;
DEBUGLOG(3, "RMF_freeMatchTable");
RMF_freeBuilderTable(tbl->builders, tbl->thread_count);
free(tbl);
}
BYTE RMF_compatibleParameters(const FL2_matchTable* const tbl, const RMF_parameters * const p, size_t const dict_reduce)
{
RMF_parameters params = RMF_clampParams(*p);
RMF_reduceDict(¶ms, dict_reduce);
return tbl->params.dictionary_size > params.dictionary_size
|| (tbl->params.dictionary_size == params.dictionary_size && tbl->alloc_struct >= RMF_isStruct(params.dictionary_size));
}
size_t RMF_applyParameters(FL2_matchTable* const tbl, const RMF_parameters* const p, size_t const dict_reduce)
{
RMF_parameters params = RMF_clampParams(*p);
RMF_reduceDict(¶ms, dict_reduce);
return RMF_applyParameters_internal(tbl, ¶ms);
}
size_t RMF_threadCount(const FL2_matchTable* const tbl)
{
return tbl->thread_count;
}
void RMF_initProgress(FL2_matchTable * const tbl)
{
if (tbl != NULL)
tbl->progress = 0;
}
void RMF_initTable(FL2_matchTable* const tbl, const void* const data, size_t const end)
{
DEBUGLOG(5, "RMF_initTable : size %u", (U32)end);
tbl->st_index = ATOMIC_INITIAL_VALUE;
if (tbl->is_struct)
RMF_structuredInit(tbl, data, end);
else
RMF_bitpackInit(tbl, data, end);
}
static void RMF_handleRepeat(RMF_buildMatch* const match_buffer,
const BYTE* const data_block,
const BYTE* const data_block_end,
size_t const next,
U32 count,
U32 const rpt_len,
U32 const depth,
U32 const max_len)
{
size_t pos = next;
U32 length = depth + rpt_len;
const BYTE* const data = data_block + match_buffer[pos].from;
const BYTE* const data_2 = data - rpt_len;
U32 block_max_len = MIN(max_len, (U32)(data_block_end - data));
while (length < block_max_len && data[length] == data_2[length])
++length;
for (; length <= max_len && count; --count) {
size_t next_i = match_buffer[pos].next & 0xFFFFFF;
match_buffer[pos].next = (U32)next_i | (length << 24);
length += rpt_len;
pos = next_i;
}
for (; count; --count) {
size_t next_i = match_buffer[pos].next & 0xFFFFFF;
match_buffer[pos].next = (U32)next_i | (max_len << 24);
pos = next_i;
}
}
typedef struct
{
size_t pos;
const BYTE* data_src;
union src_data_u src;
} BruteForceMatch;
static void RMF_bruteForceBuffered(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t pos,
size_t const list_count,
size_t const slot,
size_t const depth,
size_t const max_depth)
{
BruteForceMatch buffer[MAX_BRUTE_FORCE_LIST_SIZE + 1];
const BYTE* const data_src = data_block + depth;
size_t const limit = max_depth - depth;
const BYTE* const start = data_src + block_start;
size_t i = 0;
for (;;) {
/* Load all locations from the match buffer */
buffer[i].pos = pos;
buffer[i].data_src = data_src + tbl->match_buffer[pos].from;
buffer[i].src.u32 = tbl->match_buffer[pos].src.u32;
if (++i >= list_count)
break;
pos = tbl->match_buffer[pos].next & 0xFFFFFF;
}
i = 0;
do {
size_t longest = 0;
size_t j = i + 1;
size_t longest_index = j;
const BYTE* const data = buffer[i].data_src;
do {
/* Begin with the remaining chars pulled from the match buffer */
size_t len_test = slot;
while (len_test < 4 && buffer[i].src.chars[len_test] == buffer[j].src.chars[len_test] && len_test - slot < limit)
++len_test;
len_test -= slot;
if (len_test) {
/* Complete the match length count in the raw input buffer */
const BYTE* data_2 = buffer[j].data_src;
while (data[len_test] == data_2[len_test] && len_test < limit)
++len_test;
}
if (len_test > longest) {
longest_index = j;
longest = len_test;
if (len_test >= limit)
break;
}
} while (++j < list_count);
if (longest > 0) {
/* If the existing match was extended, store the new link and length info in the match buffer */
pos = buffer[i].pos;
tbl->match_buffer[pos].next = (U32)(buffer[longest_index].pos | ((depth + longest) << 24));
}
++i;
} while (i < list_count - 1 && buffer[i].data_src >= start);
}
/* Lengthen and divide buffered chains into smaller chains, save them on a stack and process in turn.
* The match finder spends most of its time here.
*/
FORCE_INLINE_TEMPLATE
void RMF_recurseListChunk_generic(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t const block_end,
U32 depth,
U32 const max_depth,
U32 list_count,
size_t const stack_base)
{
U32 const base_depth = depth;
size_t st_index = stack_base;
size_t pos = 0;
++depth;
/* The last element is done separately and won't be copied back at the end */
--list_count;
do {
size_t const radix_8 = tbl->match_buffer[pos].src.chars[0];
/* Seen this char before? */
U32 const prev = tbl->tails_8[radix_8].prev_index;
tbl->tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_8[radix_8].list_count;
/* Link the previous occurrence to this one and record the new length */
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
tbl->tails_8[radix_8].list_count = 1;
/* Add the new sub list to the stack */
tbl->stack[st_index].head = (U32)pos;
/* This will be converted to a count at the end */
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
++pos;
} while (pos < list_count);
{ /* Do the last element */
size_t const radix_8 = tbl->match_buffer[pos].src.chars[0];
/* Nothing to do if there was no previous */
U32 const prev = tbl->tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
}
/* Convert radix values on the stack to counts and reset any used tail slots */
for (size_t j = stack_base; j < st_index; ++j) {
tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;
tbl->stack[j].count = (U32)tbl->tails_8[tbl->stack[j].count].list_count;
}
while (st_index > stack_base) {
/* Pop an item off the stack */
--st_index;
list_count = tbl->stack[st_index].count;
if (list_count < 2) {
/* Nothing to match with */
continue;
}
pos = tbl->stack[st_index].head;
size_t link = tbl->match_buffer[pos].from;
if (link < block_start) {
/* Chain starts in the overlap region which is already encoded */
continue;
}
/* Check stack space. The first comparison is unnecessary but it's a constant so should be faster */
if (st_index > STACK_SIZE - RADIX8_TABLE_SIZE
&& st_index > STACK_SIZE - list_count)
{
/* Stack may not be able to fit all possible new items. This is very rare. */
continue;
}
depth = tbl->match_buffer[pos].next >> 24;
/* Index into the 4-byte pre-loaded input char cache */
size_t slot = (depth - base_depth) & 3;
if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE) {
/* Quicker to use brute force, each string compared with all previous strings */
RMF_bruteForceBuffered(tbl,
data_block,
block_start,
pos,
list_count,
slot,
depth,
max_depth);
continue;
}
/* check for repeats at depth 4,8,16,32 etc unless depth is near max_depth */
U32 const test = max_depth != 6 && ((depth & 3) == 0)
&& (depth & (depth - 1)) == 0
&& (max_depth >= depth + (depth >> 1));
++depth;
/* Create an offset data buffer pointer for reading the next bytes */
const BYTE* const data_src = data_block + depth;
/* Last pass is done separately */
if (!test && depth < max_depth) {
size_t const prev_st_index = st_index;
/* Last element done separately */
--list_count;
/* If slot is 3 then chars need to be loaded. */
if (slot == 3 && max_depth != 6) do {
size_t const radix_8 = tbl->match_buffer[pos].src.chars[3];
size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
/* Pre-load the next link and data bytes. On some hardware execution can continue
* ahead while the data is retrieved if no operations except move are done on the data. */
tbl->match_buffer[pos].src.u32 = MEM_read32(data_src + link);
size_t const next_link = tbl->match_buffer[next_index].from;
U32 const prev = tbl->tails_8[radix_8].prev_index;
tbl->tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
/* This char has occurred before in the chain. Link the previous (> pos) occurance with this */
++tbl->tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
/* First occurrence in the chain */
tbl->tails_8[radix_8].list_count = 1;
tbl->stack[st_index].head = (U32)pos;
/* Save the char as a reference to load the count at the end */
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
pos = next_index;
link = next_link;
} while (--list_count != 0);
else do {
size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];
size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
/* Pre-load the next link to avoid waiting for RAM access */
size_t const next_link = tbl->match_buffer[next_index].from;
U32 const prev = tbl->tails_8[radix_8].prev_index;
tbl->tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
tbl->tails_8[radix_8].list_count = 1;
tbl->stack[st_index].head = (U32)pos;
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
pos = next_index;
link = next_link;
} while (--list_count != 0);
size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];
U32 const prev = tbl->tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
if (slot == 3)
tbl->match_buffer[pos].src.u32 = MEM_read32(data_src + link);
++tbl->tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
for (size_t j = prev_st_index; j < st_index; ++j) {
tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;
tbl->stack[j].count = (U32)tbl->tails_8[tbl->stack[j].count].list_count;
}
}
else if (test) {
S32 rpt = -1;
size_t rpt_head_next;
U32 rpt_dist = 0;
size_t const prev_st_index = st_index;
U32 const rpt_depth = depth - 1;
/* Last element done separately */
--list_count;
do {
size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];
size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
size_t const next_link = tbl->match_buffer[next_index].from;
if ((link - next_link) > rpt_depth) {
if (rpt > 0)
RMF_handleRepeat(tbl->match_buffer, data_block, data_block + block_end, rpt_head_next, rpt, rpt_dist, rpt_depth, tbl->max_len);
rpt = -1;
U32 const prev = tbl->tails_8[radix_8].prev_index;
tbl->tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
tbl->tails_8[radix_8].list_count = 1;
tbl->stack[st_index].head = (U32)pos;
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
pos = next_index;
link = next_link;
}
else {
U32 const dist = (U32)(link - next_link);
if (rpt < 0 || dist != rpt_dist) {
if (rpt > 0)
RMF_handleRepeat(tbl->match_buffer, data_block, data_block + block_end, rpt_head_next, rpt, rpt_dist, rpt_depth, tbl->max_len);
rpt = 0;
rpt_head_next = next_index;
rpt_dist = dist;
U32 const prev = tbl->tails_8[radix_8].prev_index;
tbl->tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
++tbl->tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
tbl->tails_8[radix_8].list_count = 1;
tbl->stack[st_index].head = (U32)pos;
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
}
else {
++rpt;
}
pos = next_index;
link = next_link;
}
} while (--list_count != 0);
if (rpt > 0)
RMF_handleRepeat(tbl->match_buffer, data_block, data_block + block_end, rpt_head_next, rpt, rpt_dist, rpt_depth, tbl->max_len);
size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];
U32 const prev = tbl->tails_8[radix_8].prev_index;
if (prev != RADIX_NULL_LINK) {
if (slot == 3) {
tbl->match_buffer[pos].src.u32 = MEM_read32(data_src + link);
}
++tbl->tails_8[radix_8].list_count;
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
for (size_t j = prev_st_index; j < st_index; ++j) {
tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;
tbl->stack[j].count = (U32)tbl->tails_8[tbl->stack[j].count].list_count;
}
}
else {
size_t const prev_st_index = st_index;
/* The last pass at max_depth */
do {
size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];
size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;
/* Pre-load the next link. */
/* The last element in tbl->match_buffer is circular so this is never an access violation. */
size_t const next_link = tbl->match_buffer[next_index].from;
U32 const prev = tbl->tails_8[radix_8].prev_index;
tbl->tails_8[radix_8].prev_index = (U32)pos;
if (prev != RADIX_NULL_LINK) {
tbl->match_buffer[prev].next = (U32)pos | (depth << 24);
}
else {
tbl->stack[st_index].count = (U32)radix_8;
++st_index;
}
pos = next_index;
link = next_link;
} while (--list_count != 0);
for (size_t j = prev_st_index; j < st_index; ++j) {
tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;
}
st_index = prev_st_index;
}
}
}
void RMF_recurseListChunk(RMF_builder* const tbl,
const BYTE* const data_block,
size_t const block_start,
size_t const block_end,
U32 const depth,
U32 const max_depth,
U32 const list_count,
size_t const stack_base)
{
if (list_count < 2)
return;
/* Template-like inline functions */
if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE)
RMF_bruteForceBuffered(tbl, data_block, block_start, 0, list_count, 0, depth, max_depth);
else if (max_depth > 6)
RMF_recurseListChunk_generic(tbl, data_block, block_start, block_end, depth, max_depth, list_count, stack_base);
else
RMF_recurseListChunk_generic(tbl, data_block, block_start, block_end, depth, 6, list_count, stack_base);
}
/* Iterate the head table concurrently with other threads, and recurse each list until max_depth is reached */
int RMF_buildTable(FL2_matchTable* const tbl,
size_t const job,
unsigned const multi_thread,
FL2_dataBlock const block)
{
DEBUGLOG(5, "RMF_buildTable : thread %u", (U32)job);
if (tbl->is_struct)
RMF_structuredBuildTable(tbl, job, multi_thread, block);
else
RMF_bitpackBuildTable(tbl, job, multi_thread, block);
if (job == 0 && tbl->st_index >= RADIX_CANCEL_INDEX) {
RMF_initListHeads(tbl);
return 1;
}
return 0;
}
void RMF_cancelBuild(FL2_matchTable * const tbl)
{
if(tbl != NULL)
FL2_atomic_add(tbl->st_index, RADIX_CANCEL_INDEX - ATOMIC_INITIAL_VALUE);
}
void RMF_resetIncompleteBuild(FL2_matchTable * const tbl)
{
RMF_initListHeads(tbl);
}
int RMF_integrityCheck(const FL2_matchTable* const tbl, const BYTE* const data, size_t const pos, size_t const end, unsigned const max_depth)
{
if (tbl->is_struct)
return RMF_structuredIntegrityCheck(tbl, data, pos, end, max_depth);
else
return RMF_bitpackIntegrityCheck(tbl, data, pos, end, max_depth);
}
void RMF_limitLengths(FL2_matchTable* const tbl, size_t const pos)
{
if (tbl->is_struct)
RMF_structuredLimitLengths(tbl, pos);
else
RMF_bitpackLimitLengths(tbl, pos);
}
BYTE* RMF_getTableAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos)
{
if (tbl->is_struct)
return RMF_structuredAsOutputBuffer(tbl, pos);
else
return RMF_bitpackAsOutputBuffer(tbl, pos);
}
size_t RMF_memoryUsage(size_t const dict_size, unsigned const buffer_resize, unsigned const thread_count)
{
size_t size = (size_t)(4U + RMF_isStruct(dict_size)) * dict_size;
size_t const buf_size = RMF_calBufSize(dict_size, buffer_resize);
size += ((buf_size - 1) * sizeof(RMF_buildMatch) + sizeof(RMF_builder)) * thread_count;
return size;
}
================================================
FILE: NanaZip.Codecs/FastLZMA2/radix_mf.h
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef RADIX_MF_H
#define RADIX_MF_H
#include "fast-lzma2.h"
#include "data_block.h"
#if defined (__cplusplus)
extern "C" {
#endif
typedef struct FL2_matchTable_s FL2_matchTable;
#define OVERLAP_FROM_DICT_SIZE(d, o) (((d) >> 4) * (o))
#define RMF_MIN_BYTES_PER_THREAD 1024
typedef struct
{
size_t dictionary_size;
unsigned match_buffer_resize;
unsigned overlap_fraction;
unsigned divide_and_conquer;
unsigned depth;
#ifdef RMF_REFERENCE
unsigned use_ref_mf;
#endif
} RMF_parameters;
FL2_matchTable* RMF_createMatchTable(const RMF_parameters* const params, size_t const dict_reduce, unsigned const thread_count);
void RMF_freeMatchTable(FL2_matchTable* const tbl);
BYTE RMF_compatibleParameters(const FL2_matchTable* const tbl, const RMF_parameters* const params, size_t const dict_reduce);
size_t RMF_applyParameters(FL2_matchTable* const tbl, const RMF_parameters* const params, size_t const dict_reduce);
size_t RMF_threadCount(const FL2_matchTable * const tbl);
void RMF_initProgress(FL2_matchTable * const tbl);
void RMF_initTable(FL2_matchTable* const tbl, const void* const data, size_t const end);
int RMF_buildTable(FL2_matchTable* const tbl,
size_t const job,
unsigned const multi_thread,
FL2_dataBlock const block);
void RMF_cancelBuild(FL2_matchTable* const tbl);
void RMF_resetIncompleteBuild(FL2_matchTable* const tbl);
int RMF_integrityCheck(const FL2_matchTable* const tbl, const BYTE* const data, size_t const pos, size_t const end, unsigned const max_depth);
void RMF_limitLengths(FL2_matchTable* const tbl, size_t const pos);
BYTE* RMF_getTableAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos);
size_t RMF_memoryUsage(size_t const dict_size, unsigned const buffer_resize, unsigned const thread_count);
#if defined (__cplusplus)
}
#endif
#endif /* RADIX_MF_H */
================================================
FILE: NanaZip.Codecs/FastLZMA2/radix_struct.c
================================================
/*
* Copyright (c) 2018, Conor McCarthy
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include "mem.h" /* U32, U64 */
#include "fl2_threading.h"
#include "fl2_internal.h"
#include "radix_internal.h"
#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define RMF_STRUCTURED
#define RADIX_MAX_LENGTH STRUCTURED_MAX_LENGTH
#define InitMatchLink(pos, link) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] = (U32)(link)
#define GetMatchLink(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK]
#define GetInitialMatchLink(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK]
#define GetMatchLength(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].lengths[(pos) & UNIT_MASK]
#define SetMatchLink(pos, link, length) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] = (U32)(link)
#define SetMatchLength(pos, link, length) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].lengths[(pos) & UNIT_MASK] = (BYTE)(length)
#define SetMatchLinkAndLength(pos, link, length) do { size_t i_ = (pos) >> UNIT_BITS, u_ = (pos) & UNIT_MASK; ((RMF_unit*)tbl->table)[i_].links[u_] = (U32)(link); ((RMF_unit*)tbl->table)[i_].lengths[u_] = (BYTE)(length); } while(0)
#define SetNull(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] = RADIX_NULL_LINK
#define IsNull(pos) (((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] == RADIX_NULL_LINK)
BYTE* RMF_structuredAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos)
{
return (BYTE*)((RMF_unit*)tbl->table + (pos >> UNIT_BITS) + ((pos & UNIT_MASK) != 0));
}
/* Restrict the match lengths so that they don't reach beyond pos */
void RMF_structuredLimitLengths(FL2_matchTable* const tbl, size_t const pos)
{
DEBUGLOG(5, "RMF_limitLengths : end %u, max length %u", (U32)pos, RADIX_MAX_LENGTH);
SetNull(pos - 1);
for (size_t length = 2; length < RADIX_MAX_LENGTH && length <= pos; ++length) {
size_t const i = (pos - length) >> UNIT_BITS;
size_t const u = (pos - length) & UNIT_MASK;
if (((RMF_unit*)tbl->table)[i].links[u] != RADIX_NULL_LINK) {
((RMF_unit*)tbl->table)[i].lengths[u] = MIN((BYTE)length, ((RMF_unit*)tbl->table)[i].lengths[u]);
}
}
}
#include "radix_engine.h"
================================================
FILE: NanaZip.Codecs/FastLZMA2/range_enc.c
================================================
/*
* Bitwise range encoder by Igor Pavlov
* Modified by Conor McCarthy
*
* Public domain
*/
#include "fl2_internal.h"
#include "mem.h"
#include "platform.h"
#include "range_enc.h"
/* The first and last elements of these tables are never used */
BYTE price_table[2][kPriceTableSize] = { {
0, 193, 182, 166, 154, 145, 137, 131,
125, 120, 115, 111, 107, 103, 100, 97,
94, 91, 89, 86, 84, 82, 80, 78,
76, 74, 72, 71, 69, 67, 66, 64,
63, 61, 60, 59, 57, 56, 55, 54,
53, 52, 50, 49, 48, 47, 46, 45,
44, 43, 42, 42, 41, 40, 39, 38,
37, 36, 36, 35, 34, 33, 33, 32,
31, 30, 30, 29, 28, 28, 27, 26,
26, 25, 25, 24, 23, 23, 22, 21,
21, 20, 20, 19, 19, 18, 18, 17,
17, 16, 16, 15, 15, 14, 14, 13,
13, 12, 12, 11, 11, 10, 10, 9,
9, 8, 8, 8, 7, 7, 6, 6,
5, 5, 5, 4, 4, 3, 3, 3,
2, 2, 2, 1, 1, 0, 0, 0
}, {
0, 0, 0, 1, 1, 2, 2, 2,
3, 3, 3, 4, 4, 5, 5, 5,
6, 6, 7, 7, 8, 8, 8, 9,
9, 10, 10, 11, 11, 12, 12, 13,
13, 13, 14, 14, 15, 15, 16, 17,
17, 18, 18, 19, 19, 20, 20, 21,
21, 22, 23, 23, 24, 24, 25, 26,
26, 27, 28, 28, 29, 30, 30, 31,
32, 33, 33, 34, 35, 36, 36, 37,
38, 39, 40, 41, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 53,
54, 55, 56, 57, 59, 60, 61, 63,
64, 66, 67, 69, 70, 72, 74, 76,
78, 80, 82, 84, 86, 89, 91, 94,
97, 100, 103, 107, 111, 115, 119, 125,
130, 137, 145, 154, 165, 181, 192, 0
} };
#if 0
#include
/* Generates price_table */
void RC_printPriceTable()
{
static const unsigned test_size = 0x4000;
const unsigned test_div = test_size >> 8;
BYTE buf[0x3062];
unsigned table0[kPriceTableSize];
unsigned table1[kPriceTableSize];
unsigned count[kPriceTableSize];
memset(table0, 0, sizeof(table0));
memset(table1, 0, sizeof(table1));
memset(count, 0, sizeof(count));
for (LZMA2_prob i = 31; i <= kBitModelTotal - 31; ++i) {
RC_encoder rc;
RC_reset(&rc);
RC_setOutputBuffer(&rc, buf);
for (unsigned j = 0; j < test_size; ++j) {
LZMA2_prob prob = i;
RC_encodeBit0(&rc, &prob);
}
RC_flush(&rc);
table0[i >> kNumMoveReducingBits] += (unsigned)rc.out_index - 5;
RC_reset(&rc);
RC_setOutputBuffer(&rc, buf);
for (unsigned j = 0; j < test_size; ++j) {
LZMA2_prob prob = i;
RC_encodeBit1(&rc, &prob);
}
RC_flush(&rc);
table1[i >> kNumMoveReducingBits] += (unsigned)rc.out_index - 5;
++count[i >> kNumMoveReducingBits];
}
for (int i = 0; i < kPriceTableSize; ++i) if (count[i]) {
table0[i] = (table0[i] / count[i]) / test_div;
table1[i] = (table1[i] / count[i]) / test_div;
}
fputs("const BYTE price_table[2][kPriceTableSize] = {\r\n", stdout);
for (int i = 0; i < kPriceTableSize;) {
for (int j = 0; j < 8; ++j, ++i)
printf("%4d,", table0[i]);
fputs("\r\n", stdout);
}
fputs("}, {\r\n", stdout);
for (int i = 0; i < kPriceTableSize;) {
for (int j = 0; j < 8; ++j, ++i)
printf("%4d,", table1[i]);
fputs("\r\n", stdout);
}
fputs("} };\r\n", stdout);
}
#endif
void RC_setOutputBuffer(RC_encoder* const rc, BYTE *const out_buffer)
{
rc->out_buffer = out_buffer;
rc->out_index = 0;
}
void RC_reset(RC_encoder* const rc)
{
rc->low = 0;
rc->range = (U32)-1;
rc->cache_size = 0;
rc->cache = 0;
}
#ifdef __64BIT__
// **************** NanaZip Modification Start ****************
//void FORCE_NOINLINE RC_shiftLow(RC_encoder* const rc)
void RC_shiftLow(RC_encoder* const rc)
// **************** NanaZip Modification End ****************
{
U64 low = rc->low;
rc->low = (U32)(low << 8);
/* VC15 compiles 'if (low < 0xFF000000 || low > 0xFFFFFFFF)' to this single-branch conditional */
if (low + 0xFFFFFFFF01000000 > 0xFFFFFF) {
BYTE high = (BYTE)(low >> 32);
rc->out_buffer[rc->out_index++] = rc->cache + high;
rc->cache = (BYTE)(low >> 24);
if (rc->cache_size != 0) {
high += 0xFF;
do {
rc->out_buffer[rc->out_index++] = high;
} while (--rc->cache_size != 0);
}
}
else {
rc->cache_size++;
}
}
#else
// **************** NanaZip Modification Start ****************
//void FORCE_NOINLINE RC_shiftLow(RC_encoder* const rc)
void RC_shiftLow(RC_encoder* const rc)
// **************** NanaZip Modification End ****************
{
U32 low = (U32)rc->low;
unsigned high = (unsigned)(rc->low >> 32);
rc->low = low << 8;
if (low < (U32)0xFF000000 || high != 0) {
rc->out_buffer[rc->out_index++] = rc->cache + (BYTE)high;
rc->cache = (BYTE)(low >> 24);
if (rc->cache_size != 0) {
high += 0xFF;
do {
rc->out_buffer[rc->out_index++] = (BYTE)high;
} while (--rc->cache_size != 0);
}
}
else {
rc->cache_size++;
}
}
#endif
void RC_encodeBitTree(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol)
{
assert(bit_count > 1);
--bit_count;
unsigned bit = symbol >> bit_count;
RC_encodeBit(rc, &probs[1], bit);
size_t tree_index = 1;
do {
--bit_count;
tree_index = (tree_index << 1) | bit;
bit = (symbol >> bit_count) & 1;
RC_encodeBit(rc, &probs[tree_index], bit);
} while (bit_count != 0);
}
void RC_encodeBitTreeReverse(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol)
{
assert(bit_count != 0);
unsigned bit = symbol & 1;
RC_encodeBit(rc, &probs[1], bit);
unsigned tree_index = 1;
while (--bit_count != 0) {
tree_index = (tree_index << 1) + bit;
symbol >>= 1;
bit = symbol & 1;
RC_encodeBit(rc, &probs[tree_index], bit);
}
}
// **************** NanaZip Modification Start ****************
//void FORCE_NOINLINE RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count)
void RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count)
// **************** NanaZip Modification End ****************
{
assert(bit_count > 0);
do {
rc->range >>= 1;
--bit_count;
rc->low += rc->range & -((int)(value >> bit_count) & 1);
if (rc->range < kTopValue) {
rc->range <<= 8;
RC_shiftLow(rc);
}
} while (bit_count != 0);
}
================================================
FILE: NanaZip.Codecs/FastLZMA2/range_enc.h
================================================
/*
* Bitwise range encoder by Igor Pavlov
* Modified by Conor McCarthy
*
* Public domain
*/
#ifndef RANGE_ENCODER_H
#define RANGE_ENCODER_H
#include "mem.h"
#include "compiler.h"
#if defined (__cplusplus)
extern "C" {
#endif
#ifdef LZMA_ENC_PROB32
typedef U32 LZMA2_prob;
#else
typedef U16 LZMA2_prob;
#endif
#define kNumTopBits 24U
#define kTopValue (1UL << kNumTopBits)
#define kNumBitModelTotalBits 11U
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5U
#define kProbInitValue (kBitModelTotal >> 1U)
#define kNumMoveReducingBits 4U
#define kNumBitPriceShiftBits 5U
#define kPriceTableSize (kBitModelTotal >> kNumMoveReducingBits)
extern BYTE price_table[2][kPriceTableSize];
#if 0
void RC_printPriceTable();
#endif
typedef struct
{
BYTE *out_buffer;
size_t out_index;
U64 cache_size;
U64 low;
U32 range;
BYTE cache;
} RC_encoder;
void RC_reset(RC_encoder* const rc);
void RC_setOutputBuffer(RC_encoder* const rc, BYTE *const out_buffer);
// **************** NanaZip Modification Start ****************
//void FORCE_NOINLINE RC_shiftLow(RC_encoder* const rc);
void RC_shiftLow(RC_encoder* const rc);
// **************** NanaZip Modification End ****************
void RC_encodeBitTree(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol);
void RC_encodeBitTreeReverse(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol);
// **************** NanaZip Modification Start ****************
//void FORCE_NOINLINE RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count);
void RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count);
// **************** NanaZip Modification End ****************
HINT_INLINE
void RC_encodeBit0(RC_encoder* const rc, LZMA2_prob *const rprob)
{
unsigned prob = *rprob;
rc->range = (rc->range >> kNumBitModelTotalBits) * prob;
prob += (kBitModelTotal - prob) >> kNumMoveBits;
*rprob = (LZMA2_prob)prob;
if (rc->range < kTopValue) {
rc->range <<= 8;
RC_shiftLow(rc);
}
}
HINT_INLINE
void RC_encodeBit1(RC_encoder* const rc, LZMA2_prob *const rprob)
{
unsigned prob = *rprob;
U32 new_bound = (rc->range >> kNumBitModelTotalBits) * prob;
rc->low += new_bound;
rc->range -= new_bound;
prob -= prob >> kNumMoveBits;
*rprob = (LZMA2_prob)prob;
if (rc->range < kTopValue) {
rc->range <<= 8;
RC_shiftLow(rc);
}
}
HINT_INLINE
void RC_encodeBit(RC_encoder* const rc, LZMA2_prob *const rprob, unsigned const bit)
{
unsigned prob = *rprob;
if (bit != 0) {
U32 const new_bound = (rc->range >> kNumBitModelTotalBits) * prob;
rc->low += new_bound;
rc->range -= new_bound;
prob -= prob >> kNumMoveBits;
}
else {
rc->range = (rc->range >> kNumBitModelTotalBits) * prob;
prob += (kBitModelTotal - prob) >> kNumMoveBits;
}
*rprob = (LZMA2_prob)prob;
if (rc->range < kTopValue) {
rc->range <<= 8;
RC_shiftLow(rc);
}
}
#define GET_PRICE(prob, symbol) \
price_table[symbol][(prob) >> kNumMoveReducingBits]
#define GET_PRICE_0(prob) price_table[0][(prob) >> kNumMoveReducingBits]
#define GET_PRICE_1(prob) price_table[1][(prob) >> kNumMoveReducingBits]
#define kMinLitPrice 8U
HINT_INLINE
unsigned RC_getTreePrice(const LZMA2_prob* const prob_table, unsigned bit_count, size_t symbol)
{
unsigned price = 0;
symbol |= ((size_t)1 << bit_count);
do {
size_t const next_symbol = symbol >> 1;
unsigned prob = prob_table[next_symbol];
size_t bit = symbol & 1;
price += GET_PRICE(prob, bit);
symbol = next_symbol;
} while (symbol != 1);
return price;
}
HINT_INLINE
unsigned RC_getReverseTreePrice(const LZMA2_prob* const prob_table, unsigned bit_count, size_t symbol)
{
unsigned prob = prob_table[1];
size_t bit = symbol & 1;
unsigned price = GET_PRICE(prob, bit);
size_t m = 1;
while (--bit_count != 0) {
m = (m << 1) | bit;
symbol >>= 1;
prob = prob_table[m];
bit = symbol & 1;
price += GET_PRICE(prob, bit);
}
return price;
}
HINT_INLINE
void RC_flush(RC_encoder* const rc)
{
for (int i = 0; i < 5; ++i)
RC_shiftLow(rc);
}
#if defined (__cplusplus)
}
#endif
#endif /* RANGE_ENCODER_H */
================================================
FILE: NanaZip.Codecs/FastLZMA2/util.c
================================================
/*
* Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#if defined (__cplusplus)
extern "C" {
#endif
/*-****************************************
* Dependencies
******************************************/
#include "util.h" /* note : ensure that platform.h is included first ! */
#include
#include
int UTIL_fileExist(const char* filename)
{
stat_t statbuf;
#if defined(_MSC_VER)
int const stat_error = _stat64(filename, &statbuf);
#else
int const stat_error = stat(filename, &statbuf);
#endif
return !stat_error;
}
int UTIL_isRegularFile(const char* infilename)
{
stat_t statbuf;
return UTIL_getFileStat(infilename, &statbuf); /* Only need to know whether it is a regular file */
}
int UTIL_getFileStat(const char* infilename, stat_t *statbuf)
{
int r;
#if defined(_MSC_VER)
r = _stat64(infilename, statbuf);
if (r || !(statbuf->st_mode & S_IFREG)) return 0; /* No good... */
#else
r = stat(infilename, statbuf);
if (r || !S_ISREG(statbuf->st_mode)) return 0; /* No good... */
#endif
return 1;
}
int UTIL_setFileStat(const char *filename, stat_t *statbuf)
{
int res = 0;
struct utimbuf timebuf;
if (!UTIL_isRegularFile(filename))
return -1;
timebuf.actime = time(NULL);
timebuf.modtime = statbuf->st_mtime;
res += utime(filename, &timebuf); /* set access and modification times */
#if !defined(_WIN32)
res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */
#endif
res += chmod(filename, statbuf->st_mode & 07777); /* Copy file permissions */
errno = 0;
return -res; /* number of errors is returned */
}
U32 UTIL_isDirectory(const char* infilename)
{
int r;
stat_t statbuf;
#if defined(_MSC_VER)
r = _stat64(infilename, &statbuf);
if (!r && (statbuf.st_mode & _S_IFDIR)) return 1;
#else
r = stat(infilename, &statbuf);
if (!r && S_ISDIR(statbuf.st_mode)) return 1;
#endif
return 0;
}
U32 UTIL_isLink(const char* infilename)
{
/* macro guards, as defined in : https://linux.die.net/man/2/lstat */
#ifndef __STRICT_ANSI__
#if defined(_BSD_SOURCE) \
|| (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|| (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) \
|| (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \
|| (defined(__APPLE__) && defined(__MACH__)) \
|| defined(__OpenBSD__) \
|| defined(__FreeBSD__)
int r;
stat_t statbuf;
r = lstat(infilename, &statbuf);
if (!r && S_ISLNK(statbuf.st_mode)) return 1;
#endif
#endif
(void)infilename;
return 0;
}
U64 UTIL_getFileSize(const char* infilename)
{
if (!UTIL_isRegularFile(infilename)) return UTIL_FILESIZE_UNKNOWN;
{ int r;
#if defined(_MSC_VER)
struct __stat64 statbuf;
r = _stat64(infilename, &statbuf);
if (r || !(statbuf.st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;
#elif defined(__MINGW32__) && defined (__MSVCRT__)
struct _stati64 statbuf;
r = _stati64(infilename, &statbuf);
if (r || !(statbuf.st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;
#else
struct stat statbuf;
r = stat(infilename, &statbuf);
if (r || !S_ISREG(statbuf.st_mode)) return UTIL_FILESIZE_UNKNOWN;
#endif
return (U64)statbuf.st_size;
}
}
U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles)
{
U64 total = 0;
int error = 0;
unsigned n;
for (n=0; n= *bufEnd) {
ptrdiff_t const newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
*bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }
*bufEnd = *bufStart + newListSize;
}
if (*bufStart + *pos + pathLength < *bufEnd) {
memcpy(*bufStart + *pos, path, pathLength+1 /* include final \0 */);
*pos += pathLength + 1;
nbFiles++;
}
}
free(path);
} while (FindNextFileA(hFile, &cFile));
FindClose(hFile);
return nbFiles;
}
#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */
int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
{
DIR *dir;
struct dirent *entry;
char* path;
int dirLength, fnameLength, pathLength, nbFiles = 0;
if (!(dir = opendir(dirName))) {
UTIL_DISPLAYLEVEL(1, "Cannot open directory '%s': %s\n", dirName, strerror(errno));
return 0;
}
dirLength = (int)strlen(dirName);
errno = 0;
while ((entry = readdir(dir)) != NULL) {
if (strcmp (entry->d_name, "..") == 0 ||
strcmp (entry->d_name, ".") == 0) continue;
fnameLength = (int)strlen(entry->d_name);
path = (char*) malloc(dirLength + fnameLength + 2);
if (!path) { closedir(dir); return 0; }
memcpy(path, dirName, dirLength);
path[dirLength] = '/';
memcpy(path+dirLength+1, entry->d_name, fnameLength);
pathLength = dirLength+1+fnameLength;
path[pathLength] = 0;
if (!followLinks && UTIL_isLink(path)) {
UTIL_DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring\n", path);
continue;
}
if (UTIL_isDirectory(path)) {
nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks); /* Recursively call "UTIL_prepareFileList" with the new path. */
if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
} else {
if (*bufStart + *pos + pathLength >= *bufEnd) {
ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
*bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
*bufEnd = *bufStart + newListSize;
if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
}
if (*bufStart + *pos + pathLength < *bufEnd) {
memcpy(*bufStart + *pos, path, pathLength + 1); /* with final \0 */
*pos += pathLength + 1;
nbFiles++;
}
}
free(path);
errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */
}
if (errno != 0) {
UTIL_DISPLAYLEVEL(1, "readdir(%s) error: %s\n", dirName, strerror(errno));
free(*bufStart);
*bufStart = NULL;
}
closedir(dir);
return nbFiles;
}
#else
int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
{
(void)bufStart; (void)bufEnd; (void)pos; (void)followLinks;
UTIL_DISPLAYLEVEL(1, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName);
return 0;
}
#endif /* #ifdef _WIN32 */
/*
* UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
* and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
* After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
* In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
*/
const char**
UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
char** allocatedBuffer, unsigned* allocatedNamesNb,
int followLinks)
{
size_t pos;
unsigned i, nbFiles;
char* buf = (char*)malloc(LIST_SIZE_INCREASE);
char* bufend = buf + LIST_SIZE_INCREASE;
const char** fileTable;
if (!buf) return NULL;
for (i=0, pos=0, nbFiles=0; i= bufend) {
ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE;
buf = (char*)UTIL_realloc(buf, newListSize);
bufend = buf + newListSize;
if (!buf) return NULL;
}
if (buf + pos + len < bufend) {
memcpy(buf+pos, inputNames[i], len+1); /* with final \0 */
pos += len + 1;
nbFiles++;
}
} else {
nbFiles += UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend, followLinks);
if (buf == NULL) return NULL;
} }
if (nbFiles == 0) { free(buf); return NULL; }
fileTable = (const char**)malloc((nbFiles+1) * sizeof(const char*));
if (!fileTable) { free(buf); return NULL; }
for (i=0, pos=0; i bufend) { free(buf); free((void*)fileTable); return NULL; }
*allocatedBuffer = buf;
*allocatedNamesNb = nbFiles;
return fileTable;
}
/*-****************************************
* Console log
******************************************/
int g_utilDisplayLevel;
/*-****************************************
* Time functions
******************************************/
#if defined(_WIN32) /* Windows */
UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static LARGE_INTEGER ticksPerSecond;
static int init = 0;
if (!init) {
if (!QueryPerformanceFrequency(&ticksPerSecond))
UTIL_DISPLAYLEVEL(1, "ERROR: QueryPerformanceFrequency() failure\n");
init = 1;
}
return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
}
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static LARGE_INTEGER ticksPerSecond;
static int init = 0;
if (!init) {
if (!QueryPerformanceFrequency(&ticksPerSecond))
UTIL_DISPLAYLEVEL(1, "ERROR: QueryPerformanceFrequency() failure\n");
init = 1;
}
return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;
}
#elif defined(__APPLE__) && defined(__MACH__)
UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static mach_timebase_info_data_t rate;
static int init = 0;
if (!init) {
mach_timebase_info(&rate);
init = 1;
}
return (((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom))/1000ULL;
}
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)
{
static mach_timebase_info_data_t rate;
static int init = 0;
if (!init) {
mach_timebase_info(&rate);
init = 1;
}
return ((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom);
}
#elif (PLATFORM_POSIX_VERSION >= 200112L) \
&& (defined(__UCLIBC__) \
|| (defined(__GLIBC__) \
&& ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \
|| (__GLIBC__ > 2))))
UTIL_time_t UTIL_getTime(void)
{
UTIL_time_t time;
if (clock_gettime(CLOCK_MONOTONIC, &time))
UTIL_DISPLAYLEVEL(1, "ERROR: Failed to get time\n"); /* we could also exit() */
return time;
}
UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t diff;
if (end.tv_nsec < begin.tv_nsec) {
diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;
diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;
} else {
diff.tv_sec = end.tv_sec - begin.tv_sec;
diff.tv_nsec = end.tv_nsec - begin.tv_nsec;
}
return diff;
}
U64 UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
U64 micro = 0;
micro += 1000000ULL * diff.tv_sec;
micro += diff.tv_nsec / 1000ULL;
return micro;
}
U64 UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)
{
UTIL_time_t const diff = UTIL_getSpanTime(begin, end);
U64 nano = 0;
nano += 1000000000ULL * diff.tv_sec;
nano += diff.tv_nsec;
return nano;
}
#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
UTIL_time_t UTIL_getTime(void) { return clock(); }
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }
#endif
/* returns time span in microseconds */
U64 UTIL_clockSpanMicro(UTIL_time_t clockStart )
{
UTIL_time_t const clockEnd = UTIL_getTime();
return UTIL_getSpanTimeMicro(clockStart, clockEnd);
}
/* returns time span in microseconds */
U64 UTIL_clockSpanNano(UTIL_time_t clockStart )
{
UTIL_time_t const clockEnd = UTIL_getTime();
return UTIL_getSpanTimeNano(clockStart, clockEnd);
}
void UTIL_waitForNextTick(void)
{
UTIL_time_t const clockStart = UTIL_getTime();
UTIL_time_t clockEnd;
do {
clockEnd = UTIL_getTime();
} while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);
}
/* count the number of physical cores */
#if defined(_WIN32) || defined(WIN32)
#include
typedef BOOL(WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
int UTIL_countPhysicalCores(void)
{
static int numPhysicalCores = 0;
if (numPhysicalCores != 0) return numPhysicalCores;
{ LPFN_GLPI glpi;
BOOL done = FALSE;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
DWORD returnLength = 0;
size_t byteOffset = 0;
glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")),
"GetLogicalProcessorInformation");
if (glpi == NULL) {
goto failed;
}
while(!done) {
DWORD rc = glpi(buffer, &returnLength);
if (FALSE == rc) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (buffer)
free(buffer);
buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);
if (buffer == NULL) {
perror("zstd");
exit(1);
}
} else {
/* some other error */
goto failed;
}
} else {
done = TRUE;
}
}
ptr = buffer;
while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) {
if (ptr->Relationship == RelationProcessorCore) {
numPhysicalCores++;
}
ptr++;
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
}
free(buffer);
return numPhysicalCores;
}
failed:
/* try to fall back on GetSystemInfo */
{ SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
numPhysicalCores = sysinfo.dwNumberOfProcessors;
if (numPhysicalCores == 0) numPhysicalCores = 1; /* just in case */
}
return numPhysicalCores;
}
#elif defined(__APPLE__)
#include
/* Use apple-provided syscall
* see: man 3 sysctl */
int UTIL_countPhysicalCores(void)
{
static S32 numPhysicalCores = 0; /* apple specifies int32_t */
if (numPhysicalCores != 0) return numPhysicalCores;
{ size_t size = sizeof(S32);
int const ret = sysctlbyname("hw.physicalcpu", &numPhysicalCores, &size, NULL, 0);
if (ret != 0) {
if (errno == ENOENT) {
/* entry not present, fall back on 1 */
numPhysicalCores = 1;
} else {
perror("zstd: can't get number of physical cpus");
exit(1);
}
}
return numPhysicalCores;
}
}
#elif defined(__linux__)
/* parse /proc/cpuinfo
* siblings / cpu cores should give hyperthreading ratio
* otherwise fall back on sysconf */
int UTIL_countPhysicalCores(void)
{
static int numPhysicalCores = 0;
if (numPhysicalCores != 0) return numPhysicalCores;
numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (numPhysicalCores == -1) {
/* value not queryable, fall back on 1 */
return numPhysicalCores = 1;
}
/* try to determine if there's hyperthreading */
{ FILE* const cpuinfo = fopen("/proc/cpuinfo", "r");
#define BUF_SIZE 80
char buff[BUF_SIZE];
int siblings = 0;
int cpu_cores = 0;
int ratio = 1;
if (cpuinfo == NULL) {
/* fall back on the sysconf value */
return numPhysicalCores;
}
/* assume the cpu cores/siblings values will be constant across all
* present processors */
while (!feof(cpuinfo)) {
if (fgets(buff, BUF_SIZE, cpuinfo) != NULL) {
if (strncmp(buff, "siblings", 8) == 0) {
const char* const sep = strchr(buff, ':');
if (*sep == '\0') {
/* formatting was broken? */
goto failed;
}
siblings = atoi(sep + 1);
}
if (strncmp(buff, "cpu cores", 9) == 0) {
const char* const sep = strchr(buff, ':');
if (*sep == '\0') {
/* formatting was broken? */
goto failed;
}
cpu_cores = atoi(sep + 1);
}
} else if (ferror(cpuinfo)) {
/* fall back on the sysconf value */
goto failed;
}
}
if (siblings && cpu_cores) {
ratio = siblings / cpu_cores;
}
failed:
fclose(cpuinfo);
return numPhysicalCores = numPhysicalCores / ratio;
}
}
#elif defined(__FreeBSD__)
#include
#include
/* Use physical core sysctl when available
* see: man 4 smp, man 3 sysctl */
int UTIL_countPhysicalCores(void)
{
static int numPhysicalCores = 0; /* freebsd sysctl is native int sized */
if (numPhysicalCores != 0) return numPhysicalCores;
#if __FreeBSD_version >= 1300008
{ size_t size = sizeof(numPhysicalCores);
int ret = sysctlbyname("kern.smp.cores", &numPhysicalCores, &size, NULL, 0);
if (ret == 0) return numPhysicalCores;
if (errno != ENOENT) {
perror("zstd: can't get number of physical cpus");
exit(1);
}
/* sysctl not present, fall through to older sysconf method */
}
#endif
numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (numPhysicalCores == -1) {
/* value not queryable, fall back on 1 */
numPhysicalCores = 1;
}
return numPhysicalCores;
}
#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
/* Use POSIX sysconf
* see: man 3 sysconf */
int UTIL_countPhysicalCores(void)
{
static int numPhysicalCores = 0;
if (numPhysicalCores != 0) return numPhysicalCores;
numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (numPhysicalCores == -1) {
/* value not queryable, fall back on 1 */
return numPhysicalCores = 1;
}
return numPhysicalCores;
}
#else
int UTIL_countPhysicalCores(void)
{
/* assume 1 */
return 1;
}
#endif
#if defined (__cplusplus)
}
#endif
================================================
FILE: NanaZip.Codecs/FastLZMA2/util.h
================================================
/*
* Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#ifndef UTIL_H_MODULE
#define UTIL_H_MODULE
#if defined (__cplusplus)
extern "C" {
#endif
/*-****************************************
* Dependencies
******************************************/
#include "platform.h" /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */
#include /* malloc, realloc, free */
#include /* size_t, ptrdiff_t */
#include /* fprintf */
#include /* stat, utime */
#include /* stat, chmod */
#if defined(_MSC_VER)
# include /* utime */
# include /* _chmod */
#else
# include /* chown, stat */
# include /* utime */
#endif
#include /* clock_t, clock, CLOCKS_PER_SEC, nanosleep */
#include "mem.h" /* U32, U64 */
/*-************************************************************
* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW
***************************************************************/
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
# define UTIL_fseek _fseeki64
#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */
# define UTIL_fseek fseeko
#elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS)
# define UTIL_fseek fseeko64
#else
# define UTIL_fseek fseek
#endif
/*-*************************************************
* Sleep & priority functions: Windows - Posix - others
***************************************************/
#if defined(_WIN32)
# include
# define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)
# define UTIL_sleep(s) Sleep(1000*s)
# define UTIL_sleepMilli(milli) Sleep(milli)
#elif PLATFORM_POSIX_VERSION > 0 /* Unix-like operating system */
# include /* sleep */
# define UTIL_sleep(s) sleep(s)
# if ZSTD_NANOSLEEP_SUPPORT /* necessarily defined in platform.h */
# define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }
# else
# define UTIL_sleepMilli(milli) /* disabled */
# endif
# if ZSTD_SETPRIORITY_SUPPORT
# include /* setpriority */
# define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20)
# else
# define SET_REALTIME_PRIORITY /* disabled */
# endif
#else /* unknown non-unix operating systen */
# define UTIL_sleep(s) /* disabled */
# define UTIL_sleepMilli(milli) /* disabled */
# define SET_REALTIME_PRIORITY /* disabled */
#endif
/*-*************************************
* Constants
***************************************/
#define LIST_SIZE_INCREASE (8*1024)
/*-****************************************
* Compiler specifics
******************************************/
#if defined(__INTEL_COMPILER)
# pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */
#endif
#if defined(__GNUC__)
# define UTIL_STATIC static __attribute__((unused))
#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# define UTIL_STATIC static inline
#elif defined(_MSC_VER)
# define UTIL_STATIC static __inline
#else
# define UTIL_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
#endif
/*-****************************************
* Console log
******************************************/
extern int g_utilDisplayLevel;
#define UTIL_DISPLAY(...) fprintf(stderr, __VA_ARGS__)
#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } }
/*-****************************************
* Time functions
******************************************/
#if defined(_WIN32) /* Windows */
#define UTIL_TIME_INITIALIZER { { 0, 0 } }
typedef LARGE_INTEGER UTIL_time_t;
#elif defined(__APPLE__) && defined(__MACH__)
#include
#define UTIL_TIME_INITIALIZER 0
typedef U64 UTIL_time_t;
#elif (PLATFORM_POSIX_VERSION >= 200112L) \
&& (defined(__UCLIBC__) \
|| (defined(__GLIBC__) \
&& ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \
|| (__GLIBC__ > 2))))
#define UTIL_TIME_INITIALIZER { 0, 0 }
typedef struct timespec UTIL_freq_t;
typedef struct timespec UTIL_time_t;
UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end);
#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */
typedef clock_t UTIL_time_t;
#define UTIL_TIME_INITIALIZER 0
#endif
UTIL_time_t UTIL_getTime(void);
U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd);
U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd);
#define SEC_TO_MICRO 1000000
/* returns time span in microseconds */
U64 UTIL_clockSpanMicro(UTIL_time_t clockStart);
/* returns time span in microseconds */
U64 UTIL_clockSpanNano(UTIL_time_t clockStart);
void UTIL_waitForNextTick(void);
/*-****************************************
* File functions
******************************************/
#if defined(_MSC_VER)
#define chmod _chmod
typedef struct __stat64 stat_t;
#else
typedef struct stat stat_t;
#endif
int UTIL_fileExist(const char* filename);
int UTIL_isRegularFile(const char* infilename);
int UTIL_setFileStat(const char* filename, stat_t* statbuf);
U32 UTIL_isDirectory(const char* infilename);
int UTIL_getFileStat(const char* infilename, stat_t* statbuf);
U32 UTIL_isLink(const char* infilename);
#define UTIL_FILESIZE_UNKNOWN ((U64)(-1))
U64 UTIL_getFileSize(const char* infilename);
U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles);
/*
* A modified version of realloc().
* If UTIL_realloc() fails the original block is freed.
*/
UTIL_STATIC void* UTIL_realloc(void *ptr, size_t size)
{
void *newptr = realloc(ptr, size);
if (newptr) return newptr;
free(ptr);
return NULL;
}
int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks);
#ifdef _WIN32
# define UTIL_HAS_CREATEFILELIST
#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */
# define UTIL_HAS_CREATEFILELIST
# include /* opendir, readdir */
# include /* strerror, memcpy */
#else
#endif /* #ifdef _WIN32 */
/*
* UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
* and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
* After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
* In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
*/
const char**
UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
char** allocatedBuffer, unsigned* allocatedNamesNb,
int followLinks);
UTIL_STATIC void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer)
{
if (allocatedBuffer) free(allocatedBuffer);
if (filenameTable) free((void*)filenameTable);
}
int UTIL_countPhysicalCores(void);
#if defined (__cplusplus)
}
#endif
#endif /* UTIL_H_MODULE */
================================================
FILE: NanaZip.Codecs/FreeBSD/dinode.h
================================================
/*-
* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause)
*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by Marshall
* Kirk McKusick and Network Associates Laboratories, the Security
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
* research program
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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 AUTHOR 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 AUTHOR 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.
*
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. The names of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* @(#)dinode.h 8.3 (Berkeley) 1/21/94
*/
#ifndef _UFS_UFS_DINODE_H_
#define _UFS_UFS_DINODE_H_
#include
#include
/*
* The root inode is the root of the filesystem. Inode 0 can't be used for
* normal purposes and historically bad blocks were linked to inode 1, thus
* the root inode is 2. (Inode 1 is no longer used for this purpose, however
* numerous dump tapes make this assumption, so we are stuck with it).
*/
#define UFS_ROOTINO ((ino_t)2)
/*
* The Whiteout inode# is a dummy non-zero inode number which will
* never be allocated to a real file. It is used as a place holder
* in the directory entry which has been tagged as a DT_WHT entry.
* See the comments about UFS_ROOTINO above.
*/
#define UFS_WINO ((ino_t)1)
/*
* The size of physical and logical block numbers and time fields in UFS.
*/
typedef int32_t ufs1_daddr_t;
typedef int64_t ufs2_daddr_t;
typedef int64_t ufs_lbn_t;
typedef int64_t ufs_time_t;
/* File permissions. */
#define IEXEC 0000100 /* Executable. */
#define IWRITE 0000200 /* Writeable. */
#define IREAD 0000400 /* Readable. */
#define ISVTX 0001000 /* Sticky bit. */
#define ISGID 0002000 /* Set-gid. */
#define ISUID 0004000 /* Set-uid. */
/* File types. */
#define IFMT 0170000 /* Mask of file type. */
#define IFIFO 0010000 /* Named pipe (fifo). */
#define IFCHR 0020000 /* Character device. */
#define IFDIR 0040000 /* Directory file. */
#define IFBLK 0060000 /* Block device. */
#define IFREG 0100000 /* Regular file. */
#define IFLNK 0120000 /* Symbolic link. */
#define IFSOCK 0140000 /* UNIX domain socket. */
#define IFWHT 0160000 /* Whiteout. */
/*
* A dinode contains all the meta-data associated with a UFS2 file.
* This structure defines the on-disk format of a dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
*/
#define UFS_NXADDR 2 /* External addresses in inode. */
#define UFS_NDADDR 12 /* Direct addresses in inode. */
#define UFS_NIADDR 3 /* Indirect addresses in inode. */
struct ufs2_dinode {
uint16_t di_mode; /* 0: IFMT, permissions; see below. */
uint16_t di_nlink; /* 2: File link count. */
uint32_t di_uid; /* 4: File owner. */
uint32_t di_gid; /* 8: File group. */
uint32_t di_blksize; /* 12: Inode blocksize. */
uint64_t di_size; /* 16: File byte count. */
uint64_t di_blocks; /* 24: Blocks actually held. */
ufs_time_t di_atime; /* 32: Last access time. */
ufs_time_t di_mtime; /* 40: Last modified time. */
ufs_time_t di_ctime; /* 48: Last inode change time. */
ufs_time_t di_birthtime; /* 56: Inode creation time. */
int32_t di_mtimensec; /* 64: Last modified time. */
int32_t di_atimensec; /* 68: Last access time. */
int32_t di_ctimensec; /* 72: Last inode change time. */
int32_t di_birthnsec; /* 76: Inode creation time. */
uint32_t di_gen; /* 80: Generation number. */
uint32_t di_kernflags; /* 84: Kernel flags. */
uint32_t di_flags; /* 88: Status flags (chflags). */
uint32_t di_extsize; /* 92: External attributes size. */
ufs2_daddr_t di_extb[UFS_NXADDR];/* 96: External attributes block. */
union {
struct {
ufs2_daddr_t di_db /* 112: Direct disk blocks. */
[UFS_NDADDR];
ufs2_daddr_t di_ib /* 208: Indirect disk blocks. */
[UFS_NIADDR];
};
char di_shortlink /* 112: Embedded symbolic link. */
[(UFS_NDADDR + UFS_NIADDR) * sizeof(ufs2_daddr_t)];
};
uint64_t di_modrev; /* 232: i_modrev for NFSv4 */
union {
uint32_t di_freelink; /* 240: SUJ: Next unlinked inode. */
uint32_t di_dirdepth; /* 240: IFDIR: depth from root dir */
};
uint32_t di_ckhash; /* 244: if CK_INODE, its check-hash */
uint32_t di_spare[2]; /* 248: Reserved; currently unused */
};
/*
* The di_db fields may be overlaid with other information for
* file types that do not have associated disk storage. Block
* and character devices overlay the first data block with their
* dev_t value. Short symbolic links place their path in the
* di_db area.
*/
#define di_rdev di_db[0]
/*
* A UFS1 dinode contains all the meta-data associated with a UFS1 file.
* This structure defines the on-disk format of a UFS1 dinode. Since
* this structure describes an on-disk structure, all its fields
* are defined by types with precise widths.
*/
struct ufs1_dinode {
uint16_t di_mode; /* 0: IFMT, permissions; see below. */
uint16_t di_nlink; /* 2: File link count. */
union {
uint32_t di_freelink; /* 4: SUJ: Next unlinked inode. */
uint32_t di_dirdepth; /* 4: IFDIR: depth from root dir */
};
uint64_t di_size; /* 8: File byte count. */
int32_t di_atime; /* 16: Last access time. */
int32_t di_atimensec; /* 20: Last access time. */
int32_t di_mtime; /* 24: Last modified time. */
int32_t di_mtimensec; /* 28: Last modified time. */
int32_t di_ctime; /* 32: Last inode change time. */
int32_t di_ctimensec; /* 36: Last inode change time. */
union {
struct {
ufs1_daddr_t di_db /* 40: Direct disk blocks. */
[UFS_NDADDR];
ufs1_daddr_t di_ib /* 88: Indirect disk blocks. */
[UFS_NIADDR];
};
char di_shortlink /* 40: Embedded symbolic link. */
[(UFS_NDADDR + UFS_NIADDR) * sizeof(ufs1_daddr_t)];
};
uint32_t di_flags; /* 100: Status flags (chflags). */
uint32_t di_blocks; /* 104: Blocks actually held. */
uint32_t di_gen; /* 108: Generation number. */
uint32_t di_uid; /* 112: File owner. */
uint32_t di_gid; /* 116: File group. */
uint64_t di_modrev; /* 120: i_modrev for NFSv4 */
};
#define UFS_LINK_MAX 65500 /* leave a few spare for special values */
#endif /* _UFS_UFS_DINODE_H_ */
================================================
FILE: NanaZip.Codecs/FreeBSD/dir.h
================================================
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)dir.h 8.2 (Berkeley) 1/21/94
*/
#ifndef _UFS_UFS_DIR_H_
#define _UFS_UFS_DIR_H_
#include
/*
* Theoretically, directories can be more than 2Gb in length, however, in
* practice this seems unlikely. So, we define the type doff_t as a 32-bit
* quantity to keep down the cost of doing lookup on a 32-bit machine.
*/
#define doff_t int32_t
#define MAXDIRSIZE (0x7fffffff)
/*
* A directory consists of some number of blocks of DIRBLKSIZ
* bytes, where DIRBLKSIZ is chosen such that it can be transferred
* to disk in a single atomic operation (e.g. 512 bytes on most machines).
*
* Each DIRBLKSIZ byte block contains some number of directory entry
* structures, which are of variable length. Each directory entry has
* a struct direct at the front of it, containing its inode number,
* the length of the entry, and the length of the name contained in
* the entry. These are followed by the name padded to a 4 byte boundary
* with null bytes. All names are guaranteed null terminated.
* The maximum length of a name in a directory is UFS_MAXNAMLEN.
*
* The macro DIRSIZ(fmt, dp) gives the amount of space required to represent
* a directory entry. Free space in a directory is represented by
* entries which have dp->d_reclen > DIRSIZ(fmt, dp). All DIRBLKSIZ bytes
* in a directory block are claimed by the directory entries. This
* usually results in the last entry in a directory having a large
* dp->d_reclen. When entries are deleted from a directory, the
* space is returned to the previous entry in the same directory
* block by increasing its dp->d_reclen. If the first entry of
* a directory block is free, then its dp->d_ino is set to 0.
* Entries other than the first in a directory do not normally have
* dp->d_ino set to 0.
*/
#define DIRBLKSIZ DEV_BSIZE
#define UFS_MAXNAMLEN 255
struct direct {
uint32_t d_ino; /* inode number of entry */
uint16_t d_reclen; /* length of this record */
uint8_t d_type; /* file type, see below */
uint8_t d_namlen; /* length of string in d_name */
char d_name[UFS_MAXNAMLEN + 1];
/* name with length <= UFS_MAXNAMLEN */
};
/*
* File types
*/
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
/*
* Convert between stat structure types and directory types.
*/
#define IFTODT(mode) (((mode) & 0170000) >> 12)
#define DTTOIF(dirtype) ((dirtype) << 12)
/*
* The DIRSIZ macro gives the minimum record length which will hold
* the directory entry. This requires the amount of space in struct direct
* without the d_name field, plus enough space for the name with a terminating
* null byte (dp->d_namlen + 1), rounded up to a 4 byte boundary.
*/
#define DIR_ROUNDUP 4 /* Directory name roundup size */
#define DIRECTSIZ(namlen) \
(roundup2(__offsetof(struct direct, d_name) + (namlen) + 1, DIR_ROUNDUP))
#if (BYTE_ORDER == LITTLE_ENDIAN)
#define DIRSIZ(oldfmt, dp) \
((oldfmt) ? DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
#else
#define DIRSIZ(oldfmt, dp) \
DIRECTSIZ((dp)->d_namlen)
#endif
#define OLDDIRFMT 1
#define NEWDIRFMT 0
/*
* Template for manipulating directories. Should use struct direct's,
* but the name field is UFS_MAXNAMLEN - 1, and this just won't do.
*/
struct dirtemplate {
uint32_t dot_ino;
int16_t dot_reclen;
uint8_t dot_type;
uint8_t dot_namlen;
char dot_name[4]; /* must be multiple of 4 */
uint32_t dotdot_ino;
int16_t dotdot_reclen;
uint8_t dotdot_type;
uint8_t dotdot_namlen;
char dotdot_name[4]; /* ditto */
};
/*
* This is the old format of directories, sanz type element.
*/
struct odirtemplate {
uint32_t dot_ino;
int16_t dot_reclen;
uint16_t dot_namlen;
char dot_name[4]; /* must be multiple of 4 */
uint32_t dotdot_ino;
int16_t dotdot_reclen;
uint16_t dotdot_namlen;
char dotdot_name[4]; /* ditto */
};
#endif /* !_DIR_H_ */
================================================
FILE: NanaZip.Codecs/FreeBSD/fs.h
================================================
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)fs.h 8.13 (Berkeley) 3/21/95
*/
#ifndef _UFS_FFS_FS_H_
#define _UFS_FFS_FS_H_
#include
#include "dinode.h"
#define NBBY 8 /* number of bits in a byte */
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y))
#endif
/*
* Each disk drive contains some number of filesystems.
* A filesystem consists of a number of cylinder groups.
* Each cylinder group has inodes and data.
*
* A filesystem is described by its super-block, which in turn
* describes the cylinder groups. The super-block is critical
* data and is replicated in each cylinder group to protect against
* catastrophic loss. This is done at `newfs' time and the critical
* super-block data does not change, so the copies need not be
* referenced further unless disaster strikes.
*
* For filesystem fs, the offsets of the various blocks of interest
* are given in the super block as:
* [fs->fs_sblkno] Super-block
* [fs->fs_cblkno] Cylinder group block
* [fs->fs_iblkno] Inode blocks
* [fs->fs_dblkno] Data blocks
* The beginning of cylinder group cg in fs, is given by
* the ``cgbase(fs, cg)'' macro.
*
* Depending on the architecture and the media, the superblock may
* reside in any one of four places. For tiny media where every block
* counts, it is placed at the very front of the partition. Historically,
* UFS1 placed it 8K from the front to leave room for the disk label and
* a small bootstrap. For UFS2 it got moved to 64K from the front to leave
* room for the disk label and a bigger bootstrap, and for really piggy
* systems we check at 256K from the front if the first three fail. In
* all cases the size of the superblock will be SBLOCKSIZE. All values are
* given in byte-offset form, so they do not imply a sector size. The
* SBLOCKSEARCH specifies the order in which the locations should be searched.
*/
#define SBLOCK_FLOPPY 0
#define SBLOCK_UFS1 8192
#define SBLOCK_UFS2 65536
#define SBLOCK_PIGGY 262144
#define SBLOCKSIZE 8192
#define SBLOCKSEARCH \
{ SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
/*
* Request standard superblock location in ffs_sbget().
*/
#define UFS_STDSB -1 /* Search standard places for superblock */
/*
* UFS_NOMSG indicates that superblock inconsistency error messages
* should not be printed. It is used by programs like fsck that
* want to print their own error message.
*
* UFS_NOCSUM causes only the superblock itself to be returned, but does
* not read in any auxiliary data structures like the cylinder group
* summary information. It is used by clients like glabel that just
* want to check for possible filesystem types. Using UFS_NOCSUM
* skips the superblock checks for csum data which allows superblocks
* that have corrupted csum data to be read and used.
*
* UFS_NOHASHFAIL will note that the check hash is wrong but will still
* return the superblock. This is used by the bootstrap code to
* give the system a chance to come up so that fsck can be run to
* correct the problem.
*
* UFS_NOWARNFAIL will warn about inconsistencies but still return the
* superblock. It includes UFS_NOHASHFAIL. UFS_NOWARNFAIL is used by
* programs like fsck_ffs(8) to debug broken filesystems.
*
* UFS_FSRONLY will only validate the superblock fields needed to
* calculate where the backup filesystem superblocks are located.
* If these values pass their validation tests, then the superblock
* is returned. This flag is used as part of the attempt to find
* alternate superblocks when using ffs_sbsearch().
*/
#define UFS_NOHASHFAIL 0x0001 /* Ignore check-hash failure */
#define UFS_NOWARNFAIL 0x0003 /* Ignore non-fatal inconsistencies */
#define UFS_NOMSG 0x0004 /* Print no error message */
#define UFS_NOCSUM 0x0008 /* Read just the superblock without csum */
#define UFS_FSRONLY 0x0010 /* Validate only values needed for recovery
of alternate superblocks */
#define UFS_ALTSBLK 0x1000 /* Flag used internally */
/*
* Max number of fragments per block. This value is NOT tweakable.
*/
#define MAXFRAG 8
/*
* Addresses stored in inodes are capable of addressing fragments
* of `blocks'. File system blocks of at most size MAXBSIZE can
* be optionally broken into 2, 4, or 8 pieces, each of which is
* addressable; these pieces may be DEV_BSIZE, or some multiple of
* a DEV_BSIZE unit.
*
* Large files consist of exclusively large data blocks. To avoid
* undue wasted disk space, the last data block of a small file may be
* allocated as only as many fragments of a large block as are
* necessary. The filesystem format retains only a single pointer
* to such a fragment, which is a piece of a single large block that
* has been divided. The size of such a fragment is determinable from
* information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
*
* The filesystem records space availability at the fragment level;
* to determine block availability, aligned fragments are examined.
*/
/*
* MINBSIZE is the smallest allowable block size.
* In order to insure that it is possible to create files of size
* 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
* MINBSIZE must be big enough to hold a cylinder group block,
* thus changes to (struct cg) must keep its size within MINBSIZE.
* Note that super blocks are always of size SBLOCKSIZE,
* and that both SBLOCKSIZE and MAXBSIZE must be >= MINBSIZE.
*/
#define MINBSIZE 4096
/*
* The path name on which the filesystem is mounted is maintained
* in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
* the super block for this name.
*/
#define MAXMNTLEN 468
/*
* The volume name for this filesystem is maintained in fs_volname.
* MAXVOLLEN defines the length of the buffer allocated.
*/
#define MAXVOLLEN 32
/*
* There is a 128-byte region in the superblock reserved for in-core
* pointers to summary information. Originally this included an array
* of pointers to blocks of struct csum; now there are just a few
* pointers and the remaining space is padded with fs_ocsp[].
*
* NOCSPTRS determines the size of this padding. Historically this
* space was used to store pointers to structures that summaried
* filesystem usage and layout information. However, these pointers
* left various kernel pointers in the superblock which made otherwise
* identical superblocks appear to have differences. So, all the
* pointers in the superblock were moved to a fs_summary_info structure
* reducing the superblock to having only a single pointer to this
* structure. When writing the superblock to disk, this pointer is
* temporarily NULL'ed out so that the kernel pointer will not appear
* in the on-disk copy of the superblock.
*/
#define NOCSPTRS ((128 / sizeof(void *)) - 1)
/*
* A summary of contiguous blocks of various sizes is maintained
* in each cylinder group. Normally this is set by the initial
* value of fs_maxcontig. To conserve space, a maximum summary size
* is set by FS_MAXCONTIG.
*/
#define FS_MAXCONTIG 16
/*
* MINFREE gives the minimum acceptable percentage of filesystem
* blocks which may be free. If the freelist drops below this level
* only the superuser may continue to allocate blocks. This may
* be set to 0 if no reserve of free blocks is deemed necessary,
* however throughput drops by fifty percent if the filesystem
* is run at between 95% and 100% full; thus the minimum default
* value of fs_minfree is 5%. However, to get good clustering
* performance, 10% is a better choice. hence we use 10% as our
* default value. With 10% free space, fragmentation is not a
* problem, so we choose to optimize for time.
*/
#define MINFREE 8
#define DEFAULTOPT FS_OPTTIME
/*
* Grigoriy Orlov has done some extensive work to fine
* tune the layout preferences for directories within a filesystem.
* His algorithm can be tuned by adjusting the following parameters
* which tell the system the average file size and the average number
* of files per directory. These defaults are well selected for typical
* filesystems, but may need to be tuned for odd cases like filesystems
* being used for squid caches or news spools.
*/
#define AVFILESIZ 16384 /* expected average file size */
#define AFPDIR 64 /* expected number of files per directory */
/*
* The maximum number of snapshot nodes that can be associated
* with each filesystem. This limit affects only the number of
* snapshot files that can be recorded within the superblock so
* that they can be found when the filesystem is mounted. However,
* maintaining too many will slow the filesystem performance, so
* having this limit is a good idea.
*/
#define FSMAXSNAP 20
/*
* Used to identify special blocks in snapshots:
*
* BLK_NOCOPY - A block that was unallocated at the time the snapshot
* was taken, hence does not need to be copied when written.
* BLK_SNAP - A block held by another snapshot that is not needed by this
* snapshot. When the other snapshot is freed, the BLK_SNAP entries
* are converted to BLK_NOCOPY. These are needed to allow fsck to
* identify blocks that are in use by other snapshots (which are
* expunged from this snapshot).
*/
#define BLK_NOCOPY ((ufs2_daddr_t)(1))
#define BLK_SNAP ((ufs2_daddr_t)(2))
/*
* Sysctl values for the fast filesystem.
*/
#define FFS_ADJ_REFCNT 1 /* adjust inode reference count */
#define FFS_ADJ_BLKCNT 2 /* adjust inode used block count */
#define FFS_BLK_FREE 3 /* free range of blocks in map */
#define FFS_DIR_FREE 4 /* free specified dir inodes in map */
#define FFS_FILE_FREE 5 /* free specified file inodes in map */
#define FFS_SET_FLAGS 6 /* set filesystem flags */
#define FFS_ADJ_NDIR 7 /* adjust number of directories */
#define FFS_ADJ_NBFREE 8 /* adjust number of free blocks */
#define FFS_ADJ_NIFREE 9 /* adjust number of free inodes */
#define FFS_ADJ_NFFREE 10 /* adjust number of free frags */
#define FFS_ADJ_NUMCLUSTERS 11 /* adjust number of free clusters */
#define FFS_SET_CWD 12 /* set current directory */
#define FFS_SET_DOTDOT 13 /* set inode number for ".." */
#define FFS_UNLINK 14 /* remove a name in the filesystem */
/* Was FFS_SET_INODE 15 */
/* Was FFS_SET_BUFOUTPUT 16 */
#define FFS_SET_SIZE 17 /* set inode size */
#define FFS_ADJ_DEPTH 18 /* adjust directory inode depth */
#define FFS_MAXID 18 /* number of valid ffs ids */
/*
* Command structure passed in to the filesystem to adjust filesystem values.
*/
#define FFS_CMD_VERSION 0x19790518 /* version ID */
struct fsck_cmd {
int32_t version; /* version of command structure */
int32_t handle; /* reference to filesystem to be changed */
int64_t value; /* inode or block number to be affected */
int64_t size; /* amount or range to be adjusted */
int64_t spare; /* reserved for future use */
};
/*
* A recovery structure placed at the end of the boot block area by newfs
* that can be used by fsck to search for alternate superblocks.
*/
struct fsrecovery {
int32_t fsr_magic; /* magic number */
int32_t fsr_fsbtodb; /* fsbtodb and dbtofsb shift constant */
int32_t fsr_sblkno; /* offset of super-block in filesys */
int32_t fsr_fpg; /* blocks per group * fs_frag */
uint32_t fsr_ncg; /* number of cylinder groups */
};
/*
* Per cylinder group information; summarized in blocks allocated
* from first cylinder group data blocks. These blocks have to be
* read in from fs_csaddr (size fs_cssize) in addition to the
* super block.
*/
struct csum {
int32_t cs_ndir; /* number of directories */
int32_t cs_nbfree; /* number of free blocks */
int32_t cs_nifree; /* number of free inodes */
int32_t cs_nffree; /* number of free frags */
};
struct csum_total {
int64_t cs_ndir; /* number of directories */
int64_t cs_nbfree; /* number of free blocks */
int64_t cs_nifree; /* number of free inodes */
int64_t cs_nffree; /* number of free frags */
int64_t cs_numclusters; /* number of free clusters */
int64_t cs_spare[3]; /* future expansion */
};
/*
* Pointers to super block summary information. Placed in a separate
* structure so there is just one pointer in the superblock.
*
* The pointers in this structure are used as follows:
* fs_contigdirs references an array that tracks the creation of new
* directories
* fs_csp references a contiguous array of struct csum for
* all cylinder groups
* fs_maxcluster references an array of cluster sizes that is computed
* as cylinder groups are inspected
* fs_active is used when creating snapshots; it points to a bitmap
* of cylinder groups for which the free-block bitmap has changed
* since the snapshot operation began.
*/
struct fs_summary_info {
uint8_t *si_contigdirs; /* (u) # of contig. allocated dirs */
struct csum *si_csp; /* (u) cg summary info buffer */
int32_t *si_maxcluster; /* (u) max cluster in each cyl group */
uint64_t *si_active; /* (u) used by snapshots to track fs */
};
#define fs_contigdirs fs_si->si_contigdirs
#define fs_csp fs_si->si_csp
#define fs_maxcluster fs_si->si_maxcluster
#define fs_active fs_si->si_active
/*
* Super block for an FFS filesystem.
*/
struct fs {
int32_t fs_firstfield; /* historic filesystem linked list, */
int32_t fs_unused_1; /* used for incore super blocks */
int32_t fs_sblkno; /* offset of super-block in filesys */
int32_t fs_cblkno; /* offset of cyl-block in filesys */
int32_t fs_iblkno; /* offset of inode-blocks in filesys */
int32_t fs_dblkno; /* offset of first data after cg */
int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */
int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */
int32_t fs_old_time; /* last time written */
int32_t fs_old_size; /* number of blocks in fs */
int32_t fs_old_dsize; /* number of data blocks in fs */
uint32_t fs_ncg; /* number of cylinder groups */
int32_t fs_bsize; /* size of basic blocks in fs */
int32_t fs_fsize; /* size of frag blocks in fs */
int32_t fs_frag; /* number of frags in a block in fs */
/* these are configuration parameters */
int32_t fs_minfree; /* minimum percentage of free blocks */
int32_t fs_old_rotdelay; /* num of ms for optimal next block */
int32_t fs_old_rps; /* disk revolutions per second */
/* these fields can be computed from the others */
int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */
int32_t fs_fshift; /* ``numfrags'' calc number of frags */
/* these are configuration parameters */
int32_t fs_maxcontig; /* max number of contiguous blks */
int32_t fs_maxbpg; /* max number of blks per cyl group */
/* these fields can be computed from the others */
int32_t fs_fragshift; /* block to frag shift */
int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
int32_t fs_sbsize; /* actual size of super block */
int32_t fs_spare1[2]; /* old fs_csmask */
/* old fs_csshift */
int32_t fs_nindir; /* value of NINDIR */
uint32_t fs_inopb; /* value of INOPB */
int32_t fs_old_nspf; /* value of NSPF */
/* yet another configuration parameter */
int32_t fs_optim; /* optimization preference, see below */
int32_t fs_old_npsect; /* # sectors/track including spares */
int32_t fs_old_interleave; /* hardware sector interleave */
int32_t fs_old_trackskew; /* sector 0 skew, per track */
int32_t fs_id[2]; /* unique filesystem id */
/* sizes determined by number of cylinder groups and their sizes */
int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */
int32_t fs_cssize; /* size of cyl grp summary area */
int32_t fs_cgsize; /* cylinder group size */
int32_t fs_spare2; /* old fs_ntrak */
int32_t fs_old_nsect; /* sectors per track */
int32_t fs_old_spc; /* sectors per cylinder */
int32_t fs_old_ncyl; /* cylinders in filesystem */
int32_t fs_old_cpg; /* cylinders per group */
uint32_t fs_ipg; /* inodes per group */
int32_t fs_fpg; /* blocks per group * fs_frag */
/* this data must be re-computed after crashes */
struct csum fs_old_cstotal; /* cylinder summary information */
/* these fields are cleared at mount time */
int8_t fs_fmod; /* super block modified flag */
int8_t fs_clean; /* filesystem is clean flag */
int8_t fs_ronly; /* mounted read-only flag */
int8_t fs_old_flags; /* old FS_ flags */
uint8_t fs_fsmnt[MAXMNTLEN]; /* name mounted on */
uint8_t fs_volname[MAXVOLLEN]; /* volume name */
uint64_t fs_swuid; /* system-wide uid */
int32_t fs_pad; /* due to alignment of fs_swuid */
/* these fields retain the current block allocation info */
int32_t fs_cgrotor; /* last cg searched */
void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */
struct fs_summary_info *fs_si;/* In-core pointer to summary info */
int32_t fs_old_cpc; /* cyl per cycle in postbl */
int32_t fs_maxbsize; /* maximum blocking factor permitted */
int64_t fs_unrefs; /* number of unreferenced inodes */
int64_t fs_providersize; /* size of underlying GEOM provider */
int64_t fs_metaspace; /* size of area reserved for metadata */
int64_t fs_sparecon64[13]; /* old rotation block list head */
int64_t fs_sblockactualloc; /* byte offset of this superblock */
int64_t fs_sblockloc; /* byte offset of standard superblock */
struct csum_total fs_cstotal; /* (u) cylinder summary information */
ufs_time_t fs_time; /* last time written */
int64_t fs_size; /* number of blocks in fs */
int64_t fs_dsize; /* number of data blocks in fs */
ufs2_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
int64_t fs_pendingblocks; /* (u) blocks being freed */
uint32_t fs_pendinginodes; /* (u) inodes being freed */
uint32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
uint32_t fs_avgfilesize; /* expected average file size */
uint32_t fs_avgfpdir; /* expected # of files per directory */
int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */
ufs_time_t fs_mtime; /* Last mount or fsck time. */
int32_t fs_sujfree; /* SUJ free list */
int32_t fs_sparecon32[21]; /* reserved for future constants */
uint32_t fs_ckhash; /* if CK_SUPERBLOCK, its check-hash */
uint32_t fs_metackhash; /* metadata check-hash, see CK_ below */
int32_t fs_flags; /* see FS_ flags below */
int32_t fs_contigsumsize; /* size of cluster summary array */
int32_t fs_maxsymlinklen; /* max length of an internal symlink */
int32_t fs_old_inodefmt; /* format of on-disk inodes */
uint64_t fs_maxfilesize; /* maximum representable file size */
int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */
int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */
int32_t fs_state; /* validate fs_clean field */
int32_t fs_old_postblformat; /* format of positional layout tables */
int32_t fs_old_nrpos; /* number of rotational positions */
int32_t fs_spare5[2]; /* old fs_postbloff */
/* old fs_rotbloff */
int32_t fs_magic; /* magic number */
};
/* Sanity checking. */
#ifdef CTASSERT
CTASSERT(sizeof(struct fs) == 1376);
#endif
/*
* Filesystem identification
*/
#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast filesystem magic number */
#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast filesystem magic number */
#define FS_BAD_MAGIC 0x19960408 /* UFS incomplete newfs magic number */
#define FS_42INODEFMT -1 /* 4.2BSD inode format */
#define FS_44INODEFMT 2 /* 4.4BSD inode format */
/*
* Preference for optimization.
*/
#define FS_OPTTIME 0 /* minimize allocation time */
#define FS_OPTSPACE 1 /* minimize disk fragmentation */
/*
* Filesystem flags.
*
* The FS_UNCLEAN flag is set by the kernel when the filesystem was
* mounted with fs_clean set to zero. The FS_DOSOFTDEP flag indicates
* that the filesystem should be managed by the soft updates code.
* Note that the FS_NEEDSFSCK flag is set and cleared by the fsck
* utility. It is set when background fsck finds an unexpected
* inconsistency which requires a traditional foreground fsck to be
* run. Such inconsistencies should only be found after an uncorrectable
* disk error. The FS_NEEDSFSCK can also be set when a mounted filesystem
* discovers an internal inconsistency such as freeing a freed inode.
* A foreground fsck will clear the FS_NEEDSFSCK flag when it has
* successfully cleaned up the filesystem. The kernel uses this
* flag to enforce that inconsistent filesystems be mounted read-only.
*
* The FS_METACKHASH flag when set indicates that the kernel maintains
* one or more check hashes. The actual set of supported check hashes
* is stored in the fs_metackhash field. Kernels that do not support
* check hashes clear the FS_METACKHASH flag to indicate that the
* check hashes need to be rebuilt (by fsck) before they can be used.
*
* When a filesystem is mounted, any flags not included in FS_SUPPORTED
* are cleared. This lets newer features know that the filesystem has
* been run on an older version of the filesystem and thus that data
* structures associated with those features are out-of-date and need
* to be rebuilt.
*
* FS_ACLS indicates that POSIX.1e ACLs are administratively enabled
* for the file system, so they should be loaded from extended attributes,
* observed for access control purposes, and be administered by object
* owners. FS_NFS4ACLS indicates that NFSv4 ACLs are administratively
* enabled. This flag is mutually exclusive with FS_ACLS. FS_MULTILABEL
* indicates that the TrustedBSD MAC Framework should attempt to back MAC
* labels into extended attributes on the file system rather than maintain
* a single mount label for all objects.
*/
#define FS_UNCLEAN 0x00000001 /* filesystem not clean at mount */
#define FS_DOSOFTDEP 0x00000002 /* filesystem using soft dependencies */
#define FS_NEEDSFSCK 0x00000004 /* filesystem needs sync fsck before mount */
#define FS_SUJ 0x00000008 /* Filesystem using softupdate journal */
#define FS_ACLS 0x00000010 /* file system has POSIX.1e ACLs enabled */
#define FS_MULTILABEL 0x00000020 /* file system is MAC multi-label */
#define FS_GJOURNAL 0x00000040 /* gjournaled file system */
#define FS_FLAGS_UPDATED 0x0000080 /* flags have been moved to new location */
#define FS_NFS4ACLS 0x00000100 /* file system has NFSv4 ACLs enabled */
#define FS_METACKHASH 0x00000200 /* kernel supports metadata check hashes */
#define FS_TRIM 0x00000400 /* issue BIO_DELETE for deleted blocks */
#define FS_SUPPORTED 0x00FFFFFF /* supported flags, others cleared at mount*/
/*
* Things that we may someday support, but currently do not.
* These flags are all cleared so we know if we ran on a kernel
* that does not support them.
*/
#define FS_INDEXDIRS 0x01000000 /* kernel supports indexed directories */
#define FS_VARBLKSIZE 0x02000000 /* kernel supports variable block sizes */
#define FS_COOLOPT1 0x04000000 /* kernel supports cool option 1 */
#define FS_COOLOPT2 0x08000000 /* kernel supports cool option 2 */
#define FS_COOLOPT3 0x10000000 /* kernel supports cool option 3 */
#define FS_COOLOPT4 0x20000000 /* kernel supports cool option 4 */
#define FS_COOLOPT5 0x40000000 /* kernel supports cool option 5 */
#define FS_COOLOPT6 0x80000000 /* kernel supports cool option 6 */
/*
* The fs_metackhash field indicates the types of metadata check-hash
* that are maintained for a filesystem. Not all filesystems check-hash
* all metadata.
*/
#define CK_SUPERBLOCK 0x0001 /* the superblock */
#define CK_CYLGRP 0x0002 /* the cylinder groups */
#define CK_INODE 0x0004 /* inodes */
#define CK_INDIR 0x0008 /* indirect blocks */
#define CK_DIR 0x0010 /* directory contents */
#define CK_SUPPORTED 0x0007 /* supported flags, others cleared at mount */
/*
* The BX_FSPRIV buffer b_xflags are used to track types of data in buffers.
*/
#define BX_SUPERBLOCK 0x00010000 /* superblock */
#define BX_CYLGRP 0x00020000 /* cylinder groups */
#define BX_INODE 0x00040000 /* inodes */
#define BX_INDIR 0x00080000 /* indirect blocks */
#define BX_DIR 0x00100000 /* directory contents */
#define PRINT_UFS_BUF_XFLAGS "\20\25dir\24indir\23inode\22cylgrp\21superblock"
/*
* Macros to access bits in the fs_active array.
*/
#define ACTIVECGNUM(fs, cg) ((fs)->fs_active[(cg) / (NBBY * sizeof(uint64_t))])
#define ACTIVECGOFF(cg) (1 << ((cg) % (NBBY * sizeof(uint64_t))))
#define ACTIVESET(fs, cg) do { \
if ((fs)->fs_active) \
ACTIVECGNUM((fs), (cg)) |= ACTIVECGOFF((cg)); \
} while (0)
#define ACTIVECLEAR(fs, cg) do { \
if ((fs)->fs_active) \
ACTIVECGNUM((fs), (cg)) &= ~ACTIVECGOFF((cg)); \
} while (0)
/*
* The size of a cylinder group is calculated by CGSIZE. The maximum size
* is limited by the fact that cylinder groups are at most one block.
* Its size is derived from the size of the maps maintained in the
* cylinder group and the (struct cg) size.
*/
#define CGSIZE(fs) \
/* base cg */ (sizeof(struct cg) + \
/* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \
/* old boff */ (fs)->fs_old_cpg * sizeof(uint16_t) + \
/* inode map */ howmany((fs)->fs_ipg, NBBY) + \
/* block map */ howmany((fs)->fs_fpg, NBBY) + sizeof(int32_t) + \
/* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
/* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \
/* cluster map */ howmany(fragstoblks(fs, (fs)->fs_fpg), NBBY)))
/*
* The minimal number of cylinder groups that should be created.
*/
#define MINCYLGRPS 4
/*
* Convert cylinder group to base address of its global summary info.
*/
#define fs_cs(fs, indx) fs_csp[indx]
/*
* Cylinder group block for a filesystem.
*/
#define CG_MAGIC 0x090255
struct cg {
int32_t cg_firstfield; /* historic cyl groups linked list */
int32_t cg_magic; /* magic number */
int32_t cg_old_time; /* time last written */
uint32_t cg_cgx; /* we are the cgx'th cylinder group */
int16_t cg_old_ncyl; /* number of cyl's this cg */
int16_t cg_old_niblk; /* number of inode blocks this cg */
uint32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
uint32_t cg_rotor; /* position of last used block */
uint32_t cg_frotor; /* position of last used frag */
uint32_t cg_irotor; /* position of last used inode */
uint32_t cg_frsum[MAXFRAG]; /* counts of available frags */
int32_t cg_old_btotoff; /* (int32) block totals per cylinder */
int32_t cg_old_boff; /* (uint16) free block positions */
uint32_t cg_iusedoff; /* (uint8) used inode map */
uint32_t cg_freeoff; /* (uint8) free block map */
uint32_t cg_nextfreeoff; /* (uint8) next available space */
uint32_t cg_clustersumoff; /* (uint32) counts of avail clusters */
uint32_t cg_clusteroff; /* (uint8) free cluster map */
uint32_t cg_nclusterblks; /* number of clusters this cg */
uint32_t cg_niblk; /* number of inode blocks this cg */
uint32_t cg_initediblk; /* last initialized inode */
uint32_t cg_unrefs; /* number of unreferenced inodes */
int32_t cg_sparecon32[1]; /* reserved for future use */
uint32_t cg_ckhash; /* check-hash of this cg */
ufs_time_t cg_time; /* time last written */
int64_t cg_sparecon64[3]; /* reserved for future use */
/* actually longer - space used for cylinder group maps */
};
/*
* Macros for access to cylinder group array structures
*/
#define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
#define cg_inosused(cgp) \
((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_iusedoff))
#define cg_blksfree(cgp) \
((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_freeoff))
#define cg_clustersfree(cgp) \
((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_clusteroff))
#define cg_clustersum(cgp) \
((int32_t *)((uintptr_t)(cgp) + (cgp)->cg_clustersumoff))
/*
* Turn filesystem block numbers into disk block addresses.
* This maps filesystem blocks to device size blocks.
*/
#define fsbtodb(fs, b) ((daddr_t)(b) << (fs)->fs_fsbtodb)
#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb)
/*
* Cylinder group macros to locate things in cylinder groups.
* They calc filesystem addresses of cylinder group data structures.
*/
#define cgbase(fs, c) (((ufs2_daddr_t)(fs)->fs_fpg) * (c))
#define cgdata(fs, c) (cgdmin(fs, c) + (fs)->fs_metaspace) /* data zone */
#define cgmeta(fs, c) (cgdmin(fs, c)) /* meta data */
#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
#define cgstart(fs, c) \
((fs)->fs_magic == FS_UFS2_MAGIC ? cgbase(fs, c) : \
(cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask))))
/*
* Macros for handling inode numbers:
* inode number to filesystem block offset.
* inode number to cylinder group number.
* inode number to filesystem block address.
*/
#define ino_to_cg(fs, x) (((ino_t)(x)) / (fs)->fs_ipg)
#define ino_to_fsba(fs, x) \
((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, (ino_t)(x))) + \
(blkstofrags((fs), ((((ino_t)(x)) % (fs)->fs_ipg) / INOPB(fs))))))
#define ino_to_fsbo(fs, x) (((ino_t)(x)) % INOPB(fs))
/*
* Give cylinder group number for a filesystem block.
* Give cylinder group block number for a filesystem block.
*/
#define dtog(fs, d) ((d) / (fs)->fs_fpg)
#define dtogd(fs, d) ((d) % (fs)->fs_fpg)
/*
* Extract the bits for a block from a map.
* Compute the cylinder and rotational position of a cyl block addr.
*/
#define blkmap(fs, map, loc) \
(((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
/*
* The following macros optimize certain frequently calculated
* quantities by using shifts and masks in place of divisions
* modulos and multiplications.
*/
#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
((loc) & (fs)->fs_qbmask)
#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
((loc) & (fs)->fs_qfmask)
#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \
(((off_t)(frag)) << (fs)->fs_fshift)
#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \
(((off_t)(blk)) << (fs)->fs_bshift)
/* Use this only when `blk' is known to be small, e.g., < UFS_NDADDR. */
#define smalllblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \
((blk) << (fs)->fs_bshift)
#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
((loc) >> (fs)->fs_bshift)
#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
((loc) >> (fs)->fs_fshift)
#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \
(((size) + (fs)->fs_qbmask) & (fs)->fs_bmask)
#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask)
#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \
((frags) >> (fs)->fs_fragshift)
#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \
((blks) << (fs)->fs_fragshift)
#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \
((fsb) & ((fs)->fs_frag - 1))
#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
((fsb) &~ ((fs)->fs_frag - 1))
/*
* Determine the number of available frags given a
* percentage to hold in reserve.
*/
#define freespace(fs, percentreserved) \
(blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
(fs)->fs_cstotal.cs_nffree - \
(((off_t)((fs)->fs_dsize)) * (percentreserved) / 100))
/*
* Determining the size of a file block in the filesystem.
*/
#define blksize(fs, ip, lbn) \
(((lbn) >= UFS_NDADDR || (ip)->i_size >= \
(uint64_t)smalllblktosize(fs, (lbn) + 1)) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (ip)->i_size))))
#define sblksize(fs, size, lbn) \
(((lbn) >= UFS_NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (size)))))
/*
* Number of indirects in a filesystem block.
*/
#define NINDIR(fs) ((fs)->fs_nindir)
/*
* Indirect lbns are aligned on UFS_NDADDR addresses where single indirects
* are the negated address of the lowest lbn reachable, double indirects
* are this lbn - 1 and triple indirects are this lbn - 2. This yields
* an unusual bit order to determine level.
*/
static inline int
lbn_level(ufs_lbn_t lbn)
{
if (lbn >= 0)
return 0;
switch (lbn & 0x3) {
case 0:
return (0);
case 1:
break;
case 2:
return (2);
case 3:
return (1);
default:
break;
}
return (-1);
}
static inline ufs_lbn_t
lbn_offset(struct fs *fs, int level)
{
ufs_lbn_t res;
for (res = 1; level > 0; level--)
res *= NINDIR(fs);
return (res);
}
/*
* Number of inodes in a secondary storage block/fragment.
*/
#define INOPB(fs) ((fs)->fs_inopb)
#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift)
/*
* Softdep journal record format.
*/
#define JOP_UNKNOWN 0 /* JOP operation is unknown */
#define JOP_ADDREF 1 /* Add a reference to an inode. */
#define JOP_REMREF 2 /* Remove a reference from an inode. */
#define JOP_NEWBLK 3 /* Allocate a block. */
#define JOP_FREEBLK 4 /* Free a block or a tree of blocks. */
#define JOP_MVREF 5 /* Move a reference from one off to another. */
#define JOP_TRUNC 6 /* Partial truncation record. */
#define JOP_SYNC 7 /* fsync() complete record. */
#define JOP_NUMJOPTYPES 8
#define JOP_NAMES { \
"unknown", \
"JOP_ADDREF", \
"JOP_REMREF", \
"JOP_NEWBLK", \
"JOP_FREEBLK", \
"JOP_MVREF", \
"JOP_TRUNC", \
"JOP_SYNC" }
#define JOP_OPTYPE(op) \
(op) < JOP_NUMJOPTYPES ? joptype[op] : joptype[JOP_UNKNOWN]
#define JREC_SIZE 32 /* Record and segment header size. */
#define SUJ_MIN (4 * 1024 * 1024) /* Minimum journal size */
#define SUJ_FILE ".sujournal" /* Journal file name */
/*
* Size of the segment record header. There is at most one for each disk
* block in the journal. The segment header is followed by an array of
* records. fsck depends on the first element in each record being 'op'
* and the second being 'ino'. Segments may span multiple disk blocks but
* the header is present on each.
*/
struct jsegrec {
uint64_t jsr_seq; /* Our sequence number */
uint64_t jsr_oldest; /* Oldest valid sequence number */
uint16_t jsr_cnt; /* Count of valid records */
uint16_t jsr_blocks; /* Count of device bsize blocks. */
uint32_t jsr_crc; /* 32bit crc of the valid space */
ufs_time_t jsr_time; /* timestamp for mount instance */
};
/*
* Reference record. Records a single link count modification.
*/
struct jrefrec {
uint32_t jr_op;
uint32_t jr_ino;
uint32_t jr_parent;
uint16_t jr_nlink;
uint16_t jr_mode;
int64_t jr_diroff;
uint64_t jr_unused;
};
/*
* Move record. Records a reference moving within a directory block. The
* nlink is unchanged but we must search both locations.
*/
struct jmvrec {
uint32_t jm_op;
uint32_t jm_ino;
uint32_t jm_parent;
uint16_t jm_unused;
int64_t jm_oldoff;
int64_t jm_newoff;
};
/*
* Block record. A set of frags or tree of blocks starting at an indirect are
* freed or a set of frags are allocated.
*/
struct jblkrec {
uint32_t jb_op;
uint32_t jb_ino;
ufs2_daddr_t jb_blkno;
ufs_lbn_t jb_lbn;
uint16_t jb_frags;
uint16_t jb_oldfrags;
uint32_t jb_unused;
};
/*
* Truncation record. Records a partial truncation so that it may be
* completed at check time. Also used for sync records.
*/
struct jtrncrec {
uint32_t jt_op;
uint32_t jt_ino;
int64_t jt_size;
uint32_t jt_extsize;
uint32_t jt_pad[3];
};
union jrec {
struct jsegrec rec_jsegrec;
struct jrefrec rec_jrefrec;
struct jmvrec rec_jmvrec;
struct jblkrec rec_jblkrec;
struct jtrncrec rec_jtrncrec;
};
#ifdef CTASSERT
CTASSERT(sizeof(struct jsegrec) == JREC_SIZE);
CTASSERT(sizeof(struct jrefrec) == JREC_SIZE);
CTASSERT(sizeof(struct jmvrec) == JREC_SIZE);
CTASSERT(sizeof(struct jblkrec) == JREC_SIZE);
CTASSERT(sizeof(struct jtrncrec) == JREC_SIZE);
CTASSERT(sizeof(union jrec) == JREC_SIZE);
#endif
extern int inside[], around[];
extern uint8_t *fragtbl[];
/*
* IOCTLs used for filesystem write suspension.
*/
#define UFSSUSPEND _IOW('U', 1, fsid_t)
#define UFSRESUME _IO('U', 2)
#endif
================================================
FILE: NanaZip.Codecs/GmSSL/endian.h
================================================
/*
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef GMSSL_ENDIAN_H
#define GMSSL_ENDIAN_H
/* Big Endian R/W */
#define GETU16(p) \
((uint16_t)(p)[0] << 8 | \
(uint16_t)(p)[1])
#define GETU32(p) \
((uint32_t)(p)[0] << 24 | \
(uint32_t)(p)[1] << 16 | \
(uint32_t)(p)[2] << 8 | \
(uint32_t)(p)[3])
#define GETU64(p) \
((uint64_t)(p)[0] << 56 | \
(uint64_t)(p)[1] << 48 | \
(uint64_t)(p)[2] << 40 | \
(uint64_t)(p)[3] << 32 | \
(uint64_t)(p)[4] << 24 | \
(uint64_t)(p)[5] << 16 | \
(uint64_t)(p)[6] << 8 | \
(uint64_t)(p)[7])
// 注意:PUTU32(buf, val++) 会出错!
#define PUTU16(p,V) \
((p)[0] = (uint8_t)((V) >> 8), \
(p)[1] = (uint8_t)(V))
#define PUTU32(p,V) \
((p)[0] = (uint8_t)((V) >> 24), \
(p)[1] = (uint8_t)((V) >> 16), \
(p)[2] = (uint8_t)((V) >> 8), \
(p)[3] = (uint8_t)(V))
#define PUTU64(p,V) \
((p)[0] = (uint8_t)((V) >> 56), \
(p)[1] = (uint8_t)((V) >> 48), \
(p)[2] = (uint8_t)((V) >> 40), \
(p)[3] = (uint8_t)((V) >> 32), \
(p)[4] = (uint8_t)((V) >> 24), \
(p)[5] = (uint8_t)((V) >> 16), \
(p)[6] = (uint8_t)((V) >> 8), \
(p)[7] = (uint8_t)(V))
/* Little Endian R/W */
#define GETU16_LE(p) (*(const uint16_t *)(p))
#define GETU32_LE(p) (*(const uint32_t *)(p))
#define GETU64_LE(p) (*(const uint64_t *)(p))
#define PUTU16_LE(p,V) *(uint16_t *)(p) = (V)
#define PUTU32_LE(p,V) *(uint32_t *)(p) = (V)
#define PUTU64_LE(p,V) *(uint64_t *)(p) = (V)
/* Rotate */
#define ROL32(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#define ROL64(a,n) (((a)<<(n))|((a)>>(64-(n))))
#define ROR32(a,n) ROL32((a),32-(n))
#define ROR64(a,n) ROL64(a,64-n)
#endif
================================================
FILE: NanaZip.Codecs/GmSSL/sm3.c
================================================
/*
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include
#include "sm3.h"
#include "endian.h"
#ifdef SM3_SSE3
# include
# include