Repository: thomasmueller/minperf
Branch: master
Commit: f97c859b5c4a
Files: 103
Total size: 983.5 KB
Directory structure:
gitextract_zbe5o8p1/
├── .gitignore
├── LICENSE
├── MAVEN.md
├── README.md
├── pom.xml
├── runjmh.sh
└── src/
├── main/
│ ├── c/
│ │ ├── Makefile
│ │ ├── filter/
│ │ │ ├── Makefile
│ │ │ └── xor.c
│ │ └── rec-split.c
│ └── java/
│ └── org/
│ └── minperf/
│ ├── BitBuffer.java
│ ├── RecSplitBuilder.java
│ ├── RecSplitEvaluator.java
│ ├── Settings.java
│ ├── bdz/
│ │ └── BDZ.java
│ ├── generator/
│ │ ├── ConcurrencyTool.java
│ │ └── Generator.java
│ ├── hash/
│ │ ├── HashPerformanceTest.java
│ │ ├── LongPair.java
│ │ ├── Mix.java
│ │ ├── Murmur2.java
│ │ ├── Murmur3.java
│ │ ├── SpookyHash.java
│ │ └── XXHash64.java
│ ├── hem/
│ │ ├── HemGenerator.java
│ │ ├── KeyReader.java
│ │ ├── Sort.java
│ │ ├── SortedSignatures.java
│ │ └── recsplit/
│ │ ├── Builder.java
│ │ ├── FastEvaluator.java
│ │ └── FastGenerator.java
│ ├── monotoneList/
│ │ ├── EliasFanoMonotoneList.java
│ │ ├── MonotoneList.java
│ │ └── MultiStageMonotoneList.java
│ ├── rank/
│ │ ├── Rank9.java
│ │ └── VerySimpleRank.java
│ ├── select/
│ │ ├── Select.java
│ │ ├── SimpleSelect.java
│ │ ├── SimpleSelectWrapper.java
│ │ └── VerySimpleSelect.java
│ ├── universal/
│ │ ├── LongHash.java
│ │ ├── StringHash.java
│ │ └── UniversalHash.java
│ └── utils/
│ ├── LargeLongList.java
│ ├── LongSet.java
│ ├── PoissonDistribution.java
│ ├── RandomSetGenerator.java
│ ├── RandomSetGeneratorSlow.java
│ └── Text.java
└── test/
└── java/
└── org/
└── minperf/
├── BitCodes.java
├── FunctionInfo.java
├── Graphics.java
├── LargeSetTest.java
├── Paper.java
├── PerformanceTest.java
├── Probability.java
├── RandomizedTest.java
├── SettingsTest.java
├── SpaceEstimator.java
├── SplitRuleTest.java
├── SplitRuleTest2.java
├── SplitRuleTest3.java
├── TestSplitStrategy.java
├── TextFileTest.java
├── TimeEstimator.java
├── WikipediaTest.java
├── bdz/
│ └── BDZTest.java
├── c/
│ └── HashGenerator.java
├── chd/
│ ├── CHD.java
│ ├── CHD2.java
│ ├── CHDTest.java
│ ├── EliasFanoList.java
│ └── EliasFanoListTest.java
├── cuckoo/
│ ├── CuckooHashMap.java
│ ├── CuckooHashTest.java
│ └── CuckooLongKeyHashSet.java
├── hash/
│ └── MixTest.java
├── hem/
│ ├── HEM.java
│ ├── MetaFile.java
│ ├── RandomGenerator.java
│ └── recsplit/
│ └── TestFast.java
├── hybrid/
│ └── HybridTest.java
├── medium/
│ ├── EstimateTimeForHugeSets.java
│ ├── EstimateTwoBillionEntries.java
│ ├── MediumRecSplit.java
│ ├── MediumTest.java
│ ├── PartitionIntoSimilarSizedSets.java
│ ├── RecSplitEliasFano.java
│ ├── SimulateProbFallIntoLarge.java
│ └── TestBBHash.java
├── monotoneList/
│ ├── FenwickTreeMonotoneList.java
│ └── MonotoneListTest.java
├── rank/
│ ├── Rank9Test.java
│ └── RankTest.java
├── select/
│ └── SelectTest.java
├── simple/
│ ├── LongCollection.java
│ ├── SimpleRecSplit.java
│ ├── SimpleTest.java
│ └── recsplit.md
├── tools/
│ ├── Dump.java
│ └── Load.java
└── utils/
├── FastDigitFromNumberExtraction.java
└── TextTest.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.checkstyle
.classpath
.project
.settings
bin
/target/
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: MAVEN.md
================================================
Please ensure that unit tests actually pass.
```
mvn clean install -DskipTests
java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBench
```
================================================
FILE: README.md
================================================
# minperf
A Minimal Perfect Hash Function Library.
* Mainly written in Java. Includes a C version (currently only evaluation of a MPHF).
* Can generate, in linear time, MPHFs that need less than 1.58 bits per key.
* Can generate MPHFs in less than 100 ns/key, evaluation faster than 100 ns/key, at less than 3 bits per key.
* Concurrent generation.
* Tested up to 1 billion keys.
* Two parameters to configure space needed, generation time, and evaluation time.
* Can be used as a static bloom filter, by storing a hash fingerprint per key.
* Performance very similar than the [Sux4J](https://github.com/vigna/Sux4J) CHD and GOV algorithms, but configurable, with ability to use less space.
This library should already be usable, but it is still work in progress. The plan is to publish a paper.
The algorithm used is described [here as text](https://github.com/thomasmueller/minperf/blob/master/src/test/java/org/minperf/simple/recsplit.md), and
[here as slideshow](https://github.com/thomasmueller/minperf/raw/master/src/test/java/org/minperf/simple/recsplit.pdf) ([also available on SlideShare](https://www.slideshare.net/ThomasMueller12/recsplit-minimal-perfect-hashing)).
================================================
FILE: pom.xml
================================================
4.0.0thomasmuellerminperf1.0-SNAPSHOT1.4UTF-8benchmarksjarorg.apache.maven.pluginsmaven-compiler-plugin2.3.21.81.8maven-assembly-pluginpackagesinglejar-with-dependenciesjunitjunit4.13.1testorg.openjdk.jmhjmh-core${jmh.version}org.openjdk.jmhjmh-generator-annprocess${jmh.version}provided
================================================
FILE: runjmh.sh
================================================
mvn clean install -DskipTests && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBench > JmhBench.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchBloom > JmhBenchBloom.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchCuckoo8_4 > JmhBenchCuckoo8_4.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchCuckoo16_4 > JmhBenchCuckoo16_4.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchXor8 > JmhBenchXor8.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchXor16 > JmhBenchXor16.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchXor16 > JmhBenchXor16.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchXor > JmhBenchXor.log && java -Xmx16g -cp target/minperf-1.0-SNAPSHOT-jar-with-dependencies.jar org.minperf.bloom.JmhBenchCuckoo > JmhBenchCuckoo.log
================================================
FILE: src/main/c/Makefile
================================================
#
# RecSplit for C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
TARGETS = rec-split
CC = gcc
CFLAGS = -Wall -g -O3
all: $(TARGETS)
rec-split: rec-split.o
# gcc rec-split.o -o rec-split
rec-split.o: rec-split.c
# gcc -c rec-split.c -o rec-split.o
clean:
rm -f *.a *.o $(TARGETS)
decompile:
objdump -S --disassemble rec-split
================================================
FILE: src/main/c/filter/Makefile
================================================
#
# RecSplit for C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
TARGETS = xor
CC = gcc
CFLAGS = -Wall -g -O3
all: $(TARGETS)
xor: xor.o
# gcc xor.o -o xor
xor.o: xor.c
# gcc -c xor.c -o xor.o
clean:
rm -f *.a *.o $(TARGETS)
decompile:
objdump -S --disassemble xor
================================================
FILE: src/main/c/filter/xor.c
================================================
#include
#include
#include
#include
#include
#include
#include
#include
#include
// file I/O
int64_t getFileSize(FILE* fp) {
struct stat buf;
int fd = fileno(fp);
fstat(fd, &buf);
int64_t size = buf.st_size;
return size;
}
int loadFile(char* directory, char* fileName, uint8_t** target) {
if (!fileName || !directory) {
printf("No file\n");
return 0;
}
char* fullFileName = malloc(strlen(directory) + strlen(fileName) + 2);
sprintf(fullFileName, "%s/%s", directory, fileName);
printf("Loading file %s\n", fullFileName);
FILE* fp = fopen(fullFileName, "r");
free(fullFileName);
if (!fp) {
printf("Could not open file\n");
return 0;
}
int64_t fileSize = getFileSize(fp);
printf("File size: %lld\n", fileSize);
*target = malloc(fileSize);
size_t len = fread(*target, fileSize, 1, fp);
if (len != 1) {
printf("Could not full read the file\n");
return 0;
}
fclose(fp);
printf("(%lld bytes)\n", fileSize);
return 1;
}
// bit manipulation
uint64_t rotateLeft64(uint64_t x, uint32_t n) {
// TODO check if this is the best way, and if it always works as expected
return (x << (n & 63)) | (x >> (64 - (n & 63)));
}
int numberOfLeadingZeros64(uint64_t x) {
// If x is 0, the result is undefined.
return __builtin_clzl(x);
}
int numberOfLeadingZeros32(uint32_t x) {
// If x is 0, the result is undefined.
return __builtin_clz(x);
}
// hashing related
inline uint32_t reduce(uint32_t hash, uint32_t n) {
// http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
return (uint32_t) (((uint64_t) hash * n) >> 32);
}
// from https://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc/11660651#11660651
typedef unsigned __int128 uint128_t;
// data
uint8_t* data;
uint32_t getArrayLength(uint32_t size) {
return (uint32_t) (3 + (uint64_t) 123 * size / 100);
}
uint64_t hash64(uint64_t x) {
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9L;
x = (x ^ (x >> 27)) * 0x94d049bb133111ebL;
x = x ^ (x >> 31);
return x;
}
uint32_t fingerprint(uint64_t hash) {
return (uint32_t) (hash & ((1 << 8) - 1));
}
// XorFilter8
struct XorFilter8 {
uint32_t size;
uint32_t arrayLength;
uint32_t blockLength;
uint32_t hashIndex;
uint8_t* fingerprints;
};
struct XorFilter8 filter;
void XorFilter_load(struct XorFilter8* this) {
printf("Loading...\n");
this->size = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
printf("Size %d\n", this->size);
this->hashIndex = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
printf("HashIndex %d\n", this->hashIndex);
this->arrayLength = getArrayLength(this->size);
this->blockLength = this->arrayLength / 3;
this->fingerprints = data + 8;
}
uint32_t XorFilter_mayContain(struct XorFilter8* this, uint64_t key) {
uint64_t hash = hash64(key + this->hashIndex);
uint32_t f = fingerprint(hash);
uint32_t r0 = (uint32_t) hash;
uint32_t r1 = (uint32_t) (hash >> 16);
uint32_t r2 = (uint32_t) (hash >> 32);
uint32_t h0 = reduce(r0, this->blockLength);
uint32_t h1 = reduce(r1, this->blockLength) + this->blockLength;
uint32_t h2 = reduce(r2, this->blockLength) + 2 * this->blockLength;
f ^= this->fingerprints[h0] ^ this->fingerprints[h1] ^ this->fingerprints[h2];
return (f & 0xff) == 0;
}
// demo
int main(int argc, char** argv) {
char* directory = ".";
++argv;
--argc;
if (argc > 0) {
directory = argv[0];
++argv;
--argc;
}
printf("Directory %s\n", directory);
char* hashFile = "hash.bin";
char* keyFile = "keys.txt";
if (!loadFile(directory, hashFile, &data)) {
return 0;
}
FILE* input;
if(!keyFile) {
input = stdin;
} else {
char* fullFileName = malloc(strlen(directory) + strlen(keyFile) + 2);
sprintf(fullFileName, "%s/%s", directory, keyFile);
printf("Loading file %s\n", fullFileName);
input = fopen(fullFileName, "rb");
free(fullFileName);
if (!input) {
printf("Could not open file %s\n", keyFile);
return 0;
}
}
XorFilter_load(&filter);
char line[255];
// used to measure time of i/o
// (it turned out to be 50 ns / key)
/*
for(int i=0; i<5; i++) {
clock_t start = clock();
int64_t sum = 0;
while (fgets(line, 255, input)) {
int len = strlen(line);
// trim
while (len > 0 && line[len - 1] < ' ') {
line[--len] = 0;
}
sum += len;
}
clock_t time = (clock() - start);
printf("sum: %lld sec: %ld %d\n", sum, time, CLOCKS_PER_SEC);
rewind(input);
}
*/
clock_t start = clock();
int64_t sum = 0;
while (fgets(line, 255, input)) {
int len = strlen(line);
// trim
while (len > 0 && line[len - 1] < ' ') {
line[--len] = 0;
}
uint64_t key = atoll(line);
uint32_t contain = XorFilter_mayContain(&filter, key);
sum += contain;
}
clock_t time = (clock() - start);
printf("Sum: %lld time: %ld ticks, at %d ticks/second\n", sum, time, CLOCKS_PER_SEC);
free(data);
return 0;
}
================================================
FILE: src/main/c/rec-split.c
================================================
#include
#include
#include
#include
#include
#include
#include
#include
#include
// file I/O
int64_t getFileSize(FILE* fp) {
struct stat buf;
int fd = fileno(fp);
fstat(fd, &buf);
int64_t size = buf.st_size;
return size;
}
void fixEndian(uint64_t* longArray, uint64_t byteCount) {
uint8_t* byteArray = (uint8_t*) longArray;
uint64_t l=0;
uint64_t b=0;
while(b> (64 - (n & 63)));
}
int numberOfLeadingZeros64(uint64_t x) {
// If x is 0, the result is undefined.
return __builtin_clzl(x);
}
int numberOfLeadingZeros32(uint32_t x) {
// If x is 0, the result is undefined.
return __builtin_clz(x);
}
// hashing related
inline uint32_t reduce(uint32_t hash, uint32_t n) {
// http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
return (uint32_t) (((uint64_t) hash * n) >> 32);
}
uint64_t getScaleFactor(uint32_t multiply, uint32_t divide) {
return divide == 0 ? 0 : ((uint64_t) multiply << 32) / divide + 1;
}
// from https://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc/11660651#11660651
typedef unsigned __int128 uint128_t;
uint128_t getSipHash24b128(char* b, int start, int end, uint64_t k0, uint64_t k1) {
uint64_t v0 = k0 ^ 0x736f6d6570736575L;
uint64_t v1 = k1 ^ 0x646f72616e646f6dL;
uint64_t v2 = k0 ^ 0x6c7967656e657261L;
uint64_t v3 = k1 ^ 0x7465646279746573L;
int repeat;
for (int off = start; off <= end + 8; off += 8) {
long m;
if (off <= end) {
m = 0;
int i = 0;
for (; i < 8 && off + i < end; i++) {
m |= ((uint64_t) b[off + i] & 255) << (8 * i);
}
if (i < 8) {
m |= ((uint64_t) end - start) << 56;
}
v3 ^= m;
repeat = 2;
} else {
m = 0;
v2 ^= 0xff;
repeat = 4;
}
for (int i = 0; i < repeat; i++) {
v0 += v1;
v2 += v3;
v1 = rotateLeft64(v1, 13);
v3 = rotateLeft64(v3, 16);
v1 ^= v0;
v3 ^= v2;
v0 = rotateLeft64(v0, 32);
v2 += v1;
v0 += v3;
v1 = rotateLeft64(v1, 17);
v3 = rotateLeft64(v3, 21);
v1 ^= v2;
v3 ^= v0;
v2 = rotateLeft64(v2, 32);
}
v0 ^= m;
}
return ((uint128_t) (v0 ^ v1) << 64) ^ v2 ^ v3;
}
uint64_t getSipHash24b(char* b, int start, int end, uint64_t k0, uint64_t k1) {
uint64_t v0 = k0 ^ 0x736f6d6570736575L;
uint64_t v1 = k1 ^ 0x646f72616e646f6dL;
uint64_t v2 = k0 ^ 0x6c7967656e657261L;
uint64_t v3 = k1 ^ 0x7465646279746573L;
int repeat;
for (int off = start; off <= end + 8; off += 8) {
long m;
if (off <= end) {
m = 0;
int i = 0;
for (; i < 8 && off + i < end; i++) {
m |= ((uint64_t) b[off + i] & 255) << (8 * i);
}
if (i < 8) {
m |= ((uint64_t) end - start) << 56;
}
v3 ^= m;
repeat = 2;
} else {
m = 0;
v2 ^= 0xff;
repeat = 4;
}
for (int i = 0; i < repeat; i++) {
v0 += v1;
v2 += v3;
v1 = rotateLeft64(v1, 13);
v3 = rotateLeft64(v3, 16);
v1 ^= v0;
v3 ^= v2;
v0 = rotateLeft64(v0, 32);
v2 += v1;
v0 += v3;
v1 = rotateLeft64(v1, 17);
v3 = rotateLeft64(v3, 21);
v1 ^= v2;
v3 ^= v0;
v2 = rotateLeft64(v2, 32);
}
v0 ^= m;
}
return v0 ^ v1 ^ v2 ^ v3;
}
uint64_t getSipHash24(char* b, uint64_t k0, uint64_t k1) {
// TODO assuming 8 bits per char
return getSipHash24b(b, 0, strlen(b), k0, k1);
}
uint64_t universalHash(char* key, uint64_t index) {
return getSipHash24(key, index, index);
}
// BitBuffer
uint64_t* data;
uint64_t pos;
uint64_t readBit() {
uint64_t p = pos++;
return (data[p >> 6] >> (63 - (p & 63))) & 1;
}
uint64_t readEliasDelta() {
int qq = 0;
while (readBit() == 0) {
qq++;
}
int64_t q = 1;
for (int i = qq; i > 0; i--) {
q = (q << 1) | readBit();
}
uint64_t x = 1;
for (int64_t i = q - 2; i >= 0; i--) {
x = (x << 1) | readBit();
}
return x;
}
uint64_t readNumber(uint64_t pos, int bitCount) {
if (bitCount == 0) {
return 0;
}
int remainingBits = 64 - (pos & 63);
int index = pos >> 6;
long x = data[index];
if (bitCount <= remainingBits) {
x >>= remainingBits - bitCount;
return x & ((1L << bitCount) - 1);
}
x = x & ((1L << remainingBits) - 1);
return (x << (bitCount - remainingBits)) |
(data[index + 1] >> (64 - bitCount + remainingBits));
}
uint32_t supplementalHash(uint64_t hash, uint64_t index) {
// it would be better to use long,
// but with some processors, 32-bit multiplication
// seem to be much faster
// (about 1200 ms for 32 bit, about 2000 ms for 64 bit)
uint32_t x = (uint32_t) (rotateLeft64(hash, (uint32_t) index) ^ index);
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = (x >> 16) ^ x;
return x;
}
uint64_t unfoldSigned(uint64_t x) {
return ((x & 1) == 1) ? (x + 1) / 2 : -(x / 2);
}
int getEliasDeltaSize(uint64_t value) {
if (value <= 0) {
// illegal argument
return -1;
}
int q = 64 - numberOfLeadingZeros64(value);
int qq = 31 - numberOfLeadingZeros32(q);
int len = qq + qq + q;
return len;
}
int readUntilZeroMore(int count, uint64_t pos) {
while (true) {
long x = data[++pos];
if (x == -1L) {
count += 64;
continue;
}
return count + numberOfLeadingZeros64(~x);
}
}
int readUntilZero(uint64_t pos) {
int remainingBits = 64 - (pos & 63);
uint64_t index = pos >> 6;
uint64_t x = data[index] << (64 - remainingBits);
int count = numberOfLeadingZeros64(~x);
if (count < remainingBits) {
return count;
}
return readUntilZeroMore(count, index);
}
uint64_t skipGolombRice(uint64_t pos, int shift) {
int q = readUntilZero(pos);
return pos + q + 1 + shift;
}
// MultiStageMonotoneList
struct MultiStageMonotoneList {
uint64_t startLevel1, startLevel2, startLevel3;
int bitCount1, bitCount2, bitCount3;
uint32_t count1, count2, count3;
uint64_t factor;
uint32_t add;
};
struct MultiStageMonotoneList list;
#define SHIFT1 6
#define SHIFT2 3
#define FACTOR1 32
#define FACTOR2 16
void MultiStageMonotoneList_load(struct MultiStageMonotoneList* this) {
this->count3 = (uint32_t) readEliasDelta() - 1;
int diff = (uint32_t) readEliasDelta() - 1;
this->factor = getScaleFactor(diff, this->count3);
this->add = (uint32_t) unfoldSigned(readEliasDelta() - 1);
this->bitCount1 = (int) readEliasDelta() - 1;
this->bitCount2 = (int) readEliasDelta() - 1;
this->bitCount3 = (int) readEliasDelta() - 1;
this->startLevel1 = pos;
this->count2 = (this->count3 + (1 << SHIFT2) - 1) >> SHIFT2;
this->count1 = (this->count3 + (1 << SHIFT1) - 1) >> SHIFT1;
this->startLevel2 = this->startLevel1 + this->count1 * this->bitCount1;
this->startLevel3 = this->startLevel2 + this->count2 * this->bitCount2;
pos = (this->startLevel3 + this->bitCount3 * this->count3);
}
uint32_t MultiStageMonotoneList_get(struct MultiStageMonotoneList* this, uint32_t i) {
int expected = (int) ((i * this->factor) >> 32) + this->add;
long a = readNumber(this->startLevel1 + (i >> SHIFT1) * this->bitCount1, this->bitCount1);
long b = readNumber(this->startLevel2 + (i >> SHIFT2) * this->bitCount2, this->bitCount2);
long c = readNumber(this->startLevel3 + i * this->bitCount3, this->bitCount3);
return (int) (expected + a * FACTOR1 + b * FACTOR2 + c);
}
uint64_t MultiStageMonotoneList_getPair(struct MultiStageMonotoneList* this, uint32_t i) {
return ((uint64_t) MultiStageMonotoneList_get(this, i) << 32) | (MultiStageMonotoneList_get(this, i + 1));
}
// Settings
#define MAX_SIZE 4096
#define SUPPLEMENTAL_HASH_SHIFT 18
struct Settings {
int leafSize;
int averageBucketSize;
int rice[MAX_SIZE];
int splits[MAX_SIZE];
};
struct Settings settings;
void Settings_load(struct Settings* this) {
this->leafSize = readEliasDelta() - 1;
this->averageBucketSize = readEliasDelta() - 1;
uint32_t len = readEliasDelta() - 1;
printf("Loading settings: leafSize: %d, averageBucketSize: %d, maxBucketSize: %d\n",
this->leafSize,
this->averageBucketSize,
len);
for(int i=0; isplits[i] = unfoldSigned(readEliasDelta() - 1);
this->rice[i] = readEliasDelta() - 1;
// if (i < 32)
// printf(" %d: rice=%d, splits: %d\n", i, this->rice[i], this->splits[i]);
}
}
uint64_t getUniversalHashIndex(uint64_t index) {
return index >> SUPPLEMENTAL_HASH_SHIFT;
}
// RecSplitEvaluator
struct RecSplitEvaluator {
uint64_t size;
uint32_t bucketCount;
uint32_t minStartDiff;
struct MultiStageMonotoneList startList;
uint32_t minOffsetDiff;
struct MultiStageMonotoneList offsetList;
uint32_t startBuckets;
uint32_t endHeader;
uint32_t endOffsetList;
};
struct RecSplitEvaluator evaluator;
uint32_t getBucketCount(uint64_t size, int averageBucketSize) {
return (uint32_t) ((size + averageBucketSize - 1) / averageBucketSize);
}
void RecSplitEvaluator_load(struct RecSplitEvaluator* this) {
this->size = readEliasDelta() - 1;
printf("Hash size %lld\n", this->size);
this->bucketCount = getBucketCount(this->size, settings.averageBucketSize);
printf("Buckets: %d\n", this->bucketCount);
int alternative = readBit() != 0;
if (alternative) {
// not supported
printf("Not supported: alternative hash\n");
return;
}
this->minOffsetDiff = (uint32_t) (readEliasDelta() - 1);
// printf("minOffsetDiff: %d\n", this->minOffsetDiff);
this->minStartDiff = (uint32_t) (readEliasDelta() - 1);
// printf("minStartDiff: %d\n", this->minStartDiff);
this->endHeader = pos;
MultiStageMonotoneList_load(&(this->offsetList));
this->endOffsetList = pos;
MultiStageMonotoneList_load(&(this->startList));
this->startBuckets = pos;
// printf("hash loaded\n");
}
uint32_t getMinBitCount(uint32_t size) {
// at least 1.375 bits per key (if it is less, fill with zeroes)
return (size * 11 + 7) >> 3;
}
uint32_t skip(struct RecSplitEvaluator* this, uint64_t pos, uint32_t size) {
if (size < 2) {
return pos;
}
pos = skipGolombRice(pos, settings.rice[size]);
if (size <= settings.leafSize) {
return pos;
}
int split = settings.splits[size];
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
int s = firstPart;
for (int i = 0; i < split; i++) {
pos = skip(this, pos, s);
s = otherPart;
}
return pos;
}
uint32_t evaluate2(struct RecSplitEvaluator* this, uint64_t pos, char* obj, uint64_t hashCode,
uint64_t index, uint32_t add, uint32_t size) {
while (true) {
if (size < 2) {
return add;
}
int shift = settings.rice[size];
uint64_t q = readUntilZero(pos);
pos += q + 1;
uint64_t value = (q << shift) | readNumber(pos, shift);
pos += shift;
uint64_t oldX = getUniversalHashIndex(index);
index += value + 1;
uint64_t x = getUniversalHashIndex(index);
if (x != oldX) {
hashCode = universalHash(obj, x);
}
if (size <= settings.leafSize) {
int h = supplementalHash(hashCode, index);
h = reduce(h, size);
//printf("shift %d q %d value %lld oldX %lld x %lld size %d h %d add %d\n", shift, q, value, oldX, x, size, h, add);
return add + h;
}
int split = settings.splits[size];
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
int h = supplementalHash(hashCode, index);
if (firstPart != otherPart) {
h = reduce(h, size);
if (h < firstPart) {
size = firstPart;
continue;
}
pos = skip(this, pos, firstPart);
add += firstPart;
size = otherPart;
continue;
}
h = reduce(h, split);
for (int i = 0; i < h; i++) {
pos = skip(this, pos, firstPart);
add += firstPart;
}
size = firstPart;
}
}
uint64_t evaluate(struct RecSplitEvaluator* this, char* obj) {
uint64_t hashCode = universalHash(obj, 0);
//printf(" hashCode %s = %lld\n", obj, hashCode);
uint32_t b;
if (this->bucketCount == 1) {
b = 0;
} else {
b = reduce((uint32_t) hashCode, this->bucketCount);
}
//printf(" bucket %d\n", b);
uint32_t startPos;
uint64_t offsetPair = MultiStageMonotoneList_getPair(&this->offsetList, b);
uint32_t offset = (uint32_t) (offsetPair >> 32) + b * this->minOffsetDiff;
uint32_t offsetNext = ((uint32_t) offsetPair) + (b + 1) * this->minOffsetDiff;
if (offsetNext == offset) {
// entry not found
return 0;
}
uint32_t bucketSize = offsetNext - offset;
startPos = this->startBuckets +
getMinBitCount(offset) +
MultiStageMonotoneList_get(&this->startList, b) + b * this->minStartDiff;
// printf(" startPos %d offset %d bucketSize %d\n", startPos, offset, bucketSize);
return evaluate2(this, startPos, obj, hashCode, 0, offset, bucketSize);
}
// demo
int main(int argc, char** argv) {
char* directory = ".";
++argv;
--argc;
if (argc > 0) {
directory = argv[0];
++argv;
--argc;
}
printf("Directory %s\n", directory);
char* settingsFile = "settings.bin";
char* hashFile = "hash.bin";
char* keyFile = "keys.txt";
if (!loadFile(directory, settingsFile, &data)) {
return 0;
}
Settings_load(&settings);
free(data);
if (!loadFile(directory, hashFile, &data)) {
return 0;
}
FILE* input;
if(!keyFile) {
input = stdin;
} else {
char* fullFileName = malloc(strlen(directory) + strlen(keyFile) + 2);
sprintf(fullFileName, "%s/%s", directory, keyFile);
printf("Loading file %s\n", fullFileName);
input = fopen(fullFileName, "rb");
free(fullFileName);
if (!input) {
printf("Could not open file %s\n", keyFile);
return 0;
}
}
pos = 0;
RecSplitEvaluator_load(&evaluator);
char line[255];
// used to measure time of i/o
// (it turned out to be 50 ns / key)
/*
for(int i=0; i<5; i++) {
clock_t start = clock();
int64_t sum = 0;
while (fgets(line, 255, input)) {
int len = strlen(line);
// trim
while (len > 0 && line[len - 1] < ' ') {
line[--len] = 0;
}
sum += len;
}
clock_t time = (clock() - start);
printf("sum: %lld sec: %ld %d\n", sum, time, CLOCKS_PER_SEC);
rewind(input);
}
*/
clock_t start = clock();
int64_t sum = 0;
while (fgets(line, 255, input)) {
int len = strlen(line);
// trim
while (len > 0 && line[len - 1] < ' ') {
line[--len] = 0;
}
uint64_t index = evaluate(&evaluator, line);
sum += index;
}
clock_t time = (clock() - start);
// with leafSize 8 and averageBucketSize 128 and 10 million keys,
// that is 1.79 bits/key, average key length 55 bits/key,
// evaluate takes about 220 ns/key with -O3, and 260 ns/key with -Os
// with leafSize 6 and averageBucketSize 18 and 10 million keys,
// that is 2.33 bits/key, average key length 55 bits/key,
// evaluate takes about 140 ns/key with -O3
printf("sum: %lld time: %ld ticks, at %d ticks/second\n", sum, time, CLOCKS_PER_SEC);
free(data);
return 0;
}
================================================
FILE: src/main/java/org/minperf/BitBuffer.java
================================================
package org.minperf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
/**
* A simple bit buffer. It is partially optimized for reading, but writing is
* relatively slow. Writing will only add bits (bitwise or with existing bits).
*/
public class BitBuffer {
public final long[] data;
private int pos;
public BitBuffer(long bits) {
this.data = new long[(int)((bits + 63) / 64)];
}
public BitBuffer(byte[] data) {
this.data = new long[(data.length + 7) / 8];
if (this.data.length != data.length * 8) {
data = Arrays.copyOf(data, this.data.length * 8);
}
ByteBuffer.wrap(data).order(ByteOrder.BIG_ENDIAN).asLongBuffer().get(this.data);
}
/**
* Create a buffer that shared the byte data, but uses a separate position
* (initially 0).
*
* @param buffer the buffer
*/
public BitBuffer(BitBuffer buffer) {
this.data = buffer.data;
}
public void write(BitBuffer bits) {
int count = bits.pos;
bits.pos = 0;
// for (int i = 0; i < count; i++) {
// writeBit(bits.readBit());
// }
int i = 0;
for (; i < count - 31; i += 32) {
writeNumber(bits.readNumber(32), 32);
}
for (; i < count; i++) {
writeBit(bits.readBit());
}
}
public int position() {
return pos;
}
public void seek(int pos) {
this.pos = pos;
}
/**
* Read a number.
*
* @param bitCount the number of bits, at most 63
* @return the value
*/
public long readNumber(int bitCount) {
long x = readNumber(pos, bitCount);
pos += bitCount;
return x;
}
public long readLong() {
return (readNumber(32) << 32) | readNumber(32);
}
/**
* Read a number.
*
* @param pos the position
* @param bitCount the number of bits, at most 63
* @return the value
*/
public long readNumber(long pos, int bitCount) {
if (bitCount == 0) {
return 0;
}
int remainingBits = 64 - ((int) pos & 63);
int index = (int) (pos >>> 6);
long x = data[index];
if (bitCount <= remainingBits) {
x >>>= remainingBits - bitCount;
return x & ((1L << bitCount) - 1);
}
x = x & ((1L << remainingBits) - 1);
return (x << (bitCount - remainingBits)) |
(data[index + 1] >>> (64 - bitCount + remainingBits));
}
/**
* Fold a signed number into an unsigned number. Negative numbers are odd,
* and positive numbers are even. For example, -5 is converted to 11, and 5
* to 10.
*
* @param x a signed number
* @return an unsigned number
*/
public static long foldSigned(long x) {
return x > 0 ? x * 2 - 1 : -x * 2;
}
/**
* Unfold an unsigned number into a signed number.
*
* @param x an unsigned number
* @return a signed number
*/
public static long unfoldSigned(long x) {
return ((x & 1) == 1) ? (x + 1) / 2 : -(x / 2);
}
public void writeBit(long x) {
if (x == 1) {
data[pos >>> 6] |= 1L << (63 - (pos & 63));
}
pos++;
}
public long readBit() {
return (data[pos >>> 6] >>> (63 - (pos++ & 63))) & 1;
}
public int readUntilZero(int pos) {
int remainingBits = 64 - (pos & 63);
int index = pos >>> 6;
long x = data[index] << (64 - remainingBits);
int count = Long.numberOfLeadingZeros(~x);
if (count < remainingBits) {
return count;
}
return readUntilZeroMore(count, index);
}
private int readUntilZeroMore(int count, int index) {
while (true) {
long x = data[++index];
if (x == -1L) {
count += 64;
continue;
}
return count + Long.numberOfLeadingZeros(~x);
}
}
private int readUntilZero() {
int len = readUntilZero(pos);
pos += len + 1;
return len;
}
public void writeGolombRice(int shift, long value) {
writeGolombRiceFast(shift, value);
}
public void writeGolombRiceSlow(int shift, long value) {
long q = value >>> shift;
for (int i = 0; i < q; i++) {
writeBit(1);
}
writeBit(0);
for (int i = shift - 1; i >= 0; i--) {
writeBit((value >>> i) & 1);
}
}
public void writeGolombRiceFast(int shift, long value) {
long q = value >>> shift;
if (q < 63) {
long m = (2L << q) - 2;
writeNumber(m, (int) (q + 1));
} else {
for (int i = 0; i < q; i++) {
writeBit(1);
}
writeBit(0);
}
writeNumber(value & ((1L << shift) - 1), shift);
// for (int i = shift - 1; i >= 0; i--) {
// writeBit((value >>> i) & 1);
// }
}
// public void writeVarLong(long x) {
// while ((x & ~0x7f) != 0) {
// writeNumber((0x80 | (x & 0x7f)) & 0xff, 8);
// x >>>= 7;
// }
// writeNumber(x & 0xff, 8);
// }
// public long readVarLong() {
// long x = buff.get();
// if (x >= 0) {
// return x;
// }
// x &= 0x7f;
// for (int s = 7; s < 64; s += 7) {
// long b = buff.get();
// x |= (b & 0x7f) << s;
// if (b >= 0) {
// break;
// }
// }
// return x;
// }
public long readGolombRice(int pos, int shift) {
int q = readUntilZero(pos);
return (q << shift) | readNumber(pos + q + 1, shift);
}
public long readGolombRice(int shift) {
long q = readUntilZero();
return (q << shift) | readNumber(shift);
// int q = 0;
// while (readBit() == 1) {
// q++;
// }
// long x = ((long) q) << shift;
// for (int i = shift - 1; i >= 0; i--) {
// x |= readBit() << i;
// }
// return x;
}
public void skipGolombRice(int shift) {
pos = skipGolombRice(pos, shift);
}
public int skipGolombRice(int pos, int shift) {
int q = readUntilZero(pos);
return pos + q + 1 + shift;
}
public void writeEliasDelta(long value) {
if (value <= 0) {
throw new IllegalArgumentException();
}
int q = 64 - Long.numberOfLeadingZeros(value);
int qq = 31 - Integer.numberOfLeadingZeros(q);
for (int i = 0; i < qq; i++) {
writeBit(0);
}
for (int i = qq; i >= 0; i--) {
writeBit((q >>> i) & 1);
}
for (int i = q - 2; i >= 0; i--) {
writeBit((value >>> i) & 1);
}
}
public long readEliasDelta() {
int qq = 0;
while (readBit() == 0) {
qq++;
}
long q = 1;
for (int i = qq; i > 0; i--) {
q = (q << 1) | readBit();
}
long x = 1;
for (long i = q - 2; i >= 0; i--) {
x = (x << 1) | readBit();
}
return x;
}
/**
* Write a number of bits. The most significant bit is written first.
*
* @param x the number
* @param bitCount the number of bits, at most 63
*/
public void writeNumber(long x, int bitCount) {
// while (bitCount-- > 0) {
// writeBit((x >>> bitCount) & 1);
// }
if (bitCount == 0) {
return;
}
int remainingBits = 64 - (pos & 63);
int index = pos >>> 6;
if (bitCount <= remainingBits) {
data[index] |= x << (remainingBits - bitCount);
} else {
data[index] |= x >>> (bitCount - remainingBits);
data[index + 1] |= x << (64 - bitCount + remainingBits);
}
pos += bitCount;
}
public void clearBits(int bitCount) {
if (bitCount == 0) {
return;
}
int remainingBits = 64 - (pos & 63);
int index = pos >>> 6;
long x = (1 << bitCount) - 1;
if (bitCount <= remainingBits) {
data[index] &= ~(x << (remainingBits - bitCount));
} else {
data[index] &= ~(x >>> (bitCount - remainingBits));
data[index + 1] &= ~(x << (64 - bitCount + remainingBits));
}
pos += bitCount;
}
public byte[] toByteArray() {
byte[] d = new byte[data.length * 8];
ByteBuffer.wrap(d).order(ByteOrder.BIG_ENDIAN).asLongBuffer()
.put(data, 0, (pos + 63) / 64);
if ((pos + 7) / 8 == d.length) {
return d;
}
return Arrays.copyOf(d, (pos + 7) / 8);
}
public void clear() {
Arrays.fill(data, 0);
}
public long[] getLongArray() {
return data;
}
public static int getGolombRiceSize(int shift, long value) {
return (int) ((value >>> shift) + 1 + shift);
}
public static int getEliasDeltaSize(long value) {
if (value <= 0) {
throw new IllegalArgumentException();
}
int q = 64 - Long.numberOfLeadingZeros(value);
int qq = 31 - Integer.numberOfLeadingZeros(q);
int len = qq + qq + q;
return len;
}
}
================================================
FILE: src/main/java/org/minperf/RecSplitBuilder.java
================================================
package org.minperf;
import java.util.Collection;
import org.minperf.generator.ConcurrencyTool;
import org.minperf.generator.Generator;
import org.minperf.universal.UniversalHash;
/**
* A builder to generate a MPHF description, or to get an evaluator of a description.
*
* @param the type
*/
public class RecSplitBuilder {
private final UniversalHash hash;
private int averageBucketSize = 256;
private int leafSize = 10;
private boolean eliasFanoMonotoneLists = true;
private int parallelism = Runtime.getRuntime().availableProcessors();
private int maxChunkSize = Integer.MAX_VALUE;
private RecSplitBuilder(UniversalHash hash) {
this.hash = hash;
}
/**
* Create a new instance of the builder, with the given universal hash implementation.
*
* @param the type
* @param hash the universal hash function
* @return the builder
*/
public static RecSplitBuilder newInstance(UniversalHash hash) {
return new RecSplitBuilder(hash);
}
public RecSplitBuilder averageBucketSize(int averageBucketSize) {
if (averageBucketSize < 4 || averageBucketSize > 64 * 1024) {
throw new IllegalArgumentException("averageBucketSize out of range: " + averageBucketSize);
}
this.averageBucketSize = averageBucketSize;
return this;
}
public RecSplitBuilder leafSize(int leafSize) {
if (leafSize < 1 || leafSize > 25) {
throw new IllegalArgumentException("leafSize out of range: " + leafSize);
}
this.leafSize = leafSize;
return this;
}
public RecSplitBuilder eliasFanoMonotoneLists(boolean eliasFano) {
this.eliasFanoMonotoneLists = eliasFano;
return this;
}
public RecSplitBuilder maxChunkSize(int maxChunkSize) {
this.maxChunkSize = maxChunkSize;
return this;
}
public RecSplitBuilder parallelism(int parallelism) {
this.parallelism = parallelism;
return this;
}
/**
* Generate the hash function description for a collection.
* The entries in the collection must be unique.
*
* @param collection the collection
* @return the hash function description
*/
public BitBuffer generate(Collection collection) {
Settings s = new Settings(leafSize, averageBucketSize);
ConcurrencyTool pool = new ConcurrencyTool(parallelism);
Generator g = new Generator(
pool, hash, s,
eliasFanoMonotoneLists, maxChunkSize);
BitBuffer result = g.generate(collection);
return result;
}
public RecSplitEvaluator buildEvaluator(BitBuffer description) {
Settings s = new Settings(leafSize, averageBucketSize);
return new RecSplitEvaluator(new BitBuffer(description), hash, s, eliasFanoMonotoneLists);
}
}
================================================
FILE: src/main/java/org/minperf/RecSplitEvaluator.java
================================================
package org.minperf;
import org.minperf.bdz.BDZ;
import org.minperf.generator.Generator;
import org.minperf.monotoneList.MonotoneList;
import org.minperf.universal.UniversalHash;
/**
* Evaluator for the hybrid mechanism.
*
* @param the data type
*/
public class RecSplitEvaluator {
private final Settings settings;
private final UniversalHash hash;
private final BitBuffer buffer;
private final long size;
private final int bucketCount;
private final int minStartDiff;
private final MonotoneList startList;
private final int minOffsetDiff;
private final MonotoneList offsetList;
private final int startBuckets;
private final int endHeader;
private final int endOffsetList;
private final BDZ alternative;
public RecSplitEvaluator(BitBuffer buffer, UniversalHash hash, Settings settings, boolean eliasFanoMonotoneLists) {
this.settings = settings;
this.hash = hash;
this.buffer = buffer;
this.size = (int) (buffer.readEliasDelta() - 1);
this.bucketCount = Settings.getBucketCount(size, settings.getAverageBucketSize());
boolean alternative = buffer.readBit() != 0;
this.minOffsetDiff = (int) (buffer.readEliasDelta() - 1);
this.minStartDiff = (int) (buffer.readEliasDelta() - 1);
this.endHeader = buffer.position();
this.offsetList = MonotoneList.load(buffer, eliasFanoMonotoneLists);
this.endOffsetList = buffer.position();
this.startList = MonotoneList.load(buffer, eliasFanoMonotoneLists);
this.startBuckets = buffer.position();
if (alternative) {
int b = bucketCount;
int offset = offsetList.get(b);
int pos = startBuckets +
Generator.getMinBitCount(offset) +
startList.get(b) + b * minStartDiff;
buffer.seek(pos);
this.alternative = BDZ.load(hash, buffer);
} else {
this.alternative = null;
}
}
public int getHeaderSize() {
return endHeader;
}
public int getOffsetListSize() {
return endOffsetList - endHeader;
}
public int getStartListSize() {
return startBuckets - endOffsetList;
}
public int evaluate(T obj) {
int b;
long hashCode = hash.universalHash(obj, 0);
//System.out.println("hashCode " + obj + " =" + hashCode);
if (bucketCount == 1) {
b = 0;
} else {
b = Settings.reduce((int) hashCode, bucketCount);
}
//System.out.println("bucket " + b);
int startPos;
long offsetPair = offsetList.getPair(b);
int offset = (int) (offsetPair >>> 32) + b * minOffsetDiff;
int offsetNext = ((int) offsetPair) + (b + 1) * minOffsetDiff;
if (offsetNext == offset) {
if (alternative == null) {
// entry not found
return 0;
}
offset = offsetList.get(bucketCount) + bucketCount * minOffsetDiff;
return offset + alternative.evaluate(obj);
}
int bucketSize = offsetNext - offset;
startPos = startBuckets +
Generator.getMinBitCount(offset) +
startList.get(b) + b * minStartDiff;
//System.out.println("startPos " + startPos + " offset " + offset + " bucketSize " + bucketSize);
return evaluate(startPos, obj, hashCode, 0, offset, bucketSize);
}
private int skip(int pos, int size) {
if (size < 2) {
return pos;
}
pos = buffer.skipGolombRice(pos, settings.getGolombRiceShift(size));
if (size <= settings.getLeafSize()) {
return pos;
}
int split = settings.getSplit(size);
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
int s = firstPart;
for (int i = 0; i < split; i++) {
pos = skip(pos, s);
s = otherPart;
}
return pos;
}
private int evaluate(int pos, T obj, long hashCode,
long index, int add, int size) {
while (true) {
if (size < 2) {
return add;
}
int shift = settings.getGolombRiceShift(size);
long q = buffer.readUntilZero(pos);
pos += q + 1;
long value = (q << shift) | buffer.readNumber(pos, shift);
pos += shift;
long oldX = Settings.getUniversalHashIndex(index);
index += value + 1;
long x = Settings.getUniversalHashIndex(index);
if (x != oldX) {
hashCode = hash.universalHash(obj, x);
}
if (size <= settings.getLeafSize()) {
int h = Settings.supplementalHash(hashCode, index);
h = Settings.reduce(h, size);
//System.out.printf("shift %d q %lld value %d oldX %d x %d size %d h %d add %d\n", shift, q, value, oldX, x, size, h, add);
return add + h;
}
int split = settings.getSplit(size);
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
int h = Settings.supplementalHash(hashCode, index);
if (firstPart != otherPart) {
h = Settings.reduce(h, size);
if (h < firstPart) {
size = firstPart;
continue;
}
pos = skip(pos, firstPart);
add += firstPart;
size = otherPart;
continue;
}
h = Settings.reduce(h, split);
for (int i = 0; i < h; i++) {
pos = skip(pos, firstPart);
add += firstPart;
}
size = firstPart;
}
}
}
================================================
FILE: src/main/java/org/minperf/Settings.java
================================================
package org.minperf;
/**
* The settings used to generate the hash function.
*/
public class Settings {
public static final boolean IMPROVED_SPLIT_RULES = true;
/**
* The number of supplemental hash functions per universal hash is 2 ^ this
* number. Could be increased to reduce the number of universal hash
* function calls, which also speeds up evaluation time.
*/
public static final int SUPPLEMENTAL_HASH_SHIFT = 18;
/**
* The number of times the same universal hash is mixed using the
* supplemental hash function. Must be a power of 2.
*/
private static final long SUPPLEMENTAL_HASH_CALLS = 1 << SUPPLEMENTAL_HASH_SHIFT;
/**
* The Rice parameter k to use for leaves of size = array index.
*/
private static final int[] RICE_LEAF = { 0, 0, 0, 1, 3, 4, 5, 7, 8, 10, 11,
12, 14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 32, 33, 35,
36, 38, 39, 40, 42 };
/**
* The Rice parameter k that is used to split medium sized sets that are
* evenly split into subsets.
*/
private static final int[][] RICE_SPLIT_MORE = {
// 0 .. 6
{ }, { }, { }, { }, { }, { 4}, { 4},
// 7 .. 13
{ 4}, { 7}, { 7}, { 10, 7}, { 11, 7}, { 11, 7}, { 14, 8},
// 14 .. 18
{ 14, 8}, { 15, 8}, { 18, 8}, { 18, 8}, { 19, 8},
// 19 .. 23
{ 22, 13}, { 22, 13}, { 23, 14}, { 26, 14}, { 27, 14},
// 24 .. 25
{ 27, 14}, { 31, 20, 12}};
/**
* Convert an array of strings to an array of integers. This is needed to
* work around the bytecode limit of Java methods.
*/
private static int[] splitIntegerList(String x) {
if (x.trim().isEmpty()) {
return new int[0];
}
String[] array = x.split(",");
int[] result = new int[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = Integer.parseInt(array[i].trim());
}
return result;
}
/**
* Array of size, split, k.
*/
static int[][] SPLIT_RULES = {
// leafSize 0
splitIntegerList(""),
// leafSize 1
splitIntegerList(""),
// leafSize 2
splitIntegerList("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"),
// leafSize 3
splitIntegerList("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"),
// leafSize 4
splitIntegerList("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"),
// leafSize 5
splitIntegerList("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"),
// leafSize 6
splitIntegerList("0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"),
// leafSize 7
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,-1,0,9,-2,1,10,-3,1,11,-4,1,12,-5,1,13,-6,1,14,-7,2,15,3,4,16,-7,2,17,-7,2,18,3,4,19,-7,2,20,-7,2,21,3,4,22,-1,1,23,-2,1,24,4,6,25,-4,2,26,-5,2,27,-6,2,28,-7,2,29,-5,2,30,-6,2,31,-7,2,32,-11,2,33,-12,2,34,-6,2,35,-7,2,36,-15,2,37,-6,2,38,-7,2,39,-18,2,40,-5,2,41,-6,2,42,2,2,43,-1,1,44,-2,1,45,-21,2,46,-4,2,47,-5,2,48,-6,2,49,-7,2,50,-5,2,51,-6,2,52,-7,2,53,-11,2,54,-5,2,55,-6,2,56,-7,2,57,-21,3,58,-6,2,59,-28,3,60,-21,3,61,-5,2,62,-6,2,63,3,6,64,-1,1,65,-2,1,66,-3,1,67,-4,2,68,-5,2,69,-6,2,70,-7,2,71,-8,2,72,-9,2,73,-10,2,74,-11,2,75,-5,2,76,-6,2,77,-7,2,78,-15,2,79,-7,2,80,-7,2,81,-18,3,82,-5,2,83,-6,2,84,-21,3,85,-22,3,86,-23,3,87,-24,3,88,-4,2,89,-26,3,90,-27,3,91,-28,3,92,-24,3,93,-30,3,94,-31,3,95,-32,3,96,-5,2,97,-34,3,98,-35,3,99,-36,3,100,-31,3,101,-38,3,102,-39,3,103,-5,2,104,-6,2,105,-42,3,106,-1,1,107,-44,3,108,-21,3,109,-4,2,110,-5,2,111,-6,2,112,-21,3,113,-21,3,114,-24,3,115,-24,3,116,-21,3,117,-21,3,118,-27,3,119,-28,3,120,-21,3,121,-28,3,122,-28,3,123,-21,3,124,-5,2,125,-28,3,126,-63,3,127,-1,1,128,-63,3,129,-63,3,130,-4,2,131,-5,2,132,-6,2,133,-7,2,134,-8,2,135,-63,3,136,-63,3,137,-63,3,138,-5,2,139,-6,2,140,-7,2,141,-15,3,142,-7,2,143,-7,2,144,-18,3,145,-5,2,146,-6,2,147,-21,3,148,-1,0,149,-2,1,150,-24,3,151,-4,2,152,-5,2,153,-6,2,154,-7,2,155,-5,2,156,-6,2,157,-7,2,158,-32,3,159,-5,2,160,-6,2,161,-7,2,162,-36,3,163,-6,2,164,-7,2,165,-39,3,166,-5,2,167,-6,2,168,-21,3,169,-21,3,170,-21,3,171,-21,3,172,-4,2,173,-21,3,174,-21,3,175,-21,3,176,-21,3,177,-21,3,178,-21,3,179,-21,3,180,-21,3,181,-21,3,182,-21,3,183,-21,3,184,-21,3,185,-21,3,186,-21,3,187,-21,3,188,-21,3,189,-63,3,190,-1,0,191,-2,1,192,-3,1,193,-4,2,194,-5,2,195,-6,2,196,-7,2,197,-7,2,198,-7,2,199,-7,2,200,-4,2,201,-5,2,202,-6,2,203,-7,2,204,-15,3,205,-7,2,206,-7,2,207,-18,3,208,-5,2,209,-6,2,210,-21,3,211,-21,3,212,-21,3,213,-24,3,214,-4,2,215,-21,3,216,-21,3,217,-21,3,218,-5,2,219,-24,3,220,-24,3,221,-32,3,222,-21,3,223,-21,3,224,-21,3,225,-99,4,226,-24,3,227,-24,3,228,-102,4,229,-21,3,230,-21,3,231,-21,3,232,-21,3,233,-21,3,234,-21,3,235,-4,2,236,-21,3,237,-21,3,238,-21,3,239,-21,3,240,-21,3,241,-21,3,242,-95,4,243,-21,3,244,-21,3,245,-21,3,246,-99,4,247,-21,3,248,-21,3,249,-102,4,250,-21,3,251,-21,3,252,-126,4,253,-1,0,254,-2,1,255,-3,1,256,-4,2,257,-5,2,258,-6,2,259,-7,2,260,-7,2,261,-7,2,262,-7,2,263,-4,2,264,-5,2,265,-6,2,266,-7,2,267,-15,3,268,-7,2,269,-7,2,270,-18,3,271,-5,2,272,-6,2,273,-126,4,274,-126,4,275,-126,4,276,-126,4,277,-4,2,278,-126,4,279,-126,4,280,-126,4,281,-126,4,282,-126,4,283,-126,4,284,-126,4,285,-126,4,286,-126,4,287,-126,4,288,-126,4,289,-126,4,290,-126,4,291,-126,4,292,-126,4,293,-126,4,294,-126,4,295,-126,4,296,-126,4,297,-126,4,298,-4,2,299,-126,4,300,-126,4,301,-126,4,302,-126,4,303,-126,4,304,-126,4,305,-126,4,306,-126,4,307,-126,4,308,-126,4,309,-126,4,310,-126,4,311,-126,4,312,-126,4,313,-126,4,314,-126,4,315,-126,4,316,-126,4,317,-126,4,318,-126,4,319,-4,2,320,-126,4,321,-126,4,322,-126,4,323,-126,4,324,-126,4,325,-126,4,326,-4,2,327,-126,4,328,-126,4,329,-126,4,330,-15,3,331,-126,4,332,-126,4,333,-18,3,334,-5,2,335,-126,4,336,-21,3,337,-21,3,338,-21,3,339,-150,4,340,-4,2,341,-21,3,342,-21,3,343,-21,3,344,-5,2,345,-156,4,346,-157,4,347,-95,4,348,-21,3,349,-21,3,350,-21,3,351,-99,4,352,-163,4,353,-164,4,354,-102,4,355,-5,2,356,-21,3,357,-21,3,358,-21,3,359,-21,3,360,-21,3,361,-4,2,362,-21,3,363,-21,3,364,-21,3,365,-5,2,366,-21,3,367,-21,3,368,-95,4,369,-21,3,370,-21,3,371,-21,3,372,-99,4,373,-21,3,374,-21,3,375,-102,4,376,-5,2,377,-21,3,378,-126,4,379,-126,4,380,-126,4,381,-126,4,382,-4,2,383,-5,2,384,-126,4,385,-126,4,386,-126,4,387,-126,4,388,-126,4,389,-4,2,390,-5,2,391,-126,4,392,-126,4,393,-15,3,394,-126,4,395,-126,4,396,-18,3,397,-5,2,398,-126,4,399,-126,4,400,-126,4,401,-126,4,402,-126,4,403,-4,2,404,-126,4,405,-126,4,406,-126,4,407,-126,4,408,-126,4,409,-126,4,410,-126,4,411,-126,4,412,-126,4,413,-126,4,414,-126,4,415,-126,4,416,-126,4,417,-126,4,418,-126,4,419,-126,4,420,-126,4,421,-126,4,422,-126,4,423,-126,4,424,-4,2,425,-126,4,426,-126,4,427,-126,4,428,-126,4,429,-126,4,430,-126,4,431,-126,4,432,-126,4,433,-126,4,434,-21,3,435,-21,3,436,-21,3,437,-21,3,438,-21,3,439,-21,3,440,-21,3,441,-126,4,442,-126,4,443,-126,4,444,-126,4,445,-4,2,446,-5,2,447,-126,4,448,-126,4,449,-126,4,450,-126,4,451,-126,4,452,-4,2,453,-5,2,454,-126,4,455,-126,4,456,-15,3,457,-126,4,458,-126,4,459,-18,3,460,-5,2,461,-126,4,462,-21,3,463,-21,3,464,-21,3,465,-126,4,466,-4,2,467,-5,2,468,-21,3,469,-21,3,470,-5,2,471,-126,4,472,-126,4,473,-95,4,474,-5,2,475,-21,3,476,-21,3,477,-99,4,478,-126,4,479,-126,4,480,-102,4,481,-5,2,482,-21,3,483,-21,3,484,-21,3,485,-21,3,486,-21,3,487,-4,2,488,-5,2,489,-21,3,490,-21,3,491,-5,2,492,-21,3,493,-91,4,494,-95,4,495,-5,2,496,-91,4,497,-91,4,498,-99,4,499,-91,4,500,-91,4,501,-102,4,502,-91,4,503,-91,4,504,-126,4,505,-126,4,506,-126,4,507,-126,4,508,-4,2,509,-5,2,510,-126,4,511,-126,4,512,-126,4,513,-126,4,514,-126,4,515,-4,2,516,-5,2,517,-126,4,518,-126,4,519,-15,3,520,-126,4,521,-126,4,522,-18,3,523,-5,2,524,-126,4,525,-126,4,526,-126,4,527,-126,4,528,-126,4,529,-4,2,530,-126,4,531,-126,4,532,-126,4,533,-126,4,534,-126,4,535,-126,4,536,-126,4,537,-126,4,538,-126,4,539,-126,4,540,-126,4,541,-126,4,542,-126,4,543,-126,4,544,-5,2,545,-126,4,546,-21,3,547,-21,3,548,-21,3,549,-21,3,550,-4,2,551,-21,3,552,-21,3,553,-21,3,554,-21,3,555,-21,3,556,-21,3,557,-21,3,558,-21,3,559,-21,3,560,-21,3,561,-21,3,562,-21,3,563,-21,3,564,-21,3,565,-5,2,566,-21,3,567,-126,4,568,-126,4,569,-126,4,570,-126,4,571,-4,2,572,-5,2,573,-126,4,574,-126,4,575,-126,4,576,-126,4,577,-126,4,578,-4,2,579,-5,2,580,-126,4,581,-126,4,582,-15,3,583,-126,4,584,-126,4,585,-18,3,586,-5,2,587,-126,4,588,-21,3,589,-21,3,590,-21,3,591,-126,4,592,-4,2,593,-5,2,594,-21,3,595,-91,4,596,-5,2,597,-126,4,598,-94,4,599,-95,4,600,-91,4,601,-91,4,602,-21,3,603,-99,4,604,-94,4,605,-94,4,606,-102,4,607,-5,2,608,-21,3,609,-105,4,610,-105,4,611,-105,4,612,-87,4,613,-4,2,614,-5,2,615,-105,4,616,-91,4,617,-87,4,618,-87,4,619,-91,4,620,-95,4,621,-91,4,622,-91,4,623,-91,4,624,-99,4,625,-91,4,626,-91,4,627,-102,4,628,-91,4,629,-91,4,630,-126,4,631,-126,4,632,-126,4,633,-126,4,634,-4,2,635,-5,2,636,-126,4,637,-126,4,638,-126,4,639,-126,4,640,-126,4,641,-4,2,642,-5,2,643,-126,4,644,-126,4,645,-15,3,646,-126,4,647,-126,4,648,-18,3,649,-5,2,650,-126,4,651,-126,4,652,-126,4,653,-126,4,654,-126,4,655,-4,2,656,-126,4,657,-126,4,658,-126,4,659,-5,2,660,-126,4,661,-126,4,662,-126,4,663,-5,2,664,-126,4,665,-126,4,666,-126,4,667,-126,4,668,-126,4,669,-126,4,670,-5,2,671,-126,4,672,-21,3,673,-21,3,674,-21,3,675,-21,3,676,-4,2,677,-21,3,678,-21,3,679,-21,3,680,-5,2,681,-21,3,682,-21,3,683,-21,3,684,-5,2,685,-21,3,686,-21,3,687,-21,3,688,-21,3,689,-21,3,690,-21,3,691,-5,2,692,-21,3,693,-126,4,694,-126,4,695,-126,4,696,-126,4,697,-4,2,698,-5,2,699,-126,4,700,-126,4,701,-126,4,702,-126,4,703,-126,4,704,-4,2,705,-5,2,706,-126,4,707,-126,4,708,-15,3,709,-126,4,710,-126,4,711,-18,3,712,-5,2,713,-126,4,714,-21,3,715,-21,3,716,-21,3,717,-87,4,718,-4,2,719,-5,2,720,-21,3,721,-91,4,722,-87,4,723,-87,4,724,-94,4,725,-95,4,726,-5,2,727,-91,4,728,-91,4,729,-99,4,730,-94,4,731,-94,4,732,-102,4,733,-5,2,734,-91,4,735,-105,4,736,-105,4,737,-105,4,738,-87,4,739,-4,2,740,-5,2,741,-105,4,742,-91,4,743,-87,4,744,-87,4,745,-91,4,746,-95,4,747,-91,4,748,-91,4,749,-91,4,750,-99,4,751,-91,4,752,-91,4,753,-102,4,754,-5,2,755,-91,4,756,-126,4,757,-126,4,758,-126,4,759,-126,4,760,-4,2,761,-5,2,762,-126,4,763,-126,4,764,-126,4,765,-126,4,766,-126,4,767,-4,2,768,-5,2,769,-126,4,770,-126,4,771,-15,3,772,-126,4,773,-126,4,774,-18,3,775,-5,2,776,-126,4,777,-126,4,778,-126,4,779,-126,4,780,-126,4,781,-4,2,782,-5,2,783,-126,4,784,-126,4,785,-5,2,786,-126,4,787,-126,4,788,-126,4,789,-5,2,790,-126,4,791,-126,4,792,-126,4,793,-126,4,794,-126,4,795,-126,4,796,-5,2,797,-126,4,798,-21,3,799,-21,3,800,-21,3,801,-21,3,802,-4,2,803,-5,2,804,-21,3,805,-21,3,806,-5,2,807,-21,3,808,-21,3,809,-21,3,810,-5,2,811,-21,3,812,-21,3,813,-21,3,814,-21,3,815,-21,3,816,-21,3,817,-5,2,818,-21,3,819,-126,4,820,-126,4,821,-126,4,822,-126,4,823,-4,2,824,-5,2,825,-126,4,826,-126,4,827,-126,4,828,-126,4,829,-126,4,830,-4,2,831,-5,2,832,-126,4,833,-126,4,834,-15,3,835,-126,4,836,-126,4,837,-18,3,838,-5,2,839,-126,4,840,-21,3,841,-21,3,842,-21,3,843,-87,4,844,-4,2,845,-5,2,846,-21,3,847,-91,4,848,-87,4,849,-87,4,850,-94,4,851,-95,4,852,-5,2,853,-91,4,854,-91,4,855,-99,4,856,-94,4,857,-94,4,858,-102,4,859,-5,2,860,-91,4,861,-105,4,862,-105,4,863,-105,4,864,-87,4,865,-4,2,866,-5,2,867,-105,4,868,-91,4,869,-87,4,870,-87,4,871,-91,4,872,-95,4,873,-5,2,874,-91,4,875,-91,4,876,-99,4,877,-91,4,878,-91,4,879,-102,4,880,-5,2,881,-91,4,882,-126,4,883,-126,4,884,-126,4,885,-126,4,886,-4,2,887,-5,2,888,-126,4,889,-126,4,890,-126,4,891,-126,4,892,-126,4,893,-4,2,894,-5,2,895,-126,4,896,-126,4,897,-15,3,898,-126,4,899,-126,4,900,-18,3,901,-5,2,902,-126,4,903,-21,3,904,-126,4,905,-126,4,906,-126,4,907,-4,2,908,-5,2,909,-126,4,910,-126,4,911,-5,2,912,-126,4,913,-126,4,914,-126,4,915,-5,2,916,-126,4,917,-126,4,918,-126,4,919,-126,4,920,-126,4,921,-126,4,922,-5,2,923,-126,4,924,-21,3,925,-21,3,926,-21,3,927,-21,3,928,-4,2,929,-5,2,930,-21,3,931,-21,3,932,-5,2,933,-21,3,934,-21,3,935,-21,3,936,-5,2,937,-21,3,938,-21,3,939,-21,3,940,-21,3,941,-21,3,942,-21,3,943,-5,2,944,-21,3,945,-126,4,946,-126,4,947,-126,4,948,-126,4,949,-4,2,950,-5,2,951,-126,4,952,-126,4,953,-126,4,954,-126,4,955,-126,4,956,-4,2,957,-5,2,958,-126,4,959,-126,4,960,-15,3,961,-126,4,962,-126,4,963,-18,3,964,-5,2,965,-126,4,966,-21,3,967,-21,3,968,-21,3,969,-87,4,970,-4,2,971,-5,2,972,-21,3,973,-91,4,974,-5,2,975,-87,4,976,-94,4,977,-95,4,978,-5,2,979,-91,4,980,-91,4,981,-99,4,982,-94,4,983,-94,4,984,-102,4,985,-5,2,986,-91,4,987,-105,4,988,-105,4,989,-105,4,990,-87,4,991,-4,2,992,-5,2,993,-105,4,994,-21,3,995,-5,2,996,-87,4,997,-91,4,998,-21,3,999,-5,2,1000,-91,4,1001,-91,4,1002,-21,3,1003,-91,4,1004,-91,4,1005,-21,3,1006,-5,2,1007,-91,4,1008,-126,4,1009,-126,4,1010,-126,4,1011,-126,4,1012,-4,2,1013,-5,2,1014,-126,4,1015,-126,4,1016,-126,4,1017,-126,4,1018,-126,4,1019,-4,2,1020,-5,2,1021,-126,4,1022,-126,4,1023,-15,3,1024,-126,4,1025,-126,4,1026,-18,3,1027,-5,2,1028,-6,2,1029,-21,3,1030,-126,4,1031,-126,4,1032,-126,4,1033,-4,2,1034,-5,2,1035,-126,4,1036,-126,4,1037,-5,2,1038,-126,4,1039,-126,4,1040,-126,4,1041,-5,2,1042,-126,4,1043,-126,4,1044,-126,4,1045,-126,4,1046,-126,4,1047,-126,4,1048,-5,2,1049,-126,4,1050,-21,3,1051,-21,3,1052,-21,3,1053,-21,3,1054,-4,2,1055,-5,2,1056,-21,3,1057,-21,3,1058,-5,2,1059,-21,3,1060,-21,3,1061,-21,3,1062,-5,2,1063,-21,3,1064,-21,3,1065,-21,3,1066,-21,3,1067,-21,3,1068,-21,3,1069,-5,2,1070,-21,3,1071,-126,4,1072,-126,4,1073,-126,4,1074,-126,4,1075,-4,2,1076,-5,2,1077,-126,4,1078,-126,4,1079,-126,4,1080,-126,4,1081,-126,4,1082,-4,2,1083,-5,2,1084,-126,4,1085,-126,4,1086,-15,3,1087,-126,4,1088,-126,4,1089,-18,3,1090,-5,2,1091,-126,4,1092,-21,3,1093,-21,3,1094,-21,3,1095,-87,4,1096,-4,2,1097,-5,2,1098,-21,3,1099,-91,4,1100,-5,2,1101,-87,4,1102,-94,4,1103,-95,4,1104,-5,2,1105,-91,4,1106,-91,4,1107,-99,4,1108,-94,4,1109,-94,4,1110,-102,4,1111,-5,2,1112,-91,4,1113,-105,4,1114,-105,4,1115,-105,4,1116,-87,4,1117,-4,2,1118,-5,2,1119,-105,4,1120,-21,3,1121,-5,2,1122,-87,4,1123,-91,4,1124,-21,3,1125,-5,2,1126,-91,4,1127,-91,4,1128,-21,3,1129,-91,4,1130,-91,4,1131,-21,3,1132,-5,2,1133,-91,4,1134,-126,4,1135,-126,4,1136,-126,4,1137,-126,4,1138,-4,2,1139,-5,2,1140,-126,4,1141,-126,4,1142,-126,4,1143,-126,4,1144,-126,4,1145,-4,2,1146,-5,2,1147,-6,2,1148,-126,4,1149,-15,3,1150,-126,4,1151,-126,4,1152,-18,3,1153,-5,2,1154,-6,2,1155,-21,3,1156,-126,4,1157,-126,4,1158,-126,4,1159,-4,2,1160,-5,2,1161,-126,4,1162,-126,4,1163,-5,2,1164,-126,4,1165,-126,4,1166,-126,4,1167,-5,2,1168,-126,4,1169,-126,4,1170,-126,4,1171,-126,4,1172,-126,4,1173,-126,4,1174,-5,2,1175,-126,4,1176,-21,3,1177,-21,3,1178,-21,3,1179,-21,3,1180,-4,2,1181,-5,2,1182,-21,3,1183,-21,3,1184,-5,2,1185,-21,3,1186,-21,3,1187,-21,3,1188,-5,2,1189,-21,3,1190,-21,3,1191,-21,3,1192,-21,3,1193,-21,3,1194,-21,3,1195,-5,2,1196,-21,3,1197,-126,4,1198,-126,4,1199,-126,4,1200,-126,4,1201,-4,2,1202,-5,2,1203,-126,4,1204,-126,4,1205,-126,4,1206,-126,4,1207,-126,4,1208,-4,2,1209,-5,2,1210,-126,4,1211,-126,4,1212,-15,3,1213,-126,4,1214,-126,4,1215,-18,3,1216,-5,2,1217,-126,4,1218,-21,3,1219,-21,3,1220,-21,3,1221,-87,4,1222,-4,2,1223,-5,2,1224,-21,3,1225,-91,4,1226,-5,2,1227,-87,4,1228,-94,4,1229,-95,4,1230,-5,2,1231,-91,4,1232,-91,4,1233,-99,4,1234,-94,4,1235,-94,4,1236,-102,4,1237,-5,2,1238,-91,4,1239,-105,4,1240,-105,4,1241,-105,4,1242,-87,4,1243,-4,2,1244,-5,2,1245,-105,4,1246,-21,3,1247,-5,2,1248,-87,4,1249,-91,4,1250,-21,3,1251,-5,2,1252,-91,4,1253,-91,4,1254,-21,3,1255,-91,4,1256,-91,4,1257,-21,3,1258,-5,2,1259,-91,4,1260,-126,4,1261,-126,4,1262,-126,4,1263,-126,4,1264,-4,2,1265,-5,2,1266,-6,2,1267,-126,4,1268,-126,4,1269,-126,4,1270,-126,4,1271,-4,2,1272,-5,2,1273,-6,2,1274,-126,4,1275,-15,3,1276,-126,4,1277,-126,4,1278,-18,3,1279,-5,2,1280,-6,2,1281,-21,3,1282,-126,4,1283,-126,4,1284,-126,4,1285,-4,2,1286,-5,2,1287,-126,4,1288,-126,4,1289,-5,2,1290,-126,4,1291,-126,4,1292,-126,4,1293,-5,2,1294,-126,4,1295,-126,4,1296,-126,4,1297,-126,4,1298,-126,4,1299,-126,4,1300,-5,2,1301,-126,4,1302,-21,3,1303,-21,3,1304,-21,3,1305,-21,3,1306,-4,2,1307,-5,2,1308,-21,3,1309,-21,3,1310,-5,2,1311,-21,3,1312,-21,3,1313,-21,3,1314,-5,2,1315,-21,3,1316,-21,3,1317,-21,3,1318,-21,3,1319,-21,3,1320,-21,3,1321,-5,2,1322,-21,3,1323,-63,4,1324,-126,4,1325,-126,4,1326,-126,4,1327,-63,4,1328,-63,4,1329,-126,4,1330,-126,4,1331,-126,4,1332,-126,4,1333,-73,4,1334,-4,2,1335,-5,2,1336,-126,4,1337,-126,4,1338,-15,3,1339,-126,4,1340,-126,4,1341,-63,4,1342,-5,2,1343,-126,4,1344,-63,4,1345,-63,4,1346,-63,4,1347,-87,4,1348,-63,4,1349,-63,4,1350,-63,4,1351,-91,4,1352,-5,2,1353,-87,4,1354,-94,4,1355,-95,4,1356,-5,2,1357,-91,4,1358,-91,4,1359,-99,4,1360,-94,4,1361,-94,4,1362,-102,4,1363,-5,2,1364,-91,4,1365,-105,4,1366,-105,4,1367,-105,4,1368,-87,4,1369,-4,2,1370,-5,2,1371,-6,2,1372,-21,3,1373,-5,2,1374,-87,4,1375,-91,4,1376,-21,3,1377,-5,2,1378,-91,4,1379,-91,4,1380,-21,3,1381,-91,4,1382,-91,4,1383,-21,3,1384,-5,2,1385,-91,4,1386,-126,4,1387,-126,4,1388,-126,4,1389,-126,4,1390,-4,2,1391,-5,2,1392,-6,2,1393,-126,4,1394,-126,4,1395,-126,4,1396,-126,4,1397,-4,2,1398,-5,2,1399,-6,2,1400,-126,4,1401,-15,3,1402,-126,4,1403,-126,4,1404,-18,3,1405,-5,2,1406,-6,2,1407,-21,3,1408,-126,4,1409,-126,4,1410,-126,4,1411,-4,2,1412,-5,2,1413,-126,4,1414,-126,4,1415,-5,2,1416,-126,4,1417,-126,4,1418,-126,4,1419,-5,2,1420,-126,4,1421,-126,4,1422,-126,4,1423,-126,4,1424,-126,4,1425,-126,4,1426,-5,2,1427,-126,4,1428,-21,3,1429,-21,3,1430,-21,3,1431,-21,3,1432,-4,2,1433,-5,2,1434,-21,3,1435,-21,3,1436,-5,2,1437,-21,3,1438,-21,3,1439,-21,3,1440,-5,2,1441,-21,3,1442,-21,3,1443,-21,3,1444,-21,3,1445,-21,3,1446,-21,3,1447,-5,2,1448,-21,3,1449,-63,4,1450,-63,4,1451,-63,4,1452,-126,4,1453,-63,4,1454,-63,4,1455,-63,4,1456,-126,4,1457,-126,4,1458,-126,4,1459,-73,4,1460,-4,2,1461,-5,2,1462,-126,4,1463,-126,4,1464,-15,3,1465,-709,5,1466,-73,4,1467,-63,4,1468,-5,2,1469,-713,5,1470,-63,4,1471,-63,4,1472,-63,4,1473,-87,4,1474,-63,4,1475,-63,4,1476,-63,4,1477,-91,4,1478,-5,2,1479,-87,4,1480,-94,4,1481,-95,4,1482,-5,2,1483,-91,4,1484,-91,4,1485,-99,4,1486,-94,4,1487,-94,4,1488,-102,4,1489,-5,2,1490,-91,4,1491,-105,4,1492,-105,4,1493,-105,4,1494,-87,4,1495,-4,2,1496,-5,2,1497,-6,2,1498,-21,3,1499,-5,2,1500,-87,4,1501,-91,4,1502,-21,3,1503,-5,2,1504,-91,4,1505,-91,4,1506,-21,3,1507,-91,4,1508,-91,4,1509,-21,3,1510,-5,2,1511,-91,4,1512,-756,5,1513,-756,5,1514,-756,5,1515,-756,5,1516,-4,2,1517,-5,2,1518,-756,5,1519,-756,5,1520,-757,5,1521,-758,5,1522,-759,5,1523,-4,2,1524,-5,2,1525,-762,5,1526,-763,5,1527,-15,3,1528,-763,5,1529,-763,5,1530,-18,3,1531,-5,2,1532,-763,5,1533,-21,3,1534,-756,5,1535,-756,5,1536,-756,5,1537,-4,2,1538,-5,2,1539,-756,5,1540,-756,5,1541,-5,2,1542,-756,5,1543,-756,5,1544,-756,5,1545,-5,2,1546,-756,5,1547,-756,5,1548,-756,5,1549,-756,5,1550,-756,5,1551,-756,5,1552,-5,2,1553,-756,5,1554,-21,3,1555,-21,3,1556,-21,3,1557,-21,3,1558,-4,2,1559,-5,2,1560,-21,3,1561,-21,3,1562,-5,2,1563,-21,3,1564,-21,3,1565,-21,3,1566,-5,2,1567,-21,3,1568,-21,3,1569,-21,3,1570,-21,3,1571,-784,5,1572,-21,3,1573,-5,2,1574,-784,5,1575,-756,5,1576,-756,5,1577,-756,5,1578,-756,5,1579,-4,2,1580,-5,2,1581,-756,5,1582,-756,5,1583,-756,5,1584,-756,5,1585,-73,4,1586,-4,2,1587,-5,2,1588,-756,5,1589,-756,5,1590,-15,3,1591,-756,5,1592,-756,5,1593,-18,3,1594,-5,2,1595,-756,5,1596,-21,3,1597,-778,5,1598,-779,5,1599,-87,4,1600,-4,2,1601,-5,2,1602,-63,4,1603,-91,4,1604,-5,2,1605,-87,4,1606,-94,4,1607,-95,4,1608,-5,2,1609,-91,4,1610,-91,4,1611,-99,4,1612,-94,4,1613,-63,4,1614,-102,4,1615,-5,2,1616,-91,4,1617,-105,4,1618,-105,4,1619,-105,4,1620,-87,4,1621,-4,2,1622,-5,2,1623,-105,4,1624,-21,3,1625,-5,2,1626,-87,4,1627,-91,4,1628,-21,3,1629,-5,2,1630,-91,4,1631,-91,4,1632,-21,3,1633,-91,4,1634,-91,4,1635,-21,3,1636,-5,2,1637,-91,4,1638,-756,5,1639,-757,5,1640,-758,5,1641,-759,5,1642,-4,2,1643,-5,2,1644,-762,5,1645,-763,5,1646,-763,5,1647,-763,5,1648,-763,5,1649,-4,2,1650,-5,2,1651,-763,5,1652,-763,5,1653,-15,3,1654,-765,5,1655,-766,5,1656,-18,3,1657,-5,2,1658,-6,2,1659,-21,3,1660,-778,5,1661,-779,5,1662,-780,5,1663,-4,2,1664,-5,2,1665,-783,5,1666,-784,5,1667,-5,2,1668,-786,5,1669,-787,5,1670,-788,5,1671,-5,2,1672,-790,5,1673,-791,5,1674,-792,5,1675,-793,5,1676,-794,5,1677,-795,5,1678,-5,2,1679,-797,5,1680,-21,3,1681,-21,3,1682,-21,3,1683,-21,3,1684,-4,2,1685,-5,2,1686,-21,3,1687,-21,3,1688,-5,2,1689,-21,3,1690,-21,3,1691,-21,3,1692,-5,2,1693,-21,3,1694,-21,3,1695,-21,3,1696,-21,3,1697,-21,3,1698,-21,3,1699,-5,2,1700,-21,3,1701,-63,4,1702,-63,4,1703,-63,4,1704,-822,5,1705,-63,4,1706,-63,4,1707,-63,4,1708,-63,4,1709,-827,5,1710,-828,5,1711,-73,4,1712,-63,4,1713,-63,4,1714,-832,5,1715,-833,5,1716,-15,3,1717,-835,5,1718,-73,4,1719,-63,4,1720,-5,2,1721,-839,5,1722,-63,4,1723,-63,4,1724,-63,4,1725,-87,4,1726,-63,4,1727,-63,4,1728,-63,4,1729,-91,4,1730,-5,2,1731,-87,4,1732,-94,4,1733,-95,4,1734,-5,2,1735,-91,4,1736,-91,4,1737,-99,4,1738,-94,4,1739,-94,4,1740,-102,4,1741,-5,2,1742,-91,4,1743,-105,4,1744,-63,4,1745,-105,4,1746,-87,4,1747,-4,2,1748,-5,2,1749,-63,4,1750,-21,3,1751,-5,2,1752,-87,4,1753,-91,4,1754,-21,3,1755,-5,2,1756,-91,4,1757,-91,4,1758,-21,3,1759,-91,4,1760,-91,4,1761,-21,3,1762,-5,2,1763,-91,4,1764,-756,5,1765,-757,5,1766,-758,5,1767,-759,5,1768,-4,2,1769,-5,2,1770,-6,2,1771,-763,5,1772,-763,5,1773,-763,5,1774,-763,5,1775,-4,2,1776,-5,2,1777,-6,2,1778,-763,5,1779,-15,3,1780,-763,5,1781,-763,5,1782,-18,3,1783,-5,2,1784,-6,2,1785,-21,3,1786,-756,5,1787,-756,5,1788,-756,5,1789,-4,2,1790,-5,2,1791,-756,5,1792,-756,5,1793,-5,2,1794,-756,5,1795,-756,5,1796,-756,5,1797,-5,2,1798,-756,5,1799,-756,5,1800,-756,5,1801,-756,5,1802,-756,5,1803,-756,5,1804,-5,2,1805,-756,5,1806,-21,3,1807,-21,3,1808,-21,3,1809,-21,3,1810,-4,2,1811,-5,2,1812,-21,3,1813,-21,3,1814,-5,2,1815,-21,3,1816,-21,3,1817,-21,3,1818,-5,2,1819,-21,3,1820,-21,3,1821,-21,3,1822,-21,3,1823,-21,3,1824,-21,3,1825,-5,2,1826,-21,3,1827,-63,4,1828,-63,4,1829,-63,4,1830,-63,4,1831,-63,4,1832,-63,4,1833,-63,4,1834,-63,4,1835,-63,4,1836,-63,4,1837,-73,4,1838,-63,4,1839,-63,4,1840,-63,4,1841,-63,4,1842,-15,3,1843,-63,4,1844,-73,4,1845,-63,4,1846,-63,4,1847,-63,4,1848,-63,4,1849,-63,4,1850,-63,4,1851,-87,4,1852,-63,4,1853,-63,4,1854,-63,4,1855,-91,4,1856,-5,2,1857,-87,4,1858,-94,4,1859,-95,4,1860,-5,2,1861,-91,4,1862,-91,4,1863,-99,4,1864,-94,4,1865,-94,4,1866,-102,4,1867,-5,2,1868,-91,4,1869,-105,4,1870,-63,4,1871,-105,4,1872,-21,3,1873,-4,2,1874,-5,2,1875,-63,4,1876,-21,3,1877,-5,2,1878,-87,4,1879,-91,4,1880,-21,3,1881,-5,2,1882,-91,4,1883,-91,4,1884,-21,3,1885,-91,4,1886,-91,4,1887,-21,3,1888,-5,2,1889,-91,4,1890,-630,5,1891,-631,5,1892,-632,5,1893,-633,5,1894,-4,2,1895,-5,2,1896,-6,2,1897,-637,5,1898,-637,5,1899,-637,5,1900,-637,5,1901,-4,2,1902,-5,2,1903,-6,2,1904,-637,5,1905,-15,3,1906,-639,5,1907,-640,5,1908,-18,3,1909,-5,2,1910,-6,2,1911,-21,3,1912,-652,5,1913,-653,5,1914,-654,5,1915,-4,2,1916,-5,2,1917,-657,5,1918,-658,5,1919,-5,2,1920,-660,5,1921,-661,5,1922,-662,5,1923,-5,2,1924,-664,5,1925,-665,5,1926,-666,5,1927,-667,5,1928,-668,5,1929,-669,5,1930,-5,2,1931,-671,5,1932,-21,3,1933,-21,3,1934,-21,3,1935,-21,3,1936,-4,2,1937,-5,2,1938,-21,3,1939,-21,3,1940,-5,2,1941,-21,3,1942,-21,3,1943,-21,3,1944,-5,2,1945,-21,3,1946,-21,3,1947,-21,3,1948,-21,3,1949,-21,3,1950,-21,3,1951,-5,2,1952,-21,3,1953,-63,4,1954,-63,4,1955,-63,4,1956,-63,4,1957,-63,4,1958,-63,4,1959,-63,4,1960,-63,4,1961,-63,4,1962,-63,4,1963,-73,4,1964,-63,4,1965,-63,4,1966,-63,4,1967,-63,4,1968,-15,3,1969,-63,4,1970,-73,4,1971,-63,4,1972,-63,4,1973,-63,4,1974,-63,4,1975,-63,4,1976,-63,4,1977,-87,4,1978,-63,4,1979,-63,4,1980,-63,4,1981,-91,4,1982,-5,2,1983,-87,4,1984,-94,4,1985,-95,4,1986,-5,2,1987,-91,4,1988,-91,4,1989,-99,4,1990,-94,4,1991,-94,4,1992,-102,4,1993,-5,2,1994,-91,4,1995,-63,4,1996,-63,4,1997,-63,4,1998,-21,3,1999,-63,4,2000,-63,4,2001,-63,4,2002,-21,3,2003,-5,2,2004,-87,4,2005,-91,4,2006,-21,3,2007,-5,2,2008,-91,4,2009,-91,4,2010,-21,3,2011,-91,4,2012,-91,4,2013,-21,3,2014,-5,2,2015,-91,4,2016,-630,5,2017,-631,5,2018,-632,5,2019,-633,5,2020,-4,2,2021,-5,2,2022,-6,2,2023,-637,5,2024,-637,5,2025,-637,5,2026,-637,5,2027,-4,2,2028,-5,2,2029,-6,2,2030,-637,5,2031,-15,3,2032,-637,5,2033,-637,5,2034,-18,3,2035,-5,2,2036,-6,2,2037,-21,3,2038,-526,5,2039,-527,5,2040,-528,5,2041,-4,2,2042,-5,2,2043,-531,5,2044,-532,5,2045,-5,2,2046,-534,5,2047,-535,5,0,0,0"),
// leafSize 8
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,-1,0,10,-2,1,11,-3,1,12,-4,1,13,-5,1,14,-7,2,15,-7,2,16,-8,2,17,-8,2,18,3,4,19,-8,2,20,-8,2,21,3,4,22,-7,2,23,-7,2,24,3,4,25,-1,1,26,-2,1,27,-3,1,28,4,7,29,-5,2,30,-6,2,31,-7,2,32,4,7,33,-1,1,34,-2,1,35,-3,1,36,-4,2,37,-5,2,38,-6,2,39,-7,2,40,-8,2,41,-9,2,42,-10,2,43,-11,2,44,-12,2,45,-5,2,46,-7,2,47,-7,2,48,-8,2,49,-21,2,50,-18,2,51,-8,2,52,-24,3,53,-21,3,54,-7,2,55,-7,2,56,-24,3,57,-25,3,58,-26,3,59,-27,3,60,-28,3,61,-29,3,62,-30,3,63,-31,3,64,-32,3,65,-32,3,66,-32,3,67,-32,3,68,-4,2,69,-32,3,70,-32,3,71,-32,3,72,-32,3,73,-32,3,74,-32,3,75,-32,3,76,-32,3,77,-32,3,78,-39,3,79,-39,3,80,-40,3,81,-21,3,82,-32,3,83,-40,3,84,-24,3,85,-21,3,86,-40,3,87,-40,3,88,-24,3,89,-24,3,90,-26,3,91,-27,3,92,-28,3,93,-24,3,94,-24,3,95,-24,3,96,3,6,97,-1,1,98,-2,1,99,-3,1,100,-4,2,101,-5,2,102,-6,2,103,-7,2,104,-8,2,105,-9,2,106,-8,2,107,-11,2,108,-4,2,109,-5,2,110,-7,2,111,-7,2,112,-8,2,113,-8,2,114,-18,3,115,-8,2,116,-20,3,117,-21,3,118,-7,2,119,-7,2,120,-24,3,121,-1,1,122,-26,3,123,-27,3,124,-28,3,125,-24,3,126,-30,3,127,-31,3,128,-32,3,129,-1,1,130,-34,3,131,-35,3,132,-4,2,133,-5,2,134,-6,2,135,-32,3,136,-40,3,137,-41,3,138,-42,3,139,-43,3,140,-44,3,141,-5,2,142,-32,3,143,-7,2,144,-8,2,145,-21,3,146,-18,3,147,-3,1,148,-24,3,149,-21,3,150,-7,2,151,-7,2,152,-24,3,153,-1,0,154,-2,1,155,-3,1,156,-28,3,157,-5,2,158,-6,2,159,-7,2,160,-32,3,161,-1,0,162,-2,1,163,-3,1,164,-4,2,165,-5,2,166,-6,2,167,-7,2,168,-8,2,169,-8,2,170,-8,2,171,-8,2,172,-4,2,173,-5,2,174,-7,2,175,-7,2,176,-8,2,177,-21,3,178,-18,3,179,-8,2,180,-24,3,181,-21,3,182,-7,2,183,-7,2,184,-24,3,185,-24,3,186,-24,3,187,-24,3,188,-28,3,189,-5,2,190,-24,3,191,-24,3,192,-96,4,193,-1,0,194,-2,1,195,-3,1,196,-4,2,197,-5,2,198,-6,2,199,-7,2,200,-8,2,201,-8,2,202,-8,2,203,-8,2,204,-4,2,205,-5,2,206,-7,2,207,-7,2,208,-8,2,209,-8,2,210,-96,4,211,-8,2,212,-4,2,213,-96,4,214,-7,2,215,-7,2,216,-96,4,217,-1,0,218,-2,1,219,-3,1,220,-96,4,221,-5,2,222,-6,2,223,-7,2,224,-96,4,225,-1,0,226,-2,1,227,-3,1,228,-4,2,229,-5,2,230,-6,2,231,-7,2,232,-8,2,233,-8,2,234,-8,2,235,-8,2,236,-4,2,237,-5,2,238,-7,2,239,-7,2,240,-96,4,241,-96,4,242,-96,4,243,-96,4,244,-96,4,245,-96,4,246,-7,2,247,-96,4,248,-96,4,249,-96,4,250,-96,4,251,-96,4,252,-124,4,253,-96,4,254,-96,4,255,-96,4,256,-128,4,257,-1,0,258,-2,1,259,-3,1,260,-4,2,261,-5,2,262,-6,2,263,-7,2,264,-8,2,265,-8,2,266,-8,2,267,-96,4,268,-4,2,269,-5,2,270,-7,2,271,-96,4,272,-96,4,273,-128,4,274,-18,3,275,-128,4,276,-128,4,277,-128,4,278,-96,4,279,-128,4,280,-128,4,281,-128,4,282,-128,4,283,-128,4,284,-128,4,285,-128,4,286,-128,4,287,-128,4,288,-96,4,289,-96,4,290,-96,4,291,-96,4,292,-4,2,293,-96,4,294,-96,4,295,-96,4,296,-96,4,297,-96,4,298,-96,4,299,-96,4,300,-4,2,301,-96,4,302,-96,4,303,-96,4,304,-96,4,305,-96,4,306,-96,4,307,-96,4,308,-4,2,309,-96,4,310,-96,4,311,-96,4,312,-96,4,313,-96,4,314,-96,4,315,-96,4,316,-96,4,317,-96,4,318,-96,4,319,-96,4,320,-96,4,321,-96,4,322,-96,4,323,-96,4,324,-4,2,325,-96,4,326,-96,4,327,-96,4,328,-96,4,329,-96,4,330,-96,4,331,-96,4,332,-4,2,333,-96,4,334,-96,4,335,-96,4,336,-96,4,337,-96,4,338,-96,4,339,-96,4,340,-96,4,341,-96,4,342,-96,4,343,-96,4,344,-96,4,345,-96,4,346,-96,4,347,-96,4,348,-96,4,349,-96,4,350,-96,4,351,-96,4,352,-96,4,353,-96,4,354,-96,4,355,-96,4,356,-4,2,357,-96,4,358,-96,4,359,-96,4,360,-96,4,361,-96,4,362,-96,4,363,-96,4,364,-4,2,365,-96,4,366,-96,4,367,-96,4,368,-96,4,369,-96,4,370,-18,3,371,-96,4,372,-96,4,373,-96,4,374,-96,4,375,-96,4,376,-96,4,377,-96,4,378,-96,4,379,-96,4,380,-96,4,381,-96,4,382,-96,4,383,-96,4,384,-96,4,385,-96,4,386,-96,4,387,-96,4,388,-4,2,389,-96,4,390,-96,4,391,-96,4,392,-96,4,393,-96,4,394,-96,4,395,-96,4,396,-4,2,397,-96,4,398,-96,4,399,-96,4,400,-96,4,401,-96,4,402,-96,4,403,-96,4,404,-4,2,405,-96,4,406,-96,4,407,-96,4,408,-96,4,409,-96,4,410,-96,4,411,-96,4,412,-96,4,413,-96,4,414,-96,4,415,-96,4,416,-96,4,417,-96,4,418,-96,4,419,-96,4,420,-4,2,421,-96,4,422,-96,4,423,-96,4,424,-96,4,425,-96,4,426,-96,4,427,-96,4,428,-4,2,429,-96,4,430,-96,4,431,-96,4,432,-96,4,433,-96,4,434,-96,4,435,-96,4,436,-96,4,437,-96,4,438,-96,4,439,-96,4,440,-96,4,441,-96,4,442,-96,4,443,-96,4,444,-96,4,445,-96,4,446,-96,4,447,-96,4,448,-96,4,449,-96,4,450,-96,4,451,-96,4,452,-4,2,453,-96,4,454,-96,4,455,-96,4,456,-96,4,457,-96,4,458,-96,4,459,-96,4,460,-4,2,461,-96,4,462,-96,4,463,-96,4,464,-96,4,465,-96,4,466,-18,3,467,-96,4,468,-96,4,469,-96,4,470,-96,4,471,-96,4,472,-96,4,473,-96,4,474,-96,4,475,-96,4,476,-96,4,477,-96,4,478,-96,4,479,-96,4,480,-96,4,481,-96,4,482,-96,4,483,-96,4,484,-4,2,485,-96,4,486,-96,4,487,-96,4,488,-96,4,489,-96,4,490,-96,4,491,-96,4,492,-4,2,493,-96,4,494,-96,4,495,-96,4,496,-96,4,497,-96,4,498,-18,3,499,-96,4,500,-4,2,501,-96,4,502,-96,4,503,-96,4,504,-96,4,505,-96,4,506,-96,4,507,-96,4,508,-96,4,509,-96,4,510,-96,4,511,-96,4,512,-96,4,513,-96,4,514,-96,4,515,-96,4,516,-4,2,517,-96,4,518,-96,4,519,-96,4,520,-96,4,521,-96,4,522,-96,4,523,-96,4,524,-4,2,525,-96,4,526,-96,4,527,-96,4,528,-96,4,529,-96,4,530,-96,4,531,-96,4,532,-96,4,533,-96,4,534,-96,4,535,-96,4,536,-96,4,537,-96,4,538,-96,4,539,-96,4,540,-96,4,541,-96,4,542,-96,4,543,-96,4,544,-96,4,545,-96,4,546,-96,4,547,-96,4,548,-4,2,549,-96,4,550,-96,4,551,-96,4,552,-96,4,553,-96,4,554,-96,4,555,-96,4,556,-4,2,557,-96,4,558,-96,4,559,-96,4,560,-96,4,561,-96,4,562,-18,3,563,-96,4,564,-96,4,565,-96,4,566,-96,4,567,-96,4,568,-96,4,569,-96,4,570,-96,4,571,-96,4,572,-96,4,573,-96,4,574,-96,4,575,-96,4,576,-96,4,577,-96,4,578,-96,4,579,-96,4,580,-4,2,581,-96,4,582,-96,4,583,-96,4,584,-96,4,585,-96,4,586,-96,4,587,-96,4,588,-4,2,589,-96,4,590,-96,4,591,-96,4,592,-96,4,593,-96,4,594,-18,3,595,-96,4,596,-4,2,597,-96,4,598,-96,4,599,-96,4,600,-96,4,601,-96,4,602,-96,4,603,-96,4,604,-96,4,605,-96,4,606,-96,4,607,-96,4,608,-96,4,609,-96,4,610,-96,4,611,-96,4,612,-4,2,613,-96,4,614,-96,4,615,-96,4,616,-96,4,617,-96,4,618,-96,4,619,-96,4,620,-4,2,621,-96,4,622,-96,4,623,-96,4,624,-96,4,625,-96,4,626,-96,4,627,-96,4,628,-96,4,629,-96,4,630,-96,4,631,-96,4,632,-96,4,633,-96,4,634,-96,4,635,-96,4,636,-96,4,637,-96,4,638,-96,4,639,-96,4,640,-96,4,641,-96,4,642,-96,4,643,-96,4,644,-4,2,645,-96,4,646,-96,4,647,-96,4,648,-96,4,649,-96,4,650,-96,4,651,-96,4,652,-4,2,653,-96,4,654,-96,4,655,-96,4,656,-96,4,657,-96,4,658,-18,3,659,-96,4,660,-96,4,661,-96,4,662,-96,4,663,-96,4,664,-96,4,665,-96,4,666,-96,4,667,-96,4,668,-96,4,669,-96,4,670,-96,4,671,-96,4,672,-96,4,673,-96,4,674,-96,4,675,-96,4,676,-4,2,677,-96,4,678,-96,4,679,-96,4,680,-96,4,681,-96,4,682,-96,4,683,-96,4,684,-4,2,685,-96,4,686,-96,4,687,-96,4,688,-96,4,689,-96,4,690,-18,3,691,-96,4,692,-4,2,693,-96,4,694,-96,4,695,-96,4,696,-96,4,697,-96,4,698,-96,4,699,-96,4,700,-96,4,701,-96,4,702,-96,4,703,-96,4,704,-96,4,705,-96,4,706,-96,4,707,-96,4,708,-4,2,709,-96,4,710,-96,4,711,-96,4,712,-96,4,713,-96,4,714,-96,4,715,-96,4,716,-4,2,717,-96,4,718,-96,4,719,-96,4,720,-96,4,721,-96,4,722,-96,4,723,-96,4,724,-96,4,725,-96,4,726,-96,4,727,-96,4,728,-96,4,729,-96,4,730,-96,4,731,-96,4,732,-96,4,733,-96,4,734,-96,4,735,-96,4,736,-96,4,737,-96,4,738,-96,4,739,-96,4,740,-4,2,741,-96,4,742,-96,4,743,-96,4,744,-96,4,745,-96,4,746,-96,4,747,-96,4,748,-4,2,749,-96,4,750,-96,4,751,-96,4,752,-96,4,753,-96,4,754,-18,3,755,-96,4,756,-96,4,757,-96,4,758,-96,4,759,-96,4,760,-96,4,761,-96,4,762,-96,4,763,-96,4,764,-96,4,765,-96,4,766,-96,4,767,-96,4,768,-96,4,769,-96,4,770,-96,4,771,-96,4,772,-4,2,773,-96,4,774,-96,4,775,-96,4,776,-96,4,777,-96,4,778,-96,4,779,-96,4,780,-4,2,781,-96,4,782,-96,4,783,-96,4,784,-96,4,785,-96,4,786,-18,3,787,-96,4,788,-4,2,789,-96,4,790,-96,4,791,-96,4,792,-96,4,793,-96,4,794,-96,4,795,-96,4,796,-96,4,797,-96,4,798,-96,4,799,-96,4,800,-96,4,801,-96,4,802,-96,4,803,-96,4,804,-4,2,805,-96,4,806,-96,4,807,-96,4,808,-96,4,809,-96,4,810,-96,4,811,-96,4,812,-4,2,813,-96,4,814,-96,4,815,-96,4,816,-96,4,817,-96,4,818,-96,4,819,-96,4,820,-96,4,821,-96,4,822,-96,4,823,-96,4,824,-96,4,825,-96,4,826,-96,4,827,-96,4,828,-96,4,829,-96,4,830,-96,4,831,-96,4,832,-96,4,833,-96,4,834,-96,4,835,-96,4,836,-4,2,837,-96,4,838,-96,4,839,-96,4,840,-96,4,841,-96,4,842,-96,4,843,-96,4,844,-4,2,845,-96,4,846,-96,4,847,-96,4,848,-96,4,849,-96,4,850,-18,3,851,-96,4,852,-96,4,853,-96,4,854,-96,4,855,-96,4,856,-96,4,857,-96,4,858,-96,4,859,-96,4,860,-96,4,861,-96,4,862,-96,4,863,-96,4,864,-96,4,865,-96,4,866,-96,4,867,-96,4,868,-4,2,869,-96,4,870,-96,4,871,-96,4,872,-96,4,873,-96,4,874,-96,4,875,-96,4,876,-4,2,877,-96,4,878,-96,4,879,-96,4,880,-96,4,881,-96,4,882,-18,3,883,-96,4,884,-4,2,885,-96,4,886,-96,4,887,-96,4,888,-96,4,889,-96,4,890,-96,4,891,-96,4,892,-96,4,893,-96,4,894,-96,4,895,-96,4,896,-96,4,897,-96,4,898,-96,4,899,-96,4,900,-4,2,901,-96,4,902,-96,4,903,-96,4,904,-96,4,905,-96,4,906,-96,4,907,-96,4,908,-4,2,909,-96,4,910,-96,4,911,-96,4,912,-96,4,913,-96,4,914,-96,4,915,-96,4,916,-96,4,917,-96,4,918,-96,4,919,-96,4,920,-96,4,921,-96,4,922,-96,4,923,-96,4,924,-96,4,925,-96,4,926,-96,4,927,-96,4,928,-96,4,929,-96,4,930,-96,4,931,-96,4,932,-4,2,933,-96,4,934,-96,4,935,-96,4,936,-96,4,937,-96,4,938,-96,4,939,-96,4,940,-4,2,941,-96,4,942,-96,4,943,-96,4,944,-96,4,945,-96,4,946,-18,3,947,-96,4,948,-96,4,949,-96,4,950,-96,4,951,-96,4,952,-96,4,953,-96,4,954,-96,4,955,-96,4,956,-96,4,957,-96,4,958,-96,4,959,-96,4,960,-96,4,961,-96,4,962,-96,4,963,-96,4,964,-4,2,965,-96,4,966,-96,4,967,-96,4,968,-96,4,969,-96,4,970,-96,4,971,-96,4,972,-4,2,973,-96,4,974,-96,4,975,-96,4,976,-96,4,977,-96,4,978,-18,3,979,-96,4,980,-4,2,981,-96,4,982,-96,4,983,-96,4,984,-96,4,985,-96,4,986,-96,4,987,-96,4,988,-96,4,989,-96,4,990,-96,4,991,-96,4,992,-96,4,993,-96,4,994,-96,4,995,-96,4,996,-4,2,997,-96,4,998,-96,4,999,-96,4,1000,-96,4,1001,-96,4,1002,-96,4,1003,-96,4,1004,-4,2,1005,-96,4,1006,-96,4,1007,-96,4,1008,-96,4,1009,-96,4,1010,-96,4,1011,-96,4,1012,-96,4,1013,-96,4,1014,-96,4,1015,-96,4,1016,-96,4,1017,-96,4,1018,-96,4,1019,-96,4,1020,-96,4,1021,-96,4,1022,-96,4,1023,-96,4,1024,-96,4,1025,-96,4,1026,-96,4,1027,-96,4,1028,-4,2,1029,-96,4,1030,-96,4,1031,-96,4,1032,-96,4,1033,-96,4,1034,-96,4,1035,-96,4,1036,-4,2,1037,-96,4,1038,-96,4,1039,-96,4,1040,-96,4,1041,-96,4,1042,-18,3,1043,-96,4,1044,-96,4,1045,-96,4,1046,-96,4,1047,-96,4,1048,-96,4,1049,-96,4,1050,-96,4,1051,-96,4,1052,-96,4,1053,-96,4,1054,-96,4,1055,-96,4,1056,-96,4,1057,-96,4,1058,-96,4,1059,-96,4,1060,-4,2,1061,-96,4,1062,-96,4,1063,-96,4,1064,-96,4,1065,-96,4,1066,-96,4,1067,-96,4,1068,-4,2,1069,-96,4,1070,-96,4,1071,-96,4,1072,-96,4,1073,-96,4,1074,-18,3,1075,-96,4,1076,-4,2,1077,-96,4,1078,-96,4,1079,-96,4,1080,-96,4,1081,-96,4,1082,-96,4,1083,-96,4,1084,-96,4,1085,-96,4,1086,-96,4,1087,-96,4,1088,-96,4,1089,-96,4,1090,-96,4,1091,-96,4,1092,-4,2,1093,-96,4,1094,-96,4,1095,-96,4,1096,-96,4,1097,-96,4,1098,-96,4,1099,-96,4,1100,-4,2,1101,-96,4,1102,-96,4,1103,-96,4,1104,-96,4,1105,-96,4,1106,-96,4,1107,-96,4,1108,-96,4,1109,-96,4,1110,-96,4,1111,-96,4,1112,-96,4,1113,-96,4,1114,-96,4,1115,-96,4,1116,-96,4,1117,-96,4,1118,-96,4,1119,-96,4,1120,-96,4,1121,-96,4,1122,-96,4,1123,-96,4,1124,-4,2,1125,-96,4,1126,-96,4,1127,-96,4,1128,-96,4,1129,-96,4,1130,-96,4,1131,-96,4,1132,-4,2,1133,-96,4,1134,-96,4,1135,-96,4,1136,-96,4,1137,-96,4,1138,-18,3,1139,-96,4,1140,-96,4,1141,-96,4,1142,-96,4,1143,-96,4,1144,-96,4,1145,-96,4,1146,-96,4,1147,-96,4,1148,-96,4,1149,-96,4,1150,-96,4,1151,-96,4,1152,-96,4,1153,-96,4,1154,-96,4,1155,-96,4,1156,-4,2,1157,-96,4,1158,-96,4,1159,-96,4,1160,-96,4,1161,-96,4,1162,-96,4,1163,-96,4,1164,-4,2,1165,-96,4,1166,-96,4,1167,-96,4,1168,-96,4,1169,-96,4,1170,-18,3,1171,-96,4,1172,-4,2,1173,-96,4,1174,-96,4,1175,-96,4,1176,-96,4,1177,-96,4,1178,-96,4,1179,-96,4,1180,-96,4,1181,-96,4,1182,-96,4,1183,-96,4,1184,-96,4,1185,-96,4,1186,-96,4,1187,-96,4,1188,-4,2,1189,-96,4,1190,-96,4,1191,-96,4,1192,-96,4,1193,-96,4,1194,-96,4,1195,-96,4,1196,-4,2,1197,-96,4,1198,-96,4,1199,-96,4,1200,-96,4,1201,-96,4,1202,-96,4,1203,-96,4,1204,-96,4,1205,-96,4,1206,-96,4,1207,-96,4,1208,-96,4,1209,-96,4,1210,-96,4,1211,-96,4,1212,-96,4,1213,-96,4,1214,-96,4,1215,-96,4,1216,-96,4,1217,-96,4,1218,-96,4,1219,-96,4,1220,-4,2,1221,-96,4,1222,-96,4,1223,-96,4,1224,-96,4,1225,-96,4,1226,-96,4,1227,-96,4,1228,-4,2,1229,-96,4,1230,-96,4,1231,-96,4,1232,-96,4,1233,-96,4,1234,-18,3,1235,-96,4,1236,-96,4,1237,-96,4,1238,-96,4,1239,-96,4,1240,-96,4,1241,-96,4,1242,-96,4,1243,-96,4,1244,-96,4,1245,-96,4,1246,-96,4,1247,-96,4,1248,-96,4,1249,-96,4,1250,-96,4,1251,-96,4,1252,-4,2,1253,-96,4,1254,-96,4,1255,-96,4,1256,-96,4,1257,-96,4,1258,-96,4,1259,-96,4,1260,-4,2,1261,-96,4,1262,-96,4,1263,-96,4,1264,-96,4,1265,-96,4,1266,-18,3,1267,-96,4,1268,-4,2,1269,-96,4,1270,-96,4,1271,-96,4,1272,-96,4,1273,-96,4,1274,-96,4,1275,-96,4,1276,-96,4,1277,-96,4,1278,-96,4,1279,-96,4,1280,-96,4,1281,-96,4,1282,-96,4,1283,-96,4,1284,-4,2,1285,-96,4,1286,-96,4,1287,-96,4,1288,-96,4,1289,-96,4,1290,-96,4,1291,-96,4,1292,-4,2,1293,-96,4,1294,-96,4,1295,-96,4,1296,-96,4,1297,-96,4,1298,-96,4,1299,-96,4,1300,-96,4,1301,-96,4,1302,-96,4,1303,-96,4,1304,-96,4,1305,-96,4,1306,-96,4,1307,-96,4,1308,-96,4,1309,-96,4,1310,-96,4,1311,-96,4,1312,-96,4,1313,-96,4,1314,-96,4,1315,-96,4,1316,-4,2,1317,-96,4,1318,-96,4,1319,-96,4,1320,-96,4,1321,-96,4,1322,-96,4,1323,-96,4,1324,-4,2,1325,-96,4,1326,-96,4,1327,-96,4,1328,-96,4,1329,-96,4,1330,-18,3,1331,-96,4,1332,-96,4,1333,-96,4,1334,-96,4,1335,-96,4,1336,-96,4,1337,-96,4,1338,-96,4,1339,-96,4,1340,-96,4,1341,-96,4,1342,-96,4,1343,-96,4,1344,-96,4,1345,-96,4,1346,-96,4,1347,-96,4,1348,-4,2,1349,-96,4,1350,-96,4,1351,-96,4,1352,-96,4,1353,-96,4,1354,-96,4,1355,-96,4,1356,-4,2,1357,-96,4,1358,-96,4,1359,-96,4,1360,-96,4,1361,-96,4,1362,-18,3,1363,-96,4,1364,-4,2,1365,-96,4,1366,-96,4,1367,-96,4,1368,-96,4,1369,-96,4,1370,-96,4,1371,-96,4,1372,-96,4,1373,-96,4,1374,-96,4,1375,-96,4,1376,-96,4,1377,-96,4,1378,-96,4,1379,-96,4,1380,-4,2,1381,-96,4,1382,-96,4,1383,-96,4,1384,-96,4,1385,-96,4,1386,-96,4,1387,-96,4,1388,-4,2,1389,-96,4,1390,-96,4,1391,-96,4,1392,-96,4,1393,-96,4,1394,-96,4,1395,-96,4,1396,-96,4,1397,-96,4,1398,-96,4,1399,-96,4,1400,-96,4,1401,-96,4,1402,-96,4,1403,-96,4,1404,-96,4,1405,-96,4,1406,-96,4,1407,-96,4,1408,-96,4,1409,-96,4,1410,-96,4,1411,-96,4,1412,-4,2,1413,-96,4,1414,-96,4,1415,-96,4,1416,-96,4,1417,-96,4,1418,-96,4,1419,-96,4,1420,-4,2,1421,-96,4,1422,-96,4,1423,-96,4,1424,-96,4,1425,-96,4,1426,-18,3,1427,-96,4,1428,-96,4,1429,-96,4,1430,-96,4,1431,-96,4,1432,-96,4,1433,-96,4,1434,-96,4,1435,-96,4,1436,-96,4,1437,-96,4,1438,-96,4,1439,-96,4,1440,-96,4,1441,-96,4,1442,-96,4,1443,-96,4,1444,-4,2,1445,-96,4,1446,-96,4,1447,-96,4,1448,-96,4,1449,-96,4,1450,-96,4,1451,-96,4,1452,-4,2,1453,-96,4,1454,-96,4,1455,-96,4,1456,-96,4,1457,-96,4,1458,-18,3,1459,-96,4,1460,-4,2,1461,-96,4,1462,-96,4,1463,-96,4,1464,-96,4,1465,-96,4,1466,-96,4,1467,-96,4,1468,-96,4,1469,-96,4,1470,-96,4,1471,-96,4,1472,-96,4,1473,-96,4,1474,-96,4,1475,-96,4,1476,-4,2,1477,-96,4,1478,-96,4,1479,-96,4,1480,-96,4,1481,-96,4,1482,-96,4,1483,-96,4,1484,-4,2,1485,-96,4,1486,-96,4,1487,-96,4,1488,-96,4,1489,-96,4,1490,-96,4,1491,-96,4,1492,-96,4,1493,-96,4,1494,-96,4,1495,-96,4,1496,-96,4,1497,-96,4,1498,-96,4,1499,-96,4,1500,-96,4,1501,-96,4,1502,-96,4,1503,-96,4,1504,-96,4,1505,-96,4,1506,-96,4,1507,-96,4,1508,-4,2,1509,-96,4,1510,-96,4,1511,-96,4,1512,-96,4,1513,-96,4,1514,-96,4,1515,-96,4,1516,-4,2,1517,-96,4,1518,-96,4,1519,-96,4,1520,-96,4,1521,-96,4,1522,-18,3,1523,-96,4,1524,-96,4,1525,-96,4,1526,-96,4,1527,-96,4,1528,-96,4,1529,-96,4,1530,-96,4,1531,-96,4,1532,-96,4,1533,-96,4,1534,-96,4,1535,-96,4,1536,-96,4,1537,-96,4,1538,-96,4,1539,-96,4,1540,-4,2,1541,-96,4,1542,-96,4,1543,-96,4,1544,-96,4,1545,-96,4,1546,-96,4,1547,-96,4,1548,-4,2,1549,-96,4,1550,-96,4,1551,-96,4,1552,-96,4,1553,-96,4,1554,-18,3,1555,-96,4,1556,-4,2,1557,-96,4,1558,-96,4,1559,-96,4,1560,-96,4,1561,-96,4,1562,-96,4,1563,-96,4,1564,-96,4,1565,-96,4,1566,-96,4,1567,-96,4,1568,-96,4,1569,-96,4,1570,-96,4,1571,-96,4,1572,-4,2,1573,-96,4,1574,-96,4,1575,-96,4,1576,-96,4,1577,-96,4,1578,-96,4,1579,-96,4,1580,-4,2,1581,-96,4,1582,-96,4,1583,-96,4,1584,-96,4,1585,-96,4,1586,-18,3,1587,-96,4,1588,-96,4,1589,-96,4,1590,-96,4,1591,-96,4,1592,-96,4,1593,-96,4,1594,-96,4,1595,-96,4,1596,-96,4,1597,-96,4,1598,-96,4,1599,-96,4,1600,-96,4,1601,-96,4,1602,-96,4,1603,-96,4,1604,-4,2,1605,-96,4,1606,-96,4,1607,-96,4,1608,-96,4,1609,-96,4,1610,-96,4,1611,-96,4,1612,-4,2,1613,-96,4,1614,-96,4,1615,-96,4,1616,-96,4,1617,-96,4,1618,-18,3,1619,-96,4,1620,-96,4,1621,-96,4,1622,-96,4,1623,-96,4,1624,-96,4,1625,-96,4,1626,-96,4,1627,-96,4,1628,-96,4,1629,-96,4,1630,-96,4,1631,-96,4,1632,-96,4,1633,-96,4,1634,-96,4,1635,-96,4,1636,-4,2,1637,-96,4,1638,-96,4,1639,-96,4,1640,-96,4,1641,-96,4,1642,-96,4,1643,-96,4,1644,-4,2,1645,-96,4,1646,-96,4,1647,-96,4,1648,-96,4,1649,-96,4,1650,-18,3,1651,-96,4,1652,-4,2,1653,-96,4,1654,-96,4,1655,-96,4,1656,-96,4,1657,-96,4,1658,-96,4,1659,-96,4,1660,-96,4,1661,-96,4,1662,-96,4,1663,-96,4,1664,-96,4,1665,-96,4,1666,-96,4,1667,-96,4,1668,-4,2,1669,-96,4,1670,-96,4,1671,-96,4,1672,-96,4,1673,-96,4,1674,-96,4,1675,-96,4,1676,-4,2,1677,-96,4,1678,-96,4,1679,-96,4,1680,-96,4,1681,-96,4,1682,-18,3,1683,-96,4,1684,-96,4,1685,-96,4,1686,-96,4,1687,-96,4,1688,-96,4,1689,-96,4,1690,-96,4,1691,-96,4,1692,-96,4,1693,-96,4,1694,-96,4,1695,-96,4,1696,-96,4,1697,-96,4,1698,-96,4,1699,-96,4,1700,-4,2,1701,-96,4,1702,-96,4,1703,-96,4,1704,-96,4,1705,-96,4,1706,-96,4,1707,-96,4,1708,-4,2,1709,-96,4,1710,-96,4,1711,-96,4,1712,-96,4,1713,-96,4,1714,-18,3,1715,-96,4,1716,-96,4,1717,-96,4,1718,-96,4,1719,-96,4,1720,-96,4,1721,-96,4,1722,-96,4,1723,-96,4,1724,-96,4,1725,-96,4,1726,-96,4,1727,-96,4,1728,-96,4,1729,-96,4,1730,-96,4,1731,-96,4,1732,-4,2,1733,-96,4,1734,-96,4,1735,-96,4,1736,-96,4,1737,-96,4,1738,-96,4,1739,-96,4,1740,-4,2,1741,-96,4,1742,-96,4,1743,-96,4,1744,-96,4,1745,-96,4,1746,-18,3,1747,-96,4,1748,-4,2,1749,-96,4,1750,-96,4,1751,-96,4,1752,-96,4,1753,-96,4,1754,-96,4,1755,-96,4,1756,-96,4,1757,-96,4,1758,-96,4,1759,-96,4,1760,-96,4,1761,-96,4,1762,-96,4,1763,-96,4,1764,-4,2,1765,-96,4,1766,-96,4,1767,-96,4,1768,-96,4,1769,-96,4,1770,-96,4,1771,-96,4,1772,-4,2,1773,-96,4,1774,-96,4,1775,-96,4,1776,-96,4,1777,-96,4,1778,-18,3,1779,-96,4,1780,-96,4,1781,-96,4,1782,-96,4,1783,-96,4,1784,-96,4,1785,-96,4,1786,-96,4,1787,-96,4,1788,-96,4,1789,-96,4,1790,-96,4,1791,-96,4,1792,-96,4,1793,-96,4,1794,-96,4,1795,-96,4,1796,-4,2,1797,-96,4,1798,-96,4,1799,-96,4,1800,-96,4,1801,-96,4,1802,-96,4,1803,-96,4,1804,-4,2,1805,-96,4,1806,-96,4,1807,-96,4,1808,-96,4,1809,-96,4,1810,-18,3,1811,-96,4,1812,-96,4,1813,-96,4,1814,-96,4,1815,-96,4,1816,-96,4,1817,-96,4,1818,-96,4,1819,-96,4,1820,-96,4,1821,-96,4,1822,-96,4,1823,-96,4,1824,-96,4,1825,-96,4,1826,-96,4,1827,-96,4,1828,-4,2,1829,-96,4,1830,-96,4,1831,-96,4,1832,-96,4,1833,-96,4,1834,-96,4,1835,-96,4,1836,-4,2,1837,-96,4,1838,-96,4,1839,-96,4,1840,-96,4,1841,-96,4,1842,-18,3,1843,-96,4,1844,-4,2,1845,-96,4,1846,-96,4,1847,-96,4,1848,-96,4,1849,-96,4,1850,-96,4,1851,-96,4,1852,-96,4,1853,-96,4,1854,-96,4,1855,-96,4,1856,-96,4,1857,-96,4,1858,-96,4,1859,-96,4,1860,-4,2,1861,-96,4,1862,-96,4,1863,-96,4,1864,-96,4,1865,-96,4,1866,-96,4,1867,-96,4,1868,-4,2,1869,-96,4,1870,-96,4,1871,-96,4,1872,-96,4,1873,-96,4,1874,-18,3,1875,-96,4,1876,-96,4,1877,-96,4,1878,-96,4,1879,-96,4,1880,-96,4,1881,-96,4,1882,-96,4,1883,-96,4,1884,-96,4,1885,-96,4,1886,-96,4,1887,-96,4,1888,-96,4,1889,-96,4,1890,-96,4,1891,-96,4,1892,-4,2,1893,-96,4,1894,-96,4,1895,-96,4,1896,-96,4,1897,-96,4,1898,-96,4,1899,-96,4,1900,-4,2,1901,-96,4,1902,-96,4,1903,-96,4,1904,-96,4,1905,-96,4,1906,-18,3,1907,-96,4,1908,-96,4,1909,-96,4,1910,-96,4,1911,-96,4,1912,-96,4,1913,-96,4,1914,-96,4,1915,-96,4,1916,-96,4,1917,-96,4,1918,-96,4,1919,-96,4,1920,-96,4,1921,-96,4,1922,-96,4,1923,-96,4,1924,-4,2,1925,-96,4,1926,-96,4,1927,-96,4,1928,-96,4,1929,-96,4,1930,-96,4,1931,-96,4,1932,-4,2,1933,-96,4,1934,-96,4,1935,-96,4,1936,-96,4,1937,-96,4,1938,-18,3,1939,-96,4,1940,-4,2,1941,-96,4,1942,-96,4,1943,-96,4,1944,-96,4,1945,-96,4,1946,-96,4,1947,-96,4,1948,-96,4,1949,-96,4,1950,-96,4,1951,-96,4,1952,-96,4,1953,-96,4,1954,-96,4,1955,-96,4,1956,-4,2,1957,-96,4,1958,-96,4,1959,-96,4,1960,-96,4,1961,-96,4,1962,-96,4,1963,-96,4,1964,-4,2,1965,-96,4,1966,-96,4,1967,-96,4,1968,-96,4,1969,-96,4,1970,-18,3,1971,-96,4,1972,-96,4,1973,-96,4,1974,-96,4,1975,-96,4,1976,-96,4,1977,-96,4,1978,-96,4,1979,-96,4,1980,-96,4,1981,-96,4,1982,-96,4,1983,-96,4,1984,-96,4,1985,-96,4,1986,-96,4,1987,-96,4,1988,-4,2,1989,-96,4,1990,-96,4,1991,-96,4,1992,-96,4,1993,-96,4,1994,-96,4,1995,-96,4,1996,-4,2,1997,-5,2,1998,-96,4,1999,-96,4,2000,-96,4,2001,-96,4,2002,-18,3,2003,-96,4,2004,-96,4,2005,-96,4,2006,-96,4,2007,-96,4,2008,-96,4,2009,-96,4,2010,-96,4,2011,-96,4,2012,-96,4,2013,-96,4,2014,-96,4,2015,-96,4,2016,-96,4,2017,-96,4,2018,-96,4,2019,-96,4,2020,-4,2,2021,-96,4,2022,-96,4,2023,-96,4,2024,-96,4,2025,-96,4,2026,-96,4,2027,-96,4,2028,-4,2,2029,-96,4,2030,-96,4,2031,-96,4,2032,-96,4,2033,-96,4,2034,-18,3,2035,-96,4,2036,-4,2,2037,-96,4,2038,-96,4,2039,-96,4,2040,-96,4,2041,-96,4,2042,-96,4,2043,-96,4,2044,-96,4,2045,-96,4,2046,-96,4,2047,-96,4,0,0,0"),
// leafSize 9
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,-2,1,11,-2,1,12,-3,1,13,-5,1,14,-7,2,15,-7,2,16,-8,2,17,-8,2,18,-9,2,19,-9,2,20,-9,2,21,3,4,22,-7,2,23,-7,2,24,3,4,25,-8,2,26,-8,2,27,3,4,28,4,7,29,-2,1,30,-6,2,31,-7,2,32,4,7,33,-9,2,34,-7,2,35,5,9,36,4,7,37,-1,1,38,-2,1,39,-7,2,40,-8,2,41,-9,2,42,-6,2,43,-7,2,44,-8,2,45,-9,2,46,-10,2,47,-9,2,48,-8,2,49,-8,2,50,-9,2,51,-7,2,52,-8,2,53,-8,2,54,-9,2,55,-27,3,56,-24,3,57,-21,3,58,-8,2,59,-27,3,60,-24,3,61,-8,2,62,-8,2,63,-27,3,64,-32,3,65,-32,3,66,-32,3,67,-32,3,68,-32,3,69,-33,3,70,-34,3,71,-35,3,72,-36,3,73,-32,3,74,-36,3,75,-36,3,76,-36,3,77,-36,3,78,-36,3,79,-36,3,80,-36,3,81,-36,3,82,-36,3,83,-38,3,84,-40,3,85,-41,3,86,-41,3,87,-43,3,88,-44,3,89,-44,3,90,-45,3,91,-27,3,92,-24,3,93,-21,3,94,-45,3,95,-27,3,96,3,6,97,-45,3,98,-45,3,99,-27,3,100,-32,3,101,-5,2,102,-6,2,103,-7,2,104,-32,3,105,-9,2,106,-27,3,107,-35,3,108,3,6,109,-1,1,110,-2,1,111,-3,1,112,-4,2,113,-5,2,114,-6,2,115,-7,2,116,-8,2,117,-9,2,118,-8,2,119,-9,2,120,-4,2,121,-5,2,122,-7,2,123,-7,2,124,-8,2,125,-8,2,126,-9,2,127,-8,2,128,-32,3,129,-21,3,130,-7,2,131,-7,2,132,-24,3,133,-8,2,134,-26,3,135,-27,3,136,-28,3,137,-29,3,138,-24,3,139,-31,3,140,-32,3,141,-33,3,142,-34,3,143,-35,3,144,-36,3,145,-1,0,146,-2,1,147,-7,2,148,-8,2,149,-9,2,150,-6,2,151,-7,2,152,-8,2,153,-9,2,154,-9,2,155,-2,1,156,-8,2,157,-8,2,158,-9,2,159,-7,2,160,-8,2,161,-8,2,162,-9,2,163,-27,3,164,-24,3,165,-21,3,166,-8,2,167,-27,3,168,-24,3,169,-8,2,170,-8,2,171,-27,3,172,-32,3,173,-27,3,174,-27,3,175,-32,3,176,-32,3,177,-33,3,178,-27,3,179,-35,3,180,-36,3,181,-36,3,182,-36,3,183,-32,3,184,-32,3,185,-32,3,186,-6,2,187,-7,2,188,-36,3,189,-36,3,190,-36,3,191,-36,3,192,-32,3,193,-32,3,194,-32,3,195,-7,2,196,-36,3,197,-36,3,198,-36,3,199,-27,3,200,-24,3,201,-21,3,202,-32,3,203,-27,3,204,-96,4,205,-36,3,206,-36,3,207,-27,3,208,-32,3,209,-5,2,210,-6,2,211,-7,2,212,-32,3,213,-105,4,214,-27,3,215,-35,3,216,-108,4,217,-1,0,218,-2,1,219,-3,1,220,-4,2,221,-5,2,222,-6,2,223,-7,2,224,-8,2,225,-9,2,226,-9,2,227,-2,1,228,-9,2,229,-5,2,230,-7,2,231,-7,2,232,-8,2,233,-8,2,234,-9,2,235,-9,2,236,-108,4,237,-108,4,238,-7,2,239,-27,3,240,-108,4,241,-8,2,242,-8,2,243,-108,4,244,-108,4,245,-2,1,246,-6,2,247,-7,2,248,-108,4,249,-108,4,250,-7,2,251,-108,4,252,-108,4,253,-108,4,254,-108,4,255,-108,4,256,-108,4,257,-108,4,258,-108,4,259,-108,4,260,-108,4,261,-108,4,262,-108,4,263,-108,4,264,-108,4,265,-108,4,266,-108,4,267,-108,4,268,-108,4,269,-108,4,270,-108,4,271,-108,4,272,-108,4,273,-108,4,274,-108,4,275,-135,4,276,-108,4,277,-108,4,278,-108,4,279,-135,4,280,-140,4,281,-135,4,282,-135,4,283,-140,4,284,-140,4,285,-141,4,286,-135,4,287,-143,4,288,-144,4,289,-144,4,290,-144,4,291,-144,4,292,-144,4,293,-144,4,294,-144,4,295,-144,4,296,-144,4,297,-144,4,298,-145,4,299,-146,4,300,-148,4,301,-149,4,302,-149,4,303,-151,4,304,-152,4,305,-152,4,306,-153,4,307,-140,4,308,-144,4,309,-144,4,310,-153,4,311,-144,4,312,-96,4,313,-153,4,314,-153,4,315,-144,4,316,-144,4,317,-96,4,318,-96,4,319,-96,4,320,-144,4,321,-96,4,322,-151,4,323,-144,4,324,3,8,325,-1,0,326,-2,1,327,-3,1,328,-4,2,329,-5,2,330,-6,2,331,-7,2,332,-8,2,333,-9,2,334,-9,2,335,-2,1,336,-9,2,337,-5,2,338,-7,2,339,-7,2,340,-8,2,341,-8,2,342,-9,2,343,-9,2,344,-2,1,345,-21,3,346,-7,2,347,-7,2,348,-24,3,349,-8,2,350,-8,2,351,-27,3,352,-28,3,353,-27,3,354,-24,3,355,-24,3,356,-32,3,357,-33,3,358,-27,3,359,-35,3,360,-36,3,361,-36,3,362,-2,1,363,-7,2,364,-32,3,365,-32,3,366,-6,2,367,-7,2,368,-8,2,369,-36,3,370,-36,3,371,-2,1,372,-32,3,373,-32,3,374,-32,3,375,-7,2,376,-8,2,377,-8,2,378,-36,3,379,-27,3,380,-24,3,381,-21,3,382,-32,3,383,-27,3,384,-24,3,385,-8,2,386,-8,2,387,-27,3,388,-32,3,389,-27,3,390,-27,3,391,-32,3,392,-32,3,393,-33,3,394,-27,3,395,-35,3,396,-36,3,397,-36,3,398,-2,1,399,-7,2,400,-32,3,401,-32,3,402,-6,2,403,-7,2,404,-8,2,405,-81,4,406,-81,4,407,-81,4,408,-32,3,409,-32,3,410,-86,4,411,-7,2,412,-88,4,413,-89,4,414,-90,4,415,-27,3,416,-24,3,417,-21,3,418,-94,4,419,-27,3,420,-96,4,421,-97,4,422,-98,4,423,-27,3,424,-32,3,425,-96,4,426,-96,4,427,-96,4,428,-104,4,429,-96,4,430,-27,3,431,-107,4,432,-108,4,433,-108,4,434,-108,4,435,-108,4,436,-4,2,437,-5,2,438,-108,4,439,-108,4,440,-108,4,441,-108,4,442,-108,4,443,-108,4,444,-108,4,445,-5,2,446,-108,4,447,-108,4,448,-108,4,449,-108,4,450,-108,4,451,-108,4,452,-128,4,453,-21,3,454,-108,4,455,-108,4,456,-108,4,457,-108,4,458,-108,4,459,-108,4,460,-108,4,461,-108,4,462,-108,4,463,-108,4,464,-140,4,465,-141,4,466,-108,4,467,-143,4,468,-144,4,469,-145,4,470,-146,4,471,-147,4,472,-148,4,473,-149,4,474,-6,2,475,-151,4,476,-152,4,477,-153,4,478,-154,4,479,-155,4,480,-156,4,481,-157,4,482,-158,4,483,-159,4,484,-160,4,485,-161,4,486,-162,4,487,-108,4,488,-24,3,489,-21,3,490,-166,4,491,-140,4,492,-24,3,493,-169,4,494,-170,4,495,-27,3,496,-172,4,497,-27,3,498,-27,3,499,-175,4,500,-176,4,501,-177,4,502,-27,3,503,-179,4,504,-180,4,505,-181,4,506,-182,4,507,-7,2,508,-152,4,509,-153,4,510,-6,2,511,-7,2,512,-188,4,513,-189,4,514,-190,4,515,-191,4,516,-160,4,517,-161,4,518,-162,4,519,-7,2,520,-196,4,521,-197,4,522,-90,4,523,-27,3,524,-24,3,525,-21,3,526,-170,4,527,-27,3,528,-96,4,529,-205,4,530,-98,4,531,-27,3,532,-144,4,533,-5,2,534,-96,4,535,-96,4,536,-180,4,537,-96,4,538,-27,3,539,-180,4,540,-108,4,541,-108,4,542,-108,4,543,-108,4,544,-4,2,545,-5,2,546,-108,4,547,-108,4,548,-108,4,549,-108,4,550,-108,4,551,-108,4,552,-108,4,553,-5,2,554,-108,4,555,-108,4,556,-108,4,557,-108,4,558,-108,4,559,-108,4,560,-108,4,561,-21,3,562,-108,4,563,-108,4,564,-108,4,565,-108,4,566,-108,4,567,-108,4,568,-108,4,569,-108,4,570,-108,4,571,-108,4,572,-108,4,573,-108,4,574,-108,4,575,-108,4,576,-108,4,577,-108,4,578,-108,4,579,-108,4,580,-108,4,581,-108,4,582,-108,4,583,-108,4,584,-108,4,585,-108,4,586,-108,4,587,-108,4,588,-108,4,589,-108,4,590,-108,4,591,-108,4,592,-108,4,593,-108,4,594,-108,4,595,-108,4,596,-108,4,597,-21,3,598,-108,4,599,-108,4,600,-108,4,601,-108,4,602,-108,4,603,-108,4,604,-140,4,605,-108,4,606,-108,4,607,-140,4,608,-140,4,609,-141,4,610,-108,4,611,-143,4,612,-144,4,613,-144,4,614,-144,4,615,-140,4,616,-140,4,617,-140,4,618,-6,2,619,-144,4,620,-144,4,621,-144,4,622,-144,4,623,-144,4,624,-140,4,625,-144,4,626,-144,4,627,-144,4,628,-144,4,629,-144,4,630,-144,4,631,-27,3,632,-24,3,633,-21,3,634,-144,4,635,-27,3,636,-96,4,637,-144,4,638,-144,4,639,-27,3,640,-144,4,641,-5,2,642,-96,4,643,-96,4,644,-144,4,645,-96,4,646,-27,3,647,-144,4,648,-324,4,649,-324,4,650,-2,1,651,-324,4,652,-4,2,653,-5,2,654,-6,2,655,-7,2,656,-8,2,657,-9,2,658,-9,2,659,-2,1,660,-4,2,661,-5,2,662,-7,2,663,-7,2,664,-8,2,665,-8,2,666,-9,2,667,-9,2,668,-2,1,669,-21,3,670,-7,2,671,-7,2,672,-24,3,673,-8,2,674,-8,2,675,-27,3,676,-28,3,677,-27,3,678,-24,3,679,-24,3,680,-32,3,681,-33,3,682,-27,3,683,-35,3,684,-36,3,685,-36,3,686,-2,1,687,-7,2,688,-32,3,689,-32,3,690,-6,2,691,-7,2,692,-8,2,693,-36,3,694,-36,3,695,-2,1,696,-32,3,697,-32,3,698,-32,3,699,-7,2,700,-8,2,701,-8,2,702,-36,3,703,-27,3,704,-24,3,705,-21,3,706,-32,3,707,-27,3,708,-24,3,709,-8,2,710,-8,2,711,-27,3,712,-32,3,713,-27,3,714,-27,3,715,-32,3,716,-32,3,717,-24,3,718,-27,3,719,-35,3,720,-36,3,721,-36,3,722,-2,1,723,-7,2,724,-32,3,725,-77,4,726,-6,2,727,-79,4,728,-80,4,729,-81,4,730,-81,4,731,-81,4,732,-84,4,733,-85,4,734,-86,4,735,-80,4,736,-88,4,737,-89,4,738,-90,4,739,-27,3,740,-24,3,741,-21,3,742,-94,4,743,-27,3,744,-96,4,745,-97,4,746,-98,4,747,-99,4,748,-100,4,749,-5,2,750,-96,4,751,-96,4,752,-104,4,753,-96,4,754,-99,4,755,-107,4,756,-108,4,757,-108,4,758,-108,4,759,-108,4,760,-4,2,761,-5,2,762,-108,4,763,-108,4,764,-108,4,765,-108,4,766,-108,4,767,-108,4,768,-4,2,769,-5,2,770,-108,4,771,-108,4,772,-108,4,773,-108,4,774,-108,4,775,-108,4,776,-128,4,777,-21,3,778,-108,4,779,-108,4,780,-24,3,781,-108,4,782,-108,4,783,-108,4,784,-108,4,785,-108,4,786,-24,3,787,-24,3,788,-140,4,789,-141,4,790,-108,4,791,-143,4,792,-144,4,793,-145,4,794,-146,4,795,-7,2,796,-148,4,797,-149,4,798,-6,2,799,-7,2,800,-152,4,801,-153,4,802,-154,4,803,-155,4,804,-156,4,805,-149,4,806,-324,5,807,-331,5,808,-332,5,809,-332,5,810,-324,5,811,-108,4,812,-24,3,813,-21,3,814,-332,5,815,-351,5,816,-348,5,817,-340,5,818,-332,5,819,-351,5,820,-356,5,821,-351,5,822,-358,5,823,-356,5,824,-356,5,825,-357,5,826,-358,5,827,-359,5,828,-360,5,829,-360,5,830,-360,5,831,-363,5,832,-356,5,833,-356,5,834,-366,5,835,-367,5,836,-360,5,837,-360,5,838,-360,5,839,-360,5,840,-356,5,841,-356,5,842,-356,5,843,-367,5,844,-360,5,845,-89,4,846,-90,4,847,-383,5,848,-380,5,849,-381,5,850,-364,5,851,-383,5,852,-96,4,853,-368,5,854,-98,4,855,-351,5,856,-388,5,857,-5,2,858,-96,4,859,-96,4,860,-356,5,861,-96,4,862,-358,5,863,-359,5,864,-108,4,865,-108,4,866,-108,4,867,-432,5,868,-4,2,869,-5,2,870,-432,5,871,-432,5,872,-432,5,873,-432,5,874,-433,5,875,-434,5,876,-435,5,877,-437,5,878,-439,5,879,-439,5,880,-440,5,881,-440,5,882,-441,5,883,-441,5,884,-432,5,885,-432,5,886,-440,5,887,-440,5,888,-432,5,889,-441,5,890,-441,5,891,-432,5,892,-432,5,893,-434,5,894,-438,5,895,-439,5,896,-432,5,897,-432,5,898,-439,5,899,-432,5,900,-432,5,901,-432,5,902,-432,5,903,-432,5,904,-432,5,905,-432,5,906,-438,5,907,-439,5,908,-432,5,909,-432,5,910,-432,5,911,-432,5,912,-432,5,913,-432,5,914,-432,5,915,-439,5,916,-432,5,917,-432,5,918,-432,5,919,-459,5,920,-456,5,921,-453,5,922,-432,5,923,-459,5,924,-456,5,925,-432,5,926,-440,5,927,-459,5,928,-464,5,929,-459,5,930,-459,5,931,-464,5,932,-464,5,933,-465,5,934,-459,5,935,-467,5,936,-468,5,937,-468,5,938,-468,5,939,-468,5,940,-468,5,941,-468,5,942,-468,5,943,-468,5,944,-468,5,945,-468,5,946,-469,5,947,-470,5,948,-472,5,949,-473,5,950,-473,5,951,-475,5,952,-476,5,953,-476,5,954,-477,5,955,-464,5,956,-468,5,957,-468,5,958,-477,5,959,-468,5,960,-432,5,961,-477,5,962,-477,5,963,-468,5,964,-468,5,965,-437,5,966,-438,5,967,-439,5,968,-468,5,969,-441,5,970,-475,5,971,-468,5,972,-324,5,973,-325,5,974,-326,5,975,-327,5,976,-328,5,977,-329,5,978,-330,5,979,-331,5,980,-332,5,981,-333,5,982,-334,5,983,-335,5,984,-336,5,985,-337,5,986,-338,5,987,-339,5,988,-340,5,989,-341,5,990,-342,5,991,-343,5,992,-344,5,993,-345,5,994,-346,5,995,-347,5,996,-348,5,997,-349,5,998,-350,5,999,-351,5,1000,-352,5,1001,-353,5,1002,-354,5,1003,-355,5,1004,-356,5,1005,-357,5,1006,-358,5,1007,-359,5,1008,-360,5,1009,-361,5,1010,-362,5,1011,-363,5,1012,-364,5,1013,-365,5,1014,-366,5,1015,-367,5,1016,-368,5,1017,-369,5,1018,-370,5,1019,-371,5,1020,-372,5,1021,-373,5,1022,-374,5,1023,-375,5,1024,-376,5,1025,-377,5,1026,-378,5,1027,-379,5,1028,-380,5,1029,-381,5,1030,-382,5,1031,-383,5,1032,-384,5,1033,-385,5,1034,-386,5,1035,-387,5,1036,-388,5,1037,-389,5,1038,-390,5,1039,-391,5,1040,-392,5,1041,-393,5,1042,-394,5,1043,-395,5,1044,-396,5,1045,-397,5,1046,-398,5,1047,-399,5,1048,-400,5,1049,-401,5,1050,-402,5,1051,-403,5,1052,-404,5,1053,-405,5,1054,-406,5,1055,-407,5,1056,-408,5,1057,-409,5,1058,-410,5,1059,-411,5,1060,-412,5,1061,-413,5,1062,-414,5,1063,-415,5,1064,-416,5,1065,-417,5,1066,-418,5,1067,-419,5,1068,-420,5,1069,-421,5,1070,-422,5,1071,-423,5,1072,-424,5,1073,-425,5,1074,-426,5,1075,-427,5,1076,-428,5,1077,-429,5,1078,-430,5,1079,-431,5,1080,-432,5,1081,-433,5,1082,-434,5,1083,-435,5,1084,-4,2,1085,-437,5,1086,-438,5,1087,-439,5,1088,-440,5,1089,-441,5,1090,-442,5,1091,-443,5,1092,-444,5,1093,-445,5,1094,-446,5,1095,-447,5,1096,-448,5,1097,-449,5,1098,-450,5,1099,-451,5,1100,-452,5,1101,-453,5,1102,-454,5,1103,-455,5,1104,-456,5,1105,-457,5,1106,-458,5,1107,-459,5,1108,-460,5,1109,-461,5,1110,-462,5,1111,-463,5,1112,-464,5,1113,-465,5,1114,-466,5,1115,-467,5,1116,-468,5,1117,-469,5,1118,-470,5,1119,-471,5,1120,-472,5,1121,-473,5,1122,-474,5,1123,-475,5,1124,-476,5,1125,-477,5,1126,-478,5,1127,-479,5,1128,-480,5,1129,-481,5,1130,-482,5,1131,-483,5,1132,-484,5,1133,-485,5,1134,-486,5,1135,-487,5,1136,-488,5,1137,-489,5,1138,-490,5,1139,-491,5,1140,-492,5,1141,-493,5,1142,-494,5,1143,-495,5,1144,-496,5,1145,-497,5,1146,-498,5,1147,-499,5,1148,-500,5,1149,-501,5,1150,-502,5,1151,-503,5,1152,-504,5,1153,-505,5,1154,-506,5,1155,-507,5,1156,-508,5,1157,-509,5,1158,-510,5,1159,-511,5,1160,-512,5,1161,-513,5,1162,-514,5,1163,-515,5,1164,-516,5,1165,-517,5,1166,-518,5,1167,-519,5,1168,-520,5,1169,-521,5,1170,-522,5,1171,-523,5,1172,-524,5,1173,-525,5,1174,-526,5,1175,-527,5,1176,-528,5,1177,-529,5,1178,-530,5,1179,-531,5,1180,-532,5,1181,-533,5,1182,-534,5,1183,-535,5,1184,-536,5,1185,-537,5,1186,-538,5,1187,-539,5,1188,-540,5,1189,-541,5,1190,-542,5,1191,-543,5,1192,-4,2,1193,-545,5,1194,-546,5,1195,-547,5,1196,-548,5,1197,-549,5,1198,-550,5,1199,-551,5,1200,-552,5,1201,-553,5,1202,-554,5,1203,-555,5,1204,-556,5,1205,-557,5,1206,-558,5,1207,-559,5,1208,-560,5,1209,-561,5,1210,-562,5,1211,-563,5,1212,-564,5,1213,-565,5,1214,-566,5,1215,-567,5,1216,-568,5,1217,-569,5,1218,-570,5,1219,-571,5,1220,-572,5,1221,-573,5,1222,-574,5,1223,-575,5,1224,-576,5,1225,-577,5,1226,-578,5,1227,-579,5,1228,-580,5,1229,-581,5,1230,-582,5,1231,-583,5,1232,-584,5,1233,-585,5,1234,-586,5,1235,-587,5,1236,-588,5,1237,-589,5,1238,-590,5,1239,-591,5,1240,-592,5,1241,-593,5,1242,-594,5,1243,-595,5,1244,-596,5,1245,-597,5,1246,-598,5,1247,-599,5,1248,-600,5,1249,-601,5,1250,-602,5,1251,-603,5,1252,-604,5,1253,-605,5,1254,-606,5,1255,-607,5,1256,-608,5,1257,-609,5,1258,-610,5,1259,-611,5,1260,-612,5,1261,-613,5,1262,-614,5,1263,-615,5,1264,-616,5,1265,-617,5,1266,-618,5,1267,-619,5,1268,-620,5,1269,-621,5,1270,-622,5,1271,-623,5,1272,-624,5,1273,-625,5,1274,-626,5,1275,-627,5,1276,-628,5,1277,-629,5,1278,-324,5,1279,-351,5,1280,-348,5,1281,-633,5,1282,-324,5,1283,-351,5,1284,-636,5,1285,-324,5,1286,-324,5,1287,-351,5,1288,-356,5,1289,-5,2,1290,-642,5,1291,-643,5,1292,-356,5,1293,-645,5,1294,-351,5,1295,-359,5,1296,-648,5,1297,-648,5,1298,-648,5,1299,-648,5,1300,-4,2,1301,-5,2,1302,-648,5,1303,-648,5,1304,-648,5,1305,-648,5,1306,-649,5,1307,-650,5,1308,-4,2,1309,-5,2,1310,-655,5,1311,-655,5,1312,-656,5,1313,-656,5,1314,-657,5,1315,-657,5,1316,-657,5,1317,-648,5,1318,-656,5,1319,-656,5,1320,-648,5,1321,-657,5,1322,-657,5,1323,-648,5,1324,-648,5,1325,-650,5,1326,-654,5,1327,-655,5,1328,-648,5,1329,-648,5,1330,-655,5,1331,-648,5,1332,-648,5,1333,-649,5,1334,-650,5,1335,-655,5,1336,-656,5,1337,-657,5,1338,-654,5,1339,-655,5,1340,-332,5,1341,-333,5,1342,-334,5,1343,-335,5,1344,-332,5,1345,-333,5,1346,-333,5,1347,-339,5,1348,-340,5,1349,-341,5,1350,-342,5,1351,-675,5,1352,-672,5,1353,-324,5,1354,-341,5,1355,-351,5,1356,-324,5,1357,-341,5,1358,-342,5,1359,-351,5,1360,-356,5,1361,-351,5,1362,-331,5,1363,-356,5,1364,-356,5,1365,-357,5,1366,-351,5,1367,-359,5,1368,-360,5,1369,-360,5,1370,-360,5,1371,-356,5,1372,-356,5,1373,-356,5,1374,-360,5,1375,-360,5,1376,-360,5,1377,-81,4,1378,-81,4,1379,-81,4,1380,-356,5,1381,-85,4,1382,-86,4,1383,-360,5,1384,-88,4,1385,-89,4,1386,-90,4,1387,-356,5,1388,-356,5,1389,-360,5,1390,-648,5,1391,-356,5,1392,-648,5,1393,-648,5,1394,-648,5,1395,-360,5,1396,-360,5,1397,-5,2,1398,-648,5,1399,-648,5,1400,-324,5,1401,-333,5,1402,-360,5,1403,-324,5,1404,-324,5,1405,-325,5,1406,-326,5,1407,-327,5,1408,-328,5,1409,-329,5,1410,-330,5,1411,-331,5,1412,-332,5,1413,-333,5,1414,-334,5,1415,-335,5,1416,-336,5,1417,-337,5,1418,-338,5,1419,-339,5,1420,-340,5,1421,-341,5,1422,-342,5,1423,-343,5,1424,-324,5,1425,-345,5,1426,-346,5,1427,-347,5,1428,-348,5,1429,-349,5,1430,-350,5,1431,-351,5,1432,-352,5,1433,-353,5,1434,-354,5,1435,-355,5,1436,-324,5,1437,-324,5,1438,-358,5,1439,-324,5,1440,-324,5,1441,-324,5,1442,-324,5,1443,-331,5,1444,-324,5,1445,-324,5,1446,-330,5,1447,-331,5,1448,-324,5,1449,-324,5,1450,-324,5,1451,-324,5,1452,-324,5,1453,-324,5,1454,-324,5,1455,-331,5,1456,-324,5,1457,-324,5,1458,-324,5,1459,-352,5,1460,-348,5,1461,-345,5,1462,-332,5,1463,-351,5,1464,-348,5,1465,-332,5,1466,-332,5,1467,-351,5,1468,-356,5,1469,-351,5,1470,-351,5,1471,-356,5,1472,-356,5,1473,-357,5,1474,-358,5,1475,-359,5,1476,-360,5,1477,-360,5,1478,-360,5,1479,-356,5,1480,-356,5,1481,-356,5,1482,-330,5,1483,-331,5,1484,-360,5,1485,-360,5,1486,-360,5,1487,-360,5,1488,-356,5,1489,-356,5,1490,-356,5,1491,-367,5,1492,-360,5,1493,-360,5,1494,-360,5,1495,-383,5,1496,-380,5,1497,-345,5,1498,-356,5,1499,-383,5,1500,-420,5,1501,-360,5,1502,-360,5,1503,-351,5,1504,-388,5,1505,-420,5,1506,-420,5,1507,-420,5,1508,-356,5,1509,-420,5,1510,-358,5,1511,-359,5,1512,-432,5,1513,-432,5,1514,-432,5,1515,-432,5,1516,-4,2,1517,-432,5,1518,-432,5,1519,-432,5,1520,-432,5,1521,-432,5,1522,-432,5,1523,-432,5,1524,-432,5,1525,-432,5,1526,-432,5,1527,-432,5,1528,-432,5,1529,-432,5,1530,-432,5,1531,-432,5,1532,-432,5,1533,-432,5,1534,-432,5,1535,-432,5,1536,-432,5,1537,-432,5,1538,-432,5,1539,-432,5,1540,-432,5,1541,-432,5,1542,-432,5,1543,-432,5,1544,-432,5,1545,-432,5,1546,-432,5,1547,-432,5,1548,-432,5,1549,-432,5,1550,-432,5,1551,-432,5,1552,-432,5,1553,-432,5,1554,-432,5,1555,-432,5,1556,-432,5,1557,-432,5,1558,-432,5,1559,-432,5,1560,-432,5,1561,-432,5,1562,-432,5,1563,-439,5,1564,-432,5,1565,-432,5,1566,-432,5,1567,-432,5,1568,-432,5,1569,-432,5,1570,-432,5,1571,-459,5,1572,-432,5,1573,-432,5,1574,-432,5,1575,-459,5,1576,-464,5,1577,-459,5,1578,-459,5,1579,-464,5,1580,-464,5,1581,-465,5,1582,-459,5,1583,-467,5,1584,-468,5,1585,-468,5,1586,-468,5,1587,-464,5,1588,-468,5,1589,-468,5,1590,-468,5,1591,-468,5,1592,-468,5,1593,-468,5,1594,-469,5,1595,-470,5,1596,-472,5,1597,-473,5,1598,-473,5,1599,-468,5,1600,-476,5,1601,-476,5,1602,-477,5,1603,-464,5,1604,-464,5,1605,-468,5,1606,-477,5,1607,-464,5,1608,-432,5,1609,-477,5,1610,-477,5,1611,-468,5,1612,-468,5,1613,-432,5,1614,-432,5,1615,-432,5,1616,-468,5,1617,-432,5,1618,-468,5,1619,-468,5,1620,-324,5,1621,-325,5,1622,-326,5,1623,-327,5,1624,-4,2,1625,-329,5,1626,-330,5,1627,-331,5,1628,-332,5,1629,-333,5,1630,-334,5,1631,-335,5,1632,-336,5,1633,-337,5,1634,-338,5,1635,-339,5,1636,-340,5,1637,-341,5,1638,-342,5,1639,-343,5,1640,-344,5,1641,-345,5,1642,-346,5,1643,-347,5,1644,-348,5,1645,-349,5,1646,-350,5,1647,-351,5,1648,-352,5,1649,-353,5,1650,-354,5,1651,-355,5,1652,-356,5,1653,-357,5,1654,-358,5,1655,-359,5,1656,-360,5,1657,-361,5,1658,-362,5,1659,-363,5,1660,-364,5,1661,-365,5,1662,-366,5,1663,-367,5,1664,-368,5,1665,-369,5,1666,-370,5,1667,-371,5,1668,-372,5,1669,-373,5,1670,-374,5,1671,-375,5,1672,-376,5,1673,-377,5,1674,-378,5,1675,-379,5,1676,-380,5,1677,-381,5,1678,-382,5,1679,-383,5,1680,-384,5,1681,-385,5,1682,-386,5,1683,-387,5,1684,-388,5,1685,-389,5,1686,-390,5,1687,-391,5,1688,-392,5,1689,-393,5,1690,-394,5,1691,-395,5,1692,-396,5,1693,-397,5,1694,-398,5,1695,-399,5,1696,-400,5,1697,-401,5,1698,-402,5,1699,-403,5,1700,-404,5,1701,-324,5,1702,-325,5,1703,-326,5,1704,-408,5,1705,-409,5,1706,-410,5,1707,-411,5,1708,-412,5,1709,-413,5,1710,-414,5,1711,-415,5,1712,-416,5,1713,-417,5,1714,-418,5,1715,-419,5,1716,-420,5,1717,-421,5,1718,-422,5,1719,-423,5,1720,-424,5,1721,-425,5,1722,-426,5,1723,-427,5,1724,-428,5,1725,-429,5,1726,-430,5,1727,-431,5,1728,-432,5,1729,-433,5,1730,-434,5,1731,-435,5,1732,-4,2,1733,-5,2,1734,-438,5,1735,-439,5,1736,-440,5,1737,-441,5,1738,-442,5,1739,-443,5,1740,-444,5,1741,-5,2,1742,-446,5,1743,-447,5,1744,-448,5,1745,-449,5,1746,-450,5,1747,-451,5,1748,-452,5,1749,-432,5,1750,-454,5,1751,-455,5,1752,-456,5,1753,-457,5,1754,-458,5,1755,-459,5,1756,-460,5,1757,-461,5,1758,-462,5,1759,-463,5,1760,-464,5,1761,-465,5,1762,-466,5,1763,-467,5,1764,-468,5,1765,-469,5,1766,-470,5,1767,-471,5,1768,-472,5,1769,-473,5,1770,-474,5,1771,-475,5,1772,-476,5,1773,-477,5,1774,-478,5,1775,-479,5,1776,-480,5,1777,-481,5,1778,-482,5,1779,-483,5,1780,-484,5,1781,-485,5,1782,-486,5,1783,-351,5,1784,-324,5,1785,-21,3,1786,-490,5,1787,-324,5,1788,-324,5,1789,-324,5,1790,-324,5,1791,-324,5,1792,-324,5,1793,-324,5,1794,-331,5,1795,-324,5,1796,-324,5,1797,-324,5,1798,-331,5,1799,-324,5,1800,-324,5,1801,-324,5,1802,-324,5,1803,-331,5,1804,-324,5,1805,-324,5,1806,-324,5,1807,-324,5,1808,-324,5,1809,-324,5,1810,-324,5,1811,-324,5,1812,-324,5,1813,-324,5,1814,-324,5,1815,-331,5,1816,-324,5,1817,-324,5,1818,-324,5,1819,-351,5,1820,-348,5,1821,-324,5,1822,-332,5,1823,-351,5,1824,-324,5,1825,-332,5,1826,-332,5,1827,-324,5,1828,-356,5,1829,-329,5,1830,-330,5,1831,-331,5,1832,-324,5,1833,-333,5,1834,-331,5,1835,-324,5,1836,-324,5,1837,-325,5,1838,-326,5,1839,-327,5,1840,-4,2,1841,-329,5,1842,-330,5,1843,-331,5,1844,-332,5,1845,-333,5,1846,-334,5,1847,-335,5,1848,-336,5,1849,-337,5,1850,-338,5,1851,-339,5,1852,-340,5,1853,-341,5,1854,-342,5,1855,-342,5,1856,-324,5,1857,-345,5,1858,-339,5,1859,-339,5,1860,-348,5,1861,-341,5,1862,-341,5,1863,-351,5,1864,-352,5,1865,-351,5,1866,-348,5,1867,-348,5,1868,-324,5,1869,-324,5,1870,-351,5,1871,-324,5,1872,-324,5,1873,-324,5,1874,-324,5,1875,-331,5,1876,-324,5,1877,-324,5,1878,-330,5,1879,-331,5,1880,-324,5,1881,-324,5,1882,-324,5,1883,-324,5,1884,-324,5,1885,-324,5,1886,-324,5,1887,-331,5,1888,-324,5,1889,-324,5,1890,-324,5,1891,-352,5,1892,-348,5,1893,-345,5,1894,-332,5,1895,-351,5,1896,-348,5,1897,-332,5,1898,-332,5,1899,-351,5,1900,-324,5,1901,-351,5,1902,-351,5,1903,-324,5,1904,-324,5,1905,-324,5,1906,-351,5,1907,-324,5,1908,-324,5,1909,-324,5,1910,-324,5,1911,-331,5,1912,-324,5,1913,-324,5,1914,-330,5,1915,-331,5,1916,-324,5,1917,-324,5,1918,-324,5,1919,-324,5,1920,-324,5,1921,-324,5,1922,-324,5,1923,-331,5,1924,-324,5,1925,-324,5,1926,-324,5,1927,-351,5,1928,-348,5,1929,-345,5,1930,-324,5,1931,-351,5,1932,-324,5,1933,-324,5,1934,-324,5,1935,-351,5,1936,-356,5,1937,-329,5,1938,-330,5,1939,-331,5,1940,-356,5,1941,-333,5,1942,-351,5,1943,-359,5,1944,-324,5,1945,-324,5,1946,-324,5,1947,-324,5,1948,-4,2,1949,-324,5,1950,-324,5,1951,-324,5,1952,-324,5,1953,-324,5,1954,-325,5,1955,-326,5,1956,-327,5,1957,-324,5,1958,-324,5,1959,-324,5,1960,-324,5,1961,-332,5,1962,-333,5,1963,-333,5,1964,-333,5,1965,-324,5,1966,-331,5,1967,-332,5,1968,-324,5,1969,-332,5,1970,-333,5,1971,-324,5,1972,-324,5,1973,-326,5,1974,-330,5,1975,-331,5,1976,-324,5,1977,-324,5,1978,-331,5,1979,-324,5,1980,-324,5,1981,-325,5,1982,-326,5,1983,-331,5,1984,-332,5,1985,-333,5,1986,-330,5,1987,-331,5,1988,-332,5,1989,-333,5,1990,-334,5,1991,-335,5,1992,-340,5,1993,-341,5,1994,-342,5,1995,-339,5,1996,-340,5,1997,-341,5,1998,-342,5,1999,-351,5,2000,-348,5,2001,-345,5,2002,-350,5,2003,-351,5,2004,-348,5,2005,-349,5,2006,-350,5,2007,-351,5,2008,-356,5,2009,-353,5,2010,-351,5,2011,-356,5,2012,-356,5,2013,-357,5,2014,-351,5,2015,-359,5,2016,-360,5,2017,-360,5,2018,-360,5,2019,-356,5,2020,-360,5,2021,-360,5,2022,-360,5,2023,-360,5,2024,-360,5,2025,-360,5,2026,-360,5,2027,-360,5,2028,-360,5,2029,-360,5,2030,-324,5,2031,-360,5,2032,-360,5,2033,-324,5,2034,-324,5,2035,-356,5,2036,-360,5,2037,-360,5,2038,-324,5,2039,-360,5,2040,-324,5,2041,-324,5,2042,-324,5,2043,-360,5,2044,-360,5,2045,-329,5,2046,-330,5,2047,-331,5,0,0,0"),
// leafSize 10
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,-1,0,12,-2,1,13,-3,1,14,-4,1,15,-5,1,16,-8,2,17,-7,2,18,-8,2,19,-9,2,20,-10,2,21,3,4,22,-10,2,23,-10,2,24,3,4,25,-5,2,26,-8,2,27,3,4,28,-8,2,29,-9,2,30,3,5,31,-1,1,32,4,7,33,-3,1,34,-10,2,35,-5,2,36,4,7,37,-7,2,38,-8,2,39,-9,2,40,4,7,41,-1,1,42,-2,1,43,-3,1,44,-4,2,45,5,10,46,-6,2,47,-7,2,48,-8,2,49,-9,2,50,5,10,51,-1,1,52,-2,1,53,-3,1,54,-4,2,55,-5,2,56,-6,2,57,-7,2,58,-8,2,59,-9,2,60,-10,2,61,-1,1,62,-2,1,63,-13,2,64,-4,2,65,-5,2,66,-8,2,67,-7,2,68,-8,2,69,-9,2,70,-10,2,71,-21,3,72,-32,3,73,-23,3,74,-24,3,75,-30,3,76,-36,3,77,-27,3,78,-28,3,79,-29,3,80,-30,3,81,-36,3,82,-32,3,83,-33,3,84,-4,2,85,-40,3,86,-36,3,87,-37,3,88,-38,3,89,-39,3,90,-40,3,91,-1,1,92,-42,3,93,-43,3,94,-4,2,95,-45,3,96,-6,2,97,-47,3,98,-48,3,99,-49,3,100,-50,3,101,-1,1,102,-50,3,103,-50,3,104,-4,2,105,-5,2,106,-6,2,107,-7,2,108,-50,3,109,-50,3,110,-50,3,111,-1,1,112,-52,3,113,-50,3,114,-4,2,115,-5,2,116,-50,3,117,-7,2,118,-50,3,119,-59,3,120,3,7,121,-1,1,122,-2,1,123,-3,1,124,-24,3,125,-5,2,126,-6,2,127,-7,2,128,-8,2,129,-9,2,130,-30,3,131,-36,3,132,-32,3,133,-33,3,134,-4,2,135,-40,3,136,-36,3,137,-30,3,138,-38,3,139,-39,3,140,-40,3,141,-1,1,142,-40,3,143,-43,3,144,-4,2,145,-45,3,146,-6,2,147,-7,2,148,-8,2,149,-9,2,150,3,7,151,-1,0,152,-2,1,153,-3,1,154,-4,2,155,-5,2,156,-6,2,157,-7,2,158,-8,2,159,-9,2,160,-10,2,161,-10,2,162,-2,1,163,-10,2,164,-4,2,165,-5,2,166,-8,2,167,-7,2,168,-8,2,169,-9,2,170,-20,3,171,-21,3,172,-20,3,173,-23,3,174,-24,3,175,-20,3,176,-8,2,177,-27,3,178,-28,3,179,-29,3,180,-30,3,181,-30,3,182,-32,3,183,-30,3,184,-4,2,185,-5,2,186,-36,3,187,-30,3,188,-30,3,189,-30,3,190,-40,3,191,-40,3,192,-40,3,193,-40,3,194,-4,2,195,-45,3,196,-6,2,197,-7,2,198,-8,2,199,-40,3,200,-50,3,201,-50,3,202,-2,1,203,-50,3,204,-4,2,205,-5,2,206,-6,2,207,-7,2,208,-8,2,209,-9,2,210,-10,2,211,-10,2,212,-2,1,213,-10,2,214,-4,2,215,-5,2,216,-8,2,217,-7,2,218,-8,2,219,-9,2,220,-20,3,221,-21,3,222,-32,3,223,-23,3,224,-24,3,225,-30,3,226,-36,3,227,-27,3,228,-28,3,229,-29,3,230,-30,3,231,-30,3,232,-32,3,233,-30,3,234,-4,2,235,-40,3,236,-36,3,237,-30,3,238,-30,3,239,-30,3,240,-90,4,241,-90,4,242,-90,4,243,-90,4,244,-90,4,245,-95,4,246,-90,4,247,-90,4,248,-90,4,249,-99,4,250,-100,4,251,-100,4,252,-100,4,253,-100,4,254,-100,4,255,-100,4,256,-100,4,257,-100,4,258,-100,4,259,-100,4,260,-110,4,261,-110,4,262,-110,4,263,-110,4,264,-4,2,265,-110,4,266,-100,4,267,-110,4,268,-110,4,269,-110,4,270,-120,4,271,-120,4,272,-120,4,273,-120,4,274,-100,4,275,-120,4,276,-120,4,277,-120,4,278,-120,4,279,-120,4,280,-130,4,281,-130,4,282,-132,4,283,-130,4,284,-4,2,285,-135,4,286,-136,4,287,-130,4,288,-130,4,289,-139,4,290,-140,4,291,-140,4,292,-140,4,293,-140,4,294,-4,2,295,-145,4,296,-146,4,297,-147,4,298,-148,4,299,-149,4,300,-150,4,301,-150,4,302,-150,4,303,-150,4,304,-4,2,305,-150,4,306,-150,4,307,-150,4,308,-150,4,309,-150,4,310,-150,4,311,-151,4,312,-152,4,313,-153,4,314,-4,2,315,-5,2,316,-158,4,317,-157,4,318,-158,4,319,-159,4,320,-20,3,321,-21,3,322,-20,3,323,-150,4,324,-150,4,325,-20,3,326,-160,4,327,-150,4,328,-150,4,329,-150,4,330,-150,4,331,-151,4,332,-150,4,333,-153,4,334,-4,2,335,-5,2,336,-150,4,337,-157,4,338,-158,4,339,-159,4,340,-150,4,341,-151,4,342,-152,4,343,-153,4,344,-4,2,345,-150,4,346,-156,4,347,-157,4,348,-158,4,349,-159,4,350,-150,4,351,-151,4,352,-152,4,353,-153,4,354,-4,2,355,-5,2,356,-156,4,357,-157,4,358,-158,4,359,-159,4,360,-160,4,361,-161,4,362,-162,4,363,-163,4,364,-4,2,365,-5,2,366,-166,4,367,-167,4,368,-168,4,369,-169,4,370,-20,3,371,-21,3,372,-182,4,373,-23,3,374,-24,3,375,-180,4,376,-186,4,377,-177,4,378,-178,4,379,-179,4,380,-180,4,381,-181,4,382,-182,4,383,-183,4,384,-4,2,385,-190,4,386,-86,4,387,-187,4,388,-188,4,389,-89,4,390,-90,4,391,-90,4,392,-90,4,393,-90,4,394,-4,2,395,-95,4,396,-90,4,397,-90,4,398,-90,4,399,-99,4,400,-100,4,401,-100,4,402,-100,4,403,-100,4,404,-4,2,405,-100,4,406,-100,4,407,-100,4,408,-100,4,409,-100,4,410,-110,4,411,-110,4,412,-110,4,413,-110,4,414,-4,2,415,-110,4,416,-100,4,417,-110,4,418,-110,4,419,-110,4,420,-120,4,421,-120,4,422,-120,4,423,-120,4,424,-100,4,425,-5,2,426,-120,4,427,-120,4,428,-120,4,429,-120,4,430,-100,4,431,-100,4,432,-100,4,433,-100,4,434,-4,2,435,-135,4,436,-136,4,437,-100,4,438,-100,4,439,-100,4,440,-140,4,441,-140,4,442,-140,4,443,-140,4,444,-4,2,445,-145,4,446,-140,4,447,-140,4,448,-140,4,449,-140,4,450,3,9,451,-1,0,452,-2,1,453,-3,1,454,-4,2,455,-5,2,456,-6,2,457,-7,2,458,-8,2,459,-9,2,460,-10,2,461,-10,2,462,-2,1,463,-10,2,464,-4,2,465,-5,2,466,-8,2,467,-7,2,468,-8,2,469,-19,3,470,-20,3,471,-21,3,472,-20,3,473,-23,3,474,-24,3,475,-20,3,476,-8,2,477,-27,3,478,-28,3,479,-29,3,480,-30,3,481,-30,3,482,-32,3,483,-30,3,484,-4,2,485,-5,2,486,-36,3,487,-7,2,488,-30,3,489,-30,3,490,-40,3,491,-40,3,492,-2,1,493,-40,3,494,-4,2,495,-45,3,496,-6,2,497,-7,2,498,-8,2,499,-9,2,500,-50,3,501,-50,3,502,-2,1,503,-50,3,504,-4,2,505,-5,2,506,-6,2,507,-7,2,508,-58,4,509,-59,4,510,-60,4,511,-60,4,512,-60,4,513,-60,4,514,-60,4,515,-60,4,516,-66,4,517,-67,4,518,-68,4,519,-69,4,520,-70,4,521,-71,4,522,-32,3,523,-73,4,524,-74,4,525,-75,4,526,-76,4,527,-77,4,528,-78,4,529,-79,4,530,-80,4,531,-80,4,532,-82,4,533,-80,4,534,-4,2,535,-85,4,536,-86,4,537,-87,4,538,-88,4,539,-89,4,540,-90,4,541,-90,4,542,-90,4,543,-90,4,544,-4,2,545,-95,4,546,-90,4,547,-90,4,548,-98,4,549,-99,4,550,-100,4,551,-100,4,552,-100,4,553,-100,4,554,-4,2,555,-5,2,556,-100,4,557,-100,4,558,-100,4,559,-109,4,560,-110,4,561,-110,4,562,-110,4,563,-110,4,564,-4,2,565,-5,2,566,-100,4,567,-110,4,568,-110,4,569,-110,4,570,-120,4,571,-120,4,572,-120,4,573,-120,4,574,-100,4,575,-5,2,576,-6,2,577,-120,4,578,-120,4,579,-120,4,580,-130,4,581,-130,4,582,-132,4,583,-130,4,584,-4,2,585,-135,4,586,-136,4,587,-130,4,588,-130,4,589,-139,4,590,-140,4,591,-140,4,592,-140,4,593,-140,4,594,-4,2,595,-145,4,596,-6,2,597,-140,4,598,-148,4,599,-149,4,600,-150,4,601,-151,4,602,-152,4,603,-153,4,604,-4,2,605,-5,2,606,-6,2,607,-7,2,608,-158,4,609,-159,4,610,-160,4,611,-161,4,612,-162,4,613,-163,4,614,-4,2,615,-5,2,616,-166,4,617,-7,2,618,-168,4,619,-169,4,620,-20,3,621,-21,3,622,-20,3,623,-23,3,624,-24,3,625,-20,3,626,-168,4,627,-27,3,628,-28,3,629,-29,3,630,-30,3,631,-30,3,632,-150,4,633,-30,3,634,-4,2,635,-5,2,636,-186,4,637,-7,2,638,-30,3,639,-30,3,640,-190,4,641,-191,4,642,-2,1,643,-193,4,644,-4,2,645,-195,4,646,-6,2,647,-7,2,648,-8,2,649,-199,4,650,-200,4,651,-201,4,652,-2,1,653,-203,4,654,-4,2,655,-5,2,656,-6,2,657,-7,2,658,-8,2,659,-59,4,660,-60,4,661,-60,4,662,-60,4,663,-60,4,664,-60,4,665,-60,4,666,-66,4,667,-67,4,668,-68,4,669,-69,4,670,-70,4,671,-21,3,672,-32,3,673,-23,3,674,-74,4,675,-75,4,676,-76,4,677,-77,4,678,-78,4,679,-79,4,680,-80,4,681,-80,4,682,-82,4,683,-80,4,684,-4,2,685,-85,4,686,-86,4,687,-87,4,688,-88,4,689,-89,4,690,-90,4,691,-90,4,692,-90,4,693,-90,4,694,-4,2,695,-95,4,696,-90,4,697,-90,4,698,-98,4,699,-99,4,700,-100,4,701,-100,4,702,-100,4,703,-100,4,704,-4,2,705,-5,2,706,-100,4,707,-100,4,708,-100,4,709,-109,4,710,-110,4,711,-110,4,712,-110,4,713,-110,4,714,-4,2,715,-5,2,716,-100,4,717,-110,4,718,-110,4,719,-110,4,720,-120,4,721,-120,4,722,-120,4,723,-120,4,724,-100,4,725,-5,2,726,-6,2,727,-120,4,728,-120,4,729,-120,4,730,-130,4,731,-130,4,732,-132,4,733,-130,4,734,-4,2,735,-135,4,736,-136,4,737,-130,4,738,-130,4,739,-139,4,740,-140,4,741,-140,4,742,-140,4,743,-140,4,744,-4,2,745,-145,4,746,-6,2,747,-7,2,748,-140,4,749,-149,4,750,-150,4,751,-150,4,752,-150,4,753,-150,4,754,-4,2,755,-5,2,756,-6,2,757,-7,2,758,-150,4,759,-150,4,760,-150,4,761,-151,4,762,-150,4,763,-150,4,764,-4,2,765,-5,2,766,-150,4,767,-7,2,768,-150,4,769,-150,4,770,-20,3,771,-21,3,772,-20,3,773,-23,3,774,-24,3,775,-20,3,776,-150,4,777,-27,3,778,-28,3,779,-29,3,780,-30,3,781,-30,3,782,-150,4,783,-30,3,784,-4,2,785,-5,2,786,-150,4,787,-7,2,788,-30,3,789,-30,3,790,-150,4,791,-151,4,792,-152,4,793,-153,4,794,-4,2,795,-150,4,796,-6,2,797,-7,2,798,-150,4,799,-159,4,800,-150,4,801,-151,4,802,-152,4,803,-153,4,804,-4,2,805,-5,2,806,-6,2,807,-7,2,808,-150,4,809,-59,4,810,-60,4,811,-60,4,812,-60,4,813,-60,4,814,-60,4,815,-60,4,816,-66,4,817,-67,4,818,-68,4,819,-69,4,820,-70,4,821,-21,3,822,-150,4,823,-70,4,824,-74,4,825,-75,4,826,-76,4,827,-77,4,828,-78,4,829,-79,4,830,-80,4,831,-80,4,832,-82,4,833,-80,4,834,-4,2,835,-85,4,836,-86,4,837,-87,4,838,-88,4,839,-89,4,840,-90,4,841,-90,4,842,-90,4,843,-90,4,844,-4,2,845,-95,4,846,-90,4,847,-90,4,848,-98,4,849,-99,4,850,-100,4,851,-100,4,852,-100,4,853,-100,4,854,-4,2,855,-5,2,856,-100,4,857,-100,4,858,-100,4,859,-100,4,860,-110,4,861,-110,4,862,-110,4,863,-110,4,864,-4,2,865,-5,2,866,-100,4,867,-110,4,868,-110,4,869,-110,4,870,-120,4,871,-120,4,872,-120,4,873,-120,4,874,-100,4,875,-5,2,876,-6,2,877,-120,4,878,-120,4,879,-120,4,880,-100,4,881,-100,4,882,-132,4,883,-100,4,884,-4,2,885,-135,4,886,-136,4,887,-100,4,888,-100,4,889,-100,4,890,-140,4,891,-140,4,892,-140,4,893,-140,4,894,-4,2,895,-145,4,896,-6,2,897,-7,2,898,-140,4,899,-140,4,900,-450,5,901,-450,5,902,-450,5,903,-450,5,904,-450,5,905,-450,5,906,-450,5,907,-450,5,908,-450,5,909,-450,5,910,-450,5,911,-451,5,912,-452,5,913,-453,5,914,-454,5,915,-455,5,916,-458,5,917,-457,5,918,-458,5,919,-450,5,920,-450,5,921,-450,5,922,-452,5,923,-450,5,924,-450,5,925,-455,5,926,-460,5,927,-450,5,928,-450,5,929,-450,5,930,-450,5,931,-451,5,932,-450,5,933,-453,5,934,-454,5,935,-455,5,936,-450,5,937,-457,5,938,-458,5,939,-459,5,940,-450,5,941,-451,5,942,-452,5,943,-453,5,944,-454,5,945,-450,5,946,-456,5,947,-457,5,948,-458,5,949,-459,5,950,-450,5,951,-451,5,952,-452,5,953,-453,5,954,-454,5,955,-455,5,956,-456,5,957,-457,5,958,-58,4,959,-59,4,960,-60,4,961,-60,4,962,-60,4,963,-60,4,964,-60,4,965,-60,4,966,-450,5,967,-450,5,968,-450,5,969,-450,5,970,-450,5,971,-450,5,972,-482,5,973,-450,5,974,-450,5,975,-450,5,976,-450,5,977,-450,5,978,-450,5,979,-450,5,980,-450,5,981,-451,5,982,-450,5,983,-453,5,984,-454,5,985,-450,5,986,-450,5,987,-450,5,988,-450,5,989,-450,5,990,-450,5,991,-451,5,992,-452,5,993,-453,5,994,-454,5,995,-450,5,996,-456,5,997,-457,5,998,-450,5,999,-450,5,1000,-450,5,1001,-451,5,1002,-452,5,1003,-453,5,1004,-454,5,1005,-455,5,1006,-456,5,1007,-457,5,1008,-458,5,1009,-450,5,1010,-450,5,1011,-451,5,1012,-452,5,1013,-453,5,1014,-454,5,1015,-455,5,1016,-466,5,1017,-457,5,1018,-458,5,1019,-459,5,1020,-450,5,1021,-451,5,1022,-452,5,1023,-453,5,1024,-474,5,1025,-455,5,1026,-456,5,1027,-457,5,1028,-458,5,1029,-459,5,1030,-450,5,1031,-451,5,1032,-450,5,1033,-453,5,1034,-4,2,1035,-450,5,1036,-450,5,1037,-457,5,1038,-458,5,1039,-450,5,1040,-450,5,1041,-451,5,1042,-452,5,1043,-453,5,1044,-4,2,1045,-450,5,1046,-456,5,1047,-457,5,1048,-450,5,1049,-450,5,1050,-450,5,1051,-450,5,1052,-450,5,1053,-450,5,1054,-4,2,1055,-455,5,1056,-456,5,1057,-457,5,1058,-450,5,1059,-450,5,1060,-450,5,1061,-450,5,1062,-452,5,1063,-450,5,1064,-4,2,1065,-455,5,1066,-458,5,1067,-457,5,1068,-458,5,1069,-450,5,1070,-470,5,1071,-471,5,1072,-470,5,1073,-473,5,1074,-474,5,1075,-475,5,1076,-466,5,1077,-477,5,1078,-478,5,1079,-479,5,1080,-480,5,1081,-480,5,1082,-482,5,1083,-480,5,1084,-4,2,1085,-485,5,1086,-486,5,1087,-487,5,1088,-480,5,1089,-480,5,1090,-450,5,1091,-450,5,1092,-452,5,1093,-450,5,1094,-4,2,1095,-450,5,1096,-456,5,1097,-457,5,1098,-458,5,1099,-459,5,1100,-450,5,1101,-450,5,1102,-452,5,1103,-450,5,1104,-4,2,1105,-455,5,1106,-456,5,1107,-457,5,1108,-458,5,1109,-59,4,1110,-60,4,1111,-60,4,1112,-60,4,1113,-60,4,1114,-60,4,1115,-60,4,1116,-66,4,1117,-67,4,1118,-68,4,1119,-69,4,1120,-70,4,1121,-471,5,1122,-482,5,1123,-473,5,1124,-474,5,1125,-450,5,1126,-450,5,1127,-450,5,1128,-450,5,1129,-450,5,1130,-530,5,1131,-530,5,1132,-532,5,1133,-450,5,1134,-4,2,1135,-535,5,1136,-536,5,1137,-537,5,1138,-538,5,1139,-539,5,1140,-540,5,1141,-540,5,1142,-540,5,1143,-540,5,1144,-4,2,1145,-545,5,1146,-546,5,1147,-547,5,1148,-548,5,1149,-549,5,1150,-550,5,1151,-550,5,1152,-550,5,1153,-550,5,1154,-4,2,1155,-555,5,1156,-556,5,1157,-557,5,1158,-550,5,1159,-559,5,1160,-560,5,1161,-560,5,1162,-560,5,1163,-560,5,1164,-4,2,1165,-565,5,1166,-558,5,1167,-567,5,1168,-560,5,1169,-560,5,1170,-570,5,1171,-570,5,1172,-570,5,1173,-570,5,1174,-574,5,1175,-575,5,1176,-576,5,1177,-577,5,1178,-570,5,1179,-570,5,1180,-580,5,1181,-580,5,1182,-582,5,1183,-580,5,1184,-4,2,1185,-585,5,1186,-586,5,1187,-587,5,1188,-580,5,1189,-589,5,1190,-590,5,1191,-590,5,1192,-590,5,1193,-590,5,1194,-4,2,1195,-595,5,1196,-596,5,1197,-597,5,1198,-598,5,1199,-599,5,1200,-600,5,1201,-600,5,1202,-600,5,1203,-600,5,1204,-4,2,1205,-600,5,1206,-600,5,1207,-600,5,1208,-600,5,1209,-600,5,1210,-600,5,1211,-601,5,1212,-602,5,1213,-603,5,1214,-4,2,1215,-605,5,1216,-608,5,1217,-607,5,1218,-608,5,1219,-609,5,1220,-600,5,1221,-600,5,1222,-602,5,1223,-600,5,1224,-600,5,1225,-605,5,1226,-610,5,1227,-600,5,1228,-600,5,1229,-600,5,1230,-600,5,1231,-601,5,1232,-600,5,1233,-603,5,1234,-4,2,1235,-605,5,1236,-600,5,1237,-607,5,1238,-608,5,1239,-609,5,1240,-600,5,1241,-601,5,1242,-602,5,1243,-603,5,1244,-4,2,1245,-600,5,1246,-606,5,1247,-607,5,1248,-608,5,1249,-609,5,1250,-600,5,1251,-601,5,1252,-602,5,1253,-603,5,1254,-4,2,1255,-605,5,1256,-606,5,1257,-607,5,1258,-608,5,1259,-59,4,1260,-60,4,1261,-60,4,1262,-60,4,1263,-60,4,1264,-60,4,1265,-60,4,1266,-66,4,1267,-67,4,1268,-68,4,1269,-69,4,1270,-70,4,1271,-621,5,1272,-632,5,1273,-623,5,1274,-74,4,1275,-75,4,1276,-76,4,1277,-77,4,1278,-78,4,1279,-79,4,1280,-80,4,1281,-80,4,1282,-82,4,1283,-80,4,1284,-4,2,1285,-85,4,1286,-600,5,1287,-600,5,1288,-600,5,1289,-600,5,1290,-600,5,1291,-600,5,1292,-600,5,1293,-600,5,1294,-4,2,1295,-600,5,1296,-600,5,1297,-600,5,1298,-600,5,1299,-600,5,1300,-600,5,1301,-601,5,1302,-602,5,1303,-603,5,1304,-4,2,1305,-5,2,1306,-606,5,1307,-607,5,1308,-608,5,1309,-600,5,1310,-600,5,1311,-601,5,1312,-602,5,1313,-603,5,1314,-4,2,1315,-5,2,1316,-608,5,1317,-607,5,1318,-608,5,1319,-609,5,1320,-600,5,1321,-601,5,1322,-602,5,1323,-603,5,1324,-624,5,1325,-5,2,1326,-606,5,1327,-607,5,1328,-608,5,1329,-609,5,1330,-600,5,1331,-601,5,1332,-600,5,1333,-603,5,1334,-4,2,1335,-600,5,1336,-600,5,1337,-607,5,1338,-608,5,1339,-600,5,1340,-600,5,1341,-601,5,1342,-602,5,1343,-603,5,1344,-4,2,1345,-600,5,1346,-606,5,1347,-607,5,1348,-608,5,1349,-609,5,1350,3,10,1351,-1,0,1352,-2,1,1353,-3,1,1354,-4,2,1355,-5,2,1356,-6,2,1357,-7,2,1358,-8,2,1359,-9,2,1360,-10,2,1361,-10,2,1362,-2,1,1363,-10,2,1364,-4,2,1365,-5,2,1366,-8,2,1367,-7,2,1368,-8,2,1369,-19,3,1370,-20,3,1371,-21,3,1372,-20,3,1373,-23,3,1374,-24,3,1375,-20,3,1376,-8,2,1377,-27,3,1378,-28,3,1379,-29,3,1380,-30,3,1381,-30,3,1382,-32,3,1383,-30,3,1384,-4,2,1385,-5,2,1386,-36,3,1387,-7,2,1388,-30,3,1389,-30,3,1390,-40,3,1391,-40,3,1392,-2,1,1393,-40,3,1394,-4,2,1395,-45,3,1396,-6,2,1397,-7,2,1398,-8,2,1399,-9,2,1400,-50,4,1401,-50,4,1402,-50,4,1403,-50,4,1404,-50,4,1405,-50,4,1406,-56,4,1407,-57,4,1408,-58,4,1409,-59,4,1410,-60,4,1411,-60,4,1412,-60,4,1413,-60,4,1414,-60,4,1415,-60,4,1416,-66,4,1417,-67,4,1418,-68,4,1419,-69,4,1420,-70,4,1421,-71,4,1422,-72,4,1423,-73,4,1424,-74,4,1425,-75,4,1426,-76,4,1427,-77,4,1428,-78,4,1429,-79,4,1430,-80,4,1431,-80,4,1432,-82,4,1433,-80,4,1434,-4,2,1435,-85,4,1436,-86,4,1437,-87,4,1438,-88,4,1439,-89,4,1440,-90,4,1441,-90,4,1442,-90,4,1443,-90,4,1444,-4,2,1445,-95,4,1446,-90,4,1447,-90,4,1448,-98,4,1449,-99,4,1450,-100,4,1451,-100,4,1452,-100,4,1453,-100,4,1454,-4,2,1455,-5,2,1456,-100,4,1457,-100,4,1458,-100,4,1459,-109,4,1460,-110,4,1461,-110,4,1462,-110,4,1463,-110,4,1464,-4,2,1465,-5,2,1466,-100,4,1467,-110,4,1468,-110,4,1469,-110,4,1470,-120,4,1471,-120,4,1472,-120,4,1473,-120,4,1474,-100,4,1475,-5,2,1476,-6,2,1477,-120,4,1478,-120,4,1479,-120,4,1480,-100,4,1481,-100,4,1482,-100,4,1483,-100,4,1484,-4,2,1485,-135,4,1486,-136,4,1487,-100,4,1488,-100,4,1489,-109,4,1490,-140,4,1491,-140,4,1492,-140,4,1493,-140,4,1494,-4,2,1495,-145,4,1496,-6,2,1497,-7,2,1498,-140,4,1499,-149,4,1500,-150,4,1501,-151,4,1502,-2,1,1503,-153,4,1504,-4,2,1505,-5,2,1506,-6,2,1507,-7,2,1508,-8,2,1509,-159,4,1510,-160,4,1511,-161,4,1512,-2,1,1513,-163,4,1514,-4,2,1515,-5,2,1516,-8,2,1517,-7,2,1518,-8,2,1519,-19,3,1520,-20,3,1521,-21,3,1522,-20,3,1523,-23,3,1524,-24,3,1525,-20,3,1526,-8,2,1527,-27,3,1528,-28,3,1529,-29,3,1530,-30,3,1531,-30,3,1532,-32,3,1533,-30,3,1534,-4,2,1535,-5,2,1536,-150,4,1537,-7,2,1538,-30,3,1539,-30,3,1540,-150,4,1541,-151,4,1542,-2,1,1543,-153,4,1544,-4,2,1545,-195,4,1546,-6,2,1547,-7,2,1548,-8,2,1549,-159,4,1550,-50,4,1551,-50,4,1552,-50,4,1553,-50,4,1554,-50,4,1555,-50,4,1556,-56,4,1557,-57,4,1558,-58,4,1559,-59,4,1560,-60,4,1561,-60,4,1562,-60,4,1563,-60,4,1564,-60,4,1565,-60,4,1566,-66,4,1567,-67,4,1568,-68,4,1569,-69,4,1570,-70,4,1571,-71,4,1572,-72,4,1573,-70,4,1574,-74,4,1575,-75,4,1576,-76,4,1577,-77,4,1578,-78,4,1579,-79,4,1580,-80,4,1581,-80,4,1582,-82,4,1583,-80,4,1584,-4,2,1585,-85,4,1586,-86,4,1587,-87,4,1588,-88,4,1589,-89,4,1590,-90,4,1591,-90,4,1592,-90,4,1593,-90,4,1594,-4,2,1595,-95,4,1596,-90,4,1597,-90,4,1598,-98,4,1599,-99,4,1600,-100,4,1601,-100,4,1602,-100,4,1603,-100,4,1604,-4,2,1605,-5,2,1606,-100,4,1607,-100,4,1608,-100,4,1609,-109,4,1610,-110,4,1611,-110,4,1612,-110,4,1613,-110,4,1614,-4,2,1615,-5,2,1616,-100,4,1617,-110,4,1618,-110,4,1619,-110,4,1620,-120,4,1621,-120,4,1622,-120,4,1623,-120,4,1624,-100,4,1625,-5,2,1626,-6,2,1627,-7,2,1628,-120,4,1629,-120,4,1630,-100,4,1631,-100,4,1632,-100,4,1633,-100,4,1634,-4,2,1635,-135,4,1636,-136,4,1637,-100,4,1638,-100,4,1639,-109,4,1640,-140,4,1641,-140,4,1642,-2,1,1643,-293,5,1644,-4,2,1645,-295,5,1646,-296,5,1647,-297,5,1648,-298,5,1649,-299,5,1650,-300,5,1651,-301,5,1652,-302,5,1653,-303,5,1654,-304,5,1655,-305,5,1656,-306,5,1657,-307,5,1658,-308,5,1659,-309,5,1660,-310,5,1661,-311,5,1662,-312,5,1663,-313,5,1664,-4,2,1665,-315,5,1666,-316,5,1667,-317,5,1668,-318,5,1669,-319,5,1670,-320,5,1671,-321,5,1672,-322,5,1673,-323,5,1674,-324,5,1675,-325,5,1676,-326,5,1677,-327,5,1678,-328,5,1679,-329,5,1680,-330,5,1681,-331,5,1682,-332,5,1683,-333,5,1684,-4,2,1685,-335,5,1686,-336,5,1687,-337,5,1688,-338,5,1689,-339,5,1690,-340,5,1691,-341,5,1692,-342,5,1693,-343,5,1694,-4,2,1695,-345,5,1696,-346,5,1697,-347,5,1698,-348,5,1699,-349,5,1700,-350,5,1701,-351,5,1702,-352,5,1703,-353,5,1704,-4,2,1705,-355,5,1706,-356,5,1707,-357,5,1708,-358,5,1709,-359,5,1710,-360,5,1711,-361,5,1712,-362,5,1713,-363,5,1714,-4,2,1715,-365,5,1716,-366,5,1717,-367,5,1718,-368,5,1719,-369,5,1720,-370,5,1721,-371,5,1722,-372,5,1723,-373,5,1724,-374,5,1725,-375,5,1726,-376,5,1727,-377,5,1728,-378,5,1729,-379,5,1730,-380,5,1731,-381,5,1732,-382,5,1733,-383,5,1734,-4,2,1735,-385,5,1736,-386,5,1737,-387,5,1738,-388,5,1739,-389,5,1740,-390,5,1741,-391,5,1742,-392,5,1743,-393,5,1744,-4,2,1745,-395,5,1746,-396,5,1747,-397,5,1748,-398,5,1749,-399,5,1750,-400,5,1751,-401,5,1752,-402,5,1753,-403,5,1754,-4,2,1755,-405,5,1756,-406,5,1757,-407,5,1758,-408,5,1759,-409,5,1760,-410,5,1761,-411,5,1762,-412,5,1763,-413,5,1764,-4,2,1765,-415,5,1766,-416,5,1767,-417,5,1768,-418,5,1769,-419,5,1770,-420,5,1771,-421,5,1772,-422,5,1773,-423,5,1774,-424,5,1775,-5,2,1776,-426,5,1777,-427,5,1778,-428,5,1779,-429,5,1780,-430,5,1781,-431,5,1782,-432,5,1783,-433,5,1784,-4,2,1785,-435,5,1786,-436,5,1787,-437,5,1788,-438,5,1789,-439,5,1790,-440,5,1791,-441,5,1792,-442,5,1793,-443,5,1794,-4,2,1795,-445,5,1796,-446,5,1797,-447,5,1798,-448,5,1799,-449,5,1800,-450,5,1801,-451,5,1802,-452,5,1803,-453,5,1804,-4,2,1805,-5,2,1806,-456,5,1807,-457,5,1808,-458,5,1809,-459,5,1810,-460,5,1811,-461,5,1812,-462,5,1813,-463,5,1814,-4,2,1815,-5,2,1816,-466,5,1817,-467,5,1818,-468,5,1819,-19,3,1820,-20,3,1821,-21,3,1822,-20,3,1823,-473,5,1824,-474,5,1825,-20,3,1826,-476,5,1827,-477,5,1828,-478,5,1829,-479,5,1830,-480,5,1831,-481,5,1832,-482,5,1833,-483,5,1834,-4,2,1835,-5,2,1836,-486,5,1837,-487,5,1838,-488,5,1839,-489,5,1840,-490,5,1841,-491,5,1842,-492,5,1843,-493,5,1844,-4,2,1845,-495,5,1846,-496,5,1847,-497,5,1848,-498,5,1849,-499,5,1850,-500,5,1851,-501,5,1852,-502,5,1853,-503,5,1854,-4,2,1855,-5,2,1856,-506,5,1857,-57,4,1858,-58,4,1859,-59,4,1860,-60,4,1861,-60,4,1862,-60,4,1863,-60,4,1864,-60,4,1865,-60,4,1866,-66,4,1867,-67,4,1868,-68,4,1869,-69,4,1870,-70,4,1871,-71,4,1872,-522,5,1873,-73,4,1874,-74,4,1875,-75,4,1876,-76,4,1877,-77,4,1878,-78,4,1879,-79,4,1880,-80,4,1881,-80,4,1882,-82,4,1883,-80,4,1884,-4,2,1885,-85,4,1886,-86,4,1887,-80,4,1888,-88,4,1889,-89,4,1890,-90,4,1891,-90,4,1892,-90,4,1893,-90,4,1894,-4,2,1895,-450,5,1896,-90,4,1897,-90,4,1898,-90,4,1899,-450,5,1900,-450,5,1901,-451,5,1902,-452,5,1903,-453,5,1904,-4,2,1905,-5,2,1906,-456,5,1907,-457,5,1908,-458,5,1909,-559,5,1910,-560,5,1911,-561,5,1912,-562,5,1913,-563,5,1914,-4,2,1915,-5,2,1916,-466,5,1917,-567,5,1918,-568,5,1919,-569,5,1920,-570,5,1921,-571,5,1922,-572,5,1923,-573,5,1924,-474,5,1925,-5,2,1926,-6,2,1927,-577,5,1928,-578,5,1929,-579,5,1930,-580,5,1931,-581,5,1932,-582,5,1933,-483,5,1934,-4,2,1935,-585,5,1936,-586,5,1937,-487,5,1938,-488,5,1939,-589,5,1940,-590,5,1941,-591,5,1942,-592,5,1943,-593,5,1944,-4,2,1945,-595,5,1946,-6,2,1947,-597,5,1948,-598,5,1949,-599,5,1950,-600,5,1951,-601,5,1952,-602,5,1953,-603,5,1954,-4,2,1955,-5,2,1956,-6,2,1957,-607,5,1958,-608,5,1959,-609,5,1960,-610,5,1961,-611,5,1962,-612,5,1963,-613,5,1964,-4,2,1965,-5,2,1966,-616,5,1967,-617,5,1968,-618,5,1969,-619,5,1970,-20,3,1971,-21,3,1972,-20,3,1973,-23,3,1974,-24,3,1975,-20,3,1976,-626,5,1977,-600,5,1978,-628,5,1979,-629,5,1980,-630,5,1981,-631,5,1982,-632,5,1983,-633,5,1984,-4,2,1985,-5,2,1986,-636,5,1987,-637,5,1988,-638,5,1989,-639,5,1990,-640,5,1991,-641,5,1992,-642,5,1993,-643,5,1994,-4,2,1995,-645,5,1996,-6,2,1997,-647,5,1998,-648,5,1999,-649,5,2000,-650,5,2001,-651,5,2002,-652,5,2003,-653,5,2004,-4,2,2005,-5,2,2006,-6,2,2007,-657,5,2008,-58,4,2009,-59,4,2010,-60,4,2011,-60,4,2012,-60,4,2013,-60,4,2014,-60,4,2015,-60,4,2016,-66,4,2017,-67,4,2018,-68,4,2019,-69,4,2020,-70,4,2021,-21,3,2022,-72,4,2023,-70,4,2024,-74,4,2025,-75,4,2026,-76,4,2027,-77,4,2028,-78,4,2029,-79,4,2030,-80,4,2031,-80,4,2032,-82,4,2033,-80,4,2034,-4,2,2035,-85,4,2036,-86,4,2037,-87,4,2038,-88,4,2039,-89,4,2040,-90,4,2041,-90,4,2042,-90,4,2043,-90,4,2044,-4,2,2045,-95,4,2046,-90,4,2047,-90,4,0,0,0"),
// leafSize 11
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,-2,1,13,-2,1,14,-3,1,15,-4,1,16,-8,2,17,-7,2,18,-8,2,19,-8,2,20,-10,2,21,-10,2,22,-11,2,23,-11,2,24,3,4,25,-11,2,26,-11,2,27,3,4,28,-8,2,29,-8,2,30,3,5,31,-10,2,32,-10,2,33,3,5,34,-1,1,35,-2,1,36,4,7,37,-4,2,38,-5,2,39,-6,2,40,4,7,41,-8,2,42,-9,2,43,-10,2,44,4,8,45,5,10,46,-2,1,47,-3,1,48,-4,2,49,-5,2,50,5,10,51,-7,2,52,-8,2,53,-9,2,54,-10,2,55,5,11,56,-1,1,57,-2,1,58,-3,1,59,-4,2,60,-10,2,61,-11,2,62,-7,2,63,-8,2,64,-9,2,65,-10,2,66,-11,2,67,-2,1,68,-2,1,69,-14,2,70,-10,2,71,-10,2,72,-22,3,73,-8,2,74,-8,2,75,-10,2,76,-10,2,77,-22,3,78,-33,3,79,-24,3,80,-30,3,81,-31,3,82,-27,3,83,-33,3,84,-40,3,85,-30,3,86,-31,3,87,-32,3,88,-33,3,89,-44,3,90,-40,3,91,-36,3,92,-4,2,93,-43,3,94,-44,3,95,-40,3,96,-41,3,97,-42,3,98,-43,3,99,-44,3,100,-50,3,101,-46,3,102,-47,3,103,-4,2,104,-50,3,105,-50,3,106,-44,3,107,-52,3,108,-53,3,109,-54,3,110,-55,3,111,-1,1,112,-55,3,113,-55,3,114,-4,2,115,-55,3,116,-55,3,117,-7,2,118,-55,3,119,-55,3,120,-55,3,121,-55,3,122,-57,3,123,-57,3,124,-55,3,125,-60,3,126,-21,3,127,-22,3,128,-8,2,129,-8,2,130,-20,3,131,-21,3,132,3,7,133,-1,1,134,-2,1,135,-3,1,136,-4,2,137,-5,2,138,-33,3,139,-40,3,140,-30,3,141,-9,2,142,-10,2,143,-33,3,144,-44,3,145,-40,3,146,-36,3,147,-4,2,148,-43,3,149,-44,3,150,3,7,151,-8,2,152,-20,3,153,-43,3,154,-44,3,155,-50,3,156,-2,1,157,-3,1,158,-8,2,159,-10,2,160,-50,3,161,-11,2,162,-8,2,163,-9,2,164,-10,2,165,3,7,166,-1,0,167,-2,1,168,-3,1,169,-4,2,170,-5,2,171,-6,2,172,-7,2,173,-8,2,174,-9,2,175,-10,2,176,-11,2,177,-11,2,178,-2,1,179,-11,2,180,-5,2,181,-8,2,182,-7,2,183,-8,2,184,-8,2,185,-20,3,186,-21,3,187,-22,3,188,-22,3,189,-24,3,190,-25,3,191,-26,3,192,-27,3,193,-28,3,194,-29,3,195,-30,3,196,-31,3,197,-32,3,198,-33,3,199,-33,3,200,4,11,201,-36,3,202,-4,2,203,-5,2,204,-44,3,205,-40,3,206,-33,3,207,-33,3,208,-33,3,209,-44,3,210,-45,3,211,-2,1,212,-44,3,213,-4,2,214,-5,2,215,-50,3,216,-7,2,217,-8,2,218,-9,2,219,-44,3,220,4,11,221,-1,0,222,-2,1,223,-3,1,224,-4,2,225,-5,2,226,-6,2,227,-7,2,228,-8,2,229,-9,2,230,-10,2,231,-11,2,232,-11,2,233,-2,1,234,-11,2,235,-5,2,236,-8,2,237,-7,2,238,-8,2,239,-8,2,240,-20,3,241,-21,3,242,-22,3,243,-22,3,244,-24,3,245,-25,3,246,-26,3,247,-27,3,248,-28,3,249,-29,3,250,-30,3,251,-31,3,252,-32,3,253,-33,3,254,-33,3,255,-33,3,256,-36,3,257,-4,2,258,-5,2,259,-6,2,260,-40,3,261,-33,3,262,-33,3,263,-33,3,264,-44,3,265,-45,3,266,-2,1,267,-44,3,268,-4,2,269,-5,2,270,-50,3,271,-7,2,272,-8,2,273,-9,2,274,-44,3,275,-55,3,276,-55,3,277,-2,1,278,-55,3,279,-4,2,280,-10,2,281,-50,3,282,-7,2,283,-8,2,284,-9,2,285,-65,4,286,-66,4,287,-66,4,288,-66,4,289,-66,4,290,-20,3,291,-21,3,292,-22,3,293,-73,4,294,-74,4,295,-75,4,296,-21,3,297,-22,3,298,-33,3,299,-79,4,300,-30,3,301,-81,4,302,-82,4,303,-83,4,304,-84,4,305,-85,4,306,-86,4,307,-87,4,308,-88,4,309,-89,4,310,-90,4,311,-91,4,312,-4,2,313,-93,4,314,-94,4,315,-95,4,316,-96,4,317,-97,4,318,-98,4,319,-99,4,320,-100,4,321,-99,4,322,-99,4,323,-4,2,324,-104,4,325,-105,4,326,-99,4,327,-99,4,328,-108,4,329,-109,4,330,-110,4,331,-110,4,332,-110,4,333,-110,4,334,-4,2,335,-115,4,336,-116,4,337,-110,4,338,-110,4,339,-110,4,340,-120,4,341,-121,4,342,-121,4,343,-121,4,344,-121,4,345,-105,4,346,-105,4,347,-105,4,348,-120,4,349,-121,4,350,-20,3,351,-110,4,352,-132,4,353,-132,4,354,-132,4,355,-132,4,356,-4,2,357,-5,2,358,-138,4,359,-132,4,360,-132,4,361,-132,4,362,-132,4,363,-143,4,364,-144,4,365,-165,4,366,-146,4,367,-4,2,368,-148,4,369,-149,4,370,-150,4,371,-151,4,372,-20,3,373,-153,4,374,-154,4,375,-155,4,376,-156,4,377,-157,4,378,-158,4,379,-159,4,380,-160,4,381,-161,4,382,-162,4,383,-163,4,384,-164,4,385,-165,4,386,-166,4,387,-167,4,388,-168,4,389,-4,2,390,-5,2,391,-6,2,392,-172,4,393,-173,4,394,-174,4,395,-175,4,396,-176,4,397,-177,4,398,-178,4,399,-179,4,400,-5,2,401,-181,4,402,-182,4,403,-183,4,404,-184,4,405,-20,3,406,-21,3,407,-22,3,408,-22,3,409,-24,3,410,-25,3,411,-4,2,412,-165,4,413,-165,4,414,-165,4,415,-195,4,416,-196,4,417,-197,4,418,-198,4,419,-199,4,420,-200,4,421,-201,4,422,-4,2,423,-5,2,424,-99,4,425,-205,4,426,-206,4,427,-207,4,428,-208,4,429,-209,4,430,-210,4,431,-211,4,432,-212,4,433,-4,2,434,-5,2,435,-215,4,436,-209,4,437,-217,4,438,-218,4,439,-219,4,440,-220,4,441,-220,4,442,-220,4,443,-220,4,444,-4,2,445,-5,2,446,-6,2,447,-7,2,448,-220,4,449,-220,4,450,-220,4,451,-220,4,452,-221,4,453,-222,4,454,-223,4,455,-5,2,456,-228,4,457,-7,2,458,-228,4,459,-228,4,460,-20,3,461,-21,3,462,-22,3,463,-22,3,464,-24,3,465,-25,3,466,-4,2,467,-27,3,468,-28,3,469,-21,3,470,-30,3,471,-31,3,472,-220,4,473,-220,4,474,-220,4,475,-220,4,476,-220,4,477,-4,2,478,-5,2,479,-94,4,480,-220,4,481,-220,4,482,-220,4,483,-220,4,484,-220,4,485,-220,4,486,-222,4,487,-223,4,488,-4,2,489,-5,2,490,-220,4,491,-7,2,492,-228,4,493,-229,4,494,-230,4,495,-55,4,496,-55,4,497,-55,4,498,-55,4,499,-55,4,500,-60,4,501,-61,4,502,-62,4,503,-63,4,504,-64,4,505,-65,4,506,-66,4,507,-66,4,508,-66,4,509,-66,4,510,-70,4,511,-21,3,512,-22,3,513,-73,4,514,-74,4,515,-75,4,516,-76,4,517,-77,4,518,-78,4,519,-79,4,520,-80,4,521,-81,4,522,-82,4,523,-83,4,524,-84,4,525,-85,4,526,-86,4,527,-87,4,528,-88,4,529,-89,4,530,-90,4,531,-91,4,532,-4,2,533,-93,4,534,-94,4,535,-95,4,536,-96,4,537,-97,4,538,-98,4,539,-99,4,540,-100,4,541,-99,4,542,-99,4,543,-4,2,544,-104,4,545,-105,4,546,-99,4,547,-99,4,548,-108,4,549,-109,4,550,-110,4,551,-110,4,552,-110,4,553,-110,4,554,-4,2,555,-115,4,556,-116,4,557,-110,4,558,-110,4,559,-110,4,560,-120,4,561,-121,4,562,-121,4,563,-121,4,564,-121,4,565,-20,3,566,-21,3,567,-22,3,568,-120,4,569,-121,4,570,-20,3,571,-21,3,572,-132,4,573,-132,4,574,-132,4,575,-132,4,576,-4,2,577,-5,2,578,-138,4,579,-132,4,580,-132,4,581,-132,4,582,-132,4,583,-143,4,584,-144,4,585,-165,4,586,-146,4,587,-4,2,588,-148,4,589,-149,4,590,-150,4,591,-151,4,592,-20,3,593,-153,4,594,-154,4,595,-155,4,596,-156,4,597,-157,4,598,-158,4,599,-159,4,600,-160,4,601,-161,4,602,-154,4,603,-163,4,604,-164,4,605,-165,4,606,-166,4,607,-165,4,608,-168,4,609,-4,2,610,-5,2,611,-6,2,612,-7,2,613,-165,4,614,-165,4,615,-175,4,616,-176,4,617,-177,4,618,-176,4,619,-179,4,620,-5,2,621,-165,4,622,-7,2,623,-175,4,624,-19,3,625,-20,3,626,-21,3,627,-22,3,628,-22,3,629,-24,3,630,-25,3,631,-4,2,632,-27,3,633,-28,3,634,-21,3,635,-30,3,636,-31,3,637,-165,4,638,-165,4,639,-166,4,640,-200,4,641,-165,4,642,-4,2,643,-5,2,644,-99,4,645,-165,4,646,-165,4,647,-165,4,648,-175,4,649,-165,4,650,-165,4,651,-165,4,652,-168,4,653,-4,2,654,-5,2,655,-165,4,656,-7,2,657,-165,4,658,-174,4,659,-175,4,660,3,9,661,-1,0,662,-2,1,663,-3,1,664,-4,2,665,-5,2,666,-6,2,667,-7,2,668,-8,2,669,-9,2,670,-10,2,671,-11,2,672,-11,2,673,-2,1,674,-11,2,675,-5,2,676,-8,2,677,-7,2,678,-8,2,679,-19,3,680,-20,3,681,-21,3,682,-22,3,683,-22,3,684,-24,3,685,-25,3,686,-4,2,687,-27,3,688,-28,3,689,-21,3,690,-30,3,691,-31,3,692,-32,3,693,-33,3,694,-33,3,695,-33,3,696,-36,3,697,-4,2,698,-5,2,699,-6,2,700,-40,3,701,-33,3,702,-33,3,703,-33,3,704,-44,3,705,-45,3,706,-2,1,707,-44,3,708,-4,2,709,-5,2,710,-50,3,711,-7,2,712,-8,2,713,-9,2,714,-10,2,715,-55,4,716,-55,4,717,-55,4,718,-55,4,719,-55,4,720,-60,4,721,-61,4,722,-62,4,723,-63,4,724,-64,4,725,-65,4,726,-66,4,727,-66,4,728,-66,4,729,-66,4,730,-70,4,731,-71,4,732,-72,4,733,-73,4,734,-74,4,735,-75,4,736,-76,4,737,-77,4,738,-78,4,739,-79,4,740,-80,4,741,-81,4,742,-82,4,743,-83,4,744,-84,4,745,-85,4,746,-86,4,747,-87,4,748,-88,4,749,-89,4,750,-90,4,751,-91,4,752,-4,2,753,-93,4,754,-94,4,755,-95,4,756,-96,4,757,-97,4,758,-98,4,759,-99,4,760,-100,4,761,-99,4,762,-99,4,763,-4,2,764,-104,4,765,-105,4,766,-99,4,767,-99,4,768,-108,4,769,-109,4,770,-110,4,771,-110,4,772,-110,4,773,-110,4,774,-4,2,775,-115,4,776,-116,4,777,-110,4,778,-110,4,779,-110,4,780,-120,4,781,-121,4,782,-121,4,783,-121,4,784,-121,4,785,-20,3,786,-21,3,787,-22,3,788,-120,4,789,-121,4,790,-20,3,791,-21,3,792,-132,4,793,-132,4,794,-132,4,795,-132,4,796,-4,2,797,-5,2,798,-138,4,799,-132,4,800,-132,4,801,-132,4,802,-132,4,803,-143,4,804,-144,4,805,-145,4,806,-146,4,807,-4,2,808,-148,4,809,-149,4,810,-150,4,811,-151,4,812,-20,3,813,-153,4,814,-154,4,815,-155,4,816,-156,4,817,-157,4,818,-150,4,819,-159,4,820,-160,4,821,-161,4,822,-154,4,823,-163,4,824,-164,4,825,-165,4,826,-166,4,827,-2,1,828,-168,4,829,-4,2,830,-5,2,831,-6,2,832,-7,2,833,-8,2,834,-174,4,835,-175,4,836,-176,4,837,-177,4,838,-2,1,839,-179,4,840,-5,2,841,-8,2,842,-7,2,843,-8,2,844,-19,3,845,-20,3,846,-21,3,847,-22,3,848,-22,3,849,-24,3,850,-25,3,851,-4,2,852,-27,3,853,-28,3,854,-21,3,855,-30,3,856,-31,3,857,-32,3,858,-33,3,859,-33,3,860,-200,4,861,-165,4,862,-4,2,863,-5,2,864,-99,4,865,-165,4,866,-8,2,867,-33,3,868,-33,3,869,-209,4,870,-210,4,871,-2,1,872,-212,4,873,-4,2,874,-5,2,875,-215,4,876,-7,2,877,-8,2,878,-9,2,879,-54,4,880,-220,4,881,-221,4,882,-2,1,883,-223,4,884,-4,2,885,-5,2,886,-6,2,887,-7,2,888,-8,2,889,-9,2,890,-10,2,891,-231,4,892,-232,4,893,-2,1,894,-234,4,895,-5,2,896,-8,2,897,-7,2,898,-8,2,899,-19,3,900,-20,3,901,-21,3,902,-22,3,903,-22,3,904,-24,3,905,-25,3,906,-4,2,907,-27,3,908,-28,3,909,-21,3,910,-30,3,911,-31,3,912,-32,3,913,-33,3,914,-33,3,915,-33,3,916,-36,3,917,-4,2,918,-5,2,919,-94,4,920,-260,5,921,-8,2,922,-33,3,923,-263,5,924,-264,5,925,-265,5,926,-266,5,927,-267,5,928,-268,5,929,-269,5,930,-270,5,931,-271,5,932,-272,5,933,-273,5,934,-274,5,935,-55,4,936,-55,4,937,-55,4,938,-55,4,939,-55,4,940,-60,4,941,-61,4,942,-62,4,943,-63,4,944,-64,4,945,-65,4,946,-66,4,947,-66,4,948,-66,4,949,-66,4,950,-70,4,951,-71,4,952,-292,5,953,-73,4,954,-74,4,955,-75,4,956,-76,4,957,-77,4,958,-78,4,959,-79,4,960,-80,4,961,-81,4,962,-82,4,963,-83,4,964,-84,4,965,-85,4,966,-86,4,967,-87,4,968,-88,4,969,-89,4,970,-90,4,971,-91,4,972,-4,2,973,-93,4,974,-94,4,975,-95,4,976,-96,4,977,-97,4,978,-98,4,979,-99,4,980,-100,4,981,-99,4,982,-99,4,983,-4,2,984,-104,4,985,-105,4,986,-99,4,987,-327,5,988,-328,5,989,-329,5,990,-330,5,991,-331,5,992,-332,5,993,-333,5,994,-334,5,995,-335,5,996,-336,5,997,-337,5,998,-338,5,999,-339,5,1000,-340,5,1001,-341,5,1002,-342,5,1003,-343,5,1004,-344,5,1005,-345,5,1006,-346,5,1007,-347,5,1008,-348,5,1009,-349,5,1010,-350,5,1011,-351,5,1012,-352,5,1013,-353,5,1014,-354,5,1015,-355,5,1016,-356,5,1017,-357,5,1018,-358,5,1019,-359,5,1020,-360,5,1021,-361,5,1022,-362,5,1023,-363,5,1024,-364,5,1025,-365,5,1026,-366,5,1027,-367,5,1028,-368,5,1029,-369,5,1030,-370,5,1031,-371,5,1032,-372,5,1033,-373,5,1034,-374,5,1035,-375,5,1036,-376,5,1037,-377,5,1038,-378,5,1039,-379,5,1040,-380,5,1041,-381,5,1042,-382,5,1043,-383,5,1044,-384,5,1045,-385,5,1046,-386,5,1047,-387,5,1048,-388,5,1049,-389,5,1050,-390,5,1051,-391,5,1052,-392,5,1053,-393,5,1054,-394,5,1055,-395,5,1056,-396,5,1057,-397,5,1058,-398,5,1059,-399,5,1060,-400,5,1061,-401,5,1062,-402,5,1063,-403,5,1064,-404,5,1065,-405,5,1066,-406,5,1067,-407,5,1068,-408,5,1069,-409,5,1070,-410,5,1071,-4,2,1072,-412,5,1073,-413,5,1074,-414,5,1075,-415,5,1076,-416,5,1077,-417,5,1078,-418,5,1079,-419,5,1080,-420,5,1081,-421,5,1082,-4,2,1083,-423,5,1084,-424,5,1085,-425,5,1086,-426,5,1087,-427,5,1088,-428,5,1089,-429,5,1090,-430,5,1091,-431,5,1092,-432,5,1093,-4,2,1094,-434,5,1095,-435,5,1096,-436,5,1097,-437,5,1098,-438,5,1099,-439,5,1100,-440,5,1101,-441,5,1102,-442,5,1103,-443,5,1104,-4,2,1105,-445,5,1106,-446,5,1107,-447,5,1108,-448,5,1109,-449,5,1110,-450,5,1111,-451,5,1112,-452,5,1113,-453,5,1114,-454,5,1115,-455,5,1116,-456,5,1117,-457,5,1118,-458,5,1119,-459,5,1120,-460,5,1121,-461,5,1122,-462,5,1123,-463,5,1124,-464,5,1125,-465,5,1126,-4,2,1127,-467,5,1128,-468,5,1129,-469,5,1130,-470,5,1131,-471,5,1132,-472,5,1133,-473,5,1134,-474,5,1135,-475,5,1136,-476,5,1137,-4,2,1138,-478,5,1139,-479,5,1140,-480,5,1141,-481,5,1142,-482,5,1143,-483,5,1144,-484,5,1145,-485,5,1146,-486,5,1147,-487,5,1148,-4,2,1149,-489,5,1150,-490,5,1151,-491,5,1152,-492,5,1153,-493,5,1154,-494,5,1155,-55,4,1156,-55,4,1157,-55,4,1158,-55,4,1159,-55,4,1160,-60,4,1161,-61,4,1162,-62,4,1163,-63,4,1164,-64,4,1165,-65,4,1166,-66,4,1167,-66,4,1168,-66,4,1169,-66,4,1170,-70,4,1171,-511,5,1172,-512,5,1173,-73,4,1174,-440,5,1175,-440,5,1176,-440,5,1177,-440,5,1178,-440,5,1179,-440,5,1180,-440,5,1181,-440,5,1182,-440,5,1183,-523,5,1184,-524,5,1185,-525,5,1186,-526,5,1187,-527,5,1188,-528,5,1189,-529,5,1190,-530,5,1191,-531,5,1192,-4,2,1193,-533,5,1194,-534,5,1195,-535,5,1196,-536,5,1197,-537,5,1198,-538,5,1199,-539,5,1200,-540,5,1201,-541,5,1202,-542,5,1203,-4,2,1204,-544,5,1205,-545,5,1206,-546,5,1207,-547,5,1208,-548,5,1209,-549,5,1210,-550,5,1211,-551,5,1212,-552,5,1213,-553,5,1214,-4,2,1215,-555,5,1216,-556,5,1217,-557,5,1218,-558,5,1219,-559,5,1220,-560,5,1221,-561,5,1222,-562,5,1223,-563,5,1224,-564,5,1225,-565,5,1226,-566,5,1227,-567,5,1228,-568,5,1229,-569,5,1230,-570,5,1231,-571,5,1232,-572,5,1233,-573,5,1234,-574,5,1235,-575,5,1236,-4,2,1237,-577,5,1238,-578,5,1239,-579,5,1240,-580,5,1241,-581,5,1242,-582,5,1243,-583,5,1244,-584,5,1245,-585,5,1246,-586,5,1247,-4,2,1248,-588,5,1249,-589,5,1250,-590,5,1251,-591,5,1252,-572,5,1253,-593,5,1254,-594,5,1255,-595,5,1256,-596,5,1257,-597,5,1258,-598,5,1259,-599,5,1260,-600,5,1261,-601,5,1262,-602,5,1263,-603,5,1264,-604,5,1265,-605,5,1266,-606,5,1267,-607,5,1268,-608,5,1269,-4,2,1270,-5,2,1271,-611,5,1272,-612,5,1273,-613,5,1274,-614,5,1275,-615,5,1276,-616,5,1277,-617,5,1278,-618,5,1279,-619,5,1280,-5,2,1281,-621,5,1282,-622,5,1283,-623,5,1284,-19,3,1285,-20,3,1286,-626,5,1287,-627,5,1288,-628,5,1289,-629,5,1290,-630,5,1291,-4,2,1292,-632,5,1293,-633,5,1294,-634,5,1295,-635,5,1296,-636,5,1297,-637,5,1298,-638,5,1299,-639,5,1300,-640,5,1301,-641,5,1302,-4,2,1303,-5,2,1304,-644,5,1305,-645,5,1306,-646,5,1307,-647,5,1308,-648,5,1309,-649,5,1310,-650,5,1311,-651,5,1312,-652,5,1313,-4,2,1314,-5,2,1315,-655,5,1316,-656,5,1317,-657,5,1318,-658,5,1319,-659,5,1320,-660,5,1321,-660,5,1322,-660,5,1323,-660,5,1324,-4,2,1325,-5,2,1326,-660,5,1327,-660,5,1328,-660,5,1329,-660,5,1330,-660,5,1331,-660,5,1332,-661,5,1333,-662,5,1334,-663,5,1335,-5,2,1336,-668,5,1337,-667,5,1338,-668,5,1339,-19,3,1340,-20,3,1341,-21,3,1342,-660,5,1343,-661,5,1344,-660,5,1345,-660,5,1346,-4,2,1347,-660,5,1348,-660,5,1349,-21,3,1350,-660,5,1351,-660,5,1352,-660,5,1353,-660,5,1354,-661,5,1355,-662,5,1356,-660,5,1357,-4,2,1358,-5,2,1359,-666,5,1360,-660,5,1361,-668,5,1362,-669,5,1363,-670,5,1364,-660,5,1365,-660,5,1366,-662,5,1367,-663,5,1368,-4,2,1369,-5,2,1370,-50,4,1371,-667,5,1372,-668,5,1373,-669,5,1374,-54,4,1375,-55,4,1376,-55,4,1377,-55,4,1378,-55,4,1379,-55,4,1380,-60,4,1381,-61,4,1382,-62,4,1383,-63,4,1384,-64,4,1385,-65,4,1386,-66,4,1387,-66,4,1388,-66,4,1389,-66,4,1390,-70,4,1391,-71,4,1392,-72,4,1393,-73,4,1394,-74,4,1395,-75,4,1396,-76,4,1397,-77,4,1398,-78,4,1399,-79,4,1400,-80,4,1401,-81,4,1402,-82,4,1403,-83,4,1404,-84,4,1405,-85,4,1406,-86,4,1407,-87,4,1408,-88,4,1409,-89,4,1410,-90,4,1411,-91,4,1412,-4,2,1413,-93,4,1414,-94,4,1415,-660,5,1416,-660,5,1417,-660,5,1418,-660,5,1419,-660,5,1420,-660,5,1421,-660,5,1422,-660,5,1423,-4,2,1424,-660,5,1425,-660,5,1426,-660,5,1427,-660,5,1428,-660,5,1429,-660,5,1430,-660,5,1431,-661,5,1432,-662,5,1433,-663,5,1434,-4,2,1435,-660,5,1436,-660,5,1437,-667,5,1438,-668,5,1439,-669,5,1440,-660,5,1441,-660,5,1442,-661,5,1443,-662,5,1444,-663,5,1445,-20,3,1446,-21,3,1447,-22,3,1448,-668,5,1449,-668,5,1450,-20,3,1451,-21,3,1452,-660,5,1453,-661,5,1454,-662,5,1455,-663,5,1456,-4,2,1457,-5,2,1458,-660,5,1459,-667,5,1460,-668,5,1461,-669,5,1462,-670,5,1463,-660,5,1464,-660,5,1465,-660,5,1466,-660,5,1467,-4,2,1468,-660,5,1469,-660,5,1470,-660,5,1471,-660,5,1472,-20,3,1473,-660,5,1474,-660,5,1475,-660,5,1476,-662,5,1477,-660,5,1478,-668,5,1479,-660,5,1480,-660,5,1481,-660,5,1482,-668,5,1483,-660,5,1484,-660,5,1485,-660,5,1486,-660,5,1487,-662,5,1488,-660,5,1489,-4,2,1490,-5,2,1491,-666,5,1492,-667,5,1493,-668,5,1494,-660,5,1495,-660,5,1496,-660,5,1497,-660,5,1498,-662,5,1499,-660,5,1500,-5,2,1501,-676,5,1502,-667,5,1503,-668,5,1504,-19,3,1505,-20,3,1506,-21,3,1507,-22,3,1508,-22,3,1509,-660,5,1510,-685,5,1511,-4,2,1512,-687,5,1513,-688,5,1514,-21,3,1515,-690,5,1516,-691,5,1517,-692,5,1518,-693,5,1519,-693,5,1520,-660,5,1521,-696,5,1522,-4,2,1523,-5,2,1524,-99,4,1525,-700,5,1526,-701,5,1527,-693,5,1528,-693,5,1529,-660,5,1530,-660,5,1531,-662,5,1532,-660,5,1533,-4,2,1534,-5,2,1535,-660,5,1536,-667,5,1537,-668,5,1538,-669,5,1539,-54,4,1540,-660,5,1541,-660,5,1542,-662,5,1543,-660,5,1544,-4,2,1545,-5,2,1546,-660,5,1547,-667,5,1548,-668,5,1549,-669,5,1550,-670,5,1551,-671,5,1552,-671,5,1553,-233,5,1554,-234,5,1555,-5,2,1556,-676,5,1557,-237,5,1558,-238,5,1559,-19,3,1560,-20,3,1561,-21,3,1562,-22,3,1563,-22,3,1564,-24,3,1565,-685,5,1566,-4,2,1567,-247,5,1568,-248,5,1569,-249,5,1570,-250,5,1571,-251,5,1572,-252,5,1573,-253,5,1574,-254,5,1575,-255,5,1576,-256,5,1577,-257,5,1578,-258,5,1579,-94,4,1580,-260,5,1581,-261,5,1582,-262,5,1583,-263,5,1584,-264,5,1585,-265,5,1586,-266,5,1587,-267,5,1588,-268,5,1589,-269,5,1590,-270,5,1591,-271,5,1592,-272,5,1593,-273,5,1594,-274,5,1595,-275,5,1596,-276,5,1597,-277,5,1598,-278,5,1599,-279,5,1600,-280,5,1601,-61,4,1602,-282,5,1603,-63,4,1604,-64,4,1605,-65,4,1606,-66,4,1607,-66,4,1608,-66,4,1609,-66,4,1610,-290,5,1611,-291,5,1612,-292,5,1613,-73,4,1614,-74,4,1615,-75,4,1616,-296,5,1617,-297,5,1618,-298,5,1619,-79,4,1620,-300,5,1621,-81,4,1622,-82,4,1623,-303,5,1624,-304,5,1625,-305,5,1626,-306,5,1627,-307,5,1628,-308,5,1629,-309,5,1630,-310,5,1631,-311,5,1632,-308,5,1633,-313,5,1634,-314,5,1635,-315,5,1636,-316,5,1637,-317,5,1638,-318,5,1639,-319,5,1640,-320,5,1641,-321,5,1642,-322,5,1643,-4,2,1644,-324,5,1645,-325,5,1646,-326,5,1647,-327,5,1648,-328,5,1649,-329,5,1650,-330,5,1651,-331,5,1652,-332,5,1653,-333,5,1654,-4,2,1655,-335,5,1656,-336,5,1657,-337,5,1658,-338,5,1659,-339,5,1660,-340,5,1661,-341,5,1662,-342,5,1663,-343,5,1664,-344,5,1665,-345,5,1666,-346,5,1667,-347,5,1668,-348,5,1669,-349,5,1670,-350,5,1671,-351,5,1672,-352,5,1673,-353,5,1674,-354,5,1675,-355,5,1676,-4,2,1677,-357,5,1678,-358,5,1679,-359,5,1680,-360,5,1681,-361,5,1682,-362,5,1683,-363,5,1684,-364,5,1685,-365,5,1686,-366,5,1687,-4,2,1688,-368,5,1689,-369,5,1690,-370,5,1691,-371,5,1692,-372,5,1693,-373,5,1694,-374,5,1695,-375,5,1696,-376,5,1697,-377,5,1698,-378,5,1699,-379,5,1700,-380,5,1701,-381,5,1702,-382,5,1703,-383,5,1704,-384,5,1705,-385,5,1706,-386,5,1707,-387,5,1708,-388,5,1709,-4,2,1710,-390,5,1711,-391,5,1712,-392,5,1713,-393,5,1714,-394,5,1715,-395,5,1716,-396,5,1717,-397,5,1718,-398,5,1719,-399,5,1720,-400,5,1721,-401,5,1722,-402,5,1723,-403,5,1724,-404,5,1725,-405,5,1726,-406,5,1727,-407,5,1728,-408,5,1729,-409,5,1730,-410,5,1731,-4,2,1732,-412,5,1733,-413,5,1734,-414,5,1735,-415,5,1736,-416,5,1737,-417,5,1738,-418,5,1739,-419,5,1740,-420,5,1741,-421,5,1742,-4,2,1743,-5,2,1744,-424,5,1745,-425,5,1746,-426,5,1747,-427,5,1748,-428,5,1749,-429,5,1750,-430,5,1751,-431,5,1752,-432,5,1753,-4,2,1754,-5,2,1755,-435,5,1756,-436,5,1757,-437,5,1758,-438,5,1759,-439,5,1760,-440,5,1761,-441,5,1762,-442,5,1763,-443,5,1764,-4,2,1765,-5,2,1766,-446,5,1767,-447,5,1768,-448,5,1769,-449,5,1770,-450,5,1771,-451,5,1772,-452,5,1773,-453,5,1774,-454,5,1775,-5,2,1776,-456,5,1777,-457,5,1778,-458,5,1779,-19,3,1780,-20,3,1781,-21,3,1782,-440,5,1783,-441,5,1784,-464,5,1785,-465,5,1786,-4,2,1787,-467,5,1788,-468,5,1789,-21,3,1790,-470,5,1791,-471,5,1792,-472,5,1793,-473,5,1794,-474,5,1795,-475,5,1796,-476,5,1797,-4,2,1798,-5,2,1799,-385,5,1800,-480,5,1801,-481,5,1802,-482,5,1803,-483,5,1804,-484,5,1805,-485,5,1806,-486,5,1807,-487,5,1808,-4,2,1809,-5,2,1810,-490,5,1811,-491,5,1812,-492,5,1813,-493,5,1814,-494,5,1815,-55,4,1816,-55,4,1817,-55,4,1818,-55,4,1819,-55,4,1820,-60,4,1821,-61,4,1822,-62,4,1823,-63,4,1824,-64,4,1825,-65,4,1826,-66,4,1827,-66,4,1828,-66,4,1829,-66,4,1830,-70,4,1831,-71,4,1832,-490,5,1833,-73,4,1834,-74,4,1835,-75,4,1836,-76,4,1837,-77,4,1838,-78,4,1839,-79,4,1840,-80,4,1841,-81,4,1842,-82,4,1843,-83,4,1844,-84,4,1845,-85,4,1846,-86,4,1847,-87,4,1848,-88,4,1849,-440,5,1850,-440,5,1851,-440,5,1852,-4,2,1853,-440,5,1854,-440,5,1855,-440,5,1856,-440,5,1857,-440,5,1858,-440,5,1859,-440,5,1860,-440,5,1861,-442,5,1862,-443,5,1863,-4,2,1864,-440,5,1865,-440,5,1866,-447,5,1867,-448,5,1868,-440,5,1869,-440,5,1870,-440,5,1871,-441,5,1872,-442,5,1873,-443,5,1874,-4,2,1875,-440,5,1876,-440,5,1877,-447,5,1878,-448,5,1879,-449,5,1880,-560,5,1881,-561,5,1882,-562,5,1883,-563,5,1884,-564,5,1885,-20,3,1886,-21,3,1887,-440,5,1888,-448,5,1889,-448,5,1890,-20,3,1891,-21,3,1892,-572,5,1893,-573,5,1894,-574,5,1895,-575,5,1896,-4,2,1897,-5,2,1898,-578,5,1899,-572,5,1900,-580,5,1901,-581,5,1902,-582,5,1903,-583,5,1904,-584,5,1905,-585,5,1906,-586,5,1907,-4,2,1908,-588,5,1909,-589,5,1910,-590,5,1911,-591,5,1912,-20,3,1913,-593,5,1914,-594,5,1915,-595,5,1916,-596,5,1917,-597,5,1918,-598,5,1919,-599,5,1920,-600,5,1921,-601,5,1922,-602,5,1923,-603,5,1924,-604,5,1925,-605,5,1926,-606,5,1927,-607,5,1928,-608,5,1929,-4,2,1930,-5,2,1931,-605,5,1932,-605,5,1933,-613,5,1934,-614,5,1935,-615,5,1936,-616,5,1937,-617,5,1938,-618,5,1939,-619,5,1940,-5,2,1941,-621,5,1942,-615,5,1943,-623,5,1944,-19,3,1945,-20,3,1946,-21,3,1947,-22,3,1948,-22,3,1949,-605,5,1950,-605,5,1951,-4,2,1952,-605,5,1953,-605,5,1954,-21,3,1955,-605,5,1956,-605,5,1957,-605,5,1958,-605,5,1959,-606,5,1960,-640,5,1961,-641,5,1962,-4,2,1963,-5,2,1964,-440,5,1965,-645,5,1966,-613,5,1967,-614,5,1968,-615,5,1969,-649,5,1970,-650,5,1971,-649,5,1972,-652,5,1973,-4,2,1974,-5,2,1975,-655,5,1976,-649,5,1977,-649,5,1978,-658,5,1979,-659,5,1980,3,11,1981,-1,0,1982,-2,1,1983,-3,1,1984,-4,2,1985,-5,2,1986,-6,2,1987,-7,2,1988,-8,2,1989,-9,2,1990,-10,2,1991,-11,2,1992,-11,2,1993,-2,1,1994,-11,2,1995,-5,2,1996,-8,2,1997,-7,2,1998,-8,2,1999,-19,3,2000,-20,3,2001,-21,3,2002,-22,3,2003,-22,3,2004,-24,3,2005,-25,3,2006,-4,2,2007,-27,3,2008,-28,3,2009,-21,3,2010,-30,3,2011,-31,3,2012,-32,3,2013,-33,3,2014,-33,3,2015,-2,1,2016,-36,3,2017,-4,2,2018,-5,2,2019,-6,2,2020,-40,3,2021,-8,2,2022,-33,3,2023,-33,3,2024,-44,3,2025,-45,3,2026,-2,1,2027,-44,3,2028,-4,2,2029,-5,2,2030,-50,4,2031,-7,2,2032,-8,2,2033,-53,4,2034,-54,4,2035,-55,4,2036,-55,4,2037,-55,4,2038,-55,4,2039,-55,4,2040,-60,4,2041,-61,4,2042,-62,4,2043,-63,4,2044,-64,4,2045,-65,4,2046,-66,4,2047,-66,4,0,0,0"),
// leafSize 12
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,12,14,13,-2,1,14,-2,1,15,-3,1,16,-4,1,17,-7,2,18,-8,2,19,-8,2,20,-10,2,21,-10,2,22,-11,2,23,-11,2,24,-12,2,25,-12,2,26,-12,2,27,3,4,28,-8,2,29,-8,2,30,3,5,31,-10,2,32,-10,2,33,3,5,34,-11,2,35,-11,2,36,3,5,37,-1,1,38,-2,1,39,-3,1,40,4,7,41,-8,2,42,-12,2,43,-10,2,44,4,8,45,-12,2,46,-10,2,47,-11,2,48,4,8,49,-1,1,50,5,10,51,-3,1,52,-8,2,53,-5,2,54,-10,2,55,5,11,56,-12,2,57,-9,2,58,-10,2,59,-11,2,60,5,11,61,-1,1,62,-2,1,63,-3,1,64,-4,2,65,-10,2,66,6,13,67,-12,2,68,-8,2,69,-9,2,70,-10,2,71,-11,2,72,-12,2,73,-7,2,74,-8,2,75,-9,2,76,-10,2,77,-11,2,78,-12,2,79,-24,3,80,-10,2,81,-21,3,82,-22,3,83,-23,3,84,-24,3,85,-8,2,86,-10,2,87,-21,3,88,-22,3,89,-23,3,90,-24,3,91,-36,3,92,-44,3,93,-33,3,94,-34,3,95,-35,3,96,-36,3,97,-1,1,98,-48,3,99,-33,3,100,-40,3,101,-35,3,102,-36,3,103,-48,3,104,-44,3,105,-50,3,106,-40,3,107,-47,3,108,-48,3,109,-1,1,110,-44,3,111,-45,3,112,-46,3,113,-47,3,114,-48,3,115,-55,3,116,-50,3,117,-57,3,118,-58,3,119,-59,3,120,-60,3,121,-55,3,122,-60,3,123,-60,3,124,-58,3,125,-59,3,126,-60,3,127,-60,3,128,-8,2,129,-60,3,130,-60,3,131,-60,3,132,-66,3,133,-66,3,134,-8,2,135,-60,3,136,-66,3,137,-66,3,138,-66,3,139,-7,2,140,-8,2,141,-9,2,142,-66,3,143,-66,3,144,3,7,145,-1,0,146,-2,1,147,-21,3,148,-22,3,149,-23,3,150,-24,3,151,-36,3,152,-44,3,153,-33,3,154,-10,2,155,-11,2,156,-36,3,157,-36,3,158,-44,3,159,-33,3,160,-40,3,161,-35,3,162,-36,3,163,-48,3,164,-44,3,165,3,7,166,-40,3,167,-23,3,168,-48,3,169,-48,3,170,-44,3,171,-50,3,172,-7,2,173,-8,2,174,-48,3,175,-55,3,176,-44,3,177,-12,2,178,-10,2,179,-11,2,180,3,7,181,-1,0,182,-2,1,183,-3,1,184,-4,2,185,-5,2,186,-60,3,187,-7,2,188,-8,2,189,-9,2,190,-10,2,191,-11,2,192,-12,2,193,-12,2,194,-2,1,195,-12,2,196,-8,2,197,-7,2,198,3,7,199,-8,2,200,-20,3,201,-21,3,202,-22,3,203,-23,3,204,-24,3,205,-7,2,206,-8,2,207,-9,2,208,-10,2,209,-11,2,210,-12,2,211,-31,3,212,-32,3,213,-33,3,214,-34,3,215,-35,3,216,-36,3,217,-36,3,218,-36,3,219,-21,3,220,4,11,221,-23,3,222,-24,3,223,-33,3,224,-44,3,225,-60,3,226,-36,3,227,-36,3,228,-48,3,229,-48,3,230,-50,3,231,-11,2,232,-12,2,233,-5,2,234,-36,3,235,-55,3,236,-8,2,237,-9,2,238,-10,2,239,-48,3,240,4,11,241,-1,0,242,-2,1,243,-3,1,244,-4,2,245,-5,2,246,-6,2,247,-7,2,248,-8,2,249,-9,2,250,-10,2,251,-11,2,252,-12,2,253,-12,2,254,-2,1,255,-15,3,256,-8,2,257,-7,2,258,-60,3,259,-8,2,260,-20,3,261,-21,3,262,-22,3,263,-23,3,264,4,11,265,-1,0,266,-2,1,267,-27,3,268,-4,2,269,-5,2,270,-30,3,271,-7,2,272,-8,2,273,-33,3,274,-10,2,275,-11,2,276,-36,3,277,-36,3,278,-36,3,279,-36,3,280,-40,3,281,-33,3,282,-102,4,283,-33,3,284,-44,3,285,-45,3,286,-36,3,287,-36,3,288,-48,3,289,-48,3,290,-50,3,291,-48,3,292,-8,2,293,-5,2,294,-44,3,295,-55,3,296,-8,2,297,-9,2,298,-10,2,299,-48,3,300,-60,4,301,-60,4,302,-60,4,303,-60,4,304,-60,4,305,-65,4,306,-66,4,307,-67,4,308,-68,4,309,-69,4,310,-70,4,311,-71,4,312,-72,4,313,-66,4,314,-74,4,315,-75,4,316,-76,4,317,-77,4,318,-78,4,319,-55,3,320,-80,4,321,-81,4,322,-82,4,323,-83,4,324,-60,4,325,-77,4,326,-86,4,327,-87,4,328,-88,4,329,-89,4,330,-66,4,331,-91,4,332,-92,4,333,-93,4,334,-70,4,335,-71,4,336,-96,4,337,-96,4,338,-98,4,339,-99,4,340,-100,4,341,-77,4,342,-102,4,343,-103,4,344,-104,4,345,-105,4,346,-106,4,347,-107,4,348,-108,4,349,-108,4,350,-110,4,351,-108,4,352,-112,4,353,-113,4,354,-114,4,355,-115,4,356,-116,4,357,-108,4,358,-118,4,359,-119,4,360,-120,4,361,-121,4,362,-120,4,363,-120,4,364,-124,4,365,-125,4,366,-126,4,367,-120,4,368,-120,4,369,-120,4,370,-120,4,371,-131,4,372,-132,4,373,-126,4,374,-126,4,375,-126,4,376,-126,4,377,-137,4,378,-180,4,379,-115,4,380,-132,4,381,-132,4,382,-132,4,383,-143,4,384,-144,4,385,-145,4,386,-146,4,387,-21,3,388,-190,4,389,-191,4,390,-126,4,391,-151,4,392,-152,4,393,-153,4,394,-154,4,395,-155,4,396,-156,4,397,-157,4,398,-158,4,399,-159,4,400,-180,4,401,-137,4,402,-162,4,403,-163,4,404,-164,4,405,-165,4,406,-166,4,407,-23,3,408,-168,4,409,-169,4,410,-170,4,411,-191,4,412,-172,4,413,-173,4,414,-174,4,415,-175,4,416,-176,4,417,-177,4,418,-178,4,419,-179,4,420,-180,4,421,-181,4,422,-182,4,423,-183,4,424,-4,2,425,-5,2,426,-66,4,427,-187,4,428,-188,4,429,-189,4,430,-190,4,431,-191,4,432,-192,4,433,-193,4,434,-194,4,435,-15,3,436,-196,4,437,-77,4,438,-198,4,439,-199,4,440,-20,3,441,-21,3,442,-22,3,443,-23,3,444,-180,4,445,-7,2,446,-206,4,447,-207,4,448,-208,4,449,-209,4,450,-210,4,451,-180,4,452,-188,4,453,-213,4,454,-190,4,455,-191,4,456,-216,4,457,-217,4,458,-218,4,459,-21,3,460,-220,4,461,-23,3,462,-198,4,463,-223,4,464,-224,4,465,-60,4,466,-226,4,467,-227,4,468,-228,4,469,-229,4,470,-230,4,471,-231,4,472,-232,4,473,-5,2,474,-234,4,475,-235,4,476,-236,4,477,-237,4,478,-238,4,479,-239,4,480,-240,4,481,-240,4,482,-240,4,483,-240,4,484,-4,2,485,-5,2,486,-66,4,487,-7,2,488,-240,4,489,-240,4,490,-240,4,491,-240,4,492,-240,4,493,-241,4,494,-242,4,495,-15,3,496,-240,4,497,-7,2,498,-60,4,499,-19,3,500,-20,3,501,-21,3,502,-22,3,503,-23,3,504,-240,4,505,-241,4,506,-242,4,507,-27,3,508,-4,2,509,-5,2,510,-30,3,511,-7,2,512,-8,2,513,-33,3,514,-250,4,515,-251,4,516,-240,4,517,-240,4,518,-2,1,519,-240,4,520,-240,4,521,-33,3,522,-102,4,523,-33,3,524,-240,4,525,-240,4,526,-240,4,527,-240,4,528,-240,4,529,-241,4,530,-240,4,531,-243,4,532,-8,2,533,-5,2,534,-114,4,535,-55,4,536,-8,2,537,-249,4,538,-58,4,539,-59,4,540,3,9,541,-1,0,542,-2,1,543,-3,1,544,-4,2,545,-65,4,546,-66,4,547,-67,4,548,-68,4,549,-69,4,550,-70,4,551,-71,4,552,-72,4,553,-66,4,554,-74,4,555,-75,4,556,-76,4,557,-77,4,558,-78,4,559,-55,4,560,-80,4,561,-21,3,562,-82,4,563,-83,4,564,-60,4,565,-85,4,566,-86,4,567,-87,4,568,-88,4,569,-89,4,570,-66,4,571,-91,4,572,-92,4,573,-93,4,574,-70,4,575,-71,4,576,-96,4,577,-96,4,578,-98,4,579,-99,4,580,-100,4,581,-77,4,582,-102,4,583,-103,4,584,-104,4,585,-105,4,586,-106,4,587,-107,4,588,-108,4,589,-108,4,590,-110,4,591,-108,4,592,-112,4,593,-113,4,594,-114,4,595,-115,4,596,-116,4,597,-108,4,598,-118,4,599,-119,4,600,-120,4,601,-121,4,602,-120,4,603,-120,4,604,-124,4,605,-125,4,606,-126,4,607,-120,4,608,-120,4,609,-120,4,610,-120,4,611,-131,4,612,-132,4,613,-126,4,614,-126,4,615,-126,4,616,-126,4,617,-137,4,618,-180,4,619,-115,4,620,-132,4,621,-132,4,622,-132,4,623,-132,4,624,-144,4,625,-145,4,626,-146,4,627,-21,3,628,-180,4,629,-180,4,630,-126,4,631,-151,4,632,-152,4,633,-153,4,634,-154,4,635,-155,4,636,-156,4,637,-157,4,638,-158,4,639,-159,4,640,-180,4,641,-137,4,642,-162,4,643,-163,4,644,-164,4,645,-165,4,646,-166,4,647,-23,3,648,-168,4,649,-169,4,650,-170,4,651,-180,4,652,-7,2,653,-165,4,654,-66,4,655,-115,4,656,-66,4,657,-177,4,658,-70,4,659,-71,4,660,-180,4,661,-181,4,662,-180,4,663,-183,4,664,-4,2,665,-5,2,666,-66,4,667,-7,2,668,-180,4,669,-180,4,670,-180,4,671,-191,4,672,-192,4,673,-193,4,674,-192,4,675,-15,3,676,-76,4,677,-77,4,678,-198,4,679,-19,3,680,-20,3,681,-21,3,682,-22,3,683,-23,3,684,-180,4,685,-7,2,686,-8,2,687,-198,4,688,-198,4,689,-198,4,690,-198,4,691,-7,2,692,-8,2,693,-33,3,694,-190,4,695,-191,4,696,-180,4,697,-181,4,698,-2,1,699,-21,3,700,-220,4,701,-23,3,702,-198,4,703,-108,4,704,-180,4,705,-165,4,706,-190,4,707,-191,4,708,-180,4,709,-181,4,710,-180,4,711,-220,4,712,-220,4,713,-5,2,714,-198,4,715,-55,4,716,-8,2,717,-57,4,718,-58,4,719,-59,4,720,3,9,721,-1,0,722,-2,1,723,-3,1,724,-4,2,725,-5,2,726,-6,2,727,-7,2,728,-8,2,729,-9,2,730,-10,2,731,-11,2,732,-12,2,733,-12,2,734,-2,1,735,-15,3,736,-8,2,737,-7,2,738,-8,2,739,-19,3,740,-20,3,741,-21,3,742,-22,3,743,-23,3,744,-24,3,745,-24,3,746,-24,3,747,-27,3,748,-5,2,749,-21,3,750,-30,3,751,-31,3,752,-32,3,753,-33,3,754,-34,3,755,-35,3,756,-36,3,757,-36,3,758,-2,1,759,-36,3,760,-40,3,761,-33,3,762,-33,3,763,-33,3,764,-44,3,765,-45,3,766,-36,3,767,-36,3,768,-48,3,769,-48,3,770,-50,4,771,-48,3,772,-8,2,773,-5,2,774,-54,4,775,-55,4,776,-56,4,777,-57,4,778,-58,4,779,-59,4,780,-60,4,781,-60,4,782,-60,4,783,-60,4,784,-60,4,785,-65,4,786,-66,4,787,-67,4,788,-68,4,789,-69,4,790,-70,4,791,-71,4,792,-72,4,793,-66,4,794,-74,4,795,-75,4,796,-76,4,797,-77,4,798,-78,4,799,-79,4,800,-80,4,801,-81,4,802,-82,4,803,-83,4,804,-84,4,805,-85,4,806,-86,4,807,-66,4,808,-88,4,809,-89,4,810,-90,4,811,-91,4,812,-92,4,813,-93,4,814,-94,4,815,-95,4,816,-96,4,817,-96,4,818,-98,4,819,-99,4,820,-100,4,821,-101,4,822,-102,4,823,-103,4,824,-104,4,825,-105,4,826,-106,4,827,-107,4,828,-108,4,829,-108,4,830,-110,4,831,-108,4,832,-112,4,833,-113,4,834,-114,4,835,-115,4,836,-116,4,837,-108,4,838,-118,4,839,-119,4,840,-120,4,841,-121,4,842,-120,4,843,-120,4,844,-124,4,845,-125,4,846,-126,4,847,-120,4,848,-120,4,849,-120,4,850,-130,4,851,-131,4,852,-132,4,853,-126,4,854,-126,4,855,-126,4,856,-126,4,857,-137,4,858,-138,4,859,-7,2,860,-132,4,861,-21,3,862,-132,4,863,-143,4,864,-144,4,865,-145,4,866,-146,4,867,-21,3,868,-22,3,869,-23,3,870,-24,3,871,-151,4,872,-152,4,873,-120,4,874,-154,4,875,-155,4,876,-156,4,877,-157,4,878,-158,4,879,-126,4,880,-160,4,881,-161,4,882,-162,4,883,-163,4,884,-164,4,885,-165,4,886,-66,4,887,-23,3,888,-60,4,889,-66,4,890,-66,4,891,-66,4,892,-7,2,893,-8,2,894,-66,4,895,-60,4,896,-66,4,897,-177,4,898,-70,4,899,-71,4,900,-180,4,901,-181,4,902,-2,1,903,-183,4,904,-4,2,905,-5,2,906,-66,4,907,-7,2,908,-8,2,909,-9,2,910,-190,4,911,-191,4,912,-192,4,913,-193,4,914,-2,1,915,-15,3,916,-76,4,917,-77,4,918,-198,4,919,-19,3,920,-20,3,921,-21,3,922,-22,3,923,-23,3,924,-24,3,925,-7,2,926,-8,2,927,-9,2,928,-198,4,929,-209,4,930,-210,4,931,-31,3,932,-32,3,933,-33,3,934,-34,3,935,-35,3,936,-36,3,937,-36,3,938,-2,1,939,-21,3,940,-220,4,941,-23,3,942,-24,3,943,-108,4,944,-180,4,945,-60,4,946,-36,3,947,-36,3,948,-228,4,949,-229,4,950,-230,4,951,-33,3,952,-232,4,953,-5,2,954,-36,3,955,-55,4,956,-56,4,957,-57,4,958,-58,4,959,-59,4,960,-240,4,961,-241,4,962,-2,1,963,-243,5,964,-4,2,965,-5,2,966,-66,4,967,-247,5,968,-248,5,969,-249,5,970,-250,5,971,-251,5,972,-252,5,973,-253,5,974,-254,5,975,-15,3,976,-76,4,977,-77,4,978,-60,4,979,-259,5,980,-260,5,981,-261,5,982,-262,5,983,-263,5,984,-264,5,985,-265,5,986,-266,5,987,-267,5,988,-268,5,989,-269,5,990,-270,5,991,-271,5,992,-272,5,993,-273,5,994,-274,5,995,-275,5,996,-276,5,997,-277,5,998,-278,5,999,-279,5,1000,-280,5,1001,-281,5,1002,-102,4,1003,-283,5,1004,-284,5,1005,-285,5,1006,-286,5,1007,-287,5,1008,-288,5,1009,-289,5,1010,-290,5,1011,-291,5,1012,-292,5,1013,-293,5,1014,-114,4,1015,-295,5,1016,-296,5,1017,-297,5,1018,-298,5,1019,-299,5,1020,-60,4,1021,-301,5,1022,-302,5,1023,-303,5,1024,-60,4,1025,-305,5,1026,-306,5,1027,-307,5,1028,-308,5,1029,-309,5,1030,-310,5,1031,-311,5,1032,-312,5,1033,-313,5,1034,-314,5,1035,-315,5,1036,-316,5,1037,-317,5,1038,-318,5,1039,-319,5,1040,-320,5,1041,-321,5,1042,-322,5,1043,-323,5,1044,-264,5,1045,-325,5,1046,-326,5,1047,-327,5,1048,-328,5,1049,-329,5,1050,-330,5,1051,-331,5,1052,-332,5,1053,-333,5,1054,-334,5,1055,-335,5,1056,-336,5,1057,-337,5,1058,-338,5,1059,-339,5,1060,-340,5,1061,-341,5,1062,-342,5,1063,-343,5,1064,-344,5,1065,-345,5,1066,-346,5,1067,-347,5,1068,-348,5,1069,-349,5,1070,-350,5,1071,-351,5,1072,-352,5,1073,-353,5,1074,-354,5,1075,-355,5,1076,-356,5,1077,-357,5,1078,-358,5,1079,-359,5,1080,-360,5,1081,-361,5,1082,-362,5,1083,-363,5,1084,-364,5,1085,-365,5,1086,-366,5,1087,-367,5,1088,-368,5,1089,-369,5,1090,-370,5,1091,-371,5,1092,-372,5,1093,-373,5,1094,-374,5,1095,-375,5,1096,-376,5,1097,-377,5,1098,-378,5,1099,-379,5,1100,-380,5,1101,-381,5,1102,-382,5,1103,-383,5,1104,-384,5,1105,-385,5,1106,-386,5,1107,-387,5,1108,-388,5,1109,-389,5,1110,-390,5,1111,-391,5,1112,-392,5,1113,-393,5,1114,-394,5,1115,-395,5,1116,-396,5,1117,-397,5,1118,-398,5,1119,-399,5,1120,-400,5,1121,-401,5,1122,-402,5,1123,-403,5,1124,-404,5,1125,-405,5,1126,-406,5,1127,-407,5,1128,-408,5,1129,-409,5,1130,-410,5,1131,-411,5,1132,-412,5,1133,-413,5,1134,-414,5,1135,-415,5,1136,-416,5,1137,-417,5,1138,-418,5,1139,-419,5,1140,-420,5,1141,-421,5,1142,-422,5,1143,-423,5,1144,-4,2,1145,-425,5,1146,-360,5,1147,-427,5,1148,-428,5,1149,-429,5,1150,-430,5,1151,-431,5,1152,-432,5,1153,-433,5,1154,-434,5,1155,-15,3,1156,-436,5,1157,-437,5,1158,-438,5,1159,-439,5,1160,-440,5,1161,-441,5,1162,-442,5,1163,-443,5,1164,-444,5,1165,-445,5,1166,-446,5,1167,-447,5,1168,-448,5,1169,-449,5,1170,-450,5,1171,-451,5,1172,-452,5,1173,-453,5,1174,-454,5,1175,-455,5,1176,-456,5,1177,-457,5,1178,-458,5,1179,-459,5,1180,-460,5,1181,-461,5,1182,-462,5,1183,-463,5,1184,-464,5,1185,-60,4,1186,-466,5,1187,-467,5,1188,-468,5,1189,-469,5,1190,-470,5,1191,-471,5,1192,-472,5,1193,-473,5,1194,-474,5,1195,-475,5,1196,-476,5,1197,-477,5,1198,-478,5,1199,-59,4,1200,-480,5,1201,-481,5,1202,-482,5,1203,-483,5,1204,-4,2,1205,-485,5,1206,-66,4,1207,-487,5,1208,-488,5,1209,-489,5,1210,-490,5,1211,-491,5,1212,-492,5,1213,-493,5,1214,-494,5,1215,-15,3,1216,-496,5,1217,-497,5,1218,-60,4,1219,-480,5,1220,-500,5,1221,-501,5,1222,-502,5,1223,-503,5,1224,-504,5,1225,-505,5,1226,-506,5,1227,-507,5,1228,-4,2,1229,-509,5,1230,-510,5,1231,-511,5,1232,-512,5,1233,-513,5,1234,-514,5,1235,-515,5,1236,-516,5,1237,-517,5,1238,-518,5,1239,-519,5,1240,-520,5,1241,-521,5,1242,-522,5,1243,-523,5,1244,-524,5,1245,-525,5,1246,-526,5,1247,-527,5,1248,-528,5,1249,-529,5,1250,-530,5,1251,-531,5,1252,-532,5,1253,-533,5,1254,-534,5,1255,-55,4,1256,-536,5,1257,-537,5,1258,-58,4,1259,-59,4,1260,-540,5,1261,-541,5,1262,-542,5,1263,-543,5,1264,-4,2,1265,-65,4,1266,-66,4,1267,-67,4,1268,-68,4,1269,-69,4,1270,-70,4,1271,-71,4,1272,-72,4,1273,-66,4,1274,-74,4,1275,-75,4,1276,-76,4,1277,-77,4,1278,-78,4,1279,-55,4,1280,-80,4,1281,-561,5,1282,-480,5,1283,-480,5,1284,-60,4,1285,-77,4,1286,-480,5,1287,-66,4,1288,-66,4,1289,-480,5,1290,-66,4,1291,-571,5,1292,-572,5,1293,-573,5,1294,-70,4,1295,-71,4,1296,-576,5,1297,-577,5,1298,-578,5,1299,-579,5,1300,-580,5,1301,-77,4,1302,-582,5,1303,-583,5,1304,-584,5,1305,-585,5,1306,-586,5,1307,-587,5,1308,-588,5,1309,-589,5,1310,-590,5,1311,-591,5,1312,-592,5,1313,-593,5,1314,-594,5,1315,-595,5,1316,-596,5,1317,-597,5,1318,-598,5,1319,-599,5,1320,-600,5,1321,-601,5,1322,-602,5,1323,-603,5,1324,-604,5,1325,-605,5,1326,-606,5,1327,-607,5,1328,-608,5,1329,-609,5,1330,-610,5,1331,-611,5,1332,-612,5,1333,-613,5,1334,-614,5,1335,-615,5,1336,-616,5,1337,-617,5,1338,-618,5,1339,-619,5,1340,-620,5,1341,-621,5,1342,-622,5,1343,-623,5,1344,-624,5,1345,-625,5,1346,-626,5,1347,-21,3,1348,-628,5,1349,-629,5,1350,-630,5,1351,-631,5,1352,-632,5,1353,-633,5,1354,-634,5,1355,-635,5,1356,-636,5,1357,-637,5,1358,-638,5,1359,-639,5,1360,-640,5,1361,-641,5,1362,-642,5,1363,-643,5,1364,-644,5,1365,-645,5,1366,-646,5,1367,-647,5,1368,-648,5,1369,-66,4,1370,-66,4,1371,-651,5,1372,-652,5,1373,-653,5,1374,-66,4,1375,-60,4,1376,-66,4,1377,-657,5,1378,-70,4,1379,-71,4,1380,-660,5,1381,-661,5,1382,-662,5,1383,-663,5,1384,-4,2,1385,-5,2,1386,-66,4,1387,-667,5,1388,-668,5,1389,-669,5,1390,-670,5,1391,-671,5,1392,-672,5,1393,-673,5,1394,-674,5,1395,-15,3,1396,-76,4,1397,-77,4,1398,-678,5,1399,-19,3,1400,-20,3,1401,-21,3,1402,-22,3,1403,-683,5,1404,-684,5,1405,-685,5,1406,-686,5,1407,-687,5,1408,-688,5,1409,-689,5,1410,-690,5,1411,-691,5,1412,-692,5,1413,-693,5,1414,-694,5,1415,-695,5,1416,-696,5,1417,-697,5,1418,-698,5,1419,-21,3,1420,-700,5,1421,-701,5,1422,-702,5,1423,-703,5,1424,-704,5,1425,-60,4,1426,-706,5,1427,-707,5,1428,-708,5,1429,-709,5,1430,-710,5,1431,-711,5,1432,-712,5,1433,-5,2,1434,-714,5,1435,-55,4,1436,-56,4,1437,-57,4,1438,-58,4,1439,-59,4,1440,-720,5,1441,-720,5,1442,-720,5,1443,-720,5,1444,-4,2,1445,-5,2,1446,-720,5,1447,-720,5,1448,-720,5,1449,-720,5,1450,-720,5,1451,-720,5,1452,-720,5,1453,-721,5,1454,-722,5,1455,-15,3,1456,-728,5,1457,-727,5,1458,-728,5,1459,-19,3,1460,-20,3,1461,-21,3,1462,-22,3,1463,-23,3,1464,-720,5,1465,-721,5,1466,-722,5,1467,-720,5,1468,-5,2,1469,-21,3,1470,-720,5,1471,-720,5,1472,-720,5,1473,-720,5,1474,-720,5,1475,-720,5,1476,-720,5,1477,-721,5,1478,-722,5,1479,-723,5,1480,-720,5,1481,-728,5,1482,-729,5,1483,-730,5,1484,-720,5,1485,-720,5,1486,-730,5,1487,-731,5,1488,-720,5,1489,-721,5,1490,-50,4,1491,-723,5,1492,-728,5,1493,-5,2,1494,-54,4,1495,-55,4,1496,-56,4,1497,-57,4,1498,-58,4,1499,-59,4,1500,-60,4,1501,-60,4,1502,-60,4,1503,-60,4,1504,-60,4,1505,-65,4,1506,-66,4,1507,-67,4,1508,-68,4,1509,-69,4,1510,-70,4,1511,-71,4,1512,-72,4,1513,-66,4,1514,-74,4,1515,-75,4,1516,-76,4,1517,-77,4,1518,-78,4,1519,-79,4,1520,-80,4,1521,-81,4,1522,-82,4,1523,-83,4,1524,-84,4,1525,-77,4,1526,-86,4,1527,-66,4,1528,-66,4,1529,-89,4,1530,-90,4,1531,-91,4,1532,-92,4,1533,-93,4,1534,-94,4,1535,-95,4,1536,-96,4,1537,-96,4,1538,-98,4,1539,-99,4,1540,-100,4,1541,-101,4,1542,-102,4,1543,-103,4,1544,-720,5,1545,-720,5,1546,-720,5,1547,-720,5,1548,-720,5,1549,-720,5,1550,-720,5,1551,-720,5,1552,-720,5,1553,-720,5,1554,-720,5,1555,-720,5,1556,-720,5,1557,-720,5,1558,-720,5,1559,-720,5,1560,-720,5,1561,-720,5,1562,-722,5,1563,-723,5,1564,-720,5,1565,-720,5,1566,-720,5,1567,-727,5,1568,-728,5,1569,-729,5,1570,-720,5,1571,-720,5,1572,-720,5,1573,-727,5,1574,-728,5,1575,-729,5,1576,-730,5,1577,-720,5,1578,-720,5,1579,-727,5,1580,-728,5,1581,-21,3,1582,-730,5,1583,-720,5,1584,-720,5,1585,-720,5,1586,-720,5,1587,-21,3,1588,-22,3,1589,-23,3,1590,-24,3,1591,-720,5,1592,-720,5,1593,-753,5,1594,-720,5,1595,-720,5,1596,-720,5,1597,-720,5,1598,-720,5,1599,-753,5,1600,-720,5,1601,-720,5,1602,-66,4,1603,-720,5,1604,-720,5,1605,-720,5,1606,-66,4,1607,-23,3,1608,-60,4,1609,-66,4,1610,-66,4,1611,-66,4,1612,-727,5,1613,-728,5,1614,-66,4,1615,-60,4,1616,-66,4,1617,-720,5,1618,-70,4,1619,-71,4,1620,-720,5,1621,-720,5,1622,-722,5,1623,-720,5,1624,-4,2,1625,-5,2,1626,-66,4,1627,-727,5,1628,-728,5,1629,-729,5,1630,-720,5,1631,-720,5,1632,-720,5,1633,-720,5,1634,-722,5,1635,-15,3,1636,-76,4,1637,-77,4,1638,-720,5,1639,-19,3,1640,-20,3,1641,-21,3,1642,-22,3,1643,-23,3,1644,-24,3,1645,-727,5,1646,-728,5,1647,-729,5,1648,-730,5,1649,-720,5,1650,-720,5,1651,-751,5,1652,-752,5,1653,-753,5,1654,-754,5,1655,-755,5,1656,-756,5,1657,-756,5,1658,-758,5,1659,-21,3,1660,-720,5,1661,-23,3,1662,-24,3,1663,-108,4,1664,-764,5,1665,-60,4,1666,-756,5,1667,-756,5,1668,-228,5,1669,-229,5,1670,-230,5,1671,-231,5,1672,-232,5,1673,-233,5,1674,-234,5,1675,-55,4,1676,-56,4,1677,-57,4,1678,-58,4,1679,-59,4,1680,-240,5,1681,-241,5,1682,-242,5,1683,-243,5,1684,-244,5,1685,-245,5,1686,-66,4,1687,-247,5,1688,-248,5,1689,-249,5,1690,-250,5,1691,-251,5,1692,-252,5,1693,-253,5,1694,-254,5,1695,-255,5,1696,-256,5,1697,-77,4,1698,-60,4,1699,-259,5,1700,-260,5,1701,-261,5,1702,-262,5,1703,-263,5,1704,-264,5,1705,-265,5,1706,-266,5,1707,-267,5,1708,-268,5,1709,-269,5,1710,-270,5,1711,-271,5,1712,-272,5,1713,-273,5,1714,-274,5,1715,-275,5,1716,-276,5,1717,-277,5,1718,-278,5,1719,-279,5,1720,-280,5,1721,-281,5,1722,-102,4,1723,-283,5,1724,-284,5,1725,-285,5,1726,-286,5,1727,-287,5,1728,-288,5,1729,-289,5,1730,-290,5,1731,-291,5,1732,-292,5,1733,-293,5,1734,-294,5,1735,-295,5,1736,-296,5,1737,-297,5,1738,-298,5,1739,-299,5,1740,-240,5,1741,-241,5,1742,-242,5,1743,-243,5,1744,-244,5,1745,-240,5,1746,-240,5,1747,-307,5,1748,-308,5,1749,-309,5,1750,-310,5,1751,-311,5,1752,-312,5,1753,-247,5,1754,-314,5,1755,-315,5,1756,-316,5,1757,-317,5,1758,-318,5,1759,-319,5,1760,-320,5,1761,-321,5,1762,-322,5,1763,-323,5,1764,-264,5,1765,-325,5,1766,-326,5,1767,-327,5,1768,-328,5,1769,-329,5,1770,-264,5,1771,-331,5,1772,-332,5,1773,-333,5,1774,-264,5,1775,-264,5,1776,-336,5,1777,-337,5,1778,-338,5,1779,-339,5,1780,-340,5,1781,-341,5,1782,-342,5,1783,-343,5,1784,-344,5,1785,-345,5,1786,-346,5,1787,-347,5,1788,-348,5,1789,-349,5,1790,-350,5,1791,-351,5,1792,-352,5,1793,-353,5,1794,-354,5,1795,-355,5,1796,-356,5,1797,-357,5,1798,-358,5,1799,-359,5,1800,-360,5,1801,-361,5,1802,-362,5,1803,-363,5,1804,-364,5,1805,-365,5,1806,-366,5,1807,-367,5,1808,-368,5,1809,-369,5,1810,-370,5,1811,-371,5,1812,-372,5,1813,-373,5,1814,-374,5,1815,-375,5,1816,-376,5,1817,-377,5,1818,-378,5,1819,-379,5,1820,-380,5,1821,-381,5,1822,-382,5,1823,-383,5,1824,-384,5,1825,-385,5,1826,-386,5,1827,-387,5,1828,-388,5,1829,-389,5,1830,-390,5,1831,-391,5,1832,-392,5,1833,-393,5,1834,-394,5,1835,-395,5,1836,-396,5,1837,-397,5,1838,-398,5,1839,-399,5,1840,-400,5,1841,-401,5,1842,-402,5,1843,-403,5,1844,-404,5,1845,-405,5,1846,-406,5,1847,-407,5,1848,-408,5,1849,-409,5,1850,-410,5,1851,-411,5,1852,-412,5,1853,-413,5,1854,-414,5,1855,-415,5,1856,-416,5,1857,-417,5,1858,-418,5,1859,-419,5,1860,-420,5,1861,-421,5,1862,-422,5,1863,-423,5,1864,-4,2,1865,-5,2,1866,-66,4,1867,-427,5,1868,-428,5,1869,-429,5,1870,-430,5,1871,-431,5,1872,-432,5,1873,-433,5,1874,-434,5,1875,-15,3,1876,-436,5,1877,-360,5,1878,-438,5,1879,-439,5,1880,-20,3,1881,-420,5,1882,-442,5,1883,-443,5,1884,-444,5,1885,-445,5,1886,-446,5,1887,-447,5,1888,-448,5,1889,-449,5,1890,-450,5,1891,-451,5,1892,-452,5,1893,-453,5,1894,-454,5,1895,-455,5,1896,-456,5,1897,-457,5,1898,-458,5,1899,-21,3,1900,-460,5,1901,-461,5,1902,-462,5,1903,-463,5,1904,-464,5,1905,-60,4,1906,-466,5,1907,-467,5,1908,-468,5,1909,-469,5,1910,-470,5,1911,-471,5,1912,-472,5,1913,-5,2,1914,-474,5,1915,-55,4,1916,-476,5,1917,-477,5,1918,-58,4,1919,-59,4,1920,-480,5,1921,-481,5,1922,-482,5,1923,-483,5,1924,-4,2,1925,-5,2,1926,-66,4,1927,-487,5,1928,-488,5,1929,-489,5,1930,-490,5,1931,-491,5,1932,-492,5,1933,-493,5,1934,-494,5,1935,-15,3,1936,-496,5,1937,-497,5,1938,-60,4,1939,-19,3,1940,-20,3,1941,-21,3,1942,-22,3,1943,-480,5,1944,-504,5,1945,-505,5,1946,-506,5,1947,-507,5,1948,-4,2,1949,-5,2,1950,-510,5,1951,-511,5,1952,-512,5,1953,-513,5,1954,-514,5,1955,-515,5,1956,-516,5,1957,-517,5,1958,-518,5,1959,-519,5,1960,-520,5,1961,-521,5,1962,-420,5,1963,-523,5,1964,-524,5,1965,-525,5,1966,-526,5,1967,-527,5,1968,-528,5,1969,-529,5,1970,-530,5,1971,-531,5,1972,-532,5,1973,-5,2,1974,-534,5,1975,-55,4,1976,-56,4,1977,-57,4,1978,-58,4,1979,-59,4,1980,-60,4,1981,-60,4,1982,-60,4,1983,-60,4,1984,-60,4,1985,-65,4,1986,-66,4,1987,-67,4,1988,-68,4,1989,-69,4,1990,-70,4,1991,-71,4,1992,-72,4,1993,-66,4,1994,-74,4,1995,-75,4,1996,-76,4,1997,-77,4,1998,-78,4,1999,-55,4,2000,-80,4,2001,-81,4,2002,-82,4,2003,-83,4,2004,-60,4,2005,-77,4,2006,-86,4,2007,-66,4,2008,-66,4,2009,-89,4,2010,-66,4,2011,-91,4,2012,-92,4,2013,-93,4,2014,-70,4,2015,-71,4,2016,-96,4,2017,-96,4,2018,-480,5,2019,-480,5,2020,-480,5,2021,-77,4,2022,-480,5,2023,-480,5,2024,-480,5,2025,-480,5,2026,-480,5,2027,-480,5,2028,-480,5,2029,-481,5,2030,-480,5,2031,-483,5,2032,-480,5,2033,-480,5,2034,-480,5,2035,-480,5,2036,-480,5,2037,-489,5,2038,-480,5,2039,-480,5,2040,-480,5,2041,-480,5,2042,-482,5,2043,-483,5,2044,-480,5,2045,-480,5,2046,-480,5,2047,-487,5,0,0,0"),
// leafSize 13
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,12,14,13,13,15,14,-1,1,15,-2,1,16,-3,1,17,-4,1,18,-5,2,19,-8,2,20,-10,2,21,-8,2,22,-11,2,23,-10,2,24,-11,2,25,-12,2,26,-13,2,27,3,4,28,-13,2,29,-13,2,30,3,5,31,-5,2,32,-8,2,33,3,5,34,-8,2,35,-11,2,36,3,5,37,-11,2,38,-12,2,39,3,5,40,4,7,41,-2,1,42,-3,1,43,-4,2,44,4,8,45,-6,2,46,-7,2,47,-8,2,48,4,8,49,-10,2,50,-11,2,51,-12,2,52,4,8,53,-1,1,54,-2,1,55,5,11,56,-4,2,57,-5,2,58,-6,2,59,-7,2,60,5,11,61,-9,2,62,-10,2,63,-11,2,64,-12,2,65,5,11,66,6,13,67,-2,1,68,-3,1,69,-4,2,70,-5,2,71,-6,2,72,6,14,73,-8,2,74,-9,2,75,-10,2,76,-11,2,77,-12,2,78,6,14,79,-1,1,80,-2,1,81,-3,1,82,-4,2,83,-5,2,84,-6,2,85,-7,2,86,-8,2,87,-9,2,88,-10,2,89,-11,2,90,-12,2,91,-13,2,92,-1,1,93,-2,1,94,-16,3,95,-17,3,96,-8,2,97,-8,2,98,-10,2,99,-21,3,100,-22,3,101,-23,3,102,-24,3,103,-25,3,104,-26,3,105,-40,3,106,-28,3,107,-52,3,108,-30,3,109,-44,3,110,-32,3,111,-33,3,112,-52,3,113,-48,3,114,-36,3,115,-37,3,116,-38,3,117,-39,3,118,-40,3,119,-41,3,120,-55,3,121,-4,2,122,-44,3,123,-6,2,124,-52,3,125,-60,3,126,-48,3,127,-49,3,128,-50,3,129,-51,3,130,-52,3,131,-65,3,132,-60,3,133,-55,3,134,-4,2,135,-5,2,136,-6,2,137,-65,3,138,-60,3,139,-52,3,140,-62,3,141,-63,3,142,-64,3,143,-65,3,144,-66,3,145,-2,1,146,-3,1,147,-4,2,148,-5,2,149,-6,2,150,-72,3,151,-8,2,152,-9,2,153,-10,2,154,-11,2,155,-12,2,156,-78,3,157,-1,0,158,-2,1,159,-3,1,160,-4,2,161,-5,2,162,-6,2,163,-7,2,164,-8,2,165,-9,2,166,-10,2,167,-11,2,168,-12,2,169,-13,2,170,-13,2,171,-2,1,172,-16,3,173,-17,3,174,-8,2,175,-8,2,176,-20,3,177,-21,3,178,-22,3,179,-23,3,180,-24,3,181,-25,3,182,-26,3,183,-40,3,184,-26,3,185,-52,3,186,-30,3,187,-44,3,188,-24,3,189,-33,3,190,-52,3,191,-48,3,192,-36,3,193,-37,3,194,-38,3,195,3,7,196,-1,0,197,-2,1,198,-3,1,199,-4,2,200,-5,2,201,-6,2,202,-7,2,203,-8,2,204,-9,2,205,-10,2,206,-11,2,207,-12,2,208,-52,3,209,-78,4,210,-78,4,211,-78,4,212,-4,2,213,-5,2,214,-8,2,215,-78,4,216,-78,4,217,-22,3,218,-23,3,219,-24,3,220,-25,3,221,-78,4,222,-78,4,223,-78,4,224,-78,4,225,-78,4,226,-78,4,227,-78,4,228,-78,4,229,-78,4,230,-87,4,231,-88,4,232,-89,4,233,-90,4,234,3,8,235,-1,0,236,-2,1,237,-3,1,238,-4,2,239,-5,2,240,-6,2,241,-7,2,242,-8,2,243,-9,2,244,-10,2,245,-11,2,246,-12,2,247,-13,2,248,-13,2,249,-2,1,250,-16,3,251,-17,3,252,-8,2,253,-8,2,254,-20,3,255,-21,3,256,-22,3,257,-23,3,258,-24,3,259,-25,3,260,4,11,261,-1,0,262,-2,1,263,-3,1,264,-4,2,265,-5,2,266,-6,2,267,-7,2,268,-8,2,269,-9,2,270,-10,2,271,-11,2,272,-12,2,273,-39,3,274,-40,3,275,-2,1,276,-39,3,277,-4,2,278,-44,3,279,-8,2,280,-7,2,281,-21,3,282,-48,3,283,-23,3,284,-24,3,285,-25,3,286,-52,3,287,-52,3,288,-2,1,289,-55,3,290,-4,2,291,-5,2,292,-6,2,293,-7,2,294,-60,4,295,-9,2,296,-10,2,297,-63,4,298,-64,4,299,-65,4,300,-66,4,301,-65,4,302,-65,4,303,-65,4,304,-65,4,305,-65,4,306,-72,4,307,-73,4,308,-74,4,309,-75,4,310,-76,4,311,-77,4,312,4,12,313,-1,0,314,-2,1,315,-3,1,316,-4,2,317,-5,2,318,-6,2,319,-7,2,320,-8,2,321,-9,2,322,-10,2,323,-11,2,324,-12,2,325,-13,3,326,-13,3,327,-13,3,328,-16,3,329,-17,3,330,-8,2,331,-8,2,332,-20,3,333,-21,3,334,-22,3,335,-23,3,336,-24,3,337,-25,3,338,-26,3,339,-27,3,340,-26,3,341,-26,3,342,-30,3,343,-5,2,344,-24,3,345,-33,3,346,-26,3,347,-35,3,348,-36,3,349,-37,3,350,-38,3,351,-39,3,352,-40,3,353,-2,1,354,-39,3,355,-4,2,356,-44,3,357,-6,2,358,-7,2,359,-8,2,360,-48,3,361,-39,3,362,-39,3,363,-39,3,364,-52,3,365,-52,3,366,-2,1,367,-55,4,368,-4,2,369,-5,2,370,-6,2,371,-7,2,372,-60,4,373,-61,4,374,-62,4,375,-63,4,376,-64,4,377,-65,4,378,-66,4,379,-65,4,380,-65,4,381,-65,4,382,-65,4,383,-65,4,384,-72,4,385,-73,4,386,-74,4,387,-75,4,388,-76,4,389,-77,4,390,-78,4,391,-78,4,392,-78,4,393,-78,4,394,-78,4,395,-78,4,396,-78,4,397,-78,4,398,-78,4,399,-87,4,400,-88,4,401,-89,4,402,-90,4,403,-91,4,404,-91,4,405,-91,4,406,-16,3,407,-4,2,408,-91,4,409,-89,4,410,-78,4,411,-78,4,412,-78,4,413,-101,4,414,-102,4,415,-103,4,416,-104,4,417,-105,4,418,-104,4,419,-107,4,420,-108,4,421,-109,4,422,-110,4,423,-111,4,424,-112,4,425,-113,4,426,-114,4,427,-115,4,428,-116,4,429,-117,4,430,-118,4,431,-117,4,432,-120,4,433,-4,2,434,-122,4,435,-117,4,436,-124,4,437,-125,4,438,-126,4,439,-127,4,440,-128,4,441,-129,4,442,-130,4,443,-131,4,444,-132,4,445,-133,4,446,-4,2,447,-5,2,448,-130,4,449,-137,4,450,-138,4,451,-130,4,452,-130,4,453,-141,4,454,-142,4,455,-143,4,456,-144,4,457,-145,4,458,-146,4,459,-4,2,460,-5,2,461,-6,2,462,-150,4,463,-151,4,464,-152,4,465,-153,4,466,-154,4,467,-155,4,468,-156,4,469,-157,4,470,-158,4,471,-159,4,472,-4,2,473,-5,2,474,-6,2,475,-163,4,476,-164,4,477,-165,4,478,-166,4,479,-78,4,480,-78,4,481,-78,4,482,-78,4,483,-78,4,484,-16,3,485,-17,3,486,-78,4,487,-78,4,488,-20,3,489,-21,3,490,-22,3,491,-23,3,492,-24,3,493,-25,3,494,-234,4,495,-235,4,496,-236,4,497,-237,4,498,-4,2,499,-5,2,500,-6,2,501,-78,4,502,-234,4,503,-243,4,504,-244,4,505,-245,4,506,-246,4,507,-195,4,508,-196,4,509,-197,4,510,-198,4,511,-4,2,512,-5,2,513,-6,2,514,-7,2,515,-203,4,516,-204,4,517,-205,4,518,-206,4,519,-207,4,520,-78,4,521,-78,4,522,-78,4,523,-78,4,524,-4,2,525,-78,4,526,-78,4,527,-78,4,528,-78,4,529,-22,3,530,-88,4,531,-24,3,532,-25,3,533,-78,4,534,-78,4,535,-78,4,536,-78,4,537,-4,2,538,-78,4,539,-78,4,540,-78,4,541,-78,4,542,-87,4,543,-88,4,544,-89,4,545,-90,4,546,-234,4,547,-235,4,548,-2,1,549,-237,4,550,-4,2,551,-5,2,552,-6,2,553,-7,2,554,-8,2,555,-243,4,556,-244,4,557,-245,4,558,-246,4,559,-13,3,560,-13,3,561,-13,3,562,-16,3,563,-17,3,564,-8,2,565,-19,3,566,-20,3,567,-21,3,568,-22,3,569,-23,3,570,-24,3,571,-25,3,572,-260,4,573,-261,4,574,-2,1,575,-263,4,576,-4,2,577,-5,2,578,-6,2,579,-7,2,580,-8,2,581,-9,2,582,-270,4,583,-271,4,584,-272,4,585,-78,4,586,-234,4,587,-78,4,588,-78,4,589,-4,2,590,-278,4,591,-78,4,592,-78,4,593,-78,4,594,-282,4,595,-23,3,596,-24,3,597,-25,3,598,-286,4,599,-287,4,600,-2,1,601,-55,4,602,-4,2,603,-5,2,604,-6,2,605,-59,4,606,-60,4,607,-61,4,608,-62,4,609,-63,4,610,-64,4,611,-65,4,612,-66,4,613,-65,4,614,-65,4,615,-65,4,616,-65,4,617,-65,4,618,-72,4,619,-73,4,620,-74,4,621,-75,4,622,-76,4,623,-77,4,624,-312,4,625,-312,4,626,-2,1,627,-312,4,628,-4,2,629,-5,2,630,-6,2,631,-7,2,632,-8,2,633,-9,2,634,-10,2,635,-312,4,636,-312,4,637,-13,3,638,-13,3,639,-13,3,640,-16,3,641,-17,3,642,-8,2,643,-19,3,644,-20,3,645,-21,3,646,-22,3,647,-23,3,648,-24,3,649,-25,3,650,-26,3,651,-27,3,652,-26,3,653,-26,3,654,-30,3,655,-5,2,656,-24,3,657,-33,3,658,-26,3,659,-35,3,660,-36,3,661,-37,3,662,-38,3,663,-39,3,664,-40,3,665,-2,1,666,-39,3,667,-4,2,668,-44,3,669,-6,2,670,-7,2,671,-8,2,672,-312,4,673,-39,3,674,-39,3,675,-39,3,676,-52,4,677,-52,4,678,-52,4,679,-55,4,680,-52,4,681,-52,4,682,-52,4,683,-59,4,684,-60,4,685,-61,4,686,-62,4,687,-63,4,688,-64,4,689,-65,4,690,-66,4,691,-65,4,692,-65,4,693,-65,4,694,-65,4,695,-65,4,696,-72,4,697,-73,4,698,-74,4,699,-75,4,700,-76,4,701,-77,4,702,-78,4,703,-78,4,704,-78,4,705,-78,4,706,-4,2,707,-78,4,708,-78,4,709,-78,4,710,-78,4,711,-87,4,712,-88,4,713,-89,4,714,-90,4,715,-91,4,716,-91,4,717,-91,4,718,-16,3,719,-4,2,720,-5,2,721,-89,4,722,-78,4,723,-78,4,724,-78,4,725,-78,4,726,-78,4,727,-103,4,728,-104,4,729,-105,4,730,-104,4,731,-107,4,732,-108,4,733,-109,4,734,-110,4,735,-111,4,736,-112,4,737,-113,4,738,-114,4,739,-115,4,740,-116,4,741,-117,4,742,-118,4,743,-117,4,744,-120,4,745,-4,2,746,-122,4,747,-6,2,748,-124,4,749,-125,4,750,-126,4,751,-127,4,752,-128,4,753,-129,4,754,-130,4,755,-131,4,756,-132,4,757,-133,4,758,-4,2,759,-5,2,760,-6,2,761,-137,4,762,-138,4,763,-130,4,764,-130,4,765,-141,4,766,-142,4,767,-143,4,768,-144,4,769,-145,4,770,-146,4,771,-4,2,772,-5,2,773,-6,2,774,-72,4,775,-151,4,776,-152,4,777,-153,4,778,-76,4,779,-77,4,780,-78,4,781,-78,4,782,-78,4,783,-78,4,784,-4,2,785,-78,4,786,-78,4,787,-78,4,788,-78,4,789,-78,4,790,-78,4,791,-78,4,792,-78,4,793,-78,4,794,-78,4,795,-78,4,796,-16,3,797,-4,2,798,-78,4,799,-78,4,800,-78,4,801,-78,4,802,-78,4,803,-78,4,804,-78,4,805,-78,4,806,-312,5,807,-312,5,808,-314,5,809,-315,5,810,-78,4,811,-317,5,812,-318,5,813,-78,4,814,-320,5,815,-78,4,816,-78,4,817,-323,5,818,-324,5,819,-312,5,820,-312,5,821,-314,5,822,-312,5,823,-316,5,824,-317,5,825,-318,5,826,-319,5,827,-320,5,828,-321,5,829,-322,5,830,-323,5,831,-324,5,832,-78,4,833,-78,4,834,-78,4,835,-78,4,836,-4,2,837,-78,4,838,-78,4,839,-78,4,840,-78,4,841,-334,5,842,-88,4,843,-89,4,844,-337,5,845,-78,4,846,-78,4,847,-78,4,848,-78,4,849,-4,2,850,-78,4,851,-78,4,852,-72,4,853,-78,4,854,-87,4,855,-88,4,856,-89,4,857,-90,4,858,-312,5,859,-313,5,860,-314,5,861,-315,5,862,-316,5,863,-317,5,864,-318,5,865,-319,5,866,-320,5,867,-321,5,868,-322,5,869,-323,5,870,-324,5,871,-312,5,872,-313,5,873,-314,5,874,-328,5,875,-329,5,876,-330,5,877,-331,5,878,-332,5,879,-333,5,880,-334,5,881,-335,5,882,-336,5,883,-337,5,884,-312,5,885,-313,5,886,-314,5,887,-315,5,888,-316,5,889,-317,5,890,-318,5,891,-319,5,892,-320,5,893,-321,5,894,-322,5,895,-323,5,896,-324,5,897,-390,5,898,-352,5,899,-392,5,900,-390,5,901,-394,5,902,-356,5,903,-396,5,904,-397,5,905,-398,5,906,-360,5,907,-335,5,908,-336,5,909,-337,5,910,-364,5,911,-364,5,912,-366,5,913,-312,5,914,-368,5,915,-369,5,916,-370,5,917,-371,5,918,-312,5,919,-312,5,920,-374,5,921,-375,5,922,-376,5,923,-377,5,924,-378,5,925,-379,5,926,-380,5,927,-381,5,928,-382,5,929,-383,5,930,-384,5,931,-385,5,932,-386,5,933,-387,5,934,-388,5,935,-389,5,936,3,10,937,-1,0,938,-2,1,939,-3,1,940,-4,2,941,-5,2,942,-6,2,943,-7,2,944,-8,2,945,-9,2,946,-10,2,947,-11,2,948,-12,2,949,-13,3,950,-13,3,951,-13,3,952,-16,3,953,-17,3,954,-8,2,955,-19,3,956,-20,3,957,-21,3,958,-22,3,959,-23,3,960,-24,3,961,-25,3,962,-26,3,963,-27,3,964,-26,3,965,-26,3,966,-30,3,967,-5,2,968,-24,3,969,-33,3,970,-26,3,971,-35,3,972,-36,3,973,-37,3,974,-38,3,975,-39,3,976,-40,3,977,-2,1,978,-39,3,979,-4,2,980,-44,3,981,-6,2,982,-7,2,983,-8,2,984,-48,3,985,-39,3,986,-39,3,987,-51,4,988,-52,4,989,-52,4,990,-52,4,991,-55,4,992,-52,4,993,-52,4,994,-52,4,995,-59,4,996,-60,4,997,-61,4,998,-62,4,999,-63,4,1000,-64,4,1001,-65,4,1002,-66,4,1003,-65,4,1004,-65,4,1005,-65,4,1006,-65,4,1007,-65,4,1008,-72,4,1009,-73,4,1010,-74,4,1011,-75,4,1012,-76,4,1013,-77,4,1014,-78,4,1015,-78,4,1016,-78,4,1017,-78,4,1018,-4,2,1019,-78,4,1020,-78,4,1021,-78,4,1022,-78,4,1023,-87,4,1024,-88,4,1025,-89,4,1026,-90,4,1027,-91,4,1028,-91,4,1029,-91,4,1030,-16,3,1031,-4,2,1032,-5,2,1033,-89,4,1034,-78,4,1035,-78,4,1036,-78,4,1037,-78,4,1038,-78,4,1039,-78,4,1040,-104,4,1041,-105,4,1042,-104,4,1043,-107,4,1044,-108,4,1045,-109,4,1046,-110,4,1047,-111,4,1048,-112,4,1049,-113,4,1050,-114,4,1051,-115,4,1052,-116,4,1053,-117,4,1054,-118,4,1055,-117,4,1056,-120,4,1057,-4,2,1058,-122,4,1059,-6,2,1060,-124,4,1061,-125,4,1062,-126,4,1063,-127,4,1064,-128,4,1065,-129,4,1066,-130,4,1067,-131,4,1068,-132,4,1069,-133,4,1070,-4,2,1071,-5,2,1072,-6,2,1073,-137,4,1074,-138,4,1075,-130,4,1076,-130,4,1077,-141,4,1078,-142,4,1079,-143,4,1080,-144,4,1081,-145,4,1082,-146,4,1083,-4,2,1084,-5,2,1085,-6,2,1086,-72,4,1087,-143,4,1088,-74,4,1089,-75,4,1090,-76,4,1091,-77,4,1092,-78,4,1093,-78,4,1094,-78,4,1095,-78,4,1096,-4,2,1097,-78,4,1098,-78,4,1099,-78,4,1100,-78,4,1101,-78,4,1102,-78,4,1103,-78,4,1104,-78,4,1105,-78,4,1106,-78,4,1107,-78,4,1108,-16,3,1109,-4,2,1110,-78,4,1111,-78,4,1112,-78,4,1113,-78,4,1114,-78,4,1115,-78,4,1116,-78,4,1117,-78,4,1118,-78,4,1119,-78,4,1120,-78,4,1121,-78,4,1122,-78,4,1123,-78,4,1124,-78,4,1125,-78,4,1126,-78,4,1127,-78,4,1128,-78,4,1129,-78,4,1130,-78,4,1131,-195,4,1132,-196,4,1133,-2,1,1134,-198,4,1135,-4,2,1136,-5,2,1137,-6,2,1138,-7,2,1139,-8,2,1140,-9,2,1141,-10,2,1142,-206,4,1143,-207,4,1144,-78,4,1145,-78,4,1146,-78,4,1147,-78,4,1148,-4,2,1149,-78,4,1150,-78,4,1151,-78,4,1152,-78,4,1153,-87,4,1154,-88,4,1155,-89,4,1156,-90,4,1157,-78,4,1158,-78,4,1159,-78,4,1160,-78,4,1161,-4,2,1162,-78,4,1163,-78,4,1164,-72,4,1165,-78,4,1166,-74,4,1167,-75,4,1168,-76,4,1169,-77,4,1170,-234,5,1171,-235,5,1172,-236,5,1173,-237,5,1174,-238,5,1175,-239,5,1176,-240,5,1177,-241,5,1178,-242,5,1179,-243,5,1180,-244,5,1181,-245,5,1182,-246,5,1183,-247,5,1184,-248,5,1185,-249,5,1186,-250,5,1187,-251,5,1188,-252,5,1189,-253,5,1190,-254,5,1191,-255,5,1192,-256,5,1193,-257,5,1194,-258,5,1195,-259,5,1196,-260,5,1197,-261,5,1198,-262,5,1199,-263,5,1200,-264,5,1201,-265,5,1202,-266,5,1203,-267,5,1204,-268,5,1205,-269,5,1206,-270,5,1207,-271,5,1208,-272,5,1209,-78,4,1210,-274,5,1211,-78,4,1212,-78,4,1213,-4,2,1214,-278,5,1215,-279,5,1216,-78,4,1217,-281,5,1218,-282,5,1219,-283,5,1220,-284,5,1221,-285,5,1222,-286,5,1223,-287,5,1224,-288,5,1225,-289,5,1226,-290,5,1227,-291,5,1228,-292,5,1229,-293,5,1230,-294,5,1231,-295,5,1232,-296,5,1233,-297,5,1234,-298,5,1235,-299,5,1236,-300,5,1237,-301,5,1238,-302,5,1239,-303,5,1240,-304,5,1241,-305,5,1242,-306,5,1243,-307,5,1244,-308,5,1245,-309,5,1246,-310,5,1247,-311,5,1248,4,15,1249,-1,0,1250,-2,1,1251,-3,1,1252,-4,2,1253,-5,2,1254,-6,2,1255,-7,2,1256,-8,2,1257,-9,2,1258,-10,2,1259,-11,2,1260,-12,2,1261,-13,3,1262,-13,3,1263,-13,3,1264,-16,3,1265,-17,3,1266,-13,3,1267,-19,3,1268,-20,3,1269,-21,3,1270,-22,3,1271,-23,3,1272,-24,3,1273,-25,3,1274,-26,3,1275,-27,3,1276,-26,3,1277,-26,3,1278,-30,3,1279,-5,2,1280,-24,3,1281,-33,3,1282,-26,3,1283,-35,3,1284,-36,3,1285,-37,3,1286,-38,3,1287,-39,3,1288,-40,3,1289,-2,1,1290,-39,3,1291,-4,2,1292,-44,3,1293,-6,2,1294,-7,2,1295,-8,2,1296,-48,3,1297,-39,3,1298,-39,3,1299,-51,4,1300,-52,4,1301,-52,4,1302,-52,4,1303,-55,4,1304,-52,4,1305,-52,4,1306,-52,4,1307,-59,4,1308,-60,4,1309,-61,4,1310,-62,4,1311,-63,4,1312,-64,4,1313,-65,4,1314,-66,4,1315,-65,4,1316,-65,4,1317,-65,4,1318,-65,4,1319,-65,4,1320,-72,4,1321,-73,4,1322,-74,4,1323,-75,4,1324,-76,4,1325,-77,4,1326,-78,4,1327,-78,4,1328,-78,4,1329,-78,4,1330,-4,2,1331,-78,4,1332,-78,4,1333,-78,4,1334,-78,4,1335,-87,4,1336,-88,4,1337,-89,4,1338,-90,4,1339,-91,4,1340,-91,4,1341,-91,4,1342,-16,3,1343,-17,3,1344,-5,2,1345,-89,4,1346,-78,4,1347,-78,4,1348,-78,4,1349,-78,4,1350,-78,4,1351,-78,4,1352,-104,4,1353,-105,4,1354,-104,4,1355,-107,4,1356,-108,4,1357,-109,4,1358,-110,4,1359,-111,4,1360,-112,4,1361,-113,4,1362,-114,4,1363,-115,4,1364,-116,4,1365,-117,4,1366,-118,4,1367,-117,4,1368,-120,4,1369,-4,2,1370,-122,4,1371,-6,2,1372,-124,4,1373,-125,4,1374,-126,4,1375,-127,4,1376,-128,4,1377,-129,4,1378,-130,4,1379,-131,4,1380,-132,4,1381,-133,4,1382,-4,2,1383,-5,2,1384,-6,2,1385,-137,4,1386,-138,4,1387,-130,4,1388,-130,4,1389,-141,4,1390,-142,4,1391,-143,4,1392,-144,4,1393,-2,1,1394,-146,4,1395,-4,2,1396,-5,2,1397,-6,2,1398,-72,4,1399,-73,4,1400,-74,4,1401,-75,4,1402,-76,4,1403,-77,4,1404,-78,4,1405,-78,4,1406,-78,4,1407,-78,4,1408,-4,2,1409,-78,4,1410,-78,4,1411,-78,4,1412,-78,4,1413,-78,4,1414,-78,4,1415,-78,4,1416,-78,4,1417,-78,4,1418,-78,4,1419,-78,4,1420,-16,3,1421,-17,3,1422,-78,4,1423,-78,4,1424,-78,4,1425,-78,4,1426,-78,4,1427,-78,4,1428,-78,4,1429,-78,4,1430,-78,4,1431,-78,4,1432,-78,4,1433,-78,4,1434,-78,4,1435,-78,4,1436,-78,4,1437,-78,4,1438,-78,4,1439,-78,4,1440,-78,4,1441,-78,4,1442,-78,4,1443,-195,4,1444,-196,4,1445,-2,1,1446,-198,4,1447,-4,2,1448,-5,2,1449,-6,2,1450,-7,2,1451,-8,2,1452,-9,2,1453,-10,2,1454,-195,4,1455,-207,4,1456,-78,4,1457,-78,4,1458,-78,4,1459,-78,4,1460,-4,2,1461,-78,4,1462,-78,4,1463,-78,4,1464,-78,4,1465,-87,4,1466,-88,4,1467,-89,4,1468,-90,4,1469,-78,4,1470,-78,4,1471,-78,4,1472,-78,4,1473,-4,2,1474,-78,4,1475,-78,4,1476,-72,4,1477,-73,4,1478,-74,4,1479,-75,4,1480,-76,4,1481,-77,4,1482,-234,5,1483,-235,5,1484,-236,5,1485,-237,5,1486,-238,5,1487,-239,5,1488,-240,5,1489,-241,5,1490,-242,5,1491,-243,5,1492,-244,5,1493,-245,5,1494,-246,5,1495,-247,5,1496,-248,5,1497,-249,5,1498,-250,5,1499,-251,5,1500,-252,5,1501,-253,5,1502,-254,5,1503,-255,5,1504,-256,5,1505,-257,5,1506,-258,5,1507,-259,5,1508,-260,5,1509,-261,5,1510,-262,5,1511,-263,5,1512,-264,5,1513,-265,5,1514,-266,5,1515,-267,5,1516,-268,5,1517,-269,5,1518,-270,5,1519,-271,5,1520,-272,5,1521,-273,5,1522,-274,5,1523,-275,5,1524,-276,5,1525,-277,5,1526,-278,5,1527,-279,5,1528,-280,5,1529,-281,5,1530,-282,5,1531,-283,5,1532,-284,5,1533,-285,5,1534,-286,5,1535,-287,5,1536,-288,5,1537,-289,5,1538,-290,5,1539,-291,5,1540,-292,5,1541,-293,5,1542,-234,5,1543,-295,5,1544,-296,5,1545,-234,5,1546,-298,5,1547,-299,5,1548,-300,5,1549,-301,5,1550,-302,5,1551,-303,5,1552,-304,5,1553,-305,5,1554,-306,5,1555,-307,5,1556,-308,5,1557,-309,5,1558,-310,5,1559,-311,5,1560,-312,5,1561,-313,5,1562,-314,5,1563,-315,5,1564,-312,5,1565,-317,5,1566,-318,5,1567,-319,5,1568,-320,5,1569,-321,5,1570,-322,5,1571,-323,5,1572,-324,5,1573,-13,3,1574,-13,3,1575,-13,3,1576,-312,5,1577,-329,5,1578,-330,5,1579,-331,5,1580,-332,5,1581,-333,5,1582,-334,5,1583,-335,5,1584,-336,5,1585,-337,5,1586,-338,5,1587,-339,5,1588,-340,5,1589,-341,5,1590,-342,5,1591,-343,5,1592,-344,5,1593,-345,5,1594,-346,5,1595,-347,5,1596,-348,5,1597,-349,5,1598,-350,5,1599,-351,5,1600,-352,5,1601,-353,5,1602,-354,5,1603,-4,2,1604,-356,5,1605,-357,5,1606,-358,5,1607,-359,5,1608,-360,5,1609,-361,5,1610,-362,5,1611,-363,5,1612,-364,5,1613,-365,5,1614,-366,5,1615,-55,4,1616,-4,2,1617,-369,5,1618,-370,5,1619,-371,5,1620,-60,4,1621,-61,4,1622,-62,4,1623,-63,4,1624,-64,4,1625,-65,4,1626,-312,5,1627,-65,4,1628,-65,4,1629,-65,4,1630,-65,4,1631,-65,4,1632,-312,5,1633,-312,5,1634,-312,5,1635,-312,5,1636,-312,5,1637,-312,5,1638,-312,5,1639,-313,5,1640,-314,5,1641,-315,5,1642,-4,2,1643,-317,5,1644,-318,5,1645,-319,5,1646,-320,5,1647,-399,5,1648,-400,5,1649,-401,5,1650,-402,5,1651,-403,5,1652,-404,5,1653,-405,5,1654,-16,3,1655,-4,2,1656,-408,5,1657,-409,5,1658,-332,5,1659,-333,5,1660,-334,5,1661,-335,5,1662,-414,5,1663,-415,5,1664,-416,5,1665,-417,5,1666,-418,5,1667,-419,5,1668,-420,5,1669,-421,5,1670,-422,5,1671,-423,5,1672,-424,5,1673,-425,5,1674,-426,5,1675,-427,5,1676,-428,5,1677,-429,5,1678,-430,5,1679,-431,5,1680,-432,5,1681,-4,2,1682,-434,5,1683,-435,5,1684,-436,5,1685,-437,5,1686,-438,5,1687,-439,5,1688,-440,5,1689,-441,5,1690,-442,5,1691,-443,5,1692,-444,5,1693,-445,5,1694,-4,2,1695,-5,2,1696,-448,5,1697,-449,5,1698,-450,5,1699,-451,5,1700,-452,5,1701,-453,5,1702,-454,5,1703,-455,5,1704,-456,5,1705,-457,5,1706,-458,5,1707,-4,2,1708,-5,2,1709,-461,5,1710,-462,5,1711,-463,5,1712,-464,5,1713,-465,5,1714,-466,5,1715,-467,5,1716,-468,5,1717,-469,5,1718,-470,5,1719,-471,5,1720,-4,2,1721,-5,2,1722,-474,5,1723,-475,5,1724,-476,5,1725,-477,5,1726,-78,4,1727,-78,4,1728,-78,4,1729,-78,4,1730,-78,4,1731,-78,4,1732,-16,3,1733,-17,3,1734,-78,4,1735,-78,4,1736,-20,3,1737,-21,3,1738,-468,5,1739,-491,5,1740,-492,5,1741,-78,4,1742,-494,5,1743,-495,5,1744,-496,5,1745,-497,5,1746,-4,2,1747,-5,2,1748,-500,5,1749,-78,4,1750,-502,5,1751,-503,5,1752,-78,4,1753,-505,5,1754,-506,5,1755,-507,5,1756,-508,5,1757,-509,5,1758,-510,5,1759,-4,2,1760,-5,2,1761,-513,5,1762,-514,5,1763,-515,5,1764,-516,5,1765,-517,5,1766,-518,5,1767,-519,5,1768,-78,4,1769,-78,4,1770,-78,4,1771,-78,4,1772,-4,2,1773,-78,4,1774,-78,4,1775,-78,4,1776,-78,4,1777,-22,3,1778,-442,5,1779,-531,5,1780,-532,5,1781,-78,4,1782,-78,4,1783,-78,4,1784,-78,4,1785,-4,2,1786,-78,4,1787,-78,4,1788,-78,4,1789,-78,4,1790,-78,4,1791,-88,4,1792,-89,4,1793,-455,5,1794,-546,5,1795,-547,5,1796,-548,5,1797,-549,5,1798,-4,2,1799,-5,2,1800,-6,2,1801,-553,5,1802,-554,5,1803,-555,5,1804,-556,5,1805,-557,5,1806,-558,5,1807,-13,3,1808,-13,3,1809,-13,3,1810,-16,3,1811,-17,3,1812,-564,5,1813,-19,3,1814,-20,3,1815,-21,3,1816,-22,3,1817,-23,3,1818,-24,3,1819,-546,5,1820,-572,5,1821,-573,5,1822,-574,5,1823,-575,5,1824,-4,2,1825,-5,2,1826,-6,2,1827,-579,5,1828,-580,5,1829,-581,5,1830,-582,5,1831,-583,5,1832,-584,5,1833,-78,4,1834,-586,5,1835,-78,4,1836,-78,4,1837,-4,2,1838,-590,5,1839,-78,4,1840,-78,4,1841,-78,4,1842,-594,5,1843,-23,3,1844,-24,3,1845,-25,3,1846,-52,4,1847,-52,4,1848,-52,4,1849,-55,4,1850,-52,4,1851,-52,4,1852,-52,4,1853,-59,4,1854,-60,4,1855,-61,4,1856,-62,4,1857,-63,4,1858,-64,4,1859,-65,4,1860,-66,4,1861,-65,4,1862,-65,4,1863,-65,4,1864,-65,4,1865,-65,4,1866,-72,4,1867,-73,4,1868,-74,4,1869,-75,4,1870,-76,4,1871,-77,4,1872,-624,5,1873,-312,5,1874,-312,5,1875,-312,5,1876,-4,2,1877,-312,5,1878,-312,5,1879,-312,5,1880,-312,5,1881,-312,5,1882,-312,5,1883,-312,5,1884,-312,5,1885,-13,3,1886,-13,3,1887,-13,3,1888,-16,3,1889,-312,5,1890,-320,5,1891,-320,5,1892,-312,5,1893,-312,5,1894,-312,5,1895,-312,5,1896,-312,5,1897,-312,5,1898,-312,5,1899,-312,5,1900,-314,5,1901,-315,5,1902,-312,5,1903,-317,5,1904,-320,5,1905,-312,5,1906,-320,5,1907,-312,5,1908,-312,5,1909,-312,5,1910,-312,5,1911,-312,5,1912,-312,5,1913,-314,5,1914,-315,5,1915,-4,2,1916,-312,5,1917,-318,5,1918,-319,5,1919,-320,5,1920,-312,5,1921,-322,5,1922,-323,5,1923,-324,5,1924,-312,5,1925,-313,5,1926,-314,5,1927,-55,4,1928,-4,2,1929,-317,5,1930,-318,5,1931,-319,5,1932,-60,4,1933,-61,4,1934,-62,4,1935,-63,4,1936,-64,4,1937,-65,4,1938,-66,4,1939,-65,4,1940,-65,4,1941,-65,4,1942,-65,4,1943,-65,4,1944,-312,5,1945,-312,5,1946,-312,5,1947,-312,5,1948,-312,5,1949,-312,5,1950,-312,5,1951,-312,5,1952,-312,5,1953,-312,5,1954,-4,2,1955,-312,5,1956,-312,5,1957,-312,5,1958,-312,5,1959,-312,5,1960,-312,5,1961,-312,5,1962,-312,5,1963,-312,5,1964,-313,5,1965,-314,5,1966,-16,3,1967,-4,2,1968,-317,5,1969,-320,5,1970,-312,5,1971,-312,5,1972,-312,5,1973,-312,5,1974,-312,5,1975,-312,5,1976,-312,5,1977,-312,5,1978,-314,5,1979,-312,5,1980,-312,5,1981,-312,5,1982,-312,5,1983,-312,5,1984,-312,5,1985,-312,5,1986,-312,5,1987,-312,5,1988,-312,5,1989,-312,5,1990,-312,5,1991,-314,5,1992,-312,5,1993,-4,2,1994,-312,5,1995,-318,5,1996,-312,5,1997,-312,5,1998,-312,5,1999,-312,5,2000,-312,5,2001,-312,5,2002,-312,5,2003,-312,5,2004,-312,5,2005,-312,5,2006,-4,2,2007,-317,5,2008,-318,5,2009,-312,5,2010,-312,5,2011,-321,5,2012,-322,5,2013,-312,5,2014,-312,5,2015,-312,5,2016,-312,5,2017,-312,5,2018,-312,5,2019,-4,2,2020,-317,5,2021,-318,5,2022,-312,5,2023,-312,5,2024,-312,5,2025,-312,5,2026,-312,5,2027,-312,5,2028,-312,5,2029,-312,5,2030,-314,5,2031,-312,5,2032,-4,2,2033,-317,5,2034,-318,5,2035,-319,5,2036,-320,5,2037,-312,5,2038,-312,5,2039,-312,5,2040,-312,5,2041,-312,5,2042,-313,5,2043,-314,5,2044,-16,3,2045,-312,5,2046,-317,5,2047,-320,5,0,0,0"),
// leafSize 14
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,12,14,13,13,15,14,14,16,15,-2,1,16,-2,1,17,-3,1,18,-5,2,19,-8,2,20,-10,2,21,-8,2,22,-11,2,23,-10,2,24,-11,2,25,-12,2,26,-13,2,27,-13,2,28,-14,2,29,-14,2,30,3,5,31,-14,2,32,-8,2,33,3,5,34,-8,2,35,-11,2,36,3,5,37,-11,2,38,-12,2,39,3,5,40,-13,2,41,-13,2,42,3,5,43,-1,1,44,4,8,45,-3,1,46,-7,2,47,-8,2,48,4,8,49,-10,2,50,-11,2,51,-12,2,52,4,8,53,-14,2,54,-12,2,55,-13,2,56,4,8,57,-1,1,58,-2,1,59,-7,2,60,5,11,61,-9,2,62,-10,2,63,-11,2,64,-12,2,65,5,11,66,-14,2,67,-11,2,68,-12,2,69,-13,2,70,5,11,71,-1,1,72,6,14,73,-8,2,74,-9,2,75,-10,2,76,-11,2,77,-12,2,78,6,14,79,-14,2,80,-10,2,81,-11,2,82,-12,2,83,-13,2,84,6,14,85,-1,1,86,-2,1,87,-9,2,88,-10,2,89,-11,2,90,-12,2,91,-13,2,92,-14,2,93,-9,2,94,-10,2,95,-11,2,96,-12,2,97,-13,2,98,-14,2,99,-2,1,100,-16,3,101,-23,3,102,-24,3,103,-25,3,104,-26,3,105,-27,3,106,-28,3,107,-42,3,108,-52,3,109,-39,3,110,-26,3,111,-27,3,112,-28,3,113,-48,3,114,-36,3,115,-37,3,116,-56,3,117,-39,3,118,-48,3,119,-41,3,120,-42,3,121,-56,3,122,-52,3,123,-39,3,124,-40,3,125,-60,3,126,-42,3,127,-1,1,128,-44,3,129,-51,3,130,-52,3,131,-53,3,132,-48,3,133,-55,3,134,-56,3,135,-65,3,136,-52,3,137,-65,3,138,-60,3,139,-55,3,140,-70,3,141,-1,1,142,-70,3,143,-65,3,144,-60,3,145,-11,2,146,-12,2,147,-69,3,148,-70,3,149,-65,3,150,-72,3,151,-11,2,152,-12,2,153,-13,2,154,-70,3,155,-1,0,156,-78,3,157,-14,3,158,-10,2,159,-11,2,160,-12,2,161,-13,2,162,-78,3,163,-14,3,164,-10,2,165,-11,2,166,-12,2,167,-13,2,168,-84,3,169,-1,0,170,-2,1,171,-9,2,172,-10,2,173,-11,2,174,-12,2,175,-13,2,176,-14,3,177,-9,2,178,-10,2,179,-11,2,180,-12,2,181,-13,2,182,-14,3,183,-27,3,184,-28,3,185,-42,3,186,-52,3,187,-39,3,188,-26,3,189,-27,3,190,-28,3,191,-42,3,192,-52,3,193,-39,3,194,-26,3,195,3,7,196,-28,3,197,-48,3,198,-42,3,199,-56,3,200,-52,3,201,-39,3,202,-48,3,203,-8,2,204,-42,3,205,-84,4,206,-52,3,207,-39,3,208,-52,3,209,-14,3,210,3,7,211,-1,0,212,-2,1,213,-78,4,214,-84,4,215,-5,2,216,-6,2,217,-7,2,218,-84,4,219,-84,4,220,-84,4,221,-11,2,222,-12,2,223,-13,2,224,4,11,225,-1,0,226,-78,4,227,-84,4,228,-84,4,229,-95,4,230,-96,4,231,-97,4,232,-84,4,233,-84,4,234,3,8,235,-1,0,236,-2,1,237,-27,3,238,-84,4,239,-5,2,240,-84,4,241,-7,2,242,-8,2,243,-9,2,244,-10,2,245,-11,2,246,-84,4,247,-13,2,248,-14,3,249,-39,3,250,-96,4,251,-97,4,252,3,8,253,-1,0,254,-2,1,255,-3,1,256,-4,2,257,-5,2,258,-6,2,259,-7,2,260,-8,2,261,-9,2,262,-10,2,263,-11,2,264,-12,2,265,-13,2,266,-14,3,267,-14,3,268,-14,3,269,-17,3,270,-8,2,271,-8,2,272,-20,3,273,-21,3,274,-22,3,275,-23,3,276,-24,3,277,-25,3,278,-26,3,279,-27,3,280,4,12,281,-1,0,282,-2,1,283,-3,1,284,-4,2,285,-5,2,286,-6,2,287,-7,2,288,-78,4,289,-9,2,290,-10,2,291,-39,3,292,-12,2,293,-13,3,294,-14,3,295,-14,3,296,-44,3,297,-148,4,298,-149,4,299,-65,4,300,-48,3,301,-91,4,302,-148,4,303,-149,4,304,-52,3,305,-25,3,306,-26,3,307,-27,3,308,-56,3,309,-56,3,310,-154,4,311,-149,4,312,4,12,313,-1,0,314,-2,1,315,-63,4,316,-154,4,317,-65,4,318,-84,4,319,-39,3,320,-8,2,321,-69,4,322,-70,4,323,-11,2,324,-12,2,325,-13,3,326,-14,3,327,-75,4,328,-76,4,329,-77,4,330,-78,4,331,-79,4,332,-52,3,333,-81,4,334,-82,4,335,-83,4,336,4,12,337,-1,0,338,-2,1,339,-3,1,340,-4,2,341,-5,2,342,-6,2,343,-7,2,344,-8,2,345,-9,2,346,-10,2,347,-11,2,348,-12,2,349,-13,3,350,5,16,351,-1,0,352,-2,1,353,-3,1,354,-4,2,355,-5,2,356,-20,3,357,-21,3,358,-78,4,359,-23,3,360,-24,3,361,-25,3,362,-26,3,363,-27,3,364,-28,3,365,-28,3,366,-30,3,367,-5,2,368,-56,4,369,-33,3,370,-26,3,371,-91,4,372,-36,3,373,-37,3,374,-38,3,375,-39,3,376,-26,3,377,-27,3,378,-42,3,379,-42,3,380,-44,3,381,-42,3,382,-70,4,383,-8,2,384,-48,3,385,-39,3,386,-134,4,387,-135,4,388,-52,3,389,-39,3,390,5,16,391,-13,3,392,-56,4,393,-56,4,394,-56,4,395,-143,4,396,-84,4,397,-7,2,398,-8,2,399,-9,2,400,-10,2,401,-65,4,402,-12,2,403,-13,3,404,-14,3,405,-69,4,406,-70,4,407,-70,4,408,-72,4,409,-73,4,410,-74,4,411,-75,4,412,-76,4,413,-77,4,414,-78,4,415,-65,4,416,-80,4,417,-81,4,418,-82,4,419,-83,4,420,-84,4,421,-84,4,422,-84,4,423,-87,4,424,-88,4,425,-89,4,426,-90,4,427,-91,4,428,-78,4,429,-93,4,430,-94,4,431,-95,4,432,-96,4,433,-97,4,434,-84,4,435,-84,4,436,-84,4,437,-101,4,438,-102,4,439,-103,4,440,-104,4,441,-105,4,442,-106,4,443,-107,4,444,-108,4,445,-109,4,446,-110,4,447,-111,4,448,-112,4,449,-113,4,450,-114,4,451,-115,4,452,-116,4,453,-117,4,454,-118,4,455,-65,4,456,-120,4,457,-121,4,458,-122,4,459,-123,4,460,-70,4,461,-125,4,462,-126,4,463,-126,4,464,-128,4,465,-75,4,466,-130,4,467,-117,4,468,-78,4,469,-79,4,470,-134,4,471,-135,4,472,-136,4,473,-83,4,474,-84,4,475,-139,4,476,-140,4,477,-140,4,478,-142,4,479,-143,4,480,-144,4,481,-91,4,482,-14,3,483,-147,4,484,-148,4,485,-149,4,486,-234,4,487,-97,4,488,-14,3,489,-153,4,490,-154,4,491,-155,4,492,-156,4,493,-143,4,494,-158,4,495,-159,4,496,-160,4,497,-161,4,498,-78,4,499,-149,4,500,-164,4,501,-81,4,502,-82,4,503,-83,4,504,-84,4,505,-84,4,506,-156,4,507,-84,4,508,-84,4,509,-84,4,510,-84,4,511,-84,4,512,-78,4,513,-84,4,514,-84,4,515,-84,4,516,-84,4,517,-84,4,518,-84,4,519,-78,4,520,-130,4,521,-78,4,522,-210,4,523,-78,4,524,-134,4,525,-135,4,526,-136,4,527,-84,4,528,-84,4,529,-84,4,530,-140,4,531,-195,4,532,-252,4,533,-143,4,534,-78,4,535,-78,4,536,-78,4,537,-84,4,538,-148,4,539,-149,4,540,-84,4,541,-84,4,542,-84,4,543,-84,4,544,-154,4,545,-13,3,546,-210,4,547,-211,4,548,-78,4,549,-78,4,550,-84,4,551,-5,2,552,-78,4,553,-7,2,554,-84,4,555,-84,4,556,-84,4,557,-221,4,558,-84,4,559,-13,3,560,-84,4,561,-84,4,562,-78,4,563,-84,4,564,-252,4,565,-84,4,566,-14,3,567,-97,4,568,-84,4,569,-84,4,570,-234,4,571,-84,4,572,-14,3,573,-27,3,574,-84,4,575,-263,4,576,-84,4,577,-13,3,578,-14,3,579,-234,4,580,-244,4,581,-245,4,582,-78,4,583,-13,3,584,-234,4,585,-210,4,586,-96,4,587,-97,4,588,-252,4,589,-253,4,590,-2,1,591,-255,4,592,-4,2,593,-5,2,594,-6,2,595,-7,2,596,-8,2,597,-9,2,598,-262,4,599,-263,4,600,-264,4,601,-13,3,602,-252,4,603,-253,4,604,-2,1,605,-255,4,606,-4,2,607,-5,2,608,-20,3,609,-21,3,610,-78,4,611,-65,4,612,-24,3,613,-25,3,614,-26,3,615,-27,3,616,-280,4,617,-281,4,618,-2,1,619,-283,4,620,-4,2,621,-5,2,622,-6,2,623,-7,2,624,-78,4,625,-9,2,626,-280,4,627,-39,3,628,-292,4,629,-13,3,630,-280,4,631,-281,4,632,-252,4,633,-78,4,634,-70,4,635,-65,4,636,-300,4,637,-91,4,638,-84,4,639,-84,4,640,-52,4,641,-39,3,642,-252,4,643,-27,3,644,-56,4,645,-56,4,646,-78,4,647,-84,4,648,-312,4,649,-313,4,650,-2,1,651,-9,2,652,-84,4,653,-65,4,654,-84,4,655,-13,3,656,-14,3,657,-69,4,658,-70,4,659,-323,4,660,-72,4,661,-13,3,662,-312,4,663,-75,4,664,-76,4,665,-77,4,666,-78,4,667,-65,4,668,-52,4,669,-81,4,670,-280,4,671,-83,4,672,-336,4,673,-336,4,674,-2,1,675,-336,4,676,-4,2,677,-5,2,678,-6,2,679,-7,2,680,-8,2,681,-9,2,682,-10,2,683,-336,4,684,-336,4,685,-13,3,686,-336,4,687,-337,4,688,-2,1,689,-339,4,690,-4,2,691,-5,2,692,-20,3,693,-21,3,694,-78,4,695,-23,3,696,-24,3,697,-25,3,698,-26,3,699,-27,3,700,-28,3,701,-28,3,702,-312,4,703,-5,2,704,-56,4,705,-33,3,706,-90,4,707,-65,4,708,-36,3,709,-37,3,710,-38,3,711,-39,3,712,-26,3,713,-27,3,714,-42,3,715,-42,3,716,-44,3,717,-42,3,718,-70,4,719,-8,2,720,-48,3,721,-39,3,722,-134,4,723,-135,4,724,-52,4,725,-39,3,726,-336,4,727,-55,4,728,-56,4,729,-56,4,730,-56,4,731,-143,4,732,-84,4,733,-343,5,734,-344,5,735,-345,5,736,-346,5,737,-65,4,738,-348,5,739,-13,3,740,-350,5,741,-69,4,742,-70,4,743,-70,4,744,-72,4,745,-73,4,746,-74,4,747,-75,4,748,-76,4,749,-77,4,750,-78,4,751,-65,4,752,-80,4,753,-81,4,754,-82,4,755,-83,4,756,-84,4,757,-84,4,758,-84,4,759,-87,4,760,-88,4,761,-89,4,762,-90,4,763,-91,4,764,-78,4,765,-93,4,766,-94,4,767,-95,4,768,-96,4,769,-97,4,770,-84,4,771,-84,4,772,-84,4,773,-78,4,774,-78,4,775,-103,4,776,-104,4,777,-105,4,778,-106,4,779,-107,4,780,-390,5,781,-109,4,782,-110,4,783,-111,4,784,-112,4,785,-113,4,786,-114,4,787,-115,4,788,-116,4,789,-117,4,790,-118,4,791,-390,5,792,-120,4,793,-121,4,794,-122,4,795,-123,4,796,-390,5,797,-125,4,798,-126,4,799,-126,4,800,-128,4,801,-78,4,802,-336,5,803,-350,5,804,-390,5,805,-390,5,806,-336,5,807,-336,5,808,-336,5,809,-390,5,810,-390,5,811,-336,5,812,-336,5,813,-337,5,814,-336,5,815,-336,5,816,-336,5,817,-390,5,818,-390,5,819,-336,5,820,-336,5,821,-336,5,822,-336,5,823,-390,5,824,-390,5,825,-336,5,826,-336,5,827,-336,5,828,-78,4,829,-350,5,830,-336,5,831,-78,4,832,-78,4,833,-78,4,834,-78,4,835,-350,5,836,-80,4,837,-81,4,838,-82,4,839,-83,4,840,-84,4,841,-84,4,842,-350,5,843,-84,4,844,-84,4,845,-84,4,846,-84,4,847,-84,4,848,-78,4,849,-84,4,850,-84,4,851,-84,4,852,-84,4,853,-84,4,854,-84,4,855,-78,4,856,-390,5,857,-78,4,858,-336,5,859,-78,4,860,-390,5,861,-390,5,862,-390,5,863,-84,4,864,-390,5,865,-420,5,866,-390,5,867,-336,5,868,-336,5,869,-390,5,870,-414,5,871,-414,5,872,-414,5,873,-420,5,874,-390,5,875,-390,5,876,-420,5,877,-420,5,878,-420,5,879,-420,5,880,-390,5,881,-13,3,882,-336,5,883,-336,5,884,-414,5,885,-414,5,886,-420,5,887,-341,5,888,-420,5,889,-343,5,890,-420,5,891,-420,5,892,-420,5,893,-347,5,894,-420,5,895,-13,3,896,-420,5,897,-421,5,898,-414,5,899,-420,5,900,-336,5,901,-427,5,902,-434,5,903,-433,5,904,-420,5,905,-420,5,906,-336,5,907,-433,5,908,-434,5,909,-363,5,910,-420,5,911,-347,5,912,-420,5,913,-13,3,914,-350,5,915,-345,5,916,-346,5,917,-347,5,918,-78,4,919,-13,3,920,-350,5,921,-375,5,922,-390,5,923,-433,5,924,-336,5,925,-337,5,926,-338,5,927,-339,5,928,-340,5,929,-341,5,930,-342,5,931,-343,5,932,-344,5,933,-345,5,934,-346,5,935,-347,5,936,-348,5,937,-13,3,938,-350,5,939,-351,5,940,-352,5,941,-353,5,942,-354,5,943,-355,5,944,-356,5,945,-357,5,946,-414,5,947,-401,5,948,-360,5,949,-361,5,950,-362,5,951,-363,5,952,-336,5,953,-337,5,954,-338,5,955,-339,5,956,-340,5,957,-341,5,958,-342,5,959,-343,5,960,-414,5,961,-345,5,962,-346,5,963,-375,5,964,-348,5,965,-13,3,966,-350,5,967,-351,5,968,-380,5,969,-484,5,970,-406,5,971,-336,5,972,-384,5,973,-427,5,974,-470,5,975,-471,5,976,-388,5,977,-389,5,978,-390,5,979,-363,5,980,-56,4,981,-56,4,982,-484,5,983,-479,5,984,-336,5,985,-337,5,986,-338,5,987,-399,5,988,-484,5,989,-336,5,990,-420,5,991,-13,3,992,-390,5,993,-405,5,994,-406,5,995,-347,5,996,-408,5,997,-13,3,998,-350,5,999,-411,5,1000,-412,5,1001,-413,5,1002,-414,5,1003,-350,5,1004,-388,5,1005,-417,5,1006,-390,5,1007,-419,5,1008,3,10,1009,-1,0,1010,-2,1,1011,-3,1,1012,-4,2,1013,-5,2,1014,-6,2,1015,-7,2,1016,-8,2,1017,-9,2,1018,-10,2,1019,-11,2,1020,-12,2,1021,-13,3,1022,-14,3,1023,-14,3,1024,-14,3,1025,-17,3,1026,-13,3,1027,-19,3,1028,-20,3,1029,-21,3,1030,-22,3,1031,-23,3,1032,-24,3,1033,-25,3,1034,-26,3,1035,-27,3,1036,-28,3,1037,-28,3,1038,-30,3,1039,-5,2,1040,-5,2,1041,-33,3,1042,-26,3,1043,-27,3,1044,-36,3,1045,-37,3,1046,-38,3,1047,-39,3,1048,-40,3,1049,-14,3,1050,-42,3,1051,-42,3,1052,-44,3,1053,-42,3,1054,-7,2,1055,-8,2,1056,-48,3,1057,-39,3,1058,-39,3,1059,-51,4,1060,-52,4,1061,-14,3,1062,-390,5,1063,-55,4,1064,-56,4,1065,-56,4,1066,-56,4,1067,-59,4,1068,-60,4,1069,-61,4,1070,-62,4,1071,-63,4,1072,-64,4,1073,-65,4,1074,-66,4,1075,-67,4,1076,-68,4,1077,-69,4,1078,-70,4,1079,-70,4,1080,-72,4,1081,-73,4,1082,-74,4,1083,-75,4,1084,-76,4,1085,-77,4,1086,-78,4,1087,-79,4,1088,-80,4,1089,-81,4,1090,-82,4,1091,-83,4,1092,-84,4,1093,-84,4,1094,-84,4,1095,-87,4,1096,-88,4,1097,-89,4,1098,-90,4,1099,-91,4,1100,-14,3,1101,-93,4,1102,-94,4,1103,-95,4,1104,-96,4,1105,-97,4,1106,-14,3,1107,-14,3,1108,-14,3,1109,-78,4,1110,-78,4,1111,-78,4,1112,-104,4,1113,-105,4,1114,-106,4,1115,-107,4,1116,-108,4,1117,-109,4,1118,-84,4,1119,-111,4,1120,-112,4,1121,-113,4,1122,-114,4,1123,-115,4,1124,-116,4,1125,-117,4,1126,-118,4,1127,-119,4,1128,-120,4,1129,-121,4,1130,-122,4,1131,-123,4,1132,-124,4,1133,-125,4,1134,-126,4,1135,-126,4,1136,-128,4,1137,-129,4,1138,-130,4,1139,-14,3,1140,-132,4,1141,-133,4,1142,-134,4,1143,-135,4,1144,-136,4,1145,-137,4,1146,-138,4,1147,-139,4,1148,-140,4,1149,-140,4,1150,-142,4,1151,-143,4,1152,-144,4,1153,-145,4,1154,-68,4,1155,-69,4,1156,-70,4,1157,-65,4,1158,-72,4,1159,-70,4,1160,-70,4,1161,-70,4,1162,-70,4,1163,-70,4,1164,-78,4,1165,-78,4,1166,-78,4,1167,-78,4,1168,-78,4,1169,-78,4,1170,-78,4,1171,-79,4,1172,-80,4,1173,-81,4,1174,-82,4,1175,-83,4,1176,-84,4,1177,-84,4,1178,-84,4,1179,-84,4,1180,-84,4,1181,-84,4,1182,-84,4,1183,-84,4,1184,-14,3,1185,-84,4,1186,-84,4,1187,-84,4,1188,-84,4,1189,-84,4,1190,-14,3,1191,-78,4,1192,-78,4,1193,-78,4,1194,-78,4,1195,-78,4,1196,-84,4,1197,-84,4,1198,-84,4,1199,-84,4,1200,-84,4,1201,-84,4,1202,-84,4,1203,-195,4,1204,-84,4,1205,-84,4,1206,-78,4,1207,-78,4,1208,-78,4,1209,-84,4,1210,-84,4,1211,-8,2,1212,-84,4,1213,-84,4,1214,-84,4,1215,-84,4,1216,-78,4,1217,-14,3,1218,-210,4,1219,-211,4,1220,-78,4,1221,-78,4,1222,-84,4,1223,-5,2,1224,-84,4,1225,-7,2,1226,-84,4,1227,-84,4,1228,-84,4,1229,-210,4,1230,-222,5,1231,-13,3,1232,-84,4,1233,-84,4,1234,-70,4,1235,-84,4,1236,-84,4,1237,-95,4,1238,-96,4,1239,-97,4,1240,-70,4,1241,-65,4,1242,-234,5,1243,-235,5,1244,-236,5,1245,-70,4,1246,-70,4,1247,-239,5,1248,-78,4,1249,-241,5,1250,-242,5,1251,-243,5,1252,-244,5,1253,-245,5,1254,-78,4,1255,-247,5,1256,-248,5,1257,-81,4,1258,-82,4,1259,-83,4,1260,-252,5,1261,-253,5,1262,-254,5,1263,-255,5,1264,-256,5,1265,-257,5,1266,-258,5,1267,-259,5,1268,-260,5,1269,-261,5,1270,-262,5,1271,-263,5,1272,-264,5,1273,-265,5,1274,-266,5,1275,-267,5,1276,-268,5,1277,-269,5,1278,-270,5,1279,-271,5,1280,-272,5,1281,-273,5,1282,-274,5,1283,-65,4,1284,-276,5,1285,-277,5,1286,-278,5,1287,-279,5,1288,-280,5,1289,-281,5,1290,-282,5,1291,-283,5,1292,-284,5,1293,-285,5,1294,-286,5,1295,-287,5,1296,-78,4,1297,-289,5,1298,-290,5,1299,-291,5,1300,-292,5,1301,-13,3,1302,-280,5,1303,-14,3,1304,-296,5,1305,-78,4,1306,-84,4,1307,-299,5,1308,-300,5,1309,-301,5,1310,-84,4,1311,-84,4,1312,-304,5,1313,-305,5,1314,-306,5,1315,-307,5,1316,-308,5,1317,-309,5,1318,-70,4,1319,-84,4,1320,-312,5,1321,-313,5,1322,-314,5,1323,-252,5,1324,-70,4,1325,-317,5,1326,-318,5,1327,-319,5,1328,-320,5,1329,-321,5,1330,-322,5,1331,-323,5,1332,-324,5,1333,-13,3,1334,-14,3,1335,-327,5,1336,-328,5,1337,-329,5,1338,-330,5,1339,-331,5,1340,-332,5,1341,-333,5,1342,-334,5,1343,-335,5,1344,4,15,1345,-1,0,1346,-2,1,1347,-3,1,1348,-4,2,1349,-5,2,1350,-6,2,1351,-7,2,1352,-8,2,1353,-9,2,1354,-10,2,1355,-11,2,1356,-12,2,1357,-13,3,1358,-14,3,1359,-14,3,1360,-14,3,1361,-17,3,1362,-13,3,1363,-19,3,1364,-20,3,1365,-21,3,1366,-22,3,1367,-23,3,1368,-24,3,1369,-25,3,1370,-26,3,1371,-27,3,1372,-28,3,1373,-28,3,1374,-30,3,1375,-5,2,1376,-5,2,1377,-33,3,1378,-26,3,1379,-27,3,1380,-36,3,1381,-37,3,1382,-38,3,1383,-39,3,1384,-14,3,1385,-14,3,1386,-42,3,1387,-42,3,1388,-44,3,1389,-42,3,1390,-7,2,1391,-8,2,1392,-48,3,1393,-39,3,1394,-39,3,1395,-51,4,1396,-52,4,1397,-14,3,1398,-390,5,1399,-55,4,1400,-56,4,1401,-56,4,1402,-56,4,1403,-59,4,1404,-60,4,1405,-61,4,1406,-62,4,1407,-63,4,1408,-64,4,1409,-65,4,1410,-66,4,1411,-67,4,1412,-68,4,1413,-69,4,1414,-70,4,1415,-70,4,1416,-72,4,1417,-73,4,1418,-74,4,1419,-75,4,1420,-76,4,1421,-77,4,1422,-78,4,1423,-79,4,1424,-80,4,1425,-81,4,1426,-82,4,1427,-83,4,1428,-84,4,1429,-84,4,1430,-84,4,1431,-87,4,1432,-88,4,1433,-89,4,1434,-90,4,1435,-91,4,1436,-14,3,1437,-93,4,1438,-94,4,1439,-95,4,1440,-96,4,1441,-97,4,1442,-14,3,1443,-14,3,1444,-14,3,1445,-78,4,1446,-78,4,1447,-78,4,1448,-104,4,1449,-105,4,1450,-106,4,1451,-107,4,1452,-108,4,1453,-109,4,1454,-84,4,1455,-84,4,1456,-112,4,1457,-113,4,1458,-114,4,1459,-115,4,1460,-116,4,1461,-117,4,1462,-118,4,1463,-119,4,1464,-120,4,1465,-121,4,1466,-122,4,1467,-123,4,1468,-124,4,1469,-125,4,1470,-126,4,1471,-126,4,1472,-128,4,1473,-129,4,1474,-130,4,1475,-14,3,1476,-132,4,1477,-133,4,1478,-134,4,1479,-135,4,1480,-136,4,1481,-137,4,1482,-138,4,1483,-139,4,1484,-140,4,1485,-140,4,1486,-70,4,1487,-65,4,1488,-144,4,1489,-67,4,1490,-68,4,1491,-69,4,1492,-70,4,1493,-65,4,1494,-72,4,1495,-70,4,1496,-70,4,1497,-70,4,1498,-70,4,1499,-70,4,1500,-78,4,1501,-78,4,1502,-78,4,1503,-78,4,1504,-78,4,1505,-78,4,1506,-78,4,1507,-79,4,1508,-80,4,1509,-81,4,1510,-82,4,1511,-83,4,1512,-84,4,1513,-84,4,1514,-84,4,1515,-84,4,1516,-84,4,1517,-84,4,1518,-84,4,1519,-84,4,1520,-14,3,1521,-84,4,1522,-84,4,1523,-84,4,1524,-84,4,1525,-84,4,1526,-14,3,1527,-78,4,1528,-78,4,1529,-78,4,1530,-78,4,1531,-78,4,1532,-84,4,1533,-84,4,1534,-84,4,1535,-84,4,1536,-84,4,1537,-84,4,1538,-84,4,1539,-195,4,1540,-84,4,1541,-84,4,1542,-78,4,1543,-78,4,1544,-78,4,1545,-84,4,1546,-84,4,1547,-8,2,1548,-84,4,1549,-84,4,1550,-84,4,1551,-84,4,1552,-78,4,1553,-14,3,1554,-210,5,1555,-211,5,1556,-78,4,1557,-78,4,1558,-84,4,1559,-215,5,1560,-84,4,1561,-217,5,1562,-84,4,1563,-84,4,1564,-84,4,1565,-221,5,1566,-222,5,1567,-223,5,1568,-84,4,1569,-84,4,1570,-70,4,1571,-65,4,1572,-84,4,1573,-95,4,1574,-70,4,1575,-70,4,1576,-70,4,1577,-65,4,1578,-234,5,1579,-235,5,1580,-236,5,1581,-70,4,1582,-70,4,1583,-239,5,1584,-78,4,1585,-241,5,1586,-242,5,1587,-243,5,1588,-244,5,1589,-245,5,1590,-78,4,1591,-247,5,1592,-248,5,1593,-81,4,1594,-82,4,1595,-83,4,1596,-252,5,1597,-253,5,1598,-254,5,1599,-255,5,1600,-256,5,1601,-257,5,1602,-258,5,1603,-259,5,1604,-260,5,1605,-261,5,1606,-262,5,1607,-263,5,1608,-264,5,1609,-265,5,1610,-252,5,1611,-253,5,1612,-254,5,1613,-269,5,1614,-270,5,1615,-271,5,1616,-272,5,1617,-273,5,1618,-274,5,1619,-275,5,1620,-276,5,1621,-277,5,1622,-278,5,1623,-279,5,1624,-280,5,1625,-281,5,1626,-282,5,1627,-283,5,1628,-284,5,1629,-285,5,1630,-286,5,1631,-287,5,1632,-288,5,1633,-289,5,1634,-290,5,1635,-291,5,1636,-292,5,1637,-13,3,1638,-14,3,1639,-14,3,1640,-296,5,1641,-78,4,1642,-84,4,1643,-299,5,1644,-300,5,1645,-301,5,1646,-84,4,1647,-84,4,1648,-304,5,1649,-305,5,1650,-306,5,1651,-307,5,1652,-308,5,1653,-309,5,1654,-70,4,1655,-65,4,1656,-312,5,1657,-313,5,1658,-314,5,1659,-252,5,1660,-70,4,1661,-252,5,1662,-318,5,1663,-319,5,1664,-320,5,1665,-321,5,1666,-322,5,1667,-323,5,1668,-324,5,1669,-13,3,1670,-14,3,1671,-327,5,1672,-328,5,1673,-329,5,1674,-330,5,1675,-331,5,1676,-332,5,1677,-333,5,1678,-334,5,1679,-335,5,1680,-336,5,1681,-337,5,1682,-338,5,1683,-339,5,1684,-4,2,1685,-341,5,1686,-342,5,1687,-343,5,1688,-344,5,1689,-345,5,1690,-346,5,1691,-347,5,1692,-348,5,1693,-13,3,1694,-350,5,1695,-351,5,1696,-352,5,1697,-353,5,1698,-4,2,1699,-355,5,1700,-356,5,1701,-357,5,1702,-358,5,1703,-359,5,1704,-360,5,1705,-361,5,1706,-362,5,1707,-363,5,1708,-364,5,1709,-365,5,1710,-366,5,1711,-367,5,1712,-56,4,1713,-369,5,1714,-370,5,1715,-371,5,1716,-372,5,1717,-373,5,1718,-374,5,1719,-375,5,1720,-376,5,1721,-377,5,1722,-378,5,1723,-379,5,1724,-380,5,1725,-381,5,1726,-312,5,1727,-383,5,1728,-384,5,1729,-385,5,1730,-386,5,1731,-387,5,1732,-388,5,1733,-389,5,1734,-390,5,1735,-55,4,1736,-56,4,1737,-56,4,1738,-56,4,1739,-395,5,1740,-60,4,1741,-397,5,1742,-398,5,1743,-399,5,1744,-400,5,1745,-65,4,1746,-402,5,1747,-13,3,1748,-14,3,1749,-69,4,1750,-70,4,1751,-70,4,1752,-336,5,1753,-336,5,1754,-336,5,1755,-336,5,1756,-336,5,1757,-336,5,1758,-336,5,1759,-65,4,1760,-336,5,1761,-336,5,1762,-336,5,1763,-336,5,1764,-336,5,1765,-337,5,1766,-338,5,1767,-423,5,1768,-424,5,1769,-425,5,1770,-426,5,1771,-427,5,1772,-350,5,1773,-429,5,1774,-430,5,1775,-431,5,1776,-432,5,1777,-433,5,1778,-350,5,1779,-351,5,1780,-352,5,1781,-359,5,1782,-360,5,1783,-439,5,1784,-440,5,1785,-441,5,1786,-442,5,1787,-443,5,1788,-444,5,1789,-445,5,1790,-446,5,1791,-447,5,1792,-448,5,1793,-449,5,1794,-450,5,1795,-451,5,1796,-452,5,1797,-453,5,1798,-454,5,1799,-65,4,1800,-456,5,1801,-457,5,1802,-458,5,1803,-459,5,1804,-70,4,1805,-461,5,1806,-462,5,1807,-463,5,1808,-464,5,1809,-75,4,1810,-466,5,1811,-467,5,1812,-78,4,1813,-79,4,1814,-470,5,1815,-471,5,1816,-472,5,1817,-390,5,1818,-390,5,1819,-475,5,1820,-476,5,1821,-477,5,1822,-478,5,1823,-479,5,1824,-480,5,1825,-390,5,1826,-14,3,1827,-483,5,1828,-484,5,1829,-485,5,1830,-486,5,1831,-487,5,1832,-14,3,1833,-489,5,1834,-490,5,1835,-491,5,1836,-336,5,1837,-493,5,1838,-494,5,1839,-495,5,1840,-336,5,1841,-336,5,1842,-336,5,1843,-499,5,1844,-336,5,1845,-336,5,1846,-336,5,1847,-336,5,1848,-336,5,1849,-337,5,1850,-350,5,1851,-84,4,1852,-84,4,1853,-84,4,1854,-84,4,1855,-84,4,1856,-350,5,1857,-84,4,1858,-84,4,1859,-84,4,1860,-84,4,1861,-84,4,1862,-350,5,1863,-78,4,1864,-520,5,1865,-78,4,1866,-522,5,1867,-78,4,1868,-524,5,1869,-525,5,1870,-526,5,1871,-84,4,1872,-84,4,1873,-84,4,1874,-530,5,1875,-531,5,1876,-532,5,1877,-533,5,1878,-78,4,1879,-78,4,1880,-78,4,1881,-84,4,1882,-538,5,1883,-539,5,1884,-84,4,1885,-84,4,1886,-84,4,1887,-84,4,1888,-70,4,1889,-13,3,1890,-546,5,1891,-547,5,1892,-78,4,1893,-78,4,1894,-84,4,1895,-5,2,1896,-78,4,1897,-553,5,1898,-84,4,1899,-84,4,1900,-84,4,1901,-557,5,1902,-390,5,1903,-13,3,1904,-84,4,1905,-84,4,1906,-78,4,1907,-84,4,1908,-564,5,1909,-390,5,1910,-14,3,1911,-91,4,1912,-84,4,1913,-84,4,1914,-570,5,1915,-84,4,1916,-14,3,1917,-573,5,1918,-84,4,1919,-575,5,1920,-336,5,1921,-13,3,1922,-14,3,1923,-579,5,1924,-580,5,1925,-581,5,1926,-336,5,1927,-13,3,1928,-584,5,1929,-585,5,1930,-336,5,1931,-336,5,1932,-588,5,1933,-589,5,1934,-590,5,1935,-591,5,1936,-4,2,1937,-5,2,1938,-6,2,1939,-595,5,1940,-596,5,1941,-597,5,1942,-598,5,1943,-599,5,1944,-600,5,1945,-13,3,1946,-602,5,1947,-603,5,1948,-604,5,1949,-605,5,1950,-4,2,1951,-5,2,1952,-20,3,1953,-21,3,1954,-78,4,1955,-65,4,1956,-24,3,1957,-25,3,1958,-26,3,1959,-615,5,1960,-616,5,1961,-617,5,1962,-618,5,1963,-619,5,1964,-4,2,1965,-5,2,1966,-6,2,1967,-623,5,1968,-78,4,1969,-289,5,1970,-290,5,1971,-291,5,1972,-292,5,1973,-13,3,1974,-280,5,1975,-281,5,1976,-296,5,1977,-78,4,1978,-70,4,1979,-65,4,1980,-300,5,1981,-91,4,1982,-84,4,1983,-84,4,1984,-52,4,1985,-291,5,1986,-642,5,1987,-307,5,1988,-56,4,1989,-56,4,1990,-78,4,1991,-84,4,1992,-312,5,1993,-313,5,1994,-314,5,1995,-63,4,1996,-84,4,1997,-65,4,1998,-84,4,1999,-13,3,2000,-14,3,2001,-69,4,2002,-70,4,2003,-323,5,2004,-324,5,2005,-13,3,2006,-312,5,2007,-75,4,2008,-76,4,2009,-77,4,2010,-78,4,2011,-65,4,2012,-332,5,2013,-81,4,2014,-280,5,2015,-83,4,2016,-336,5,2017,-336,5,2018,-336,5,2019,-336,5,2020,-4,2,2021,-336,5,2022,-336,5,2023,-336,5,2024,-336,5,2025,-336,5,2026,-336,5,2027,-336,5,2028,-336,5,2029,-13,3,2030,-336,5,2031,-337,5,2032,-338,5,2033,-339,5,2034,-4,2,2035,-336,5,2036,-336,5,2037,-336,5,2038,-78,4,2039,-336,5,2040,-336,5,2041,-336,5,2042,-336,5,2043,-336,5,2044,-336,5,2045,-337,5,2046,-312,5,2047,-341,5,0,0,0"),
// leafSize 15
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,12,14,13,13,15,14,14,16,15,15,18,16,-1,1,17,-2,1,18,-3,1,19,-4,1,20,-10,2,21,-8,2,22,-11,2,23,-10,2,24,-11,2,25,-10,2,26,-13,2,27,-13,2,28,-13,2,29,-14,2,30,-15,2,31,-1,1,32,-15,2,33,3,5,34,-8,2,35,-5,2,36,3,5,37,-11,2,38,-10,2,39,3,5,40,-10,2,41,-13,2,42,3,5,43,-13,2,44,-14,2,45,3,5,46,-1,1,47,-2,1,48,4,8,49,-10,2,50,-11,2,51,-12,2,52,4,8,53,-8,2,54,-15,2,55,-10,2,56,4,8,57,-12,2,58,-13,2,59,-14,2,60,4,8,61,-1,1,62,-2,1,63,-3,1,64,-4,2,65,5,11,66,-14,2,67,-7,2,68,-8,2,69,-9,2,70,5,11,71,-11,2,72,-12,2,73,-13,2,74,-14,2,75,5,11,76,-1,1,77,-2,1,78,6,14,79,-4,2,80,-5,2,81,-6,2,82,-7,2,83,-8,2,84,6,14,85,-10,2,86,-11,2,87,-12,2,88,-13,2,89,-14,2,90,6,15,91,7,17,92,-2,1,93,-3,1,94,-4,2,95,-5,2,96,-6,2,97,-7,2,98,7,17,99,-9,2,100,-10,2,101,-11,2,102,-12,2,103,-13,2,104,-14,2,105,-15,3,106,-15,3,107,-9,2,108,-10,2,109,-11,2,110,-12,2,111,-13,2,112,-14,3,113,-15,3,114,-24,3,115,-25,3,116,-26,3,117,-27,3,118,-28,3,119,-29,3,120,-30,3,121,-30,3,122,-52,3,123,-45,3,124,-26,3,125,-60,3,126,-36,3,127,-52,3,128,-30,3,129,-39,3,130,-60,3,131,-56,3,132,-42,3,133,-43,3,134,-44,3,135,-45,3,136,-45,3,137,-39,3,138,-60,3,139,-49,3,140,-65,3,141,-51,3,142,-52,3,143,-45,3,144,-60,3,145,-70,3,146,-56,3,147,-57,3,148,-58,3,149,-59,3,150,-60,3,151,-60,3,152,-2,1,153,-75,3,154,-70,3,155,-65,3,156,-65,3,157,-7,2,158,-60,3,159,-75,3,160,-70,3,161,-11,2,162,-12,2,163,-13,2,164,-14,3,165,-75,3,166,-75,3,167,-2,1,168,-78,3,169,-78,3,170,-15,3,171,-6,2,172,-7,2,173,-75,3,174,-84,3,175,-10,2,176,-11,2,177,-12,2,178,-13,2,179,-14,3,180,-90,3,181,-90,3,182,-84,3,183,-3,1,184,-4,2,185,-5,2,186,-6,2,187,-7,2,188,-90,4,189,-9,2,190,-10,2,191,-11,2,192,-12,2,193,-90,4,194,-14,3,195,-15,3,196,-98,4,197,-98,4,198,-98,4,199,-98,4,200,-98,4,201,-98,4,202,-98,4,203,-15,3,204,-24,3,205,-25,3,206,-26,3,207,-90,4,208,-90,4,209,-90,4,210,-90,4,211,-15,3,212,-90,4,213,-90,4,214,-98,4,215,-90,4,216,-90,4,217,-90,4,218,-98,4,219,-90,4,220,-90,4,221,-90,4,222,-90,4,223,-90,4,224,-90,4,225,3,8,226,-1,0,227,-2,1,228,-90,4,229,-4,2,230,-90,4,231,-6,2,232,-90,4,233,-8,2,234,-9,2,235,-10,2,236,-11,2,237,-12,2,238,-13,2,239,-14,3,240,-90,4,241,-91,4,242,-98,4,243,-90,4,244,-90,4,245,-90,4,246,-91,4,247,-90,4,248,-98,4,249,-90,4,250,-90,4,251,-26,3,252,3,8,253,-28,3,254,-29,3,255,-90,4,256,-91,4,257,-98,4,258,-90,4,259,-91,4,260,-15,3,261,-90,4,262,-90,4,263,-98,4,264,-90,4,265,-100,4,266,-101,4,267,-102,4,268,-103,4,269,-14,3,270,3,8,271,-1,0,272,-2,1,273,-3,1,274,-4,2,275,-5,2,276,-6,2,277,-7,2,278,-8,2,279,-9,2,280,-10,2,281,-11,2,282,-12,2,283,-13,3,284,-14,3,285,-15,3,286,-15,3,287,-15,3,288,-18,3,289,-19,3,290,-15,3,291,-21,3,292,-22,3,293,-23,3,294,3,8,295,-25,3,296,-26,3,297,-27,3,298,-28,3,299,-29,3,300,4,12,301,-1,0,302,-2,1,303,-3,1,304,-4,2,305,-5,2,306,-6,2,307,-7,2,308,-8,2,309,-39,3,310,-10,2,311,-11,2,312,-42,3,313,-13,3,314,-14,3,315,-45,3,316,-91,4,317,-2,1,318,-48,3,319,-4,2,320,-5,2,321,-21,3,322,-52,3,323,-98,4,324,-15,3,325,-25,3,326,-56,3,327,-27,3,328,-28,3,329,-29,3,330,-60,4,331,-60,4,332,-60,4,333,-60,4,334,-60,4,335,-65,4,336,4,12,337,-15,3,338,-68,4,339,-39,3,340,-70,4,341,-71,4,342,-72,4,343,-73,4,344,-74,4,345,-75,4,346,-75,4,347,-75,4,348,-78,4,349,-75,4,350,-75,4,351,-75,4,352,-75,4,353,-83,4,354,-84,4,355,-85,4,356,-86,4,357,-87,4,358,-88,4,359,-89,4,360,4,12,361,-1,0,362,-2,1,363,-3,1,364,-4,2,365,-5,2,366,-6,2,367,-7,2,368,-8,2,369,-9,2,370,-10,2,371,-11,2,372,-12,2,373,-13,3,374,-14,3,375,-15,3,376,-15,3,377,-15,3,378,-18,3,379,-15,3,380,-15,3,381,-21,3,382,-22,3,383,-23,3,384,-24,3,385,-25,3,386,-26,3,387,-27,3,388,-28,3,389,-29,3,390,-30,3,391,-91,4,392,4,12,393,-33,3,394,-4,2,395,-5,2,396,-36,3,397,-7,2,398,-98,4,399,-39,3,400,-30,3,401,-15,3,402,-42,3,403,-15,3,404,-15,3,405,-45,3,406,-45,3,407,-2,1,408,-48,3,409,-4,2,410,-5,2,411,-6,2,412,-52,3,413,-8,2,414,-15,3,415,-10,2,416,-56,4,417,-57,4,418,-58,4,419,-14,3,420,-60,4,421,-60,4,422,-60,4,423,-60,4,424,-60,4,425,-65,4,426,-66,4,427,-67,4,428,-68,4,429,-69,4,430,-70,4,431,-71,4,432,-72,4,433,-73,4,434,-74,4,435,-75,4,436,-75,4,437,-75,4,438,-78,4,439,-75,4,440,-75,4,441,-75,4,442,-75,4,443,-83,4,444,-84,4,445,-85,4,446,-86,4,447,-87,4,448,-88,4,449,-89,4,450,5,17,451,-1,0,452,-2,1,453,-3,1,454,-4,2,455,-5,2,456,-6,2,457,-7,2,458,-8,2,459,-9,2,460,-10,2,461,-11,2,462,-12,2,463,-13,3,464,-14,3,465,-15,3,466,-15,3,467,-15,3,468,-18,3,469,-15,3,470,-15,3,471,-21,3,472,-22,3,473,-23,3,474,-24,3,475,-25,3,476,-26,3,477,-27,3,478,-28,3,479,-29,3,480,-30,3,481,-30,3,482,-30,3,483,-33,3,484,-4,2,485,-5,2,486,-36,3,487,-7,2,488,-30,3,489,-39,3,490,-30,3,491,-15,3,492,-42,3,493,-15,3,494,-15,3,495,-45,3,496,-45,3,497,-2,1,498,-48,3,499,-4,2,500,-140,4,501,-6,2,502,-52,3,503,-8,2,504,-15,3,505,-10,2,506,-56,4,507,-57,4,508,-58,4,509,-59,4,510,-60,4,511,-60,4,512,-60,4,513,-60,4,514,-60,4,515,-65,4,516,-66,4,517,-67,4,518,-68,4,519,-69,4,520,-70,4,521,-71,4,522,-72,4,523,-73,4,524,-74,4,525,-75,4,526,-75,4,527,-75,4,528,-78,4,529,-4,2,530,-75,4,531,-75,4,532,-75,4,533,-83,4,534,-84,4,535,-85,4,536,-86,4,537,-87,4,538,-88,4,539,-89,4,540,-90,4,541,-91,4,542,-90,4,543,-90,4,544,-4,2,545,-90,4,546,-90,4,547,-90,4,548,-98,4,549,-99,4,550,-100,4,551,-101,4,552,-102,4,553,-103,4,554,-14,3,555,-15,3,556,-15,3,557,-98,4,558,-108,4,559,-109,4,560,-110,4,561,-111,4,562,-14,3,563,-15,3,564,-90,4,565,-90,4,566,-116,4,567,-117,4,568,-118,4,569,-119,4,570,-120,4,571,-121,4,572,-122,4,573,-123,4,574,-98,4,575,-125,4,576,-126,4,577,-127,4,578,-128,4,579,-129,4,580,-130,4,581,-131,4,582,-132,4,583,-133,4,584,-134,4,585,-135,4,586,-136,4,587,-137,4,588,-138,4,589,-4,2,590,-140,4,591,-6,2,592,-142,4,593,-143,4,594,-144,4,595,-145,4,596,-146,4,597,-147,4,598,-148,4,599,-14,3,600,-150,4,601,-151,4,602,-152,4,603,-153,4,604,-154,4,605,-155,4,606,-78,4,607,-15,3,608,-158,4,609,-75,4,610,-70,4,611,-161,4,612,-72,4,613,-73,4,614,-14,3,615,-75,4,616,-75,4,617,-75,4,618,-78,4,619,-78,4,620,-15,3,621,-75,4,622,-75,4,623,-75,4,624,-84,4,625,-85,4,626,-86,4,627,-87,4,628,-88,4,629,-14,3,630,-90,4,631,-90,4,632,-84,4,633,-90,4,634,-4,2,635,-90,4,636,-90,4,637,-90,4,638,-90,4,639,-90,4,640,-90,4,641,-90,4,642,-90,4,643,-90,4,644,-14,3,645,-15,3,646,-98,4,647,-98,4,648,-98,4,649,-98,4,650,-98,4,651,-98,4,652,-14,3,653,-15,3,654,-294,4,655,-90,4,656,-90,4,657,-90,4,658,-90,4,659,-90,4,660,-300,4,661,-15,3,662,-2,1,663,-90,4,664,-4,2,665,-90,4,666,-90,4,667,-90,4,668,-8,2,669,-90,4,670,-10,2,671,-311,4,672,-90,4,673,-13,3,674,-14,3,675,-225,4,676,-226,4,677,-2,1,678,-90,4,679,-4,2,680,-90,4,681,-6,2,682,-90,4,683,-8,2,684,-9,2,685,-235,4,686,-90,4,687,-237,4,688,-13,3,689,-14,3,690,-90,4,691,-91,4,692,-98,4,693,-90,4,694,-90,4,695,-90,4,696,-336,4,697,-15,3,698,-98,4,699,-75,4,700,-70,4,701,-101,4,702,-252,4,703,-73,4,704,-14,3,705,-75,4,706,-75,4,707,-75,4,708,-78,4,709,-78,4,710,-15,3,711,-75,4,712,-75,4,713,-75,4,714,-84,4,715,-85,4,716,-86,4,717,-87,4,718,-88,4,719,-14,3,720,-360,4,721,-360,4,722,-2,1,723,-360,4,724,-4,2,725,-5,2,726,-6,2,727,-7,2,728,-360,5,729,-360,5,730,-360,5,731,-360,5,732,-360,5,733,-13,3,734,-14,3,735,-15,3,736,-90,4,737,-15,3,738,-18,3,739,-15,3,740,-15,3,741,-360,5,742,-360,5,743,-360,5,744,-294,4,745,-360,5,746,-360,5,747,-360,5,748,-360,5,749,-360,5,750,-300,4,751,-301,4,752,-2,1,753,-303,4,754,-4,2,755,-5,2,756,-360,5,757,-307,5,758,-308,5,759,-360,5,760,-310,5,761,-311,5,762,-360,5,763,-13,3,764,-14,3,765,-360,5,766,-91,4,767,-362,5,768,-360,5,769,-364,5,770,-90,4,771,-366,5,772,-360,5,773,-98,4,774,-375,5,775,-370,5,776,-56,4,777,-57,4,778,-58,4,779,-374,5,780,-60,4,781,-60,4,782,-60,4,783,-363,5,784,-60,4,785,-360,5,786,-336,5,787,-360,5,788,-360,5,789,-360,5,790,-360,5,791,-360,5,792,-360,5,793,-360,5,794,-360,5,795,-360,5,796,-361,5,797,-362,5,798,-360,5,799,-364,5,800,-365,5,801,-366,5,802,-367,5,803,-360,5,804,-360,5,805,-360,5,806,-360,5,807,-360,5,808,-360,5,809,-360,5,810,-360,5,811,-361,5,812,-362,5,813,-363,5,814,-364,5,815,-365,5,816,-366,5,817,-367,5,818,-368,5,819,-369,5,820,-370,5,821,-371,5,822,-372,5,823,-360,5,824,-374,5,825,-375,5,826,-376,5,827,-377,5,828,-378,5,829,-379,5,830,-380,5,831,-381,5,832,-382,5,833,-383,5,834,-384,5,835,-385,5,836,-386,5,837,-387,5,838,-388,5,839,-389,5,840,-390,5,841,-391,5,842,-392,5,843,-393,5,844,-394,5,845,-395,5,846,-396,5,847,-397,5,848,-398,5,849,-399,5,850,-400,5,851,-401,5,852,-402,5,853,-403,5,854,-404,5,855,-405,5,856,-406,5,857,-407,5,858,-408,5,859,-409,5,860,-360,5,861,-411,5,862,-412,5,863,-413,5,864,-414,5,865,-415,5,866,-56,4,867,-360,5,868,-360,5,869,-405,5,870,-360,5,871,-361,5,872,-362,5,873,-363,5,874,-364,5,875,-425,5,876,-426,5,877,-427,5,878,-428,5,879,-429,5,880,-430,5,881,-431,5,882,-432,5,883,-433,5,884,-434,5,885,-435,5,886,-436,5,887,-437,5,888,-438,5,889,-439,5,890,-440,5,891,-441,5,892,-442,5,893,-443,5,894,-444,5,895,-445,5,896,-446,5,897,-447,5,898,-448,5,899,-449,5,900,-450,5,901,-450,5,902,-450,5,903,-450,5,904,-450,5,905,-450,5,906,-450,5,907,-450,5,908,-450,5,909,-450,5,910,-450,5,911,-450,5,912,-450,5,913,-13,3,914,-14,3,915,-450,5,916,-451,5,917,-452,5,918,-450,5,919,-454,5,920,-455,5,921,-450,5,922,-450,5,923,-450,5,924,-450,5,925,-450,5,926,-450,5,927,-450,5,928,-450,5,929,-450,5,930,-450,5,931,-451,5,932,-452,5,933,-450,5,934,-454,5,935,-455,5,936,-450,5,937,-457,5,938,-458,5,939,-450,5,940,-460,5,941,-15,3,942,-450,5,943,-15,3,944,-15,3,945,-450,5,946,-451,5,947,-452,5,948,-450,5,949,-454,5,950,-450,5,951,-456,5,952,-52,4,953,-458,5,954,-15,3,955,-460,5,956,-56,4,957,-57,4,958,-58,4,959,-59,4,960,-60,4,961,-60,4,962,-60,4,963,-60,4,964,-60,4,965,-450,5,966,-450,5,967,-450,5,968,-450,5,969,-450,5,970,-450,5,971,-450,5,972,-450,5,973,-450,5,974,-450,5,975,-450,5,976,-451,5,977,-452,5,978,-450,5,979,-454,5,980,-455,5,981,-456,5,982,-457,5,983,-450,5,984,-450,5,985,-450,5,986,-450,5,987,-450,5,988,-450,5,989,-14,3,990,-450,5,991,-450,5,992,-452,5,993,-453,5,994,-454,5,995,-455,5,996,-456,5,997,-457,5,998,-450,5,999,-450,5,1000,-450,5,1001,-450,5,1002,-450,5,1003,-450,5,1004,-14,3,1005,-15,3,1006,-15,3,1007,-459,5,1008,-450,5,1009,-450,5,1010,-450,5,1011,-450,5,1012,-14,3,1013,-15,3,1014,-474,5,1015,-475,5,1016,-476,5,1017,-450,5,1018,-450,5,1019,-450,5,1020,-450,5,1021,-450,5,1022,-450,5,1023,-450,5,1024,-476,5,1025,-450,5,1026,-450,5,1027,-450,5,1028,-450,5,1029,-450,5,1030,-450,5,1031,-450,5,1032,-450,5,1033,-450,5,1034,-450,5,1035,-450,5,1036,-450,5,1037,-450,5,1038,-450,5,1039,-4,2,1040,-450,5,1041,-456,5,1042,-450,5,1043,-450,5,1044,-450,5,1045,-450,5,1046,-450,5,1047,-450,5,1048,-450,5,1049,-14,3,1050,-450,5,1051,-450,5,1052,-450,5,1053,-450,5,1054,-450,5,1055,-450,5,1056,-528,5,1057,-15,3,1058,-450,5,1059,-450,5,1060,-450,5,1061,-450,5,1062,-450,5,1063,-450,5,1064,-14,3,1065,-450,5,1066,-450,5,1067,-452,5,1068,-528,5,1069,-528,5,1070,-15,3,1071,-456,5,1072,-457,5,1073,-450,5,1074,-534,5,1075,-535,5,1076,-536,5,1077,-537,5,1078,-538,5,1079,-14,3,1080,3,10,1081,-1,0,1082,-2,1,1083,-3,1,1084,-4,2,1085,-5,2,1086,-6,2,1087,-7,2,1088,-8,2,1089,-9,2,1090,-10,2,1091,-11,2,1092,-12,2,1093,-13,3,1094,-14,3,1095,-15,3,1096,-15,3,1097,-15,3,1098,-18,3,1099,-15,3,1100,-15,3,1101,-21,3,1102,-22,3,1103,-23,3,1104,-24,3,1105,-25,3,1106,-26,3,1107,-27,3,1108,-28,3,1109,-29,3,1110,-30,3,1111,-30,3,1112,-30,3,1113,-33,3,1114,-4,2,1115,-5,2,1116,-36,3,1117,-7,2,1118,-30,3,1119,-39,3,1120,-30,3,1121,-15,3,1122,-42,3,1123,-15,3,1124,-15,3,1125,-45,3,1126,-45,3,1127,-2,1,1128,-48,3,1129,-4,2,1130,-5,2,1131,-6,2,1132,-52,4,1133,-8,2,1134,-15,3,1135,-55,4,1136,-56,4,1137,-57,4,1138,-58,4,1139,-59,4,1140,-60,4,1141,-60,4,1142,-60,4,1143,-60,4,1144,-60,4,1145,-65,4,1146,-66,4,1147,-67,4,1148,-68,4,1149,-69,4,1150,-70,4,1151,-71,4,1152,-72,4,1153,-73,4,1154,-74,4,1155,-75,4,1156,-75,4,1157,-75,4,1158,-78,4,1159,-4,2,1160,-75,4,1161,-75,4,1162,-75,4,1163,-83,4,1164,-84,4,1165,-85,4,1166,-86,4,1167,-87,4,1168,-88,4,1169,-14,3,1170,-90,4,1171,-91,4,1172,-90,4,1173,-90,4,1174,-4,2,1175,-5,2,1176,-90,4,1177,-90,4,1178,-98,4,1179,-99,4,1180,-100,4,1181,-101,4,1182,-102,4,1183,-103,4,1184,-14,3,1185,-15,3,1186,-15,3,1187,-98,4,1188,-108,4,1189,-109,4,1190,-110,4,1191,-111,4,1192,-14,3,1193,-15,3,1194,-294,5,1195,-90,4,1196,-90,4,1197,-90,4,1198,-90,4,1199,-119,4,1200,-300,5,1201,-301,5,1202,-302,5,1203,-123,4,1204,-98,4,1205,-125,4,1206,-126,4,1207,-127,4,1208,-98,4,1209,-129,4,1210,-130,4,1211,-131,4,1212,-132,4,1213,-13,3,1214,-14,3,1215,-135,4,1216,-136,4,1217,-137,4,1218,-138,4,1219,-4,2,1220,-140,4,1221,-6,2,1222,-142,4,1223,-143,4,1224,-144,4,1225,-70,4,1226,-146,4,1227,-147,4,1228,-148,4,1229,-14,3,1230,-150,4,1231,-151,4,1232,-2,1,1233,-75,4,1234,-70,4,1235,-65,4,1236,-336,5,1237,-15,3,1238,-60,4,1239,-75,4,1240,-70,4,1241,-71,4,1242,-72,4,1243,-73,4,1244,-74,4,1245,-75,4,1246,-75,4,1247,-75,4,1248,-78,4,1249,-78,4,1250,-75,4,1251,-75,4,1252,-75,4,1253,-75,4,1254,-84,4,1255,-85,4,1256,-86,4,1257,-87,4,1258,-88,4,1259,-14,3,1260,-360,5,1261,-361,5,1262,-362,5,1263,-363,5,1264,-360,5,1265,-360,5,1266,-366,5,1267,-367,5,1268,-368,5,1269,-369,5,1270,-370,5,1271,-371,5,1272,-372,5,1273,-13,3,1274,-14,3,1275,-15,3,1276,-98,4,1277,-15,3,1278,-360,5,1279,-15,3,1280,-15,3,1281,-360,5,1282,-360,5,1283,-383,5,1284,-384,5,1285,-385,5,1286,-386,5,1287,-387,5,1288,-388,5,1289,-389,5,1290,-390,5,1291,-391,5,1292,-392,5,1293,-393,5,1294,-390,5,1295,-390,5,1296,-396,5,1297,-390,5,1298,-398,5,1299,-399,5,1300,-400,5,1301,-15,3,1302,-402,5,1303,-15,3,1304,-15,3,1305,-405,5,1306,-406,5,1307,-405,5,1308,-408,5,1309,-405,5,1310,-90,4,1311,-405,5,1312,-412,5,1313,-405,5,1314,-15,3,1315,-415,5,1316,-56,4,1317,-57,4,1318,-58,4,1319,-14,3,1320,-60,4,1321,-60,4,1322,-60,4,1323,-75,4,1324,-60,4,1325,-65,4,1326,-360,5,1327,-360,5,1328,-360,5,1329,-360,5,1330,-360,5,1331,-360,5,1332,-360,5,1333,-360,5,1334,-360,5,1335,-360,5,1336,-361,5,1337,-362,5,1338,-360,5,1339,-360,5,1340,-360,5,1341,-366,5,1342,-367,5,1343,-360,5,1344,-360,5,1345,-360,5,1346,-360,5,1347,-360,5,1348,-360,5,1349,-14,3,1350,3,10,1351,-1,0,1352,-2,1,1353,-3,1,1354,-4,2,1355,-5,2,1356,-6,2,1357,-7,2,1358,-8,2,1359,-9,2,1360,-10,2,1361,-11,2,1362,-12,2,1363,-13,3,1364,-14,3,1365,-15,3,1366,-15,3,1367,-15,3,1368,-18,3,1369,-15,3,1370,-15,3,1371,-21,3,1372,-22,3,1373,-23,3,1374,-24,3,1375,-25,3,1376,-26,3,1377,-27,3,1378,-28,3,1379,-29,3,1380,-30,3,1381,-30,3,1382,-30,3,1383,-33,3,1384,-4,2,1385,-5,2,1386,-36,3,1387,-7,2,1388,-30,3,1389,-39,3,1390,-30,3,1391,-15,3,1392,-42,3,1393,-15,3,1394,-15,3,1395,-45,3,1396,-45,3,1397,-2,1,1398,-48,3,1399,-4,2,1400,-5,2,1401,-51,4,1402,-52,4,1403,-8,2,1404,-15,3,1405,-55,4,1406,-56,4,1407,-57,4,1408,-58,4,1409,-59,4,1410,-60,4,1411,-60,4,1412,-60,4,1413,-60,4,1414,-60,4,1415,-65,4,1416,-66,4,1417,-67,4,1418,-68,4,1419,-69,4,1420,-70,4,1421,-71,4,1422,-72,4,1423,-73,4,1424,-74,4,1425,-75,4,1426,-75,4,1427,-75,4,1428,-78,4,1429,-4,2,1430,-75,4,1431,-75,4,1432,-75,4,1433,-83,4,1434,-84,4,1435,-85,4,1436,-86,4,1437,-87,4,1438,-88,4,1439,-14,3,1440,4,15,1441,-91,4,1442,-2,1,1443,-3,1,1444,-4,2,1445,-5,2,1446,-6,2,1447,-7,2,1448,-98,4,1449,-9,2,1450,-10,2,1451,-11,2,1452,-12,2,1453,-13,3,1454,-14,3,1455,-15,3,1456,-15,3,1457,-98,4,1458,-108,4,1459,-109,4,1460,-110,4,1461,-111,4,1462,-14,3,1463,-15,3,1464,-24,3,1465,-25,3,1466,-26,3,1467,-27,3,1468,-28,3,1469,-29,3,1470,-30,3,1471,-121,4,1472,-122,4,1473,-123,4,1474,-98,4,1475,-125,4,1476,-36,3,1477,-127,4,1478,-98,4,1479,-39,3,1480,-130,4,1481,-131,4,1482,-42,3,1483,-15,3,1484,-15,3,1485,-45,3,1486,-136,4,1487,-137,4,1488,-138,4,1489,-4,2,1490,-140,4,1491,-51,4,1492,-52,4,1493,-143,4,1494,-144,4,1495,-70,4,1496,-56,4,1497,-57,4,1498,-58,4,1499,-59,4,1500,-60,4,1501,-60,4,1502,-60,4,1503,-75,4,1504,-70,4,1505,-65,4,1506,-78,4,1507,-67,4,1508,-60,4,1509,-75,4,1510,-70,4,1511,-71,4,1512,-72,4,1513,-73,4,1514,-74,4,1515,-75,4,1516,-75,4,1517,-75,4,1518,-78,4,1519,-78,4,1520,-75,4,1521,-75,4,1522,-75,4,1523,-75,4,1524,-84,4,1525,-85,4,1526,-86,4,1527,-87,4,1528,-88,4,1529,-14,3,1530,-90,4,1531,-91,4,1532,-84,4,1533,-90,4,1534,-4,2,1535,-5,2,1536,-90,4,1537,-90,4,1538,-98,4,1539,-90,4,1540,-100,4,1541,-101,4,1542,-102,4,1543,-103,4,1544,-14,3,1545,-15,3,1546,-98,4,1547,-98,4,1548,-108,4,1549,-109,4,1550,-110,4,1551,-111,4,1552,-14,3,1553,-15,3,1554,-90,4,1555,-90,4,1556,-90,4,1557,-90,4,1558,-90,4,1559,-90,4,1560,-120,4,1561,-15,3,1562,-122,4,1563,-123,4,1564,-98,4,1565,-125,4,1566,-126,4,1567,-127,4,1568,-98,4,1569,-129,4,1570,-130,4,1571,-131,4,1572,-132,4,1573,-133,4,1574,-134,4,1575,-225,5,1576,-226,5,1577,-227,5,1578,-138,4,1579,-229,5,1580,-140,4,1581,-231,5,1582,-142,4,1583,-143,4,1584,-144,4,1585,-70,4,1586,-146,4,1587,-237,5,1588,-238,5,1589,-239,5,1590,-60,4,1591,-60,4,1592,-98,4,1593,-75,4,1594,-70,4,1595,-65,4,1596,-78,4,1597,-15,3,1598,-60,4,1599,-75,4,1600,-70,4,1601,-71,4,1602,-252,5,1603,-73,4,1604,-74,4,1605,-75,4,1606,-75,4,1607,-75,4,1608,-78,4,1609,-78,4,1610,-75,4,1611,-75,4,1612,-75,4,1613,-75,4,1614,-84,4,1615,-85,4,1616,-86,4,1617,-87,4,1618,-88,4,1619,-14,3,1620,-270,5,1621,-271,5,1622,-272,5,1623,-273,5,1624,-274,5,1625,-275,5,1626,-276,5,1627,-277,5,1628,-278,5,1629,-279,5,1630,-280,5,1631,-281,5,1632,-282,5,1633,-13,3,1634,-14,3,1635,-285,5,1636,-98,4,1637,-272,5,1638,-288,5,1639,-274,5,1640,-275,5,1641,-291,5,1642,-292,5,1643,-293,5,1644,-294,5,1645,-295,5,1646,-296,5,1647,-297,5,1648,-298,5,1649,-299,5,1650,-300,5,1651,-301,5,1652,-302,5,1653,-303,5,1654,-304,5,1655,-305,5,1656,-306,5,1657,-307,5,1658,-308,5,1659,-309,5,1660,-310,5,1661,-311,5,1662,-312,5,1663,-13,3,1664,-14,3,1665,-315,5,1666,-316,5,1667,-317,5,1668,-318,5,1669,-4,2,1670,-90,4,1671,-321,5,1672,-322,5,1673,-323,5,1674,-15,3,1675,-325,5,1676,-56,4,1677,-327,5,1678,-328,5,1679,-329,5,1680,-270,5,1681,-271,5,1682,-272,5,1683,-75,4,1684,-274,5,1685,-270,5,1686,-336,5,1687,-60,4,1688,-270,5,1689,-339,5,1690,-270,5,1691,-270,5,1692,-270,5,1693,-343,5,1694,-344,5,1695,-345,5,1696,-346,5,1697,-347,5,1698,-348,5,1699,-4,2,1700,-350,5,1701,-351,5,1702,-352,5,1703,-353,5,1704,-354,5,1705,-355,5,1706,-356,5,1707,-357,5,1708,-358,5,1709,-359,5,1710,-360,5,1711,-361,5,1712,-362,5,1713,-363,5,1714,-4,2,1715,-365,5,1716,-366,5,1717,-367,5,1718,-368,5,1719,-369,5,1720,-370,5,1721,-371,5,1722,-372,5,1723,-13,3,1724,-14,3,1725,-15,3,1726,-15,3,1727,-15,3,1728,-18,3,1729,-15,3,1730,-15,3,1731,-381,5,1732,-382,5,1733,-383,5,1734,-384,5,1735,-385,5,1736,-386,5,1737,-387,5,1738,-388,5,1739,-389,5,1740,-390,5,1741,-391,5,1742,-392,5,1743,-393,5,1744,-4,2,1745,-395,5,1746,-396,5,1747,-397,5,1748,-398,5,1749,-399,5,1750,-400,5,1751,-15,3,1752,-402,5,1753,-15,3,1754,-15,3,1755,-405,5,1756,-406,5,1757,-407,5,1758,-408,5,1759,-4,2,1760,-410,5,1761,-411,5,1762,-52,4,1763,-413,5,1764,-15,3,1765,-415,5,1766,-56,4,1767,-57,4,1768,-58,4,1769,-59,4,1770,-60,4,1771,-60,4,1772,-60,4,1773,-60,4,1774,-60,4,1775,-65,4,1776,-66,4,1777,-67,4,1778,-68,4,1779,-69,4,1780,-70,4,1781,-71,4,1782,-72,4,1783,-73,4,1784,-74,4,1785,-75,4,1786,-75,4,1787,-75,4,1788,-360,5,1789,-4,2,1790,-75,4,1791,-75,4,1792,-75,4,1793,-75,4,1794,-360,5,1795,-360,5,1796,-360,5,1797,-360,5,1798,-360,5,1799,-14,3,1800,4,16,1801,-1,0,1802,-2,1,1803,-3,1,1804,-4,2,1805,-5,2,1806,-6,2,1807,-7,2,1808,-8,2,1809,-9,2,1810,-10,2,1811,-11,2,1812,-12,2,1813,-13,3,1814,-14,3,1815,-15,3,1816,-15,3,1817,-15,3,1818,-18,3,1819,-15,3,1820,-15,3,1821,-21,3,1822,-22,3,1823,-23,3,1824,-24,3,1825,-25,3,1826,-26,3,1827,-27,3,1828,-28,3,1829,-29,3,1830,-30,3,1831,-30,3,1832,-30,3,1833,-33,3,1834,-4,2,1835,-5,2,1836,-36,3,1837,-7,2,1838,-30,3,1839,-39,3,1840,-30,3,1841,-15,3,1842,-42,3,1843,-15,3,1844,-15,3,1845,-45,3,1846,-45,3,1847,-2,1,1848,-48,4,1849,-4,2,1850,-5,2,1851,-51,4,1852,-52,4,1853,-53,4,1854,-15,3,1855,-55,4,1856,-56,4,1857,-57,4,1858,-58,4,1859,-59,4,1860,-60,4,1861,-60,4,1862,-60,4,1863,-60,4,1864,-60,4,1865,-65,4,1866,-66,4,1867,-67,4,1868,-68,4,1869,-69,4,1870,-70,4,1871,-71,4,1872,-72,4,1873,-73,4,1874,-74,4,1875,-75,4,1876,-75,4,1877,-75,4,1878,-78,4,1879,-4,2,1880,-75,4,1881,-75,4,1882,-75,4,1883,-83,4,1884,-84,4,1885,-85,4,1886,-86,4,1887,-87,4,1888,-88,4,1889,-14,3,1890,-90,4,1891,-91,4,1892,-90,4,1893,-90,4,1894,-4,2,1895,-5,2,1896,-90,4,1897,-90,4,1898,-98,4,1899,-90,4,1900,-100,4,1901,-101,4,1902,-102,4,1903,-103,4,1904,-14,3,1905,-15,3,1906,-15,3,1907,-98,4,1908,-108,4,1909,-109,4,1910,-110,4,1911,-111,4,1912,-14,3,1913,-15,3,1914,-90,4,1915,-90,4,1916,-90,4,1917,-90,4,1918,-90,4,1919,-90,4,1920,-120,4,1921,-91,4,1922,-122,4,1923,-123,4,1924,-98,4,1925,-125,4,1926,-126,4,1927,-127,4,1928,-98,4,1929,-129,4,1930,-130,4,1931,-131,4,1932,-132,4,1933,-133,4,1934,-134,4,1935,-135,4,1936,-136,4,1937,-137,4,1938,-138,4,1939,-4,2,1940,-140,4,1941,-6,2,1942,-142,4,1943,-143,4,1944,-144,4,1945,-70,4,1946,-146,4,1947,-147,4,1948,-148,4,1949,-14,3,1950,-60,4,1951,-60,4,1952,-60,4,1953,-75,4,1954,-70,4,1955,-65,4,1956,-78,4,1957,-15,3,1958,-60,4,1959,-75,4,1960,-70,4,1961,-71,4,1962,-72,4,1963,-73,4,1964,-74,4,1965,-75,4,1966,-75,4,1967,-75,4,1968,-78,4,1969,-78,4,1970,-75,4,1971,-75,4,1972,-75,4,1973,-75,4,1974,-84,4,1975,-85,4,1976,-86,4,1977,-87,4,1978,-88,4,1979,-14,3,1980,-90,4,1981,-90,4,1982,-84,4,1983,-90,4,1984,-4,2,1985,-5,2,1986,-90,4,1987,-90,4,1988,-90,4,1989,-90,4,1990,-90,4,1991,-90,4,1992,-90,4,1993,-90,4,1994,-14,3,1995,-15,3,1996,-98,4,1997,-90,4,1998,-98,4,1999,-98,4,2000,-98,4,2001,-98,4,2002,-14,3,2003,-15,3,2004,-90,4,2005,-90,4,2006,-90,4,2007,-90,4,2008,-90,4,2009,-90,4,2010,-90,4,2011,-15,3,2012,-90,4,2013,-90,4,2014,-90,4,2015,-90,4,2016,-90,4,2017,-90,4,2018,-98,4,2019,-90,4,2020,-90,4,2021,-90,4,2022,-90,4,2023,-90,4,2024,-90,4,2025,-225,5,2026,-226,5,2027,-227,5,2028,-90,4,2029,-229,5,2030,-90,4,2031,-231,5,2032,-90,4,2033,-233,5,2034,-234,5,2035,-235,5,2036,-90,4,2037,-237,5,2038,-238,5,2039,-239,5,2040,-60,4,2041,-60,4,2042,-98,4,2043,-75,4,2044,-70,4,2045,-65,4,2046,-78,4,2047,-15,3,0,0,0"),
// leafSize 16
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,12,14,13,13,15,14,14,16,15,15,18,16,16,19,17,-1,1,18,-2,1,19,-3,1,20,-4,1,21,-8,2,22,-11,2,23,-10,2,24,-8,2,25,-10,2,26,-13,2,27,-11,2,28,-13,2,29,-13,2,30,-15,2,31,-15,2,32,-16,2,33,3,5,34,-2,1,35,-16,2,36,3,5,37,-8,2,38,-10,2,39,3,5,40,-8,2,41,-13,2,42,3,5,43,-11,2,44,-13,2,45,3,5,46,-15,2,47,-15,2,48,3,5,49,-1,1,50,-2,1,51,-3,1,52,4,8,53,-5,2,54,-15,2,55,-7,2,56,4,8,57,-9,2,58,-10,2,59,-11,2,60,4,8,61,-13,2,62,-14,2,63,-15,2,64,4,8,65,5,11,66,-2,1,67,-3,1,68,-4,2,69,-5,2,70,5,11,71,-7,2,72,-8,2,73,-13,2,74,-10,2,75,5,11,76,-16,3,77,-13,2,78,6,14,79,-15,2,80,5,12,81,-1,1,82,-2,1,83,-3,1,84,6,14,85,-5,2,86,-6,2,87,-7,2,88,-8,2,89,-9,2,90,6,15,91,7,17,92,-12,2,93,-13,2,94,-14,2,95,-15,3,96,6,15,97,-1,1,98,7,17,99,-3,1,100,-4,2,101,-5,2,102,-6,2,103,-7,2,104,-8,2,105,7,18,106,-10,2,107,-11,2,108,-12,2,109,-13,2,110,-14,2,111,-15,3,112,7,18,113,-1,1,114,-2,1,115,-3,1,116,-4,2,117,-5,2,118,-6,2,119,-7,2,120,-8,2,121,-9,2,122,-10,2,123,-11,2,124,-12,2,125,-13,2,126,-14,3,127,-15,3,128,-16,3,129,-17,3,130,-18,3,131,-19,3,132,-20,3,133,-21,3,134,-22,3,135,-23,3,136,-24,3,137,-25,3,138,-26,3,139,-27,3,140,-28,3,141,-29,3,142,-30,3,143,-31,3,144,-32,3,145,-33,3,146,-56,3,147,-42,3,148,-52,3,149,-5,2,150,-45,3,151,-39,3,152,-56,3,153,-48,3,154,-42,3,155,-75,3,156,-60,3,157,-45,3,158,-16,3,159,-16,3,160,-48,3,161,-65,3,162,-64,3,163,-3,1,164,-52,3,165,-60,3,166,-70,3,167,-7,2,168,-56,3,169,-64,3,170,-80,3,171,-75,3,172,-60,3,173,-16,3,174,-78,3,175,-15,3,176,-64,3,177,-65,3,178,-80,3,179,-3,1,180,-75,3,181,-5,2,182,-70,3,183,-7,2,184,-8,2,185,-80,3,186,-90,3,187,-75,3,188,-16,3,189,-13,2,190,-78,3,191,-15,3,192,-96,4,193,-1,0,194,-96,4,195,-90,4,196,-84,4,197,-5,2,198,-6,2,199,-7,2,200,-8,2,201,-96,4,202,-90,4,203,-91,4,204,-96,4,205,-96,4,206,-14,3,207,-15,3,208,-96,4,209,-1,0,210,-105,4,211,-3,1,212,-4,2,213,-5,2,214,-6,2,215,-7,2,216,-8,2,217,-105,4,218,-106,4,219,-107,4,220,-108,4,221,-109,4,222,-14,3,223,-15,3,224,-112,4,225,-1,0,226,-2,1,227,-3,1,228,-4,2,229,-5,2,230,-6,2,231,-7,2,232,-8,2,233,-9,2,234,-112,4,235,-112,4,236,-112,4,237,-112,4,238,-14,3,239,-15,3,240,-16,3,241,-16,3,242,-16,3,243,-19,3,244,-16,3,245,-16,3,246,-112,4,247,-112,4,248,-112,4,249,-112,4,250,-112,4,251,-112,4,252,-112,4,253,-112,4,254,-112,4,255,-112,4,256,-112,4,257,-112,4,258,-105,4,259,-112,4,260,-112,4,261,-105,4,262,-112,4,263,-112,4,264,-112,4,265,-112,4,266,-112,4,267,-112,4,268,-112,4,269,-112,4,270,3,8,271,-16,3,272,-112,4,273,-112,4,274,-105,4,275,-105,4,276,-112,4,277,-112,4,278,-112,4,279,-112,4,280,-112,4,281,-112,4,282,-112,4,283,-112,4,284,-112,4,285,-16,3,286,-112,4,287,-15,3,288,3,8,289,-1,0,290,-2,1,291,-3,1,292,-4,2,293,-5,2,294,-6,2,295,-7,2,296,-8,2,297,-9,2,298,-10,2,299,-11,2,300,-12,2,301,-13,3,302,-14,3,303,-15,3,304,-16,3,305,-16,3,306,-96,4,307,-90,4,308,-84,4,309,-16,3,310,-22,3,311,-23,3,312,-24,3,313,-96,4,314,-90,4,315,3,8,316,-28,3,317,-29,3,318,-30,3,319,-31,3,320,-96,4,321,-96,4,322,-105,4,323,-96,4,324,-4,2,325,-96,4,326,-96,4,327,-96,4,328,-96,4,329,-105,4,330,-106,4,331,-107,4,332,-108,4,333,-109,4,334,-14,3,335,-15,3,336,3,8,337,-1,0,338,-2,1,339,-3,1,340,-4,2,341,-5,2,342,-6,2,343,-7,2,344,-8,2,345,-9,2,346,-10,2,347,-11,2,348,-12,2,349,-13,3,350,-14,3,351,-15,3,352,-16,3,353,-16,3,354,-16,3,355,-19,3,356,-16,3,357,-16,3,358,-22,3,359,-23,3,360,-24,3,361,-25,3,362,-26,3,363,-27,3,364,-28,3,365,-29,3,366,-30,3,367,-31,3,368,-32,3,369,-33,3,370,-32,3,371,-32,3,372,-36,3,373,-5,2,374,-7,2,375,-39,3,376,-32,3,377,-31,3,378,-42,3,379,-16,3,380,-16,3,381,-45,3,382,-16,3,383,-16,3,384,4,12,385,-1,0,386,-2,1,387,-3,1,388,-4,2,389,-5,2,390,-6,2,391,-7,2,392,-8,2,393,-9,2,394,-10,2,395,-11,2,396,-60,4,397,-13,3,398,-14,3,399,-15,3,400,-112,4,401,-65,4,402,-112,4,403,-112,4,404,-4,2,405,-5,2,406,-70,4,407,-23,3,408,-24,3,409,-25,3,410,-26,3,411,-75,4,412,-28,3,413,-29,3,414,-30,3,415,-31,3,416,-80,4,417,-80,4,418,-80,4,419,-80,4,420,-84,4,421,-80,4,422,-80,4,423,-80,4,424,-80,4,425,-89,4,426,-90,4,427,-91,4,428,-92,4,429,-93,4,430,-14,3,431,-15,3,432,-96,4,433,-96,4,434,-98,4,435,-96,4,436,-4,2,437,-96,4,438,-96,4,439,-96,4,440,-96,4,441,-105,4,442,-106,4,443,-107,4,444,-108,4,445,-109,4,446,-14,3,447,-15,3,448,4,13,449,-1,0,450,-2,1,451,-3,1,452,-4,2,453,-5,2,454,-6,2,455,-7,2,456,-8,2,457,-9,2,458,-10,2,459,-11,2,460,-12,2,461,-13,3,462,-14,3,463,-15,3,464,-16,3,465,-16,3,466,-16,3,467,-19,3,468,-16,3,469,-16,3,470,-22,3,471,-23,3,472,-24,3,473,-25,3,474,-26,3,475,-27,3,476,-28,3,477,-29,3,478,-30,3,479,-31,3,480,5,17,481,-1,0,482,-2,1,483,-3,1,484,-4,2,485,-5,2,486,-6,2,487,-7,2,488,-8,2,489,-9,2,490,-10,2,491,-11,2,492,-12,2,493,-13,3,494,-14,3,495,-15,3,496,-16,3,497,-16,3,498,-16,3,499,-19,3,500,-52,3,501,-16,3,502,-22,3,503,-23,3,504,-56,4,505,-25,3,506,-26,3,507,-27,3,508,-60,4,509,-29,3,510,-30,3,511,-31,3,512,-64,4,513,-65,4,514,-64,4,515,-64,4,516,-64,4,517,-64,4,518,-70,4,519,-71,4,520,-72,4,521,-73,4,522,-74,4,523,-75,4,524,-60,4,525,-77,4,526,-78,4,527,-64,4,528,-80,4,529,-80,4,530,-80,4,531,-80,4,532,-84,4,533,-80,4,534,-80,4,535,-80,4,536,-80,4,537,-96,4,538,-90,4,539,-91,4,540,-92,4,541,-93,4,542,-14,3,543,-15,3,544,-96,4,545,-96,4,546,-98,4,547,-96,4,548,-4,2,549,-5,2,550,-96,4,551,-96,4,552,-96,4,553,-105,4,554,-106,4,555,-107,4,556,-108,4,557,-109,4,558,-14,3,559,-15,3,560,5,17,561,-1,0,562,-2,1,563,-3,1,564,-4,2,565,-5,2,566,-6,2,567,-7,2,568,-8,2,569,-9,2,570,-10,2,571,-11,2,572,-12,2,573,-13,3,574,-14,3,575,-15,3,576,-16,3,577,-16,3,578,-16,3,579,-19,3,580,-16,3,581,-16,3,582,-22,3,583,-23,3,584,-24,3,585,-25,3,586,-26,3,587,-27,3,588,-28,3,589,-29,3,590,-30,3,591,-31,3,592,-32,3,593,-33,3,594,-32,3,595,-32,3,596,-36,3,597,-5,2,598,-7,2,599,-39,3,600,-32,3,601,-15,3,602,-42,3,603,-16,3,604,-16,3,605,-45,3,606,-16,3,607,-16,3,608,-48,3,609,-48,3,610,-2,1,611,-48,3,612,-52,4,613,-5,2,614,-15,3,615,-16,3,616,-56,4,617,-57,4,618,-58,4,619,-59,4,620,-60,4,621,-61,4,622,-62,4,623,-63,4,624,-64,4,625,-65,4,626,-64,4,627,-64,4,628,-64,4,629,-64,4,630,-70,4,631,-71,4,632,-72,4,633,-73,4,634,-74,4,635,-75,4,636,-60,4,637,-77,4,638,-78,4,639,-64,4,640,-80,4,641,-80,4,642,-80,4,643,-80,4,644,-84,4,645,-80,4,646,-80,4,647,-80,4,648,-80,4,649,-89,4,650,-90,4,651,-91,4,652,-92,4,653,-93,4,654,-14,3,655,-15,3,656,-96,4,657,-96,4,658,-98,4,659,-96,4,660,-4,2,661,-5,2,662,-96,4,663,-96,4,664,-96,4,665,-105,4,666,-106,4,667,-107,4,668,-108,4,669,-109,4,670,-14,3,671,-15,3,672,-112,4,673,-112,4,674,-112,4,675,-112,4,676,-4,2,677,-5,2,678,-112,4,679,-112,4,680,-112,4,681,-112,4,682,-112,4,683,-123,4,684,-124,4,685,-13,3,686,-14,3,687,-15,3,688,-16,3,689,-16,3,690,-16,3,691,-19,3,692,-16,3,693,-16,3,694,-22,3,695,-23,3,696,-24,3,697,-112,4,698,-112,4,699,-112,4,700,-112,4,701,-112,4,702,-112,4,703,-112,4,704,-144,4,705,-145,4,706,-146,4,707,-147,4,708,-148,4,709,-5,2,710,-150,4,711,-151,4,712,-152,4,713,-153,4,714,-154,4,715,-75,4,716,-156,4,717,-157,4,718,-16,3,719,-16,3,720,-160,4,721,-65,4,722,-64,4,723,-163,4,724,-164,4,725,-165,4,726,-70,4,727,-16,3,728,-168,4,729,-64,4,730,-80,4,731,-75,4,732,-60,4,733,-16,3,734,-78,4,735,-15,3,736,-80,4,737,-65,4,738,-80,4,739,-80,4,740,-75,4,741,-80,4,742,-70,4,743,-80,4,744,-80,4,745,-80,4,746,-90,4,747,-75,4,748,-60,4,749,-93,4,750,-78,4,751,-15,3,752,-96,4,753,-96,4,754,-96,4,755,-90,4,756,-84,4,757,-5,2,758,-96,4,759,-96,4,760,-96,4,761,-96,4,762,-90,4,763,-91,4,764,-96,4,765,-96,4,766,-14,3,767,-15,3,768,-96,4,769,-96,4,770,-105,4,771,-96,4,772,-4,2,773,-5,2,774,-96,4,775,-96,4,776,-96,4,777,-105,4,778,-106,4,779,-107,4,780,-108,4,781,-109,4,782,-14,3,783,-15,3,784,-112,4,785,-112,4,786,-112,4,787,-112,4,788,-4,2,789,-5,2,790,-112,4,791,-112,4,792,-112,4,793,-112,4,794,-112,4,795,-112,4,796,-112,4,797,-13,3,798,-14,3,799,-15,3,800,-16,3,801,-16,3,802,-16,3,803,-19,3,804,-16,3,805,-16,3,806,-22,3,807,-23,3,808,-24,3,809,-112,4,810,-112,4,811,-112,4,812,-112,4,813,-112,4,814,-112,4,815,-112,4,816,-336,5,817,-337,5,818,-338,5,819,-339,5,820,-112,4,821,-341,5,822,-112,4,823,-112,4,824,-344,5,825,-112,4,826,-112,4,827,-75,4,828,-112,4,829,-112,4,830,-350,5,831,-351,5,832,-384,5,833,-385,5,834,-386,5,835,-387,5,836,-112,4,837,-389,5,838,-390,5,839,-391,5,840,-392,5,841,-80,4,842,-90,4,843,-75,4,844,-60,4,845,-13,3,846,-398,5,847,-399,5,848,-288,5,849,-289,5,850,-290,5,851,-291,5,852,-292,5,853,-293,5,854,-294,5,855,-295,5,856,-296,5,857,-96,4,858,-298,5,859,-75,4,860,-300,5,861,-301,5,862,-302,5,863,-303,5,864,-96,4,865,-96,4,866,-96,4,867,-90,4,868,-84,4,869,-5,2,870,-96,4,871,-96,4,872,-96,4,873,-96,4,874,-90,4,875,-315,5,876,-316,5,877,-96,4,878,-318,5,879,-15,3,880,-96,4,881,-96,4,882,-105,4,883,-96,4,884,-4,2,885,-5,2,886,-96,4,887,-96,4,888,-96,4,889,-105,4,890,-106,4,891,-107,4,892,-108,4,893,-109,4,894,-14,3,895,-15,3,896,-336,5,897,-337,5,898,-338,5,899,-339,5,900,-340,5,901,-341,5,902,-342,5,903,-343,5,904,-344,5,905,-345,5,906,-346,5,907,-347,5,908,-348,5,909,-13,3,910,-350,5,911,-351,5,912,-352,5,913,-353,5,914,-354,5,915,-355,5,916,-356,5,917,-357,5,918,-358,5,919,-359,5,920,-360,5,921,-361,5,922,-362,5,923,-363,5,924,-364,5,925,-365,5,926,-366,5,927,-367,5,928,-448,5,929,-449,5,930,-450,5,931,-451,5,932,-452,5,933,-453,5,934,-454,5,935,-375,5,936,-456,5,937,-457,5,938,-458,5,939,-459,5,940,-460,5,941,-381,5,942,-14,3,943,-15,3,944,-384,5,945,-385,5,946,-386,5,947,-387,5,948,-388,5,949,-389,5,950,-390,5,951,-391,5,952,-392,5,953,-393,5,954,-394,5,955,-395,5,956,-336,5,957,-13,3,958,-14,3,959,-384,5,960,-400,5,961,-336,5,962,-402,5,963,-403,5,964,-404,5,965,-405,5,966,-406,5,967,-407,5,968,-408,5,969,-409,5,970,-410,5,971,-411,5,972,-412,5,973,-413,5,974,-414,5,975,-415,5,976,-416,5,977,-417,5,978,-418,5,979,-419,5,980,-420,5,981,-421,5,982,-422,5,983,-423,5,984,-424,5,985,-96,4,986,-426,5,987,-427,5,988,-428,5,989,-429,5,990,-14,3,991,-15,3,992,-432,5,993,-433,5,994,-434,5,995,-435,5,996,-436,5,997,-437,5,998,-438,5,999,-439,5,1000,-440,5,1001,-441,5,1002,-442,5,1003,-443,5,1004,-444,5,1005,-445,5,1006,-14,3,1007,-15,3,1008,-448,5,1009,-449,5,1010,-450,5,1011,-451,5,1012,-452,5,1013,-453,5,1014,-454,5,1015,-455,5,1016,-456,5,1017,-457,5,1018,-458,5,1019,-459,5,1020,-460,5,1021,-13,3,1022,-14,3,1023,-15,3,1024,-16,3,1025,-16,3,1026,-16,3,1027,-467,5,1028,-16,3,1029,-16,3,1030,-470,5,1031,-471,5,1032,-472,5,1033,-473,5,1034,-474,5,1035,-475,5,1036,-476,5,1037,-477,5,1038,-478,5,1039,-479,5,1040,-480,5,1041,-481,5,1042,-482,5,1043,-483,5,1044,-4,2,1045,-485,5,1046,-486,5,1047,-487,5,1048,-488,5,1049,-489,5,1050,-490,5,1051,-491,5,1052,-492,5,1053,-13,3,1054,-14,3,1055,-15,3,1056,-16,3,1057,-16,3,1058,-16,3,1059,-499,5,1060,-52,4,1061,-16,3,1062,-502,5,1063,-503,5,1064,-56,4,1065,-505,5,1066,-506,5,1067,-507,5,1068,-60,4,1069,-509,5,1070,-510,5,1071,-511,5,1072,-64,4,1073,-65,4,1074,-64,4,1075,-64,4,1076,-64,4,1077,-64,4,1078,-70,4,1079,-64,4,1080,-448,5,1081,-448,5,1082,-448,5,1083,-448,5,1084,-60,4,1085,-448,5,1086,-526,5,1087,-15,3,1088,-528,5,1089,-529,5,1090,-530,5,1091,-531,5,1092,-532,5,1093,-533,5,1094,-534,5,1095,-535,5,1096,-536,5,1097,-537,5,1098,-538,5,1099,-539,5,1100,-540,5,1101,-541,5,1102,-14,3,1103,-15,3,1104,-544,5,1105,-545,5,1106,-546,5,1107,-547,5,1108,-4,2,1109,-549,5,1110,-550,5,1111,-551,5,1112,-552,5,1113,-553,5,1114,-554,5,1115,-555,5,1116,-556,5,1117,-557,5,1118,-14,3,1119,-15,3,1120,-560,5,1121,-560,5,1122,-560,5,1123,-560,5,1124,-4,2,1125,-560,5,1126,-560,5,1127,-560,5,1128,-560,5,1129,-560,5,1130,-560,5,1131,-560,5,1132,-560,5,1133,-13,3,1134,-14,3,1135,-15,3,1136,-16,3,1137,-16,3,1138,-16,3,1139,-560,5,1140,-16,3,1141,-16,3,1142,-560,5,1143,-560,5,1144,-560,5,1145,-560,5,1146,-560,5,1147,-560,5,1148,-560,5,1149,-560,5,1150,-560,5,1151,-560,5,1152,-560,5,1153,-560,5,1154,-562,5,1155,-563,5,1156,-560,5,1157,-565,5,1158,-567,5,1159,-560,5,1160,-568,5,1161,-15,3,1162,-560,5,1163,-16,3,1164,-16,3,1165,-560,5,1166,-16,3,1167,-16,3,1168,-560,5,1169,-561,5,1170,-562,5,1171,-563,5,1172,-52,4,1173,-565,5,1174,-15,3,1175,-16,3,1176,-56,4,1177,-57,4,1178,-58,4,1179,-59,4,1180,-60,4,1181,-61,4,1182,-62,4,1183,-63,4,1184,-64,4,1185,-65,4,1186,-64,4,1187,-64,4,1188,-64,4,1189,-64,4,1190,-70,4,1191,-64,4,1192,-72,4,1193,-73,4,1194,-74,4,1195,-75,4,1196,-60,4,1197,-77,4,1198,-78,4,1199,-15,3,1200,-80,4,1201,-80,4,1202,-80,4,1203,-80,4,1204,-560,5,1205,-80,4,1206,-80,4,1207,-80,4,1208,-80,4,1209,-560,5,1210,-560,5,1211,-560,5,1212,-560,5,1213,-560,5,1214,-14,3,1215,-15,3,1216,-560,5,1217,-561,5,1218,-560,5,1219,-563,5,1220,-4,2,1221,-565,5,1222,-566,5,1223,-567,5,1224,-568,5,1225,-560,5,1226,-560,5,1227,-560,5,1228,-560,5,1229,-560,5,1230,-14,3,1231,-15,3,1232,-560,5,1233,-561,5,1234,-562,5,1235,-563,5,1236,-4,2,1237,-565,5,1238,-566,5,1239,-567,5,1240,-568,5,1241,-569,5,1242,-570,5,1243,-560,5,1244,-560,5,1245,-13,3,1246,-14,3,1247,-15,3,1248,-16,3,1249,-16,3,1250,-16,3,1251,-19,3,1252,-16,3,1253,-16,3,1254,-582,5,1255,-583,5,1256,-584,5,1257,-585,5,1258,-586,5,1259,-587,5,1260,-588,5,1261,-589,5,1262,-590,5,1263,-591,5,1264,-560,5,1265,-560,5,1266,-560,5,1267,-560,5,1268,-560,5,1269,-565,5,1270,-560,5,1271,-560,5,1272,-560,5,1273,-560,5,1274,-560,5,1275,-75,4,1276,-560,5,1277,-560,5,1278,-16,3,1279,-16,3,1280,-560,5,1281,-65,4,1282,-64,4,1283,-560,5,1284,-560,5,1285,-60,4,1286,-70,4,1287,-16,3,1288,-560,5,1289,-64,4,1290,-80,4,1291,-75,4,1292,-60,4,1293,-16,3,1294,-78,4,1295,-15,3,1296,-80,4,1297,-65,4,1298,-80,4,1299,-80,4,1300,-75,4,1301,-80,4,1302,-70,4,1303,-80,4,1304,-80,4,1305,-80,4,1306,-560,5,1307,-75,4,1308,-60,4,1309,-77,4,1310,-78,4,1311,-15,3,1312,-656,5,1313,-656,5,1314,-656,5,1315,-560,5,1316,-84,4,1317,-5,2,1318,-656,5,1319,-656,5,1320,-656,5,1321,-656,5,1322,-560,5,1323,-560,5,1324,-656,5,1325,-656,5,1326,-14,3,1327,-15,3,1328,-656,5,1329,-657,5,1330,-665,5,1331,-659,5,1332,-4,2,1333,-5,2,1334,-662,5,1335,-663,5,1336,-664,5,1337,-665,5,1338,-666,5,1339,-667,5,1340,-668,5,1341,-669,5,1342,-14,3,1343,-15,3,1344,3,10,1345,-1,0,1346,-2,1,1347,-3,1,1348,-4,2,1349,-5,2,1350,-6,2,1351,-7,2,1352,-8,2,1353,-9,2,1354,-10,2,1355,-11,2,1356,-12,2,1357,-13,3,1358,-14,3,1359,-15,3,1360,-16,3,1361,-16,3,1362,-16,3,1363,-19,3,1364,-16,3,1365,-16,3,1366,-22,3,1367,-23,3,1368,-24,3,1369,-25,3,1370,-26,3,1371,-27,3,1372,-28,3,1373,-29,3,1374,-30,3,1375,-31,3,1376,-32,3,1377,-33,3,1378,-32,3,1379,-32,3,1380,-36,3,1381,-5,2,1382,-7,2,1383,-39,3,1384,-32,3,1385,-15,3,1386,-42,3,1387,-16,3,1388,-16,3,1389,-45,3,1390,-16,3,1391,-16,3,1392,-384,5,1393,-385,5,1394,-386,5,1395,-387,5,1396,-52,4,1397,-384,5,1398,-384,5,1399,-391,5,1400,-56,4,1401,-80,4,1402,-90,4,1403,-75,4,1404,-60,4,1405,-61,4,1406,-14,3,1407,-15,3,1408,-288,5,1409,-65,4,1410,-290,5,1411,-291,5,1412,-292,5,1413,-293,5,1414,-70,4,1415,-295,5,1416,-296,5,1417,-560,5,1418,-298,5,1419,-75,4,1420,-300,5,1421,-13,3,1422,-78,4,1423,-288,5,1424,-80,4,1425,-80,4,1426,-80,4,1427,-80,4,1428,-84,4,1429,-80,4,1430,-80,4,1431,-80,4,1432,-80,4,1433,-665,5,1434,-90,4,1435,-91,4,1436,-92,4,1437,-93,4,1438,-14,3,1439,-15,3,1440,-96,4,1441,-96,4,1442,-98,4,1443,-96,4,1444,-4,2,1445,-5,2,1446,-96,4,1447,-96,4,1448,-96,4,1449,-105,4,1450,-106,4,1451,-107,4,1452,-108,4,1453,-109,4,1454,-14,3,1455,-15,3,1456,-336,5,1457,-337,5,1458,-338,5,1459,-339,5,1460,-4,2,1461,-341,5,1462,-342,5,1463,-343,5,1464,-344,5,1465,-345,5,1466,-346,5,1467,-347,5,1468,-348,5,1469,-13,3,1470,-14,3,1471,-15,3,1472,-16,3,1473,-16,3,1474,-16,3,1475,-355,5,1476,-16,3,1477,-16,3,1478,-358,5,1479,-359,5,1480,-360,5,1481,-361,5,1482,-362,5,1483,-363,5,1484,-364,5,1485,-365,5,1486,-366,5,1487,-367,5,1488,-448,5,1489,-449,5,1490,-448,5,1491,-448,5,1492,-4,2,1493,-448,5,1494,-448,5,1495,-375,5,1496,-448,5,1497,-448,5,1498,-448,5,1499,-448,5,1500,-448,5,1501,-381,5,1502,-14,3,1503,-15,3,1504,-384,5,1505,-385,5,1506,-386,5,1507,-387,5,1508,-4,2,1509,-389,5,1510,-390,5,1511,-391,5,1512,-392,5,1513,-393,5,1514,-394,5,1515,-395,5,1516,-60,4,1517,-13,3,1518,-14,3,1519,-15,3,1520,-400,5,1521,-65,4,1522,-80,4,1523,-403,5,1524,-75,4,1525,-400,5,1526,-336,5,1527,-407,5,1528,-408,5,1529,-80,4,1530,-90,4,1531,-336,5,1532,-412,5,1533,-413,5,1534,-414,5,1535,-415,5,1536,-336,5,1537,-337,5,1538,-96,4,1539,-90,4,1540,-420,5,1541,-341,5,1542,-342,5,1543,-343,5,1544,-344,5,1545,-96,4,1546,-426,5,1547,-427,5,1548,-428,5,1549,-429,5,1550,-14,3,1551,-15,3,1552,-432,5,1553,-433,5,1554,-105,4,1555,-435,5,1556,-4,2,1557,-432,5,1558,-438,5,1559,-439,5,1560,-440,5,1561,-441,5,1562,-442,5,1563,-443,5,1564,-444,5,1565,-445,5,1566,-14,3,1567,-15,3,1568,-448,5,1569,-449,5,1570,-450,5,1571,-451,5,1572,-4,2,1573,-448,5,1574,-448,5,1575,-455,5,1576,-456,5,1577,-457,5,1578,-458,5,1579,-459,5,1580,-460,5,1581,-13,3,1582,-14,3,1583,-15,3,1584,-16,3,1585,-16,3,1586,-16,3,1587,-448,5,1588,-16,3,1589,-16,3,1590,-448,5,1591,-448,5,1592,-448,5,1593,-448,5,1594,-448,5,1595,-448,5,1596,-448,5,1597,-477,5,1598,-478,5,1599,-479,5,1600,-480,5,1601,-481,5,1602,-480,5,1603,-483,5,1604,-4,2,1605,-480,5,1606,-480,5,1607,-480,5,1608,-480,5,1609,-489,5,1610,-490,5,1611,-491,5,1612,-492,5,1613,-13,3,1614,-14,3,1615,-15,3,1616,-16,3,1617,-16,3,1618,-16,3,1619,-480,5,1620,-52,4,1621,-16,3,1622,-480,5,1623,-480,5,1624,-56,4,1625,-480,5,1626,-480,5,1627,-480,5,1628,-60,4,1629,-480,5,1630,-480,5,1631,-480,5,1632,-64,4,1633,-65,4,1634,-64,4,1635,-64,4,1636,-64,4,1637,-64,4,1638,-70,4,1639,-64,4,1640,-72,4,1641,-73,4,1642,-74,4,1643,-75,4,1644,-60,4,1645,-77,4,1646,-78,4,1647,-15,3,1648,-80,4,1649,-80,4,1650,-80,4,1651,-80,4,1652,-448,5,1653,-80,4,1654,-80,4,1655,-80,4,1656,-80,4,1657,-441,5,1658,-448,5,1659,-448,5,1660,-448,5,1661,-448,5,1662,-14,3,1663,-15,3,1664,-448,5,1665,-449,5,1666,-448,5,1667,-451,5,1668,-4,2,1669,-448,5,1670,-448,5,1671,-455,5,1672,-456,5,1673,-448,5,1674,-448,5,1675,-448,5,1676,-448,5,1677,-448,5,1678,-14,3,1679,-15,3,1680,3,10,1681,-1,0,1682,-2,1,1683,-3,1,1684,-4,2,1685,-5,2,1686,-6,2,1687,-7,2,1688,-8,2,1689,-9,2,1690,-10,2,1691,-11,2,1692,-12,2,1693,-13,3,1694,-14,3,1695,-15,3,1696,-16,3,1697,-16,3,1698,-16,3,1699,-19,3,1700,-16,3,1701,-16,3,1702,-22,3,1703,-23,3,1704,-24,3,1705,-25,3,1706,-26,3,1707,-27,3,1708,-28,3,1709,-29,3,1710,-30,3,1711,-31,3,1712,-32,3,1713,-33,3,1714,-32,3,1715,-32,3,1716,-36,3,1717,-5,2,1718,-7,2,1719,-39,3,1720,-32,3,1721,-15,3,1722,-42,3,1723,-16,3,1724,-16,3,1725,-45,3,1726,-16,3,1727,-16,3,1728,-48,3,1729,-48,3,1730,-2,1,1731,-48,3,1732,-52,4,1733,-5,2,1734,-15,3,1735,-16,3,1736,-56,4,1737,-57,4,1738,-58,4,1739,-59,4,1740,-60,4,1741,-61,4,1742,-62,4,1743,-63,4,1744,-64,4,1745,-65,4,1746,-64,4,1747,-64,4,1748,-64,4,1749,-64,4,1750,-70,4,1751,-64,4,1752,-72,4,1753,-73,4,1754,-74,4,1755,-75,4,1756,-60,4,1757,-77,4,1758,-78,4,1759,-15,3,1760,-80,4,1761,-80,4,1762,-80,4,1763,-80,4,1764,-84,4,1765,-80,4,1766,-80,4,1767,-80,4,1768,-80,4,1769,-89,4,1770,-90,4,1771,-91,4,1772,-92,4,1773,-93,4,1774,-14,3,1775,-15,3,1776,-96,4,1777,-96,4,1778,-98,4,1779,-96,4,1780,-4,2,1781,-5,2,1782,-96,4,1783,-96,4,1784,-96,4,1785,-105,4,1786,-106,4,1787,-107,4,1788,-108,4,1789,-109,4,1790,-14,3,1791,-15,3,1792,-112,4,1793,-112,4,1794,-112,4,1795,-112,4,1796,-4,2,1797,-5,2,1798,-6,2,1799,-112,4,1800,-112,4,1801,-112,4,1802,-112,4,1803,-123,4,1804,-124,4,1805,-13,3,1806,-14,3,1807,-15,3,1808,-16,3,1809,-16,3,1810,-16,3,1811,-19,3,1812,-4,2,1813,-16,3,1814,-22,3,1815,-23,3,1816,-24,3,1817,-25,3,1818,-26,3,1819,-112,4,1820,-112,4,1821,-112,4,1822,-112,4,1823,-112,4,1824,-112,4,1825,-112,4,1826,-146,4,1827,-147,4,1828,-148,4,1829,-5,2,1830,-150,4,1831,-151,4,1832,-152,4,1833,-153,4,1834,-154,4,1835,-75,4,1836,-60,4,1837,-157,4,1838,-16,3,1839,-16,3,1840,-160,4,1841,-65,4,1842,-64,4,1843,-163,4,1844,-164,4,1845,-60,4,1846,-70,4,1847,-16,3,1848,-56,4,1849,-64,4,1850,-80,4,1851,-75,4,1852,-60,4,1853,-61,4,1854,-78,4,1855,-15,3,1856,-80,4,1857,-65,4,1858,-80,4,1859,-80,4,1860,-75,4,1861,-80,4,1862,-70,4,1863,-80,4,1864,-80,4,1865,-80,4,1866,-90,4,1867,-75,4,1868,-60,4,1869,-93,4,1870,-78,4,1871,-15,3,1872,-96,4,1873,-96,4,1874,-96,4,1875,-90,4,1876,-84,4,1877,-5,2,1878,-96,4,1879,-96,4,1880,-96,4,1881,-96,4,1882,-90,4,1883,-91,4,1884,-96,4,1885,-96,4,1886,-14,3,1887,-15,3,1888,-96,4,1889,-96,4,1890,-105,4,1891,-96,4,1892,-4,2,1893,-5,2,1894,-96,4,1895,-96,4,1896,-96,4,1897,-105,4,1898,-106,4,1899,-107,4,1900,-108,4,1901,-109,4,1902,-14,3,1903,-15,3,1904,-112,4,1905,-112,4,1906,-112,4,1907,-112,4,1908,-4,2,1909,-5,2,1910,-6,2,1911,-112,4,1912,-112,4,1913,-112,4,1914,-112,4,1915,-112,4,1916,-112,4,1917,-13,3,1918,-14,3,1919,-15,3,1920,-16,3,1921,-16,3,1922,-16,3,1923,-19,3,1924,-4,2,1925,-16,3,1926,-22,3,1927,-23,3,1928,-24,3,1929,-25,3,1930,-26,3,1931,-112,4,1932,-112,4,1933,-112,4,1934,-112,4,1935,-112,4,1936,-112,4,1937,-65,4,1938,-105,4,1939,-112,4,1940,-112,4,1941,-60,4,1942,-112,4,1943,-112,4,1944,-112,4,1945,-112,4,1946,-112,4,1947,-75,4,1948,-60,4,1949,-112,4,1950,-270,5,1951,-16,3,1952,-112,4,1953,-65,4,1954,-64,4,1955,-80,4,1956,-112,4,1957,-60,4,1958,-70,4,1959,-16,3,1960,-56,4,1961,-80,4,1962,-90,4,1963,-75,4,1964,-60,4,1965,-61,4,1966,-78,4,1967,-15,3,1968,-288,5,1969,-289,5,1970,-290,5,1971,-291,5,1972,-292,5,1973,-293,5,1974,-294,5,1975,-295,5,1976,-296,5,1977,-96,4,1978,-298,5,1979,-299,5,1980,-300,5,1981,-13,3,1982,-14,3,1983,-15,3,1984,-96,4,1985,-96,4,1986,-96,4,1987,-90,4,1988,-84,4,1989,-5,2,1990,-96,4,1991,-96,4,1992,-96,4,1993,-96,4,1994,-90,4,1995,-315,5,1996,-316,5,1997,-317,5,1998,-318,5,1999,-319,5,2000,-96,4,2001,-96,4,2002,-105,4,2003,-96,4,2004,-4,2,2005,-5,2,2006,-96,4,2007,-96,4,2008,-96,4,2009,-105,4,2010,-106,4,2011,-107,4,2012,-108,4,2013,-109,4,2014,-14,3,2015,-15,3,2016,-336,5,2017,-337,5,2018,-338,5,2019,-339,5,2020,-4,2,2021,-341,5,2022,-342,5,2023,-343,5,2024,-344,5,2025,-345,5,2026,-346,5,2027,-347,5,2028,-348,5,2029,-13,3,2030,-14,3,2031,-15,3,2032,-16,3,2033,-16,3,2034,-16,3,2035,-355,5,2036,-4,2,2037,-16,3,2038,-358,5,2039,-359,5,2040,-360,5,2041,-361,5,2042,-362,5,2043,-363,5,2044,-364,5,2045,-365,5,2046,-366,5,2047,-367,5,0,0,0"),
// leafSize 17
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,12,14,13,13,15,14,14,16,15,15,18,16,16,19,17,17,21,18,-2,1,19,-2,1,20,-3,1,21,-8,2,22,-11,2,23,-10,2,24,-8,2,25,-10,2,26,-13,2,27,-11,2,28,-13,2,29,-13,2,30,-15,2,31,-15,2,32,-16,2,33,-16,2,34,-17,2,35,-2,1,36,3,5,37,-17,2,38,-10,2,39,3,5,40,-8,2,41,-13,2,42,3,5,43,-11,2,44,-13,2,45,3,5,46,-15,2,47,-15,2,48,3,5,49,-16,2,50,-16,2,51,3,5,52,4,8,53,-2,1,54,-15,2,55,-7,2,56,4,8,57,-9,2,58,-10,2,59,-11,2,60,4,8,61,-13,2,62,-14,2,63,-15,2,64,4,8,65,5,11,66,-15,2,67,-16,2,68,4,9,69,-1,1,70,5,11,71,-7,2,72,-8,2,73,-13,2,74,-10,2,75,5,11,76,-16,3,77,-13,2,78,6,14,79,-15,2,80,5,12,81,-17,3,82,-14,2,83,-15,3,84,-16,3,85,5,12,86,-1,1,87,-2,1,88,-8,2,89,-9,2,90,6,15,91,7,17,92,-12,2,93,-13,2,94,-14,2,95,-15,3,96,6,15,97,-17,3,98,-13,2,99,-14,2,100,-15,3,101,-16,3,102,6,15,103,-1,1,104,-2,1,105,7,18,106,-10,2,107,-11,2,108,-12,2,109,-13,2,110,-14,2,111,-15,3,112,7,18,113,-17,3,114,-12,2,115,-13,2,116,-14,3,117,-15,3,118,-16,3,119,7,18,120,-1,1,121,-2,1,122,-10,2,123,-11,2,124,-12,2,125,-13,2,126,-14,3,127,-15,3,128,-16,3,129,-17,3,130,-11,2,131,-12,2,132,-13,2,133,-14,3,134,-15,3,135,-16,3,136,-17,3,137,-18,3,138,-19,3,139,-27,3,140,-28,3,141,-29,3,142,-30,3,143,-31,3,144,-32,3,145,-33,3,146,-34,3,147,-51,3,148,-29,3,149,-30,3,150,-31,3,151,-32,3,152,-33,3,153,-34,3,154,-42,3,155,-75,3,156,-60,3,157,-45,3,158,-39,3,159,-16,3,160,-48,3,161,-42,3,162,-60,3,163,-51,3,164,-68,3,165,-80,3,166,-64,3,167,-48,3,168,-56,3,169,-64,3,170,-51,3,171,-75,3,172,-60,3,173,-68,3,174,-78,3,175,-85,3,176,-64,3,177,-75,3,178,-15,3,179,-60,3,180,-68,3,181,-85,3,182,-80,3,183,-64,3,184,-65,3,185,-80,3,186,-90,3,187,-85,3,188,-1,0,189,-70,3,190,-85,4,191,-15,3,192,-96,4,193,-17,3,194,-75,3,195,-90,4,196,-16,3,197,-85,4,198,-96,4,199,-80,4,200,-17,3,201,-96,4,202,-90,4,203,-16,3,204,-102,4,205,-1,0,206,-2,1,207,-102,4,208,-96,4,209,-90,4,210,-105,4,211,-102,4,212,-15,3,213,-16,3,214,-102,4,215,-96,4,216,-17,3,217,-105,4,218,-14,3,219,-15,3,220,-16,3,221,-102,4,222,-1,0,223,-2,1,224,-112,4,225,-17,3,226,-112,4,227,-112,4,228,-14,3,229,-15,3,230,-16,3,231,-112,4,232,-17,3,233,-114,4,234,-115,4,235,-14,3,236,-15,3,237,-16,3,238,-119,4,239,-1,0,240,-16,3,241,-17,3,242,-119,4,243,-119,4,244,-119,4,245,-14,3,246,-15,3,247,-16,3,248,-17,3,249,-119,4,250,-119,4,251,-119,4,252,-14,3,253,-15,3,254,-16,3,255,-17,3,256,-112,4,257,-112,4,258,-112,4,259,-112,4,260,-112,4,261,-112,4,262,-112,4,263,-119,4,264,-119,4,265,-119,4,266,-119,4,267,-119,4,268,-119,4,269,-119,4,270,-119,4,271,-119,4,272,-119,4,273,-102,4,274,-112,4,275,-112,4,276,-112,4,277,-112,4,278,-112,4,279,-119,4,280,-119,4,281,-119,4,282,-119,4,283,-102,4,284,-102,4,285,-119,4,286,-119,4,287,-112,4,288,3,8,289,-85,4,290,-119,4,291,-119,4,292,-112,4,293,-112,4,294,-96,4,295,-119,4,296,-119,4,297,-9,2,298,-119,4,299,-85,4,300,-96,4,301,-119,4,302,-119,4,303,-15,3,304,-16,3,305,-17,3,306,3,8,307,-1,0,308,-2,1,309,-85,4,310,-96,4,311,-96,4,312,-6,2,313,-7,2,314,-8,2,315,-9,2,316,-102,4,317,-96,4,318,-80,4,319,-13,3,320,-14,3,321,-15,3,322,-16,3,323,-17,3,324,-17,3,325,-17,3,326,-102,4,327,-96,4,328,-90,4,329,-105,4,330,-14,3,331,-15,3,332,-16,3,333,-102,4,334,-96,4,335,-29,3,336,3,8,337,-1,0,338,-2,1,339,-33,3,340,-102,4,341,-5,2,342,-6,2,343,-112,4,344,-8,2,345,-9,2,346,-10,2,347,-11,2,348,-12,2,349,-13,3,350,-112,4,351,-15,3,352,-16,3,353,-17,3,354,-48,3,355,-15,3,356,-16,3,357,3,8,358,-1,0,359,-2,1,360,-3,1,361,-4,2,362,-5,2,363,-6,2,364,-7,2,365,-8,2,366,-9,2,367,-10,2,368,-11,2,369,-12,2,370,-13,3,371,-14,3,372,-15,3,373,-16,3,374,-17,3,375,-17,3,376,-17,3,377,-20,3,378,-16,3,379,-17,3,380,-23,3,381,-24,3,382,-25,3,383,-26,3,384,4,12,385,-28,3,386,-80,4,387,-30,3,388,-31,3,389,-32,3,390,-33,3,391,-34,3,392,-8,2,393,-36,3,394,-10,2,395,-11,2,396,-90,4,397,-13,3,398,-14,3,399,-42,3,400,-112,4,401,-17,3,402,-96,4,403,-80,4,404,-68,4,405,-48,3,406,-17,3,407,-119,4,408,4,12,409,-1,0,410,-2,1,411,-105,4,412,-4,2,413,-5,2,414,-6,2,415,-7,2,416,-8,2,417,-60,4,418,-112,4,419,-11,2,420,-12,2,421,-64,4,422,-14,3,423,-15,3,424,-16,3,425,-119,4,426,-90,4,427,-70,4,428,-102,4,429,-96,4,430,-96,4,431,-125,4,432,-75,4,433,-15,3,434,-16,3,435,-17,3,436,-96,4,437,-80,4,438,-102,4,439,-31,3,440,-32,3,441,-33,3,442,-85,4,443,-85,4,444,-85,4,445,-102,4,446,-96,4,447,-90,4,448,4,13,449,-1,0,450,-2,1,451,-3,1,452,-102,4,453,-96,4,454,-17,3,455,-119,4,456,-48,3,457,-15,3,458,-16,3,459,-102,4,460,-12,2,461,-13,3,462,-105,4,463,-15,3,464,-16,3,465,-17,3,466,-109,4,467,-14,3,468,-15,3,469,-112,4,470,-17,3,471,-114,4,472,-64,4,473,-14,3,474,-15,3,475,-16,3,476,4,13,477,-1,0,478,-2,1,479,-3,1,480,-4,2,481,-5,2,482,-6,2,483,-7,2,484,-8,2,485,-9,2,486,-10,2,487,-11,2,488,-12,2,489,-13,3,490,-14,3,491,-15,3,492,-16,3,493,-17,3,494,-17,3,495,-17,3,496,-20,3,497,-16,3,498,-90,4,499,-23,3,500,-24,3,501,-25,3,502,-26,3,503,-27,3,504,-96,4,505,-29,3,506,-30,3,507,-31,3,508,-32,3,509,-33,3,510,5,17,511,-1,0,512,-2,1,513,-3,1,514,-4,2,515,-5,2,516,-6,2,517,-7,2,518,-8,2,519,-9,2,520,-112,4,521,-11,2,522,-12,2,523,-13,3,524,-14,3,525,-15,3,526,-16,3,527,-17,3,528,-80,4,529,-17,3,530,-112,4,531,-123,4,532,-56,4,533,-85,4,534,-14,3,535,-15,3,536,-60,4,537,-112,4,538,-28,3,539,-29,3,540,-64,4,541,-31,3,542,-32,3,543,-33,3,544,-68,4,545,-68,4,546,-70,4,547,-85,4,548,-72,4,549,-96,4,550,-102,4,551,-75,4,552,-60,4,553,-105,4,554,-85,4,555,-96,4,556,-80,4,557,-64,4,558,-48,3,559,-15,3,560,5,17,561,-85,4,562,-2,1,563,-85,4,564,-4,2,565,-96,4,566,-90,4,567,-119,4,568,-8,2,569,-9,2,570,-10,2,571,-11,2,572,-96,4,573,-13,3,574,-14,3,575,-15,3,576,-16,3,577,-17,3,578,-102,4,579,-102,4,580,-102,4,581,-105,4,582,-106,4,583,-107,4,584,-108,4,585,-109,4,586,-14,3,587,-15,3,588,-112,4,589,-17,3,590,-80,4,591,-115,4,592,-14,3,593,-15,3,594,-16,3,595,5,17,596,-1,0,597,-2,1,598,-3,1,599,-4,2,600,-5,2,601,-6,2,602,-7,2,603,-8,2,604,-9,2,605,-10,2,606,-11,2,607,-12,2,608,-13,3,609,-14,3,610,-15,3,611,-16,3,612,-17,3,613,-17,3,614,-17,3,615,-105,4,616,-16,3,617,-17,3,618,-23,3,619,-24,3,620,-25,3,621,-26,3,622,-112,4,623,-28,3,624,-29,3,625,-30,3,626,-31,3,627,-32,3,628,-33,3,629,-119,4,630,-119,4,631,-36,3,632,-112,4,633,-123,4,634,-39,3,635,-125,4,636,-14,3,637,-42,3,638,-16,3,639,-17,3,640,-45,3,641,-16,3,642,-16,3,643,-48,3,644,-17,3,645,-85,4,646,-51,4,647,-52,4,648,-51,4,649,-68,4,650,-90,4,651,-56,4,652,-80,4,653,-58,4,654,-59,4,655,-60,4,656,-96,4,657,-85,4,658,-80,4,659,-64,4,660,-65,4,661,-66,4,662,-102,4,663,-68,4,664,-68,4,665,-70,4,666,-85,4,667,-72,4,668,-96,4,669,-74,4,670,-75,4,671,-60,4,672,-112,4,673,-85,4,674,-96,4,675,-80,4,676,-64,4,677,-82,4,678,-15,3,679,-119,4,680,-85,4,681,-85,4,682,-85,4,683,-102,4,684,-96,4,685,-90,4,686,-91,4,687,-92,4,688,-93,4,689,-14,3,690,-102,4,691,-96,4,692,-17,3,693,-98,4,694,-14,3,695,-15,3,696,-16,3,697,-102,4,698,-102,4,699,-102,4,700,-105,4,701,-106,4,702,-107,4,703,-108,4,704,-109,4,705,-14,3,706,-15,3,707,-112,4,708,-17,3,709,-114,4,710,-115,4,711,-14,3,712,-15,3,713,-16,3,714,-119,4,715,-119,4,716,-119,4,717,-112,4,718,-123,4,719,-124,4,720,-13,3,721,-14,3,722,-15,3,723,-16,3,724,-17,3,725,-130,4,726,-131,4,727,-13,3,728,-14,3,729,-15,3,730,-16,3,731,-17,3,732,-17,3,733,-17,3,734,-112,4,735,-112,4,736,-112,4,737,-112,4,738,-112,4,739,-144,4,740,-145,4,741,-112,4,742,-147,4,743,-119,4,744,-119,4,745,-119,4,746,-151,4,747,-152,4,748,-119,4,749,-154,4,750,-75,4,751,-156,4,752,-157,4,753,-158,4,754,-306,5,755,-160,4,756,-161,4,757,-162,4,758,-163,4,759,-68,4,760,-80,4,761,-64,4,762,-167,4,763,-168,4,764,-288,4,765,-85,4,766,-75,4,767,-60,4,768,-68,4,769,-85,4,770,-85,4,771,-80,4,772,-75,4,773,-15,3,774,-60,4,775,-68,4,776,-85,4,777,-80,4,778,-64,4,779,-65,4,780,-80,4,781,-90,4,782,-85,4,783,-85,4,784,-70,4,785,-85,4,786,-96,4,787,-96,4,788,-17,3,789,-75,4,790,-90,4,791,-112,4,792,-85,4,793,-96,4,794,-80,4,795,-64,4,796,-96,4,797,-90,4,798,-119,4,799,-102,4,800,-102,4,801,-102,4,802,-102,4,803,-96,4,804,-90,4,805,-357,5,806,-102,4,807,-15,3,808,-16,3,809,-102,4,810,-96,4,811,-17,3,812,-336,5,813,-14,3,814,-15,3,815,-16,3,816,-102,4,817,-102,4,818,-102,4,819,-112,4,820,-17,3,821,-112,4,822,-112,4,823,-14,3,824,-15,3,825,-16,3,826,-112,4,827,-17,3,828,-114,4,829,-115,4,830,-14,3,831,-15,3,832,-16,3,833,-119,4,834,-119,4,835,-16,3,836,-17,3,837,-119,4,838,-119,4,839,-13,3,840,-14,3,841,-15,3,842,-16,3,843,-17,3,844,-119,4,845,-119,4,846,-13,3,847,-14,3,848,-15,3,849,-16,3,850,-17,3,851,-112,4,852,-112,4,853,-112,4,854,-112,4,855,-112,4,856,-408,5,857,-112,4,858,-119,4,859,-119,4,860,-384,5,861,-85,4,862,-119,4,863,-119,4,864,-119,4,865,-119,4,866,-306,5,867,-357,5,868,-358,5,869,-359,5,870,-112,4,871,-68,4,872,-85,4,873,-80,4,874,-119,4,875,-365,5,876,-60,4,877,-85,4,878,-85,4,879,-80,4,880,-64,4,881,-119,4,882,-372,5,883,-288,5,884,-408,5,885,-409,5,886,-410,5,887,-68,4,888,-85,4,889,-96,4,890,-80,4,891,-75,4,892,-416,5,893,-60,4,894,-85,4,895,-96,4,896,-80,4,897,-64,4,898,-14,3,899,-423,5,900,-424,5,901,-306,5,902,-307,5,903,-308,5,904,-85,4,905,-96,4,906,-96,4,907,-312,5,908,-75,4,909,-314,5,910,-315,5,911,-102,4,912,-96,4,913,-80,4,914,-13,3,915,-320,5,916,-321,5,917,-357,5,918,-408,5,919,-359,5,920,-410,5,921,-102,4,922,-96,4,923,-90,4,924,-448,5,925,-449,5,926,-450,5,927,-16,3,928,-102,4,929,-96,4,930,-13,3,931,-336,5,932,-337,5,933,-373,5,934,-374,5,935,-102,4,936,-460,5,937,-13,3,938,-112,4,939,-448,5,940,-464,5,941,-465,5,942,-347,5,943,-348,5,944,-13,3,945,-112,4,946,-351,5,947,-352,5,948,-353,5,949,-354,5,950,-15,3,951,-16,3,952,-476,5,953,-476,5,954,-476,5,955,-476,5,956,-476,5,957,-476,5,958,-448,5,959,-476,5,960,-476,5,961,-476,5,962,-476,5,963,-476,5,964,-476,5,965,-13,3,966,-14,3,967,-15,3,968,-476,5,969,-476,5,970,-477,5,971,-478,5,972,-462,5,973,-481,5,974,-476,5,975,-476,5,976,-476,5,977,-476,5,978,-476,5,979,-384,5,980,-476,5,981,-386,5,982,-476,5,983,-476,5,984,-476,5,985,-476,5,986,-476,5,987,-477,5,988,-478,5,989,-479,5,990,-480,5,991,-481,5,992,-482,5,993,-483,5,994,-484,5,995,-485,5,996,-476,5,997,-402,5,998,-488,5,999,-13,3,1000,-14,3,1001,-15,3,1002,-476,5,1003,-408,5,1004,-409,5,1005,-410,5,1006,-411,5,1007,-412,5,1008,-448,5,1009,-414,5,1010,-415,5,1011,-416,5,1012,-60,4,1013,-418,5,1014,-419,5,1015,-420,5,1016,-64,4,1017,-14,3,1018,-15,3,1019,-424,5,1020,-510,5,1021,-426,5,1022,-476,5,1023,-102,4,1024,-96,4,1025,-96,4,1026,-476,5,1027,-476,5,1028,-15,3,1029,-469,5,1030,-510,5,1031,-96,4,1032,-476,5,1033,-438,5,1034,-14,3,1035,-15,3,1036,-476,5,1037,-476,5,1038,-478,5,1039,-478,5,1040,-102,4,1041,-96,4,1042,-476,5,1043,-448,5,1044,-449,5,1045,-450,5,1046,-486,5,1047,-102,4,1048,-476,5,1049,-13,3,1050,-455,5,1051,-15,3,1052,-16,3,1053,-493,5,1054,-476,5,1055,-460,5,1056,-13,3,1057,-476,5,1058,-15,3,1059,-16,3,1060,-465,5,1061,-476,5,1062,-14,3,1063,-15,3,1064,-476,5,1065,-476,5,1066,-510,5,1067,-64,4,1068,-14,3,1069,-15,3,1070,-510,5,1071,-476,5,1072,-477,5,1073,-478,5,1074,-479,5,1075,-4,2,1076,-481,5,1077,-482,5,1078,-483,5,1079,-484,5,1080,-485,5,1081,-486,5,1082,-487,5,1083,-488,5,1084,-13,3,1085,-14,3,1086,-15,3,1087,-16,3,1088,-17,3,1089,-17,3,1090,-17,3,1091,-510,5,1092,-16,3,1093,-498,5,1094,-499,5,1095,-500,5,1096,-501,5,1097,-502,5,1098,-510,5,1099,-504,5,1100,-505,5,1101,-506,5,1102,-507,5,1103,-508,5,1104,-509,5,1105,-510,5,1106,-511,5,1107,-512,5,1108,-513,5,1109,-4,2,1110,-515,5,1111,-516,5,1112,-517,5,1113,-518,5,1114,-519,5,1115,-520,5,1116,-521,5,1117,-522,5,1118,-13,3,1119,-14,3,1120,-15,3,1121,-16,3,1122,-17,3,1123,-528,5,1124,-17,3,1125,-530,5,1126,-560,5,1127,-56,4,1128,-533,5,1129,-14,3,1130,-15,3,1131,-60,4,1132,-560,5,1133,-538,5,1134,-539,5,1135,-64,4,1136,-541,5,1137,-542,5,1138,-560,5,1139,-68,4,1140,-68,4,1141,-70,4,1142,-561,5,1143,-72,4,1144,-572,5,1145,-550,5,1146,-476,5,1147,-60,4,1148,-560,5,1149,-561,5,1150,-572,5,1151,-476,5,1152,-64,4,1153,-558,5,1154,-15,3,1155,-560,5,1156,-561,5,1157,-562,5,1158,-563,5,1159,-4,2,1160,-572,5,1161,-566,5,1162,-567,5,1163,-568,5,1164,-569,5,1165,-570,5,1166,-578,5,1167,-572,5,1168,-13,3,1169,-14,3,1170,-15,3,1171,-16,3,1172,-17,3,1173,-578,5,1174,-579,5,1175,-580,5,1176,-581,5,1177,-582,5,1178,-583,5,1179,-584,5,1180,-585,5,1181,-14,3,1182,-15,3,1183,-588,5,1184,-17,3,1185,-510,5,1186,-591,5,1187,-14,3,1188,-15,3,1189,-16,3,1190,-595,5,1191,-595,5,1192,-595,5,1193,-595,5,1194,-4,2,1195,-595,5,1196,-595,5,1197,-595,5,1198,-595,5,1199,-595,5,1200,-595,5,1201,-595,5,1202,-595,5,1203,-13,3,1204,-14,3,1205,-15,3,1206,-16,3,1207,-17,3,1208,-17,3,1209,-17,3,1210,-595,5,1211,-16,3,1212,-17,3,1213,-595,5,1214,-595,5,1215,-595,5,1216,-595,5,1217,-595,5,1218,-595,5,1219,-595,5,1220,-595,5,1221,-595,5,1222,-595,5,1223,-595,5,1224,-595,5,1225,-595,5,1226,-595,5,1227,-595,5,1228,-595,5,1229,-595,5,1230,-13,3,1231,-14,3,1232,-595,5,1233,-16,3,1234,-17,3,1235,-595,5,1236,-16,3,1237,-16,3,1238,-595,5,1239,-17,3,1240,-560,5,1241,-51,4,1242,-52,4,1243,-51,4,1244,-68,4,1245,-595,5,1246,-56,4,1247,-80,4,1248,-58,4,1249,-59,4,1250,-60,4,1251,-595,5,1252,-572,5,1253,-80,4,1254,-64,4,1255,-65,4,1256,-66,4,1257,-595,5,1258,-68,4,1259,-68,4,1260,-70,4,1261,-581,5,1262,-72,4,1263,-595,5,1264,-74,4,1265,-75,4,1266,-60,4,1267,-595,5,1268,-588,5,1269,-595,5,1270,-80,4,1271,-64,4,1272,-82,4,1273,-15,3,1274,-595,5,1275,-85,4,1276,-85,4,1277,-85,4,1278,-595,5,1279,-595,5,1280,-595,5,1281,-595,5,1282,-595,5,1283,-595,5,1284,-14,3,1285,-595,5,1286,-595,5,1287,-17,3,1288,-595,5,1289,-14,3,1290,-15,3,1291,-16,3,1292,-595,5,1293,-596,5,1294,-597,5,1295,-595,5,1296,-595,5,1297,-595,5,1298,-595,5,1299,-595,5,1300,-14,3,1301,-15,3,1302,-595,5,1303,-17,3,1304,-595,5,1305,-595,5,1306,-14,3,1307,-15,3,1308,-16,3,1309,-595,5,1310,-596,5,1311,-597,5,1312,-605,5,1313,-595,5,1314,-595,5,1315,-13,3,1316,-14,3,1317,-15,3,1318,-16,3,1319,-17,3,1320,-595,5,1321,-595,5,1322,-13,3,1323,-14,3,1324,-15,3,1325,-16,3,1326,-17,3,1327,-17,3,1328,-17,3,1329,-622,5,1330,-623,5,1331,-624,5,1332,-625,5,1333,-626,5,1334,-595,5,1335,-595,5,1336,-629,5,1337,-595,5,1338,-624,5,1339,-625,5,1340,-626,5,1341,-627,5,1342,-595,5,1343,-629,5,1344,-595,5,1345,-75,4,1346,-595,5,1347,-595,5,1348,-595,5,1349,-306,5,1350,-595,5,1351,-595,5,1352,-60,4,1353,-595,5,1354,-68,4,1355,-80,4,1356,-64,4,1357,-595,5,1358,-595,5,1359,-288,5,1360,-408,5,1361,-75,4,1362,-60,4,1363,-68,4,1364,-85,4,1365,-85,4,1366,-80,4,1367,-75,4,1368,-15,3,1369,-60,4,1370,-68,4,1371,-85,4,1372,-80,4,1373,-64,4,1374,-65,4,1375,-80,4,1376,-90,4,1377,-85,4,1378,-85,4,1379,-70,4,1380,-85,4,1381,-595,5,1382,-595,5,1383,-17,3,1384,-75,4,1385,-90,4,1386,-679,5,1387,-85,4,1388,-595,5,1389,-80,4,1390,-64,4,1391,-595,5,1392,-90,4,1393,-679,5,1394,-697,5,1395,-697,5,1396,-697,5,1397,-697,5,1398,-595,5,1399,-90,4,1400,-448,5,1401,-697,5,1402,-15,3,1403,-16,3,1404,-697,5,1405,-595,5,1406,-17,3,1407,-336,5,1408,-14,3,1409,-15,3,1410,-16,3,1411,-697,5,1412,-698,5,1413,-699,5,1414,-707,5,1415,-17,3,1416,-707,5,1417,-707,5,1418,-14,3,1419,-15,3,1420,-16,3,1421,-707,5,1422,-17,3,1423,-709,5,1424,-710,5,1425,-14,3,1426,-15,3,1427,-16,3,1428,3,10,1429,-1,0,1430,-2,1,1431,-3,1,1432,-4,2,1433,-5,2,1434,-6,2,1435,-7,2,1436,-8,2,1437,-9,2,1438,-10,2,1439,-11,2,1440,-12,2,1441,-13,3,1442,-14,3,1443,-15,3,1444,-16,3,1445,-17,3,1446,-17,3,1447,-17,3,1448,-20,3,1449,-16,3,1450,-17,3,1451,-23,3,1452,-24,3,1453,-25,3,1454,-26,3,1455,-27,3,1456,-28,3,1457,-29,3,1458,-30,3,1459,-31,3,1460,-32,3,1461,-33,3,1462,-476,5,1463,-476,5,1464,-36,3,1465,-707,5,1466,-68,4,1467,-39,3,1468,-80,4,1469,-714,5,1470,-42,3,1471,-16,3,1472,-408,5,1473,-45,3,1474,-80,4,1475,-16,3,1476,-48,3,1477,-17,3,1478,-288,5,1479,-408,5,1480,-52,4,1481,-410,5,1482,-68,4,1483,-85,4,1484,-56,4,1485,-80,4,1486,-58,4,1487,-59,4,1488,-60,4,1489,-418,5,1490,-96,4,1491,-80,4,1492,-64,4,1493,-65,4,1494,-15,3,1495,-16,3,1496,-306,5,1497,-307,5,1498,-70,4,1499,-85,4,1500,-96,4,1501,-96,4,1502,-74,4,1503,-75,4,1504,-60,4,1505,-77,4,1506,-595,5,1507,-96,4,1508,-80,4,1509,-64,4,1510,-14,3,1511,-15,3,1512,-476,5,1513,-85,4,1514,-85,4,1515,-85,4,1516,-707,5,1517,-96,4,1518,-90,4,1519,-448,5,1520,-92,4,1521,-93,4,1522,-14,3,1523,-707,5,1524,-96,4,1525,-17,3,1526,-336,5,1527,-14,3,1528,-15,3,1529,-16,3,1530,-102,4,1531,-102,4,1532,-102,4,1533,-105,4,1534,-106,4,1535,-107,4,1536,-108,4,1537,-109,4,1538,-14,3,1539,-15,3,1540,-112,4,1541,-17,3,1542,-114,4,1543,-13,3,1544,-14,3,1545,-15,3,1546,-16,3,1547,-119,4,1548,-119,4,1549,-119,4,1550,-112,4,1551,-123,4,1552,-124,4,1553,-13,3,1554,-14,3,1555,-15,3,1556,-16,3,1557,-17,3,1558,-119,4,1559,-131,4,1560,-13,3,1561,-14,3,1562,-15,3,1563,-16,3,1564,-17,3,1565,-17,3,1566,-17,3,1567,-112,4,1568,-112,4,1569,-112,4,1570,-112,4,1571,-112,4,1572,-112,4,1573,-112,4,1574,-384,5,1575,-408,5,1576,-119,4,1577,-119,4,1578,-119,4,1579,-119,4,1580,-119,4,1581,-476,5,1582,-477,5,1583,-476,5,1584,-60,4,1585,-157,4,1586,-476,5,1587,-476,5,1588,-160,4,1589,-476,5,1590,-476,5,1591,-408,5,1592,-402,5,1593,-80,4,1594,-13,3,1595,-14,3,1596,-15,3,1597,-16,3,1598,-408,5,1599,-409,5,1600,-410,5,1601,-411,5,1602,-4,2,1603,-448,5,1604,-80,4,1605,-75,4,1606,-416,5,1607,-60,4,1608,-418,5,1609,-85,4,1610,-80,4,1611,-64,4,1612,-14,3,1613,-15,3,1614,-16,3,1615,-510,5,1616,-426,5,1617,-70,4,1618,-85,4,1619,-96,4,1620,-96,4,1621,-448,5,1622,-75,4,1623,-15,3,1624,-476,5,1625,-85,4,1626,-96,4,1627,-80,4,1628,-438,5,1629,-96,4,1630,-90,4,1631,-476,5,1632,-102,4,1633,-478,5,1634,-102,4,1635,-102,4,1636,-96,4,1637,-90,4,1638,-448,5,1639,-449,5,1640,-450,5,1641,-16,3,1642,-102,4,1643,-96,4,1644,-13,3,1645,-455,5,1646,-15,3,1647,-16,3,1648,-17,3,1649,-102,4,1650,-460,5,1651,-13,3,1652,-112,4,1653,-15,3,1654,-16,3,1655,-17,3,1656,-14,3,1657,-15,3,1658,-16,3,1659,-112,4,1660,-17,3,1661,-80,4,1662,-64,4,1663,-14,3,1664,-15,3,1665,-510,5,1666,-476,5,1667,-477,5,1668,-478,5,1669,-479,5,1670,-4,2,1671,-476,5,1672,-476,5,1673,-483,5,1674,-484,5,1675,-485,5,1676,-486,5,1677,-487,5,1678,-488,5,1679,-13,3,1680,-14,3,1681,-15,3,1682,-16,3,1683,-17,3,1684,-17,3,1685,-17,3,1686,-476,5,1687,-16,3,1688,-408,5,1689,-476,5,1690,-476,5,1691,-476,5,1692,-476,5,1693,-476,5,1694,-408,5,1695,-476,5,1696,-476,5,1697,-507,5,1698,-508,5,1699,-509,5,1700,-510,5,1701,-511,5,1702,-510,5,1703,-513,5,1704,-4,2,1705,-510,5,1706,-510,5,1707,-510,5,1708,-510,5,1709,-510,5,1710,-408,5,1711,-521,5,1712,-522,5,1713,-13,3,1714,-14,3,1715,-15,3,1716,-16,3,1717,-17,3,1718,-80,4,1719,-17,3,1720,-418,5,1721,-85,4,1722,-56,4,1723,-85,4,1724,-14,3,1725,-15,3,1726,-60,4,1727,-476,5,1728,-96,4,1729,-510,5,1730,-64,4,1731,-510,5,1732,-510,5,1733,-476,5,1734,-306,5,1735,-307,5,1736,-70,4,1737,-85,4,1738,-96,4,1739,-96,4,1740,-448,5,1741,-75,4,1742,-314,5,1743,-476,5,1744,-102,4,1745,-96,4,1746,-80,4,1747,-64,4,1748,-558,5,1749,-15,3,1750,-560,5,1751,-85,4,1752,-560,5,1753,-85,4,1754,-102,4,1755,-96,4,1756,-476,5,1757,-448,5,1758,-560,5,1759,-560,5,1760,-560,5,1761,-102,4,1762,-476,5,1763,-13,3,1764,-336,5,1765,-15,3,1766,-16,3,1767,-17,3,1768,-476,5,1769,-477,5,1770,-478,5,1771,-476,5,1772,-476,5,1773,-476,5,1774,-476,5,1775,-476,5,1776,-14,3,1777,-15,3,1778,-476,5,1779,-17,3,1780,-80,4,1781,-476,5,1782,-14,3,1783,-15,3,1784,-16,3,1785,3,11,1786,-1,0,1787,-2,1,1788,-3,1,1789,-4,2,1790,-5,2,1791,-6,2,1792,-7,2,1793,-8,2,1794,-9,2,1795,-10,2,1796,-11,2,1797,-12,2,1798,-13,3,1799,-14,3,1800,-15,3,1801,-16,3,1802,-17,3,1803,-17,3,1804,-17,3,1805,-20,3,1806,-16,3,1807,-17,3,1808,-23,3,1809,-24,3,1810,-25,3,1811,-26,3,1812,-27,3,1813,-28,3,1814,-29,3,1815,-30,3,1816,-31,3,1817,-32,3,1818,-33,3,1819,-34,3,1820,-34,3,1821,-36,3,1822,-5,2,1823,-7,2,1824,-39,3,1825,-32,3,1826,-15,3,1827,-42,3,1828,-16,3,1829,-16,3,1830,-45,3,1831,-16,3,1832,-16,3,1833,-48,4,1834,-17,3,1835,-17,3,1836,-51,4,1837,-52,4,1838,-51,4,1839,-15,3,1840,-16,3,1841,-56,4,1842,-57,4,1843,-58,4,1844,-59,4,1845,-60,4,1846,-61,4,1847,-62,4,1848,-63,4,1849,-64,4,1850,-65,4,1851,-66,4,1852,-51,4,1853,-68,4,1854,-68,4,1855,-70,4,1856,-64,4,1857,-72,4,1858,-73,4,1859,-74,4,1860,-75,4,1861,-60,4,1862,-77,4,1863,-78,4,1864,-15,3,1865,-80,4,1866,-64,4,1867,-82,4,1868,-15,3,1869,-16,3,1870,-85,4,1871,-85,4,1872,-85,4,1873,-80,4,1874,-89,4,1875,-90,4,1876,-91,4,1877,-92,4,1878,-93,4,1879,-14,3,1880,-15,3,1881,-96,4,1882,-17,3,1883,-98,4,1884,-14,3,1885,-15,3,1886,-16,3,1887,-102,4,1888,-102,4,1889,-102,4,1890,-105,4,1891,-106,4,1892,-107,4,1893,-108,4,1894,-109,4,1895,-14,3,1896,-15,3,1897,-112,4,1898,-17,3,1899,-114,4,1900,-13,3,1901,-14,3,1902,-15,3,1903,-16,3,1904,4,16,1905,-1,0,1906,-2,1,1907,-112,4,1908,-123,4,1909,-124,4,1910,-13,3,1911,-14,3,1912,-15,3,1913,-16,3,1914,-17,3,1915,-11,2,1916,-12,2,1917,-13,3,1918,-14,3,1919,-15,3,1920,-16,3,1921,-17,3,1922,-17,3,1923,-17,3,1924,-112,4,1925,-112,4,1926,-112,4,1927,-112,4,1928,-112,4,1929,-112,4,1930,-112,4,1931,-112,4,1932,-28,3,1933,-29,3,1934,-30,3,1935,-31,3,1936,-32,3,1937,-33,3,1938,-510,5,1939,-154,4,1940,-75,4,1941,-60,4,1942,-157,4,1943,-39,3,1944,-16,3,1945,-160,4,1946,-42,3,1947,-60,4,1948,-163,4,1949,-68,4,1950,-80,4,1951,-64,4,1952,-48,4,1953,-17,3,1954,-64,4,1955,-85,4,1956,-75,4,1957,-60,4,1958,-68,4,1959,-78,4,1960,-85,4,1961,-80,4,1962,-75,4,1963,-66,4,1964,-60,4,1965,-68,4,1966,-85,4,1967,-80,4,1968,-64,4,1969,-65,4,1970,-80,4,1971,-90,4,1972,-85,4,1973,-85,4,1974,-70,4,1975,-85,4,1976,-15,3,1977,-96,4,1978,-17,3,1979,-75,4,1980,-90,4,1981,-16,3,1982,-85,4,1983,-96,4,1984,-80,4,1985,-64,4,1986,-96,4,1987,-90,4,1988,-560,5,1989,-85,4,1990,-85,4,1991,-85,4,1992,-102,4,1993,-96,4,1994,-90,4,1995,-105,4,1996,-102,4,1997,-15,3,1998,-16,3,1999,-102,4,2000,-96,4,2001,-17,3,2002,-105,4,2003,-14,3,2004,-15,3,2005,-16,3,2006,-102,4,2007,-102,4,2008,-102,4,2009,-112,4,2010,-17,3,2011,-107,4,2012,-13,3,2013,-109,4,2014,-15,3,2015,-16,3,2016,-112,4,2017,-17,3,2018,-114,4,2019,-13,3,2020,-14,3,2021,-15,3,2022,-16,3,2023,-119,4,2024,-119,4,2025,-119,4,2026,-17,3,2027,-123,4,2028,-124,4,2029,-13,3,2030,-14,3,2031,-15,3,2032,-16,3,2033,-17,3,2034,-119,4,2035,-131,4,2036,-13,3,2037,-14,3,2038,-15,3,2039,-16,3,2040,-17,3,2041,-17,3,2042,-112,4,2043,-112,4,2044,-112,4,2045,-112,4,2046,-112,4,2047,-112,4,0,0,0"),
// leafSize 18
splitIntegerList("1,1,0,2,2,0,3,3,1,4,4,3,5,5,4,6,6,5,7,7,7,8,8,8,9,9,10,10,10,11,11,11,12,12,12,14,13,13,15,14,14,16,15,15,18,16,16,19,17,17,21,18,18,22,19,-1,1,20,-2,1,21,-3,1,22,-4,1,23,-5,2,24,-8,2,25,-7,2,26,-8,2,27,-11,2,28,-10,2,29,-13,2,30,-15,2,31,-13,2,32,-16,2,33,-15,2,34,-16,2,35,-17,2,36,-18,2,37,-1,1,38,-2,1,39,3,5,40,-4,2,41,-5,2,42,3,5,43,-7,2,44,-8,2,45,3,5,46,-10,2,47,-11,2,48,3,5,49,-13,2,50,-16,2,51,3,5,52,-16,2,53,-17,2,54,3,5,55,-1,1,56,4,8,57,-3,1,58,-4,2,59,-5,2,60,4,8,61,-7,2,62,-8,2,63,-15,2,64,4,8,65,5,11,66,-18,3,67,-13,2,68,4,9,69,-15,2,70,-16,3,71,-17,3,72,4,9,73,-1,1,74,-2,1,75,5,11,76,-4,2,77,-5,2,78,-6,2,79,-7,2,80,5,12,81,-9,2,82,-10,2,83,-11,2,84,-12,2,85,5,12,86,-14,2,87,-15,3,88,-16,3,89,-17,3,90,5,12,91,-1,1,92,-2,1,93,-3,1,94,-4,2,95,-5,2,96,6,15,97,-7,2,98,-8,2,99,-9,2,100,-10,2,101,-11,2,102,6,15,103,-13,2,104,-14,2,105,-15,3,106,-16,3,107,-17,3,108,6,15,109,-1,1,110,-2,1,111,-3,1,112,7,18,113,-5,2,114,-6,2,115,-7,2,116,-8,2,117,-9,2,118,-10,2,119,7,18,120,-12,2,121,-13,2,122,-14,3,123,-15,3,124,-16,3,125,-17,3,126,7,19,127,-1,1,128,8,21,129,-3,1,130,-4,2,131,-5,2,132,-6,2,133,-7,2,134,-8,2,135,-9,2,136,8,22,137,-11,2,138,-12,2,139,-13,2,140,-14,3,141,-15,3,142,-16,3,143,-17,3,144,-18,3,145,-17,3,146,-18,3,147,-11,2,148,-12,2,149,-13,2,150,-14,3,151,-15,3,152,-16,3,153,-17,3,154,-18,3,155,-29,3,156,-30,3,157,-31,3,158,-32,3,159,-33,3,160,-34,3,161,-35,3,162,-36,3,163,-35,3,164,-36,3,165,-39,3,166,-54,3,167,-31,3,168,-60,3,169,-33,3,170,-80,3,171,-45,3,172,-64,3,173,-54,3,174,-48,3,175,-85,3,176,-68,3,177,-51,3,178,-18,3,179,-18,3,180,-90,3,181,-85,3,182,-54,3,183,-75,3,184,-72,3,185,-5,2,186,-90,3,187,-85,3,188,-80,3,189,-9,2,190,-64,3,191,-72,3,192,-90,4,193,-85,4,194,-68,3,195,-15,3,196,-16,3,197,-17,3,198,-90,4,199,-80,4,200,-72,3,201,-75,4,202,-90,4,203,-5,2,204,-96,4,205,-7,2,206,-80,4,207,-99,4,208,-72,4,209,-90,4,210,-102,4,211,-85,4,212,-14,3,213,-15,3,214,-16,3,215,-17,3,216,-108,4,217,-1,0,218,-90,4,219,-3,1,220,-108,4,221,-102,4,222,-96,4,223,-7,2,224,-8,2,225,-9,2,226,-90,4,227,-108,4,228,-102,4,229,-108,4,230,-14,3,231,-15,3,232,-16,3,233,-17,3,234,-108,4,235,-1,0,236,-108,4,237,-3,1,238,-112,4,239,-5,2,240,-6,2,241,-7,2,242,-8,2,243,-9,2,244,-108,4,245,-119,4,246,-120,4,247,-121,4,248,-14,3,249,-15,3,250,-16,3,251,-17,3,252,-126,4,253,-1,0,254,-126,4,255,-119,4,256,-4,2,257,-5,2,258,-6,2,259,-7,2,260,-8,2,261,-9,2,262,-126,4,263,-126,4,264,-126,4,265,-126,4,266,-14,3,267,-15,3,268,-16,3,269,-17,3,270,3,8,271,-17,3,272,-136,4,273,-126,4,274,-126,4,275,-126,4,276,-14,3,277,-15,3,278,-16,3,279,-17,3,280,-18,3,281,-126,4,282,-126,4,283,-126,4,284,-126,4,285,-126,4,286,-126,4,287,-17,3,288,-18,3,289,-17,3,290,-18,3,291,-126,4,292,-112,4,293,-136,4,294,-90,4,295,-136,4,296,-80,4,297,-126,4,298,-126,4,299,-119,4,300,-126,4,301,-85,4,302,-126,4,303,-126,4,304,-34,3,305,-35,3,306,-90,4,307,-126,4,308,-128,4,309,-126,4,310,-90,4,311,-90,4,312,-96,4,313,-85,4,314,-80,4,315,-90,4,316,-126,4,317,-90,4,318,-102,4,319,-85,4,320,-126,4,321,-15,3,322,-16,3,323,-17,3,324,3,8,325,-1,0,326,-2,1,327,-3,1,328,-4,2,329,-5,2,330,-6,2,331,-7,2,332,-8,2,333,-9,2,334,-10,2,335,-11,2,336,-12,2,337,-13,3,338,-14,3,339,-15,3,340,-16,3,341,-17,3,342,-18,3,343,-18,3,344,-108,4,345,-90,4,346,-108,4,347,-102,4,348,-96,4,349,-25,3,350,-26,3,351,-27,3,352,-108,4,353,-108,4,354,-102,4,355,-31,3,356,-32,3,357,-33,3,358,-34,3,359,-35,3,360,4,12,361,-1,0,362,-108,4,363,-108,4,364,-112,4,365,-5,2,366,-6,2,367,-7,2,368,-8,2,369,-9,2,370,-108,4,371,-119,4,372,-12,2,373,-13,3,374,-14,3,375,-15,3,376,-16,3,377,-17,3,378,3,8,379,-1,0,380,-2,1,381,-3,1,382,-4,2,383,-5,2,384,-6,2,385,-7,2,386,-8,2,387,-9,2,388,-10,2,389,-11,2,390,-12,2,391,-13,3,392,-14,3,393,-15,3,394,-16,3,395,-17,3,396,-18,3,397,-18,3,398,-18,3,399,-18,3,400,-4,2,401,-18,3,402,-24,3,403,-25,3,404,-26,3,405,-27,3,406,-28,3,407,-29,3,408,-30,3,409,-31,3,410,-32,3,411,-33,3,412,-34,3,413,-35,3,414,-90,4,415,-90,4,416,-90,4,417,-39,3,418,-4,2,419,-90,4,420,-96,4,421,-90,4,422,-90,4,423,-45,3,424,-100,4,425,-101,4,426,-48,3,427,-103,4,428,-18,3,429,-51,3,430,-16,3,431,-17,3,432,4,13,433,-1,0,434,-2,1,435,-3,1,436,-4,2,437,-5,2,438,-6,2,439,-7,2,440,-8,2,441,-9,2,442,-10,2,443,-11,2,444,-12,2,445,-13,3,446,-14,3,447,-15,3,448,-16,3,449,-17,3,450,5,17,451,-1,0,452,-128,4,453,-75,4,454,-4,2,455,-5,2,456,-24,3,457,-7,2,458,-80,4,459,-27,3,460,-136,4,461,-29,3,462,-30,3,463,-85,4,464,-32,3,465,-33,3,466,-34,3,467,-35,3,468,-90,4,469,-90,4,470,-90,4,471,-90,4,472,-4,2,473,-90,4,474,-96,4,475,-90,4,476,-90,4,477,-45,3,478,-100,4,479,-101,4,480,-102,4,481,-103,4,482,-14,3,483,-15,3,484,-16,3,485,-17,3,486,-108,4,487,-108,4,488,-108,4,489,-108,4,490,-112,4,491,-5,2,492,-108,4,493,-108,4,494,-108,4,495,-108,4,496,-108,4,497,-119,4,498,-120,4,499,-121,4,500,-14,3,501,-15,3,502,-16,3,503,-17,3,504,4,13,505,-1,0,506,-2,1,507,-3,1,508,-4,2,509,-5,2,510,-6,2,511,-7,2,512,-8,2,513,-9,2,514,-10,2,515,-11,2,516,-12,2,517,-13,3,518,-14,3,519,-15,3,520,-16,3,521,-17,3,522,-18,3,523,-18,3,524,-18,3,525,-18,3,526,-4,2,527,-18,3,528,-24,3,529,-18,3,530,-26,3,531,-27,3,532,-28,3,533,-29,3,534,-30,3,535,-31,3,536,-32,3,537,-33,3,538,-34,3,539,-35,3,540,5,17,541,-1,0,542,-2,1,543,-3,1,544,-4,2,545,-5,2,546,-6,2,547,-7,2,548,-8,2,549,-9,2,550,-10,2,551,-11,2,552,-12,2,553,-13,3,554,-14,3,555,-15,3,556,-16,3,557,-17,3,558,-18,3,559,-18,3,560,-128,4,561,-18,3,562,-4,2,563,-18,3,564,-60,4,565,-18,3,566,-26,3,567,-27,3,568,-64,4,569,-29,3,570,-30,3,571,-31,3,572,-68,4,573,-33,3,574,-34,3,575,-35,3,576,-72,4,577,-72,4,578,-72,4,579,-75,4,580,-4,2,581,-72,4,582,-42,3,583,-72,4,584,-80,4,585,-45,3,586,-82,4,587,-83,4,588,-48,3,589,-85,4,590,-86,4,591,-15,3,592,-16,3,593,-72,4,594,-90,4,595,-90,4,596,-90,4,597,-90,4,598,-4,2,599,-90,4,600,-96,4,601,-90,4,602,-90,4,603,-99,4,604,-100,4,605,-101,4,606,-102,4,607,-103,4,608,-14,3,609,-15,3,610,-16,3,611,-17,3,612,-108,4,613,-108,4,614,-108,4,615,-108,4,616,-112,4,617,-5,2,618,-108,4,619,-108,4,620,-108,4,621,-108,4,622,-108,4,623,-119,4,624,-120,4,625,-121,4,626,-14,3,627,-15,3,628,-16,3,629,-17,3,630,5,18,631,-1,0,632,-2,1,633,-3,1,634,-4,2,635,-5,2,636,-6,2,637,-7,2,638,-8,2,639,-9,2,640,-10,2,641,-11,2,642,-12,2,643,-13,3,644,-14,3,645,-15,3,646,-16,3,647,-17,3,648,6,22,649,-1,0,650,-2,1,651,-3,1,652,-4,2,653,-5,2,654,-6,2,655,-7,2,656,-8,2,657,-9,2,658,-10,2,659,-11,2,660,-12,2,661,-13,3,662,-14,3,663,-15,3,664,-16,3,665,-17,3,666,-18,3,667,-18,3,668,-128,4,669,-39,3,670,-4,2,671,-18,3,672,-42,3,673,-18,3,674,-26,3,675,-45,3,676,-136,4,677,-29,3,678,-48,3,679,-31,3,680,-32,3,681,-51,4,682,-34,3,683,-35,3,684,-54,4,685,-54,4,686,-56,4,687,-39,3,688,-72,4,689,-54,4,690,-60,4,691,-61,4,692,-80,4,693,-45,3,694,-64,4,695,-65,4,696,-48,3,697,-67,4,698,-68,4,699,-51,4,700,-54,4,701,-54,4,702,-72,4,703,-72,4,704,-72,4,705,-75,4,706,-4,2,707,-72,4,708,-60,4,709,-72,4,710,-80,4,711,-81,4,712,-64,4,713,-83,4,714,-84,4,715,-85,4,716,-68,4,717,-15,3,718,-16,3,719,-72,4,720,-90,4,721,-90,4,722,-90,4,723,-90,4,724,-4,2,725,-90,4,726,-96,4,727,-90,4,728,-80,4,729,-99,4,730,-100,4,731,-101,4,732,-102,4,733,-103,4,734,-14,3,735,-15,3,736,-16,3,737,-17,3,738,-108,4,739,-108,4,740,-108,4,741,-108,4,742,-112,4,743,-5,2,744,-96,4,745,-108,4,746,-108,4,747,-108,4,748,-108,4,749,-119,4,750,-120,4,751,-121,4,752,-14,3,753,-15,3,754,-16,3,755,-17,3,756,-126,4,757,-126,4,758,-128,4,759,-126,4,760,-112,4,761,-5,2,762,-6,2,763,-126,4,764,-126,4,765,-126,4,766,-136,4,767,-126,4,768,-138,4,769,-13,3,770,-14,3,771,-15,3,772,-16,3,773,-17,3,774,-126,4,775,-17,3,776,-128,4,777,-147,4,778,-148,4,779,-149,4,780,-14,3,781,-15,3,782,-16,3,783,-17,3,784,-136,4,785,-126,4,786,-138,4,787,-13,3,788,-14,3,789,-15,3,790,-16,3,791,-17,3,792,-18,3,793,-17,3,794,-18,3,795,-165,4,796,-166,4,797,-149,4,798,-72,4,799,-15,3,800,-80,4,801,-171,4,802,-64,4,803,-173,4,804,-174,4,805,-85,4,806,-68,4,807,-177,4,808,-160,4,809,-161,4,810,-90,4,811,-85,4,812,-182,4,813,-75,4,814,-72,4,815,-5,2,816,-90,4,817,-85,4,818,-80,4,819,-171,4,820,-64,4,821,-72,4,822,-90,4,823,-85,4,824,-68,4,825,-15,3,826,-16,3,827,-17,3,828,-324,5,829,-80,4,830,-72,4,831,-75,4,832,-90,4,833,-329,5,834,-96,4,835,-331,5,836,-80,4,837,-333,5,838,-72,4,839,-90,4,840,-102,4,841,-85,4,842,-338,5,843,-339,5,844,-340,5,845,-341,5,846,-108,4,847,-108,4,848,-90,4,849,-108,4,850,-108,4,851,-102,4,852,-96,4,853,-108,4,854,-80,4,855,-108,4,856,-90,4,857,-108,4,858,-102,4,859,-13,3,860,-14,3,861,-15,3,862,-16,3,863,-17,3,864,-108,4,865,-108,4,866,-108,4,867,-108,4,868,-112,4,869,-5,2,870,-96,4,871,-108,4,872,-108,4,873,-108,4,874,-108,4,875,-119,4,876,-120,4,877,-13,3,878,-14,3,879,-15,3,880,-16,3,881,-17,3,882,-126,4,883,-126,4,884,-126,4,885,-119,4,886,-112,4,887,-5,2,888,-6,2,889,-126,4,890,-126,4,891,-126,4,892,-126,4,893,-126,4,894,-126,4,895,-13,3,896,-14,3,897,-15,3,898,-16,3,899,-17,3,900,-126,4,901,-17,3,902,-136,4,903,-126,4,904,-126,4,905,-126,4,906,-14,3,907,-15,3,908,-16,3,909,-17,3,910,-126,4,911,-126,4,912,-126,4,913,-13,3,914,-14,3,915,-15,3,916,-16,3,917,-17,3,918,-378,5,919,-379,5,920,-380,5,921,-381,5,922,-382,5,923,-383,5,924,-384,5,925,-385,5,926,-386,5,927,-387,5,928,-388,5,929,-389,5,930,-390,5,931,-13,3,932,-14,3,933,-393,5,934,-394,5,935,-395,5,936,-432,5,937,-433,5,938,-434,5,939,-435,5,940,-436,5,941,-437,5,942,-438,5,943,-439,5,944,-440,5,945,-441,5,946,-442,5,947,-443,5,948,-444,5,949,-13,3,950,-14,3,951,-15,3,952,-448,5,953,-449,5,954,-324,5,955,-325,5,956,-326,5,957,-327,5,958,-328,5,959,-329,5,960,-330,5,961,-331,5,962,-332,5,963,-333,5,964,-334,5,965,-335,5,966,-336,5,967,-13,3,968,-324,5,969,-339,5,970,-340,5,971,-341,5,972,-324,5,973,-325,5,974,-108,4,975,-327,5,976,-108,4,977,-102,4,978,-96,4,979,-331,5,980,-332,5,981,-333,5,982,-108,4,983,-108,4,984,-102,4,985,-13,3,986,-324,5,987,-339,5,988,-340,5,989,-341,5,990,-360,5,991,-361,5,992,-108,4,993,-108,4,994,-112,4,995,-365,5,996,-96,4,997,-367,5,998,-368,5,999,-369,5,1000,-108,4,1001,-119,4,1002,-372,5,1003,-13,3,1004,-14,3,1005,-360,5,1006,-376,5,1007,-377,5,1008,-504,5,1009,-504,5,1010,-504,5,1011,-504,5,1012,-4,2,1013,-504,5,1014,-504,5,1015,-504,5,1016,-504,5,1017,-504,5,1018,-504,5,1019,-504,5,1020,-504,5,1021,-13,3,1022,-14,3,1023,-15,3,1024,-16,3,1025,-504,5,1026,-378,5,1027,-379,5,1028,-380,5,1029,-381,5,1030,-382,5,1031,-383,5,1032,-384,5,1033,-385,5,1034,-386,5,1035,-387,5,1036,-388,5,1037,-389,5,1038,-390,5,1039,-13,3,1040,-14,3,1041,-15,3,1042,-394,5,1043,-395,5,1044,-504,5,1045,-505,5,1046,-506,5,1047,-507,5,1048,-4,2,1049,-509,5,1050,-510,5,1051,-511,5,1052,-512,5,1053,-513,5,1054,-514,5,1055,-515,5,1056,-516,5,1057,-13,3,1058,-14,3,1059,-15,3,1060,-16,3,1061,-504,5,1062,-432,5,1063,-433,5,1064,-434,5,1065,-435,5,1066,-4,2,1067,-437,5,1068,-438,5,1069,-439,5,1070,-440,5,1071,-441,5,1072,-442,5,1073,-443,5,1074,-444,5,1075,-13,3,1076,-14,3,1077,-15,3,1078,-16,3,1079,-449,5,1080,-540,5,1081,-540,5,1082,-452,5,1083,-504,5,1084,-4,2,1085,-540,5,1086,-540,5,1087,-540,5,1088,-504,5,1089,-540,5,1090,-460,5,1091,-540,5,1092,-540,5,1093,-504,5,1094,-14,3,1095,-15,3,1096,-16,3,1097,-17,3,1098,-504,5,1099,-505,5,1100,-506,5,1101,-507,5,1102,-4,2,1103,-509,5,1104,-504,5,1105,-511,5,1106,-512,5,1107,-504,5,1108,-504,5,1109,-504,5,1110,-504,5,1111,-504,5,1112,-14,3,1113,-15,3,1114,-16,3,1115,-17,3,1116,-504,5,1117,-505,5,1118,-506,5,1119,-507,5,1120,-504,5,1121,-509,5,1122,-474,5,1123,-511,5,1124,-512,5,1125,-513,5,1126,-514,5,1127,-504,5,1128,-504,5,1129,-504,5,1130,-14,3,1131,-15,3,1132,-16,3,1133,-17,3,1134,-504,5,1135,-505,5,1136,-506,5,1137,-507,5,1138,-4,2,1139,-509,5,1140,-510,5,1141,-511,5,1142,-512,5,1143,-513,5,1144,-514,5,1145,-515,5,1146,-516,5,1147,-13,3,1148,-14,3,1149,-15,3,1150,-16,3,1151,-17,3,1152,-504,5,1153,-505,5,1154,-506,5,1155,-507,5,1156,-4,2,1157,-509,5,1158,-510,5,1159,-511,5,1160,-512,5,1161,-513,5,1162,-514,5,1163,-515,5,1164,-516,5,1165,-13,3,1166,-14,3,1167,-15,3,1168,-16,3,1169,-17,3,1170,-540,5,1171,-541,5,1172,-542,5,1173,-543,5,1174,-4,2,1175,-545,5,1176,-546,5,1177,-547,5,1178,-548,5,1179,-549,5,1180,-550,5,1181,-551,5,1182,-552,5,1183,-13,3,1184,-14,3,1185,-15,3,1186,-16,3,1187,-17,3,1188,-540,5,1189,-541,5,1190,-560,5,1191,-543,5,1192,-4,2,1193,-545,5,1194,-60,4,1195,-547,5,1196,-548,5,1197,-549,5,1198,-64,4,1199,-551,5,1200,-552,5,1201,-13,3,1202,-68,4,1203,-15,3,1204,-16,3,1205,-17,3,1206,-72,4,1207,-72,4,1208,-72,4,1209,-75,4,1210,-4,2,1211,-72,4,1212,-60,4,1213,-72,4,1214,-504,5,1215,-585,5,1216,-64,4,1217,-504,5,1218,-588,5,1219,-504,5,1220,-68,4,1221,-15,3,1222,-16,3,1223,-17,3,1224,-594,5,1225,-595,5,1226,-596,5,1227,-597,5,1228,-4,2,1229,-599,5,1230,-600,5,1231,-601,5,1232,-504,5,1233,-603,5,1234,-64,4,1235,-605,5,1236,-606,5,1237,-607,5,1238,-14,3,1239,-15,3,1240,-16,3,1241,-17,3,1242,-612,5,1243,-613,5,1244,-614,5,1245,-615,5,1246,-616,5,1247,-617,5,1248,-600,5,1249,-619,5,1250,-620,5,1251,-621,5,1252,-622,5,1253,-623,5,1254,-624,5,1255,-625,5,1256,-14,3,1257,-15,3,1258,-16,3,1259,-17,3,1260,-630,5,1261,-630,5,1262,-630,5,1263,-630,5,1264,-4,2,1265,-5,2,1266,-630,5,1267,-630,5,1268,-630,5,1269,-630,5,1270,-630,5,1271,-630,5,1272,-630,5,1273,-13,3,1274,-14,3,1275,-15,3,1276,-16,3,1277,-17,3,1278,-630,5,1279,-631,5,1280,-632,5,1281,-633,5,1282,-4,2,1283,-5,2,1284,-636,5,1285,-637,5,1286,-638,5,1287,-639,5,1288,-640,5,1289,-641,5,1290,-642,5,1291,-13,3,1292,-14,3,1293,-15,3,1294,-16,3,1295,-17,3,1296,-648,5,1297,-648,5,1298,-630,5,1299,-630,5,1300,-4,2,1301,-5,2,1302,-630,5,1303,-648,5,1304,-648,5,1305,-630,5,1306,-630,5,1307,-648,5,1308,-630,5,1309,-13,3,1310,-14,3,1311,-51,4,1312,-16,3,1313,-17,3,1314,-54,4,1315,-54,4,1316,-56,4,1317,-648,5,1318,-72,4,1319,-54,4,1320,-60,4,1321,-61,4,1322,-80,4,1323,-648,5,1324,-64,4,1325,-65,4,1326,-648,5,1327,-67,4,1328,-68,4,1329,-51,4,1330,-54,4,1331,-54,4,1332,-72,4,1333,-72,4,1334,-72,4,1335,-75,4,1336,-4,2,1337,-72,4,1338,-60,4,1339,-72,4,1340,-80,4,1341,-81,4,1342,-64,4,1343,-83,4,1344,-84,4,1345,-85,4,1346,-68,4,1347,-15,3,1348,-16,3,1349,-17,3,1350,-90,4,1351,-90,4,1352,-90,4,1353,-90,4,1354,-4,2,1355,-5,2,1356,-630,5,1357,-90,4,1358,-80,4,1359,-630,5,1360,-630,5,1361,-630,5,1362,-630,5,1363,-630,5,1364,-14,3,1365,-15,3,1366,-16,3,1367,-17,3,1368,-630,5,1369,-631,5,1370,-632,5,1371,-633,5,1372,-630,5,1373,-5,2,1374,-630,5,1375,-637,5,1376,-638,5,1377,-639,5,1378,-640,5,1379,-630,5,1380,-630,5,1381,-13,3,1382,-14,3,1383,-15,3,1384,-16,3,1385,-17,3,1386,-630,5,1387,-631,5,1388,-630,5,1389,-633,5,1390,-648,5,1391,-5,2,1392,-636,5,1393,-637,5,1394,-638,5,1395,-639,5,1396,-630,5,1397,-641,5,1398,-630,5,1399,-13,3,1400,-14,3,1401,-15,3,1402,-16,3,1403,-17,3,1404,-648,5,1405,-17,3,1406,-648,5,1407,-630,5,1408,-630,5,1409,-13,3,1410,-14,3,1411,-15,3,1412,-16,3,1413,-17,3,1414,-648,5,1415,-659,5,1416,-648,5,1417,-13,3,1418,-14,3,1419,-15,3,1420,-16,3,1421,-17,3,1422,-648,5,1423,-17,3,1424,-648,5,1425,-630,5,1426,-630,5,1427,-13,3,1428,-72,4,1429,-15,3,1430,-80,4,1431,-630,5,1432,-648,5,1433,-630,5,1434,-630,5,1435,-85,4,1436,-68,4,1437,-630,5,1438,-16,3,1439,-17,3,1440,-432,5,1441,-85,4,1442,-630,5,1443,-75,4,1444,-72,4,1445,-432,5,1446,-90,4,1447,-85,4,1448,-80,4,1449,-648,5,1450,-64,4,1451,-72,4,1452,-90,4,1453,-85,4,1454,-68,4,1455,-15,3,1456,-16,3,1457,-17,3,1458,-324,5,1459,-325,5,1460,-72,4,1461,-75,4,1462,-90,4,1463,-329,5,1464,-96,4,1465,-331,5,1466,-80,4,1467,-333,5,1468,-72,4,1469,-90,4,1470,-630,5,1471,-85,4,1472,-14,3,1473,-15,3,1474,-16,3,1475,-341,5,1476,-738,5,1477,-738,5,1478,-90,4,1479,-738,5,1480,-738,5,1481,-630,5,1482,-96,4,1483,-738,5,1484,-80,4,1485,-738,5,1486,-90,4,1487,-738,5,1488,-630,5,1489,-13,3,1490,-14,3,1491,-15,3,1492,-16,3,1493,-17,3,1494,-738,5,1495,-739,5,1496,-738,5,1497,-741,5,1498,-742,5,1499,-5,2,1500,-96,4,1501,-745,5,1502,-746,5,1503,-747,5,1504,-738,5,1505,-749,5,1506,-750,5,1507,-13,3,1508,-14,3,1509,-15,3,1510,-16,3,1511,-17,3,1512,3,10,1513,-1,0,1514,-2,1,1515,-3,1,1516,-4,2,1517,-5,2,1518,-6,2,1519,-7,2,1520,-8,2,1521,-9,2,1522,-10,2,1523,-11,2,1524,-12,2,1525,-13,3,1526,-14,3,1527,-15,3,1528,-16,3,1529,-17,3,1530,-18,3,1531,-18,3,1532,-18,3,1533,-18,3,1534,-4,2,1535,-18,3,1536,-24,3,1537,-18,3,1538,-26,3,1539,-27,3,1540,-28,3,1541,-29,3,1542,-30,3,1543,-31,3,1544,-32,3,1545,-33,3,1546,-34,3,1547,-35,3,1548,-504,5,1549,-504,5,1550,-504,5,1551,-39,3,1552,-4,2,1553,-504,5,1554,-42,3,1555,-504,5,1556,-504,5,1557,-45,3,1558,-504,5,1559,-504,5,1560,-48,3,1561,-13,3,1562,-14,3,1563,-51,4,1564,-16,3,1565,-17,3,1566,-432,5,1567,-433,5,1568,-56,4,1569,-435,5,1570,-4,2,1571,-432,5,1572,-60,4,1573,-432,5,1574,-440,5,1575,-441,5,1576,-64,4,1577,-443,5,1578,-444,5,1579,-13,3,1580,-68,4,1581,-15,3,1582,-16,3,1583,-17,3,1584,-324,5,1585,-325,5,1586,-326,5,1587,-75,4,1588,-4,2,1589,-329,5,1590,-330,5,1591,-331,5,1592,-80,4,1593,-333,5,1594,-82,4,1595,-83,4,1596,-84,4,1597,-85,4,1598,-14,3,1599,-15,3,1600,-16,3,1601,-324,5,1602,-90,4,1603,-90,4,1604,-90,4,1605,-90,4,1606,-4,2,1607,-5,2,1608,-96,4,1609,-90,4,1610,-90,4,1611,-90,4,1612,-100,4,1613,-101,4,1614,-102,4,1615,-103,4,1616,-14,3,1617,-15,3,1618,-16,3,1619,-17,3,1620,-108,4,1621,-108,4,1622,-108,4,1623,-108,4,1624,-112,4,1625,-5,2,1626,-6,2,1627,-108,4,1628,-108,4,1629,-108,4,1630,-108,4,1631,-119,4,1632,-120,4,1633,-13,3,1634,-14,3,1635,-15,3,1636,-16,3,1637,-17,3,1638,-126,4,1639,-126,4,1640,-128,4,1641,-126,4,1642,-4,2,1643,-5,2,1644,-6,2,1645,-7,2,1646,-126,4,1647,-126,4,1648,-136,4,1649,-126,4,1650,-138,4,1651,-13,3,1652,-14,3,1653,-15,3,1654,-16,3,1655,-17,3,1656,-504,5,1657,-17,3,1658,-18,3,1659,-147,4,1660,-148,4,1661,-13,3,1662,-14,3,1663,-15,3,1664,-16,3,1665,-17,3,1666,-18,3,1667,-504,5,1668,-504,5,1669,-13,3,1670,-14,3,1671,-15,3,1672,-16,3,1673,-17,3,1674,-504,5,1675,-505,5,1676,-504,5,1677,-504,5,1678,-4,2,1679,-504,5,1680,-504,5,1681,-504,5,1682,-504,5,1683,-504,5,1684,-504,5,1685,-504,5,1686,-504,5,1687,-13,3,1688,-14,3,1689,-15,3,1690,-16,3,1691,-17,3,1692,-432,5,1693,-433,5,1694,-434,5,1695,-435,5,1696,-4,2,1697,-5,2,1698,-438,5,1699,-439,5,1700,-440,5,1701,-441,5,1702,-442,5,1703,-443,5,1704,-444,5,1705,-13,3,1706,-14,3,1707,-15,3,1708,-16,3,1709,-17,3,1710,-540,5,1711,-540,5,1712,-452,5,1713,-75,4,1714,-90,4,1715,-540,5,1716,-96,4,1717,-540,5,1718,-80,4,1719,-540,5,1720,-460,5,1721,-90,4,1722,-102,4,1723,-85,4,1724,-14,3,1725,-15,3,1726,-16,3,1727,-17,3,1728,-108,4,1729,-108,4,1730,-90,4,1731,-108,4,1732,-108,4,1733,-102,4,1734,-96,4,1735,-108,4,1736,-108,4,1737,-108,4,1738,-90,4,1739,-108,4,1740,-102,4,1741,-13,3,1742,-14,3,1743,-15,3,1744,-16,3,1745,-17,3,1746,-108,4,1747,-108,4,1748,-108,4,1749,-108,4,1750,-112,4,1751,-5,2,1752,-504,5,1753,-108,4,1754,-108,4,1755,-108,4,1756,-108,4,1757,-119,4,1758,-120,4,1759,-13,3,1760,-14,3,1761,-15,3,1762,-16,3,1763,-17,3,1764,-504,5,1765,-505,5,1766,-506,5,1767,-507,5,1768,-4,2,1769,-5,2,1770,-504,5,1771,-504,5,1772,-512,5,1773,-513,5,1774,-514,5,1775,-515,5,1776,-516,5,1777,-13,3,1778,-14,3,1779,-15,3,1780,-16,3,1781,-17,3,1782,-504,5,1783,-505,5,1784,-506,5,1785,-507,5,1786,-4,2,1787,-5,2,1788,-504,5,1789,-504,5,1790,-512,5,1791,-513,5,1792,-514,5,1793,-515,5,1794,-516,5,1795,-13,3,1796,-14,3,1797,-15,3,1798,-16,3,1799,-17,3,1800,-540,5,1801,-541,5,1802,-540,5,1803,-543,5,1804,-4,2,1805,-5,2,1806,-540,5,1807,-540,5,1808,-540,5,1809,-540,5,1810,-550,5,1811,-551,5,1812,-552,5,1813,-13,3,1814,-14,3,1815,-15,3,1816,-16,3,1817,-17,3,1818,-540,5,1819,-541,5,1820,-560,5,1821,-543,5,1822,-4,2,1823,-5,2,1824,-60,4,1825,-540,5,1826,-540,5,1827,-540,5,1828,-64,4,1829,-551,5,1830,-552,5,1831,-13,3,1832,-68,4,1833,-15,3,1834,-16,3,1835,-17,3,1836,-324,5,1837,-325,5,1838,-326,5,1839,-75,4,1840,-4,2,1841,-329,5,1842,-330,5,1843,-331,5,1844,-80,4,1845,-333,5,1846,-334,5,1847,-335,5,1848,-336,5,1849,-85,4,1850,-14,3,1851,-15,3,1852,-16,3,1853,-324,5,1854,-90,4,1855,-90,4,1856,-90,4,1857,-90,4,1858,-4,2,1859,-5,2,1860,-504,5,1861,-90,4,1862,-80,4,1863,-90,4,1864,-64,4,1865,-504,5,1866,-504,5,1867,-504,5,1868,-14,3,1869,-15,3,1870,-16,3,1871,-17,3,1872,-504,5,1873,-505,5,1874,-506,5,1875,-507,5,1876,-504,5,1877,-5,2,1878,-504,5,1879,-511,5,1880,-80,4,1881,-513,5,1882,-514,5,1883,-504,5,1884,-504,5,1885,-13,3,1886,-14,3,1887,-15,3,1888,-16,3,1889,-17,3,1890,3,11,1891,-1,0,1892,-2,1,1893,-3,1,1894,-4,2,1895,-5,2,1896,-6,2,1897,-7,2,1898,-8,2,1899,-9,2,1900,-10,2,1901,-11,2,1902,-12,2,1903,-13,3,1904,-14,3,1905,-15,3,1906,-16,3,1907,-17,3,1908,-18,3,1909,-18,3,1910,-18,3,1911,-18,3,1912,-4,2,1913,-18,3,1914,-24,3,1915,-18,3,1916,-26,3,1917,-27,3,1918,-28,3,1919,-29,3,1920,-30,3,1921,-31,3,1922,-32,3,1923,-33,3,1924,-34,3,1925,-35,3,1926,-18,3,1927,-18,3,1928,-18,3,1929,-39,3,1930,-4,2,1931,-18,3,1932,-42,3,1933,-18,3,1934,-18,3,1935,-45,3,1936,-18,3,1937,-18,3,1938,-48,4,1939,-18,3,1940,-18,3,1941,-51,4,1942,-18,3,1943,-18,3,1944,-54,4,1945,-54,4,1946,-56,4,1947,-54,4,1948,-54,4,1949,-54,4,1950,-60,4,1951,-61,4,1952,-62,4,1953,-18,3,1954,-64,4,1955,-65,4,1956,-66,4,1957,-67,4,1958,-68,4,1959,-69,4,1960,-54,4,1961,-54,4,1962,-72,4,1963,-72,4,1964,-72,4,1965,-75,4,1966,-4,2,1967,-72,4,1968,-72,4,1969,-72,4,1970,-80,4,1971,-81,4,1972,-82,4,1973,-83,4,1974,-84,4,1975,-85,4,1976,-14,3,1977,-15,3,1978,-16,3,1979,-17,3,1980,-90,4,1981,-90,4,1982,-90,4,1983,-90,4,1984,-4,2,1985,-5,2,1986,-96,4,1987,-90,4,1988,-90,4,1989,-90,4,1990,-100,4,1991,-101,4,1992,-102,4,1993,-103,4,1994,-14,3,1995,-15,3,1996,-16,3,1997,-17,3,1998,-108,4,1999,-108,4,2000,-108,4,2001,-108,4,2002,-112,4,2003,-5,2,2004,-6,2,2005,-108,4,2006,-108,4,2007,-108,4,2008,-108,4,2009,-119,4,2010,-120,4,2011,-13,3,2012,-14,3,2013,-15,3,2014,-16,3,2015,-17,3,2016,4,16,2017,-1,0,2018,-128,4,2019,-3,1,2020,-4,2,2021,-5,2,2022,-6,2,2023,-7,2,2024,-8,2,2025,-9,2,2026,-136,4,2027,-11,2,2028,-12,2,2029,-13,3,2030,-14,3,2031,-15,3,2032,-16,3,2033,-17,3,2034,-18,3,2035,-17,3,2036,-18,3,2037,-147,4,2038,-148,4,2039,-13,3,2040,-14,3,2041,-15,3,2042,-16,3,2043,-17,3,2044,-18,3,2045,-29,3,2046,-30,3,2047,-31,3,0,0,0")
};
/**
* When splitting a set evenly into two subsets, the minimum size of the
* set where k = array index should be used for the Rice parameter k.
*/
private static final int[] RICE_SPLIT_2 = { 0, 4, 14, 50, 188, 726, 2858,
11346, 45214, 180512 };
// private static final int CACHE_SPLITS = 4 * 1024;
private static final int CACHE_SPLITS = 10 * 1024;
private final int leafSize;
private final int averageBucketSize;
private final int[] splits = new int[CACHE_SPLITS];
private final int[] rice = new int[CACHE_SPLITS];
/**
* Constructor for settings.
*
* @param leafSize
* @param averageBucketSize the load factor, at most 65536
*/
public Settings(int leafSize, int averageBucketSize) {
if (IMPROVED_SPLIT_RULES) {
if (leafSize < 1 || leafSize > 32) {
throw new IllegalArgumentException("leafSize out of range: " + leafSize);
}
} else {
if (leafSize < 1 || leafSize > 25) {
throw new IllegalArgumentException("leafSize out of range: " + leafSize);
}
}
if (averageBucketSize < 2 || averageBucketSize > 65536) {
throw new IllegalArgumentException("averageBucketSize out of range: " + averageBucketSize);
}
this.leafSize = leafSize;
this.averageBucketSize = averageBucketSize;
if (IMPROVED_SPLIT_RULES) {
int[] splitRules = SPLIT_RULES[leafSize];
if (splitRules.length == 0 || splitRules[0] == 0) {
throw new IllegalArgumentException("No split rules for leafSize: " + leafSize);
}
for (int i = 0; i < splitRules.length; i += 3) {
int size = splitRules[i];
splits[size] = splitRules[i + 1];
rice[size] = splitRules[i + 2];
}
for (int i = 0; i <= leafSize; i++) {
splits[i] = i;
rice[i] = RICE_LEAF[i];
}
int last = leafSize;
for (int i = leafSize; i < CACHE_SPLITS; i++) {
if (splits[i] != 0) {
last = i;
} else {
splits[i] = -last;
rice[i] = calcRiceParamSplitByTwo(i);
}
}
} else {
for (int i = 0; i < CACHE_SPLITS; i++) {
splits[i] = calcSplit(i, leafSize);
rice[i] = calcGolombRiceShift(i, leafSize);
}
}
}
public int getMaxBucketSize() {
// return averageBucketSize * 20;
return 200 + averageBucketSize * 15 / 10;
}
public static int calcRiceParamSplitByTwo(int size) {
// this will throw an exception for sizes >= 180172
for (int i = 0;; i++) {
if (RICE_SPLIT_2[i] > size) {
return i - 1;
}
}
}
static int calcNextSplit(int factor) {
return Math.max(2, (int) (1.5 + factor * .35));
}
private static int calcSplit(int size, int leafSize) {
for (int x = leafSize, f = x;;) {
if (size < x) {
return -(x / f);
} else if (size == x) {
return f;
}
f = calcNextSplit(f);
x *= f;
}
}
public int getSplit(int size) {
if (size < CACHE_SPLITS) {
return splits[size];
}
if (IMPROVED_SPLIT_RULES) {
throw new IllegalArgumentException();
}
return calcSplit(size, leafSize);
}
public static int calcGolombRiceShift(int size, int leafSize) {
if (size <= leafSize) {
return RICE_LEAF[size];
}
int index = 0;
for (int x = leafSize, f = x;;) {
f = calcNextSplit(f);
if (f <= 2) {
break;
}
x *= f;
if (size < x) {
break;
} else if (size == x) {
return RICE_SPLIT_MORE[leafSize][index];
}
index++;
}
return calcRiceParamSplitByTwo(size);
}
public int getGolombRiceShift(int size) {
if (size < CACHE_SPLITS) {
return rice[size];
}
return calcGolombRiceShift(size, leafSize);
}
public static boolean needNewUniversalHashIndex(long index) {
return (index & (SUPPLEMENTAL_HASH_CALLS - 1)) == 0;
}
public static long getUniversalHashIndex(long index) {
return index >>> SUPPLEMENTAL_HASH_SHIFT;
}
public int getLeafSize() {
return leafSize;
}
public int getAverageBucketSize() {
return averageBucketSize;
}
public static int supplementalHashShift(long hash, long index) {
long x = hash + (index * 0xbf58476d1ce4e5b9L);
x ^= (x << 13);
x ^= (x >>> 17);
x ^= (x << 5);
return (int) x;
}
public static int supplementalHashInt(long hash, long index) {
// but with some JVMs, 32-bit multiplication
// seem to be much faster
// (about 1200 ms for 32 bit, about 2000 ms for 64 bit)
int x = (int) (Long.rotateLeft(hash, (int) index) ^ index);
x = ((x >>> 16) ^ x) * 0x45d9f3b;
x = ((x >>> 16) ^ x) * 0x45d9f3b;
x = (x >>> 16) ^ x;
return x;
}
public static int supplementalHash(long hash, long index) {
long x = hash + index;
// from http://zimbry.blogspot.it/2011/09/better-bit-mixing-improving-on.html
// also used in it.unimi.dsi.fastutil
x = (x ^ (x >>> 30)) * 0xbf58476d1ce4e5b9L;
x = (x ^ (x >>> 27)) * 0x94d049bb133111ebL;
x = x ^ (x >>> 31);
return (int) x;
}
public static int getBucketCount(long size, int averageBucketSize) {
return (int) ((size + averageBucketSize - 1) / averageBucketSize);
}
public static int reduce(int hash, int n) {
// http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
return (int) (((hash & 0xffffffffL) * n) >>> 32);
}
}
================================================
FILE: src/main/java/org/minperf/bdz/BDZ.java
================================================
package org.minperf.bdz;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import org.minperf.BitBuffer;
import org.minperf.Settings;
import org.minperf.rank.VerySimpleRank;
import org.minperf.universal.UniversalHash;
/**
* A simple implementation of the BDZ algorithm as documented in
* "Simple and Space-Efficient Minimal Perfect Hash Functions" (F. C. Botelho,
* R. Pagh, N. Ziviani).
*
* This implementation around 3.66 bits/key, which is much more than really
* needed, mainly because no compression is used.
*
* @param the type
*/
public class BDZ {
// needs 3.66 bits/key
private static final int HASHES = 3;
private static final int FACTOR_TIMES_100 = 123;
private static final int BITS_PER_ENTRY = 2;
// needs 3.78 bits/key
// private static final int HASHES = 4;
// private static final int FACTOR_TIMES_100 = 132;
// private static final int BITS_PER_ENTRY = 2;
// needs 4.25 bits/key
// private static final int HASHES = 2;
// private static final int FACTOR_TIMES_100 = 240;
// private static final int BITS_PER_ENTRY = 1;
private final UniversalHash hash;
private final BitBuffer data;
private final int hashIndex;
private final int arrayLength;
private final int size;
private final int startPos;
private final VerySimpleRank rank;
private BDZ(UniversalHash hash, BitBuffer data) {
this.hash = hash;
this.data = data;
this.size = (int) data.readEliasDelta() - 1;
this.arrayLength = getArrayLength(size);
this.hashIndex = (int) data.readEliasDelta() - 1;
this.rank = VerySimpleRank.load(data);
this.startPos = data.position();
data.seek(startPos + size * BITS_PER_ENTRY);
}
public int evaluate(T x) {
int sum = 0;
for (int hi = 0; hi < HASHES; hi++) {
int h = getHash(x, hash, hashIndex, hi, arrayLength);
if (rank.get(h)) {
int pos = (int) rank.rank(h);
sum += data.readNumber(startPos + pos * BITS_PER_ENTRY, BITS_PER_ENTRY);
}
}
int h = getHash(x, hash, hashIndex, sum % HASHES, arrayLength);
int pos = (int) rank.rank(h);
return pos;
}
public static BDZ load(UniversalHash hash, BitBuffer data) {
return new BDZ(hash, data);
}
@SuppressWarnings("unchecked")
public static BitBuffer generate(UniversalHash hash, Collection set) {
int size = set.size();
int arrayLength = getArrayLength(size);
BitBuffer data = new BitBuffer(100 + arrayLength * (BITS_PER_ENTRY + 2));
data.writeEliasDelta(size + 1);
ArrayList list = new ArrayList(set);
int m = arrayLength;
ArrayList order = new ArrayList();
HashSet done = new HashSet();
T[] at;
int hashIndex = 0;
while (true) {
order.clear();
done.clear();
at = (T[]) new Object[m];
ArrayList> list2 = new ArrayList>();
for (int i = 0; i < m; i++) {
list2.add(new HashSet());
}
for (int i = 0; i < size; i++) {
T x = list.get(i);
for (int hi = 0; hi < HASHES; hi++) {
int h = getHash(x, hash, hashIndex, hi, arrayLength);
HashSet l = list2.get(h);
l.add(x);
}
}
LinkedList alone = new LinkedList();
for (int i = 0; i < arrayLength; i++) {
if (list2.get(i).size() == 1) {
alone.add(i);
}
}
while (!alone.isEmpty()) {
int i = alone.removeFirst();
HashSet l = list2.get(i);
if (l.isEmpty()) {
continue;
}
T x = l.iterator().next();
if (done.contains(x)) {
continue;
}
order.add(x);
done.add(x);
boolean found = false;
for (int hi = 0; hi < HASHES; hi++) {
int h = getHash(x, hash, hashIndex, hi, arrayLength);
l = list2.get(h);
l.remove(x);
if (l.isEmpty()) {
if (!found) {
at[h] = x;
found = true;
}
} else if (l.size() == 1) {
alone.add(h);
}
}
}
if (order.size() == size) {
break;
}
hashIndex++;
}
data.writeEliasDelta(hashIndex + 1);
BitSet visited = new BitSet();
BitSet used = new BitSet();
int[] g = new int[m];
for (int i = order.size() - 1; i >= 0; i--) {
T x = order.get(i);
int sum = 0;
int change = 0;
int target = 0;
for (int hi = 0; hi < HASHES; hi++) {
int h = getHash(x, hash, hashIndex, hi, arrayLength);
if (visited.get(h)) {
sum += g[h];
} else {
visited.set(h);
if (at[h] == x) {
used.set(h);
change = h;
target = hi;
}
}
}
int result = (HASHES + target - (sum % HASHES)) % HASHES;
g[change] = result;
}
VerySimpleRank.generate(used, data);
for (int i = 0; i < m; i++) {
if (used.get(i)) {
data.writeNumber(g[i], BITS_PER_ENTRY);
} else if (g[i] != 0) {
throw new AssertionError();
}
}
return data;
}
public int getSize() {
return size;
}
private static int getArrayLength(int size) {
return HASHES + FACTOR_TIMES_100 * size / 100;
}
private static int getHash(T x, UniversalHash hash,
int hashIndex, int index, int arrayLength) {
long r = hash.universalHash(x, hashIndex + index);
r = Settings.reduce((int) r, arrayLength / HASHES);
r = r + index * arrayLength / HASHES;
return (int) r;
}
@Override
public String toString() {
return getClass().getSimpleName() + " size " + size + " hashIndex " + hashIndex;
}
}
================================================
FILE: src/main/java/org/minperf/generator/ConcurrencyTool.java
================================================
package org.minperf.generator;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
/**
* A tool that either runs tasks one after the other (in the caller thread), or
* uses a ForkJoinPool to run the tasks in parallel.
*/
public class ConcurrencyTool {
private final ForkJoinPool pool;
public ConcurrencyTool(int parallelism) {
if (parallelism > 1) {
pool = new ForkJoinPool(parallelism);
} else {
pool = null;
}
}
public T invoke(ForkJoinTask task) {
if (pool != null) {
return pool.invoke(task);
}
return task.invoke();
}
public void invokeAll(ForkJoinTask>... tasks) {
if (pool != null) {
ForkJoinTask.invokeAll(tasks);
return;
}
for (ForkJoinTask> t : tasks) {
t.invoke();
}
}
public void shutdown() {
if (pool != null) {
pool.shutdown();
}
}
}
================================================
FILE: src/main/java/org/minperf/generator/Generator.java
================================================
package org.minperf.generator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.RecursiveAction;
import org.minperf.BitBuffer;
import org.minperf.Settings;
import org.minperf.bdz.BDZ;
import org.minperf.monotoneList.MonotoneList;
import org.minperf.universal.UniversalHash;
/**
* Generator of a hybrid MPHF. It is guaranteed to use linear space, because
* large buckets are encoded using an alternative algorithm.
*
* @param the type
*/
public class Generator {
public static final int MAX_FILL = 8;
public static final int MAX_BITS_PER_ENTRY = 8;
final ConcurrencyTool pool;
final UniversalHash hash;
private final Settings settings;
private final boolean eliasFanoMonotoneLists;
private final int maxChunkSize;
public Generator(ConcurrencyTool pool,
UniversalHash hash,
Settings settings,
boolean eliasFanoMonotoneLists,
int maxChunkSize) {
this.pool = pool;
this.settings = settings;
this.hash = hash;
this.eliasFanoMonotoneLists = eliasFanoMonotoneLists;
this.maxChunkSize = maxChunkSize;
}
@SuppressWarnings("unchecked")
public void generate(T[] data, long[] hashes, long startIndex, BitBuffer buff) {
int size = data.length;
if (size < 2) {
return;
}
if (size <= settings.getLeafSize()) {
long index = getIndex(data, hashes, startIndex);
int shift = settings.getGolombRiceShift(size);
long value = index - startIndex - 1;
buff.writeGolombRice(shift, value);
return;
}
long index = startIndex + 1;
// num_split_count++;
while (true) {
if (Settings.needNewUniversalHashIndex(index)) {
long x = Settings.getUniversalHashIndex(index);
for (int i = 0; i < size; i++) {
hashes[i] = hash.universalHash(data[i], x);
}
}
if (trySplitEvenly(hashes, index)) {
break;
}
index++;
}
int writeK = settings.getGolombRiceShift(size);
long writeIndex = index - startIndex - 1;
buff.writeGolombRice(writeK, writeIndex);
int split = settings.getSplit(size);
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
T[][] data2;
long[][] hashes2;
if (firstPart != otherPart) {
data2 = (T[][]) new Object[][] { (T[]) new Object[firstPart],
(T[]) new Object[otherPart] };
hashes2 = new long[][] { new long[firstPart], new long[otherPart] };
} else {
data2 = (T[][]) new Object[split][firstPart];
hashes2 = new long[split][firstPart];
}
splitEvenly(data, hashes, index, data2, hashes2);
for (int i = 0; i < data2.length; i++) {
generate(data2[i], hashes2[i], index, buff);
}
}
private long getIndex(T[] data, long[] hashes, long startIndex) {
int size = data.length;
long index = startIndex + 1;
// num_bij_counts[size]++;
outer: while (true) {
if (Settings.needNewUniversalHashIndex(index)) {
long x = Settings.getUniversalHashIndex(index);
for (int i = 0; i < size; i++) {
hashes[i] = hash.universalHash(data[i], x);
}
Arrays.sort(hashes);
for (int i = 1; i < size; i++) {
if (hashes[i - 1] == hashes[i]) {
index++;
while (!Settings.needNewUniversalHashIndex(index)) {
index++;
}
continue outer;
}
}
}
if (tryUnique(hashes, index)) {
return index;
}
index++;
}
}
private boolean trySplitEvenly(long[] hashes, long index) {
int size = hashes.length;
int split = settings.getSplit(size);
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
if (firstPart != otherPart) {
int limit = firstPart;
for (int i = 0; i < size; i++) {
long h = hashes[i];
int x = Settings.supplementalHash(h, index);
// num_split_evals++;
x = Settings.reduce(x, size);
if (x < limit) {
firstPart--;
}
}
return firstPart == 0;
}
int[] count = new int[split];
Arrays.fill(count, firstPart);
for (int i = 0; i < size; i++) {
long h = hashes[i];
int x = Settings.supplementalHash(h, index);
x = Settings.reduce(x, split);
// num_split_evals++;
count[x]--;
}
for (int i = 0; i < split; i++) {
if (count[i] != 0) {
return false;
}
}
return true;
}
private void splitEvenly(T[] data, long[] hashes, long index, T[][] data2,
long[][] hashes2) {
int size = data.length;
int split = data2.length;
int firstPartSize = data2[0].length;
int otherPartSize = data2[1].length;
if (firstPartSize != otherPartSize) {
int i0 = 0, i1 = 0;
int limit = firstPartSize;
for (int i = 0; i < size; i++) {
T t = data[i];
long h = hashes[i];
int x = Settings.supplementalHash(h, index);
x = Settings.reduce(x, size);
if (x < limit) {
data2[0][i0] = t;
hashes2[0][i0] = h;
i0++;
} else {
data2[1][i1] = t;
hashes2[1][i1] = h;
i1++;
}
}
return;
}
int[] pos = new int[split];
for (int i = 0; i < size; i++) {
T t = data[i];
long h = hashes[i];
int x = Settings.supplementalHash(h, index);
int bucket = Settings.reduce(x, split);
int p = pos[bucket]++;
data2[bucket][p] = t;
hashes2[bucket][p] = h;
}
}
// public static long num_split_count;
// public static long num_split_evals;
// public static long[] num_bij_evals = new long[20];
// public static long[] num_bij_counts = new long[20];
static boolean tryUnique(long[] hashes, long index) {
int bits = 0;
int size = hashes.length;
int found = (1 << size) - 1;
for (int i = 0; i < size; i++) {
long x = hashes[i];
int h = Settings.supplementalHash(x, index);
h = Settings.reduce(h, size);
// ++num_bij_evals[size];
// if ((bits & (1 << h)) != 0) {
// return false;
// }
bits |= 1 << h;
}
return bits == found;
// return true;
}
public BitBuffer generate(Collection collection) {
long size = collection.size();
int bucketCount = Settings.getBucketCount(size, settings.getAverageBucketSize());
ArrayList buckets = new ArrayList(bucketCount);
int averageBucketSize = settings.getAverageBucketSize();
if (size <= maxChunkSize || bucketCount == 1) {
for (int i = 0; i < bucketCount; i++) {
buckets.add(new Bucket(averageBucketSize));
}
for (T t : collection) {
int b;
if (bucketCount == 1) {
b = 0;
} else {
long h = hash.universalHash(t, 0);
b = Settings.reduce((int) h, bucketCount);
if (b >= bucketCount || b < 0) {
throw new AssertionError();
}
}
buckets.get(b).add(t);
}
processBuckets(size, bucketCount, buckets);
} else {
// split into chunks
int bucketsPerChunk = Math.max(1, maxChunkSize / averageBucketSize);
int remaining = bucketCount;
for (int bucketOffset = 0; bucketOffset < bucketCount; bucketOffset += bucketsPerChunk) {
int chunkSize = Math.min(bucketsPerChunk, remaining);
remaining -= chunkSize;
ArrayList buckets2 = new ArrayList(chunkSize);
for (int i = 0; i < chunkSize; i++) {
buckets2.add(new Bucket(averageBucketSize));
}
for (T t : collection) {
int b;
long h = hash.universalHash(t, 0);
b = Settings.reduce((int) h, bucketCount);
if (b >= bucketCount || b < 0) {
throw new AssertionError();
}
if (b >= bucketOffset && b < bucketOffset + bucketsPerChunk) {
buckets2.get(b - bucketOffset).add(t);
}
}
processBuckets(size, bucketCount, buckets2);
for (Bucket b2 : buckets2) {
buckets.add(b2);
}
buckets2.clear();
}
}
ArrayList alternativeList = new ArrayList();
for (int i = 0; i < buckets.size(); i++) {
Bucket b = buckets.get(i);
// move all buckets first, so overlap is not affected
b.moveToAlternative(alternativeList);
}
int[] startList = new int[buckets.size() + 1];
int[] offsetList = new int[buckets.size() + 1];
int start = 0, offset = 0;
for (int i = 0; i < buckets.size(); i++) {
Bucket b = buckets.get(i);
if (start - offset < 0) {
throw new AssertionError();
}
int pos = b.buff.position();
// possible overlap
if (i < buckets.size() - 1) {
Bucket next = buckets.get(i + 1);
int maxOverlap = Math.min(16, next.buff.position());
// at least one bit per entry
int minBitCount = getMinBitCount(b.entryCount);
maxOverlap = Math.min(maxOverlap, b.buff.position() - minBitCount);
int overlap = 0;
for (; overlap < maxOverlap; overlap++) {
if (next.buff.readNumber(0, overlap + 1) !=
b.buff.readNumber(pos - overlap - 1, overlap + 1)) {
break;
}
}
pos -= overlap;
b.buff.seek(pos);
}
start += pos;
offset += b.entryCount;
startList[i + 1] = start;
offsetList[i + 1] = offset;
}
shrinkList(startList, offsetList);
int minOffsetDiff = shrinkList(offsetList);
int minStartDiff = shrinkList(startList);
if (minStartDiff < 0) {
throw new AssertionError();
}
BitBuffer alt = null;
if (!alternativeList.isEmpty()) {
alt = BDZ.generate(hash, alternativeList);
}
int bitCount = BitBuffer.getEliasDeltaSize(size + 1);
bitCount += 1;
bitCount += BitBuffer.getEliasDeltaSize(minOffsetDiff + 1);
bitCount += BitBuffer.getEliasDeltaSize(minStartDiff + 1);
bitCount += MonotoneList.getSize(offsetList, eliasFanoMonotoneLists);
bitCount += MonotoneList.getSize(startList, eliasFanoMonotoneLists);
bitCount += start;
if (alt != null) {
bitCount += alt.position();
}
BitBuffer all = new BitBuffer(bitCount);
all.writeEliasDelta(size + 1);
all.writeBit(alternativeList.isEmpty() ? 0 : 1);
all.writeEliasDelta(minOffsetDiff + 1);
all.writeEliasDelta(minStartDiff + 1);
MonotoneList.generate(offsetList, all, eliasFanoMonotoneLists);
MonotoneList.generate(startList, all, eliasFanoMonotoneLists);
for (int i = 0; i < buckets.size(); i++) {
Bucket b = buckets.get(i);
all.write(b.buff);
}
if (alt != null) {
all.write(alt);
}
if (bitCount != all.position()) {
throw new AssertionError();
}
return all;
}
private void processBuckets(long size, int bucketCount, final ArrayList buckets) {
int averageBucketSize = (int) (size / bucketCount);
final int maxBucketSize = averageBucketSize * MAX_FILL;
final int maxBits = maxBucketSize * MAX_BITS_PER_ENTRY;
pool.invoke(new RecursiveAction() {
private static final long serialVersionUID = 1L;
@Override
protected void compute() {
RecursiveAction[] list = new RecursiveAction[buckets.size()];
for (int i = 0; i < buckets.size(); i++) {
final Bucket b = buckets.get(i);
list[i] = new RecursiveAction() {
private static final long serialVersionUID = 1L;
@Override
protected void compute() {
b.generateBucket(hash, maxBucketSize, maxBits);
}
};
}
pool.invokeAll(list);
}
});
}
public static void shrinkList(int[] targetList, int[] sourceList) {
int sum = 0;
for (int i = 1; i < sourceList.length; i++) {
int d = sourceList[i] - sourceList[i - 1];
sum += d;
targetList[i] -= getMinBitCount(sum);
if (targetList[i] < targetList[i - 1]) {
throw new IllegalArgumentException("");
}
}
}
public static int shrinkList(int[] list) {
int min = Integer.MAX_VALUE;
for (int i = 0; i < list.length - 1; i++) {
int d = list[i + 1] - list[i];
min = Math.min(min, d);
}
for (int i = 1; i < list.length; i++) {
list[i] -= i * min;
}
return min;
}
public static int getMinBitCount(int size) {
// at least 1.375 bits per key (if it is less, fill with zeroes)
return (size * 11 + 7) >> 3;
}
/**
* A bucket.
*/
class Bucket {
ArrayList list;
BitBuffer buff;
int entryCount;
boolean alternative;
Bucket(int averageBucketSize) {
list = new ArrayList(averageBucketSize * 11 / 10);
}
@Override
public String toString() {
return "" + entryCount;
}
public void moveToAlternative(ArrayList alternativeList) {
if (alternative) {
alternativeList.addAll(list);
list = null;
entryCount = 0;
buff = new BitBuffer(0);
}
}
void add(T obj) {
list.add(obj);
}
void generateBucket(UniversalHash hash, int maxBucketSize, int maxBits) {
int size = list.size();
entryCount = size;
int minSize = getMinBitCount(size);
if (size <= 1) {
// zero or one entry
buff = new BitBuffer(minSize);
while (buff.position() < minSize) {
buff.writeBit(1);
}
return;
}
if (size > maxBucketSize) {
alternative = true;
buff = new BitBuffer(0);
return;
}
@SuppressWarnings("unchecked")
T[] data = list.toArray((T[]) new Object[0]);
list = null;
long[] hashes = new long[size];
long startIndex = 0;
for (int i = 0; i < size; i++) {
hashes[i] = hash.universalHash(data[i],
Settings.getUniversalHashIndex(startIndex));
}
// this is very conservative; less memory could be allocated
int bufferSize = 8 * size;
if (settings.getLeafSize() < 6) {
bufferSize *= 4;
}
buff = new BitBuffer(bufferSize);
generate(data, hashes, startIndex, buff);
if (buff.position() < minSize) {
while (buff.position() < minSize) {
buff.writeBit(1);
}
}
if (buff.position() > maxBits) {
alternative = true;
}
}
}
}
================================================
FILE: src/main/java/org/minperf/hash/HashPerformanceTest.java
================================================
package org.minperf.hash;
import java.util.Random;
public class HashPerformanceTest {
public static void main(String... args) throws InterruptedException {
test();
test();
test();
}
private static void test() throws InterruptedException {
Thread.sleep(1000);
long dummy = 0;
for (int avgSize = 16; avgSize < 128; avgSize *= 2) {
byte[][] data = new byte[1024 * 1024][avgSize];
Random r = new Random(1);
for (int i = 0; i < data.length; i++) {
r.nextBytes(data[i]);
}
long time = System.nanoTime();
LongPair pair = new LongPair();
for (int j = 0; j < avgSize; j++) {
for (int i = 0; i < data.length; i++) {
// dummy += Murmur2.hash64(data[i], avgSize, j);
// bits: 128 10 ns/key
// bits: 256 17 ns/key
// bits: 512 34 ns/key
// dummy += Murmur2.hash64x8(data[i], avgSize, j);
// bits: 128 8 ns/key
// bits: 256 16 ns/key
// bits: 512 31 ns/key
// dummy += XXHash64.hash64(data[i], 0, avgSize, i);
// bits: 128 16 ns/key
// bits: 256 29 ns/key
// bits: 512 51 ns/key
// SpookyHash.hash128x32(data[i], 0, avgSize, i, pair);
// dummy += pair.val1;
// dummy += pair.val2;
// bits: 256 34 ns/key
// bits: 512 53 ns/key
// dummy += Murmur3.hash64x8(data[i], avgSize, j);
// bits: 128 8 ns/key
// bits: 256 16 ns/key
// bits: 512 31 ns/key
Murmur3.hash128x16(data[i], 0, avgSize, i, pair);
dummy += pair.val1;
dummy += pair.val2;
// bits: 128 16 ns/key
// bits: 256 25 ns/key
// bits: 512 42 ns/key
}
}
time = System.nanoTime() - time;
System.out.println("bits: " + avgSize * 8 + " " + time / data.length / avgSize + " ns/key");
}
System.out.println("dummy " + dummy);
}
}
================================================
FILE: src/main/java/org/minperf/hash/LongPair.java
================================================
package org.minperf.hash;
public class LongPair {
public long val1;
public long val2;
}
================================================
FILE: src/main/java/org/minperf/hash/Mix.java
================================================
package org.minperf.hash;
public class Mix {
public static int supplementalHashWeyl(long hash, long index) {
long x = hash + (index * 0xbf58476d1ce4e5b9L);
x = (x ^ (x >>> 32)) * 0xbf58476d1ce4e5b9L;
x = ((x >>> 32) ^ x);
return (int) x;
}
public static int hash32(int x) {
x = ((x >>> 16) ^ x) * 0x45d9f3b;
x = ((x >>> 16) ^ x) * 0x45d9f3b;
x = (x >>> 16) ^ x;
return x;
}
public static int unhash32(int x) {
x = ((x >>> 16) ^ x) * 0x119de1f3;
x = ((x >>> 16) ^ x) * 0x119de1f3;
x = (x >>> 16) ^ x;
return x;
}
public static long hash64(long x) {
x = (x ^ (x >>> 30)) * 0xbf58476d1ce4e5b9L;
x = (x ^ (x >>> 27)) * 0x94d049bb133111ebL;
x = x ^ (x >>> 31);
return x;
}
public static long unhash64(long x) {
x = (x ^ (x >>> 31) ^ (x >>> 62)) * 0x319642b2d24d8ec3L;
x = (x ^ (x >>> 27) ^ (x >>> 54)) * 0x96de1b173f119089L;
x = x ^ (x >>> 30) ^ (x >>> 60);
return x;
}
}
================================================
FILE: src/main/java/org/minperf/hash/Murmur2.java
================================================
package org.minperf.hash;
public class Murmur2 {
public static final long UINT_MASK = 0xFFFFFFFFl;
public static long hash(byte[] data, int length, long seed) {
long m = 0x5bd1e995l;
int r = 24;
long hash = ((seed ^ length) & UINT_MASK);
int length4 = length >>> 2;
for (int i = 0; i < length4; i++) {
int i4 = i << 2;
long k = (data[i4] & 0xff);
k |= (data[i4 + 1] & 0xff) << 8;
k |= (data[i4 + 2] & 0xff) << 16;
k |= (data[i4 + 3] & 0xff) << 24;
k = ((k * m) & UINT_MASK);
k ^= ((k >>> r) & UINT_MASK);
k = ((k * m) & UINT_MASK);
hash = ((hash * m) & UINT_MASK);
hash = ((hash ^ k) & UINT_MASK);
}
int offset = length4 << 2;
switch (length & 3) {
case 3:
hash ^= ((data[offset + 2] << 16) & UINT_MASK);
case 2:
hash ^= ((data[offset + 1] << 8) & UINT_MASK);
case 1:
hash ^= (data[offset] & UINT_MASK);
hash = ((hash * m) & UINT_MASK);
}
hash ^= ((hash >>> 13) & UINT_MASK);
hash = ((hash * m) & UINT_MASK);
hash ^= hash >>> 15;
return hash;
}
public static long hash64(byte[] data, int length, long seed) {
long m = 0xc6a4a7935bd1e995L;
int r = 47;
long h = (seed & UINT_MASK) ^ (length * m);
int length8 = length >> 3;
for (int i = 0; i < length8; i++) {
int i8 = i << 3;
long k = ((long) data[i8] & 0xff) +
(((long) data[i8 + 1] & 0xff) << 8) +
(((long) data[i8 + 2] & 0xff) << 16) +
(((long) data[i8 + 3] & 0xff) << 24) +
(((long) data[i8 + 4] & 0xff) << 32) +
(((long) data[i8 + 5] & 0xff) << 40) +
(((long) data[i8 + 6] & 0xff) << 48) +
(((long) data[i8 + 7] & 0xff) << 56);
k *= m;
k ^= k >>> r;
k *= m;
h ^= k;
h *= m;
}
switch (length & 7) {
case 7:
h ^= (long) (data[(length & ~7) + 6] & 0xff) << 48;
case 6:
h ^= (long) (data[(length & ~7) + 5] & 0xff) << 40;
case 5:
h ^= (long) (data[(length & ~7) + 4] & 0xff) << 32;
case 4:
h ^= (long) (data[(length & ~7) + 3] & 0xff) << 24;
case 3:
h ^= (long) (data[(length & ~7) + 2] & 0xff) << 16;
case 2:
h ^= (long) (data[(length & ~7) + 1] & 0xff) << 8;
case 1:
h ^= (long) (data[length & ~7] & 0xff);
h *= m;
}
h ^= h >>> r;
h *= m;
h ^= h >>> r;
return h;
}
public static long hash64x8(byte[] data, int length, long seed) {
long m = 0xc6a4a7935bd1e995L;
int r = 47;
long h = seed;
int length8 = length >> 3;
for (int i = 0; i < length8; i++) {
int i8 = i << 3;
long k = ((long) data[i8] & 0xff) +
(((long) data[i8 + 1] & 0xff) << 8) +
(((long) data[i8 + 2] & 0xff) << 16) +
(((long) data[i8 + 3] & 0xff) << 24) +
(((long) data[i8 + 4] & 0xff) << 32) +
(((long) data[i8 + 5] & 0xff) << 40) +
(((long) data[i8 + 6] & 0xff) << 48) +
(((long) data[i8 + 7] & 0xff) << 56);
k *= m;
k ^= k >>> r;
k *= m;
h ^= k;
h *= m;
}
h ^= h >>> r;
h *= m;
h ^= h >>> r;
return h;
}
}
================================================
FILE: src/main/java/org/minperf/hash/Murmur3.java
================================================
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.minperf.hash;
public class Murmur3 {
private static long UINT_MASK = 0xFFFFFFFFl;
public static long hash64(byte[] data, int length, long seed) {
long m = 0xc6a4a7935bd1e995L;
int r = 47;
long h = (seed & UINT_MASK) ^ (length * m);
int length8 = length >> 3;
for (int i = 0; i < length8; i++) {
int i8 = i << 3;
long k = ((long) data[i8] & 0xff) + (((long) data[i8 + 1] & 0xff) << 8)
+ (((long) data[i8 + 2] & 0xff) << 16) + (((long) data[i8 + 3] & 0xff) << 24)
+ (((long) data[i8 + 4] & 0xff) << 32) + (((long) data[i8 + 5] & 0xff) << 40)
+ (((long) data[i8 + 6] & 0xff) << 48) + (((long) data[i8 + 7] & 0xff) << 56);
k *= m;
k ^= k >>> r;
k *= m;
h ^= k;
h *= m;
}
switch (length & 7) {
case 7:
h ^= (long) (data[(length & ~7) + 6] & 0xff) << 48;
case 6:
h ^= (long) (data[(length & ~7) + 5] & 0xff) << 40;
case 5:
h ^= (long) (data[(length & ~7) + 4] & 0xff) << 32;
case 4:
h ^= (long) (data[(length & ~7) + 3] & 0xff) << 24;
case 3:
h ^= (long) (data[(length & ~7) + 2] & 0xff) << 16;
case 2:
h ^= (long) (data[(length & ~7) + 1] & 0xff) << 8;
case 1:
h ^= (long) (data[length & ~7] & 0xff);
h *= m;
}
h ^= h >>> r;
h *= m;
h ^= h >>> r;
return h;
}
public static long hash64x8(byte[] data, int length, long seed) {
long m = 0xc6a4a7935bd1e995L;
int r = 47;
long h = seed;
int length8 = length >> 3;
for (int i = 0; i < length8; i++) {
int i8 = i << 3;
long k = ((long) data[i8] & 0xff) +
(((long) data[i8 + 1] & 0xff) << 8) +
(((long) data[i8 + 2] & 0xff) << 16) +
(((long) data[i8 + 3] & 0xff) << 24) +
(((long) data[i8 + 4] & 0xff) << 32) +
(((long) data[i8 + 5] & 0xff) << 40) +
(((long) data[i8 + 6] & 0xff) << 48) +
(((long) data[i8 + 7] & 0xff) << 56);
k *= m;
k ^= k >>> r;
k *= m;
h ^= k;
h *= m;
}
h ^= h >>> r;
h *= m;
h ^= h >>> r;
return h;
}
public static int fmix32(int h) {
h ^= h >>> 16;
h *= 0x85ebca6b;
h ^= h >>> 13;
h *= 0xc2b2ae35;
h ^= h >>> 16;
return h;
}
public static int hash32(byte[] data, int offset, int len, int seed) {
int c1 = 0xcc9e2d51;
int c2 = 0x1b873593;
int h1 = seed;
// round down to 4 byte block
int roundedEnd = offset + (len & 0xfffffffc);
for (int i = offset; i < roundedEnd; i += 4) {
// little endian load order
int k1 = (data[i] & 0xff) | ((data[i + 1] & 0xff) << 8) | ((data[i + 2] & 0xff) << 16)
| (data[i + 3] << 24);
k1 *= c1;
// ROTL32(k1,15);
k1 = (k1 << 15) | (k1 >>> 17);
k1 *= c2;
h1 ^= k1;
// ROTL32(h1,13);
h1 = (h1 << 13) | (h1 >>> 19);
h1 = h1 * 5 + 0xe6546b64;
}
// tail
int k1 = 0;
switch (len & 0x03) {
case 3:
k1 = (data[roundedEnd + 2] & 0xff) << 16;
// fallthrough
case 2:
k1 |= (data[roundedEnd + 1] & 0xff) << 8;
// fallthrough
case 1:
k1 |= (data[roundedEnd] & 0xff);
k1 *= c1;
// ROTL32(k1,15);
k1 = (k1 << 15) | (k1 >>> 17);
k1 *= c2;
h1 ^= k1;
}
// finalization
h1 ^= len;
// fmix(h1);
h1 ^= h1 >>> 16;
h1 *= 0x85ebca6b;
h1 ^= h1 >>> 13;
h1 *= 0xc2b2ae35;
h1 ^= h1 >>> 16;
return h1;
}
// https://github.com/yonik/java_util/blob/master/src/util/hash/MurmurHash3.java
// This java port was authored by Yonik Seeley and also placed into the
// public domain.
public static void hash128(byte[] key, int offset, int len, int seed, LongPair out) {
// The original algorithm does have a 32 bit unsigned seed.
// We have to mask to match the behavior of the unsigned types and
// prevent sign extension.
long h1 = seed & 0x00000000FFFFFFFFL;
long h2 = seed & 0x00000000FFFFFFFFL;
long c1 = 0x87c37b91114253d5L;
long c2 = 0x4cf5ad432745937fL;
// round down to 16 byte block
int roundedEnd = offset + (len & 0xFFFFFFF0);
for (int i = offset; i < roundedEnd; i += 16) {
long k1 = getLongLittleEndian(key, i);
long k2 = getLongLittleEndian(key, i + 8);
k1 *= c1;
k1 = Long.rotateLeft(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = Long.rotateLeft(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2;
k2 = Long.rotateLeft(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = Long.rotateLeft(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
long k1 = 0;
long k2 = 0;
switch (len & 15) {
case 15:
k2 = (key[roundedEnd + 14] & 0xffL) << 48;
case 14:
k2 |= (key[roundedEnd + 13] & 0xffL) << 40;
case 13:
k2 |= (key[roundedEnd + 12] & 0xffL) << 32;
case 12:
k2 |= (key[roundedEnd + 11] & 0xffL) << 24;
case 11:
k2 |= (key[roundedEnd + 10] & 0xffL) << 16;
case 10:
k2 |= (key[roundedEnd + 9] & 0xffL) << 8;
case 9:
k2 |= (key[roundedEnd + 8] & 0xffL);
k2 *= c2;
k2 = Long.rotateLeft(k2, 33);
k2 *= c1;
h2 ^= k2;
case 8:
k1 = ((long) key[roundedEnd + 7]) << 56;
case 7:
k1 |= (key[roundedEnd + 6] & 0xffL) << 48;
case 6:
k1 |= (key[roundedEnd + 5] & 0xffL) << 40;
case 5:
k1 |= (key[roundedEnd + 4] & 0xffL) << 32;
case 4:
k1 |= (key[roundedEnd + 3] & 0xffL) << 24;
case 3:
k1 |= (key[roundedEnd + 2] & 0xffL) << 16;
case 2:
k1 |= (key[roundedEnd + 1] & 0xffL) << 8;
case 1:
k1 |= (key[roundedEnd] & 0xffL);
k1 *= c1;
k1 = Long.rotateLeft(k1, 31);
k1 *= c2;
h1 ^= k1;
}
// finalization
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
out.val1 = h1;
out.val2 = h2;
}
public static void hash128x16(byte[] key, int offset, int len, long seed, LongPair out) {
long h1 = seed;
long h2 = seed;
long c1 = 0x87c37b91114253d5L;
long c2 = 0x4cf5ad432745937fL;
int roundedEnd = offset + len;
if (roundedEnd > key.length) {
throw new IndexOutOfBoundsException();
}
for (int i = offset; i < roundedEnd; i += 16) {
long k1 = getLongLittleEndian(key, i);
k1 *= c1;
k1 = Long.rotateLeft(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = Long.rotateLeft(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
long k2 = getLongLittleEndian(key, i + 8);
k2 *= c2;
k2 = Long.rotateLeft(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = Long.rotateLeft(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
out.val1 = h1;
out.val2 = h2;
}
private static long getLongLittleEndian(byte[] data, int pos) {
return ((long) data[pos + 7] << 56) |
((data[pos + 6] & 0xffL) << 48) |
((data[pos + 5] & 0xffL) << 40) |
((data[pos + 4] & 0xffL) << 32) |
((data[pos + 3] & 0xffL) << 24) |
((data[pos + 2] & 0xffL) << 16) |
((data[pos + 1] & 0xffL) << 8) |
((data[pos] & 0xffL));
}
private static long fmix64(long k) {
k ^= k >>> 33;
k *= 0xff51afd7ed558ccdL;
k ^= k >>> 33;
k *= 0xc4ceb9fe1a85ec53L;
k ^= k >>> 33;
return k;
}
}
================================================
FILE: src/main/java/org/minperf/hash/SpookyHash.java
================================================
package org.minperf.hash;
public class SpookyHash {
static void hash128x32(byte[] key, int offset, int len, int seed, LongPair out) {
// 128 bit: 16 bytes
// 256 bit: 32 bytes
// 512 bit: 64 bytes
int blocksOf32 = (len/32)*32;
int end32 = offset + blocksOf32;
// handle all complete sets of 32 bytes
long a = seed, b = seed, c = 0xdeadbeefdeadbeefL, d = 0xdeadbeefdeadbeefL;
for (; offset < end32; offset += 32) {
c += readLong(key, offset);
d += readLong(key, offset + 8);
// shortMix(a,b,c,d);
c = Long.rotateLeft(c,50); c += d; a ^= c;
d = Long.rotateLeft(d,52); d += a; b ^= d;
a = Long.rotateLeft(a,30); a += b; c ^= a;
b = Long.rotateLeft(b,41); b += c; d ^= b;
c = Long.rotateLeft(c,54); c += d; a ^= c;
d = Long.rotateLeft(d,48); d += a; b ^= d;
a = Long.rotateLeft(a,38); a += b; c ^= a;
b = Long.rotateLeft(b,37); b += c; d ^= b;
c = Long.rotateLeft(c,62); c += d; a ^= c;
d = Long.rotateLeft(d,34); d += a; b ^= d;
a = Long.rotateLeft(a,5); a += b; c ^= a;
b = Long.rotateLeft(b,36); b += c; d ^= b;
a += readLong(key, offset + 16);
b += readLong(key, offset + 24);
}
d += len << 56;
c += 0xdeadbeefdeadbeefL;
d += 0xdeadbeefdeadbeefL;
// shortEnd(a,b,c,d);
d ^= c; c = Long.rotateLeft(c,15); d += c;
a ^= d; d = Long.rotateLeft(d,52); a += d;
b ^= a; a = Long.rotateLeft(a,26); b += a;
c ^= b; b = Long.rotateLeft(b,51); c += b;
d ^= c; c = Long.rotateLeft(c,28); d += c;
a ^= d; d = Long.rotateLeft(d,9); a += d;
b ^= a; a = Long.rotateLeft(a,47); b += a;
c ^= b; b = Long.rotateLeft(b,54); c += b;
d ^= c; c = Long.rotateLeft(c,32); d += c;
a ^= d; d = Long.rotateLeft(d,25); a += d;
b ^= a; a = Long.rotateLeft(a,63); b += a;
out.val1 = a;
out.val2 = b;
}
static void shortEnd(long a, long b, long c, long d) {
d ^= c; c = Long.rotateLeft(c,15); d += c;
a ^= d; d = Long.rotateLeft(d,52); a += d;
b ^= a; a = Long.rotateLeft(a,26); b += a;
c ^= b; b = Long.rotateLeft(b,51); c += b;
d ^= c; c = Long.rotateLeft(c,28); d += c;
a ^= d; d = Long.rotateLeft(d,9); a += d;
b ^= a; a = Long.rotateLeft(a,47); b += a;
c ^= b; b = Long.rotateLeft(b,54); c += b;
d ^= c; c = Long.rotateLeft(c,32); d += c;
a ^= d; d = Long.rotateLeft(d,25); a += d;
b ^= a; a = Long.rotateLeft(a,63); b += a;
}
static void shortMix(long a, long b, long c, long d) {
c = Long.rotateLeft(c,50); c += d; a ^= c;
d = Long.rotateLeft(d,52); d += a; b ^= d;
a = Long.rotateLeft(a,30); a += b; c ^= a;
b = Long.rotateLeft(b,41); b += c; d ^= b;
c = Long.rotateLeft(c,54); c += d; a ^= c;
d = Long.rotateLeft(d,48); d += a; b ^= d;
a = Long.rotateLeft(a,38); a += b; c ^= a;
b = Long.rotateLeft(b,37); b += c; d ^= b;
c = Long.rotateLeft(c,62); c += d; a ^= c;
d = Long.rotateLeft(d,34); d += a; b ^= d;
a = Long.rotateLeft(a,5); a += b; c ^= a;
b = Long.rotateLeft(b,36); b += c; d ^= b;
}
private static long readLong(byte[] data, int pos) {
return ((long) data[pos] & 0xff) +
(((long) data[pos + 1] & 0xff) << 8) +
(((long) data[pos + 2] & 0xff) << 16) +
(((long) data[pos + 3] & 0xff) << 24) +
(((long) data[pos + 4] & 0xff) << 32) +
(((long) data[pos + 5] & 0xff) << 40) +
(((long) data[pos + 6] & 0xff) << 48) +
(((long) data[pos + 7] & 0xff) << 56);
}
}
================================================
FILE: src/main/java/org/minperf/hash/XXHash64.java
================================================
package org.minperf.hash;
import static java.lang.Long.rotateLeft;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class XXHash64 {
private static final long PRIME64_1 = -7046029288634856825L;
private static final long PRIME64_2 = -4417276706812531889L;
private static final long PRIME64_3 = 1609587929392839161L;
private static final long PRIME64_4 = -8796714831421723037L;
private static final long PRIME64_5 = 2870177450012600261L;
public static long hash64(byte[] buf, int off, int len, long seed) {
checkRange(buf, off, len);
int end = off + len;
long h64;
if (len >= 32) {
int limit = end - 32;
long v1 = seed + PRIME64_1 + PRIME64_2;
long v2 = seed + PRIME64_2;
long v3 = seed + 0;
long v4 = seed - PRIME64_1;
do {
v1 += readLongLE(buf, off) * PRIME64_2;
v1 = rotateLeft(v1, 31);
v1 *= PRIME64_1;
off += 8;
v2 += readLongLE(buf, off) * PRIME64_2;
v2 = rotateLeft(v2, 31);
v2 *= PRIME64_1;
off += 8;
v3 += readLongLE(buf, off) * PRIME64_2;
v3 = rotateLeft(v3, 31);
v3 *= PRIME64_1;
off += 8;
v4 += readLongLE(buf, off) * PRIME64_2;
v4 = rotateLeft(v4, 31);
v4 *= PRIME64_1;
off += 8;
} while (off <= limit);
h64 = rotateLeft(v1, 1) + rotateLeft(v2, 7) + rotateLeft(v3, 12) + rotateLeft(v4, 18);
v1 *= PRIME64_2;
v1 = rotateLeft(v1, 31);
v1 *= PRIME64_1;
h64 ^= v1;
h64 = h64 * PRIME64_1 + PRIME64_4;
v2 *= PRIME64_2;
v2 = rotateLeft(v2, 31);
v2 *= PRIME64_1;
h64 ^= v2;
h64 = h64 * PRIME64_1 + PRIME64_4;
v3 *= PRIME64_2;
v3 = rotateLeft(v3, 31);
v3 *= PRIME64_1;
h64 ^= v3;
h64 = h64 * PRIME64_1 + PRIME64_4;
v4 *= PRIME64_2;
v4 = rotateLeft(v4, 31);
v4 *= PRIME64_1;
h64 ^= v4;
h64 = h64 * PRIME64_1 + PRIME64_4;
} else {
h64 = seed + PRIME64_5;
}
h64 += len;
while (off <= end - 8) {
long k1 = readLongLE(buf, off);
k1 *= PRIME64_2;
k1 = rotateLeft(k1, 31);
k1 *= PRIME64_1;
h64 ^= k1;
h64 = rotateLeft(h64, 27) * PRIME64_1 + PRIME64_4;
off += 8;
}
if (off <= end - 4) {
h64 ^= (readIntLE(buf, off) & 0xFFFFFFFFL) * PRIME64_1;
h64 = rotateLeft(h64, 23) * PRIME64_2 + PRIME64_3;
off += 4;
}
while (off < end) {
h64 ^= (readByte(buf, off) & 0xFF) * PRIME64_5;
h64 = rotateLeft(h64, 11) * PRIME64_1;
++off;
}
h64 ^= h64 >>> 33;
h64 *= PRIME64_2;
h64 ^= h64 >>> 29;
h64 *= PRIME64_3;
h64 ^= h64 >>> 32;
return h64;
}
public static long hash64(ByteBuffer buf, int off, int len, long seed) {
if (buf.hasArray()) {
return hash64(buf.array(), off + buf.arrayOffset(), len, seed);
}
checkRange(buf, off, len);
buf = inLittleEndianOrder(buf);
int end = off + len;
long h64;
if (len >= 32) {
int limit = end - 32;
long v1 = seed + PRIME64_1 + PRIME64_2;
long v2 = seed + PRIME64_2;
long v3 = seed + 0;
long v4 = seed - PRIME64_1;
do {
v1 += readLongLE(buf, off) * PRIME64_2;
v1 = rotateLeft(v1, 31);
v1 *= PRIME64_1;
off += 8;
v2 += readLongLE(buf, off) * PRIME64_2;
v2 = rotateLeft(v2, 31);
v2 *= PRIME64_1;
off += 8;
v3 += readLongLE(buf, off) * PRIME64_2;
v3 = rotateLeft(v3, 31);
v3 *= PRIME64_1;
off += 8;
v4 += readLongLE(buf, off) * PRIME64_2;
v4 = rotateLeft(v4, 31);
v4 *= PRIME64_1;
off += 8;
} while (off <= limit);
h64 = rotateLeft(v1, 1) + rotateLeft(v2, 7) + rotateLeft(v3, 12) + rotateLeft(v4, 18);
v1 *= PRIME64_2;
v1 = rotateLeft(v1, 31);
v1 *= PRIME64_1;
h64 ^= v1;
h64 = h64 * PRIME64_1 + PRIME64_4;
v2 *= PRIME64_2;
v2 = rotateLeft(v2, 31);
v2 *= PRIME64_1;
h64 ^= v2;
h64 = h64 * PRIME64_1 + PRIME64_4;
v3 *= PRIME64_2;
v3 = rotateLeft(v3, 31);
v3 *= PRIME64_1;
h64 ^= v3;
h64 = h64 * PRIME64_1 + PRIME64_4;
v4 *= PRIME64_2;
v4 = rotateLeft(v4, 31);
v4 *= PRIME64_1;
h64 ^= v4;
h64 = h64 * PRIME64_1 + PRIME64_4;
} else {
h64 = seed + PRIME64_5;
}
h64 += len;
while (off <= end - 8) {
long k1 = readLongLE(buf, off);
k1 *= PRIME64_2;
k1 = rotateLeft(k1, 31);
k1 *= PRIME64_1;
h64 ^= k1;
h64 = rotateLeft(h64, 27) * PRIME64_1 + PRIME64_4;
off += 8;
}
if (off <= end - 4) {
h64 ^= (readIntLE(buf, off) & 0xFFFFFFFFL) * PRIME64_1;
h64 = rotateLeft(h64, 23) * PRIME64_2 + PRIME64_3;
off += 4;
}
while (off < end) {
h64 ^= (readByte(buf, off) & 0xFF) * PRIME64_5;
h64 = rotateLeft(h64, 11) * PRIME64_1;
++off;
}
h64 ^= h64 >>> 33;
h64 *= PRIME64_2;
h64 ^= h64 >>> 29;
h64 *= PRIME64_3;
h64 ^= h64 >>> 32;
return h64;
}
private static void checkRange(ByteBuffer buf, int off, int len) {
checkLength(len);
if (len > 0) {
checkRange(buf, off);
checkRange(buf, off + len - 1);
}
}
private static void checkRange(ByteBuffer buf, int off) {
if (off < 0 || off >= buf.capacity()) {
throw new ArrayIndexOutOfBoundsException(off);
}
}
private static ByteBuffer inLittleEndianOrder(ByteBuffer buf) {
if (buf.order().equals(ByteOrder.LITTLE_ENDIAN)) {
return buf;
} else {
return buf.duplicate().order(ByteOrder.LITTLE_ENDIAN);
}
}
private static byte readByte(ByteBuffer buf, int i) {
return buf.get(i);
}
private static int readIntLE(ByteBuffer buf, int i) {
assert buf.order() == ByteOrder.LITTLE_ENDIAN;
return buf.getInt(i);
}
private static long readLongLE(ByteBuffer buf, int i) {
assert buf.order() == ByteOrder.LITTLE_ENDIAN;
return buf.getLong(i);
}
private static void checkRange(byte[] buf, int off) {
if (off < 0 || off >= buf.length) {
throw new ArrayIndexOutOfBoundsException(off);
}
}
private static void checkRange(byte[] buf, int off, int len) {
checkLength(len);
if (len > 0) {
checkRange(buf, off);
checkRange(buf, off + len - 1);
}
}
private static void checkLength(int len) {
if (len < 0) {
throw new IllegalArgumentException("lengths must be >= 0");
}
}
private static byte readByte(byte[] buf, int i) {
return buf[i];
}
private static int readIntLE(byte[] buf, int i) {
return (buf[i] & 0xFF) | ((buf[i + 1] & 0xFF) << 8) | ((buf[i + 2] & 0xFF) << 16) | ((buf[i + 3] & 0xFF) << 24);
}
private static long readLongLE(byte[] buf, int i) {
return (buf[i] & 0xFFL) | ((buf[i + 1] & 0xFFL) << 8) | ((buf[i + 2] & 0xFFL) << 16)
| ((buf[i + 3] & 0xFFL) << 24) | ((buf[i + 4] & 0xFFL) << 32) | ((buf[i + 5] & 0xFFL) << 40)
| ((buf[i + 6] & 0xFFL) << 48) | ((buf[i + 7] & 0xFFL) << 56);
}
}
================================================
FILE: src/main/java/org/minperf/hem/HemGenerator.java
================================================
package org.minperf.hem;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import org.minperf.BitBuffer;
import org.minperf.hem.recsplit.Builder;
import org.minperf.utils.RandomSetGenerator;
import org.minperf.utils.RandomSetGenerator.RandomBlockProducer;
public class HemGenerator {
public static void main(String... args) throws Exception {
new HemGenerator().test_10_12_64();
}
public void test_10_12_64() throws Exception {
// generate a MPHF with 10^12 keys, each 64 bit
// 10^12 would take around 16 hours to generate
// 2.87 bits/key, that is around 335 GB
String userHome = System.getProperty("user.home");
String fileName = userHome + "/temp/hash.bin";
FileOutputStream fOut = new FileOutputStream(fileName);
out = new DataOutputStream(new BufferedOutputStream(fOut));
totalSize = 1_000_000_000_000L;
// totalSize = 1_000_000_00L;
out.writeLong(totalSize);
generator = new RandomHashGenerator(totalSize);
lowBitCount = 64;
long expectedBlockSize = totalSize;
final int maxBlockSize = 2_000_000;
while (expectedBlockSize > maxBlockSize) {
lowBitCount--;
expectedBlockSize >>>= 1;
}
int highBitCount = 64 - lowBitCount;
System.out.println("lowBits: " + lowBitCount);
System.out.println("highBits: " + highBitCount);
System.out.println("expectedBlockSize: " + expectedBlockSize);
max = 1L << highBitCount;
startTime = System.nanoTime();
int threadCount = 8;
Thread[] threads = new Thread[threadCount];
for (int id = 0; id < threadCount; id++) {
Thread t = new Thread() {
@Override
public void run() {
long[] keys = new long[maxBlockSize * 2];
while (true) {
BlockInfo info = generateKeys(keys);
if (info == null) {
break;
}
BitBuffer buff = new Builder().generate(keys, info.len);
write(info, buff);
}
}
};
t.start();
threads[id] = t;
}
for (Thread t : threads) {
t.join();
}
out.writeLong(-1);
out.writeInt(-1);
out.close();
System.out.println("done");
testRead(fileName);
}
static void testRead(String fileName) throws IOException {
FileInputStream fIn = new FileInputStream(fileName);
DataInputStream in;
in = new DataInputStream(new BufferedInputStream(fIn));
long totalSize = in.readLong();
System.out.println("total size " + totalSize);
while(true) {
long high = in.readLong();
int len = in.readInt();
byte[] data = new byte[len];
// System.out.println("read high: " + high + " len: " + len);
if (high == -1) {
break;
}
in.readFully(data);
}
in.close();
fIn.close();
// System.out.println("done");
}
long totalSize;
DataOutputStream out;
HashGenerator generator;
int lowBitCount;
long startTime;
long high;
long max;
long total;
long totalBits;
synchronized void write(BlockInfo info, BitBuffer buff) {
total += info.len;
byte[] data = buff.toByteArray();
totalBits += data.length * 8;
long time = System.nanoTime() - startTime;
double percentDone = 100. * total / totalSize;
System.out.println(time / total + " ns/key " + (totalBits / 8 / 1024 / 1024) + " MB " + percentDone + "% "
+ (double) totalBits / total + " bits/key");
// System.out.println("write " + info.high + " len " + info.len + " " + data.length);
try {
out.writeLong(info.high);
out.writeInt(info.len);
out.write(buff.toByteArray());
} catch (IOException e) {
throw new RuntimeException();
}
}
synchronized BlockInfo generateKeys(long[] data) {
if (high >= max) {
return null;
}
BlockInfo info = new BlockInfo();
info.high = high++;
info.len = generator.generateBlock(data, lowBitCount);
if (info.len == 0) {
System.out.println("not generated! " + data.length + " " + lowBitCount);
}
return info;
}
static class BlockInfo {
int len;
long high;
}
static class RandomHashGenerator implements HashGenerator {
private final long[] buffer;
private final RandomBlockProducer producer;
private final int blockSize = 8 * 1024 * 1024;
private int offset, end;
private long highBits;
public RandomHashGenerator(long size) {
this.producer = RandomSetGenerator.randomHashProducer(new Random(1), size);
buffer = new long[blockSize];
}
@Override
public int generateBlock(long[] data, int lowBitCount) {
int len = 0;
// TODO why not 64 - lowBitCount?
int shift = 65 - lowBitCount;
while (true) {
while (offset < end) {
long x = buffer[offset];
if ((x >>> lowBitCount) != highBits) {
highBits++;
return len;
}
offset++;
data[len++] = x << shift;
}
offset = 0;
end = producer.produce(buffer, 0, blockSize, 0);
if (end == 0) {
return len;
}
}
}
}
interface HashGenerator {
int generateBlock(long[] data, int lowBits);
}
}
================================================
FILE: src/main/java/org/minperf/hem/KeyReader.java
================================================
package org.minperf.hem;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.PrimitiveIterator;
import java.util.UUID;
import java.util.concurrent.Future;
import org.minperf.hash.Mix;
import org.minperf.hash.Murmur2;
public class KeyReader {
private static final int MAX_KEY_SIZE = 1024;
private static final UUID EMPTY = new UUID(0, 0);
public static void main(String... args) {
// seq -f "%.20g" 1 1000000 > ~/temp/hash/keys.txt
// seq -f "%.20g" 1 100000000 > ~/temp/hash/keys.txt
for(int test = 0; test < 10; test++) {
Iterator it = KeyReader.readSignaturesFromTextFile2(args[0]);
long time = System.nanoTime();
long count = 0;
long dummy = 0;
while(it.hasNext()) {
UUID uuid = it.next();
count++;
dummy += uuid.getMostSignificantBits() + uuid.getLeastSignificantBits();
}
time = System.nanoTime() - time;
System.out.println("time: " + time + " dummy "+ dummy + " count " + count + " " + time / count + " ns/key");
}
}
static Iterator readSignaturesFromTextFile(final String fileName) {
return new Iterator() {
private static final int BUFFER_SIZE = 512 * 1024 * 1024;
private final InputStream input;
private final byte[] key = new byte[MAX_KEY_SIZE];
private UUID current;
{
FileInputStream fileIn;
try {
fileIn = new FileInputStream(fileName);
} catch (IOException e) {
throw new RuntimeException(e);
}
input = new BufferedInputStream(fileIn, BUFFER_SIZE);
fetchNext();
}
private void fetchNext() {
int i = 0;
for (;; i++) {
int x;
try {
x = input.read();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (x < 0) {
try {
input.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (i == 0) {
current = null;
return;
}
break;
}
if (x <= ' ') {
if (i == 0) {
i--;
continue;
}
break;
}
if (i >= MAX_KEY_SIZE) {
throw new RuntimeException("Key too long, max size " + MAX_KEY_SIZE);
}
key[i] = (byte) x;
}
current = EMPTY;
// current = getSipHash24(key, 0, i);
}
@Override
public boolean hasNext() {
return current != null;
}
@Override
public UUID next() {
UUID result = current;
if (result != null) {
fetchNext();
}
return result;
}
};
}
public static Iterator readSignaturesFromTextFile2(final String fileName) {
return new Iterator() {
private final RandomAccessFile f;
private final FileChannel fc;
private final MappedByteBuffer buff;
private final byte[] key = new byte[MAX_KEY_SIZE];
private UUID current;
private int size;
private int pos;
{
try {
f = new RandomAccessFile(fileName, "r");
fc = f.getChannel();
size = (int) fc.size();
buff = fc.map(MapMode.READ_ONLY, 0, size);
} catch (IOException e) {
throw new RuntimeException(e);
}
fetchNext();
}
private void fetchNext() {
int i=0;
for (;; i++) {
if (pos >= size) {
try {
fc.close();
f.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
current = null;
return;
}
int x = buff.get();
pos++;
if (x <= ' ') {
if (i == 0) {
i--;
continue;
}
break;
}
key[i] = (byte) x;
// if (i >= MAX_KEY_SIZE) {
// throw new RuntimeException("Key too long, max size " + MAX_KEY_SIZE);
// }
}
// current = EMPTY;
// TODO find a fast 128 bit hash function
current = new UUID(Murmur2.hash64(key, i, 0), 0);
// current = getSipHash24(buff, start, i);
}
@Override
public boolean hasNext() {
return current != null;
}
@Override
public UUID next() {
UUID result = current;
if (result != null) {
fetchNext();
}
return result;
}
};
}
static PrimitiveIterator.OfLong readSignaturesFromTextFile64(final String fileName) {
return new PrimitiveIterator.OfLong() {
private static final int MAX_BUFFER_SIZE = 512 * 1024 * 1024;
private final RandomAccessFile f;
private final FileChannel fc;
private MappedByteBuffer buff;
private long size;
private long pos;
{
try {
f = new RandomAccessFile(fileName, "r");
fc = f.getChannel();
size = fc.size();
remap();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void remap() {
try {
long s = Math.min(size - pos, MAX_BUFFER_SIZE);
buff = fc.map(MapMode.READ_ONLY, pos, s);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean hasNext() {
return pos < size;
}
@Override
public long nextLong() {
if (!buff.hasRemaining()) {
remap();
}
pos += 8;
// return buff.getLong();
return Mix.hash64(buff.getLong());
// return universalHash(buff.getLong(), 0);
}
};
}
public static Iterator readSignaturesFromTextFile64input(final String fileName) {
return new Iterator() {
private static final int BUFFER_SIZE = 8 * 1024;
private final DataInputStream in;
private long size;
private long pos;
{
try {
size = new File(fileName).length();
in = new DataInputStream(
new BufferedInputStream(
new FileInputStream(fileName)
, BUFFER_SIZE
)
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean hasNext() {
return pos < size;
}
@Override
public Long next() {
try {
pos += 8;
return in.readLong();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
}
static Iterator readSignaturesFromTextFile64b(final String fileName) {
return new Iterator() {
private static final int BUFFER_SIZE = 64 * 1024;
private final RandomAccessFile f;
private final FileChannel fc;
private final ByteBuffer buff;
private int size;
private int pos;
{
try {
f = new RandomAccessFile(fileName, "r");
fc = f.getChannel();
size = (int) fc.size();
buff = ByteBuffer.allocate(BUFFER_SIZE);
readBatch();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void readBatch() {
buff.clear();
try {
// TODO may not read all bytes (and possibly not a multiple of 64)
fc.read(buff);
} catch (IOException e) {
throw new RuntimeException(e);
}
buff.flip();
}
@Override
public boolean hasNext() {
return pos < size ;
}
@Override
public Long next() {
if (!buff.hasRemaining()) {
readBatch();
}
pos += 8;
return buff.getLong();
// return mix64(buff.getLong());
// return universalHash(buff.getLong(), 0);
}
};
}
static Iterator readSignaturesFromTextFile64async(final String fileName) {
return new Iterator() {
private static final int BUFFER_SIZE = 64 * 1024;
private final AsynchronousFileChannel fc;
private final ByteBuffer[] buffers = new ByteBuffer[2];
private Future future;
private int currentBuff = 1;
private int size;
private int pos;
{
try {
fc = AsynchronousFileChannel.open(Paths.get(fileName));
size = (int) fc.size();
buffers[0] = ByteBuffer.allocate(BUFFER_SIZE);
buffers[1] = ByteBuffer.allocate(BUFFER_SIZE);
readBatch();
readBatch();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void readBatch() {
if (future != null) {
try {
while (!future.isDone()) {
Thread.yield();
}
Integer x = future.get();
pos += x;
int readBuff = 1 ^ currentBuff;
ByteBuffer buff = buffers[readBuff];
buff.flip();
currentBuff ^= 1;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
int readBuff = 1 ^ currentBuff;
ByteBuffer buff = buffers[readBuff];
buff.clear();
// TODO may not read all bytes (and possibly not a multiple of 64)
future = fc.read(buff, pos);
}
@Override
public boolean hasNext() {
return pos < size ;
}
@Override
public Long next() {
ByteBuffer buff = buffers[currentBuff];
if (!buff.hasRemaining()) {
readBatch();
buff = buffers[currentBuff];
}
return buff.getLong();
// return mix64(buff.getLong());
// return universalHash(buff.getLong(), 0);
}
};
}
}
================================================
FILE: src/main/java/org/minperf/hem/Sort.java
================================================
package org.minperf.hem;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class Sort extends RecursiveAction {
private static final long serialVersionUID = 1L;
public static void main(String... args) {
testSortUnsigned();
int count = 128 * 1024 * 1024; // * 1024 * 1024;
for(int test = 0; test < 4; test++) {
System.out.println("test " + test);
Random r = new Random(test);
long[] data = new long[count];
long sum = 0;
for(int i = 0; i < data.length; i++) {
long x = r.nextLong();
sum += x;
data[i] = x;
}
long time = System.nanoTime();
parallelSortUnsigned(data);
// 16M: sorted in 0.497069951 secs
// 128M: sorted in 2.943904999 secs
// 256M: sorted in 5.710293362 secs
// sortUnsignedSimple(data);
// 16M: sorted in 0.46763204 secs
// 128M: sorted in 4.179389644 secs
// 256M: sorted in 8.616092879 secs
// Arrays.parallelSort(data);
// 16M: sorted in 0.399732495 secs
// 128M: sorted in 3.498315688 secs
// 256M: sorted in 7.834619304 secs
// Arrays.sort(data);
// 16M: sorted in 1.50651212 secs
// 128M: sorted in 14.864402323 secs
time = System.nanoTime() - time;
System.out.println("sorted in " + (time / 1_000_000_000.) + " secs");
long sum2 = 0;
for(long x : data) {
sum2 += x;
}
if (sum != sum2) {
throw new AssertionError("sum changed");
}
for (int i = 1; i < data.length; i++) {
if (Long.compareUnsigned(data[i - 1], data[i]) > 0) {
throw new AssertionError("index " + i);
}
}
System.out.println("compared");
}
}
private static void testSortUnsigned() {
Random r = new Random(1);
for (int test = 0; test < 1000; test++) {
int len = r.nextInt(10);
long[] data = new long[len];
for (int i = 0; i < len; i++) {
data[i] = r.nextInt(5) - 2;
}
parallelSortUnsigned(data);
// sortUnsignedSimple(data);
for (int i = 1; i < data.length; i++) {
if (Long.compareUnsigned(data[i - 1], data[i]) > 0) {
throw new AssertionError("index " + i);
}
}
}
}
private static int S = 8;
private static final long MASK = (1 << S) - 1;
private static final int BUCKETS = 1 << S;
private final long[] data;
private final int start;
private final int end;
private final int shift;
private final int level;
Sort(long[] data, int start, int end, int shift, int level) {
this.data = data;
this.start = start;
this.end = end;
this.shift = shift;
this.level = level;
}
public static void parallelSortUnsigned(long[] data, int offset, int len) {
if (len < BUCKETS) {
sortUnsignedSimple(data, offset, len);
return;
}
ForkJoinPool.commonPool().invoke(new Sort(data, offset, offset + len, 64 - S, 0));
}
public static void parallelSortUnsigned(long[] data) {
parallelSortUnsigned(data, 0, data.length);
}
@Override
protected void compute() {
if (level > 0 && end - start < BUCKETS) {
Arrays.sort(data, start, end);
return;
}
int[] pos = new int[BUCKETS];
for (int i = start; i < end; i++) {
long x = data[i];
int b = (int) ((x >>> shift) & MASK);
pos[b]++;
}
int[] stop = new int[BUCKETS];
int sum = start;
for (int i = 0; i < pos.length; i++) {
int count = pos[i];
pos[i] = sum;
sum += count;
stop[i] = sum;
}
int i = start;
long x = data[i];
outer:
for(int bucket = 0;;) {
int targetBucket = (int) ((x >>> shift) & MASK);
int index = pos[targetBucket]++;
long next = data[index];
data[index] = x;
x = next;
if (index == i) {
while (true) {
index = pos[bucket];
if (index < stop[bucket]) {
break;
}
bucket++;
if (bucket >= BUCKETS) {
break outer;
}
}
i = index;
x = data[index];
}
}
ArrayList tasks = new ArrayList<>();
int startBucket = start;
for (int bucket = 0; bucket < BUCKETS; bucket++) {
int stopBucket = pos[bucket];
if (stopBucket - startBucket < BUCKETS) {
Arrays.sort(data, startBucket, stopBucket);
} else {
tasks.add(new Sort(data, startBucket, stopBucket, shift - S, level + 1));
}
startBucket = stopBucket;
}
if (!tasks.isEmpty()) {
invokeAll(tasks);
}
}
static void sortUnsignedSimple(long[] data, int offset, int len) {
int left = offset, right = offset + len - 1;
while(true) {
while (left < data.length && data[left] >= 0) {
left++;
}
while (right > 0 && data[right] < 0) {
right--;
}
if (left >= right) {
break;
}
long temp = data[left];
data[left++] = data[right];
data[right--] = temp;
}
Arrays.parallelSort(data, offset, left);
Arrays.parallelSort(data, left, len);
}
static void sort(long[] data) {
sort(data, 0, data.length, 64 - S);
}
static void sort(long[] data, int start, int end, int shift) {
if (end - start < BUCKETS) {
Arrays.sort(data, start, end);
return;
}
int[] pos = new int[BUCKETS];
for(int i=start; i>> shift) & MASK);
pos[b]++;
}
int[] stop = new int[BUCKETS];
int sum = start;
for (int i = 0; i < pos.length; i++) {
int count = pos[i];
pos[i] = sum;
sum += count;
stop[i] = sum;
}
int i = start;
long x = data[i];
outer:
for(int bucket = 0;;) {
int targetBucket = (int) ((x >>> shift) & MASK);
int index = pos[targetBucket]++;
long next = data[index];
data[index] = x;
x = next;
if (index == i) {
while (true) {
index = pos[bucket];
if (index < stop[bucket]) {
break;
}
bucket++;
if (bucket >= BUCKETS) {
break outer;
}
}
i = index;
x = data[index];
}
}
int startBucket = start;
for (int bucket = 0; bucket < BUCKETS; bucket++) {
int stopBucket = pos[bucket];
sort(data, startBucket, stopBucket, shift - S);
startBucket = stopBucket;
}
}
}
================================================
FILE: src/main/java/org/minperf/hem/SortedSignatures.java
================================================
package org.minperf.hem;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.PrimitiveIterator;
import org.minperf.BitBuffer;
public class SortedSignatures {
private static final int MAP_SIZE = 512 * 1024 * 1024;
private static final int BUFFER_SIZE = 4 * 1024 * 1024;
private static final int OVERLAP = 1024;
static class FileIterator {
private final RandomAccessFile f;
private final FileChannel fc;
private MappedByteBuffer buff;
private long offset;
private final long size;
FileIterator(String fileName) {
try {
f = new RandomAccessFile(fileName, "r");
fc = f.getChannel();
size = fc.size();
remap();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private long position() {
return offset + buff.position();
}
void remap() {
try {
long pos = buff == null ? 0 : position();
offset = pos / (MAP_SIZE / 2) * (MAP_SIZE / 2);
long s = Math.min(size - offset, MAP_SIZE);
buff = fc.map(MapMode.READ_ONLY, offset, s);
buff.position((int) (pos - offset));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void remapIfNeeded() {
if (buff.position() > MAP_SIZE / 2) {
remap();
}
}
void close() {
try {
fc.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
PrimitiveIterator.OfLong iteratorVarLong(final int len) {
return new PrimitiveIterator.OfLong() {
private int i;
private long x;
@Override
public boolean hasNext() {
return i < len;
}
@Override
public long nextLong() {
remapIfNeeded();
x += readVarLong(buff);
return x;
}
};
}
PrimitiveIterator.OfLong iteratorGolombRice(final int len, final int shift) {
return new PrimitiveIterator.OfLong() {
private int i;
private long last;
private byte[] bytes = new byte[(BUFFER_SIZE + OVERLAP) / 8];
private BitBuffer buffer;
{
int readBytes = (int) Math.min(BUFFER_SIZE / 8, size);
remapIfNeeded();
buff.get(bytes, OVERLAP / 8, readBytes);
buffer = new BitBuffer(bytes);
buffer.seek(OVERLAP);
}
@Override
public boolean hasNext() {
return i < len;
}
@Override
public long nextLong() {
long x = buffer.readGolombRice(shift);
last += x;
int pos = buffer.position();
if (pos > BUFFER_SIZE) {
System.arraycopy(bytes, BUFFER_SIZE / 8, bytes, 0, OVERLAP / 8);
int readBytes = (int) Math.min(BUFFER_SIZE / 8, size - position());
remapIfNeeded();
buff.get(bytes, OVERLAP / 8, readBytes);
buffer = new BitBuffer(bytes);
buffer.seek(pos - BUFFER_SIZE);
}
return last;
}
};
}
}
static class FileWriter {
private final FileChannel fc;
FileWriter(String fileName) {
try {
@SuppressWarnings("resource")
RandomAccessFile f = new RandomAccessFile(fileName, "rw");
fc = f.getChannel();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void close() {
try {
fc.truncate(fc.position());
fc.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void writeDiffsGolombRice(long[] data, int shift) {
// Sort.parallelSort(data);
BitBuffer buff = new BitBuffer(BUFFER_SIZE + OVERLAP);
long last = 0;
for(long x : data) {
long diff = x - last;
last = x;
buff.writeGolombRice(shift, diff);
if (buff.position() > BUFFER_SIZE) {
writeBlock(buff);
}
}
write(ByteBuffer.wrap(buff.toByteArray()));
}
void writeBlock(BitBuffer buff) {
int pos = buff.position();
write(ByteBuffer.wrap(buff.toByteArray(), 0, BUFFER_SIZE / 8));
BitBuffer buff2 = new BitBuffer(OVERLAP);
buff.seek(BUFFER_SIZE);
while (buff.position() < pos) {
buff2.writeBit(buff.readBit());
}
buff.clear();
buff.seek(0);
buff.write(buff2);
}
void writeDiffsVarLong(long[] data) {
// Sort.parallelSort(data);
ByteBuffer buff = ByteBuffer.allocate(BUFFER_SIZE);
long last = 0;
for(long x : data) {
long diff = x - last;
last = x;
writeVarLong(buff, diff);
if (buff.remaining() < 16) {
buff.flip();
write(buff);
buff.clear();
}
}
buff.flip();
write(buff);
}
void write(ByteBuffer data) {
try {
// TODO return value is currently not checked
fc.write(data);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
static class FileWriterChannel {
private final FileChannel fc;
FileWriterChannel(String fileName) {
try {
new File(fileName).delete();
@SuppressWarnings("resource")
RandomAccessFile f = new RandomAccessFile(fileName, "rw");
fc = f.getChannel();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void close() {
try {
fc.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void writeDiffsEliasDelta(long[] data) {
// Sort.parallelSort(data);
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(data.length);
buffer.flip();
write(buffer);
BitBuffer buff = new BitBuffer(BUFFER_SIZE);
long last = 0;
for(long x : data) {
long diff = x - last;
last = x;
buff.writeEliasDelta(diff);
writeBitBuffer(buff, false);
}
writeBitBuffer(buff, true);
}
void writeBitBuffer(BitBuffer buff, boolean always) {
int remaining = 8 * BUFFER_SIZE - buff.position();
if (always) {
remaining = 0;
}
if (remaining < 256) {
byte[] b = buff.toByteArray();
ByteBuffer buffer = ByteBuffer.allocate(b.length + 1);
buffer.put((byte) remaining);
write(buffer);
buff.seek(0);
}
}
void writeDiffsGolombRice(long[] data, int shift) {
// Sort.parallelSort(data);
BitBuffer buff = new BitBuffer(BUFFER_SIZE);
long last = 0;
for(long x : data) {
long diff = x - last;
last = x;
buff.writeGolombRice(shift, diff);
writeBitBuffer(buff, false);
}
writeBitBuffer(buff, true);
}
void writeDiffs(long[] data) {
// Sort.parallelSort(data);
ByteBuffer buff = ByteBuffer.allocate(BUFFER_SIZE);
long last = 0;
for(long x : data) {
long diff = x - last;
last = x;
writeVarLong(buff, diff);
if (buff.remaining() < 16) {
buff.flip();
write(buff);
buff.clear();
}
}
buff.flip();
write(buff);
}
void write(ByteBuffer data) {
try {
fc.write(data);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void writeVarLong(ByteBuffer buff, long x) {
while ((x & ~0x7f) != 0) {
buff.put((byte) (0x80 | (x & 0x7f)));
x >>>= 7;
}
buff.put((byte) x);
}
public static long readVarLong(ByteBuffer buff) {
long x = buff.get();
if (x >= 0) {
return x;
}
x &= 0x7f;
for (int s = 7; s < 64; s += 7) {
long b = buff.get();
x |= (b & 0x7f) << s;
if (b >= 0) {
break;
}
}
return x;
}
}
================================================
FILE: src/main/java/org/minperf/hem/recsplit/Builder.java
================================================
package org.minperf.hem.recsplit;
import org.minperf.BitBuffer;
import org.minperf.hash.Mix;
public class Builder {
private static final int[] SHIFT = { 0, 0, 0, 1, 3, 4, 5, 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, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3 };
private int averageBucketSize = 16;
private int leafSize = 5;
public Builder leafSize(int leafSize) {
this.leafSize = leafSize;
return this;
}
public Builder averageBucketSize(int averageBucketSize) {
this.averageBucketSize = averageBucketSize;
return this;
}
public BitBuffer generate(long[] keys) {
return new FastGenerator(leafSize, averageBucketSize).generate(keys);
}
public BitBuffer generate(long[] keys, int len) {
return new FastGenerator(leafSize, averageBucketSize).generate(keys, len);
}
public FastEvaluator evaluator(BitBuffer buff) {
return new FastEvaluator(buff, averageBucketSize, leafSize, 0);
}
public static int supplementalHash(long x, int index) {
// TODO can save one multiplication for generation
//System.out.println(" " + x + " [" + index + "]");
return Mix.supplementalHashWeyl(x, index);
}
public static int reduce(int hash, int n) {
// http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
return (int) (((hash & 0xffffffffL) * n) >>> 32);
}
public static int getBucketCount(long size, int averageBucketSize) {
int bucketCount = (int) ((size + averageBucketSize - 1) / averageBucketSize);
return nextPowerOf2(bucketCount);
}
static int nextPowerOf2(int x) {
if (Integer.bitCount(x) == 1) {
return x;
}
return Integer.highestOneBit(x) * 2;
}
public static int getGolombRiceShift(int size) {
return SHIFT[size];
}
}
================================================
FILE: src/main/java/org/minperf/hem/recsplit/FastEvaluator.java
================================================
package org.minperf.hem.recsplit;
import org.minperf.BitBuffer;
import org.minperf.monotoneList.MultiStageMonotoneList;
public class FastEvaluator {
private final BitBuffer buffer;
private final long size;
private final int leafSize;
private final int bucketCount;
private final int bucketShift;
private final MultiStageMonotoneList startList;
private final MultiStageMonotoneList offsetList;
private final int startBuckets;
FastEvaluator(BitBuffer buffer, int averageBucketSize, int leafSize, int shift) {
this.buffer = buffer;
this.size = (int) (buffer.readEliasDelta() - 1);
this.bucketCount = Builder.getBucketCount(size, averageBucketSize);
this.leafSize = leafSize;
int bucketBitCount = 31 - Integer.numberOfLeadingZeros(bucketCount);
this.bucketShift = 64 - bucketBitCount - shift;
this.startList = MultiStageMonotoneList.load(buffer);
this.offsetList = MultiStageMonotoneList.load(buffer);
this.startBuckets = buffer.position();
}
public int evaluate(long hashCode) {
int b;
if (bucketCount == 1) {
b = 0;
} else {
b = (int) (hashCode >>> bucketShift);
}
int startPos;
long offsetPair = offsetList.getPair(b);
int offset = (int) (offsetPair >>> 32);
int offsetNext = (int) offsetPair;
if (offsetNext == offset) {
// entry not found
return -1;
}
int bucketSize = offsetNext - offset;
startPos = startBuckets + startList.get(b);
return evaluate(startPos, hashCode, 0, offset, bucketSize);
}
private int skip(int pos, int size) {
if (size < 2) {
return pos;
}
pos = buffer.skipGolombRice(pos, Builder.getGolombRiceShift(size));
if (size <= leafSize) {
return pos;
}
int firstPart = size / 2;
pos = skip(pos, firstPart);
pos = skip(pos, size - firstPart);
return pos;
}
private int evaluate(int pos, long hashCode,
int index, int add, int size) {
while (true) {
if (size < 2) {
return add;
}
int shift = Builder.getGolombRiceShift(size);
long q = buffer.readUntilZero(pos);
pos += q + 1;
long value = (q << shift) | buffer.readNumber(pos, shift);
pos += shift;
index += value;
if (size <= leafSize) {
int h = Builder.supplementalHash(hashCode, index);
switch(size) {
case 2:
h = h & 1;
break;
case 4:
h = h & 3;
break;
default:
h = Builder.reduce(h, size);
}
return add + h;
}
int firstPart = size / 2;
int h = Builder.supplementalHash(hashCode, index++);
h = h & 1;
if (h == 1) {
pos = skip(pos, firstPart);
add += firstPart;
size = size - firstPart;
} else {
size = firstPart;
}
}
}
}
================================================
FILE: src/main/java/org/minperf/hem/recsplit/FastGenerator.java
================================================
package org.minperf.hem.recsplit;
import java.util.Arrays;
import org.minperf.BitBuffer;
import org.minperf.monotoneList.MultiStageMonotoneList;
public class FastGenerator {
private static final int MAX_BUCKET_SIZE = 64;
private final int leafSize;
private final int averageBucketSize;
private BitBuffer buff;
private BitBuffer bucketBuff;
FastGenerator(int leafSize, int averageBucketSize) {
this.leafSize = leafSize;
this.averageBucketSize = averageBucketSize;
}
BitBuffer generate(long[] keys) {
return generate(keys, keys.length);
}
BitBuffer generate(long[] keys, int len) {
buff = new BitBuffer(len * 10);
if (len <= 1) {
return buff;
}
int bucketCount = Builder.getBucketCount(len, averageBucketSize);
bucketBuff = new BitBuffer(len * 10 / bucketCount);
int bucketBitCount = 31 - Integer.numberOfLeadingZeros(bucketCount);
int bucketShift = 64 - bucketBitCount;
int[] startList = new int[bucketCount];
int[] offsetList = new int[bucketCount + 1];
sortIntoBuckets(keys, len, bucketShift, bucketCount, offsetList, startList);
Arrays.fill(startList, 0);
// move to the right (this could be avoided)
System.arraycopy(offsetList, 0, offsetList, 1, bucketCount);
offsetList[0] = 0;
int startBucket = 0;
for (int i = 0; i < bucketCount; i++) {
int endBucket = offsetList[i + 1];
generateBucket(keys, startBucket, endBucket, startList, i);
startBucket = endBucket;
}
BitBuffer buff2 = new BitBuffer(len * 10);
buff2.writeEliasDelta(len + 1);
MultiStageMonotoneList.generate(startList, buff2);
MultiStageMonotoneList.generate(offsetList, buff2);
buff2.write(buff);
buff = buff2;
return buff;
}
private static void sortIntoBuckets(long[] keys, int len, int shift, int bucketCount, int[] offsetList, int[] array2) {
if (bucketCount == 1) {
offsetList[0] = keys.length;
// in this case, shift is 64, which is problematic
return;
}
boolean monotone = true;
int last = 0;
int[] pos = offsetList;
for (int i = 0; i < len; i++) {
long x = keys[i];
int b = (int) (x >>> shift);
pos[b]++;
if (b < last) {
monotone = false;
}
last = b;
}
int[] stop = array2;
int sum = 0;
int maxCount = 0;
for (int i = 0; i < bucketCount; i++) {
int count = pos[i];
maxCount = Math.max(maxCount, count);
pos[i] = sum;
sum += count;
stop[i] = sum;
}
if (maxCount > MAX_BUCKET_SIZE) {
throw new IllegalArgumentException("max=" + maxCount);
}
if (monotone) {
// shortcut if the list is already sorted
return;
}
int i = 0;
long x = keys[i];
for(int bucket = 0;;) {
int targetBucket = (int) (x >>> shift);
int index = pos[targetBucket]++;
long next = keys[index];
keys[index] = x;
x = next;
if (index == i) {
while (true) {
index = pos[bucket];
if (index < stop[bucket]) {
break;
}
bucket++;
if (bucket >= bucketCount) {
return;
}
}
i = index;
x = keys[index];
}
}
}
private void generateBucket(long[] keys, int start, int end, int[] startList, int bucketId) {
if (end == start) {
startList[bucketId] = buff.position();
return;
}
bucketBuff.clear();
bucketBuff.seek(0);
generateSet(keys, start, end, 0);
if (buff.position() > 0) {
int lastStart = startList[bucketId - 1];
for(int overlap = 8; overlap > 0; overlap--) {
if (buff.position() > overlap && bucketBuff.position() > overlap && buff.position() - lastStart >= overlap) {
long a = buff.readNumber(buff.position() - overlap, overlap);
long b = bucketBuff.readNumber(0, overlap);
if (a == b) {
buff.seek(buff.position() - overlap);
break;
}
}
}
}
startList[bucketId] = buff.position();
while (bucketId > 0) {
bucketId--;
if (startList[bucketId] > buff.position()) {
startList[bucketId] = buff.position();
} else {
break;
}
}
buff.write(bucketBuff);
}
private void generateSet(long[] keys, int start, int end, int index) {
int len = end - start;
if (len <= leafSize) {
switch (len) {
case 0:
case 1:
return;
case 2:
generateBucket2(keys, start, index);
return;
case 3:
generateBucket3(keys, start, index);
return;
case 4:
generateBucket4(keys, start, index);
return;
case 5:
generateBucket5(keys, start, index);
return;
case 6:
generateBucket6(keys, start, index);
return;
}
}
generateSetHalf(keys, start, end, index);
}
private void generateSetHalf(long[] keys, int start, int end, int index) {
int size = end - start;
int first = size / 2;
long bits;
int count;
int oldIndex = index;
for (;; index++) {
bits = 0;
count = 0;
for (int i = start; i < end; i++) {
long x = Builder.supplementalHash(keys[i], index) & 1;
bits |= x << (i - start);
count += x;
}
if (count == size - first) {
break;
}
if ((index & 0xffff) == 0xffff) {
checkDuplicateKey(keys, start, end);
}
}
sort(keys, start, end, bits);
emit(size, index - oldIndex);
generateSet(keys, start, start + size - count, index + 1);
generateSet(keys, start + size - count, start + size, index + 1);
}
private void checkDuplicateKey(long[] keys, int start, int end) {
Arrays.sort(keys, start, end);
for (int i = start + 1; i < end; i++) {
if (keys[i - 1] == keys[i]) {
throw new IllegalArgumentException("Duplicate key");
}
}
}
private static void sort(long[] keys, int start, int end, long bits) {
int len = end - start;
for (int l = 0, r = len - 1; l < r;) {
while (((bits >>> l) & 1) == 0) {
l++;
if (l >= r) {
return;
}
}
while (((bits >>> r) & 1) == 1) {
r--;
if (l >= r) {
return;
}
}
long temp = keys[start + l];
keys[start + l] = keys[start + r];
keys[start + r] = temp;
l++;
r--;
}
}
private void emit(int size, int indexDiff) {
int shift = Builder.getGolombRiceShift(size);
bucketBuff.writeGolombRice(shift, indexDiff);
}
private void generateBucket2(long[] keys, int start, int index) {
int oldIndex = index;
for (;; index++) {
int a = Builder.supplementalHash(keys[start], index) & 1;
int b = Builder.supplementalHash(keys[start + 1], index) & 1;
if (a != b) {
break;
}
}
emit(2, index - oldIndex);
}
private void generateBucket3(long[] keys, int start, int index) {
int oldIndex = index;
for (;; index++) {
int a = Builder.reduce(Builder.supplementalHash(keys[start], index), 3);
int b = Builder.reduce(Builder.supplementalHash(keys[start + 1], index), 3);
int c = Builder.reduce(Builder.supplementalHash(keys[start + 2], index), 3);
if (a != b && a != c && b != c) {
break;
}
}
emit(3, index - oldIndex);
}
private void generateBucket4(long[] keys, int start, int index) {
int oldIndex = index;
for (;; index++) {
int a = Builder.supplementalHash(keys[start], index) & 3;
int b = Builder.supplementalHash(keys[start + 1], index) & 3;
int c = Builder.supplementalHash(keys[start + 2], index) & 3;
int d = Builder.supplementalHash(keys[start + 3], index) & 3;
if (((1 << a) | (1 << b) | (1 << c) | (1 << d)) == 0xf) {
break;
}
}
emit(4, index - oldIndex);
}
private void generateBucket5(long[] keys, int start, int index) {
int oldIndex = index;
for (;; index++) {
int a = Builder.reduce(Builder.supplementalHash(keys[start], index), 5);
int b = Builder.reduce(Builder.supplementalHash(keys[start + 1], index), 5);
int c = Builder.reduce(Builder.supplementalHash(keys[start + 2], index), 5);
int d = Builder.reduce(Builder.supplementalHash(keys[start + 3], index), 5);
int e = Builder.reduce(Builder.supplementalHash(keys[start + 4], index), 5);
if (((1 << a) | (1 << b) | (1 << c) | (1 << d) | (1 << e)) == 0x1f) {
break;
}
}
emit(5, index - oldIndex);
}
private void generateBucket6(long[] keys, int start, int index) {
int oldIndex = index;
for (;; index++) {
int a = Builder.reduce(Builder.supplementalHash(keys[start], index), 6);
int b = Builder.reduce(Builder.supplementalHash(keys[start + 1], index), 6);
int c = Builder.reduce(Builder.supplementalHash(keys[start + 2], index), 6);
int d = Builder.reduce(Builder.supplementalHash(keys[start + 3], index), 6);
int e = Builder.reduce(Builder.supplementalHash(keys[start + 4], index), 6);
int f = Builder.reduce(Builder.supplementalHash(keys[start + 5], index), 6);
if (((1 << a) | (1 << b) | (1 << c) | (1 << d) | (1 << e) | (1 << f)) == 0x3f) {
break;
}
}
emit(6, index - oldIndex);
}
}
================================================
FILE: src/main/java/org/minperf/monotoneList/EliasFanoMonotoneList.java
================================================
package org.minperf.monotoneList;
import java.util.BitSet;
import org.minperf.BitBuffer;
import org.minperf.select.Select;
/**
* Each entry needs 2 + log(gap) bits, where gap is the average gap between
* entries, plus the overhead for the "select" structure. A lookup needs one
* "select" call, and is otherwise constant.
*/
public class EliasFanoMonotoneList extends MonotoneList {
private final BitBuffer buffer;
private final int start;
private final int lowBitCount;
private final Select select;
private EliasFanoMonotoneList(BitBuffer buffer, int start, int lowBitCount, Select select) {
this.buffer = buffer;
this.start = start;
this.lowBitCount = lowBitCount;
this.select = select;
}
public static EliasFanoMonotoneList generate(int[] data, BitBuffer buffer) {
int len = data.length;
// verify it is monotone
for (int i = 1; i < len; i++) {
if (data[i - 1] > data[i]) {
throw new IllegalArgumentException();
}
}
buffer.writeEliasDelta(len + 1);
int max = data[len - 1];
int lowBitCount = 32 - Integer.numberOfLeadingZeros(Integer.highestOneBit(max / len));
buffer.writeEliasDelta(lowBitCount + 1);
int start = buffer.position();
BitSet set = new BitSet();
for (int i = 0; i < len; i++) {
int x = i + (data[i] >>> lowBitCount);
set.set(x);
}
int mask = (1 << lowBitCount) - 1;
for (int i = 0; i < len; i++) {
buffer.writeNumber(data[i] & mask, lowBitCount);
}
Select select = Select.generate(set, buffer);
return new EliasFanoMonotoneList(buffer, start, lowBitCount, select);
}
public static int getSize(int[] data) {
int len = data.length;
int result = BitBuffer.getEliasDeltaSize(len + 1);
int max = data[len - 1];
int lowBitCount = 32 - Integer.numberOfLeadingZeros(Integer.highestOneBit(max / len));
result += BitBuffer.getEliasDeltaSize(lowBitCount + 1);
BitSet set = new BitSet();
for (int i = 0; i < len; i++) {
int x = i + (data[i] >>> lowBitCount);
set.set(x);
}
result += lowBitCount * len;
result += Select.getSize(set);
return result;
}
public static EliasFanoMonotoneList load(BitBuffer buffer) {
int len = (int) (buffer.readEliasDelta() - 1);
int lowBitCount = (int) (buffer.readEliasDelta() - 1);
int start = buffer.position();
buffer.seek(start + len * lowBitCount);
Select select = Select.load(buffer);
return new EliasFanoMonotoneList(buffer, start, lowBitCount, select);
}
@Override
public int get(int i) {
int low = (int) buffer.readNumber(start + i * lowBitCount, lowBitCount);
int high = (int) select.select(i) - i;
return (high << lowBitCount) + low;
}
@Override
public long getPair(int i) {
long lowPair = buffer.readNumber(start + i * lowBitCount, lowBitCount + lowBitCount);
int low1 = (int) (lowPair >>> lowBitCount);
int low2 = (int) (lowPair - ((long) low1 << lowBitCount));
long highPair = select.selectPair(i);
int high1 = (int) (highPair >>> 32) - i;
int high2 = (int) highPair - i - 1;
int result1 = (high1 << lowBitCount) + low1;
int result2 = (high2 << lowBitCount) + low2;
return ((long) result1 << 32) | result2;
}
}
================================================
FILE: src/main/java/org/minperf/monotoneList/MonotoneList.java
================================================
package org.minperf.monotoneList;
import org.minperf.BitBuffer;
/**
* A list of monotone increasing values.
*/
public abstract class MonotoneList {
public abstract int get(int i);
public abstract long getPair(int i);
public static MonotoneList generate(int[] data, BitBuffer buffer, boolean eliasFano) {
return eliasFano ?
EliasFanoMonotoneList.generate(data, buffer) :
MultiStageMonotoneList.generate(data, buffer);
}
/**
* Get the number of bits needed.
*
* @param data the data
* @param eliasFano whether the Elias-Fano datastructure should be used
* @return the number of bits
*/
public static int getSize(int[] data, boolean eliasFano) {
return eliasFano ?
EliasFanoMonotoneList.getSize(data) :
MultiStageMonotoneList.getSize(data);
}
public static MonotoneList load(BitBuffer buffer, boolean eliasFano) {
return eliasFano ?
EliasFanoMonotoneList.load(buffer) :
MultiStageMonotoneList.load(buffer);
}
}
================================================
FILE: src/main/java/org/minperf/monotoneList/MultiStageMonotoneList.java
================================================
package org.minperf.monotoneList;
import org.minperf.BitBuffer;
/**
* This implementation uses a linear regression, and 3 levels of offsets. It is
* much simpler and typically faster than an EliasFanoMonotoneList, but space
* usage is not linear.
*/
public class MultiStageMonotoneList extends MonotoneList {
public static final int SHIFT1 = 6;
public static final int SHIFT2 = 3;
public static final int FACTOR1 = 32;
public static final int FACTOR2 = 16;
private final BitBuffer buffer;
private final int startLevel1, startLevel2, startLevel3;
private final int bitCount1, bitCount2, bitCount3;
private final int count1, count2, count3;
private final long factor;
private final int add;
private MultiStageMonotoneList(BitBuffer buffer) {
this.buffer = buffer;
this.count3 = (int) buffer.readEliasDelta() - 1;
int diff = (int) buffer.readEliasDelta() - 1;
this.factor = getScaleFactor(diff, count3);
this.add = (int) BitBuffer.unfoldSigned(buffer.readEliasDelta() - 1);
this.bitCount1 = (int) buffer.readEliasDelta() - 1;
this.bitCount2 = (int) buffer.readEliasDelta() - 1;
this.bitCount3 = (int) buffer.readEliasDelta() - 1;
startLevel1 = buffer.position();
count2 = (count3 + (1 << SHIFT2) - 1) >> SHIFT2;
count1 = (count3 + (1 << SHIFT1) - 1) >> SHIFT1;
startLevel2 = startLevel1 + count1 * bitCount1;
startLevel3 = startLevel2 + count2 * bitCount2;
buffer.seek(startLevel3 + bitCount3 * count3);
}
private static long getScaleFactor(int multiply, int divide) {
return divide == 0 ? 0 : ((long) multiply << 32) / divide + 1;
}
public static MultiStageMonotoneList generate(int[] data, BitBuffer buffer) {
int start = buffer.position();
int count3 = data.length;
// verify it is monotone
for (int i = 1; i < count3; i++) {
if (data[i - 1] > data[i]) {
throw new IllegalArgumentException();
}
}
int diff = data[count3 - 1] - data[0];
long factor = getScaleFactor(diff, count3);
int add = data[0];
for (int i = 1; i < count3; i++) {
int expected = (int) ((i * factor) >>> 32);
int x = data[i];
add = Math.min(add, x - expected);
}
buffer.writeEliasDelta(count3 + 1);
buffer.writeEliasDelta(diff + 1);
buffer.writeEliasDelta(BitBuffer.foldSigned(add) + 1);
int count2 = (count3 + (1 << SHIFT2) - 1) >> SHIFT2;
int count1 = (count3 + (1 << SHIFT1) - 1) >> SHIFT1;
int[] group1 = new int[count1];
int[] group2 = new int[count2];
int[] group3 = new int[count3];
for (int i = 0; i < count3; i++) {
// int expected = (int) (i * max / count3);
int expected = (int) ((i * factor) >>> 32) + add;
int got = data[i];
int x = got - expected;
if (x < 0) {
throw new AssertionError();
}
group3[i] = x;
}
int a = Integer.MAX_VALUE;
for (int i = 0; i < count3; i++) {
int x = group3[i];
a = Math.min(a, x);
if ((i +1) >> SHIFT2 != i >> SHIFT2 || i == count3 - 1) {
group2[i >> SHIFT2] = a / FACTOR2;
a = Integer.MAX_VALUE;
}
}
a = Integer.MAX_VALUE;
for (int i = 0; i < count3; i++) {
int d = group2[i >> SHIFT2] * FACTOR2;
int x = group3[i];
group3[i] -= d;
if (group3[i] < 0) {
throw new AssertionError();
}
a = Math.min(a, x);
if ((i + 1) >> SHIFT1 != i >> SHIFT1 || i == count3 - 1) {
group1[i >> SHIFT1] = a / FACTOR1;
a = Integer.MAX_VALUE;
}
}
int last = -1;
for (int i = 0; i < count3; i++) {
int i2 = i >> SHIFT2;
if (i2 == last) {
continue;
}
int d = group1[i >> SHIFT1] * FACTOR1;
group2[i2] -= d / FACTOR2;
last = i2;
}
int max1 = 0, max2 = 0, max3 = 0;
for (int i = 0; i < group3.length; i++) {
max3 = Math.max(max3, group3[i]);
}
for (int i = 0; i < group2.length; i++) {
max2 = Math.max(max2, group2[i]);
}
for (int i = 0; i < group1.length; i++) {
max1 = Math.max(max1, group1[i]);
}
int bitCount1 = 32 - Integer.numberOfLeadingZeros(max1);
int bitCount2 = 32 - Integer.numberOfLeadingZeros(max2);
int bitCount3 = 32 - Integer.numberOfLeadingZeros(max3);
buffer.writeEliasDelta(bitCount1 + 1);
buffer.writeEliasDelta(bitCount2 + 1);
buffer.writeEliasDelta(bitCount3 + 1);
for (int x : group1) {
buffer.writeNumber(x, bitCount1);
}
for (int x : group2) {
buffer.writeNumber(x, bitCount2);
}
for (int x : group3) {
buffer.writeNumber(x, bitCount3);
}
buffer.seek(start);
return new MultiStageMonotoneList(buffer);
}
public static int getSize(int[] data) {
int result = 0;
int count3 = data.length;
// verify it is monotone
for (int i = 1; i < count3; i++) {
if (data[i - 1] > data[i]) {
throw new IllegalArgumentException();
}
}
int diff = data[count3 - 1] - data[0];
long factor = getScaleFactor(diff, count3);
int add = data[0];
for (int i = 1; i < count3; i++) {
int expected = (int) ((i * factor) >>> 32);
int x = data[i];
add = Math.min(add, x - expected);
}
result += BitBuffer.getEliasDeltaSize(count3 + 1);
result += BitBuffer.getEliasDeltaSize(diff + 1);
result += BitBuffer.getEliasDeltaSize(BitBuffer.foldSigned(add) + 1);
int count2 = (count3 + (1 << SHIFT2) - 1) >> SHIFT2;
int count1 = (count3 + (1 << SHIFT1) - 1) >> SHIFT1;
int[] group1 = new int[count1];
int[] group2 = new int[count2];
int[] group3 = new int[count3];
for (int i = 0; i < count3; i++) {
// int expected = (int) (i * max / count3);
int expected = (int) ((i * factor) >>> 32) + add;
int got = data[i];
int x = got - expected;
if (x < 0) {
throw new AssertionError();
}
group3[i] = x;
}
int a = Integer.MAX_VALUE;
for (int i = 0; i < count3; i++) {
int x = group3[i];
a = Math.min(a, x);
if ((i +1) >> SHIFT2 != i >> SHIFT2 || i == count3 - 1) {
group2[i >> SHIFT2] = a / FACTOR2;
a = Integer.MAX_VALUE;
}
}
a = Integer.MAX_VALUE;
for (int i = 0; i < count3; i++) {
int d = group2[i >> SHIFT2] * FACTOR2;
int x = group3[i];
group3[i] -= d;
if (group3[i] < 0) {
throw new AssertionError();
}
a = Math.min(a, x);
if ((i + 1) >> SHIFT1 != i >> SHIFT1 || i == count3 - 1) {
group1[i >> SHIFT1] = a / FACTOR1;
a = Integer.MAX_VALUE;
}
}
int last = -1;
for (int i = 0; i < count3; i++) {
int i2 = i >> SHIFT2;
if (i2 == last) {
continue;
}
int d = group1[i >> SHIFT1] * FACTOR1;
group2[i2] -= d / FACTOR2;
last = i2;
}
int max1 = 0, max2 = 0, max3 = 0;
for (int i = 0; i < group3.length; i++) {
max3 = Math.max(max3, group3[i]);
}
for (int i = 0; i < group2.length; i++) {
max2 = Math.max(max2, group2[i]);
}
for (int i = 0; i < group1.length; i++) {
max1 = Math.max(max1, group1[i]);
}
int bitCount1 = 32 - Integer.numberOfLeadingZeros(max1);
int bitCount2 = 32 - Integer.numberOfLeadingZeros(max2);
int bitCount3 = 32 - Integer.numberOfLeadingZeros(max3);
result += BitBuffer.getEliasDeltaSize(bitCount1 + 1);
result += BitBuffer.getEliasDeltaSize(bitCount2 + 1);
result += BitBuffer.getEliasDeltaSize(bitCount3 + 1);
result += bitCount1 * group1.length;
result += bitCount2 * group2.length;
result += bitCount3 * group3.length;
return result;
}
public static MultiStageMonotoneList load(BitBuffer buffer) {
return new MultiStageMonotoneList(buffer);
}
@Override
public int get(int i) {
int expected = (int) ((i * factor) >>> 32) + add;
long a = buffer.readNumber(startLevel1 + (i >>> SHIFT1) * bitCount1, bitCount1);
long b = buffer.readNumber(startLevel2 + (i >>> SHIFT2) * bitCount2, bitCount2);
long c = buffer.readNumber(startLevel3 + i * bitCount3, bitCount3);
return (int) (expected + a * FACTOR1 + b * FACTOR2 + c);
}
@Override
public long getPair(int i) {
return ((long) get(i) << 32) | (get(i + 1));
}
}
================================================
FILE: src/main/java/org/minperf/rank/Rank9.java
================================================
/*
* Sux4J: Succinct data structures for Java
*
* Copyright (C) 2008-2016 Sebastiano Vigna
*
* 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 3 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see .
*/
package org.minperf.rank;
import java.util.Arrays;
import java.util.BitSet;
/**
* A fast rank implementation that uses 25% additional space. This is a copy of
* the (very good) implementation in Sux4J it.unimi.dsi.sux4j.bits.Rank9 by
* Sebastiano Vigna (see copyright), with a custom serialization format.
*/
public class Rank9 {
private final long[] bits;
private final long[] counts;
long mostSignificantBit(long x) {
return 63 - Long.numberOfLeadingZeros(x);
}
public Rank9(BitSet set, long bitCount) {
long[] bits = set.toLongArray();
// One zero entry is needed at the end
bits = Arrays.copyOf(bits, 1 + (int) ((bitCount + 63) / 64));
this.bits = bits;
long length = bits.length * 64;
int numWords = (int) ((length + 63) / 64);
final int numCounts = (int) ((length + 8 * 64 - 1) / (8 * 64)) * 2;
counts = new long[numCounts + 1];
long c = 0;
int pos = 0;
for (int i = 0; i < numWords; i += 8, pos += 2) {
counts[pos] = c;
c += Long.bitCount(bits[i]);
for (int j = 1; j < 8; j++) {
counts[pos + 1] |= (i + j <= numWords ? c - counts[pos] : 0x1ffL) << 9 * (j - 1);
if (i + j < numWords) {
c += Long.bitCount(bits[i + j]);
}
}
}
counts[numCounts] = c;
}
/**
* Get the number of bits set before this position.
*
* @param pos the position
* @return the number of ones
*/
public long rank(long pos) {
int word = (int) (pos >>> 6);
int block = (word >> 2) & ~1;
int offset = (word & 7) - 1;
return counts[block] +
(counts[block + 1] >>> (offset + (offset >>> 32 - 4 & 8)) * 9 & 0x1ff) +
Long.bitCount(bits[word] & ((1L << pos) - 1));
}
/**
* Get the bit at this position
*
* @param pos the position
* @return 0 or 1
*/
public long get(long pos) {
return (bits[(int) (pos >>> 6)] >>> pos) & 1;
}
/**
* Get the number of bits set before this position, and the bit itself.
*
* @param pos the position
* @return the number of ones multiplied by 2, plus the bit (0 or 1)
*/
public long rankAndGet(long pos) {
int word = (int) (pos >>> 6);
int block = (word >> 2) & ~1;
int offset = (word & 7) - 1;
long x = bits[word];
return ((counts[block] +
(counts[block + 1] >>> (offset + (offset >>> 32 - 4 & 8)) * 9 & 0x1ff) +
Long.bitCount(x & ((1L << pos) - 1))) << 1) +
((x >>> pos) & 1);
}
/**
* Get the bit itself, and a part of the rank (use remainingRank to get the
* rest).
*
* @param pos the position
* @return the number of ones multiplied by 2, plus the bit (0 or 1)
*/
public long getAndPartialRank(long pos) {
int word = (int) (pos >>> 6);
long x = bits[word];
return ((Long.bitCount(x & ((1L << pos) - 1))) << 1) + ((x >>> pos) & 1);
}
/**
* Get the second part of the rank (see getAndPartialRank).
*
* @param pos the position
* @return the number of ones
*/
public long remainingRank(long pos) {
int word = (int) (pos >>> 6);
int block = (word >> 2) & ~1;
int offset = (word & 7) - 1;
return counts[block] + (counts[block + 1] >>> (offset + (offset >>> 32 - 4 & 8)) * 9 & 0x1ff);
}
public int getBitCount() {
return bits.length * 64 + counts.length * 64;
}
}
================================================
FILE: src/main/java/org/minperf/rank/VerySimpleRank.java
================================================
package org.minperf.rank;
import java.util.BitSet;
import org.minperf.BitBuffer;
/**
* A simple rank+select data structure implementation for a list of bits.
*
* Rank(x) gets the number of bits set to 1, before position x (positions
* starting at 0). It takes constant time in the RAM model, that means, reads a
* constant number of log(n) numbers.
*
* Select(x) gets the position of the xth 1 bit (positions starting at 0). It
* takes logarithmic time (using binary search on rank).
*/
public class VerySimpleRank {
private final BitBuffer buffer;
private final int size;
private final int superBlockPos;
private final int superBlockBits;
private final int superBlockShift;
private final int superBlockCount;
private final int superBlockEntrySize;
private final int blockPos;
private final int blockBits;
private final int blockShift;
private final int blockCount;
private final int blockEntrySize;
private final int dataPos;
private VerySimpleRank(BitBuffer buffer, int size) {
this.buffer = buffer;
this.size = size;
superBlockPos = buffer.position();
int bb = Math.max(1, 31 - Integer.numberOfLeadingZeros(size));
int sbb = bb * bb;
blockShift = 32 - Integer.numberOfLeadingZeros(bb - 1);
blockBits = 1 << blockShift;
superBlockShift = 32 - Integer.numberOfLeadingZeros(sbb - 1);
superBlockBits = 1 << superBlockShift;
blockCount = (size + blockBits - 1) / blockBits;
superBlockCount = (size + superBlockBits - 1) / superBlockBits;
superBlockEntrySize = 32 - Integer.numberOfLeadingZeros(size - 1);
blockEntrySize = 32 - Integer.numberOfLeadingZeros(superBlockBits);
blockPos = superBlockPos + superBlockEntrySize * superBlockCount;
dataPos = blockPos + blockEntrySize * blockCount;
}
/**
* Generate a rank/select object, and store it into the provided buffer.
*
* @param set the bit set
* @param buffer the buffer
* @return the generated object
*/
public static VerySimpleRank generate(BitSet set, BitBuffer buffer) {
int size = set.length() + 1;
buffer.writeEliasDelta(size + 1);
VerySimpleRank rank = new VerySimpleRank(buffer, size);
int[] superBlocks = new int[rank.superBlockCount];
int count = 0;
long last = 0;
int maxSuperBlock = (1 << rank.superBlockEntrySize) - 1;
for (long i = 0; i < rank.superBlockCount; i++) {
buffer.writeNumber(count, rank.superBlockEntrySize);
superBlocks[(int) i] = count;
if (count > maxSuperBlock) {
throw new AssertionError();
}
long next = last + rank.superBlockBits;
count += countBits(set, (int) last, (int) next);
last = next;
}
if (buffer.position() != rank.blockPos) {
throw new AssertionError();
}
count = 0;
last = 0;
int maxBlock = (1 << rank.blockEntrySize) - 1;
for (long i = 0; i < rank.blockCount; i++) {
int s = (int) (last / rank.superBlockBits);
int countRelative = count - superBlocks[s];
if (countRelative > maxBlock) {
throw new AssertionError();
}
buffer.writeNumber(countRelative, rank.blockEntrySize);
long next = last + rank.blockBits;
count += countBits(set, (int) last, (int) next);
last = next;
}
if (buffer.position() != rank.dataPos) {
throw new AssertionError();
}
for (int i = 0; i < size; i++) {
buffer.writeBit(set.get(i) ? 1 : 0);
}
return rank;
}
/**
* Generate a rank/select object from the provided buffer.
*
* @param buffer the buffer
* @return the loaded object
*/
public static VerySimpleRank load(BitBuffer buffer) {
int size = (int) (buffer.readEliasDelta() - 1);
VerySimpleRank result = new VerySimpleRank(buffer, size);
buffer.seek(result.dataPos + size);
return result;
}
/**
* Get the bit at position x.
*
* @param x the position
* @return true if the bit is set
*/
public boolean get(long x) {
if (x >= size) {
// read past the end
return false;
}
return buffer.readNumber(dataPos + (int) x, 1) == 1L;
}
/**
* Get the number of 1 bits up to the given position.
*
* @param x the position
* @return the number of 1 bits
*/
public long rank(long x) {
x = Math.min(x, size - 1);
int s = (int) (x >>> superBlockShift);
int b = (int) (x >>> blockShift);
return (int) buffer.readNumber(superBlockPos +
s * superBlockEntrySize, superBlockEntrySize) +
(int) buffer.readNumber(blockPos +
b * blockEntrySize, blockEntrySize) +
countBits(b << blockShift, (int) x);
}
private int countBits(int start, int end) {
long x = buffer.readNumber(dataPos + start, end - start);
return Long.bitCount(x);
}
/**
* Get the position of the xth 1 bit.
*
* @param x the value (starting with 0)
* @return the position, or -1 if x is too large
*/
public long select(long x) {
int min = 0, max = size + 1;
while (min < max) {
int n = (min + max) >>> 1;
long k = rank(n);
if (k > x) {
max = n;
} else {
min = n + 1;
}
}
return min >= size ? -1 : min - 1;
}
private static int countBits(BitSet set, int start, int end) {
int count = 0;
for (int i = start; i < end; i++) {
count += set.get(i) ? 1 : 0;
}
return count;
}
public int getReadBits() {
return superBlockEntrySize + blockEntrySize + blockBits;
}
public int getOverhead() {
return dataPos - superBlockPos - size;
}
public int getSize() {
return size;
}
@Override
public String toString() {
return getClass().getSimpleName() + " size " + size;
}
}
================================================
FILE: src/main/java/org/minperf/select/Select.java
================================================
package org.minperf.select;
import java.util.BitSet;
import org.minperf.BitBuffer;
/**
* A select data structure for a list of bits.
*
* Select(x) gets the position of the xth 1 bit (positions starting at 0).
*/
public abstract class Select {
public static final boolean SIMPLE_SELECT = true;
/**
* Generate a select object, and store it into the provided buffer.
*
* @param set the bit set
* @param buffer the buffer
* @return the generated object
*/
public static Select generate(BitSet set, BitBuffer buffer) {
if (SIMPLE_SELECT) {
return SimpleSelect.generate(set, buffer);
}
return VerySimpleSelect.generate(set, buffer);
}
/**
* Get the number of bits needed.
*
* @param set the bit set
* @return the number of bits
*/
public static int getSize(BitSet set) {
if (SIMPLE_SELECT) {
return SimpleSelect.getSize(set);
}
return VerySimpleSelect.getSize(set);
}
/**
* Generate a rank/select object from the provided buffer.
*
* @param buffer the buffer
* @return the loaded object
*/
public static Select load(BitBuffer buffer) {
if (SIMPLE_SELECT) {
return SimpleSelect.load(buffer);
}
return VerySimpleSelect.load(buffer);
}
/**
* Get the position of the xth 1 bit.
*
* @param x the value (starting with 0)
* @return the position (0 is the first bit), or -1 if x is too large
*/
public abstract long select(long x);
public abstract long selectPair(long x);
}
================================================
FILE: src/main/java/org/minperf/select/SimpleSelect.java
================================================
/*
* Sux4J: Succinct data structures for Java
*
* Copyright (C) 2008-2016 Sebastiano Vigna
*
* 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 3 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see .
*/
package org.minperf.select;
import java.util.BitSet;
import org.minperf.BitBuffer;
/**
* A select implementation with guaranteed O(1) query time. This is a copy of
* the (very good) implementation in Sux4J it.unimi.dsi.sux4j.bits.SimpleSelect
* by Sebastiano Vigna (see copyright), with a custom serialization format.
*/
public class SimpleSelect extends Select {
private static final long ONES_STEP_4 = 0x1111111111111111L;
private static final long ONES_STEP_8 = 0x0101010101010101L;
private static final long MSBS_STEP_8 = 0x80L * ONES_STEP_8;
private static final byte[] SELECT_IN_BYTE = {
-1, 0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1,
0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,
0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1,
0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1,
0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1,
0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1,
0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,
0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1,
0, 2, 0, 1, 0, -1, -1, -1, 1, -1, 2, 2, 1, -1, 3, 3, 1, 3, 2, 2, 1,
-1, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1, -1, 5, 5, 1, 5, 2,
2, 1, 5, 3, 3, 1, 3, 2, 2, 1, 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1,
3, 2, 2, 1, -1, 6, 6, 1, 6, 2, 2, 1, 6, 3, 3, 1, 3, 2, 2, 1, 6, 4,
4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1, 6, 5, 5, 1, 5, 2, 2, 1,
5, 3, 3, 1, 3, 2, 2, 1, 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2,
2, 1, -1, 7, 7, 1, 7, 2, 2, 1, 7, 3, 3, 1, 3, 2, 2, 1, 7, 4, 4, 1,
4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1, 7, 5, 5, 1, 5, 2, 2, 1, 5, 3,
3, 1, 3, 2, 2, 1, 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
7, 6, 6, 1, 6, 2, 2, 1, 6, 3, 3, 1, 3, 2, 2, 1, 6, 4, 4, 1, 4, 2,
2, 1, 4, 3, 3, 1, 3, 2, 2, 1, 6, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1,
3, 2, 2, 1, 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1, -1, -1,
-1, -1, -1, -1, -1, 2, -1, -1, -1, 3, -1, 3, 3, 2, -1, -1, -1, 4,
-1, 4, 4, 2, -1, 4, 4, 3, 4, 3, 3, 2, -1, -1, -1, 5, -1, 5, 5, 2,
-1, 5, 5, 3, 5, 3, 3, 2, -1, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3,
3, 2, -1, -1, -1, 6, -1, 6, 6, 2, -1, 6, 6, 3, 6, 3, 3, 2, -1, 6,
6, 4, 6, 4, 4, 2, 6, 4, 4, 3, 4, 3, 3, 2, -1, 6, 6, 5, 6, 5, 5, 2,
6, 5, 5, 3, 5, 3, 3, 2, 6, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3,
3, 2, -1, -1, -1, 7, -1, 7, 7, 2, -1, 7, 7, 3, 7, 3, 3, 2, -1, 7,
7, 4, 7, 4, 4, 2, 7, 4, 4, 3, 4, 3, 3, 2, -1, 7, 7, 5, 7, 5, 5, 2,
7, 5, 5, 3, 5, 3, 3, 2, 7, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3,
3, 2, -1, 7, 7, 6, 7, 6, 6, 2, 7, 6, 6, 3, 6, 3, 3, 2, 7, 6, 6, 4,
6, 4, 4, 2, 6, 4, 4, 3, 4, 3, 3, 2, 7, 6, 6, 5, 6, 5, 5, 2, 6, 5,
5, 3, 5, 3, 3, 2, 6, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1,
-1, -1, -1, -1, -1, -1, 4, -1, -1, -1, 4, -1, 4, 4, 3, -1, -1, -1,
-1, -1, -1, -1, 5, -1, -1, -1, 5, -1, 5, 5, 3, -1, -1, -1, 5, -1,
5, 5, 4, -1, 5, 5, 4, 5, 4, 4, 3, -1, -1, -1, -1, -1, -1, -1, 6,
-1, -1, -1, 6, -1, 6, 6, 3, -1, -1, -1, 6, -1, 6, 6, 4, -1, 6, 6,
4, 6, 4, 4, 3, -1, -1, -1, 6, -1, 6, 6, 5, -1, 6, 6, 5, 6, 5, 5, 3,
-1, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, -1, -1, -1, -1,
-1, -1, -1, 7, -1, -1, -1, 7, -1, 7, 7, 3, -1, -1, -1, 7, -1, 7, 7,
4, -1, 7, 7, 4, 7, 4, 4, 3, -1, -1, -1, 7, -1, 7, 7, 5, -1, 7, 7,
5, 7, 5, 5, 3, -1, 7, 7, 5, 7, 5, 5, 4, 7, 5, 5, 4, 5, 4, 4, 3, -1,
-1, -1, 7, -1, 7, 7, 6, -1, 7, 7, 6, 7, 6, 6, 3, -1, 7, 7, 6, 7, 6,
6, 4, 7, 6, 6, 4, 6, 4, 4, 3, -1, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5,
6, 5, 5, 3, 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, -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, 4, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1,
-1, -1, 5, -1, -1, -1, 5, -1, 5, 5, 4, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, 6,
-1, -1, -1, 6, -1, 6, 6, 4, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1,
-1, 6, -1, 6, 6, 5, -1, -1, -1, 6, -1, 6, 6, 5, -1, 6, 6, 5, 6, 5,
5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
7, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 7, -1, 7, 7, 4, -1,
-1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 7, -1, 7, 7, 5, -1, -1, -1,
7, -1, 7, 7, 5, -1, 7, 7, 5, 7, 5, 5, 4, -1, -1, -1, -1, -1, -1,
-1, 7, -1, -1, -1, 7, -1, 7, 7, 6, -1, -1, -1, 7, -1, 7, 7, 6, -1,
7, 7, 6, 7, 6, 6, 4, -1, -1, -1, 7, -1, 7, 7, 6, -1, 7, 7, 6, 7, 6,
6, 5, -1, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -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, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1,
-1, 6, -1, 6, 6, 5, -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, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 7, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 7, -1, 7, 7, 5,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1,
-1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 7, -1, 7, 7, 6, -1, -1, -1,
-1, -1, -1, -1, 7, -1, -1, -1, 7, -1, 7, 7, 6, -1, -1, -1, 7, -1,
7, 7, 6, -1, 7, 7, 6, 7, 6, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -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,
6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -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, 7, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1,
-1, 7, -1, -1, -1, 7, -1, 7, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 7
};
private static final boolean ASSERTS = true;
private static final int MAX_ONES_PER_INVENTORY = 8192;
private static final int MAX_LOG2_LONGWORDS_PER_SUBINVENTORY = 3;
/**
* The maximum size of span to qualify for a subinventory made of 16-bit
* offsets.
*/
private static final int MAX_SPAN = 1 << 16;
// The number of ones
private final long numOnes;
// The number of words
private final int numWords;
// The cached result of the bits
private transient long[] bits;
/**
* The first-level inventory containing information about one bit each
* {@link #onesPerInventory}. If the entry is nonnegative, it is the rank of
* the bit and subsequent information is recorded in {@link #subinventory16}
* as offsets of one bit each {@link #onesPerSub16} (then, sequential search
* is necessary). Otherwise, a negative value means that offsets are too
* large and they have been recorded as 64-bit values. If
* {@link #onesPerSub64} is 1, then offsets are directly stored into
* {@link #subinventory}. Otherwise, the first {@link #subinventory} entry
* is actually a pointer to {@link #exactSpill}, where the offsets can be
* found.
*/
private final long[] inventory;
/** The logarithm of the number of ones per {@link #inventory} entry. */
private final int log2OnesPerInventory;
/** The number of ones per {@link #inventory} entry. */
private final int onesPerInventory;
/** The mask associated to the number of ones per {@link #inventory} entry. */
private final int onesPerInventoryMask;
/**
* The second-level inventory (records the offset of each bit w.r.t. the
* first-level inventory).
*/
private final long[] subinventory;
/**
* The logarithm of the number of longwords used in the part of the
* subinventory associated to an inventory entry.
*/
private final int log2LongwordsPerSubinventory;
/**
* The logarithm of the number of ones for each {@link #subinventory}
* longword.
*/
private final int log2OnesPerSub64;
/** The number of ones for each {@link #subinventory} longword. */
private final int onesPerSub64;
/**
* The logarithm of the number of ones for each {@link #subinventory} short.
*/
private final int log2OnesPerSub16;
/** The number of ones for each {@link #subinventory} short. */
private final int onesPerSub16;
/**
* The mask associated to number of ones for each {@link #subinventory}
* short.
*/
private final int onesPerSub16Mask;
/** The list of exact spills. */
private final long[] exactSpill;
private SimpleSelect(BitBuffer buffer) {
numOnes = buffer.readEliasDelta() - 1;
numWords = (int) buffer.readEliasDelta() - 1;
bits = new long[numWords];
for (int i = 0; i < bits.length; i++) {
bits[i] = buffer.readLong();
}
inventory = new long[(int) buffer.readEliasDelta() - 1];
for (int i = 0; i < inventory.length; i++) {
inventory[i] = buffer.readLong();
}
log2OnesPerInventory = (int) buffer.readEliasDelta() - 1;
onesPerInventory = 1 << log2OnesPerInventory;
onesPerInventoryMask = onesPerInventory - 1;
subinventory = new long[(int) buffer.readEliasDelta() - 1];
for (int i = 0; i < subinventory.length; i++) {
subinventory[i] = buffer.readLong();
}
log2LongwordsPerSubinventory = Math.min(
MAX_LOG2_LONGWORDS_PER_SUBINVENTORY,
Math.max(0, log2OnesPerInventory - 2));
log2OnesPerSub64 = Math.max(0, log2OnesPerInventory -
log2LongwordsPerSubinventory);
onesPerSub64 = 1 << log2OnesPerSub64;
log2OnesPerSub16 = Math.max(0, log2OnesPerSub64 - 2);
onesPerSub16 = 1 << log2OnesPerSub16;
onesPerSub16Mask = onesPerSub16 - 1;
exactSpill = new long[(int) buffer.readEliasDelta() - 1];
for (int i = 0; i < exactSpill.length; i++) {
exactSpill[i] = buffer.readLong();
}
}
private SimpleSelect(BitSet bitSet) {
long length = bitSet.length();
numWords = (int) ((length + 63) / 64);
this.bits = new long[numWords];
for (int i = 0; i < length; i++) {
bits[i / 64] |= bitSet.get(i) ? (1L << (i % 64)) : 0;
}
// We compute quickly the number of ones (possibly counting spurious
// bits in the last word).
long d = 0;
for (int i = numWords; i-- != 0;) {
d += Long.bitCount(bits[i]);
}
int x = length == 0 ? 1
: (int) ((d * MAX_ONES_PER_INVENTORY + length - 1) / length);
int mostSignificantBit = 63 - Long.numberOfLeadingZeros(x);
log2OnesPerInventory = mostSignificantBit;
onesPerInventory = 1 << log2OnesPerInventory;
onesPerInventoryMask = onesPerInventory - 1;
int inventorySize = (int) ((d + onesPerInventory - 1) / onesPerInventory);
inventory = new long[inventorySize + 1];
// First phase: we build an inventory for each one out of
// onesPerInventory.
d = 0;
for (int i = 0; i < numWords; i++) {
for (int j = 0; j < 64; j++) {
if (i * 64L + j >= length) {
break;
}
if ((bits[i] & 1L << j) != 0) {
if ((d & onesPerInventoryMask) == 0) {
inventory[(int) (d >>> log2OnesPerInventory)] = i *
64L + j;
}
d++;
}
}
}
numOnes = d;
inventory[inventorySize] = length;
log2LongwordsPerSubinventory = Math.min(
MAX_LOG2_LONGWORDS_PER_SUBINVENTORY,
Math.max(0, log2OnesPerInventory - 2));
log2OnesPerSub64 = Math.max(0, log2OnesPerInventory -
log2LongwordsPerSubinventory);
log2OnesPerSub16 = Math.max(0, log2OnesPerSub64 - 2);
onesPerSub64 = 1 << log2OnesPerSub64;
onesPerSub16 = 1 << log2OnesPerSub16;
onesPerSub16Mask = onesPerSub16 - 1;
if (onesPerInventory <= 1) {
subinventory = exactSpill = new long[0];
return;
}
d = 0;
int ones;
long diff16 = 0, start = 0, span = 0;
int spilled = 0, inventoryIndex = 0;
for (int i = 0; i < numWords; i++) {
// We estimate the subinventory and exact spill size
for (int j = 0; j < 64; j++) {
if (i * 64L + j >= length) {
break;
}
if ((bits[i] & 1L << j) != 0) {
if ((d & onesPerInventoryMask) == 0) {
inventoryIndex = (int) (d >>> log2OnesPerInventory);
start = inventory[inventoryIndex];
span = inventory[inventoryIndex + 1] - start;
ones = (int) Math
.min(numOnes - d, onesPerInventory);
// We must always count (possibly unused) diff16's.
// And we cannot store less then 4 diff16.
diff16 += Math.max(4,
(ones + onesPerSub16 - 1) >>> log2OnesPerSub16);
if (span >= MAX_SPAN && onesPerSub64 > 1) {
spilled += ones;
}
}
d++;
}
}
}
int subinventorySize = (int) ((diff16 + 3) / 4);
int exactSpillSize = spilled;
subinventory = new long[subinventorySize];
exactSpill = new long[exactSpillSize];
int offset = 0;
spilled = 0;
d = 0;
for (int i = 0; i < numWords; i++) {
for (int j = 0; j < 64; j++) {
if (i * 64L + j >= length) {
break;
}
if ((bits[i] & 1L << j) != 0) {
if ((d & onesPerInventoryMask) == 0) {
inventoryIndex = (int) (d >>> log2OnesPerInventory);
start = inventory[inventoryIndex];
span = inventory[inventoryIndex + 1] - start;
offset = 0;
}
if (span < MAX_SPAN) {
if (ASSERTS) {
assert i * 64L + j - start <= MAX_SPAN;
}
if ((d & onesPerSub16Mask) == 0) {
setSubInventory16((inventoryIndex << log2LongwordsPerSubinventory + 2) +
offset++, (int) (i * 64L + j - start));
}
} else {
if (onesPerSub64 == 1) {
subinventory[(inventoryIndex << log2LongwordsPerSubinventory) +
offset++] = i * 64L + j;
} else {
if ((d & onesPerInventoryMask) == 0) {
inventory[inventoryIndex] |= 1L << 63;
subinventory[inventoryIndex << log2LongwordsPerSubinventory] = spilled;
}
exactSpill[spilled++] = i * 64L + j;
}
}
d++;
}
}
}
}
public static SimpleSelect load(BitBuffer buffer) {
return new SimpleSelect(buffer);
}
public static SimpleSelect generate(BitSet bitSet, BitBuffer buffer) {
SimpleSelect s = new SimpleSelect(bitSet);
buffer.writeEliasDelta(s.numOnes + 1);
buffer.writeEliasDelta(s.numWords + 1);
for (long x : s.bits) {
buffer.writeNumber(x, 64);
}
buffer.writeEliasDelta(s.inventory.length + 1);
for (long x : s.inventory) {
buffer.writeNumber(x, 64);
}
buffer.writeEliasDelta(s.log2OnesPerInventory + 1);
buffer.writeEliasDelta(s.subinventory.length + 1);
for (long x : s.subinventory) {
buffer.writeNumber(x, 64);
}
buffer.writeEliasDelta(s.exactSpill.length + 1);
for (long x : s.exactSpill) {
buffer.writeNumber(x, 64);
}
return s;
}
public static int getSize(BitSet bitSet) {
int result = 0;
SimpleSelect s = new SimpleSelect(bitSet);
result += BitBuffer.getEliasDeltaSize(s.numOnes + 1);
result += BitBuffer.getEliasDeltaSize(s.numWords + 1);
result += 64 * s.bits.length;
result += BitBuffer.getEliasDeltaSize(s.inventory.length + 1);
result += 64 * s.inventory.length;
result += BitBuffer.getEliasDeltaSize(s.log2OnesPerInventory + 1);
result += BitBuffer.getEliasDeltaSize(s.subinventory.length + 1);
result += 64 * s.subinventory.length;
result += BitBuffer.getEliasDeltaSize(s.exactSpill.length + 1);
result += 64 * s.exactSpill.length;
return result;
}
void setSubInventory16(int index, int x) {
subinventory[index / 4] |= ((long) x) << (16 * (index % 4));
}
int getSubInventory16(int index) {
return (short) (subinventory[index / 4] >>> (16 * (index % 4)));
}
@Override
public long select(long rank) {
if (rank >= numOnes) {
return -1;
}
int inventoryIndex = (int) (rank >>> log2OnesPerInventory);
long inventoryRank = inventory[inventoryIndex];
int subrank = (int) (rank & onesPerInventoryMask);
if (subrank == 0) {
return inventoryRank & ~(1L << 63);
}
long start;
int residual;
if (inventoryRank >= 0) {
start = inventoryRank +
getSubInventory16((inventoryIndex << log2LongwordsPerSubinventory + 2) +
(subrank >>> log2OnesPerSub16));
residual = subrank & onesPerSub16Mask;
} else {
if (onesPerSub64 == 1) {
return subinventory[(inventoryIndex << log2LongwordsPerSubinventory) +
subrank];
}
return exactSpill[(int) (subinventory[inventoryIndex << log2LongwordsPerSubinventory] + subrank)];
}
if (residual == 0) {
return start;
}
long[] bits = this.bits;
int wordIndex = (int) (start / 64);
long word = bits[wordIndex] & (-1L << start);
for (;;) {
int bitCount = Long.bitCount(word);
if (residual < bitCount) {
break;
}
word = bits[++wordIndex];
residual -= bitCount;
}
return wordIndex * 64L + selectInLong(word, residual);
}
public static int selectInLong(long x, int rank) {
assert rank < Long.bitCount(x);
// Phase 1: sums by byte
long byteSums = x - ((x & 0xa * ONES_STEP_4) >>> 1);
byteSums = (byteSums & 3 * ONES_STEP_4) +
((byteSums >>> 2) & 3 * ONES_STEP_4);
byteSums = (byteSums + (byteSums >>> 4)) & 0x0f * ONES_STEP_8;
byteSums *= ONES_STEP_8;
// Phase 2: compare each byte sum with rank to obtain the relevant byte
long rankStep8 = rank * ONES_STEP_8;
int byteOffset = (int) (((((rankStep8 | MSBS_STEP_8) - byteSums) & MSBS_STEP_8) >>> 7) *
ONES_STEP_8 >>> 53) &
~0x7;
int byteRank = (int) (rank - (((byteSums << 8) >>> byteOffset) & 0xFF));
return byteOffset +
SELECT_IN_BYTE[(int) (x >>> byteOffset & 0xFF) | byteRank << 8];
}
@Override
public long selectPair(long i) {
long x = select(i);
int curr = (int) (x / Long.SIZE);
long window = bits[curr] & -1L << x;
window &= window - 1;
while (window == 0) {
window = bits[++curr];
}
long y = curr * Long.SIZE + Long.numberOfTrailingZeros(window);
return (x << 32) | y;
}
}
================================================
FILE: src/main/java/org/minperf/select/SimpleSelectWrapper.java
================================================
package org.minperf.select;
//import it.unimi.dsi.bits.LongArrayBitVector;
//import it.unimi.dsi.sux4j.bits.SimpleSelect;
//
//import java.io.ByteArrayInputStream;
//import java.io.ByteArrayOutputStream;
//import java.io.IOException;
//import java.io.ObjectInputStream;
//import java.io.ObjectOutputStream;
//import java.util.BitSet;
//
//import org.minperf.BitBuffer;
/**
* A select implementation with guaranteed O(1) query time. This is a wrapper
* around the the (very good) implementation in Sux4J
* it.unimi.dsi.sux4j.bits.SimpleSelect by Sebastiano Vigna.
*/
public class SimpleSelectWrapper {
// extends Select {
//
// private final SimpleSelect select;
//
// private SimpleSelectWrapper(SimpleSelect select) {
// this.select = select;
// }
//
// public static SimpleSelectWrapper generate(BitSet bitSet, BitBuffer buffer) {
// int len = bitSet.length();
// LongArrayBitVector bv = LongArrayBitVector.ofLength(len);
// for (int i = 0; i < len; i++) {
// if (bitSet.get(i)) {
// bv.set(i);
// }
// }
// SimpleSelect select = new SimpleSelect(bv);
// ByteArrayOutputStream out = new ByteArrayOutputStream();
// try {
// ObjectOutputStream oo = new ObjectOutputStream(out);
// oo.writeObject(select);
// } catch (IOException e) {
// throw new RuntimeException();
// }
// byte[] data = out.toByteArray();
// buffer.writeEliasDelta(data.length + 1);
// for (byte b : data) {
// buffer.writeNumber(b & 255, 8);
// }
// return new SimpleSelectWrapper(select);
// }
//
// public static Select load(BitBuffer buffer) {
// int len = (int) buffer.readEliasDelta() - 1;
// byte[] data = new byte[len];
// for (int i = 0; i < len; i++) {
// data[i] = (byte) buffer.readNumber(8);
// }
// SimpleSelect select;
// ByteArrayInputStream in = new ByteArrayInputStream(data);
// try {
// ObjectInputStream oi = new ObjectInputStream(in);
// select = (SimpleSelect) oi.readObject();
// } catch (Exception e) {
// throw new RuntimeException();
// }
// return new SimpleSelectWrapper(select);
// }
//
// @Override
// public long select(long x) {
// return select.select(x);
// }
//
// @Override
// public long selectPair(long x) {
// long[] dest = new long[2];
// select.select(x, dest);
// return (dest[0] << 32) | dest[1];
// }
}
================================================
FILE: src/main/java/org/minperf/select/VerySimpleSelect.java
================================================
package org.minperf.select;
import java.util.ArrayList;
import java.util.BitSet;
import org.minperf.BitBuffer;
/**
* A very simple implementation that assumes one bits are somewhat evenly
* distributed.
*
* The select operation is fast and space usage is quite low, but there is no
* strict guarantee that space usage is O(n) and the select operation is
* constant time in the RAM model, in the mathematical sense.
*/
public class VerySimpleSelect extends Select {
public static final byte[] SELECT_BIT_IN_BYTE;
public static final byte[] SELECT_BIT_IN_BYTE_REVERSE;
static {
byte[] data = new byte[256 * 8];
byte[] reverse = new byte[256 * 8];
for (int n = 0; n < 8; n++) {
for (int i = 0; i < 256; i++) {
data[i + (n << 8)] = (byte) selectBitSlow(i, n);
reverse[i + (n << 8)] = (byte) selectBitSlowReverse((long) i << (64 - 8), n);
}
}
SELECT_BIT_IN_BYTE = data;
SELECT_BIT_IN_BYTE_REVERSE = reverse;
}
// must be a power of 2
private static final int BITS_PER_BLOCK = 32;
private static final int BITS_PER_BLOCK_SHIFT =
31 - Integer.numberOfLeadingZeros(BITS_PER_BLOCK);
private final BitBuffer buffer;
private final int blockCount;
private final long blockCountScale;
private final int size;
private final int cardinality;
private final int bitCount;
private final int added;
private final int offsetPos;
private final int dataPos;
private VerySimpleSelect(BitBuffer buffer) {
this.buffer = buffer;
this.size = (int) (buffer.readEliasDelta() - 1);
this.cardinality = (int) (buffer.readEliasDelta() - 1);
this.blockCount = (cardinality + BITS_PER_BLOCK - 1) / BITS_PER_BLOCK;
this.blockCountScale = getScaleFactor(size, blockCount);
this.added = (int) BitBuffer.unfoldSigned(buffer.readEliasDelta() - 1);
this.bitCount = (int) (buffer.readEliasDelta() - 1);
this.offsetPos = buffer.position();
this.dataPos = offsetPos + bitCount * blockCount;
buffer.seek(dataPos + size);
}
public static VerySimpleSelect generate(BitSet set, BitBuffer buffer) {
int start = buffer.position();
int size = set.length() + 1;
buffer.writeEliasDelta(size + 1);
int cardinality = set.cardinality();
buffer.writeEliasDelta(cardinality + 1);
int blockCount = (cardinality + BITS_PER_BLOCK - 1) / BITS_PER_BLOCK;
ArrayList list = new ArrayList();
int pos = set.nextSetBit(0);
for (int i = 0; i < blockCount; i++) {
list.add(pos);
for (int j = 0; j < BITS_PER_BLOCK; j++) {
pos = set.nextSetBit(pos + 1);
}
}
long blockCountScale = getScaleFactor(size, blockCount);
int minDiff = Integer.MAX_VALUE;
for (int i = 0; i < list.size(); i++) {
// int expected = (int) ((long) size * i / blockCount);
int expected = (int) ((i * blockCountScale) >>> 32);
int got = list.get(i);
int diff = got - expected;
list.set(i, diff);
minDiff = Math.min(minDiff, diff);
}
if (list.size() == 0) {
minDiff = 0;
}
buffer.writeEliasDelta(BitBuffer.foldSigned(-minDiff) + 1);
int max = 0;
for (int i = 0; i < list.size(); i++) {
int x = list.get(i) - minDiff;
max = Math.max(max, x);
list.set(i, x);
}
int bitCount = 32 - Integer.numberOfLeadingZeros(max);
buffer.writeEliasDelta(bitCount + 1);
for (int i = 0; i < list.size(); i++) {
buffer.writeNumber(list.get(i), bitCount);
}
for (int i = 0; i < size; i++) {
buffer.writeBit(set.get(i) ? 1 : 0);
}
buffer.seek(start);
return new VerySimpleSelect(buffer);
}
public static int getSize(BitSet set) {
int result = 0;
int size = set.length() + 1;
result += BitBuffer.getEliasDeltaSize(size + 1);
int cardinality = set.cardinality();
result += BitBuffer.getEliasDeltaSize(cardinality + 1);
int blockCount = (cardinality + BITS_PER_BLOCK - 1) / BITS_PER_BLOCK;
ArrayList list = new ArrayList();
int pos = set.nextSetBit(0);
for (int i = 0; i < blockCount; i++) {
list.add(pos);
for (int j = 0; j < BITS_PER_BLOCK; j++) {
pos = set.nextSetBit(pos + 1);
}
}
long blockCountScale = getScaleFactor(size, blockCount);
int minDiff = Integer.MAX_VALUE;
for (int i = 0; i < list.size(); i++) {
// int expected = (int) ((long) size * i / blockCount);
int expected = (int) ((i * blockCountScale) >>> 32);
int got = list.get(i);
int diff = got - expected;
list.set(i, diff);
minDiff = Math.min(minDiff, diff);
}
if (list.size() == 0) {
minDiff = 0;
}
result += BitBuffer.getEliasDeltaSize(BitBuffer.foldSigned(-minDiff) + 1);
int max = 0;
for (int i = 0; i < list.size(); i++) {
int x = list.get(i) - minDiff;
max = Math.max(max, x);
list.set(i, x);
}
int bitCount = 32 - Integer.numberOfLeadingZeros(max);
result += BitBuffer.getEliasDeltaSize(bitCount + 1);
result += bitCount * list.size();
result += size;
return result;
}
private static long getScaleFactor(int multiply, int divide) {
return divide == 0 ? 0 : ((long) multiply << 32) / divide + 1;
}
public static VerySimpleSelect load(BitBuffer buffer) {
return new VerySimpleSelect(buffer);
}
@Override
public long select(long x) {
int block = (int) (x >>> BITS_PER_BLOCK_SHIFT);
int expected = (int) ((block * blockCountScale) >>> 32);
long read = buffer.readNumber(offsetPos + block * bitCount, bitCount);
long result = expected + read - added;
int remaining = (int) (x - ((long) block << BITS_PER_BLOCK_SHIFT));
while (true) {
int data = (int) buffer.readNumber((int) result + dataPos, 32);
int bitCount = Integer.bitCount(data);
if (remaining < bitCount) {
return result + selectBitReverse(data, remaining);
}
result += 32;
remaining -= bitCount;
}
}
@Override
public long selectPair(long x) {
int block = (int) (x >>> BITS_PER_BLOCK_SHIFT);
int expected = (int) ((block * blockCountScale) >>> 32);
long read = buffer.readNumber(offsetPos + block * bitCount, bitCount);
long result = expected + read - added;
int remaining = (int) (x - ((long) block << BITS_PER_BLOCK_SHIFT));
while (true) {
int data = (int) buffer.readNumber((int) result + dataPos, 32);
int bitCount = Integer.bitCount(data);
if (remaining < bitCount) {
int bit1 = selectBitReverse(data, remaining);
int bit2;
if (bit1 != 31 && data << (bit1 + 1) != 0) {
data <<= bit1 + 1;
bit1 += result;
bit2 = bit1 + 1 + Integer.numberOfLeadingZeros(data);
} else {
bit1 += result;
bit2 = bit1 + 1;
while (true) {
data = (int) buffer.readNumber(bit2 + dataPos, 32);
if (data != 0) {
bit2 += Integer.numberOfLeadingZeros(data);
break;
}
bit2 += 32;
}
}
return ((long) bit1 << 32) | bit2;
}
result += 32;
remaining -= bitCount;
}
}
public static int selectBitSlowReverse(long x, int n) {
return selectBitSlow(Long.reverse(x), n);
}
public static int selectBitSlow(long x, int n) {
n++;
for (int i = 0; i < 64; i++) {
if ((x & 1) == 1) {
n--;
if (n == 0) {
return i;
}
}
x >>>= 1;
}
return -1;
}
public static int selectBitLongReverse(long x, int n) {
// int bitCount = Long.bitCount(x & 0xffffffff00000000L);
int bitCount = Long.bitCount(x >>> 32);
int more = (bitCount - n - 1) >> 31;
int result = more & 32;
n -= bitCount & more;
// bitCount = Long.bitCount((x << result) & 0xffff000000000000L);
bitCount = Long.bitCount((x << result) >>> 48);
more = (bitCount - n - 1) >> 31;
result += more & 16;
n -= bitCount & more;
// bitCount = Long.bitCount((x << result) & 0xff00000000000000L);
bitCount = Long.bitCount((x << result) >>> 56);
more = (bitCount - n - 1) >> 31;
result += more & 8;
n -= bitCount & more;
return SELECT_BIT_IN_BYTE_REVERSE[(int) ((x << result) >>> 56) | (n << 8)] + result;
}
public static int selectBitLong(long x, int n) {
int bitCount = Long.bitCount(x & 0xffffffffL);
int more = (bitCount - n - 1) >> 31;
int result = more & 32;
n -= bitCount & more;
bitCount = Long.bitCount((x >>> result) & 0xffff);
more = (bitCount - n - 1) >> 31;
result += more & 16;
n -= bitCount & more;
bitCount = Long.bitCount((x >>> result) & 0xff);
more = (bitCount - n - 1) >> 31;
result += more & 8;
n -= bitCount & more;
return SELECT_BIT_IN_BYTE[(int) ((x >>> result) & 0xff) | (n << 8)] + result;
}
public static int selectBitReverse(int x, int n) {
// int bitCount = Integer.bitCount(x & 0xffff0000);
int bitCount = Integer.bitCount(x >>> 16);
int more = (bitCount - n - 1) >> 31;
int result = more & 16;
n -= bitCount & more;
// bitCount = Integer.bitCount((x << result) & 0xff000000);
bitCount = Integer.bitCount((x << result) >>> 24);
more = (bitCount - n - 1) >> 31;
result += more & 8;
n -= bitCount & more;
return SELECT_BIT_IN_BYTE_REVERSE[((x << result) >>> 24) | (n << 8)] + result;
}
public static int selectBit(int x, int n) {
int bitCount = Integer.bitCount(x & 0xffff);
int more = (bitCount - n - 1) >> 31;
int result = more & 16;
n -= bitCount & more;
bitCount = Integer.bitCount((x >>> result) & 0xff);
more = (bitCount - n - 1) >> 31;
result += more & 8;
n -= bitCount & more;
return SELECT_BIT_IN_BYTE[((x >>> result) & 0xff) | (n << 8)] + result;
}
}
================================================
FILE: src/main/java/org/minperf/universal/LongHash.java
================================================
package org.minperf.universal;
/**
* A sample hash implementation for long keys.
*/
public class LongHash implements UniversalHash {
public static long universalHash(long x, long index) {
long v0 = index ^ 0x736f6d6570736575L;
long v1 = index ^ 0x646f72616e646f6dL;
long v2 = index ^ 0x6c7967656e657261L;
long v3 = index ^ 0x7465646279746573L;
v3 ^= x;
for (int i = 0; i < 4; i++) {
v0 += v1;
v2 += v3;
v1 = Long.rotateLeft(v1, 13);
v3 = Long.rotateLeft(v3, 16);
v1 ^= v0;
v3 ^= v2;
v0 = Long.rotateLeft(v0, 32);
v2 += v1;
v0 += v3;
v1 = Long.rotateLeft(v1, 17);
v3 = Long.rotateLeft(v3, 21);
v1 ^= v2;
v3 ^= v0;
v2 = Long.rotateLeft(v2, 32);
}
v0 ^= x;
return v0 ^ v1 ^ v2 ^ v3;
}
@Override
public long universalHash(Long key, long index) {
return universalHash((long) key, index);
}
@Override
public String toString() {
return "LongHash (SipHash)";
}
}
================================================
FILE: src/main/java/org/minperf/universal/StringHash.java
================================================
package org.minperf.universal;
import java.nio.charset.Charset;
/**
* A hash implementation for string keys.
*/
public class StringHash implements UniversalHash {
private static final Charset UTF8 = Charset.forName("UTF-8");
@Override
public long universalHash(String key, long index) {
return getSipHash24(key, index, index);
}
/**
* A cryptographically relatively secure hash function. It is supposed
* to protected against hash-flooding denial-of-service attacks.
*
* @param o the string
* @param k0 key 0
* @param k1 key 1
* @return the hash value
*/
public static long getSipHash24(String o, long k0, long k1) {
byte[] b = o.getBytes(UTF8);
return getSipHash24(b, 0, b.length, k0, k1);
}
/**
* A cryptographically relatively secure hash function. It is supposed
* to protected against hash-flooding denial-of-service attacks.
*
* @param b the data
* @param start the start position
* @param end the end position plus one
* @param k0 key 0
* @param k1 key 1
* @return the hash value
*/
public static long getSipHash24(byte[] b, int start, int end, long k0,
long k1) {
long v0 = k0 ^ 0x736f6d6570736575L;
long v1 = k1 ^ 0x646f72616e646f6dL;
long v2 = k0 ^ 0x6c7967656e657261L;
long v3 = k1 ^ 0x7465646279746573L;
int repeat;
for (int off = start; off <= end + 8; off += 8) {
long m;
if (off <= end) {
m = 0;
int i = 0;
for (; i < 8 && off + i < end; i++) {
m |= ((long) b[off + i] & 255) << (8 * i);
}
if (i < 8) {
m |= ((long) end - start) << 56;
}
v3 ^= m;
repeat = 2;
} else {
m = 0;
v2 ^= 0xff;
repeat = 4;
}
for (int i = 0; i < repeat; i++) {
v0 += v1;
v2 += v3;
v1 = Long.rotateLeft(v1, 13);
v3 = Long.rotateLeft(v3, 16);
v1 ^= v0;
v3 ^= v2;
v0 = Long.rotateLeft(v0, 32);
v2 += v1;
v0 += v3;
v1 = Long.rotateLeft(v1, 17);
v3 = Long.rotateLeft(v3, 21);
v1 ^= v2;
v3 ^= v0;
v2 = Long.rotateLeft(v2, 32);
}
v0 ^= m;
}
return v0 ^ v1 ^ v2 ^ v3;
}
@Override
public String toString() {
return "StringHash (SipHash)";
}
}
================================================
FILE: src/main/java/org/minperf/universal/UniversalHash.java
================================================
package org.minperf.universal;
/**
* An interface that can calculate multiple hash values for an object. The
* returned hash value of two distinct objects may be the same for a given
* hash function index, but as more hash functions indices are called for
* those objects, the returned value must eventually be different
* (the earlier the better).
*
* The returned value does not need to be uniformly distributed.
*
* @param the type
*/
public interface UniversalHash {
/**
* Calculate the hash of the given object.
*
* @param key the key in the set
* @param index the hash function index (0, 1, 2,...)
* @return the universal hash (64 bits)
*/
long universalHash(T key, long index);
}
================================================
FILE: src/main/java/org/minperf/utils/LargeLongList.java
================================================
package org.minperf.utils;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Spliterator;
/**
* A persisted list of longs.
*/
public class LargeLongList extends AbstractList {
static final int CHUNK_SHIFT = 27;
static final int CHUNK_SIZE = 1 << CHUNK_SHIFT;
private static final int CHUNK_MASK = CHUNK_SIZE - 1;
private final int size;
private ArrayList list = new ArrayList();
LargeLongList(int size, ArrayList list) {
this.size = size;
this.list = list;
}
@Override
public Long get(int index) {
if (index == 0) {
System.out.println("...LargeLongList.get[0]");
}
return list.get(index >>> CHUNK_SHIFT).get(index & CHUNK_MASK);
}
@Override
public int size() {
return size;
}
@Override
public void finalize() {
dispose();
}
public void dispose() {
for (LargeLongArray a : list) {
a.dispose();
}
}
public static LargeLongList create(Collection collection) {
int size = collection.size();
int chunks = (size + CHUNK_SIZE - 1) / CHUNK_SIZE;
int remaining = size;
Iterator iterator = collection.iterator();
ArrayList list = new ArrayList();
for (int i = 0; i < chunks; i++) {
int len = Math.min(CHUNK_SIZE, remaining);
list.add(LargeLongArray.create(iterator, len));
remaining -= len;
}
return new LargeLongList(size, list);
}
@Override
public Spliterator spliterator() {
throw new UnsupportedOperationException();
}
/**
* A large long array.
*/
static class LargeLongArray {
private File file;
private FileChannel channel;
private MappedByteBuffer map;
private final int size;
private boolean closed;
public LargeLongArray(int size, File file, FileChannel channel,
MappedByteBuffer map) {
this.size = size;
this.file = file;
this.channel = channel;
this.map = map;
}
static LargeLongArray create(Iterator iterator, int size) {
try {
File file = File.createTempFile("list", ".tmp");
file.deleteOnExit();
try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
FileChannel channel = raf.getChannel();
MappedByteBuffer map = channel
.map(MapMode.READ_WRITE, 0, size * 8L);
for (int i = 0; i < size; i++) {
long x = iterator.next();
map.putLong(x);
}
return new LargeLongArray(size, file, channel, map);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void finalize() {
dispose();
}
public void dispose() {
if (closed) {
return;
}
closed = true;
try {
channel.close();
file.delete();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Long get(int index) {
if (index > size) {
throw new IllegalArgumentException();
}
return map.getLong(index * 8);
}
}
}
================================================
FILE: src/main/java/org/minperf/utils/LongSet.java
================================================
package org.minperf.utils;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;
/**
* A map of longs. Only add an iteration are not supported. This implementation
* doesn't use much memory.
*/
public class LongSet extends AbstractSet {
LargeLongArray data;
boolean containsZero;
private long size;
public LongSet(int capacity) {
// 80% fill rate
long len = capacity * 12L / 10;
data = new LargeLongArray(len);
}
@Override
public int size() {
return (int) size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean add(Long e) {
if (e == 0) {
if (containsZero) {
return false;
}
containsZero = true;
size++;
return true;
}
long x = e;
if (size * 10 > data.size() * 11) {
// more than 90% full
throw new UnsupportedOperationException();
}
long index = (x & 0xffffffffffffL) % data.size();
while (true) {
if (data.get(index) == x) {
return false;
}
if (data.get(index) == 0) {
data.set(index, x);
size++;
return true;
}
index++;
if (index >= data.size()) {
index = 0;
}
}
}
@Override
public Iterator iterator() {
return new Iterator() {
private long index;
{
index = -1;
if (!containsZero) {
fetchNext();
}
}
private void fetchNext() {
while (true) {
index++;
if (index >= data.size()) {
return;
}
if (data.get(index) != 0) {
return;
}
}
}
@Override
public boolean hasNext() {
return index < data.size();
}
@Override
public Long next() {
if (!hasNext()) {
throw new UnsupportedOperationException();
}
if (index == -1) {
fetchNext();
return 0L;
}
long result = data.get(index);
fetchNext();
return result;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void forEachRemaining(Consumer super Long> action) {
throw new UnsupportedOperationException();
}
};
}
@Override
public Spliterator spliterator() {
throw new UnsupportedOperationException();
}
/**
* A large long array.
*/
static class LargeLongArray {
private static final int CHUNK_SHIFT = 20;
private static final int CHUNK_SIZE = 1 << CHUNK_SHIFT;
private static final int CHUNK_MASK = CHUNK_SIZE - 1;
private final long[][] data;
private final long size;
LargeLongArray(long size) {
this.size = size;
int chunkCount = (int) ((size + CHUNK_SIZE - 1) >>> CHUNK_SHIFT);
data = new long[chunkCount][];
long remaining = size;
for (int i = 0; i < chunkCount - 1; i++) {
data[i] = new long[CHUNK_SIZE];
remaining -= CHUNK_SIZE;
}
data[chunkCount - 1] = new long[(int) remaining];
}
long get(long i) {
return data[(int) (i >>> CHUNK_SHIFT)][(int) (i & CHUNK_MASK)];
}
void set(long i, long x) {
data[(int) (i >>> CHUNK_SHIFT)][(int) (i & CHUNK_MASK)] = x;
}
long size() {
return size;
}
}
}
================================================
FILE: src/main/java/org/minperf/utils/PoissonDistribution.java
================================================
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.minperf.utils;
/**
* Poisson distribution. This code is based on the
* implementation at Apache Commons Math 4.
*
* See http://en.wikipedia.org/wiki/Poisson_distribution,
* http://mathworld.wolfram.com/PoissonDistribution.html
*/
public class PoissonDistribution {
private static final double PI = 105414357.0 / 33554432.0 + 1.984187159361080883e-9;
private static final double TWO_PI = 2 * PoissonDistribution.PI;
// Exact Stirling expansion error for certain values.
private static final double[] EXACT_STIRLING_ERRORS = { 0.0,
0.1534264097200273452913848, 0.0810614667953272582196702,
0.0548141210519176538961390, 0.0413406959554092940938221,
0.03316287351993628748511048, 0.02767792568499833914878929,
0.02374616365629749597132920, 0.02079067210376509311152277,
0.01848845053267318523077934, 0.01664469118982119216319487,
0.01513497322191737887351255, 0.01387612882307074799874573,
0.01281046524292022692424986, 0.01189670994589177009505572,
0.01110455975820691732662991, 0.010411265261972096497478567,
0.009799416126158803298389475, 0.009255462182712732917728637,
0.008768700134139385462952823, 0.008330563433362871256469318,
0.007934114564314020547248100, 0.007573675487951840794972024,
0.007244554301320383179543912, 0.006942840107209529865664152,
0.006665247032707682442354394, 0.006408994188004207068439631,
0.006171712263039457647532867, 0.005951370112758847735624416,
0.005746216513010115682023589, 0.005554733551962801371038690 };
public static double probability(double p, int x) {
double logProbability = logProbability(p, x);
if (logProbability == Double.NEGATIVE_INFINITY) {
return 0;
}
return Math.exp(logProbability);
}
private static double logProbability(double p, int x) {
if (x < 0 || x == Integer.MAX_VALUE) {
return Double.NEGATIVE_INFINITY;
} else if (x == 0) {
return -p;
}
return -getStirlingError(x) - getDeviancePart(x, p) - 0.5 *
Math.log(PoissonDistribution.TWO_PI) - 0.5 * Math.log(x);
}
/**
* Compute the error of Stirling's series at the given value.
*
* Reference: Eric W. Weisstein. "Stirling's Series." From MathWorld - A
* Wolfram Web Resource. http://mathworld.wolfram.com/StirlingsSeries.html
*
* @param z the value.
* @return the Striling's series error.
*/
private static double getStirlingError(double z) {
if (z < 15.0) {
double z2 = 2.0 * z;
if (Math.floor(z2) == z2) {
return EXACT_STIRLING_ERRORS[(int) z2];
}
throw new IllegalArgumentException("Unsupported z value " + z);
}
double z2 = z * z;
return (0.083333333333333333333 -
(0.00277777777777777777778 -
(0.00079365079365079365079365 -
(0.000595238095238095238095238 -
0.0008417508417508417508417508 / z2) /
z2) /
z2) /
z2) /
z;
}
/**
* A part of the deviance portion of the saddle point approximation.
*
* Reference: Catherine Loader (2000). "Fast and Accurate Computation of
* Binomial Probabilities." http://www.herine.net/stat/papers/dbinom.pdf
*
* @param x the x value.
* @param mu the average.
* @return a part of the deviance.
*/
private static double getDeviancePart(double x, double mu) {
if (Math.abs(x - mu) < 0.1 * (x + mu)) {
double d = x - mu;
double v = d / (x + mu);
double s1 = v * d;
double s = Double.NaN;
double ej = 2.0 * x * v;
v *= v;
int j = 1;
while (s1 != s) {
s = s1;
ej *= v;
s1 = s + ej / ((j * 2) + 1);
++j;
}
return s1;
}
if (x == 0) {
return mu;
}
return x * Math.log(x / mu) + mu - x;
}
}
================================================
FILE: src/main/java/org/minperf/utils/RandomSetGenerator.java
================================================
package org.minperf.utils;
import java.util.Random;
/**
* A PRNG that returns unique (distinct) 64-bit entries in somewhat sorted
* order. Not fully sorted, for speed, but the largest entry of a block is
* guaranteed to be smaller of the smallest entry of the next block. The set
* doesn't need to be kept fully in memory.
*/
public class RandomSetGenerator {
public static void main(String... args) {
long size = 1_000_000_000_000L;
System.out.println(size * 150 / 1000000 / 1000 / 60 / 60. + " h");
// sorted: with 24 ns / key, it would take 6 h to generate
// not fully sorted: with 4 ns / key, it would take 1 h to generate
System.out.println((double) Long.MAX_VALUE + " max long");
long[] data = new long[2_000_000];
Random r = new Random(1);
RandomBlockProducer it = randomHashProducer(r, size);
long len = 0;
long start = System.nanoTime();
long maxLastBlock = -1;
for (long remaining = size; remaining >= 0;) {
int produced = it.produce(data, 0, data.length, 0);
len += produced;
if (produced == 0) {
break;
}
long minBlock = Long.MAX_VALUE, maxBlock = -1;
for (int i = 0; i < produced; i++) {
long x = data[i];
minBlock = Math.min(minBlock, x);
maxBlock = Math.max(maxBlock, x);
}
if (minBlock > maxBlock) {
throw new AssertionError();
}
if (minBlock < maxLastBlock) {
throw new AssertionError();
}
maxLastBlock = maxBlock;
System.out.println("produced " + produced);
remaining -= produced;
long time = System.nanoTime() - start;
System.out.println(size + " " + (double) time / len + " ns/key len " + len);
}
}
public static RandomBlockProducer randomHashProducer(Random r, long size) {
return randomProducer(r, size, 63);
}
private static RandomBlockProducer randomProducer(final Random r, final long size, final int shift) {
if (shift <= 44) {
if (shift != 44) {
throw new IllegalArgumentException();
}
return new RandomBlockProducer() {
long remaining = size;
@Override
public int produce(long[] data, int offset, int len, long add) {
if (len < size) {
return 0;
}
for (int i = 0; i < size; i++) {
data[i + offset] = hash44(i + offset + add + 1) + add;
// break;
}
// Arrays.parallelSort(data, offset, offset + (int) size);
// Arrays.sort(data, offset, offset + (int) size);
remaining = 0;
return (int) size;
}
@Override
public long remaining() {
return remaining;
}
};
}
return new RandomBlockProducer() {
long remaining = size, zeros = randomHalf(r, size);
long bitMask;
RandomBlockProducer child = randomProducer(r, zeros, shift - 1);
@Override
public int produce(long[] data, int offset, int len, long add) {
int produced = 0;
while (true) {
if (child.remaining() == 0) {
if (bitMask != 0) {
return produced;
}
bitMask = 1L << shift;
child = randomProducer(r, size - zeros, shift - 1);
}
int p = child.produce(data, offset, len, bitMask + add);
if (p == 0) {
return produced;
}
produced += p;
offset += p;
len -= p;
remaining -= p;
}
}
@Override
public long remaining() {
return remaining;
}
};
}
/**
* Get the number of entries that are supposed to be below the half,
* according to the probability theory. For example, for a number of coin
* flips, how many are heads.
*
* @param r the random generator
* @param samples the total number of entries
* @return the number of entries that should be used for one half
*/
static long randomHalf(Random r, long samples) {
long low = 0, high = samples;
double x = r.nextDouble();
while (low + 1 < high) {
long mid = (low + high) / 2;
double p = probabilityBucketAtMost(samples, mid);
if (x > p) {
low = mid;
} else {
high = mid;
}
}
return (low + high) / 2;
}
static double probabilityBucketAtMost(long flips, long heads) {
// https://www.fourmilab.ch/rpkp/experiments/statistics.html
long x = heads;
long n = flips;
double variance = Math.sqrt(n / 4);
// mean
long mu = n / 2;
// https://en.wikipedia.org/wiki/Normal_distribution
// Numerical approximations for the normal CDF
// the probability that the value of a standard normal random variable X
// is <= x
return phi((x - mu) / variance);
}
static double phi(double x) {
return 0.5 * (1 + Math.signum(x) * Math.sqrt(1 - Math.exp(-2 * x * x / Math.PI)));
}
public static long hash64(long x) {
x = (x ^ (x >>> 30)) * 0xbf58476d1ce4e5b9L;
x = (x ^ (x >>> 27)) * 0x94d049bb133111ebL;
x = x ^ (x >>> 31);
return x;
}
public static long hash44(long x) {
x = (x ^ (x >>> 20)) * 0xbf58476d1ce4e5b9L;
x &= (1L << 44) - 1;
x = (x ^ (x >>> 17)) * 0x94d049bb133111ebL;
x &= (1L << 44) - 1;
x = x ^ (x >>> 21);
x &= (1L << 44) - 1;
return x;
}
public static long hash32(long x) {
x = (x ^ (x >>> 16)) * 0xbf58476d1ce4e5b9L;
x &= 0xffffffffL;
x = (x ^ (x >>> 16)) * 0x94d049bb133111ebL;
x &= 0xffffffffL;
x = x ^ (x >>> 16);
return x & 0xffffffffL;
}
public static long hash16(long x) {
x = (x ^ (x >>> 7)) * 0xbf58476d1ce4e5b9L;
x &= 0xffff;
x = (x ^ (x >>> 5)) * 0x94d049bb133111ebL;
x &= 0xffff;
x = x ^ (x >>> 9);
return x & 0xffff;
}
public interface RandomBlockProducer {
int produce(long[] data, int offset, int len, long add);
long remaining();
}
}
================================================
FILE: src/main/java/org/minperf/utils/RandomSetGeneratorSlow.java
================================================
package org.minperf.utils;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
/**
* A PRNG that returns unique (distinct) entries in sorted order. The set
* doesn't need to be kept fully in memory. Also, with more than 100'000
* entries, this is faster that generating the set fully in memory (due to not
* having to keep the whole set in memory, to check for duplicates).
*/
public class RandomSetGeneratorSlow {
public static void main(String... args) {
Random r = new Random();
for(long size = 1000; size > 0; size *= 10) {
for(int limit = 10; limit < size; limit*=10) {
long time = System.nanoTime();
Iterator it = randomSequence(r, size, 64, limit);
while(it.hasNext()) {
it.next();
}
time = System.nanoTime() - time;
System.out.println(size + " " + time / size + " ns/key limit " + limit);
}
}
// Iterator it = randomSequence(r, 10, 32, 100);
// while(it.hasNext()) {
// System.out.println(it.next());
// }
}
public static Iterable randomSequence(final long size) {
return new Iterable() {
@Override
public Iterator iterator() {
return randomSequence(new Random(size), size, 64, 10000);
}
};
}
/**
* Random sequence generator.
*
* @param r the random generator
* @param size the number of entries to generate
* @param shift the number of bits of the result
* @return the iterator
*/
static Iterator randomSequence(final Random r, final long size, final int shift, final int limit) {
if (size < limit) {
// small lists are generated using a regular hash set
HashSet set = new HashSet((int) size);
// this would ensure the list is fully sorted
// TreeSet set = new TreeSet();
if (shift == 64) {
while (set.size() < size) {
set.add(r.nextLong());
}
} else {
while (set.size() < size) {
set.add(r.nextLong() & ((2L << shift) - 1));
}
}
return set.iterator();
}
// large lists are created recursively
return new Iterator() {
long remaining = size, zeros = randomHalf(r, size);
Iterator lowBits0 = randomSequence(r, zeros, shift - 1, limit);
Iterator lowBits1;
@Override
public boolean hasNext() {
return remaining > 0;
}
@Override
public Long next() {
remaining--;
if (lowBits0 != null) {
if (lowBits0.hasNext()) {
return lowBits0.next();
}
lowBits0 = null;
}
if (lowBits1 == null) {
lowBits1 = randomSequence(r, size - zeros, shift - 1, limit);
}
return (1L << shift) + lowBits1.next();
}
};
}
/**
* Get the number of entries that are supposed to be below the half,
* according to the probability theory. For example, for a number of coin
* flips, how many are heads.
*
* @param r the random generator
* @param samples the total number of entries
* @return the number of entries that should be used for one half
*/
static long randomHalf(Random r, long samples) {
long low = 0, high = samples;
double x = r.nextDouble();
while (low + 1 < high) {
long mid = (low + high) / 2;
double p = probabilityBucketAtMost(samples, mid);
if (x > p) {
low = mid;
} else {
high = mid;
}
}
return (low + high) / 2;
}
static double probabilityBucketAtMost(long flips, long heads) {
// https://www.fourmilab.ch/rpkp/experiments/statistics.html
long x = heads;
long n = flips;
double variance = Math.sqrt(n/4);
// mean
long mu = n / 2;
// https://en.wikipedia.org/wiki/Normal_distribution
// Numerical approximations for the normal CDF
// the probability that the value of a standard normal random variable X is <= x
return phi((x - mu) / variance);
}
static double phi(double x) {
return 0.5 * (1 + Math.signum(x) * Math.sqrt(1 - Math.exp(-2 * x * x / Math.PI)));
}
}
================================================
FILE: src/main/java/org/minperf/utils/Text.java
================================================
package org.minperf.utils;
import java.util.Comparator;
import org.minperf.universal.StringHash;
import org.minperf.universal.UniversalHash;
/**
* A text. It is similar to a String, but needs less memory.
*/
public class Text implements CharSequence {
/**
* The byte data (may be shared, so must not be modified).
*/
final byte[] data;
/**
* The offset (start location).
*/
private final int offset;
/**
* The length.
*/
private final int len;
public Text(byte[] data, int offset, int len) {
this.data = data;
this.offset = offset;
this.len = len;
}
public static int indexOf(byte[] data, int index, int character) {
while (data[index] != character) {
index++;
}
return index;
}
/**
* The hash code (using a universal hash function).
*
* @param index the hash function index
* @return the hash code
*/
public long hashCode(long index) {
return StringHash.getSipHash24(data, offset, offset + len, index, 0);
}
@Override
public int hashCode() {
return (int) hashCode(0);
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (!(other instanceof Text)) {
return false;
}
Text o = (Text) other;
if (o.len != len) {
return false;
}
for (int i = 0; i < len; i++) {
if (data[offset + i] != o.data[o.offset + i]) {
return false;
}
}
return true;
}
public int compareFast(Text o) {
int comp = Integer.compare(len, o.len);
if (comp != 0) {
return comp;
}
for (int i = 0; i < len; i++) {
int b = data[offset + i] & 0xff;
int b2 = o.data[o.offset + i] & 0xff;
if (b != b2) {
return b > b2 ? 1 : -1;
}
}
return 0;
}
@Override
public String toString() {
return new String(data, offset, len);
}
@Override
public int length() {
return len;
}
@Override
public char charAt(int index) {
return (char) data[offset + index];
}
@Override
public CharSequence subSequence(int start, int end) {
return new Text(data, offset + start, end - start);
}
/**
* The universal hash function for text.
*/
public static class UniversalTextHash implements UniversalHash {
@Override
public long universalHash(Text o, long index) {
return o.hashCode(index);
}
}
/**
* Compare two texts. For improved speed, sorting is a bit unusual: sorting
* is first done by size, and only then by data. This is a bit faster then
* always sorting by data.
*/
public static class FastComparator implements Comparator {
private int equalCount;
@Override
public int compare(Text o1, Text o2) {
int comp = o1.compareFast(o2);
if (comp == 0) {
equalCount++;
}
return comp;
}
public int equalCount() {
return equalCount;
}
}
}
================================================
FILE: src/test/java/org/minperf/BitCodes.java
================================================
package org.minperf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.Random;
import org.junit.Test;
/**
* Tests for Rice-Golomb codes, Elias Delta codes, and the FastBitBuffer class.
*/
public class BitCodes {
public static void main(String... args) {
for (int i = 0; i < 10; i++) {
testPerformance();
}
}
private static void testPerformance() {
BitBuffer buff = new BitBuffer(8 * 1024 * 1024);
int len = 10000;
for (int i = 0; i < len; i++) {
buff.writeGolombRice(10, i);
}
long time = System.currentTimeMillis();
for (int j = 0; j < 1000; j++) {
buff.seek(0);
for (int i = 0; i < len; i++) {
assertEquals(i, buff.readGolombRice(10));
}
}
time = System.currentTimeMillis() - time;
System.out.println("time: " + time);
}
public static void printRiceExamples() {
for (int i = 0; i < 20; i++) {
System.out.println(" " + i + " & " +
getRice(i, 0) + " & " +
getRice(i, 1) + " & " +
getRice(i, 2) + " & " +
getRice(i, 3) + " & " +
getRice(i, 4) + " & " +
getRice(i, 5) + " \\\\");
}
}
@Test
public void testGolombRiceCoding() {
assertEquals("0", getRice(0, 0));
assertEquals("10", getRice(1, 0));
assertEquals("110", getRice(2, 0));
assertEquals("11..10", getRice(15, 0));
assertEquals("00", getRice(0, 1));
assertEquals("01", getRice(1, 1));
assertEquals("100", getRice(2, 1));
assertEquals("11..101", getRice(15, 1));
assertEquals("000", getRice(0, 2));
assertEquals("001", getRice(1, 2));
assertEquals("010", getRice(2, 2));
assertEquals("111011", getRice(15, 2));
assertEquals("0000", getRice(0, 3));
assertEquals("0001", getRice(1, 3));
assertEquals("0010", getRice(2, 3));
assertEquals("10111", getRice(15, 3));
for (int shift = 1; shift < 60; shift++) {
for (int i = 1; i < 100; i++) {
getRice(i, shift);
}
for (int i = 10; i < 100000; i *= 4) {
getRice(i, shift);
}
}
Random r = new Random();
for (int i = 0; i < 1000; i++) {
getRice(r.nextLong() & 0x7fffffffL, 60);
}
}
private static String getRice(long value, int shift) {
BitBuffer buff = new BitBuffer(128 * 1024);
buff.writeGolombRice(shift, value);
int size = BitBuffer.getGolombRiceSize(shift, value);
buff.seek(0);
StringBuilder b = new StringBuilder();
for (int i = 0; i < size; i++) {
b.append((char) ('0' + buff.readBit()));
}
String s = b.toString();
s = s.replaceFirst("^111111*", "11..1");
return s;
}
static double calcEntropy(double p) {
// On the Determination of Optimal Parameterized Prefix Codes
// for Adaptive Entropy Coding
// Amir Said
// 2.13, page 12
double m = 1 - p;
return -Math.log(1 - m) / Math.log(2) - (m / (1 - m)) *
Math.log(m) / Math.log(2);
}
public static double calcAverageRiceGolombBits(int k, double p) {
double alpha = 1 - p;
return k + (1 / (1 - Math.pow(alpha, Math.pow(2, k))));
}
public static int calcBestGolombRiceShift(double p) {
double mean = (1 - p) / p;
// double p = 1 / (mean + 1);
return calcBestGolombRiceShiftFromMean(mean);
}
public static int calcBestGolombRiceShiftFromMean(double mean) {
// variant a
double goldenRatio = (Math.sqrt(5) + 1) / 2;
double logGoldenRatioMinus1 = Math.log(goldenRatio - 1);
double k = 1 + (Math.log(logGoldenRatioMinus1 /
Math.log(mean / (mean + 1))) / Math.log(2));
// variant b
// from "On the Determination of Optimal Parameterized
// Prefix Codes for Adaptive Entropy Coding"
// double k2 = 1 + Math.log(Math.log(goldenRatio) /
// Math.log(1 / (1 - p))) / Math.log(2);
return Math.max(0, (int) k);
}
public static void verifyRiceParameterFormula() {
System.out.println("Rice Parameter Formula");
for (int leafSize = 4; leafSize < 12; leafSize++) {
double p = Probability.probabilitySplitIntoMSubsetsOfSizeN(
leafSize, 1);
verifyRiceParameterFormula(p);
}
}
private static void verifyRiceParameterFormula(double p) {
System.out.println("Pr(X = x) = (1-p)^(x-1) * p with p=" + p);
int[] counts = new int[11];
Random r = new Random(2);
int repeat = 1000000;
for (int i = 0; i < repeat; i++) {
for (int j = 1; j <= 10; j++) {
boolean success = r.nextDouble() <= p;
if (success) {
counts[j]++;
break;
}
}
}
for (int j = 1; j <= 10; j++) {
double px = counts[j] / (double) repeat;
double pFormula = Math.pow(1 - p, j - 1) * p;
System.out.println(" try " + j + ": simulated " + px +
" calculated " + pFormula);
if (Math.abs(px - pFormula) > px / 2) {
fail();
}
}
System.out.println(" Best Rice parameter");
double a = 1 - p;
double goldenRatio = (Math.sqrt(5) + 1) / 2;
double mu = (1 - p) / p;
double mu2 = a / (1 - a);
System.out.println(" mu:" + mu);
System.out.println(" mu2:" + mu2);
if (Math.abs(mu - mu2) > mu / 10) {
fail();
}
double logGoldenRatio = Math.log(goldenRatio - 1);
double logMu = Math.log(mu / (mu + 1));
int bestK = (int) Math.max(0, 1 + Math.log(logGoldenRatio / logMu) /
Math.log(2));
System.out.println(" bestK = " + bestK);
int test = calcBestGolombRiceShift(p);
assertEquals(test, bestK);
System.out.println(" Average Bits Needed");
long bitCount = 0;
r = new Random(1);
repeat = 10000;
for (int i = 0; i < repeat; i++) {
for (int j = 0;; j++) {
boolean success = r.nextDouble() <= p;
if (success) {
bitCount += BitBuffer.getGolombRiceSize(test, j);
break;
}
}
}
double averageBits = bitCount / (double) repeat;
System.out.println(" averageBits simulated " + averageBits);
double averageBits2 = calcAverageRiceGolombBits(test, p);
System.out.println(" averageBits calculated " + averageBits2);
if (Math.abs(averageBits - averageBits2) > averageBits / 10) {
fail();
}
}
public static void printEliasDeltaExample() {
System.out.println("Elias Delta code examples");
for (int i = 1; i < 10; i++) {
System.out.println(" " + i + " & " +
getEliasDelta(i) + " \\\\");
}
for (int i = 10; i < 1000000; i *= 10) {
System.out.println(" " + i + " & " +
getEliasDelta(i) + " \\\\");
}
}
@Test
public void testEliasDeltaRoundtrip() {
Random r = new Random(1);
for (int i = 0; i < 1000; i++) {
BitBuffer buff = new BitBuffer(8 * 1024 * 1024);
long val = (r.nextLong() & 0xfffffffL) + 1;
buff.writeEliasDelta(val);
assertEquals(buff.position(), BitBuffer.getEliasDeltaSize(val));
buff.writeNumber(123, 10);
int pos = buff.position();
byte[] data = buff.toByteArray();
assertEquals((pos + 7) / 8, data.length);
buff = new BitBuffer(buff.toByteArray());
assertEquals(val, buff.readEliasDelta());
assertEquals(123, buff.readNumber(10));
assertEquals(pos, buff.position());
}
}
// this test fails!!!!!
//@Test
public void testNumberRoundtrip() {
Random r = new Random(1);
BitBuffer buff = new BitBuffer(8 * 1024 * 1024);
buff.writeNumber(-1L, 64);
buff.writeNumber(0, 64);
for (int i = 0; i < 1000; i++) {
long val = r.nextLong();
int bitCount = r.nextInt(65);
if (bitCount < 64) {
val &= ((1L << bitCount) - 1);
}
buff.writeNumber(val, bitCount);
}
buff.seek(0);
r = new Random(1);
//assertEquals(-1L, buff.readNumber(64));
assertEquals(0, buff.readNumber(64));
for (int i = 0; i < 1000; i++) {
long val = r.nextLong();
int bitCount = r.nextInt(65);
if (bitCount < 64) {
val &= ((1L << bitCount) - 1);
}
long x = buff.readNumber(bitCount);
assertEquals(val, x);
}
}
@Test
public void testEliasDeltaCoding() {
assertEquals("1", getEliasDelta(1));
assertEquals("0100", getEliasDelta(2));
assertEquals("0101", getEliasDelta(3));
assertEquals("01100", getEliasDelta(4));
assertEquals("01111", getEliasDelta(7));
for (int i = 1; i < 100; i++) {
getEliasDelta(i);
}
for (int i = 10; i < 1000000000; i *= 1.1) {
getEliasDelta(i);
}
}
static String getEliasDelta(int value) {
BitBuffer buff = new BitBuffer(8 * 1024 * 1024);
buff.writeEliasDelta(value);
assertEquals(buff.position(), BitBuffer.getEliasDeltaSize(value));
int size = buff.position();
buff.seek(0);
long test = buff.readEliasDelta();
assertEquals(value, test);
assertEquals(size, buff.position());
buff.seek(0);
StringBuilder b = new StringBuilder();
for (int i = 0; i < size; i++) {
b.append((char) ('0' + buff.readBit()));
}
String s = b.toString();
return s;
}
@Test
public void testWriteBuffer() {
BitBuffer buff = new BitBuffer(8000);
for (int i = 1; i < 100; i++) {
BitBuffer b = new BitBuffer(160);
b.writeEliasDelta(i);
assertEquals(b.position(), BitBuffer.getEliasDeltaSize(i));
buff.write(b);
}
buff.seek(0);
for (int i = 1; i < 100; i++) {
assertEquals(i, buff.readEliasDelta());
}
}
@Test
public void testWriteBuffer2() {
BitBuffer buff = new BitBuffer(8000);
for (int i = 1; i < 100; i++) {
BitBuffer b = new BitBuffer(100);
// b.writeEliasDelta(i);
// assertEquals(b.position(), BitBuffer.getEliasDeltaSize(i));
for (int j = 0; j < i; j++) {
b.writeBit(1);
}
b.writeBit(0);
buff.write(b);
}
buff.seek(0);
for (int i = 1; i < 100; i++) {
// if (i != buff.readEliasDelta()) {
// System.out.println("??");
// }
// assertEquals(i, buff.readEliasDelta());
for (int j = 0; j < i; j++) {
if (1 != buff.readBit()) {
System.out.println("??");
}
// assertEquals(1, buff.readBit());
}
assertEquals(0, buff.readBit());
}
}
@Test
public void testSeek() {
BitBuffer buff = new BitBuffer(8000);
for (int i = 0; i < 100; i++) {
buff.seek(10 * i);
buff.writeNumber(i, 8);
}
buff = new BitBuffer(buff.toByteArray());
for (int i = 0; i < 100; i++) {
buff.seek(10 * i);
assertEquals(i, buff.readNumber(8));
}
}
@Test
public void testFoldUnfold() {
assertEquals(0, BitBuffer.foldSigned(0));
assertEquals(1, BitBuffer.foldSigned(1));
assertEquals(2, BitBuffer.foldSigned(-1));
testFoldUnfold(0);
testFoldUnfold(1);
testFoldUnfold(-1);
testFoldUnfold(2);
testFoldUnfold(-2);
testFoldUnfold(Long.MAX_VALUE / 2);
testFoldUnfold(Long.MIN_VALUE / 2 + 1);
Random r = new Random(1);
for (int i = 0; i < 1000; i++) {
long x = r.nextLong() & 0xfffffffL;
testFoldUnfold(x);
testFoldUnfold(-x);
}
}
private static void testFoldUnfold(long x) {
assertEquals(x, BitBuffer.unfoldSigned(BitBuffer.foldSigned(x)));
}
@Test
public void testGolombRice() {
Random r = new Random(1);
for (int i = 0; i < 1000; i++) {
BitBuffer buff = new BitBuffer(8 * 1024 * 1024);
int shift = r.nextInt(8);
int val = r.nextInt(100000);
buff.writeGolombRice(shift, val);
buff.writeGolombRice(1, 10);
int len = buff.position();
assertEquals(len, BitBuffer.getGolombRiceSize(shift, val) +
BitBuffer.getGolombRiceSize(1, 10));
buff = new BitBuffer(buff.toByteArray());
int p = buff.position();
assertEquals(val, buff.readGolombRice(shift));
assertEquals(val, buff.readGolombRice(p, shift));
p = buff.position();
assertEquals(10, buff.readGolombRice(1));
assertEquals(10, buff.readGolombRice(p, 1));
}
}
public static void printPositiveMapping() {
StringBuilder b1 = new StringBuilder();
StringBuilder b2 = new StringBuilder();
b1.append(0);
b2.append(1);
for (int i = 1; i <= 3; i++) {
b1.append(", ").append(i);
b1.append(", ").append(-i);
b2.append(", ").append(BitBuffer.foldSigned(i) + 1);
b2.append(", ").append(BitBuffer.foldSigned(-i) + 1);
}
System.out.println("(" + b1 + ", ...) is mapped to (" + b2 + ", ...)");
}
}
================================================
FILE: src/test/java/org/minperf/FunctionInfo.java
================================================
package org.minperf;
/**
* The information (time and space usage) of a minimum perfect hash function.
*/
public class FunctionInfo {
int size;
int split;
int firstPartSize;
int leafSize;
int averageBucketSize;
public double bitsPerKey;
public double generateNanos;
double evaluateNanos;
public long hashCalls;
@Override
public String toString() {
String s = "size " + size +
" leafSize " + leafSize +
" bits/key " + bitsPerKey +
" generate " + generateNanos +
" evaluate " + evaluateNanos;
if (averageBucketSize > 0) {
s += " averageBucketSize " + averageBucketSize;
}
if (split != 0) {
s += " split " +
(split > 0 ? split : (-split + ":" + (size + split)));
}
return s;
}
@Override
public int hashCode() {
return leafSize ^ averageBucketSize ^ (int) Double.doubleToLongBits(bitsPerKey);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof FunctionInfo)) {
return false;
}
FunctionInfo other = (FunctionInfo) o;
if (bitsPerKey != other.bitsPerKey) {
return false;
}
if (leafSize != other.leafSize) {
return false;
}
if (averageBucketSize != other.averageBucketSize) {
return false;
}
return true;
}
}
================================================
FILE: src/test/java/org/minperf/Graphics.java
================================================
package org.minperf;
import java.util.HashMap;
import java.util.HashSet;
import org.minperf.generator.Generator;
import org.minperf.monotoneList.MonotoneList;
import org.minperf.universal.LongHash;
import org.minperf.universal.UniversalHash;
/**
* A tool to generate Tikz graphics and a textual description of a hash function.
*/
public class Graphics {
public static void main(String... args) {
generateSplitTrees();
// generateSampleTikz();
}
public static void generateSplitTrees() {
int leafSize = 8;
int columns = 5;
System.out.print("\\begin{tabular}{");
for (int i = 0; i < columns; i++) {
System.out.print("|c");
}
System.out.println("|}");
HashMap cache = new HashMap<>();
for (int size = 0; size < 30; size++) {
if (size % columns == 0) {
System.out.println("\\hline");
} else {
System.out.println("&");
}
System.out.println(generateSplitTree(leafSize, size));
if (size % columns == columns - 1) {
System.out.println("\\\\");
for (int i = 0; i < columns; i++) {
if (i > 0) {
System.out.print(" & ");
}
int s = (size - columns + 1 + i);
System.out.print(s + " entries");
}
System.out.println("\\\\");
int averageBucketSize = 1024;
Settings settings = new Settings(leafSize, averageBucketSize);
for (int i = 0; i < columns; i++) {
if (i > 0) {
System.out.print(" & ");
}
int s = (size - columns + 1 + i);
double bits = SpaceEstimator.getExpectedBucketSpace(settings, s, 0, cache);
if (s > 0) {
bits /= s;
}
System.out.printf("%2.2f bits/key", bits);
}
System.out.println("\\\\");
}
}
}
public static String generateSplitTree(int leafSize, int size) {
if (size < 1) {
return "";
}
int averageBucketSize = 1024;
Settings settings = new Settings(leafSize, averageBucketSize);
StringBuilder buff = new StringBuilder();
buff.append("% size " + size + "\n");
buff.append("\\begin{tikzpicture}\n");
buff.append("\\node {} child[grow cyclic, rotate=-90, sibling angle=30, " + getSizeTikz(size)
+ ", level distance=7mm] {\n");
buff.append(generateSampleTikz(settings, size) + " }; \n");
buff.append("\\end{tikzpicture}");
return buff.toString();
}
public static void generateSampleTikz() {
StringBuilder bits = new StringBuilder();
System.out.println("4.4 Data Format");
int leafSize = 6;
int averageBucketSize = 32;
int size = 70;
HashSet set = RandomizedTest.createSet(size, 6);
UniversalHash hash = new LongHash();
Settings settings = new Settings(leafSize, averageBucketSize);
boolean eliasFano = true;
BitBuffer buff = RecSplitBuilder.newInstance(hash).
eliasFanoMonotoneLists(eliasFano).
leafSize(leafSize).averageBucketSize(averageBucketSize).generate(set);
buff.seek(0);
System.out.println("\\begin{tikzpicture}");
System.out.println("\\node {}");
System.out.println("child[line width=1ex, level distance=6mm] {");
System.out.println("child[edge from parent=draw, line width=.1ex, sibling distance=30mm, level distance=0mm] {");
bits.append(" & Header \\\\\n");
long size2 = buff.readEliasDelta() - 1;
appendLastBits(bits, buff, buff.position());
bits.append(" & size: " + size2 + " (Elias Delta code, plus 1)\\\\\n");
boolean alternativeHashOption = buff.readBit() != 0;
appendLastBits(bits, buff, 1);
bits.append(" & alternativeHash: " + alternativeHashOption + " (0 false, 1 true)\\\\\n");
int bucketCount = (size + (averageBucketSize - 1)) / averageBucketSize;
int start = buff.position();
int minOffsetDiff = (int) (buff.readEliasDelta() - 1);
MonotoneList offsetList = MonotoneList.load(buff, eliasFano);
appendLastBits(bits, buff, buff.position() - start);
bits.append(" & offset list (an EliasFano monotone list)\\\\\n");
start = buff.position();
int minStartDiff = (int) (buff.readEliasDelta() - 1);
MonotoneList startList = MonotoneList.load(buff, eliasFano);
appendLastBits(bits, buff, buff.position() - start);
bits.append(" & start list (an EliasFano monotone list)\\\\\n");
int startBuckets = buff.position();
for (int x = 0; x < bucketCount; x++) {
int offset = 0;
long offsetPair = offsetList.getPair(x);
int o = (int) (offsetPair >>> 32) + x * minOffsetDiff;
offset += o;
int offsetNext = ((int) offsetPair) + (x + 1) * minOffsetDiff;
int bucketSize = offsetNext - o;
int startPos = startBuckets +
Generator.getMinBitCount(offset) +
startList.get(x) + x * minStartDiff;
System.out.println(" child["+getSizeTikz(bucketSize)+"] {child[level distance=8mm]{node {$b_" + x + "$}");
System.out.println(" child[grow cyclic, rotate=-90, sibling angle=30, "+
getSizeTikz(bucketSize)+"] {");
buff.seek(startPos);
bits.append("\\hline\n");
bits.append(" & Bucket " + x + " \\\\\n");
generateBitDescription(settings, buff, bits, bucketSize);
String t = generateSampleTikz(settings, bucketSize);
System.out.println(" " + t);
System.out.println(" }}}");
}
System.out.println(";}};");
System.out.println("\\end{tikzpicture}");
System.out.println(bits.toString());
}
private static String generateSampleTikz(Settings settings, int size) {
String t = generateSampleTikzWithX(settings, size);
for (int i = 0;; i++) {
if (t.indexOf("$x$") < 0) {
break;
}
t = t.replaceFirst("\\$x\\$", "\\$_{" + (char) ('a' + i) + "}\\$");
}
return t;
}
private static String generateSampleTikzWithX(Settings settings, int size) {
if (size == 0) {
return "node {}";
} else if (size == 1) {
return "node {} child[sibling angle=5, level distance=5mm, " +
getSizeTikz(1) + "]";
}
if (size <= settings.getLeafSize()) {
StringBuilder buff = new StringBuilder();
buff.append("node {$x$} child[sibling angle=5, level distance=5mm, "+
getSizeTikz(1)+"] foreach \\x in {");
for (int i = 0; i < size; i++) {
if (i > 0) {
buff.append(", ");
}
buff.append(i);
}
buff.append("} ");
return buff.toString();
}
int split = settings.getSplit(size);
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
int childSize = firstPart;
StringBuilder buff = new StringBuilder();
buff.append("node {$x$} ");
int angle = 30;
if (size / split <= settings.getLeafSize()) {
angle = 15;
}
for (int i = 0; i < split; i++) {
buff.append("child[sibling angle=" + angle + ", "+getSizeTikz(size)+"] { ");
buff.append(generateSampleTikzWithX(settings, childSize));
buff.append("} ");
childSize = otherPart;
}
return buff.toString();
}
private static String getSizeTikz(int size) {
if (size == 1) {
return "line width=0.02em";
}
return "line width="+(size/35.)+"ex";
}
private static void generateBitDescription(Settings settings, BitBuffer in, StringBuilder bits, int size) {
if (size <= 1) {
return;
}
if (size <= settings.getLeafSize()) {
int shift = settings.getGolombRiceShift(size);
long x = in.readGolombRice(shift);
int count = BitBuffer.getGolombRiceSize(shift, x);
appendLastBits(bits, in, count);
bits.append(" & index: " + x + " (leaf of size " + size + ", k=" + shift +") \\\\\n");
return;
}
int shift = settings.getGolombRiceShift(size);
long x = in.readGolombRice(shift);
int count = BitBuffer.getGolombRiceSize(shift, x);
appendLastBits(bits, in, count);
bits.append(" & index: " + x + " (inner node of size " + size +
", k=" + shift +") \\\\\n");
int split = settings.getSplit(size);
int firstPart, otherPart;
if (split < 0) {
firstPart = -split;
otherPart = size - firstPart;
split = 2;
} else {
firstPart = size / split;
otherPart = firstPart;
}
int childSize = firstPart;
for (int i = 0; i < split; i++) {
generateBitDescription(settings, in, bits, childSize);
childSize = otherPart;
}
}
private static void appendLastBits(StringBuilder bits, BitBuffer in,
int count) {
in.seek(in.position() - count);
int i = 0;
if (count > 15) {
for (; i < 5; i++) {
long x = in.readBit();
bits.append((char) ('0' + x));
}
bits.append("...");
for (; i < count - 5; i++) {
in.readBit();
}
}
for (; i < count; i++) {
long x = in.readBit();
bits.append((char) ('0' + x));
}
}
}
================================================
FILE: src/test/java/org/minperf/LargeSetTest.java
================================================
package org.minperf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.BitSet;
import java.util.Random;
import java.util.TreeSet;
import org.junit.Assert;
import org.junit.Test;
import org.minperf.universal.LongHash;
import org.minperf.utils.LargeLongList;
import org.minperf.utils.LongSet;
/**
* Tests with large sets.
*/
public class LargeSetTest {
public static final int MAX_CHUNK_SIZE = 100_000_000;
public static void main(String... args) {
test(true);
test(false);
}
private static void test(boolean eliasFano) {
System.out.println(eliasFano ? "EliasFano" : "Fast");
int leafSize = 8;
// int averageBucketSize = 128;
// int averageBucketSize = 4096;
int averageBucketSize = 1024;
System.out.println("leafSize " + leafSize + ", averageBucketSize " + averageBucketSize +
", calcualted " +
SpaceEstimator.getExpectedSpace(leafSize, averageBucketSize) + " bits/key");
for (long len = 1_000; len <= 1_000_000_000; len *= 10) {
LongSet set = createSet((int) len, 1);
LargeLongList list = LargeLongList.create(set);
set = null;
LongHash hash = new LongHash();
long time = System.nanoTime();
BitBuffer buff = RecSplitBuilder.
newInstance(hash).
leafSize(leafSize).averageBucketSize(averageBucketSize).
eliasFanoMonotoneLists(eliasFano).
maxChunkSize(MAX_CHUNK_SIZE).
generate(list);
time = System.nanoTime() - time;
int bitCount = buff.position();
buff.seek(0);
double bitsPerKEy = (double) bitCount / len;
System.out.println(" (" + len + ", " + bitsPerKEy + ")");
System.out.println("...generated " + (double) time / len + " ns/key");
RecSplitEvaluator eval = RecSplitBuilder.
newInstance(hash).
leafSize(leafSize).averageBucketSize(averageBucketSize).
eliasFanoMonotoneLists(eliasFano).
buildEvaluator(buff);
BitSet known = new BitSet();
int i = 0;
for (long x : list) {
int index = eval.evaluate(x);
if (index > len || index < 0) {
Assert.fail("wrong entry: " + x + " " + index);
}
if (known.get(index)) {
eval.evaluate(x);
Assert.fail("duplicate entry: " + x + " " + index);
}
known.set(index);
if ((i++ & 0xffffff) == 0xffffff) {
System.out.println("...evaluated " + i);
}
}
list.dispose();
list = null;
}
}
public static LongSet createSet(int size, int seed) {
Random r = new Random(seed);
LongSet set = new LongSet(size);
long i = 0;
while (set.size() < size) {
set.add(r.nextLong());
if ((i++ & 0xffffff) == 0xffffff) {
System.out.println("...createSet size " + set.size() + " of " + size);
}
}
return set;
}
@Test
public void randomSet() {
for (int i = 0; i < 100; i++) {
Random r = new Random(i);
LongSet set = new LongSet(10);
TreeSet s2 = new TreeSet();
while (set.size() < 10) {
long x = r.nextInt(100);
set.add(x);
s2.add(x);
assertEquals(s2.size(), set.size());
assertEquals(s2.toString(), toString(set));
}
}
}
@Test
public void smallSet() {
LongSet set = new LongSet(10);
assertEquals("[]", toString(set));
assertTrue(set.isEmpty());
assertEquals(0, set.size());
assertTrue(set.add(0L));
assertFalse(set.isEmpty());
assertEquals("[0]", toString(set));
assertEquals(1, set.size());
assertFalse(set.add(0L));
assertEquals("[0]", toString(set));
assertEquals(1, set.size());
assertTrue(set.add(1L));
assertEquals("[0, 1]", toString(set));
assertEquals(2, set.size());
assertFalse(set.add(1L));
assertEquals(2, set.size());
for (int i = 2; i < 10; i++) {
assertTrue(set.add(i * 10L));
assertEquals(i + 1, set.size());
}
assertEquals("[0, 1, 20, 30, 40, 50, 60, 70, 80, 90]", toString(set));
}
private static String toString(LongSet set) {
TreeSet s2 = new TreeSet();
for (long x : set) {
s2.add(x);
}
return s2.toString();
}
}
================================================
FILE: src/test/java/org/minperf/Paper.java
================================================
package org.minperf;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
/**
* A helper class to produce data of the RecSplit paper.
*/
public class Paper {
public static void main(String... args) {
// -mx4g, Java 8: minGen 9982.65602 minEval 277.78663
// -mx8g, Java 7: minGen 10098.0 minEval 283.86
double minGen = Double.POSITIVE_INFINITY, minEval = Double.POSITIVE_INFINITY;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FunctionInfo info = RandomizedTest.test(10, 256, 100000, true, 3, true);
minGen = Math.min(minGen, info.generateNanos);
minEval = Math.min(minEval, info.evaluateNanos);
System.out.println(info);
}
System.out.println("minGen " + minGen + " minEval " + minEval);
// System.out.println(SpaceEstimator.getExpectedSpace(18, 1024));
// System.out.println(SpaceEstimator.getExpectedSpace(10, 1024));
WikipediaTest.main();
RandomizedTest.printEvaluationAndGenerationTimeVersusSpace();
LargeSetTest.main();
RandomizedTest.experimentalResults();
RandomizedTest.printEvaluationAndGenerationTimeVersusSpace();
LargeSetTest.main();
WikipediaTest.main();
RandomizedTest.experimentalResults();
// TODO improve simple monotone list
// B Generation Time Versus Space
// RandomizedTest.printEvaluationAndGenerationTimeVersusSpace();
// RandomizedTest.printTimeVersusSpace();
BitCodes.verifyRiceParameterFormula();
// RandomizedTest.printTimeVersusSpace();
// RandomizedTest.printGenerationTimeVersusSpace();
// does not always work (performance depends on the hardware):
// 4.1 Parameters
RandomizedTest.verifyParameters();
simpleTest();
// 4.3 Split Rule
SettingsTest.printSplitRule();
SettingsTest.printSplitRulesList();
// 4.4 Data Format
BitCodes.printPositiveMapping();
Graphics.generateSampleTikz();
// 4.7 Probabilities
Probability.simulateKeyInOverflow();
Probability.veryLargeBucketProbability();
Probability.asymmetricCase();
// 4.8 Rice
BitCodes.printRiceExamples();
BitCodes.printEliasDeltaExample();
// 4.9 Space Usage and Generation Time
SpaceEstimator.spaceUsageEstimateSmallSet();
SpaceEstimator.spaceUsageEstimate();
// 5.2 Time and Space Complexity of Evaluation
SpaceEstimator.listMaxRecursionDepth();
// 6.1 Reasonable Parameter Values
RandomizedTest.reasonableParameterValues();
// 6.2 Using Real-World Data
WikipediaTest.main();
// A Evaluation Time
SpaceEstimator.listEvalulationTimes();
RandomizedTest.printTimeVersusSpace();
// B Generation Time Versus Space
RandomizedTest.printGenerationTimeVersusSpace();
RandomizedTest.printEvaluationAndGenerationTimeVersusSpace();
// slow:
LargeSetTest.main();
RandomizedTest.verifyParametersBestSize();
// 6 Experimental Results
RandomizedTest.experimentalResults();
for (int averageBucketSize = 64; averageBucketSize < 1024; averageBucketSize *= 2) {
SpaceEstimator.getExpectedSpace(8, averageBucketSize);
}
supplementalHashPerfTest();
}
private static void simpleTest() {
for (int i = 8; i < 1000; i *= 2) {
RandomizedTest.test(2, i, i, true);
}
for (int i = 100; i < 10000; i *= 2) {
RandomizedTest.test(6, 20, i, true);
}
}
private static void supplementalHashPerfTest() {
final AtomicLong count = new AtomicLong();
final AtomicLong dummy = new AtomicLong();
for (int i = 0; i < 8; i++) {
new Thread() {
@Override
public void run() {
Random r = new Random();
long x = r.nextLong();
int sum = 0;
while (count.get() >= 0) {
x += r.nextLong();
for (int i = 0; i < 1000; i++) {
int h = Settings.supplementalHash(x, i);
h = Settings.reduce(h, 30);
sum += h;
}
count.incrementAndGet();
}
dummy.set(sum);
}
}.start();
}
try {
long c0 = count.get();
Thread.sleep(1000);
long c2 = count.get();
count.set(-11111111);
System.out.println("count: " + c2 + " " + c0);
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
================================================
FILE: src/test/java/org/minperf/PerformanceTest.java
================================================
package org.minperf;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Random;
import org.minperf.universal.LongHash;
import org.minperf.universal.UniversalHash;
/**
* A simple micro-benchmark.
*/
public class PerformanceTest {
private int size = 100_000;
// CHD: 2.25 bits/key, 182 nanoseconds/key
// GOV: 2.32 bits/key, 132 nanoseconds/key
// RecSplit with FastLongHash:
// 1.97 bits/key, 163 nanoseconds/key evaluation time
private int leafSize = 11;
private int averageBucketSize = 55;
// RecSplit with FastLongHash:
// 2.32 bits/key, 138 nanoseconds/key evaluation time
// private int leafSize = 12;
// private int averageBucketSize = 26;
private int repeat = 100;
public static void main(String... args) {
new PerformanceTest().execute(args);
}
private void execute(String... args) {
for (int i = 0; i < args.length; i++) {
if ("-size".equals(args[i])) {
size = Integer.parseInt(args[++i]);
} else if ("-leafSize".equals(args[i])) {
leafSize = Integer.parseInt(args[++i]);
} else if ("-averageBucketSize".equals(args[i])) {
averageBucketSize = Integer.parseInt(args[++i]);
} else if ("-repeat".equals(args[i])) {
repeat = Integer.parseInt(args[++i]);
} else {
printUsage();
}
}
System.out.println("Settings: leafSize=" + leafSize +
", averageBucketSize=" + averageBucketSize +
", size=" + size);
for (int i = 0; i < 5; i++) {
runMicroBenchmark(false);
}
for (int i = 0; i < 5; i++) {
runMicroBenchmark(true);
}
}
void printUsage() {
System.out.println("Usage: java " + getClass().getName() + " [options]");
System.out.println("Options:");
System.out.println("-size the number of randomly generated numbers, default " + size);
System.out.println("-leafSize leafSize parameter, default " + leafSize);
System.out.println("-averageBucketSize averageBucketSize parameter, default " + averageBucketSize);
System.out.println("-repeat repeat count for the evalution benchmark loop, 0 to just verify; default " + repeat);
}
void runMicroBenchmark(boolean fastHash) {
System.out.println();
HashSet set = createSet(size, 1);
ArrayList list = new ArrayList(set);
UniversalHash hash;
if (fastHash) {
hash = new FastLongHash();
} else {
hash = new LongHash();
}
long start = System.nanoTime();
byte[] data = RecSplitBuilder.newInstance(hash).
leafSize(leafSize).averageBucketSize(averageBucketSize).
generate(set).toByteArray();
long time = System.nanoTime() - start;
int bits = data.length * 8;
System.out.printf("Generated in %.2f seconds at %.2f bits/key, using %s\n",
time / 1_000_000_000., (double) bits / size,
hash);
CountingHash count = new CountingHash(hash);
RecSplitEvaluator eval = RecSplitBuilder.
newInstance(count).
leafSize(leafSize).averageBucketSize(averageBucketSize).
buildEvaluator(new BitBuffer(data));
BitSet bitSet = new BitSet();
for (Long x : set) {
int y = eval.evaluate(x);
if (y < 0 || y >= size) {
throw new AssertionError("y=" + y + " of " + size);
}
if (bitSet.get(y)) {
throw new AssertionError();
}
bitSet.set(y);
}
for (int i = 0; i < 10; i++) {
System.gc();
}
if (repeat > 0) {
eval = RecSplitBuilder.
newInstance(hash).
leafSize(leafSize).averageBucketSize(averageBucketSize).
buildEvaluator(new BitBuffer(data));
start = System.nanoTime();
for (int i = 0; i < repeat; i++) {
for (int j = 0; j < size; j++) {
Long x = list.get(j);
int y = eval.evaluate(x);
if (y < 0 || y >= size) {
throw new AssertionError("y=" + y + " of " + size);
}
}
}
time = System.nanoTime() - start;
System.out.printf("Evaluation time: %d nanoseconds/key, " +
"universalHash: %f calls/key \n",
(int) (((double) time / repeat / size)),
(double) count.getCount() / size);
}
}
public static HashSet createSet(int size, int seed) {
Random r = new Random(seed);
HashSet set = new HashSet(size);
while (set.size() < size) {
set.add(r.nextLong());
}
return set;
}
/**
* A fast long hash implementation. It is not recommended to use this in the
* real world, it is just used to test the effect of using a faster hash
* function.
*/
static class FastLongHash implements UniversalHash {
@Override
public long universalHash(Long key, long index) {
return Long.rotateLeft(key, (int) index) ^ (key >>> 16);
}
@Override
public String toString() {
return "FastLongHash (rotate&xor)";
}
}
/**
* A fast long hash implementation. It is not recommended to use this in the
* real world, it is just used to test the effect of using a faster hash
* function.
*/
static class CountingHash implements UniversalHash {
private final UniversalHash base;
private long count;
CountingHash(UniversalHash base) {
this.base = base;
}
long getCount() {
return count;
}
@Override
public long universalHash(K key, long index) {
count++;
return base.universalHash(key, index);
}
@Override
public String toString() {
return "MeasuredHash " + base;
}
}
}
================================================
FILE: src/test/java/org/minperf/Probability.java
================================================
package org.minperf;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Random;
import org.minperf.utils.PoissonDistribution;
/**
* Probability methods.
*/
public class Probability {
private static final HashMap FACTORIALS = new HashMap();
private static final HashMap PROBABILITY_CACHE = new HashMap();
public static void veryLargeBucketProbability() {
for (int averageBucketSize = 8; averageBucketSize < 16 * 1024; averageBucketSize *= 2) {
for (int multiple = 2; multiple <= 20; multiple *= 10) {
double p = probabilityLargeBucket(averageBucketSize, multiple * averageBucketSize);
double p2 = probabilityLargeBucket2(averageBucketSize, multiple * averageBucketSize);
double simulated = Double.NaN;
if (p > 0.000001) {
simulated = simulateProbabilityBucketLargerOrEqualTo(averageBucketSize, multiple * averageBucketSize);
}
System.out.println("averageBucketSize " + averageBucketSize +
" p[bucketSize >= " + multiple * averageBucketSize + "] ~ " +
p2 + "; <= " + p + "; simulated " + simulated);
}
}
}
public static double probabilityLargeBucket2(int averageBucketSize, int atLeast) {
double p = 1.0;
if (averageBucketSize > 128) {
return Double.NaN;
}
for (int size = 0; size < atLeast; size++) {
p -= getProbabilityOfBucketSize(averageBucketSize, size);
}
return p;
}
public static void simulateKeyInOverflow() {
int size = 1000000;
int averageBucketSize = 3;
int maxLoad = 5;
System.out.println("size " + size);
// calculated
double pBalls = 0;
double pTooLarge = 1;
for (int i = 0; i <= maxLoad; i++) {
double p = getProbabilityOfBucketSize(averageBucketSize, i);
System.out.println("bucket size " + i + ": p=" + p);
pBalls += i * p;
pTooLarge -= p;
}
System.out.println("average expected number of balls in regular buckets: " + pBalls);
System.out.println("probability of bucket too large: " + pTooLarge);
System.out.println("probability of ball in overflow: " + (1. - (pBalls / averageBucketSize)));
// simulated
Random r = new Random();
int buckets = size / averageBucketSize;
int[] counts = new int[buckets];
for (int i = 0; i < size; i++) {
counts[r.nextInt(buckets)]++;
}
int ballsInOverflow = 0;
int bucketsOverflow = 0;
int totalInRegularBuckets = 0;
for (int i = 0; i < buckets; i++) {
int c = counts[i];
if (c > maxLoad) {
bucketsOverflow++;
ballsInOverflow += c;
counts[i] = 0;
} else {
totalInRegularBuckets += c;
}
}
System.out.println("simulated balls in overflow: " + ballsInOverflow);
System.out.println("simulated balls in regular buckets: " + totalInRegularBuckets);
System.out.println("simulated average expected number of balls in regular buckets: " + (double) totalInRegularBuckets / buckets);
System.out.println("simulated probability of bucket too large: " + (double) bucketsOverflow / buckets);
System.out.println("simulated probability of ball in overflow: " + (double) ballsInOverflow / size);
}
private static double simulateProbabilityBucketLargerOrEqualTo(int lambda, int x) {
int count = 100000000;
Random r = new Random(x);
int larger = 0;
int testCount = count / 1000;
int loop = count / testCount;
int bucketCount = loop / lambda;
for (int j = 0; j < testCount; j++) {
int c = 0;
for (int i = 0; i < loop; i++) {
if (r.nextInt(bucketCount) == 0) {
c++;
}
}
if (c >= x) {
larger++;
}
}
return (double) larger / testCount;
}
public static double probabilityLargeBucket(int lambda, int x) {
// Poisson distribution, tail probability
return Math.exp(-lambda) * Math.pow(Math.E * lambda, x) / Math.pow(x, x);
}
public static double getProbabilityOfBucketSize(int averageBucketSize, int bucketSize) {
int a = averageBucketSize;
int x = bucketSize;
return PoissonDistribution.probability(a, x);
}
public static double getProbabilityOfBucketFallsIntoBinOfSize(int averageBucketSize, int bucketSize) {
int a = averageBucketSize;
int x = bucketSize;
double average = bucketSize * PoissonDistribution.probability(a, x);
return average / averageBucketSize;
}
public static void asymmetricCase() {
System.out.println("4.7 Probabilities");
System.out.println("Asymmetric Split");
int size = 64, step = 2;
for (int i = 0; i <= size; i += step) {
double n = size, k = i;
double p = calcCombinations((int) n, (int) k) * Math.pow(k / n, k) *
Math.pow(1 - (k / n), n - k);
System.out.println(" (" + i + ", " + p + ")");
}
}
public static void asymmetricSplitProbability() {
Random r = new Random(1);
for (int size = 20; size < 1000000; size *= 10) {
for (int i = 1; i < size / 2; i += Math.max(1, size / 20)) {
System.out.println("size " + size + " first " + i + " p approx " +
simulateAsymmetricSplitProbability(size, i, r) + " calc " + calcAsymmetricSplitProbability(size, i));
}
}
}
public static double calcExactAsymmetricSplitProbability(int size, int firstSet) {
double p;
if (size <= 143) {
p = Probability.calcAsymmetricSplitProbability(size, firstSet);
if (p == 0 || p == 1 || Double.isNaN(p)) {
System.out.println("fail at " + size + " split " + firstSet);
}
} else {
p = 0;
}
if (p == 0 || p == 1 || Double.isNaN(p)) {
p = Probability.calcApproxAsymmetricSplitProbability(size, firstSet);
}
return p;
}
private static double calcApproxAsymmetricSplitProbability(int size, int firstSet) {
// http://math.stackexchange.com/questions/64716/approximating-the-logarithm-of-the-binomial-coefficient
int n = size;
int k = firstSet;
double logComb = (n + .5) * Math.log(n) - (k + .5) * Math.log(k) -
(n - k + .5) * Math.log(n - k) - .5 * Math.log(2 * Math.PI);
return Math.exp(logComb + Math.log(k) * k - Math.log(n) * n + Math.log(n - k) * (n - k));
}
private static double calcAsymmetricSplitProbability(int size, int firstSet) {
// http://math.stackexchange.com/questions/951236/probability-of-exactly-2-low-rolls-in-5-throws-of-a-die
// (n k) p^k q^(n-k)
// p: probability of the event (prob of r.nextInt(size) < firstSet)
// q=1−p
// n: number of trials (size)
// k: the number of times the event occurs during those n trials (firstSet)
// Here, the probability that the outcome of a roll is less than 33 is 1/3
int n = size;
int k = firstSet;
// double p = (double) firstSet / size;
// double q = 1 - p;
// (n k) = (n!) / ((k! * (n-k)!))
// ((n!) / (k! * (n-k)!)) * ((k/n)^k) * ((1-(k/n))^(n-k))
// (k^k)*(n^-n)*n!*(n-k)^(n-k) / (k!*(n-k)!)
// return calcCombinations(n, k) * Math.pow(p, k) * Math.pow(q, n - k);
// (k/n)^k * (1-(k/n))^(n - k) = (k^k) / (n^n) * (n-k)^(n-k)
return calcCombinations(n, k) * Math.pow(k, k) / Math.pow(n, n) *
Math.pow(n - k, n - k);
}
private static double simulateAsymmetricSplitProbability(int size, int firstSet, Random r) {
double good = 0;
int trials = Math.max(1, 100000000 / size);
for (int j = 0; j < trials; j++) {
int count = 0;
boolean success = true;
for (int i = 0; i < size; i++) {
if (r.nextInt(size) < firstSet) {
count++;
if (count > firstSet) {
success = false;
break;
}
}
}
if (success) {
if (count == firstSet) {
good++;
}
}
}
return good / trials;
}
public static double calcCombinations(int n, int k) {
String key = "comb-" + n + "/" + k;
Double cached = PROBABILITY_CACHE.get(key);
if (cached != null) {
return cached;
}
BigInteger nf = factorial(n);
BigInteger kf = factorial(k);
BigInteger nmkf = factorial(n - k);
BigInteger u = kf.multiply(nmkf);
BigDecimal r = new BigDecimal(nf).divide(
new BigDecimal(u), 30, BigDecimal.ROUND_HALF_UP);
// System.out.println("nCk n=" + n + " k=" + k + " = " + r.doubleValue());
// approximation:
// log(n k) ~ (n log n) - (k log k) - (n-k) log(n-k)
double result = r.doubleValue();
PROBABILITY_CACHE.put(key, result);
return result;
}
public static double probabilitySplitIntoMSubsetsOfSizeN(int m, int n) {
String key = "split-" + m + "/" + n;
Double cached = PROBABILITY_CACHE.get(key);
if (cached != null) {
return cached;
}
BigInteger mm = BigInteger.valueOf(m);
BigInteger mnf = factorial(n * m);
BigInteger nf = factorial(n);
BigInteger u = nf.pow(m).multiply(mm.pow(m * n));
BigDecimal r = new BigDecimal(mnf).divide(
new BigDecimal(u), 100, BigDecimal.ROUND_HALF_UP);
double result = r.doubleValue();
PROBABILITY_CACHE.put(key, result);
return result;
}
static BigInteger factorial(long n) {
BigInteger f = FACTORIALS.get(n);
if (f == null) {
f = recursiveFactorial(1, n);
FACTORIALS.put(null, f);
}
return f;
}
private static BigInteger recursiveFactorial(long start, long n) {
long i;
if (n <= 16) {
BigInteger r = BigInteger.valueOf(start);
for (i = start + 1; i < start + n; i++) {
r = r.multiply(BigInteger.valueOf(i));
}
return r;
}
i = n / 2;
return recursiveFactorial(start, i).multiply(recursiveFactorial(start + i, n - i));
}
public static double probabilityOfDuplicates(long n, int bits) {
double x = Math.pow(2, bits);
double p = 1.0 - Math.pow(Math.E, -(double) n * n / 2 / x);
return p;
}
}
================================================
FILE: src/test/java/org/minperf/RandomizedTest.java
================================================
package org.minperf;
import static org.junit.Assert.assertTrue;
import java.lang.ref.WeakReference;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.minperf.universal.LongHash;
import org.minperf.universal.UniversalHash;
/**
* Methods to test the MPHF with random data.
*/
public class RandomizedTest {
private static final char[] HEX = "0123456789abcdef".toCharArray();
private static final int[] HEX_DECODE = new int['f' + 1];
static {
for (int i = 0; i < HEX_DECODE.length; i++) {
HEX_DECODE[i] = -1;
}
for (int i = 0; i <= 9; i++) {
HEX_DECODE[i + '0'] = i;
}
for (int i = 0; i <= 5; i++) {
HEX_DECODE[i + 'a'] = HEX_DECODE[i + 'A'] = i + 10;
}
}
public static void main(String... args) {
printLargeSet();
}
public static void printLargeSet() {
for (int i = 10; i <= 100_000_000; i *= 10) {
FunctionInfo info = RandomizedTest.test(8, 128, i, false);
System.out.println(info);
}
}
public static void printTimeVersusSpace() {
System.out.println("A Time Versus Space");
final double evaluateWeight = 20;
int size = 100000;
System.out.println("size: " + size);
ArrayList list = new ArrayList();
outer:
for (int leafSize = 2; leafSize <= 12; leafSize++) {
int minAverageBucketSize = 4;
for (int averageBucketSize = minAverageBucketSize; averageBucketSize <= 1024;) {
System.out.println("leafSize " + leafSize + " " + averageBucketSize);
FunctionInfo info = test(leafSize, averageBucketSize, size, true);
if (info.evaluateNanos >= 10000) {
if (averageBucketSize == minAverageBucketSize) {
// done
break outer;
}
// next leaf size
break;
}
if (info.bitsPerKey < 4.0) {
list.add(info);
}
if (averageBucketSize < 16) {
averageBucketSize += 2;
} else if (averageBucketSize < 32) {
averageBucketSize += 4;
} else {
averageBucketSize *= 2;
}
}
}
Collections.sort(list, new Comparator() {
@Override
public int compare(FunctionInfo o1, FunctionInfo o2) {
double time1 = o1.evaluateNanos * evaluateWeight + o1.generateNanos;
double time2 = o2.evaluateNanos * evaluateWeight + o2.generateNanos;
int comp = Double.compare(time1, time2);
if (comp == 0) {
comp = Double.compare(o1.bitsPerKey, o2.bitsPerKey);
}
return comp;
}
});
FunctionInfo last = null;
int minAverageBucketSize = Integer.MAX_VALUE, maxAverageBucketSize = 0;
int minLeafSize = Integer.MAX_VALUE, maxLeafSize = 0;
for (FunctionInfo info : list) {
if (last != null && info.bitsPerKey > last.bitsPerKey) {
continue;
}
System.out.println(" (" + info.bitsPerKey + ", " + info.evaluateNanos + ")");
minAverageBucketSize = Math.min(minAverageBucketSize, info.averageBucketSize);
maxAverageBucketSize = Math.max(maxAverageBucketSize, info.averageBucketSize);
minLeafSize = Math.min(minLeafSize, info.leafSize);
maxLeafSize = Math.max(maxLeafSize, info.leafSize);
last = info;
}
System.out.println("for averageBucketSize between " + minAverageBucketSize + " and " + maxAverageBucketSize);
System.out.println("and leafSize between " + minLeafSize + " and " + maxLeafSize);
last = null;
System.out.println("bits/key leafSize averageBucketSize evalTime genTime tableBitsPerKey");
for (FunctionInfo info : list) {
if (last != null && info.bitsPerKey > last.bitsPerKey) {
continue;
}
System.out.println(info.bitsPerKey + " " + info.leafSize + " " + info.averageBucketSize +
" " + info.evaluateNanos + " " + info.generateNanos);
last = info;
}
}
public static void printEvaluationTimeVersusSpaceMedium() {
System.out.println("A Evaluation Time Versus Space");
int size = 100000;
System.out.println("size: " + size);
ArrayList list = new ArrayList();
for (int i = 2; i < 22; i++) {
int leafSize = (int) Math.round(0.18 * i + 6.83);
int averageBucketSize = (int) Math.round(Math.pow(2, 0.3 * i + 2.79));
// FunctionInfo info =
test(leafSize, averageBucketSize, size / 10, true);
// System.out.println("leafSize " + leafSize + " " + averageBucketSize + " " +
// info.evaluateNanos + " " + info.generateNanos + " " + info.bitsPerKey);
}
for (int leafSize = 8; leafSize < 14; leafSize++) {
System.out.println("leafSize " + leafSize);
// int leafSize = (int) Math.round(0.18 * i + 6.83);
for (int averageBucketSize : new int[] { 4, 6, 8, 10, 12, 14, 16, 20, 24,
28, 32, 40, 48, 56, 64 }) {
// int averageBucketSize = (int) Math.round(Math.pow(2, 0.3 * i + 2.79));
test(leafSize, averageBucketSize, size, true);
FunctionInfo info = test(leafSize, averageBucketSize, size, true);
if (info.bitsPerKey < 2.4 && info.evaluateNanos < 250) {
System.out.println("leafSize " + leafSize + " averageBucketSize " + averageBucketSize +
" " + info.evaluateNanos + " " + info.generateNanos +
" " + info.bitsPerKey);
list.add(info);
break;
}
}
}
System.out.println("A Evaluation Time Versus Space");
for (FunctionInfo info : list) {
System.out.println(" (" + info.bitsPerKey + ", " + info.evaluateNanos + ")");
}
System.out.println("B Generation Time Versus Space");
for (FunctionInfo info : list) {
System.out.println(" (" + info.bitsPerKey + ", " + info.generateNanos + ")");
}
}
public static void printEvaluationAndGenerationTimeVersusSpace() {
System.out.println("A Evaluation Time Versus Space");
int size = 200000;
System.out.println("size: " + size);
ArrayList list = new ArrayList();
double[] data = {
// // WikipediaTest, IMPROVED_SPLIT_RULES 2, singlethreaded
5, 20, 2.359670168001244, 1079, 334,
6, 12, 2.4303717869483954, 951, 342,
6, 14, 2.357967341920603, 1155, 322,
6, 16, 2.3323145349758843, 998, 321,
6, 20, 2.2812246357299055, 1025, 334,
7, 16, 2.2096194929015978, 1242, 345,
7, 20, 2.1742915744950557, 1293, 314,
7, 24, 2.1007140296084508, 1355, 309,
8, 10, 2.377269897563485, 1694, 308,
8, 18, 2.131266063511737, 1593, 300,
8, 20, 2.11845541447963, 1650, 308,
8, 24, 2.0638098592566307, 1872, 305,
8, 64, 1.921307580838036, 2155, 363,
8, 96, 1.8674475931743013, 1985, 398,
8, 128, 1.8262873001942272, 2289, 428,
9, 12, 2.2458253510555526, 2827, 295,
9, 14, 2.21441342095181, 2695, 299,
9, 16, 2.1511489750305923, 2648, 299,
9, 18, 2.1036982168296405, 2627, 304,
9, 20, 2.0933374505834883, 2575, 302,
9, 24, 2.046982770533447, 2760, 311,
9, 28, 1.9954129667997726, 3132, 321,
9, 32, 1.9533855063391257, 3608, 305,
9, 64, 1.878018957237164, 3058, 337,
10, 32, 1.9282185286288644, 5108, 298,
10, 64, 1.8208755826407748, 8252, 332,
10, 192, 1.7124357505817613, 10393, 437,
11, 32, 1.909093715388833, 9766, 298,
11, 64, 1.7988263682605121, 17889, 313,
11, 256, 1.6815680892600802, 20773, 422,
12, 64, 1.7663794926201724, 48849, 298,
13, 128, 1.6847065892037447, 104284, 334,
13, 192, 1.657460294686805, 125301, 395,
14, 192, 1.647726743677378, 250957, 386,
14, 256, 1.6321486992942247, 264697, 445,
14, 512, 1.6139085584683803, 262655, 546,
// // WikipediaTest, IMPROVED_SPLIT_RULES = true, multithreaded gen
// 5, 20, 2.361259077360058, 754, 352,
// 6, 12, 2.415688110019585, 514, 331,
// 6, 14, 2.3353765518249885, 535, 323,
// 6, 16, 2.3029213276778484, 501, 321,
// 6, 20, 2.231098315752713, 481, 321,
// 7, 16, 2.2096194929015978, 527, 315,
// 7, 20, 2.174290497268372, 527, 316,
// 7, 24, 2.1007199543552124, 534, 321,
// 8, 10, 2.3725640327946853, 772, 312,
// 8, 18, 2.130093771572937, 612, 310,
// 8, 20, 2.1442086728126264, 622, 316,
// 8, 24, 2.063070343138105, 664, 310,
// 8, 64, 1.873041900650682, 768, 332,
// 8, 96, 1.822206496208785, 772, 357,
// 8, 128, 1.7964158042485214, 783, 379,
// 9, 12, 2.236310207756295, 903, 308,
// 9, 14, 2.1689636113162796, 900, 306,
// 9, 16, 2.142868602817803, 887, 307,
// 9, 18, 2.0976237355588925, 847, 309,
// 9, 20, 2.0890584368882004, 929, 316,
// 9, 24, 2.043965727898397, 777, 324,
// 9, 28, 1.9915222933240457, 821, 309,
// 9, 32, 1.9494118864087353, 912, 305,
// 9, 64, 1.8568808073248453, 1067, 329,
// 10, 32, 1.9271515355984201, 1319, 316,
// 10, 64, 1.821963042978214, 1889, 323,
// 10, 192, 1.7192844885315923, 2135, 392,
// 11, 32, 1.9121759302382613, 2252, 303,
// 11, 64, 1.7827549540561136, 5444, 311,
// 11, 256, 1.6774269605803371, 5891, 411,
// 12, 64, 1.7675248538918735, 9955, 327,
// 13, 128, 1.6836334021198676, 24108, 332,
// 13, 192, 1.6562855789879665, 24268, 365,
// 14, 192, 1.6426212278088357, 78389, 364,
// 14, 256, 1.6305463246018612, 80050, 425,
// 14, 512, 1.609989338485529, 82630, 482,
// 15, 256, 1.6175950974875, 155998, 403,
// 15, 512, 1.5984638208873647, 169226, 493,
// 15, 1024, 1.5884895097140768, 176353, 672,
// 16, 1024, 1.5794946669031629, 408296, 664,
// WikipediaTest, IMPROVED_SPLIT_RULES disabled
// 5, 20, 2.2934250358455595, 1257, 334,
// 6, 20, 2.2301333899505726, 1177, 338,
// 7, 16, 2.2056644551315054, 1459, 316,
// 7, 20, 2.1689277935290385, 1625, 325,
// 7, 24, 2.097395632808568, 1537, 322,
// 8, 10, 2.3722683340699433, 1990, 314,
// 8, 18, 2.127560134412306, 2131, 310,
// 8, 20, 2.146903893975849, 2270, 310,
// 8, 24, 2.0783823125303242, 2244, 315,
// 9, 12, 2.228793858569091, 3609, 302,
// 9, 14, 2.157263044381975, 3573, 304,
// 9, 16, 2.131986997469965, 3813, 307,
// 9, 18, 2.088727997602901, 3888, 305,
// 9, 20, 2.085344159281969, 4008, 304,
// 9, 24, 2.0510659982789283, 4119, 312,
// 9, 28, 2.006607237192625, 4283, 311,
// 9, 32, 1.9651353563942207, 4473, 314,
// 9, 64, 1.8612538090483068, 5012, 335,
// 10, 32, 1.9459898065405232, 8674, 310,
// 10, 64, 1.7997964108894018, 14669, 317,
// 11, 32, 1.921768633858763, 19027, 302,
// 11, 64, 1.7817167768394646, 26900, 318,
// 12, 64, 1.7734789550806909, 54813, 310,
// 13, 128, 1.6908858307695058, 179575, 338,
// 13, 192, 1.6529698752547937, 199952, 362,
// 14, 192, 1.6437121891329978, 402364, 372,
// 14, 256, 1.6302684001174041, 404552, 401,
// improved_split_simple
// 4, 20, 2.48048, 542.205, 187.983,
// 4, 24, 2.42928, 548.34, 207.861,
// 4, 28, 2.41148, 541.045, 220.402,
// 4, 32, 2.39106, 587.445, 243.149,
// 4, 64, 2.29868, 655.455, 327.285,
// 4, 96, 2.29236, 786.245, 413.026,
// 4, 128, 2.288445, 906.31, 521.701,
// 4, 192, 2.291665, 1071.705, 697.729,
// 4, 256, 2.338615, 1222.465, 896.842,
// 5, 12, 2.481445, 590.775, 169.932,
// 5, 14, 2.448975, 571.65, 180.65,
// 5, 16, 2.39643, 596.26, 181.333,
// 5, 18, 2.36181, 753.025, 186.659,
// 5, 20, 2.329635, 609.895, 199.902,
// 5, 24, 2.293775, 653.46, 209.456,
// 5, 28, 2.27104, 655.55, 214.243,
// 5, 32, 2.236775, 650.24, 233.336,
// 5, 64, 2.13028, 702.23, 298.263,
// 5, 96, 2.09587, 834.61, 369.641,
// 5, 128, 2.069325, 848.365, 441.676,
// 5, 192, 2.046835, 1037.25, 570.772,
// 5, 256, 2.040805, 1006.82, 677.424,
// 5, 512, 2.03622, 1288.425, 1194.245,
// 6, 12, 2.422205, 679.755, 157.864,
// 6, 14, 2.348045, 667.87, 167.241,
// 6, 16, 2.32142, 676.895, 169.298,
// 6, 18, 2.278715, 669.18, 175.292,
// 6, 20, 2.24959, 692.475, 188.489,
// 6, 24, 2.22949, 711.53, 204.391,
// 6, 28, 2.214285, 970.4, 212.011,
// 6, 32, 2.17879, 746.96, 225.202,
// 6, 64, 2.08618, 948.195, 296.483,
// 6, 96, 2.046315, 841.445, 357.629,
// 6, 128, 2.018775, 893.045, 424.116,
// 6, 192, 2.009245, 955.695, 542.052,
// 6, 256, 1.999575, 1060.675, 625.659,
// 6, 512, 1.981275, 1173.515, 1056.154,
// 7, 10, 2.40649, 934.015, 134.917,
// 7, 12, 2.342685, 963.06, 143.637,
// 7, 14, 2.256735, 969.365, 150.691,
// 7, 16, 2.199585, 1011.25, 155.369,
// 7, 18, 2.153345, 1021.715, 158.227,
// 7, 20, 2.144645, 1044.6, 158.149,
// 7, 24, 2.07744, 1116.36, 172.383,
// 7, 28, 2.058695, 1117.425, 175.712,
// 7, 32, 2.041425, 1171.02, 179.791,
// 7, 64, 1.9657, 1195.51, 246.424,
// 7, 96, 1.88927, 1239.09, 282.475,
// 7, 128, 1.865005, 1374.745, 334.15,
// 7, 192, 1.84498, 1498.185, 408.65,
// 7, 256, 1.837535, 1556.655, 484.289,
// 7, 512, 1.81903, 1750.75, 837.628,
// 8, 10, 2.37867, 1495.74, 141.054,
// 8, 12, 2.27321, 1456.335, 143.75,
// 8, 14, 2.22702, 1361.485, 147.132,
// 8, 16, 2.169285, 1352.785, 155.101,
// 8, 18, 2.121765, 1341.24, 155.674,
// 8, 20, 2.08732, 1433.205, 162.626,
// 8, 24, 2.04113, 1703.765, 155.698,
// 8, 28, 2.01393, 1872.255, 164.095,
// 8, 32, 1.980275, 1890.935, 172.217,
// 8, 64, 1.90684, 1933.78, 238.195,
// 8, 96, 1.86306, 1861.995, 276.053,
// 8, 128, 1.820795, 2277.445, 305.552,
// 8, 192, 1.808465, 2200.21, 384.153,
// 8, 256, 1.796845, 2432.63, 457.88,
// 8, 512, 1.772775, 2627.925, 703.463,
// 9, 10, 2.342775, 2684.44, 138.739,
// 9, 12, 2.23828, 2764.14, 138.49,
// 9, 14, 2.201795, 2536.575, 156.542,
// 9, 16, 2.14278, 2562.21, 151.358,
// 9, 18, 2.093535, 2484.925, 153.452,
// 9, 20, 2.064785, 2525.45, 159.702,
// 9, 24, 2.022555, 2510.515, 168.457,
// 9, 28, 1.99749, 2936.525, 170.246,
// 9, 32, 1.950545, 3745.315, 169.586,
// 9, 64, 1.85788, 2844.985, 211.073,
// 9, 96, 1.82558, 3854.355, 269.473,
// 9, 128, 1.78969, 3643.745, 292.384,
// 9, 192, 1.75526, 4951.505, 330.786,
// 9, 256, 1.75941, 4076.285, 421.23,
// 9, 512, 1.74503, 4833.62, 642.042,
// 9, 1024, 1.733485, 5085.565, 1089.779,
// 10, 10, 2.26647, 5994.385, 127.127,
// 10, 12, 2.20895, 6063.425, 133.45,
// 10, 14, 2.13613, 5793.905, 142.325,
// 10, 16, 2.116405, 5765.98, 149.818,
// 10, 18, 2.069445, 5045.955, 156.418,
// 10, 20, 2.0417, 5055.235, 157.168,
// 10, 24, 2.001495, 4501.335, 164.326,
// 10, 28, 1.97065, 4593.175, 166.087,
// 10, 32, 1.92606, 5303.8, 162.621,
// 10, 64, 1.80934, 8765.025, 191.302,
// 10, 96, 1.77682, 9685.165, 239.698,
// 10, 128, 1.73736, 10384.885, 255.39,
// 10, 192, 1.714485, 10500.3, 298.054,
// 10, 256, 1.697815, 10949.625, 340.407,
// 10, 512, 1.683975, 11039.485, 556.995,
// 10, 1024, 1.674175, 11566.535, 928.485,
// 11, 10, 2.25684, 12098.465, 122.634,
// 11, 12, 2.196525, 13093.21, 135.831,
// 11, 14, 2.12515, 11829.54, 139.618,
// 11, 16, 2.103765, 10143.83, 150.215,
// 11, 18, 2.050875, 8985.145, 152.343,
// 11, 20, 2.02091, 8399.96, 153.928,
// 11, 24, 1.961535, 8003.69, 155.773,
// 11, 28, 1.95324, 8601.655, 157.764,
// 11, 32, 1.907145, 10127.125, 160.339,
// 11, 64, 1.789405, 19404.98, 190.851,
// 11, 96, 1.754935, 19952.2, 234.153,
// 11, 128, 1.717035, 18210.85, 235.3,
// 11, 192, 1.69452, 23306.635, 279.228,
// 11, 256, 1.68079, 22824.155, 327.211,
// 11, 512, 1.669035, 22311.835, 527.925,
// 11, 1024, 1.65286, 25076.04, 845.709,
// 12, 10, 2.227455, 22643.33, 120.518,
// 12, 12, 2.174015, 26268.445, 133.791,
// 12, 14, 2.104935, 24317.83, 137.754,
// 12, 16, 2.05659, 21180.665, 145.368,
// 12, 18, 2.039165, 19377.72, 144.846,
// 12, 20, 2.006935, 21047.65, 153.12,
// 12, 24, 1.94188, 21689.085, 153.664,
// 12, 28, 1.936375, 22849.425, 158.15,
// 12, 32, 1.89074, 24265.935, 159.824,
// 12, 64, 1.75587, 53140.95, 175.05,
// 12, 96, 1.73322, 32236.755, 228.272,
// 12, 128, 1.69005, 55498.53, 229.207,
// 12, 192, 1.669415, 59977.9, 263.345,
// 12, 256, 1.656925, 60746.665, 300.781,
// 12, 512, 1.635245, 63767.805, 444.26,
// 12, 1024, 1.62973, 63569.64, 764.569,
// 13, 10, 2.21143, 48328.62, 115.192,
// 13, 12, 2.10655, 70906.805, 124.305,
// 13, 14, 2.07424, 80581.4, 134.342,
// 13, 16, 2.02719, 80590.855, 140.495,
// 13, 18, 1.98329, 72108.925, 144.81,
// 13, 20, 1.981005, 68867.005, 147.033,
// 13, 24, 1.921855, 66303.785, 153.31,
// 13, 28, 1.899895, 59542.925, 158.96,
// 13, 32, 1.877085, 49317.545, 159.739,
// 13, 64, 1.74228, 98851.095, 174.524,
// 13, 96, 1.70931, 101044.625, 213.047,
// 13, 128, 1.675095, 113230.025, 228.566,
// 13, 192, 1.66094, 129685.525, 270.841,
// 13, 256, 1.65179, 109093.085, 317.52,
// 13, 512, 1.624375, 144465.47, 445.139,
// 13, 1024, 1.61636, 142650.605, 736.177,
// 14, 10, 2.2058, 88520.57, 117.954,
// 14, 12, 2.10081, 150779.355, 120.79,
// 14, 14, 2.06992, 176648.28, 132.509,
// 14, 16, 2.02013, 180465.45, 133.61,
// 14, 18, 1.980155, 158706.445, 143.226,
// 14, 20, 1.977005, 136961.23, 146.619,
// 14, 24, 1.91441, 112793.52, 152.261,
// 14, 28, 1.891705, 99822.595, 154.993,
// 14, 32, 1.867235, 84616.375, 156.02,
// 14, 64, 1.741715, 146225.17, 173.922,
// 14, 96, 1.734425, 100017.37, 214.876,
// 14, 128, 1.67377, 183360.02, 232.579,
// 14, 192, 1.65015, 265466.69, 256.558,
// 14, 256, 1.63248, 280133.905, 284.565,
// 14, 512, 1.6124, 266907.36, 419.022,
// 14, 1024, 1.596, 347519.705, 622.838,
// 15, 10, 2.195685, 150867.115, 118.481,
// 15, 12, 2.07947, 282712.365, 121.882,
// 15, 14, 2.01334, 373176.395, 135.476,
// 15, 16, 2.000635, 402008.86, 137.389,
// 15, 18, 1.963445, 351145.795, 140.495,
// 15, 20, 1.965355, 307988.545, 147.11,
// 15, 24, 1.905775, 258812.12, 153.401,
// 15, 28, 1.880975, 284525.995, 161.962,
// 15, 32, 1.857065, 261793.815, 163.351,
// 15, 64, 1.728615, 385004.37, 175.091,
// 15, 96, 1.67177, 793105.765, 241.753,
// 15, 128, 1.658245, 609987.68, 242.138,
// 15, 192, 1.632715, 822227.365, 295.025,
// 15, 256, 1.62191, 673538.2, 317.271,
// 15, 512, 1.594745, 856301.05, 423.374,
// 15, 1024, 1.58679, 835599.4, 645.089,
// 16, 10, 2.192835, 248874.97, 116.926,
// 16, 12, 2.072645, 580146.355, 116.796,
// 16, 14, 2.001895, 921183.485, 129.44,
// 16, 16, 1.98756, 1098012.84, 139.59,
// 16, 18, 1.949805, 1059253.645, 144.09,
// 16, 20, 1.928705, 929469.745, 146.691,
// 16, 24, 1.898435, 625411.835, 153.217,
// 16, 28, 1.872735, 475906.27, 162.709,
// 16, 32, 1.834805, 379328.83, 160.678,
// 16, 64, 1.724945, 536426.38, 220.324,
// 16, 96, 1.663645, 1558653.495, 238.056,
// 16, 128, 1.65562, 1353223.825, 243.548,
// 16, 192, 1.624235, 1737980.76, 277.142,
// 16, 256, 1.612295, 1818499.86, 314.535,
// 16, 512, 1.585075, 2093046.415, 387.522,
// 16, 1024, 1.57934, 2179367.145, 613.495,
// 17, 10, 2.190335, 396320.4, 117.013,
// 17, 12, 2.06505, 951679.075, 124.288,
// 17, 14, 1.98992, 1505756.795, 129.896,
// 17, 16, 1.98164, 1794380.93, 140.186,
// 17, 18, 1.944195, 1706422.67, 145.83,
// 17, 20, 1.926945, 1351289.8, 151.975,
// 17, 24, 1.8967, 900890.055, 153.829,
// 17, 28, 1.86655, 913972.885, 165.015,
// 17, 32, 1.822715, 1086560.89, 159.539,
// 17, 64, 1.717095, 1023016.75, 208.903,
// 17, 96, 1.663115, 2264625.19, 225.333,
// 17, 128, 1.6467, 1849601.285, 262.772,
// 17, 192, 1.631145, 2260000.275, 284.572,
// 17, 256, 1.615295, 2569679.075, 324.995,
// 17, 512, 1.57983, 4903492.61, 391.586,
// 17, 1024, 1.572335, 5224942.645, 589.941,
// Elias Fano, Java 7, 200'000, IMPROVED_SPLIT_RULES disabled
// 4, 20, 2.470905, 531.61, 197.398,
// 4, 24, 2.41963, 568.145, 207.133,
// 4, 28, 2.398395, 567.185, 225.119,
// 4, 32, 2.37902, 604.32, 239.061,
// 4, 64, 2.249965, 642.395, 335.572,
// 4, 96, 2.21621, 715.185, 409.494,
// 4, 128, 2.194625, 742.52, 488.872,
// 4, 192, 2.17983, 804.17, 640.52,
// 4, 256, 2.168565, 877.52, 788.277,
// 5, 12, 2.458, 602.225, 158.36,
// 5, 14, 2.375055, 608.48, 164.219,
// 5, 16, 2.34033, 620.12, 166.763,
// 5, 18, 2.295295, 630.01, 174.235,
// 5, 20, 2.261475, 657.19, 166.937,
// 5, 24, 2.232125, 606.675, 181.288,
// 5, 28, 2.21222, 623.59, 186.955,
// 5, 32, 2.172215, 672.1, 199.667,
// 5, 64, 2.064325, 691.135, 260.398,
// 5, 96, 2.019225, 770.985, 306.411,
// 5, 128, 1.99705, 758.04, 374.651,
// 5, 192, 1.98014, 885.875, 450.713,
// 5, 256, 1.964155, 883.88, 569.645,
// 5, 512, 1.94885, 995.81, 938.224,
// 6, 12, 2.41533, 670.18, 144.191,
// 6, 14, 2.32433, 754.12, 149.013,
// 6, 16, 2.29281, 701.435, 155.742,
// 6, 18, 2.236085, 709.57, 158.417,
// 6, 20, 2.19864, 750.54, 164.125,
// 6, 24, 2.143515, 753.055, 169.618,
// 6, 28, 2.14354, 777.41, 173.123,
// 6, 32, 2.1053, 756.74, 187.027,
// 6, 64, 1.99434, 912.135, 237.705,
// 6, 96, 1.9514, 886.66, 281.506,
// 6, 128, 1.929665, 960.31, 346.94,
// 6, 192, 1.911185, 1037.55, 397.602,
// 6, 256, 1.896875, 1092.905, 484.627,
// 6, 512, 1.87757, 1294.395, 826.612,
// 7, 10, 2.407235, 929.085, 133.486,
// 7, 12, 2.34057, 976.235, 140.682,
// 7, 14, 2.25626, 1022.26, 146.484,
// 7, 16, 2.194895, 1016.405, 155.009,
// 7, 18, 2.147625, 1030.625, 155.313,
// 7, 20, 2.139175, 1064.085, 158.7,
// 7, 24, 2.075395, 1100.655, 158.711,
// 7, 28, 2.05703, 1126.74, 169.578,
// 7, 32, 2.040645, 1119.86, 176.318,
// 7, 64, 1.92282, 1201.13, 224.148,
// 7, 96, 1.885075, 1255.05, 268.332,
// 7, 128, 1.861525, 1354.2, 303.348,
// 7, 192, 1.841595, 1422.635, 373.644,
// 7, 256, 1.832, 1457.54, 437.773,
// 7, 512, 1.813535, 1659.425, 718.17,
// 8, 10, 2.374405, 1524.01, 128.843,
// 8, 12, 2.26062, 1619.3, 138.92,
// 8, 14, 2.21941, 1682.965, 141.848,
// 8, 16, 2.15729, 1702.655, 150.036,
// 8, 18, 2.11754, 1745.77, 154.274,
// 8, 20, 2.116515, 1790.735, 157.817,
// 8, 24, 2.056035, 1875.415, 159.602,
// 8, 28, 2.021495, 2049.04, 165.693,
// 8, 32, 1.97279, 2253.855, 168.18,
// 8, 64, 1.86501, 2519.11, 203.176,
// 8, 96, 1.81827, 2678.035, 232.168,
// 8, 128, 1.79172, 2743.885, 264.59,
// 8, 192, 1.76805, 2862.525, 325.277,
// 8, 256, 1.76191, 2964.595, 386.131,
// 8, 512, 1.741125, 3186.06, 579.771,
// 8, 1024, 1.734195, 3431.95, 992.839,
// 9, 10, 2.33308, 2921.67, 126.492,
// 9, 12, 2.220135, 3079.505, 131.824,
// 9, 14, 2.14388, 3228.985, 135.728,
// 9, 16, 2.12304, 3336.66, 143.909,
// 9, 18, 2.079285, 3363.255, 144.216,
// 9, 20, 2.053395, 3495.825, 149.323,
// 9, 24, 2.029165, 3667.125, 151.586,
// 9, 28, 2.00448, 3832.785, 162.268,
// 9, 32, 1.96081, 4133.775, 166.158,
// 9, 64, 1.83966, 4695.99, 194.566,
// 9, 96, 1.7966, 4795.8, 225.375,
// 9, 128, 1.771115, 5047.68, 251.695,
// 9, 192, 1.750705, 5154.9, 305.649,
// 9, 256, 1.74, 5394.745, 346.547,
// 9, 512, 1.721885, 5566.685, 524.276,
// 9, 1024, 1.70978, 5713.12, 908.291,
// 10, 10, 2.26205, 5947.835, 123.408,
// 10, 12, 2.19927, 6757.7, 130.215,
// 10, 14, 2.11739, 6956.82, 133.934,
// 10, 16, 2.063445, 7278.955, 136.91,
// 10, 18, 2.04491, 7254.605, 138.898,
// 10, 20, 2.01783, 7595.075, 148.459,
// 10, 24, 1.99413, 8046.975, 145.846,
// 10, 28, 1.97355, 8273.41, 152.016,
// 10, 32, 1.94444, 8527.48, 161.704,
// 10, 64, 1.786515, 14256.225, 226.411,
// 10, 96, 1.75497, 14041.155, 258.34,
// 10, 128, 1.73047, 14866.12, 270.534,
// 10, 192, 1.70212, 16027.155, 306.938,
// 10, 256, 1.68637, 16439.44, 344.142,
// 10, 512, 1.664455, 17227.03, 498.827,
// 10, 1024, 1.652735, 17443.67, 727.342,
// 11, 10, 2.252615, 12481.5, 122.729,
// 11, 12, 2.1877, 14806.225, 124.975,
// 11, 14, 2.1082, 15984.395, 132.277,
// 11, 16, 2.0481, 16268.345, 134.219,
// 11, 18, 2.033125, 16860.275, 138.096,
// 11, 20, 2.000705, 17646.71, 143.937,
// 11, 24, 1.953535, 18600.325, 148.093,
// 11, 28, 1.94897, 18719.355, 151.751,
// 11, 32, 1.92184, 19596.005, 159.312,
// 11, 64, 1.769915, 27585.715, 218.831,
// 11, 96, 1.747495, 26992.02, 249.497,
// 11, 128, 1.71072, 28903.025, 264.075,
// 11, 192, 1.68457, 30589.52, 278.156,
// 11, 256, 1.670325, 30208.16, 311.294,
// 11, 512, 1.65012, 31505.045, 444.507,
// 11, 1024, 1.638485, 32038.875, 688.599,
// 12, 10, 2.22231, 24705.74, 165.762,
// 12, 12, 2.119925, 32694.4, 126.67,
// 12, 14, 2.082335, 36846.79, 130.963,
// 12, 16, 2.025845, 38237.275, 139.186,
// 12, 18, 1.98414, 39442.495, 159.341,
// 12, 20, 1.975065, 40671.705, 192.188,
// 12, 24, 1.924715, 44007.85, 192.783,
// 12, 28, 1.930985, 45227.92, 207.617,
// 12, 32, 1.898935, 46104.27, 203.27,
// 12, 64, 1.76138, 56904.4, 213.47,
// 12, 96, 1.723725, 57794.79, 222.003,
// 12, 128, 1.69288, 61194.555, 243.219,
// 12, 192, 1.66851, 62373.59, 280.033,
// 12, 256, 1.65517, 62835.26, 304.335,
// 12, 512, 1.634315, 64540.61, 440.262,
// 12, 1024, 1.625505, 65182.255, 652.904,
// 13, 10, 2.210815, 46968.995, 121.201,
// 13, 12, 2.104695, 70740.235, 131.175,
// 13, 14, 2.06871, 85441.665, 148.519,
// 13, 16, 2.02016, 94314.83, 182.841,
// 13, 18, 1.96975, 92865.16, 182.024,
// 13, 20, 1.96359, 95121.82, 184.699,
// 13, 24, 1.906365, 102406.62, 158.303,
// 13, 28, 1.892015, 107833.15, 197.621,
// 13, 32, 1.87882, 109796.23, 219.467,
// 13, 64, 1.78156, 128046.31, 217.352,
// 13, 96, 1.689325, 192932.635, 201.226,
// 13, 128, 1.686015, 177628.955, 214.069,
// 13, 192, 1.653795, 199516.91, 245.216,
// 13, 256, 1.631885, 208383.39, 285.236,
// 13, 512, 1.614825, 213491.69, 392.089,
// 13, 1024, 1.60361, 215338.425, 590.956,
// 14, 10, 2.20516, 83841.54, 113.454,
// 14, 12, 2.09932, 145263.425, 123.554,
// 14, 14, 2.066495, 185532.01, 156.049,
// 14, 16, 2.01251, 212825.645, 175.047,
// 14, 18, 1.97061, 222303.735, 175.905,
// 14, 20, 1.93663, 226160.615, 182.177,
// 14, 24, 1.897995, 231756.305, 142.045,
// 14, 28, 1.88113, 248882.52, 147.99,
// 14, 32, 1.867775, 262275.93, 151.812,
// 14, 64, 1.77499, 291933.53, 214.264,
// 14, 96, 1.691255, 385253.28, 209.619,
// 14, 128, 1.67255, 367162.19, 230.257,
// 14, 192, 1.64475, 398807.275, 260.316,
// 14, 256, 1.63077, 400178.26, 266.605,
// 14, 512, 1.609675, 420093.275, 393.8,
// 14, 1024, 1.597995, 421539.69, 565.925,
// 15, 10, 2.19504, 143709.415, 123.098,
// 15, 12, 2.077205, 281957.6, 148.828,
// 15, 14, 2.00704, 407922.98, 165.173,
// 15, 16, 1.99023, 515948.185, 177.669,
// 15, 18, 1.94782, 543192.28, 181.059,
// 15, 20, 1.91518, 565792.075, 143.719,
// 15, 24, 1.878835, 563904.165, 141.983,
// 15, 28, 1.85811, 598985.05, 148.883,
// 15, 32, 1.832645, 623808.285, 158.145,
// 15, 64, 1.754495, 706206.44, 182.353,
// 15, 96, 1.676545, 828029.2, 217.235,
// 15, 128, 1.654275, 844462.385, 230.093,
// 15, 192, 1.629975, 869058.975, 264.801,
// 15, 256, 1.624035, 862970.86, 293.028,
// 15, 512, 1.596255, 881522.125, 373.269,
// 15, 1024, 1.58612, 920050.94, 537.217,
// 16, 10, 2.19248, 231490.225, 148.896,
// 16, 12, 2.072425, 550874.24, 129.056,
// 16, 14, 1.998785, 914380.8, 126.612,
// 16, 16, 1.982985, 1188278.2, 133.524,
// 16, 18, 1.942255, 1325198.03, 136.67,
// 16, 20, 1.913635, 1401516.895, 140.11,
// 16, 24, 1.87398, 1403906.515, 142.839,
// 16, 28, 1.84712, 1459527.195, 147.986,
// 16, 32, 1.819705, 1566934.57, 154.035,
// 16, 64, 1.74261, 1738419.015, 183.85,
// 16, 96, 1.702985, 1894356.81, 229.92,
// 16, 128, 1.63374, 2955705.28, 219.608,
// 16, 192, 1.633705, 2692669.76, 262.579,
// 16, 256, 1.605415, 3106663.265, 289.028,
// 16, 512, 1.586955, 3130124.865, 360.31,
// 16, 1024, 1.573265, 3225744.865, 539.198,
// 17, 10, 2.18964, 403617.2, 111.84,
// 17, 12, 2.06287, 1058321.445, 116.22,
// 17, 14, 1.982145, 1907377.25, 122.586,
// 17, 16, 1.93782, 2757154.59, 131.185,
// 17, 18, 1.926615, 3331391.5, 134.022,
// 17, 20, 1.898345, 3534194.99, 137.826,
// 17, 24, 1.84277, 3639365.975, 141.108,
// 17, 28, 1.836025, 3619969.58, 144.644,
// 17, 32, 1.8045, 3893431.88, 151.667,
// 17, 64, 1.737125, 4569860.49, 176.539,
// 17, 96, 1.698355, 4780985.505, 217.297,
// 17, 128, 1.633505, 5969816.71, 239.5,
// 17, 192, 1.624175, 5864469.5, 265.114,
// 17, 256, 1.596265, 6203171.485, 285.022,
// 17, 512, 1.578285, 6432832.395, 370.582,
// 17, 1024, 1.569395, 6439802.705, 541.282,
// Elias Fano, Java 7, 200'000, IMPROVED_SPLIT_RULES = true
// 4, 20, 2.48048, 512.325, 187.492,
// 4, 24, 2.42928, 522.44, 199.791,
// 4, 28, 2.41148, 541.0, 203.64,
// 4, 32, 2.39106, 548.22, 216.052,
// 4, 64, 2.29868, 631.86, 309.16,
// 4, 96, 2.29236, 736.03, 405.923,
// 4, 128, 2.288445, 835.855, 474.497,
// 4, 192, 2.291665, 1029.565, 653.614,
// 4, 256, 2.338615, 1150.045, 830.998,
// 5, 12, 2.49213, 569.56, 156.05,
// 5, 14, 2.45962, 591.465, 159.745,
// 5, 16, 2.406045, 592.14, 170.758,
// 5, 18, 2.36519, 573.265, 175.087,
// 5, 20, 2.3282, 585.93, 181.257,
// 5, 24, 2.294605, 629.065, 188.515,
// 5, 28, 2.272095, 603.55, 197.512,
// 5, 32, 2.241275, 617.39, 209.133,
// 5, 64, 2.129795, 676.85, 278.654,
// 5, 96, 2.095895, 777.125, 333.663,
// 5, 128, 2.0692, 817.78, 396.659,
// 5, 192, 2.04735, 862.545, 511.027,
// 5, 256, 2.04075, 922.57, 629.603,
// 5, 512, 2.03622, 1164.66, 1091.621,
// 6, 12, 2.408935, 623.395, 143.725,
// 6, 14, 2.32586, 671.455, 149.329,
// 6, 16, 2.29345, 688.095, 155.945,
// 6, 18, 2.23773, 679.62, 159.455,
// 6, 20, 2.20193, 702.43, 159.165,
// 6, 24, 2.145385, 762.84, 164.981,
// 6, 28, 2.146795, 785.365, 172.633,
// 6, 32, 2.109045, 767.41, 183.731,
// 6, 64, 1.99843, 861.545, 229.73,
// 6, 96, 1.951715, 889.78, 275.149,
// 6, 128, 1.93365, 930.85, 316.318,
// 6, 192, 1.916535, 1007.91, 401.383,
// 6, 256, 1.90533, 1108.97, 494.761,
// 6, 512, 1.8973, 1418.46, 844.836,
// 7, 10, 2.40649, 910.04, 134.784,
// 7, 12, 2.342685, 993.155, 142.055,
// 7, 14, 2.256735, 927.335, 146.97,
// 7, 16, 2.199585, 973.33, 149.324,
// 7, 18, 2.153345, 962.96, 156.355,
// 7, 20, 2.144645, 987.305, 157.497,
// 7, 24, 2.077455, 1071.125, 162.731,
// 7, 28, 2.05867, 1096.12, 169.757,
// 7, 32, 2.04204, 1108.09, 177.653,
// 7, 64, 1.932225, 1235.985, 218.343,
// 7, 96, 1.88419, 1275.755, 259.539,
// 7, 128, 1.8626, 1355.63, 300.261,
// 7, 192, 1.84437, 1396.935, 373.008,
// 7, 256, 1.8383, 1544.06, 442.3,
// 7, 512, 1.823355, 1750.82, 740.437,
// 8, 10, 2.374485, 1514.07, 129.072,
// 8, 12, 2.263715, 1467.805, 135.175,
// 8, 14, 2.2227, 1413.265, 139.292,
// 8, 16, 2.16154, 1380.64, 145.35,
// 8, 18, 2.12091, 1352.48, 148.251,
// 8, 20, 2.08644, 1387.02, 148.455,
// 8, 24, 2.040295, 1629.39, 152.894,
// 8, 28, 2.006125, 1910.88, 160.54,
// 8, 32, 1.95964, 2201.905, 159.756,
// 8, 64, 1.85237, 2434.215, 199.322,
// 8, 96, 1.81621, 2637.71, 227.705,
// 8, 128, 1.793235, 2762.435, 271.012,
// 8, 192, 1.77067, 2787.885, 318.298,
// 8, 256, 1.760585, 2907.465, 376.116,
// 8, 512, 1.74589, 3209.165, 603.672,
// 8, 1024, 1.742855, 3635.42, 1057.028,
// 9, 10, 2.33629, 2814.55, 126.652,
// 9, 12, 2.227765, 2857.27, 132.771,
// 9, 14, 2.155205, 2838.27, 141.183,
// 9, 16, 2.133065, 2743.4, 157.977,
// 9, 18, 2.085855, 2598.85, 147.983,
// 9, 20, 2.06114, 2421.91, 150.531,
// 9, 24, 2.02023, 2145.005, 156.36,
// 9, 28, 1.993545, 2461.175, 160.944,
// 9, 32, 1.94532, 2972.725, 157.951,
// 9, 64, 1.836165, 4199.4, 195.934,
// 9, 96, 1.797485, 4508.95, 216.692,
// 9, 128, 1.772115, 4760.695, 243.604,
// 9, 192, 1.747785, 4931.75, 297.077,
// 9, 256, 1.73752, 5074.6, 350.191,
// 9, 512, 1.721915, 5358.975, 544.411,
// 9, 1024, 1.72051, 5765.0, 946.249,
// 10, 10, 2.31985, 5532.26, 127.423,
// 10, 12, 2.21901, 5695.73, 132.357,
// 10, 14, 2.153965, 5402.715, 150.689,
// 10, 16, 2.13306, 5406.525, 144.521,
// 10, 18, 2.085745, 5197.74, 150.922,
// 10, 20, 2.05117, 5060.285, 149.832,
// 10, 24, 2.005075, 4946.91, 153.765,
// 10, 28, 1.968035, 4882.67, 159.438,
// 10, 32, 1.924895, 5276.94, 158.758,
// 10, 64, 1.810935, 8778.07, 192.856,
// 10, 96, 1.767075, 9695.245, 207.671,
// 10, 128, 1.73814, 9774.565, 233.667,
// 10, 192, 1.718085, 9978.115, 279.348,
// 10, 256, 1.70646, 10380.25, 325.488,
// 10, 512, 1.692565, 10735.725, 517.318,
// 10, 1024, 1.68614, 11369.23, 869.157,
// 11, 10, 2.26196, 11681.355, 126.062,
// 11, 12, 2.210445, 12090.35, 129.264,
// 11, 14, 2.15326, 10860.655, 142.715,
// 11, 16, 2.138095, 9001.275, 145.573,
// 11, 18, 2.091575, 7605.06, 152.51,
// 11, 20, 2.056725, 7407.825, 153.707,
// 11, 24, 2.00323, 7526.725, 158.037,
// 11, 28, 1.957745, 8824.12, 158.663,
// 11, 32, 1.909345, 10359.315, 160.264,
// 11, 64, 1.772895, 25984.87, 178.063,
// 11, 96, 1.731035, 24138.265, 200.68,
// 11, 128, 1.713125, 27240.675, 221.134,
// 11, 192, 1.69108, 27817.545, 259.051,
// 11, 256, 1.67512, 28034.72, 301.68,
// 11, 512, 1.655815, 29773.44, 449.153,
// 11, 1024, 1.65083, 27722.74, 749.245,
// 12, 10, 2.232555, 21684.515, 118.031,
// 12, 12, 2.188375, 24816.085, 131.308,
// 12, 14, 2.136095, 22334.98, 137.327,
// 12, 16, 2.131525, 17667.01, 141.235,
// 12, 18, 2.09187, 15266.93, 146.799,
// 12, 20, 2.05911, 15722.29, 153.575,
// 12, 24, 1.998115, 17725.66, 152.031,
// 12, 28, 1.946535, 20558.46, 156.045,
// 12, 32, 1.89468, 23382.52, 153.817,
// 12, 64, 1.75713, 50011.425, 168.481,
// 12, 96, 1.71889, 48595.12, 190.094,
// 12, 128, 1.69678, 56721.185, 217.878,
// 12, 192, 1.673845, 58555.555, 251.484,
// 12, 256, 1.66158, 60103.57, 279.879,
// 12, 512, 1.64087, 62022.52, 421.797,
// 12, 1024, 1.636115, 62682.005, 697.759,
// 13, 10, 2.210815, 46633.88, 114.862,
// 13, 12, 2.104695, 69929.665, 116.099,
// 13, 14, 2.06868, 85122.835, 128.55,
// 13, 16, 2.020125, 93111.61, 131.044,
// 13, 18, 1.96981, 91965.28, 136.545,
// 13, 20, 1.93844, 91637.88, 135.952,
// 13, 24, 1.905935, 85360.755, 140.874,
// 13, 28, 1.890695, 71220.105, 150.175,
// 13, 32, 1.87284, 62915.33, 153.989,
// 13, 64, 1.741925, 95439.845, 167.771,
// 13, 96, 1.700325, 117642.56, 183.434,
// 13, 128, 1.67455, 118047.255, 207.787,
// 13, 192, 1.656405, 124605.6, 244.722,
// 13, 256, 1.642845, 130119.215, 276.055,
// 13, 512, 1.62088, 133387.9, 415.556,
// 13, 1024, 1.61508, 137823.6, 653.189,
// 14, 10, 2.20516, 85786.615, 116.196,
// 14, 12, 2.09932, 149587.88, 118.289,
// 14, 14, 2.06649, 190811.015, 128.583,
// 14, 16, 2.012475, 218382.685, 132.342,
// 14, 18, 1.970125, 225597.945, 133.783,
// 14, 20, 1.93746, 221999.445, 139.745,
// 14, 24, 1.89763, 191213.015, 144.212,
// 14, 28, 1.879945, 144918.735, 151.997,
// 14, 32, 1.86595, 109697.295, 152.652,
// 14, 64, 1.737575, 162423.67, 166.307,
// 14, 96, 1.68244, 372972.755, 228.849,
// 14, 128, 1.667675, 312236.055, 246.35,
// 14, 192, 1.643375, 383708.085, 273.699,
// 14, 256, 1.627495, 383618.075, 307.331,
// 14, 512, 1.612215, 406045.51, 377.666,
// 14, 1024, 1.602745, 419758.895, 613.333,
// 15, 10, 2.19504, 146619.355, 111.976,
// 15, 12, 2.077205, 287076.2, 121.578,
// 15, 14, 2.00704, 421559.075, 129.984,
// 15, 16, 1.99023, 529179.905, 131.414,
// 15, 18, 1.947735, 555597.37, 136.639,
// 15, 20, 1.915185, 569832.705, 137.801,
// 15, 24, 1.878695, 527880.235, 141.678,
// 15, 28, 1.858525, 460067.35, 147.99,
// 15, 32, 1.830895, 339825.68, 155.367,
// 15, 64, 1.727485, 402200.83, 205.692,
// 15, 96, 1.67126, 767329.495, 216.997,
// 15, 128, 1.65341, 761072.575, 239.168,
// 15, 192, 1.62686, 861076.8, 266.652,
// 15, 256, 1.618475, 800519.57, 292.045,
// 15, 512, 1.59838, 873461.75, 393.447,
// 15, 1024, 1.58921, 900375.855, 591.985,
// 16, 10, 2.19248, 237202.64, 157.263,
// 16, 12, 2.072425, 566139.105, 125.365,
// 16, 14, 1.998785, 934930.44, 131.752,
// 16, 16, 1.982985, 1217565.345, 133.588,
// 16, 18, 1.942285, 1387565.16, 136.453,
// 16, 20, 1.913775, 1438086.85, 141.268,
// 16, 24, 1.873775, 1424060.21, 145.843,
// 16, 28, 1.846725, 1333494.76, 151.103,
// 16, 32, 1.818285, 1126361.91, 157.529,
// 16, 64, 1.72333, 576836.96, 210.774,
// 16, 96, 1.6634, 1525764.045, 218.326,
// 16, 128, 1.641725, 1919115.55, 227.214,
// 16, 192, 1.62129, 1815559.185, 232.165,
// 16, 256, 1.612415, 1827617.57, 290.803,
// 16, 512, 1.59076, 2086348.4, 391.111,
// 16, 1024, 1.57934, 2087350.045, 558.129,
// 17, 10, 2.18964, 401031.365, 125.065,
// 17, 12, 2.06287, 1045783.635, 122.734,
// 17, 14, 1.982145, 1891244.035, 127.894,
// 17, 16, 1.93782, 2745287.44, 133.509,
// 17, 18, 1.926575, 3319014.455, 144.654,
// 17, 20, 1.898375, 3520220.58, 141.428,
// 17, 24, 1.84248, 3537904.71, 144.53,
// 17, 28, 1.836415, 3107551.58, 149.173,
// 17, 32, 1.802425, 2472730.47, 152.651,
// 17, 64, 1.71758, 1325601.97, 207.873,
// 17, 96, 1.65917, 3098177.73, 212.668,
// 17, 128, 1.633325, 4726102.23, 215.806,
// 17, 192, 1.61545, 4100457.075, 267.917,
// 17, 256, 1.603505, 4421849.97, 296.195,
// 17, 512, 1.58355, 4990337.785, 349.06,
// 17, 1024, 1.57532, 5113673.05, 547.186,
};
for (int i = 0; i < data.length; i += 5) {
FunctionInfo info = new FunctionInfo();
info.leafSize = (int) data[i];
info.averageBucketSize = (int) data[i + 1];
info.bitsPerKey = data[i + 2];
info.generateNanos = data[i + 3];
info.evaluateNanos = data[i + 4];
list.add(info);
}
// printTables(list);
// int[] pairs = new int[] { 4, 20, 4, 24, 5, 20, 5, 24, 5, 64, 5, 128, 6, 128, 6, 256,
// 7, 256, 7, 512, 8, 128, 8, 256, 8, 512, 9, 256, 9, 512, 10, 12,
// 10, 256, 10, 512, 10, 1024, 11, 14, 11, 24, 11, 28, 11, 32, 11,
// 64, 11, 128, 11, 1024, 12, 32, 12, 64, 12, 128, 12, 512, 12,
// 1024, 13, 28, 13, 512, 13, 1024, 14, 28, 14, 128, 14, 256, 14,
// 1024, 15, 14, 15, 20, 15, 28, 15, 32, 15, 64, 15, 128, 15, 256,
// 15, 512, 16, 16, 16, 20, 16, 28, 16, 32, 16, 64, 16, 128, 16,
// 256, 16, 512, };
// for (int i = 0; i < pairs.length; i += 2) {
// int leafSize = pairs[i], averageBucketSize = pairs[i + 1];
// double expectedBits = SpaceEstimator.getExpectedSpace(leafSize,
// averageBucketSize);
// if (expectedBits > 2.6) {
// continue;
// }
// FunctionInfo info = test(leafSize, averageBucketSize, size, true, 5, true);
// if (info.bitsPerKey > 2.35) {
// continue;
// }
// if (info.evaluateNanos > 950) {
// continue;
// }
// System.out.println(" " + info.leafSize + ", " + info.averageBucketSize +
// ", " + info.bitsPerKey + ", " + info.generateNanos + ", " +
// info.evaluateNanos + ",");
// list.add(info);
// }
// for (int leafSize = 4; leafSize <= 17; leafSize++) {
// for (int averageBucketSize : new int[] {
// 10, 12, 14, 16, 18, 20, 24, 28, 32,
// 64, 96, 128, 192, 256, 512, 1024 }) {
// double expectedBits = SpaceEstimator.getExpectedSpace(leafSize, averageBucketSize);
// if (expectedBits > 3.2) {
// continue;
// }
// FunctionInfo info = test(leafSize, averageBucketSize, size, true, 5, true);
// if (info.bitsPerKey > 2.5) {
// continue;
// }
// if (info.evaluateNanos > 1200) {
// continue;
// }
// System.out.println(" " + info.leafSize + ", " +
// info.averageBucketSize + ", " + info.bitsPerKey + ", " +
// info.generateNanos + ", " + info.evaluateNanos + ",");
// list.add(info);
// }
// }
Collections.sort(list, new Comparator() {
@Override
public int compare(FunctionInfo o1, FunctionInfo o2) {
return Double.compare(o1.bitsPerKey, o2.bitsPerKey);
}
});
FunctionInfo last;
ArrayList evaluate = new ArrayList();
last = null;
for (FunctionInfo info : list) {
if (last == null) {
last = info;
continue;
}
if (info.evaluateNanos < last.evaluateNanos) {
evaluate.add(info);
last = info;
}
}
last = null;
ArrayList generate = new ArrayList();
for (FunctionInfo info : list) {
if (last == null) {
last = info;
continue;
}
if (info.generateNanos < last.generateNanos) {
generate.add(info);
last = info;
}
}
last = null;
ArrayList balanced = new ArrayList();
double bestScore = Double.MAX_VALUE;
for (FunctionInfo info : list) {
if (info.bitsPerKey > 2.26 && info.generateNanos > 2000) {
continue;
}
if (last == null) {
balanced.add(info);
last = info;
continue;
}
double score = 500 * info.evaluateNanos + info.generateNanos;
if (score > bestScore) {
continue;
}
bestScore = score;
if (info.evaluateNanos > last.evaluateNanos * 1.02) {
continue;
}
if (info.generateNanos > last.generateNanos * 1.02) {
continue;
}
last = info;
balanced.add(info);
}
HashSet used = new HashSet();
System.out.println("Balanced: generation time");
for (FunctionInfo info : balanced) {
System.out.println(" (" + info.bitsPerKey + ", " + info.generateNanos + ")");
}
System.out.println("Balanced: evaluation time");
for (FunctionInfo info : balanced) {
used.add(info);
System.out.println(" (" + info.bitsPerKey + ", " + info.evaluateNanos + ")");
}
// System.out.println("Best Generation: evaluation time");
// for (FunctionInfo info : generate) {
// used.add(info);
// System.out.println(" (" + info.bitsPerKey + ", " + info.evaluateNanos + ")");
// }
// System.out.println("Best Evaluation: evaluation time");
// for (FunctionInfo info : evaluate) {
// used.add(info);
// System.out.println(" (" + info.bitsPerKey + ", " + info.evaluateNanos + ")");
// }
// System.out.println("Best Generation: generation time");
// for (FunctionInfo info : generate) {
// System.out.println(" (" + info.bitsPerKey + ", " + info.generateNanos + ")");
// }
// System.out.println("Best Evaluation: generation time");
// for (FunctionInfo info : evaluate) {
// System.out.println(" (" + info.bitsPerKey + ", " + info.generateNanos + ")");
// }
ArrayList usedList = new ArrayList(used);
Collections.sort(usedList, new Comparator() {
@Override
public int compare(FunctionInfo o1, FunctionInfo o2) {
int comp = Integer.compare(o1.leafSize, o2.leafSize);
if (comp != 0) {
return comp;
}
return Integer.compare(o1.averageBucketSize, o2.averageBucketSize);
}
});
System.out.println("All used");
for (FunctionInfo info : usedList) {
System.out.println(info.leafSize + ", " + info.averageBucketSize + ", ");
}
}
private static void printTables(ArrayList list) {
System.out.println("Space");
printTables(list, 0);
System.out.println("Generation");
printTables(list, 1);
System.out.println("Evaluation");
printTables(list, 2);
}
private static void printTables(ArrayList list, int type) {
System.out.print(" ");
for (int averageBucketSize : new int[] { 10, 12, 16, 32, 64, 128, 256,
512, 1024 }) {
System.out.print(" & " + averageBucketSize);
}
System.out.println(" \\\\");
for (int leafSize = 5; leafSize <= 17; leafSize++) {
System.out.print(leafSize);
for (int averageBucketSize : new int[] { 10, 12, 16, 32, 64, 128, 256,
512, 1024 }) {
boolean found = false;
System.out.print(" & ");
for (FunctionInfo info : list) {
if (leafSize != info.leafSize ||
averageBucketSize != info.averageBucketSize) {
continue;
}
if (type == 0) {
System.out.printf("%1.2f", info.bitsPerKey);
found = true;
} else if (type == 1) {
System.out.printf("%1.1f", info.generateNanos / 1000);
found = true;
} else {
System.out.printf("%d", (int) info.evaluateNanos);
found = true;
}
}
if (!found) {
System.out.print(" ");
}
}
System.out.println(" \\\\");
}
}
public static void printGenerationTimeVersusSpace() {
System.out.println("B Generation Time Versus Space");
int size = 10000;
System.out.println("size: " + size);
ArrayList list = new ArrayList();
outer:
for (int leafSize = 2; leafSize <= 20; leafSize++) {
int minAverageBucketSize = 16;
for (int averageBucketSize = minAverageBucketSize; averageBucketSize < 8 * 1024; averageBucketSize *= 2) {
System.out.println("leafSize " + leafSize + " " + averageBucketSize);
FunctionInfo info = test(leafSize, averageBucketSize, size, true);
if (info.generateNanos >= 1000000) {
if (averageBucketSize == minAverageBucketSize) {
// done
break outer;
}
// next leaf size
break;
}
if (info.bitsPerKey < 2.4) {
list.add(info);
}
}
}
Collections.sort(list, new Comparator() {
@Override
public int compare(FunctionInfo o1, FunctionInfo o2) {
int comp = Double.compare(o1.generateNanos, o2.generateNanos);
if (comp == 0) {
comp = Double.compare(o1.bitsPerKey, o2.bitsPerKey);
}
return comp;
}
});
FunctionInfo last = null;
int minAverageBucketSize = Integer.MAX_VALUE, maxAverageBucketSize = 0;
int minLeafSize = Integer.MAX_VALUE, maxLeafSize = 0;
for (FunctionInfo info : list) {
if (last != null && info.bitsPerKey > last.bitsPerKey) {
continue;
}
System.out.println(" (" + info.bitsPerKey + ", " + info.generateNanos + ")");
minAverageBucketSize = Math.min(minAverageBucketSize, info.averageBucketSize);
maxAverageBucketSize = Math.max(maxAverageBucketSize, info.averageBucketSize);
minLeafSize = Math.min(minLeafSize, info.leafSize);
maxLeafSize = Math.max(maxLeafSize, info.leafSize);
last = info;
}
System.out.println("for averageBucketSize between " + minAverageBucketSize + " and " + maxAverageBucketSize);
System.out.println("and leafSize between " + minLeafSize + " and " + maxLeafSize);
last = null;
System.out.println("bits/key leafSize averageBucketSize evalTime genTime");
for (FunctionInfo info : list) {
if (last != null && info.bitsPerKey > last.bitsPerKey) {
continue;
}
System.out.println(info.bitsPerKey + " " + info.leafSize + " " + info.averageBucketSize +
" " + info.evaluateNanos + " " + info.generateNanos);
last = info;
}
}
public static void runTests() {
int[] pairs = {
23, 828, 23, 1656, 23, 3312,
23, 6624, 25, 1250, 25,
3750, 25, 7500, 25, 15000 };
for (int i = 0; i < pairs.length; i += 2) {
int leafSize = pairs[i], size = pairs[i + 1];
FunctionInfo info = test(leafSize, size, size, true);
System.out.println(new Timestamp(System.currentTimeMillis()).toString());
System.out.println(info);
}
}
static void verifyParameters() {
System.out.println("4.1 Parameters");
// size 100000
// CHD: generated in 1.52 seconds, 2.257 bits/key, eval 219 nanoseconds/key
// GOV: generated in 0.32 seconds, 2.324 bits/key, eval 207 nanoseconds/key
// size 1000000
// CHD:
// GOV:
RandomizedTest.test(8, 1024, 8 * 1024, true);
for (int i = 0; i < 5; i++) {
if (verifyOneTest()) {
return;
}
RandomizedTest.test(8, 1024, 8 * 1024, true);
}
Assert.fail();
}
static void verifyParametersBestSize() {
// System.out.println(RandomizedTest.test(23, 828, 828, true));
System.out.println(RandomizedTest.test(23, 1656, 1656, true));
// System.out.println(RandomizedTest.test(23, 3312, 3312, true));
// System.out.println(RandomizedTest.test(23, 6624, 6624, true));
// System.out.println(RandomizedTest.test(25, 1250, 1250, true));
// System.out.println(RandomizedTest.test(25, 3750, 3750, true));
// System.out.println(RandomizedTest.test(25, 7500, 7500, true));
// System.out.println(RandomizedTest.test(25, 15000, 15000, true));
// size: 1656 leafSize: 23 averageBucketSize: 1656 bitsPerKey: 1.517512077294686
// generateSeconds: 907.279643 evaluateNanosPerKey: 554.3478260869565
// size: 1250 leafSize: 25 averageBucketSize: 1250 bitsPerKey: 1.5112
// generateSeconds: 7416.210937 evaluateNanosPerKey: 312.8
}
private static boolean verifyOneTest() {
int size = 100_000;
int leafSize = 11;
int averageBucketSize = 12;
for (int j = 0; j < 5; j++) {
System.gc();
}
System.out.println(" size " + size + " leafSize " + leafSize + " averageBucketSize " + averageBucketSize);
FunctionInfo info = RandomizedTest.test(leafSize, averageBucketSize, size, true);
System.out.println(" " + info.bitsPerKey + " bits/key");
System.out.println(" " + info.generateNanos * size / 1_000_000_000 +
" seconds to generate");
System.out.println(" " + info.evaluateNanos +
" nanoseconds to evaluate");
if (info.bitsPerKey < 2.27 &&
info.generateNanos * size / 1_000_000_000 < 0.5 &&
info.evaluateNanos < 250) {
// all tests passed
return true;
}
return false;
}
public static void experimentalResults() {
System.out.println("6 Experimental Results");
int size = 1_000_000;
System.out.println("size " + size);
// experimentalResults(size, 16);
// experimentalResults(size, 64);
// experimentalResults(size, 128);
experimentalResults(size, 1024);
// experimentalResults(size, 4096);
}
static void experimentalResults(int size, int averageBucketSize) {
System.out.println("averageBucketSize " + averageBucketSize);
System.out.println("leafSize, bits/key");
System.out.println("calculated");
double last = 10;
for (int leafSize = 6; leafSize <= 18; leafSize++) {
double bitsPerKey = SpaceEstimator.getExpectedSpace(leafSize, averageBucketSize);
if (bitsPerKey > last) {
System.out.println("% increased");
}
last = bitsPerKey;
System.out.println(" (" + leafSize + ", " + bitsPerKey + ")");
// System.out.println("size: " + size);
}
System.out.println("experimental");
for (int leafSize = 6; leafSize <= 18; leafSize++) {
FunctionInfo info = test(leafSize, averageBucketSize, size, false);
System.out.println(" (" + info.leafSize + ", " + info.bitsPerKey + ")");
}
}
public static void reasonableParameterValues() {
System.out.println("6.1 Reasonable Parameter Values");
int leafSize = 10;
int size = 16 * 1024;
System.out.println("(leafSize=" + leafSize + ", size=" + size +
"): averageBucketSize, generation time in nanos/key");
ArrayList infos = new ArrayList();
for (int averageBucketSize = 8; averageBucketSize <= 16 * 1024; averageBucketSize *= 2) {
FunctionInfo info = test(leafSize, averageBucketSize, 16 * 1024, true);
infos.add(info);
System.out.println(" (" + info.averageBucketSize + ", " +
info.generateNanos + ")");
}
System.out
.println("averageBucketSize, evaluation time in nanos/key");
for (FunctionInfo info : infos) {
System.out.println(" (" + info.averageBucketSize + ", " +
info.evaluateNanos + ")");
}
System.out
.println("averageBucketSize, bits/key");
for (FunctionInfo info : infos) {
System.out.println(" (" + info.averageBucketSize + ", " +
info.bitsPerKey + ")");
}
}
private static long test(HashSet set, UniversalHash hash,
byte[] description, int leafSize, int averageBucketSize, int measureCount) {
BitSet known = new BitSet();
RecSplitEvaluator eval =
RecSplitBuilder.newInstance(hash).leafSize(leafSize).averageBucketSize(averageBucketSize).
buildEvaluator(new BitBuffer(description));
// verify
for (T x : set) {
int index = eval.evaluate(x);
if (index > set.size() || index < 0) {
Assert.fail("wrong entry: " + x + " " + index +
" leafSize " + leafSize +
" averageBucketSize " + averageBucketSize +
" hash " + convertBytesToHex(description));
}
if (known.get(index)) {
eval.evaluate(x);
Assert.fail("duplicate entry: " + x + " " + index +
" leafSize " + leafSize +
" averageBucketSize " + averageBucketSize +
" hash " + convertBytesToHex(description));
}
known.set(index);
}
known.clear();
known = null;
attemptGc();
// measure
// Profiler prof = new Profiler().startCollecting();
long best = Long.MAX_VALUE;
ArrayList list = new ArrayList(set);
for (int i = 0; i < measureCount; i++) {
if (list.size() > 100000) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long evaluateNanos = System.nanoTime();
for (int j = 0; j < measureCount; j++) {
for (T x : list) {
int index = eval.evaluate(x);
if (index > list.size() || index < 0) {
Assert.fail("wrong entry: " + x + " " + index +
" leafSize " + leafSize +
" averageBucketSize " + averageBucketSize +
" hash " + convertBytesToHex(description));
}
}
}
evaluateNanos = System.nanoTime() - evaluateNanos;
// System.out.println(" eval " + evaluateNanos / set.size());
best = Math.min(best, evaluateNanos);
}
// System.out.println(prof.getTop(5));
return best / measureCount;
}
public static int attemptGc() {
AtomicInteger obj = new AtomicInteger();
WeakReference