From 86c44199b0ceb0b952db26991da71393be4d29ee Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 2 May 2023 16:10:08 +1000 Subject: [PATCH] add komihash: the fast and fun hashing header! --- lib/komihash/CMakeLists.txt | 3 + lib/komihash/LICENSE | 21 + lib/komihash/README.md | 477 ++++++++++++++++++ lib/komihash/hash_comparison.png | Bin 0 -> 108020 bytes lib/komihash/komihash.h | 831 +++++++++++++++++++++++++++++++ lib/komihash/testvec.c | 99 ++++ tools/cmake/common.cmake | 1 + 7 files changed, 1432 insertions(+) create mode 100644 lib/komihash/CMakeLists.txt create mode 100644 lib/komihash/LICENSE create mode 100644 lib/komihash/README.md create mode 100644 lib/komihash/hash_comparison.png create mode 100644 lib/komihash/komihash.h create mode 100644 lib/komihash/testvec.c diff --git a/lib/komihash/CMakeLists.txt b/lib/komihash/CMakeLists.txt new file mode 100644 index 00000000..55c96885 --- /dev/null +++ b/lib/komihash/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register( + INCLUDE_DIRS . +) diff --git a/lib/komihash/LICENSE b/lib/komihash/LICENSE new file mode 100644 index 00000000..0abdeccc --- /dev/null +++ b/lib/komihash/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-2022 Aleksey Vaneev + +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. diff --git a/lib/komihash/README.md b/lib/komihash/README.md new file mode 100644 index 00000000..ba7a2cd5 --- /dev/null +++ b/lib/komihash/README.md @@ -0,0 +1,477 @@ +# KOMIHASH - Very Fast Hash Function (in C) # + +## Introduction ## + +The `komihash()` function available in the `komihash.h` file implements a very +fast 64-bit hash function, mainly designed for hash-table and hash-map uses; +produces identical hashes on both big- and little-endian systems. Function's +code is portable, scalar, header-only inlineable C (C++). + +This function features both a high large-block hashing performance (26 GB/s +on Ryzen 3700X) and a high hashing throughput for small strings/messages +(about 10 cycles/hash for 0-15-byte strings). Performance on 32-bit systems +is, however, quite low. Also, large-block hashing performance on big-endian +systems may be 20% lower due to the need of byte-swapping (can be switched off +with a define). + +Technically, `komihash` is close to the class of hash functions like `wyhash` +and `CircleHash`, which are, in turn, close to the `lehmer64` PRNG. However, +`komihash` is structurally different to them in that it accumulates the full +128-bit multiplication result, without "compression" into a single 64-bit +state variable. Thus `komihash` does not lose differentiation between +consecutive states while others may. Another important difference in +`komihash` is that it parses the input message without overlaps. While +overlaps allow a function to have fewer code branches, they are considered +"non-ideal", potentially causing collisions and seed value flaws. Beside that, +`komihash` features superior seed value handling and Perlin Noise hashing. + +Note that this function is not cryptographically-secure: in open systems it +should only be used with a secret seed, to minimize the chance of a collision +attack. However, when the default seed is used (0), this further reduces +function's overhead by 1-2 cycles/hash (compiler-dependent). + +This function passes all [SMHasher](https://github.com/rurban/smhasher) tests. + +An aspect worth noting, important to some users, is that `komihash` at its +base uses a very simple mathematical construct, and uses no author-intended +nor author-fabricated information. The base state of the function is equal to +the first mantissa bits of PI, and can be changed to any uniformly-random +values. + +## Discrete-Incremental Hashing ## + +A correct way to hash an array of independent values, and which does not +require pre-buffering, is to pass previous hash value as a seed value. This +method may be as fast or faster than pre-buffering, especially if lengths of +values in the array are not small. An additional 1-2 cycles/hash advantage is +obtained if fixed-size values are being hashed incrementally (due to +compiler's branching optimization). In most cases, incremental hashing of even +a few 2-8-byte values may be faster than using pre-buffering if the overall +input length is not known in advance. + +``` + uint64_t HashVal = komihash( &val1, sizeof( val1 ), Seed ); + HashVal = komihash( &val2, sizeof( val2 ), HashVal ); + ... + HashVal = komihash( &valN, sizeof( valN ), HashVal ); +``` + +Note that this approach is not the same as "streamed" hashing since this +approach implicitly encodes the length of each independent value. Such kind of +hashing can be beneficial when a database record is being hashed, when it is +necessary to separate fields by means of encoding their lengths. + +Discrete-incremental hashing of nested structures requires a "hash value +stack" where the current hash value is pushed into it upon each nesting, the +nested level starts at hash value 0, and the resulting value is hashed with a +popped previous hash value upon exiting the nesting level. + +## Streamed Hashing ## + +The `komihash.h` file also features a fast continuously streamed +implementation of the `komihash` hash function. Streamed hashing expects any +number of `update` calls inbetween the `init` and `final` calls: + +``` + komihash_stream_t ctx; + komihash_stream_init( &ctx, UseSeed ); + + komihash_stream_update( &ctx, &val1, sizeof( val1 )); + komihash_stream_update( &ctx, &val2, sizeof( val2 )); + ... + komihash_stream_update( &ctx, &valN, sizeof( valN )); + + uint64_t Hash = komihash_stream_final( &ctx ); +``` + +Since the `final` function is non-destructive for the context structure, the +function can be used to obtain intermediate "incremental" hashes of the data +stream being hashed, and the hashing can then be resumed. + +The hash value produced via streamed hashing can be used in the +discrete-incremental hashing outlined above (e.g., for files and blobs). + +You may also consider using [PRVHASH64S](https://github.com/avaneev/prvhash) +which provides 8.4 GB/s hashing throughput on Ryzen 3700X, and is able to +produce a hash value of any required bit-size. + +## Ports ## + +* [Java, by Dynatrace](https://github.com/dynatrace-oss/hash4j) +* [LUA, by rangercyh](https://github.com/rangercyh/lua-komihash) +* [.NET](https://www.nuget.org/packages/FastHashes/) +* [Rust](https://crates.io/crates/komihash) + +## Comparisons ## + +These are the performance comparisons made and used by the author during the +development of `komihash`. + +### LLVM clang-cl 8.0.1 64-bit, Windows 10, Ryzen 3700X (Zen2), 4.2 GHz ### + +Compiler options: `/Ox /arch:sse2`; overhead: `1.8` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|11.0 |12.7 |26.2 | +|komihash 4.3 |11.2 |13.0 |26.0 | +|komihash 3.6 |11.1 |16.9 |27.5 | +|komihash 2.8 |11.3 |17.4 |27.7 | +|wyhash_final3 |13.4 |17.8 |29.7 | +|XXH3_64 0.8.0 |17.5 |21.1 |29.0 | +|XXH64 0.8.0 |12.7 |17.3 |17.3 | +|prvhash64m 4.1 |19.9 |26.1 |4.1 | + +Compiler options: `/Ox -mavx2`; overhead: `1.8` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|11.1 |12.7 |26.3 | +|komihash 4.3 |11.2 |13.0 |25.9 | +|komihash 3.6 |11.0 |16.3 |27.5 | +|komihash 2.8 |11.1 |17.7 |27.8 | +|wyhash_final3 |13.4 |17.7 |29.8 | +|XXH3_64 0.8.0 |17.7 |21.3 |61.0 | +|XXH64 0.8.0 |12.8 |17.4 |17.1 | +|prvhash64m 4.1 |20.0 |26.2 |4.1 | + +### ICC 19.0 64-bit, Windows 10, Ryzen 3700X (Zen2), 4.2 GHz ### + +Compiler options: `/O3 /QxSSE2`; overhead: `2.0` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|18.1 |21.9 |16.4 | +|komihash 4.3 |17.9 |21.6 |16.3 | +|komihash 3.6 |20.1 |24.0 |16.3 | +|komihash 2.8 |21.3 |25.6 |16.2 | +|wyhash_final3 |24.1 |32.0 |12.6 | +|XXH3_64 0.8.0 |21.8 |27.2 |29.6 | +|XXH64 0.8.0 |24.3 |36.6 |8.9 | +|prvhash64m 4.1 |29.9 |39.1 |3.2 | + +(this is likely a worst-case scenario, when a compiler was not cross-tuned +to a competing processor architecture; also, ICC for Windows does not support +the `__builtin_expect` and `__builtin_prefetch` intrinsics) + +### LLVM clang 12.0.1 64-bit, CentOS 8, Xeon E-2176G (CoffeeLake), 4.5 GHz ### + +Compiler options: `-O3 -mavx2`; overhead: `5.3` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|12.8 |14.4 |22.4 | +|komihash 4.3 |15.3 |16.3 |22.8 | +|komihash 3.6 |16.0 |19.0 |22.3 | +|komihash 2.8 |18.1 |22.3 |23.5 | +|wyhash_final3 |14.0 |18.7 |28.4 | +|XXH3_64 0.8.0 |18.0 |29.3 |51.0 | +|XXH64 0.8.0 |12.5 |16.4 |18.2 | +|prvhash64m 4.1 |27.0 |29.9 |4.3 | + +### GCC 8.5.0 64-bit, CentOS 8, Xeon E-2176G (CoffeeLake), 4.5 GHz ### + +Compiler options: `-O3 -msse2`; overhead: `5.8` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|13.2 |15.1 |24.7 | +|komihash 4.3 |15.4 |16.2 |24.4 | +|komihash 3.6 |16.4 |20.3 |24.7 | +|komihash 2.8 |18.5 |22.4 |24.7 | +|wyhash_final3 |14.9 |19.5 |29.8 | +|XXH3_64 0.8.0 |16.9 |22.3 |26.6 | +|XXH64 0.8.0 |13.7 |17.7 |18.0 | +|prvhash64m 4.1 |23.2 |27.8 |4.3 | + +Compiler options: `-O3 -mavx2`; overhead: `5.8` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|13.8 |15.2 |24.7 | +|komihash 4.3 |15.3 |16.4 |24.4 | +|komihash 3.6 |15.8 |20.1 |24.7 | +|komihash 2.8 |16.6 |21.2 |24.7 | +|wyhash_final3 |15.4 |19.0 |30.1 | +|XXH3_64 0.8.0 |18.8 |23.4 |38.0 | +|XXH64 0.8.0 |15.3 |17.9 |18.1 | +|prvhash64m 4.1 |21.7 |27.1 |4.4 | + +### LLVM clang 8.0.0 64-bit, Windows 10, Core i7-7700K (KabyLake), 4.5 GHz ### + +Compiler options: `/Ox -mavx2`; overhead: `5.5` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|12.6 |14.5 |22.2 | +|komihash 4.3 |14.1 |16.0 |22.0 | +|komihash 3.6 |14.0 |22.0 |22.9 | +|komihash 2.8 |13.4 |22.7 |23.7 | +|wyhash_final3 |14.5 |20.1 |30.0 | +|XXH3_64 0.8.0 |18.4 |23.0 |48.3 | +|XXH64 0.8.0 |13.2 |17.3 |17.7 | +|prvhash64m 4.1 |23.2 |29.6 |4.1 | + +### ICC 19.0 64-bit, Windows 10, Core i7-7700K (KabyLake), 4.5 GHz ### + +Compiler options: `/O3 /QxSSE2`; overhead: `5.9` cycles/h. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|18.1 |21.1 |17.2 | +|komihash 4.3 |18.7 |21.5 |18.5 | +|komihash 3.6 |19.5 |23.1 |18.1 | +|komihash 2.8 |20.1 |23.6 |18.4 | +|wyhash_final3 |19.2 |24.5 |20.0 | +|XXH3_64 0.8.0 |19.9 |25.8 |28.0 | +|XXH64 0.8.0 |18.8 |24.7 |16.0 | +|prvhash64m 4.1 |25.5 |32.4 |3.2 | + +### Apple clang 12.0.0 64-bit, macOS 12.0.1, Apple M1, 3.5 GHz ### + +Compiler options: `-O3`; overhead: `unestimatable`. + +|Hash function |0-15b, cycles/h|8-28b, cycles/h|bulk, GB/s | +|---- |---- |---- |---- | +|**komihash 4.5**|8.3 |8.7 |23.6 | +|komihash 4.3 |8.6 |9.0 |23.6 | +|komihash 3.6 |8.5 |10.7 |23.6 | +|komihash 2.8 |10.1 |11.4 |23.5 | +|wyhash_final3 |7.9 |8.0 |26.1 | +|XXH3_64 0.8.0 |8.2 |8.2 |30.5 | +|XXH64 0.8.0 |8.8 |10.4 |14.5 | +|prvhash64m 4.1 |12.9 |16.8 |3.5 | + +Notes: `XXH3_64` is unseeded (seeded variant is 1 cycle/h higher). `bulk` is +256000 bytes: this means it is mainly a cache-bound performance, not +reflective of high-load situations. `GB/s` should not be misinterpreted as +`GiB/s`. `cycles/h` means `processor clock ticks per hash value`, including +overhead. Measurement error is approximately 3%. + +### Averages over all measurements (overhead excluded) ### + +|Hash function |0-15b, cycles/h|8-28b, cycles/h| +|---- |---- |---- | +|**komihash 4.5**|**9.5** |**11.4** | +|komihash 4.3 |10.4 |12.1 | +|komihash 3.6 |10.9 |15.4 | +|komihash 2.8 |11.8 |16.7 | +|wyhash_final3 |11.4 |15.9 | +|XXH3_64 0.8.0 |13.7 |18.6 | +|XXH64 0.8.0 |10.9 |15.8 | +|prvhash64m 4.1 |18.8 |24.6 | + +This is the throughput comparison of hash functions on Ryzen 3700X. The used +measurement method actually measures hash function's "latencied throughput", +or sequential hashing, due to the use of the "volatile" variable specifiers +and result accumulation. + +![TP plot](https://github.com/avaneev/komihash/blob/main/hash_comparison.png) + +The following method was used to obtain the `cycles/h` values. Note that this +method measures a "raw" throughput, when processor's branch predictor tunes to +a specific message length and a specific memory address. Practical performance +depends on actual statistics of strings (messages) being hashed, including +memory access patterns. Note that particular hash functions may "over-favor" +specific message lengths. In this respect, `komihash` does not "favor" any +specific length, thus it may be more universal. Throughput aside, hashing +quality is also an important factor as it drives a hash-map's creation and +subsequent accesses. This, and many other synthetic hash function tests should +be taken with a grain of salt. Only an actual use-case can reveal which hash +function is preferrable. + +``` + const uint64_t rc = 1ULL << 26; + const int minl = 8; const int maxl = 28; + volatile uint64_t msg[ 8 ] = { 0 }; + uint64_t v = 0; + + const TClock t1( CSystem :: getClock() ); + + for( int k = minl; k <= maxl; k++ ) + { + volatile size_t msgl = k; + volatile uint64_t sd = k + 1; + + for( uint64_t i = 0; i < rc; i++ ) + { + v ^= komihash( (uint8_t*) &msg, msgl, sd ); +// v ^= wyhash( (uint8_t*) &msg, msgl, sd, _wyp ); +// v ^= XXH3_64bits( (uint8_t*) &msg, msgl ); +// v ^= msg[ 0 ]; // Used to estimate the overhead. + msg[ 0 ]++; + } + } + + printf( "%016llx\n", v ); + printf( "%.1f\n", CSystem :: getClockDiffSec( t1 ) * 4.2e9 / + ( rc * ( maxl - minl + 1 ))); // 4.5 on Xeon, 4.5 on i7700K, 3.5 on M1 +``` + +## Discussion ## + +You may wonder, why `komihash` does not include a quite common `^MsgLen` XOR +instruction at some place in the code? The main reason is that due to the way +`komihash` parses the input message such instruction is not necessary. Another +reason is that for a non-cryptographic hash function such instruction provides +no additional security: while it may seem that such instruction protects from +simple "state XORing" collision attacks, in practice it offers no protection, +if one considers how powerful [SAT solvers](https://github.com/pysathq/pysat) +are: in less than a second they can "forge" a preimage which produces a +required hash value. It is also important to note that in such "fast" hash +functions like `komihash` the input message has complete control over the +state variables. + +Is 128-bit version of this hash function planned? Most probably, no, it is +not. While such version may be reasonable for data structure compatibility +reasons, there is no much practical sense to use 128-bit hashes at a local +level: a reliable 64-bit hash allows one to have 2.1 billion diverse binary +objects (e.g. files in a file system, or entries in a hash-map) without +collisions, on average. On the other hand, on a worldwide scale, having +128-bit hashes is clearly not enough considering the number of existing +digital devices and the number of diverse binary objects (e.g. files, records +in databases) on each of them. + +An opinion on the "bulk" performance of "fast" hash functions: in most +practical situations, when processor's total memory bandwidth is limited to +e.g. 41 GB/s, a "bulk" single-threaded hashing performance on the order of +30 GB/s is excessive considering memory bandwidth has to be spread over +multiple cores. So, practically, such "fast" hash function, working on a +high-load 8-core server, rarely receives more than 8 GB/s of bandwidth. +Another factor worth mentioning is that a server rarely has more than 10 Gb/s +network connectivity, thus further reducing practical hashing performance of +incoming data. The same applies to disk system's throughput, if on-disk data +is not yet in memory. + +## KOMIRAND ## + +The `komirand()` function available in the `komihash.h` file implements a +simple, but reliable, self-starting, and fast (`0.62` cycles/byte) 64-bit +pseudo-random number generator (PRNG) with `2^64` period. It is based on the +same mathematical construct as the `komihash` hash function. `komirand` +passes `PractRand` tests. + +## Other ## + +This function is named the way it is named is to honor +the [Komi Republic](https://en.wikipedia.org/wiki/Komi_Republic) (located in +Russia), native to the author. + +## Test Vectors ## + +Test vectors for the current version of `komihash`, string-hash pairs (note +that the parentheses are not included in the calculation). The `bulk` is a +buffer with increasing 8-bit values; `bulk` hashes are calculated from this +buffer using various lengths. See the `testvec.c` file for details. + +``` + komihash UseSeed = 0x0000000000000000: + "This is a 32-byte tester string." = 0x8e92e061278366d2 + "The cat is out of the bag" = 0xd15723521d3c37b1 + "A 16-byte string" = 0x467caa28ea3da7a6 + "The new string" = 0xf18e67bc90c43233 + "7 bytes" = 0xe72e558f5eaf2554 + bulk(6) = 0xa56469564c2ea0ff + bulk(12) = 0x64c2ad96013f70fe + bulk(20) = 0x7a3888bc95545364 + bulk(31) = 0xc77e02ed4b201b9a + bulk(32) = 0x256d74350303a1ba + bulk(40) = 0x59609c71697bb9df + bulk(47) = 0x36eb9e6a4c2c5e4b + bulk(48) = 0x8dd56c332850baa6 + bulk(56) = 0xcbb722192b353999 + bulk(64) = 0x5cf87bcba93e6a5b + bulk(72) = 0x6c79a1d9474f003f + bulk(80) = 0x88684fa67b351c33 + bulk(112) = 0xdc481a2af36a87dd + bulk(132) = 0xe172275e13a1c938 + bulk(256) = 0xa9d9cde10342d965 + + komihash UseSeed = 0x0123456789abcdef: + "This is a 32-byte tester string." = 0x6455c9cfdd577ebd + "The cat is out of the bag" = 0x5b1da0b43545d196 + "A 16-byte string" = 0x26af914213d0c915 + "The new string" = 0x62d9ca1b73250cb5 + "7 bytes" = 0x2bf17dbb71d92897 + bulk(6) = 0xaceebc32a3c0d9e4 + bulk(12) = 0xec8eb3ef4af380b4 + bulk(20) = 0x07045bd31abba34c + bulk(31) = 0xd5f619fb2e62c4ae + bulk(32) = 0x5a336fd2c4c39abe + bulk(40) = 0x0e870b4623eea8ec + bulk(47) = 0xe552edd6bf419d1d + bulk(48) = 0x37d170ddcb1223e6 + bulk(56) = 0x1cd89e708e5098b6 + bulk(64) = 0x4da1005904c8d804 + bulk(72) = 0xc8b03f196b2551ee + bulk(80) = 0x2d4d58743755344d + bulk(112) = 0x0e77e5c92f929bdd + bulk(132) = 0x0b3b216a1fc3234e + bulk(256) = 0xeb726377f8d072e8 + + komihash UseSeed = 0x0000000000000100: + "This is a 32-byte tester string." = 0x60ed46218532462a + "The cat is out of the bag" = 0xa761280322bb7698 + "A 16-byte string" = 0x11c31ccabaa524f1 + "The new string" = 0x3a43b7f58281c229 + "7 bytes" = 0x3c8a980831b70dc8 + bulk(6) = 0xea606e43d1976ccf + bulk(12) = 0xacbec1886cd23275 + bulk(20) = 0x57c3affd1b71fcdb + bulk(31) = 0x7ef6ba49a3b068c3 + bulk(32) = 0x49dbca62ed5a1ddf + bulk(40) = 0x192848484481e8c0 + bulk(47) = 0x420b43a5edba1bd7 + bulk(48) = 0xd6e8400a9de24ce3 + bulk(56) = 0xbea291b225ff384d + bulk(64) = 0xf237bc1d85f12b52 + bulk(72) = 0x577a4d993f26cd52 + bulk(80) = 0xace499103def982d + bulk(112) = 0x200c46677408d850 + bulk(132) = 0x6b003f62eba47761 + bulk(256) = 0xa8a3bd0ecf908b92 +``` + +``` + komirand Seed1/Seed2 = 0x0000000000000000: + 0xaaaaaaaaaaaaaaaa + 0xfffffffffffffffe + 0x4924924924924910 + 0xbaebaebaebaeba00 + 0x400c62cc4727496b + 0x35a969173e8f925b + 0xdb47f6bae9a247ad + 0x98e0f6cece6711fe + 0x97ffa2397fda534b + 0x11834262360df918 + 0x34e53df5399f2252 + 0xecaeb74a81d648ed + + komirand Seed1/Seed2 = 0x0123456789abcdef: + 0x776ad9718078ca64 + 0x737aa5d5221633d0 + 0x685046cca30f6f44 + 0xfb725cb01b30c1ba + 0xc501cc999ede619f + 0x8427298e525db507 + 0xd9baf3c54781f75e + 0x7f5a4e5b97b37c7b + 0xde8a0afe8e03b8c1 + 0xb6ed3e72b69fc3d6 + 0xa68727902f7628d0 + 0x44162b63af484587 + + komirand Seed1/Seed2 = 0x0000000000000100: + 0xaaaaaaaaaaababaa + 0xfffffffff8fcf8fe + 0xdb6dba1e4dbb1134 + 0xf5b7d3aec37f4cb1 + 0x66a571da7ded7051 + 0x2d59ec9245bf03d9 + 0x5c06a41bd510aed8 + 0xea5e7ea9d2bd07a2 + 0xe395015ddce7756f + 0xc07981aaeaae3b38 + 0x2e120ebfee59a5a2 + 0x9001eee495244dba +``` diff --git a/lib/komihash/hash_comparison.png b/lib/komihash/hash_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..577827761babc930c3f6bcabe43b7e5a5cc3805c GIT binary patch literal 108020 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±WFRnG1af z<99n*QRcUB(U|VUq3Cjdev;N`!C7%jamSAk=BXx!=Sxu%zbzxv&~vcQg=F3${gGW4 zr0^6i#cshFKjZ6JMk7CRm8oDi*9*-Kih}V*^yv{Q+<8Yu9EwT|M<8`{SoT)wp5iaH z#Iyb!4{u#D4_|i?C=n`d$O=F#4~Frg4D~w=0G^3Zr}s9gQ{4$B7m3| zk9J(n1y1HOf`x4eODzb`C#pSex%})5R?YZ5Ygje75(m5Ei*;4Kd?+yyhtm0ZU6DNg z@PRXbCQUsiiyD1 zBN$7QNiLT+-XA|Blvs}Xrw$7V8xxs&!rkNH?tyS7!DVM&=t+sOoUPR$`Lw}D$BiM@ zQzaPa7E(w#@IsUjHb@OmDDWTA+{`dOG;QjSJEy7eSV>FVlyJN*_P_qfIpy>4BR z?z|aF#w20S(sM8AgKc|r@Ck-wdy7sula~*~_m^qU(UJ;zEfXXtnvzV~(A}G7<{Uik z=UY}>uc%}19ynYV10t{a=46l2*V7-Tt(8(4?@G+dQ!k5!GQ^`uKC64`I@oP{CL^Pl z^|xQ2{8L`v(4$5E%I8H?ElwnHli0(8x>%*gfE1kQJ9_sa6^e{mP`20aP=d!NDv!Kk z$VL{XAq^+T{P9iLyFjAAG^n;*m88>OKlZ{$P!tQ;Q{*h@W6%)#zwbO*T939v%K%aT zY9$IMW=67e__hmS+KTKs_xE1$v^*Gpxny#%iHhdvmajwzkjgk9bI!zS2*t`y83uHp)2BBX;0~V4H9SWlzN7c+rFa!o&aMM z%!eB?3^f)_tfY)i_0b2K-CK^?LOwV&&Dgiv44A0?Im;7m_=q4~U&Yw1fHT{6rc}gh zPH2%|5VAisysyR9ktFXph@%x5m>8{)bLf!iNhM4tK`5YCohHY&NUo-E&>-oI$qwhr zqES$?X6ufr>El)eREEF>OWbpN_2YgG9k>hl#Pl2e?8T z{(_J_y#C$t-J;cB1=jQuE9K7a`ghmscmoxg2NE<$9)f)7O?lG^Ya?%oLwfa1Y&0T= z{J(~px|#P+PTQZ5t4D*7dNS#zPL!c-y1^Gocb+sq*OVzLFE&>Lwgjb(Q}++Go`u#P z;Wm7y&Jp}tn+1YSP9~ShiO_nU(_Z6a9ovGIFn zN@!+6zxZR=A9$ZeERCo=i+q~U{h@w1-W3Hkn(-x}$e++mifw!1r`19;5TTz??843B z)?MNF)Re`k38lipCS%%cD95PL#S*h$!tb&CNY;s&ln}n|W?q+i$L(*0uyKp-zS~MQL zbSY9?x-5)B-o9|$OUjB>_qm7~tl(gCW(eSJgd#p8|(BU;Mf%-&ykGm@h^ji z_Ftpj0nXS-w9Z<#W&%cw5FY|0K@?f}kq)nYDmJafE?f}48A8TRE$7<$Y+?Sc@MCP) zX-Py?Dg1bk4-Z+cN`?ItN?<^jl+id#BNCH2d(-9 z>$FI77ufpiePpKwk#uh|Pl^0A{-e}2`^udd-sVa->+4fCRh zXpN(anhhlsb!iGfaaJT!^>6=TMC}pMKh#1oW!O}Jx0~X9owHarHZjpbLFhd-jfDu? z**jjqQE^=V?@7Z~g3FkJLX{|PjwcvRiPBYnG+yiuUir}_o9P~D^ke*AN~>lZ|rpVt>Nxi{s!TqP&2e2(%!!9q$62~V???KaA* zLXs>Dk9^~Gug6V<4hzkfA63DD2-}M&nLN>Ebl-RX3=he5)~Rw%#^y$sBdB@ic@vm@ z#%1mid_$jgrcl{Cz>-IuVfs@A-Pp>5A}=m&0-OhB~s zJR{R!)z472X>nXM$VO_#eQ)6dblAw~K0?d$X*lqs|+p~;KS#) zL>>7XjN{)-Jp@>%ft3vNb|8-*SBr zQQvm4-NM*0c#An$D6EYSW@Zf#frL!kYE~p zf5J0nzg=m&6gAj#Jyx* zdos=I(X4hW$j3=e-iZ=9o})h3tKN{2kr6rSPGUk>==RD^Wn+sqoa<9It9s(HO{H^j z7L+KkZlYCe*l_C!-*hM9QVCK>0_HlK)&xSolN(|=>bWsAYwcy26jU}WS znxQre&=$Q?%Z02~aO88DNGQiy!mU_*O{=YLa@tqxD)!k^v9!itJVmaNTwL=D+to@u$AjjnvtpDVNpK7J?kLxiG*j0=f%CanB&oAF7+r+}E*+Xz za^}BsCBGZ^I4{=gPy@oS`1}}Xfn`Cz<0jR65;1d**R{vkBUkm!#0RW zT0$E`S#P*2s>{suPE9fD%A66Sk^u&8Ir(+Ex*~oq-R>*z>aJ>}+#aN>6 z(xliRMzf9QA#@x{(SzAOjAKhnhu8PZHe7+C0YY|+_P=S-mOe$z1@`%pL52Q+xDlz( z)f#A~#8alEN+H{=F(xe1d`f&fAG%rQZ$_^j8<(9%!2eDA@4XmJ8=?l`)iO$O!Vl9sf{;~eT}W>+cHWbU&_(P6X-Kk3%tH1|0`GgBen)4XTt@*S$t%noEN zSss7y-85P>;UrOK{aGCs^3k)oaxY`KfaJJJ+7%8_4n@tOx3$`3uowauU@18#Fn8p&`mmB&}z@(Iyi6fXyaED)5;kB=*B zX(9c$xr~UIWMEdG#u|u*{A>xa-?Ten;`x~*f3t8e#dUTg`}f7xwJZ0|bL~xVHXLM) zSL5nvYLi&# z_^!O#su4>O@Zt%S)6o$wWU+n}5SK2R7H$1Q3z?~)SXn_{Y{;lU2`!u7Rx8Qas(09( zOtLj`5h12Xl8Fqu^ZxZl<1EeobJ-ws$6>&TQIy*LC00QOce9EeC89}D;q*td8C%05 zM0OQ8*wW)kgdnA0jkJNBujmbRjz!@SYR^PAH#m`ES^PUbQABu3Y}|=e8re=x*zHJzVdzt&0nZrqnVC?!LX&zOZ!|ZXH*UK#WIU z@^+u27eX|sEq%Oq<}}PYDbCRRCQaL)*SnL2d|O|{L>IKYX6F%zWJY?c+0D|%`wtf zd^CwA0E3c_0bna_UPqQN88`d~`Z#zJCe}L=!+VzF-LalF_?XXGKcJILQodQxnTB!y zp`kdaED?faJ_&I1)80E=C7q~o!>Ht^XuVPfTCpq0R6;{Xg}#UsEzrGld^6A+mm&`S zYV@W*EX34ciMKt?A^6@Hl)YGN?57%yFWLvDa&L6da@`(SD9v}+wjZsDjRv%h26Z5e zllrx#4NE%k zI!4a>un) zkBqx_vz??}Y z{09(uKpfqzj6tsBQIf$E2kI8jI|K=yX-4=Gl-NkYozYT(i5q8b0L9O@XdaO(m@HDG zkCqb40YH2)tqd9F>8%%_y#$Z$A0DCxcLMMRkPUEX6t;E{vROK77(q97_OaA-VO0R10|+X?H)ZhARv|>M^~9o2Q+lnJ+9EH0)G>rf{hthzyS)=?~&EH1wD zYAI4JP)OHS@?h~7vWq+G*C70(Co=m>%EfSE79!-({(;~O<94^9tdk8lzq3Cc{z;-% z*x2|gYY!>>hW__J3BCRzSw%Q&pP$4N_^F}G2Z@s)S8Rz@Xwym0v-oQ&IEBuPI9QL*RztDVf@WuCy=EEX}k%J;f}?Tct4^&r%$uaE66&tAeDFj z2(o}pc{X*tX$k;WH|H2Qn4ioQraQ6-w&O`lFaaETH$IY3Kuijm++$>502B{U@T{?m z0{hh{Sg~cIE#7a3X3dV=$>u7_^%Wth{|a&qWsX^hHGQp*U!K3>9Z>Y;RC1quy7z-r zXwhM3M*I3d{$wqFbrh$rKee2>;HQ8j=B%u4;xcBOzUlRDo|UfN_4nvzdqpOF)!Prl zWy_oa!-$pD_92LfZ@mi)A+&+>W$1bni9i<6V^8;B+7oN0bmzz_la_$^LB**p0zZzW#he1*$ID>QLE)@%)(@CeoEO$KIRlY@GSLStH6cq zus6uWbxBaVV%3N_KcKX*D>-0k`V_!I`_U@wJLSfT)$vum>gPx^JP7w_s>g}IME{ISQR`u!qZX^%eq2#Vg!j3~)VUqls)`;{Tvi8V6__8M1a{z+>)M3EtazF02-6ME zv!l;i-ygDqom6smrbcK*qHVv1Q{SHX=x%Hkr-x3)K(?$Z1fu2}Q!}Tu-R_b6q9OOK z=@oS3@Mf5{ry!V)I(d&DQiw$##dJkYF}`;yy)Il^=n<+>AyRWBqywGnoh$?WM++ln zla{QP!a|7>GR&BTtT0dwwwv3qj?wedI9ciIL#2=!wZ^#LD=5 z)?l0=dsUAsP90GC+DOTGVkw%_=_2=x1QM9+SNta5m|CYm7ebHWdzBv$AE3Lz)cX6) z)YDgC9Zmgh3?q%pi3C`Hx>TI9f^qqM&1AXuMTQJVcB-O36F{mGAiH9Hab2^}8m3O7 zm6OeE#(8`#eq(6K+|A5#+z^&V#JMH6uB~{VylU@DNJ?i-SfhleKN8vWdkHQy) z9=*N|Es}V%MSHU$lZxt+*GK^YtaJL||5EQmErsGlqN(5yzer(enS@Wza(ZRTJFv3& zVg2EFzh!vZlk<1eqw0)wZg($Czmh_T z3L0;`Q2pkgN&k+i7K(tVxNHPi=nk|E?fCX>MB;~OT z_PPlLL;pbIhv8TZmsa|RC%lYD`Q*?YLUYYoY^0E=qYE+!n24~F#4rqK%~Nm+$5JDN zUfh&ob#n_2SeGmcr3mJ_&F#>%pE82r;=Ds=QOL9g{jVv1Kf$oD!N->3#^dGxf%pxW z`})^3b?2{OeCT5gz^pIOriLi%h>bHIxS5wyGgnWLO07VU{aG=UTv?_U))FQxEiaMe z*G+MsZ)X0H#OP-Rl|xI#-Dp>>mfir^lgaa^Lk9m4zN+!3$*7y_l!PMnc3D9#>Q^g< zAE1k_(^&<*qKnb9xwCkLsnVQ#g^cIbBabEBq&}oNEe56=N`&oMXhjmL>&2TO1%?qn zK!YuJ$?7)&WIXD~`Odm<#?3Dq4$3xrnFj9$^`5F6cNIkXK+crQa;9V{S(GMq@s7Z$ zG#IsOrh~W9_uBJ~m_J_kN+aeSE+6|fP0X5`X-rQ+bcuATTBS-%3FdS%li4*BB}+_r z13DxZ2Ah`^KGnb2CcCZ2&1>JH*5rM-FOH%x`Yr@N^Dc~V0d#NnS4iWSAyw#kq{=8_ zbWFkWWVuIVOzn;_F@eAFW7@UOb02m9 z59M$-UZ$uAGmPPWZMt!Cu5tbxFX@04W-2@!80;w$dB#K=@%ZP@pGn=fqV2ecM3kejDT!p^M3I!P$BRSjQkv^wq@`*?`Q3y@%h4vE-S7fwjGM>GMtVa&wd%1rM`NA z6fw(rX5J$v4!}bA*bShHtn+pDIAW`cm4}hqzIbVeS<5Qi7*UcJ;6(oxejn686r&oe zol?>l2;rnvqmh;H&m=yf43pr%U^$ftC`ntzBll=>Fy4;eRs3P4pqQcj{@^EarePmO ze^rvjwQa6`6eYPVte?SPpjLhXYPY(BB96T8+dPcr>U7LL`grx058W!Y^;i-->gSa z<*0j0=KRYcwWW8ZAx-kWNRLqF65#ug)0#HJw5%T{M@;YhC8k)Z_4CtC$9O@8l1!Qp z?>L-a_hQKY06p66=QjLkso)5WS+fy)!c|?(9u;MZG?m|(uq>TzPr34N^G9^o7Gz>E zA(Uu#p%(L1VtC>)CRDK@(E15TGS}|}h_1*+mWM}b)7okoRYz(4$=)xsp;P_NNOI@iVL7XGLy2|xl)y3>xa4?|NxjOatu}_hHh_Cf-DR}jh z(;!fA`zee)a$Kjn{?>?*>YCzJ^ActbFmD8s7;NX|gg&^l+ z)o42J55M|JTczz$v#Nx(ia}>eEvLSV2%(LqLKafT6IW(yfbx^+tb0#=upp9T@hK&L z!|tvJ`Q%o_<9oMWz-z`XJ=TmgxK{{@l)Nfoj@!(6T zqG%>S%&tGd9&ptuvH0fW+3S#GZXp_d_*nigljY{U@ZJNY$w#8pBULmkBD8PC$Xy0p z{+^v}LX+D3mBIgUR)j)?1U|}X!A<|R>^^Z8_WQ7S zd$!usxt&CSe~Lv>J!PH9zk+Z0-NCnQ0JbUhOe zm8{kpps8}y?i+pvsR!&ml+r+2DBnUwCb-@S)Oul}BKIU^)7B@|2eF6rn~$O;G?dZA zN|(=~_?hhwro}!}1NwTA+J2h_tx*)M?2j)GS)bS*^N6c`?nkfHHl8NUa-BNQd%6mW zrWFc@G(YkL@ZdQv|NZtx^{M{;(y_t}ArCu`EiVw$5Z{z1HafGlMV&5EU7NdT5br?A zs(R3A0>hRz^fOaD7j^M%<5|vy)s>Bv@W=5Z}(?2lV9n*>L;W;?zp%rea)+9&`lq^eLc44U#-Vmbe35H4J zfC{gCE%W`HPGz2)I8!!)!75OYP$!O*C;Vc?=|FQ?MFkrb9-%RguVP}%(UNLb29Trw zth6bDh#eIkMW=`4gM)E7#SkZ%WnrV9$Zpkg>!02Dxl3jJ^FPm1iu{AmD}j~bF=}5H z=e=fN6XdC?_ITC4avou9F2#4%I(3G18-iLI@N#Kwebg^DRSG(jUpB&2DCbTM!hanh ze1Adt>p`M>3$ANISmIKPzX!6|_=L+d14>+! zaSyUbT!z=JiiO1lIFfO|!4xXfM-FW`+IUA`mV%6NNQz6->Zsk-)qM&Rp}J7K zhbHu4cNLR$@D5vehW!_7|4iX;TYcD?8Uou!%xK!xv@w}JRvW%mem4+E-yL4 zv@uoWKM-X_^$=4+h6ndn%wCF_6iO&hbbw9^vV^{6$DKV++wi_=-T$?<)+>noq}yJ{ z1Q<4~B*ASQd`pl6C^qta*d&#o1gxtU0c(qbv|6XV30tqtH<5hjeN1&rhWI^jueDhm zcjRm`nVa-`^ylS(g^4&#z8fGZ~>w z2bS&AXp)z&WbuP-BXjMciwM5ax6XB1res{?AU@sl!IP)m&%>mL>?F-MU14X)mT2bD z|6D92&`p)>X{Oj%V8jUicog^MpTlLSkn^f;$M(u)XduVEnqYntMP$>LlJ*z2I*VJW zZRC4r2tZ9N92DaWRyx`q@ozrG&+)%~87C>sVLF5bROA4DhE@zH5OdPGcH@KOE2Q0x ziDK0J{(bZ4lQ{TZ6RCZYb`X2Mf$MQs{bZSA$Cn2t!shqG=!|Cd-lAeqoB< zzZn#!-Lg6E?DuaAO4_E`pVnNQm(LcKpBH#X3VIk5{>kdIST*+7UeDLcBi)YU#hNPE zrEnTwqdJwkMAWWjgbciaY$;kbw;n0Hqof+In3bWCW1@wrHSim_-DFbjpv{Xi-bb$z zLtuB_KgHC7i?I7PNOGx0_^qhV2G5@XEi7B8E9w;@?AM%Vf2zWK3p~7L7#w>FSV4ig zB!zI{?5?W0*yn}E(~I#`MGtPwK>nkZ%-0DfGF~}k>`3ugNxK%0N8y`ciXSeFO;cU+ zO&mJQnRc}_yly@9jO;-lAOZzMC?h-bi5o1N9=YTJJGsQEI-#}!8wxdE?w_KhrzRx9 ziG9d>g)nbpXr!R%mB&Qj-r5J3NTFDLcMGewCXvW%XF+{=K_?y(oi9g5(^`4+ExH;2 zN#I2Jn==-u&i^cnxc-*t#uwoiE9TdK)6sg&i=a&g#Aeit| zE(##8_7h&&MelWV9qI42p$%6@B*ywldDNnwMYun>oQSk$QeDzi7lx>8}&wFrUO z8W7qsHSpS^ypJ@mBM&hzjF~Mw%??J*IChi`uy}<#cxy+cv}5GgsOumb@Ztd?1dvq- z@8W1hG1;|^LJCSwo>yNbe(Sa2H>tgJp8ERZk+uD4OgfxZB)6yMbU$ssPo?mPp>)j) zTPHXTBUX8pEIrn05E5-arXqZOB`rc%CBoxIEh=5rFy#1+>)rrr7*2?YgxvDuXJVm3 zUd_{*`k(4=t8MrTDI*0~UG3b)IEHJFMB=`sf0qFmc}@-m5qfavx*YW+JENq(l1yxW z?n{ypx?OpwqGh!{(1ABs&&P5gDOx!4_q@*$l8Q6Gy~5vmyEdx%o`1inuDJ=h369>4 zBat}^212Vn!a|l?ao$GK=2ysb)6n2>CF}T7C`h)~z(S0M$AgjUTUXUZH5KKaeT%iPqDYzF%~KRm06bqs(XS-Q85rU_YzngTf$#{0lqdG zX#y2rCX&e83pQ3n#Lf%!WUP5=jG;Cd0xa`Gk6`P?7)k((z2}(9;6E|cx+h#N3k8^*kR1zY z5LI&Wt7wbeUmOp}yvNM6R266<@rS5-F_03y)|QeIuZJW|Lo;l8gKMVKaMA4_5GA*- z79_i@^WsFhcDA7+kJ$LMdFbyLW4Ry2=;ma`(VXFg5DS0)3&yYQ4h6|GjN~@n$y)0P zv<3=Ko4JbhP7Fa*_yCmG%#2L@`doYZuc1<1~gQ$1ju0vp1(?XJprV! z179{z1r!=aOHIwr*45Mur(S=6480HF?#=!MuX+sajNUU8HH>0F!yDR(aJn=PH^2^$ zxpB%in2B!t(E>l5cB=vUE%q=yT4ylhU=<@kAPK&W&&<5~-fdW!#5f3KS`PlfLqjDF z)>usD_w@7t+{kxdHDhC)$l(Ah_!yTC_{gt0@#`9dRyZmSqp>Z27j!OrdR%K$_I8|l zWD3~#oWdl3#!*=e#1-X8{D5Z<&CPN{`kAWaLDvRvU@9~d{FSP~{Fc(slj2ovkpDbc z9JhA`>c-_)nFlHVJj2#J;Q?kv)bIEsw;bjvA9Zw^T~Bo7CxQJWu^ORvh5)@1YwK?Y zKw$3TR^a(|G?MT=^73(%h%$IA=ypHUa!{QWVw}J6`)(1b$lUQ>TjI*Rn4IBD(daIa zhwy3b-Lwbdc?cOxgAkA_S)RqvtfO~Zl=vNq;-J}=Q< z_d3B#_$_so_l*BPB`i&sYSSmX@a8ZB)W8b4p9BOvl(u3U$Pi=m^l&jpVS7xifc+)C zymfM1?IJwG74;x44<#FiBA{;zi%+9rwU;~$*f@NnUp;r4twC6 zcr;U}aL!PIp!O}mYf^&-6mIQ`5TydrKvdmzGDyfid6wd7@GK%6^1*UeI9RmMF z>q#az-h>YOLe~O_&<>QQ8)DFHR^PSml$g+bl#>65ivD?(@}2fYD{AA==JIqrLxc<$ z?j`yqLMH7_kX@YMdj4*r(uI?a{?6VbbP_{EldVGqEA?5ysZuOB?XPhtI`4SUHU-_@o4D>8NGYdCt^1HS z-H_V%sSbOr6q6<4k%^&e9c(C2knT)F8Q7Pj7$r%9p^q7pssvHll<)VgC|$Q6tQ^uum3;)C8|b3()Q3KllPI@r?p8MGzrR2!iLzb>jc~0haNY49qMBV27OeKHmdDzJ=Om!0D(S z75MxY?ZtdCiI!27E!+UVr*r)jjcZ8>D3$!pi3HgSt!h&c_7vI0{5ROOzs7blFh=1j z3)9mzASXlm3_86_gyVm3*aCcRJwQ7KzmMk@9NEzSzsnw=THEV`o4?I%X<4aajO^`v z{;Z`{4=U-QEy)sCUgnSNCXfwRQc7o*4&eH!3~0=W4Dm8&k?@yR=GNB3#%v}$lt4kq%QXx2!+`*LAWCpH z2S^TKi%jhO9^Hi*o0<8jrWOc2gbD%LUXsfi|2-w*w~jS%K{_L=t-fdz6O%~(t2sb- zY61fUq^Apj=)5~c@4!;|&(v2iaX=k07TrjdU zAj(Cq@LwPTE6MPmWtxF0@L&`Lnjw+B6yzfRvwf$|_-|QVhUB0>&M^LkNArVi*2|Fs zcEuDsm=FlxIfbhdrZU+J{zS(83O{?I?E@n`e3?7y{>Sjj_I-wWSqBEXfC*;@4YXSG zbm+^|eRWa9*|b41o;i}i_k4-jR_6R4*S7gA=<_aF7Rub<;P3x9c2>2e5N$vXkbE`a zUU>(?&*_t1XQ5VT8wqB?pa!4D6RG`j3=ImtiYNLsE?Q{z_L`_;lVpMS*$%A&`umd@ zMg{Z-%DnZly<7eBy3*O?`c`GXj`3aIJUf#h!HT8D`Zi?8o7mdqVJnwE5-R>iT(b@7 zdSNj?N;|m&Ne;A>HfqydR8JAOB3o7=2S6hP~fVbnX+Bq&Rm!T9?rKs>oZK%OWs;K=F68a+2iIc_(RW9 z9s;#)d@TUn0=Xm#3Dg^x%?z8>7H^D)e(!BWT(*^ds{1dpqNS%Fc<%G?=|y}C2rsFe*4c48E7`pt$F>Q~%TVH#pmWyy1!<`k|*#5zs~k2M19|_46&tKG&52!8lyx{wnP?$YP~YZ_0biTIC+ba;2U-On zLdmCcLIFF3Nf?xsE|>&yqGqFuH4v2m+8UrdwsAQ~d(qMlwCn*YYnCY=`yh*;soQ7U zW<2B|2a+YQia;38<#IU2gE(JlBnhC3(OpMwq99Zj5h;Kc>`(uyvzninn*&%= z*!S4uwNN`uXetl#;)trSR5`pmCd`W-FRI|5dtZaLTUwV{$`!b@B$m+&o}Uh~~dna<+) zxc$Fr4M*baQ53-P(E}P!<-U&xaT6f$TC{Clt}2nEc3iUWUG_LAb>|5pwY9cxzCUgR zIa4ysLZE9%PhZ7o3ET?Tl3l>)?weD~i^SH4?RX8{WWZnAPSkt)uJ>RFgs=jm#J|7N zvG2yaB?UQtty-&O#=-dbc)&hRVmBMf%pdng$Lg8ej1=_QO>@1X>8RJe1%64AJR1BN zmI%Nyegu>HaAP8ZA^;TTKWnmjcPi;$E(V|PW?P>&NuSqp`ob-J#^k)$NBp-_v%47YTqcJO^&!s*OzOq%sNi;-sv8FGP5OShtVW5ZJ&?*w z2l|xm@N?j#TLnxjAis?xvI0^OV4Pzo*OEEoFB9!^yA8wX4y4CgZ-;I9NHFq#19Dz= zHaSV;3l~}MabM#?EoqfAUWWg2OqAF4Si8yX42u~ZoXatOiOTLxi~ptiU2Wc6Rp+T5!apw;?&*6c0rGeVXj1` z&pQ{lEssaGtq3O3<+TwefajI6cB{V_n6WXBf| z>`K1dtyl()vKLC_S2&b>xnzgGCtl*pH@t$Fh~OERfvVI%939P1J7~Yv$75G;otV{= zQDe4Q(0dK+N{pOl1MWEZl@VfImlECPg(}7;iOqpH@Tv$pb-nb*^ND+03V%_~ZCZVP zx^7iW;nMeAFHRp7#E9JU9*!_Q1lKb{5){$w%e!0^541hpfenWa7;o`V{ip$itqK|+3y zOV^f*v{@kh`=XQqas{_wd7nUUvz^IDsG3&wUmpRj{i5DzL?BtA;3D{W%Z!tY3%toe zv7m0g#9+VyxC2wQS!ucjl2FNDivup>eF>+ark>vO{;zT$V7wWe)}MINo?b58eBuoh zQlAga1R3b)Uh*#&t!qBljjKQ?)O#I8PqW$MAJAb-1WE<^?O)A+mUK};dJ4a%i;rlT z^83cW})Kb1ndrKYg(FKAH+M0CMYhxcyk z-AyEtcmbC|>UG*H_++2{#WDJ}5v;Fc#ywHqB^a(fPg?8UbUEl}c2L%+3$`NIk^i`A z-S@Pwz3-3eNPQp93er8ktTeg548_l0!`<;^1M_=cZJCZfP>3so$~wRSeS(^qm;l|W zY*w6KSiE=|+LgdHffIfiEUe?s&wC zUI&mqw4GePICX8LzvT;Hu}Q&d1GA|Djt(rMj$QkU#;y-oswW`ZHJr>|AZXtaiT}-h zC)o^4Yn~zyURU(Jo5Z4!VAO3&(tEG(DxNbA{xUg#-qH^oC3uDu^EH+l;^J_ADJdz_ zzcf}s?>$h&0tBF6$f0J#DOA!bBuIA)mgS&uOaOQr5U>Cu{5znT4Pwv-AilB${^CDb z*IMM2MS!=zgr}e>T%N@O7-z3!&EiqZ%RGXo0YWVmtx!F-e;w*=>bDa>NJE1SCPM3v zodF1I-@+UMZggo;Q6=N|e<6DX#a|p9*);^tudjfsx{U^|!F1&3ht;R6I>5VsX*`*z z=i~nLaQi6Fc3bEPkn`8?biLMtUPHUB`6G;QZ-&#U=6eA<)oby(1va#_3fT;}dTC_} zwuJY*Nus)j#;ScUG2nCFjYs@|sKV0HN3f+l z!4xU} zemtpO0Efd*!Ivfv89;V-)-t75za6@DRS@L8RTcT;U#F2ya>&ZaFavp6NfP%hu$*28 zrFEdgYl9v*n?Y1nZ(z@&9qkL2SQlKtjc;XYs;d!PJrA6#QT%0L*><0`LF5Ib82}p@ zN-mZ22oUpkOpRxJ%}2g{`}R^zmdZKI0_yzMFK%mXR|R|?ZZ5#702ZR}BJS4F%F3$g zZvWTrXofFXlcHh|u!1~95g-Tv%G=?b`lxf$4>5!tFaP$MEgm_iZ+Ya?NzgqM1On`kT6sX4Jz63=etJZH^)hgU^ zvb3_&V%(3-?B)P-cy~|^szCwg`jOwD>qoBapn zDVJaZ!cJaZev;8_@$V48zBU2g8k7+Z3ASaA7Y=T35W@I@d!?ihfgsrY-z)=1$pwXhDrS-vV17FUh* zmJOJpgMTlrGcg1oPHSd$7nhd2KzHCJ;2S}dj&J7&)HJSbeeXYmBGK#2`ugMozM)l} zhqTdWP@M?eAC@2JPA$t^|01y6cRvDF4{z^BKa7RiBXBiP68PkgK#~N)0$}dW!|!JqKi4vX zmd1OmFMVKv%>M{T(txfu4kr(wta4#t068SL#Dego5~Se3v8V8p8>2Py_rIQ17D2ZxG_M^d?f zR=hj-)~&Uge|}tjUIxzUR&RLqVTX$pxH!;%ID7X~iUIyhqf+>|%mkBZ;5=q#0OwzM z*4Za3o3@G(<4*`T$U_xm_`K+sbOa)SEdb7B5TcWSxh7}ExNA&cSo3Mk@Z|>wmc4zY zMM_vU=<)-BDPH`4#l87E)o&Lz97^VSN@hYx=8&nKnIaTP=1i$jijaBBkVry>c1WU( z6(zHfj44B9h>(b)LWcL;-}`z0gXcINKio&h_b&Uhug`U@Yn{VdOKrvLwi_m_JV#$b zBpo$4q_{}30f@}hzvXKA2M@P}>x{-pKN%=-YP?kY?{il66R<0YZ!7Jm5>P^n%j7!$ z{%6mgkq=MR_<8|-75f&eW5>v8^Zt<)rvDaWUkb~8Pum}ddK{hyy&C?sj;1MRsULj5 zyz%YalR2Ujx`#==QNttxWQyK{Wv5nteMPsvbL987LH9Kz03qYdVA)r=Kqem4@FA@- zP{?@efTRM^38!%Ig}-!YWfg_WJ&n<0ACS{T8{GI@9k__!NL4rflZV*j;P90iP-t4M zPNx0FsX?VfAD^vQ2i385o<3n`x0bgz_WAuZ^@o~fdhwt z)S0FEaw`AQaG*qJ#LE6Xd`#y)zfev!_P=le-)OOO8Ut2c~t8^_vSJzXs~TROhIQI0_B?#(l)U2fj2eYKbv|7A#EIrB`#sc)|?C5cE< zN=bQ@ki>+&nwkWzc_f$}`qkGY#>?&^Q>uGS{B@jsoUy!=9z~wv5e`m@Z<(h&U)KG} z91)yStEFuyx&NSg-w5uyqQ*~Empac(Wd(I+9?!_gaPP`WZU4GB*^x8+`D$F;P%SRU z`Bw(dnp(g9dV0E_u*X~|r43#H?=xovwSo-e!;);VSc{*nKS%5cgC|QC@6?@7QgN6e4ujk0R0_68oat=k8PVBLFd)u zD8#XNojG$#A*1B{TFE1}E!*60^be-5@B3{ZL z>6D(9*8k!032^Gs*Xa9XcJ91`m$6Giq88J5>7pq=W#P`Lt<`R(%`z8251_TRHDt2z zeZZ2%*WxsJ1ya$&BRP_}k1Yxq7#R)F*Wpw<7Y1;=d1I`tt?lma9%b(7xqI!N8-QbU zbTlT6YY3d1e4CMU#NIxONTiNFzvZ5}fm+d+*N5D?gR_S2}3Do#dI)7FjK85sq6d3wRyYHIb_xVWC3 zYQF`>C#>1|=gJz|hlob$a8k!B>3ukR_N<-k^A|6MIy-+Ln2T~WMMO~A)L8Bh4nMj@ zX(vl^e*P4?(Ql)qXy!36txHZ$9vmFRoE5BvxPZzXplD6UG=#yf&Q7h6)e3ZNDlJWJ zbM3AZ&Hp0Tf=md4<+&P2wE~AnV7G7RkJG6^y8ib7}S=Byvv zz8@T$0TFz6+GV@wti zHAsx2rnZ02(JQbuQceG|&r)1Asq&$go}M1orce4xK$)%x1~Q}?=jjHeqL)Z%`jFW* z!*=J=R@*>pYwql>OBXKW%Bt|a_%<_Re8nMd&x}1wq!!7C;l&49?&itKNs4&JPz=nK z+Or4KH5L~aBPV+X2MZ1_Y$H5;`SNAI>^Tz?eEsX0nfy=hgDJ!FpK*4kEMBXQk*>R+ zGH`I$ga%Djy+SWc)9-!vF6GW0X>=;m)I8(u%|gHz!6=jk**?#vg;NBUiE2l6bw zefgr`_*{6Of+4cCPXhzf-@os7wEdNenH(rdxpe6g4#f=7BzM=@$g}6Xy=NyTmh6<7 zFyf}ErDgB>qF$E4MI3r3e(0k0T3TA%K%YN{^yV5-CI0rSs?N*X_Q$u$**7>i7}myX*A4{) zsQNPq%eU;@xwFyG*4#Yl_U%V`dCEw1gbxxKmfxVBfQJ|z6;-E8lkC}KZjyNpN8R3j z_$sR??vOF{O6$gXibA72i?37UK|J_UQQbfmi19dgEeShv9*EdmTTji;7Z(&jNR+j! zL~bA=BJ$A1b<_+I0AL4Cjff(i(){}MvxzV)Vd$ z(9J+{jyw+#Ag8Bk{(YUP_B(z0w4a|}NQmb0lN~%f2?Cl!U0r4!#1PzqXjz7xP-rCu zS=!pVAHFZDg8a!_si~i9LeNaC{OME9M!Eg_Ujj*CmolW^;#rKnXTY-vLi&QgKTbto z#=ka8hLkom{=&VASTVy;jYHzd5+SXSAtNE-jtgbRTLN3xugXruHL}f>i-TieV1Q@m z&e}>*F-gYIVKv5w+3yPatRBd*HR*lnE~I$JmRvj`!62!-c3rqLAzvs8HW3_RO$`ld z?}&*TjhQ%Bh%30^eiSn-zZ>}5ac5t)W{`@S+Kxs!n>yO)hV_4ck^S9r_8@+5xh^afU*k{L}Tn7}`HTlIF?h{oyZJZx-)%yS6g)(#>5 zvjg%aBY53Ep=9~``hwcVd07wiWjp-?0Eu7K=N|fWy?*V6)hs9|09l@5D8})IZez(R z0YL#<@b2Baz`+^;3!}KPaJd4gArtPqe8Zxk`r@3eo11v<9!beoh!$;aXrWdF>CE4M zuJ~nx;(0&68!0LOwedSYKm6*1jZJz+#&OKZ!4Y?N?;m+Yqx%zW+M=SOoEnKvJjcw< zOOSGbO3BU5Mc+0==D+TQuy|;-t;wRJL6B*+0Mf8$Ccb{fq%mnBp)hA<{U#5%!YW_B zZ2$TT3yDCB56R2T#R0y?s~jh?hv*a-7`S`)ZX^XXBt&voH@6p+l^k4L_BFwQNbA?D zyx1wCg8u&S_w^n78GxpQ%eX-v7Zv&NY2)sVjin99x3pS<`T|BT5b)~HpNoo$iipAk zojLaX4boGSlUW*p3j6l`MX;Qb^bwTZo zg|UN7G3;B=rSX(?t?;m)m*X&Bq-b(E-o(K-ZCj|*x&p= zw^OH-_w5@&J3BNiYm8yeH#Z$q_kIsHb0;tF?K^kyzt5gOZ)tA+xe^>28ah)X&#*sW z!O`2h2s;DIhfCI?Kt@usGT^7Pj?R|or(1e)1J4bVMm9S`aXEhCM7d27ZVn{ks_N=U z2`!dyq_hN6(?)fVHO3&rewZT>W?xQC0EI2Rckelztv({1s`=>ikt-&L4xK8sDPa|5 zi~Tb{!Yr_dE}cnyBwRvQU*X&Wu+>r($d;vKibF~GclnrEjLWoP*>+| z`3W`;$nSMi69)%J@Sj0@%9>+hBMz@Uf0Kmyu6vMN?Poj4m+s>Uq z;8l=WFFhyGh<}-wm_W9RJQBan180zef&!$Z?C#xzz$%r#!XJ&2~=gDvt=HxW?^>G}TaW~HU1xk#8T2xgP=V0d_-$Cz-nBRuPW20q}l)dK< z_6~B2e6#Gt@c?&s3EZR#85RXrk{nFaHQ1MWx<+;{F6YGxosk~+{SiGGj~)Ba6wAIl?(_Ti+xAD&kgBVz+fpPVcShCLhQiL=%s|(F zT;>B>E;cxqB4Vc8xPeQop`igm?|x$ZU5f&~{TFAkh&eeqn9Ri-u7`33iqzZAbXzYy z1Y03^Wtl>_0{95A5b*C)W1}ceDar&taY$A|%mJGrz{={2-m-vIVq#*h_zpBAw5~@# zhG(_ErTa#az$38r7dvF9rlLzK)A{p@=wMntIEy$*zE8A054uBXXzl3uj6oSl!E9uP z@sbP#L;5~_sse_+Bh2CLlp&Rb6ER>f%~+V7ZjYAAit-px5hB>8ygx1%)k08Nsv7%^&V_h z&E?--KFdOt5HzCcxv_g5{?0|ACQX^p&RD$pLx&inxoL9u?A~o;VnW4vOA-w*-9S$~ zf4*-fv{#tgjGsTVwY3$>-1PKx46`6wVczO+V^*D1%y^4|jn>DG$vV_jLpy-$3)-Hm6f+RmoB5B=Jrggx12sFGZ#4V3sE|OeS#psY7kP8a!bw-n$BgM zZ(Lnk!OQ4LN|qYxj%Izj9dtmK5&1^-#_D%K5Cps|oDWzrEKi>7`0BS?WUtT}wDAO8 z3%2id!j5uuaffKV4yJJjoLlPZ9F{_35$IY|2HP`k2m^inUjZ6Ej#tL7?E`LWqOdRr zJIBf@kEv)lRR^pD?h?kw#tyJPp~JOJqKcnPqM>LiNOKi1WSEsRv)e9>&} zYlfC}RFcC-t`HYS@>2u{U6BLpr+cFe1mc^2Ei9lB>UVC3U?8tj5WILQH&@q(?_j{m zd-m)PXbYSoZKsAPyz^qas$aN>S#F#B+zMl+hX*Ku?c$e_zA`g2vusnfwh-ltcd`@} z6Vnw>Ig~C(@#K8fCyE?RG@hx;xYYOX2pp7G|6w6x!p!0-98JrfKE;FK0vJ_uJ$Fu! zi|bZ$@_}TopqX&|nc5mj0wMz|0kIK`bICuW9z&=;by$j5>b;A^Sh&$+hGsg8k(>6W3`ge6PX85bH7wC|=S-3Iz_kANAO zcNwOWn2?C+E2QrQYNL(QVqEdS$^DN{a3jv|*s%iBC#+>SO9HbZ94=bs_VzXKOo5X? z)Snxv9YIRnNM!tPTKD<7y!P`yyPhdkTinw|sxmP-iG6fnK)4?8Fp3~N6Y6-hz>1fb z7vIL`8QV%R&H>WWm=TV42idgtsYRrwrxbR?G!BA*!CBK#F!XP1;>%ti-sz~%;z*;lKxHvj) zIc$SY%>`BsvnCWga;yX&59!hyN$p=}wpJd_*3y)dTL1)0lRar$;lawd5wQ0FmYP%^sSgLLCZhbhqCyGZ2#`la=Gtwb@id);o+g7+pFCc%V?EbX?Hf@ zzn?2tu3Wf)Ab&AbI4vwXTF=110R0~LPCg=$l9Q6;aEsi%%h%vzm|Ot36dbIP)~1AXC7h4fuq#z8$ocV%e#iH}>@Cd_ADVD^+31{^!P zyEwXF&Xhd!EHXg1SXpg-5U*9ArOyf2Auc9ndRr;B!wvBynt&1sl;v&9G0*1T${UNU z4qO(3Ah(RomZ|9WuYTY$k?-4Fv@|e-P_j!~d!((+6PnCK?G?BSINbMyMK=x(1|nn; zNODqAaclj{%K_cbSMTh-HvoJIpKog`nm&W2Apd=`H{$tOem>)ClJatLTSE9J>85-|qW+LAwGV#-OP_9~By7c_oHAda5zx!Q|N~J!1 z>W|6076lb0C1ILZx+RaxaLMeKd?sIfkS6hbUl+rQ#|RoJtqqpwd1(BQHt zdt-@&S=RE(3g&=g3b3lMwuD4Ji6kr|Q&d}#WDYeRd9cs$Gtf*`Rci6gFjp9wnA`yr z^W8WQnz~JoU)hU;p&Q9BAJg{EE%$!-35lrO(Y!F-jb!kYt1ECjlssi6B@Uuq+(eT| z-Qb{_m{=~3gShyE>gr%@Tdyk%_pz|ZPe`PC&@$lrM^pLu`RC^6nGLoaF)S)AE&UHO z8J{?@Urvr?G7{MzQs_h;`G|&JMHU4}G^; z8Hbv?4Ns{0&wZ*Ko0~i2tri}C7byat-zNtvbt_$LU?j?0b6G#X!DGY80sMd<#}Sgz z;f9f@`UVD5Q&W3wN*uA5kVG6dG?d)E8NulGi6}og>2~$raM`JNBJnj6iqNlbI8UDZj2n^Ap!MA0s1#>fJIFL> zRf_<2z%>Smd^_0KB3RzEww9EaQ>E$C#o{qf!telt1QwD&^1&n|5UCxvY)72^?OOagJ^7Bu=SN3<{{1|fd0c{tfH*Ug4k?U*8l(BdY~ z(l{QH!LAaEEE`RdaqyUzHH9giKVed=v5^s!);D1S?d$8f-{1$tW&g->(p}KT($dA% zRmpKyM9p~H;Vmw5JU(oXR~b*paIwd{0KqqP@*OyxbVns6rB;D)4kPSl1_lP!WqJPp z-wV)s+Rkpy&`s4OS+)9mRWI9|CCNPOvxy`yIT!BiLWiCSj|mXw10j}{$FTdOERTR` z1ulc<&VOQ?h;l5%UhD^(LLp@$tH@(rk-&w~aG;=HzaknMo&I=Tp)Gj&^!Ly47En1r zbYO;>oAol!FVT8}5yw1O+WU1fGBWopAMT#Rdj|pv&+G-1dX|!Px|=A?v-`H`y1*fC zFBZ@Dw5wb8Q>=;q5L}Qs&}uE4#%`=A&juP)JY^+fhVsZW?fnzK1nB|=L>zRx7Ehh= zm({v+u6XM2aW>_5k21cUf7Kjz{NSSl(>9TY9}6q`Iv4specu!ZnWtrIP!$w>O$w>X zejd@fQT3|kYR=&wAy)zo*UhZ7_kVsgayaX=qD8IQZ)*YNcYg-U``T`6tfqW@;HHBLkFjVF83vZ|X{=Iy9rpqWq#oV9zgVwbx zefhkWxq4==l&B@PehE|bFB3m2%8;LQQ7875;gEe^b5_=FwX6HKmA?_Hj*(-a`Y6OF zmv=Zrm{zTf-n@K5m+))hQB9N3o(+S(yT4=8_;qcU`ixQ%Zllc7_gq~?h_QZ05$$nS zKg&(ao+w4-KR2hmvUNX9RLt}%jKvI`<}Y%q>2k|I{DFZw$E@f2B6QCq#HbOZK^r_l1#5$(FqBJUa#Wm>65Om1}HL!*wdr4 z&ilrc>35S{LWf&RQCxCUtuxiEeeIE+&f_7gT116a@e>@xZ|b#F}~cdj}9 zZrC3Y&(bS3l$-8cqp8E2{SVd)jsMNEQ#*BtjBHjPT@&&Aciz!Lab#*PRqnSv1`*&c ze|14r<<3cKYlG5uT2D})d+n=f1RwAEz=lz^cA*dHLG3_T7iNncZMRu|x9Bu>hu{2{ zR=ZiSk;cA#X#-Nb%AP!Yc+V#(q5@~;-n*pujxir8DXCG(({xpEZ~*gxzw)!Cj-()s zQ)L~X{Glx5MbLIs$UvUTA^4boYelaP690pX3ia6nr_zy^u(DDJC{BNSE`g+dyHe>w zKs7QLOd}5p3c?I^)fzGxS)48$kE2v){Rl~lq$zZs#<9A~nId}#h9q;>Q>W^=L$6wf zsqr1gf`-NWBhV!zB;bJJDrvanR2RdbrK03m3fn#II8au|H=X>azkLgzKW5Gi%LB;g zT1=?Gah{kv>>syo2hTk+LdK5vt>TXt78a0j!@&DD?j%UCd+F6qvBmlMe>eWkBjh(+ zqM-e?xH$ghi)0yf$SFwd;FRFn<{flGFE37}FS_gA#dWs^!A*c80am+8B?UVdZ=5D2 zjZ!)0*Fc)W(iC4;lMoXFsYnWcrUymz_wRlOka1bdZUO|u0;?zXuWma(=je;a?Zw5( zsivxmTRCZS6`;?*ll6$8`os-nH^j+Pgv67<%L}CI*O|vQDN+hkQrMf!%>x_;flm7S zzfVu|@bWg?7t~rY+|E7iM&(-6Uxl#1i5xr?719@Q_VX*;mBpW*&MpOL+1 zX+b2xLE{2tPY?V5{ua|f&-`zHN$0sIhh>fyo3Z^_sneop+@i+4OgdcoCZ6NY-S%ud zZ;{SCYuOot!H2YS@BX*TjHlo67GIfeabWwtp?$*Jf8@tkEj;9Zi&e{M>v<3G6+cJl z{~!KwS^9`n>fWzv3wl<+t{=FEQX8ZAan;1}zOKNP8>@HZr{gT8Qu}&Eb0CTt?+PBg z$YQaJE;eO3e(N8)Z)U1pzdvy7`zx_RA$T~XG1T|kJ?nP|R#OJK|arQafnSXCy@DaiP{!;TI8%C{ zio?Sr?0ANARhy%n90TSW7e9GIhWiG;2eX7@?PQA|KSohPh!+D536ciRYli6u=}TXT ztE-p8b+%M(Ub3RAjy4o~aryTnJ6VIScLzodEG#UbMHEK~`NZm4z?}2xlc@^Hi3cpo z`>Cry^4D5Zu81t z*7PSbXO=ggs;=y7&F|;LG!qUwDDZ-Od~e5mbh3n`31_2{Vr_*4KsC3I|HSRyN*hG6 zg4(EHm>9vinTjilii#>L`$JpTm3_rvGO-%1(CUi5KAjL+@3wy>kKrmPFeKnv)SdaZ4SPjhm{>%yrZ1>j4$i`5HaIl&$DPgN z?AhVkP;HHl-d+VMDZ1P0@y%c|RiPt+m%`YMt#dnWkX5CHu|}*sxHC(b$kon^_i)QG zq!{NxkeQpFM!M{A`t%6^Ew~3iZP|p3`sr2BK7yen2WF9zix)P9OsIrkYlX^XnDPvQ zFl=-yA2ZXH)}!)IGD(vKX9(8}>rq-WP@bx=a~2eMB7)l3*cckp$X9zqd;vQO)eEVo zt1zemcQ-dLPfuKwK)T@jSwsaQ>jRb-#!wOD?CJ`;pPQH0DqhFmGHIw(C>=;{{|ac- z3BTLg^3Tni_KS~5sl=MVUADUtS%`8`j={KEQH1bQ#OW-U3@QC;4B~ug{b9jc;ChRz!Y;Np6#2p|P-XW6Ry!Y{S8$}PRNtjj=1d+5 z-}pn!8jOu3zQHETouD|GXK^T73kRRSu>@=LYi(r_>`lilzsPmJ^!MOsY$|hP{pint zy?K#3@6&GHBx^Jyn;XwxzTBVgM*C%aT%JJ@a6MM{o>CZ>A2dn8VL)n};4F9_K{X*a zpxPt&3y;^GYm`EE?c(gC3@JB1KhkzfG^j6RIY5V}934mT51IJYCw}~3dZG1rU$^l= z!LVJUUnAG2#>~#wbJA^7st1Y1$gh3@L@y|FtPsR-<2*miERs74UvU-`%at{xF8@|m z4rQt>{fL2xQGm)wB;yDM{lTH_erz+Q)%HROy~7{G7n zH2aj4>?%Bx!I~4M;UdJRfhRRHJJ)t&7xIUa*<008bhl{@P{Ue4pLap5^;YkT|VO{=3vmC>g%DTyV@oIoHL8eYYjAsC)Gu~TzS zoHATUUS3{GYNkanbXIvN7cP@++YseNq8b_-LG3~~hMz0exDPhoRlqG!(m*T8e{{>r z%b{bC#!+513BnmoNAKONR-oNxjoM0C4_yzIcMWjRH*ek~Uo-;))$4ygLfGtVZ$C%_cW!;wa}cwj z;<4|ntZtf1YFwCRAsC9W!Jr3shzsOO{s{20_qicgmXa%-@FNX z0C^@JybpbSR!e>NX|`#hmkuNm6a~!wV+;Ee^7qF{lDR5egNcbuWd)nt3cqlEpd!|{ zCOX*|8`BXUf??dVXAX8p8WO0#wY6a6>Hi7#%$`>^*Do=}f%%JH(d{jfaVKUnF$-!Xu#lBM+$y*)-QK2CMDlC6BHb7p8v_xx8z1pim$F?I z}Y!#wf2BTnx|>gwDv@l&OT)+9yvy zefZabmPvQ9W)sMK|wgq79?}<1QAdYzI|I+UIx%zTv@}SKx)D*Nga6vSE!|B zIW$P%3%F2d1&~s4LfoG2CIMikPh`EnFs8y3laiEFf=`DN0*!qeoL9lPLOgJCasuh^ znx^j|ffH&f&OUSyRJ-@=$stHZ|Pad*56VcjIU_^1W`7 z{XqFx>M==bw}iU7y6^p#a9~iz%_Br1pG8fEg{7smloV_)@{rY|ShBlnQM?Vc;k1iO z`RRVyg>#ZvY_Q1)8<f~SL*#;=MmDiGVVu1@FDrN2LZob?+Ir%X>z7m5N5NNbPQGI`PjJUEOP z+gD)e5W4QKqod>FBS*M8V1!BnWd#KS&4IRS2?Zrqs9mVru6J z(c&@T<20eW6}gdbI`OcXq|QeTz0GiBOatd!v$+wJYP{{%Td-cxa^WMJo|#csBNyP{ znBi{54Go<&Dmq#?3ULV9=+Bqc)f#eg2*#cs7&(s7YfxEXMqwqCyLG4sEC>-=>*^d4 z?2wD0w>9jBB~Ovs;0IEEgEj=0o4YMh6{j54jhqd3q}SI4ndy)5r0Izqfzo1W$)3{I z*V{`7tx&hG4)6sPyCBIFvv{A)ayM(_?mdRnD`&Rf*ZHDdm zC>kYhn!fO^OItL`QJx~w1Y$K1DkL#{Ud{TS69raiNpRG`p%%h-ffej)Pw@w26yS4a zXJ=vWg^d&Ij9ddF0(SsFOTHfSLD?~^yl|8XPvF&GdXVf^a7v&t#26bs5=^)}}!f|6KdkNnJO9GVuJ8yL0clO1YaT?)R z-QMA0S+-c1?eM&y8{<6~?)gkiO+mjYu_;Qc{3CLq1623G`z+M@`TCMiv68ZK?eZ7; zsHEcJbGo`sQ2b!527w;Qf>VZH1OA+rASoh(E@74nO38+psRlk2CDQ_0!8{xseeM^@ zX6b3HR#HX=xh`vV_|={EuduJk*jCWIp_xI-sJ5Ki5ul>mq_e* z8CsW@XogXKbx10ea9xK6nKiB=1{ga3dmX*K7NF##2|b@aX*f60fU5`Pjoq!Qrw7;x zN+fi7EC#SzL*)06bT~f?T60TsnO`CUGA=H7rg7R2#xUuH+D)*W(DNzBohr7uzi=p& zx1x7p`#mF`U#j*@8Y=WbRnH_D4q8;bd8?Chff3DJlmL7k zm=)9VCxpBrNT(ah7Ms)g_{OGp9i=8ZsXl2K7~(OYpY;Y~$-q#ER@}RH$0j6HUs=Bl z5DOQy;{ybvp6+fmCh$6U4$AQJvN8bKFMd^W)38Q1EHflpBg_YD2|mbx5fY$|TsRH1 zkHD(5Z=XACSN-uUxVC4`Gv7(iVDY>k5hvcim*|8vXrUh;0O*MH9BCRHUhMnowvb!T z{~5#miP|pUkecNmX#Sz7qH?9mn2N%X*%%zwi~m*IdYwKE)(V#&eic8zCUTS#711b~ z3?Eg#hG002@NWqg{7&+4j=YEY^(ieT8(%|rgiNm`e;v2|XK(mqmL zCmaO_guRgw?En?Z`*pX@NB@`X0u!yG=3}TPWdAZJdsUJ|5Xl_QkiUrjko?||$8B=5 zv%A2YI5DyHMYO57i$Vr$<;}j;IPO9$Hnz4mPQJ=A``EvpK`q~XJWaH z3?Sakn;hXfB}lb!dqFadCQ!8VbH#JAu=tF>W{lOPbmK{qVr>p%i4Ydwz1tJ01s4&h zniAhSR|VL-P%%79F5N>~NiH9{eDqYYU?@wSC5z{3s7kOta+BQL31k~EP(j-Bcfs1Ajt_M&?(kFMX8Si9$t)yEd?*xf6=j(2muK7cod>ca1@r8Nu_{l||dNaiJj-rU@2fDWw?v~6Y64&I58dRSC6vA8l4@|T~` zIy|fe+c$!_hQ{582bh_!A0dyh<%S8DgjunB>0DD~&%MC1dy@OOL+mUgL0*;ICV5sqq zfAiI^VN55_B0Rqo+to^n+^Y;lDzHPtILJc40t9P?eya2ZXUDXDg;q2qNZBArfP`R|K!ya?>^#zQob3fVr11llzM?5@Q6Yj+Nj5S>!4g+g9-%h5 z*_o4z3n3WLd#}(67%F+51RQbJKVp?Tdf6!FOz4{2=%p}msVr9hD=+wIelBA@h zWBDMshp3)Ic@~I*;l{}@dc!qizmC|BI;H987;QiA1(PVga|uoZi1P>`NbZ>VR7+q_ zMRyz6W+V2llcVW$x3D=cO$J!pf!)YW^??!`9YJf8%`K2vRb#Yv1}j0Oz>(n73J!q3 ztEZ<28akN}U}D15-I$MBSSQ3EOnklL(S;p|Uk>Pe0>$Vk<1rMYV`S8$IRo&Ce+%{= z|7x_l$V$q^*%`cH!nJEKoLRu_?bJv;P(6Sf23=!d4_f^7tB&cXb3+r$li=tccAkUL zqCO|zynVZdSV(q6;(H(;zv%Bzb_3$$-gS4QaF|*A@Lkl2ADZ2!Glxmg=(6Lg0K^qd z7z12npz4Q5QkAb0FA~*O%WCLsODF`9Ecf9WDsq8*@V!(M1@~WMAl?QpYCI#7?9m*@ z30lC{$47{x7;PZVz$b_kgQru+qM$GWUjR=_Hi{3rXNM1SA)N5=09}I=VLtm9#6&Hy zDZ=*-4i0h-;1f+WH`CUx<$jX0$(Ak{yZ}a`URxwbYYFXrADE9$BfkFxz5=;}Q<&b-geTD=k^68Fey>qj(wkJ+FJ%fCN zO>&P5tB`CsF+YFq?Aa$ER?^e)rl}|?p~8Rq{CUv(56TO0>tIYa5O(h4$0r>e<|ikq zR|5B{@Q=_4SJ@4Nx}2Zya!YC1wq?sU zIwRc!R=Blgj#*l!Agbc)AzI-iVH^pr7)WuBH&Im8(cTVYQCvcTYxyA1ATBD9F*GCu zPH+TRieCcktcuie4cJXA1Okbrv4nIm23P=gDCadKAd5eL%B!e+c=yi4$Ox9PrN4i{ z8-Y&6c{D$SPeT}h6EYN{+^bjXXoG{z65sWApm3{grmhH%Mj$d-U^FZpX$@ZxEe~LC zM6Cd79VUJT0O2!GQ(Y8sRX7d|h{s0q3ISz)q}BnN+V}4-Q7SK+u8!5(!+5EKQs_OE-lEe0|W4!1YN$2(#t02pD=i0U;fk<*rNVWD)5x%HkYt3 ziB1Esf*V}pg(!$DrDJMw2ZKHwSh2B2pu;iBS&rewL4;kH`%~Js-igc4&&T7WrXIyI zojLOu4s>i?M2N(3ECikj6$`jioJwu*UbM8dScWkh0jvYgI4n-TmzKZ`!pw|o0sdE0 zfn=-^csQKISda63E%^UI8qI&IqWU3&jua~K&G558vxWm6ABU{|Rp{mhVgtl$2m=a8 zwx}bK+rUNDryeD7&p7imx3}=jcys~>r)dvaDQFBka(zgalFJmaYX!4j+t;y zzQ7PTQ1r<`Vk5?M3pkOLl@&qQr*U+KJNa;hm@UU)b+M&+W?|W1@qaI${*`JUAu`Mx zJc1};mZcG^t=S!0?`W830jK~{>|lY_jdhdDXPh)XW{uG{EoPrlnYbKNowaAG{PWtp zS+VSh$;R|`{;B5uhQ%WjQ4=Dhnwy4x7rRuhYtg?OVcaaTUzE@}!Rz5cz2z{i*xeTn zvfy?`KkBJ?qacpmcTH*UwhU8o7MiP}5qHTH-Ogkp(M`w0go^Q+ZFTR;2@nmzLi;+T zBO1qak|-hS$0MUvQlgR@y)qZCUCmvwXX&U;{B0t{w^VB0+Y|wLi*%Zv>z>{BACLll zH+C?o{wF~zDTS*2AMe7!gE?IPSO2)V$=a;dWs`@y3_mLl#3C`d?st2y^|}}JVoTy@ ziL#H%oYO`%5&dD8md3w^`VXR3g#5FiKdOpZRcN@AI4;8!V+m_VA^rb(;`Q)x)tJT= Z?cW33RU!>8x3}QONbj)j6M|#J{|D6>ns5LB literal 0 HcmV?d00001 diff --git a/lib/komihash/komihash.h b/lib/komihash/komihash.h new file mode 100644 index 00000000..7a72fda8 --- /dev/null +++ b/lib/komihash/komihash.h @@ -0,0 +1,831 @@ +/** + * komihash.h version 4.7 + * + * The inclusion file for the "komihash" hash function, "komirand" 64-bit + * PRNG, and streamed "komihash" implementation. + * + * Description is available at https://github.com/avaneev/komihash + * + * License + * + * Copyright (c) 2021-2022 Aleksey Vaneev + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef KOMIHASH_INCLUDED +#define KOMIHASH_INCLUDED + +#include +#include + +// Macros that apply byte-swapping. + +#if defined( __GNUC__ ) || defined( __clang__ ) + + #define KOMIHASH_BYTESW32( v ) __builtin_bswap32( v ) + #define KOMIHASH_BYTESW64( v ) __builtin_bswap64( v ) + +#elif defined( _MSC_VER ) + + #define KOMIHASH_BYTESW32( v ) _byteswap_ulong( v ) + #define KOMIHASH_BYTESW64( v ) _byteswap_uint64( v ) + +#else // defined( _MSC_VER ) + + #define KOMIHASH_BYTESW32( v ) ( \ + ( v & 0xFF000000 ) >> 24 | \ + ( v & 0x00FF0000 ) >> 8 | \ + ( v & 0x0000FF00 ) << 8 | \ + ( v & 0x000000FF ) << 24 ) + + #define KOMIHASH_BYTESW64( v ) ( \ + ( v & 0xFF00000000000000 ) >> 56 | \ + ( v & 0x00FF000000000000 ) >> 40 | \ + ( v & 0x0000FF0000000000 ) >> 24 | \ + ( v & 0x000000FF00000000 ) >> 8 | \ + ( v & 0x00000000FF000000 ) << 8 | \ + ( v & 0x0000000000FF0000 ) << 24 | \ + ( v & 0x000000000000FF00 ) << 40 | \ + ( v & 0x00000000000000FF ) << 56 ) + +#endif // defined( _MSC_VER ) + +// Endianness-definition macro, can be defined externally (e.g. =1, if +// endianness-correction is unnecessary in any case, to reduce its associated +// overhead). + +#if !defined( KOMIHASH_LITTLE_ENDIAN ) + #if defined( _WIN32 ) || defined( __LITTLE_ENDIAN__ ) || \ + ( defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + + #define KOMIHASH_LITTLE_ENDIAN 1 + + #elif defined( __BIG_ENDIAN__ ) || \ + ( defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + + #define KOMIHASH_LITTLE_ENDIAN 0 + + #else // defined( __BIG_ENDIAN__ ) + + #warning KOMIHASH: cannot determine endianness, assuming little-endian. + + #define KOMIHASH_LITTLE_ENDIAN 1 + + #endif // defined( __BIG_ENDIAN__ ) +#endif // !defined( KOMIHASH_LITTLE_ENDIAN ) + +// Macros that apply byte-swapping, used for endianness-correction. + +#if KOMIHASH_LITTLE_ENDIAN + + #define KOMIHASH_EC32( v ) ( v ) + #define KOMIHASH_EC64( v ) ( v ) + +#else // KOMIHASH_LITTLE_ENDIAN + + #define KOMIHASH_EC32( v ) KOMIHASH_BYTESW32( v ) + #define KOMIHASH_EC64( v ) KOMIHASH_BYTESW64( v ) + +#endif // KOMIHASH_LITTLE_ENDIAN + +// Likelihood macros that are used for manually-guided micro-optimization. + +#if defined( __GNUC__ ) || defined( __clang__ ) + + #define KOMIHASH_LIKELY( x ) __builtin_expect( x, 1 ) + #define KOMIHASH_UNLIKELY( x ) __builtin_expect( x, 0 ) + +#else // likelihood macros + + #define KOMIHASH_LIKELY( x ) ( x ) + #define KOMIHASH_UNLIKELY( x ) ( x ) + +#endif // likelihood macros + +// Memory address prefetch macro (temporal locality=1, in case a collision +// resolution would be necessary). + +#if defined( __GNUC__ ) || defined( __clang__ ) + + #define KOMIHASH_PREFETCH( addr ) __builtin_prefetch( addr, 0, 1 ) + +#else // prefetch macro + + #define KOMIHASH_PREFETCH( addr ) + +#endif // prefetch macro + +/** + * An auxiliary function that returns an unsigned 32-bit value created out of + * a sequence of bytes in memory. This function is used to convert endianness + * of in-memory 32-bit unsigned values, and to avoid unaligned memory + * accesses. + * + * @param p Pointer to 4 bytes in memory. Alignment is unimportant. + * @return Endianness-corrected 32-bit value from memory. + */ + +static inline uint32_t kh_lu32ec( const uint8_t* const p ) +{ + uint32_t v; + memcpy( &v, p, 4 ); + + return( KOMIHASH_EC32( v )); +} + +/** + * An auxiliary function that returns an unsigned 64-bit value created out of + * a sequence of bytes in memory. This function is used to convert endianness + * of in-memory 64-bit unsigned values, and to avoid unaligned memory + * accesses. + * + * @param p Pointer to 8 bytes in memory. Alignment is unimportant. + * @return Endianness-corrected 64-bit value from memory. + */ + +static inline uint64_t kh_lu64ec( const uint8_t* const p ) +{ + uint64_t v; + memcpy( &v, p, 8 ); + + return( KOMIHASH_EC64( v )); +} + +/** + * Function builds an unsigned 64-bit value out of remaining bytes in a + * message, and pads it with the "final byte". This function can only be + * called if less than 8 bytes are left to read. The message should be "long", + * permitting Msg[ -3 ] reads. + * + * @param Msg Message pointer, alignment is unimportant. + * @param MsgLen Message's remaining length, in bytes; can be 0. + * @return Final byte-padded value from the message. + */ + +static inline uint64_t kh_lpu64ec_l3( const uint8_t* const Msg, + const size_t MsgLen ) +{ + const int ml8 = -(int) ( MsgLen * 8 ); + + if( MsgLen < 4 ) + { + const uint8_t* const Msg3 = Msg + MsgLen - 3; + const uint64_t m = (uint64_t) Msg3[ 0 ] | (uint64_t) Msg3[ 1 ] << 8 | + (uint64_t) Msg3[ 2 ] << 16; + + return( 1ULL << (( Msg3[ 2 ] >> 7 ) - ml8 ) | m >> ( 24 + ml8 )); + } + + const uint64_t mh = kh_lu32ec( Msg + MsgLen - 4 ); + const uint64_t ml = kh_lu32ec( Msg ); + + return( 1ULL << ( (int) ( mh >> 31 ) - ml8 ) | + ml | ( mh >> ( 64 + ml8 )) << 32 ); +} + +/** + * Function builds an unsigned 64-bit value out of remaining bytes in a + * message, and pads it with the "final byte". This function can only be + * called if less than 8 bytes are left to read. Can be used on "short" + * messages, but MsgLen should be greater than 0. + * + * @param Msg Message pointer, alignment is unimportant. + * @param MsgLen Message's remaining length, in bytes; cannot be 0. + * @return Final byte-padded value from the message. + */ + +static inline uint64_t kh_lpu64ec_nz( const uint8_t* const Msg, + const size_t MsgLen ) +{ + const int ml8 = -(int) ( MsgLen * 8 ); + + if( MsgLen < 4 ) + { + uint64_t m = Msg[ 0 ]; + const uint8_t mf = Msg[ MsgLen - 1 ]; + + if( MsgLen > 1 ) + { + m |= (uint64_t) Msg[ 1 ] << 8; + + if( MsgLen > 2 ) + { + m |= (uint64_t) mf << 16; + } + } + + return( 1ULL << (( mf >> 7 ) - ml8 ) | m ); + } + + const uint64_t mh = kh_lu32ec( Msg + MsgLen - 4 ); + const uint64_t ml = kh_lu32ec( Msg ); + + return( 1ULL << ( (int) ( mh >> 31 ) - ml8 ) | + ml | ( mh >> ( 64 + ml8 )) << 32 ); +} + +/** + * Function builds an unsigned 64-bit value out of remaining bytes in a + * message, and pads it with the "final byte". This function can only be + * called if less than 8 bytes are left to read. The message should be "long", + * permitting Msg[ -4 ] reads. + * + * @param Msg Message pointer, alignment is unimportant. + * @param MsgLen Message's remaining length, in bytes; can be 0. + * @return Final byte-padded value from the message. + */ + +static inline uint64_t kh_lpu64ec_l4( const uint8_t* const Msg, + const size_t MsgLen ) +{ + const int ml8 = -(int) ( MsgLen * 8 ); + + if( MsgLen < 5 ) + { + const uint64_t m = kh_lu32ec( Msg + MsgLen - 4 ); + + return( 1ULL << ( (int) ( m >> 31 ) - ml8 ) | m >> ( 32 + ml8 )); + } + + const uint64_t m = kh_lu64ec( Msg + MsgLen - 8 ); + + return( 1ULL << ( (int) ( m >> 63 ) - ml8 ) | m >> ( 64 + ml8 )); +} + +#if defined( __SIZEOF_INT128__ ) + + /** + * 64-bit by 64-bit unsigned multiplication. + * + * @param m1 Multiplier 1. + * @param m2 Multiplier 2. + * @param[out] rl The lower half of the 128-bit result. + * @param[out] rh The higher half of the 128-bit result. + */ + + static inline void kh_m128( const uint64_t m1, const uint64_t m2, + uint64_t* const rl, uint64_t* const rh ) + { + const __uint128_t r = (__uint128_t) m1 * m2; + + *rl = (uint64_t) r; + *rh = (uint64_t) ( r >> 64 ); + } + +#elif defined( _MSC_VER ) && defined( _M_X64 ) + + #include + + static inline void kh_m128( const uint64_t m1, const uint64_t m2, + uint64_t* const rl, uint64_t* const rh ) + { + *rl = _umul128( m1, m2, rh ); + } + +#else // defined( _MSC_VER ) + + // _umul128() code for 32-bit systems, adapted from mullu(), + // from https://go.dev/src/runtime/softfloat64.go + // Licensed under BSD-style license. + + static inline uint64_t kh__emulu( const uint32_t x, const uint32_t y ) + { + return( x * (uint64_t) y ); + } + + static inline void kh_m128( const uint64_t u, const uint64_t v, + uint64_t* const rl, uint64_t* const rh ) + { + *rl = u * v; + + const uint32_t u0 = (uint32_t) u; + const uint32_t v0 = (uint32_t) v; + const uint64_t w0 = kh__emulu( u0, v0 ); + const uint32_t u1 = (uint32_t) ( u >> 32 ); + const uint32_t v1 = (uint32_t) ( v >> 32 ); + const uint64_t t = kh__emulu( u1, v0 ) + ( w0 >> 32 ); + const uint64_t w1 = (uint32_t) t + kh__emulu( u0, v1 ); + + *rh = kh__emulu( u1, v1 ) + ( w1 >> 32 ) + ( t >> 32 ); + } + +#endif // defined( _MSC_VER ) + +// Macro for common hashing round with 16-byte input, using the "r1h" +// temporary variable. + +#define KOMIHASH_HASH16( m ) \ + kh_m128( Seed1 ^ kh_lu64ec( m ), \ + Seed5 ^ kh_lu64ec( m + 8 ), &Seed1, &r1h ); \ + Seed5 += r1h; \ + Seed1 ^= Seed5; + +// Macro for common hashing round without input, using the "r2h" temporary +// variable. + +#define KOMIHASH_HASHROUND() \ + kh_m128( Seed1, Seed5, &Seed1, &r2h ); \ + Seed5 += r2h; \ + Seed1 ^= Seed5; + +// Macro for common hashing finalization round, with the final hashing input +// expected in the "r1h" and "r2h" temporary variables. The macro inserts the +// function return instruction. + +#define KOMIHASH_HASHFIN() \ + kh_m128( r1h, r2h, &Seed1, &r1h ); \ + Seed5 += r1h; \ + Seed1 ^= Seed5; \ + KOMIHASH_HASHROUND(); \ + return( Seed1 ); + +// Macro for a common 64-byte full-performance hashing loop. Expects Msg and +// MsgLen values (greater than 63), requires initialized Seed1-8 values, uses +// r1h-r4h temporary variables. +// +// The "shifting" arrangement of Seed1-4 (below) does not increase individual +// SeedN's PRNG period beyond 2^64, but reduces a chance of any occassional +// synchronization between PRNG lanes happening. Practically, Seed1-4 together +// become a single "fused" 256-bit PRNG value, having a summary PRNG period. + +#define KOMIHASH_HASHLOOP64() \ + do \ + { \ + KOMIHASH_PREFETCH( Msg ); \ + \ + kh_m128( Seed1 ^ kh_lu64ec( Msg ), \ + Seed5 ^ kh_lu64ec( Msg + 8 ), &Seed1, &r1h ); \ + \ + kh_m128( Seed2 ^ kh_lu64ec( Msg + 16 ), \ + Seed6 ^ kh_lu64ec( Msg + 24 ), &Seed2, &r2h ); \ + \ + kh_m128( Seed3 ^ kh_lu64ec( Msg + 32 ), \ + Seed7 ^ kh_lu64ec( Msg + 40 ), &Seed3, &r3h ); \ + \ + kh_m128( Seed4 ^ kh_lu64ec( Msg + 48 ), \ + Seed8 ^ kh_lu64ec( Msg + 56 ), &Seed4, &r4h ); \ + \ + Msg += 64; \ + MsgLen -= 64; \ + \ + Seed5 += r1h; \ + Seed6 += r2h; \ + Seed7 += r3h; \ + Seed8 += r4h; \ + Seed2 ^= Seed5; \ + Seed3 ^= Seed6; \ + Seed4 ^= Seed7; \ + Seed1 ^= Seed8; \ + \ + } while( KOMIHASH_LIKELY( MsgLen > 63 )); + +/** + * The hashing epilogue function (for internal use). + * + * @param Msg Pointer to the remaining part of the message. + * @param MsgLen Remaining part's length, can be zero. + * @param Seed1 Latest Seed1 value. + * @param Seed5 Latest Seed5 value. + * @return 64-bit hash value. + */ + +static inline uint64_t komihash_epi( const uint8_t* Msg, size_t MsgLen, + uint64_t Seed1, uint64_t Seed5 ) +{ + uint64_t r1h, r2h; + + KOMIHASH_PREFETCH( Msg ); + + if( KOMIHASH_LIKELY( MsgLen > 31 )) + { + KOMIHASH_HASH16( Msg ); + KOMIHASH_HASH16( Msg + 16 ); + + Msg += 32; + MsgLen -= 32; + } + + if( MsgLen > 15 ) + { + KOMIHASH_HASH16( Msg ); + + Msg += 16; + MsgLen -= 16; + } + + if( MsgLen > 7 ) + { + r2h = Seed5 ^ kh_lpu64ec_l4( Msg + 8, MsgLen - 8 ); + r1h = Seed1 ^ kh_lu64ec( Msg ); + } + else + { + r1h = Seed1 ^ kh_lpu64ec_l4( Msg, MsgLen ); + r2h = Seed5; + } + + KOMIHASH_HASHFIN(); +} + +/** + * KOMIHASH hash function. Produces and returns a 64-bit hash value of the + * specified message, string, or binary data block. Designed for 64-bit + * hash-table and hash-map uses. Produces identical hashes on both big- and + * little-endian systems. + * + * @param Msg0 The message to produce a hash from. The alignment of this + * pointer is unimportant. It is valid to pass 0 when MsgLen==0 (assuming that + * compiler's implementation of the address prefetch is non-failing for any + * address). + * @param MsgLen Message's length, in bytes, can be zero. + * @param UseSeed Optional value, to use instead of the default seed. To use + * the default seed, set to 0. The UseSeed value can have any bit length and + * statistical quality, and is used only as an additional entropy source. May + * need endianness-correction if this value is shared between big- and + * little-endian systems. + * @return 64-bit hash of the input data. + */ + +static inline uint64_t komihash( const void* const Msg0, size_t MsgLen, + const uint64_t UseSeed ) +{ + const uint8_t* Msg = (const uint8_t*) Msg0; + + // The seeds are initialized to the first mantissa bits of PI. + + uint64_t Seed1 = 0x243F6A8885A308D3 ^ ( UseSeed & 0x5555555555555555 ); + uint64_t Seed5 = 0x452821E638D01377 ^ ( UseSeed & 0xAAAAAAAAAAAAAAAA ); + uint64_t r1h, r2h; + + // The three instructions in the "KOMIHASH_HASHROUND" macro represent the + // simplest constant-less PRNG, scalable to any even-sized state + // variables, with the `Seed1` being the PRNG output (2^64 PRNG period). + // It passes `PractRand` tests with rare non-systematic "unusual" + // evaluations. + // + // To make this PRNG reliable, self-starting, and eliminate a risk of + // stopping, the following variant can be used, which is a "register + // checker-board", a source of raw entropy. The PRNG is available as the + // komirand() function. Not required for hashing (but works for it) since + // the input entropy is usually available in abundance during hashing. + // + // Seed5 += r2h + 0xAAAAAAAAAAAAAAAA; + // + // (the `0xAAAA...` constant should match register's size; essentially, + // it is a replication of the `10` bit-pair; it is not an arbitrary + // constant). + + KOMIHASH_HASHROUND(); // Required for PerlinNoise. + + if( KOMIHASH_LIKELY( MsgLen < 16 )) + { + KOMIHASH_PREFETCH( Msg ); + + r1h = Seed1; + r2h = Seed5; + + if( MsgLen > 7 ) + { + // The following two XOR instructions are equivalent to mixing a + // message with a cryptographic one-time-pad (bitwise modulo 2 + // addition). Message's statistics and distribution are thus + // unimportant. + + r2h ^= kh_lpu64ec_l3( Msg + 8, MsgLen - 8 ); + r1h ^= kh_lu64ec( Msg ); + } + else + if( KOMIHASH_LIKELY( MsgLen != 0 )) + { + r1h ^= kh_lpu64ec_nz( Msg, MsgLen ); + } + + KOMIHASH_HASHFIN(); + } + + if( KOMIHASH_LIKELY( MsgLen < 32 )) + { + KOMIHASH_PREFETCH( Msg ); + + KOMIHASH_HASH16( Msg ); + + if( MsgLen > 23 ) + { + r2h = Seed5 ^ kh_lpu64ec_l4( Msg + 24, MsgLen - 24 ); + r1h = Seed1 ^ kh_lu64ec( Msg + 16 ); + } + else + { + r1h = Seed1 ^ kh_lpu64ec_l4( Msg + 16, MsgLen - 16 ); + r2h = Seed5; + } + + KOMIHASH_HASHFIN(); + } + + if( MsgLen > 63 ) + { + uint64_t Seed2 = 0x13198A2E03707344 ^ Seed1; + uint64_t Seed3 = 0xA4093822299F31D0 ^ Seed1; + uint64_t Seed4 = 0x082EFA98EC4E6C89 ^ Seed1; + uint64_t Seed6 = 0xBE5466CF34E90C6C ^ Seed5; + uint64_t Seed7 = 0xC0AC29B7C97C50DD ^ Seed5; + uint64_t Seed8 = 0x3F84D5B5B5470917 ^ Seed5; + uint64_t r3h, r4h; + + KOMIHASH_HASHLOOP64(); + + Seed5 ^= Seed6 ^ Seed7 ^ Seed8; + Seed1 ^= Seed2 ^ Seed3 ^ Seed4; + } + + return( komihash_epi( Msg, MsgLen, Seed1, Seed5 )); +} + +/** + * Simple, reliable, self-starting yet efficient PRNG, with 2^64 period. + * 0.62 cycles/byte performance. Self-starts in 4 iterations, which is a + * suggested "warming up" initialization before using its output. + * + * @param[in,out] Seed1 Seed value 1. Can be initialized to any value + * (even 0). This is the usual "PRNG seed" value. + * @param[in,out] Seed2 Seed value 2, a supporting variable. Best initialized + * to the same value as Seed1. + * @return The next uniformly-random 64-bit value. + */ + +static inline uint64_t komirand( uint64_t* const Seed1, uint64_t* const Seed2 ) +{ + uint64_t rh; + + kh_m128( *Seed1, *Seed2, Seed1, &rh ); + *Seed2 += rh + 0xAAAAAAAAAAAAAAAA; + *Seed1 ^= *Seed2; + + return( *Seed1 ); +} + +#if !defined( KOMIHASH_BUFSIZE ) + + #define KOMIHASH_BUFSIZE 768 // Streamed hashing's buffer size in bytes, + // must be a multiple of 64, and not less than 128. + +#endif // !defined( KOMIHASH_BUFSIZE ) + +/** + * Context structure that holds streamed hashing state. The komihash_init() + * function should be called to initalize the structure before hashing. Note + * that the default buffer size is modest, permitting placement of this + * structure on stack. Seed[ 0 ] is used as initial UseSeed storage. + */ + +typedef struct { + uint8_t fb[ 8 ]; ///< Stream's final byte (at [7]), array to avoid OOB. + uint8_t Buf[ KOMIHASH_BUFSIZE ]; ///< Buffer. + uint64_t Seed[ 8 ]; ///< Hashing state variables. + size_t BufFill; ///< Buffer-fill length (position). + size_t IsHashing; ///< 0 or 1, equals 1 if the actual hashing was started. +} komihash_stream_t; + +/** + * Function initializes the streamed "komihash" session. + * + * @param[out] ctx Pointer to the context structure. + * @param UseSeed Optional value, to use instead of the default seed. To use + * the default seed, set to 0. The UseSeed value can have any bit length and + * statistical quality, and is used only as an additional entropy source. May + * need endianness-correction if this value is shared between big- and + * little-endian systems. + */ + +static inline void komihash_stream_init( komihash_stream_t* const ctx, + const uint64_t UseSeed ) +{ + ctx -> Seed[ 0 ] = UseSeed; + ctx -> BufFill = 0; + ctx -> IsHashing = 0; +} + +/** + * Function updates the streamed hashing state with a new input data. + * + * @param[in,out] ctx Pointer to the context structure. The structure must be + * initialized via the komihash_stream_init() function. + * @param Msg0 The next part of the whole message being hashed. The alignment + * of this pointer is unimportant. It is valid to pass 0 when MsgLen==0. + * @param MsgLen Message's length, in bytes, can be zero. + */ + +static inline void komihash_stream_update( komihash_stream_t* const ctx, + const void* const Msg0, size_t MsgLen ) +{ + const uint8_t* Msg = (const uint8_t*) Msg0; + + const uint8_t* SwMsg = 0; + size_t SwMsgLen = 0; + size_t BufFill = ctx -> BufFill; + + if( BufFill + MsgLen >= KOMIHASH_BUFSIZE && BufFill != 0 ) + { + const size_t CopyLen = KOMIHASH_BUFSIZE - BufFill; + memcpy( ctx -> Buf + BufFill, Msg, CopyLen ); + BufFill = 0; + + SwMsg = Msg + CopyLen; + SwMsgLen = MsgLen - CopyLen; + + Msg = ctx -> Buf; + MsgLen = KOMIHASH_BUFSIZE; + } + else + if( MsgLen < 9 ) + { + // For buffering speed-up. + + uint8_t* op = ctx -> Buf + BufFill; + + if( MsgLen == 4 ) + { + memcpy( op, Msg, 4 ); + ctx -> BufFill = BufFill + 4; + return; + } + + if( MsgLen == 8 ) + { + memcpy( op, Msg, 8 ); + ctx -> BufFill = BufFill + 8; + return; + } + + ctx -> BufFill = BufFill + MsgLen; + uint8_t* const ope = op + MsgLen; + + while( op != ope ) + { + *op = *Msg; + Msg++; + op++; + } + + return; + } + + if( BufFill == 0 ) + { + while( MsgLen > 127 ) + { + uint64_t Seed1, Seed2, Seed3, Seed4; + uint64_t Seed5, Seed6, Seed7, Seed8; + uint64_t r1h, r2h, r3h, r4h; + + if( ctx -> IsHashing ) + { + Seed1 = ctx -> Seed[ 0 ]; + Seed2 = ctx -> Seed[ 1 ]; + Seed3 = ctx -> Seed[ 2 ]; + Seed4 = ctx -> Seed[ 3 ]; + Seed5 = ctx -> Seed[ 4 ]; + Seed6 = ctx -> Seed[ 5 ]; + Seed7 = ctx -> Seed[ 6 ]; + Seed8 = ctx -> Seed[ 7 ]; + } + else + { + ctx -> IsHashing = 1; + + const uint64_t UseSeed = ctx -> Seed[ 0 ]; + Seed1 = 0x243F6A8885A308D3 ^ ( UseSeed & 0x5555555555555555 ); + Seed5 = 0x452821E638D01377 ^ ( UseSeed & 0xAAAAAAAAAAAAAAAA ); + + KOMIHASH_HASHROUND(); + + Seed2 = 0x13198A2E03707344 ^ Seed1; + Seed3 = 0xA4093822299F31D0 ^ Seed1; + Seed4 = 0x082EFA98EC4E6C89 ^ Seed1; + Seed6 = 0xBE5466CF34E90C6C ^ Seed5; + Seed7 = 0xC0AC29B7C97C50DD ^ Seed5; + Seed8 = 0x3F84D5B5B5470917 ^ Seed5; + } + + KOMIHASH_HASHLOOP64(); + + ctx -> Seed[ 0 ] = Seed1; + ctx -> Seed[ 1 ] = Seed2; + ctx -> Seed[ 2 ] = Seed3; + ctx -> Seed[ 3 ] = Seed4; + ctx -> Seed[ 4 ] = Seed5; + ctx -> Seed[ 5 ] = Seed6; + ctx -> Seed[ 6 ] = Seed7; + ctx -> Seed[ 7 ] = Seed8; + + if( SwMsgLen == 0 ) + { + if( MsgLen == 0 ) + { + ctx -> fb[ 7 ] = Msg[ -1 ]; + ctx -> BufFill = 0; + return; + } + + break; + } + + Msg = SwMsg; + MsgLen = SwMsgLen; + SwMsgLen = 0; + } + } + + memcpy( ctx -> Buf + BufFill, Msg, MsgLen ); + ctx -> BufFill = BufFill + MsgLen; +} + +/** + * Function finalizes the streamed hashing session, and returns the resulting + * hash value of the previously hashed data. This value is equal to the value + * returned by the komihash() function for the same provided data. + * + * Note that since this function is non-destructive for the context structure, + * the function can be used to obtain intermediate hashes of the data stream + * being hashed, and the hashing can then be resumed. + * + * @param[in] ctx Pointer to the context structure. The structure must be + * initialized via the komihash_stream_init() function. + * @return 64-bit hash value. + */ + +static inline uint64_t komihash_stream_final( komihash_stream_t* const ctx ) +{ + const uint8_t* Msg = ctx -> Buf; + size_t MsgLen = ctx -> BufFill; + + if( ctx -> IsHashing == 0 ) + { + return( komihash( Msg, MsgLen, ctx -> Seed[ 0 ])); + } + + ctx -> fb[ 4 ] = 0; + ctx -> fb[ 5 ] = 0; + ctx -> fb[ 6 ] = 0; + + uint64_t Seed1 = ctx -> Seed[ 0 ]; + uint64_t Seed2 = ctx -> Seed[ 1 ]; + uint64_t Seed3 = ctx -> Seed[ 2 ]; + uint64_t Seed4 = ctx -> Seed[ 3 ]; + uint64_t Seed5 = ctx -> Seed[ 4 ]; + uint64_t Seed6 = ctx -> Seed[ 5 ]; + uint64_t Seed7 = ctx -> Seed[ 6 ]; + uint64_t Seed8 = ctx -> Seed[ 7 ]; + + if( MsgLen > 63 ) + { + uint64_t r1h, r2h, r3h, r4h; + + KOMIHASH_HASHLOOP64(); + } + + Seed5 ^= Seed6 ^ Seed7 ^ Seed8; + Seed1 ^= Seed2 ^ Seed3 ^ Seed4; + + return( komihash_epi( Msg, MsgLen, Seed1, Seed5 )); +} + +/** + * FOR TESTING PURPOSES ONLY - use the komihash() function instead. + * + * @param Msg The message to produce a hash from. + * @param MsgLen Message's length, in bytes. + * @param UseSeed Seed to use. + * @return 64-bit hash value. + */ + +static inline uint64_t komihash_stream_oneshot( const void* const Msg, + const size_t MsgLen, const uint64_t UseSeed ) +{ + komihash_stream_t ctx; + + komihash_stream_init( &ctx, UseSeed ); + komihash_stream_update( &ctx, Msg, MsgLen ); + + return( komihash_stream_final( &ctx )); +} + +#endif // KOMIHASH_INCLUDED diff --git a/lib/komihash/testvec.c b/lib/komihash/testvec.c new file mode 100644 index 00000000..3a405381 --- /dev/null +++ b/lib/komihash/testvec.c @@ -0,0 +1,99 @@ +/** + * testvec.c version 4.3.1 + * + * The program that lists test vectors and their hash values, for the current + * version of komihash. Also prints initial outputs of `komirand` PRNG. + * + * Description is available at https://github.com/avaneev/komihash + * + * License + * + * Copyright (c) 2021-2022 Aleksey Vaneev + * + * 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. + */ + +#include +#include "komihash.h" + +int main() +{ + const int seedc = 3; + const uint64_t seeds[ seedc ] = { 0, 0x0123456789ABCDEF, 256 }; + + const int strc = 5; + const char* const strs[ strc ] = { + "This is a 32-byte tester string.", + "The cat is out of the bag", + "A 16-byte string", + "The new string", + "7 bytes" + }; + + const int bulkc = 15; + const int bulks[ bulkc ] = { 6, 12, 20, 31, 32, 40, 47, 48, 56, 64, + 72, 80, 112, 132, 256 }; + + uint8_t bulkbuf[ 256 ]; + int i; + + for( i = 0; i < 256; i++ ) + { + bulkbuf[ i ] = (uint8_t) i; + } + + int j; + + for( j = 0; j < seedc; j++ ) + { + printf( "\tkomihash UseSeed = 0x%016llx:\n", seeds[ j ]); + + for( i = 0; i < strc; i++ ) + { + const char* const s = strs[ i ]; + const size_t sl = strlen( s ); + + printf( "\t\"%s\" = 0x%016llx\n", s, + komihash( s, sl, seeds[ j ])); + } + + for( i = 0; i < bulkc; i++ ) + { + printf( "\tbulk(%i) = 0x%016llx\n", bulks[ i ], + komihash( bulkbuf, bulks[ i ], seeds[ j ])); + } + + printf( "\n" ); + } + + for( j = 0; j < seedc; j++ ) + { + printf( "\tkomirand Seed1/Seed2 = 0x%016llx:\n", seeds[ j ]); + + uint64_t Seed1 = seeds[ j ]; + uint64_t Seed2 = seeds[ j ]; + + for( i = 0; i < 12; i++ ) + { + printf( "\t0x%016llx\n", komirand( &Seed1, &Seed2 )); + } + + printf( "\n" ); + } +} diff --git a/tools/cmake/common.cmake b/tools/cmake/common.cmake index acb017a4..1c24c5db 100644 --- a/tools/cmake/common.cmake +++ b/tools/cmake/common.cmake @@ -7,6 +7,7 @@ set(COMPONENTS "") # External dependencies list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/catch2") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/cbor") +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/komihash") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libmad") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/libtags") list(APPEND EXTRA_COMPONENT_DIRS "$ENV{PROJ_PATH}/lib/lvgl")